Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion yarn-project/simulator/src/common/debug_fn_name.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Fr } from '@aztec/foundation/fields';
import { FunctionSelector } from '@aztec/stdlib/abi';
import type { AztecAddress } from '@aztec/stdlib/aztec-address';

import type { PublicContractsDBInterface } from './db_interfaces.js';
import type { PublicContractsDBInterface } from '../public/db_interfaces.js';

export async function getPublicFunctionDebugName(
db: PublicContractsDBInterface,
Expand Down
1 change: 0 additions & 1 deletion yarn-project/simulator/src/common/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from './errors.js';
export * from './stats/index.js';
export * from './message_load_oracle_inputs.js';
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type { Note, NoteStatus } from '@aztec/stdlib/note';
import { type MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
import type { BlockHeader, TxHash } from '@aztec/stdlib/tx';

import type { MessageLoadOracleInputs } from '../../../common/message_load_oracle_inputs.js';
import type { MessageLoadOracleInputs } from '../../message_load_oracle_inputs.js';

/**
* Information about a note needed during execution.
Expand Down
46 changes: 44 additions & 2 deletions yarn-project/simulator/src/private/execution_data_provider.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/constants';
import type { Fr, Point } from '@aztec/foundation/fields';
import type {
EventSelector,
Expand All @@ -14,8 +15,8 @@ import type { NoteStatus } from '@aztec/stdlib/note';
import { type MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
import type { BlockHeader, TxHash } from '@aztec/stdlib/tx';

import type { CommitmentsDBInterface } from '../common/db_interfaces.js';
import type { NoteData } from './acvm/index.js';
import type { MessageLoadOracleInputs } from './message_load_oracle_inputs.js';

/**
* Error thrown when a contract is not found in the database.
Expand All @@ -38,7 +39,7 @@ export class ContractClassNotFoundError extends Error {
/**
* The interface for the data layer required to perform private and utility execution.
*/
export interface ExecutionDataProvider extends CommitmentsDBInterface {
export interface ExecutionDataProvider {
/**
* Returns a contract instance associated with an address, if available.
* @param address - Address.
Expand Down Expand Up @@ -117,6 +118,40 @@ export interface ExecutionDataProvider extends CommitmentsDBInterface {
*/
getNullifierIndex(nullifier: Fr): Promise<bigint | undefined>;

/**
* Gets the index of a nullifier in the nullifier tree.
* @param nullifier - The nullifier.
* @returns - The index of the nullifier. Undefined if it does not exist in the tree.
*/
getNullifierIndex(nullifier: Fr): Promise<bigint | undefined>;

/**
* Returns a nullifier membership witness for the given nullifier or undefined if not found.
* REFACTOR: Same as getL1ToL2MembershipWitness, can be combined with aztec-node method that does almost the same thing.
* @param nullifier - Nullifier we're looking for.
*/
getNullifierMembershipWitnessAtLatestBlock(nullifier: Fr): Promise<NullifierMembershipWitness | undefined>;

/**
* Fetches a message from the db, given its key.
* @param contractAddress - Address of a contract by which the message was emitted.
* @param messageHash - Hash of the message.
* @param secret - Secret used to compute a nullifier.
* @dev Contract address and secret are only used to compute the nullifier to get non-nullified messages
* @returns The l1 to l2 membership witness (index of message in the tree and sibling path).
*/
getL1ToL2MembershipWitness(
contractAddress: AztecAddress,
messageHash: Fr,
secret: Fr,
): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>>;

/**
* @param leafIndex the leaf to look up
* @returns The l1 to l2 leaf message hash or undefined if not found.
*/
getL1ToL2MessageHash(leafIndex: bigint): Promise<Fr | undefined>;

/**
* Retrieve the databases view of the Block Header object.
* This structure is fed into the circuits simulator and is used to prove against certain historical roots.
Expand Down Expand Up @@ -263,6 +298,13 @@ export interface ExecutionDataProvider extends CommitmentsDBInterface {
recipient: AztecAddress,
): Promise<void>;

/**
* Gets note hash in the note hash tree at the given leaf index.
* @param leafIndex - the leaf to look up.
* @returns - The note hash at that index. Undefined if leaf index is not found.
*/
getNoteHash(leafIndex: bigint): Promise<Fr | undefined>;

/**
* Searches for a log with the corresponding `tag` and returns it along with contextual transaction information.
* Returns null if no such log exists, and throws if more than one exists.
Expand Down
1 change: 1 addition & 0 deletions yarn-project/simulator/src/private/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export { extractCallStack } from './acvm/acvm.js';
export { type NoteData, TypedOracle } from './acvm/oracle/typed_oracle.js';
export { Oracle } from './acvm/oracle/oracle.js';
export { HashedValuesCache } from './hashed_values_cache.js';
export { MessageLoadOracleInputs } from './message_load_oracle_inputs.js';
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ import { jest } from '@jest/globals';
import { Matcher, type MatcherCreator, type MockProxy, mock } from 'jest-mock-extended';
import { toFunctionSelector } from 'viem';

import { MessageLoadOracleInputs } from '../common/message_load_oracle_inputs.js';
import { buildL1ToL2Message } from '../test/utils.js';
import type { ExecutionDataProvider } from './execution_data_provider.js';
import { MessageLoadOracleInputs } from './message_load_oracle_inputs.js';
import { WASMSimulator } from './providers/acvm_wasm.js';
import { AcirSimulator } from './simulator.js';

Expand Down
22 changes: 11 additions & 11 deletions yarn-project/simulator/src/public/avm/avm_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ import {
import { encodeToBytecode } from './serialization/bytecode_serialization.js';
import { Opcode } from './serialization/instruction_serialization.js';
import {
mockCheckNullifierExists,
mockGetBytecodeCommitment,
mockGetContractClass,
mockGetContractInstance,
mockGetNullifierIndex,
mockL1ToL2MessageExists,
mockNoteHashCount,
mockNoteHashExists,
Expand Down Expand Up @@ -626,7 +626,7 @@ describe('AVM simulator: transpiled Noir contracts', () => {
const bytecode = getAvmTestContractBytecode('nullifier_exists');

if (exists) {
mockGetNullifierIndex(treesDB, leafIndex, siloedNullifier0);
mockCheckNullifierExists(treesDB, true, siloedNullifier0);
}

const results = await new AvmSimulator(context).executeBytecode(bytecode);
Expand Down Expand Up @@ -892,9 +892,9 @@ describe('AVM simulator: transpiled Noir contracts', () => {
mockGetContractInstance(contractsDB, contractInstanceWithAddress);
mockGetContractInstance(contractsDB, contractInstanceWithAddress);
mockGetContractInstance(contractsDB, contractInstanceWithAddress);
mockGetNullifierIndex(treesDB, await siloAddress(contractInstanceWithAddress.address));
mockGetNullifierIndex(treesDB, await siloAddress(contractInstanceWithAddress.address));
mockGetNullifierIndex(treesDB, await siloAddress(contractInstanceWithAddress.address));
mockCheckNullifierExists(treesDB, true, await siloAddress(contractInstanceWithAddress.address));
mockCheckNullifierExists(treesDB, true, await siloAddress(contractInstanceWithAddress.address));
mockCheckNullifierExists(treesDB, true, await siloAddress(contractInstanceWithAddress.address));

const bytecode = getAvmTestContractBytecode('test_get_contract_instance');

Expand Down Expand Up @@ -930,7 +930,7 @@ describe('AVM simulator: transpiled Noir contracts', () => {
mockGetBytecodeCommitment(contractsDB, await computePublicBytecodeCommitment(contractClass.packedBytecode));
const contractInstance = await makeContractInstanceFromClassId(contractClass.id);
mockGetContractInstance(contractsDB, contractInstance);
mockGetNullifierIndex(treesDB, await siloAddress(contractInstance.address));
mockCheckNullifierExists(treesDB, true, await siloAddress(contractInstance.address));

const nestedTrace = mock<PublicSideEffectTraceInterface>();
mockTraceFork(trace, nestedTrace);
Expand All @@ -951,7 +951,7 @@ describe('AVM simulator: transpiled Noir contracts', () => {
const contractInstance = await makeContractInstanceFromClassId(contractClass.id);
mockGetContractInstance(contractsDB, contractInstance);
mockGetBytecodeCommitment(contractsDB, await computePublicBytecodeCommitment(contractClass.packedBytecode));
mockGetNullifierIndex(treesDB, await siloAddress(contractInstance.address));
mockCheckNullifierExists(treesDB, true, await siloAddress(contractInstance.address));

const nestedTrace = mock<PublicSideEffectTraceInterface>();
mockTraceFork(trace, nestedTrace);
Expand All @@ -975,7 +975,7 @@ describe('AVM simulator: transpiled Noir contracts', () => {
mockGetBytecodeCommitment(contractsDB, await computePublicBytecodeCommitment(contractClass.packedBytecode));
const contractInstance = await makeContractInstanceFromClassId(contractClass.id);
mockGetContractInstance(contractsDB, contractInstance);
mockGetNullifierIndex(treesDB, await siloAddress(contractInstance.address));
mockCheckNullifierExists(treesDB, true, await siloAddress(contractInstance.address));

mockTraceFork(trace);

Expand All @@ -994,7 +994,7 @@ describe('AVM simulator: transpiled Noir contracts', () => {
mockGetBytecodeCommitment(contractsDB, await computePublicBytecodeCommitment(contractClass.packedBytecode));
const contractInstance = await makeContractInstanceFromClassId(contractClass.id);
mockGetContractInstance(contractsDB, contractInstance);
mockGetNullifierIndex(treesDB, await siloAddress(contractInstance.address));
mockCheckNullifierExists(treesDB, true, await siloAddress(contractInstance.address));

const nestedTrace = mock<PublicSideEffectTraceInterface>();
mockTraceFork(trace, nestedTrace);
Expand All @@ -1021,7 +1021,7 @@ describe('AVM simulator: transpiled Noir contracts', () => {
mockGetBytecodeCommitment(contractsDB, await computePublicBytecodeCommitment(contractClass.packedBytecode));
const contractInstance = await makeContractInstanceFromClassId(contractClass.id);
mockGetContractInstance(contractsDB, contractInstance);
mockGetNullifierIndex(treesDB, await siloAddress(contractInstance.address));
mockCheckNullifierExists(treesDB, true, await siloAddress(contractInstance.address));

mockTraceFork(trace);

Expand All @@ -1043,7 +1043,7 @@ describe('AVM simulator: transpiled Noir contracts', () => {
mockGetBytecodeCommitment(contractsDB, await computePublicBytecodeCommitment(contractClass.packedBytecode));
const contractInstance = await makeContractInstanceFromClassId(contractClass.id);
mockGetContractInstance(contractsDB, contractInstance);
mockGetNullifierIndex(treesDB, await siloAddress(contractInstance.address));
mockCheckNullifierExists(treesDB, true, await siloAddress(contractInstance.address));

mockTraceFork(trace);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Field, Uint8, Uint32 } from '../avm_memory_types.js';
import { InstructionExecutionError, StaticCallAlterationError } from '../errors.js';
import { initContext, initExecutionEnvironment, initPersistableStateManager } from '../fixtures/index.js';
import {
mockGetNullifierIndex,
mockCheckNullifierExists,
mockL1ToL2MessageExists,
mockNoteHashCount,
mockNoteHashExists,
Expand Down Expand Up @@ -159,7 +159,7 @@ describe('Accrued Substate', () => {
const addressOffset = 1;

if (exists) {
mockGetNullifierIndex(treesDB, leafIndex, value0);
mockCheckNullifierExists(treesDB, true, value0);
}

context.machineState.memory.set(value0Offset, new Field(value0)); // nullifier
Expand Down Expand Up @@ -210,7 +210,7 @@ describe('Accrued Substate', () => {
});

it('Nullifier collision reverts (nullifier exists in host state)', async () => {
mockGetNullifierIndex(treesDB, leafIndex); // db will say that nullifier already exists
mockCheckNullifierExists(treesDB, true, leafIndex);
context.machineState.memory.set(value0Offset, new Field(value0));
await expect(new EmitNullifier(/*indirect=*/ 0, /*offset=*/ value0Offset).execute(context)).rejects.toThrow(
new InstructionExecutionError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import { initContext, initPersistableStateManager } from '../fixtures/index.js';
import { encodeToBytecode } from '../serialization/bytecode_serialization.js';
import { Opcode } from '../serialization/instruction_serialization.js';
import {
mockCheckNullifierExists,
mockGetBytecodeCommitment,
mockGetContractClass,
mockGetContractInstance,
mockGetNullifierIndex,
mockTraceFork,
} from '../test_utils.js';
import { EnvironmentVariable, GetEnvVar } from './environment_getters.js';
Expand Down Expand Up @@ -128,7 +128,7 @@ describe('External Calls', () => {
mockGetBytecodeCommitment(contractsDB, await computePublicBytecodeCommitment(contractClass.packedBytecode));
const contractInstance = await makeContractInstanceFromClassId(contractClass.id);
mockGetContractInstance(contractsDB, contractInstance);
mockGetNullifierIndex(treesDB, contractInstance.address.toField());
mockCheckNullifierExists(treesDB, true, contractInstance.address.toField());

const { l2GasLeft: initialL2Gas, daGasLeft: initialDaGas } = context.machineState;

Expand Down Expand Up @@ -174,14 +174,14 @@ describe('External Calls', () => {
new Set(/*indirect=*/ 0, /*dstOffset=*/ 1, TypeTag.UINT32, 1).as(Opcode.SET_8, Set.wireFormat8),
new Return(/*indirect=*/ 0, /*retOffset=*/ 0, /*size=*/ 1),
]);
mockGetNullifierIndex(treesDB, addr);
mockCheckNullifierExists(treesDB, true, addr);

const contractClass = await makeContractClassPublic(0, otherContextInstructionsBytecode);
mockGetContractClass(contractsDB, contractClass);
mockGetBytecodeCommitment(contractsDB, await computePublicBytecodeCommitment(contractClass.packedBytecode));
const contractInstance = await makeContractInstanceFromClassId(contractClass.id);
mockGetContractInstance(contractsDB, contractInstance);
mockGetNullifierIndex(treesDB, contractInstance.address.toField());
mockCheckNullifierExists(treesDB, true, contractInstance.address.toField());

const { l2GasLeft: initialL2Gas, daGasLeft: initialDaGas } = context.machineState;

Expand Down Expand Up @@ -252,7 +252,7 @@ describe('External Calls', () => {
];

const otherContextInstructionsBytecode = encodeToBytecode(otherContextInstructions);
mockGetNullifierIndex(treesDB, addr.toFr());
mockCheckNullifierExists(treesDB, true, addr.toFr());

const contractClass = await makeContractClassPublic(0, otherContextInstructionsBytecode);
mockGetContractClass(contractsDB, contractClass);
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/simulator/src/public/avm/test_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export function mockNoteHashExists(worldStateDB: PublicTreesDB, _leafIndex: Fr,
});
}

export function mockGetNullifierIndex(worldStateDB: PublicTreesDB, leafIndex: Fr, _ignoredValue?: Fr) {
(worldStateDB as jest.Mocked<PublicTreesDB>).getNullifierIndex.mockResolvedValue(leafIndex.toBigInt());
export function mockCheckNullifierExists(worldStateDB: PublicTreesDB, exists: boolean, _ignoredValue?: Fr) {
(worldStateDB as jest.Mocked<PublicTreesDB>).checkNullifierExists.mockResolvedValue(exists);
}

export function mockL1ToL2MessageExists(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import type { L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/constants';
import type { Fr } from '@aztec/foundation/fields';
import type { FunctionSelector } from '@aztec/stdlib/abi';
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
import type { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
import type { NullifierMembershipWitness } from '@aztec/stdlib/trees';

import type { MessageLoadOracleInputs } from './message_load_oracle_inputs.js';

/**
* Database interface for providing access to public state.
Expand Down Expand Up @@ -62,47 +58,3 @@ export interface PublicContractsDBInterface {
*/
getDebugFunctionName(contractAddress: AztecAddress, selector: FunctionSelector): Promise<string | undefined>;
}

/** Database interface for providing access to note hash tree, l1 to l2 message tree, and nullifier tree. */
export interface CommitmentsDBInterface {
/**
* Fetches a message from the db, given its key.
* @param contractAddress - Address of a contract by which the message was emitted.
* @param messageHash - Hash of the message.
* @param secret - Secret used to compute a nullifier.
* @dev Contract address and secret are only used to compute the nullifier to get non-nullified messages
* @returns The l1 to l2 membership witness (index of message in the tree and sibling path).
*/
getL1ToL2MembershipWitness(
contractAddress: AztecAddress,
messageHash: Fr,
secret: Fr,
): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>>;

/**
* @param leafIndex the leaf to look up
* @returns The l1 to l2 leaf message hash or undefined if not found.
*/
getL1ToL2MessageHash(leafIndex: bigint): Promise<Fr | undefined>;

/**
* Gets note hash in the note hash tree at the given leaf index.
* @param leafIndex - the leaf to look up.
* @returns - The note hash at that index. Undefined if leaf index is not found.
*/
getNoteHash(leafIndex: bigint): Promise<Fr | undefined>;

/**
* Gets the index of a nullifier in the nullifier tree.
* @param nullifier - The nullifier.
* @returns - The index of the nullifier. Undefined if it does not exist in the tree.
*/
getNullifierIndex(nullifier: Fr): Promise<bigint | undefined>;

/**
* Returns a nullifier membership witness for the given nullifier or undefined if not found.
* REFACTOR: Same as getL1ToL2MembershipWitness, can be combined with aztec-node method that does almost the same thing.
* @param nullifier - Nullifier we're looking for.
*/
getNullifierMembershipWitnessAtLatestBlock(nullifier: Fr): Promise<NullifierMembershipWitness | undefined>;
}
2 changes: 1 addition & 1 deletion yarn-project/simulator/src/public/hinting_db_sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import {

import { strict as assert } from 'assert';

import type { PublicContractsDBInterface } from '../common/db_interfaces.js';
import type { PublicContractsDBInterface } from './db_interfaces.js';
import { PublicTreesDB } from './public_db_sources.js';

/**
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/simulator/src/public/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from '../common/db_interfaces.js';
export * from './db_interfaces.js';
export * from './public_tx_simulator/index.js';
export * from './public_db_sources.js';
export { PublicProcessor, PublicProcessorFactory } from './public_processor/public_processor.js';
Expand Down
Loading