UNPKG

snarky-smt

Version:

Sparse Merkle Tree for SnarkyJS

78 lines (77 loc) 2.94 kB
import { Poseidon } from 'snarkyjs'; import { CSMTUtils } from './proofs'; import { CompactSparseMerkleTree } from './csmt'; export { CompactDeepSparseMerkleSubTree }; /** * This is used to compute new roots for state transitions based on sideNodes. * * @class CompactSparseMerkleTree * @extends {CompactDeepSparseMerkleSubTree<K, V>} * @template K * @template V */ class CompactDeepSparseMerkleSubTree extends CompactSparseMerkleTree { /** * Creates an instance of CompactDeepSparseMerkleSubTree. * @param {Store<V>} store * @param {Field} root * @param {Provable<K>} keyType * @param {Provable<V>} valueType * @param {{ hasher?: Hasher; hashKey?: boolean; hashValue?: boolean }} [options={ * hasher: Poseidon.hash, * hashKey: true, * hashValue: true, * }] hasher: The hash function to use, defaults to Poseidon.hash; hashKey: * whether to hash the key, the default is true; hashValue: whether to hash the value, * the default is true. * @memberof CompactDeepSparseMerkleSubTree */ constructor(store, root, keyType, valueType, options = { hasher: Poseidon.hash, hashKey: true, hashValue: true, }) { super(store, keyType, valueType, root, options); } /** * Add a branch to the tree, a branch is generated by smt.prove. * * @param {CompactSparseMerkleProof} proof * @param {K} key * @param {V} [value] * @memberof CompactDeepSparseMerkleSubTree */ async addBranch(proof, key, value) { const { ok, updates } = CSMTUtils.verifyProofWithUpdates(proof, this.getRoot(), key, this.keyType, value, this.valueType, { hasher: this.th.getHasher(), hashKey: this.config.hashKey, hashValue: this.config.hashValue, }); if (!ok) { throw new Error('Invalid proof'); } if (value !== undefined) { let path = null; if (this.config.hashKey) { path = this.th.path(key); } else { let keyFields = this.keyType.toFields(key); if (keyFields.length > 1) { throw new Error(`The length of key fields is greater than 1, the key needs to be hashed before it can be processed, option 'hashKey' must be set to true`); } path = keyFields[0]; } this.store.preparePutValue(path, value); } updates?.forEach((v) => { this.store.preparePutNodes(v[0], v[1]); }); if (!this.th.isEmptyData(proof.siblingData)) { if (proof.sideNodes.length > 0) { this.store.preparePutNodes(proof.sideNodes[0], proof.siblingData); } } await this.store.commit(); } }