'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var ffjavascript = require('ffjavascript'); var blake2b = require('blake2b'); var createBlakeHash = require('blake-hash'); var ethers = require('ethers'); var assert = require('assert'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var blake2b__default = /*#__PURE__*/_interopDefaultLegacy(blake2b); var createBlakeHash__default = /*#__PURE__*/_interopDefaultLegacy(createBlakeHash); var ethers__default = /*#__PURE__*/_interopDefaultLegacy(ethers); var assert__default = /*#__PURE__*/_interopDefaultLegacy(assert); async function buildBabyJub() { const bn128 = await ffjavascript.getCurveFromName("bn128"); return new BabyJub(bn128.Fr); } class BabyJub { constructor(F) { this.F = F; this.p = ffjavascript.Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); this.pm1d2 = ffjavascript.Scalar.div(ffjavascript.Scalar.sub(this.p, ffjavascript.Scalar.e(1)), ffjavascript.Scalar.e(2)); this.Generator = [ F.e("995203441582195749578291179787384436505546430278305826713579947235728471134"), F.e("5472060717959818805561601436314318772137091100104008585924551046643952123905") ]; this.Base8 = [ F.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"), F.e("16950150798460657717958625567821834550301663161624707787222815936182638968203") ]; this.order = ffjavascript.Scalar.fromString("21888242871839275222246405745257275088614511777268538073601725287587578984328"); this.subOrder = ffjavascript.Scalar.shiftRight(this.order, 3); this.A = F.e("168700"); this.D = F.e("168696"); } addPoint(a,b) { const F = this.F; const res = []; /* does the equivalent of: res[0] = bigInt((a[0]*b[1] + b[0]*a[1]) * bigInt(bigInt("1") + d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q); res[1] = bigInt((a[1]*b[1] - cta*a[0]*b[0]) * bigInt(bigInt("1") - d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q); */ const beta = F.mul(a[0],b[1]); const gamma = F.mul(a[1],b[0]); const delta = F.mul( F.sub(a[1], F.mul(this.A, a[0])), F.add(b[0], b[1]) ); const tau = F.mul(beta, gamma); const dtau = F.mul(this.D, tau); res[0] = F.div( F.add(beta, gamma), F.add(F.one, dtau) ); res[1] = F.div( F.add(delta, F.sub(F.mul(this.A,beta), gamma)), F.sub(F.one, dtau) ); return res; } mulPointEscalar(base, e) { const F = this.F; let res = [F.e("0"),F.e("1")]; let rem = e; let exp = base; while (! ffjavascript.Scalar.isZero(rem)) { if (ffjavascript.Scalar.isOdd(rem)) { res = this.addPoint(res, exp); } exp = this.addPoint(exp, exp); rem = ffjavascript.Scalar.shiftRight(rem, 1); } return res; } inSubgroup(P) { const F = this.F; if (!this.inCurve(P)) return false; const res= this.mulPointEscalar(P, this.subOrder); return (F.isZero(res[0]) && F.eq(res[1], F.one)); } inCurve(P) { const F = this.F; const x2 = F.square(P[0]); const y2 = F.square(P[1]); if (!F.eq( F.add(F.mul(this.A, x2), y2), F.add(F.one, F.mul(F.mul(x2, y2), this.D)))) return false; return true; } packPoint(P) { const F = this.F; const buff = new Uint8Array(32); F.toRprLE(buff, 0, P[1]); const n = F.toObject(P[0]); if (ffjavascript.Scalar.gt(n, this.pm1d2)) { buff[31] = buff[31] | 0x80; } return buff; } unpackPoint(buff) { const F = this.F; let sign = false; const P = new Array(2); if (buff[31] & 0x80) { sign = true; buff[31] = buff[31] & 0x7F; } P[1] = F.fromRprLE(buff, 0); if (ffjavascript.Scalar.gt(F.toObject(P[1]), this.p)) return null; const y2 = F.square(P[1]); const x2 = F.div( F.sub(F.one, y2), F.sub(this.A, F.mul(this.D, y2)) ); const x2h = F.exp(x2, F.half); if (! F.eq(F.one, x2h)) return null; let x = F.sqrt(x2); if (x == null) return null; if (sign) x = F.neg(x); P[0] = x; return P; } } const GENPOINT_PREFIX = "PedersenGenerator"; const windowSize = 4; const nWindowsPerSegment = 50; async function buildPedersenHash() { const babyJub = await buildBabyJub(); return new PedersenHash(babyJub); } class PedersenHash { constructor(babyJub) { this.babyJub = babyJub; this.bases = []; } baseHash(type, S) { if (type == "blake") { return createBlakeHash__default["default"]("blake256").update(S).digest(); } else if (type == "blake2b") { return Buffer.from(blake2b__default["default"](32).update(Buffer.from(S)).digest()); } } hash(msg, options) { options = options || {}; options.baseHash = options.baseHash || "blake"; const babyJub = this.babyJub; const bitsPerSegment = windowSize*nWindowsPerSegment; const bits = this.buffer2bits(msg); const nSegments = Math.floor((bits.length - 1)/(windowSize*nWindowsPerSegment)) +1; let accP = [babyJub.F.zero,babyJub.F.one]; for (let s=0; s> 1; res[i*8+2] = (b & 0x04) >> 2; res[i*8+3] = (b & 0x08) >> 3; res[i*8+4] = (b & 0x10) >> 4; res[i*8+5] = (b & 0x20) >> 5; res[i*8+6] = (b & 0x40) >> 6; res[i*8+7] = (b & 0x80) >> 7; } return res; } } const SEED$1 = "mimc"; const NROUNDS$1 = 91; async function buildMimc7() { const bn128 = await ffjavascript.getCurveFromName("bn128"); return new Mimc7(bn128.Fr); } class Mimc7 { constructor (F) { this.F = F; this.cts = this.getConstants(SEED$1, 91); } getIV(seed) { const F = this.F; if (typeof seed === "undefined") seed = SEED$1; const c = ethers__default["default"].utils.keccak256(ethers__default["default"].utils.toUtf8Bytes(seed+"_iv")); const cn = ffjavascript.Scalar.e(c); const iv = ffjavascript.Scalar.mod(cn, F.p); return iv; }; getConstants(seed, nRounds) { const F = this.F; if (typeof nRounds === "undefined") nRounds = NROUNDS$1; const cts = new Array(nRounds); let c = ethers__default["default"].utils.keccak256(ethers__default["default"].utils.toUtf8Bytes(SEED$1)); for (let i=1; i { res[k] = unsringifyConstants$1(Fr, o[k]); }); return res; } else { return o; } } async function buildPoseidon$1() { const bn128 = await ffjavascript.getCurveFromName("bn128"); const F = bn128.Fr; const opt = unsringifyConstants$1(F, poseidonConstants$1); const N_ROUNDS_F = 8; const N_ROUNDS_P = [56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68]; const pow5 = a => F.mul(a, F.square(F.square(a, a))); function poseidon(inputs) { assert__default["default"](inputs.length > 0); assert__default["default"](inputs.length <= N_ROUNDS_P.length); const t = inputs.length + 1; const nRoundsF = N_ROUNDS_F; const nRoundsP = N_ROUNDS_P[t - 2]; const C = opt.C[t-2]; const S = opt.S[t-2]; const M = opt.M[t-2]; const P = opt.P[t-2]; let state = [F.zero, ...inputs.map(a => F.e(a))]; state = state.map((a, i) => F.add(a, C[i])); for (let r = 0; r < nRoundsF/2-1; r++) { state = state.map(a => pow5(a)); state = state.map((a, i) => F.add(a, C[(r +1)* t +i])); state = state.map((_, i) => state.reduce((acc, a, j) => F.add(acc, F.mul(M[j][i], a)), F.zero) ); } state = state.map(a => pow5(a)); state = state.map((a, i) => F.add(a, C[(nRoundsF/2-1 +1)* t +i])); state = state.map((_, i) => state.reduce((acc, a, j) => F.add(acc, F.mul(P[j][i], a)), F.zero) ); for (let r = 0; r < nRoundsP; r++) { state[0] = pow5(state[0]); state[0] = F.add(state[0], C[(nRoundsF/2 +1)*t + r]); const s0 = state.reduce((acc, a, j) => { return F.add(acc, F.mul(S[(t*2-1)*r+j], a)); }, F.zero); for (let k=1; k pow5(a)); state = state.map((a, i) => F.add(a, C[ (nRoundsF/2 +1)*t + nRoundsP + r*t + i ])); state = state.map((_, i) => state.reduce((acc, a, j) => F.add(acc, F.mul(M[j][i], a)), F.zero) ); } state = state.map(a => pow5(a)); state = state.map((_, i) => state.reduce((acc, a, j) => F.add(acc, F.mul(M[j][i], a)), F.zero) ); return state[0]; } poseidon.F = F; return poseidon; } const SEED = "mimcsponge"; const NROUNDS = 220; async function buildMimcSponge() { const bn128 = await ffjavascript.getCurveFromName("bn128"); return new MimcSponge(bn128.Fr); } class MimcSponge { constructor (F) { this.F = F; this.cts = this.getConstants(SEED, NROUNDS); } getIV (seed) { const F = this.F; if (typeof seed === "undefined") seed = SEED; const c = ethers__default["default"].utils.keccak256(ethers__default["default"].utils.toUtf8Bytes(seed+"_iv")); const cn = ffjavascript.Scalar.e(c); const iv = cn.mod(F.p); return iv; }; getConstants (seed, nRounds) { const F = this.F; if (typeof nRounds === "undefined") nRounds = NROUNDS; const cts = new Array(nRounds); let c = ethers__default["default"].utils.keccak256(ethers__default["default"].utils.toUtf8Bytes(SEED)); for (let i=1; i= this.babyJub.subOrder) return false; const hm = this.mimc7.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]); const hms = ffjavascript.Scalar.e(this.babyJub.F.toObject(hm)); const Pleft = this.babyJub.mulPointEscalar(this.babyJub.Base8, sig.S); let Pright = this.babyJub.mulPointEscalar(A, ffjavascript.Scalar.mul(hms, 8)); Pright = this.babyJub.addPoint(sig.R8, Pright); if (!this.babyJub.F.eq(Pleft[0],Pright[0])) return false; if (!this.babyJub.F.eq(Pleft[1],Pright[1])) return false; return true; } verifyPoseidon(msg, sig, A) { // Check parameters if (typeof sig != "object") return false; if (!Array.isArray(sig.R8)) return false; if (sig.R8.length!= 2) return false; if (!this.babyJub.inCurve(sig.R8)) return false; if (!Array.isArray(A)) return false; if (A.length!= 2) return false; if (!this.babyJub.inCurve(A)) return false; if (sig.S>= this.babyJub.subOrder) return false; const hm = this.poseidon([sig.R8[0], sig.R8[1], A[0], A[1], msg]); const hms = ffjavascript.Scalar.e(this.babyJub.F.toObject(hm)); const Pleft = this.babyJub.mulPointEscalar(this.babyJub.Base8, sig.S); let Pright = this.babyJub.mulPointEscalar(A, ffjavascript.Scalar.mul(hms, 8)); Pright = this.babyJub.addPoint(sig.R8, Pright); if (!this.babyJub.F.eq(Pleft[0],Pright[0])) return false; if (!this.babyJub.F.eq(Pleft[1],Pright[1])) return false; return true; } verifyMiMCSponge(msg, sig, A) { // Check parameters if (typeof sig != "object") return false; if (!Array.isArray(sig.R8)) return false; if (sig.R8.length!= 2) return false; if (!this.babyJub.inCurve(sig.R8)) return false; if (!Array.isArray(A)) return false; if (A.length!= 2) return false; if (!this.babyJub.inCurve(A)) return false; if (sig.S>= this.babyJub.subOrder) return false; const hm = this.mimcSponge.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]); const hms = ffjavascript.Scalar.e(this.babyJub.F.toObject(hm)); const Pleft = this.babyJub.mulPointEscalar(this.babyJub.Base8, sig.S); let Pright = this.babyJub.mulPointEscalar(A, ffjavascript.Scalar.mul(hms, 8)); Pright = this.babyJub.addPoint(sig.R8, Pright); if (!this.babyJub.F.eq(Pleft[0],Pright[0])) return false; if (!this.babyJub.F.eq(Pleft[1],Pright[1])) return false; return true; } packSignature(sig) { const buff = new Uint8Array(64); const R8p = this.babyJub.packPoint(sig.R8); buff.set(R8p, 0); ffjavascript.Scalar.toRprLE(buff, 32, sig.S, 32); return buff; } unpackSignature(sigBuff) { return { R8: this.babyJub.unpackPoint(sigBuff.slice(0,32)), S: ffjavascript.Scalar.fromRprLE(sigBuff, 32, 32) }; } } // Copyright (c) 2018 Jordi Baylina class Contract { constructor() { this.code = []; this.labels = {}; this.pendingLabels = {}; } createTxData() { let C; // Check all labels are defined const pendingLabels = Object.keys(this.pendingLabels); if (pendingLabels.length>0) { throw new Error("Lables not defined: "+ pendingLabels.join(", ")); } let setLoaderLength = 0; let genLoadedLength = -1; while (genLoadedLength!=setLoaderLength) { setLoaderLength = genLoadedLength; C = new Contract(); C.codesize(); C.push(setLoaderLength); C.push(0); C.codecopy(); C.push(this.code.length); C.push(0); C.return(); genLoadedLength = C.code.length; } return ethers__default["default"].utils.hexlify(C.code.concat(this.code)); } stop() { this.code.push(0x00); } add() { this.code.push(0x01); } mul() { this.code.push(0x02); } sub() { this.code.push(0x03); } div() { this.code.push(0x04); } sdiv() { this.code.push(0x05); } mod() { this.code.push(0x06); } smod() { this.code.push(0x07); } addmod() { this.code.push(0x08); } mulmod() { this.code.push(0x09); } exp() { this.code.push(0x0a); } signextend() { this.code.push(0x0b); } lt() { this.code.push(0x10); } gt() { this.code.push(0x11); } slt() { this.code.push(0x12); } sgt() { this.code.push(0x13); } eq() { this.code.push(0x14); } iszero() { this.code.push(0x15); } and() { this.code.push(0x16); } or() { this.code.push(0x17); } shor() { this.code.push(0x18); } not() { this.code.push(0x19); } byte() { this.code.push(0x1a); } keccak() { this.code.push(0x20); } sha3() { this.code.push(0x20); } // alias address() { this.code.push(0x30); } balance() { this.code.push(0x31); } origin() { this.code.push(0x32); } caller() { this.code.push(0x33); } callvalue() { this.code.push(0x34); } calldataload() { this.code.push(0x35); } calldatasize() { this.code.push(0x36); } calldatacopy() { this.code.push(0x37); } codesize() { this.code.push(0x38); } codecopy() { this.code.push(0x39); } gasprice() { this.code.push(0x3a); } extcodesize() { this.code.push(0x3b); } extcodecopy() { this.code.push(0x3c); } returndatasize() { this.code.push(0x3d); } returndatacopy() { this.code.push(0x3e); } blockhash() { this.code.push(0x40); } coinbase() { this.code.push(0x41); } timestamp() { this.code.push(0x42); } number() { this.code.push(0x43); } difficulty() { this.code.push(0x44); } gaslimit() { this.code.push(0x45); } pop() { this.code.push(0x50); } mload() { this.code.push(0x51); } mstore() { this.code.push(0x52); } mstore8() { this.code.push(0x53); } sload() { this.code.push(0x54); } sstore() { this.code.push(0x55); } _pushLabel(label) { if (typeof this.labels[label] != "undefined") { this.push(this.labels[label]); } else { this.pendingLabels[label] = this.pendingLabels[label] || []; this.pendingLabels[label].push(this.code.length); this.push("0x000000"); } } _fillLabel(label) { if (!this.pendingLabels[label]) return; let dst = this.labels[label]; const dst3 = [dst >> 16, (dst >> 8) & 0xFF, dst & 0xFF]; this.pendingLabels[label].forEach((p) => { for (let i=0; i<3; i++) { this.code[p+i+1] = dst3[i]; } }); delete this.pendingLabels[label]; } jmp(label) { if (typeof label !== "undefined") { this._pushLabel(label); } this.code.push(0x56); } jmpi(label) { if (typeof label !== "undefined") { this._pushLabel(label); } this.code.push(0x57); } pc() { this.code.push(0x58); } msize() { this.code.push(0x59); } gas() { this.code.push(0x5a); } label(name) { if (typeof this.labels[name] != "undefined") { throw new Error("Label already defined"); } this.labels[name] = this.code.length; this.code.push(0x5b); this._fillLabel(name); } push(data) { if ((typeof data !== "string") || (data.slice(0,2) != "0x")) { let v = ffjavascript.Scalar.e(data); if (ffjavascript.Scalar.isNegative(v)) { v = ffjavascript.Scalar.add(ffjavascript.Scalar.shl(ffjavascript.Scalar.e(1), 256), v); } let S = ffjavascript.Scalar.toString(v, 16); if (S.length % 2) S = "0"+S; S = "0x" +S; data = S; } const d = ethers__default["default"].utils.arrayify(data); if (d.length == 0 || d.length > 32) { throw new Error("Assertion failed"); } this.code.push(0x5F + d.length); for (let i=0; i= 16) { throw new Error("Assertion failed"); } this.code.push(0x80 + n); } swap(n) { if (n < 1 || n > 16) { throw new Error("Assertion failed"); } this.code.push(0x8f + n); } log0() { this.code.push(0xa0); } log1() { this.code.push(0xa1); } log2() { this.code.push(0xa2); } log3() { this.code.push(0xa3); } log4() { this.code.push(0xa4); } create() { this.code.push(0xf0); } call() { this.code.push(0xf1); } callcode() { this.code.push(0xf2); } return() { this.code.push(0xf3); } delegatecall() { this.code.push(0xf4); } staticcall() { this.code.push(0xfa); } revert() { this.code.push(0xfd); } invalid() { this.code.push(0xfe); } selfdestruct() { this.code.push(0xff); } } // Copyright (c) 2018 Jordi Baylina function createCode$2(seed, n) { let ci = ethers__default["default"].utils.keccak256(ethers__default["default"].utils.toUtf8Bytes(seed)); const C = new Contract(); C.push(0x44); C.push("0x00"); C.push("0x00"); C.calldatacopy(); C.push("0x0100000000000000000000000000000000000000000000000000000000"); C.push("0x00"); C.mload(); C.div(); C.push("0xd15ca109"); // MiMCpe7(uint256,uint256) // C.push("0x8c42199e"); // MiMCpe7(uint256,uint256,uint256) C.eq(); C.jmpi("start"); C.invalid(); C.label("start"); C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q C.push("0x24"); C.mload(); // k q C.dup(1); // q k q C.dup(0); // q q k q C.push("0x04"); C.mload(); // x q q k q C.dup(3); // k x q q k q C.addmod(); // t=x+k q k q C.dup(1); // q t q k q C.dup(0); // q q t q k q C.dup(2); // t q q t q k q C.dup(0); // t t q q t q k q C.mulmod(); // a=t^2 q t q k q C.dup(1); // q a q t q k q C.dup(1); // a q a q t q k q C.dup(0); // a a q a q t q k q C.mulmod(); // b=t^4 a q t q k q C.mulmod(); // c=t^6 t q k q C.mulmod(); // r=t^7 k q for (let i=0; i8)) throw new Error("Invalid number of inputs. Must be 1<=nInputs<=8"); const t = nInputs + 1; const nRoundsF = N_ROUNDS_F; const nRoundsP = N_ROUNDS_P[t - 2]; const C = new Contract(); function saveM() { for (let i=0; i=nRoundsP+nRoundsF/2)) { for (let j=0; j { res[k] = unsringifyConstants(Fr, o[k]); }); return res; } else { return o; } } async function buildPoseidon() { const bn128 = await ffjavascript.getCurveFromName("bn128"); const F = bn128.Fr; // Parameters are generated by a reference script https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/generate_parameters_grain.sage // Used like so: sage generate_parameters_grain.sage 1 0 254 2 8 56 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 const {C, M} = unsringifyConstants(F, poseidonConstants); // Using recommended parameters from whitepaper https://eprint.iacr.org/2019/458.pdf (table 2, table 8) // Generated by https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/calc_round_numbers.py // And rounded up to nearest integer that divides by t const N_ROUNDS_F = 8; const N_ROUNDS_P = [56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68]; const pow5 = a => F.mul(a, F.square(F.square(a, a))); function poseidon(inputs) { assert__default["default"](inputs.length > 0); assert__default["default"](inputs.length <= N_ROUNDS_P.length); const t = inputs.length + 1; const nRoundsF = N_ROUNDS_F; const nRoundsP = N_ROUNDS_P[t - 2]; let state = [F.zero, ...inputs.map(a => F.e(a))]; for (let r = 0; r < nRoundsF + nRoundsP; r++) { state = state.map((a, i) => F.add(a, C[t - 2][r * t + i])); if (r < nRoundsF / 2 || r >= nRoundsF / 2 + nRoundsP) { state = state.map(a => pow5(a)); } else { state[0] = pow5(state[0]); } state = state.map((_, i) => state.reduce((acc, a, j) => F.add(acc, F.mul(M[t - 2][i][j], a)), F.zero) ); } return state[0]; } poseidon.F = F; return poseidon; } class SMTMemDb { constructor(F) { this.nodes = {}; this.root = F.zero; this.F = F; } async getRoot() { return this.root; } _key2str(k) { this.F; const keyS = this.F.toString(k); return keyS; } _normalize(n) { this.F; for (let i=0; i=0; level--) { let oldNode, newNode; const sibling = resFind.siblings[level]; if (keyBits[level]) { oldNode = [sibling, rtOld]; newNode = [sibling, rtNew]; } else { oldNode = [rtOld, sibling]; newNode = [rtNew, sibling]; } rtOld = this.hash0(oldNode[0], oldNode[1]); rtNew = this.hash0(newNode[0], newNode[1]); dels.push(rtOld); ins.push([rtNew, newNode]); } res.newRoot = rtNew; await this.db.multiDel(dels); await this.db.multiIns(ins); await this.db.setRoot(rtNew); this.root = rtNew; return res; } async delete(_key) { const F = this.F; const key = F.e(_key); const resFind = await this.find(key); if (!resFind.found) throw new Error("Key does not exists"); const res = { siblings: [], delKey: key, delValue: resFind.foundValue }; const dels = []; const ins = []; let rtOld = this.hash1(key, resFind.foundValue); let rtNew; dels.push(rtOld); let mixed; if (resFind.siblings.length > 0) { const record = await this.db.get(resFind.siblings[resFind.siblings.length - 1]); if ((record.length == 3)&&(F.eq(record[0], F.one))) { mixed = false; res.oldKey = record[1]; res.oldValue = record[2]; res.isOld0 = false; rtNew = resFind.siblings[resFind.siblings.length - 1]; } else if (record.length == 2) { mixed = true; res.oldKey = key; res.oldValue = F.zero; res.isOld0 = true; rtNew = F.zero; } else { throw new Error("Invalid node. Database corrupted"); } } else { rtNew = F.zero; res.oldKey = key; res.oldValue = F.zero; res.isOld0 = true; } const keyBits = this._splitBits(key); for (let level = resFind.siblings.length-1; level >=0; level--) { let newSibling = resFind.siblings[level]; if ((level == resFind.siblings.length-1)&&(!res.isOld0)) { newSibling = F.zero; } const oldSibling = resFind.siblings[level]; if (keyBits[level]) { rtOld = this.hash0(oldSibling, rtOld); } else { rtOld = this.hash0(rtOld, oldSibling); } dels.push(rtOld); if (!F.isZero(newSibling)) { mixed = true; } if (mixed) { res.siblings.unshift(resFind.siblings[level]); let newNode; if (keyBits[level]) { newNode = [newSibling, rtNew]; } else { newNode = [rtNew, newSibling]; } rtNew = this.hash0(newNode[0], newNode[1]); ins.push([rtNew, newNode]); } } await this.db.multiIns(ins); await this.db.setRoot(rtNew); this.root = rtNew; await this.db.multiDel(dels); res.newRoot = rtNew; res.oldRoot = rtOld; return res; } async insert(_key, _value) { const F = this.F; const key = F.e(_key); const value = F.e(_value); let addedOne = false; const res = {}; res.oldRoot = this.root; const newKeyBits = this._splitBits(key); let rtOld; const resFind = await this.find(key); if (resFind.found) throw new Error("Key already exists"); res.siblings = resFind.siblings; let mixed; if (!resFind.isOld0) { const oldKeyits = this._splitBits(resFind.notFoundKey); for (let i= res.siblings.length; oldKeyits[i] == newKeyBits[i]; i++) { res.siblings.push(F.zero); } rtOld = this.hash1(resFind.notFoundKey, resFind.notFoundValue); res.siblings.push(rtOld); addedOne = true; mixed = false; } else if (res.siblings.length >0) { mixed = true; rtOld = F.zero; } const inserts = []; const dels = []; let rt = this.hash1(key, value); inserts.push([rt,[1, key, value]] ); for (let i=res.siblings.length-1; i>=0; i--) { if ((i0) && (F.isZero(res.siblings[res.siblings.length-1]))) { res.siblings.pop(); } res.oldKey = resFind.notFoundKey; res.oldValue = resFind.notFoundValue; res.newRoot = rt; res.isOld0 = resFind.isOld0; await this.db.multiIns(inserts); await this.db.setRoot(rt); this.root = rt; await this.db.multiDel(dels); return res; } async find(_key) { const key = this.F.e(_key); const keyBits = this._splitBits(key); return await this._find(key, keyBits, this.root, 0); } async _find(key, keyBits, root, level) { const F = this.F; if (typeof root === "undefined") root = this.root; let res; if (F.isZero(root)) { res = { found: false, siblings: [], notFoundKey: key, notFoundValue: F.zero, isOld0: true }; return res; } const record = await this.db.get(root); if ((record.length==3)&&(F.eq(record[0],F.one))) { if (F.eq(record[1],key)) { res = { found: true, siblings: [], foundValue: record[2], isOld0: false }; } else { res = { found: false, siblings: [], notFoundKey: record[1], notFoundValue: record[2], isOld0: false }; } } else { if (keyBits[level] == 0) { res = await this._find(key, keyBits, record[0], level+1); res.siblings.unshift(record[1]); } else { res = await this._find(key, keyBits, record[1], level+1); res.siblings.unshift(record[0]); } } return res; } } async function newMemEmptyTrie() { const {hash0, hash1,F} = await getHashes(); const db = new SMTMemDb(F); const rt = await db.getRoot(); const smt = new SMT(db, rt, hash0, hash1, F); return smt; } const mimc7Contract=_mimc7Contract; const mimcSpongecontract=_mimcSpongeContract; const poseidonContract=_poseidonContract; exports.SMT = SMT; exports.SMTMemDb = SMTMemDb; exports.buildBabyjub = buildBabyJub; exports.buildEddsa = buildEddsa; exports.buildMimc7 = buildMimc7; exports.buildMimcSponge = buildMimcSponge; exports.buildPedersenHash = buildPedersenHash; exports.buildPoseidon = buildPoseidon$1; exports.buildPoseidonSlow = buildPoseidon; exports.buildSMT = buildSMT; exports.evmasm = Contract; exports.mimc7Contract = mimc7Contract; exports.mimcSpongecontract = mimcSpongecontract; exports.newMemEmptyTrie = newMemEmptyTrie; exports.poseidonContract = poseidonContract;