Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: tree leaf type #7443

Closed
wants to merge 2 commits into from
Closed
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
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@
"siloes",
"sload",
"snakecase",
"Snapshotted",
"solhint",
"SSTORE",
"staticcall",
Expand Down
39 changes: 20 additions & 19 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
type NullifierLeafPreimage,
type PUBLIC_DATA_TREE_HEIGHT,
type PublicDataTreeLeafPreimage,
NullifierLeaf,
} from '@aztec/circuits.js';
import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash';
import { type L1ContractAddresses, createEthereumChain } from '@aztec/ethereum';
Expand Down Expand Up @@ -181,13 +182,13 @@ export class AztecNodeService implements AztecNode {
const prover = config.disableProver
? undefined
: await TxProver.new(
config,
worldStateSynchronizer,
telemetry,
await archiver
.getBlock(-1)
.then(b => b?.header ?? worldStateSynchronizer.getCommitted().buildInitialHeader()),
);
config,
worldStateSynchronizer,
telemetry,
await archiver
.getBlock(-1)
.then(b => b?.header ?? worldStateSynchronizer.getCommitted().buildInitialHeader()),
);

if (!prover && !config.disableSequencer) {
throw new Error("Can't start a sequencer without a prover");
Expand All @@ -197,16 +198,16 @@ export class AztecNodeService implements AztecNode {
const sequencer = config.disableSequencer
? undefined
: await SequencerClient.new(
config,
p2pClient,
worldStateSynchronizer,
archiver,
archiver,
archiver,
prover!,
simulationProvider,
telemetry,
);
config,
p2pClient,
worldStateSynchronizer,
archiver,
archiver,
archiver,
prover!,
simulationProvider,
telemetry,
);

return new AztecNodeService(
config,
Expand Down Expand Up @@ -423,7 +424,7 @@ export class AztecNodeService implements AztecNode {
leafValue: Fr,
): Promise<bigint | undefined> {
const committedDb = await this.#getWorldState(blockNumber);
return committedDb.findLeafIndex(treeId, leafValue.toBuffer());
return committedDb.findLeafIndex(treeId, leafValue);
}

/**
Expand Down Expand Up @@ -611,7 +612,7 @@ export class AztecNodeService implements AztecNode {
nullifier: Fr,
): Promise<NullifierMembershipWitness | undefined> {
const db = await this.#getWorldState(blockNumber);
const index = await db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
const index = await db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, new NullifierLeaf(nullifier));
if (!index) {
return undefined;
}
Expand Down
10 changes: 7 additions & 3 deletions yarn-project/foundation/src/fifo/serial_queue.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isPromise } from '../promise/utils.js';
import { MemoryFifo } from './memory_fifo.js';

/**
Expand Down Expand Up @@ -56,11 +57,14 @@ export class SerialQueue {
* @param fn - The function to enqueue.
* @returns A resolution promise. Rejects if the function does, or if the function could not be enqueued.
*/
public put<T>(fn: () => Promise<T>): Promise<T> {
public put<T>(fn: () => T | Promise<T>): Promise<T> {
return new Promise((resolve, reject) => {
const accepted = this.queue.put(async () => {
try {
const res = await fn();
let res = fn();
if (isPromise(res)) {
res = await res;
}
resolve(res);
} catch (e) {
reject(e);
Expand All @@ -76,6 +80,6 @@ export class SerialQueue {
* Awaiting this ensures the queue is empty before resuming.
*/
public async syncPoint() {
await this.put(async () => {});
await this.put(async () => { });
}
}
8 changes: 8 additions & 0 deletions yarn-project/foundation/src/promise/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,11 @@ export function promiseWithResolvers<T>(): PromiseWithResolvers<T> {
reject,
};
}

/**
* Checks if the given object is a Promise.
* A weaker version of Node's util.types.isPromise that works in the browser.
*/
export function isPromise(obj: any): obj is PromiseLike<any> {
return obj && typeof obj.then === 'function';
}
23 changes: 11 additions & 12 deletions yarn-project/merkle-tree/src/interfaces/indexed_tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ export interface BatchInsertionResult<TreeHeight extends number, SubtreeSiblingP
*/
export interface IndexedTree
extends MerkleTree<Buffer>,
TreeSnapshotBuilder<IndexedTreeSnapshot>,
Omit<AppendOnlyTree<Buffer>, keyof TreeSnapshotBuilder<TreeSnapshot<Buffer>>> {
TreeSnapshotBuilder<IndexedTreeSnapshot>,
Omit<AppendOnlyTree<Buffer>, keyof TreeSnapshotBuilder<TreeSnapshot<Buffer>>> {
/**
* Finds the index of the largest leaf whose value is less than or equal to the provided value.
* @param newValue - The new value to be inserted into the tree.
Expand All @@ -94,15 +94,15 @@ export interface IndexedTree
includeUncommitted: boolean,
):
| {
/**
* The index of the found leaf.
*/
index: bigint;
/**
* A flag indicating if the corresponding leaf's value is equal to `newValue`.
*/
alreadyPresent: boolean;
}
/**
* The index of the found leaf.
*/
index: bigint;
/**
* A flag indicating if the corresponding leaf's value is equal to `newValue`.
*/
alreadyPresent: boolean;
}
| undefined;

/**
Expand All @@ -122,6 +122,5 @@ export interface IndexedTree
batchInsert<TreeHeight extends number, SubtreeHeight extends number, SubtreeSiblingPathHeight extends number>(
leaves: Buffer[],
subtreeHeight: SubtreeHeight,
includeUncommitted: boolean,
): Promise<BatchInsertionResult<TreeHeight, SubtreeSiblingPathHeight>>;
}
4 changes: 2 additions & 2 deletions yarn-project/merkle-tree/src/interfaces/merkle_tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export interface MerkleTree<T extends Bufferable = Buffer> extends SiblingPathSo
* @param includeUncommitted - Indicates whether to include uncommitted data.
* @returns The index of the first leaf found with a given value (undefined if not found).
*/
findLeafIndex(leaf: T, includeUncommitted: boolean): bigint | undefined;
findLeafIndex(leaf: Buffer, includeUncommitted: boolean): bigint | undefined;

/**
* Returns the first index containing a leaf value after `startIndex`.
Expand All @@ -66,5 +66,5 @@ export interface MerkleTree<T extends Bufferable = Buffer> extends SiblingPathSo
* @param includeUncommitted - Indicates whether to include uncommitted data.
* @returns The index of the first leaf found with a given value (undefined if not found).
*/
findLeafIndexAfter(leaf: T, startIndex: bigint, includeUncommitted: boolean): bigint | undefined;
findLeafIndexAfter(leaf: Buffer, startIndex: bigint, includeUncommitted: boolean): bigint | undefined;
}
4 changes: 2 additions & 2 deletions yarn-project/merkle-tree/src/sparse_tree/sparse_tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ export class SparseTree<T extends Bufferable> extends TreeBase<T> implements Upd
return this.#snapshotBuilder.getSnapshot(block);
}

public findLeafIndex(_value: T, _includeUncommitted: boolean): bigint | undefined {
public findLeafIndex(_value: Buffer, _includeUncommitted: boolean): bigint | undefined {
throw new Error('Finding leaf index is not supported for sparse trees');
}

public findLeafIndexAfter(_value: T, _startIndex: bigint, _includeUncommitted: boolean): bigint | undefined {
public findLeafIndexAfter(_value: Buffer, _startIndex: bigint, _includeUncommitted: boolean): bigint | undefined {
throw new Error('Finding leaf index is not supported for sparse trees');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,15 @@ export class StandardIndexedTree extends TreeBase<Buffer> implements IndexedTree
includeUncommitted: boolean,
):
| {
/**
* The index of the found leaf.
*/
index: bigint;
/**
* A flag indicating if the corresponding leaf's value is equal to `newValue`.
*/
alreadyPresent: boolean;
}
/**
* The index of the found leaf.
*/
index: bigint;
/**
* A flag indicating if the corresponding leaf's value is equal to `newValue`.
*/
alreadyPresent: boolean;
}
| undefined {
let lowLeafIndex = this.getDbLowLeafIndex(newKey);
let lowLeafPreimage = lowLeafIndex !== undefined ? this.getDbPreimage(lowLeafIndex) : undefined;
Expand Down
9 changes: 4 additions & 5 deletions yarn-project/merkle-tree/src/standard_tree/standard_tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,14 @@ export class StandardTree<T extends Bufferable = Buffer> extends TreeBase<T> imp
return this.#snapshotBuilder.getSnapshot(blockNumber);
}

public findLeafIndex(value: T, includeUncommitted: boolean): bigint | undefined {
public findLeafIndex(value: Buffer, includeUncommitted: boolean): bigint | undefined {
return this.findLeafIndexAfter(value, 0n, includeUncommitted);
}

public findLeafIndexAfter(value: T, startIndex: bigint, includeUncommitted: boolean): bigint | undefined {
const buffer = serializeToBuffer(value);
public findLeafIndexAfter(value: Buffer, startIndex: bigint, includeUncommitted: boolean): bigint | undefined {
for (let i = startIndex; i < this.getNumLeaves(includeUncommitted); i++) {
const currentValue = this.getLeafValue(i, includeUncommitted);
if (currentValue && serializeToBuffer(currentValue).equals(buffer)) {
const leaf = this.getLeafBuffer(i, includeUncommitted);
if (leaf && leaf.equals(value)) {
return i;
}
}
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/merkle-tree/src/tree_base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ export abstract class TreeBase<T extends Bufferable> implements MerkleTree<T> {
* @param includeUncommitted - Indicates whether to include uncommitted data.
* @returns The index of the first leaf found with a given value (undefined if not found).
*/
abstract findLeafIndex(value: T, includeUncommitted: boolean): bigint | undefined;
abstract findLeafIndex(value: Buffer, includeUncommitted: boolean): bigint | undefined;

/**
* Returns the first index containing a leaf value after `startIndex`.
Expand All @@ -356,5 +356,5 @@ export abstract class TreeBase<T extends Bufferable> implements MerkleTree<T> {
* @param includeUncommitted - Indicates whether to include uncommitted data.
* @returns The index of the first leaf found with a given value (undefined if not found).
*/
abstract findLeafIndexAfter(leaf: T, startIndex: bigint, includeUncommitted: boolean): bigint | undefined;
abstract findLeafIndexAfter(leaf: Buffer, startIndex: bigint, includeUncommitted: boolean): bigint | undefined;
}
6 changes: 3 additions & 3 deletions yarn-project/merkle-tree/src/unbalanced_tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ export class UnbalancedTree<T extends Bufferable = Buffer> implements MerkleTree
* @returns The index of the first leaf found with a given value (undefined if not found).
* @remark This is NOT the index as inserted, but the index which will be used to calculate path structure.
*/
public findLeafIndex(value: T): bigint | undefined {
const key = this.valueCache[serializeToBuffer(value).toString('hex')];
public findLeafIndex(value: Buffer): bigint | undefined {
const key = this.valueCache[value.toString('hex')];
const [, , index] = key.split(':');
return BigInt(index);
}
Expand All @@ -112,7 +112,7 @@ export class UnbalancedTree<T extends Bufferable = Buffer> implements MerkleTree
* @returns The index of the first leaf found with a given value (undefined if not found).
* @remark This is not really used for a wonky tree, but required to implement MerkleTree.
*/
public findLeafIndexAfter(value: T, startIndex: bigint): bigint | undefined {
public findLeafIndexAfter(value: Buffer, startIndex: bigint): bigint | undefined {
const index = this.findLeafIndex(value);
if (!index || index < startIndex) {
return undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import { padArrayEnd } from '@aztec/foundation/collection';
import { type Tuple, assertLength, toFriendlyJSON } from '@aztec/foundation/serialize';
import { getVKIndex, getVKSiblingPath, getVKTreeRoot } from '@aztec/noir-protocol-circuits-types';
import { HintsBuilder, computeFeePayerBalanceLeafSlot } from '@aztec/simulator';
import { type MerkleTreeOperations } from '@aztec/world-state';
import { MerkleTreeLeafType, type MerkleTreeOperations } from '@aztec/world-state';

/**
* Type representing the names of the trees for the base rollup.
Expand Down Expand Up @@ -108,7 +108,7 @@ export async function buildBaseRollupInput(
const {
lowLeavesWitnessData: nullifierWitnessLeaves,
newSubtreeSiblingPath: nullifiersSubtreeSiblingPath,
sortedNewLeaves: sortednullifiers,
sortedNewLeaves: sortedNullifiers,
sortedNewLeavesIndexes,
} = await db.batchInsert(
MerkleTreeId.NULLIFIER_TREE,
Expand Down Expand Up @@ -144,7 +144,7 @@ export async function buildBaseRollupInput(
? nullifierPredecessorMembershipWitnessesWithoutPadding[i]
: makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT),
),
sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, i => Fr.fromBuffer(sortednullifiers[i])),
sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, i => Fr.fromBuffer(sortedNullifiers[i])),
sortedNullifierIndexes: makeTuple(MAX_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]),
noteHashSubtreeSiblingPath,
nullifierSubtreeSiblingPath,
Expand Down Expand Up @@ -391,18 +391,18 @@ export async function getSubtreeSiblingPath(
}

// Scan a tree searching for a specific value and return a membership witness proof for it
export async function getMembershipWitnessFor<N extends number>(
value: Fr,
treeId: MerkleTreeId,
export async function getMembershipWitnessFor<N extends number, ID extends MerkleTreeId>(
value: MerkleTreeLeafType<ID>,
treeId: ID,
height: N,
db: MerkleTreeOperations,
): Promise<MembershipWitness<N>> {
// If this is an empty tx, then just return zeroes
if (value.isZero()) {
if (value.isEmpty()) {
return makeEmptyMembershipWitness(height);
}

const index = await db.findLeafIndex(treeId, value.toBuffer());
const index = await db.findLeafIndex(treeId, value);
if (index === undefined) {
throw new Error(`Leaf with value ${value} not found in tree ${MerkleTreeId[treeId]}`);
}
Expand Down Expand Up @@ -435,8 +435,7 @@ export function validateSimulatedTree(
}
if (simulatedTree.nextAvailableLeafIndex !== localTree.nextAvailableLeafIndex) {
throw new Error(
`${label ?? name} tree next available leaf index mismatch (local ${localTree.nextAvailableLeafIndex}, simulated ${
simulatedTree.nextAvailableLeafIndex
`${label ?? name} tree next available leaf index mismatch (local ${localTree.nextAvailableLeafIndex}, simulated ${simulatedTree.nextAvailableLeafIndex
})`,
);
}
Expand Down
5 changes: 3 additions & 2 deletions yarn-project/simulator/src/public/hints_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ import {
buildPublicDataHints,
buildPublicDataReadRequestHints,
buildSiloedNullifierReadRequestHints,
NullifierLeaf,
} from '@aztec/circuits.js';
import { type Tuple } from '@aztec/foundation/serialize';
import { type IndexedTreeId, type MerkleTreeOperations } from '@aztec/world-state';

export class HintsBuilder {
constructor(private db: MerkleTreeOperations) {}
constructor(private db: MerkleTreeOperations) { }

async getNullifierReadRequestHints(
nullifierReadRequests: Tuple<ScopedReadRequest, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX>,
Expand Down Expand Up @@ -71,7 +72,7 @@ export class HintsBuilder {
}

async getNullifierMembershipWitness(nullifier: Fr) {
const index = await this.db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
const index = await this.db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, new NullifierLeaf(nullifier));
if (index === undefined) {
throw new Error(`Cannot find the leaf for nullifier ${nullifier.toBigInt()}.`);
}
Expand Down
Loading
Loading