export type MerklePath = { /** Index of the leaf in the tree (0-based) */ leafIndex: number; /** Sibling hashes from leaf level up to (but not including) the root */ path: Uint8Array[]; /** * 0 = current node is left child, sibling is right * 1 = current node is right child, sibling is left * (matches your Circom `pathIndices` semantics) */ indices: number[]; }; /** * Circuit-compatible Merkle path format. * The pathIndex is used directly (circuit converts to bits internally via Num2Bits). */ export type CircuitMerklePath = { /** Leaf index (circuit converts to bits internally) */ pathIndex: number; /** Sibling hashes as field elements */ pathElements: bigint[]; }; export type Bytes32 = Uint8Array; /** * Fixed-depth binary Merkle tree over BN254 Fr: * - Leaves and internal nodes are 32-byte big-endian Fr elements. * - Hash is Poseidon(2)(left, right). * - Unfilled leaves use the Poseidon zero chain: * zero[0] = 0 * zero[i+1] = Poseidon(zero[i], zero[i]) * * Depth must match: * - Circom WithdrawCircuit(depth) * - Rust MERKLE_TREE_HEIGHT */ export declare class MerkleTree { readonly depth: number; readonly zeroes: Uint8Array[]; readonly layers: Uint8Array[][]; nextIndex: number; constructor(depth?: number); get capacity(): number; get root(): Uint8Array; /** * Insert a leaf and recompute the path up to the root. * Returns the leaf index and the new root. */ insert(leaf: Uint8Array): { index: number; root: Uint8Array; }; /** * Return Merkle proof (path + indices) for a given leaf index. * This feeds directly into the Circom `MerklePathVerifier(depth)`: * - `pathElements[i]` = sibling * - `pathIndices[i]` = 0/1 as defined above */ getPath(index: number): MerklePath; /** * Return Merkle proof in circuit-compatible format. * The circuit uses pathIndex directly and converts to bits via Num2Bits(levels). */ getCircuitPath(index: number): CircuitMerklePath; } /** * The Poseidon zero chain: `z[0] = 0`, `z[i+1] = Poseidon(z[i], z[i])`. * * This is the `zeroes` array a `MerkleTree` builds in its constructor, without * the tree. Deposits need a Merkle path for their dummy inputs, but the circuit * disables the path check when a input amount is zero (`enabled <== 1 - IsZero(amount)` * in transaction.circom), so the values are never constrained — only their * count is. * * Allocating a full depth-22 `MerkleTree` for this costs ~130 MB and several * seconds. This costs 22 hashes. Any deposit-shaped transaction should use it. */ export declare function poseidonZeroChain(depth?: number): Uint8Array[];