diff --git a/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts b/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts index 8270b171ffe..6234870fe42 100644 --- a/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts +++ b/yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts @@ -6,6 +6,7 @@ import { LogId, NullifierMembershipWitness, PublicDataWitness, + PublicSimulationOutput, SiblingPath, Tx, TxEffect, @@ -41,7 +42,14 @@ export function createAztecNodeRpcServer(node: AztecNode) { PublicDataWitness, SiblingPath, }, - { Tx, TxReceipt, EncryptedL2BlockL2Logs, UnencryptedL2BlockL2Logs, NullifierMembershipWitness }, + { + PublicSimulationOutput, + Tx, + TxReceipt, + EncryptedL2BlockL2Logs, + UnencryptedL2BlockL2Logs, + NullifierMembershipWitness, + }, // disable methods not part of the AztecNode interface ['start', 'stop'], ); diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 980c9cf6df0..54b15609cd4 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -13,10 +13,10 @@ import { LogType, MerkleTreeId, NullifierMembershipWitness, - type ProcessOutput, type ProverClient, type ProverConfig, PublicDataWitness, + PublicSimulationOutput, type SequencerConfig, type SiblingPath, type Tx, @@ -634,7 +634,7 @@ export class AztecNodeService implements AztecNode { * Simulates the public part of a transaction with the current state. * @param tx - The transaction to simulate. **/ - public async simulatePublicCalls(tx: Tx): Promise { + public async simulatePublicCalls(tx: Tx): Promise { this.log.info(`Simulating tx ${tx.getTxHash()}`); const blockNumber = (await this.blockSource.getBlockNumber()) + 1; @@ -674,15 +674,15 @@ export class AztecNodeService implements AztecNode { } this.log.debug(`Simulated tx ${tx.getTxHash()} succeeds`); const [processedTx] = processedTxs; - return { - constants: processedTx.data.constants, - encryptedLogs: processedTx.encryptedLogs, - unencryptedLogs: processedTx.unencryptedLogs, - end: processedTx.data.end, - revertReason: processedTx.revertReason, - publicReturnValues: returns[0], - gasUsed: processedTx.gasUsed, - }; + return new PublicSimulationOutput( + processedTx.encryptedLogs, + processedTx.unencryptedLogs, + processedTx.revertReason, + processedTx.data.constants, + processedTx.data.end, + returns[0], + processedTx.gasUsed, + ); } public async setConfig(config: Partial): Promise { diff --git a/yarn-project/circuit-types/src/aztec_node/rpc/aztec_node_client.ts b/yarn-project/circuit-types/src/aztec_node/rpc/aztec_node_client.ts index 79f9795f9f4..8591c53795f 100644 --- a/yarn-project/circuit-types/src/aztec_node/rpc/aztec_node_client.ts +++ b/yarn-project/circuit-types/src/aztec_node/rpc/aztec_node_client.ts @@ -9,8 +9,9 @@ import { type AztecNode } from '../../interfaces/aztec-node.js'; import { NullifierMembershipWitness } from '../../interfaces/nullifier_tree.js'; import { L2Block } from '../../l2_block.js'; import { EncryptedL2BlockL2Logs, ExtendedUnencryptedL2Log, LogId, UnencryptedL2BlockL2Logs } from '../../logs/index.js'; +import { PublicDataWitness } from '../../public_data_witness.js'; import { SiblingPath } from '../../sibling_path/index.js'; -import { Tx, TxHash, TxReceipt } from '../../tx/index.js'; +import { PublicSimulationOutput, Tx, TxHash, TxReceipt } from '../../tx/index.js'; import { TxEffect } from '../../tx_effect.js'; /** @@ -34,9 +35,17 @@ export function createAztecNodeClient(url: string, fetch = defaultFetch): AztecN TxEffect, LogId, TxHash, + PublicDataWitness, SiblingPath, }, - { Tx, TxReceipt, EncryptedL2BlockL2Logs, UnencryptedL2BlockL2Logs, NullifierMembershipWitness }, + { + PublicSimulationOutput, + Tx, + TxReceipt, + EncryptedL2BlockL2Logs, + UnencryptedL2BlockL2Logs, + NullifierMembershipWitness, + }, false, 'node', fetch, diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index d59543943e8..bf1df022131 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -22,7 +22,7 @@ import { import { type MerkleTreeId } from '../merkle_tree_id.js'; import { type PublicDataWitness } from '../public_data_witness.js'; import { type SiblingPath } from '../sibling_path/index.js'; -import { type ProcessOutput, type Tx, type TxHash, type TxReceipt } from '../tx/index.js'; +import { type PublicSimulationOutput, type Tx, type TxHash, type TxReceipt } from '../tx/index.js'; import { type TxEffect } from '../tx_effect.js'; import { type SequencerConfig } from './configs.js'; import { type L2BlockNumber } from './l2_block_number.js'; @@ -283,7 +283,7 @@ export interface AztecNode { * This currently just checks that the transaction execution succeeds. * @param tx - The transaction to simulate. **/ - simulatePublicCalls(tx: Tx): Promise; + simulatePublicCalls(tx: Tx): Promise; /** * Updates the configuration of this node. diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index 9cda922037c..ba36cd68556 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -27,7 +27,7 @@ import { type ContractInstanceWithAddress, SerializableContractInstance } from ' import { EncryptedL2Log } from './logs/encrypted_l2_log.js'; import { EncryptedFunctionL2Logs, EncryptedTxL2Logs, Note, UnencryptedTxL2Logs } from './logs/index.js'; import { ExtendedNote } from './notes/index.js'; -import { type ProcessOutput, type ProcessReturnValues, SimulatedTx, Tx, TxHash } from './tx/index.js'; +import { type ProcessReturnValues, PublicSimulationOutput, SimulatedTx, Tx, TxHash } from './tx/index.js'; /** * Testing utility to create empty logs composed from a single empty log. @@ -129,15 +129,15 @@ export const mockTxForRollup = (seed = 1, { hasLogs = false }: { hasLogs?: boole export const mockSimulatedTx = (seed = 1, hasLogs = true) => { const tx = mockTx(seed, { hasLogs }); const dec: ProcessReturnValues = [new Fr(1n), new Fr(2n), new Fr(3n), new Fr(4n)]; - const output: ProcessOutput = { - constants: makeCombinedConstantData(), - encryptedLogs: tx.encryptedLogs, - unencryptedLogs: tx.unencryptedLogs, - end: makeCombinedAccumulatedData(), - revertReason: undefined, - publicReturnValues: dec, - gasUsed: {}, - }; + const output = new PublicSimulationOutput( + tx.encryptedLogs, + tx.unencryptedLogs, + undefined, + makeCombinedConstantData(), + makeCombinedAccumulatedData(), + dec, + {}, + ); return new SimulatedTx(tx, dec, output); }; diff --git a/yarn-project/circuit-types/src/tx/index.ts b/yarn-project/circuit-types/src/tx/index.ts index e113a56430e..6d69130adaf 100644 --- a/yarn-project/circuit-types/src/tx/index.ts +++ b/yarn-project/circuit-types/src/tx/index.ts @@ -3,4 +3,5 @@ export * from './simulated_tx.js'; export * from './tx_hash.js'; export * from './tx_receipt.js'; export * from './processed_tx.js'; +export * from './public_simulation_output.js'; export * from './tx_validator.js'; diff --git a/yarn-project/circuit-types/src/tx/public_simulation_output.ts b/yarn-project/circuit-types/src/tx/public_simulation_output.ts new file mode 100644 index 00000000000..24443814680 --- /dev/null +++ b/yarn-project/circuit-types/src/tx/public_simulation_output.ts @@ -0,0 +1,48 @@ +import { CombinedAccumulatedData, CombinedConstantData, Fr, Gas } from '@aztec/circuits.js'; +import { mapValues } from '@aztec/foundation/collection'; + +import { EncryptedTxL2Logs, UnencryptedTxL2Logs } from '../logs/tx_l2_logs.js'; +import { type SimulationError } from '../simulation_error.js'; +import { type PublicKernelType } from './processed_tx.js'; + +/** Return values of simulating a circuit. */ +export type ProcessReturnValues = Fr[] | undefined; + +/** + * Outputs of processing the public component of a transaction. + */ +export class PublicSimulationOutput { + constructor( + public encryptedLogs: EncryptedTxL2Logs, + public unencryptedLogs: UnencryptedTxL2Logs, + public revertReason: SimulationError | undefined, + public constants: CombinedConstantData, + public end: CombinedAccumulatedData, + public publicReturnValues: ProcessReturnValues, + public gasUsed: Partial>, + ) {} + + toJSON() { + return { + encryptedLogs: this.encryptedLogs.toJSON(), + unencryptedLogs: this.unencryptedLogs.toJSON(), + revertReason: this.revertReason, + constants: this.constants.toBuffer().toString('hex'), + end: this.end.toBuffer().toString('hex'), + publicReturnValues: this.publicReturnValues?.map(fr => fr.toString()), + gasUsed: mapValues(this.gasUsed, gas => gas?.toJSON()), + }; + } + + static fromJSON(json: any): PublicSimulationOutput { + return new PublicSimulationOutput( + EncryptedTxL2Logs.fromJSON(json.encryptedLogs), + UnencryptedTxL2Logs.fromJSON(json.unencryptedLogs), + json.revertReason, + CombinedConstantData.fromBuffer(Buffer.from(json.constants, 'hex')), + CombinedAccumulatedData.fromBuffer(Buffer.from(json.end, 'hex')), + json.publicReturnValues?.map(Fr.fromString), + mapValues(json.gasUsed, gas => (gas ? Gas.fromJSON(gas) : undefined)), + ); + } +} diff --git a/yarn-project/circuit-types/src/tx/simulated_tx.ts b/yarn-project/circuit-types/src/tx/simulated_tx.ts index 61883a5d1f5..45387f1664a 100644 --- a/yarn-project/circuit-types/src/tx/simulated_tx.ts +++ b/yarn-project/circuit-types/src/tx/simulated_tx.ts @@ -1,44 +1,9 @@ -import { CombinedAccumulatedData, CombinedConstantData, Fr, Gas } from '@aztec/circuits.js'; -import { mapValues } from '@aztec/foundation/collection'; +import { Fr, Gas } from '@aztec/circuits.js'; -import { EncryptedTxL2Logs, UnencryptedTxL2Logs } from '../logs/index.js'; -import { type ProcessedTx, PublicKernelType } from './processed_tx.js'; +import { PublicKernelType } from './processed_tx.js'; +import { type ProcessReturnValues, PublicSimulationOutput } from './public_simulation_output.js'; import { Tx } from './tx.js'; -/** Return values of simulating a circuit. */ -export type ProcessReturnValues = Fr[] | undefined; - -/** - * Outputs of processing the public component of a transaction. - * REFACTOR: Rename. - */ -export type ProcessOutput = Pick & - Pick & { publicReturnValues: ProcessReturnValues }; - -function processOutputToJSON(output: ProcessOutput) { - return { - encryptedLogs: output.encryptedLogs.toJSON(), - unencryptedLogs: output.unencryptedLogs.toJSON(), - revertReason: output.revertReason, - constants: output.constants.toBuffer().toString('hex'), - end: output.end.toBuffer().toString('hex'), - publicReturnValues: output.publicReturnValues?.map(fr => fr.toString()), - gasUsed: mapValues(output.gasUsed, gas => gas?.toJSON()), - }; -} - -function processOutputFromJSON(json: any): ProcessOutput { - return { - encryptedLogs: EncryptedTxL2Logs.fromJSON(json.encryptedLogs), - unencryptedLogs: UnencryptedTxL2Logs.fromJSON(json.unencryptedLogs), - revertReason: json.revertReason, - constants: CombinedConstantData.fromBuffer(Buffer.from(json.constants, 'hex')), - end: CombinedAccumulatedData.fromBuffer(Buffer.from(json.end, 'hex')), - publicReturnValues: json.publicReturnValues?.map(Fr.fromString), - gasUsed: mapValues(json.gasUsed, gas => (gas ? Gas.fromJSON(gas) : undefined)), - }; -} - // REFACTOR: Review what we need to expose to the user when running a simulation. // Eg tx already has encrypted and unencrypted logs, but those cover only the ones // emitted during private. We need the ones from ProcessOutput to include the public @@ -46,7 +11,11 @@ function processOutputFromJSON(json: any): ProcessOutput { // the public side of things. This also points at this class needing to be split into // two: one with just private simulation, and one that also includes public simulation. export class SimulatedTx { - constructor(public tx: Tx, public privateReturnValues?: ProcessReturnValues, public publicOutput?: ProcessOutput) {} + constructor( + public tx: Tx, + public privateReturnValues?: ProcessReturnValues, + public publicOutput?: PublicSimulationOutput, + ) {} /** * Returns suggested total and teardown gas limits for the simulated tx. @@ -79,7 +48,7 @@ export class SimulatedTx { return { tx: this.tx.toJSON(), privateReturnValues: this.privateReturnValues?.map(fr => fr.toString()), - publicOutput: this.publicOutput && processOutputToJSON(this.publicOutput), + publicOutput: this.publicOutput && this.publicOutput.toJSON(), }; } @@ -90,7 +59,7 @@ export class SimulatedTx { */ public static fromJSON(obj: any) { const tx = Tx.fromJSON(obj.tx); - const publicOutput = obj.publicOutput ? processOutputFromJSON(obj.publicOutput) : undefined; + const publicOutput = obj.publicOutput ? PublicSimulationOutput.fromJSON(obj.publicOutput) : undefined; const privateReturnValues = obj.privateReturnValues?.map(Fr.fromString); return new SimulatedTx(tx, privateReturnValues, publicOutput);