diff --git a/barretenberg/cpp/src/barretenberg/vm2/common/avm_inputs.hpp b/barretenberg/cpp/src/barretenberg/vm2/common/avm_inputs.hpp index 3fbc3d72c9ac..8904b52e53ac 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/common/avm_inputs.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/common/avm_inputs.hpp @@ -147,6 +147,19 @@ template struct GetLeafPreimageHint { MSGPACK_FIELDS(hintKey, index, leaf, nextIndex, nextValue); }; +struct GetLeafValueHint { + AppendOnlyTreeSnapshot hintKey; + // params + world_state::MerkleTreeId treeId; + uint64_t index; + // return + FF value; + + bool operator==(const GetLeafValueHint& other) const = default; + + MSGPACK_FIELDS(hintKey, treeId, index, value); +}; + //////////////////////////////////////////////////////////////////////////// // Hints (other) //////////////////////////////////////////////////////////////////////////// @@ -174,6 +187,8 @@ struct ExecutionHints { std::vector getSiblingPathHints; std::vector getPreviousValueIndexHints; std::vector> getLeafPreimageHintsPublicDataTree; + std::vector> getLeafPreimageHintsNullifierTree; + std::vector getLeafValueHints; bool operator==(const ExecutionHints& other) const = default; @@ -183,7 +198,9 @@ struct ExecutionHints { bytecodeCommitments, getSiblingPathHints, getPreviousValueIndexHints, - getLeafPreimageHintsPublicDataTree); + getLeafPreimageHintsPublicDataTree, + getLeafPreimageHintsNullifierTree, + getLeafValueHints); }; //////////////////////////////////////////////////////////////////////////// diff --git a/barretenberg/cpp/src/barretenberg/vm2/common/avm_inputs.testdata.bin b/barretenberg/cpp/src/barretenberg/vm2/common/avm_inputs.testdata.bin index 9924c420ed1d..3bae0a36cc56 100644 Binary files a/barretenberg/cpp/src/barretenberg/vm2/common/avm_inputs.testdata.bin and b/barretenberg/cpp/src/barretenberg/vm2/common/avm_inputs.testdata.bin differ diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/db_interfaces.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/db_interfaces.hpp index 163f93d1f290..b264f7d6b9c0 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/db_interfaces.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/db_interfaces.hpp @@ -3,6 +3,7 @@ #include #include "barretenberg/crypto/merkle_tree/hash_path.hpp" +#include "barretenberg/crypto/merkle_tree/indexed_tree/indexed_leaf.hpp" #include "barretenberg/crypto/merkle_tree/response.hpp" #include "barretenberg/crypto/merkle_tree/types.hpp" #include "barretenberg/vm2/common/avm_inputs.hpp" @@ -30,9 +31,13 @@ class LowLevelMerkleDBInterface { crypto::merkle_tree::index_t leaf_index) const = 0; virtual crypto::merkle_tree::GetLowIndexedLeafResponse get_low_indexed_leaf(world_state::MerkleTreeId tree_id, const FF& value) const = 0; + // Returns the value if it exists, 0 otherwise. + virtual FF get_leaf_value(world_state::MerkleTreeId tree_id, crypto::merkle_tree::index_t leaf_index) const = 0; // We don't template the preimage methods because templated methods cannot be virtual. virtual crypto::merkle_tree::IndexedLeaf get_leaf_preimage_public_data_tree(crypto::merkle_tree::index_t leaf_index) const = 0; + virtual crypto::merkle_tree::IndexedLeaf get_leaf_preimage_nullifier_tree( + crypto::merkle_tree::index_t leaf_index) const = 0; }; // High level access to a merkle db. In general these will be constrained. diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/raw_data_dbs.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/raw_data_dbs.cpp index f6ac295482df..185a9aefc258 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/raw_data_dbs.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/raw_data_dbs.cpp @@ -5,6 +5,7 @@ #include #include "barretenberg/common/log.hpp" +#include "barretenberg/crypto/merkle_tree/indexed_tree/indexed_leaf.hpp" #include "barretenberg/vm2/simulation/lib/contract_crypto.hpp" namespace bb::avm2::simulation { @@ -101,7 +102,11 @@ HintedRawMerkleDB::HintedRawMerkleDB(const ExecutionHints& hints, const TreeSnap "\n * get_previous_value_index hints: ", hints.getPreviousValueIndexHints.size(), "\n * get_leaf_preimage hints_public_data_tree: ", - hints.getLeafPreimageHintsPublicDataTree.size()); + hints.getLeafPreimageHintsPublicDataTree.size(), + "\n * get_leaf_preimage hints_nullifier_tree: ", + hints.getLeafPreimageHintsNullifierTree.size(), + "\n * get_leaf_value_hints: ", + hints.getLeafValueHints.size()); debug("Initializing HintedRawMerkleDB with snapshots...", "\n * nullifierTree: ", tree_roots.nullifierTree.root, @@ -149,6 +154,20 @@ HintedRawMerkleDB::HintedRawMerkleDB(const ExecutionHints& hints, const TreeSnap /*nextVal=*/get_leaf_preimage_hint.nextValue, }; } + + for (const auto& get_leaf_preimage_hint : hints.getLeafPreimageHintsNullifierTree) { + GetLeafPreimageKey key = { get_leaf_preimage_hint.hintKey, get_leaf_preimage_hint.index }; + get_leaf_preimage_hints_nullifier_tree[key] = { + /*val=*/get_leaf_preimage_hint.leaf, + /*nextIdx=*/get_leaf_preimage_hint.nextIndex, + /*nextVal=*/get_leaf_preimage_hint.nextValue, + }; + } + + for (const auto& get_leaf_value_hint : hints.getLeafValueHints) { + GetLeafValueKey key = { get_leaf_value_hint.hintKey, get_leaf_value_hint.treeId, get_leaf_value_hint.index }; + get_leaf_value_hints[key] = get_leaf_value_hint.value; + } } const AppendOnlyTreeSnapshot& HintedRawMerkleDB::get_tree_info(world_state::MerkleTreeId tree_id) const @@ -207,6 +226,14 @@ crypto::merkle_tree::GetLowIndexedLeafResponse HintedRawMerkleDB::get_low_indexe return it->second; } +FF HintedRawMerkleDB::get_leaf_value(world_state::MerkleTreeId tree_id, crypto::merkle_tree::index_t leaf_index) const +{ + auto tree_info = get_tree_info(tree_id); + GetLeafValueKey key = { tree_info, tree_id, leaf_index }; + auto it = get_leaf_value_hints.find(key); + return it == get_leaf_value_hints.end() ? 0 : it->second; +} + crypto::merkle_tree::IndexedLeaf HintedRawMerkleDB:: get_leaf_preimage_public_data_tree(crypto::merkle_tree::index_t leaf_index) const { @@ -225,4 +252,22 @@ crypto::merkle_tree::IndexedLeaf Hinte return it->second; } +crypto::merkle_tree::IndexedLeaf HintedRawMerkleDB:: + get_leaf_preimage_nullifier_tree(crypto::merkle_tree::index_t leaf_index) const +{ + auto tree_info = get_tree_info(world_state::MerkleTreeId::NULLIFIER_TREE); + GetLeafPreimageKey key = { tree_info, leaf_index }; + auto it = get_leaf_preimage_hints_nullifier_tree.find(key); + if (it == get_leaf_preimage_hints_nullifier_tree.end()) { + throw std::runtime_error(format("Leaf preimage (NULLIFIER_TREE) not found for key (root: ", + tree_info.root, + ", size: ", + tree_info.nextAvailableLeafIndex, + ", leaf_index: ", + leaf_index, + ")")); + } + return it->second; +} + } // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/raw_data_dbs.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/raw_data_dbs.hpp index e26f8f474e78..59d7c4c9ed34 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/raw_data_dbs.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/raw_data_dbs.hpp @@ -2,6 +2,7 @@ #include "barretenberg/common/utils.hpp" #include "barretenberg/crypto/merkle_tree/hash_path.hpp" +#include "barretenberg/crypto/merkle_tree/indexed_tree/indexed_leaf.hpp" #include "barretenberg/vm2/common/avm_inputs.hpp" #include "barretenberg/vm2/common/aztec_types.hpp" #include "barretenberg/vm2/common/field.hpp" @@ -40,8 +41,11 @@ class HintedRawMerkleDB final : public LowLevelMerkleDBInterface { crypto::merkle_tree::index_t leaf_index) const override; crypto::merkle_tree::GetLowIndexedLeafResponse get_low_indexed_leaf(world_state::MerkleTreeId tree_id, const FF& value) const override; + FF get_leaf_value(world_state::MerkleTreeId tree_id, crypto::merkle_tree::index_t leaf_index) const override; crypto::merkle_tree::IndexedLeaf get_leaf_preimage_public_data_tree( crypto::merkle_tree::index_t leaf_index) const override; + crypto::merkle_tree::IndexedLeaf get_leaf_preimage_nullifier_tree( + crypto::merkle_tree::index_t leaf_index) const override; private: TreeSnapshots tree_roots; @@ -55,6 +59,11 @@ class HintedRawMerkleDB final : public LowLevelMerkleDBInterface { using GetLeafPreimageKey = utils::HashableTuple; unordered_flat_map> get_leaf_preimage_hints_public_data_tree; + unordered_flat_map> + get_leaf_preimage_hints_nullifier_tree; + using GetLeafValueKey = + utils::HashableTuple; + unordered_flat_map get_leaf_value_hints; const AppendOnlyTreeSnapshot& get_tree_info(world_state::MerkleTreeId tree_id) const; }; diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_dbs.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_dbs.hpp index 718dd097cf73..b1ea741ca0d2 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_dbs.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_dbs.hpp @@ -32,10 +32,18 @@ class MockLowLevelMerkleDB : public LowLevelMerkleDBInterface { get_low_indexed_leaf, (world_state::MerkleTreeId tree_id, const FF& value), (const, override)); + MOCK_METHOD(FF, + get_leaf_value, + (world_state::MerkleTreeId tree_id, crypto::merkle_tree::index_t leaf_index), + (const, override)); MOCK_METHOD(crypto::merkle_tree::IndexedLeaf, get_leaf_preimage_public_data_tree, (crypto::merkle_tree::index_t leaf_index), (const, override)); + MOCK_METHOD(crypto::merkle_tree::IndexedLeaf, + get_leaf_preimage_nullifier_tree, + (crypto::merkle_tree::index_t leaf_index), + (const, override)); }; class MockHighLevelMerkleDB : public HighLevelMerkleDBInterface { diff --git a/yarn-project/simulator/src/public/hinting_db_sources.ts b/yarn-project/simulator/src/public/hinting_db_sources.ts index d65521b25d34..a25abd612f6f 100644 --- a/yarn-project/simulator/src/public/hinting_db_sources.ts +++ b/yarn-project/simulator/src/public/hinting_db_sources.ts @@ -7,7 +7,9 @@ import { AvmContractClassHint, AvmContractInstanceHint, type AvmExecutionHints, + AvmGetLeafPreimageHintNullifierTree, AvmGetLeafPreimageHintPublicDataTree, + AvmGetLeafValueHint, AvmGetPreviousValueIndexHint, AvmGetSiblingPathHint, } from '@aztec/stdlib/avm'; @@ -17,11 +19,15 @@ import { AppendOnlyTreeSnapshot, type IndexedTreeId, MerkleTreeId, + type MerkleTreeLeafType, + NullifierLeaf, PublicDataTreeLeaf, type SequentialInsertionResult, getTreeName, } from '@aztec/stdlib/trees'; +import { strict as assert } from 'assert'; + import type { PublicContractsDBInterface } from '../common/db_interfaces.js'; import { PublicTreesDB } from './public_db_sources.js'; @@ -147,8 +153,20 @@ export class HintingPublicTreesDB extends PublicTreesDB { ), ); break; + case MerkleTreeId.NULLIFIER_TREE: + this.hints.getLeafPreimageHintsNullifierTree.push( + new AvmGetLeafPreimageHintNullifierTree( + key, + index, + preimage.asLeaf() as NullifierLeaf, + preimage.getNextIndex(), + new Fr(preimage.getNextKey()), + ), + ); + break; default: - HintingPublicTreesDB.log.debug(`getLeafPreimage not hinted for tree ${getTreeName(treeId)} yet!`); + // Use getLeafValue for the other trees. + throw new Error('getLeafPreimage only supported for PublicDataTree and NullifierTree!'); break; } } @@ -156,6 +174,23 @@ export class HintingPublicTreesDB extends PublicTreesDB { return preimage; } + public override async getLeafValue( + treeId: ID, + index: bigint, + ): Promise | undefined> { + // Use getLeafPreimage for PublicDataTree and NullifierTree. + assert(treeId == MerkleTreeId.NOTE_HASH_TREE || treeId == MerkleTreeId.L1_TO_L2_MESSAGE_TREE); + + const value = await super.getLeafValue(treeId, index); + if (value) { + const key = await this.getHintKey(treeId); + // We can cast to Fr because we know the type of the tree. + this.hints.getLeafValueHints.push(new AvmGetLeafValueHint(key, treeId, index, value as Fr)); + } + + return value; + } + // State modification. public override async sequentialInsert( treeId: ID, diff --git a/yarn-project/simulator/src/public/public_db_sources.ts b/yarn-project/simulator/src/public/public_db_sources.ts index a7623b8bd0da..4c6ce5eb743b 100644 --- a/yarn-project/simulator/src/public/public_db_sources.ts +++ b/yarn-project/simulator/src/public/public_db_sources.ts @@ -437,6 +437,9 @@ export class PublicTreesDB extends ForwardMerkleTree implements PublicStateDBInt public async getL1ToL2LeafValue(leafIndex: bigint): Promise { const timer = new Timer(); const leafValue = await this.getLeafValue(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, leafIndex); + // TODO(fcarreiro): We need this for the hints. Might move it to the hinting layer. + await this.getSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, leafIndex); + this.logger.debug(`[DB] Fetched L1 to L2 message leaf value`, { eventName: 'public-db-access', duration: timer.ms(), @@ -448,6 +451,9 @@ export class PublicTreesDB extends ForwardMerkleTree implements PublicStateDBInt public async getNoteHash(leafIndex: bigint): Promise { const timer = new Timer(); const leafValue = await this.getLeafValue(MerkleTreeId.NOTE_HASH_TREE, leafIndex); + // TODO(fcarreiro): We need this for the hints. Might move it to the hinting layer. + await this.getSiblingPath(MerkleTreeId.NOTE_HASH_TREE, leafIndex); + this.logger.debug(`[DB] Fetched note hash leaf value`, { eventName: 'public-db-access', duration: timer.ms(), @@ -458,7 +464,16 @@ export class PublicTreesDB extends ForwardMerkleTree implements PublicStateDBInt public async getNullifierIndex(nullifier: Fr): Promise { const timer = new Timer(); - const index = (await this.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]))[0]; + const lowLeafResult = await this.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt()); + if (!lowLeafResult) { + throw new Error('Low leaf not found'); + } + // TODO(fcarreiro): We need this for the hints. Might move it to the hinting layer. + await this.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, lowLeafResult.index); + // TODO(fcarreiro): We need this for the hints. Might move it to the hinting layer. + await this.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, lowLeafResult.index); + const index = lowLeafResult.alreadyPresent ? lowLeafResult.index : undefined; + this.logger.debug(`[DB] Fetched nullifier index`, { eventName: 'public-db-access', duration: timer.ms(), diff --git a/yarn-project/stdlib/src/avm/avm.ts b/yarn-project/stdlib/src/avm/avm.ts index 41bac0ed980f..8f07cf83fb1b 100644 --- a/yarn-project/stdlib/src/avm/avm.ts +++ b/yarn-project/stdlib/src/avm/avm.ts @@ -9,6 +9,7 @@ import { AztecAddress } from '../aztec-address/index.js'; import { PublicKeys } from '../keys/public_keys.js'; import { AppendOnlyTreeSnapshot } from '../trees/append_only_tree_snapshot.js'; import type { MerkleTreeId } from '../trees/merkle_tree_id.js'; +import { NullifierLeaf } from '../trees/nullifier_leaf.js'; import { PublicDataTreeLeaf } from '../trees/public_data_leaf.js'; import { AvmCircuitPublicInputs } from './avm_circuit_public_inputs.js'; import { serializeWithMessagePack } from './message_pack.js'; @@ -186,7 +187,33 @@ function AvmGetLeafPreimageHintFactory(klass: { }; } +// Note: only supported for PUBLIC_DATA_TREE and NULLIFIER_TREE. export class AvmGetLeafPreimageHintPublicDataTree extends AvmGetLeafPreimageHintFactory(PublicDataTreeLeaf) {} +export class AvmGetLeafPreimageHintNullifierTree extends AvmGetLeafPreimageHintFactory(NullifierLeaf) {} + +// Hint for MerkleTreeDB.getLeafValue. +// Note: only supported for NOTE_HASH_TREE and L1_TO_L2_MESSAGE_TREE. +export class AvmGetLeafValueHint { + constructor( + public readonly hintKey: AppendOnlyTreeSnapshot, + // params + public readonly treeId: MerkleTreeId, + public readonly index: bigint, + // return + public readonly value: Fr, + ) {} + + static get schema() { + return z + .object({ + hintKey: AppendOnlyTreeSnapshot.schema, + treeId: z.number().int().nonnegative(), + index: schemas.BigInt, + value: schemas.Fr, + }) + .transform(({ hintKey, treeId, index, value }) => new AvmGetLeafValueHint(hintKey, treeId, index, value)); + } +} //////////////////////////////////////////////////////////////////////////// // Hints (other) @@ -225,6 +252,8 @@ export class AvmExecutionHints { public readonly getSiblingPathHints: AvmGetSiblingPathHint[] = [], public readonly getPreviousValueIndexHints: AvmGetPreviousValueIndexHint[] = [], public readonly getLeafPreimageHintsPublicDataTree: AvmGetLeafPreimageHintPublicDataTree[] = [], + public readonly getLeafPreimageHintsNullifierTree: AvmGetLeafPreimageHintNullifierTree[] = [], + public readonly getLeafValueHints: AvmGetLeafValueHint[] = [], ) {} static empty() { @@ -241,6 +270,8 @@ export class AvmExecutionHints { getSiblingPathHints: AvmGetSiblingPathHint.schema.array(), getPreviousValueIndexHints: AvmGetPreviousValueIndexHint.schema.array(), getLeafPreimageHintsPublicDataTree: AvmGetLeafPreimageHintPublicDataTree.schema.array(), + getLeafPreimageHintsNullifierTree: AvmGetLeafPreimageHintNullifierTree.schema.array(), + getLeafValueHints: AvmGetLeafValueHint.schema.array(), }) .transform( ({ @@ -251,6 +282,8 @@ export class AvmExecutionHints { getSiblingPathHints, getPreviousValueIndexHints, getLeafPreimageHintsPublicDataTree, + getLeafPreimageHintsNullifierTree, + getLeafValueHints, }) => new AvmExecutionHints( enqueuedCalls, @@ -260,6 +293,8 @@ export class AvmExecutionHints { getSiblingPathHints, getPreviousValueIndexHints, getLeafPreimageHintsPublicDataTree, + getLeafPreimageHintsNullifierTree, + getLeafValueHints, ), ); } diff --git a/yarn-project/stdlib/src/tests/factories.ts b/yarn-project/stdlib/src/tests/factories.ts index 2bbdaf151b7a..ec7aef6a33ea 100644 --- a/yarn-project/stdlib/src/tests/factories.ts +++ b/yarn-project/stdlib/src/tests/factories.ts @@ -62,7 +62,9 @@ import { AvmContractInstanceHint, AvmEnqueuedCallHint, AvmExecutionHints, + AvmGetLeafPreimageHintNullifierTree, AvmGetLeafPreimageHintPublicDataTree, + AvmGetLeafValueHint, AvmGetPreviousValueIndexHint, AvmGetSiblingPathHint, RevertCode, @@ -142,7 +144,7 @@ import { PublicTubeData } from '../rollup/public_tube_data.js'; import { RootRollupInputs, RootRollupPublicInputs } from '../rollup/root_rollup.js'; import { PrivateBaseStateDiffHints } from '../rollup/state_diff_hints.js'; import { AppendOnlyTreeSnapshot } from '../trees/append_only_tree_snapshot.js'; -import { NullifierLeafPreimage } from '../trees/nullifier_leaf.js'; +import { NullifierLeaf, NullifierLeafPreimage } from '../trees/nullifier_leaf.js'; import { PublicDataTreeLeaf, PublicDataTreeLeafPreimage } from '../trees/public_data_leaf.js'; import { BlockHeader } from '../tx/block_header.js'; import { CallContext } from '../tx/call_context.js'; @@ -988,6 +990,15 @@ export function makePublicDataTreeLeaf(seed = 0): PublicDataTreeLeaf { return new PublicDataTreeLeaf(new Fr(seed), new Fr(seed + 1)); } +/** + * Makes arbitrary nullifier leaf. + * @param seed - The seed to use for generating the nullifier leaf. + * @returns A nullifier leaf. + */ +export function makeNullifierLeaf(seed = 0): NullifierLeaf { + return new NullifierLeaf(new Fr(seed)); +} + /** * Makes arbitrary public data tree leaf preimages. * @param seed - The seed to use for generating the public data tree leaf preimage. @@ -1295,6 +1306,29 @@ export function makeAvmGetLeafPreimageHintPublicDataTree(seed = 0): AvmGetLeafPr ); } +export function makeAvmGetLeafPreimageHintNullifierTree(seed = 0): AvmGetLeafPreimageHintNullifierTree { + // We want a possibly large index, but non-random. + const index = BigInt(`0x${sha256(Buffer.from(seed.toString())).toString('hex')}`) % (1n << 64n); + return new AvmGetLeafPreimageHintNullifierTree( + makeAppendOnlyTreeSnapshot(seed), + /*index=*/ index, + /*leaf=*/ makeNullifierLeaf(seed + 3), + /*nextIndex=*/ index + 1n, + /*nextValue*/ new Fr(seed + 0x500), + ); +} + +export function makeAvmGetLeafValueHint(seed = 0): AvmGetLeafValueHint { + // We want a possibly large index, but non-random. + const index = BigInt(`0x${sha256(Buffer.from(seed.toString())).toString('hex')}`) % (1n << 64n); + return new AvmGetLeafValueHint( + makeAppendOnlyTreeSnapshot(seed), + /*treeId=*/ (seed + 1) % 5, + /*index=*/ index, + /*value=*/ new Fr(seed + 3), + ); +} + /** * Makes arbitrary AvmContractInstanceHint. * @param seed - The seed to use for generating the state reference. @@ -1361,11 +1395,13 @@ export async function makeAvmExecutionHints( bytecodeCommitments: await makeArrayAsync(baseLength + 5, makeAvmBytecodeCommitmentHint, seed + 0x4900), getSiblingPathHints: makeArray(baseLength + 5, makeAvmGetSiblingPathHint, seed + 0x4b00), getPreviousValueIndexHints: makeArray(baseLength + 5, makeAvmGetPreviousValueIndexHint, seed + 0x4d00), - getLeafPreimageHintPublicDataTrees: makeArray( + getLeafPreimageHintPublicDataTree: makeArray( baseLength + 5, makeAvmGetLeafPreimageHintPublicDataTree, seed + 0x4f00, ), + getLeafPreimageHintNullifierTree: makeArray(baseLength + 5, makeAvmGetLeafPreimageHintNullifierTree, seed + 0x5100), + getLeafValueHints: makeArray(baseLength + 5, makeAvmGetLeafValueHint, seed + 0x5300), ...overrides, }; @@ -1376,7 +1412,9 @@ export async function makeAvmExecutionHints( fields.bytecodeCommitments, fields.getSiblingPathHints, fields.getPreviousValueIndexHints, - fields.getLeafPreimageHintPublicDataTrees, + fields.getLeafPreimageHintPublicDataTree, + fields.getLeafPreimageHintNullifierTree, + fields.getLeafValueHints, ); } diff --git a/yarn-project/stdlib/src/trees/nullifier_leaf.ts b/yarn-project/stdlib/src/trees/nullifier_leaf.ts index 5f64514c31c6..eb93d2c69bd0 100644 --- a/yarn-project/stdlib/src/trees/nullifier_leaf.ts +++ b/yarn-project/stdlib/src/trees/nullifier_leaf.ts @@ -88,7 +88,7 @@ export class NullifierLeafPreimage implements IndexedTreeLeafPreimage { } static fromLeaf(leaf: NullifierLeaf, nextKey: bigint, nextIndex: bigint): NullifierLeafPreimage { - return new NullifierLeafPreimage(leaf.nullifier, new Fr(nextKey), nextIndex); + return new NullifierLeafPreimage(leaf.value, new Fr(nextKey), nextIndex); } static clone(preimage: NullifierLeafPreimage): NullifierLeafPreimage { @@ -104,19 +104,19 @@ export class NullifierLeaf implements IndexedTreeLeaf { /** * Nullifier value. */ - public nullifier: Fr, + public value: Fr, ) {} getKey(): bigint { - return this.nullifier.toBigInt(); + return this.value.toBigInt(); } toBuffer(): Buffer { - return this.nullifier.toBuffer(); + return this.value.toBuffer(); } isEmpty(): boolean { - return this.nullifier.isZero(); + return this.value.isZero(); } updateTo(_another: NullifierLeaf): NullifierLeaf { @@ -130,4 +130,8 @@ export class NullifierLeaf implements IndexedTreeLeaf { static fromBuffer(buf: Buffer): NullifierLeaf { return new NullifierLeaf(Fr.fromBuffer(buf)); } + + static get schema() { + return z.object({ value: schemas.Fr }).transform(({ value }) => new NullifierLeaf(value)); + } } diff --git a/yarn-project/world-state/src/native/merkle_trees_facade.ts b/yarn-project/world-state/src/native/merkle_trees_facade.ts index 1fd7db9c7ccd..0e49e2feeb6b 100644 --- a/yarn-project/world-state/src/native/merkle_trees_facade.ts +++ b/yarn-project/world-state/src/native/merkle_trees_facade.ts @@ -295,7 +295,7 @@ export function serializeLeaf(leaf: Fr | NullifierLeaf | PublicDataTreeLeaf): Se if (leaf instanceof Fr) { return leaf.toBuffer(); } else if (leaf instanceof NullifierLeaf) { - return { value: leaf.nullifier.toBuffer() }; + return { value: leaf.value.toBuffer() }; } else { return { value: leaf.value.toBuffer(), slot: leaf.slot.toBuffer() }; }