From d53cb52c325b2f6e1b525a1afd1e3e00b0a8f843 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Mon, 25 Mar 2024 17:18:52 +0000 Subject: [PATCH 1/6] chore: added the code for split commitment circuits --- src/boilerplate/common/commitment-storage.mjs | 320 ++++++++++-------- src/transformers/visitors/toCircuitVisitor.ts | 13 +- .../visitors/toOrchestrationVisitor.ts | 7 +- test/real-world-zapps/Escrow.zol | 4 +- 4 files changed, 195 insertions(+), 149 deletions(-) diff --git a/src/boilerplate/common/commitment-storage.mjs b/src/boilerplate/common/commitment-storage.mjs index a51db2048..e1cd8234a 100644 --- a/src/boilerplate/common/commitment-storage.mjs +++ b/src/boilerplate/common/commitment-storage.mjs @@ -9,7 +9,12 @@ import logger from './logger.mjs'; import utils from "zkp-utils"; import { poseidonHash } from './number-theory.mjs'; import { generateProof } from './zokrates.mjs'; -import { SumType, reduceTree, toBinArray, poseidonConcatHash } from './smt_utils.mjs'; +import { + SumType, + reduceTree, + toBinArray, + poseidonConcatHash, +} from './smt_utils.mjs'; import { hlt } from './hash-lookup.mjs'; const { MONGO_URL, COMMITMENTS_DB, COMMITMENTS_COLLECTION } = config; @@ -32,7 +37,9 @@ const SMT = SumType([Branch, Leaf], () => { throw new TypeError('Invalid data structure provided'); }); +// eslint-disable-next-line camelcase let smt_tree = SMT(hlt[0]); +// eslint-disable-next-line camelcase let temp_smt_tree = SMT(hlt[0]); // for temporary updates before proof generation // Gets the hash of a smt_tree (or subtree) @@ -43,21 +50,25 @@ export async function storeCommitment(commitment) { const connection = await mongo.connection(MONGO_URL); const db = connection.db(COMMITMENTS_DB); // we'll also compute and store the nullifier hash. - const nullifierHash = commitment.secretKey ? poseidonHash([ - BigInt(commitment.preimage.stateVarId.hex(32)), - BigInt(commitment.secretKey.hex(32)), - BigInt(commitment.preimage.salt.hex(32)), - ]) : ''; + const nullifierHash = commitment.secretKey + ? poseidonHash([ + BigInt(commitment.preimage.stateVarId.hex(32)), + BigInt(commitment.secretKey.hex(32)), + BigInt(commitment.preimage.salt.hex(32)), + ]) + : ''; const preimage = generalise(commitment.preimage).all.hex(32); - preimage.value = generalise(commitment.preimage.value).all ? generalise(commitment.preimage.value).all.integer : generalise(commitment.preimage.value).integer; + preimage.value = generalise(commitment.preimage.value).all + ? generalise(commitment.preimage.value).all.integer + : generalise(commitment.preimage.value).integer; const data = { _id: commitment.hash.hex(32), - name: commitment.name, - mappingKey: commitment.mappingKey ? commitment.mappingKey : null, - secretKey: commitment.secretKey? commitment.secretKey.hex(32) : null, + name: commitment.name, + mappingKey: commitment.mappingKey ? commitment.mappingKey : null, + secretKey: commitment.secretKey ? commitment.secretKey.hex(32) : null, preimage, isNullified: commitment.isNullified, - nullifier: commitment.secretKey? nullifierHash.hex(32) : null, + nullifier: commitment.secretKey ? nullifierHash.hex(32) : null, }; logger.debug(`Storing commitment ${data._id}`); return db.collection(COMMITMENTS_COLLECTION).insertOne(data); @@ -65,59 +76,62 @@ export async function storeCommitment(commitment) { // function to retrieve commitment with a specified stateVarId export async function getCommitmentsById(id) { - const connection = await mongo.connection(MONGO_URL); - const db = connection.db(COMMITMENTS_DB); - const commitments = await db - .collection(COMMITMENTS_COLLECTION) - .find({ 'preimage.stateVarId': generalise(id).hex(32) }) - .toArray(); - return commitments; - } + const connection = await mongo.connection(MONGO_URL); + const db = connection.db(COMMITMENTS_DB); + const commitments = await db + .collection(COMMITMENTS_COLLECTION) + .find({ 'preimage.stateVarId': generalise(id).hex(32) }) + .toArray(); + return commitments; +} // function to retrieve commitment with a specified stateVarId export async function getCurrentWholeCommitment(id) { - const connection = await mongo.connection(MONGO_URL); - const db = connection.db(COMMITMENTS_DB); - const commitment = await db - .collection(COMMITMENTS_COLLECTION) - .findOne({ 'preimage.stateVarId': generalise(id).hex(32), isNullified: false }); - return commitment; - } + const connection = await mongo.connection(MONGO_URL); + const db = connection.db(COMMITMENTS_DB); + const commitment = await db.collection(COMMITMENTS_COLLECTION).findOne({ + 'preimage.stateVarId': generalise(id).hex(32), + isNullified: false, + }); + return commitment; +} // function to retrieve commitment with a specified stateName export async function getCommitmentsByState(name, mappingKey = null) { - const connection = await mongo.connection(MONGO_URL); - const db = connection.db(COMMITMENTS_DB); - const query = { 'name': name }; - if (mappingKey) query['mappingKey'] = generalise(mappingKey).integer; - const commitments = await db - .collection(COMMITMENTS_COLLECTION) - .find(query) - .toArray(); - return commitments; + const connection = await mongo.connection(MONGO_URL); + const db = connection.db(COMMITMENTS_DB); + const query = { name: name }; + if (mappingKey) query['mappingKey'] = generalise(mappingKey).integer; + const commitments = await db + .collection(COMMITMENTS_COLLECTION) + .find(query) + .toArray(); + return commitments; } // function to retrieve all known nullified commitments export async function getNullifiedCommitments() { - const connection = await mongo.connection(MONGO_URL); - const db = connection.db(COMMITMENTS_DB); - const commitments = await db - .collection(COMMITMENTS_COLLECTION) - .find({ isNullified: true }) - .toArray(); - return commitments; + const connection = await mongo.connection(MONGO_URL); + const db = connection.db(COMMITMENTS_DB); + const commitments = await db + .collection(COMMITMENTS_COLLECTION) + .find({ isNullified: true }) + .toArray(); + return commitments; } /** * @returns all the commitments existent in this database. */ - export async function getAllCommitments() { - const connection = await mongo.connection(MONGO_URL); - const db = connection.db(COMMITMENTS_DB); - const allCommitments = await db.collection(COMMITMENTS_COLLECTION).find().toArray(); - return allCommitments; - } - +export async function getAllCommitments() { + const connection = await mongo.connection(MONGO_URL); + const db = connection.db(COMMITMENTS_DB); + const allCommitments = await db + .collection(COMMITMENTS_COLLECTION) + .find() + .toArray(); + return allCommitments; +} // function to update an existing commitment export async function updateCommitment(commitment, updates) { @@ -129,104 +143,126 @@ export async function updateCommitment(commitment, updates) { } // This is a helper function to insertLeaf in smt that calls the recursion -function _insertLeaf(val, tree, binArr){ - if (binArr.length > 0) { - switch (tree.tag) { - case 'branch': // Recursively enter developed subtree - return binArr[0] === '0' - ? Branch(_insertLeaf(val, tree.left, binArr.slice(1)), tree.right) - : Branch(tree.left, _insertLeaf(val, tree.right, binArr.slice(1))); - - case 'leaf': // Open undeveloped subtree - return binArr[0] === '0' - ? Branch( - _insertLeaf(val, Leaf(hlt[TRUNC_LENGTH - (binArr.length - 1)]), binArr.slice(1)), - Leaf(hlt[TRUNC_LENGTH - (binArr.length - 1)]), - ) - : Branch( - Leaf(hlt[TRUNC_LENGTH - (binArr.length - 1)]), - _insertLeaf(val, Leaf(hlt[TRUNC_LENGTH - (binArr.length - 1)]), binArr.slice(1)), - ); - - - default: { - return tree; - } - } - } else return Leaf(val); - }; - - // This inserts a value into the smt as a leaf - function insertLeaf(val, tree) { - const binArr = toBinArray(generalise(val)) - const padBinArr = Array(254 - binArr.length) - .fill("0") - .concat(...binArr).slice(0, TRUNC_LENGTH); - return _insertLeaf(val, tree, padBinArr); - }; +function _insertLeaf(val, tree, binArr) { + if (binArr.length > 0) { + switch (tree.tag) { + case 'branch': // Recursively enter developed subtree + return binArr[0] === '0' + ? Branch(_insertLeaf(val, tree.left, binArr.slice(1)), tree.right) + : Branch(tree.left, _insertLeaf(val, tree.right, binArr.slice(1))); + + case 'leaf': // Open undeveloped subtree + return binArr[0] === '0' + ? Branch( + _insertLeaf( + val, + Leaf(hlt[TRUNC_LENGTH - (binArr.length - 1)]), + binArr.slice(1), + ), + Leaf(hlt[TRUNC_LENGTH - (binArr.length - 1)]), + ) + : Branch( + Leaf(hlt[TRUNC_LENGTH - (binArr.length - 1)]), + _insertLeaf( + val, + Leaf(hlt[TRUNC_LENGTH - (binArr.length - 1)]), + binArr.slice(1), + ), + ); + + default: { + return tree; + } + } + } else return Leaf(val); +} + +// This inserts a value into the smt as a leaf +function insertLeaf(val, tree) { + const binArr = toBinArray(generalise(val)); + const padBinArr = Array(254 - binArr.length) + .fill('0') + .concat(...binArr) + .slice(0, TRUNC_LENGTH); + return _insertLeaf(val, tree, padBinArr); +} // function to mark a commitment as nullified for a mongo db and update the nullifier tree export async function markNullified(commitmentHash, secretKey = null) { - const connection = await mongo.connection(MONGO_URL); - const db = connection.db(COMMITMENTS_DB); - const query = { _id: commitmentHash.hex(32) }; - const commitment = await db - .collection(COMMITMENTS_COLLECTION) - .findOne(query); - const nullifier = poseidonHash([ - BigInt(commitment.preimage.stateVarId), - BigInt(commitment.secretKey || secretKey), - BigInt(commitment.preimage.salt), - ]) - const update = { - $set: { - isNullified: true, - nullifier: generalise(nullifier).hex(32), - }, - }; - // updating the original tree - smt_tree = temp_smt_tree; - - return db.collection(COMMITMENTS_COLLECTION).updateOne(query, update); - } + const connection = await mongo.connection(MONGO_URL); + const db = connection.db(COMMITMENTS_DB); + const query = { _id: commitmentHash.hex(32) }; + const commitment = await db.collection(COMMITMENTS_COLLECTION).findOne(query); + const nullifier = poseidonHash([ + BigInt(commitment.preimage.stateVarId), + BigInt(commitment.secretKey || secretKey), + BigInt(commitment.preimage.salt), + ]); + const update = { + $set: { + isNullified: true, + nullifier: generalise(nullifier).hex(32), + }, + }; + // updating the original tree + // eslint-disable-next-line camelcase + smt_tree = temp_smt_tree; + return db.collection(COMMITMENTS_COLLECTION).updateOne(query, update); +} - export function getInputCommitments( - publicKey, - value, - commitments, - isStruct = false +export function getInputCommitments( + contractName, + publicKey, + value, + commitments, + isStruct = false, ) { - - const possibleCommitments = commitments.filter( - (entry) => entry.preimage.publicKey === publicKey && !entry.isNullified - ); - if (isStruct) { - - let possibleCommitmentsProp = getStructInputCommitments(value, possibleCommitments); - if ( - possibleCommitmentsProp.length > 0 - ) - return [true, possibleCommitmentsProp[0][0], possibleCommitmentsProp[0][1]]; - return null; - } - possibleCommitments.sort( - (commitA, commitB) => - parseInt(commitB.preimage.value, 10) - parseInt(commitA.preimage.value, 10) - ); - var commitmentsSum = 0; - possibleCommitments.forEach(commit => { - commitmentsSum += parseInt(commit.preimage.value, 10); - }); - if ( - parseInt(possibleCommitments[0].preimage.value, 10) + - parseInt(possibleCommitments[1].preimage.value, 10) >= - parseInt(value, 10) - ) { - return [true, possibleCommitments[0], possibleCommitments[1]]; - } else if (commitmentsSum >= parseInt(value, 10)) - return [false, possibleCommitments[0], possibleCommitments[1]]; - return null; + const possibleCommitments = commitments.filter( + entry => entry.preimage.publicKey === publicKey && !entry.isNullified, + ); + let commitmentsSum = 0; + possibleCommitments.forEach(commit => { + commitmentsSum += parseInt(commit.preimage.value, 10); + }); + if (isStruct) { + const possibleCommitmentsProp = getStructInputCommitments( + value, + possibleCommitments, + ); + if (possibleCommitmentsProp.length > 0) + return [ + true, + possibleCommitmentsProp[0][0], + possibleCommitmentsProp[0][1], + ]; + return null; + } + if ( + possibleCommitments.length === 1 && + commitmentsSum >= parseInt(value, 10) + ) { + logger.warn( + 'Only one commitment exists, but it is enough to use. Calling Split Commitment circuit. It will generate proof to split commitments, this will require an on-chain verification', + ); + return [true, possibleCommitments[0], null]; + } + possibleCommitments.sort( + (commitA, commitB) => + parseInt(commitB.preimage.value, 10) - + parseInt(commitA.preimage.value, 10), + ); + + if ( + parseInt(possibleCommitments[0].preimage.value, 10) + + parseInt(possibleCommitments[1].preimage.value, 10) >= + parseInt(value, 10) + ) { + return [true, possibleCommitments[0], possibleCommitments[1]]; + } + if (commitmentsSum >= parseInt(value, 10)) + return [false, possibleCommitments[0], possibleCommitments[1]]; + return null; } function getStructInputCommitments( @@ -428,7 +464,7 @@ export async function joinCommitments( newCommitment.integer, ].flat(Infinity); - const res = await generateProof("joinCommitments", allInputs); + const res = await generateProof('joinCommitments', allInputs); const proof = generalise(Object.values(res.proof).flat(Infinity)) .map((coeff) => coeff.integer) .flat(Infinity); diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index 7656b8d11..6d8f42cc0 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -176,12 +176,18 @@ const visitor = { const joinCommitmentsNode = buildNode('File', { - fileName: `joinCommitments`, + fileName: `joinSplitCommitments`, fileId: node.id, nodes: [ ], }); - // check for joinCommitments + const splitCommitmentsNode = buildNode('File', { + fileName: `spiltCommitments`, + fileId: node.id, + nodes: [ ], + }); + + // check for joinCommitments and splitCommitments for(const [, indicator ] of Object.entries(indicators)){ if((indicator instanceof StateVariableIndicator) && indicator.isPartitioned @@ -189,6 +195,9 @@ const visitor = { if (!parent._newASTPointer.some(n => n.fileName === joinCommitmentsNode.fileName)){ parent._newASTPointer.push(joinCommitmentsNode); } + if (!parent._newASTPointer.some(n => n.fileName === splitCommitmentsNode.fileName)){ + parent._newASTPointer.push(splitCommitmentsNode); + } } if(indicator instanceof StateVariableIndicator && indicator.encryptionRequired) { const num = indicator.isStruct ? indicator.referencingPaths[0]?.getStructDeclaration()?.members.length + 2 : 3; diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index e13337f3d..2fae2469b 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -245,8 +245,9 @@ const visitor = { if (file.nodeType === 'SetupCommonFilesBoilerplate') { file.constructorParams = state.constructorParams; file.contractImports = state.contractImports; - if(state.isjoinCommitmentsFunction?.includes('true')) + if(state.isjoinSplitCommitmentsFunction?.includes('true')) file.functionNames.push('joinCommitments'); + file.functionNames.push('splitCommitments'); } if (file.nodes?.[0].nodeType === 'IntegrationTestBoilerplate') { file.nodes[0].constructorParams = state.constructorParams; @@ -354,8 +355,8 @@ const visitor = { indicators.isPartitioned && !indicators.isStruct && indicators.isNullified ) { - state.isjoinCommitmentsFunction ??= []; - state.isjoinCommitmentsFunction?.push('true'); + state.isjoinSplitCommitmentsFunction ??= []; + state.isjoinSplitCommitmentsFunction?.push('true'); } } diff --git a/test/real-world-zapps/Escrow.zol b/test/real-world-zapps/Escrow.zol index 7c0a41aad..d6b30be58 100644 --- a/test/real-world-zapps/Escrow.zol +++ b/test/real-world-zapps/Escrow.zol @@ -11,8 +11,8 @@ contract Escrow { secret mapping(address => uint256) public balances; IERC20 public erc20; - constructor(address _erc20) { - erc20 = IERC20(_erc20); + constructor(address erc20Address) { + erc20 = IERC20(erc20Address); } function deposit(uint256 amount) public { From dc7e8bbf37c5b69e225c616f81d94cbad5c9f08f Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Tue, 26 Mar 2024 11:02:51 +0000 Subject: [PATCH 2/6] chore: added the code for split Commitments --- circuits/common/splitCommitments.zok | 141 +++ src/boilerplate/common/commitment-storage.mjs | 907 +++++++++++------- .../nodes/ContractBoilerplateGenerator.ts | 16 +- .../raw/ContractBoilerplateGenerator.ts | 49 +- .../javascript/raw/boilerplate-generator.ts | 14 +- .../circuit/zokrates/toCircuit.ts | 5 + src/transformers/visitors/toCircuitVisitor.ts | 4 +- 7 files changed, 783 insertions(+), 353 deletions(-) create mode 100644 circuits/common/splitCommitments.zok diff --git a/circuits/common/splitCommitments.zok b/circuits/common/splitCommitments.zok new file mode 100644 index 000000000..263302c22 --- /dev/null +++ b/circuits/common/splitCommitments.zok @@ -0,0 +1,141 @@ +from "ecc/babyjubjubParams" import main as curveParams +from "ecc/edwardsScalarMult" import main as scalarMult +from "ecc/edwardsCompress" import main as edwardsCompress +from "utils/pack/u32/nonStrictUnpack256.zok" import main as field_to_u32_8 +from "hashes/sha256/sha256Padded.zok" import sha256Padded as sha256Padded +from "./common/hashes/mimc/altbn254/mimc2.zok" import main as mimc2 +from "utils/pack/bool/nonStrictUnpack256.zok" import main as field_to_bool_256 +from "utils/casts/u32_8_to_bool_256.zok" import main as u32_8_to_bool_256 +from "./common/hashes/poseidon/poseidon.zok" import main as poseidon +from "./common/casts/u32_array_to_field.zok" import main as u32_array_to_field +from "utils/pack/bool/pack256.zok" import main as bool_256_to_field +from "./common/merkle-tree/mimc/altbn254/verify-membership/height32.zok" import main as checkRoot +from "./common/merkle-tree/sparse-merkle-tree/checkproof.zok" import checkUpdatedPath as checkUpdatedPath +from "./common/merkle-tree/sparse-merkle-tree/checkproof.zok" import main as checkproof + +def main(\ + private field value,\ + private field fromId,\ + private field stateVarId,\ + private bool isMapping,\ + private field oldCommitment_0_owner_secretKey_field,\ + public field nullifierRoot,\ + public field newNullifierRoot,\ + public field oldCommitment_0_nullifier,\ + public field[32] oldCommitment_0_nullifier_nonmembershipWitness_siblingPath,\ + private field[32] oldCommitment_0_nullifier_nonmembershipWitness_newsiblingPath,\ + private field oldCommitment_0_value,\ + private field oldCommitment_0_salt_field,\ + public field commitmentRoot,\ + private field oldCommitment_0_membershipWitness_index,\ + private field[32] oldCommitment_0_membershipWitness_siblingPath,\ + private field newCommitment_0_owner_publicKey_field,\ + private field newCommitment_0_salt_field,\ + public field newCommitment_0_commitment\ + private field newCommitment_1_owner_publicKey_field,\ + private field newCommitment_1_salt_field,\ + public field newCommitment_1_commitment\ +) -> (bool) : + +// check if state is mapping or not + + field oldCommitment_0_stateVarId_field = if isMapping == true then mimc2([stateVarId, fromId]) else stateVarId fi + + + field newCommitment_stateVarId_field = if isMapping == true then mimc2([stateVarId, fromId]) else stateVarId fi + + + u32[8] newCommitment_stateVarId = field_to_u32_8(newCommitment_stateVarId_field) + + + field oldCommitment_0 = oldCommitment_0_value + + // oldCommitment_0 - PoKoSK: + // The correctness of this secret key will be constrained within the oldCommitment existence check. + + field[2] oldCommitment_0_owner_publicKey_point = scalarMult(field_to_bool_256(oldCommitment_0_owner_secretKey_field), [curveParams().Gu, curveParams().Gv], curveParams()) + + bool oldCommitment_0_owner_publicKey_sign = edwardsCompress(oldCommitment_0_owner_publicKey_point)[0] + + bool[254] yBits = field_to_bool_256(oldCommitment_0_owner_publicKey_point[1])[2..256] + yBits[0] = oldCommitment_0_owner_publicKey_sign + + field oldCommitment_0_owner_publicKey_field = bool_256_to_field([false, false, ...yBits]) + + // Nullify oldCommitment_0: + + field oldCommitment_0_nullifier_check_field = poseidon([\ + oldCommitment_0_stateVarId_field,\ + oldCommitment_0_owner_secretKey_field,\ + oldCommitment_0_salt_field\ + ]) + + assert(\ + field_to_bool_256(oldCommitment_0_nullifier)[8..256] == field_to_bool_256(oldCommitment_0_nullifier_check_field)[8..256]\ + ) + + assert(\ + nullifierRoot == checkproof(\ + oldCommitment_0_nullifier_nonmembershipWitness_siblingPath,\ + oldCommitment_0_nullifier\ + ) ) + + assert( newNullifierRoot == checkUpdatedPath(oldCommitment_0_nullifier_nonmembershipWitness_newsiblingPath,\ + oldCommitment_0_nullifier) ) + + // oldCommitment_0_commitment: preimage check + + field oldCommitment_0_commitment_field = poseidon([\ + oldCommitment_0_stateVarId_field,\ + oldCommitment_0,\ + oldCommitment_0_owner_publicKey_field,\ + oldCommitment_0_salt_field\ + ]) + + // oldCommitment_0_commitment: existence check + + field oldCommitment_0_commitmentRoot_check = checkRoot(\ + oldCommitment_0_membershipWitness_siblingPath,\ + oldCommitment_0_commitment_field,\ + oldCommitment_0_membershipWitness_index\ + ) + + + assert(\ + field_to_bool_256(commitmentRoot)[8..256] == field_to_bool_256(oldCommitment_0_commitmentRoot_check)[8..256]\ + ) + + + // prepare secret state 'newCommitments' for commitments + + + + field newCommitment_0_value_field = value + field newCommitment_1_value_field = oldCommitment_0_value - value + // preimage check - newCommitment_commitment + + field newCommitment_0_commitment_check_field = poseidon([\ + newCommitment_stateVarId_field,\ + newCommitment_0_value_field,\ + newCommitment_0_owner_publicKey_field,\ + newCommitment_0_salt_field\ + ]) + + assert(\ + field_to_bool_256(newCommitment_0_commitment)[8..256] == field_to_bool_256(newCommitment_0_commitment_check_field)[8..256]\ + ) + + // preimage check - newCommitment_commitment + + field newCommitment_1_commitment_check_field = poseidon([\ + newCommitment_stateVarId_field,\ + newCommitment_1_value_field,\ + newCommitment_1_owner_publicKey_field,\ + newCommitment_1_salt_field\ + ]) + + assert(\ + field_to_bool_256(newCommitment_1_commitment)[8..256] == field_to_bool_256(newCommitment_1_commitment_check_field)[8..256]\ + ) + + return true diff --git a/src/boilerplate/common/commitment-storage.mjs b/src/boilerplate/common/commitment-storage.mjs index e1cd8234a..1d672dcd5 100644 --- a/src/boilerplate/common/commitment-storage.mjs +++ b/src/boilerplate/common/commitment-storage.mjs @@ -1,3 +1,4 @@ +/* eslint-disable camelcase */ /* eslint-disable import/no-cycle */ /** Logic for storing and retrieving commitments from a mongo DB. @@ -6,7 +7,7 @@ import config from 'config'; import gen from 'general-number'; import mongo from './mongo.mjs'; import logger from './logger.mjs'; -import utils from "zkp-utils"; +import utils from 'zkp-utils'; import { poseidonHash } from './number-theory.mjs'; import { generateProof } from './zokrates.mjs'; import { @@ -212,7 +213,7 @@ export async function markNullified(commitmentHash, secretKey = null) { } export function getInputCommitments( - contractName, + contractName, publicKey, value, commitments, @@ -242,9 +243,6 @@ export function getInputCommitments( possibleCommitments.length === 1 && commitmentsSum >= parseInt(value, 10) ) { - logger.warn( - 'Only one commitment exists, but it is enough to use. Calling Split Commitment circuit. It will generate proof to split commitments, this will require an on-chain verification', - ); return [true, possibleCommitments[0], null]; } possibleCommitments.sort( @@ -252,7 +250,7 @@ export function getInputCommitments( parseInt(commitB.preimage.value, 10) - parseInt(commitA.preimage.value, 10), ); - + if ( parseInt(possibleCommitments[0].preimage.value, 10) + parseInt(possibleCommitments[1].preimage.value, 10) >= @@ -265,357 +263,592 @@ export function getInputCommitments( return null; } -function getStructInputCommitments( - value, - possibleCommitments -) { - if (possibleCommitments.length < 2) { - logger.warn('Enough Commitments dont exists to use.' ) - return null; - } - let possibleCommitmentsProp = []; - value.forEach((propValue, i) => { - let possibleCommitmentsTemp = []; - possibleCommitments.sort( - (commitA, commitB) => - parseInt(Object.values(commitB.preimage.value)[i], 10) - - parseInt(Object.values(commitA.preimage.value)[i], 10) - ); - if (!possibleCommitmentsProp.length) { - if ( - parseInt(Object.values(possibleCommitments[0].preimage.value)[i], 10) + - parseInt(Object.values(possibleCommitments[1].preimage.value)[i], 10) >= - parseInt(propValue, 10) - ) { - possibleCommitmentsProp.push([ - possibleCommitments[0], - possibleCommitments[1], - ]); - } else { - possibleCommitments.splice(0,2); - possibleCommitmentsProp = getStructInputCommitments(value, possibleCommitments); - } - } else { - possibleCommitments.forEach((possibleCommit) => { - if (possibleCommitmentsProp.includes(possibleCommit)) possibleCommitmentsTemp.push(possibleCommit); - }); - if ( - possibleCommitmentsTemp.length > 1 && - parseInt(Object.values(possibleCommitmentsTemp[0].preimage.value)[i], 10) + - parseInt(Object.values(possibleCommitmentsTemp[1].preimage.value)[i], 10) < - parseInt(propValue, 10) - ) { - possibleCommitments.splice(0,2); - possibleCommitmentsProp = getStructInputCommitments(value, possibleCommitments); - } - } - }); - return possibleCommitmentsProp; +function getStructInputCommitments(value, possibleCommitments) { + if (possibleCommitments.length < 2) { + logger.warn('Enough Commitments dont exists to use.'); + return null; + } + let possibleCommitmentsProp = []; + value.forEach((propValue, i) => { + let possibleCommitmentsTemp = []; + possibleCommitments.sort( + (commitA, commitB) => + parseInt(Object.values(commitB.preimage.value)[i], 10) - + parseInt(Object.values(commitA.preimage.value)[i], 10), + ); + if (!possibleCommitmentsProp.length) { + if ( + parseInt(Object.values(possibleCommitments[0].preimage.value)[i], 10) + + parseInt( + Object.values(possibleCommitments[1].preimage.value)[i], + 10, + ) >= + parseInt(propValue, 10) + ) { + possibleCommitmentsProp.push([ + possibleCommitments[0], + possibleCommitments[1], + ]); + } else { + possibleCommitments.splice(0, 2); + possibleCommitmentsProp = getStructInputCommitments( + value, + possibleCommitments, + ); + } + } else { + possibleCommitments.forEach(possibleCommit => { + if (possibleCommitmentsProp.includes(possibleCommit)) + possibleCommitmentsTemp.push(possibleCommit); + }); + if ( + possibleCommitmentsTemp.length > 1 && + parseInt( + Object.values(possibleCommitmentsTemp[0].preimage.value)[i], + 10, + ) + + parseInt( + Object.values(possibleCommitmentsTemp[1].preimage.value)[i], + 10, + ) < + parseInt(propValue, 10) + ) { + possibleCommitments.splice(0, 2); + possibleCommitmentsProp = getStructInputCommitments( + value, + possibleCommitments, + ); + } + } + }); + return possibleCommitmentsProp; } export async function joinCommitments( - contractName, - statename, - secretKey, - publicKey, - stateVarId, - commitments, - witnesses, - instance, - contractAddr, - web3, + contractName, + statename, + secretKey, + publicKey, + stateVarId, + commitments, + witnesses, + instance, + contractAddr, + web3, ) { - logger.warn( - "Existing Commitments are not appropriate and we need to call Join Commitment Circuit. It will generate proof to join commitments, this will require an on-chain verification" - ); - - const oldCommitment_0_prevSalt = generalise(commitments[0].preimage.salt); - const oldCommitment_1_prevSalt = generalise(commitments[1].preimage.salt); - const oldCommitment_0_prev = generalise(commitments[0].preimage.value); - const oldCommitment_1_prev = generalise(commitments[1].preimage.value); - - // Extract set membership witness: - - const oldCommitment_0_witness = witnesses[0]; - const oldCommitment_1_witness = witnesses[1]; - - const oldCommitment_0_index = generalise(oldCommitment_0_witness.index); - const oldCommitment_1_index = generalise(oldCommitment_1_witness.index); - const oldCommitment_root = generalise(oldCommitment_0_witness.root); - const oldCommitment_0_path = generalise(oldCommitment_0_witness.path).all; - const oldCommitment_1_path = generalise(oldCommitment_1_witness.path).all; - - // increment would go here but has been filtered out - - // Calculate nullifier(s): - - let oldCommitment_stateVarId = stateVarId[0]; - if (stateVarId.length > 1) { - oldCommitment_stateVarId = generalise( - utils.mimcHash( - [generalise(stateVarId[0]).bigInt, generalise(stateVarId[1]).bigInt], - "ALT_BN_254" - ) - ).hex(32); - } - - let oldCommitment_0_nullifier = poseidonHash([ - BigInt(oldCommitment_stateVarId), - BigInt(secretKey.hex(32)), - BigInt(oldCommitment_0_prevSalt.hex(32)), - ]); - let oldCommitment_1_nullifier = poseidonHash([ - BigInt(oldCommitment_stateVarId), - BigInt(secretKey.hex(32)), - BigInt(oldCommitment_1_prevSalt.hex(32)), - ]); - oldCommitment_0_nullifier = generalise(oldCommitment_0_nullifier.hex(32)); // truncate - oldCommitment_1_nullifier = generalise(oldCommitment_1_nullifier.hex(32)); // truncate - - // Non-membership witness for Nullifier - const oldCommitment_0_nullifier_NonMembership_witness = getnullifierMembershipWitness( - oldCommitment_0_nullifier - ); - const oldCommitment_1_nullifier_NonMembership_witness = getnullifierMembershipWitness( - oldCommitment_1_nullifier - ); - - const oldCommitment_nullifierRoot = generalise(oldCommitment_0_nullifier_NonMembership_witness.root); - const oldCommitment_0_nullifier_path = generalise( - oldCommitment_0_nullifier_NonMembership_witness.path - ).all; - const oldCommitment_1_nullifier_path = generalise( - oldCommitment_1_nullifier_NonMembership_witness.path - ).all; - - - await temporaryUpdateNullifier(a_0_nullifier); - await temporaryUpdateNullifier(a_1_nullifier); - - const oldCommitment_0_updated_nullifier_NonMembership_witness = getupdatedNullifierPaths( - oldCommitment_0_nullifier - ); - const oldCommitment_1_updated_nullifier_NonMembership_witness = getupdatedNullifierPaths( - oldCommitment_1_nullifier - ); - - const oldCommitment_0_nullifier_newpath = generalise( - oldCommitment_0_updated_nullifier_NonMembership_witness.path - ).all; - const oldCommitment_1_nullifier_newpath = generalise( - oldCommitment_1_updated_nullifier_NonMembership_witness.path - ).all; - const oldCommitment_newNullifierRoot = generalise(oldCommitment_0_updated_nullifier_NonMembership_witness.root); - // Calculate commitment(s): - - const newCommitment_newSalt = generalise(utils.randomHex(31)); - - let newCommitment_value = - parseInt(oldCommitment_0_prev.integer, 10) + - parseInt(oldCommitment_1_prev.integer, 10); - - newCommitment_value = generalise(newCommitment_value); - - let newCommitment = poseidonHash([ - BigInt(oldCommitment_stateVarId), - BigInt(newCommitment_value.hex(32)), - BigInt(publicKey.hex(32)), - BigInt(newCommitment_newSalt.hex(32)), - ]); - - newCommitment = generalise(newCommitment.hex(32)); // truncate - - let stateVarID = parseInt(oldCommitment_stateVarId, 16); - let fromID = 0; - let isMapping = 0; - if (stateVarId.length > 1) { - stateVarID = stateVarId[0]; - fromID = stateVarId[1].integer; - isMapping = 1; - } - - // Call Zokrates to generate the proof: - const allInputs = [ - fromID, - stateVarID, - isMapping, - secretKey.integer, - secretKey.integer, - - oldCommitment_nullifierRoot.integer, - oldCommitment_newNullifierRoot.integer, - oldCommitment_0_nullifier.integer, - oldCommitment_0_nullifier_path.integer, - oldCommitment_0_nullifier_newpath.integer, - oldCommitment_1_nullifier.integer, - oldCommitment_1_nullifier_path.integer, - oldCommitment_1_nullifier_newpath.integer, - oldCommitment_0_prev.integer, - oldCommitment_0_prevSalt.integer, - oldCommitment_1_prev.integer, - oldCommitment_1_prevSalt.integer, - oldCommitment_root.integer, - oldCommitment_0_index.integer, - oldCommitment_0_path.integer, - oldCommitment_1_index.integer, - oldCommitment_1_path.integer, - publicKey.integer, - newCommitment_newSalt.integer, - newCommitment.integer, - ].flat(Infinity); + logger.warn( + 'Existing Commitments are not appropriate and we need to call Join Commitment Circuit. It will generate proof to join commitments, this will require an on-chain verification', + ); + + const oldCommitment_0_prevSalt = generalise(commitments[0].preimage.salt); + const oldCommitment_1_prevSalt = generalise(commitments[1].preimage.salt); + const oldCommitment_0_prev = generalise(commitments[0].preimage.value); + const oldCommitment_1_prev = generalise(commitments[1].preimage.value); + + // Extract set membership witness: + + const oldCommitment_0_witness = witnesses[0]; + const oldCommitment_1_witness = witnesses[1]; + + const oldCommitment_0_index = generalise(oldCommitment_0_witness.index); + const oldCommitment_1_index = generalise(oldCommitment_1_witness.index); + const oldCommitment_root = generalise(oldCommitment_0_witness.root); + const oldCommitment_0_path = generalise(oldCommitment_0_witness.path).all; + const oldCommitment_1_path = generalise(oldCommitment_1_witness.path).all; + + // increment would go here but has been filtered out + + // Calculate nullifier(s): + + let oldCommitment_stateVarId = stateVarId[0]; + if (stateVarId.length > 1) { + oldCommitment_stateVarId = generalise( + utils.mimcHash( + [generalise(stateVarId[0]).bigInt, generalise(stateVarId[1]).bigInt], + 'ALT_BN_254', + ), + ).hex(32); + } + + let oldCommitment_0_nullifier = poseidonHash([ + BigInt(oldCommitment_stateVarId), + BigInt(secretKey.hex(32)), + BigInt(oldCommitment_0_prevSalt.hex(32)), + ]); + let oldCommitment_1_nullifier = poseidonHash([ + BigInt(oldCommitment_stateVarId), + BigInt(secretKey.hex(32)), + BigInt(oldCommitment_1_prevSalt.hex(32)), + ]); + oldCommitment_0_nullifier = generalise(oldCommitment_0_nullifier.hex(32)); // truncate + oldCommitment_1_nullifier = generalise(oldCommitment_1_nullifier.hex(32)); // truncate + + // Non-membership witness for Nullifier + const oldCommitment_0_nullifier_NonMembership_witness = getnullifierMembershipWitness( + oldCommitment_0_nullifier, + ); + const oldCommitment_1_nullifier_NonMembership_witness = getnullifierMembershipWitness( + oldCommitment_1_nullifier, + ); + + const oldCommitment_nullifierRoot = generalise( + oldCommitment_0_nullifier_NonMembership_witness.root, + ); + const oldCommitment_0_nullifier_path = generalise( + oldCommitment_0_nullifier_NonMembership_witness.path, + ).all; + const oldCommitment_1_nullifier_path = generalise( + oldCommitment_1_nullifier_NonMembership_witness.path, + ).all; + + await temporaryUpdateNullifier(a_0_nullifier); + await temporaryUpdateNullifier(a_1_nullifier); + + const oldCommitment_0_updated_nullifier_NonMembership_witness = getupdatedNullifierPaths( + oldCommitment_0_nullifier, + ); + const oldCommitment_1_updated_nullifier_NonMembership_witness = getupdatedNullifierPaths( + oldCommitment_1_nullifier, + ); + + const oldCommitment_0_nullifier_newpath = generalise( + oldCommitment_0_updated_nullifier_NonMembership_witness.path, + ).all; + const oldCommitment_1_nullifier_newpath = generalise( + oldCommitment_1_updated_nullifier_NonMembership_witness.path, + ).all; + const oldCommitment_newNullifierRoot = generalise( + oldCommitment_0_updated_nullifier_NonMembership_witness.root, + ); + // Calculate commitment(s): + + const newCommitment_newSalt = generalise(utils.randomHex(31)); + + let newCommitment_value = + parseInt(oldCommitment_0_prev.integer, 10) + + parseInt(oldCommitment_1_prev.integer, 10); + + newCommitment_value = generalise(newCommitment_value); + + let newCommitment = poseidonHash([ + BigInt(oldCommitment_stateVarId), + BigInt(newCommitment_value.hex(32)), + BigInt(publicKey.hex(32)), + BigInt(newCommitment_newSalt.hex(32)), + ]); + + newCommitment = generalise(newCommitment.hex(32)); // truncate + + let stateVarID = parseInt(oldCommitment_stateVarId, 16); + let fromID = 0; + let isMapping = 0; + if (stateVarId.length > 1) { + stateVarID = stateVarId[0]; + fromID = stateVarId[1].integer; + isMapping = 1; + } + + // Call Zokrates to generate the proof: + const allInputs = [ + fromID, + stateVarID, + isMapping, + secretKey.integer, + secretKey.integer, + + oldCommitment_nullifierRoot.integer, + oldCommitment_newNullifierRoot.integer, + oldCommitment_0_nullifier.integer, + oldCommitment_0_nullifier_path.integer, + oldCommitment_0_nullifier_newpath.integer, + oldCommitment_1_nullifier.integer, + oldCommitment_1_nullifier_path.integer, + oldCommitment_1_nullifier_newpath.integer, + oldCommitment_0_prev.integer, + oldCommitment_0_prevSalt.integer, + oldCommitment_1_prev.integer, + oldCommitment_1_prevSalt.integer, + oldCommitment_root.integer, + oldCommitment_0_index.integer, + oldCommitment_0_path.integer, + oldCommitment_1_index.integer, + oldCommitment_1_path.integer, + publicKey.integer, + newCommitment_newSalt.integer, + newCommitment.integer, + ].flat(Infinity); const res = await generateProof('joinCommitments', allInputs); - const proof = generalise(Object.values(res.proof).flat(Infinity)) - .map((coeff) => coeff.integer) - .flat(Infinity); - // Send transaction to the blockchain: - - const txData = await instance.methods - .joinCommitments( - oldCommitment_nullifierRoot.integer, - oldCommitment_newNullifierRoot.integer, - [oldCommitment_0_nullifier.integer, oldCommitment_1_nullifier.integer], - oldCommitment_root.integer, - [newCommitment.integer], - proof - ).encodeABI(); - - let txParams = { - from: config.web3.options.defaultAccount, - to: contractAddr, - gas: config.web3.options.defaultGas, - gasPrice: config.web3.options.defaultGasPrice, - data: txData, - chainId: await web3.eth.net.getId(), - }; - - const key = config.web3.key; - - const signed = await web3.eth.accounts.signTransaction(txParams, key); - - const sendTxn = await web3.eth.sendSignedTransaction(signed.rawTransaction); - - let tx = await instance.getPastEvents("allEvents"); - - tx = tx[0]; - - await markNullified(generalise(commitments[0]._id), secretKey.hex(32)); - await markNullified(generalise(commitments[1]._id), secretKey.hex(32)); - await storeCommitment({ - hash: newCommitment, - name: statename, - mappingKey: fromID, - preimage: { - stateVarId: generalise(oldCommitment_stateVarId), - value: newCommitment_value, - salt: newCommitment_newSalt, - publicKey: publicKey, - }, - secretKey: secretKey, - isNullified: false, - }); - - return { tx }; + const proof = generalise(Object.values(res.proof).flat(Infinity)) + .map(coeff => coeff.integer) + .flat(Infinity); + // Send transaction to the blockchain: + + const txData = await instance.methods + .joinCommitments( + oldCommitment_nullifierRoot.integer, + oldCommitment_newNullifierRoot.integer, + [oldCommitment_0_nullifier.integer, oldCommitment_1_nullifier.integer], + oldCommitment_root.integer, + [newCommitment.integer], + proof, + ) + .encodeABI(); + + let txParams = { + from: config.web3.options.defaultAccount, + to: contractAddr, + gas: config.web3.options.defaultGas, + gasPrice: config.web3.options.defaultGasPrice, + data: txData, + chainId: await web3.eth.net.getId(), + }; + + const key = config.web3.key; + + const signed = await web3.eth.accounts.signTransaction(txParams, key); + + const sendTxn = await web3.eth.sendSignedTransaction(signed.rawTransaction); + + let tx = await instance.getPastEvents('allEvents'); + + tx = tx[0]; + + await markNullified(generalise(commitments[0]._id), secretKey.hex(32)); + await markNullified(generalise(commitments[1]._id), secretKey.hex(32)); + await storeCommitment({ + hash: newCommitment, + name: statename, + mappingKey: fromID, + preimage: { + stateVarId: generalise(oldCommitment_stateVarId), + value: newCommitment_value, + salt: newCommitment_newSalt, + publicKey: publicKey, + }, + secretKey: secretKey, + isNullified: false, + }); + + return { tx }; } +export async function splitCommitments( + contractName, + statename, + value, + secretKey, + publicKey, + stateVarId, + commitment, + witness, + instance, + contractAddr, + web3, +) { + logger.warn( + 'Only one commitment exists, but it is enough to use. Calling Split Commitment circuit. It will generate proof to split commitments, this will require an on-chain verification', + ); + + const oldCommitment_0_prevSalt = generalise(commitment.preimage.salt); + const oldCommitment_0_prev = generalise(commitment.preimage.value); - // This is a helper function for checkMembership -const _getnullifierMembershipWitness = (binArr, element, tree, acc) => { - switch (tree.tag) { - case 'branch': - return binArr[0] === '0' - ? _getnullifierMembershipWitness( - binArr.slice(1), - element, - tree.left, - [getHash(tree.right) ].concat(acc), - ) - : _getnullifierMembershipWitness( - binArr.slice(1), - element, - tree.right, - [getHash(tree.left)].concat(acc), - ); - case "leaf": { - if (binArr.length > 0) { - while (binArr.length > 0) { - binArr[0] === "0" - ? (acc = [hlt[TRUNC_LENGTH - (binArr.length - 1)]].concat(acc)) - : (acc = [hlt[TRUNC_LENGTH - (binArr.length - 1)]].concat(acc)); - binArr = binArr.slice(1); - } - return { isMember: false, path: acc }; - } else { - return tree.val !== element - ? { isMember: false, path: acc } - : { isMember: true, path: acc }; - } - } - default: - return tree; - } + // Extract set membership witness: + + const oldCommitment_0_witness = witnesses; + + const oldCommitment_0_index = generalise(oldCommitment_0_witness.index); + const oldCommitment_root = generalise(oldCommitment_0_witness.root); + const oldCommitment_0_path = generalise(oldCommitment_0_witness.path).all; + + // increment would go here but has been filtered out + + // Calculate nullifier(s): + + let oldCommitment_stateVarId = stateVarId[0]; + if (stateVarId.length > 1) { + oldCommitment_stateVarId = generalise( + utils.mimcHash( + [generalise(stateVarId[0]).bigInt, generalise(stateVarId[1]).bigInt], + 'ALT_BN_254', + ), + ).hex(32); + } + + let oldCommitment_0_nullifier = poseidonHash([ + BigInt(oldCommitment_stateVarId), + BigInt(secretKey.hex(32)), + BigInt(oldCommitment_0_prevSalt.hex(32)), + ]); + + oldCommitment_0_nullifier = generalise(oldCommitment_0_nullifier.hex(32)); // truncate + + // Non-membership witness for Nullifier + const oldCommitment_0_nullifier_NonMembership_witness = getnullifierMembershipWitness( + oldCommitment_0_nullifier, + ); + + const oldCommitment_nullifierRoot = generalise( + oldCommitment_0_nullifier_NonMembership_witness.root, + ); + const oldCommitment_0_nullifier_path = generalise( + oldCommitment_0_nullifier_NonMembership_witness.path, + ).all; + + await temporaryUpdateNullifier(oldCommitment_0_nullifier); + + const oldCommitment_0_updated_nullifier_NonMembership_witness = getupdatedNullifierPaths( + oldCommitment_0_nullifier, + ); + + const oldCommitment_0_nullifier_newpath = generalise( + oldCommitment_0_updated_nullifier_NonMembership_witness.path, + ).all; + + const oldCommitment_newNullifierRoot = generalise( + oldCommitment_0_updated_nullifier_NonMembership_witness.root, + ); + // Calculate commitment(s): + + const newCommitment_0_newSalt = generalise(utils.randomHex(31)); + + let newCommitment_0_value = parseInt(value.integer, 10); + + newCommitment_0_value = generalise(newCommitment_0_value); + + let newCommitment_0 = poseidonHash([ + BigInt(oldCommitment_stateVarId), + BigInt(newCommitment_0_value.hex(32)), + BigInt(publicKey.hex(32)), + BigInt(newCommitment_0_newSalt.hex(32)), + ]); + + newCommitment_1 = generalise(newCommitment_1.hex(32)); // truncate + + const newCommitment_1_newSalt = generalise(utils.randomHex(31)); + + let newCommitment_1_value = parseInt(oldCommitment_0_prev.integer, 10) - parseInt(value.integer, 10); + + newCommitment_1_value = generalise(newCommitment_1_value); + + let newCommitment_1 = poseidonHash([ + BigInt(oldCommitment_stateVarId), + BigInt(newCommitment_1_value.hex(32)), + BigInt(publicKey.hex(32)), + BigInt(newCommitment_1_newSalt.hex(32)), + ]); + + newCommitment_1 = generalise(newCommitment_1.hex(32)); // truncate + + let stateVarID = parseInt(oldCommitment_stateVarId, 16); + let fromID = 0; + let isMapping = 0; + if (stateVarId.length > 1) { + stateVarID = stateVarId[0]; + fromID = stateVarId[1].integer; + isMapping = 1; + } + + // Call Zokrates to generate the proof: + const allInputs = [ + value.integer, + fromID, + stateVarID, + isMapping, + secretKey.integer, + + oldCommitment_nullifierRoot.integer, + oldCommitment_newNullifierRoot.integer, + oldCommitment_0_nullifier.integer, + oldCommitment_0_nullifier_path.integer, + oldCommitment_0_nullifier_newpath.integer, + oldCommitment_0_prev.integer, + oldCommitment_0_prevSalt.integer, + oldCommitment_root.integer, + oldCommitment_0_index.integer, + oldCommitment_0_path.integer, + publicKey.integer, + newCommitment_0_newSalt.integer, + newCommitment_0.integer, + publicKey.integer, + newCommitment_1_newSalt.integer, + newCommitment_1.integer, + ].flat(Infinity); + + const res = await generateProof('splitCommitments', allInputs); + const proof = generalise(Object.values(res.proof).flat(Infinity)) + .map(coeff => coeff.integer) + .flat(Infinity); + // Send transaction to the blockchain: + + const txData = await instance.methods + .splitCommitments( + oldCommitment_nullifierRoot.integer, + oldCommitment_newNullifierRoot.integer, + [oldCommitment_0_nullifier.integer.integer], + oldCommitment_root.integer, + [newCommitment_0.integer, newCommitment_1.integer], + proof, + ) + .encodeABI(); + + let txParams = { + from: config.web3.options.defaultAccount, + to: contractAddr, + gas: config.web3.options.defaultGas, + gasPrice: config.web3.options.defaultGasPrice, + data: txData, + chainId: await web3.eth.net.getId(), }; -export async function updateNullifierTree() { - smt_tree = temp_smt_tree; -} + const key = config.web3.key; + const signed = await web3.eth.accounts.signTransaction(txParams, key); -export function getnullifierMembershipWitness(nullifier) { + const sendTxn = await web3.eth.sendSignedTransaction(signed.rawTransaction); + + let tx = await instance.getPastEvents('allEvents'); + + tx = tx[0]; + + await markNullified(generalise(commitment._id), secretKey.hex(32)); + + await storeCommitment({ + hash: newCommitment_0, + name: statename, + mappingKey: fromID, + preimage: { + stateVarId: generalise(oldCommitment_stateVarId), + value: newCommitment_0_value, + salt: newCommitment_0_newSalt, + publicKey: publicKey, + }, + secretKey: secretKey, + isNullified: false, + }); - const binArr = toBinArray(generalise(nullifier)) - const padBinArr = Array(254 - binArr.length) - .fill("0") - .concat(...binArr).slice(0, TRUNC_LENGTH); - const membershipPath = _getnullifierMembershipWitness(padBinArr, nullifier, smt_tree, []); - const root = getHash(smt_tree); - const witness = {path : membershipPath.path, root: root} - return witness; + await storeCommitment({ + hash: newCommitment_1, + name: statename, + mappingKey: fromID, + preimage: { + stateVarId: generalise(oldCommitment_stateVarId), + value: newCommitment_1_value, + salt: newCommitment_1_newSalt, + publicKey: publicKey, + }, + secretKey: secretKey, + isNullified: false, + }); + return { tx }; } -export async function temporaryUpdateNullifier(nullifier){ - - temp_smt_tree = insertLeaf(generalise(nullifier).hex(32), temp_smt_tree); - +// This is a helper function for checkMembership +const _getnullifierMembershipWitness = (binArr, element, tree, acc) => { + switch (tree.tag) { + case 'branch': + return binArr[0] === '0' + ? _getnullifierMembershipWitness( + binArr.slice(1), + element, + tree.left, + [getHash(tree.right)].concat(acc), + ) + : _getnullifierMembershipWitness( + binArr.slice(1), + element, + tree.right, + [getHash(tree.left)].concat(acc), + ); + case 'leaf': { + if (binArr.length > 0) { + while (binArr.length > 0) { + binArr[0] === '0' + ? (acc = [hlt[TRUNC_LENGTH - (binArr.length - 1)]].concat(acc)) + : (acc = [hlt[TRUNC_LENGTH - (binArr.length - 1)]].concat(acc)); + binArr = binArr.slice(1); + } + return { isMember: false, path: acc }; + } else { + return tree.val !== element + ? { isMember: false, path: acc } + : { isMember: true, path: acc }; + } + } + default: + return tree; + } +}; + +export async function updateNullifierTree() { + smt_tree = temp_smt_tree; } -export async function reinstateNullifiers() { - const initialised = []; - const nullifiedCommitments = await getNullifiedCommitments(); - if (!nullifiedCommitments) { - logger.info('No nullifiers to add to the tree'); - return; - } - logger.warn( - 'Reinstatiating nullifiers - NOTE that any nullifiers added from another client may not be known here, so the tree will be out of sync.', - ); - for (const c of nullifiedCommitments) { - if (WHOLE_STATES.includes(c.name) && !initialised.includes(c.preimage.stateVarId)) { - logger.debug(`initialising state ${c.name}`); - smt_tree = insertLeaf(poseidonHash([BigInt(c.preimage.stateVarId), BigInt(0), BigInt(0)]).hex(32), smt_tree); - initialised.push(c.preimage.stateVarId); - } - logger.debug(`nullifying state ${c.name}: ${c.nullifier}`); - smt_tree = insertLeaf(c.nullifier, smt_tree); - } - temp_smt_tree = smt_tree; +export function getnullifierMembershipWitness(nullifier) { + const binArr = toBinArray(generalise(nullifier)); + const padBinArr = Array(254 - binArr.length) + .fill('0') + .concat(...binArr) + .slice(0, TRUNC_LENGTH); + const membershipPath = _getnullifierMembershipWitness( + padBinArr, + nullifier, + smt_tree, + [], + ); + const root = getHash(smt_tree); + const witness = { path: membershipPath.path, root: root }; + return witness; +} + +export async function temporaryUpdateNullifier(nullifier) { + temp_smt_tree = insertLeaf(generalise(nullifier).hex(32), temp_smt_tree); } -export function getupdatedNullifierPaths(nullifier){ - const binArr = toBinArray(generalise(nullifier)); - const padBinArr = Array(254 - binArr.length) - .fill("0") - .concat(...binArr) - .slice(0, TRUNC_LENGTH); - const membershipPath = _getnullifierMembershipWitness( - padBinArr, - nullifier, - temp_smt_tree, - [] - ); - const root = getHash(temp_smt_tree); - const witness = { path: membershipPath.path, root: root }; - return witness; +export async function reinstateNullifiers() { + const initialised = []; + const nullifiedCommitments = await getNullifiedCommitments(); + if (!nullifiedCommitments) { + logger.info('No nullifiers to add to the tree'); + return; + } + logger.warn( + 'Reinstatiating nullifiers - NOTE that any nullifiers added from another client may not be known here, so the tree will be out of sync.', + ); + for (const c of nullifiedCommitments) { + if ( + WHOLE_STATES.includes(c.name) && + !initialised.includes(c.preimage.stateVarId) + ) { + logger.debug(`initialising state ${c.name}`); + smt_tree = insertLeaf( + poseidonHash([BigInt(c.preimage.stateVarId), BigInt(0), BigInt(0)]).hex( + 32, + ), + smt_tree, + ); + initialised.push(c.preimage.stateVarId); + } + logger.debug(`nullifying state ${c.name}: ${c.nullifier}`); + smt_tree = insertLeaf(c.nullifier, smt_tree); + } + temp_smt_tree = smt_tree; } +export function getupdatedNullifierPaths(nullifier) { + const binArr = toBinArray(generalise(nullifier)); + const padBinArr = Array(254 - binArr.length) + .fill('0') + .concat(...binArr) + .slice(0, TRUNC_LENGTH); + const membershipPath = _getnullifierMembershipWitness( + padBinArr, + nullifier, + temp_smt_tree, + [], + ); + const root = getHash(temp_smt_tree); + const witness = { path: membershipPath.path, root: root }; + return witness; +} diff --git a/src/boilerplate/contract/solidity/nodes/ContractBoilerplateGenerator.ts b/src/boilerplate/contract/solidity/nodes/ContractBoilerplateGenerator.ts index 010840cfa..9bea62e34 100644 --- a/src/boilerplate/contract/solidity/nodes/ContractBoilerplateGenerator.ts +++ b/src/boilerplate/contract/solidity/nodes/ContractBoilerplateGenerator.ts @@ -57,6 +57,8 @@ class ContractBoilerplateGenerator { 'verify', 'joinCommitmentsFunction', 'joinCommitmentsCircuitName', + 'splitCommitmentsFunction', + 'splitCommitmentsCircuitName', ]; }, @@ -69,10 +71,10 @@ class ContractBoilerplateGenerator { stateVariableDeclarations() { const { scope } = this; - let isjoinCommitmentsFunction : string[]=[]; + let isjoinSplitCommitmentsFunction : string[]=[]; for(const [, binding ] of Object.entries(scope.bindings)){ if((binding instanceof VariableBinding) && binding.isPartitioned && binding.isNullified && !binding.isStruct ) - isjoinCommitmentsFunction?.push('true'); + isjoinSplitCommitmentsFunction?.push('true'); } let { indicators: { nullifiersRequired, oldCommitmentAccessRequired, newCommitmentsRequired, containsAccessedOnlyState, encryptionRequired }, @@ -81,8 +83,8 @@ class ContractBoilerplateGenerator { (b: any) => b.kind === 'FunctionDefinition' && b.path.containsSecret, ); let functionNames = Object.values(fnDefBindings).map((b: any) => b.path.getUniqueFunctionName()); - if (isjoinCommitmentsFunction.includes('true')) { - functionNames.push('joinCommitments') + if (isjoinSplitCommitmentsFunction.includes('true')) { + functionNames.push('joinCommitments', 'splitCommitments'); nullifiersRequired = true; oldCommitmentAccessRequired = true; } @@ -107,10 +109,10 @@ class ContractBoilerplateGenerator { let { indicators: { nullifiersRequired, oldCommitmentAccessRequired, newCommitmentsRequired, containsAccessedOnlyState, encryptionRequired }, } = this.scope; - let isjoinCommitmentsFunction : string[]=[]; + let isjoinSplitCommitmentsFunction : string[]=[]; for(const [, binding ] of Object.entries(this.scope.bindings)){ if((binding instanceof VariableBinding) && binding.isPartitioned && binding.isNullified && !binding.isStruct) - isjoinCommitmentsFunction?.push('true'); + isjoinSplitCommitmentsFunction?.push('true'); } let parameterList: any[]; let paramtype: string; @@ -176,7 +178,7 @@ class ContractBoilerplateGenerator { circuitParams[ functionName ] = parameterList; } const constructorContainsSecret = Object.values(this.scope.bindings).some((binding: any) => binding.node.kind === 'constructor') - return { nullifiersRequired, oldCommitmentAccessRequired, newCommitmentsRequired, containsAccessedOnlyState, encryptionRequired, constructorContainsSecret, circuitParams, isjoinCommitmentsFunction}; + return { nullifiersRequired, oldCommitmentAccessRequired, newCommitmentsRequired, containsAccessedOnlyState, encryptionRequired, constructorContainsSecret, circuitParams, isjoinSplitCommitmentsFunction}; }, }; diff --git a/src/boilerplate/contract/solidity/raw/ContractBoilerplateGenerator.ts b/src/boilerplate/contract/solidity/raw/ContractBoilerplateGenerator.ts index 5ba86aea0..abae7a1b3 100644 --- a/src/boilerplate/contract/solidity/raw/ContractBoilerplateGenerator.ts +++ b/src/boilerplate/contract/solidity/raw/ContractBoilerplateGenerator.ts @@ -109,7 +109,7 @@ class ContractBoilerplateGenerator { encryptionRequired, circuitParams, constructorContainsSecret, - isjoinCommitmentsFunction, + isjoinSplitCommitmentsFunction, }): string[] { const verifyFunctionSignature = ` function verify( @@ -207,7 +207,7 @@ class ContractBoilerplateGenerator { ]; const verifyInputs: string[] = []; - const joinCommitmentsInputs: string[] = []; + const joinSplitCommitmentsInputs: string[] = []; for (let [name, _params] of Object.entries(circuitParams)) { if (_params) for (let [type, _inputs] of Object.entries(_params)) { @@ -262,9 +262,9 @@ class ContractBoilerplateGenerator { }`] : [] ]; - if (isjoinCommitmentsFunction?.includes('true')) { + if (isjoinSplitCommitmentsFunction?.includes('true')) { - joinCommitmentsInputs.push( + joinSplitCommitmentsInputs.push( ` function joinCommitments(uint256 nullifierRoot, uint256 latestNullifierRoot, uint256[] calldata newNullifiers, uint256 commitmentRoot, uint256[] calldata newCommitments, uint256[] calldata proof) public { @@ -284,7 +284,27 @@ class ContractBoilerplateGenerator { inputs.newCommitments = newCommitments; verify(proof, uint(FunctionNames.joinCommitments), inputs); - }`) + } + + function splitCommitments(uint256 nullifierRoot, uint256 latestNullifierRoot, uint256[] calldata newNullifiers, uint256 commitmentRoot, uint256[] calldata newCommitments, uint256[] calldata proof) public { + + Inputs memory inputs; + + inputs.customInputs = new uint[](1); + inputs.customInputs[0] = 1; + + inputs.nullifierRoot = nullifierRoot; + + inputs.latestNullifierRoot = latestNullifierRoot; + + inputs.newNullifiers = newNullifiers; + + inputs.commitmentRoot = commitmentRoot; + + inputs.newCommitments = newCommitments; + + verify(proof, uint(FunctionNames.splitCommitments), inputs); + }`) verifyInputs.push(` if (functionId == uint(FunctionNames.joinCommitments)) { @@ -302,6 +322,23 @@ class ContractBoilerplateGenerator { inputs[k++] = newCommitments[0]; inputs[k++] = 1; + } + + if (functionId == uint(FunctionNames.splitCommitments)) { + + + require(newNullifierRoot == _inputs.nullifierRoot, "Input NullifierRoot does not exist."); + + uint k = 0; + + inputs[k++] = _inputs.nullifierRoot; + inputs[k++] = _inputs.latestNullifierRoot; + inputs[k++] = newNullifiers[0]; + inputs[k++] = _inputs.commitmentRoot; + inputs[k++] = newCommitments[0]; + inputs[k++] = newCommitments[1]; + inputs[k++] = 1; + }`) } @@ -312,7 +349,7 @@ class ContractBoilerplateGenerator { ${verifyInputs.join('\n')} ${verification.join('\n')} }`, - `${joinCommitmentsInputs}` + `${joinSplitCommitmentsInputs}` ]; diff --git a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts index a5bef90b0..d9a1e6c4e 100644 --- a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts @@ -165,6 +165,18 @@ class BoilerplateGenerator { \nlet ${stateName}_witness_0; \nlet ${stateName}_witness_1; + if(${stateName}_1_oldCommitment === null && ${stateName}_commitmentFlag){ + \n${stateName}_witness_0 = await getMembershipWitness('${contractName}', generalise(${stateName}_0_oldCommitment._id).integer); + \n const tx = await splitCommitments('${contractName}', '${mappingName}', ${stateName}_newCommitmentValue.integer, secretKey, publicKey, [${stateVarId.join(' , ')}], ${stateName}_0_oldCommitment, ${stateName}_witness_0, instance, contractAddr, web3); + ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); + + [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( + publicKey.hex(32), + ${stateName}_newCommitmentValue.integer, + ${stateName}_preimage, + ); + } + while(${stateName}_commitmentFlag === false) { \n${stateName}_witness_0 = await getMembershipWitness('${contractName}', generalise(${stateName}_0_oldCommitment._id).integer); \n${stateName}_witness_1 = await getMembershipWitness('${contractName}', generalise(${stateName}_1_oldCommitment._id).integer); @@ -405,7 +417,7 @@ class BoilerplateGenerator { `\nimport fs from 'fs'; \n`, `\nimport { getContractInstance, getContractAddress, registerKey } from './common/contract.mjs';`, - `\nimport { storeCommitment, getCurrentWholeCommitment, getCommitmentsById, getAllCommitments, getInputCommitments, joinCommitments, markNullified,getnullifierMembershipWitness,getupdatedNullifierPaths,temporaryUpdateNullifier,updateNullifierTree } from './common/commitment-storage.mjs';`, + `\nimport { storeCommitment, getCurrentWholeCommitment, getCommitmentsById, getAllCommitments, getInputCommitments, joinCommitments, splitCommitments, markNullified,getnullifierMembershipWitness,getupdatedNullifierPaths,temporaryUpdateNullifier,updateNullifierTree } from './common/commitment-storage.mjs';`, `\nimport { generateProof } from './common/zokrates.mjs';`, `\nimport { getMembershipWitness, getRoot } from './common/timber.mjs';`, `\nimport Web3 from './common/web3.mjs';`, diff --git a/src/codeGenerators/circuit/zokrates/toCircuit.ts b/src/codeGenerators/circuit/zokrates/toCircuit.ts index a31c55d8f..41c42501f 100644 --- a/src/codeGenerators/circuit/zokrates/toCircuit.ts +++ b/src/codeGenerators/circuit/zokrates/toCircuit.ts @@ -53,6 +53,9 @@ function codeGenerator(node: any) { if (!file && node.fileName === `joinCommitments`) { thisFile.file = fs.readFileSync(path.resolve(fileURLToPath(import.meta.url), '../../../../../circuits/common/joinCommitments.zok'), 'utf8'); } + if (!file && node.fileName === `splitCommitments`) { + thisFile.file = fs.readFileSync(path.resolve(fileURLToPath(import.meta.url), '../../../../../circuits/common/splitCommitments.zok'), 'utf8'); + } const importedFiles = collectImportFiles(thisFile.file, 'circuit'); return [thisFile, ...importedFiles]; } @@ -197,6 +200,8 @@ function codeGenerator(node: any) { } case 'JoinCommitmentFunctionDefinition' : return `${CircuitBP.uniqueify(node.body.statements.flatMap(codeGenerator)).join('\n')}`; + case 'SplitCommitmentFunctionDefinition' : + return `${CircuitBP.uniqueify(node.body.statements.flatMap(codeGenerator)).join('\n')}`; case 'Return': return ` ` ; diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index 6d8f42cc0..90ed2fdd3 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -176,13 +176,13 @@ const visitor = { const joinCommitmentsNode = buildNode('File', { - fileName: `joinSplitCommitments`, + fileName: `joinCommitments`, fileId: node.id, nodes: [ ], }); const splitCommitmentsNode = buildNode('File', { - fileName: `spiltCommitments`, + fileName: `splitCommitments`, fileId: node.id, nodes: [ ], }); From 064e0925989ae34a416e3e9d36bc9a765f65a6ff Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Tue, 26 Mar 2024 11:37:21 +0000 Subject: [PATCH 3/6] chore: bug fixed in split commitment circuit --- circuits/common/splitCommitments.zok | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circuits/common/splitCommitments.zok b/circuits/common/splitCommitments.zok index 263302c22..1222147b3 100644 --- a/circuits/common/splitCommitments.zok +++ b/circuits/common/splitCommitments.zok @@ -31,7 +31,7 @@ def main(\ private field[32] oldCommitment_0_membershipWitness_siblingPath,\ private field newCommitment_0_owner_publicKey_field,\ private field newCommitment_0_salt_field,\ - public field newCommitment_0_commitment\ + public field newCommitment_0_commitment,\ private field newCommitment_1_owner_publicKey_field,\ private field newCommitment_1_salt_field,\ public field newCommitment_1_commitment\ From b319294f5f530a07486083272c12367f05e22679 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Tue, 26 Mar 2024 13:04:28 +0000 Subject: [PATCH 4/6] chore: added a fix for joi/split circuits --- circuits/common/joinCommitments.zok | 2 +- circuits/common/splitCommitments.zok | 2 +- src/boilerplate/common/commitment-storage.mjs | 15 +++++---------- .../javascript/raw/boilerplate-generator.ts | 2 +- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/circuits/common/joinCommitments.zok b/circuits/common/joinCommitments.zok index 555079f73..b16831c47 100644 --- a/circuits/common/joinCommitments.zok +++ b/circuits/common/joinCommitments.zok @@ -22,7 +22,7 @@ def main(\ public field nullifierRoot,\ public field newNullifierRoot,\ public field oldCommitment_0_nullifier,\ - public field[32] oldCommitment_0_nullifier_nonmembershipWitness_siblingPath,\ + private field[32] oldCommitment_0_nullifier_nonmembershipWitness_siblingPath,\ private field[32] oldCommitment_0_nullifier_nonmembershipWitness_newsiblingPath,\ public field oldCommitment_1_nullifier,\ private field[32] oldCommitment_1_nullifier_nonmembershipWitness_siblingPath,\ diff --git a/circuits/common/splitCommitments.zok b/circuits/common/splitCommitments.zok index 1222147b3..6a3b167f4 100644 --- a/circuits/common/splitCommitments.zok +++ b/circuits/common/splitCommitments.zok @@ -22,7 +22,7 @@ def main(\ public field nullifierRoot,\ public field newNullifierRoot,\ public field oldCommitment_0_nullifier,\ - public field[32] oldCommitment_0_nullifier_nonmembershipWitness_siblingPath,\ + private field[32] oldCommitment_0_nullifier_nonmembershipWitness_siblingPath,\ private field[32] oldCommitment_0_nullifier_nonmembershipWitness_newsiblingPath,\ private field oldCommitment_0_value,\ private field oldCommitment_0_salt_field,\ diff --git a/src/boilerplate/common/commitment-storage.mjs b/src/boilerplate/common/commitment-storage.mjs index 1d672dcd5..d5118d554 100644 --- a/src/boilerplate/common/commitment-storage.mjs +++ b/src/boilerplate/common/commitment-storage.mjs @@ -10,12 +10,7 @@ import logger from './logger.mjs'; import utils from 'zkp-utils'; import { poseidonHash } from './number-theory.mjs'; import { generateProof } from './zokrates.mjs'; -import { - SumType, - reduceTree, - toBinArray, - poseidonConcatHash, -} from './smt_utils.mjs'; +import { SumType, reduceTree, toBinArray, poseidonConcatHash } from './smt_utils.mjs'; import { hlt } from './hash-lookup.mjs'; const { MONGO_URL, COMMITMENTS_DB, COMMITMENTS_COLLECTION } = config; @@ -213,7 +208,6 @@ export async function markNullified(commitmentHash, secretKey = null) { } export function getInputCommitments( - contractName, publicKey, value, commitments, @@ -555,7 +549,7 @@ export async function splitCommitments( // Extract set membership witness: - const oldCommitment_0_witness = witnesses; + const oldCommitment_0_witness = witness; const oldCommitment_0_index = generalise(oldCommitment_0_witness.index); const oldCommitment_root = generalise(oldCommitment_0_witness.root); @@ -623,11 +617,12 @@ export async function splitCommitments( BigInt(newCommitment_0_newSalt.hex(32)), ]); - newCommitment_1 = generalise(newCommitment_1.hex(32)); // truncate + newCommitment_0 = generalise(newCommitment_0.hex(32)); // truncate const newCommitment_1_newSalt = generalise(utils.randomHex(31)); - let newCommitment_1_value = parseInt(oldCommitment_0_prev.integer, 10) - parseInt(value.integer, 10); + let newCommitment_1_value = + parseInt(oldCommitment_0_prev.integer, 10) - parseInt(value.integer, 10); newCommitment_1_value = generalise(newCommitment_1_value); diff --git a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts index d9a1e6c4e..746093335 100644 --- a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts @@ -167,7 +167,7 @@ class BoilerplateGenerator { if(${stateName}_1_oldCommitment === null && ${stateName}_commitmentFlag){ \n${stateName}_witness_0 = await getMembershipWitness('${contractName}', generalise(${stateName}_0_oldCommitment._id).integer); - \n const tx = await splitCommitments('${contractName}', '${mappingName}', ${stateName}_newCommitmentValue.integer, secretKey, publicKey, [${stateVarId.join(' , ')}], ${stateName}_0_oldCommitment, ${stateName}_witness_0, instance, contractAddr, web3); + \n const tx = await splitCommitments('${contractName}', '${mappingName}', ${stateName}_newCommitmentValue, secretKey, publicKey, [${stateVarId.join(' , ')}], ${stateName}_0_oldCommitment, ${stateName}_witness_0, instance, contractAddr, web3); ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( From 18355928df6bacaba79736a4517f1b34b9200043 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Tue, 26 Mar 2024 13:21:33 +0000 Subject: [PATCH 5/6] chore: fixed a bug in split commitments --- src/boilerplate/common/commitment-storage.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boilerplate/common/commitment-storage.mjs b/src/boilerplate/common/commitment-storage.mjs index d5118d554..32d35560e 100644 --- a/src/boilerplate/common/commitment-storage.mjs +++ b/src/boilerplate/common/commitment-storage.mjs @@ -680,7 +680,7 @@ export async function splitCommitments( .splitCommitments( oldCommitment_nullifierRoot.integer, oldCommitment_newNullifierRoot.integer, - [oldCommitment_0_nullifier.integer.integer], + [oldCommitment_0_nullifier.integer], oldCommitment_root.integer, [newCommitment_0.integer, newCommitment_1.integer], proof, From a64959a85d6ef1671e4ed31196ebebbb77e8e181 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Thu, 4 Apr 2024 11:51:05 +0100 Subject: [PATCH 6/6] chore: bug fix --- src/transformers/visitors/toOrchestrationVisitor.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 2fae2469b..9bb1e5e3c 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -245,9 +245,11 @@ const visitor = { if (file.nodeType === 'SetupCommonFilesBoilerplate') { file.constructorParams = state.constructorParams; file.contractImports = state.contractImports; - if(state.isjoinSplitCommitmentsFunction?.includes('true')) + if(state.isjoinSplitCommitmentsFunction?.includes('true')){ file.functionNames.push('joinCommitments'); file.functionNames.push('splitCommitments'); + } + } if (file.nodes?.[0].nodeType === 'IntegrationTestBoilerplate') { file.nodes[0].constructorParams = state.constructorParams;