From 2c50098c02c7abdc582f22d2e7d865d2e97cc972 Mon Sep 17 00:00:00 2001 From: thunkar Date: Wed, 22 May 2024 14:02:20 +0000 Subject: [PATCH 1/5] batched simulations, lighter txexecutionrequests --- .../src/core/libraries/ConstantsGen.sol | 2 +- .../oracle/enqueue_public_function_call.nr | 2 +- .../crates/types/src/constants.nr | 2 +- .../aztec-node/src/aztec-node/server.ts | 2 +- .../account_manager/deploy_account_method.ts | 11 ++- .../aztec.js/src/contract/batch_call.ts | 62 +++++++++++++++ .../contract/contract_function_interaction.ts | 25 ++++-- .../src/entrypoint/default_entrypoint.ts | 8 +- .../default_multi_call_entrypoint.ts | 6 +- .../aztec.js/src/entrypoint/payload.ts | 11 +-- .../src/fee/native_fee_payment_method.ts | 9 ++- .../src/fee/private_fee_payment_method.ts | 20 ++--- .../src/fee/public_fee_payment_method.ts | 20 ++--- yarn-project/aztec.js/src/index.ts | 3 +- yarn-project/aztec.js/src/utils/authwit.ts | 6 +- .../circuit-types/src/function_call.ts | 73 ++++++++++++------ yarn-project/circuit-types/src/mocks.ts | 2 +- .../src/tx/public_simulation_output.ts | 8 +- yarn-project/circuit-types/src/tx/tx.ts | 2 +- .../circuit-types/src/tx_execution_request.ts | 20 +++-- yarn-project/circuits.js/src/constants.gen.ts | 2 +- .../src/structs/public_call_request.ts | 30 +++++--- .../circuits.js/src/tests/factories.ts | 2 +- .../end-to-end/src/e2e_fees/failures.test.ts | 43 ++++++----- .../end-to-end/src/e2e_state_vars.test.ts | 50 +++++++++++- .../entrypoints/src/account_entrypoint.ts | 6 +- .../entrypoints/src/dapp_entrypoint.ts | 10 +-- yarn-project/foundation/src/abi/decoder.ts | 14 ++-- .../pxe/src/pxe_service/pxe_service.ts | 21 ++--- .../src/pxe_service/test/pxe_test_suite.ts | 21 +---- .../src/tx_validator/phases_validator.test.ts | 4 +- .../src/tx_validator/phases_validator.ts | 11 +-- yarn-project/simulator/src/acvm/serialize.ts | 2 +- .../src/client/client_execution_context.ts | 6 +- .../src/client/private_execution.test.ts | 15 ++-- .../simulator/src/client/private_execution.ts | 13 ++-- .../simulator/src/client/simulator.ts | 11 ++- .../client/unconstrained_execution.test.ts | 9 ++- .../src/client/unconstrained_execution.ts | 13 ++-- yarn-project/simulator/src/mocks/fixtures.ts | 11 ++- .../src/public/abstract_phase_manager.ts | 5 +- .../simulator/src/public/avm_executor.test.ts | 5 +- .../simulator/src/public/execution.ts | 2 +- yarn-project/simulator/src/public/executor.ts | 19 +++-- .../simulator/src/public/index.test.ts | 76 +++++++++++-------- .../src/public/public_execution_context.ts | 4 +- .../src/public/public_processor.test.ts | 22 +++--- .../simulator/src/public/public_processor.ts | 4 +- .../src/public/transitional_adaptors.ts | 14 +--- 49 files changed, 456 insertions(+), 283 deletions(-) diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 9d61a722058..6923824f55a 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -217,7 +217,7 @@ library Constants { uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = CONSTANT_ROLLUP_DATA_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 5; uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = - 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH; + 3 + CALL_CONTEXT_LENGTH; uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674; uint256 internal constant NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr index 03ec1ebd9e9..34491d8d8ee 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr @@ -80,7 +80,7 @@ pub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_F // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields! let item = PublicCallStackItem { contract_address: AztecAddress::from_field(reader.read()), - function_data: reader.read_struct(FunctionData::deserialize), + function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false }, public_inputs: PublicCircuitPublicInputs { call_context: reader.read_struct(CallContext::deserialize), args_hash: reader.read(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 2a74118adde..ecdec2fb7f9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -211,7 +211,7 @@ global CONSTANT_ROLLUP_DATA_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + 4 + GLOB // + 5 for rollup_type, height_in_block_tree, txs_effects_hash, out_hash, accumulated_fees global BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = CONSTANT_ROLLUP_DATA_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 5; -global ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH: u64 = 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH; +global ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH: u64 = 3 + CALL_CONTEXT_LENGTH; global GET_NOTES_ORACLE_RETURN_LENGTH: u64 = 674; global NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048; global NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP: Field = 2048; diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 54b15609cd4..6c817777b8c 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -680,7 +680,7 @@ export class AztecNodeService implements AztecNode { processedTx.revertReason, processedTx.data.constants, processedTx.data.end, - returns[0], + returns, processedTx.gasUsed, ); } diff --git a/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts b/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts index fb0d91e8198..c4d494c817b 100644 --- a/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts +++ b/yarn-project/aztec.js/src/account_manager/deploy_account_method.ts @@ -1,7 +1,8 @@ -import { type Fr, FunctionData } from '@aztec/circuits.js'; +import { type Fr } from '@aztec/circuits.js'; import { type ContractArtifact, type FunctionArtifact, + FunctionSelector, encodeArguments, getFunctionArtifact, } from '@aztec/foundation/abi'; @@ -54,10 +55,16 @@ export class DeployAccountMethod extends DeployMethod { const feePayload = await EntrypointPayload.fromFeeOptions(options?.fee); exec.calls.push({ + name: this.#feePaymentArtifact.name, to: address, args: encodeArguments(this.#feePaymentArtifact, [emptyAppPayload, feePayload]), - functionData: FunctionData.fromAbi(this.#feePaymentArtifact), + selector: FunctionSelector.fromNameAndParameters( + this.#feePaymentArtifact.name, + this.#feePaymentArtifact.parameters, + ), + type: this.#feePaymentArtifact.functionType, isStatic: this.#feePaymentArtifact.isStatic, + returnTypes: this.#feePaymentArtifact.returnTypes, }); exec.authWitnesses ??= []; diff --git a/yarn-project/aztec.js/src/contract/batch_call.ts b/yarn-project/aztec.js/src/contract/batch_call.ts index ac7a65f40a1..22ea99b0931 100644 --- a/yarn-project/aztec.js/src/contract/batch_call.ts +++ b/yarn-project/aztec.js/src/contract/batch_call.ts @@ -1,7 +1,9 @@ import { type FunctionCall, type TxExecutionRequest } from '@aztec/circuit-types'; +import { FunctionType, decodeReturnValues } from '@aztec/foundation/abi'; import { type Wallet } from '../account/index.js'; import { BaseContractInteraction, type SendMethodOptions } from './base_contract_interaction.js'; +import type { SimulateMethodOptions } from './contract_function_interaction.js'; /** A batch of function calls to be sent as a single transaction through a wallet. */ export class BatchCall extends BaseContractInteraction { @@ -23,4 +25,64 @@ export class BatchCall extends BaseContractInteraction { } return this.txRequest; } + + /** + * Simulate a transaction and get its return values + * Differs from prove in a few important ways: + * 1. It returns the values of the function execution + * 2. It supports `unconstrained`, `private` and `public` functions + * + * @param options - An optional object containing additional configuration for the transaction. + * @returns The result of the transaction as returned by the contract function. + */ + public async simulate(options: SimulateMethodOptions = {}): Promise { + const { calls, unconstrained } = this.calls.reduce<{ + /** + * The public and private function calls in the batch + */ + calls: [FunctionCall, number][]; + /** + * The unconstrained function calls in the batch. + */ + unconstrained: [FunctionCall, number][]; + }>( + (acc, current, index) => { + if (current.type === FunctionType.UNCONSTRAINED) { + acc.unconstrained.push([current, index]); + } else { + acc.calls.push([current, index]); + } + return acc; + }, + { calls: [], unconstrained: [] }, + ); + + const unconstrainedCalls = await Promise.all( + unconstrained.map(async indexedCall => { + const call = indexedCall[0]; + return [await this.wallet.simulateUnconstrained(call.name, call.args, call.to, options?.from), indexedCall[1]]; + }), + ); + + const txRequest = await this.wallet.createTxExecutionRequest({ calls: calls.map(indexedCall => indexedCall[0]) }); + const simulatedTx = await this.wallet.simulateTx(txRequest, true, options?.from); + + const results: any[] = []; + + unconstrainedCalls.forEach(([result, index]) => { + results[index] = result; + }); + calls.forEach(([call, callIndex], resultIndex) => { + // As account entrypoints are private, for private functions we retrieve the return values from the first nested call + // since we're interested in the first set of values AFTER the account entrypoint + // For public functions we retrieve the first values directly from the public output. + const rawReturnValues = + call.type == FunctionType.PRIVATE + ? simulatedTx.privateReturnValues?.nested?.[resultIndex].values + : simulatedTx.publicOutput?.publicReturnValues?.[resultIndex].values; + + results[callIndex] = rawReturnValues ? decodeReturnValues(call.returnTypes, rawReturnValues) : []; + }); + return results; + } } diff --git a/yarn-project/aztec.js/src/contract/contract_function_interaction.ts b/yarn-project/aztec.js/src/contract/contract_function_interaction.ts index 1ba216d9854..d74a282efff 100644 --- a/yarn-project/aztec.js/src/contract/contract_function_interaction.ts +++ b/yarn-project/aztec.js/src/contract/contract_function_interaction.ts @@ -1,6 +1,12 @@ import type { FunctionCall, TxExecutionRequest } from '@aztec/circuit-types'; -import { type AztecAddress, FunctionData, type GasSettings } from '@aztec/circuits.js'; -import { type FunctionAbi, FunctionType, decodeReturnValues, encodeArguments } from '@aztec/foundation/abi'; +import { type AztecAddress, type GasSettings } from '@aztec/circuits.js'; +import { + type FunctionAbi, + FunctionSelector, + FunctionType, + decodeReturnValues, + encodeArguments, +} from '@aztec/foundation/abi'; import { type Wallet } from '../account/wallet.js'; import { BaseContractInteraction, type SendMethodOptions } from './base_contract_interaction.js'; @@ -61,8 +67,15 @@ export class ContractFunctionInteraction extends BaseContractInteraction { */ public request(): FunctionCall { const args = encodeArguments(this.functionDao, this.args); - const functionData = FunctionData.fromAbi(this.functionDao); - return { args, functionData, to: this.contractAddress, isStatic: this.functionDao.isStatic }; + return { + name: this.functionDao.name, + args, + selector: FunctionSelector.fromNameAndParameters(this.functionDao.name, this.functionDao.parameters), + type: this.functionDao.functionType, + to: this.contractAddress, + isStatic: this.functionDao.isStatic, + returnTypes: this.functionDao.returnTypes, + }; } /** @@ -88,8 +101,8 @@ export class ContractFunctionInteraction extends BaseContractInteraction { const rawReturnValues = this.functionDao.functionType == FunctionType.PRIVATE ? simulatedTx.privateReturnValues?.nested?.[0].values - : simulatedTx.publicOutput?.publicReturnValues?.values; + : simulatedTx.publicOutput?.publicReturnValues?.[0].values; - return rawReturnValues ? decodeReturnValues(this.functionDao, rawReturnValues) : []; + return rawReturnValues ? decodeReturnValues(this.functionDao.returnTypes, rawReturnValues) : []; } } diff --git a/yarn-project/aztec.js/src/entrypoint/default_entrypoint.ts b/yarn-project/aztec.js/src/entrypoint/default_entrypoint.ts index 9728d610c59..d387f4cddb9 100644 --- a/yarn-project/aztec.js/src/entrypoint/default_entrypoint.ts +++ b/yarn-project/aztec.js/src/entrypoint/default_entrypoint.ts @@ -1,5 +1,6 @@ import { PackedValues, TxExecutionRequest } from '@aztec/circuit-types'; import { GasSettings, TxContext } from '@aztec/circuits.js'; +import { FunctionType } from '@aztec/foundation/abi'; import { type EntrypointInterface, type ExecutionRequestInit } from './entrypoint.js'; @@ -17,13 +18,18 @@ export class DefaultEntrypoint implements EntrypointInterface { } const call = calls[0]; + + if (call.type !== FunctionType.PRIVATE) { + throw new Error('Public entrypoints are not allowed'); + } + const entrypointPackedValues = PackedValues.fromValues(call.args); const gasSettings = exec.fee?.gasSettings ?? GasSettings.default(); const txContext = new TxContext(this.chainId, this.protocolVersion, gasSettings); return Promise.resolve( new TxExecutionRequest( call.to, - call.functionData, + call.selector, entrypointPackedValues.hash, txContext, [...packedArguments, entrypointPackedValues], diff --git a/yarn-project/aztec.js/src/entrypoint/default_multi_call_entrypoint.ts b/yarn-project/aztec.js/src/entrypoint/default_multi_call_entrypoint.ts index 8d5e7e6cd3f..d55dca77da1 100644 --- a/yarn-project/aztec.js/src/entrypoint/default_multi_call_entrypoint.ts +++ b/yarn-project/aztec.js/src/entrypoint/default_multi_call_entrypoint.ts @@ -1,7 +1,7 @@ import { type EntrypointInterface, EntrypointPayload, type ExecutionRequestInit } from '@aztec/aztec.js/entrypoint'; import { PackedValues, TxExecutionRequest } from '@aztec/circuit-types'; -import { type AztecAddress, FunctionData, GasSettings, TxContext } from '@aztec/circuits.js'; -import { type FunctionAbi, encodeArguments } from '@aztec/foundation/abi'; +import { type AztecAddress, GasSettings, TxContext } from '@aztec/circuits.js'; +import { type FunctionAbi, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { getCanonicalMultiCallEntrypointAddress } from '@aztec/protocol-contracts/multi-call-entrypoint'; /** @@ -24,7 +24,7 @@ export class DefaultMultiCallEntrypoint implements EntrypointInterface { const txRequest = TxExecutionRequest.from({ firstCallArgsHash: entrypointPackedArgs.hash, origin: this.address, - functionData: FunctionData.fromAbi(abi), + functionSelector: FunctionSelector.fromNameAndParameters(abi.name, abi.parameters), txContext: new TxContext(this.chainId, this.version, gasSettings), argsOfCalls: [...payload.packedArguments, ...packedArguments, entrypointPackedArgs], authWitnesses, diff --git a/yarn-project/aztec.js/src/entrypoint/payload.ts b/yarn-project/aztec.js/src/entrypoint/payload.ts index 9b1416114a1..66b481093a9 100644 --- a/yarn-project/aztec.js/src/entrypoint/payload.ts +++ b/yarn-project/aztec.js/src/entrypoint/payload.ts @@ -1,5 +1,6 @@ -import { type FunctionCall, PackedValues, emptyFunctionCall } from '@aztec/circuit-types'; +import { FunctionCall, PackedValues } from '@aztec/circuit-types'; import { Fr, type GasSettings, GeneratorIndex } from '@aztec/circuits.js'; +import { FunctionType } from '@aztec/foundation/abi'; import { padArrayEnd } from '@aztec/foundation/collection'; import { pedersenHash } from '@aztec/foundation/crypto'; import { type Tuple } from '@aztec/foundation/serialize'; @@ -53,9 +54,9 @@ export class EntrypointPayload { /* eslint-disable camelcase */ this.#functionCalls = functionCalls.map((call, index) => ({ args_hash: this.#packedArguments[index].hash, - function_selector: call.functionData.selector.toField(), + function_selector: call.selector.toField(), target_address: call.to.toField(), - is_public: !call.functionData.isPrivate, + is_public: call.type == FunctionType.PUBLIC, is_static: call.isStatic, })); /* eslint-enable camelcase */ @@ -131,7 +132,7 @@ export class EntrypointPayload { if (functionCalls.length > APP_MAX_CALLS) { throw new Error(`Expected at most ${APP_MAX_CALLS} function calls, got ${functionCalls.length}`); } - const paddedCalls = padArrayEnd(functionCalls, emptyFunctionCall(), APP_MAX_CALLS); + const paddedCalls = padArrayEnd(functionCalls, FunctionCall.empty(), APP_MAX_CALLS); return new EntrypointPayload(paddedCalls, GeneratorIndex.SIGNATURE_PAYLOAD); } @@ -142,7 +143,7 @@ export class EntrypointPayload { */ static async fromFeeOptions(feeOpts?: FeeOptions) { const calls = feeOpts ? await feeOpts.paymentMethod.getFunctionCalls(feeOpts?.gasSettings) : []; - const paddedCalls = padArrayEnd(calls, emptyFunctionCall(), FEE_MAX_CALLS); + const paddedCalls = padArrayEnd(calls, FunctionCall.empty(), FEE_MAX_CALLS); return new EntrypointPayload(paddedCalls, GeneratorIndex.FEE_PAYLOAD); } } diff --git a/yarn-project/aztec.js/src/fee/native_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/native_fee_payment_method.ts index 7fab211e9d9..f69bb84fc46 100644 --- a/yarn-project/aztec.js/src/fee/native_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/native_fee_payment_method.ts @@ -1,6 +1,6 @@ import { type FunctionCall } from '@aztec/circuit-types'; -import { type AztecAddress, FunctionData, type GasSettings } from '@aztec/circuits.js'; -import { FunctionSelector } from '@aztec/foundation/abi'; +import { type AztecAddress, type GasSettings } from '@aztec/circuits.js'; +import { FunctionSelector, FunctionType } from '@aztec/foundation/abi'; import { GasTokenAddress } from '@aztec/protocol-contracts/gas-token'; import { type FeePaymentMethod } from './fee_payment_method.js'; @@ -47,10 +47,13 @@ export class NativeFeePaymentMethod implements FeePaymentMethod { getFunctionCalls(gasSettings: GasSettings): Promise { return Promise.resolve([ { + name: 'pay_fee', to: this.#gasTokenAddress, - functionData: new FunctionData(FunctionSelector.fromSignature('pay_fee(Field)'), /*isPrivate=*/ false), + selector: FunctionSelector.fromSignature('pay_fee(Field)'), + type: FunctionType.PUBLIC, isStatic: false, args: [gasSettings.getFeeLimit()], + returnTypes: [], }, ]); } diff --git a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts index cbd7f7c1317..8cdd17d10f4 100644 --- a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts @@ -1,7 +1,7 @@ import { type FunctionCall } from '@aztec/circuit-types'; -import { FunctionData, type GasSettings } from '@aztec/circuits.js'; +import { type GasSettings } from '@aztec/circuits.js'; import { computeSecretHash } from '@aztec/circuits.js/hash'; -import { FunctionSelector } from '@aztec/foundation/abi'; +import { FunctionSelector, FunctionType } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; @@ -64,13 +64,13 @@ export class PrivateFeePaymentMethod implements FeePaymentMethod { this.wallet.getChainId(), this.wallet.getVersion(), { + name: 'unshield', args: [this.wallet.getCompleteAddress().address, this.paymentContract, maxFee, nonce], - functionData: new FunctionData( - FunctionSelector.fromSignature('unshield((Field),(Field),Field,Field)'), - /*isPrivate=*/ true, - ), + selector: FunctionSelector.fromSignature('unshield((Field),(Field),Field,Field)'), + type: FunctionType.PRIVATE, isStatic: false, to: this.asset, + returnTypes: [], }, ); await this.wallet.createAuthWit(messageHash); @@ -79,13 +79,13 @@ export class PrivateFeePaymentMethod implements FeePaymentMethod { return [ { + name: 'fee_entrypoint_private', to: this.getPaymentContract(), - functionData: new FunctionData( - FunctionSelector.fromSignature('fee_entrypoint_private(Field,(Field),Field,Field)'), - /*isPrivate=*/ true, - ), + selector: FunctionSelector.fromSignature('fee_entrypoint_private(Field,(Field),Field,Field)'), + type: FunctionType.PRIVATE, isStatic: false, args: [maxFee, this.asset, secretHashForRebate, nonce], + returnTypes: [], }, ]; } diff --git a/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts index fad9cbcbfa0..bca1ba0f03b 100644 --- a/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts @@ -1,6 +1,6 @@ import { type FunctionCall } from '@aztec/circuit-types'; -import { FunctionData, type GasSettings } from '@aztec/circuits.js'; -import { FunctionSelector } from '@aztec/foundation/abi'; +import { type GasSettings } from '@aztec/circuits.js'; +import { FunctionSelector, FunctionType } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; @@ -57,26 +57,26 @@ export class PublicFeePaymentMethod implements FeePaymentMethod { this.wallet.getChainId(), this.wallet.getVersion(), { + name: 'transfer_public', args: [this.wallet.getAddress(), this.paymentContract, maxFee, nonce], - functionData: new FunctionData( - FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), - /*isPrivate=*/ false, - ), + selector: FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), + type: FunctionType.PUBLIC, isStatic: false, to: this.asset, + returnTypes: [], }, ); return Promise.resolve([ this.wallet.setPublicAuthWit(messageHash, true).request(), { + name: 'fee_entrypoint_public', to: this.getPaymentContract(), - functionData: new FunctionData( - FunctionSelector.fromSignature('fee_entrypoint_public(Field,(Field),Field)'), - /*isPrivate=*/ true, - ), + selector: FunctionSelector.fromSignature('fee_entrypoint_public(Field,(Field),Field)'), + type: FunctionType.PRIVATE, isStatic: false, args: [maxFee, this.asset, nonce], + returnTypes: [], }, ]); } diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index ed54657b950..c98751767e4 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -92,7 +92,7 @@ export { Body, CompleteAddress, ExtendedNote, - type FunctionCall, + FunctionCall, GrumpkinPrivateKey, L1ToL2Message, L1Actor, @@ -118,7 +118,6 @@ export { TxStatus, UnencryptedL2Log, createAztecNodeClient, - emptyFunctionCall, merkleTreeIds, mockTx, Comparator, diff --git a/yarn-project/aztec.js/src/utils/authwit.ts b/yarn-project/aztec.js/src/utils/authwit.ts index 173f8b9f472..41655da79fb 100644 --- a/yarn-project/aztec.js/src/utils/authwit.ts +++ b/yarn-project/aztec.js/src/utils/authwit.ts @@ -22,11 +22,7 @@ export const computeAuthWitMessageHash = (caller: AztecAddress, chainId: Fr, ver action.to.toField(), chainId, version, - computeInnerAuthWitHash([ - caller.toField(), - action.functionData.selector.toField(), - PackedValues.fromValues(action.args).hash, - ]), + computeInnerAuthWitHash([caller.toField(), action.selector.toField(), PackedValues.fromValues(action.args).hash]), ); }; // docs:end:authwit_computeAuthWitMessageHash diff --git a/yarn-project/circuit-types/src/function_call.ts b/yarn-project/circuit-types/src/function_call.ts index dcadf32121e..cded239241e 100644 --- a/yarn-project/circuit-types/src/function_call.ts +++ b/yarn-project/circuit-types/src/function_call.ts @@ -1,26 +1,55 @@ -import { AztecAddress, type Fr, FunctionData } from '@aztec/circuits.js'; +import { AztecAddress, type Fr } from '@aztec/circuits.js'; +import { type AbiType, FunctionSelector, FunctionType } from '@aztec/foundation/abi'; +import { type FieldsOf } from '@aztec/foundation/types'; /** A request to call a function on a contract from a given address. */ -export type FunctionCall = { - /** The recipient contract */ - to: AztecAddress; - /** The function being called */ - functionData: FunctionData; - /** Whether this call can make modifications to state or not */ - isStatic: boolean; - /** The encoded args */ - args: Fr[]; -}; +export class FunctionCall { + constructor( + /** The name of the function to call */ + public name: string, + /** The recipient contract */ + public to: AztecAddress, + /** The function being called */ + public selector: FunctionSelector, + /** Type of the function */ + public type: FunctionType, + /** Whether this call can make modifications to state or not */ + public isStatic: boolean, + /** The encoded args */ + public args: Fr[], + /** The return type for decoding */ + public returnTypes: AbiType[], + ) {} -/** - * Creates an empty function call. - * @returns an empty function call. - */ -export function emptyFunctionCall() { - return { - to: AztecAddress.ZERO, - functionData: FunctionData.empty(), - isStatic: false, - args: [], - }; + static getFields(fields: FieldsOf) { + return [ + fields.name, + fields.to, + fields.selector, + fields.type, + fields.isStatic, + fields.args, + fields.returnTypes, + ] as const; + } + + static from(fields: FieldsOf): FunctionCall { + return new FunctionCall(...FunctionCall.getFields(fields)); + } + + /** + * Creates an empty function call. + * @returns an empty function call. + */ + public static empty() { + return { + name: '', + to: AztecAddress.ZERO, + selector: FunctionSelector.empty(), + type: FunctionType.PUBLIC, + isStatic: false, + args: [], + returnTypes: [], + }; + } } diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index 0fc51c62cdb..ee0ef6fd273 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -152,7 +152,7 @@ export const mockSimulatedTx = (seed = 1, hasLogs = true) => { undefined, makeCombinedConstantData(), makeCombinedAccumulatedData(), - dec, + [dec], {}, ); return new SimulatedTx(tx, dec, 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 d28daa3dc4b..6645d3f7a6f 100644 --- a/yarn-project/circuit-types/src/tx/public_simulation_output.ts +++ b/yarn-project/circuit-types/src/tx/public_simulation_output.ts @@ -43,7 +43,7 @@ export class PublicSimulationOutput { public revertReason: SimulationError | undefined, public constants: CombinedConstantData, public end: CombinedAccumulatedData, - public publicReturnValues: NestedProcessReturnValues, + public publicReturnValues: NestedProcessReturnValues[], public gasUsed: Partial>, ) {} @@ -54,7 +54,7 @@ export class PublicSimulationOutput { revertReason: this.revertReason, constants: this.constants.toBuffer().toString('hex'), end: this.end.toBuffer().toString('hex'), - publicReturnValues: this.publicReturnValues?.toJSON(), + publicReturnValues: this.publicReturnValues.map(returns => returns?.toJSON()), gasUsed: mapValues(this.gasUsed, gas => gas?.toJSON()), }; } @@ -66,7 +66,9 @@ export class PublicSimulationOutput { json.revertReason, CombinedConstantData.fromBuffer(Buffer.from(json.constants, 'hex')), CombinedAccumulatedData.fromBuffer(Buffer.from(json.end, 'hex')), - NestedProcessReturnValues.fromJSON(json.publicReturnValues), + Array.isArray(json.publicReturnValues) + ? json.publicReturnValues.map((returns: any) => NestedProcessReturnValues.fromJSON(returns)) + : [], mapValues(json.gasUsed, gas => (gas ? Gas.fromJSON(gas) : undefined)), ); } diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index 44853dcd91e..6aef8ba6279 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -182,7 +182,7 @@ export class Tx { ? // needsSetup? then we pay through a fee payment contract this.data.forPublic?.needsSetup ? // if the first call is to `approve_public_authwit`, then it's a public payment - this.enqueuedPublicFunctionCalls.at(-1)!.functionData.selector.toField().toBigInt() === 0x43417bb1n + this.enqueuedPublicFunctionCalls.at(-1)!.functionSelector.toField().toBigInt() === 0x43417bb1n ? 'fpc_public' : 'fpc_private' : 'native' diff --git a/yarn-project/circuit-types/src/tx_execution_request.ts b/yarn-project/circuit-types/src/tx_execution_request.ts index 9d7101877dc..4db2547ac79 100644 --- a/yarn-project/circuit-types/src/tx_execution_request.ts +++ b/yarn-project/circuit-types/src/tx_execution_request.ts @@ -1,4 +1,4 @@ -import { AztecAddress, Fr, FunctionData, TxContext, TxRequest, Vector } from '@aztec/circuits.js'; +import { AztecAddress, Fr, FunctionData, FunctionSelector, TxContext, TxRequest, Vector } from '@aztec/circuits.js'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; @@ -15,10 +15,9 @@ export class TxExecutionRequest { */ public origin: AztecAddress, /** - * Function data representing the function to call. - * TODO(#3417): Remove this field and replace with a function selector. + * Selector of the function to call. */ - public functionData: FunctionData, + public functionSelector: FunctionSelector, /** * The hash of arguments of first call to be executed (usually account entrypoint). * @dev This hash is a pointer to `argsOfCalls` unordered array. @@ -42,13 +41,18 @@ export class TxExecutionRequest { ) {} toTxRequest(): TxRequest { - return new TxRequest(this.origin, this.functionData, this.firstCallArgsHash, this.txContext); + return new TxRequest( + this.origin, + new FunctionData(this.functionSelector, true), + this.firstCallArgsHash, + this.txContext, + ); } static getFields(fields: FieldsOf) { return [ fields.origin, - fields.functionData, + fields.functionSelector, fields.firstCallArgsHash, fields.txContext, fields.argsOfCalls, @@ -67,7 +71,7 @@ export class TxExecutionRequest { toBuffer() { return serializeToBuffer( this.origin, - this.functionData, + this.functionSelector, this.firstCallArgsHash, this.txContext, new Vector(this.argsOfCalls), @@ -92,7 +96,7 @@ export class TxExecutionRequest { const reader = BufferReader.asReader(buffer); return new TxExecutionRequest( reader.readObject(AztecAddress), - reader.readObject(FunctionData), + reader.readObject(FunctionSelector), Fr.fromBuffer(reader), reader.readObject(TxContext), reader.readVector(PackedValues), diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index f8de41b9cf8..1ba42de9b06 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -235,7 +235,7 @@ export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = export const CONSTANT_ROLLUP_DATA_LENGTH = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + 4 + GLOBAL_VARIABLES_LENGTH; export const BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = CONSTANT_ROLLUP_DATA_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 5; -export const ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 2 + FUNCTION_DATA_LENGTH + CALL_CONTEXT_LENGTH; +export const ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 3 + CALL_CONTEXT_LENGTH; export const GET_NOTES_ORACLE_RETURN_LENGTH = 674; export const NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; export const NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/yarn-project/circuits.js/src/structs/public_call_request.ts b/yarn-project/circuits.js/src/structs/public_call_request.ts index 752adfc7672..d8fc26b3dfc 100644 --- a/yarn-project/circuits.js/src/structs/public_call_request.ts +++ b/yarn-project/circuits.js/src/structs/public_call_request.ts @@ -9,7 +9,7 @@ import { computeVarArgsHash } from '../hash/hash.js'; import { CallContext } from './call_context.js'; import { CallRequest } from './call_request.js'; import { CallerContext } from './caller_context.js'; -import { FunctionData } from './function_data.js'; +import { FunctionData, FunctionSelector } from './index.js'; import { PublicCallStackItem } from './public_call_stack_item.js'; import { PublicCircuitPublicInputs } from './public_circuit_public_inputs.js'; import { Vector } from './shared.js'; @@ -26,9 +26,8 @@ export class PublicCallRequest { public contractAddress: AztecAddress, /** * Data identifying the function being called. - * TODO(#3417): Remove this since the only useful data is the function selector, which is already part of the call context. */ - public functionData: FunctionData, + public functionSelector: FunctionSelector, /** * Context of the public call. * TODO(#3417): Check if all fields of CallContext are actually needed. @@ -52,7 +51,7 @@ export class PublicCallRequest { toBuffer() { return serializeToBuffer( this.contractAddress, - this.functionData, + this.functionSelector, this.callContext, this.parentCallContext, new Vector(this.args), @@ -68,7 +67,7 @@ export class PublicCallRequest { const reader = BufferReader.asReader(buffer); return new PublicCallRequest( new AztecAddress(reader.readBytes(32)), - FunctionData.fromBuffer(reader), + FunctionSelector.fromBuffer(reader), CallContext.fromBuffer(reader), CallContext.fromBuffer(reader), reader.readVector(Fr), @@ -92,7 +91,7 @@ export class PublicCallRequest { static getFields(fields: FieldsOf) { return [ fields.contractAddress, - fields.functionData, + fields.functionSelector, fields.callContext, fields.parentCallContext, fields.args, @@ -107,7 +106,12 @@ export class PublicCallRequest { const publicInputs = PublicCircuitPublicInputs.empty(); publicInputs.callContext = this.callContext; publicInputs.argsHash = this.getArgsHash(); - return new PublicCallStackItem(this.contractAddress, this.functionData, publicInputs, true); + return new PublicCallStackItem( + this.contractAddress, + new FunctionData(this.functionSelector, false), + publicInputs, + true, + ); } /** @@ -141,13 +145,19 @@ export class PublicCallRequest { } static empty() { - return new PublicCallRequest(AztecAddress.ZERO, FunctionData.empty(), CallContext.empty(), CallContext.empty(), []); + return new PublicCallRequest( + AztecAddress.ZERO, + FunctionSelector.empty(), + CallContext.empty(), + CallContext.empty(), + [], + ); } isEmpty(): boolean { return ( this.contractAddress.isZero() && - this.functionData.isEmpty() && + this.functionSelector.isEmpty() && this.callContext.isEmpty() && this.parentCallContext.isEmpty() && this.args.length === 0 @@ -157,7 +167,7 @@ export class PublicCallRequest { [inspect.custom]() { return `PublicCallRequest { contractAddress: ${this.contractAddress} - functionData: ${this.functionData} + functionSelector: ${this.functionSelector} callContext: ${this.callContext} parentCallContext: ${this.parentCallContext} args: ${this.args} }`; diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index d9608ee0211..6da05ef1f5d 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -508,7 +508,7 @@ export function makePublicCallRequest(seed = 1): PublicCallRequest { return new PublicCallRequest( makeAztecAddress(seed), - new FunctionData(makeSelector(seed + 0x1), /*isPrivate=*/ false), + makeSelector(seed + 0x1), childCallContext, parentCallContext, makeTuple(ARGS_LENGTH, fr, seed + 0x10), 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 20225b21a9e..34029bae995 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 @@ -8,7 +8,8 @@ import { TxStatus, computeAuthWitMessageHash, } from '@aztec/aztec.js'; -import { FunctionData, type GasSettings } from '@aztec/circuits.js'; +import { type GasSettings } from '@aztec/circuits.js'; +import { FunctionType } from '@aztec/foundation/abi'; import { type TokenContract as BananaCoin, type FPCContract } from '@aztec/noir-contracts.js'; import { expectMapping } from '../fixtures/utils.js'; @@ -226,13 +227,13 @@ class BuggedSetupFeePaymentMethod extends PublicFeePaymentMethod { this.wallet.getChainId(), this.wallet.getVersion(), { + name: 'transfer_public', args: [this.wallet.getAddress(), this.paymentContract, maxFee, nonce], - functionData: new FunctionData( - FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), - /*isPrivate=*/ false, - ), + selector: FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), + type: FunctionType.PUBLIC, isStatic: false, to: this.asset, + returnTypes: [], }, ); @@ -241,13 +242,13 @@ class BuggedSetupFeePaymentMethod extends PublicFeePaymentMethod { return Promise.resolve([ this.wallet.setPublicAuthWit(messageHash, true).request(), { + name: 'fee_entrypoint_public', to: this.getPaymentContract(), - functionData: new FunctionData( - FunctionSelector.fromSignature('fee_entrypoint_public(Field,(Field),Field)'), - /*isPrivate=*/ true, - ), + selector: FunctionSelector.fromSignature('fee_entrypoint_public(Field,(Field),Field)'), + type: FunctionType.PRIVATE, isStatic: false, args: [tooMuchFee, this.asset, nonce], + returnTypes: [], }, ]); } @@ -263,13 +264,13 @@ class BuggedTeardownFeePaymentMethod extends PublicFeePaymentMethod { this.wallet.getChainId(), this.wallet.getVersion(), { + name: 'transfer_public', args: [this.wallet.getAddress(), this.paymentContract, maxFee, nonce], - functionData: new FunctionData( - FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), - /*isPrivate=*/ false, - ), + selector: FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), + type: FunctionType.PUBLIC, isStatic: false, to: this.asset, + returnTypes: [], }, ); @@ -280,23 +281,23 @@ class BuggedTeardownFeePaymentMethod extends PublicFeePaymentMethod { return Promise.resolve([ // in this, we're actually paying the fee in setup { + name: 'fee_entrypoint_public', to: this.getPaymentContract(), - functionData: new FunctionData( - FunctionSelector.fromSignature('fee_entrypoint_public(Field,(Field),Field)'), - /*isPrivate=*/ true, - ), + selector: FunctionSelector.fromSignature('fee_entrypoint_public(Field,(Field),Field)'), + type: FunctionType.PRIVATE, isStatic: false, args: [maxFee, this.asset, nonce], + returnTypes: [], }, // and trying to take a little extra in teardown, but specify a bad nonce { + name: 'transfer_public', to: this.asset, - functionData: new FunctionData( - FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), - /*isPrivate=*/ false, - ), + selector: FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), + type: FunctionType.PUBLIC, isStatic: false, args: [this.wallet.getAddress(), this.paymentContract, new Fr(1), Fr.random()], + returnTypes: [], }, ]); } diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index 2eebaec5d99..ff34a9980b1 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -1,4 +1,4 @@ -import { AztecAddress, Fr, type Wallet } from '@aztec/aztec.js'; +import { AztecAddress, BatchCall, Fr, type Wallet } from '@aztec/aztec.js'; import { AuthContract, DocsExampleContract, TestContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; @@ -33,6 +33,17 @@ describe('e2e_state_vars', () => { await contract.methods.match_shared_immutable(s.account, s.points).send().wait(); }); + it('initialize and read SharedImmutable', async () => { + // Initializes the shared immutable and then reads the value using an unconstrained function + // checking the return values: + + await contract.methods.initialize_shared_immutable(1).send().wait(); + + const read = await contract.methods.get_shared_immutable().simulate(); + + expect(read).toEqual({ account: wallet.getAddress(), points: read.points }); + }); + it('private read of SharedImmutable', async () => { // Initializes the shared immutable and then reads the value using an unconstrained function // checking the return values with: @@ -40,8 +51,6 @@ describe('e2e_state_vars', () => { // 2. A constrained private function that calls another private function that reads. // The indirect, adds 1 to the point to ensure that we are returning the correct value. - await contract.methods.initialize_shared_immutable(1).send().wait(); - const a = await contract.methods.get_shared_immutable_constrained_private().simulate(); const b = await contract.methods.get_shared_immutable_constrained_private_indirect().simulate(); const c = await contract.methods.get_shared_immutable().simulate(); @@ -51,6 +60,23 @@ describe('e2e_state_vars', () => { await contract.methods.match_shared_immutable(c.account, c.points).send().wait(); }); + it('private read of SharedImmutable in batches', async () => { + // Reads the value using an unconstrained function checking the return values with: + // 1. A constrained private function that reads it directly + // 2. A constrained private function that calls another private function that reads. + // The indirect, adds 1 to the point to ensure that we are returning the correct value. + + const [a, b, c] = await new BatchCall(wallet, [ + contract.methods.get_shared_immutable_constrained_private().request(), + contract.methods.get_shared_immutable_constrained_private_indirect().request(), + contract.methods.get_shared_immutable().request(), + ]).simulate(); + + expect(a).toEqual(c); + expect(b).toEqual({ account: c.account, points: c.points + 1n }); + await contract.methods.match_shared_immutable(c.account, c.points).send().wait(); + }); + it('public read of SharedImmutable', async () => { // Reads the value using an unconstrained function checking the return values with: // 1. A constrained public function that reads it directly @@ -67,6 +93,24 @@ describe('e2e_state_vars', () => { await contract.methods.match_shared_immutable(c.account, c.points).send().wait(); }); + it('public read of SharedImmutable in batches', async () => { + // Reads the value using an unconstrained function checking the return values with: + // 1. A constrained public function that reads it directly + // 2. A constrained public function that calls another public function that reads. + // The indirect, adds 1 to the point to ensure that we are returning the correct value. + + const [a, b, c] = await new BatchCall(wallet, [ + contract.methods.get_shared_immutable_constrained_public().request(), + contract.methods.get_shared_immutable_constrained_public_indirect().request(), + contract.methods.get_shared_immutable().request(), + ]).simulate(); + + expect(a).toEqual(c); + expect(b).toEqual({ account: c.account, points: c.points + 1n }); + + await contract.methods.match_shared_immutable(c.account, c.points).send().wait(); + }); + it('public multiread of SharedImmutable', async () => { // Reads the value using an unconstrained function checking the return values with: // 1. A constrained public function that reads 5 times directly (going beyond the previous 4 Field return value) diff --git a/yarn-project/entrypoints/src/account_entrypoint.ts b/yarn-project/entrypoints/src/account_entrypoint.ts index a7a9450f36f..11266fa8e93 100644 --- a/yarn-project/entrypoints/src/account_entrypoint.ts +++ b/yarn-project/entrypoints/src/account_entrypoint.ts @@ -1,8 +1,8 @@ import { type AuthWitnessProvider } from '@aztec/aztec.js/account'; import { type EntrypointInterface, EntrypointPayload, type ExecutionRequestInit } from '@aztec/aztec.js/entrypoint'; import { PackedValues, TxExecutionRequest } from '@aztec/circuit-types'; -import { type AztecAddress, FunctionData, GasSettings, TxContext } from '@aztec/circuits.js'; -import { type FunctionAbi, encodeArguments } from '@aztec/foundation/abi'; +import { type AztecAddress, GasSettings, TxContext } from '@aztec/circuits.js'; +import { type FunctionAbi, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { DEFAULT_CHAIN_ID, DEFAULT_VERSION } from './constants.js'; @@ -33,7 +33,7 @@ export class DefaultAccountEntrypoint implements EntrypointInterface { const txRequest = TxExecutionRequest.from({ firstCallArgsHash: entrypointPackedArgs.hash, origin: this.address, - functionData: FunctionData.fromAbi(abi), + functionSelector: FunctionSelector.fromNameAndParameters(abi.name, abi.parameters), txContext: new TxContext(this.chainId, this.version, gasSettings), argsOfCalls: [...appPayload.packedArguments, ...feePayload.packedArguments, entrypointPackedArgs], authWitnesses: [appAuthWitness, feeAuthWitness], diff --git a/yarn-project/entrypoints/src/dapp_entrypoint.ts b/yarn-project/entrypoints/src/dapp_entrypoint.ts index 5f7572da58e..18a217f2eda 100644 --- a/yarn-project/entrypoints/src/dapp_entrypoint.ts +++ b/yarn-project/entrypoints/src/dapp_entrypoint.ts @@ -2,8 +2,8 @@ import { computeInnerAuthWitHash, computeOuterAuthWitHash } from '@aztec/aztec.j import { type AuthWitnessProvider } from '@aztec/aztec.js/account'; import { type EntrypointInterface, EntrypointPayload, type ExecutionRequestInit } from '@aztec/aztec.js/entrypoint'; import { PackedValues, TxExecutionRequest } from '@aztec/circuit-types'; -import { type AztecAddress, Fr, FunctionData, GasSettings, TxContext } from '@aztec/circuits.js'; -import { type FunctionAbi, encodeArguments } from '@aztec/foundation/abi'; +import { type AztecAddress, Fr, GasSettings, TxContext } from '@aztec/circuits.js'; +import { type FunctionAbi, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { DEFAULT_CHAIN_ID, DEFAULT_VERSION } from './constants.js'; @@ -31,9 +31,9 @@ export class DefaultDappEntrypoint implements EntrypointInterface { const abi = this.getEntrypointAbi(); const entrypointPackedArgs = PackedValues.fromValues(encodeArguments(abi, [payload, this.userAddress])); const gasSettings = exec.fee?.gasSettings ?? GasSettings.default(); - const functionData = FunctionData.fromAbi(abi); + const functionSelector = FunctionSelector.fromNameAndParameters(abi.name, abi.parameters); - const innerHash = computeInnerAuthWitHash([Fr.ZERO, functionData.selector.toField(), entrypointPackedArgs.hash]); + const innerHash = computeInnerAuthWitHash([Fr.ZERO, functionSelector.toField(), entrypointPackedArgs.hash]); const outerHash = computeOuterAuthWitHash( this.dappEntrypointAddress, new Fr(this.chainId), @@ -46,7 +46,7 @@ export class DefaultDappEntrypoint implements EntrypointInterface { const txRequest = TxExecutionRequest.from({ firstCallArgsHash: entrypointPackedArgs.hash, origin: this.dappEntrypointAddress, - functionData, + functionSelector, txContext: new TxContext(this.chainId, this.version, gasSettings), argsOfCalls: [...payload.packedArguments, entrypointPackedArgs], authWitnesses: [authWitness], diff --git a/yarn-project/foundation/src/abi/decoder.ts b/yarn-project/foundation/src/abi/decoder.ts index c98bac63823..361525fea7a 100644 --- a/yarn-project/foundation/src/abi/decoder.ts +++ b/yarn-project/foundation/src/abi/decoder.ts @@ -1,6 +1,6 @@ import { AztecAddress } from '../aztec-address/index.js'; import { type Fr } from '../fields/index.js'; -import { type ABIParameter, type ABIVariable, type AbiType, type FunctionAbi } from './abi.js'; +import { type ABIParameter, type ABIVariable, type AbiType } from './abi.js'; import { isAztecAddressStruct } from './utils.js'; /** @@ -13,7 +13,7 @@ export type DecodedReturn = bigint | boolean | AztecAddress | DecodedReturn[] | * Missing support for integer and string. */ class ReturnValuesDecoder { - constructor(private artifact: FunctionAbi, private flattened: Fr[]) {} + constructor(private returnTypes: AbiType[], private flattened: Fr[]) {} /** * Decodes a single return value from field to the given type. @@ -80,13 +80,13 @@ class ReturnValuesDecoder { * @returns The decoded return values. */ public decode(): DecodedReturn { - if (this.artifact.returnTypes.length > 1) { + if (this.returnTypes.length > 1) { throw new Error('Multiple return values not supported'); } - if (this.artifact.returnTypes.length === 0) { + if (this.returnTypes.length === 0) { return []; } - return this.decodeReturn(this.artifact.returnTypes[0]); + return this.decodeReturn(this.returnTypes[0]); } } @@ -96,8 +96,8 @@ class ReturnValuesDecoder { * @param returnValues - The decoded return values. * @returns */ -export function decodeReturnValues(abi: FunctionAbi, returnValues: Fr[]) { - return new ReturnValuesDecoder(abi, returnValues.slice()).decode(); +export function decodeReturnValues(returnTypes: AbiType[], returnValues: Fr[]) { + return new ReturnValuesDecoder(returnTypes, returnValues.slice()).decode(); } /** diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 253759a0e27..00edcbe689a 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -26,7 +26,6 @@ import { AztecAddress, CallRequest, type CompleteAddress, - FunctionData, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, type PartialAddress, type PrivateKernelTailCircuitPublicInputs, @@ -426,9 +425,6 @@ export class PXEService implements PXE { simulatePublic: boolean, msgSender: AztecAddress | undefined = undefined, ): Promise { - if (!txRequest.functionData.isPrivate) { - throw new Error(`Public entrypoints are not allowed`); - } return await this.jobQueue.put(async () => { const timer = new Timer(); const simulatedTx = await this.#simulateAndProve(txRequest, msgSender); @@ -518,10 +514,13 @@ export class PXEService implements PXE { } return { + name: functionDao.name, args: encodeArguments(functionDao, args), - functionData: FunctionData.fromAbi(functionDao), + selector: FunctionSelector.fromNameAndParameters(functionDao.name, functionDao.parameters), + type: functionDao.functionType, to, isStatic: functionDao.isStatic, + returnTypes: functionDao.returnTypes, }; } @@ -550,14 +549,10 @@ export class PXEService implements PXE { */ async #getSimulationParameters(execRequest: FunctionCall | TxExecutionRequest) { const contractAddress = (execRequest as FunctionCall).to ?? (execRequest as TxExecutionRequest).origin; - const functionArtifact = await this.contractDataOracle.getFunctionArtifact( - contractAddress, - execRequest.functionData.selector, - ); - const debug = await this.contractDataOracle.getFunctionDebugMetadata( - contractAddress, - execRequest.functionData.selector, - ); + const functionSelector = + (execRequest as FunctionCall).selector ?? (execRequest as TxExecutionRequest).functionSelector; + const functionArtifact = await this.contractDataOracle.getFunctionArtifact(contractAddress, functionSelector); + const debug = await this.contractDataOracle.getFunctionDebugMetadata(contractAddress, functionSelector); return { contractAddress, diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts index 6d7422be7b4..fae3b3ca4bd 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts @@ -9,13 +9,15 @@ import { AztecAddress, CompleteAddress, Fr, - FunctionData, + FunctionSelector, INITIAL_L2_BLOCK_NUM, Point, PublicKeys, TxContext, getContractClassFromArtifact, } from '@aztec/circuits.js'; +import { FunctionType } from '@aztec/foundation/abi'; +import { makeFunctionCall } from '@aztec/simulator'; export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => { describe(testName, () => { @@ -126,23 +128,6 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => await expect(pxe.registerContract({ instance, artifact })).rejects.toThrow(/Artifact does not match/i); }); - it('throws when simulating a tx targeting public entrypoint', async () => { - const functionData = FunctionData.empty(); - functionData.isPrivate = false; - const txExecutionRequest = TxExecutionRequest.from({ - origin: AztecAddress.random(), - firstCallArgsHash: new Fr(0), - functionData, - txContext: TxContext.empty(), - argsOfCalls: [], - authWitnesses: [], - }); - - await expect(async () => await pxe.proveTx(txExecutionRequest, false)).rejects.toThrow( - 'Public entrypoints are not allowed', - ); - }); - // Note: Not testing a successful run of `proveTx`, `sendTx`, `getTxReceipt` and `simulateUnconstrained` here as it requires // a larger setup and it's sufficiently tested in the e2e tests. diff --git a/yarn-project/sequencer-client/src/tx_validator/phases_validator.test.ts b/yarn-project/sequencer-client/src/tx_validator/phases_validator.test.ts index 4b852cc5c93..452c716712d 100644 --- a/yarn-project/sequencer-client/src/tx_validator/phases_validator.test.ts +++ b/yarn-project/sequencer-client/src/tx_validator/phases_validator.test.ts @@ -117,12 +117,12 @@ describe('PhasesTxValidator', () => { ): { address: AztecAddress; selector: FunctionSelector } { const fn = tx.enqueuedPublicFunctionCalls.at(-1 * index - 1)!; fn.contractAddress = address ?? fn.contractAddress; - fn.functionData.selector = selector; + fn.functionSelector = selector; tx.data.forPublic!.endNonRevertibleData.publicCallStack[index] = fn.toCallRequest(); return { address: fn.contractAddress, - selector: fn.functionData.selector, + selector: fn.functionSelector, }; } }); diff --git a/yarn-project/sequencer-client/src/tx_validator/phases_validator.ts b/yarn-project/sequencer-client/src/tx_validator/phases_validator.ts index da118a5d976..25a9a8b1134 100644 --- a/yarn-project/sequencer-client/src/tx_validator/phases_validator.ts +++ b/yarn-project/sequencer-client/src/tx_validator/phases_validator.ts @@ -37,7 +37,7 @@ export class PhasesTxValidator implements TxValidator { this.#log.warn( `Rejecting tx ${Tx.getHash(tx)} because it calls setup function not on allow list: ${ setupFn.contractAddress - }:${setupFn.functionData.selector}`, + }:${setupFn.functionSelector}`, ); return false; @@ -52,10 +52,7 @@ export class PhasesTxValidator implements TxValidator { return true; } - const { - contractAddress, - functionData: { selector }, - } = publicCall; + const { contractAddress, functionSelector } = publicCall; // do these checks first since they don't require the contract class for (const entry of allowList) { @@ -63,7 +60,7 @@ export class PhasesTxValidator implements TxValidator { continue; } - if (contractAddress.equals(entry.address) && entry.selector.equals(selector)) { + if (contractAddress.equals(entry.address) && entry.selector.equals(functionSelector)) { return true; } } @@ -78,7 +75,7 @@ export class PhasesTxValidator implements TxValidator { continue; } - if (contractClass.contractClassId.equals(entry.classId) && entry.selector.equals(selector)) { + if (contractClass.contractClassId.equals(entry.classId) && entry.selector.equals(functionSelector)) { return true; } } diff --git a/yarn-project/simulator/src/acvm/serialize.ts b/yarn-project/simulator/src/acvm/serialize.ts index 0e3a1656d05..c3232565436 100644 --- a/yarn-project/simulator/src/acvm/serialize.ts +++ b/yarn-project/simulator/src/acvm/serialize.ts @@ -55,7 +55,7 @@ export function toACVMField( export function toAcvmEnqueuePublicFunctionResult(item: PublicCallRequest): ACVMField[] { const fields = [ item.contractAddress.toField(), - ...item.functionData.toFields(), + item.functionSelector.toField(), ...item.callContext.toFields(), item.getArgsHash(), ]; diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 148cddf078e..be573601a31 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -10,7 +10,6 @@ import { } from '@aztec/circuit-types'; import { CallContext, - FunctionData, FunctionSelector, type Header, PrivateContextInputs, @@ -468,7 +467,6 @@ export class ClientExecutionContext extends ViewDataOracle { isStaticCall = isStaticCall || this.callContext.isStaticCall; const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector); - const targetFunctionData = FunctionData.fromAbi(targetArtifact); const derivedTxContext = this.txContext.clone(); @@ -498,7 +496,7 @@ export class ClientExecutionContext extends ViewDataOracle { context, targetArtifact, targetContractAddress, - targetFunctionData, + functionSelector, ); if (isStaticCall) { @@ -552,7 +550,7 @@ export class ClientExecutionContext extends ViewDataOracle { args, callContext: derivedCallContext, parentCallContext: this.callContext, - functionData: FunctionData.fromAbi(targetArtifact), + functionSelector, contractAddress: targetContractAddress, }); } diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 7ac7ffae681..abba4d5b019 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -12,7 +12,6 @@ import { AppendOnlyTreeSnapshot, CallContext, CompleteAddress, - FunctionData, GasSettings, GeneratorIndex, type GrumpkinPrivateKey, @@ -113,11 +112,10 @@ describe('Private Execution test suite', () => { txContext?: Partial>; }) => { const packedArguments = PackedValues.fromValues(encodeArguments(artifact, args)); - const functionData = FunctionData.fromAbi(artifact); const txRequest = TxExecutionRequest.from({ origin: contractAddress, firstCallArgsHash: packedArguments.hash, - functionData, + functionSelector: FunctionSelector.fromNameAndParameters(artifact.name, artifact.parameters), txContext: TxContext.from({ ...txContextFields, ...txContext }), argsOfCalls: [packedArguments], authWitnesses: [], @@ -832,11 +830,14 @@ describe('Private Execution test suite', () => { }); // Alter function data to match the manipulated oracle - const functionData = FunctionData.fromAbi(childContractArtifact); + const functionSelector = FunctionSelector.fromNameAndParameters( + childContractArtifact.name, + childContractArtifact.parameters, + ); const publicCallRequest = PublicCallRequest.from({ contractAddress: childAddress, - functionData: functionData, + functionSelector, args: [new Fr(42n)], callContext: CallContext.from({ msgSender: parentAddress, @@ -871,7 +872,9 @@ describe('Private Execution test suite', () => { oracle.getFunctionArtifact.mockImplementation(() => Promise.resolve({ ...teardown })); const result = await runSimulator({ artifact: entrypoint }); expect(result.publicTeardownFunctionCall.isEmpty()).toBeFalsy(); - expect(result.publicTeardownFunctionCall.functionData).toEqual(FunctionData.fromAbi(teardown)); + expect(result.publicTeardownFunctionCall.functionSelector).toEqual( + FunctionSelector.fromNameAndParameters(teardown.name, teardown.parameters), + ); }); }); diff --git a/yarn-project/simulator/src/client/private_execution.ts b/yarn-project/simulator/src/client/private_execution.ts index f774bf9208f..4b27d4c8cdf 100644 --- a/yarn-project/simulator/src/client/private_execution.ts +++ b/yarn-project/simulator/src/client/private_execution.ts @@ -1,5 +1,5 @@ -import { type FunctionData, PrivateCallStackItem, PrivateCircuitPublicInputs } from '@aztec/circuits.js'; -import { type FunctionArtifact } from '@aztec/foundation/abi'; +import { FunctionData, PrivateCallStackItem, PrivateCircuitPublicInputs } from '@aztec/circuits.js'; +import type { FunctionArtifact, FunctionSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -17,10 +17,9 @@ export async function executePrivateFunction( context: ClientExecutionContext, artifact: FunctionArtifact, contractAddress: AztecAddress, - functionData: FunctionData, + functionSelector: FunctionSelector, log = createDebugLogger('aztec:simulator:secret_execution'), ): Promise { - const functionSelector = functionData.selector; log.verbose(`Executing external function ${contractAddress}:${functionSelector}(${artifact.name})`); const acir = artifact.bytecode; const initialWitness = context.getInitialWitness(artifact); @@ -47,7 +46,11 @@ export async function executePrivateFunction( const encryptedLogs = context.getEncryptedLogs(); const unencryptedLogs = context.getUnencryptedLogs(); - const callStackItem = new PrivateCallStackItem(contractAddress, functionData, publicInputs); + const callStackItem = new PrivateCallStackItem( + contractAddress, + new FunctionData(functionSelector, true), + publicInputs, + ); const rawReturnValues = await context.unpackReturns(publicInputs.returnsHash); diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index 842abf65891..44ce65225af 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -1,5 +1,5 @@ import { type AztecNode, type FunctionCall, type Note, type TxExecutionRequest } from '@aztec/circuit-types'; -import { CallContext, FunctionData } from '@aztec/circuits.js'; +import { CallContext } from '@aztec/circuits.js'; import { type ArrayType, type FunctionArtifact, @@ -110,7 +110,7 @@ export class AcirSimulator { context, entryPointArtifact, contractAddress, - request.functionData, + request.functionSelector, ); return executionResult; } catch (err) { @@ -141,7 +141,7 @@ export class AcirSimulator { context, entryPointArtifact, contractAddress, - request.functionData, + request.selector, request.args, ); } catch (err) { @@ -193,10 +193,13 @@ export class AcirSimulator { const extendedNoteItems = note.items.concat(Array(maxNoteFields - note.items.length).fill(Fr.ZERO)); const execRequest: FunctionCall = { + name: artifact.name, to: contractAddress, - functionData: FunctionData.empty(), + selector: FunctionSelector.empty(), + type: FunctionType.UNCONSTRAINED, isStatic: artifact.isStatic, args: encodeArguments(artifact, [contractAddress, nonce, storageSlot, noteTypeId, extendedNoteItems]), + returnTypes: artifact.returnTypes, }; const [innerNoteHash, uniqueNoteHash, siloedNoteHash, innerNullifier] = (await this.runUnconstrained( diff --git a/yarn-project/simulator/src/client/unconstrained_execution.test.ts b/yarn-project/simulator/src/client/unconstrained_execution.test.ts index 362ef413501..788da2d37bc 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.test.ts @@ -1,6 +1,6 @@ import { type AztecNode, type FunctionCall, Note } from '@aztec/circuit-types'; -import { CompleteAddress, FunctionData, Header } from '@aztec/circuits.js'; -import { FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; +import { CompleteAddress, Header } from '@aztec/circuits.js'; +import { FunctionSelector, FunctionType, encodeArguments } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { StatefulTestContractArtifact } from '@aztec/noir-contracts.js/StatefulTest'; @@ -62,10 +62,13 @@ describe('Unconstrained Execution test suite', () => { ); const execRequest: FunctionCall = { + name: artifact.name, to: contractAddress, - functionData: new FunctionData(FunctionSelector.empty(), /*isPrivate=*/ true), + selector: FunctionSelector.empty(), + type: FunctionType.UNCONSTRAINED, isStatic: false, args: encodeArguments(artifact, [owner]), + returnTypes: artifact.returnTypes, }; const result = await acirSimulator.runUnconstrained(execRequest, artifact, AztecAddress.random()); diff --git a/yarn-project/simulator/src/client/unconstrained_execution.ts b/yarn-project/simulator/src/client/unconstrained_execution.ts index 9b42a556009..39f130c63c1 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.ts @@ -1,5 +1,9 @@ -import { type FunctionData } from '@aztec/circuits.js'; -import { type DecodedReturn, type FunctionArtifact, decodeReturnValues } from '@aztec/foundation/abi'; +import { + type DecodedReturn, + type FunctionArtifact, + type FunctionSelector, + decodeReturnValues, +} from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { type Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -18,11 +22,10 @@ export async function executeUnconstrainedFunction( oracle: ViewDataOracle, artifact: FunctionArtifact, contractAddress: AztecAddress, - functionData: FunctionData, + functionSelector: FunctionSelector, args: Fr[], log = createDebugLogger('aztec:simulator:unconstrained_execution'), ): Promise { - const functionSelector = functionData.selector; log.verbose(`Executing unconstrained function ${contractAddress}:${functionSelector}(${artifact.name})`); const acir = artifact.bytecode; @@ -45,6 +48,6 @@ export async function executeUnconstrainedFunction( }); const returnWitness = witnessMapToFields(acirExecutionResult.returnWitness); - return decodeReturnValues(artifact, returnWitness); + return decodeReturnValues(artifact.returnTypes, returnWitness); } // docs:end:execute_unconstrained_function diff --git a/yarn-project/simulator/src/mocks/fixtures.ts b/yarn-project/simulator/src/mocks/fixtures.ts index ffe0997606a..3ca3cf6aa5b 100644 --- a/yarn-project/simulator/src/mocks/fixtures.ts +++ b/yarn-project/simulator/src/mocks/fixtures.ts @@ -6,13 +6,13 @@ import { CallRequest, type ContractStorageUpdateRequest, Fr, - FunctionData, Gas, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, type PrivateKernelTailCircuitPublicInputs, type PublicCallRequest, } from '@aztec/circuits.js'; import { makeAztecAddress, makeSelector } from '@aztec/circuits.js/testing'; +import { FunctionType } from '@aztec/foundation/abi'; import { padArrayEnd } from '@aztec/foundation/collection'; import { type PublicExecution, type PublicExecutionResult } from '../public/execution.js'; @@ -65,9 +65,9 @@ export class PublicExecutionResultBuilder { revertReason?: SimulationError; }) { const builder = new PublicExecutionResultBuilder({ - callContext: new CallContext(from, tx.to, tx.functionData.selector, false, false, 0), + callContext: new CallContext(from, tx.to, tx.selector, false, false, 0), contractAddress: tx.to, - functionData: tx.functionData, + functionSelector: tx.selector, args: tx.args, }); @@ -130,11 +130,14 @@ export class PublicExecutionResultBuilder { } export const makeFunctionCall = ( + name = 'function', to = makeAztecAddress(30), selector = makeSelector(5), + type = FunctionType.PUBLIC, args = new Array(ARGS_LENGTH).fill(Fr.ZERO), isStatic = false, -) => ({ to, functionData: new FunctionData(selector, /*isPrivate=*/ false), args, isStatic }); + returnTypes = [], +) => ({ name, to, selector, type, args, isStatic, returnTypes }); export function addKernelPublicCallStack( kernelOutput: PrivateKernelTailCircuitPublicInputs, diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index 2d066f8345f..c29244a1959 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -13,6 +13,7 @@ import { ContractStorageRead, ContractStorageUpdateRequest, Fr, + FunctionData, Gas, type GlobalVariables, type Header, @@ -283,7 +284,7 @@ export abstract class AbstractPhaseManager { // Sanity check for a current upstream assumption. // Consumers of the result seem to expect "reverted <=> revertReason !== undefined". - const functionSelector = result.execution.functionData.selector.toString(); + const functionSelector = result.execution.functionSelector.toString(); if (result.reverted && !result.revertReason) { throw new Error( `Simulation of ${result.execution.contractAddress.toString()}:${functionSelector} reverted with no reason.`, @@ -474,7 +475,7 @@ export abstract class AbstractPhaseManager { return new PublicCallStackItem( result.execution.contractAddress, - result.execution.functionData, + new FunctionData(result.execution.functionSelector, false), publicCircuitPublicInputs, isExecutionRequest, ); diff --git a/yarn-project/simulator/src/public/avm_executor.test.ts b/yarn-project/simulator/src/public/avm_executor.test.ts index a5aad855eb4..fa14d8fb372 100644 --- a/yarn-project/simulator/src/public/avm_executor.test.ts +++ b/yarn-project/simulator/src/public/avm_executor.test.ts @@ -1,4 +1,4 @@ -import { AztecAddress, CallContext, FunctionData, FunctionSelector, type Header } from '@aztec/circuits.js'; +import { AztecAddress, CallContext, FunctionSelector, type Header } from '@aztec/circuits.js'; import { makeHeader } from '@aztec/circuits.js/testing'; import { randomInt } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; @@ -42,7 +42,6 @@ describe('AVM WitGen and Proof Generation', () => { const bytecode = addArtifact.bytecode; publicContracts.getBytecode.mockResolvedValue(bytecode); - const functionData = FunctionData.fromAbi(addArtifact); const args: Fr[] = [new Fr(99), new Fr(12)]; // We call initContext here to load up a AvmExecutionEnvironment that prepends the calldata with the function selector // and the args hash. In reality, we should simulate here and get this from the output of the simulation call. @@ -50,7 +49,7 @@ describe('AVM WitGen and Proof Generation', () => { const context = initContext({ env: initExecutionEnvironment({ calldata: args }) }); const execution: PublicExecution = { contractAddress, - functionData, + functionSelector: FunctionSelector.fromNameAndParameters(addArtifact.name, addArtifact.parameters), args: context.environment.calldata, callContext, }; diff --git a/yarn-project/simulator/src/public/execution.ts b/yarn-project/simulator/src/public/execution.ts index ff63cd0138b..80be913f99a 100644 --- a/yarn-project/simulator/src/public/execution.ts +++ b/yarn-project/simulator/src/public/execution.ts @@ -78,7 +78,7 @@ export interface PublicExecutionResult { /** * The execution of a public function. */ -export type PublicExecution = Pick; +export type PublicExecution = Pick; /** * Returns if the input is a public execution result and not just a public execution. diff --git a/yarn-project/simulator/src/public/executor.ts b/yarn-project/simulator/src/public/executor.ts index cd6b8a0ef80..20c5d2ca970 100644 --- a/yarn-project/simulator/src/public/executor.ts +++ b/yarn-project/simulator/src/public/executor.ts @@ -44,11 +44,11 @@ export async function executePublicFunction( ): Promise { const bytecode = await context.contractsDb.getBytecode( context.execution.contractAddress, - context.execution.functionData.selector, + context.execution.functionSelector, ); if (!bytecode) { throw new Error( - `Bytecode not found for ${context.execution.contractAddress}:${context.execution.functionData.selector}`, + `Bytecode not found for ${context.execution.contractAddress}:${context.execution.functionSelector}`, ); } @@ -68,7 +68,7 @@ async function executeTopLevelPublicFunctionAvm( bytecode: Buffer, ): Promise { const address = executionContext.execution.contractAddress; - const selector = executionContext.execution.functionData.selector; + const selector = executionContext.execution.functionSelector; const startGas = executionContext.availableGas; const log = createDebugLogger('aztec:simulator:public_execution'); log.verbose(`[AVM] Executing public external function ${address.toString()}:${selector}.`); @@ -131,10 +131,9 @@ async function executePublicFunctionAcvm( nested: boolean, ): Promise { const execution = context.execution; - const { contractAddress, functionData } = execution; - const selector = functionData.selector; + const { contractAddress, functionSelector } = execution; const log = createDebugLogger('aztec:simulator:public_execution'); - log.verbose(`[ACVM] Executing public external function ${contractAddress.toString()}:${selector}.`); + log.verbose(`[ACVM] Executing public external function ${contractAddress.toString()}:${functionSelector}.`); const initialWitness = context.getInitialWitness(); const acvmCallback = new Oracle(context); @@ -154,7 +153,7 @@ async function executePublicFunctionAcvm( err.message, { contractAddress, - functionSelector: selector, + functionSelector, }, extractCallStack(err), { cause: err }, @@ -357,9 +356,9 @@ export class PublicExecutor { const bytecodePath = path.join(artifactsPath, 'avm_bytecode.bin'); const proofPath = path.join(artifactsPath, 'proof'); - const { args, functionData, contractAddress } = avmExecution; - let bytecode = await this.contractsDb.getBytecode(contractAddress, functionData.selector); - assert(!!bytecode, `Bytecode not found for ${contractAddress}:${functionData.selector}`); + const { args, functionSelector, contractAddress } = avmExecution; + let bytecode = await this.contractsDb.getBytecode(contractAddress, functionSelector); + assert(!!bytecode, `Bytecode not found for ${contractAddress}:${functionSelector}`); // This should be removed once we do bytecode validation. bytecode = await decompressBytecodeIfCompressed(bytecode!); // Write call data and bytecode to files. diff --git a/yarn-project/simulator/src/public/index.test.ts b/yarn-project/simulator/src/public/index.test.ts index 1386a3dd23f..e5775a70938 100644 --- a/yarn-project/simulator/src/public/index.test.ts +++ b/yarn-project/simulator/src/public/index.test.ts @@ -2,7 +2,6 @@ import { type L1ToL2Message, NullifierMembershipWitness, SiblingPath } from '@az import { AppendOnlyTreeSnapshot, CallContext, - FunctionData, Gas, GasFees, GlobalVariables, @@ -114,7 +113,7 @@ describe.skip('ACIR public execution simulator', () => { describe('mint', () => { it('should run the mint_public function', async () => { const mintArtifact = TokenContractArtifact.functions.find(f => f.name === 'mint_public')!; - const functionData = FunctionData.fromAbi(mintArtifact); + const functionSelector = FunctionSelector.fromNameAndParameters(mintArtifact.name, mintArtifact.parameters); const mintAmount = 140n; const args = encodeArguments(mintArtifact, [recipient, mintAmount]); @@ -133,7 +132,7 @@ describe.skip('ACIR public execution simulator', () => { .mockResolvedValueOnce(previousBalance) // reading user's balance .mockResolvedValueOnce(previousTotalSupply); // reading total supply - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; const result = await simulate(execution, globalVariables); expect(result.revertReason).toBeUndefined(); @@ -175,7 +174,7 @@ describe.skip('ACIR public execution simulator', () => { describe('transfer', () => { let transferArtifact: FunctionArtifact; - let functionData: FunctionData; + let functionSelector: FunctionSelector; let args: Fr[]; let sender: AztecAddress; let callContext: CallContext; @@ -185,7 +184,7 @@ describe.skip('ACIR public execution simulator', () => { beforeEach(() => { transferArtifact = TokenContractArtifact.functions.find(f => f.name === 'transfer_public')!; - functionData = new FunctionData(FunctionSelector.empty(), /*isPrivate=*/ false); + functionSelector = FunctionSelector.fromNameAndParameters(transferArtifact.name, transferArtifact.parameters); sender = AztecAddress.random(); args = encodeArguments(transferArtifact, [sender, recipient, 140n, 0n]); @@ -195,7 +194,7 @@ describe.skip('ACIR public execution simulator', () => { publicContracts.getBytecode.mockResolvedValue(transferArtifact.bytecode); - execution = { contractAddress, functionData, args, callContext }; + execution = { contractAddress, functionSelector, args, callContext }; }); const mockStore = (senderBalance: Fr, recipientBalance: Fr) => { @@ -256,7 +255,7 @@ describe.skip('ACIR public execution simulator', () => { let childContractAddress: AztecAddress; let parentEntryPointFn: FunctionArtifact; let parentEntryPointFnSelector: FunctionSelector; - let functionData: FunctionData; + let functionSelector: FunctionSelector; let callContext: CallContext; beforeEach(() => { @@ -266,7 +265,6 @@ describe.skip('ACIR public execution simulator', () => { parentEntryPointFn.name, parentEntryPointFn.parameters, ); - functionData = new FunctionData(parentEntryPointFnSelector, /*isPrivate=*/ false); childContractAddress = AztecAddress.random(); callContext = makeCallContext(parentContractAddress); }, 10000); @@ -289,7 +287,12 @@ describe.skip('ACIR public execution simulator', () => { } }); - const execution: PublicExecution = { contractAddress: parentContractAddress, functionData, args, callContext }; + const execution: PublicExecution = { + contractAddress: parentContractAddress, + functionSelector, + args, + callContext, + }; const globalVariables = new GlobalVariables( new Fr(69), new Fr(420), @@ -331,7 +334,12 @@ describe.skip('ACIR public execution simulator', () => { } }); - const execution: PublicExecution = { contractAddress: parentContractAddress, functionData, args, callContext }; + const execution: PublicExecution = { + contractAddress: parentContractAddress, + functionSelector, + args, + callContext, + }; const result = await simulate(execution, globalVariables); const childExecutionResult = result.nestedExecutions[0]; @@ -348,14 +356,14 @@ describe.skip('ACIR public execution simulator', () => { describe('Public -> Private / Cross Chain messaging', () => { let contractAddress: AztecAddress; - let functionData: FunctionData; + let functionSelector: FunctionSelector; let amount: Fr; let params: Fr[]; beforeEach(async () => { contractAddress = AztecAddress.random(); await mockInitializationNullifierCallback(contractAddress); - functionData = new FunctionData(FunctionSelector.empty(), /*isPrivate=*/ false); + functionSelector = FunctionSelector.empty(); amount = new Fr(1); params = [amount, new Fr(1)]; }); @@ -372,7 +380,7 @@ describe.skip('ACIR public execution simulator', () => { // mock initial balance to be greater than the amount being sent publicState.storageRead.mockResolvedValue(amount); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; const result = await simulate(execution, globalVariables); // Assert the note hash was created @@ -395,7 +403,7 @@ describe.skip('ACIR public execution simulator', () => { publicContracts.getBytecode.mockResolvedValue(createL2ToL1MessagePublicArtifact.bytecode); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; const result = await simulate(execution, globalVariables); // Assert the l2 to l1 message was created @@ -416,7 +424,7 @@ describe.skip('ACIR public execution simulator', () => { publicContracts.getBytecode.mockResolvedValue(createNullifierPublicArtifact.bytecode); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; const result = await simulate(execution, globalVariables); expect(result.newNullifiers).toEqual([expect.objectContaining({ value: nullifier })]); @@ -513,7 +521,7 @@ describe.skip('ACIR public execution simulator', () => { mockOracles(); globalVariables = computeGlobalVariables(); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); const result = await simulate(execution, globalVariables); expect(result.newNullifiers.length).toEqual(1); @@ -530,7 +538,7 @@ describe.skip('ACIR public execution simulator', () => { // Prepare the state globalVariables = computeGlobalVariables(); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); const { revertReason, reverted } = await simulate(execution, globalVariables); expect(reverted).toBe(true); @@ -547,7 +555,7 @@ describe.skip('ACIR public execution simulator', () => { mockOracles(); globalVariables = computeGlobalVariables(); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); const { revertReason, reverted } = await simulate(execution, globalVariables); expect(reverted).toBe(true); @@ -564,7 +572,7 @@ describe.skip('ACIR public execution simulator', () => { mockOracles(); globalVariables = computeGlobalVariables(); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); const { revertReason, reverted } = await simulate(execution, globalVariables); expect(reverted).toBe(true); @@ -581,7 +589,7 @@ describe.skip('ACIR public execution simulator', () => { globalVariables = computeGlobalVariables(); globalVariables.chainId = Fr.random(); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); const { revertReason, reverted } = await simulate(execution, globalVariables); expect(reverted).toBe(true); @@ -598,7 +606,7 @@ describe.skip('ACIR public execution simulator', () => { globalVariables = computeGlobalVariables(); globalVariables.version = Fr.random(); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); const { revertReason, reverted } = await simulate(execution, globalVariables); expect(reverted).toBe(true); @@ -616,7 +624,7 @@ describe.skip('ACIR public execution simulator', () => { mockOracles(); globalVariables = computeGlobalVariables(); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); const { revertReason, reverted } = await simulate(execution, globalVariables); expect(reverted).toBe(true); @@ -634,7 +642,7 @@ describe.skip('ACIR public execution simulator', () => { mockOracles(); globalVariables = computeGlobalVariables(); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); const { revertReason, reverted } = await simulate(execution, globalVariables); expect(reverted).toBe(true); @@ -647,7 +655,7 @@ describe.skip('ACIR public execution simulator', () => { let contractAddress: AztecAddress; let callContext: CallContext; let assertGlobalVarsArtifact: FunctionArtifact; - let functionData: FunctionData; + let functionSelector: FunctionSelector; const modifyGlobalVariables = (globalVariables: GlobalVariables, propertyIndex: number, value: any) => { const globalVariablesFields = globalVariables.toFields(); @@ -659,7 +667,10 @@ describe.skip('ACIR public execution simulator', () => { contractAddress = AztecAddress.random(); callContext = makeCallContext(AztecAddress.random()); assertGlobalVarsArtifact = TestContractArtifact.functions.find(f => f.name === 'assert_public_global_vars')!; - functionData = FunctionData.fromAbi(assertGlobalVarsArtifact); + functionSelector = FunctionSelector.fromNameAndParameters( + assertGlobalVarsArtifact.name, + assertGlobalVarsArtifact.parameters, + ); }); beforeEach(() => { @@ -693,7 +704,7 @@ describe.skip('ACIR public execution simulator', () => { args = encodeArguments(assertGlobalVarsArtifact, rawArgs); } - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); expect(() => simulate(execution, globalVariables)).not.toThrow(); @@ -709,7 +720,7 @@ describe.skip('ACIR public execution simulator', () => { args = encodeArguments(assertGlobalVarsArtifact, rawArgs); } - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); const { revertReason, reverted } = await simulate(execution, globalVariables); @@ -725,13 +736,16 @@ describe.skip('ACIR public execution simulator', () => { let contractAddress: AztecAddress; let callContext: CallContext; let assertHeaderPublicArtifact: FunctionArtifact; - let functionData: FunctionData; + let functionSelector: FunctionSelector; beforeAll(() => { contractAddress = AztecAddress.random(); callContext = makeCallContext(AztecAddress.random()); assertHeaderPublicArtifact = TestContractArtifact.functions.find(f => f.name === 'assert_header_public')!; - functionData = FunctionData.fromAbi(assertHeaderPublicArtifact); + functionSelector = FunctionSelector.fromNameAndParameters( + assertHeaderPublicArtifact.name, + assertHeaderPublicArtifact.parameters, + ); }); beforeEach(() => { @@ -741,7 +755,7 @@ describe.skip('ACIR public execution simulator', () => { it('Header is correctly set', () => { const args = encodeArguments(assertHeaderPublicArtifact, [header.hash()]); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); expect(() => simulate(execution, globalVariables)).not.toThrow(); @@ -751,7 +765,7 @@ describe.skip('ACIR public execution simulator', () => { const unexpectedHeaderHash = Fr.random(); const args = encodeArguments(assertHeaderPublicArtifact, [unexpectedHeaderHash]); - const execution: PublicExecution = { contractAddress, functionData, args, callContext }; + const execution: PublicExecution = { contractAddress, functionSelector, args, callContext }; executor = new PublicExecutor(publicState, publicContracts, commitmentsDb, header); const { revertReason, reverted } = await simulate(execution, globalVariables); diff --git a/yarn-project/simulator/src/public/public_execution_context.ts b/yarn-project/simulator/src/public/public_execution_context.ts index e8c6fefcda8..77ef60aa8cd 100644 --- a/yarn-project/simulator/src/public/public_execution_context.ts +++ b/yarn-project/simulator/src/public/public_execution_context.ts @@ -1,7 +1,6 @@ import { UnencryptedFunctionL2Logs, type UnencryptedL2Log } from '@aztec/circuit-types'; import { CallContext, - FunctionData, type FunctionSelector, type Gas, type GasSettings, @@ -212,7 +211,6 @@ export class PublicExecutionContext extends TypedOracle { `Public function call: addr=${targetContractAddress} selector=${functionSelector} args=${args.join(',')}`, ); - const functionData = new FunctionData(functionSelector, /*isPrivate=*/ false); const callContext = CallContext.from({ msgSender: isDelegateCall ? this.execution.callContext.msgSender : this.execution.contractAddress, storageContractAddress: isDelegateCall ? this.execution.contractAddress : targetContractAddress, @@ -225,7 +223,7 @@ export class PublicExecutionContext extends TypedOracle { const nestedExecution: PublicExecution = { args, contractAddress: targetContractAddress, - functionData, + functionSelector, callContext, }; diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 24bf534abd8..ceab32c5b83 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -392,7 +392,7 @@ describe('public_processor', () => { nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ from: publicCallRequests[1].contractAddress, - tx: makeFunctionCall(baseContractAddress, makeSelector(5)), + tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 13, baseContractAddress), new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 14, baseContractAddress), @@ -400,7 +400,7 @@ describe('public_processor', () => { }).build(), PublicExecutionResultBuilder.fromFunctionCall({ from: publicCallRequests[1].contractAddress, - tx: makeFunctionCall(baseContractAddress, makeSelector(5)), + tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), revertReason: new SimulationError('Simulation Failed', []), }).build(), ], @@ -412,7 +412,7 @@ describe('public_processor', () => { nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ from: teardown.contractAddress, - tx: makeFunctionCall(baseContractAddress, makeSelector(5)), + tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 12, baseContractAddress), ], @@ -497,7 +497,7 @@ describe('public_processor', () => { nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ from: publicCallRequests[1].contractAddress, - tx: makeFunctionCall(baseContractAddress, makeSelector(5)), + tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 12, baseContractAddress), new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 13, baseContractAddress), @@ -505,7 +505,7 @@ describe('public_processor', () => { }).build(), PublicExecutionResultBuilder.fromFunctionCall({ from: publicCallRequests[1].contractAddress, - tx: makeFunctionCall(baseContractAddress, makeSelector(5)), + tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), revertReason: new SimulationError('Simulation Failed', []), }).build(), ], @@ -522,7 +522,7 @@ describe('public_processor', () => { nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ from: teardown.contractAddress, - tx: makeFunctionCall(baseContractAddress, makeSelector(5)), + tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 14, baseContractAddress), ], @@ -600,7 +600,7 @@ describe('public_processor', () => { nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ from: publicCallRequests[0].contractAddress, - tx: makeFunctionCall(baseContractAddress, makeSelector(5)), + tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 12, baseContractAddress), new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 13, baseContractAddress), @@ -620,12 +620,12 @@ describe('public_processor', () => { nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ from: teardown.contractAddress, - tx: makeFunctionCall(baseContractAddress, makeSelector(5)), + tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), revertReason: new SimulationError('Simulation Failed', []), }).build(teardownResultSettings), PublicExecutionResultBuilder.fromFunctionCall({ from: teardown.contractAddress, - tx: makeFunctionCall(baseContractAddress, makeSelector(5)), + tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 14, baseContractAddress), ], @@ -744,7 +744,7 @@ describe('public_processor', () => { nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ from: teardown!.contractAddress, - tx: makeFunctionCall(baseContractAddress, makeSelector(5)), + tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11, baseContractAddress), new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 12, baseContractAddress), @@ -752,7 +752,7 @@ describe('public_processor', () => { }).build({ startGasLeft: teardownGas, endGasLeft: teardownGas, transactionFee }), PublicExecutionResultBuilder.fromFunctionCall({ from: teardown!.contractAddress, - tx: makeFunctionCall(baseContractAddress, makeSelector(5)), + tx: makeFunctionCall('', baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 13, baseContractAddress), ], diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index e50040c1224..a52257beffa 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -114,7 +114,7 @@ export class PublicProcessor { txs = txs.map(tx => Tx.clone(tx)); const result: ProcessedTx[] = []; const failed: FailedTx[] = []; - const returns: NestedProcessReturnValues[] = []; + let returns: NestedProcessReturnValues[] = []; for (const tx of txs) { // only process up to the limit of the block @@ -152,7 +152,7 @@ export class PublicProcessor { await blockProver.addNewTx(processedTx); } result.push(processedTx); - returns.push(returnValues?.[0] ?? new NestedProcessReturnValues([])); + returns = returns.concat(returnValues ?? []); } catch (err: any) { const errorMessage = err instanceof Error ? err.message : 'Unknown error'; this.log.warn(`Failed to process tx ${tx.getTxHash()}: ${errorMessage} ${err?.stack}`); diff --git a/yarn-project/simulator/src/public/transitional_adaptors.ts b/yarn-project/simulator/src/public/transitional_adaptors.ts index 74e6d004788..f40b7b336d0 100644 --- a/yarn-project/simulator/src/public/transitional_adaptors.ts +++ b/yarn-project/simulator/src/public/transitional_adaptors.ts @@ -1,13 +1,6 @@ // All code in this file needs to die once the public executor is phased out in favor of the AVM. import { UnencryptedFunctionL2Logs } from '@aztec/circuit-types'; -import { - CallContext, - FunctionData, - type Gas, - type GasSettings, - type GlobalVariables, - type Header, -} from '@aztec/circuits.js'; +import { CallContext, type Gas, type GasSettings, type GlobalVariables, type Header } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { promisify } from 'util'; @@ -48,7 +41,7 @@ export function createAvmExecutionEnvironment( current.args, gasSettings, transactionFee, - current.functionData.selector, + current.functionSelector, ); } @@ -65,12 +58,11 @@ export function createPublicExecution( isStaticCall: avmEnvironment.isStaticCall, sideEffectCounter: startSideEffectCounter, }); - const functionData = new FunctionData(avmEnvironment.temporaryFunctionSelector, /*isPrivate=*/ false); const execution: PublicExecution = { contractAddress: avmEnvironment.address, callContext, args: calldata, - functionData, + functionSelector: avmEnvironment.temporaryFunctionSelector, }; return execution; } From 3a25e06023e8ddbcc98ebf6df696feaaa4c233d1 Mon Sep 17 00:00:00 2001 From: thunkar Date: Wed, 22 May 2024 14:04:43 +0000 Subject: [PATCH 2/5] leave only batched sims --- .../end-to-end/src/e2e_state_vars.test.ts | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index ff34a9980b1..a39dc693bd2 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -45,22 +45,6 @@ describe('e2e_state_vars', () => { }); it('private read of SharedImmutable', async () => { - // Initializes the shared immutable and then reads the value using an unconstrained function - // checking the return values with: - // 1. A constrained private function that reads it directly - // 2. A constrained private function that calls another private function that reads. - // The indirect, adds 1 to the point to ensure that we are returning the correct value. - - const a = await contract.methods.get_shared_immutable_constrained_private().simulate(); - const b = await contract.methods.get_shared_immutable_constrained_private_indirect().simulate(); - const c = await contract.methods.get_shared_immutable().simulate(); - - expect(a).toEqual(c); - expect(b).toEqual({ account: c.account, points: c.points + 1n }); - await contract.methods.match_shared_immutable(c.account, c.points).send().wait(); - }); - - it('private read of SharedImmutable in batches', async () => { // Reads the value using an unconstrained function checking the return values with: // 1. A constrained private function that reads it directly // 2. A constrained private function that calls another private function that reads. @@ -83,22 +67,6 @@ describe('e2e_state_vars', () => { // 2. A constrained public function that calls another public function that reads. // The indirect, adds 1 to the point to ensure that we are returning the correct value. - const a = await contract.methods.get_shared_immutable_constrained_public().simulate(); - const b = await contract.methods.get_shared_immutable_constrained_public_indirect().simulate(); - const c = await contract.methods.get_shared_immutable().simulate(); - - expect(a).toEqual(c); - expect(b).toEqual({ account: c.account, points: c.points + 1n }); - - await contract.methods.match_shared_immutable(c.account, c.points).send().wait(); - }); - - it('public read of SharedImmutable in batches', async () => { - // Reads the value using an unconstrained function checking the return values with: - // 1. A constrained public function that reads it directly - // 2. A constrained public function that calls another public function that reads. - // The indirect, adds 1 to the point to ensure that we are returning the correct value. - const [a, b, c] = await new BatchCall(wallet, [ contract.methods.get_shared_immutable_constrained_public().request(), contract.methods.get_shared_immutable_constrained_public_indirect().request(), From b61d1a2e106d61425b2d0cb45c301d3a23faf0a7 Mon Sep 17 00:00:00 2001 From: thunkar Date: Wed, 22 May 2024 14:35:25 +0000 Subject: [PATCH 3/5] constants --- l1-contracts/src/core/libraries/ConstantsGen.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 6923824f55a..760b91b4636 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -216,8 +216,7 @@ library Constants { APPEND_ONLY_TREE_SNAPSHOT_LENGTH + 4 + GLOBAL_VARIABLES_LENGTH; uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = CONSTANT_ROLLUP_DATA_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 5; - uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = - 3 + CALL_CONTEXT_LENGTH; + uint256 internal constant ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH = 3 + CALL_CONTEXT_LENGTH; uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674; uint256 internal constant NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; From e053137da1835369c00b45d907df72309e31ad08 Mon Sep 17 00:00:00 2001 From: thunkar Date: Wed, 22 May 2024 14:36:41 +0000 Subject: [PATCH 4/5] formatting fix --- yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts index fae3b3ca4bd..8a9e8bc99b3 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts @@ -1,6 +1,5 @@ import { type PXE, - TxExecutionRequest, randomContractArtifact, randomContractInstanceWithAddress, randomDeployedContract, @@ -9,15 +8,11 @@ import { AztecAddress, CompleteAddress, Fr, - FunctionSelector, INITIAL_L2_BLOCK_NUM, Point, PublicKeys, - TxContext, getContractClassFromArtifact, } from '@aztec/circuits.js'; -import { FunctionType } from '@aztec/foundation/abi'; -import { makeFunctionCall } from '@aztec/simulator'; export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => { describe(testName, () => { From 870ae480cdc94e6331f391ede4ecb3bdc764473b Mon Sep 17 00:00:00 2001 From: thunkar Date: Wed, 22 May 2024 17:46:37 +0000 Subject: [PATCH 5/5] comment --- yarn-project/circuit-types/src/tx_execution_request.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/yarn-project/circuit-types/src/tx_execution_request.ts b/yarn-project/circuit-types/src/tx_execution_request.ts index 4db2547ac79..bbef6c9cede 100644 --- a/yarn-project/circuit-types/src/tx_execution_request.ts +++ b/yarn-project/circuit-types/src/tx_execution_request.ts @@ -43,7 +43,8 @@ export class TxExecutionRequest { toTxRequest(): TxRequest { return new TxRequest( this.origin, - new FunctionData(this.functionSelector, true), + // Entrypoints must be private as as defined by the protocol. + new FunctionData(this.functionSelector, true /* isPrivate */), this.firstCallArgsHash, this.txContext, );