From 10d3f6fe851dc73f5f12edec26b028fe526f0be6 Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Tue, 26 Nov 2024 17:39:12 -0300 Subject: [PATCH] chore: Delete old serialization methods (#9951) Cleans up several toJSON and fromJSON methods that are no longer needed since we moved to schemas. Also drops hex serialization for most complex entities, such as circuit inputs and outputs, and replaces it with base64. --- .../archiver/kv_archiver_store/block_store.ts | 4 +- .../memory_archiver_store.ts | 3 +- yarn-project/archiver/src/index.ts | 3 +- .../archiver/src/test/mock_l2_block_source.ts | 12 +- .../aztec-node/src/aztec-node/server.test.ts | 2 + .../aztec.js/src/rpc_clients/node/index.ts | 45 +++---- yarn-project/aztec/src/examples/util.ts | 3 +- yarn-project/bot/src/factory.ts | 6 +- .../circuit-types/src/auth_witness.ts | 6 +- yarn-project/circuit-types/src/body.ts | 7 +- .../src/interfaces/nullifier_tree.ts | 16 --- yarn-project/circuit-types/src/l2_block.ts | 15 +-- .../l2_block_stream.test.ts | 2 +- .../src/logs/encrypted_l2_log.ts | 15 +-- .../src/logs/encrypted_l2_note_log.ts | 14 +-- .../circuit-types/src/logs/event_metadata.ts | 26 +--- .../src/logs/extended_unencrypted_l2_log.ts | 10 +- .../src/logs/function_l2_logs.test.ts | 6 +- .../src/logs/function_l2_logs.ts | 38 ------ .../src/logs/get_logs_response.ts | 2 +- .../src/logs/l1_payload/payload.test.ts | 18 ++- .../src/logs/l1_payload/payload.ts | 34 +++-- .../src/logs/l2_block_l2_logs.test.ts | 11 -- .../src/logs/l2_block_l2_logs.ts | 55 +------- yarn-project/circuit-types/src/logs/log_id.ts | 8 -- .../circuit-types/src/logs/tx_l2_logs.test.ts | 4 +- .../circuit-types/src/logs/tx_l2_logs.ts | 50 -------- .../src/logs/unencrypted_l2_log.test.ts | 11 ++ .../src/logs/unencrypted_l2_log.ts | 15 +-- .../src/messaging/l1_to_l2_message.ts | 3 +- .../src/notes/extended_note.test.ts | 38 ++++-- .../circuit-types/src/notes/extended_note.ts | 44 +++++-- .../src/p2p/consensus_payload.ts | 7 +- .../src/private_execution_result.test.ts | 9 +- .../src/private_execution_result.ts | 119 +----------------- .../epoch_proof_quote.test.ts | 3 +- .../prover_coordination/epoch_proof_quote.ts | 14 +-- .../epoch_proof_quote_payload.ts | 21 +--- .../circuit-types/src/public_data_witness.ts | 5 +- .../src/public_execution_request.ts | 7 -- .../src/sibling_path/sibling_path.test.ts | 19 +++ .../src/sibling_path/sibling_path.ts | 18 +-- .../circuit-types/src/simulation_error.ts | 11 +- .../circuit-types/src/tx/block_hash.ts | 29 +++++ yarn-project/circuit-types/src/tx/index.ts | 1 + .../src/tx/public_simulation_output.test.ts | 11 ++ .../src/tx/public_simulation_output.ts | 37 ------ .../circuit-types/src/tx/simulated_tx.test.ts | 31 +++-- .../circuit-types/src/tx/simulated_tx.ts | 53 ++------ yarn-project/circuit-types/src/tx/tx.test.ts | 8 ++ yarn-project/circuit-types/src/tx/tx.ts | 73 +++-------- .../circuit-types/src/tx/tx_receipt.test.ts | 9 +- .../circuit-types/src/tx/tx_receipt.ts | 36 +----- yarn-project/circuit-types/src/tx_effect.ts | 63 +++++++--- .../src/tx_execution_request.test.ts | 3 +- .../circuit-types/src/tx_execution_request.ts | 5 +- .../src/contract/interfaces/contract_class.ts | 8 +- .../__snapshots__/revert_code.test.ts.snap | 44 ++----- .../circuits.js/src/structs/avm/avm.ts | 37 +++--- .../src/structs/avm/avm_accumulated_data.ts | 5 +- .../structs/avm/avm_circuit_public_inputs.ts | 5 +- .../src/structs/client_ivc_proof.ts | 7 +- .../src/structs/complete_address.ts | 3 +- .../src/structs/content_commitment.ts | 18 +-- .../circuits.js/src/structs/function_data.ts | 23 ++-- yarn-project/circuits.js/src/structs/gas.ts | 8 -- .../circuits.js/src/structs/gas_fees.ts | 11 -- .../src/structs/global_variables.ts | 29 +---- .../circuits.js/src/structs/header.ts | 18 +-- .../kernel/combined_accumulated_data.ts | 11 +- .../kernel/kernel_circuit_public_inputs.ts | 11 +- .../kernel/private_accumulated_data.ts | 5 +- .../private_kernel_circuit_public_inputs.ts | 6 +- .../kernel/private_kernel_empty_inputs.ts | 13 +- ...ivate_kernel_tail_circuit_public_inputs.ts | 6 +- ..._to_public_kernel_circuit_public_inputs.ts | 5 +- .../src/structs/parity/base_parity_inputs.ts | 13 +- .../structs/parity/parity_public_inputs.ts | 13 +- .../src/structs/parity/root_parity_input.ts | 9 +- .../src/structs/parity/root_parity_inputs.ts | 13 +- .../src/structs/partial_state_reference.ts | 8 -- .../structs/private_circuit_public_inputs.ts | 14 +-- .../structs/private_validation_requests.ts | 5 +- yarn-project/circuits.js/src/structs/proof.ts | 5 +- .../src/structs/public_data_write.ts | 6 +- .../src/structs/recursive_proof.ts | 11 +- .../src/structs/revert_code.test.ts | 6 +- .../circuits.js/src/structs/revert_code.ts | 11 +- .../rollup/append_only_tree_snapshot.ts | 11 +- .../base_or_merge_rollup_public_inputs.ts | 13 +- .../src/structs/rollup/base_rollup_hints.ts | 9 +- .../src/structs/rollup/block_merge_rollup.ts | 11 +- ...block_root_or_block_merge_public_inputs.ts | 13 +- .../src/structs/rollup/block_root_rollup.ts | 13 +- .../rollup/empty_block_root_rollup_inputs.ts | 15 +-- .../src/structs/rollup/merge_rollup.ts | 15 +-- .../rollup/private_base_rollup_inputs.ts | 13 +- .../rollup/public_base_rollup_inputs.ts | 16 +-- .../src/structs/rollup/root_rollup.ts | 27 ++-- .../src/structs/rollup/tube_inputs.ts | 11 +- .../src/structs/rollup_validation_requests.ts | 5 +- .../circuits.js/src/structs/shared.ts | 5 - .../src/structs/state_reference.ts | 4 - .../src/structs/trees/nullifier_leaf.ts | 16 --- .../circuits.js/src/structs/tx_context.ts | 8 -- .../src/structs/verification_key.ts | 15 +-- .../src/structs/vk_witness_data.ts | 3 +- .../circuits.js/src/types/public_keys.ts | 3 +- yarn-project/cli-wallet/src/cmds/cancel_tx.ts | 2 +- yarn-project/cli-wallet/src/cmds/send.ts | 2 +- .../infrastructure/setup_protocol_contract.ts | 3 +- .../cli/src/cmds/pxe/get_current_base_fee.ts | 3 +- yarn-project/cli/src/utils/inspect.ts | 2 +- .../end-to-end/src/e2e_fees/failures.test.ts | 2 +- .../src/e2e_prover/e2e_prover_test.ts | 2 +- .../src/fixtures/snapshot_manager.ts | 4 +- .../e2e_prover_coordination.test.ts | 2 +- yarn-project/foundation/src/abi/abi.ts | 2 +- .../foundation/src/abi/encoder.test.ts | 6 +- .../foundation/src/abi/event_selector.ts | 10 +- .../foundation/src/abi/function_selector.ts | 10 +- .../foundation/src/abi/note_selector.ts | 10 +- yarn-project/foundation/src/abi/selector.ts | 3 +- .../foundation/src/aztec-address/index.ts | 10 +- .../foundation/src/buffer/buffer32.ts | 20 +-- .../secp256k1-signer/secp256k1_signer.test.ts | 6 +- .../foundation/src/eth-address/index.ts | 17 +-- .../src/eth-signature/eth_signature.test.ts | 26 ++-- .../src/eth-signature/eth_signature.ts | 29 +++-- yarn-project/foundation/src/fields/fields.ts | 20 +-- .../foundation/src/fields/point.test.ts | 3 +- yarn-project/foundation/src/fields/point.ts | 20 ++- .../foundation/src/json-rpc/client/fetch.ts | 31 +++-- .../foundation/src/json-rpc/convert.test.ts | 26 +++- .../foundation/src/json-rpc/convert.ts | 4 +- yarn-project/foundation/src/json-rpc/index.ts | 2 +- .../foundation/src/schemas/schemas.ts | 79 +++++------- yarn-project/foundation/src/schemas/utils.ts | 39 ++++-- .../src/serialize/type_registry.test.ts | 90 +++++++++++++ .../foundation/src/serialize/type_registry.ts | 34 ++++- yarn-project/foundation/src/string/index.ts | 4 + .../__snapshots__/noir_test_gen.test.ts.snap | 4 +- .../proving_job_database/persisted.ts | 11 +- .../prover-node/src/quote-provider/http.ts | 5 +- .../pxe/src/simulator_oracle/index.ts | 5 +- .../src/block_builder/light.ts | 4 +- .../global_variable_builder/global_builder.ts | 2 +- .../src/publisher/l1-publisher.ts | 2 +- .../simulator/src/avm/journal/journal.ts | 3 +- yarn-project/simulator/src/common/errors.ts | 3 +- .../public/enqueued_call_side_effect_trace.ts | 5 +- .../simulator/src/public/side_effect_trace.ts | 5 +- yarn-project/txe/src/util/encoding.ts | 3 +- .../types/src/abi/contract_artifact.ts | 19 +-- yarn-project/world-state/package.json | 3 +- .../src/native/world_state_version.ts | 33 ++--- yarn-project/yarn.lock | 1 + 157 files changed, 1054 insertions(+), 1308 deletions(-) create mode 100644 yarn-project/circuit-types/src/sibling_path/sibling_path.test.ts create mode 100644 yarn-project/circuit-types/src/tx/block_hash.ts create mode 100644 yarn-project/circuit-types/src/tx/public_simulation_output.test.ts create mode 100644 yarn-project/foundation/src/serialize/type_registry.test.ts diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts index 91ae9d578c2..3d15de3fbbb 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts @@ -1,4 +1,4 @@ -import { Body, type InBlock, L2Block, type TxEffect, type TxHash, TxReceipt } from '@aztec/circuit-types'; +import { Body, type InBlock, L2Block, L2BlockHash, type TxEffect, type TxHash, TxReceipt } from '@aztec/circuit-types'; import { AppendOnlyTreeSnapshot, type AztecAddress, Header, INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { type AztecKVStore, type AztecMap, type AztecSingleton, type Range } from '@aztec/kv-store'; @@ -211,7 +211,7 @@ export class BlockStore { TxReceipt.statusFromRevertCode(tx.revertCode), '', tx.transactionFee.toBigInt(), - block.data.hash().toBuffer(), + L2BlockHash.fromField(block.data.hash()), block.data.number, ); } diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts index 7f34e559ccc..df606d16fab 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts @@ -9,6 +9,7 @@ import { type InBlock, type InboxLeaf, type L2Block, + L2BlockHash, type L2BlockL2Logs, type LogFilter, LogId, @@ -450,7 +451,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { TxReceipt.statusFromRevertCode(txEffect.revertCode), '', txEffect.transactionFee.toBigInt(), - block.data.hash().toBuffer(), + L2BlockHash.fromField(block.data.hash()), block.data.number, ), ); diff --git a/yarn-project/archiver/src/index.ts b/yarn-project/archiver/src/index.ts index ae7f86f8c20..24112863fc1 100644 --- a/yarn-project/archiver/src/index.ts +++ b/yarn-project/archiver/src/index.ts @@ -1,3 +1,4 @@ +import { jsonStringify } from '@aztec/foundation/json-rpc'; import { createDebugLogger } from '@aztec/foundation/log'; import { fileURLToPath } from '@aztec/foundation/url'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; @@ -25,7 +26,7 @@ async function main() { const config = getArchiverConfigFromEnv(); const { l1RpcUrl: rpcUrl, l1Contracts } = config; - log.info(`Starting archiver in main(): ${JSON.stringify(config)}`); + log.info(`Starting archiver in main(): ${jsonStringify(config)}`); const publicClient = createPublicClient({ chain: localhost, transport: http(rpcUrl), diff --git a/yarn-project/archiver/src/test/mock_l2_block_source.ts b/yarn-project/archiver/src/test/mock_l2_block_source.ts index 2ab843cb42a..cbd2e3363d3 100644 --- a/yarn-project/archiver/src/test/mock_l2_block_source.ts +++ b/yarn-project/archiver/src/test/mock_l2_block_source.ts @@ -1,4 +1,12 @@ -import { L2Block, type L2BlockSource, type L2Tips, type TxHash, TxReceipt, TxStatus } from '@aztec/circuit-types'; +import { + L2Block, + L2BlockHash, + type L2BlockSource, + type L2Tips, + type TxHash, + TxReceipt, + TxStatus, +} from '@aztec/circuit-types'; import { EthAddress, type Header } from '@aztec/circuits.js'; import { DefaultL1ContractsConfig } from '@aztec/ethereum'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -144,7 +152,7 @@ export class MockL2BlockSource implements L2BlockSource { TxStatus.SUCCESS, '', txEffect.transactionFee.toBigInt(), - block.hash().toBuffer(), + L2BlockHash.fromField(block.hash()), block.number, ), ); diff --git a/yarn-project/aztec-node/src/aztec-node/server.test.ts b/yarn-project/aztec-node/src/aztec-node/server.test.ts index 29bbf20e274..666bd426440 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.test.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.test.ts @@ -143,12 +143,14 @@ describe('aztec node', () => { maxBlockNumber: new MaxBlockNumber(true, new Fr(1)), getSize: () => 1, toBuffer: () => Fr.ZERO.toBuffer(), + toString: () => Fr.ZERO.toString(), }; validMaxBlockNumberMetadata.data.rollupValidationRequests = { maxBlockNumber: new MaxBlockNumber(true, new Fr(5)), getSize: () => 1, toBuffer: () => Fr.ZERO.toBuffer(), + toString: () => Fr.ZERO.toString(), }; lastBlockNumber = 3; diff --git a/yarn-project/aztec.js/src/rpc_clients/node/index.ts b/yarn-project/aztec.js/src/rpc_clients/node/index.ts index 9cf3195f334..0db9d0edf35 100644 --- a/yarn-project/aztec.js/src/rpc_clients/node/index.ts +++ b/yarn-project/aztec.js/src/rpc_clients/node/index.ts @@ -1,8 +1,10 @@ import { type PXE } from '@aztec/circuit-types'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; import { type DebugLogger } from '@aztec/foundation/log'; import { NoRetryError, makeBackoff, retry } from '@aztec/foundation/retry'; -import axios, { type AxiosError, type AxiosResponse } from 'axios'; +import { Axios, type AxiosError } from 'axios'; +import { inspect } from 'util'; import { createPXEClient } from '../pxe_client.js'; @@ -15,34 +17,19 @@ import { createPXEClient } from '../pxe_client.js'; * @returns The response data. */ async function axiosFetch(host: string, rpcMethod: string, body: any, useApiEndpoints: boolean) { - let resp: AxiosResponse; - if (useApiEndpoints) { - resp = await axios - .post(`${host}/${rpcMethod}`, body, { - headers: { 'content-type': 'application/json' }, - }) - .catch((error: AxiosError) => { - if (error.response) { - return error.response; - } - throw error; - }); - } else { - resp = await axios - .post( - host, - { ...body, method: rpcMethod }, - { - headers: { 'content-type': 'application/json' }, - }, - ) - .catch((error: AxiosError) => { - if (error.response) { - return error.response; - } - throw error; - }); - } + const request = new Axios({ + headers: { 'content-type': 'application/json' }, + transformRequest: [(data: any) => jsonStringify(data)], + transformResponse: [(data: any) => JSON.parse(data)], + }); + const [url, content] = useApiEndpoints ? [`${host}/${rpcMethod}`, body] : [host, { ...body, method: rpcMethod }]; + const resp = await request.post(url, content).catch((error: AxiosError) => { + if (error.response) { + return error.response; + } + const errorMessage = `Error fetching from host ${host} with method ${rpcMethod}: ${inspect(error)}`; + throw new Error(errorMessage); + }); const isOK = resp.status >= 200 && resp.status < 300; if (isOK) { diff --git a/yarn-project/aztec/src/examples/util.ts b/yarn-project/aztec/src/examples/util.ts index 0d38e5beeef..2ba7c3e6e93 100644 --- a/yarn-project/aztec/src/examples/util.ts +++ b/yarn-project/aztec/src/examples/util.ts @@ -1,4 +1,5 @@ import { EthAddress } from '@aztec/aztec.js'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; import type { Abi, Narrow } from 'abitype'; import { type Account, type Chain, type Hex, type HttpTransport, type PublicClient, type WalletClient } from 'viem'; @@ -28,7 +29,7 @@ export async function deployL1Contract( const receipt = await publicClient.waitForTransactionReceipt({ hash }); const contractAddress = receipt.contractAddress; if (!contractAddress) { - throw new Error(`No contract address found in receipt: ${JSON.stringify(receipt)}`); + throw new Error(`No contract address found in receipt: ${jsonStringify(receipt)}`); } return EthAddress.fromString(receipt.contractAddress!); diff --git a/yarn-project/bot/src/factory.ts b/yarn-project/bot/src/factory.ts index b05e840fdb2..2a72653005a 100644 --- a/yarn-project/bot/src/factory.ts +++ b/yarn-project/bot/src/factory.ts @@ -70,7 +70,7 @@ export class BotFactory { this.log.info(`Initializing account at ${account.getAddress().toString()}`); const sentTx = account.deploy(); const txHash = await sentTx.getTxHash(); - this.log.info(`Sent tx with hash ${txHash.to0xString()}`); + this.log.info(`Sent tx with hash ${txHash.toString()}`); if (this.config.flushSetupTransactions) { this.log.verbose('Flushing transactions'); await this.node!.flushTxs(); @@ -117,7 +117,7 @@ export class BotFactory { this.log.info(`Deploying token contract at ${address.toString()}`); const sentTx = deploy.send(deployOpts); const txHash = await sentTx.getTxHash(); - this.log.info(`Sent tx with hash ${txHash.to0xString()}`); + this.log.info(`Sent tx with hash ${txHash.toString()}`); if (this.config.flushSetupTransactions) { this.log.verbose('Flushing transactions'); await this.node!.flushTxs(); @@ -164,7 +164,7 @@ export class BotFactory { } const sentTx = new BatchCall(token.wallet, calls).send(); const txHash = await sentTx.getTxHash(); - this.log.info(`Sent tx with hash ${txHash.to0xString()}`); + this.log.info(`Sent tx with hash ${txHash.toString()}`); if (this.config.flushSetupTransactions) { this.log.verbose('Flushing transactions'); await this.node!.flushTxs(); diff --git a/yarn-project/circuit-types/src/auth_witness.ts b/yarn-project/circuit-types/src/auth_witness.ts index f661817edbd..ea135a2d5dd 100644 --- a/yarn-project/circuit-types/src/auth_witness.ts +++ b/yarn-project/circuit-types/src/auth_witness.ts @@ -2,6 +2,7 @@ import { Vector } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { hexSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; /** * An authentication witness. Used to authorize an action by a user. @@ -37,12 +38,11 @@ export class AuthWitness { } toString() { - return '0x' + this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromString(str: string) { - const hex = str.replace(/^0x/, ''); - return AuthWitness.fromBuffer(Buffer.from(hex, 'hex')); + return AuthWitness.fromBuffer(hexToBuffer(str)); } static random() { diff --git a/yarn-project/circuit-types/src/body.ts b/yarn-project/circuit-types/src/body.ts index 48617fa2016..7c5d131a5c8 100644 --- a/yarn-project/circuit-types/src/body.ts +++ b/yarn-project/circuit-types/src/body.ts @@ -1,3 +1,4 @@ +import { type ZodFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { computeUnbalancedMerkleRoot } from '@aztec/foundation/trees'; @@ -21,7 +22,7 @@ export class Body { }); } - static get schema() { + static get schema(): ZodFor { return z .object({ txEffects: z.array(TxEffect.schema), @@ -29,10 +30,6 @@ export class Body { .transform(({ txEffects }) => new Body(txEffects)); } - toJSON() { - return { txEffects: this.txEffects }; - } - /** * Serializes a block body * @returns A serialized L2 block body. diff --git a/yarn-project/circuit-types/src/interfaces/nullifier_tree.ts b/yarn-project/circuit-types/src/interfaces/nullifier_tree.ts index bfc6097ab09..ec46c4d99e9 100644 --- a/yarn-project/circuit-types/src/interfaces/nullifier_tree.ts +++ b/yarn-project/circuit-types/src/interfaces/nullifier_tree.ts @@ -54,20 +54,4 @@ export class NullifierMembershipWitness { public toFields(): Fr[] { return [new Fr(this.index), ...this.leafPreimage.toFields(), ...this.siblingPath.toFields()]; } - - public toJSON() { - return { - index: '0x' + this.index.toString(16), - leafPreimage: this.leafPreimage.toJSON(), - siblingPath: this.siblingPath.toString(), - }; - } - - static fromJSON(json: any): NullifierMembershipWitness { - return new NullifierMembershipWitness( - BigInt(json.index), - NullifierLeafPreimage.fromJSON(json.leafPreimage), - SiblingPath.fromString(json.siblingPath), - ); - } } diff --git a/yarn-project/circuit-types/src/l2_block.ts b/yarn-project/circuit-types/src/l2_block.ts index bf5f8bffe33..169ff874fd6 100644 --- a/yarn-project/circuit-types/src/l2_block.ts +++ b/yarn-project/circuit-types/src/l2_block.ts @@ -1,7 +1,8 @@ -import { AppendOnlyTreeSnapshot, Header, STRING_ENCODING } from '@aztec/circuits.js'; +import { AppendOnlyTreeSnapshot, Header } from '@aztec/circuits.js'; import { sha256, sha256ToField } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { z } from 'zod'; @@ -31,14 +32,6 @@ export class L2Block { .transform(({ archive, header, body }) => new L2Block(archive, header, body)); } - toJSON() { - return { - archive: this.archive, - header: this.header, - body: this.body, - }; - } - /** * Deserializes a block from a buffer * @returns A deserialized L2 block. @@ -66,7 +59,7 @@ export class L2Block { * @returns Deserialized L2 block. */ static fromString(str: string): L2Block { - return L2Block.fromBuffer(Buffer.from(str, STRING_ENCODING)); + return L2Block.fromBuffer(hexToBuffer(str)); } /** @@ -74,7 +67,7 @@ export class L2Block { * @returns A serialized L2 block as a string. */ toString(): string { - return this.toBuffer().toString(STRING_ENCODING); + return bufferToHex(this.toBuffer()); } /** diff --git a/yarn-project/circuit-types/src/l2_block_downloader/l2_block_stream.test.ts b/yarn-project/circuit-types/src/l2_block_downloader/l2_block_stream.test.ts index 756c598eb1e..bb8eaafc83a 100644 --- a/yarn-project/circuit-types/src/l2_block_downloader/l2_block_stream.test.ts +++ b/yarn-project/circuit-types/src/l2_block_downloader/l2_block_stream.test.ts @@ -42,7 +42,7 @@ describe('L2BlockStream', () => { const makeBlock = (number: number) => ({ number } as L2Block); - const makeHeader = (number: number) => mock
({ hash: () => new Fr(number) }); + const makeHeader = (number: number) => mock
({ hash: () => new Fr(number) } as Header); const setRemoteTips = (latest_: number, proven?: number, finalized?: number) => { proven = proven ?? 0; diff --git a/yarn-project/circuit-types/src/logs/encrypted_l2_log.ts b/yarn-project/circuit-types/src/logs/encrypted_l2_log.ts index f59b98fa6a6..da67376b042 100644 --- a/yarn-project/circuit-types/src/logs/encrypted_l2_log.ts +++ b/yarn-project/circuit-types/src/logs/encrypted_l2_log.ts @@ -25,23 +25,10 @@ export class EncryptedL2Log { static get schema() { return z - .object({ data: schemas.BufferHex, maskedContractAddress: schemas.Fr }) + .object({ data: schemas.Buffer, maskedContractAddress: schemas.Fr }) .transform(({ data, maskedContractAddress }) => new EncryptedL2Log(data, maskedContractAddress)); } - /** Returns a JSON-friendly representation of the log. */ - public toJSON(): object { - return { - data: this.data.toString('hex'), - maskedContractAddress: this.maskedContractAddress.toString(), - }; - } - - /** Converts a plain JSON object into an instance. */ - public static fromJSON(obj: any) { - return new EncryptedL2Log(Buffer.from(obj.data, 'hex'), Fr.fromString(obj.maskedContractAddress)); - } - /** * Deserializes log from a buffer. * @param buffer - The buffer containing the log. diff --git a/yarn-project/circuit-types/src/logs/encrypted_l2_note_log.ts b/yarn-project/circuit-types/src/logs/encrypted_l2_note_log.ts index 23f5a2a99b1..62d4d7ff62d 100644 --- a/yarn-project/circuit-types/src/logs/encrypted_l2_note_log.ts +++ b/yarn-project/circuit-types/src/logs/encrypted_l2_note_log.ts @@ -25,20 +25,8 @@ export class EncryptedL2NoteLog { return this.data; } - /** Returns a JSON-friendly representation of the log. */ - public toJSON(): object { - return { data: this.data.toString('hex') }; - } - static get schema() { - return z - .object({ data: schemas.HexString }) - .transform(({ data }) => new EncryptedL2NoteLog(Buffer.from(data, 'hex'))); - } - - /** Converts a plain JSON object into an instance. */ - public static fromJSON(obj: any) { - return new EncryptedL2NoteLog(Buffer.from(obj.data, 'hex')); + return z.object({ data: schemas.Buffer }).transform(({ data }) => new EncryptedL2NoteLog(data)); } /** diff --git a/yarn-project/circuit-types/src/logs/event_metadata.ts b/yarn-project/circuit-types/src/logs/event_metadata.ts index b63d8b8bba5..e5b4a89f221 100644 --- a/yarn-project/circuit-types/src/logs/event_metadata.ts +++ b/yarn-project/circuit-types/src/logs/event_metadata.ts @@ -1,4 +1,4 @@ -import { type AbiType, AbiTypeSchema, EventSelector, decodeFromAbi } from '@aztec/foundation/abi'; +import { type AbiType, AbiTypeSchema, type EventSelector, decodeFromAbi } from '@aztec/foundation/abi'; import { Fr } from '@aztec/foundation/fields'; import { schemas } from '@aztec/foundation/schemas'; @@ -49,37 +49,13 @@ export class EventMetadata { }; } - /** - * Serializes the metadata to a JSON-friendly format - */ - public toJSON() { - return { - type: 'event_metadata', // TODO(palla/schemas): Remove this type property - eventSelector: this.eventSelector, - abiType: this.abiType, - fieldNames: this.fieldNames, - }; - } - static get schema() { return z .object({ eventSelector: schemas.EventSelector, abiType: AbiTypeSchema, fieldNames: z.array(z.string()), - type: z.literal('event_metadata').optional(), }) .transform(obj => new EventMetadata(obj)); } - - /** - * Creates an EventMetadata instance from a JSON representation - */ - public static fromJSON(json: any): EventMetadata { - return new EventMetadata({ - eventSelector: EventSelector.fromString(json.eventSelector), - abiType: json.abiType, - fieldNames: json.fieldNames, - }); - } } diff --git a/yarn-project/circuit-types/src/logs/extended_unencrypted_l2_log.ts b/yarn-project/circuit-types/src/logs/extended_unencrypted_l2_log.ts index b571879aacd..9bdab9deeb4 100644 --- a/yarn-project/circuit-types/src/logs/extended_unencrypted_l2_log.ts +++ b/yarn-project/circuit-types/src/logs/extended_unencrypted_l2_log.ts @@ -1,4 +1,5 @@ import { BufferReader } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import isEqual from 'lodash.isequal'; @@ -22,10 +23,6 @@ export class ExtendedUnencryptedL2Log { return new ExtendedUnencryptedL2Log(LogId.random(), UnencryptedL2Log.random()); } - toJSON() { - return { id: this.id, log: this.log }; - } - static get schema() { return z .object({ @@ -52,7 +49,7 @@ export class ExtendedUnencryptedL2Log { * @returns A string containing the serialized log. */ public toString(): string { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -92,7 +89,6 @@ export class ExtendedUnencryptedL2Log { * @returns An `ExtendedUnencryptedL2Log` object. */ public static fromString(data: string): ExtendedUnencryptedL2Log { - const buffer = Buffer.from(data, 'hex'); - return ExtendedUnencryptedL2Log.fromBuffer(buffer); + return ExtendedUnencryptedL2Log.fromBuffer(hexToBuffer(data)); } } diff --git a/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts b/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts index 5effe039a0c..d0f49d57c7c 100644 --- a/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts +++ b/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts @@ -1,3 +1,5 @@ +import { jsonStringify } from '@aztec/foundation/json-rpc'; + import { EncryptedFunctionL2Logs, EncryptedNoteFunctionL2Logs, UnencryptedFunctionL2Logs } from './function_l2_logs.js'; function shouldBehaveLikeFunctionL2Logs( @@ -19,8 +21,8 @@ function shouldBehaveLikeFunctionL2Logs( it('can encode L2Logs to JSON and back', () => { const l2Logs = FunctionL2Logs.random(3); - const buffer = JSON.stringify(l2Logs.toJSON()); - const recovered = FunctionL2Logs.fromJSON(JSON.parse(buffer)); + const buffer = jsonStringify(l2Logs); + const recovered = FunctionL2Logs.schema.parse(JSON.parse(buffer)); expect(recovered).toEqual(l2Logs); }); diff --git a/yarn-project/circuit-types/src/logs/function_l2_logs.ts b/yarn-project/circuit-types/src/logs/function_l2_logs.ts index e3127e63cd6..2171fb2c17e 100644 --- a/yarn-project/circuit-types/src/logs/function_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/function_l2_logs.ts @@ -62,14 +62,6 @@ export abstract class FunctionL2Logs l.hash())); return sha256Trunc(preimage); } - - /** - * Convert a FunctionL2Logs class object to a plain JSON object. - * @returns A plain object with FunctionL2Logs properties. - */ - public toJSON() { - return { logs: this.logs }; - } } export class EncryptedNoteFunctionL2Logs extends FunctionL2Logs { @@ -118,16 +110,6 @@ export class EncryptedNoteFunctionL2Logs extends FunctionL2Logs { @@ -176,16 +158,6 @@ export class EncryptedFunctionL2Logs extends FunctionL2Logs { } return new EncryptedFunctionL2Logs(logs); } - - /** - * Convert a plain JSON object to a FunctionL2Logs class object. - * @param obj - A plain FunctionL2Logs JSON object. - * @returns A FunctionL2Logs class object. - */ - public static fromJSON(obj: any) { - const logs = obj.logs.map(EncryptedL2Log.fromJSON); - return new EncryptedFunctionL2Logs(logs); - } } export class UnencryptedFunctionL2Logs extends FunctionL2Logs { @@ -234,14 +206,4 @@ export class UnencryptedFunctionL2Logs extends FunctionL2Logs } return new UnencryptedFunctionL2Logs(logs); } - - /** - * Convert a plain JSON object to a FunctionL2Logs class object. - * @param obj - A plain FunctionL2Logs JSON object. - * @returns A FunctionL2Logs class object. - */ - public static fromJSON(obj: any) { - const logs = obj.logs.map(UnencryptedL2Log.fromJSON); - return new UnencryptedFunctionL2Logs(logs); - } } diff --git a/yarn-project/circuit-types/src/logs/get_logs_response.ts b/yarn-project/circuit-types/src/logs/get_logs_response.ts index 6f1d156be0b..62b2ff6d833 100644 --- a/yarn-project/circuit-types/src/logs/get_logs_response.ts +++ b/yarn-project/circuit-types/src/logs/get_logs_response.ts @@ -52,7 +52,7 @@ export class TxScopedL2Log { dataStartIndexForTx: z.number(), blockNumber: z.number(), isFromPublic: z.boolean(), - logData: schemas.BufferB64, + logData: schemas.Buffer, }) .transform( ({ txHash, dataStartIndexForTx, blockNumber, isFromPublic, logData }) => diff --git a/yarn-project/circuit-types/src/logs/l1_payload/payload.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/payload.test.ts index a4fa27d833a..6dc3a358683 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/payload.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/payload.test.ts @@ -1,13 +1,23 @@ import { Fr } from '@aztec/foundation/fields'; +import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc'; + +import times from 'lodash.times'; import { Event, Note } from './payload.js'; describe('note', () => { + let note: Note; + + beforeEach(() => { + note = new Note(times(5, Fr.random)); + }); + it('convert to and from buffer', () => { - const fields = Array.from({ length: 5 }).map(() => Fr.random()); - const note = new Note(fields); - const buf = note.toBuffer(); - expect(Note.fromBuffer(buf)).toEqual(note); + expect(Note.fromBuffer(note.toBuffer())).toEqual(note); + }); + + it('converts to and from json', () => { + expect(jsonParseWithSchema(jsonStringify(note), Note.schema)).toEqual(note); }); }); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/payload.ts index cc460a2a3cd..4bcad7408fc 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/payload.ts @@ -1,8 +1,9 @@ import { Vector } from '@aztec/circuits.js'; import { randomInt } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { schemas } from '@aztec/foundation/schemas'; import { BufferReader } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; /** * The Note class represents a Note emitted from a Noir contract as a vector of Fr (finite field) elements. @@ -11,11 +12,11 @@ import { BufferReader } from '@aztec/foundation/serialize'; */ export class Payload extends Vector { toJSON() { - return this.toString(); + return this.toBuffer(); } static get schema() { - return hexSchemaFor(Payload); + return schemas.Buffer.transform(Payload.fromBuffer); } /** @@ -49,7 +50,7 @@ export class Payload extends Vector { * @returns A hex string with the vector length as first element. */ override toString() { - return '0x' + this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -58,8 +59,7 @@ export class Payload extends Vector { * @returns A Note instance. */ static fromString(str: string) { - const hex = str.replace(/^0x/, ''); - return Payload.fromBuffer(Buffer.from(hex, 'hex')); + return Payload.fromBuffer(hexToBuffer(str)); } get length() { @@ -71,6 +71,24 @@ export class Payload extends Vector { } } -export class Event extends Payload {} +export class Event extends Payload { + static override get schema() { + return schemas.Buffer.transform(Event.fromBuffer); + } + + static override fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new Event(reader.readVector(Fr)); + } +} -export class Note extends Payload {} +export class Note extends Payload { + static override get schema() { + return schemas.Buffer.transform(Note.fromBuffer); + } + + static override fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new Note(reader.readVector(Fr)); + } +} diff --git a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts index 41ea8c0eee8..e16b963525b 100644 --- a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts +++ b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts @@ -45,17 +45,6 @@ function shouldBehaveLikeL2BlockL2Logs( } }); - it('serializes to and from JSON via fromJSON', () => { - const l2Logs = - L2BlockL2Logs.name == 'ContractClass2BlockL2Logs' - ? L2BlockL2Logs.random(3, 1, 1) - : L2BlockL2Logs.random(3, 4, 2); - const json = jsonStringify(l2Logs); - const recovered = L2BlockL2Logs.fromJSON(JSON.parse(json)); - expect(recovered).toEqual(l2Logs); - expect(recovered).toBeInstanceOf(L2BlockL2Logs); - }); - it('serializes to and from JSON via schema', () => { const l2Logs = L2BlockL2Logs.name == 'ContractClass2BlockL2Logs' diff --git a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.ts b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.ts index 2698fc2fc12..82bf2d4a899 100644 --- a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.ts @@ -1,5 +1,6 @@ import { type ZodFor } from '@aztec/foundation/schemas'; import { BufferReader, prefixBufferWithLength } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import isEqual from 'lodash.isequal'; import { z } from 'zod'; @@ -70,7 +71,7 @@ export abstract class L2BlockL2Logs EncryptedNoteTxL2Logs.fromJSON(log)); - return new EncryptedNoteL2BlockL2Logs(txLogs); - } - /** * Deserializes logs from a buffer. * @param buffer - The buffer containing the serialized logs. @@ -144,8 +135,7 @@ export class EncryptedNoteL2BlockL2Logs extends L2BlockL2Logs { return 'Encrypted'; } - /** - * Convert a plain JSON object to a L2BlockL2Logs class object. - * @param obj - A plain L2BlockL2Logs JSON object. - * @returns A L2BlockL2Logs class object. - */ - public static fromJSON(obj: any) { - const txLogs = obj.txLogs.map((log: any) => EncryptedTxL2Logs.fromJSON(log)); - return new EncryptedL2BlockL2Logs(txLogs); - } - /** * Deserializes logs from a buffer. * @param buffer - The buffer containing the serialized logs. @@ -225,8 +205,7 @@ export class EncryptedL2BlockL2Logs extends L2BlockL2Logs { * @returns A new `L2BlockL2Logs` object. */ public static fromString(data: string): EncryptedL2BlockL2Logs { - const buffer = Buffer.from(data, 'hex'); - return EncryptedL2BlockL2Logs.fromBuffer(buffer); + return EncryptedL2BlockL2Logs.fromBuffer(hexToBuffer(data)); } /** @@ -275,16 +254,6 @@ export class UnencryptedL2BlockL2Logs extends L2BlockL2Logs { return 'Unencrypted'; } - /** - * Convert a plain JSON object to a L2BlockL2Logs class object. - * @param obj - A plain L2BlockL2Logs JSON object. - * @returns A L2BlockL2Logs class object. - */ - public static fromJSON(obj: any) { - const txLogs = obj.txLogs.map((log: any) => UnencryptedTxL2Logs.fromJSON(log)); - return new UnencryptedL2BlockL2Logs(txLogs); - } - /** * Deserializes logs from a buffer. * @param buffer - The buffer containing the serialized logs. @@ -306,8 +275,7 @@ export class UnencryptedL2BlockL2Logs extends L2BlockL2Logs { * @returns A new `L2BlockL2Logs` object. */ public static fromString(data: string): UnencryptedL2BlockL2Logs { - const buffer = Buffer.from(data, 'hex'); - return UnencryptedL2BlockL2Logs.fromBuffer(buffer); + return UnencryptedL2BlockL2Logs.fromBuffer(hexToBuffer(data)); } /** @@ -358,16 +326,6 @@ export class ContractClass2BlockL2Logs extends L2BlockL2Logs { return 'ContractClass'; } - /** - * Convert a plain JSON object to a L2BlockL2Logs class object. - * @param obj - A plain L2BlockL2Logs JSON object. - * @returns A L2BlockL2Logs class object. - */ - public static fromJSON(obj: any) { - const txLogs = obj.txLogs.map((log: any) => ContractClassTxL2Logs.fromJSON(log)); - return new ContractClass2BlockL2Logs(txLogs); - } - /** * Deserializes logs from a buffer. * @param buffer - The buffer containing the serialized logs. @@ -389,8 +347,7 @@ export class ContractClass2BlockL2Logs extends L2BlockL2Logs { * @returns A new `L2BlockL2Logs` object. */ public static fromString(data: string): ContractClass2BlockL2Logs { - const buffer = Buffer.from(data, 'hex'); - return ContractClass2BlockL2Logs.fromBuffer(buffer); + return ContractClass2BlockL2Logs.fromBuffer(hexToBuffer(data)); } /** diff --git a/yarn-project/circuit-types/src/logs/log_id.ts b/yarn-project/circuit-types/src/logs/log_id.ts index 731763b1f07..fe718fb3821 100644 --- a/yarn-project/circuit-types/src/logs/log_id.ts +++ b/yarn-project/circuit-types/src/logs/log_id.ts @@ -50,14 +50,6 @@ export class LogId { .transform(({ blockNumber, txIndex, logIndex }) => new LogId(blockNumber, txIndex, logIndex)); } - toJSON() { - return { - blockNumber: this.blockNumber, - txIndex: this.txIndex, - logIndex: this.logIndex, - }; - } - /** * Serializes log id to a buffer. * @returns A buffer containing the serialized log id. diff --git a/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts b/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts index 5fd7831ebe5..6bec9823692 100644 --- a/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts +++ b/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts @@ -22,8 +22,8 @@ function shouldBehaveLikeTxL2Logs( it('can encode TxL2Logs to JSON and back', () => { const l2Logs = TxL2Logs.name == 'ContractClassTxL2Logs' ? TxL2Logs.random(1, 1) : TxL2Logs.random(4, 2); - const buffer = jsonStringify(l2Logs.toJSON()); - const recovered = TxL2Logs.fromJSON(JSON.parse(buffer)); + const buffer = jsonStringify(l2Logs); + const recovered = TxL2Logs.schema.parse(JSON.parse(buffer)); expect(recovered).toEqual(l2Logs); }); diff --git a/yarn-project/circuit-types/src/logs/tx_l2_logs.ts b/yarn-project/circuit-types/src/logs/tx_l2_logs.ts index afa1f715752..b27b2346f02 100644 --- a/yarn-project/circuit-types/src/logs/tx_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/tx_l2_logs.ts @@ -76,16 +76,6 @@ export abstract class TxL2Logs log.toJSON()), - }; - } - /** * Unrolls logs from this tx. * @returns Unrolled logs. @@ -209,16 +199,6 @@ export class UnencryptedTxL2Logs extends TxL2Logs { return new UnencryptedTxL2Logs(functionLogs); } - /** - * Convert a plain JSON object to a TxL2Logs class object. - * @param obj - A plain TxL2Logs JSON object. - * @returns A TxL2Logs class object. - */ - public static fromJSON(obj: any) { - const functionLogs = obj.functionLogs.map((log: any) => UnencryptedFunctionL2Logs.fromJSON(log)); - return new UnencryptedTxL2Logs(functionLogs); - } - /** * Computes unencrypted logs hash as is done in the kernel and decoder contract. * @param logs - Logs to be hashed. @@ -303,16 +283,6 @@ export class EncryptedNoteTxL2Logs extends TxL2Logs { return new EncryptedNoteTxL2Logs(functionLogs); } - /** - * Convert a plain JSON object to a TxL2Logs class object. - * @param obj - A plain TxL2Logs JSON object. - * @returns A TxL2Logs class object. - */ - public static fromJSON(obj: any) { - const functionLogs = obj.functionLogs.map((log: any) => EncryptedNoteFunctionL2Logs.fromJSON(log)); - return new EncryptedNoteTxL2Logs(functionLogs); - } - /** * Computes encrypted logs hash as is done in the kernel and decoder contract. * @param logs - Logs to be hashed. @@ -396,16 +366,6 @@ export class EncryptedTxL2Logs extends TxL2Logs { return new EncryptedTxL2Logs(functionLogs); } - /** - * Convert a plain JSON object to a TxL2Logs class object. - * @param obj - A plain TxL2Logs JSON object. - * @returns A TxL2Logs class object. - */ - public static fromJSON(obj: any) { - const functionLogs = obj.functionLogs.map((log: any) => EncryptedFunctionL2Logs.fromJSON(log)); - return new EncryptedTxL2Logs(functionLogs); - } - /** * Computes encrypted logs hash as is done in the kernel and decoder contract. * @param logs - Logs to be hashed. @@ -490,16 +450,6 @@ export class ContractClassTxL2Logs extends TxL2Logs { return new ContractClassTxL2Logs(functionLogs); } - /** - * Convert a plain JSON object to a TxL2Logs class object. - * @param obj - A plain TxL2Logs JSON object. - * @returns A TxL2Logs class object. - */ - public static fromJSON(obj: any) { - const functionLogs = obj.functionLogs.map((log: any) => UnencryptedFunctionL2Logs.fromJSON(log)); - return new ContractClassTxL2Logs(functionLogs); - } - /** * @param logs - Logs to be hashed. * @returns The hash of the logs. diff --git a/yarn-project/circuit-types/src/logs/unencrypted_l2_log.test.ts b/yarn-project/circuit-types/src/logs/unencrypted_l2_log.test.ts index 60f89766d9d..7917be9f8a6 100644 --- a/yarn-project/circuit-types/src/logs/unencrypted_l2_log.test.ts +++ b/yarn-project/circuit-types/src/logs/unencrypted_l2_log.test.ts @@ -1,3 +1,5 @@ +import { jsonStringify } from '@aztec/foundation/json-rpc'; + import { UnencryptedL2Log } from './unencrypted_l2_log.js'; describe('UnencryptedL2Log', () => { @@ -9,4 +11,13 @@ describe('UnencryptedL2Log', () => { expect(recovered).toEqual(l2Logs); }); + + it('can encode to JSON and back', () => { + const l2Logs = UnencryptedL2Log.random(); + + const buffer = jsonStringify(l2Logs); + const recovered = UnencryptedL2Log.schema.parse(JSON.parse(buffer)); + + expect(recovered).toEqual(l2Logs); + }); }); diff --git a/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts b/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts index b43778409a9..942dad32db2 100644 --- a/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts +++ b/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts @@ -48,23 +48,10 @@ export class UnencryptedL2Log { static get schema() { return z - .object({ contractAddress: schemas.AztecAddress, data: schemas.BufferHex }) + .object({ contractAddress: schemas.AztecAddress, data: schemas.Buffer }) .transform(({ contractAddress, data }) => new UnencryptedL2Log(contractAddress, data)); } - /** Returns a JSON-friendly representation of the log. */ - public toJSON(): object { - return { - contractAddress: this.contractAddress.toString(), - data: this.data.toString('hex'), - }; - } - - /** Converts a plain JSON object into an instance. */ - public static fromJSON(obj: any) { - return new UnencryptedL2Log(AztecAddress.fromString(obj.contractAddress), Buffer.from(obj.data, 'hex')); - } - /** * Deserializes log from a buffer. * @param buffer - The buffer or buffer reader containing the log. diff --git a/yarn-project/circuit-types/src/messaging/l1_to_l2_message.ts b/yarn-project/circuit-types/src/messaging/l1_to_l2_message.ts index e68a73a83e8..3dc438940e2 100644 --- a/yarn-project/circuit-types/src/messaging/l1_to_l2_message.ts +++ b/yarn-project/circuit-types/src/messaging/l1_to_l2_message.ts @@ -4,6 +4,7 @@ import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { sha256ToField } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex } from '@aztec/foundation/string'; import { type AztecNode } from '../interfaces/aztec-node.js'; import { MerkleTreeId } from '../merkle_tree_id.js'; @@ -55,7 +56,7 @@ export class L1ToL2Message { } toString(): string { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromString(data: string): L1ToL2Message { diff --git a/yarn-project/circuit-types/src/notes/extended_note.test.ts b/yarn-project/circuit-types/src/notes/extended_note.test.ts index 25a2280b527..a5035cc5406 100644 --- a/yarn-project/circuit-types/src/notes/extended_note.test.ts +++ b/yarn-project/circuit-types/src/notes/extended_note.test.ts @@ -1,18 +1,40 @@ +import { jsonStringify } from '@aztec/foundation/json-rpc'; + import { randomExtendedNote, randomUniqueNote } from '../mocks.js'; import { ExtendedNote, UniqueNote } from './extended_note.js'; -describe('Extended Note', () => { +describe('ExtendedNote', () => { + let note: ExtendedNote; + + beforeEach(() => { + note = randomExtendedNote(); + }); + it('convert to and from buffer', () => { - const extendedNote = randomExtendedNote(); - const buf = extendedNote.toBuffer(); - expect(ExtendedNote.fromBuffer(buf)).toEqual(extendedNote); + const buf = note.toBuffer(); + expect(ExtendedNote.fromBuffer(buf)).toEqual(note); + }); + + it('convert to and from JSON', () => { + const json = jsonStringify(note); + expect(ExtendedNote.schema.parse(JSON.parse(json))).toEqual(note); }); }); -describe('Unique Note', () => { +describe('UniqueNote', () => { + let note: UniqueNote; + + beforeEach(() => { + note = randomUniqueNote(); + }); + it('convert to and from buffer', () => { - const uniqueNote = randomUniqueNote(); - const buf = uniqueNote.toBuffer(); - expect(UniqueNote.fromBuffer(buf)).toEqual(uniqueNote); + const buf = note.toBuffer(); + expect(UniqueNote.fromBuffer(buf)).toEqual(note); + }); + + it('convert to and from JSON', () => { + const json = jsonStringify(note); + expect(UniqueNote.schema.parse(JSON.parse(json))).toEqual(note); }); }); diff --git a/yarn-project/circuit-types/src/notes/extended_note.ts b/yarn-project/circuit-types/src/notes/extended_note.ts index a3c3506cdbb..cac982b01b8 100644 --- a/yarn-project/circuit-types/src/notes/extended_note.ts +++ b/yarn-project/circuit-types/src/notes/extended_note.ts @@ -1,7 +1,10 @@ import { AztecAddress, Fr } from '@aztec/circuits.js'; import { NoteSelector } from '@aztec/foundation/abi'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { schemas } from '@aztec/foundation/schemas'; import { BufferReader } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; + +import { z } from 'zod'; import { Note } from '../logs/l1_payload/payload.js'; import { TxHash } from '../tx/tx_hash.js'; @@ -49,21 +52,27 @@ export class ExtendedNote { return new this(note, owner, contractAddress, storageSlot, noteTypeId, txHash); } - toJSON() { - return this.toString(); - } - static get schema() { - return hexSchemaFor(ExtendedNote); + return z + .object({ + note: Note.schema, + owner: schemas.AztecAddress, + contractAddress: schemas.AztecAddress, + storageSlot: schemas.Fr, + noteTypeId: schemas.NoteSelector, + txHash: TxHash.schema, + }) + .transform(({ note, owner, contractAddress, storageSlot, noteTypeId, txHash }) => { + return new ExtendedNote(note, owner, contractAddress, storageSlot, noteTypeId, txHash); + }); } toString() { - return '0x' + this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromString(str: string) { - const hex = str.replace(/^0x/, ''); - return ExtendedNote.fromBuffer(Buffer.from(hex, 'hex')); + return ExtendedNote.fromBuffer(hexToBuffer(str)); } static random() { @@ -99,7 +108,19 @@ export class UniqueNote extends ExtendedNote { } static override get schema() { - return hexSchemaFor(UniqueNote); + return z + .object({ + note: Note.schema, + owner: schemas.AztecAddress, + contractAddress: schemas.AztecAddress, + storageSlot: schemas.Fr, + noteTypeId: schemas.NoteSelector, + txHash: TxHash.schema, + nonce: schemas.Fr, + }) + .transform(({ note, owner, contractAddress, storageSlot, noteTypeId, txHash, nonce }) => { + return new UniqueNote(note, owner, contractAddress, storageSlot, noteTypeId, txHash, nonce); + }); } override toBuffer(): Buffer { @@ -141,7 +162,6 @@ export class UniqueNote extends ExtendedNote { } static override fromString(str: string) { - const hex = str.replace(/^0x/, ''); - return UniqueNote.fromBuffer(Buffer.from(hex, 'hex')); + return UniqueNote.fromBuffer(hexToBuffer(str)); } } diff --git a/yarn-project/circuit-types/src/p2p/consensus_payload.ts b/yarn-project/circuit-types/src/p2p/consensus_payload.ts index a5ce2fbed50..3c4d5e946b0 100644 --- a/yarn-project/circuit-types/src/p2p/consensus_payload.ts +++ b/yarn-project/circuit-types/src/p2p/consensus_payload.ts @@ -1,6 +1,7 @@ import { Header } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { encodeAbiParameters, parseAbiParameters } from 'viem'; @@ -26,19 +27,19 @@ export class ConsensusPayload implements Signable { getPayloadToSign(domainSeperator: SignatureDomainSeperator): Buffer { const abi = parseAbiParameters('uint8, (bytes32, bytes32, (uint256, uint256), bytes, bytes32[])'); - const txArray = this.txHashes.map(tx => tx.to0xString()); + const txArray = this.txHashes.map(tx => tx.toString()); const encodedData = encodeAbiParameters(abi, [ domainSeperator, [ this.archive.toString(), this.header.hash().toString(), [0n, 0n] /* @todo See #9963 */, - `0x${this.header.toString()}`, + this.header.toString(), txArray, ], ] as const); - return Buffer.from(encodedData.slice(2), 'hex'); + return hexToBuffer(encodedData); } toBuffer(): Buffer { diff --git a/yarn-project/circuit-types/src/private_execution_result.test.ts b/yarn-project/circuit-types/src/private_execution_result.test.ts index f67092467df..1b3a97f766e 100644 --- a/yarn-project/circuit-types/src/private_execution_result.test.ts +++ b/yarn-project/circuit-types/src/private_execution_result.test.ts @@ -1,5 +1,5 @@ import { Fr, PrivateCircuitPublicInputs } from '@aztec/circuits.js'; -import { jsonStringify } from '@aztec/foundation/json-rpc'; +import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc'; import { PrivateExecutionResult, @@ -36,8 +36,11 @@ describe('execution_result', () => { }); describe('serialization', () => { - const instance = PrivateExecutionResult.random(); - expect(PrivateExecutionResult.schema.parse(JSON.parse(jsonStringify(instance)))).toEqual(instance); + it('serializes and deserializes correctly', () => { + const instance = PrivateExecutionResult.random(); + jsonParseWithSchema; + expect(jsonParseWithSchema(jsonStringify(instance), PrivateExecutionResult.schema)).toEqual(instance); + }); }); describe('collectNoteHashLeafIndexMap', () => { diff --git a/yarn-project/circuit-types/src/private_execution_result.ts b/yarn-project/circuit-types/src/private_execution_result.ts index 588c4c44ab2..893ecc0ad4f 100644 --- a/yarn-project/circuit-types/src/private_execution_result.ts +++ b/yarn-project/circuit-types/src/private_execution_result.ts @@ -3,7 +3,7 @@ import { NoteSelector } from '@aztec/foundation/abi'; import { times } from '@aztec/foundation/collection'; import { randomBytes, randomInt } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; -import { type ZodFor, hexSchemaFor, mapSchema, schemas } from '@aztec/foundation/schemas'; +import { type ZodFor, mapSchema, schemas } from '@aztec/foundation/schemas'; import { type FieldsOf } from '@aztec/foundation/types'; import { z } from 'zod'; @@ -46,22 +46,6 @@ export class NoteAndSlot { return new NoteAndSlot(fields.note, fields.storageSlot, fields.noteTypeId); } - toJSON() { - return { - note: this.note.toBuffer().toString('hex'), - storageSlot: this.storageSlot.toBuffer().toString('hex'), - noteTypeId: this.noteTypeId.toString(), - }; - } - - public static fromJSON(json: any): NoteAndSlot { - return new NoteAndSlot( - Note.fromBuffer(Buffer.from(json.note, 'hex')), - Fr.fromString(json.storageSlot), - NoteSelector.fromString(json.noteTypeId), - ); - } - static random() { return new NoteAndSlot(Note.random(), Fr.random(), NoteSelector.random()); } @@ -115,18 +99,6 @@ export class CountedNoteLog extends CountedLog { .transform(({ log, counter, noteHashCounter }) => new CountedNoteLog(log, counter, noteHashCounter)); } - toJSON() { - return { - log: this.log.toJSON(), - counter: this.counter, - noteHashCounter: this.noteHashCounter, - }; - } - - static fromJSON(json: any) { - return new CountedNoteLog(EncryptedL2NoteLog.fromJSON(json.log), json.counter, json.noteHashCounter); - } - static random() { return new CountedNoteLog(EncryptedL2NoteLog.random(), randomInt(10), randomInt(10)); } @@ -138,7 +110,7 @@ export class CountedPublicExecutionRequest { static get schema() { return z .object({ - request: hexSchemaFor(PublicExecutionRequest), // TODO(palla/schema) Use PublicExecutionRequest.schema, + request: PublicExecutionRequest.schema, counter: schemas.Integer, }) .transform(CountedPublicExecutionRequest.from); @@ -152,20 +124,6 @@ export class CountedPublicExecutionRequest { return this.request.isEmpty() && !this.counter; } - toJSON() { - return { - request: this.request.toBuffer().toString('hex'), - counter: this.counter, - }; - } - - static fromJSON(json: any) { - return new CountedPublicExecutionRequest( - PublicExecutionRequest.fromBuffer(Buffer.from(json.request, 'hex')), - json.counter, - ); - } - static random() { return new CountedPublicExecutionRequest(PublicExecutionRequest.random(), 0); } @@ -220,8 +178,8 @@ export class PrivateExecutionResult { static get schema(): ZodFor { return z .object({ - acir: schemas.BufferHex, - vk: schemas.BufferHex, + acir: schemas.Buffer, + vk: schemas.Buffer, partialWitness: mapSchema(z.coerce.number(), z.string()), publicInputs: PrivateCircuitPublicInputs.schema, noteHashLeafIndexMap: mapSchema(schemas.BigInt, schemas.BigInt), @@ -230,7 +188,7 @@ export class PrivateExecutionResult { returnValues: z.array(schemas.Fr), nestedExecutions: z.array(z.lazy(() => PrivateExecutionResult.schema)), enqueuedPublicFunctionCalls: z.array(CountedPublicExecutionRequest.schema), - publicTeardownFunctionCall: hexSchemaFor(PublicExecutionRequest), // TODO(palla/schema) Use PublicExecutionRequest.schema + publicTeardownFunctionCall: PublicExecutionRequest.schema, noteEncryptedLogs: z.array(CountedNoteLog.schema), encryptedLogs: z.array(CountedLog.schemaFor(EncryptedL2Log)), contractClassLogs: z.array(CountedLog.schemaFor(UnencryptedL2Log)), @@ -257,34 +215,6 @@ export class PrivateExecutionResult { ); } - toJSON(): any { - return { - acir: this.acir.toString('hex'), - vk: this.vk.toString('hex'), - partialWitness: Array.from(this.partialWitness.entries()), - publicInputs: this.publicInputs.toJSON(), - noteHashLeafIndexMap: Array.from(this.noteHashLeafIndexMap.entries()).map(([key, value]) => [ - key.toString(), - value.toString(), - ]), - newNotes: this.newNotes.map(note => note.toJSON()), - noteHashNullifierCounterMap: Array.from(this.noteHashNullifierCounterMap.entries()), - returnValues: this.returnValues.map(fr => fr.toBuffer().toString('hex')), - nestedExecutions: this.nestedExecutions.map(exec => exec.toJSON()), - enqueuedPublicFunctionCalls: this.enqueuedPublicFunctionCalls.map(call => call.toJSON()), - publicTeardownFunctionCall: this.publicTeardownFunctionCall.toBuffer().toString('hex'), - noteEncryptedLogs: this.noteEncryptedLogs.map(log => log.toJSON()), - encryptedLogs: this.encryptedLogs.map(countedLog => ({ - log: countedLog.log.toJSON(), - counter: countedLog.counter, - })), - contractClassLogs: this.contractClassLogs.map(countedLog => ({ - log: countedLog.log.toJSON(), - counter: countedLog.counter, - })), - }; - } - static random(nested = 1): PrivateExecutionResult { return new PrivateExecutionResult( randomBytes(4), @@ -303,45 +233,6 @@ export class PrivateExecutionResult { [new CountedLog(UnencryptedL2Log.random(), randomInt(10))], ); } - - static fromJSON(json: any): PrivateExecutionResult { - return new PrivateExecutionResult( - Buffer.from(json.acir, 'hex'), - Buffer.from(json.vk, 'hex'), - Array.isArray(json.partialWitness) - ? new Map(json.partialWitness.map(([key, value]: any[]) => [Number(key), value as string])) - : new Map(), - PrivateCircuitPublicInputs.fromJSON(json.publicInputs), - Array.isArray(json.noteHashLeafIndexMap) - ? new Map(json.noteHashLeafIndexMap.map(([key, value]: any[]) => [BigInt(key), BigInt(value)])) - : new Map(), - Array.isArray(json.newNotes) ? json.newNotes.map((note: any) => NoteAndSlot.fromJSON(note)) : [], - Array.isArray(json.noteHashNullifierCounterMap) - ? new Map(json.noteHashNullifierCounterMap.map(([key, value]: any[]) => [Number(key), Number(value)])) - : new Map(), - json.returnValues.map((fr: any) => new Fr(Buffer.from(fr, 'hex'))), - Array.isArray(json.nestedExecutions) - ? json.nestedExecutions.map((exec: any) => PrivateExecutionResult.fromJSON(exec)) - : [], - Array.isArray(json.enqueuedPublicFunctionCalls) - ? json.enqueuedPublicFunctionCalls.map((call: any) => CountedPublicExecutionRequest.fromJSON(call)) - : [], - PublicExecutionRequest.fromBuffer(Buffer.from(json.publicTeardownFunctionCall, 'hex')), - Array.isArray(json.noteEncryptedLogs) - ? json.noteEncryptedLogs.map((json: any) => CountedNoteLog.fromJSON(json)) - : [], - Array.isArray(json.encryptedLogs) - ? json.encryptedLogs.map( - (json: any) => new CountedLog(EncryptedL2Log.fromJSON(json.log), json.counter), - ) - : [], - Array.isArray(json.contractClassLogs) - ? json.contractClassLogs.map( - (json: any) => new CountedLog(UnencryptedL2Log.fromJSON(json.log), json.counter), - ) - : [], - ); - } } export function collectNoteHashLeafIndexMap( diff --git a/yarn-project/circuit-types/src/prover_coordination/epoch_proof_quote.test.ts b/yarn-project/circuit-types/src/prover_coordination/epoch_proof_quote.test.ts index 78f68edee04..fe29fcb941d 100644 --- a/yarn-project/circuit-types/src/prover_coordination/epoch_proof_quote.test.ts +++ b/yarn-project/circuit-types/src/prover_coordination/epoch_proof_quote.test.ts @@ -1,5 +1,6 @@ import { EthAddress } from '@aztec/circuits.js'; import { Signature } from '@aztec/foundation/eth-signature'; +import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc'; import { EpochProofQuote } from './epoch_proof_quote.js'; import { EpochProofQuotePayload } from './epoch_proof_quote_payload.js'; @@ -30,7 +31,7 @@ describe('epoch proof quote', () => { }); it('should serialize and deserialize from JSON', () => { - const deserialised = EpochProofQuote.fromJSON(quote.toJSON()); + const deserialised = jsonParseWithSchema(jsonStringify(quote), EpochProofQuote.schema); checkEquivalence(quote, deserialised); }); }); diff --git a/yarn-project/circuit-types/src/prover_coordination/epoch_proof_quote.ts b/yarn-project/circuit-types/src/prover_coordination/epoch_proof_quote.ts index d6f7222cf8b..454d01aa585 100644 --- a/yarn-project/circuit-types/src/prover_coordination/epoch_proof_quote.ts +++ b/yarn-project/circuit-types/src/prover_coordination/epoch_proof_quote.ts @@ -1,7 +1,6 @@ import { Buffer32 } from '@aztec/foundation/buffer'; import { type Secp256k1Signer, keccak256 } from '@aztec/foundation/crypto'; import { Signature } from '@aztec/foundation/eth-signature'; -import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; @@ -44,26 +43,15 @@ export class EpochProofQuote extends Gossipable { return new EpochProofQuote(reader.readObject(EpochProofQuotePayload), reader.readObject(Signature)); } - toJSON() { - return { - payload: this.payload.toJSON(), - signature: this.signature.to0xString(), - }; - } - static get schema() { return z .object({ payload: EpochProofQuotePayload.schema, - signature: schemas.Signature, + signature: Signature.schema, }) .transform(({ payload, signature }) => new EpochProofQuote(payload, signature)); } - static fromJSON(obj: any) { - return EpochProofQuote.schema.parse(obj); - } - // TODO: https://github.com/AztecProtocol/aztec-packages/issues/8911 /** * Creates a new quote with a signature. diff --git a/yarn-project/circuit-types/src/prover_coordination/epoch_proof_quote_payload.ts b/yarn-project/circuit-types/src/prover_coordination/epoch_proof_quote_payload.ts index 7f1e87eee87..60c06e39501 100644 --- a/yarn-project/circuit-types/src/prover_coordination/epoch_proof_quote_payload.ts +++ b/yarn-project/circuit-types/src/prover_coordination/epoch_proof_quote_payload.ts @@ -3,6 +3,7 @@ import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; +import omit from 'lodash.omit'; import { inspect } from 'util'; import { z } from 'zod'; @@ -82,31 +83,21 @@ export class EpochProofQuotePayload { } toJSON() { - return { - epochToProve: this.epochToProve.toString(), - validUntilSlot: this.validUntilSlot.toString(), - bondAmount: this.bondAmount.toString(), - prover: this.prover.toString(), - basisPointFee: this.basisPointFee, - }; + return omit(this, 'asBuffer', 'size'); } static get schema() { return z .object({ - epochToProve: z.coerce.bigint(), - validUntilSlot: z.coerce.bigint(), - bondAmount: z.coerce.bigint(), + epochToProve: schemas.BigInt, + validUntilSlot: schemas.BigInt, + bondAmount: schemas.BigInt, prover: schemas.EthAddress, - basisPointFee: z.number(), + basisPointFee: schemas.Integer, }) .transform(EpochProofQuotePayload.from); } - static fromJSON(obj: any): EpochProofQuotePayload { - return EpochProofQuotePayload.schema.parse(obj); - } - toViemArgs(): { epochToProve: bigint; validUntilSlot: bigint; diff --git a/yarn-project/circuit-types/src/public_data_witness.ts b/yarn-project/circuit-types/src/public_data_witness.ts index cdc33705231..41e43418b9a 100644 --- a/yarn-project/circuit-types/src/public_data_witness.ts +++ b/yarn-project/circuit-types/src/public_data_witness.ts @@ -2,6 +2,7 @@ import { Fr, PUBLIC_DATA_TREE_HEIGHT, PublicDataTreeLeafPreimage } from '@aztec/ import { toBigIntBE } from '@aztec/foundation/bigint-buffer'; import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { z } from 'zod'; @@ -63,7 +64,7 @@ export class PublicDataWitness { * Returns a string representation of the TxEffect object. */ toString(): string { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static random() { @@ -95,6 +96,6 @@ export class PublicDataWitness { * @returns An instance of PublicDataWitness. */ static fromString(str: string) { - return PublicDataWitness.fromBuffer(Buffer.from(str, 'hex')); + return PublicDataWitness.fromBuffer(hexToBuffer(str)); } } diff --git a/yarn-project/circuit-types/src/public_execution_request.ts b/yarn-project/circuit-types/src/public_execution_request.ts index 7cf834cb1c8..6371bac3b09 100644 --- a/yarn-project/circuit-types/src/public_execution_request.ts +++ b/yarn-project/circuit-types/src/public_execution_request.ts @@ -40,13 +40,6 @@ export class PublicExecutionRequest { .transform(PublicExecutionRequest.from); } - toJSON() { - return { - callContext: this.callContext, - args: this.args, - }; - } - static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); return new PublicExecutionRequest(CallContext.fromBuffer(reader), reader.readVector(Fr)); diff --git a/yarn-project/circuit-types/src/sibling_path/sibling_path.test.ts b/yarn-project/circuit-types/src/sibling_path/sibling_path.test.ts new file mode 100644 index 00000000000..d48e32e820b --- /dev/null +++ b/yarn-project/circuit-types/src/sibling_path/sibling_path.test.ts @@ -0,0 +1,19 @@ +import { jsonStringify } from '@aztec/foundation/json-rpc'; + +import { SiblingPath } from './sibling_path.js'; + +describe('SiblingPath', () => { + it('serializes to JSON', () => { + const path = SiblingPath.random(10); + const json = jsonStringify(path); + expect(SiblingPath.schema.parse(JSON.parse(json))).toEqual(path); + }); + + it('validates length', () => { + const path = SiblingPath.random(10); + const json = jsonStringify(path); + expect(() => SiblingPath.schemaFor(12).parse(JSON.parse(json))).toThrow( + expect.objectContaining({ name: 'ZodError' }), + ); + }); +}); diff --git a/yarn-project/circuit-types/src/sibling_path/sibling_path.ts b/yarn-project/circuit-types/src/sibling_path/sibling_path.ts index a18d02ce951..96738dab368 100644 --- a/yarn-project/circuit-types/src/sibling_path/sibling_path.ts +++ b/yarn-project/circuit-types/src/sibling_path/sibling_path.ts @@ -1,12 +1,13 @@ import { makeTuple } from '@aztec/foundation/array'; import { Fr } from '@aztec/foundation/fields'; -import { hexSchema, hexSchemaFor } from '@aztec/foundation/schemas'; +import { schemas } from '@aztec/foundation/schemas'; import { type Tuple, assertLength, deserializeArrayFromVector, serializeArrayOfBufferableToVector, } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type Hasher } from '@aztec/types/interfaces'; /** @@ -37,17 +38,18 @@ export class SiblingPath { } static get schema() { - return hexSchemaFor(SiblingPath); + return schemas.Buffer.transform(b => SiblingPath.fromBuffer(b)); } static schemaFor(size: N) { - return hexSchema - .transform(str => SiblingPath.fromString(str) as SiblingPath) - .refine(path => path.pathSize === size, 'Unexpected size'); + return schemas.Buffer.transform(b => SiblingPath.fromBuffer(b) as SiblingPath).refine( + path => path.pathSize === size, + path => ({ message: `Expected sibling path size ${size} but got ${path.pathSize}` }), + ); } toJSON() { - return this.toString(); + return this.toBuffer(); } /** @@ -137,7 +139,7 @@ export class SiblingPath { * @returns A hex string representation of the sibling path. */ public toString(): string { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -146,7 +148,7 @@ export class SiblingPath { * @returns A SiblingPath object. */ public static fromString(repr: string): SiblingPath { - return SiblingPath.fromBuffer(Buffer.from(repr, 'hex')); + return SiblingPath.fromBuffer(hexToBuffer(repr)); } /** diff --git a/yarn-project/circuit-types/src/simulation_error.ts b/yarn-project/circuit-types/src/simulation_error.ts index 70cd960217a..3e84bbdb60e 100644 --- a/yarn-project/circuit-types/src/simulation_error.ts +++ b/yarn-project/circuit-types/src/simulation_error.ts @@ -1,4 +1,4 @@ -import { AztecAddress, Fr, FunctionSelector } from '@aztec/circuits.js'; +import { AztecAddress, type Fr, FunctionSelector } from '@aztec/circuits.js'; import { type OpcodeLocation } from '@aztec/foundation/abi'; import { schemas } from '@aztec/foundation/schemas'; @@ -220,15 +220,6 @@ export class SimulationError extends Error { }; } - static fromJSON(obj: ReturnType) { - return new SimulationError( - obj.originalMessage, - obj.functionErrorStack, - obj.revertData.map(serializedFr => Fr.fromString(serializedFr)), - obj.noirErrorStack, - ); - } - static get schema() { return z .object({ diff --git a/yarn-project/circuit-types/src/tx/block_hash.ts b/yarn-project/circuit-types/src/tx/block_hash.ts new file mode 100644 index 00000000000..010b2e6ca16 --- /dev/null +++ b/yarn-project/circuit-types/src/tx/block_hash.ts @@ -0,0 +1,29 @@ +import { Fr } from '@aztec/circuits.js'; +import { Buffer32 } from '@aztec/foundation/buffer'; +import { schemas } from '@aztec/foundation/schemas'; + +/** Hash of an L2 block. */ +export class L2BlockHash extends Buffer32 { + constructor( + /** The buffer containing the hash. */ + hash: Buffer, + ) { + super(hash); + } + + static override random() { + return new L2BlockHash(Fr.random().toBuffer()); + } + + static get schema() { + return schemas.BufferHex.transform(value => new L2BlockHash(value)); + } + + static zero() { + return new L2BlockHash(Buffer32.ZERO.toBuffer()); + } + + static override fromField(hash: Fr) { + return new L2BlockHash(hash.toBuffer()); + } +} diff --git a/yarn-project/circuit-types/src/tx/index.ts b/yarn-project/circuit-types/src/tx/index.ts index bc94339f36b..30cae14ee88 100644 --- a/yarn-project/circuit-types/src/tx/index.ts +++ b/yarn-project/circuit-types/src/tx/index.ts @@ -7,3 +7,4 @@ export * from './tx_hash.js'; export * from './tx_receipt.js'; export * from './validator/tx_validator.js'; export * from './validator/empty_validator.js'; +export * from './block_hash.js'; diff --git a/yarn-project/circuit-types/src/tx/public_simulation_output.test.ts b/yarn-project/circuit-types/src/tx/public_simulation_output.test.ts new file mode 100644 index 00000000000..8582164a408 --- /dev/null +++ b/yarn-project/circuit-types/src/tx/public_simulation_output.test.ts @@ -0,0 +1,11 @@ +import { jsonStringify } from '@aztec/foundation/json-rpc'; + +import { PublicSimulationOutput } from './public_simulation_output.js'; + +describe('PublicSimulationOutput', () => { + it('serializes to JSON', () => { + const output = PublicSimulationOutput.random(); + const json = jsonStringify(output); + expect(PublicSimulationOutput.schema.parse(JSON.parse(json))).toEqual(output); + }); +}); diff --git a/yarn-project/circuit-types/src/tx/public_simulation_output.ts b/yarn-project/circuit-types/src/tx/public_simulation_output.ts index a6748c071aa..98ca5e8fc60 100644 --- a/yarn-project/circuit-types/src/tx/public_simulation_output.ts +++ b/yarn-project/circuit-types/src/tx/public_simulation_output.ts @@ -1,5 +1,4 @@ import { CombinedConstantData, Fr, Gas } from '@aztec/circuits.js'; -import { mapValues } from '@aztec/foundation/collection'; import { type ZodFor, schemas } from '@aztec/foundation/schemas'; import times from 'lodash.times'; @@ -31,20 +30,6 @@ export class NestedProcessReturnValues { .transform(({ values, nested }) => new NestedProcessReturnValues(values, nested)); } - toJSON(): any { - return { - values: this.values?.map(fr => fr.toString()), - nested: this.nested.map(n => n.toJSON()), - }; - } - - static fromJSON(json: any): NestedProcessReturnValues { - return new NestedProcessReturnValues( - json.values?.map(Fr.fromString), - json.nested?.map((n: any) => NestedProcessReturnValues.fromJSON(n)), - ); - } - static empty() { return new NestedProcessReturnValues([]); } @@ -90,28 +75,6 @@ export class PublicSimulationOutput { ); } - toJSON() { - return { - revertReason: this.revertReason, - constants: this.constants.toBuffer().toString('hex'), - txEffect: this.txEffect.toBuffer().toString('hex'), - publicReturnValues: this.publicReturnValues.map(returns => returns?.toJSON()), - gasUsed: mapValues(this.gasUsed, gas => gas?.toJSON()), - }; - } - - static fromJSON(json: any): PublicSimulationOutput { - return new PublicSimulationOutput( - json.revertReason, - CombinedConstantData.fromBuffer(Buffer.from(json.constants, 'hex')), - TxEffect.fromBuffer(Buffer.from(json.txEffect, 'hex')), - Array.isArray(json.publicReturnValues) - ? json.publicReturnValues.map((returns: any) => NestedProcessReturnValues.fromJSON(returns)) - : [], - mapValues(json.gasUsed, gas => Gas.fromJSON(gas)), - ); - } - static random() { return new PublicSimulationOutput( SimulationError.random(), diff --git a/yarn-project/circuit-types/src/tx/simulated_tx.test.ts b/yarn-project/circuit-types/src/tx/simulated_tx.test.ts index 035bab4f517..a12a51e3452 100644 --- a/yarn-project/circuit-types/src/tx/simulated_tx.test.ts +++ b/yarn-project/circuit-types/src/tx/simulated_tx.test.ts @@ -1,18 +1,33 @@ +import { jsonStringify } from '@aztec/foundation/json-rpc'; + import { mockSimulatedTx } from '../mocks.js'; -import { TxSimulationResult } from './simulated_tx.js'; +import { TxProvingResult, TxSimulationResult } from './simulated_tx.js'; describe('simulated_tx', () => { - let simulatedTx: TxSimulationResult; - beforeEach(() => { - simulatedTx = mockSimulatedTx(); - }); - describe('json', () => { + describe('TxSimulationResult', () => { + let simulatedTx: TxSimulationResult; + beforeEach(() => { + simulatedTx = mockSimulatedTx(); + }); + it('convert to and from json', () => { - expect(TxSimulationResult.fromJSON(JSON.parse(JSON.stringify(simulatedTx.toJSON())))).toEqual(simulatedTx); + expect(TxSimulationResult.schema.parse(JSON.parse(jsonStringify(simulatedTx)))).toEqual(simulatedTx); }); + it('convert undefined effects to and from json', () => { simulatedTx.publicOutput = undefined; - expect(TxSimulationResult.fromJSON(JSON.parse(JSON.stringify(simulatedTx.toJSON())))).toEqual(simulatedTx); + expect(TxSimulationResult.schema.parse(JSON.parse(jsonStringify(simulatedTx)))).toEqual(simulatedTx); + }); + }); + + describe('TxProvingResult', () => { + let tx: TxProvingResult; + beforeEach(() => { + tx = TxProvingResult.random(); + }); + + it('convert to and from json', () => { + expect(TxProvingResult.schema.parse(JSON.parse(jsonStringify(tx)))).toEqual(tx); }); }); }); diff --git a/yarn-project/circuit-types/src/tx/simulated_tx.ts b/yarn-project/circuit-types/src/tx/simulated_tx.ts index 62c6270908c..f53e55e2923 100644 --- a/yarn-project/circuit-types/src/tx/simulated_tx.ts +++ b/yarn-project/circuit-types/src/tx/simulated_tx.ts @@ -55,19 +55,6 @@ export class PrivateSimulationResult { ); return tx; } - - public toJSON() { - return { - privateExecutionResult: this.privateExecutionResult.toJSON(), - publicInputs: this.publicInputs.toBuffer().toString('hex'), - }; - } - - public static fromJSON(obj: any) { - const privateExecutionResult = PrivateExecutionResult.fromJSON(obj.privateExecutionResult); - const publicInputs = PrivateKernelTailCircuitPublicInputs.fromBuffer(Buffer.from(obj.publicInputs, 'hex')); - return new PrivateSimulationResult(privateExecutionResult, publicInputs); - } } export class TxSimulationResult extends PrivateSimulationResult { @@ -126,21 +113,12 @@ export class TxSimulationResult extends PrivateSimulationResult { ); } - public override toJSON() { - return { - privateExecutionResult: this.privateExecutionResult.toJSON(), - publicInputs: this.publicInputs.toBuffer().toString('hex'), - publicOutput: this.publicOutput ? this.publicOutput.toJSON() : undefined, - profileResult: this.profileResult, - }; - } - - public static override fromJSON(obj: any) { - const privateExecutionResult = PrivateExecutionResult.fromJSON(obj.privateExecutionResult); - const publicInputs = PrivateKernelTailCircuitPublicInputs.fromBuffer(Buffer.from(obj.publicInputs, 'hex')); - const publicOuput = obj.publicOutput ? PublicSimulationOutput.fromJSON(obj.publicOutput) : undefined; - const profileResult = obj.profileResult; - return new TxSimulationResult(privateExecutionResult, publicInputs, publicOuput, profileResult); + static random() { + return new TxSimulationResult( + PrivateExecutionResult.random(), + PrivateKernelTailCircuitPublicInputs.empty(), + PublicSimulationOutput.random(), + ); } } @@ -186,19 +164,12 @@ export class TxProvingResult { return new TxProvingResult(fields.privateExecutionResult, fields.publicInputs, fields.clientIvcProof); } - public toJSON() { - return { - privateExecutionResult: this.privateExecutionResult, - publicInputs: this.publicInputs, - clientIvcProof: this.clientIvcProof, - }; - } - - public static fromJSON(obj: any) { - const privateExecutionResult = PrivateExecutionResult.fromJSON(obj.privateExecutionResult); - const publicInputs = PrivateKernelTailCircuitPublicInputs.fromBuffer(Buffer.from(obj.publicInputs, 'hex')); - const clientIvcProof = ClientIvcProof.fromBuffer(Buffer.from(obj.clientIvcProof, 'hex')); - return new TxProvingResult(privateExecutionResult, publicInputs, clientIvcProof); + static random() { + return new TxProvingResult( + PrivateExecutionResult.random(), + PrivateKernelTailCircuitPublicInputs.empty(), + ClientIvcProof.empty(), + ); } } diff --git a/yarn-project/circuit-types/src/tx/tx.test.ts b/yarn-project/circuit-types/src/tx/tx.test.ts index 3cfe2c1a4eb..0710303b16b 100644 --- a/yarn-project/circuit-types/src/tx/tx.test.ts +++ b/yarn-project/circuit-types/src/tx/tx.test.ts @@ -1,3 +1,5 @@ +import { jsonStringify } from '@aztec/foundation/json-rpc'; + import { mockTx } from '../mocks.js'; import { Tx } from './tx.js'; @@ -7,4 +9,10 @@ describe('Tx', () => { const buf = tx.toBuffer(); expect(Tx.fromBuffer(buf)).toEqual(tx); }); + + it('convert to and from json', () => { + const tx = mockTx(); + const json = jsonStringify(tx); + expect(Tx.schema.parse(JSON.parse(json))).toEqual(tx); + }); }); diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index e290ad2a46f..d049697cec3 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -7,8 +7,8 @@ import { } from '@aztec/circuits.js'; import { type Buffer32 } from '@aztec/foundation/buffer'; import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; -import { hexSchema } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type FieldsOf } from '@aztec/foundation/types'; import { z } from 'zod'; @@ -154,65 +154,30 @@ export class Tx extends Gossipable { } static get schema() { - // TODO(palla/schemas): Use the nested objects schemas as opposed to the toBuffers return z .object({ - data: hexSchema, // PrivateKernelTailCircuitPublicInputs.schema, - clientIvcProof: hexSchema, // ClientIvcProof.schema, - noteEncryptedLogs: hexSchema, // EncryptedNoteTxL2Logs.schema, - encryptedLogs: hexSchema, // EncryptedTxL2Logs.schema, - unencryptedLogs: hexSchema, // UnencryptedTxL2Logs.schema, - contractClassLogs: hexSchema, // ContractClassTxL2Logs.schema, - enqueuedPublicFunctionCalls: z.array(hexSchema), // z.array(PublicExecutionRequest.schema), - publicTeardownFunctionCall: hexSchema, // PublicExecutionRequest.schema, + data: PrivateKernelTailCircuitPublicInputs.schema, + clientIvcProof: ClientIvcProof.schema, + noteEncryptedLogs: EncryptedNoteTxL2Logs.schema, + encryptedLogs: EncryptedTxL2Logs.schema, + unencryptedLogs: UnencryptedTxL2Logs.schema, + contractClassLogs: ContractClassTxL2Logs.schema, + enqueuedPublicFunctionCalls: z.array(PublicExecutionRequest.schema), + publicTeardownFunctionCall: PublicExecutionRequest.schema, }) - .transform(Tx.fromJSON); + .transform(Tx.from); } - /** - * Convert a Tx class object to a plain JSON object. - * @returns A plain object with Tx properties. - */ - public toJSON() { - return { - data: this.data.toBuffer().toString('hex'), - noteEncryptedLogs: this.noteEncryptedLogs.toBuffer().toString('hex'), - encryptedLogs: this.encryptedLogs.toBuffer().toString('hex'), - unencryptedLogs: this.unencryptedLogs.toBuffer().toString('hex'), - contractClassLogs: this.contractClassLogs.toBuffer().toString('hex'), - clientIvcProof: this.clientIvcProof.toBuffer().toString('hex'), - enqueuedPublicFunctionCalls: this.enqueuedPublicFunctionCalls.map(f => f.toBuffer().toString('hex')) ?? [], - publicTeardownFunctionCall: this.publicTeardownFunctionCall.toBuffer().toString('hex'), - }; - } - - /** - * Convert a plain JSON object to a Tx class object. - * @param obj - A plain Tx JSON object. - * @returns A Tx class object. - */ - public static fromJSON(obj: any) { - const publicInputs = PrivateKernelTailCircuitPublicInputs.fromBuffer(Buffer.from(obj.data, 'hex')); - const noteEncryptedLogs = EncryptedNoteTxL2Logs.fromBuffer(Buffer.from(obj.noteEncryptedLogs, 'hex')); - const encryptedLogs = EncryptedTxL2Logs.fromBuffer(Buffer.from(obj.encryptedLogs, 'hex')); - const unencryptedLogs = UnencryptedTxL2Logs.fromBuffer(Buffer.from(obj.unencryptedLogs, 'hex')); - const contractClassLogs = ContractClassTxL2Logs.fromBuffer(Buffer.from(obj.contractClassLogs, 'hex')); - const clientIvcProof = ClientIvcProof.fromBuffer(Buffer.from(obj.clientIvcProof, 'hex')); - const enqueuedPublicFunctionCalls = obj.enqueuedPublicFunctionCalls - ? obj.enqueuedPublicFunctionCalls.map((x: string) => PublicExecutionRequest.fromBuffer(Buffer.from(x, 'hex'))) - : []; - const publicTeardownFunctionCall = PublicExecutionRequest.fromBuffer( - Buffer.from(obj.publicTeardownFunctionCall, 'hex'), - ); + static from(fields: FieldsOf) { return new Tx( - publicInputs, - clientIvcProof, - noteEncryptedLogs, - encryptedLogs, - unencryptedLogs, - contractClassLogs, - enqueuedPublicFunctionCalls, - publicTeardownFunctionCall, + fields.data, + fields.clientIvcProof, + fields.noteEncryptedLogs, + fields.encryptedLogs, + fields.unencryptedLogs, + fields.contractClassLogs, + fields.enqueuedPublicFunctionCalls, + fields.publicTeardownFunctionCall, ); } diff --git a/yarn-project/circuit-types/src/tx/tx_receipt.test.ts b/yarn-project/circuit-types/src/tx/tx_receipt.test.ts index 2eac60ece2e..b55ec33b7a8 100644 --- a/yarn-project/circuit-types/src/tx/tx_receipt.test.ts +++ b/yarn-project/circuit-types/src/tx/tx_receipt.test.ts @@ -1,3 +1,6 @@ +import { jsonStringify } from '@aztec/foundation/json-rpc'; + +import { L2BlockHash } from './block_hash.js'; import { TxHash } from './tx_hash.js'; import { TxReceipt, TxStatus } from './tx_receipt.js'; @@ -8,16 +11,16 @@ describe('TxReceipt', () => { TxStatus.SUCCESS, 'error', BigInt(1), - Buffer.from('blockHash'), + L2BlockHash.random(), undefined, ); - expect(TxReceipt.fromJSON(receipt.toJSON())).toEqual(receipt); + expect(TxReceipt.schema.parse(JSON.parse(jsonStringify(receipt)))).toEqual(receipt); }); it('serializes and deserializes from json with undefined fields', () => { const receipt = new TxReceipt(TxHash.random(), TxStatus.DROPPED, 'error', undefined, undefined, undefined); - expect(TxReceipt.fromJSON(receipt.toJSON())).toEqual(receipt); + expect(TxReceipt.schema.parse(JSON.parse(jsonStringify(receipt)))).toEqual(receipt); }); }); diff --git a/yarn-project/circuit-types/src/tx/tx_receipt.ts b/yarn-project/circuit-types/src/tx/tx_receipt.ts index 280dae346b7..50b6c840086 100644 --- a/yarn-project/circuit-types/src/tx/tx_receipt.ts +++ b/yarn-project/circuit-types/src/tx/tx_receipt.ts @@ -5,6 +5,7 @@ import { type FieldsOf } from '@aztec/foundation/types'; import { z } from 'zod'; +import { L2BlockHash } from './block_hash.js'; import { TxHash } from './tx_hash.js'; /** @@ -36,7 +37,7 @@ export class TxReceipt { /** The transaction fee paid for the transaction. */ public transactionFee?: bigint, /** The hash of the block containing the transaction. */ - public blockHash?: Buffer, + public blockHash?: L2BlockHash, /** The block number in which the transaction was included. */ public blockNumber?: number, /** Information useful for testing/debugging, set when test flag is set to true in `waitOpts`. */ @@ -47,29 +48,13 @@ export class TxReceipt { return new TxReceipt(TxHash.zero(), TxStatus.DROPPED, ''); } - /** - * Convert a Tx class object to a plain JSON object. - * @returns A plain object with Tx properties. - */ - public toJSON() { - return { - txHash: this.txHash.toString(), - status: this.status.toString(), - error: this.error, - blockHash: this.blockHash?.toString('hex'), - blockNumber: this.blockNumber, - transactionFee: this.transactionFee?.toString(), - ...(this.debugInfo && { debugInfo: this.debugInfo }), - }; - } - static get schema() { return z .object({ txHash: TxHash.schema, status: z.nativeEnum(TxStatus), error: z.string(), - blockHash: schemas.BufferHex.optional(), + blockHash: L2BlockHash.schema.optional(), blockNumber: z.number().optional(), transactionFee: schemas.BigInt.optional(), debugInfo: DebugInfoSchema.optional(), @@ -89,21 +74,6 @@ export class TxReceipt { ); } - /** - * Convert a plain JSON object to a Tx class object. - * @param obj - A plain Tx JSON object. - * @returns A Tx class object. - */ - public static fromJSON(obj: any) { - const txHash = TxHash.fromString(obj.txHash); - const status = obj.status as TxStatus; - const error = obj.error; - const transactionFee = obj.transactionFee ? BigInt(obj.transactionFee) : undefined; - const blockHash = obj.blockHash ? Buffer.from(obj.blockHash, 'hex') : undefined; - const blockNumber = obj.blockNumber ? Number(obj.blockNumber) : undefined; - return new TxReceipt(txHash, status, error, transactionFee, blockHash, blockNumber); - } - public static statusFromRevertCode(revertCode: RevertCode) { if (revertCode.equals(RevertCode.OK)) { return TxStatus.SUCCESS; diff --git a/yarn-project/circuit-types/src/tx_effect.ts b/yarn-project/circuit-types/src/tx_effect.ts index 8a06a7fb09b..3a00f06c9a2 100644 --- a/yarn-project/circuit-types/src/tx_effect.ts +++ b/yarn-project/circuit-types/src/tx_effect.ts @@ -7,17 +7,22 @@ import { PublicDataWrite, RevertCode, } from '@aztec/circuits.js'; -import { makeTuple } from '@aztec/foundation/array'; +import { type FieldsOf, makeTuple } from '@aztec/foundation/array'; import { padArrayEnd } from '@aztec/foundation/collection'; import { sha256Trunc } from '@aztec/foundation/crypto'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; +import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, serializeArrayOfBufferableToVector, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { inspect } from 'util'; +import { z } from 'zod'; import { ContractClassTxL2Logs, EncryptedNoteTxL2Logs, EncryptedTxL2Logs, UnencryptedTxL2Logs } from './logs/index.js'; import { TxHash } from './tx/tx_hash.js'; +export { RevertCodeEnum } from '@aztec/circuits.js'; + export class TxEffect { constructor( /** @@ -264,21 +269,51 @@ export class TxEffect { } /** Returns a hex representation of the TxEffect object. */ - toString(): string { - return this.toBuffer().toString('hex'); + toString() { + return bufferToHex(this.toBuffer()); } - toJSON() { - return this.toString(); + static from(fields: Omit, 'txHash'>) { + return new TxEffect( + fields.revertCode, + fields.transactionFee, + fields.noteHashes, + fields.nullifiers, + fields.l2ToL1Msgs, + fields.publicDataWrites, + fields.noteEncryptedLogsLength, + fields.encryptedLogsLength, + fields.unencryptedLogsLength, + fields.contractClassLogsLength, + fields.noteEncryptedLogs, + fields.encryptedLogs, + fields.unencryptedLogs, + fields.contractClassLogs, + ); } static get schema() { - return hexSchemaFor(TxEffect); + return z + .object({ + revertCode: RevertCode.schema, + transactionFee: schemas.Fr, + noteHashes: z.array(schemas.Fr), + nullifiers: z.array(schemas.Fr), + l2ToL1Msgs: z.array(schemas.Fr), + publicDataWrites: z.array(PublicDataWrite.schema), + noteEncryptedLogsLength: schemas.Fr, + encryptedLogsLength: schemas.Fr, + unencryptedLogsLength: schemas.Fr, + contractClassLogsLength: schemas.Fr, + noteEncryptedLogs: EncryptedNoteTxL2Logs.schema, + encryptedLogs: EncryptedTxL2Logs.schema, + unencryptedLogs: UnencryptedTxL2Logs.schema, + contractClassLogs: ContractClassTxL2Logs.schema, + }) + .transform(TxEffect.from); } [inspect.custom]() { - // print out the non-empty fields - return `TxEffect { revertCode: ${this.revertCode}, transactionFee: ${this.transactionFee}, @@ -290,10 +325,10 @@ export class TxEffect { encryptedLogsLength: ${this.encryptedLogsLength}, unencryptedLogsLength: ${this.unencryptedLogsLength}, contractClassLogsLength: ${this.contractClassLogsLength}, - noteEncryptedLogs: ${JSON.stringify(this.noteEncryptedLogs.toJSON())}, - encryptedLogs: ${JSON.stringify(this.encryptedLogs.toJSON())}, - unencryptedLogs: ${JSON.stringify(this.unencryptedLogs.toJSON())} - contractClassLogs: ${JSON.stringify(this.contractClassLogs.toJSON())} + noteEncryptedLogs: ${jsonStringify(this.noteEncryptedLogs)}, + encryptedLogs: ${jsonStringify(this.encryptedLogs)}, + unencryptedLogs: ${jsonStringify(this.unencryptedLogs)} + contractClassLogs: ${jsonStringify(this.contractClassLogs)} }`; } @@ -303,7 +338,7 @@ export class TxEffect { * @returns An instance of TxEffect. */ static fromString(str: string) { - return TxEffect.fromBuffer(Buffer.from(str, 'hex')); + return TxEffect.fromBuffer(hexToBuffer(str)); } get txHash(): TxHash { diff --git a/yarn-project/circuit-types/src/tx_execution_request.test.ts b/yarn-project/circuit-types/src/tx_execution_request.test.ts index 2cb04307dfa..d1de9f1c4db 100644 --- a/yarn-project/circuit-types/src/tx_execution_request.test.ts +++ b/yarn-project/circuit-types/src/tx_execution_request.test.ts @@ -1,6 +1,5 @@ -import { jsonStringify } from '@aztec/foundation/json-rpc'; +import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc'; -import { jsonParseWithSchema } from '../../foundation/src/json-rpc/convert.js'; import { TxExecutionRequest } from './tx_execution_request.js'; describe('TxExecutionRequest', () => { diff --git a/yarn-project/circuit-types/src/tx_execution_request.ts b/yarn-project/circuit-types/src/tx_execution_request.ts index 9588de8c160..2a99636da2e 100644 --- a/yarn-project/circuit-types/src/tx_execution_request.ts +++ b/yarn-project/circuit-types/src/tx_execution_request.ts @@ -1,6 +1,7 @@ import { AztecAddress, Fr, FunctionData, FunctionSelector, TxContext, TxRequest, Vector } from '@aztec/circuits.js'; import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { z } from 'zod'; @@ -101,7 +102,7 @@ export class TxExecutionRequest { * @returns The string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -127,7 +128,7 @@ export class TxExecutionRequest { * @returns The deserialized TxRequest object. */ static fromString(str: string): TxExecutionRequest { - return TxExecutionRequest.fromBuffer(Buffer.from(str, 'hex')); + return TxExecutionRequest.fromBuffer(hexToBuffer(str)); } static random() { diff --git a/yarn-project/circuits.js/src/contract/interfaces/contract_class.ts b/yarn-project/circuits.js/src/contract/interfaces/contract_class.ts index 82d0a4960a2..002c3ac4f75 100644 --- a/yarn-project/circuits.js/src/contract/interfaces/contract_class.ts +++ b/yarn-project/circuits.js/src/contract/interfaces/contract_class.ts @@ -45,7 +45,7 @@ export interface ExecutablePrivateFunction extends PrivateFunction { } const ExecutablePrivateFunctionSchema = PrivateFunctionSchema.and( - z.object({ bytecode: schemas.BufferB64 }), + z.object({ bytecode: schemas.Buffer }), ) satisfies ZodFor; /** Public function definition within a contract class. */ @@ -58,7 +58,7 @@ export interface PublicFunction { export const PublicFunctionSchema = z.object({ selector: schemas.FunctionSelector, - bytecode: schemas.BufferB64, + bytecode: schemas.Buffer, }) satisfies ZodFor; /** Unconstrained function definition. */ @@ -72,7 +72,7 @@ export interface UnconstrainedFunction { const UnconstrainedFunctionSchema = z.object({ /** lala */ selector: schemas.FunctionSelector, - bytecode: schemas.BufferB64, + bytecode: schemas.Buffer, }) satisfies ZodFor; /** Sibling paths and sibling commitments for proving membership of a private function within a contract class. */ @@ -124,7 +124,7 @@ export const ContractClassSchema = z.object({ artifactHash: schemas.Fr, privateFunctions: z.array(PrivateFunctionSchema), publicFunctions: z.array(PublicFunctionSchema), - packedBytecode: schemas.BufferB64, + packedBytecode: schemas.Buffer, }) satisfies ZodFor; /** Commitments to fields of a contract class. */ diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/revert_code.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/revert_code.test.ts.snap index a4fdeb08c29..5cc25a3728b 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/revert_code.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/revert_code.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`revert_code should serialize properly 1`] = ` +exports[`revert_code should serialize RevertCode<0> properly 1`] = ` { "data": [ 0, @@ -40,7 +40,7 @@ exports[`revert_code should serialize properly 1`] = ` } `; -exports[`revert_code should serialize properly 2`] = ` +exports[`revert_code should serialize RevertCode<0> properly 2`] = ` { "data": [ 0, @@ -49,14 +49,9 @@ exports[`revert_code should serialize properly 2`] = ` } `; -exports[`revert_code should serialize properly 3`] = ` -{ - "type": "Fr", - "value": "0x0000000000000000000000000000000000000000000000000000000000000000", -} -`; +exports[`revert_code should serialize RevertCode<0> properly 3`] = `"0x0000000000000000000000000000000000000000000000000000000000000000"`; -exports[`revert_code should serialize properly 4`] = ` +exports[`revert_code should serialize RevertCode<1> properly 1`] = ` { "data": [ 0, @@ -96,7 +91,7 @@ exports[`revert_code should serialize properly 4`] = ` } `; -exports[`revert_code should serialize properly 5`] = ` +exports[`revert_code should serialize RevertCode<1> properly 2`] = ` { "data": [ 1, @@ -105,14 +100,9 @@ exports[`revert_code should serialize properly 5`] = ` } `; -exports[`revert_code should serialize properly 6`] = ` -{ - "type": "Fr", - "value": "0x0000000000000000000000000000000000000000000000000000000000000001", -} -`; +exports[`revert_code should serialize RevertCode<1> properly 3`] = `"0x0000000000000000000000000000000000000000000000000000000000000001"`; -exports[`revert_code should serialize properly 7`] = ` +exports[`revert_code should serialize RevertCode<2> properly 1`] = ` { "data": [ 0, @@ -152,7 +142,7 @@ exports[`revert_code should serialize properly 7`] = ` } `; -exports[`revert_code should serialize properly 8`] = ` +exports[`revert_code should serialize RevertCode<2> properly 2`] = ` { "data": [ 2, @@ -161,14 +151,9 @@ exports[`revert_code should serialize properly 8`] = ` } `; -exports[`revert_code should serialize properly 9`] = ` -{ - "type": "Fr", - "value": "0x0000000000000000000000000000000000000000000000000000000000000002", -} -`; +exports[`revert_code should serialize RevertCode<2> properly 3`] = `"0x0000000000000000000000000000000000000000000000000000000000000002"`; -exports[`revert_code should serialize properly 10`] = ` +exports[`revert_code should serialize RevertCode<3> properly 1`] = ` { "data": [ 0, @@ -208,7 +193,7 @@ exports[`revert_code should serialize properly 10`] = ` } `; -exports[`revert_code should serialize properly 11`] = ` +exports[`revert_code should serialize RevertCode<3> properly 2`] = ` { "data": [ 3, @@ -217,9 +202,4 @@ exports[`revert_code should serialize properly 11`] = ` } `; -exports[`revert_code should serialize properly 12`] = ` -{ - "type": "Fr", - "value": "0x0000000000000000000000000000000000000000000000000000000000000003", -} -`; +exports[`revert_code should serialize RevertCode<3> properly 3`] = `"0x0000000000000000000000000000000000000000000000000000000000000003"`; diff --git a/yarn-project/circuits.js/src/structs/avm/avm.ts b/yarn-project/circuits.js/src/structs/avm/avm.ts index b4020f36511..30c37a7b132 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm.ts @@ -1,8 +1,9 @@ import { PublicDataTreeLeafPreimage } from '@aztec/circuits.js'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { type ContractClassIdPreimage } from '../../contract/contract_class_id.js'; @@ -34,7 +35,7 @@ export class AvmEnqueuedCallHint { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -79,7 +80,7 @@ export class AvmEnqueuedCallHint { * @returns The deserialized instance. */ static fromString(str: string): AvmEnqueuedCallHint { - return AvmEnqueuedCallHint.fromBuffer(Buffer.from(str, 'hex')); + return AvmEnqueuedCallHint.fromBuffer(hexToBuffer(str)); } } @@ -100,7 +101,7 @@ export class AvmKeyValueHint { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -145,7 +146,7 @@ export class AvmKeyValueHint { * @returns The deserialized instance. */ static fromString(str: string): AvmKeyValueHint { - return AvmKeyValueHint.fromBuffer(Buffer.from(str, 'hex')); + return AvmKeyValueHint.fromBuffer(hexToBuffer(str)); } } @@ -182,7 +183,7 @@ export class AvmExternalCallHint { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -245,7 +246,7 @@ export class AvmExternalCallHint { * @returns The deserialized instance. */ static fromString(str: string): AvmExternalCallHint { - return AvmExternalCallHint.fromBuffer(Buffer.from(str, 'hex')); + return AvmExternalCallHint.fromBuffer(hexToBuffer(str)); } } @@ -272,7 +273,7 @@ export class AvmContractInstanceHint { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -341,7 +342,7 @@ export class AvmContractInstanceHint { * @returns The deserialized instance. */ static fromString(str: string): AvmContractInstanceHint { - return AvmContractInstanceHint.fromBuffer(Buffer.from(str, 'hex')); + return AvmContractInstanceHint.fromBuffer(hexToBuffer(str)); } } @@ -369,7 +370,7 @@ export class AvmContractBytecodeHints { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -434,7 +435,7 @@ export class AvmContractBytecodeHints { * @returns The deserialized instance. */ static fromString(str: string): AvmContractBytecodeHints { - return AvmContractBytecodeHints.fromBuffer(Buffer.from(str, 'hex')); + return AvmContractBytecodeHints.fromBuffer(hexToBuffer(str)); } } @@ -914,7 +915,7 @@ export class AvmExecutionHints { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -1026,7 +1027,7 @@ export class AvmExecutionHints { * @returns The deserialized instance. */ static fromString(str: string): AvmCircuitInputs { - return AvmCircuitInputs.fromBuffer(Buffer.from(str, 'hex')); + return AvmCircuitInputs.fromBuffer(hexToBuffer(str)); } } @@ -1061,7 +1062,7 @@ export class AvmCircuitInputs { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static empty(): AvmCircuitInputs { @@ -1114,16 +1115,16 @@ export class AvmCircuitInputs { * @returns The deserialized instance. */ static fromString(str: string): AvmCircuitInputs { - return AvmCircuitInputs.fromBuffer(Buffer.from(str, 'hex')); + return AvmCircuitInputs.fromBuffer(hexToBuffer(str)); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a buffer representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string. */ static get schema() { - return hexSchemaFor(AvmCircuitInputs); + return bufferSchemaFor(AvmCircuitInputs); } } diff --git a/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts b/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts index 2e01efc6ee2..c68d93b13e4 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm_accumulated_data.ts @@ -2,6 +2,7 @@ import { makeTuple } from '@aztec/foundation/array'; import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { inspect } from 'util'; @@ -83,11 +84,11 @@ export class AvmAccumulatedData { } static fromString(str: string) { - return this.fromBuffer(Buffer.from(str, 'hex')); + return this.fromBuffer(hexToBuffer(str)); } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static empty() { diff --git a/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts index 0ff41750b69..8877b4b8003 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm_circuit_public_inputs.ts @@ -1,6 +1,7 @@ import { makeTuple } from '@aztec/foundation/array'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { inspect } from 'util'; @@ -80,11 +81,11 @@ export class AvmCircuitPublicInputs { } static fromString(str: string) { - return AvmCircuitPublicInputs.fromBuffer(Buffer.from(str, 'hex')); + return AvmCircuitPublicInputs.fromBuffer(hexToBuffer(str)); } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromFields(fields: Fr[] | FieldReader) { diff --git a/yarn-project/circuits.js/src/structs/client_ivc_proof.ts b/yarn-project/circuits.js/src/structs/client_ivc_proof.ts index 737870e5080..a35b8f6c84f 100644 --- a/yarn-project/circuits.js/src/structs/client_ivc_proof.ts +++ b/yarn-project/circuits.js/src/structs/client_ivc_proof.ts @@ -1,4 +1,4 @@ -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import * as fs from 'fs/promises'; @@ -67,12 +67,11 @@ export class ClientIvcProof { } static get schema() { - // TODO(palla/schemas): Consider using a b64 schema instead - return hexSchemaFor(ClientIvcProof); + return bufferSchemaFor(ClientIvcProof); } toJSON() { - return '0x' + this.toBuffer().toString('hex'); + return this.toBuffer(); } static fromBuffer(buffer: Buffer | BufferReader): ClientIvcProof { diff --git a/yarn-project/circuits.js/src/structs/complete_address.ts b/yarn-project/circuits.js/src/structs/complete_address.ts index 04d083ae50c..5fbd1132e40 100644 --- a/yarn-project/circuits.js/src/structs/complete_address.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.ts @@ -2,6 +2,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { hexSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex } from '@aztec/foundation/string'; import { computePartialAddress } from '../contract/contract_address.js'; import { computeAddress, computePreaddress, deriveKeys } from '../keys/index.js'; @@ -141,6 +142,6 @@ export class CompleteAddress { * @returns A hexadecimal string representation of the CompleteAddress. */ toString(): string { - return `0x${this.toBuffer().toString('hex')}`; + return bufferToHex(this.toBuffer()); } } diff --git a/yarn-project/circuits.js/src/structs/content_commitment.ts b/yarn-project/circuits.js/src/structs/content_commitment.ts index 578a6831ff5..8e2e9680ba2 100644 --- a/yarn-project/circuits.js/src/structs/content_commitment.ts +++ b/yarn-project/circuits.js/src/structs/content_commitment.ts @@ -1,6 +1,7 @@ import { Fr } from '@aztec/foundation/fields'; import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex } from '@aztec/foundation/string'; import { z } from 'zod'; @@ -34,24 +35,15 @@ export class ContentCommitment { return z .object({ numTxs: schemas.Fr, - txsEffectsHash: schemas.BufferHex, - inHash: schemas.BufferHex, - outHash: schemas.BufferHex, + txsEffectsHash: schemas.Buffer, + inHash: schemas.Buffer, + outHash: schemas.Buffer, }) .transform( ({ numTxs, txsEffectsHash, inHash, outHash }) => new ContentCommitment(numTxs, txsEffectsHash, inHash, outHash), ); } - toJSON() { - return { - numTxs: this.numTxs, - txsEffectsHash: this.txsEffectsHash.toString('hex'), - inHash: this.inHash.toString('hex'), - outHash: this.outHash.toString('hex'), - }; - } - getSize() { return this.toBuffer().length; } @@ -113,7 +105,7 @@ export class ContentCommitment { } public toString(): string { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromString(str: string): ContentCommitment { diff --git a/yarn-project/circuits.js/src/structs/function_data.ts b/yarn-project/circuits.js/src/structs/function_data.ts index 02f58a2deaa..afc63a96d21 100644 --- a/yarn-project/circuits.js/src/structs/function_data.ts +++ b/yarn-project/circuits.js/src/structs/function_data.ts @@ -1,7 +1,10 @@ import { type FunctionAbi, FunctionSelector, FunctionType } from '@aztec/foundation/abi'; import { Fr } from '@aztec/foundation/fields'; +import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { z } from 'zod'; + import { FUNCTION_DATA_LENGTH } from '../constants.gen.js'; import { type ContractFunctionDao } from '../types/contract_function_dao.js'; @@ -21,6 +24,15 @@ export class FunctionData { ); } + static get schema() { + return z + .object({ + selector: schemas.FunctionSelector, + isPrivate: z.boolean(), + }) + .transform(({ selector, isPrivate }) => new FunctionData(selector, isPrivate)); + } + /** * Serialize this as a buffer. * @returns The buffer. @@ -88,15 +100,4 @@ export class FunctionData { return new FunctionData(selector, isPrivate); } - - public toJSON() { - return { - selector: this.selector.toString(), - isPrivate: this.isPrivate, - }; - } - - public static fromJSON(json: any) { - return new FunctionData(FunctionSelector.fromString(json.selector), json.isPrivate); - } } diff --git a/yarn-project/circuits.js/src/structs/gas.ts b/yarn-project/circuits.js/src/structs/gas.ts index 4dc6f24f087..7952b2cbbbd 100644 --- a/yarn-project/circuits.js/src/structs/gas.ts +++ b/yarn-project/circuits.js/src/structs/gas.ts @@ -93,12 +93,4 @@ export class Gas { const reader = FieldReader.asReader(fields); return new Gas(reader.readU32(), reader.readU32()); } - - toJSON() { - return { daGas: this.daGas, l2Gas: this.l2Gas }; - } - - static fromJSON(json: any) { - return new Gas(json.daGas, json.l2Gas); - } } diff --git a/yarn-project/circuits.js/src/structs/gas_fees.ts b/yarn-project/circuits.js/src/structs/gas_fees.ts index 6cab097c0ce..dcaabb12da8 100644 --- a/yarn-project/circuits.js/src/structs/gas_fees.ts +++ b/yarn-project/circuits.js/src/structs/gas_fees.ts @@ -83,17 +83,6 @@ export class GasFees { return serializeToFields(this.feePerDaGas, this.feePerL2Gas); } - static fromJSON(obj: any) { - return new GasFees(Fr.fromString(obj.feePerDaGas), Fr.fromString(obj.feePerL2Gas)); - } - - toJSON() { - return { - feePerDaGas: this.feePerDaGas.toString(), - feePerL2Gas: this.feePerL2Gas.toString(), - }; - } - [inspect.custom]() { return `GasFees { feePerDaGas=${this.feePerDaGas} feePerL2Gas=${this.feePerL2Gas} }`; } diff --git a/yarn-project/circuits.js/src/structs/global_variables.ts b/yarn-project/circuits.js/src/structs/global_variables.ts index f49badfe8ff..914dc7b5fb6 100644 --- a/yarn-project/circuits.js/src/structs/global_variables.ts +++ b/yarn-project/circuits.js/src/structs/global_variables.ts @@ -1,6 +1,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; @@ -84,19 +85,6 @@ export class GlobalVariables { ); } - static fromJSON(obj: any): GlobalVariables { - return new GlobalVariables( - Fr.fromString(obj.chainId), - Fr.fromString(obj.version), - Fr.fromString(obj.blockNumber), - Fr.fromString(obj.slotNumber), - Fr.fromString(obj.timestamp), - EthAddress.fromString(obj.coinbase), - AztecAddress.fromString(obj.feeRecipient), - GasFees.fromJSON(obj.gasFees), - ); - } - static fromFields(fields: Fr[] | FieldReader): GlobalVariables { const reader = FieldReader.asReader(fields); @@ -140,19 +128,6 @@ export class GlobalVariables { return fields; } - toJSON() { - return { - chainId: this.chainId.toString(), - version: this.version.toString(), - blockNumber: this.blockNumber.toString(), - slotNumber: this.slotNumber.toString(), - timestamp: this.timestamp.toString(), - coinbase: this.coinbase.toString(), - feeRecipient: this.feeRecipient.toString(), - gasFees: this.gasFees.toJSON(), - }; - } - /** * A trimmed version of the JSON representation of the global variables, * tailored for human consumption. @@ -163,7 +138,7 @@ export class GlobalVariables { slotNumber: this.slotNumber.toNumber(), timestamp: this.timestamp.toString(), coinbase: this.coinbase.toString(), - gasFees: this.gasFees.toJSON(), + gasFees: jsonStringify(this.gasFees), }; } diff --git a/yarn-project/circuits.js/src/structs/header.ts b/yarn-project/circuits.js/src/structs/header.ts index f31f85a2ef9..654d202eb51 100644 --- a/yarn-project/circuits.js/src/structs/header.ts +++ b/yarn-project/circuits.js/src/structs/header.ts @@ -2,6 +2,7 @@ import { poseidon2HashWithSeparator } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { inspect } from 'util'; @@ -40,16 +41,6 @@ export class Header { .transform(Header.from); } - toJSON() { - return { - lastArchive: this.lastArchive, - contentCommitment: this.contentCommitment, - state: this.state, - globalVariables: this.globalVariables, - totalFees: this.totalFees, - }; - } - static getFields(fields: FieldsOf
) { // Note: The order here must match the order in the HeaderLib solidity library. return [ @@ -139,13 +130,12 @@ export class Header { * Serializes this instance into a string. * @returns Encoded string. */ - public toString(): string { - return this.toBuffer().toString('hex'); + public toString() { + return bufferToHex(this.toBuffer()); } static fromString(str: string): Header { - const buffer = Buffer.from(str.replace(/^0x/i, ''), 'hex'); - return Header.fromBuffer(buffer); + return Header.fromBuffer(hexToBuffer(str)); } hash(): Fr { diff --git a/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts index 16ba5e3b7b7..b245c70f7b6 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts @@ -1,8 +1,9 @@ import { type FieldsOf, makeTuple } from '@aztec/foundation/array'; import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { inspect } from 'util'; @@ -116,11 +117,11 @@ export class CombinedAccumulatedData { } static get schema() { - return hexSchemaFor(CombinedAccumulatedData); + return bufferSchemaFor(CombinedAccumulatedData); } toJSON() { - return this.toString(); + return this.toBuffer(); } toBuffer() { @@ -128,7 +129,7 @@ export class CombinedAccumulatedData { } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -160,7 +161,7 @@ export class CombinedAccumulatedData { * @returns Deserialized object. */ static fromString(str: string) { - return CombinedAccumulatedData.fromBuffer(Buffer.from(str, 'hex')); + return CombinedAccumulatedData.fromBuffer(hexToBuffer(str)); } static empty() { diff --git a/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.ts index 2ec58bdd269..e5abfe011f1 100644 --- a/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.ts @@ -1,6 +1,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { Gas } from '../gas.js'; import { PartialStateReference } from '../partial_state_reference.js'; @@ -89,20 +90,20 @@ export class KernelCircuitPublicInputs { } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromString(str: string) { - return KernelCircuitPublicInputs.fromBuffer(Buffer.from(str, 'hex')); + return KernelCircuitPublicInputs.fromBuffer(hexToBuffer(str)); } /** Returns a hex representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string. */ static get schema() { - return hexSchemaFor(KernelCircuitPublicInputs); + return bufferSchemaFor(KernelCircuitPublicInputs); } } diff --git a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts index 86b7a03ac7f..a314fdde586 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts @@ -1,5 +1,6 @@ import { makeTuple } from '@aztec/foundation/array'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { MAX_CONTRACT_CLASS_LOGS_PER_TX, @@ -75,7 +76,7 @@ export class PrivateAccumulatedData { } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -103,7 +104,7 @@ export class PrivateAccumulatedData { * @returns Deserialized object. */ static fromString(str: string) { - return PrivateAccumulatedData.fromBuffer(Buffer.from(str, 'hex')); + return PrivateAccumulatedData.fromBuffer(hexToBuffer(str)); } static empty() { diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_circuit_public_inputs.ts index 1db065b1464..1839ce2c98d 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_circuit_public_inputs.ts @@ -1,6 +1,6 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { PrivateValidationRequests } from '../private_validation_requests.js'; @@ -40,11 +40,11 @@ export class PrivateKernelCircuitPublicInputs { ) {} static get schema() { - return hexSchemaFor(PrivateKernelCircuitPublicInputs); + return bufferSchemaFor(PrivateKernelCircuitPublicInputs); } toJSON() { - return '0x' + this.toBuffer().toString('hex'); + return this.toBuffer(); } toBuffer() { diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_empty_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_empty_inputs.ts index 0a97d999581..9fe7957baa0 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_empty_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_empty_inputs.ts @@ -1,6 +1,7 @@ import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { RECURSIVE_PROOF_LENGTH } from '../../constants.gen.js'; @@ -22,7 +23,7 @@ export class PrivateKernelEmptyInputData { } toString(): string { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromBuffer(buf: Buffer) { @@ -37,7 +38,7 @@ export class PrivateKernelEmptyInputData { } static fromString(str: string): PrivateKernelEmptyInputData { - return PrivateKernelEmptyInputData.fromBuffer(Buffer.from(str, 'hex')); + return PrivateKernelEmptyInputData.fromBuffer(hexToBuffer(str)); } static from(fields: FieldsOf) { @@ -50,14 +51,14 @@ export class PrivateKernelEmptyInputData { ); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a buffer representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string. */ static get schema() { - return hexSchemaFor(PrivateKernelEmptyInputData); + return bufferSchemaFor(PrivateKernelEmptyInputData); } } diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts index 7ce5ae26c0d..d21a7590db9 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts @@ -1,6 +1,6 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { countAccumulatedItems, mergeAccumulatedData } from '../../utils/index.js'; @@ -131,11 +131,11 @@ export class PrivateKernelTailCircuitPublicInputs { } static get schema() { - return hexSchemaFor(PrivateKernelTailCircuitPublicInputs); + return bufferSchemaFor(PrivateKernelTailCircuitPublicInputs); } toJSON() { - return '0x' + this.toBuffer().toString('hex'); + return this.toBuffer(); } getSize() { diff --git a/yarn-project/circuits.js/src/structs/kernel/private_to_public_kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_to_public_kernel_circuit_public_inputs.ts index 7a93e0cee96..ed837be8084 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_to_public_kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_to_public_kernel_circuit_public_inputs.ts @@ -1,5 +1,6 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { Gas } from '../gas.js'; import { PublicCallRequest } from '../public_call_request.js'; @@ -56,10 +57,10 @@ export class PrivateToPublicKernelCircuitPublicInputs { } static fromString(str: string) { - return PrivateToPublicKernelCircuitPublicInputs.fromBuffer(Buffer.from(str, 'hex')); + return PrivateToPublicKernelCircuitPublicInputs.fromBuffer(hexToBuffer(str)); } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } } diff --git a/yarn-project/circuits.js/src/structs/parity/base_parity_inputs.ts b/yarn-project/circuits.js/src/structs/parity/base_parity_inputs.ts index 44a6804c840..a02b44025a3 100644 --- a/yarn-project/circuits.js/src/structs/parity/base_parity_inputs.ts +++ b/yarn-project/circuits.js/src/structs/parity/base_parity_inputs.ts @@ -1,6 +1,7 @@ import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUM_MSGS_PER_BASE_PARITY } from '../../constants.gen.js'; @@ -30,7 +31,7 @@ export class BaseParityInputs { /** Serializes the inputs to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -48,16 +49,16 @@ export class BaseParityInputs { * @returns - The deserialized inputs. */ static fromString(str: string) { - return BaseParityInputs.fromBuffer(Buffer.from(str, 'hex')); + return BaseParityInputs.fromBuffer(hexToBuffer(str)); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a buffer representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string. */ static get schema() { - return hexSchemaFor(BaseParityInputs); + return bufferSchemaFor(BaseParityInputs); } } diff --git a/yarn-project/circuits.js/src/structs/parity/parity_public_inputs.ts b/yarn-project/circuits.js/src/structs/parity/parity_public_inputs.ts index d0cd63e2565..1f2f3551c02 100644 --- a/yarn-project/circuits.js/src/structs/parity/parity_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/parity/parity_public_inputs.ts @@ -1,6 +1,7 @@ import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; export class ParityPublicInputs { @@ -30,12 +31,12 @@ export class ParityPublicInputs { * @returns The inputs serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** @@ -72,10 +73,10 @@ export class ParityPublicInputs { * @returns A new ParityPublicInputs instance. */ static fromString(str: string) { - return ParityPublicInputs.fromBuffer(Buffer.from(str, 'hex')); + return ParityPublicInputs.fromBuffer(hexToBuffer(str)); } static get schema() { - return hexSchemaFor(ParityPublicInputs); + return bufferSchemaFor(ParityPublicInputs); } } diff --git a/yarn-project/circuits.js/src/structs/parity/root_parity_input.ts b/yarn-project/circuits.js/src/structs/parity/root_parity_input.ts index aa26e28386e..e9b159b4387 100644 --- a/yarn-project/circuits.js/src/structs/parity/root_parity_input.ts +++ b/yarn-project/circuits.js/src/structs/parity/root_parity_input.ts @@ -1,6 +1,7 @@ import { Fr } from '@aztec/foundation/fields'; import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { VK_TREE_HEIGHT } from '../../constants.gen.js'; @@ -25,7 +26,7 @@ export class RootParityInput { } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static from( @@ -55,16 +56,16 @@ export class RootParityInput { str: string, expectedSize?: PROOF_LENGTH, ): RootParityInput { - return RootParityInput.fromBuffer(Buffer.from(str, 'hex'), expectedSize); + return RootParityInput.fromBuffer(hexToBuffer(str), expectedSize); } /** Returns a hex representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string with expected size. */ static schemaFor(expectedSize?: N) { - return schemas.HexString.transform(str => RootParityInput.fromString(str, expectedSize)); + return schemas.Buffer.transform(buf => RootParityInput.fromBuffer(buf, expectedSize)); } } diff --git a/yarn-project/circuits.js/src/structs/parity/root_parity_inputs.ts b/yarn-project/circuits.js/src/structs/parity/root_parity_inputs.ts index aa74c1092f2..2b09078c755 100644 --- a/yarn-project/circuits.js/src/structs/parity/root_parity_inputs.ts +++ b/yarn-project/circuits.js/src/structs/parity/root_parity_inputs.ts @@ -1,5 +1,6 @@ -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { NUM_BASE_PARITY_PER_ROOT_PARITY, RECURSIVE_PROOF_LENGTH } from '../../constants.gen.js'; import { RootParityInput } from './root_parity_input.js'; @@ -26,7 +27,7 @@ export class RootParityInputs { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -50,16 +51,16 @@ export class RootParityInputs { * @returns A new RootParityInputs instance. */ static fromString(str: string) { - return RootParityInputs.fromBuffer(Buffer.from(str, 'hex')); + return RootParityInputs.fromBuffer(hexToBuffer(str)); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a buffer representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string. */ static get schema() { - return hexSchemaFor(RootParityInputs); + return bufferSchemaFor(RootParityInputs); } } diff --git a/yarn-project/circuits.js/src/structs/partial_state_reference.ts b/yarn-project/circuits.js/src/structs/partial_state_reference.ts index fe484113835..7e212e71262 100644 --- a/yarn-project/circuits.js/src/structs/partial_state_reference.ts +++ b/yarn-project/circuits.js/src/structs/partial_state_reference.ts @@ -19,14 +19,6 @@ export class PartialStateReference { public readonly publicDataTree: AppendOnlyTreeSnapshot, ) {} - toJSON() { - return { - noteHashTree: this.noteHashTree, - nullifierTree: this.nullifierTree, - publicDataTree: this.publicDataTree, - }; - } - static get schema() { return z .object({ diff --git a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts index dfb3fa6d00f..cded605058d 100644 --- a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts @@ -1,6 +1,6 @@ import { makeTuple } from '@aztec/foundation/array'; import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, FieldReader, @@ -323,18 +323,10 @@ export class PrivateCircuitPublicInputs { } public toJSON() { - return this.toBuffer().toString('hex'); - } - - public static fromJSON(value: any) { - return PrivateCircuitPublicInputs.fromBuffer(Buffer.from(value, 'hex')); - } - - public static fromString(str: string) { - return PrivateCircuitPublicInputs.fromBuffer(Buffer.from(str, 'hex')); + return this.toBuffer(); } static get schema() { - return hexSchemaFor(PrivateCircuitPublicInputs); + return bufferSchemaFor(PrivateCircuitPublicInputs); } } diff --git a/yarn-project/circuits.js/src/structs/private_validation_requests.ts b/yarn-project/circuits.js/src/structs/private_validation_requests.ts index f026fbfacaf..3b8da4dc030 100644 --- a/yarn-project/circuits.js/src/structs/private_validation_requests.ts +++ b/yarn-project/circuits.js/src/structs/private_validation_requests.ts @@ -2,6 +2,7 @@ import { makeTuple } from '@aztec/foundation/array'; import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; import { type Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { inspect } from 'util'; @@ -69,7 +70,7 @@ export class PrivateValidationRequests { } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromFields(fields: Fr[] | FieldReader) { @@ -105,7 +106,7 @@ export class PrivateValidationRequests { * @returns Deserialized object. */ static fromString(str: string) { - return PrivateValidationRequests.fromBuffer(Buffer.from(str, 'hex')); + return PrivateValidationRequests.fromBuffer(hexToBuffer(str)); } static empty() { diff --git a/yarn-project/circuits.js/src/structs/proof.ts b/yarn-project/circuits.js/src/structs/proof.ts index 57b57606df4..ec6af85223c 100644 --- a/yarn-project/circuits.js/src/structs/proof.ts +++ b/yarn-project/circuits.js/src/structs/proof.ts @@ -1,5 +1,6 @@ import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { AGGREGATION_OBJECT_LENGTH } from '../constants.gen.js'; @@ -61,7 +62,7 @@ export class Proof { * @returns The hex string representation of the proof data. */ public toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } public withoutPublicInputs(): Buffer { @@ -89,7 +90,7 @@ export class Proof { * @returns - A new Proof instance. */ static fromString(str: string) { - return Proof.fromBuffer(Buffer.from(str, 'hex')); + return Proof.fromBuffer(hexToBuffer(str)); } /** Returns whether this proof is actually empty. */ diff --git a/yarn-project/circuits.js/src/structs/public_data_write.ts b/yarn-project/circuits.js/src/structs/public_data_write.ts index 7f4c2e49ca4..001d14a7878 100644 --- a/yarn-project/circuits.js/src/structs/public_data_write.ts +++ b/yarn-project/circuits.js/src/structs/public_data_write.ts @@ -1,7 +1,7 @@ -import { STRING_ENCODING } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { z } from 'zod'; @@ -55,11 +55,11 @@ export class PublicDataWrite { } static fromString(str: string) { - return PublicDataWrite.fromBuffer(Buffer.from(str, STRING_ENCODING)); + return PublicDataWrite.fromBuffer(hexToBuffer(str)); } toString() { - return this.toBuffer().toString(STRING_ENCODING); + return bufferToHex(this.toBuffer()); } static empty() { diff --git a/yarn-project/circuits.js/src/structs/recursive_proof.ts b/yarn-project/circuits.js/src/structs/recursive_proof.ts index ce5a3b0dcae..d1329ee857a 100644 --- a/yarn-project/circuits.js/src/structs/recursive_proof.ts +++ b/yarn-project/circuits.js/src/structs/recursive_proof.ts @@ -2,6 +2,7 @@ import { makeTuple } from '@aztec/foundation/array'; import { Fr } from '@aztec/foundation/fields'; import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { Proof, makeEmptyProof } from './proof.js'; @@ -73,7 +74,7 @@ export class RecursiveProof { * @returns The hex string representation of the proof data. */ public toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -82,17 +83,17 @@ export class RecursiveProof { * @returns - A new Proof instance. */ static fromString(str: string, expectedSize?: N): RecursiveProof { - return RecursiveProof.fromBuffer(Buffer.from(str, 'hex'), expectedSize); + return RecursiveProof.fromBuffer(hexToBuffer(str), expectedSize); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a buffer representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string with expected size. */ static schemaFor(expectedSize?: N) { - return schemas.HexString.transform(str => RecursiveProof.fromString(str, expectedSize)); + return schemas.Buffer.transform(b => RecursiveProof.fromBuffer(b, expectedSize)); } } diff --git a/yarn-project/circuits.js/src/structs/revert_code.test.ts b/yarn-project/circuits.js/src/structs/revert_code.test.ts index e2188f7a93a..1fafefb47c4 100644 --- a/yarn-project/circuits.js/src/structs/revert_code.test.ts +++ b/yarn-project/circuits.js/src/structs/revert_code.test.ts @@ -1,10 +1,11 @@ import { Fr } from '@aztec/foundation/fields'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; import { RevertCode } from './revert_code.js'; describe('revert_code', () => { it.each([RevertCode.OK, RevertCode.APP_LOGIC_REVERTED, RevertCode.TEARDOWN_REVERTED, RevertCode.BOTH_REVERTED])( - 'should serialize properly', + 'should serialize %s properly', revertCode => { expect(revertCode.getSerializedLength()).toBe(1); @@ -20,6 +21,9 @@ describe('revert_code', () => { expect(field).toMatchSnapshot(); expect(RevertCode.fromField(field)).toEqual(revertCode); expect(RevertCode.fromFields([field])).toEqual(revertCode); + + const json = jsonStringify(revertCode); + expect(RevertCode.schema.parse(JSON.parse(json))).toEqual(revertCode); }, ); diff --git a/yarn-project/circuits.js/src/structs/revert_code.ts b/yarn-project/circuits.js/src/structs/revert_code.ts index 55ac00d331c..7e4357f05ae 100644 --- a/yarn-project/circuits.js/src/structs/revert_code.ts +++ b/yarn-project/circuits.js/src/structs/revert_code.ts @@ -2,8 +2,9 @@ import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader } from '@aztec/foundation/serialize'; import { inspect } from 'util'; +import { z } from 'zod'; -enum RevertCodeEnum { +export enum RevertCodeEnum { OK = 0, APP_LOGIC_REVERTED = 1, TEARDOWN_REVERTED = 2, @@ -55,6 +56,14 @@ export class RevertCode { } } + public toJSON() { + return this.code; + } + + static get schema() { + return z.nativeEnum(RevertCodeEnum).transform(value => new RevertCode(value)); + } + /** * Having different serialization methods allows for * decoupling the serialization for producing the content commitment hash diff --git a/yarn-project/circuits.js/src/structs/rollup/append_only_tree_snapshot.ts b/yarn-project/circuits.js/src/structs/rollup/append_only_tree_snapshot.ts index b4c71e37be1..5a97560f2e9 100644 --- a/yarn-project/circuits.js/src/structs/rollup/append_only_tree_snapshot.ts +++ b/yarn-project/circuits.js/src/structs/rollup/append_only_tree_snapshot.ts @@ -1,11 +1,12 @@ import { Fr } from '@aztec/foundation/fields'; import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { inspect } from 'util'; import { z } from 'zod'; -import { STRING_ENCODING, type UInt32 } from '../shared.js'; +import { type UInt32 } from '../shared.js'; /** * Snapshot of an append only tree. @@ -39,10 +40,6 @@ export class AppendOnlyTreeSnapshot { .transform(({ root, nextAvailableLeafIndex }) => new AppendOnlyTreeSnapshot(root, nextAvailableLeafIndex)); } - toJSON() { - return { root: this.root, nextAvailableLeafIndex: this.nextAvailableLeafIndex }; - } - getSize() { return this.root.size + 4; } @@ -56,7 +53,7 @@ export class AppendOnlyTreeSnapshot { } toString(): string { - return this.toBuffer().toString(STRING_ENCODING); + return bufferToHex(this.toBuffer()); } static fromBuffer(buffer: Buffer | BufferReader): AppendOnlyTreeSnapshot { @@ -65,7 +62,7 @@ export class AppendOnlyTreeSnapshot { } static fromString(str: string): AppendOnlyTreeSnapshot { - return AppendOnlyTreeSnapshot.fromBuffer(Buffer.from(str, STRING_ENCODING)); + return AppendOnlyTreeSnapshot.fromBuffer(hexToBuffer(str)); } static fromFields(fields: Fr[] | FieldReader): AppendOnlyTreeSnapshot { diff --git a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts index 981d1f0faa6..c42337e1c0f 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts @@ -1,6 +1,7 @@ import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { PartialStateReference } from '../partial_state_reference.js'; import { RollupTypes } from '../shared.js'; @@ -108,7 +109,7 @@ export class BaseOrMergeRollupPublicInputs { * @returns - The hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -117,16 +118,16 @@ export class BaseOrMergeRollupPublicInputs { * @returns A new BaseOrMergeRollupPublicInputs instance. */ static fromString(str: string) { - return BaseOrMergeRollupPublicInputs.fromBuffer(Buffer.from(str, 'hex')); + return BaseOrMergeRollupPublicInputs.fromBuffer(hexToBuffer(str)); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a buffer representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string. */ static get schema() { - return hexSchemaFor(BaseOrMergeRollupPublicInputs); + return bufferSchemaFor(BaseOrMergeRollupPublicInputs); } } diff --git a/yarn-project/circuits.js/src/structs/rollup/base_rollup_hints.ts b/yarn-project/circuits.js/src/structs/rollup/base_rollup_hints.ts index d9176c82f6d..80f627b4fab 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_rollup_hints.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_rollup_hints.ts @@ -1,4 +1,5 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { ARCHIVE_HEIGHT } from '../../constants.gen.js'; @@ -56,7 +57,7 @@ export class PrivateBaseRollupHints { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromBuffer(buffer: Buffer | BufferReader): PrivateBaseRollupHints { @@ -71,7 +72,7 @@ export class PrivateBaseRollupHints { } static fromString(str: string) { - return PrivateBaseRollupHints.fromBuffer(Buffer.from(str, 'hex')); + return PrivateBaseRollupHints.fromBuffer(hexToBuffer(str)); } static empty() { @@ -130,7 +131,7 @@ export class PublicBaseRollupHints { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromBuffer(buffer: Buffer | BufferReader): PublicBaseRollupHints { @@ -145,7 +146,7 @@ export class PublicBaseRollupHints { } static fromString(str: string) { - return PublicBaseRollupHints.fromBuffer(Buffer.from(str, 'hex')); + return PublicBaseRollupHints.fromBuffer(hexToBuffer(str)); } static empty() { diff --git a/yarn-project/circuits.js/src/structs/rollup/block_merge_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/block_merge_rollup.ts index 6732a4ffadf..e134ad16ba0 100644 --- a/yarn-project/circuits.js/src/structs/rollup/block_merge_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/block_merge_rollup.ts @@ -1,5 +1,6 @@ -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { PreviousRollupBlockData } from './previous_rollup_block_data.js'; @@ -27,7 +28,7 @@ export class BlockMergeRollupInputs { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -49,16 +50,16 @@ export class BlockMergeRollupInputs { * @returns A new BlockMergeRollupInputs instance. */ static fromString(str: string) { - return BlockMergeRollupInputs.fromBuffer(Buffer.from(str, 'hex')); + return BlockMergeRollupInputs.fromBuffer(hexToBuffer(str)); } /** Returns a hex representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string. */ static get schema() { - return hexSchemaFor(BlockMergeRollupInputs); + return bufferSchemaFor(BlockMergeRollupInputs); } } diff --git a/yarn-project/circuits.js/src/structs/rollup/block_root_or_block_merge_public_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/block_root_or_block_merge_public_inputs.ts index 639f335b760..00eeb3666a7 100644 --- a/yarn-project/circuits.js/src/structs/rollup/block_root_or_block_merge_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/block_root_or_block_merge_public_inputs.ts @@ -1,7 +1,8 @@ import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, type Tuple, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { AZTEC_MAX_EPOCH_DURATION } from '../../constants.gen.js'; @@ -107,7 +108,7 @@ export class BlockRootOrBlockMergePublicInputs { * @returns - The hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -116,17 +117,17 @@ export class BlockRootOrBlockMergePublicInputs { * @returns A new BaseOrMergeRollupPublicInputs instance. */ static fromString(str: string) { - return BlockRootOrBlockMergePublicInputs.fromBuffer(Buffer.from(str, 'hex')); + return BlockRootOrBlockMergePublicInputs.fromBuffer(hexToBuffer(str)); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a buffer representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string. */ static get schema() { - return hexSchemaFor(BlockRootOrBlockMergePublicInputs); + return bufferSchemaFor(BlockRootOrBlockMergePublicInputs); } } diff --git a/yarn-project/circuits.js/src/structs/rollup/block_root_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/block_root_rollup.ts index 3a63c40ddb3..18c1c289cb2 100644 --- a/yarn-project/circuits.js/src/structs/rollup/block_root_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/block_root_rollup.ts @@ -1,6 +1,7 @@ import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { @@ -69,7 +70,7 @@ export class BlockRootRollupInputs { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -126,16 +127,16 @@ export class BlockRootRollupInputs { * @returns A new RootRollupInputs instance. */ static fromString(str: string) { - return BlockRootRollupInputs.fromBuffer(Buffer.from(str, 'hex')); + return BlockRootRollupInputs.fromBuffer(hexToBuffer(str)); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a buffer representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string. */ static get schema() { - return hexSchemaFor(BlockRootRollupInputs); + return bufferSchemaFor(BlockRootRollupInputs); } } diff --git a/yarn-project/circuits.js/src/structs/rollup/empty_block_root_rollup_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/empty_block_root_rollup_inputs.ts index ba42802e1ae..f4355e835a7 100644 --- a/yarn-project/circuits.js/src/structs/rollup/empty_block_root_rollup_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/empty_block_root_rollup_inputs.ts @@ -1,6 +1,7 @@ import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { GlobalVariables } from '../global_variables.js'; @@ -33,7 +34,7 @@ export class EmptyBlockRootRollupInputs { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -84,16 +85,16 @@ export class EmptyBlockRootRollupInputs { * @returns A new RootRollupInputs instance. */ static fromString(str: string) { - return EmptyBlockRootRollupInputs.fromBuffer(Buffer.from(str, 'hex')); + return EmptyBlockRootRollupInputs.fromBuffer(hexToBuffer(str)); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a buffer representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } - /** Creates an instance from a hex string. */ + /** Creates an instance from a buffer string. */ static get schema() { - return hexSchemaFor(EmptyBlockRootRollupInputs); + return bufferSchemaFor(EmptyBlockRootRollupInputs); } } diff --git a/yarn-project/circuits.js/src/structs/rollup/merge_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/merge_rollup.ts index 2950f2f1614..2b38a5f6188 100644 --- a/yarn-project/circuits.js/src/structs/rollup/merge_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/merge_rollup.ts @@ -1,5 +1,6 @@ -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { PreviousRollupData } from './previous_rollup_data.js'; @@ -27,7 +28,7 @@ export class MergeRollupInputs { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -46,16 +47,16 @@ export class MergeRollupInputs { * @returns A new MergeRollupInputs instance. */ static fromString(str: string) { - return MergeRollupInputs.fromBuffer(Buffer.from(str, 'hex')); + return MergeRollupInputs.fromBuffer(hexToBuffer(str)); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a buffer representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } - /** Creates an instance from a hex string. */ + /** Creates an instance from a string. */ static get schema() { - return hexSchemaFor(MergeRollupInputs); + return bufferSchemaFor(MergeRollupInputs); } } diff --git a/yarn-project/circuits.js/src/structs/rollup/private_base_rollup_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/private_base_rollup_inputs.ts index 1d354861e1a..a83a6655e28 100644 --- a/yarn-project/circuits.js/src/structs/rollup/private_base_rollup_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/private_base_rollup_inputs.ts @@ -1,5 +1,6 @@ -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { PrivateBaseRollupHints } from './base_rollup_hints.js'; @@ -26,24 +27,24 @@ export class PrivateBaseRollupInputs { } static fromString(str: string) { - return PrivateBaseRollupInputs.fromBuffer(Buffer.from(str, 'hex')); + return PrivateBaseRollupInputs.fromBuffer(hexToBuffer(str)); } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static empty() { return new PrivateBaseRollupInputs(PrivateTubeData.empty(), PrivateBaseRollupHints.empty()); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a buffer representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string. */ static get schema() { - return hexSchemaFor(PrivateBaseRollupInputs); + return bufferSchemaFor(PrivateBaseRollupInputs); } } diff --git a/yarn-project/circuits.js/src/structs/rollup/public_base_rollup_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/public_base_rollup_inputs.ts index 1fa11ed3688..2bf644f4b81 100644 --- a/yarn-project/circuits.js/src/structs/rollup/public_base_rollup_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/public_base_rollup_inputs.ts @@ -1,5 +1,6 @@ -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { AvmProofData } from './avm_proof_data.js'; @@ -33,25 +34,26 @@ export class PublicBaseRollupInputs { toBuffer() { return serializeToBuffer(...PublicBaseRollupInputs.getFields(this)); } + static fromString(str: string) { - return PublicBaseRollupInputs.fromBuffer(Buffer.from(str, 'hex')); + return PublicBaseRollupInputs.fromBuffer(hexToBuffer(str)); } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static empty() { return new PublicBaseRollupInputs(PublicTubeData.empty(), AvmProofData.empty(), PublicBaseRollupHints.empty()); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } - /** Creates an instance from a hex string. */ + /** Creates an instance from a string. */ static get schema() { - return hexSchemaFor(PublicBaseRollupInputs); + return bufferSchemaFor(PublicBaseRollupInputs); } } diff --git a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts index a8eb8b433e5..180bfbdcc30 100644 --- a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts @@ -1,6 +1,7 @@ import { Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, type Tuple, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { AZTEC_MAX_EPOCH_DURATION } from '../../constants.gen.js'; @@ -36,7 +37,7 @@ export class RootRollupInputs { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -76,17 +77,17 @@ export class RootRollupInputs { * @returns A new RootRollupInputs instance. */ static fromString(str: string) { - return RootRollupInputs.fromBuffer(Buffer.from(str, 'hex')); + return RootRollupInputs.fromBuffer(hexToBuffer(str)); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } - /** Creates an instance from a hex string. */ + /** Creates an instance from a string. */ static get schema() { - return hexSchemaFor(RootRollupInputs); + return bufferSchemaFor(RootRollupInputs); } } @@ -163,20 +164,20 @@ export class RootRollupPublicInputs { } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromString(str: string) { - return RootRollupPublicInputs.fromBuffer(Buffer.from(str, 'hex')); + return RootRollupPublicInputs.fromBuffer(hexToBuffer(str)); } - /** Returns a hex representation for JSON serialization. */ + /** Returns a representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } - /** Creates an instance from a hex string. */ + /** Creates an instance from a string. */ static get schema() { - return hexSchemaFor(RootRollupPublicInputs); + return bufferSchemaFor(RootRollupPublicInputs); } } diff --git a/yarn-project/circuits.js/src/structs/rollup/tube_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/tube_inputs.ts index 0320d0ec228..86a58efbaf8 100644 --- a/yarn-project/circuits.js/src/structs/rollup/tube_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/tube_inputs.ts @@ -1,5 +1,6 @@ -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { ClientIvcProof } from '../client_ivc_proof.js'; @@ -28,7 +29,7 @@ export class TubeInputs { * @returns The instance serialized to a hex string. */ toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** @@ -50,7 +51,7 @@ export class TubeInputs { * @returns A new TubeInputs instance. */ static fromString(str: string) { - return TubeInputs.fromBuffer(Buffer.from(str, 'hex')); + return TubeInputs.fromBuffer(hexToBuffer(str)); } static empty() { @@ -59,11 +60,11 @@ export class TubeInputs { /** Returns a hex representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string. */ static get schema() { - return hexSchemaFor(TubeInputs); + return bufferSchemaFor(TubeInputs); } } diff --git a/yarn-project/circuits.js/src/structs/rollup_validation_requests.ts b/yarn-project/circuits.js/src/structs/rollup_validation_requests.ts index 4113649893d..2d2279b8c88 100644 --- a/yarn-project/circuits.js/src/structs/rollup_validation_requests.ts +++ b/yarn-project/circuits.js/src/structs/rollup_validation_requests.ts @@ -1,5 +1,6 @@ import { type Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { MaxBlockNumber } from './max_block_number.js'; @@ -23,7 +24,7 @@ export class RollupValidationRequests { } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromFields(fields: Fr[] | FieldReader) { @@ -47,7 +48,7 @@ export class RollupValidationRequests { * @returns Deserialized object. */ static fromString(str: string) { - return RollupValidationRequests.fromBuffer(Buffer.from(str, 'hex')); + return RollupValidationRequests.fromBuffer(hexToBuffer(str)); } static empty() { diff --git a/yarn-project/circuits.js/src/structs/shared.ts b/yarn-project/circuits.js/src/structs/shared.ts index c8cce1576fe..ae40dd95953 100644 --- a/yarn-project/circuits.js/src/structs/shared.ts +++ b/yarn-project/circuits.js/src/structs/shared.ts @@ -43,8 +43,3 @@ export enum RollupTypes { Merge = 1, Root = 2, } - -/** - * String encoding of serialized buffer data - */ -export const STRING_ENCODING: BufferEncoding = 'hex'; diff --git a/yarn-project/circuits.js/src/structs/state_reference.ts b/yarn-project/circuits.js/src/structs/state_reference.ts index 8f0c1fd0be0..49e91ac5324 100644 --- a/yarn-project/circuits.js/src/structs/state_reference.ts +++ b/yarn-project/circuits.js/src/structs/state_reference.ts @@ -19,10 +19,6 @@ export class StateReference { public partial: PartialStateReference, ) {} - toJSON() { - return { l1ToL2MessageTree: this.l1ToL2MessageTree, partial: this.partial }; - } - static get schema() { return z .object({ diff --git a/yarn-project/circuits.js/src/structs/trees/nullifier_leaf.ts b/yarn-project/circuits.js/src/structs/trees/nullifier_leaf.ts index 8d561e1ebfb..52b8be14aec 100644 --- a/yarn-project/circuits.js/src/structs/trees/nullifier_leaf.ts +++ b/yarn-project/circuits.js/src/structs/trees/nullifier_leaf.ts @@ -38,14 +38,6 @@ export class NullifierLeafPreimage implements IndexedTreeLeafPreimage { ); } - toJSON() { - return { - nullifier: this.nullifier.toString(), - nextNullifier: this.nextNullifier.toString(), - nextIndex: '0x' + this.nextIndex.toString(16), - }; - } - getKey(): bigint { return this.nullifier.toBigInt(); } @@ -102,14 +94,6 @@ export class NullifierLeafPreimage implements IndexedTreeLeafPreimage { static clone(preimage: NullifierLeafPreimage): NullifierLeafPreimage { return new NullifierLeafPreimage(preimage.nullifier, preimage.nextNullifier, preimage.nextIndex); } - - static fromJSON(json: any): NullifierLeafPreimage { - return new NullifierLeafPreimage( - Fr.fromString(json.nullifier), - Fr.fromString(json.nextNullifier), - BigInt(json.nextIndex), - ); - } } /** diff --git a/yarn-project/circuits.js/src/structs/tx_context.ts b/yarn-project/circuits.js/src/structs/tx_context.ts index 526ff0860ef..33234b4417a 100644 --- a/yarn-project/circuits.js/src/structs/tx_context.ts +++ b/yarn-project/circuits.js/src/structs/tx_context.ts @@ -37,14 +37,6 @@ export class TxContext { .transform(TxContext.from); } - toJSON() { - return { - chainId: this.chainId, - version: this.version, - gasSettings: this.gasSettings, - }; - } - getSize() { return this.chainId.size + this.version.size + this.gasSettings.getSize(); } diff --git a/yarn-project/circuits.js/src/structs/verification_key.ts b/yarn-project/circuits.js/src/structs/verification_key.ts index 22aa2d68e04..f3fc4a27610 100644 --- a/yarn-project/circuits.js/src/structs/verification_key.ts +++ b/yarn-project/circuits.js/src/structs/verification_key.ts @@ -1,8 +1,9 @@ import { makeTuple } from '@aztec/foundation/array'; import { times } from '@aztec/foundation/collection'; import { Fq, Fr } from '@aztec/foundation/fields'; -import { hexSchemaFor } from '@aztec/foundation/schemas'; +import { bufferSchemaFor } from '@aztec/foundation/schemas'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex, hexToBuffer } from '@aztec/foundation/string'; import { HONK_VERIFICATION_KEY_LENGTH_IN_FIELDS } from '../constants.gen.js'; import { CircuitType } from './shared.js'; @@ -100,11 +101,11 @@ export class VerificationKeyAsFields { static get schema() { // TODO(palla/schemas): Should we verify the hash matches the key when deserializing? - return hexSchemaFor(VerificationKeyAsFields); + return bufferSchemaFor(VerificationKeyAsFields); } toJSON() { - return '0x' + this.toBuffer().toString('hex'); + return this.toBuffer(); } /** @@ -261,7 +262,7 @@ export class VerificationKeyData { } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromBuffer(buffer: Buffer | BufferReader): VerificationKeyData { @@ -273,7 +274,7 @@ export class VerificationKeyData { } static fromString(str: string): VerificationKeyData { - return VerificationKeyData.fromBuffer(Buffer.from(str, 'hex')); + return VerificationKeyData.fromBuffer(hexToBuffer(str)); } public clone() { @@ -282,11 +283,11 @@ export class VerificationKeyData { /** Returns a hex representation for JSON serialization. */ toJSON() { - return this.toString(); + return this.toBuffer(); } /** Creates an instance from a hex string. */ static get schema() { - return hexSchemaFor(VerificationKeyData); + return bufferSchemaFor(VerificationKeyData); } } diff --git a/yarn-project/circuits.js/src/structs/vk_witness_data.ts b/yarn-project/circuits.js/src/structs/vk_witness_data.ts index 723475b5fa2..90e2239cd65 100644 --- a/yarn-project/circuits.js/src/structs/vk_witness_data.ts +++ b/yarn-project/circuits.js/src/structs/vk_witness_data.ts @@ -1,6 +1,7 @@ import { makeTuple } from '@aztec/foundation/array'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex } from '@aztec/foundation/string'; import { VK_TREE_HEIGHT } from '../constants.gen.js'; import { type UInt32 } from './shared.js'; @@ -37,6 +38,6 @@ export class VkWitnessData { } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } } diff --git a/yarn-project/circuits.js/src/types/public_keys.ts b/yarn-project/circuits.js/src/types/public_keys.ts index 321fc04c7a3..d426ab2f3b8 100644 --- a/yarn-project/circuits.js/src/types/public_keys.ts +++ b/yarn-project/circuits.js/src/types/public_keys.ts @@ -2,6 +2,7 @@ import { poseidon2HashWithSeparator } from '@aztec/foundation/crypto'; import { Fr, Point } from '@aztec/foundation/fields'; import { schemas } from '@aztec/foundation/schemas'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { bufferToHex } from '@aztec/foundation/string'; import { type FieldsOf } from '@aztec/foundation/types'; import { z } from 'zod'; @@ -184,7 +185,7 @@ export class PublicKeys { } toString() { - return this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } static fromString(keys: string) { diff --git a/yarn-project/cli-wallet/src/cmds/cancel_tx.ts b/yarn-project/cli-wallet/src/cmds/cancel_tx.ts index c0fb4812f77..2d6ae924075 100644 --- a/yarn-project/cli-wallet/src/cmds/cancel_tx.ts +++ b/yarn-project/cli-wallet/src/cmds/cancel_tx.ts @@ -45,7 +45,7 @@ export async function cancelTx( log(` Tx fee: ${cancelReceipt.transactionFee}`); log(` Status: ${cancelReceipt.status}`); log(` Block number: ${cancelReceipt.blockNumber}`); - log(` Block hash: ${cancelReceipt.blockHash?.toString('hex')}`); + log(` Block hash: ${cancelReceipt.blockHash?.toString()}`); } catch (err: any) { log(`Could not cancel transaction\n ${err.message}`); } diff --git a/yarn-project/cli-wallet/src/cmds/send.ts b/yarn-project/cli-wallet/src/cmds/send.ts index fa6af43fa93..b87097ec125 100644 --- a/yarn-project/cli-wallet/src/cmds/send.ts +++ b/yarn-project/cli-wallet/src/cmds/send.ts @@ -42,7 +42,7 @@ export async function send( log(` Tx fee: ${receipt.transactionFee}`); log(` Status: ${receipt.status}`); log(` Block number: ${receipt.blockNumber}`); - log(` Block hash: ${receipt.blockHash?.toString('hex')}`); + log(` Block hash: ${receipt.blockHash?.toString()}`); } catch (err: any) { log(`Transaction failed\n ${err.message}`); } diff --git a/yarn-project/cli/src/cmds/infrastructure/setup_protocol_contract.ts b/yarn-project/cli/src/cmds/infrastructure/setup_protocol_contract.ts index 113bfea6a09..a7473487d31 100644 --- a/yarn-project/cli/src/cmds/infrastructure/setup_protocol_contract.ts +++ b/yarn-project/cli/src/cmds/infrastructure/setup_protocol_contract.ts @@ -1,5 +1,6 @@ import { SignerlessWallet, type WaitOpts, createPXEClient, makeFetch } from '@aztec/aztec.js'; import { DefaultMultiCallEntrypoint } from '@aztec/aztec.js/entrypoint'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; import { type LogFn } from '@aztec/foundation/log'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; @@ -18,7 +19,7 @@ export async function setupProtocolContracts( proven: !skipProofWait, provenTimeout: 600, }; - log('setupProtocolContracts: Wait options' + JSON.stringify(waitOpts)); + log('setupProtocolContracts: Wait options' + jsonStringify(waitOpts)); log('setupProtocolContracts: Creating PXE client...'); const pxe = createPXEClient(rpcUrl, makeFetch([1, 1, 1, 1, 1], false)); const wallet = new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(l1ChainId, 1)); diff --git a/yarn-project/cli/src/cmds/pxe/get_current_base_fee.ts b/yarn-project/cli/src/cmds/pxe/get_current_base_fee.ts index 1d64ad585f2..c736a4766b6 100644 --- a/yarn-project/cli/src/cmds/pxe/get_current_base_fee.ts +++ b/yarn-project/cli/src/cmds/pxe/get_current_base_fee.ts @@ -1,8 +1,9 @@ import { createCompatibleClient } from '@aztec/aztec.js'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; export async function getCurrentBaseFee(rpcUrl: string, debugLogger: DebugLogger, log: LogFn) { const client = await createCompatibleClient(rpcUrl, debugLogger); const fees = await client.getCurrentBaseFees(); - log(`Current fees: ${JSON.stringify(fees.toJSON())}`); + log(`Current fees: ${jsonStringify(fees)}`); } diff --git a/yarn-project/cli/src/utils/inspect.ts b/yarn-project/cli/src/utils/inspect.ts index 855c38b9ef5..77d6c067a7e 100644 --- a/yarn-project/cli/src/utils/inspect.ts +++ b/yarn-project/cli/src/utils/inspect.ts @@ -58,7 +58,7 @@ export async function inspectTx( const artifactMap = opts?.artifactMap ?? (await getKnownArtifacts(pxe)); if (opts.includeBlockInfo) { - log(` Block: ${receipt.blockNumber} (${receipt.blockHash?.toString('hex')})`); + log(` Block: ${receipt.blockNumber} (${receipt.blockHash?.toString()})`); } if (receipt.transactionFee) { log(` Fee: ${receipt.transactionFee.toString()}`); diff --git a/yarn-project/end-to-end/src/e2e_fees/failures.test.ts b/yarn-project/end-to-end/src/e2e_fees/failures.test.ts index dcacb4ca441..664f920873d 100644 --- a/yarn-project/end-to-end/src/e2e_fees/failures.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/failures.test.ts @@ -242,7 +242,7 @@ describe('e2e_fees failures', () => { }, }) .wait(), - ).rejects.toThrow(/Transaction [0-9a-f]{64} was dropped\. Reason: Tx dropped by P2P node\./); + ).rejects.toThrow(/Transaction (0x)?[0-9a-fA-F]{64} was dropped\. Reason: Tx dropped by P2P node\./); }); it('includes transaction that error in teardown', async () => { diff --git a/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts b/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts index 15e77e4e775..e2d230a40a2 100644 --- a/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts +++ b/yarn-project/end-to-end/src/e2e_prover/e2e_prover_test.ts @@ -253,7 +253,7 @@ export class FullProverTest { // The simulated prover node (now shutdown) used private key index 2 const proverNodePrivateKey = getPrivateKeyFromIndex(2); - const proverNodeSenderAddress = privateKeyToAddress(new Buffer32(proverNodePrivateKey!).to0xString()); + const proverNodeSenderAddress = privateKeyToAddress(new Buffer32(proverNodePrivateKey!).toString()); this.proverAddress = EthAddress.fromString(proverNodeSenderAddress); this.logger.verbose(`Funding prover node at ${proverNodeSenderAddress}`); diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts index 3a85d0ff79b..6f58a48dda6 100644 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts @@ -368,7 +368,7 @@ async function setupFromFresh( const cheatCodes = await CheatCodes.create(aztecNodeConfig.l1RpcUrl, pxe); if (statePath) { - writeFileSync(`${statePath}/aztec_node_config.json`, JSON.stringify(aztecNodeConfig)); + writeFileSync(`${statePath}/aztec_node_config.json`, JSON.stringify(aztecNodeConfig, resolver)); } return { @@ -497,7 +497,7 @@ export const addAccounts = logger.verbose('Account deployment tx hashes:'); for (const provenTx of provenTxs) { - logger.verbose(provenTx.getTxHash().to0xString()); + logger.verbose(provenTx.getTxHash().toString()); } logger.verbose('Deploying accounts...'); diff --git a/yarn-project/end-to-end/src/prover-coordination/e2e_prover_coordination.test.ts b/yarn-project/end-to-end/src/prover-coordination/e2e_prover_coordination.test.ts index 665abe523dc..6ec6832ff53 100644 --- a/yarn-project/end-to-end/src/prover-coordination/e2e_prover_coordination.test.ts +++ b/yarn-project/end-to-end/src/prover-coordination/e2e_prover_coordination.test.ts @@ -112,7 +112,7 @@ describe('e2e_prover_coordination', () => { const proverKey = Buffer32.random(); proverSigner = new Secp256k1Signer(proverKey); proverWallet = createWalletClient({ - account: privateKeyToAccount(proverKey.to0xString()), + account: privateKeyToAccount(proverKey.toString()), chain: foundry, transport: http(ctx.aztecNodeConfig.l1RpcUrl), }); diff --git a/yarn-project/foundation/src/abi/abi.ts b/yarn-project/foundation/src/abi/abi.ts index 2f13d6ab67a..4ba09fb11a9 100644 --- a/yarn-project/foundation/src/abi/abi.ts +++ b/yarn-project/foundation/src/abi/abi.ts @@ -230,7 +230,7 @@ export interface FunctionArtifact extends FunctionAbi { export const FunctionArtifactSchema = FunctionAbiSchema.and( z.object({ - bytecode: schemas.BufferB64, + bytecode: schemas.Buffer, verificationKey: z.string().optional(), debugSymbols: z.string(), debug: FunctionDebugMetadataSchema.optional(), diff --git a/yarn-project/foundation/src/abi/encoder.test.ts b/yarn-project/foundation/src/abi/encoder.test.ts index 0f1e6841cba..0b901d030ef 100644 --- a/yarn-project/foundation/src/abi/encoder.test.ts +++ b/yarn-project/foundation/src/abi/encoder.test.ts @@ -1,7 +1,7 @@ import { AztecAddress } from '../aztec-address/index.js'; import { Fr } from '../fields/fields.js'; import { Point } from '../fields/point.js'; -import { jsonParseWithSchema } from '../json-rpc/convert.js'; +import { jsonParseWithSchema, jsonStringify } from '../json-rpc/convert.js'; import { schemas } from '../schemas/schemas.js'; import { type FunctionAbi, FunctionType } from './abi.js'; import { encodeArguments } from './encoder.js'; @@ -30,7 +30,7 @@ describe('abi/encoder', () => { const field = Fr.random(); expect(encodeArguments(abi, [field])).toEqual([field]); - const serializedField = jsonParseWithSchema(JSON.stringify(field), schemas.Fr); + const serializedField = jsonParseWithSchema(jsonStringify(field), schemas.Fr); expect(encodeArguments(abi, [serializedField])).toEqual([field]); }); @@ -122,7 +122,7 @@ describe('abi/encoder', () => { const completeAddressLike = { address, publicKey: Point.random(), partialAddress: Fr.random() }; expect(encodeArguments(abi, [completeAddressLike])).toEqual([address.toField()]); - const serializedAddress = jsonParseWithSchema(JSON.stringify(address), schemas.AztecAddress); + const serializedAddress = jsonParseWithSchema(jsonStringify(address), schemas.AztecAddress); expect(encodeArguments(abi, [serializedAddress])).toEqual([address.toField()]); }); diff --git a/yarn-project/foundation/src/abi/event_selector.ts b/yarn-project/foundation/src/abi/event_selector.ts index ea4d8bd234c..0203d562380 100644 --- a/yarn-project/foundation/src/abi/event_selector.ts +++ b/yarn-project/foundation/src/abi/event_selector.ts @@ -1,6 +1,7 @@ import { fromHex, toBigIntBE } from '../bigint-buffer/index.js'; import { poseidon2HashBytes, randomBytes } from '../crypto/index.js'; import { type Fr } from '../fields/fields.js'; +import { hexSchemaFor } from '../schemas/utils.js'; import { BufferReader } from '../serialize/buffer_reader.js'; import { Selector } from './selector.js'; @@ -83,9 +84,10 @@ export class EventSelector extends Selector { } toJSON() { - return { - type: 'EventSelector', - value: this.toString(), - }; + return this.toString(); + } + + static get schema() { + return hexSchemaFor(EventSelector); } } diff --git a/yarn-project/foundation/src/abi/function_selector.ts b/yarn-project/foundation/src/abi/function_selector.ts index 7641234f9ab..00b75d1b500 100644 --- a/yarn-project/foundation/src/abi/function_selector.ts +++ b/yarn-project/foundation/src/abi/function_selector.ts @@ -1,6 +1,7 @@ import { fromHex, toBigIntBE } from '../bigint-buffer/index.js'; import { poseidon2HashBytes, randomBytes } from '../crypto/index.js'; import { type Fr } from '../fields/fields.js'; +import { hexSchemaFor } from '../schemas/utils.js'; import { BufferReader } from '../serialize/buffer_reader.js'; import { FieldReader } from '../serialize/field_reader.js'; import { TypeRegistry } from '../serialize/type_registry.js'; @@ -132,10 +133,11 @@ export class FunctionSelector extends Selector { } toJSON() { - return { - type: 'FunctionSelector', - value: this.toString(), - }; + return this.toString(); + } + + static get schema() { + return hexSchemaFor(FunctionSelector); } } diff --git a/yarn-project/foundation/src/abi/note_selector.ts b/yarn-project/foundation/src/abi/note_selector.ts index 8fdcaa945c3..10f784620f1 100644 --- a/yarn-project/foundation/src/abi/note_selector.ts +++ b/yarn-project/foundation/src/abi/note_selector.ts @@ -1,6 +1,7 @@ import { toBigIntBE } from '../bigint-buffer/index.js'; import { randomBytes } from '../crypto/index.js'; import { type Fr } from '../fields/fields.js'; +import { hexSchemaFor } from '../schemas/utils.js'; import { BufferReader } from '../serialize/buffer_reader.js'; import { TypeRegistry } from '../serialize/type_registry.js'; import { Selector } from './selector.js'; @@ -58,14 +59,11 @@ export class NoteSelector extends Selector { } toJSON() { - return { - type: 'NoteSelector', - value: this.toString(), - }; + return this.toString(); } - static fromJSON(json: any): NoteSelector { - return NoteSelector.fromString(json.value); + static get schema() { + return hexSchemaFor(NoteSelector); } } diff --git a/yarn-project/foundation/src/abi/selector.ts b/yarn-project/foundation/src/abi/selector.ts index e8f56e01093..9ee416654b3 100644 --- a/yarn-project/foundation/src/abi/selector.ts +++ b/yarn-project/foundation/src/abi/selector.ts @@ -2,6 +2,7 @@ import { inspect } from 'util'; import { toBufferBE } from '../bigint-buffer/index.js'; import { Fr } from '../fields/index.js'; +import { bufferToHex } from '../string/index.js'; /** A selector is the first 4 bytes of the hash of a signature. */ export abstract class Selector { @@ -36,7 +37,7 @@ export abstract class Selector { * @returns The string. */ toString(): string { - return '0x' + this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } [inspect.custom]() { diff --git a/yarn-project/foundation/src/aztec-address/index.ts b/yarn-project/foundation/src/aztec-address/index.ts index d58fd9b0d77..fe965da95e1 100644 --- a/yarn-project/foundation/src/aztec-address/index.ts +++ b/yarn-project/foundation/src/aztec-address/index.ts @@ -2,6 +2,7 @@ import { inspect } from 'util'; import { Fr, Point, fromBuffer } from '../fields/index.js'; +import { hexSchemaFor } from '../schemas/utils.js'; import { type BufferReader, FieldReader } from '../serialize/index.js'; import { TypeRegistry } from '../serialize/type_registry.js'; import { hexToBuffer } from '../string/index.js'; @@ -133,10 +134,11 @@ export class AztecAddress { } toJSON() { - return { - type: 'AztecAddress', - value: this.toString(), - }; + return this.toString(); + } + + static get schema() { + return hexSchemaFor(AztecAddress, AztecAddress.isAddress); } } diff --git a/yarn-project/foundation/src/buffer/buffer32.ts b/yarn-project/foundation/src/buffer/buffer32.ts index 4b1c2e1c25d..799df3f27ec 100644 --- a/yarn-project/foundation/src/buffer/buffer32.ts +++ b/yarn-project/foundation/src/buffer/buffer32.ts @@ -2,6 +2,8 @@ import { randomBytes } from '@aztec/foundation/crypto'; import { type Fr } from '@aztec/foundation/fields'; import { BufferReader, deserializeBigInt, serializeBigInt } from '@aztec/foundation/serialize'; +import { bufferToHex } from '../string/index.js'; + /** * A class representing a 32 byte Buffer. */ @@ -67,17 +69,13 @@ export class Buffer32 { * @returns The hex string. */ public toString() { - return this.buffer.toString('hex'); + return bufferToHex(this.buffer); } toJSON() { return this.toString(); } - public to0xString(): `0x${string}` { - return `0x${this.buffer.toString('hex')}`; - } - /** * Convert this hash to a big int. * @returns The big int. @@ -117,18 +115,6 @@ export class Buffer32 { * @param str - The TX hash in string format. * @returns A new Buffer32 object. */ - public static fromStringUnchecked(str: string): Buffer32 { - return new Buffer32(Buffer.from(str, 'hex')); - } - - /** - * Converts a string into a Buffer32 object. - * NOTE: this method includes checks for the 0x prefix and the length of the string. - * if you dont need this checks, use fromStringUnchecked instead. - * - * @param str - The TX hash in string format. - * @returns A new Buffer32 object. - */ public static fromString(str: string): Buffer32 { if (str.startsWith('0x')) { str = str.slice(2); diff --git a/yarn-project/foundation/src/crypto/secp256k1-signer/secp256k1_signer.test.ts b/yarn-project/foundation/src/crypto/secp256k1-signer/secp256k1_signer.test.ts index 707227208f2..05c9d12fdc7 100644 --- a/yarn-project/foundation/src/crypto/secp256k1-signer/secp256k1_signer.test.ts +++ b/yarn-project/foundation/src/crypto/secp256k1-signer/secp256k1_signer.test.ts @@ -31,13 +31,13 @@ describe('Secp256k1Signer', () => { const ethHashedMessage = hashMessage({ raw: message }); const ethHashedMessageBuffer = Buffer32.fromBuffer(Buffer.from(ethHashedMessage.slice(2), 'hex')); - const viemSignature = Signature.from0xString(await viemSigner.signMessage({ message: { raw: message } })); + const viemSignature = Signature.fromString(await viemSigner.signMessage({ message: { raw: message } })); const lightSignature = lightSigner.sign(ethHashedMessageBuffer); // Check signatures match expect(viemSignature.equals(lightSignature)).toBe(true); - const viemPublicKey = await viemRecoverPublicKey({ hash: ethHashedMessage, signature: viemSignature.to0xString() }); + const viemPublicKey = await viemRecoverPublicKey({ hash: ethHashedMessage, signature: viemSignature.toString() }); const lightPublicKey = lightRecoverPublicKey(ethHashedMessageBuffer, lightSignature); // Check recovered public keys match @@ -46,7 +46,7 @@ describe('Secp256k1Signer', () => { // Get the eth address can be recovered from the message and signature const viemPublicKeyToAddress = publicKeyToAddress(viemPublicKey); const viemAddress = EthAddress.fromString( - await viemRecoverAddress({ hash: ethHashedMessage, signature: viemSignature.to0xString() }), + await viemRecoverAddress({ hash: ethHashedMessage, signature: viemSignature.toString() }), ); const lightAddress = lightRecoverAddress( Buffer32.fromBuffer(Buffer.from(ethHashedMessage.slice(2), 'hex')), diff --git a/yarn-project/foundation/src/eth-address/index.ts b/yarn-project/foundation/src/eth-address/index.ts index f30e61a0230..ed9acffbb5b 100644 --- a/yarn-project/foundation/src/eth-address/index.ts +++ b/yarn-project/foundation/src/eth-address/index.ts @@ -3,8 +3,10 @@ import { inspect } from 'util'; import { keccak256String } from '../crypto/keccak/index.js'; import { randomBytes } from '../crypto/random/index.js'; import { Fr } from '../fields/index.js'; +import { hexSchemaFor } from '../schemas/utils.js'; import { BufferReader, FieldReader } from '../serialize/index.js'; import { TypeRegistry } from '../serialize/type_registry.js'; +import { bufferToHex } from '../string/index.js'; /** * Represents an Ethereum address as a 20-byte buffer and provides various utility methods @@ -154,7 +156,7 @@ export class EthAddress { * @returns A hex-encoded string representation of the Ethereum address. */ public toString() { - return `0x${this.buffer.toString('hex')}` as `0x${string}`; + return bufferToHex(this.buffer); } [inspect.custom]() { @@ -226,19 +228,12 @@ export class EthAddress { return new EthAddress(reader.readBytes(EthAddress.SIZE_IN_BYTES)); } - /** - * Friendly representation for debugging purposes. - * @returns A hex string representing the address. - */ - toFriendlyJSON() { + toJSON() { return this.toString(); } - toJSON() { - return { - type: 'EthAddress', - value: this.toString(), - }; + static get schema() { + return hexSchemaFor(EthAddress, EthAddress.isAddress); } } diff --git a/yarn-project/foundation/src/eth-signature/eth_signature.test.ts b/yarn-project/foundation/src/eth-signature/eth_signature.test.ts index 2a2fd690184..ec76be5b6fa 100644 --- a/yarn-project/foundation/src/eth-signature/eth_signature.test.ts +++ b/yarn-project/foundation/src/eth-signature/eth_signature.test.ts @@ -25,15 +25,15 @@ describe('eth signature', () => { expect(deserialized).toEqual(serialized); }; - it('should serialize / deserialize to buffer', () => { + it('should serialize and deserialize to buffer', () => { const serialized = signature.toBuffer(); const deserialized = Signature.fromBuffer(serialized); checkEquivalence(signature, deserialized); }); - it('should serialize / deserialize real signature to hex string', () => { - const serialized = signature.to0xString(); - const deserialized = Signature.from0xString(serialized); + it('should serialize and deserialize real signature to hex string', () => { + const serialized = signature.toString(); + const deserialized = Signature.fromString(serialized); checkEquivalence(signature, deserialized); }); @@ -42,24 +42,24 @@ describe('eth signature', () => { expect(sender).toEqual(signer.address); }); - it('should serialize / deserialize to hex string with v=0', () => { + it('should serialize and deserialize to hex string with v=0', () => { const signature = new Signature(Buffer32.random(), Buffer32.random(), 0, false); - const serialized = signature.to0xString(); - const deserialized = Signature.from0xString(serialized); + const serialized = signature.toString(); + const deserialized = Signature.fromString(serialized); checkEquivalence(signature, deserialized); }); - it('should serialize / deserialize to hex string with 1-digit v', () => { + it('should serialize and deserialize to hex string with 1-digit v', () => { const signature = new Signature(Buffer32.random(), Buffer32.random(), 1, false); - const serialized = signature.to0xString(); - const deserialized = Signature.from0xString(serialized); + const serialized = signature.toString(); + const deserialized = Signature.fromString(serialized); checkEquivalence(signature, deserialized); }); - it('should serialize / deserialize to hex string with 2-digit v', () => { + it('should serialize and deserialize to hex string with 2-digit v', () => { const signature = new Signature(Buffer32.random(), Buffer32.random(), 26, false); - const serialized = signature.to0xString(); - const deserialized = Signature.from0xString(serialized); + const serialized = signature.toString(); + const deserialized = Signature.fromString(serialized); checkEquivalence(signature, deserialized); }); }); diff --git a/yarn-project/foundation/src/eth-signature/eth_signature.ts b/yarn-project/foundation/src/eth-signature/eth_signature.ts index 521cf680e9e..dec046702d0 100644 --- a/yarn-project/foundation/src/eth-signature/eth_signature.ts +++ b/yarn-project/foundation/src/eth-signature/eth_signature.ts @@ -1,6 +1,10 @@ import { Buffer32 } from '@aztec/foundation/buffer'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { z } from 'zod'; + +import { hasHexPrefix, hexToBuffer } from '../string/index.js'; + /**Viem Signature * * A version of the Signature class that uses `0x${string}` values for r and s rather than @@ -45,7 +49,7 @@ export class Signature { return new Signature(r, s, v, isEmpty); } - static isValid0xString(sig: `0x${string}`): boolean { + static isValidString(sig: `0x${string}`): boolean { return /^0x[0-9a-f]{129,}$/i.test(sig); } @@ -54,10 +58,9 @@ export class Signature { * parsing from viem, we can expect the v value to be a u8, rather than our * default serialization of u32 */ - static from0xString(sig: `0x${string}`): Signature { - const buf = Buffer.from(sig.slice(2), 'hex'); + static fromString(sig: `0x${string}`): Signature { + const buf = hexToBuffer(sig); const reader = BufferReader.asReader(buf); - const r = reader.readObject(Buffer32); const s = reader.readObject(Buffer32); const v = parseInt(sig.slice(2 + 64 * 2), 16); @@ -95,8 +98,8 @@ export class Signature { return this.size; } - to0xString(): `0x${string}` { - return `0x${this.r.toString()}${this.s.toString()}${this.v.toString(16)}`; + toString(): `0x${string}` { + return `0x${this.r.buffer.toString('hex')}${this.s.buffer.toString('hex')}${this.v.toString(16)}`; } /** @@ -104,14 +107,22 @@ export class Signature { */ toViemSignature(): ViemSignature { return { - r: this.r.to0xString(), - s: this.s.to0xString(), + r: this.r.toString(), + s: this.s.toString(), v: this.v, isEmpty: this.isEmpty, }; } toJSON() { - return this.to0xString(); + return this.toString(); + } + + static get schema() { + return z + .string() + .refine(hasHexPrefix, 'No hex prefix') + .refine(Signature.isValidString, 'Not a valid Ethereum signature') + .transform(Signature.fromString); } } diff --git a/yarn-project/foundation/src/fields/fields.ts b/yarn-project/foundation/src/fields/fields.ts index 4653d0eeee8..84b559c4f3c 100644 --- a/yarn-project/foundation/src/fields/fields.ts +++ b/yarn-project/foundation/src/fields/fields.ts @@ -4,6 +4,7 @@ import { inspect } from 'util'; import { toBigIntBE, toBufferBE } from '../bigint-buffer/index.js'; import { randomBytes } from '../crypto/random/index.js'; +import { hexSchemaFor } from '../schemas/utils.js'; import { BufferReader } from '../serialize/buffer_reader.js'; import { TypeRegistry } from '../serialize/type_registry.js'; @@ -300,12 +301,12 @@ export class Fr extends BaseField { return Fr.fromBuffer(rootBuf); } - // TODO(palla/schemas): Use toString instead of structured type toJSON() { - return { - type: 'Fr', - value: this.toString(), - }; + return this.toString(); + } + + static get schema() { + return hexSchemaFor(Fr); } } @@ -385,10 +386,11 @@ export class Fq extends BaseField { } toJSON() { - return { - type: 'Fq', - value: this.toString(), - }; + return this.toString(); + } + + static get schema() { + return hexSchemaFor(Fq); } } diff --git a/yarn-project/foundation/src/fields/point.test.ts b/yarn-project/foundation/src/fields/point.test.ts index f2b4813683a..f98771fb5c0 100644 --- a/yarn-project/foundation/src/fields/point.test.ts +++ b/yarn-project/foundation/src/fields/point.test.ts @@ -1,3 +1,4 @@ +import { jsonParseWithSchema, jsonStringify } from '../json-rpc/convert.js'; import { schemas } from '../schemas/schemas.js'; import { updateInlineTestData } from '../testing/test_data.js'; import { Fr } from './fields.js'; @@ -93,7 +94,7 @@ describe('Point', () => { it('serializes from and to JSON', () => { const p = Point.random(); - const p2 = schemas.Point.parse(JSON.parse(JSON.stringify(p))); + const p2 = jsonParseWithSchema(jsonStringify(p), schemas.Point); expect(p).toEqual(p2); expect(p2).toBeInstanceOf(Point); }); diff --git a/yarn-project/foundation/src/fields/point.ts b/yarn-project/foundation/src/fields/point.ts index bfe1adcb3e7..96135f47b50 100644 --- a/yarn-project/foundation/src/fields/point.ts +++ b/yarn-project/foundation/src/fields/point.ts @@ -1,7 +1,9 @@ import { toBigIntBE } from '../bigint-buffer/index.js'; import { poseidon2Hash } from '../crypto/poseidon/index.js'; import { randomBoolean } from '../crypto/random/index.js'; +import { hexSchemaFor } from '../schemas/utils.js'; import { BufferReader, FieldReader, serializeToBuffer } from '../serialize/index.js'; +import { bufferToHex, hexToBuffer } from '../string/index.js'; import { Fr } from './fields.js'; /** @@ -34,6 +36,14 @@ export class Point { // TODO(#7386): check if on curve } + toJSON() { + return this.toString(); + } + + static get schema() { + return hexSchemaFor(Point); + } + /** * Generate a random Point instance. * @@ -84,14 +94,14 @@ export class Point { /** * Create a Point instance from a hex-encoded string. - * The input 'address' should be prefixed with '0x' or not, and have exactly 128 hex characters representing the x and y coordinates. + * The input should be prefixed with '0x' or not, and have exactly 128 hex characters representing the x and y coordinates. * Throws an error if the input length is invalid or coordinate values are out of range. * - * @param address - The hex-encoded string representing the Point coordinates. + * @param str - The hex-encoded string representing the Point coordinates. * @returns A Point instance. */ - static fromString(address: string) { - return this.fromBuffer(Buffer.from(address.replace(/^0x/i, ''), 'hex')); + static fromString(str: string) { + return this.fromBuffer(hexToBuffer(str)); } /** @@ -211,7 +221,7 @@ export class Point { * @returns A hex-encoded string representing the Point instance. */ toString() { - return '0x' + this.toBuffer().toString('hex'); + return bufferToHex(this.toBuffer()); } /** diff --git a/yarn-project/foundation/src/json-rpc/client/fetch.ts b/yarn-project/foundation/src/json-rpc/client/fetch.ts index f93dce97f43..56773431b6d 100644 --- a/yarn-project/foundation/src/json-rpc/client/fetch.ts +++ b/yarn-project/foundation/src/json-rpc/client/fetch.ts @@ -1,4 +1,4 @@ -import { format } from 'util'; +import { format, inspect } from 'util'; import { type DebugLogger, createDebugLogger } from '../../log/index.js'; import { NoRetryError, makeBackoff, retry } from '../../retry/index.js'; @@ -25,18 +25,23 @@ export async function defaultFetch( ) { log.debug(format(`JsonRpcClient.fetch`, host, rpcMethod, '->', body)); let resp: Response; - if (useApiEndpoints) { - resp = await fetch(`${host}/${rpcMethod}`, { - method: 'POST', - body: jsonStringify(body), - headers: { 'content-type': 'application/json' }, - }); - } else { - resp = await fetch(host, { - method: 'POST', - body: jsonStringify({ ...body, method: rpcMethod }), - headers: { 'content-type': 'application/json' }, - }); + try { + if (useApiEndpoints) { + resp = await fetch(`${host}/${rpcMethod}`, { + method: 'POST', + body: jsonStringify(body), + headers: { 'content-type': 'application/json' }, + }); + } else { + resp = await fetch(host, { + method: 'POST', + body: jsonStringify({ ...body, method: rpcMethod }), + headers: { 'content-type': 'application/json' }, + }); + } + } catch (err) { + const errorMessage = `Error fetching from host ${host} with method ${rpcMethod}: ${inspect(err)}`; + throw new Error(errorMessage); } let responseJson; diff --git a/yarn-project/foundation/src/json-rpc/convert.test.ts b/yarn-project/foundation/src/json-rpc/convert.test.ts index b0817f765d4..98f06a0fb70 100644 --- a/yarn-project/foundation/src/json-rpc/convert.test.ts +++ b/yarn-project/foundation/src/json-rpc/convert.test.ts @@ -1,5 +1,6 @@ import { type ZodTypeAny, z } from 'zod'; +import { schemas } from '../schemas/schemas.js'; import { mapSchema, setSchema } from '../schemas/utils.js'; import { jsonStringify } from './convert.js'; @@ -9,27 +10,27 @@ describe('jsonStringify', () => { expect(schema.parse(JSON.parse(json))).toEqual(value); }; - it('object with primitive types', () => { + it('handles object with primitive types', () => { const values = { a: 10, b: 'foo', c: true }; test(values, z.object({ a: z.number(), b: z.string(), c: z.boolean() })); }); - it('object with bigints', () => { + it('handles object with bigints', () => { const values = { a: 10n }; test(values, z.object({ a: z.coerce.bigint() })); }); - it('tuples', () => { + it('handles tuples', () => { const values = [10, 'foo', true]; test(values, z.tuple([z.number(), z.string(), z.boolean()])); }); - it('arrays', () => { + it('handles arrays', () => { const values = [10, 20, 30]; test(values, z.array(z.number())); }); - it('maps', () => { + it('handles maps', () => { const values = new Map([ ['a', 10], ['b', 20], @@ -37,8 +38,21 @@ describe('jsonStringify', () => { test(values, mapSchema(z.string(), z.number())); }); - it('sets', () => { + it('handles sets', () => { const values = new Set([10, 20]); test(values, setSchema(z.number())); }); + + it('handles buffers', () => { + const value = Buffer.from('hello'); + const json = jsonStringify(value); + expect(json).toEqual('"aGVsbG8="'); + test(value, schemas.Buffer); + }); + + it('handles nullish', () => { + const values = [null, undefined]; + const json = jsonStringify(values); + expect(JSON.parse(json)).toEqual([null, null]); + }); }); diff --git a/yarn-project/foundation/src/json-rpc/convert.ts b/yarn-project/foundation/src/json-rpc/convert.ts index 8b040d74483..c518b3faa36 100644 --- a/yarn-project/foundation/src/json-rpc/convert.ts +++ b/yarn-project/foundation/src/json-rpc/convert.ts @@ -23,7 +23,9 @@ export function jsonStringify(obj: object, prettify?: boolean): string { (_key, value) => { if (typeof value === 'bigint') { return value.toString(); - } else if (typeof value === 'object' && Buffer.isBuffer(value)) { + } else if (typeof value === 'object' && value && value.type === 'Buffer' && Array.isArray(value.data)) { + return Buffer.from(value.data).toString('base64'); + } else if (typeof value === 'object' && value && Buffer.isBuffer(value)) { return value.toString('base64'); } else if (typeof value === 'object' && value instanceof Map) { return Array.from(value.entries()); diff --git a/yarn-project/foundation/src/json-rpc/index.ts b/yarn-project/foundation/src/json-rpc/index.ts index 2e33ff54f4e..8b918b16c74 100644 --- a/yarn-project/foundation/src/json-rpc/index.ts +++ b/yarn-project/foundation/src/json-rpc/index.ts @@ -1 +1 @@ -export { jsonStringify } from './convert.js'; +export { jsonStringify, jsonParseWithSchema, tryJsonStringify } from './convert.js'; diff --git a/yarn-project/foundation/src/schemas/schemas.ts b/yarn-project/foundation/src/schemas/schemas.ts index eca83d8bcd0..5677274d59c 100644 --- a/yarn-project/foundation/src/schemas/schemas.ts +++ b/yarn-project/foundation/src/schemas/schemas.ts @@ -7,65 +7,45 @@ import { NoteSelector } from '../abi/note_selector.js'; import { AztecAddress } from '../aztec-address/index.js'; import { Buffer32 } from '../buffer/buffer32.js'; import { EthAddress } from '../eth-address/index.js'; -import { Signature } from '../eth-signature/eth_signature.js'; import { Fq, Fr } from '../fields/fields.js'; import { Point } from '../fields/point.js'; -import { hasHexPrefix, isHex, withoutHexPrefix } from '../string/index.js'; +import { isHex, withoutHexPrefix } from '../string/index.js'; import { type ZodFor } from './types.js'; -import { hexSchema, maybeStructuredStringSchemaFor } from './utils.js'; - -const FrSchema = maybeStructuredStringSchemaFor('Fr', Fr, isHex); -const FqSchema = maybeStructuredStringSchemaFor('Fq', Fq, isHex); +import { bufferSchema, hexSchema } from './utils.js'; /** Validation schemas for common types. Every schema must match its toJSON. */ export const schemas = { - /** Accepts both a 0x string and a structured `{ type: EthAddress, value: '0x...' }` */ - EthAddress: maybeStructuredStringSchemaFor('EthAddress', EthAddress, EthAddress.isAddress), - - /** Accepts both a 0x string and a structured `{ type: AztecAddress, value: '0x...' }` */ - AztecAddress: maybeStructuredStringSchemaFor('AztecAddress', AztecAddress, AztecAddress.isAddress), + /** Accepts a hex string. */ + EthAddress: EthAddress.schema, - /** Accepts both a 0x string and a structured type. */ - FunctionSelector: maybeStructuredStringSchemaFor('FunctionSelector', FunctionSelector), + /** Accepts a hex string. */ + AztecAddress: AztecAddress.schema, - /** Accepts both a 0x string and a structured type. */ - NoteSelector: maybeStructuredStringSchemaFor('NoteSelector', NoteSelector), + /** Accepts a hex string. */ + FunctionSelector: FunctionSelector.schema, - /** Accepts both a 0x string and a structured type. */ - EventSelector: maybeStructuredStringSchemaFor('EventSelector', EventSelector), + /** Accepts a hex string. */ + NoteSelector: NoteSelector.schema, - /** Field element. Accepts a 0x prefixed hex string or a structured type. */ - Fr: FrSchema, + /** Accepts a hex string. */ + EventSelector: EventSelector.schema, - /** Field element. Accepts a 0x prefixed hex string or a structured type. */ - Fq: FqSchema, + /** Accepts a hex string. */ + Fr: Fr.schema, - /** Point. Serialized as 0x prefixed string or a type. */ - Point: z - .object({ - x: FrSchema, - y: FrSchema, - isInfinite: z.boolean().optional(), - }) - .or(hexSchema) - .transform(value => - typeof value === 'string' ? Point.fromString(value) : new Point(value.x, value.y, value.isInfinite ?? false), - ), + /** Accepts a hex string. */ + Fq: Fq.schema, - /** Accepts a 0x string */ - Signature: z - .string() - .refine(hasHexPrefix, 'No hex prefix') - .refine(Signature.isValid0xString, 'Not a valid Ethereum signature') - .transform(Signature.from0xString), + /** Point. Serialized as a hex string. */ + Point: Point.schema, - /** Coerces any input to bigint */ + /** Coerces any input to bigint. */ BigInt: z.union([z.bigint(), z.number(), z.string()]).pipe(z.coerce.bigint()), - /** Coerces any input to integer number */ + /** Coerces any input to integer number. */ Integer: z.union([z.bigint(), z.number(), z.string()]).pipe(z.coerce.number().int()), - /** Coerces input to UInt32 */ + /** Coerces input to UInt32. */ UInt32: z.union([z.bigint(), z.number(), z.string()]).pipe( z.coerce .number() @@ -74,31 +54,28 @@ export const schemas = { .max(2 ** 32 - 1), ), - /** Accepts a hex string as a Buffer32 type */ + /** Accepts a hex string as a Buffer32 type. */ Buffer32: z.string().refine(isHex, 'Not a valid hex string').transform(Buffer32.fromString), - /** Accepts a base64 string or a structured `{ type: 'Buffer', data: [byte, byte...] }` as a buffer */ - BufferB64: z.union([ - z - .string() - .base64() - .transform(data => Buffer.from(data, 'base64')), + /** Accepts a base64 string or an object `{ type: 'Buffer', data: [byte, byte...] }` as a buffer. */ + Buffer: z.union([ + bufferSchema, z .object({ type: z.literal('Buffer'), - data: z.array(z.number().int().max(255)), + data: z.array(z.number().int().min(0).max(255)), }) .transform(({ data }) => Buffer.from(data)), ]), - /** Accepts a hex string with optional 0x prefix as a buffer */ + /** Accepts a hex string as a buffer. */ BufferHex: z .string() .refine(isHex, 'Not a valid hex string') .transform(withoutHexPrefix) .transform(data => Buffer.from(data, 'hex')), - /** Hex string with an optional 0x prefix, which gets removed as part of the parsing */ + /** Hex string with an optional 0x prefix which gets removed as part of the parsing. */ HexString: hexSchema, }; diff --git a/yarn-project/foundation/src/schemas/utils.ts b/yarn-project/foundation/src/schemas/utils.ts index 412c49bc967..5e12c46848b 100644 --- a/yarn-project/foundation/src/schemas/utils.ts +++ b/yarn-project/foundation/src/schemas/utils.ts @@ -15,6 +15,17 @@ import { type ZodFor } from './types.js'; export const hexSchema = z.string().refine(isHex, 'Not a valid hex string').transform(withoutHexPrefix); +// Copied from zod internals, which was copied from https://stackoverflow.com/questions/7860392/determine-if-string-is-in-base64-using-javascript +const base64Regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/; + +/** Schema for a buffer represented as a base64 string. */ +export const bufferSchema = z + .string() + // We only test the str for base64 if it's shorter than 1024 bytes, otherwise we've run into maximum + // stack size exceeded errors when trying to validate excessively long strings (such as contract bytecode). + .refine(str => str.length > 1024 || base64Regex.test(str), 'Not a valid base64 string') + .transform(data => Buffer.from(data, 'base64')); + export class ZodNullableOptional extends ZodOptional { _isNullableOptional = true; @@ -43,6 +54,8 @@ export function optional(schema: T) { return ZodNullableOptional.create(schema); } +type ToJsonIs = T extends { toJSON(): TRet } ? T : never; + /** * Creates a schema that accepts a hex string and uses it to hydrate an instance. * @param klazz - Class that implements either fromString or fromBuffer. @@ -50,28 +63,34 @@ export function optional(schema: T) { */ export function hexSchemaFor( klazz: TClass, + refinement?: (input: string) => boolean, ): ZodType< TClass extends { fromString(str: string): infer TInstance } | { fromBuffer(buf: Buffer): infer TInstance } - ? TInstance + ? ToJsonIs : never, any, string > { + const stringSchema = refinement ? z.string().refine(refinement, `Not a valid instance`) : z.string(); + const hexSchema = stringSchema.refine(isHex, 'Not a valid hex string').transform(withoutHexPrefix); return 'fromString' in klazz ? hexSchema.transform(klazz.fromString.bind(klazz)) : hexSchema.transform(str => Buffer.from(str, 'hex')).transform(klazz.fromBuffer.bind(klazz)); } -// TODO(palla/schemas): Delete this class once all serialization of the type { type: string, value: string } are removed. -export function maybeStructuredStringSchemaFor( - name: string, +/** + * Creates a schema that accepts a base64 string and uses it to hydrate an instance. + * @param klazz - Class that implements fromBuffer. + * @returns A schema for the class. + */ +export function bufferSchemaFor( klazz: TClass, - refinement?: (input: string) => boolean, -): ZodFor { - const stringSchema = refinement ? z.string().refine(refinement, `Not a valid ${name}`) : z.string(); - return z - .union([stringSchema, z.object({ type: z.literal(name), value: stringSchema })]) - .transform(input => klazz.fromString(typeof input === 'string' ? input : input.value)); +): ZodType< + TClass extends { fromBuffer(buf: Buffer): infer TInstance } ? ToJsonIs : never, + any, + string +> { + return bufferSchema.transform(klazz.fromBuffer.bind(klazz)); } /** Creates a schema for a js Map type that matches the serialization used in jsonStringify. */ diff --git a/yarn-project/foundation/src/serialize/type_registry.test.ts b/yarn-project/foundation/src/serialize/type_registry.test.ts new file mode 100644 index 00000000000..b77e96a837f --- /dev/null +++ b/yarn-project/foundation/src/serialize/type_registry.test.ts @@ -0,0 +1,90 @@ +import { EventSelector } from '../abi/event_selector.js'; +import { FunctionSelector } from '../abi/function_selector.js'; +import { NoteSelector } from '../abi/note_selector.js'; +import { AztecAddress } from '../aztec-address/index.js'; +import { EthAddress } from '../eth-address/index.js'; +import { Fq, Fr } from '../fields/fields.js'; +import { resolver, reviver } from './type_registry.js'; + +describe('TypeRegistry', () => { + it('serializes registered type with type info', () => { + const data = { fr: Fr.random() }; + const json = JSON.stringify(data, resolver); + const parsed = JSON.parse(json); + expect(parsed.fr).toEqual({ type: 'Fr', value: data.fr.toString() }); + }); + + it('deserializes registered types in objects', () => { + const data = { + fr: Fr.random(), + fq: Fq.random(), + aztecAddress: AztecAddress.random(), + ethAddress: EthAddress.random(), + functionSelector: FunctionSelector.random(), + noteSelector: NoteSelector.random(), + }; + + const json = JSON.stringify(data, resolver); + const parsed = JSON.parse(json, reviver); + + expect(parsed).toEqual(data); + expect(parsed.fr).toBeInstanceOf(Fr); + expect(parsed.fq).toBeInstanceOf(Fq); + expect(parsed.aztecAddress).toBeInstanceOf(AztecAddress); + expect(parsed.ethAddress).toBeInstanceOf(EthAddress); + expect(parsed.functionSelector).toBeInstanceOf(FunctionSelector); + expect(parsed.noteSelector).toBeInstanceOf(NoteSelector); + }); + + it('deserializes registered types in arrays', () => { + const data = [ + Fr.random(), + Fq.random(), + AztecAddress.random(), + EthAddress.random(), + FunctionSelector.random(), + NoteSelector.random(), + ]; + + const json = JSON.stringify(data, resolver); + const parsed = JSON.parse(json, reviver); + + expect(parsed).toEqual(data); + expect(parsed[0]).toBeInstanceOf(Fr); + expect(parsed[1]).toBeInstanceOf(Fq); + expect(parsed[2]).toBeInstanceOf(AztecAddress); + expect(parsed[3]).toBeInstanceOf(EthAddress); + expect(parsed[4]).toBeInstanceOf(FunctionSelector); + expect(parsed[5]).toBeInstanceOf(NoteSelector); + }); + + it('ignores unregistered types', () => { + const data = { eventSelector: EventSelector.random() }; + const json = JSON.stringify(data, resolver); + const parsed = JSON.parse(json); + expect(parsed.eventSelector).toEqual(data.eventSelector.toString()); + }); + + it('handles plain objects', () => { + const data = { obj: { number: 10, string: 'string', fr: Fr.random() } }; + const json = JSON.stringify(data, resolver); + const parsed = JSON.parse(json, reviver); + expect(parsed).toEqual(data); + expect(parsed.obj.fr).toBeInstanceOf(Fr); + }); + + it('handles plain arrays', () => { + const data = [10, 'string', Fr.random()]; + const json = JSON.stringify(data, resolver); + const parsed = JSON.parse(json, reviver); + expect(parsed).toEqual(data); + expect(parsed[2]).toBeInstanceOf(Fr); + }); + + it('handles bigints', () => { + const data = { bigInt: BigInt(10) }; + const json = JSON.stringify(data, resolver); + const parsed = JSON.parse(json, reviver); + expect(parsed.bigInt).toEqual(BigInt(10)); + }); +}); diff --git a/yarn-project/foundation/src/serialize/type_registry.ts b/yarn-project/foundation/src/serialize/type_registry.ts index 85146710ed8..39a6bd00ad3 100644 --- a/yarn-project/foundation/src/serialize/type_registry.ts +++ b/yarn-project/foundation/src/serialize/type_registry.ts @@ -1,3 +1,5 @@ +import { mapValues } from '../collection/object.js'; + type Deserializable = { fromString(str: string): object }; /** @@ -23,9 +25,39 @@ export class TypeRegistry { } } +function replace(value: T) { + if ( + value && + typeof value === 'object' && + 'toString' in value && + TypeRegistry.getConstructor(value.constructor.name) + ) { + return { + type: value.constructor.name, + value: value.toString(), + }; + } + + return value; +} + // Resolver function that enables JSON serialization of BigInts. export function resolver(_: any, value: any) { - return typeof value === 'bigint' ? value.toString() + 'n' : value; + if (typeof value === 'bigint') { + return value.toString() + 'n'; + } + + if (typeof value === 'object' && value) { + if (Array.isArray(value)) { + return value.map(replace); + } else if (Buffer.isBuffer(value)) { + return { type: 'buffer', value: value.toString('hex') }; + } else { + return mapValues(value, replace); + } + } + + return value; } // Reviver function that uses TypeRegistry to instantiate objects. diff --git a/yarn-project/foundation/src/string/index.ts b/yarn-project/foundation/src/string/index.ts index 250b3c02581..1b85173fc1a 100644 --- a/yarn-project/foundation/src/string/index.ts +++ b/yarn-project/foundation/src/string/index.ts @@ -14,6 +14,10 @@ export function hexToBuffer(str: string): Buffer { return Buffer.from(withoutHexPrefix(str), 'hex'); } +export function bufferToHex(buffer: Buffer): `0x${string}` { + return `0x${buffer.toString('hex')}`; +} + export function pluralize(str: string, count: number | bigint, plural?: string): string { return count === 1 || count === 1n ? str : plural ?? `${str}s`; } diff --git a/yarn-project/noir-protocol-circuits-types/src/__snapshots__/noir_test_gen.test.ts.snap b/yarn-project/noir-protocol-circuits-types/src/__snapshots__/noir_test_gen.test.ts.snap index c5b038f46bb..af7128a8549 100644 --- a/yarn-project/noir-protocol-circuits-types/src/__snapshots__/noir_test_gen.test.ts.snap +++ b/yarn-project/noir-protocol-circuits-types/src/__snapshots__/noir_test_gen.test.ts.snap @@ -9,7 +9,7 @@ exports[`Data generation for noir tests Computes contract info for defaultContra address: AztecAddress { inner: 0x29bc2e90ff6ec5f4a7c7f502e368af01eb74131a2eec6320e0e45419cddc7b6d }, partial_address: PartialAddress { inner: 0x1a68423cf4f04eaede2b0e93131916b8b7330dae6e8ee202679d12a4eb49cc0b }, contract_class_id: ContractClassId { inner: 0x1195b865ef122d75c8c4d6102d536193b69bbb712c85bafcbf7694f52e2d8c36 }, - public_keys: PublicKeys { inner: 01498945581e0eb9f8427ad6021184c700ef091d570892c437d12c7d90364bbd170ae506787c5c43d6ca9255d571c10fa9ffa9d141666e290c347c5c9ab7e34400c044b05b6ca83b9c2dbae79cc1135155956a64e136819136e9947fe5e5866c1c1f0ca244c7cd46b682552bff8ae77dea40b966a71de076ec3b7678f2bdb1511b00316144359e9a3ec8e49c1cdb7eeb0cedd190dfd9dc90eea5115aa779e287080ffc74d7a8b0bccb88ac11f45874172f3847eb8b92654aaa58a3d2b8dc7833019c111f36ad3fc1d9b7a7a14344314d2864b94f030594cd67f753ef774a1efb2039907fe37f08d10739255141bb066c506a12f7d1e8dfec21abc58494705b6f }, + public_keys: PublicKeys { inner: 0x01498945581e0eb9f8427ad6021184c700ef091d570892c437d12c7d90364bbd170ae506787c5c43d6ca9255d571c10fa9ffa9d141666e290c347c5c9ab7e34400c044b05b6ca83b9c2dbae79cc1135155956a64e136819136e9947fe5e5866c1c1f0ca244c7cd46b682552bff8ae77dea40b966a71de076ec3b7678f2bdb1511b00316144359e9a3ec8e49c1cdb7eeb0cedd190dfd9dc90eea5115aa779e287080ffc74d7a8b0bccb88ac11f45874172f3847eb8b92654aaa58a3d2b8dc7833019c111f36ad3fc1d9b7a7a14344314d2864b94f030594cd67f753ef774a1efb2039907fe37f08d10739255141bb066c506a12f7d1e8dfec21abc58494705b6f }, salted_initialization_hash: SaltedInitializationHash { inner: 0x13a939daa511233e5446905ed2cadbee14948fa75df183b53b5c14b612bffe88 }, deployer: AztecAddress { inner: 0x0000000000000000000000000000000000000000000000000000000000000000 } }" @@ -24,7 +24,7 @@ exports[`Data generation for noir tests Computes contract info for parentContrac address: AztecAddress { inner: 0x2749b685f752f6dfe1d4e532fc036839004926b7c18abf1a4f69ddf97d62f40e }, partial_address: PartialAddress { inner: 0x1c30ee02dcd41bcdfc5191dc36ccaae15cdc7e1fc6bd8a0cbe1baeaf1335a771 }, contract_class_id: ContractClassId { inner: 0x24f1b8df215c10ee7edd213b439c8f8e99198a802a3e1e41597b6554b17049a3 }, - public_keys: PublicKeys { inner: 01498945581e0eb9f8427ad6021184c700ef091d570892c437d12c7d90364bbd170ae506787c5c43d6ca9255d571c10fa9ffa9d141666e290c347c5c9ab7e34400c044b05b6ca83b9c2dbae79cc1135155956a64e136819136e9947fe5e5866c1c1f0ca244c7cd46b682552bff8ae77dea40b966a71de076ec3b7678f2bdb1511b00316144359e9a3ec8e49c1cdb7eeb0cedd190dfd9dc90eea5115aa779e287080ffc74d7a8b0bccb88ac11f45874172f3847eb8b92654aaa58a3d2b8dc7833019c111f36ad3fc1d9b7a7a14344314d2864b94f030594cd67f753ef774a1efb2039907fe37f08d10739255141bb066c506a12f7d1e8dfec21abc58494705b6f }, + public_keys: PublicKeys { inner: 0x01498945581e0eb9f8427ad6021184c700ef091d570892c437d12c7d90364bbd170ae506787c5c43d6ca9255d571c10fa9ffa9d141666e290c347c5c9ab7e34400c044b05b6ca83b9c2dbae79cc1135155956a64e136819136e9947fe5e5866c1c1f0ca244c7cd46b682552bff8ae77dea40b966a71de076ec3b7678f2bdb1511b00316144359e9a3ec8e49c1cdb7eeb0cedd190dfd9dc90eea5115aa779e287080ffc74d7a8b0bccb88ac11f45874172f3847eb8b92654aaa58a3d2b8dc7833019c111f36ad3fc1d9b7a7a14344314d2864b94f030594cd67f753ef774a1efb2039907fe37f08d10739255141bb066c506a12f7d1e8dfec21abc58494705b6f }, salted_initialization_hash: SaltedInitializationHash { inner: 0x24bd6ac7a182e2cf25e437c72f53544ef81dfd97d9afee23abb07a638e7be749 }, deployer: AztecAddress { inner: 0x0000000000000000000000000000000000000000000000000000000000000000 } }" diff --git a/yarn-project/prover-client/src/proving_broker/proving_job_database/persisted.ts b/yarn-project/prover-client/src/proving_broker/proving_job_database/persisted.ts index 748ad387124..c03684b1bf3 100644 --- a/yarn-project/prover-client/src/proving_broker/proving_job_database/persisted.ts +++ b/yarn-project/prover-client/src/proving_broker/proving_job_database/persisted.ts @@ -1,4 +1,5 @@ import { type V2ProofOutput, V2ProvingJob, type V2ProvingJobId, V2ProvingJobResult } from '@aztec/circuit-types'; +import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc'; import { type AztecKVStore, type AztecMap } from '@aztec/kv-store'; import { type ProvingJobDatabase } from '../proving_job_database.js'; @@ -13,14 +14,14 @@ export class PersistedProvingJobDatabase implements ProvingJobDatabase { } async addProvingJob(job: V2ProvingJob): Promise { - await this.jobs.set(job.id, JSON.stringify(job)); + await this.jobs.set(job.id, jsonStringify(job)); } *allProvingJobs(): Iterable<[V2ProvingJob, V2ProvingJobResult | undefined]> { for (const jobStr of this.jobs.values()) { - const job = V2ProvingJob.parse(JSON.parse(jobStr)); + const job = jsonParseWithSchema(jobStr, V2ProvingJob); const resultStr = this.jobResults.get(job.id); - const result = resultStr ? V2ProvingJobResult.parse(JSON.parse(resultStr)) : undefined; + const result = resultStr ? jsonParseWithSchema(resultStr, V2ProvingJobResult) : undefined; yield [job, result]; } } @@ -34,11 +35,11 @@ export class PersistedProvingJobDatabase implements ProvingJobDatabase { async setProvingJobError(id: V2ProvingJobId, err: Error): Promise { const res: V2ProvingJobResult = { error: err.message }; - await this.jobResults.set(id, JSON.stringify(res)); + await this.jobResults.set(id, jsonStringify(res)); } async setProvingJobResult(id: V2ProvingJobId, value: V2ProofOutput): Promise { const res: V2ProvingJobResult = { value }; - await this.jobResults.set(id, JSON.stringify(res)); + await this.jobResults.set(id, jsonStringify(res)); } } diff --git a/yarn-project/prover-node/src/quote-provider/http.ts b/yarn-project/prover-node/src/quote-provider/http.ts index 2e3a6ce6798..a50318143e9 100644 --- a/yarn-project/prover-node/src/quote-provider/http.ts +++ b/yarn-project/prover-node/src/quote-provider/http.ts @@ -1,4 +1,5 @@ import { type L2Block } from '@aztec/circuit-types'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; import { type QuoteProvider, type QuoteProviderResult } from './index.js'; import { getTotalFees, getTxCount } from './utils.js'; @@ -17,7 +18,7 @@ export class HttpQuoteProvider implements QuoteProvider { const response = await fetch(this.url, { method: 'POST', - body: JSON.stringify(payload), + body: jsonStringify(payload), headers: { 'content-type': 'application/json' }, }); @@ -27,7 +28,7 @@ export class HttpQuoteProvider implements QuoteProvider { const data = await response.json(); if (!data.basisPointFee || !data.bondAmount) { - throw new Error(`Missing required fields (basisPointFee | bondAmount) in response: ${JSON.stringify(data)}`); + throw new Error(`Missing required fields (basisPointFee | bondAmount) in response: ${jsonStringify(data)}`); } const basisPointFee = Number(data.basisPointFee); diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index a7ca08660f2..00dfea9c56d 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -27,6 +27,7 @@ import { } from '@aztec/circuits.js'; import { type FunctionArtifact, getFunctionArtifact } from '@aztec/foundation/abi'; import { poseidon2Hash } from '@aztec/foundation/crypto'; +import { tryJsonStringify } from '@aztec/foundation/json-rpc'; import { createDebugLogger } from '@aztec/foundation/log'; import { type KeyStore } from '@aztec/key-store'; import { type AcirSimulator, type DBOracle, MessageLoadOracleInputs } from '@aztec/simulator'; @@ -556,9 +557,9 @@ export class SimulatorOracle implements DBOracle { if (incomingNotePayload || outgoingNotePayload) { if (incomingNotePayload && outgoingNotePayload && !incomingNotePayload.equals(outgoingNotePayload)) { this.log.warn( - `Incoming and outgoing note payloads do not match. Incoming: ${JSON.stringify( + `Incoming and outgoing note payloads do not match. Incoming: ${tryJsonStringify( incomingNotePayload, - )}, Outgoing: ${JSON.stringify(outgoingNotePayload)}`, + )}, Outgoing: ${tryJsonStringify(outgoingNotePayload)}`, ); continue; } diff --git a/yarn-project/sequencer-client/src/block_builder/light.ts b/yarn-project/sequencer-client/src/block_builder/light.ts index 44d92ca2a23..35ac23d476a 100644 --- a/yarn-project/sequencer-client/src/block_builder/light.ts +++ b/yarn-project/sequencer-client/src/block_builder/light.ts @@ -17,6 +17,8 @@ import { buildBaseRollupHints, buildHeaderFromTxEffects, getTreeSnapshot } from import { type TelemetryClient } from '@aztec/telemetry-client'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; +import { inspect } from 'util'; + /** * Builds a block and its header from a set of processed tx without running any circuits. */ @@ -32,7 +34,7 @@ export class LightweightBlockBuilder implements BlockBuilder { constructor(private db: MerkleTreeWriteOperations, private telemetry: TelemetryClient) {} async startNewBlock(numTxs: number, globalVariables: GlobalVariables, l1ToL2Messages: Fr[]): Promise { - this.logger.verbose('Starting new block', { numTxs, globalVariables: globalVariables.toJSON(), l1ToL2Messages }); + this.logger.verbose('Starting new block', { numTxs, globalVariables: inspect(globalVariables), l1ToL2Messages }); this.numTxs = numTxs; this.globalVariables = globalVariables; this.l1ToL2Messages = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP); diff --git a/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts b/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts index adb1cb4f9e5..3ca0a790c77 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts @@ -89,7 +89,7 @@ export class GlobalVariableBuilder implements GlobalVariableBuilderInterface { feeRecipient, gasFees, ); - this.log.debug(`Built global variables for block ${blockNumber}`, globalVariables.toJSON()); + this.log.debug(`Built global variables for block ${blockNumber}`, globalVariables.toFriendlyJSON()); return globalVariables; } } diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 29b4c8d1de3..2bc6c67d9b8 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -738,7 +738,7 @@ export class L1Publisher { const attestations = encodedData.attestations ? encodedData.attestations.map(attest => attest.toViemSignature()) : []; - const txHashes = encodedData.txHashes ? encodedData.txHashes.map(txHash => txHash.to0xString()) : []; + const txHashes = encodedData.txHashes ? encodedData.txHashes.map(txHash => txHash.toString()) : []; const args = [ { header: `0x${encodedData.header.toString('hex')}`, diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index f89d4c94f90..90bb0e75b89 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -9,6 +9,7 @@ import { } from '@aztec/circuits.js'; import { computePublicDataTreeLeafSlot, siloNoteHash, siloNullifier } from '@aztec/circuits.js/hash'; import { Fr } from '@aztec/foundation/fields'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; import { createDebugLogger } from '@aztec/foundation/log'; import assert from 'assert'; @@ -468,7 +469,7 @@ export class AvmPersistableStateManager { if (exists) { const instance = new SerializableContractInstance(instanceWithAddress); this.log.debug( - `Got contract instance (address=${contractAddress}): exists=${exists}, instance=${JSON.stringify(instance)}`, + `Got contract instance (address=${contractAddress}): exists=${exists}, instance=${jsonStringify(instance)}`, ); this.trace.traceGetContractInstance(contractAddress, exists, instance); diff --git a/yarn-project/simulator/src/common/errors.ts b/yarn-project/simulator/src/common/errors.ts index f51536ac457..da35b96d784 100644 --- a/yarn-project/simulator/src/common/errors.ts +++ b/yarn-project/simulator/src/common/errors.ts @@ -6,6 +6,7 @@ import { } from '@aztec/circuit-types'; import { type Fr } from '@aztec/circuits.js'; import type { BrilligFunctionId, FunctionAbi, FunctionDebugMetadata, OpcodeLocation } from '@aztec/foundation/abi'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; import { type RawAssertionPayload } from '@noir-lang/acvm_js'; import { abiDecodeError } from '@noir-lang/noirc_abi'; @@ -153,7 +154,7 @@ export function resolveAssertionMessage(errorPayload: RawAssertionPayload, abi: if (typeof decoded === 'string') { return decoded; } else { - return JSON.stringify(decoded); + return jsonStringify(decoded); } } diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts index 768243bf473..41298d80f63 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts @@ -58,6 +58,7 @@ import { import { computePublicDataTreeLeafSlot, siloNullifier } from '@aztec/circuits.js/hash'; import { padArrayEnd } from '@aztec/foundation/collection'; import { Fr } from '@aztec/foundation/fields'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; import { createDebugLogger } from '@aztec/foundation/log'; import { assert } from 'console'; @@ -495,9 +496,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI new AvmContractBytecodeHints(bytecode, instance, contractClass), ); this.log.debug( - `Bytecode retrieval for contract execution traced: exists=${exists}, instance=${JSON.stringify( - contractInstance, - )}`, + `Bytecode retrieval for contract execution traced: exists=${exists}, instance=${jsonStringify(contractInstance)}`, ); } diff --git a/yarn-project/simulator/src/public/side_effect_trace.ts b/yarn-project/simulator/src/public/side_effect_trace.ts index ac1f4a98f16..dcb86a1850d 100644 --- a/yarn-project/simulator/src/public/side_effect_trace.ts +++ b/yarn-project/simulator/src/public/side_effect_trace.ts @@ -45,6 +45,7 @@ import { TreeLeafReadRequest, } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; import { createDebugLogger } from '@aztec/foundation/log'; import { assert } from 'console'; @@ -362,9 +363,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { new AvmContractBytecodeHints(bytecode, instance, contractClass), ); this.log.debug( - `Bytecode retrieval for contract execution traced: exists=${exists}, instance=${JSON.stringify( - contractInstance, - )}`, + `Bytecode retrieval for contract execution traced: exists=${exists}, instance=${jsonStringify(contractInstance)}`, ); } diff --git a/yarn-project/txe/src/util/encoding.ts b/yarn-project/txe/src/util/encoding.ts index 0b65122a61f..1853378af76 100644 --- a/yarn-project/txe/src/util/encoding.ts +++ b/yarn-project/txe/src/util/encoding.ts @@ -1,6 +1,7 @@ import { AztecAddress } from '@aztec/circuits.js'; import { type ContractArtifact, ContractArtifactSchema } from '@aztec/foundation/abi'; import { Fr } from '@aztec/foundation/fields'; +import { hexToBuffer } from '@aztec/foundation/string'; import { z } from 'zod'; @@ -23,7 +24,7 @@ export function addressFromSingle(obj: ForeignCallSingle) { } export function fromArray(obj: ForeignCallArray) { - return obj.map(str => Fr.fromBuffer(Buffer.from(str, 'hex'))); + return obj.map(str => Fr.fromBuffer(hexToBuffer(str))); } export function toSingle(obj: Fr | AztecAddress) { diff --git a/yarn-project/types/src/abi/contract_artifact.ts b/yarn-project/types/src/abi/contract_artifact.ts index 0141145e7b3..7e2f5b54bdd 100644 --- a/yarn-project/types/src/abi/contract_artifact.ts +++ b/yarn-project/types/src/abi/contract_artifact.ts @@ -13,6 +13,7 @@ import { type StructValue, type TypedStructFieldValue, } from '@aztec/foundation/abi'; +import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc'; import { AZTEC_INITIALIZER_ATTRIBUTE, @@ -29,21 +30,7 @@ import { * @returns A buffer. */ export function contractArtifactToBuffer(artifact: ContractArtifact): Buffer { - return Buffer.from( - JSON.stringify(artifact, (key, value) => { - if ( - key === 'bytecode' && - value !== null && - typeof value === 'object' && - value.type === 'Buffer' && - Array.isArray(value.data) - ) { - return Buffer.from(value.data).toString('base64'); - } - return value; - }), - 'utf-8', - ); + return Buffer.from(jsonStringify(artifact), 'utf-8'); } /** @@ -52,7 +39,7 @@ export function contractArtifactToBuffer(artifact: ContractArtifact): Buffer { * @returns Deserialized artifact. */ export function contractArtifactFromBuffer(buffer: Buffer): ContractArtifact { - return ContractArtifactSchema.parse(JSON.parse(buffer.toString('utf-8'))); + return jsonParseWithSchema(buffer.toString('utf-8'), ContractArtifactSchema); } /** diff --git a/yarn-project/world-state/package.json b/yarn-project/world-state/package.json index 29b1124e272..6ffcf4bd889 100644 --- a/yarn-project/world-state/package.json +++ b/yarn-project/world-state/package.json @@ -71,7 +71,8 @@ "@aztec/types": "workspace:^", "bindings": "^1.5.0", "msgpackr": "^1.10.2", - "tslib": "^2.4.0" + "tslib": "^2.4.0", + "zod": "^3.23.8" }, "devDependencies": { "@aztec/archiver": "workspace:^", diff --git a/yarn-project/world-state/src/native/world_state_version.ts b/yarn-project/world-state/src/native/world_state_version.ts index 20707d354ab..2be422b9e16 100644 --- a/yarn-project/world-state/src/native/world_state_version.ts +++ b/yarn-project/world-state/src/native/world_state_version.ts @@ -1,38 +1,29 @@ import { EthAddress } from '@aztec/circuits.js'; +import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc'; import { readFile, writeFile } from 'fs/promises'; +import { z } from 'zod'; export class WorldStateVersion { - constructor(readonly version: number, readonly rollupAddress: EthAddress) {} + constructor(public readonly version: number, public readonly rollupAddress: EthAddress) {} static async readVersion(filename: string) { const versionData = await readFile(filename, 'utf-8').catch(() => undefined); - if (versionData === undefined) { - return undefined; - } - const versionJSON = JSON.parse(versionData); - if (versionJSON.version === undefined || versionJSON.rollupAddress === undefined) { - return undefined; - } - return WorldStateVersion.fromJSON(versionJSON); + return versionData === undefined ? undefined : jsonParseWithSchema(versionData, WorldStateVersion.schema); } public async writeVersionFile(filename: string) { - const data = JSON.stringify(this.toJSON()); + const data = jsonStringify(this); await writeFile(filename, data, 'utf-8'); } - toJSON() { - return { - version: this.version, - rollupAddress: this.rollupAddress.toChecksumString(), - }; - } - - static fromJSON(obj: any): WorldStateVersion { - const version = obj.version; - const rollupAddress = EthAddress.fromString(obj.rollupAddress); - return new WorldStateVersion(version, rollupAddress); + static get schema() { + return z + .object({ + version: z.number(), + rollupAddress: EthAddress.schema, + }) + .transform(({ version, rollupAddress }) => new WorldStateVersion(version, rollupAddress)); } static empty() { diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 57c3aa91fda..2d0af3c2c7c 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -1328,6 +1328,7 @@ __metadata: ts-node: ^10.9.1 tslib: ^2.4.0 typescript: ^5.0.4 + zod: ^3.23.8 languageName: unknown linkType: soft