From 870d6d5ead60b62bdb9387d1f126c184f4dbd894 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Tue, 24 Sep 2024 16:35:39 +0100 Subject: [PATCH 01/24] adding batch circuits Signed-off-by: Chengxuan Xing --- solidity/contracts/factory.sol | 4 +- .../zeto_fungible_initializable.sol | 3 +- .../contracts/lib/verifier_anon_batch.sol | 303 ++++++ .../contracts/lib/verifier_anon_enc_batch.sol | 338 +++++++ .../lib/verifier_anon_enc_nullifier_batch.sol | 415 +++++++++ .../verifier_anon_enc_nullifier_kyc_batch.sol | 422 +++++++++ ...on_enc_nullifier_non_repudiation_batch.sol | 877 ++++++++++++++++++ .../lib/verifier_anon_nullifier_batch.sol | 380 ++++++++ .../lib/verifier_anon_nullifier_kyc_batch.sol | 387 ++++++++ solidity/contracts/zeto_anon.sol | 23 +- solidity/contracts/zeto_anon_enc.sol | 18 +- .../contracts/zeto_anon_enc_nullifier.sol | 13 +- .../contracts/zeto_anon_enc_nullifier_kyc.sol | 13 +- ...eto_anon_enc_nullifier_non_repudiation.sol | 13 +- solidity/contracts/zeto_anon_nullifier.sol | 13 +- .../contracts/zeto_anon_nullifier_kyc.sol | 13 +- zkp/circuits/anon.circom | 56 +- zkp/circuits/anon_batch.circom | 20 + zkp/circuits/anon_enc.circom | 84 +- zkp/circuits/anon_enc_batch.circom | 20 + zkp/circuits/anon_enc_nullifier.circom | 109 +-- zkp/circuits/anon_enc_nullifier_batch.circom | 20 + zkp/circuits/anon_enc_nullifier_kyc.circom | 138 +-- .../anon_enc_nullifier_kyc_batch.circom | 20 + .../anon_enc_nullifier_non_repudiation.circom | 162 +--- ...enc_nullifier_non_repudiation_batch.circom | 20 + zkp/circuits/anon_nullifier.circom | 81 +- zkp/circuits/anon_nullifier_batch.circom | 20 + zkp/circuits/anon_nullifier_kyc.circom | 111 +-- zkp/circuits/anon_nullifier_kyc_batch.circom | 20 + zkp/circuits/basetokens/anon_base.circom | 72 ++ zkp/circuits/basetokens/anon_enc_base.circom | 100 ++ .../basetokens/anon_enc_nullifier_base.circom | 125 +++ .../anon_enc_nullifier_kyc_base.circom | 154 +++ ..._enc_nullifier_non_repudiation_base.circom | 178 ++++ .../basetokens/anon_nullifier_base.circom | 97 ++ .../basetokens/anon_nullifier_kyc_base.circom | 127 +++ zkp/circuits/gen-config.json | 7 + zkp/circuits/gen.js | 70 +- 39 files changed, 4274 insertions(+), 772 deletions(-) create mode 100644 solidity/contracts/lib/verifier_anon_batch.sol create mode 100644 solidity/contracts/lib/verifier_anon_enc_batch.sol create mode 100644 solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol create mode 100644 solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol create mode 100644 solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol create mode 100644 solidity/contracts/lib/verifier_anon_nullifier_batch.sol create mode 100644 solidity/contracts/lib/verifier_anon_nullifier_kyc_batch.sol create mode 100644 zkp/circuits/anon_batch.circom create mode 100644 zkp/circuits/anon_enc_batch.circom create mode 100644 zkp/circuits/anon_enc_nullifier_batch.circom create mode 100644 zkp/circuits/anon_enc_nullifier_kyc_batch.circom create mode 100644 zkp/circuits/anon_enc_nullifier_non_repudiation_batch.circom create mode 100644 zkp/circuits/anon_nullifier_batch.circom create mode 100644 zkp/circuits/anon_nullifier_kyc_batch.circom create mode 100644 zkp/circuits/basetokens/anon_base.circom create mode 100644 zkp/circuits/basetokens/anon_enc_base.circom create mode 100644 zkp/circuits/basetokens/anon_enc_nullifier_base.circom create mode 100644 zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom create mode 100644 zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom create mode 100644 zkp/circuits/basetokens/anon_nullifier_base.circom create mode 100644 zkp/circuits/basetokens/anon_nullifier_kyc_base.circom diff --git a/solidity/contracts/factory.sol b/solidity/contracts/factory.sol index 5f93795..735b531 100644 --- a/solidity/contracts/factory.sol +++ b/solidity/contracts/factory.sol @@ -30,6 +30,7 @@ contract ZetoTokenFactory is Ownable { address depositVerifier; address withdrawVerifier; address verifier; + address batchVerifier; } event ZetoTokenDeployed(address indexed zetoToken); @@ -83,7 +84,8 @@ contract ZetoTokenFactory is Ownable { initialOwner, args.verifier, args.depositVerifier, - args.withdrawVerifier + args.withdrawVerifier, + args.batchVerifier ); emit ZetoTokenDeployed(instance); return instance; diff --git a/solidity/contracts/lib/interfaces/zeto_fungible_initializable.sol b/solidity/contracts/lib/interfaces/zeto_fungible_initializable.sol index 88996cb..a7f6c6d 100644 --- a/solidity/contracts/lib/interfaces/zeto_fungible_initializable.sol +++ b/solidity/contracts/lib/interfaces/zeto_fungible_initializable.sol @@ -20,6 +20,7 @@ interface IZetoFungibleInitializable { address initialOwner, address _depositVerifier, address _withdrawVerifier, - address _verifier + address _verifier, + address _batchVerifier ) external; } diff --git a/solidity/contracts/lib/verifier_anon_batch.sol b/solidity/contracts/lib/verifier_anon_batch.sol new file mode 100644 index 0000000..559bbbb --- /dev/null +++ b/solidity/contracts/lib/verifier_anon_batch.sol @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: GPL-3.0 +/* + Copyright 2021 0KIMS association. + + This file is generated with [snarkJS](https://github.com/iden3/snarkjs). + + snarkJS is a free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + snarkJS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with snarkJS. If not, see . +*/ + +pragma solidity >=0.7.0 <0.9.0; + +contract Groth16Verifier_AnonBatch { + // Scalar field size + uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; + // Base field size + uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + + // Verification Key data + uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042; + uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958; + uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132; + uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731; + uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679; + uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856; + uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + uint256 constant deltax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant deltax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant deltay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + + + uint256 constant IC0x = 3944445075228117821565047604309603820750410202018016930603758668358261843334; + uint256 constant IC0y = 19711951516505465677916699605008107163330091662763114395955513140341801084904; + + uint256 constant IC1x = 10024224123696554332933959563789684919413349073272276892782203947930331299424; + uint256 constant IC1y = 20519109008487818648924793377164949144965439508556951350226813126173272972409; + + uint256 constant IC2x = 1142173056187437846551638621853081194566151147956191754797065528924777141391; + uint256 constant IC2y = 16031000099246098401525163660770199821855637849160899105526656734827553900160; + + uint256 constant IC3x = 7098793361958481515578594788921578408626331172533029034769487091259177553933; + uint256 constant IC3y = 18915702772411484313477583493617809166313147544546482894351481289848486181796; + + uint256 constant IC4x = 19005971096426827854128837349584492075969620357702027599715901169439142039107; + uint256 constant IC4y = 17532207718210544125714029032797641112877037912343528214735964170516471571921; + + uint256 constant IC5x = 1936021015178206426119341748943108180794913319638205912535284413609581525602; + uint256 constant IC5y = 7967302136211472331990287049203658686597431243250329181974784035551218197358; + + uint256 constant IC6x = 9992554524016746312003618199582955623647477467519651007496252737703754630352; + uint256 constant IC6y = 997153275981161531565982027728817123365375819829482012091549818270423282402; + + uint256 constant IC7x = 7712197579878897669743418158040651069819471864798300359532421509343128597573; + uint256 constant IC7y = 20498432515857145880555260380958760566875858463167134358631571286825812813269; + + uint256 constant IC8x = 18584297171621908469803449997963801603823813214190833275839121570817476657021; + uint256 constant IC8y = 2445386723403677400308664765622312273023037374330967243299653211986462592642; + + uint256 constant IC9x = 14133192108880623735273270944236158184105520798975796184751235384867979739155; + uint256 constant IC9y = 20404122581377456550753849206502073960629482972120621127516616915445683083056; + + uint256 constant IC10x = 21620582086891038692341479911819403068709367310253070056590551238915328633223; + uint256 constant IC10y = 18630174909646554249973638979405958638024971216151180247838752724473240059069; + + uint256 constant IC11x = 6342596883522327201634816902398912758838128458794280117859726335647563585947; + uint256 constant IC11y = 2824016079010236948181204053147426819259406110745168974616977685808163801290; + + uint256 constant IC12x = 43159074190541489778203261134463021016969587199344421115375597833984885585; + uint256 constant IC12y = 17350896801758852580882302620622451451656238190131669741645781468036782408702; + + uint256 constant IC13x = 5321216183955287064016722685217746316057734432786380277070838310613909336891; + uint256 constant IC13y = 2334801222880043538040480613345627043718796655094720160375512110863749425857; + + uint256 constant IC14x = 3896684584635540489763375035772495988353847533817784420117417709276419469254; + uint256 constant IC14y = 10946516808373943526791204345554417681977551778921357378409837151667749092291; + + uint256 constant IC15x = 13544430687582833351555151609955883457501780885438485005798150036967658669454; + uint256 constant IC15y = 12107768107013128150501889862480428065699648543203108548328101125430038577111; + + uint256 constant IC16x = 20956163448328444323344906937345570843311197655153127557251918352529849395595; + uint256 constant IC16y = 9598212570598439607775417965490373879497529804091617545914636036363751490464; + + uint256 constant IC17x = 8449456092675518202758567183735078063848547815110371262936870940442334259757; + uint256 constant IC17y = 21524144134927604254378260953498622529381737979908227933427485851545206692964; + + uint256 constant IC18x = 393847122473837845101843958338171385083705802293147226527157239309984511996; + uint256 constant IC18y = 10752382192217751383168301683456208551797510589007358704657988919297497446610; + + uint256 constant IC19x = 15228891166659766368605640799948864234093810898436039102385035716690203722442; + uint256 constant IC19y = 10660180881739048220615741801758109202106271107338130476996669627381881546392; + + uint256 constant IC20x = 7611617887611604008702014435739239029985615041644938533863855284962222542764; + uint256 constant IC20y = 830253140800199591016113383493114526088389823306942699451888210794961973972; + + + // Memory data + uint16 constant pVk = 0; + uint16 constant pPairing = 128; + + uint16 constant pLastMem = 896; + + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[20] calldata _pubSignals) public view returns (bool) { + assembly { + function checkField(v) { + if iszero(lt(v, r)) { + mstore(0, 0) + return(0, 0x20) + } + } + + // G1 function to multiply a G1 value(x,y) to value in an address + function g1_mulAccC(pR, x, y, s) { + let success + let mIn := mload(0x40) + mstore(mIn, x) + mstore(add(mIn, 32), y) + mstore(add(mIn, 64), s) + + success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + + mstore(add(mIn, 64), mload(pR)) + mstore(add(mIn, 96), mload(add(pR, 32))) + + success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + } + + function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk { + let _pPairing := add(pMem, pPairing) + let _pVk := add(pMem, pVk) + + mstore(_pVk, IC0x) + mstore(add(_pVk, 32), IC0y) + + // Compute the linear combination vk_x + + g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0))) + + g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32))) + + g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64))) + + g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96))) + + g1_mulAccC(_pVk, IC5x, IC5y, calldataload(add(pubSignals, 128))) + + g1_mulAccC(_pVk, IC6x, IC6y, calldataload(add(pubSignals, 160))) + + g1_mulAccC(_pVk, IC7x, IC7y, calldataload(add(pubSignals, 192))) + + g1_mulAccC(_pVk, IC8x, IC8y, calldataload(add(pubSignals, 224))) + + g1_mulAccC(_pVk, IC9x, IC9y, calldataload(add(pubSignals, 256))) + + g1_mulAccC(_pVk, IC10x, IC10y, calldataload(add(pubSignals, 288))) + + g1_mulAccC(_pVk, IC11x, IC11y, calldataload(add(pubSignals, 320))) + + g1_mulAccC(_pVk, IC12x, IC12y, calldataload(add(pubSignals, 352))) + + g1_mulAccC(_pVk, IC13x, IC13y, calldataload(add(pubSignals, 384))) + + g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416))) + + g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448))) + + g1_mulAccC(_pVk, IC16x, IC16y, calldataload(add(pubSignals, 480))) + + g1_mulAccC(_pVk, IC17x, IC17y, calldataload(add(pubSignals, 512))) + + g1_mulAccC(_pVk, IC18x, IC18y, calldataload(add(pubSignals, 544))) + + g1_mulAccC(_pVk, IC19x, IC19y, calldataload(add(pubSignals, 576))) + + g1_mulAccC(_pVk, IC20x, IC20y, calldataload(add(pubSignals, 608))) + + + // -A + mstore(_pPairing, calldataload(pA)) + mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q)) + + // B + mstore(add(_pPairing, 64), calldataload(pB)) + mstore(add(_pPairing, 96), calldataload(add(pB, 32))) + mstore(add(_pPairing, 128), calldataload(add(pB, 64))) + mstore(add(_pPairing, 160), calldataload(add(pB, 96))) + + // alpha1 + mstore(add(_pPairing, 192), alphax) + mstore(add(_pPairing, 224), alphay) + + // beta2 + mstore(add(_pPairing, 256), betax1) + mstore(add(_pPairing, 288), betax2) + mstore(add(_pPairing, 320), betay1) + mstore(add(_pPairing, 352), betay2) + + // vk_x + mstore(add(_pPairing, 384), mload(add(pMem, pVk))) + mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32)))) + + + // gamma2 + mstore(add(_pPairing, 448), gammax1) + mstore(add(_pPairing, 480), gammax2) + mstore(add(_pPairing, 512), gammay1) + mstore(add(_pPairing, 544), gammay2) + + // C + mstore(add(_pPairing, 576), calldataload(pC)) + mstore(add(_pPairing, 608), calldataload(add(pC, 32))) + + // delta2 + mstore(add(_pPairing, 640), deltax1) + mstore(add(_pPairing, 672), deltax2) + mstore(add(_pPairing, 704), deltay1) + mstore(add(_pPairing, 736), deltay2) + + + let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20) + + isOk := and(success, mload(_pPairing)) + } + + let pMem := mload(0x40) + mstore(0x40, add(pMem, pLastMem)) + + // Validate that all evaluations ∈ F + + checkField(calldataload(add(_pubSignals, 0))) + + checkField(calldataload(add(_pubSignals, 32))) + + checkField(calldataload(add(_pubSignals, 64))) + + checkField(calldataload(add(_pubSignals, 96))) + + checkField(calldataload(add(_pubSignals, 128))) + + checkField(calldataload(add(_pubSignals, 160))) + + checkField(calldataload(add(_pubSignals, 192))) + + checkField(calldataload(add(_pubSignals, 224))) + + checkField(calldataload(add(_pubSignals, 256))) + + checkField(calldataload(add(_pubSignals, 288))) + + checkField(calldataload(add(_pubSignals, 320))) + + checkField(calldataload(add(_pubSignals, 352))) + + checkField(calldataload(add(_pubSignals, 384))) + + checkField(calldataload(add(_pubSignals, 416))) + + checkField(calldataload(add(_pubSignals, 448))) + + checkField(calldataload(add(_pubSignals, 480))) + + checkField(calldataload(add(_pubSignals, 512))) + + checkField(calldataload(add(_pubSignals, 544))) + + checkField(calldataload(add(_pubSignals, 576))) + + checkField(calldataload(add(_pubSignals, 608))) + + checkField(calldataload(add(_pubSignals, 640))) + + + // Validate all evaluations + let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) + + mstore(0, isValid) + return(0, 0x20) + } + } + } diff --git a/solidity/contracts/lib/verifier_anon_enc_batch.sol b/solidity/contracts/lib/verifier_anon_enc_batch.sol new file mode 100644 index 0000000..08fa76b --- /dev/null +++ b/solidity/contracts/lib/verifier_anon_enc_batch.sol @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: GPL-3.0 +/* + Copyright 2021 0KIMS association. + + This file is generated with [snarkJS](https://github.com/iden3/snarkjs). + + snarkJS is a free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + snarkJS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with snarkJS. If not, see . +*/ + +pragma solidity >=0.7.0 <0.9.0; + +contract Groth16Verifier_AnonEncBatch { + // Scalar field size + uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; + // Base field size + uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + + // Verification Key data + uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042; + uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958; + uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132; + uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731; + uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679; + uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856; + uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + uint256 constant deltax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant deltax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant deltay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + + + uint256 constant IC0x = 7189741265667894171386648378312185912800151749367063899439033842829619018531; + uint256 constant IC0y = 17884484227326304060547068939975681487394009815094922588370149976422726273268; + + uint256 constant IC1x = 6976989834931789878418842558738463271861881797006171069806563232198951042869; + uint256 constant IC1y = 4607620418496754938241282900428029803466093854317753547452611458077967907674; + + uint256 constant IC2x = 1104559830706076731296654664075637185187356334768646358777598477822609389028; + uint256 constant IC2y = 3345550768796772178044166540721073265036018491137886953153002525534815362810; + + uint256 constant IC3x = 7339167904292788453737629411047095669569958420885203529836108618320029225321; + uint256 constant IC3y = 10127811846629680704572895087773581197933131108027374452597163321161722356281; + + uint256 constant IC4x = 17995410030890053741976076817185127523995916552402057091226681421315541788709; + uint256 constant IC4y = 14362557177387632374616439821157396761988637853842253785476976058551274774314; + + uint256 constant IC5x = 13293531195867414094312058265307495428535040802030900847168051381875064849320; + uint256 constant IC5y = 20854607687676821128519061564661683540031633583994135645214015131023213236658; + + uint256 constant IC6x = 3806382113870713333535697141069048771701877301218229542219146213062636519118; + uint256 constant IC6y = 968164612680877984576678128366936845032166057358019883376362869104455951991; + + uint256 constant IC7x = 7414361066968300446965646463524768189839597644475453090614884170383834231467; + uint256 constant IC7y = 18871824017586458935577810902748110232038032948171198588195313828414014642834; + + uint256 constant IC8x = 2681577168042166677173735754938968405641600798435441472230369938066386631441; + uint256 constant IC8y = 20989323624899116464465781536163070510329583651379897156356229335935295115550; + + uint256 constant IC9x = 837988643285174883060701192686929019767214369278310628575501631534377414317; + uint256 constant IC9y = 1497027309281778698096450532537321682620096834272532975906513350631947481246; + + uint256 constant IC10x = 13846091047999257285561818943917831947161925448727251083606199040901309455483; + uint256 constant IC10y = 21140858725718514275007364686974077359947858906470399301442263017523861516462; + + uint256 constant IC11x = 15327736368672693106243983767532414151733383231820598039546845408367990407510; + uint256 constant IC11y = 8978233402234246206405919493829088814272806423483168479609950953091130281624; + + uint256 constant IC12x = 2808000964050401522326265944234314863481085671375895951164989497843153038972; + uint256 constant IC12y = 11531380100407111226047699879374413435547572518965709942666525827464698301031; + + uint256 constant IC13x = 7703837959548087219235606509992045716672614065853991067483742493093046292830; + uint256 constant IC13y = 2855993324665746281147411571159804015907170749504611606481193074879718553646; + + uint256 constant IC14x = 902373741697942289280883575614240691556745280904627931982629145867494138505; + uint256 constant IC14y = 15733161533380354744692088486161623354470279164235678485868913277212174304447; + + uint256 constant IC15x = 10994298705029863992028152134353022932251042831787422154933994573982689419045; + uint256 constant IC15y = 17398965607134011589197925374325765086901718241003855850730487379127452367799; + + uint256 constant IC16x = 11892951991080935208554921924154615154971175142927057562324705784166460551163; + uint256 constant IC16y = 5691008018070641581295928491484464757049108925919901219628385025776797906143; + + uint256 constant IC17x = 16385349760746062660392139502252187515058108917152683574075970755109588098255; + uint256 constant IC17y = 4006132200257192648446443543123854816490277008709107776860749056319583986723; + + uint256 constant IC18x = 15737238506544786286259248091214287531404595722259507957910389449246442985860; + uint256 constant IC18y = 8774257820042718930005071001419692491634003552583131904074826546903152827936; + + uint256 constant IC19x = 5261338761583986889127298709462187597480484617121164266844247211605815308980; + uint256 constant IC19y = 6461699773895519123933988281435508110784080627465540530243192163198806094903; + + uint256 constant IC20x = 13036766766347670871820341262760106552456337170159401152071561005164842009774; + uint256 constant IC20y = 4274612413808318257961480446591695381400369399274465055760884716846613784526; + + uint256 constant IC21x = 18562363328719873772558553506930699000799009500209416935448544000103659611256; + uint256 constant IC21y = 6385384130214162329638041686219155710711521598989619892924465023706403534836; + + uint256 constant IC22x = 17307502141503920070248089676990085687750784085011485656505049451549390745686; + uint256 constant IC22y = 16334791657275865216071338891586271191049672233905856090086893120335561416428; + + uint256 constant IC23x = 2382115653931008587031786671517514604327077298833478735209768652527387951249; + uint256 constant IC23y = 10812017646661427158453552758883333361569252034751344876291235951652181181624; + + uint256 constant IC24x = 21260776816977489464621013688132612122819671246444567586980092869722567001366; + uint256 constant IC24y = 20734284890134842035357978897812101948609357231813112868709593640153549726412; + + uint256 constant IC25x = 6214032079313504274522884081468353949125435329668975592674808638707721409871; + uint256 constant IC25y = 7937870012562608748137139051862521736631851938383982008246874681096560011742; + + + // Memory data + uint16 constant pVk = 0; + uint16 constant pPairing = 128; + + uint16 constant pLastMem = 896; + + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[25] calldata _pubSignals) public view returns (bool) { + assembly { + function checkField(v) { + if iszero(lt(v, r)) { + mstore(0, 0) + return(0, 0x20) + } + } + + // G1 function to multiply a G1 value(x,y) to value in an address + function g1_mulAccC(pR, x, y, s) { + let success + let mIn := mload(0x40) + mstore(mIn, x) + mstore(add(mIn, 32), y) + mstore(add(mIn, 64), s) + + success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + + mstore(add(mIn, 64), mload(pR)) + mstore(add(mIn, 96), mload(add(pR, 32))) + + success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + } + + function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk { + let _pPairing := add(pMem, pPairing) + let _pVk := add(pMem, pVk) + + mstore(_pVk, IC0x) + mstore(add(_pVk, 32), IC0y) + + // Compute the linear combination vk_x + + g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0))) + + g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32))) + + g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64))) + + g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96))) + + g1_mulAccC(_pVk, IC5x, IC5y, calldataload(add(pubSignals, 128))) + + g1_mulAccC(_pVk, IC6x, IC6y, calldataload(add(pubSignals, 160))) + + g1_mulAccC(_pVk, IC7x, IC7y, calldataload(add(pubSignals, 192))) + + g1_mulAccC(_pVk, IC8x, IC8y, calldataload(add(pubSignals, 224))) + + g1_mulAccC(_pVk, IC9x, IC9y, calldataload(add(pubSignals, 256))) + + g1_mulAccC(_pVk, IC10x, IC10y, calldataload(add(pubSignals, 288))) + + g1_mulAccC(_pVk, IC11x, IC11y, calldataload(add(pubSignals, 320))) + + g1_mulAccC(_pVk, IC12x, IC12y, calldataload(add(pubSignals, 352))) + + g1_mulAccC(_pVk, IC13x, IC13y, calldataload(add(pubSignals, 384))) + + g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416))) + + g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448))) + + g1_mulAccC(_pVk, IC16x, IC16y, calldataload(add(pubSignals, 480))) + + g1_mulAccC(_pVk, IC17x, IC17y, calldataload(add(pubSignals, 512))) + + g1_mulAccC(_pVk, IC18x, IC18y, calldataload(add(pubSignals, 544))) + + g1_mulAccC(_pVk, IC19x, IC19y, calldataload(add(pubSignals, 576))) + + g1_mulAccC(_pVk, IC20x, IC20y, calldataload(add(pubSignals, 608))) + + g1_mulAccC(_pVk, IC21x, IC21y, calldataload(add(pubSignals, 640))) + + g1_mulAccC(_pVk, IC22x, IC22y, calldataload(add(pubSignals, 672))) + + g1_mulAccC(_pVk, IC23x, IC23y, calldataload(add(pubSignals, 704))) + + g1_mulAccC(_pVk, IC24x, IC24y, calldataload(add(pubSignals, 736))) + + g1_mulAccC(_pVk, IC25x, IC25y, calldataload(add(pubSignals, 768))) + + + // -A + mstore(_pPairing, calldataload(pA)) + mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q)) + + // B + mstore(add(_pPairing, 64), calldataload(pB)) + mstore(add(_pPairing, 96), calldataload(add(pB, 32))) + mstore(add(_pPairing, 128), calldataload(add(pB, 64))) + mstore(add(_pPairing, 160), calldataload(add(pB, 96))) + + // alpha1 + mstore(add(_pPairing, 192), alphax) + mstore(add(_pPairing, 224), alphay) + + // beta2 + mstore(add(_pPairing, 256), betax1) + mstore(add(_pPairing, 288), betax2) + mstore(add(_pPairing, 320), betay1) + mstore(add(_pPairing, 352), betay2) + + // vk_x + mstore(add(_pPairing, 384), mload(add(pMem, pVk))) + mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32)))) + + + // gamma2 + mstore(add(_pPairing, 448), gammax1) + mstore(add(_pPairing, 480), gammax2) + mstore(add(_pPairing, 512), gammay1) + mstore(add(_pPairing, 544), gammay2) + + // C + mstore(add(_pPairing, 576), calldataload(pC)) + mstore(add(_pPairing, 608), calldataload(add(pC, 32))) + + // delta2 + mstore(add(_pPairing, 640), deltax1) + mstore(add(_pPairing, 672), deltax2) + mstore(add(_pPairing, 704), deltay1) + mstore(add(_pPairing, 736), deltay2) + + + let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20) + + isOk := and(success, mload(_pPairing)) + } + + let pMem := mload(0x40) + mstore(0x40, add(pMem, pLastMem)) + + // Validate that all evaluations ∈ F + + checkField(calldataload(add(_pubSignals, 0))) + + checkField(calldataload(add(_pubSignals, 32))) + + checkField(calldataload(add(_pubSignals, 64))) + + checkField(calldataload(add(_pubSignals, 96))) + + checkField(calldataload(add(_pubSignals, 128))) + + checkField(calldataload(add(_pubSignals, 160))) + + checkField(calldataload(add(_pubSignals, 192))) + + checkField(calldataload(add(_pubSignals, 224))) + + checkField(calldataload(add(_pubSignals, 256))) + + checkField(calldataload(add(_pubSignals, 288))) + + checkField(calldataload(add(_pubSignals, 320))) + + checkField(calldataload(add(_pubSignals, 352))) + + checkField(calldataload(add(_pubSignals, 384))) + + checkField(calldataload(add(_pubSignals, 416))) + + checkField(calldataload(add(_pubSignals, 448))) + + checkField(calldataload(add(_pubSignals, 480))) + + checkField(calldataload(add(_pubSignals, 512))) + + checkField(calldataload(add(_pubSignals, 544))) + + checkField(calldataload(add(_pubSignals, 576))) + + checkField(calldataload(add(_pubSignals, 608))) + + checkField(calldataload(add(_pubSignals, 640))) + + checkField(calldataload(add(_pubSignals, 672))) + + checkField(calldataload(add(_pubSignals, 704))) + + checkField(calldataload(add(_pubSignals, 736))) + + checkField(calldataload(add(_pubSignals, 768))) + + checkField(calldataload(add(_pubSignals, 800))) + + + // Validate all evaluations + let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) + + mstore(0, isValid) + return(0, 0x20) + } + } + } diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol new file mode 100644 index 0000000..1545642 --- /dev/null +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol @@ -0,0 +1,415 @@ +// SPDX-License-Identifier: GPL-3.0 +/* + Copyright 2021 0KIMS association. + + This file is generated with [snarkJS](https://github.com/iden3/snarkjs). + + snarkJS is a free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + snarkJS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with snarkJS. If not, see . +*/ + +pragma solidity >=0.7.0 <0.9.0; + +contract Groth16Verifier_AnonEncNullifierBatch { + // Scalar field size + uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; + // Base field size + uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + + // Verification Key data + uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042; + uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958; + uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132; + uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731; + uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679; + uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856; + uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + uint256 constant deltax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant deltax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant deltay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + + + uint256 constant IC0x = 15463228992890913407256271912655902703204304471203583418871710110367568509017; + uint256 constant IC0y = 6081643586730902920310484720784368541485121289118172242921785599841793039397; + + uint256 constant IC1x = 7690092334332803225358122531593469612638564706239742127383115275750637128544; + uint256 constant IC1y = 4070716537409257501255053424367331199883828899205760134468805014488240593235; + + uint256 constant IC2x = 1897861027150832646882538023040630326718005087509077431813937643855057325512; + uint256 constant IC2y = 1439104093149456820519872532162098266586027883053410812354650892557521752658; + + uint256 constant IC3x = 4247406668949246815522915881558097313801033425260638984520747823588066294010; + uint256 constant IC3y = 384187583735544539895332388057505134919889393310645722394574257594265340544; + + uint256 constant IC4x = 2163280919944916722705407124486638913202715101976337577933948527523763136316; + uint256 constant IC4y = 17743925429712862815908467894864768203059146362469259706665186071908793546304; + + uint256 constant IC5x = 1619258089617143478432432741785464751663918498436908219039181629518309232037; + uint256 constant IC5y = 11630616902607787050358650172682737668169372249533372501954846248236883577037; + + uint256 constant IC6x = 11856397151368437471647436909385425738968114143993909218432032948582691038255; + uint256 constant IC6y = 678272634636435534137608607645423344933204026891856980589563368261431859655; + + uint256 constant IC7x = 5770940534172849936200191790166968674512475692082635469024125098067660874340; + uint256 constant IC7y = 5796891932643059731209408355543252398184249413054025674322014797701901199161; + + uint256 constant IC8x = 21157884469337147167484623772858155700668090233318692577599491819791268263103; + uint256 constant IC8y = 11319817801893944559243060679771033423769978982984416308930737959593420067187; + + uint256 constant IC9x = 17155601633062182536973842836383359711305654711820090042777274053320592459792; + uint256 constant IC9y = 4153339199036173911292560028271096884640710297588841704979849414084725739989; + + uint256 constant IC10x = 19502162444772235516642339462161346484221330878380009887837212894180467490090; + uint256 constant IC10y = 8746377545292087029262304097721851587587533642816798045978033468894796298271; + + uint256 constant IC11x = 10492727340495605431811280843573770802173281509627577093132502224855941607786; + uint256 constant IC11y = 12593957599668519647646623252624235771356540353621190049672109046663132567393; + + uint256 constant IC12x = 2141055855219834142007696005384065075492349785073794976665158196389003189441; + uint256 constant IC12y = 17406300413981635438953802745917216957016698564219386571963271017518080214467; + + uint256 constant IC13x = 19032830625159879771752338038675350316929691880552436444519236054639916485885; + uint256 constant IC13y = 12903015174084070036198447168709051493274452823678667961495604360873262456786; + + uint256 constant IC14x = 16371683632587610030576224024875254515874360648746009582599446538505985845307; + uint256 constant IC14y = 11173673008313918399612751353743129118083339259017536663266638097162487858620; + + uint256 constant IC15x = 15737548200096487165947831292170304880183367558719053011425105902130220221758; + uint256 constant IC15y = 17935613113686543895175918584771321696813538867893834513577602284559153945408; + + uint256 constant IC16x = 18944733370869458467936382884278952997679539994012239122340654508303854835845; + uint256 constant IC16y = 15129624232037524523766906312590739384074339500781885555180217280630980807979; + + uint256 constant IC17x = 766879213842683919337084764327101390445760653210017226852735122564521980106; + uint256 constant IC17y = 13257194366329105926979110483114146395805993555097867134185789623853915836985; + + uint256 constant IC18x = 466834947469548587015244622123248056190476516827510567771023410872527806519; + uint256 constant IC18y = 19073602954069385500938225445649671911205643444983500612737255746611614950303; + + uint256 constant IC19x = 17648949249985332116986320075129441784946087962808100600088809464478557448096; + uint256 constant IC19y = 21066315663090040597626054677994311826852899593331220450852631484801939023727; + + uint256 constant IC20x = 20154598293008989566712339828669128400118781474137050820769849877249304503719; + uint256 constant IC20y = 15496920822463556703581064294717331871146167137627219477973885063073492653138; + + uint256 constant IC21x = 2324404389181201284864046287742150257907858884919451986972847726132386478888; + uint256 constant IC21y = 18134091977179255262951024580719856195604717288045403200882669041767528019153; + + uint256 constant IC22x = 13221158529900749092192403410247720061249921155486754588343968542295912904556; + uint256 constant IC22y = 5028152056563650345537782053038682532283749227333291047889444926654818553282; + + uint256 constant IC23x = 19361641654406595295525840785289520677449987795910033166894352349186921404440; + uint256 constant IC23y = 10650981683931869840049161361062935794760639354500379916723750499138676334844; + + uint256 constant IC24x = 11148283475053323553211040486718325234959050263310938469899343323289033646909; + uint256 constant IC24y = 3109004693780647674006249758989929090923302709028884287247288297028214451989; + + uint256 constant IC25x = 13228357596868509323150572957775844911612210741725650349702162165507904750898; + uint256 constant IC25y = 6331432384044620993460078250696905421162322835257350537296378202567121643631; + + uint256 constant IC26x = 9536375111163305409151475098581692610659685731562165281574114090536689951418; + uint256 constant IC26y = 9038552082961206589631129524924598934056043439597158013469625214978143001100; + + uint256 constant IC27x = 8844438162532508945581808751476500747305933630010310294265168458587341146748; + uint256 constant IC27y = 12351730175630032342235309720309605330011746933984028737009670971810498581435; + + uint256 constant IC28x = 890093037798729429015514465180574619659335658459970475515347887554928607216; + uint256 constant IC28y = 3321203689472727739933204766233295262326623168468132630828838742083531545396; + + uint256 constant IC29x = 894376188310087732920965947612568506834752896038979836462341779500867941506; + uint256 constant IC29y = 8608004138419721497755714589979878275974393904523232633132083164800041862950; + + uint256 constant IC30x = 11044931439964914456344334341371494069878373560303210878419944483124170473203; + uint256 constant IC30y = 9803427855593328173483023013452443696485604414496416903172860867880720274417; + + uint256 constant IC31x = 1684103584023867101860046558439190165716975237508236450519282487084361635734; + uint256 constant IC31y = 5133408065911135276667071999828368466267845111169710299435079940536432113214; + + uint256 constant IC32x = 4338534039647724941082052989726012587859023977099240507207676336872464936054; + uint256 constant IC32y = 16897374641288201732671683609162272649324322852915208569511172322936944220689; + + uint256 constant IC33x = 9170416470183524991008272907301201709743366647977411580114896261165534711616; + uint256 constant IC33y = 3690044898492576264147530421921970583305121687878000452671756007226539391733; + + uint256 constant IC34x = 8334815801605428511890555908274200358088845436285928522753824970808649461924; + uint256 constant IC34y = 12560518115013611619606981133430503709544765639252741401402558626147052803884; + + uint256 constant IC35x = 19825884431345163793705281160397189448823019129369075206515699595090927399070; + uint256 constant IC35y = 7994765120516944787797908101755469459475652122106465411690195168496698193539; + + uint256 constant IC36x = 8596966023108930042949859388566908182935873370403952072939322045302182518981; + uint256 constant IC36y = 5807387851106953848587697067446771376304295390995987291509842895574618702671; + + + // Memory data + uint16 constant pVk = 0; + uint16 constant pPairing = 128; + + uint16 constant pLastMem = 896; + + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[36] calldata _pubSignals) public view returns (bool) { + assembly { + function checkField(v) { + if iszero(lt(v, r)) { + mstore(0, 0) + return(0, 0x20) + } + } + + // G1 function to multiply a G1 value(x,y) to value in an address + function g1_mulAccC(pR, x, y, s) { + let success + let mIn := mload(0x40) + mstore(mIn, x) + mstore(add(mIn, 32), y) + mstore(add(mIn, 64), s) + + success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + + mstore(add(mIn, 64), mload(pR)) + mstore(add(mIn, 96), mload(add(pR, 32))) + + success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + } + + function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk { + let _pPairing := add(pMem, pPairing) + let _pVk := add(pMem, pVk) + + mstore(_pVk, IC0x) + mstore(add(_pVk, 32), IC0y) + + // Compute the linear combination vk_x + + g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0))) + + g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32))) + + g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64))) + + g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96))) + + g1_mulAccC(_pVk, IC5x, IC5y, calldataload(add(pubSignals, 128))) + + g1_mulAccC(_pVk, IC6x, IC6y, calldataload(add(pubSignals, 160))) + + g1_mulAccC(_pVk, IC7x, IC7y, calldataload(add(pubSignals, 192))) + + g1_mulAccC(_pVk, IC8x, IC8y, calldataload(add(pubSignals, 224))) + + g1_mulAccC(_pVk, IC9x, IC9y, calldataload(add(pubSignals, 256))) + + g1_mulAccC(_pVk, IC10x, IC10y, calldataload(add(pubSignals, 288))) + + g1_mulAccC(_pVk, IC11x, IC11y, calldataload(add(pubSignals, 320))) + + g1_mulAccC(_pVk, IC12x, IC12y, calldataload(add(pubSignals, 352))) + + g1_mulAccC(_pVk, IC13x, IC13y, calldataload(add(pubSignals, 384))) + + g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416))) + + g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448))) + + g1_mulAccC(_pVk, IC16x, IC16y, calldataload(add(pubSignals, 480))) + + g1_mulAccC(_pVk, IC17x, IC17y, calldataload(add(pubSignals, 512))) + + g1_mulAccC(_pVk, IC18x, IC18y, calldataload(add(pubSignals, 544))) + + g1_mulAccC(_pVk, IC19x, IC19y, calldataload(add(pubSignals, 576))) + + g1_mulAccC(_pVk, IC20x, IC20y, calldataload(add(pubSignals, 608))) + + g1_mulAccC(_pVk, IC21x, IC21y, calldataload(add(pubSignals, 640))) + + g1_mulAccC(_pVk, IC22x, IC22y, calldataload(add(pubSignals, 672))) + + g1_mulAccC(_pVk, IC23x, IC23y, calldataload(add(pubSignals, 704))) + + g1_mulAccC(_pVk, IC24x, IC24y, calldataload(add(pubSignals, 736))) + + g1_mulAccC(_pVk, IC25x, IC25y, calldataload(add(pubSignals, 768))) + + g1_mulAccC(_pVk, IC26x, IC26y, calldataload(add(pubSignals, 800))) + + g1_mulAccC(_pVk, IC27x, IC27y, calldataload(add(pubSignals, 832))) + + g1_mulAccC(_pVk, IC28x, IC28y, calldataload(add(pubSignals, 864))) + + g1_mulAccC(_pVk, IC29x, IC29y, calldataload(add(pubSignals, 896))) + + g1_mulAccC(_pVk, IC30x, IC30y, calldataload(add(pubSignals, 928))) + + g1_mulAccC(_pVk, IC31x, IC31y, calldataload(add(pubSignals, 960))) + + g1_mulAccC(_pVk, IC32x, IC32y, calldataload(add(pubSignals, 992))) + + g1_mulAccC(_pVk, IC33x, IC33y, calldataload(add(pubSignals, 1024))) + + g1_mulAccC(_pVk, IC34x, IC34y, calldataload(add(pubSignals, 1056))) + + g1_mulAccC(_pVk, IC35x, IC35y, calldataload(add(pubSignals, 1088))) + + g1_mulAccC(_pVk, IC36x, IC36y, calldataload(add(pubSignals, 1120))) + + + // -A + mstore(_pPairing, calldataload(pA)) + mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q)) + + // B + mstore(add(_pPairing, 64), calldataload(pB)) + mstore(add(_pPairing, 96), calldataload(add(pB, 32))) + mstore(add(_pPairing, 128), calldataload(add(pB, 64))) + mstore(add(_pPairing, 160), calldataload(add(pB, 96))) + + // alpha1 + mstore(add(_pPairing, 192), alphax) + mstore(add(_pPairing, 224), alphay) + + // beta2 + mstore(add(_pPairing, 256), betax1) + mstore(add(_pPairing, 288), betax2) + mstore(add(_pPairing, 320), betay1) + mstore(add(_pPairing, 352), betay2) + + // vk_x + mstore(add(_pPairing, 384), mload(add(pMem, pVk))) + mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32)))) + + + // gamma2 + mstore(add(_pPairing, 448), gammax1) + mstore(add(_pPairing, 480), gammax2) + mstore(add(_pPairing, 512), gammay1) + mstore(add(_pPairing, 544), gammay2) + + // C + mstore(add(_pPairing, 576), calldataload(pC)) + mstore(add(_pPairing, 608), calldataload(add(pC, 32))) + + // delta2 + mstore(add(_pPairing, 640), deltax1) + mstore(add(_pPairing, 672), deltax2) + mstore(add(_pPairing, 704), deltay1) + mstore(add(_pPairing, 736), deltay2) + + + let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20) + + isOk := and(success, mload(_pPairing)) + } + + let pMem := mload(0x40) + mstore(0x40, add(pMem, pLastMem)) + + // Validate that all evaluations ∈ F + + checkField(calldataload(add(_pubSignals, 0))) + + checkField(calldataload(add(_pubSignals, 32))) + + checkField(calldataload(add(_pubSignals, 64))) + + checkField(calldataload(add(_pubSignals, 96))) + + checkField(calldataload(add(_pubSignals, 128))) + + checkField(calldataload(add(_pubSignals, 160))) + + checkField(calldataload(add(_pubSignals, 192))) + + checkField(calldataload(add(_pubSignals, 224))) + + checkField(calldataload(add(_pubSignals, 256))) + + checkField(calldataload(add(_pubSignals, 288))) + + checkField(calldataload(add(_pubSignals, 320))) + + checkField(calldataload(add(_pubSignals, 352))) + + checkField(calldataload(add(_pubSignals, 384))) + + checkField(calldataload(add(_pubSignals, 416))) + + checkField(calldataload(add(_pubSignals, 448))) + + checkField(calldataload(add(_pubSignals, 480))) + + checkField(calldataload(add(_pubSignals, 512))) + + checkField(calldataload(add(_pubSignals, 544))) + + checkField(calldataload(add(_pubSignals, 576))) + + checkField(calldataload(add(_pubSignals, 608))) + + checkField(calldataload(add(_pubSignals, 640))) + + checkField(calldataload(add(_pubSignals, 672))) + + checkField(calldataload(add(_pubSignals, 704))) + + checkField(calldataload(add(_pubSignals, 736))) + + checkField(calldataload(add(_pubSignals, 768))) + + checkField(calldataload(add(_pubSignals, 800))) + + checkField(calldataload(add(_pubSignals, 832))) + + checkField(calldataload(add(_pubSignals, 864))) + + checkField(calldataload(add(_pubSignals, 896))) + + checkField(calldataload(add(_pubSignals, 928))) + + checkField(calldataload(add(_pubSignals, 960))) + + checkField(calldataload(add(_pubSignals, 992))) + + checkField(calldataload(add(_pubSignals, 1024))) + + checkField(calldataload(add(_pubSignals, 1056))) + + checkField(calldataload(add(_pubSignals, 1088))) + + checkField(calldataload(add(_pubSignals, 1120))) + + checkField(calldataload(add(_pubSignals, 1152))) + + + // Validate all evaluations + let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) + + mstore(0, isValid) + return(0, 0x20) + } + } + } diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol new file mode 100644 index 0000000..4a00e5f --- /dev/null +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol @@ -0,0 +1,422 @@ +// SPDX-License-Identifier: GPL-3.0 +/* + Copyright 2021 0KIMS association. + + This file is generated with [snarkJS](https://github.com/iden3/snarkjs). + + snarkJS is a free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + snarkJS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with snarkJS. If not, see . +*/ + +pragma solidity >=0.7.0 <0.9.0; + +contract Groth16Verifier_AnonEncNullifierKycBatch { + // Scalar field size + uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; + // Base field size + uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + + // Verification Key data + uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042; + uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958; + uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132; + uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731; + uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679; + uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856; + uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + uint256 constant deltax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant deltax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant deltay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + + + uint256 constant IC0x = 11662660143860874931072351186047069691934558454076806957543648503057847943513; + uint256 constant IC0y = 10038348414197657683445922076295262289652998118153787101974831249817368174353; + + uint256 constant IC1x = 8988535072375717724497491246352234049328213447683207989537377224470040054966; + uint256 constant IC1y = 8166282710103471067373199268434356717037308329558570925972507352895336171600; + + uint256 constant IC2x = 18432294692910581759472826919355763187872967572458291145949908209816982819688; + uint256 constant IC2y = 21529300506719821524307516873688911621260384833976448337733933552847314256874; + + uint256 constant IC3x = 614735613818836283841982905943976709929041752739745042789141794733265028134; + uint256 constant IC3y = 3860703814665496245605558172188863798062943606333015527826728127069465082427; + + uint256 constant IC4x = 21110382318575147474338865721398707915802737103567042212867029114347240559300; + uint256 constant IC4y = 11477828230558650608120671853203757664438453457364362308796561794776172008451; + + uint256 constant IC5x = 10955202528924804812958438713742990627683883390569205805287044297181502266729; + uint256 constant IC5y = 17858987609351477507179059147091144336664455743112357073106373084043189280164; + + uint256 constant IC6x = 9247132710507257341694745715536030078362897235873976845653448343004216578059; + uint256 constant IC6y = 4077530447461105776970121739853125425415755933636891068527434065606633343729; + + uint256 constant IC7x = 9282229099621743758927934855838604257685882618355194980012233357617245438364; + uint256 constant IC7y = 15674736937935764122279448687928959717281418334634353011570533455984105715121; + + uint256 constant IC8x = 9722132009325333783456053646735667902530261615407197523392160208704603988454; + uint256 constant IC8y = 14618244177095367221394852282157340600459069670233465954719723502618367220099; + + uint256 constant IC9x = 973628821824034631277519892548216364093065392435755888383034381618210105026; + uint256 constant IC9y = 19130664929693827307694622317521885236690764504040079683400014381939179764886; + + uint256 constant IC10x = 18497489122159836005440235191181397682168825652742401878718303497751950476573; + uint256 constant IC10y = 184674817624142463950860554146189016898202305618730035365532664689559015024; + + uint256 constant IC11x = 20742886562308807174975673124416469858072816509700038966264317699622470845864; + uint256 constant IC11y = 6892841648413503913935428607180182195114904340636618216544980552932522306183; + + uint256 constant IC12x = 1554767197776271090848221696659744029443606469011424330576588038599488901790; + uint256 constant IC12y = 17824173807300533295074190605171784659758705215735044173456990718107986673990; + + uint256 constant IC13x = 8926678800934477977183437663176073269804039617131246226117210958642974831665; + uint256 constant IC13y = 7759817179292182986840792444788081906199101563123339998406609301418454149912; + + uint256 constant IC14x = 892387531981845359273038619022215455220935019529138222295972719463971685626; + uint256 constant IC14y = 21664606451742576757250844476052733616001992300681450622144236517957407335395; + + uint256 constant IC15x = 11644738412527836785033238753051417149187120228925099428899706835198503714732; + uint256 constant IC15y = 20385101286516026017516350545863829411647430450169209244102096545003646405227; + + uint256 constant IC16x = 6914380489103854988747068027174251954079888530380820907417133182165125002895; + uint256 constant IC16y = 16001027808620196049156676450902737881221224855685201356892867218134413591974; + + uint256 constant IC17x = 14819004697379517927442020076999128258818136109044427450238213315710239729290; + uint256 constant IC17y = 18234035980915600023635619254964104942336216004642311690220730031352749295516; + + uint256 constant IC18x = 10782655998802736438708390186837190841583872252631539739869717362042994127890; + uint256 constant IC18y = 6223193220871490512854223407339053827650007826976048957711920097140884329831; + + uint256 constant IC19x = 1895164154807081669060491556433373630284427382709469252391398895819775411625; + uint256 constant IC19y = 15502891301545941170843587746206524939661082838133458062213752972874935576258; + + uint256 constant IC20x = 13887414818061216296960695706977042112426565238817982814880739463438328917279; + uint256 constant IC20y = 7484477067983396480837362197475960184311309962467034141451929400540619439308; + + uint256 constant IC21x = 5054771292297611149580407057004026930126834333985311096593522198136005344912; + uint256 constant IC21y = 9846301605360728746360669788291305483667978418447570933133518441453812077532; + + uint256 constant IC22x = 6375011858346699471620766703454180460474959318906959854737520006721913377252; + uint256 constant IC22y = 3796913124771080981656421285118700913079563083089989934442241685039240456288; + + uint256 constant IC23x = 12664019414260530425201012729657179596363883228871830375986018330410576140745; + uint256 constant IC23y = 7724324759234305150098870450511243647469859115829862950119746163372770734859; + + uint256 constant IC24x = 8414475932517376718246446511190686353933356473167597163507393977956520237760; + uint256 constant IC24y = 18567739092665780186541027431450016060501602309168108628165515395048109525145; + + uint256 constant IC25x = 3120359907362450985974214561527700848503852347080997608106866995365092938990; + uint256 constant IC25y = 15598034416975435647171366075254343399116960825160529831975796905883095316090; + + uint256 constant IC26x = 7618398623080814369986094262260112943677198176279294076050134118180709564420; + uint256 constant IC26y = 6351701903764767447401679181425343449080736954061708171606650791995388240779; + + uint256 constant IC27x = 7660149068846033504478826117178890832918932678832205596487410124265824854510; + uint256 constant IC27y = 2491826788761961957821876406677372156214488096819322910097327511124260678669; + + uint256 constant IC28x = 20794838749313203903911030270946907016433597109553720174221656385211714777857; + uint256 constant IC28y = 17812498163364921099637863734271985783984365300073299650639268105274324002530; + + uint256 constant IC29x = 4470726918138395764759380807649395990732471367466166253310755622776103465819; + uint256 constant IC29y = 17507663986159322748561449962825208817145248778005235057962503024107788565141; + + uint256 constant IC30x = 2282738716454269120180527219287809294651441549016730273033210373774062724582; + uint256 constant IC30y = 9623151597448060795671840649081334455274395484568727058139159897873039048540; + + uint256 constant IC31x = 17305720772558963560489472259732910387932131794541742579825391441778640282514; + uint256 constant IC31y = 17978483020480616572180687903365084753182987002773905082575771176385017798184; + + uint256 constant IC32x = 7571937518121766238677733127868492321558436932028274617193759428484887548524; + uint256 constant IC32y = 13639634797327254842916621072030476726854653633267901223609159210218680193213; + + uint256 constant IC33x = 20491321178426427862122967005183398251779924470644678424571372683050891038410; + uint256 constant IC33y = 11866037972312670211817727171740620564847008846992179291696597777640193650198; + + uint256 constant IC34x = 7405036655032262031472090543721788457203124544189082692990295451049187204918; + uint256 constant IC34y = 17405807581678636956378393569562099137850325108621234185518676366335548019795; + + uint256 constant IC35x = 12328260325084982532450273571086533395727110714550084687965119377605785323469; + uint256 constant IC35y = 8142505738758504286142612135433392554621238433204631934113088648731836869316; + + uint256 constant IC36x = 21455489380416043414802439866337341338095098412697364482542368506991948195301; + uint256 constant IC36y = 177380340269897070531510667485546719600921933001020617304645726088643982991; + + uint256 constant IC37x = 3450411197718861866556684118720127022485036312758274952373537023832934853655; + uint256 constant IC37y = 15542683513967475831837975619927185145121842635660806931638451693301339778065; + + + // Memory data + uint16 constant pVk = 0; + uint16 constant pPairing = 128; + + uint16 constant pLastMem = 896; + + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[37] calldata _pubSignals) public view returns (bool) { + assembly { + function checkField(v) { + if iszero(lt(v, r)) { + mstore(0, 0) + return(0, 0x20) + } + } + + // G1 function to multiply a G1 value(x,y) to value in an address + function g1_mulAccC(pR, x, y, s) { + let success + let mIn := mload(0x40) + mstore(mIn, x) + mstore(add(mIn, 32), y) + mstore(add(mIn, 64), s) + + success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + + mstore(add(mIn, 64), mload(pR)) + mstore(add(mIn, 96), mload(add(pR, 32))) + + success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + } + + function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk { + let _pPairing := add(pMem, pPairing) + let _pVk := add(pMem, pVk) + + mstore(_pVk, IC0x) + mstore(add(_pVk, 32), IC0y) + + // Compute the linear combination vk_x + + g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0))) + + g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32))) + + g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64))) + + g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96))) + + g1_mulAccC(_pVk, IC5x, IC5y, calldataload(add(pubSignals, 128))) + + g1_mulAccC(_pVk, IC6x, IC6y, calldataload(add(pubSignals, 160))) + + g1_mulAccC(_pVk, IC7x, IC7y, calldataload(add(pubSignals, 192))) + + g1_mulAccC(_pVk, IC8x, IC8y, calldataload(add(pubSignals, 224))) + + g1_mulAccC(_pVk, IC9x, IC9y, calldataload(add(pubSignals, 256))) + + g1_mulAccC(_pVk, IC10x, IC10y, calldataload(add(pubSignals, 288))) + + g1_mulAccC(_pVk, IC11x, IC11y, calldataload(add(pubSignals, 320))) + + g1_mulAccC(_pVk, IC12x, IC12y, calldataload(add(pubSignals, 352))) + + g1_mulAccC(_pVk, IC13x, IC13y, calldataload(add(pubSignals, 384))) + + g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416))) + + g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448))) + + g1_mulAccC(_pVk, IC16x, IC16y, calldataload(add(pubSignals, 480))) + + g1_mulAccC(_pVk, IC17x, IC17y, calldataload(add(pubSignals, 512))) + + g1_mulAccC(_pVk, IC18x, IC18y, calldataload(add(pubSignals, 544))) + + g1_mulAccC(_pVk, IC19x, IC19y, calldataload(add(pubSignals, 576))) + + g1_mulAccC(_pVk, IC20x, IC20y, calldataload(add(pubSignals, 608))) + + g1_mulAccC(_pVk, IC21x, IC21y, calldataload(add(pubSignals, 640))) + + g1_mulAccC(_pVk, IC22x, IC22y, calldataload(add(pubSignals, 672))) + + g1_mulAccC(_pVk, IC23x, IC23y, calldataload(add(pubSignals, 704))) + + g1_mulAccC(_pVk, IC24x, IC24y, calldataload(add(pubSignals, 736))) + + g1_mulAccC(_pVk, IC25x, IC25y, calldataload(add(pubSignals, 768))) + + g1_mulAccC(_pVk, IC26x, IC26y, calldataload(add(pubSignals, 800))) + + g1_mulAccC(_pVk, IC27x, IC27y, calldataload(add(pubSignals, 832))) + + g1_mulAccC(_pVk, IC28x, IC28y, calldataload(add(pubSignals, 864))) + + g1_mulAccC(_pVk, IC29x, IC29y, calldataload(add(pubSignals, 896))) + + g1_mulAccC(_pVk, IC30x, IC30y, calldataload(add(pubSignals, 928))) + + g1_mulAccC(_pVk, IC31x, IC31y, calldataload(add(pubSignals, 960))) + + g1_mulAccC(_pVk, IC32x, IC32y, calldataload(add(pubSignals, 992))) + + g1_mulAccC(_pVk, IC33x, IC33y, calldataload(add(pubSignals, 1024))) + + g1_mulAccC(_pVk, IC34x, IC34y, calldataload(add(pubSignals, 1056))) + + g1_mulAccC(_pVk, IC35x, IC35y, calldataload(add(pubSignals, 1088))) + + g1_mulAccC(_pVk, IC36x, IC36y, calldataload(add(pubSignals, 1120))) + + g1_mulAccC(_pVk, IC37x, IC37y, calldataload(add(pubSignals, 1152))) + + + // -A + mstore(_pPairing, calldataload(pA)) + mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q)) + + // B + mstore(add(_pPairing, 64), calldataload(pB)) + mstore(add(_pPairing, 96), calldataload(add(pB, 32))) + mstore(add(_pPairing, 128), calldataload(add(pB, 64))) + mstore(add(_pPairing, 160), calldataload(add(pB, 96))) + + // alpha1 + mstore(add(_pPairing, 192), alphax) + mstore(add(_pPairing, 224), alphay) + + // beta2 + mstore(add(_pPairing, 256), betax1) + mstore(add(_pPairing, 288), betax2) + mstore(add(_pPairing, 320), betay1) + mstore(add(_pPairing, 352), betay2) + + // vk_x + mstore(add(_pPairing, 384), mload(add(pMem, pVk))) + mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32)))) + + + // gamma2 + mstore(add(_pPairing, 448), gammax1) + mstore(add(_pPairing, 480), gammax2) + mstore(add(_pPairing, 512), gammay1) + mstore(add(_pPairing, 544), gammay2) + + // C + mstore(add(_pPairing, 576), calldataload(pC)) + mstore(add(_pPairing, 608), calldataload(add(pC, 32))) + + // delta2 + mstore(add(_pPairing, 640), deltax1) + mstore(add(_pPairing, 672), deltax2) + mstore(add(_pPairing, 704), deltay1) + mstore(add(_pPairing, 736), deltay2) + + + let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20) + + isOk := and(success, mload(_pPairing)) + } + + let pMem := mload(0x40) + mstore(0x40, add(pMem, pLastMem)) + + // Validate that all evaluations ∈ F + + checkField(calldataload(add(_pubSignals, 0))) + + checkField(calldataload(add(_pubSignals, 32))) + + checkField(calldataload(add(_pubSignals, 64))) + + checkField(calldataload(add(_pubSignals, 96))) + + checkField(calldataload(add(_pubSignals, 128))) + + checkField(calldataload(add(_pubSignals, 160))) + + checkField(calldataload(add(_pubSignals, 192))) + + checkField(calldataload(add(_pubSignals, 224))) + + checkField(calldataload(add(_pubSignals, 256))) + + checkField(calldataload(add(_pubSignals, 288))) + + checkField(calldataload(add(_pubSignals, 320))) + + checkField(calldataload(add(_pubSignals, 352))) + + checkField(calldataload(add(_pubSignals, 384))) + + checkField(calldataload(add(_pubSignals, 416))) + + checkField(calldataload(add(_pubSignals, 448))) + + checkField(calldataload(add(_pubSignals, 480))) + + checkField(calldataload(add(_pubSignals, 512))) + + checkField(calldataload(add(_pubSignals, 544))) + + checkField(calldataload(add(_pubSignals, 576))) + + checkField(calldataload(add(_pubSignals, 608))) + + checkField(calldataload(add(_pubSignals, 640))) + + checkField(calldataload(add(_pubSignals, 672))) + + checkField(calldataload(add(_pubSignals, 704))) + + checkField(calldataload(add(_pubSignals, 736))) + + checkField(calldataload(add(_pubSignals, 768))) + + checkField(calldataload(add(_pubSignals, 800))) + + checkField(calldataload(add(_pubSignals, 832))) + + checkField(calldataload(add(_pubSignals, 864))) + + checkField(calldataload(add(_pubSignals, 896))) + + checkField(calldataload(add(_pubSignals, 928))) + + checkField(calldataload(add(_pubSignals, 960))) + + checkField(calldataload(add(_pubSignals, 992))) + + checkField(calldataload(add(_pubSignals, 1024))) + + checkField(calldataload(add(_pubSignals, 1056))) + + checkField(calldataload(add(_pubSignals, 1088))) + + checkField(calldataload(add(_pubSignals, 1120))) + + checkField(calldataload(add(_pubSignals, 1152))) + + checkField(calldataload(add(_pubSignals, 1184))) + + + // Validate all evaluations + let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) + + mstore(0, isValid) + return(0, 0x20) + } + } + } diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol new file mode 100644 index 0000000..97c429e --- /dev/null +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol @@ -0,0 +1,877 @@ +// SPDX-License-Identifier: GPL-3.0 +/* + Copyright 2021 0KIMS association. + + This file is generated with [snarkJS](https://github.com/iden3/snarkjs). + + snarkJS is a free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + snarkJS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with snarkJS. If not, see . +*/ + +pragma solidity >=0.7.0 <0.9.0; + +contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { + // Scalar field size + uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; + // Base field size + uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + + // Verification Key data + uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042; + uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958; + uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132; + uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731; + uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679; + uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856; + uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + uint256 constant deltax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant deltax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant deltay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + + + uint256 constant IC0x = 4462440718767044134998162351966451562518066257960346710377069184713247719285; + uint256 constant IC0y = 4569752707050948599946597207280276287539329707858295488707483945649429752219; + + uint256 constant IC1x = 15444985678636809312978594800523174081806733286376064553166174284965990139183; + uint256 constant IC1y = 15433744612719169811415194739223495951802871404441319181779987345899861341844; + + uint256 constant IC2x = 9885990037414753377583491462853432028093686282965905887310871111746174146380; + uint256 constant IC2y = 20559621090064053286923137529065108649443916661380064235986881033473985498037; + + uint256 constant IC3x = 15220266112866916329409503976568109087433925172545814071973149694002321739963; + uint256 constant IC3y = 9967028147547737060550357745757741357384433858664020146728346926570784983213; + + uint256 constant IC4x = 21329947211706016683568942206967750269087916034352353170682885227754293170481; + uint256 constant IC4y = 18598611223760756746575538031357011297686509434289269381366033907229098220076; + + uint256 constant IC5x = 6514122334235498249799999850630828523118746412876175037603777859661056194113; + uint256 constant IC5y = 7613641592052195772596513870294777261887749836185436293599101594590688831764; + + uint256 constant IC6x = 6746606194181022767983976806013080529050278399390805600511506371718262635580; + uint256 constant IC6y = 5040900530838847143133329941371911710669409792156418239777488229389953818400; + + uint256 constant IC7x = 16310252749266624170922178444895128571401957143728059112218900449972972021945; + uint256 constant IC7y = 19849405078170349616501907658417816640086069293900944359599337260725978612567; + + uint256 constant IC8x = 12943035592697513054598143597066138028290758819564583428418427834613361895771; + uint256 constant IC8y = 17603815873244763036387162451789002048178806753191740409503763948085037340112; + + uint256 constant IC9x = 12904271190452756689460709035613620779998753026875639942268876213610218682758; + uint256 constant IC9y = 3412240378584514469154301902106616900474125795462889373052017372977004157425; + + uint256 constant IC10x = 6331691481693568933183361080303344249163638849089168559069564832681362334724; + uint256 constant IC10y = 8408438512114059108704924659251298284430944217379780473759408521889262932134; + + uint256 constant IC11x = 8041263062859819383030208297472141365592753021388417731220753939751969377673; + uint256 constant IC11y = 15906453673686024215193939771448924145012672899421766118859189664796191133751; + + uint256 constant IC12x = 7215339494632317536574335410420512887140888961605922801690610674703936791690; + uint256 constant IC12y = 5270686168977103760944011889775790356727316296740640282588783046492617013757; + + uint256 constant IC13x = 3217265341412273322595135399781332967556551397197686878201114947206899054156; + uint256 constant IC13y = 7503102616401391535922628018582147279050323109558452732992780862830810951818; + + uint256 constant IC14x = 21246857811876870925486466013559756448469407207868226507156573943584195736416; + uint256 constant IC14y = 2733600684692003494872043879919178019288831300666309740857197105148878418766; + + uint256 constant IC15x = 20600577122988085366331314426352471330562718199855297539550267926322810640841; + uint256 constant IC15y = 16231929330271171876691408231412975041329685804795284908069818974298184549413; + + uint256 constant IC16x = 3013516493834933880571265579483555886116657612754656330314477838378338957763; + uint256 constant IC16y = 4496376340543514378135122386308791454382914017654185722966748034632858780883; + + uint256 constant IC17x = 14566715754086819820722811868524340109011579761633272047360433652167657911302; + uint256 constant IC17y = 5888712996271153651928451024341855957619655490208576862345200510559556697910; + + uint256 constant IC18x = 4481146920828229318871654483669942380846673321468443130293564421234695733769; + uint256 constant IC18y = 20271157044718789134443586019092533529315594280339405708777284721610164653084; + + uint256 constant IC19x = 12058758612490882679974363077579305208323053447875272297097120038018135913052; + uint256 constant IC19y = 15251484383604866864466202236981169528921776054941270557067166534203735798927; + + uint256 constant IC20x = 14361789899910818132818801031990221222431521926232911846069754141800047412360; + uint256 constant IC20y = 3150377779097660373125294170878683323827601265329891132712370470232745767578; + + uint256 constant IC21x = 19363025835995411733853977290476358325305107158384513584747918019127024228124; + uint256 constant IC21y = 18971551945271501522521473636649169684106226800265391745493927350489770667653; + + uint256 constant IC22x = 19094123125018762499054135540373802123371844243522347851507632970534404969456; + uint256 constant IC22y = 16670188470952100839466765185789885210730956023356075788636114796410130484092; + + uint256 constant IC23x = 18122032629347733938830121928377898437942771900957000944580840182850254686544; + uint256 constant IC23y = 5216591827501717404562544133936814946372134527719938477347011881553820377662; + + uint256 constant IC24x = 20338962917949833865771215887219893815884228544407317459733265502406290301230; + uint256 constant IC24y = 18217754241610423349007139096743310765887097807831672993502649666085097852143; + + uint256 constant IC25x = 20415938860422927750334419431682847419560950986736944577610364321907854090207; + uint256 constant IC25y = 1811706832137740078783015389752767524932208339888912260166095247754144082605; + + uint256 constant IC26x = 4009615321508047815711260104064529330703213737451287105919871546750408469276; + uint256 constant IC26y = 18353785168680766219428431427679557273060790378919012461419940007988830704229; + + uint256 constant IC27x = 9111725773120243221625374051231594321895925829959250777918988474111428552809; + uint256 constant IC27y = 8767914060970317701665738928409076785543974302457898585340147516686911169299; + + uint256 constant IC28x = 9843768039128456379484000470399826391786235218161014147193172378749485822345; + uint256 constant IC28y = 5942986358657480708744873333864211643806585484697708152331924831769550465700; + + uint256 constant IC29x = 21775778568767886964628862364878941499703483357546030912029290600060115760142; + uint256 constant IC29y = 14929316967024371538821998281577672404071550473413718889357628563929361046156; + + uint256 constant IC30x = 13927585571628534987997056150531190480940393397582513342264249485661286014978; + uint256 constant IC30y = 18232879627291556798959023849791585712917959449605097433654417997703384643144; + + uint256 constant IC31x = 18717068744029556727791880077138509136276808456366864775434322758401574592031; + uint256 constant IC31y = 14289080330654706444332688360679772953527061236492671656041020814456080933241; + + uint256 constant IC32x = 16538883082347184299127040695141316363634496860825578138296375998653495560797; + uint256 constant IC32y = 838870550326759636834239199515684239156603027830904458425034813850430718985; + + uint256 constant IC33x = 19009604105059969680889512086998975232417248905100216470638342724167877756963; + uint256 constant IC33y = 6887762894722810554303309191435986523098450884585415905948255411223686038312; + + uint256 constant IC34x = 16531683071318864874894878077899797406696996911006270311201733386895839734603; + uint256 constant IC34y = 8666717519577217798093188521875192145777039694421065876796414865172120401375; + + uint256 constant IC35x = 6177777554055783807993222014736847207883074977905725744563635107454847595529; + uint256 constant IC35y = 4263138318324315888046557447563161181503642778249092020567460303413399452760; + + uint256 constant IC36x = 4205536387120632613819296547301273289162157974895928179450315436333715150332; + uint256 constant IC36y = 20312416997511154415477343858536574450102877883177957262921784717954324572426; + + uint256 constant IC37x = 12942617918080900315903228453269136398127168902964184649535351245368329432965; + uint256 constant IC37y = 19157458222473093380136466829908207278488549984635155725898745872282753655398; + + uint256 constant IC38x = 12797139682577877058905772870479578076694731322444268435625480538739066576084; + uint256 constant IC38y = 20727104588637013174769304334623997926735939407551079492066161364902539626657; + + uint256 constant IC39x = 16193627270614812573290129156347962719805742569353052701817456772794934381276; + uint256 constant IC39y = 10942250866161132274428730958320192333701173304290140196956890358201765926569; + + uint256 constant IC40x = 12971960018139257046178803998989010317968596739040721055352793253859131510352; + uint256 constant IC40y = 19283254125631514544373761191562602608074231373915387788984894295259121506408; + + uint256 constant IC41x = 4973223975910783897813848245279259988338994201214380734138076226251147962275; + uint256 constant IC41y = 20308006563490699737057375027526499910953601577265600622293092320172949802335; + + uint256 constant IC42x = 17030317867513821418791571886460926935054674465473331652069943110476185476933; + uint256 constant IC42y = 20572233136020505493971200425387951894248945385198937170069383285929957457043; + + uint256 constant IC43x = 7692553451176703422505793001654611374627553094893150073088893053319586919972; + uint256 constant IC43y = 12753082405115929758469368345500564751358540682206343637633766733129482166950; + + uint256 constant IC44x = 12870749622804530478159602007951060728771320326463469142136290512480053201004; + uint256 constant IC44y = 14895591827941652855814380755451320737860546253193499816608439236526809467098; + + uint256 constant IC45x = 89196947066260254533869499130107799131613847960990725360446302663710649562; + uint256 constant IC45y = 407076608675591844134527309673272501547629118028165689413285461476628842228; + + uint256 constant IC46x = 14763410266333218926868118079821358534475399613923338328605601243110555424754; + uint256 constant IC46y = 17599204885038240804241721503294011005635060311218576426371347302446614183376; + + uint256 constant IC47x = 10118726747047738678104431085895810720035635051697291562288025077298088214733; + uint256 constant IC47y = 19322776357993901409655478160822770136901958925596664461964210451717594181232; + + uint256 constant IC48x = 17433596912197488142536558811210087828544024952005985935923537263724296695715; + uint256 constant IC48y = 10563946409897498644381864090366712696299250976464889740911072749915084138898; + + uint256 constant IC49x = 13437595226325828138834863780845764635828817268034607359176754616642326181698; + uint256 constant IC49y = 8377501808190853158752612250000097188008118650864377354654651658326636024296; + + uint256 constant IC50x = 18380606598711703423374534752675429629825934246200986774111473072918584427127; + uint256 constant IC50y = 14232575728529611668428027475223047875946997946012917158798714777202094329503; + + uint256 constant IC51x = 722367671757803999310885906594262002822084370153325403880129053184420701885; + uint256 constant IC51y = 16991411294824433258874180108296453730430695993836125555989956901768262080509; + + uint256 constant IC52x = 13496020518115514933800937650955414355602397955693565400373440221057424537585; + uint256 constant IC52y = 21065909895058099897589334673787294003396134826786731888651936425421401478719; + + uint256 constant IC53x = 19623439250443309619091947329218651409469889127936492083551551030014415896214; + uint256 constant IC53y = 2625205233558748178418480276522280268356341127041102822640388160424014599246; + + uint256 constant IC54x = 18346431934989235235833835905032456484485923699641645879365705207333658419610; + uint256 constant IC54y = 517136907682197625978064556574394476141925443618454737065827648376316242433; + + uint256 constant IC55x = 3138979905429106492828819779751961380852688942103014057270129945377102144728; + uint256 constant IC55y = 4903465287653415944608220202728816459875049299077299191348062489631432289882; + + uint256 constant IC56x = 3818666132496281252885342231969340100538892736272659098800199156423224696365; + uint256 constant IC56y = 16725255918872290527175982515440134508971630677817020227810816026732210759797; + + uint256 constant IC57x = 15849945242555071680578608251305533796240075167241767933635389762711709136304; + uint256 constant IC57y = 19623688497762019513766109452410765776236408137598055032664841343031733872901; + + uint256 constant IC58x = 15716627876476566418700698390911198187392470943729864252876805318847758555152; + uint256 constant IC58y = 21542720348956544826709230687050296321659755973899277940138213870535244729164; + + uint256 constant IC59x = 21693658306551142818774093970554285626530270967824079536598117886288628593146; + uint256 constant IC59y = 924528975935198499881293343023992285582826421462419983235368422315682295343; + + uint256 constant IC60x = 2378988107331033347460850151679461477793580217621829504536004163397015104074; + uint256 constant IC60y = 12839955041049287886502233201322183004427713008073313732274669695946418614228; + + uint256 constant IC61x = 21832468341560924658936327710153414558584780085683422694779457426165847177089; + uint256 constant IC61y = 117312274264272090414958277926262025708715360017579806546714831556964057144; + + uint256 constant IC62x = 3018238629968161579494804425259779540781422065436598113149379387035094736680; + uint256 constant IC62y = 8568458668401807393362413596709511290191073330862014248063413032803554773399; + + uint256 constant IC63x = 1282793573958458968971927933094471206080893678228175350336079122446958404776; + uint256 constant IC63y = 12498603528174334143768096584632542894223916853926331868937535155229078638823; + + uint256 constant IC64x = 9617959971065461584955469690391462382117093995070687589510083232925219095129; + uint256 constant IC64y = 11018863524303246149442260755881908287922941691112564596126416087093604345628; + + uint256 constant IC65x = 18494675724266065932303746924977017396929113474307371806359401523788727941102; + uint256 constant IC65y = 16097535133295928634162162517780143088230159419521341109791303759244723908021; + + uint256 constant IC66x = 3415083099541466355922472786777524696440486815659826538362856059090168466055; + uint256 constant IC66y = 21843737062657972494870832477594000579903382696442884201323513267380462660556; + + uint256 constant IC67x = 4627469073003492692081267340370476560059598725588643453272534146391992363677; + uint256 constant IC67y = 3394839797037366879180540434526009043184480393900353544974252557966593979511; + + uint256 constant IC68x = 16855117520614012750593394661559522115224312772742007753023953667480926227578; + uint256 constant IC68y = 17816700617479284171736370741327140530451913327152676849112278920461098914234; + + uint256 constant IC69x = 3512208942781784738441229046544557918978151298191395832170296860208887519468; + uint256 constant IC69y = 2505225700037331828802591636773326790452866581901318024097244918874744068789; + + uint256 constant IC70x = 11811112894872754299085263479604560501590590478241268189245643688628440648683; + uint256 constant IC70y = 18546962230916329328755427039622326464268028514850216640604830927968030769941; + + uint256 constant IC71x = 17329412769385041011755512074931622014464544007921945629255020213102531435089; + uint256 constant IC71y = 8532056905413803097496014769465279358661845164966338552710370018656926026144; + + uint256 constant IC72x = 12499852871185561422253376167019799648735207172681464009840294461239195188222; + uint256 constant IC72y = 20319333061740917925764368843994465380456164024362416598740064213349463358219; + + uint256 constant IC73x = 13611836739262056798799919892708716022648332399944377961590069121334082918207; + uint256 constant IC73y = 1840281673669819140440191639717881323130098454217953330681420681771305528256; + + uint256 constant IC74x = 3080059060826164654915928266386228070871170799938996404113716331864067144292; + uint256 constant IC74y = 12503063943054595204075468765331127452619970579940584908913636468482392270520; + + uint256 constant IC75x = 16433923389361333775927126833800818558680612925507786003170775000710001722305; + uint256 constant IC75y = 10503596066126211820217060014066415391057376892373743702389353058655984064889; + + uint256 constant IC76x = 15065785319856470226961945722003203551387687174246998508091850983372092860681; + uint256 constant IC76y = 17896225228571809315986423739118202445046664678781781514879686360269381776743; + + uint256 constant IC77x = 6870507339911801179138872152150615339958013992518264372631788950671523537614; + uint256 constant IC77y = 18037987737220811416285453912965586061676687691975309793517013459422037469273; + + uint256 constant IC78x = 11822997279102317026991317765680191121052478599918882398078859661358268572609; + uint256 constant IC78y = 9534844203451570681341326976899711845339261467471924061990479104987248699193; + + uint256 constant IC79x = 814895131247362788031531982991074036243262345850417573362708717291604432861; + uint256 constant IC79y = 21119163236943748654854615264754138892357106429981990456746055653318414462289; + + uint256 constant IC80x = 20977523352094306502640039044972336388464193873230419392339943532501600182549; + uint256 constant IC80y = 6946114395405271880485956008591194883884526407256410182099924261288084717296; + + uint256 constant IC81x = 7761194069996716601950630741239994979663258841042742617860461241304593607995; + uint256 constant IC81y = 6797191380097140836268094911544893630353880091765474528227264913999543456188; + + uint256 constant IC82x = 5000779558587306016002634421106764294422377396987971375779683765476680617367; + uint256 constant IC82y = 2847606885305153491337801029460483228469102266671889774030818592958554461000; + + uint256 constant IC83x = 2751416486345290827256675548931184221845108475099448535337243712621306648334; + uint256 constant IC83y = 13178855505750200729609370638681050600585376172418107165516640570458326734329; + + uint256 constant IC84x = 2231240240887990908791102754456950032619892746141888228754833711047565335291; + uint256 constant IC84y = 8186246799537450893888429295287350584243812961324933766087162379650650478146; + + uint256 constant IC85x = 6763520269685728106480261588448536867109810505037764388066571118455009345663; + uint256 constant IC85y = 13992198566440164726742004323044186581843713357791293320583243615794358038697; + + uint256 constant IC86x = 15119414408862590555871972886368557114099256030532542417814685037330684720768; + uint256 constant IC86y = 12651960976713863505082588076208802297943780899939898803346701374131052398909; + + uint256 constant IC87x = 21408174621836638638819070586317447414399450694528139169612961883475232668246; + uint256 constant IC87y = 8578504868019990506679317007240468112720944674191565915486280347133203190720; + + uint256 constant IC88x = 2782647542257934843851469693770665300487229167835685576077113843718087959867; + uint256 constant IC88y = 8867931823375641744668523057812106126349767332031839302450573191270189134171; + + uint256 constant IC89x = 11081787434921178311521055933193567788981208429171218116392059771404415915928; + uint256 constant IC89y = 13788691199354900700437740369989382948494894015767885728090020000181419577173; + + uint256 constant IC90x = 20412142355431119883654327361709186157969186949695197008618502840030428727513; + uint256 constant IC90y = 2637978714522201963297964679788704513672820014439747969926130681129386713861; + + uint256 constant IC91x = 16239438031981465694184986627702858819230905991973519513613416477752335486284; + uint256 constant IC91y = 586067010227246804824172701580729134690358529668454744500238895375711939871; + + uint256 constant IC92x = 6929626034770046196919926728056089724077903835689930035058009754021646837317; + uint256 constant IC92y = 14007720231836246873596106523297514407552613621031343551101023830932032505831; + + uint256 constant IC93x = 16191063119243167501349773152042552977077071420162570551428089527910135791691; + uint256 constant IC93y = 2984063520247837772995081663217075179586748361247613654084564271711901631617; + + uint256 constant IC94x = 1805678180711203997152780674041106704122361139443780127259289188160052960798; + uint256 constant IC94y = 15270845587733837292535075619741580576161184393824166722506351632755753865314; + + uint256 constant IC95x = 3030851989242786878227015219826255264454396167798762189510444533025354203347; + uint256 constant IC95y = 16780636433243520227559677544450077156636715628577721858217260980176889413252; + + uint256 constant IC96x = 4997143430537083890383903744684245387767882305763508413837134908583524834001; + uint256 constant IC96y = 8464708169272634602912508283222037851304014468407864911550343690773336631317; + + uint256 constant IC97x = 19449990402403926111015018329109064212719623759776180438013078952765416102804; + uint256 constant IC97y = 21012811006445063812663363396478099871012832817952978452182474412706339501325; + + uint256 constant IC98x = 21410072561093014667243485477372681620347269649123295559095808164172911680365; + uint256 constant IC98y = 19048135683243837600048166328392524449612017127669778956891490700257195759044; + + uint256 constant IC99x = 21807812488351239382456202149286344533518638925893692239226566402570030214620; + uint256 constant IC99y = 3629742897674077941851845853759045237433919524958880146116523921237166952508; + + uint256 constant IC100x = 12427392476134497199132588563614579041639492579857449719794721285072670141886; + uint256 constant IC100y = 12371491225153780473943451544387687913512052832901359322741447080589728901639; + + uint256 constant IC101x = 18443769813381837683086382929315220708416867094711673553986325183433940633782; + uint256 constant IC101y = 13338795090806453026229937430211181391630005899559855875683874904665077837972; + + uint256 constant IC102x = 7574561200290261962423462434572163854621504572881617953107242661231763189666; + uint256 constant IC102y = 21866390679404529040744442684466099062367291297634322269244096831308344158789; + + + // Memory data + uint16 constant pVk = 0; + uint16 constant pPairing = 128; + + uint16 constant pLastMem = 896; + + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[102] calldata _pubSignals) public view returns (bool) { + assembly { + function checkField(v) { + if iszero(lt(v, r)) { + mstore(0, 0) + return(0, 0x20) + } + } + + // G1 function to multiply a G1 value(x,y) to value in an address + function g1_mulAccC(pR, x, y, s) { + let success + let mIn := mload(0x40) + mstore(mIn, x) + mstore(add(mIn, 32), y) + mstore(add(mIn, 64), s) + + success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + + mstore(add(mIn, 64), mload(pR)) + mstore(add(mIn, 96), mload(add(pR, 32))) + + success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + } + + function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk { + let _pPairing := add(pMem, pPairing) + let _pVk := add(pMem, pVk) + + mstore(_pVk, IC0x) + mstore(add(_pVk, 32), IC0y) + + // Compute the linear combination vk_x + + g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0))) + + g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32))) + + g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64))) + + g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96))) + + g1_mulAccC(_pVk, IC5x, IC5y, calldataload(add(pubSignals, 128))) + + g1_mulAccC(_pVk, IC6x, IC6y, calldataload(add(pubSignals, 160))) + + g1_mulAccC(_pVk, IC7x, IC7y, calldataload(add(pubSignals, 192))) + + g1_mulAccC(_pVk, IC8x, IC8y, calldataload(add(pubSignals, 224))) + + g1_mulAccC(_pVk, IC9x, IC9y, calldataload(add(pubSignals, 256))) + + g1_mulAccC(_pVk, IC10x, IC10y, calldataload(add(pubSignals, 288))) + + g1_mulAccC(_pVk, IC11x, IC11y, calldataload(add(pubSignals, 320))) + + g1_mulAccC(_pVk, IC12x, IC12y, calldataload(add(pubSignals, 352))) + + g1_mulAccC(_pVk, IC13x, IC13y, calldataload(add(pubSignals, 384))) + + g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416))) + + g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448))) + + g1_mulAccC(_pVk, IC16x, IC16y, calldataload(add(pubSignals, 480))) + + g1_mulAccC(_pVk, IC17x, IC17y, calldataload(add(pubSignals, 512))) + + g1_mulAccC(_pVk, IC18x, IC18y, calldataload(add(pubSignals, 544))) + + g1_mulAccC(_pVk, IC19x, IC19y, calldataload(add(pubSignals, 576))) + + g1_mulAccC(_pVk, IC20x, IC20y, calldataload(add(pubSignals, 608))) + + g1_mulAccC(_pVk, IC21x, IC21y, calldataload(add(pubSignals, 640))) + + g1_mulAccC(_pVk, IC22x, IC22y, calldataload(add(pubSignals, 672))) + + g1_mulAccC(_pVk, IC23x, IC23y, calldataload(add(pubSignals, 704))) + + g1_mulAccC(_pVk, IC24x, IC24y, calldataload(add(pubSignals, 736))) + + g1_mulAccC(_pVk, IC25x, IC25y, calldataload(add(pubSignals, 768))) + + g1_mulAccC(_pVk, IC26x, IC26y, calldataload(add(pubSignals, 800))) + + g1_mulAccC(_pVk, IC27x, IC27y, calldataload(add(pubSignals, 832))) + + g1_mulAccC(_pVk, IC28x, IC28y, calldataload(add(pubSignals, 864))) + + g1_mulAccC(_pVk, IC29x, IC29y, calldataload(add(pubSignals, 896))) + + g1_mulAccC(_pVk, IC30x, IC30y, calldataload(add(pubSignals, 928))) + + g1_mulAccC(_pVk, IC31x, IC31y, calldataload(add(pubSignals, 960))) + + g1_mulAccC(_pVk, IC32x, IC32y, calldataload(add(pubSignals, 992))) + + g1_mulAccC(_pVk, IC33x, IC33y, calldataload(add(pubSignals, 1024))) + + g1_mulAccC(_pVk, IC34x, IC34y, calldataload(add(pubSignals, 1056))) + + g1_mulAccC(_pVk, IC35x, IC35y, calldataload(add(pubSignals, 1088))) + + g1_mulAccC(_pVk, IC36x, IC36y, calldataload(add(pubSignals, 1120))) + + g1_mulAccC(_pVk, IC37x, IC37y, calldataload(add(pubSignals, 1152))) + + g1_mulAccC(_pVk, IC38x, IC38y, calldataload(add(pubSignals, 1184))) + + g1_mulAccC(_pVk, IC39x, IC39y, calldataload(add(pubSignals, 1216))) + + g1_mulAccC(_pVk, IC40x, IC40y, calldataload(add(pubSignals, 1248))) + + g1_mulAccC(_pVk, IC41x, IC41y, calldataload(add(pubSignals, 1280))) + + g1_mulAccC(_pVk, IC42x, IC42y, calldataload(add(pubSignals, 1312))) + + g1_mulAccC(_pVk, IC43x, IC43y, calldataload(add(pubSignals, 1344))) + + g1_mulAccC(_pVk, IC44x, IC44y, calldataload(add(pubSignals, 1376))) + + g1_mulAccC(_pVk, IC45x, IC45y, calldataload(add(pubSignals, 1408))) + + g1_mulAccC(_pVk, IC46x, IC46y, calldataload(add(pubSignals, 1440))) + + g1_mulAccC(_pVk, IC47x, IC47y, calldataload(add(pubSignals, 1472))) + + g1_mulAccC(_pVk, IC48x, IC48y, calldataload(add(pubSignals, 1504))) + + g1_mulAccC(_pVk, IC49x, IC49y, calldataload(add(pubSignals, 1536))) + + g1_mulAccC(_pVk, IC50x, IC50y, calldataload(add(pubSignals, 1568))) + + g1_mulAccC(_pVk, IC51x, IC51y, calldataload(add(pubSignals, 1600))) + + g1_mulAccC(_pVk, IC52x, IC52y, calldataload(add(pubSignals, 1632))) + + g1_mulAccC(_pVk, IC53x, IC53y, calldataload(add(pubSignals, 1664))) + + g1_mulAccC(_pVk, IC54x, IC54y, calldataload(add(pubSignals, 1696))) + + g1_mulAccC(_pVk, IC55x, IC55y, calldataload(add(pubSignals, 1728))) + + g1_mulAccC(_pVk, IC56x, IC56y, calldataload(add(pubSignals, 1760))) + + g1_mulAccC(_pVk, IC57x, IC57y, calldataload(add(pubSignals, 1792))) + + g1_mulAccC(_pVk, IC58x, IC58y, calldataload(add(pubSignals, 1824))) + + g1_mulAccC(_pVk, IC59x, IC59y, calldataload(add(pubSignals, 1856))) + + g1_mulAccC(_pVk, IC60x, IC60y, calldataload(add(pubSignals, 1888))) + + g1_mulAccC(_pVk, IC61x, IC61y, calldataload(add(pubSignals, 1920))) + + g1_mulAccC(_pVk, IC62x, IC62y, calldataload(add(pubSignals, 1952))) + + g1_mulAccC(_pVk, IC63x, IC63y, calldataload(add(pubSignals, 1984))) + + g1_mulAccC(_pVk, IC64x, IC64y, calldataload(add(pubSignals, 2016))) + + g1_mulAccC(_pVk, IC65x, IC65y, calldataload(add(pubSignals, 2048))) + + g1_mulAccC(_pVk, IC66x, IC66y, calldataload(add(pubSignals, 2080))) + + g1_mulAccC(_pVk, IC67x, IC67y, calldataload(add(pubSignals, 2112))) + + g1_mulAccC(_pVk, IC68x, IC68y, calldataload(add(pubSignals, 2144))) + + g1_mulAccC(_pVk, IC69x, IC69y, calldataload(add(pubSignals, 2176))) + + g1_mulAccC(_pVk, IC70x, IC70y, calldataload(add(pubSignals, 2208))) + + g1_mulAccC(_pVk, IC71x, IC71y, calldataload(add(pubSignals, 2240))) + + g1_mulAccC(_pVk, IC72x, IC72y, calldataload(add(pubSignals, 2272))) + + g1_mulAccC(_pVk, IC73x, IC73y, calldataload(add(pubSignals, 2304))) + + g1_mulAccC(_pVk, IC74x, IC74y, calldataload(add(pubSignals, 2336))) + + g1_mulAccC(_pVk, IC75x, IC75y, calldataload(add(pubSignals, 2368))) + + g1_mulAccC(_pVk, IC76x, IC76y, calldataload(add(pubSignals, 2400))) + + g1_mulAccC(_pVk, IC77x, IC77y, calldataload(add(pubSignals, 2432))) + + g1_mulAccC(_pVk, IC78x, IC78y, calldataload(add(pubSignals, 2464))) + + g1_mulAccC(_pVk, IC79x, IC79y, calldataload(add(pubSignals, 2496))) + + g1_mulAccC(_pVk, IC80x, IC80y, calldataload(add(pubSignals, 2528))) + + g1_mulAccC(_pVk, IC81x, IC81y, calldataload(add(pubSignals, 2560))) + + g1_mulAccC(_pVk, IC82x, IC82y, calldataload(add(pubSignals, 2592))) + + g1_mulAccC(_pVk, IC83x, IC83y, calldataload(add(pubSignals, 2624))) + + g1_mulAccC(_pVk, IC84x, IC84y, calldataload(add(pubSignals, 2656))) + + g1_mulAccC(_pVk, IC85x, IC85y, calldataload(add(pubSignals, 2688))) + + g1_mulAccC(_pVk, IC86x, IC86y, calldataload(add(pubSignals, 2720))) + + g1_mulAccC(_pVk, IC87x, IC87y, calldataload(add(pubSignals, 2752))) + + g1_mulAccC(_pVk, IC88x, IC88y, calldataload(add(pubSignals, 2784))) + + g1_mulAccC(_pVk, IC89x, IC89y, calldataload(add(pubSignals, 2816))) + + g1_mulAccC(_pVk, IC90x, IC90y, calldataload(add(pubSignals, 2848))) + + g1_mulAccC(_pVk, IC91x, IC91y, calldataload(add(pubSignals, 2880))) + + g1_mulAccC(_pVk, IC92x, IC92y, calldataload(add(pubSignals, 2912))) + + g1_mulAccC(_pVk, IC93x, IC93y, calldataload(add(pubSignals, 2944))) + + g1_mulAccC(_pVk, IC94x, IC94y, calldataload(add(pubSignals, 2976))) + + g1_mulAccC(_pVk, IC95x, IC95y, calldataload(add(pubSignals, 3008))) + + g1_mulAccC(_pVk, IC96x, IC96y, calldataload(add(pubSignals, 3040))) + + g1_mulAccC(_pVk, IC97x, IC97y, calldataload(add(pubSignals, 3072))) + + g1_mulAccC(_pVk, IC98x, IC98y, calldataload(add(pubSignals, 3104))) + + g1_mulAccC(_pVk, IC99x, IC99y, calldataload(add(pubSignals, 3136))) + + g1_mulAccC(_pVk, IC100x, IC100y, calldataload(add(pubSignals, 3168))) + + g1_mulAccC(_pVk, IC101x, IC101y, calldataload(add(pubSignals, 3200))) + + g1_mulAccC(_pVk, IC102x, IC102y, calldataload(add(pubSignals, 3232))) + + + // -A + mstore(_pPairing, calldataload(pA)) + mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q)) + + // B + mstore(add(_pPairing, 64), calldataload(pB)) + mstore(add(_pPairing, 96), calldataload(add(pB, 32))) + mstore(add(_pPairing, 128), calldataload(add(pB, 64))) + mstore(add(_pPairing, 160), calldataload(add(pB, 96))) + + // alpha1 + mstore(add(_pPairing, 192), alphax) + mstore(add(_pPairing, 224), alphay) + + // beta2 + mstore(add(_pPairing, 256), betax1) + mstore(add(_pPairing, 288), betax2) + mstore(add(_pPairing, 320), betay1) + mstore(add(_pPairing, 352), betay2) + + // vk_x + mstore(add(_pPairing, 384), mload(add(pMem, pVk))) + mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32)))) + + + // gamma2 + mstore(add(_pPairing, 448), gammax1) + mstore(add(_pPairing, 480), gammax2) + mstore(add(_pPairing, 512), gammay1) + mstore(add(_pPairing, 544), gammay2) + + // C + mstore(add(_pPairing, 576), calldataload(pC)) + mstore(add(_pPairing, 608), calldataload(add(pC, 32))) + + // delta2 + mstore(add(_pPairing, 640), deltax1) + mstore(add(_pPairing, 672), deltax2) + mstore(add(_pPairing, 704), deltay1) + mstore(add(_pPairing, 736), deltay2) + + + let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20) + + isOk := and(success, mload(_pPairing)) + } + + let pMem := mload(0x40) + mstore(0x40, add(pMem, pLastMem)) + + // Validate that all evaluations ∈ F + + checkField(calldataload(add(_pubSignals, 0))) + + checkField(calldataload(add(_pubSignals, 32))) + + checkField(calldataload(add(_pubSignals, 64))) + + checkField(calldataload(add(_pubSignals, 96))) + + checkField(calldataload(add(_pubSignals, 128))) + + checkField(calldataload(add(_pubSignals, 160))) + + checkField(calldataload(add(_pubSignals, 192))) + + checkField(calldataload(add(_pubSignals, 224))) + + checkField(calldataload(add(_pubSignals, 256))) + + checkField(calldataload(add(_pubSignals, 288))) + + checkField(calldataload(add(_pubSignals, 320))) + + checkField(calldataload(add(_pubSignals, 352))) + + checkField(calldataload(add(_pubSignals, 384))) + + checkField(calldataload(add(_pubSignals, 416))) + + checkField(calldataload(add(_pubSignals, 448))) + + checkField(calldataload(add(_pubSignals, 480))) + + checkField(calldataload(add(_pubSignals, 512))) + + checkField(calldataload(add(_pubSignals, 544))) + + checkField(calldataload(add(_pubSignals, 576))) + + checkField(calldataload(add(_pubSignals, 608))) + + checkField(calldataload(add(_pubSignals, 640))) + + checkField(calldataload(add(_pubSignals, 672))) + + checkField(calldataload(add(_pubSignals, 704))) + + checkField(calldataload(add(_pubSignals, 736))) + + checkField(calldataload(add(_pubSignals, 768))) + + checkField(calldataload(add(_pubSignals, 800))) + + checkField(calldataload(add(_pubSignals, 832))) + + checkField(calldataload(add(_pubSignals, 864))) + + checkField(calldataload(add(_pubSignals, 896))) + + checkField(calldataload(add(_pubSignals, 928))) + + checkField(calldataload(add(_pubSignals, 960))) + + checkField(calldataload(add(_pubSignals, 992))) + + checkField(calldataload(add(_pubSignals, 1024))) + + checkField(calldataload(add(_pubSignals, 1056))) + + checkField(calldataload(add(_pubSignals, 1088))) + + checkField(calldataload(add(_pubSignals, 1120))) + + checkField(calldataload(add(_pubSignals, 1152))) + + checkField(calldataload(add(_pubSignals, 1184))) + + checkField(calldataload(add(_pubSignals, 1216))) + + checkField(calldataload(add(_pubSignals, 1248))) + + checkField(calldataload(add(_pubSignals, 1280))) + + checkField(calldataload(add(_pubSignals, 1312))) + + checkField(calldataload(add(_pubSignals, 1344))) + + checkField(calldataload(add(_pubSignals, 1376))) + + checkField(calldataload(add(_pubSignals, 1408))) + + checkField(calldataload(add(_pubSignals, 1440))) + + checkField(calldataload(add(_pubSignals, 1472))) + + checkField(calldataload(add(_pubSignals, 1504))) + + checkField(calldataload(add(_pubSignals, 1536))) + + checkField(calldataload(add(_pubSignals, 1568))) + + checkField(calldataload(add(_pubSignals, 1600))) + + checkField(calldataload(add(_pubSignals, 1632))) + + checkField(calldataload(add(_pubSignals, 1664))) + + checkField(calldataload(add(_pubSignals, 1696))) + + checkField(calldataload(add(_pubSignals, 1728))) + + checkField(calldataload(add(_pubSignals, 1760))) + + checkField(calldataload(add(_pubSignals, 1792))) + + checkField(calldataload(add(_pubSignals, 1824))) + + checkField(calldataload(add(_pubSignals, 1856))) + + checkField(calldataload(add(_pubSignals, 1888))) + + checkField(calldataload(add(_pubSignals, 1920))) + + checkField(calldataload(add(_pubSignals, 1952))) + + checkField(calldataload(add(_pubSignals, 1984))) + + checkField(calldataload(add(_pubSignals, 2016))) + + checkField(calldataload(add(_pubSignals, 2048))) + + checkField(calldataload(add(_pubSignals, 2080))) + + checkField(calldataload(add(_pubSignals, 2112))) + + checkField(calldataload(add(_pubSignals, 2144))) + + checkField(calldataload(add(_pubSignals, 2176))) + + checkField(calldataload(add(_pubSignals, 2208))) + + checkField(calldataload(add(_pubSignals, 2240))) + + checkField(calldataload(add(_pubSignals, 2272))) + + checkField(calldataload(add(_pubSignals, 2304))) + + checkField(calldataload(add(_pubSignals, 2336))) + + checkField(calldataload(add(_pubSignals, 2368))) + + checkField(calldataload(add(_pubSignals, 2400))) + + checkField(calldataload(add(_pubSignals, 2432))) + + checkField(calldataload(add(_pubSignals, 2464))) + + checkField(calldataload(add(_pubSignals, 2496))) + + checkField(calldataload(add(_pubSignals, 2528))) + + checkField(calldataload(add(_pubSignals, 2560))) + + checkField(calldataload(add(_pubSignals, 2592))) + + checkField(calldataload(add(_pubSignals, 2624))) + + checkField(calldataload(add(_pubSignals, 2656))) + + checkField(calldataload(add(_pubSignals, 2688))) + + checkField(calldataload(add(_pubSignals, 2720))) + + checkField(calldataload(add(_pubSignals, 2752))) + + checkField(calldataload(add(_pubSignals, 2784))) + + checkField(calldataload(add(_pubSignals, 2816))) + + checkField(calldataload(add(_pubSignals, 2848))) + + checkField(calldataload(add(_pubSignals, 2880))) + + checkField(calldataload(add(_pubSignals, 2912))) + + checkField(calldataload(add(_pubSignals, 2944))) + + checkField(calldataload(add(_pubSignals, 2976))) + + checkField(calldataload(add(_pubSignals, 3008))) + + checkField(calldataload(add(_pubSignals, 3040))) + + checkField(calldataload(add(_pubSignals, 3072))) + + checkField(calldataload(add(_pubSignals, 3104))) + + checkField(calldataload(add(_pubSignals, 3136))) + + checkField(calldataload(add(_pubSignals, 3168))) + + checkField(calldataload(add(_pubSignals, 3200))) + + checkField(calldataload(add(_pubSignals, 3232))) + + checkField(calldataload(add(_pubSignals, 3264))) + + + // Validate all evaluations + let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) + + mstore(0, isValid) + return(0, 0x20) + } + } + } diff --git a/solidity/contracts/lib/verifier_anon_nullifier_batch.sol b/solidity/contracts/lib/verifier_anon_nullifier_batch.sol new file mode 100644 index 0000000..ddc96d7 --- /dev/null +++ b/solidity/contracts/lib/verifier_anon_nullifier_batch.sol @@ -0,0 +1,380 @@ +// SPDX-License-Identifier: GPL-3.0 +/* + Copyright 2021 0KIMS association. + + This file is generated with [snarkJS](https://github.com/iden3/snarkjs). + + snarkJS is a free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + snarkJS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with snarkJS. If not, see . +*/ + +pragma solidity >=0.7.0 <0.9.0; + +contract Groth16Verifier_AnonNullifierBatch { + // Scalar field size + uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; + // Base field size + uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + + // Verification Key data + uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042; + uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958; + uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132; + uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731; + uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679; + uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856; + uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + uint256 constant deltax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant deltax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant deltay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + + + uint256 constant IC0x = 20844143144179933686367702853401659001635520044243582300318059483239634177695; + uint256 constant IC0y = 6956893127987346586986829449841068920703970681116433429161149984274729955150; + + uint256 constant IC1x = 3145257296588116228951217917659437011153808048295016630750634661573227655136; + uint256 constant IC1y = 11692686976241793602361646805224113669146832518433186263786203652119894682202; + + uint256 constant IC2x = 16258810049061785642786324998613222807846599083981592205168287535492316537730; + uint256 constant IC2y = 12251560167068319041987936419160993971679197422612698232359757036111894372663; + + uint256 constant IC3x = 251781136374948237986551327298197994537136901024713712357336516445425740592; + uint256 constant IC3y = 6227059871063762497220415891053961379240079035599643882420648758298833266542; + + uint256 constant IC4x = 8649560149784748604025905683235874568511947437413239525159237000293037617298; + uint256 constant IC4y = 8747524132149016931009206153273351341814570313184540398314387764445409252158; + + uint256 constant IC5x = 11524377559110038208935035612054843778802434027463732360891441909399945816797; + uint256 constant IC5y = 18828274067104221019896291561320103025121737743752362258177323570247152671928; + + uint256 constant IC6x = 7385161427131949497271670148755048425729464306154555291161088833019700279471; + uint256 constant IC6y = 19079861300823810080891280375686529744645001290941546750584479382979657289246; + + uint256 constant IC7x = 17934278616854511206424984073030417465445581765105585112091416104033803743042; + uint256 constant IC7y = 14710666138261018736711867414590007817342686156878524386850840867533993802458; + + uint256 constant IC8x = 14707384838160911457918999203818273609600051806011767213346322440794319155905; + uint256 constant IC8y = 13237987873586454942683016892111323980921950273085113968390467646435158084741; + + uint256 constant IC9x = 7562227225802748091972005428011361130005690253417511123075521190518795738149; + uint256 constant IC9y = 4661931025029160592061867769468775700733100438820387043571605053268353675276; + + uint256 constant IC10x = 8832584362940380960579414511468218447553605312077025224926791197187056385556; + uint256 constant IC10y = 9302218887041506854463034373316824720242916558732217573892008557715786667965; + + uint256 constant IC11x = 21209555931154727846096629287250005552280019040728430802966166542147340144233; + uint256 constant IC11y = 2071566621746845771862041312284464859664491179818305304210166050356392949705; + + uint256 constant IC12x = 950277162574048517298972242135187100023190595461411049273998606674829666008; + uint256 constant IC12y = 13575683112393817689056421975285185373895786482959786206453183726981837783596; + + uint256 constant IC13x = 12035747924156260190306427775717226720739331292774066045356563771007872767717; + uint256 constant IC13y = 3362253945111797894473225828901933246093284841324718877342445660643508802152; + + uint256 constant IC14x = 14137346988181889936217575935826112345993273796400738991890809144357301565496; + uint256 constant IC14y = 15637121408408019060319858805343647729218308519116021027187930932370871262676; + + uint256 constant IC15x = 13762873643526268013947632485931813861248721924789455076140043231430980762390; + uint256 constant IC15y = 9963293110830377293739765877755694764499419331215622126241313239553878025491; + + uint256 constant IC16x = 16692574613238032287283652982184597546335524897465441956026040107887285592543; + uint256 constant IC16y = 17292178457651461126524604559702058819667208809285906910210631878380949540985; + + uint256 constant IC17x = 21006997381406654206993340273166716734805806423755224685869754804308263604614; + uint256 constant IC17y = 11276113338642452423709056895012512446623471098033288820386384037599973211369; + + uint256 constant IC18x = 5549790547342287258223232153342939363197412516882599097529421254710739277932; + uint256 constant IC18y = 2321980957868435036369134816018219753345397660500077204638931350984124152509; + + uint256 constant IC19x = 15576570213143935319990221618758579058427975921328599747785461731895205749979; + uint256 constant IC19y = 2934186338144369040954708903760643286101176787266350772513796084984222769874; + + uint256 constant IC20x = 6137477004926598404997675240907254540828053394371866068349832466271296672929; + uint256 constant IC20y = 20888861283647246107329551100697915011175737920485206165339138558619907573843; + + uint256 constant IC21x = 14463409262299509615392506481758018285658547737656813334743931121364861756703; + uint256 constant IC21y = 7332787039324208062358154360486138008259450181030941396848043512484238275757; + + uint256 constant IC22x = 16601356363302138980638118097559879425695247168438568916519789560117559369274; + uint256 constant IC22y = 17787921183075222020103570772036143742977525428618366807704027634151186727940; + + uint256 constant IC23x = 12583431235651781757939013640433576160419876103048391410427308386104111565232; + uint256 constant IC23y = 3986398443693889094738419603281333618352214730101632334117232653906612934881; + + uint256 constant IC24x = 3853568607428240670449556852094203559518256205705378610563709475235813985869; + uint256 constant IC24y = 543064818712667001693516860666177754509195083882304081179747934873049678706; + + uint256 constant IC25x = 2885563210258556414381788942320848534195847749693881492631885970929346938859; + uint256 constant IC25y = 8131940318918107670107005557739113937288882470046042271398018679856018871886; + + uint256 constant IC26x = 17010995670940491819617933270493324753886079844847190687868033412180995569776; + uint256 constant IC26y = 1131002585900701640305315232975026396983461884863407554004202067072144971084; + + uint256 constant IC27x = 8218092164315760638693205679360581362550320900615925231277371834562473628432; + uint256 constant IC27y = 804708916368827372063223656560578153797821838602606304217568072164318993236; + + uint256 constant IC28x = 5399094891216602742965040821422609449504212935322660879066435153850561721165; + uint256 constant IC28y = 1265562530391696201126288116617589607013674244193599604325171580589223550213; + + uint256 constant IC29x = 12663247164972275544017007748295885957218341893889185539064234743460082294717; + uint256 constant IC29y = 9413051200923723465055492328404732423271148428325190065591941881643336354578; + + uint256 constant IC30x = 10229493101680001535059987062347611183366892099697060172642147707296073449034; + uint256 constant IC30y = 5341823103341504835994668879856735786794919965665449958641465848415231797279; + + uint256 constant IC31x = 17299647136322859689775136480319515957049987852882873899315494679093188679533; + uint256 constant IC31y = 5603736654692809267331406367699483579804529124597898174480040309340108654851; + + + // Memory data + uint16 constant pVk = 0; + uint16 constant pPairing = 128; + + uint16 constant pLastMem = 896; + + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[31] calldata _pubSignals) public view returns (bool) { + assembly { + function checkField(v) { + if iszero(lt(v, r)) { + mstore(0, 0) + return(0, 0x20) + } + } + + // G1 function to multiply a G1 value(x,y) to value in an address + function g1_mulAccC(pR, x, y, s) { + let success + let mIn := mload(0x40) + mstore(mIn, x) + mstore(add(mIn, 32), y) + mstore(add(mIn, 64), s) + + success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + + mstore(add(mIn, 64), mload(pR)) + mstore(add(mIn, 96), mload(add(pR, 32))) + + success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + } + + function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk { + let _pPairing := add(pMem, pPairing) + let _pVk := add(pMem, pVk) + + mstore(_pVk, IC0x) + mstore(add(_pVk, 32), IC0y) + + // Compute the linear combination vk_x + + g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0))) + + g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32))) + + g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64))) + + g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96))) + + g1_mulAccC(_pVk, IC5x, IC5y, calldataload(add(pubSignals, 128))) + + g1_mulAccC(_pVk, IC6x, IC6y, calldataload(add(pubSignals, 160))) + + g1_mulAccC(_pVk, IC7x, IC7y, calldataload(add(pubSignals, 192))) + + g1_mulAccC(_pVk, IC8x, IC8y, calldataload(add(pubSignals, 224))) + + g1_mulAccC(_pVk, IC9x, IC9y, calldataload(add(pubSignals, 256))) + + g1_mulAccC(_pVk, IC10x, IC10y, calldataload(add(pubSignals, 288))) + + g1_mulAccC(_pVk, IC11x, IC11y, calldataload(add(pubSignals, 320))) + + g1_mulAccC(_pVk, IC12x, IC12y, calldataload(add(pubSignals, 352))) + + g1_mulAccC(_pVk, IC13x, IC13y, calldataload(add(pubSignals, 384))) + + g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416))) + + g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448))) + + g1_mulAccC(_pVk, IC16x, IC16y, calldataload(add(pubSignals, 480))) + + g1_mulAccC(_pVk, IC17x, IC17y, calldataload(add(pubSignals, 512))) + + g1_mulAccC(_pVk, IC18x, IC18y, calldataload(add(pubSignals, 544))) + + g1_mulAccC(_pVk, IC19x, IC19y, calldataload(add(pubSignals, 576))) + + g1_mulAccC(_pVk, IC20x, IC20y, calldataload(add(pubSignals, 608))) + + g1_mulAccC(_pVk, IC21x, IC21y, calldataload(add(pubSignals, 640))) + + g1_mulAccC(_pVk, IC22x, IC22y, calldataload(add(pubSignals, 672))) + + g1_mulAccC(_pVk, IC23x, IC23y, calldataload(add(pubSignals, 704))) + + g1_mulAccC(_pVk, IC24x, IC24y, calldataload(add(pubSignals, 736))) + + g1_mulAccC(_pVk, IC25x, IC25y, calldataload(add(pubSignals, 768))) + + g1_mulAccC(_pVk, IC26x, IC26y, calldataload(add(pubSignals, 800))) + + g1_mulAccC(_pVk, IC27x, IC27y, calldataload(add(pubSignals, 832))) + + g1_mulAccC(_pVk, IC28x, IC28y, calldataload(add(pubSignals, 864))) + + g1_mulAccC(_pVk, IC29x, IC29y, calldataload(add(pubSignals, 896))) + + g1_mulAccC(_pVk, IC30x, IC30y, calldataload(add(pubSignals, 928))) + + g1_mulAccC(_pVk, IC31x, IC31y, calldataload(add(pubSignals, 960))) + + + // -A + mstore(_pPairing, calldataload(pA)) + mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q)) + + // B + mstore(add(_pPairing, 64), calldataload(pB)) + mstore(add(_pPairing, 96), calldataload(add(pB, 32))) + mstore(add(_pPairing, 128), calldataload(add(pB, 64))) + mstore(add(_pPairing, 160), calldataload(add(pB, 96))) + + // alpha1 + mstore(add(_pPairing, 192), alphax) + mstore(add(_pPairing, 224), alphay) + + // beta2 + mstore(add(_pPairing, 256), betax1) + mstore(add(_pPairing, 288), betax2) + mstore(add(_pPairing, 320), betay1) + mstore(add(_pPairing, 352), betay2) + + // vk_x + mstore(add(_pPairing, 384), mload(add(pMem, pVk))) + mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32)))) + + + // gamma2 + mstore(add(_pPairing, 448), gammax1) + mstore(add(_pPairing, 480), gammax2) + mstore(add(_pPairing, 512), gammay1) + mstore(add(_pPairing, 544), gammay2) + + // C + mstore(add(_pPairing, 576), calldataload(pC)) + mstore(add(_pPairing, 608), calldataload(add(pC, 32))) + + // delta2 + mstore(add(_pPairing, 640), deltax1) + mstore(add(_pPairing, 672), deltax2) + mstore(add(_pPairing, 704), deltay1) + mstore(add(_pPairing, 736), deltay2) + + + let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20) + + isOk := and(success, mload(_pPairing)) + } + + let pMem := mload(0x40) + mstore(0x40, add(pMem, pLastMem)) + + // Validate that all evaluations ∈ F + + checkField(calldataload(add(_pubSignals, 0))) + + checkField(calldataload(add(_pubSignals, 32))) + + checkField(calldataload(add(_pubSignals, 64))) + + checkField(calldataload(add(_pubSignals, 96))) + + checkField(calldataload(add(_pubSignals, 128))) + + checkField(calldataload(add(_pubSignals, 160))) + + checkField(calldataload(add(_pubSignals, 192))) + + checkField(calldataload(add(_pubSignals, 224))) + + checkField(calldataload(add(_pubSignals, 256))) + + checkField(calldataload(add(_pubSignals, 288))) + + checkField(calldataload(add(_pubSignals, 320))) + + checkField(calldataload(add(_pubSignals, 352))) + + checkField(calldataload(add(_pubSignals, 384))) + + checkField(calldataload(add(_pubSignals, 416))) + + checkField(calldataload(add(_pubSignals, 448))) + + checkField(calldataload(add(_pubSignals, 480))) + + checkField(calldataload(add(_pubSignals, 512))) + + checkField(calldataload(add(_pubSignals, 544))) + + checkField(calldataload(add(_pubSignals, 576))) + + checkField(calldataload(add(_pubSignals, 608))) + + checkField(calldataload(add(_pubSignals, 640))) + + checkField(calldataload(add(_pubSignals, 672))) + + checkField(calldataload(add(_pubSignals, 704))) + + checkField(calldataload(add(_pubSignals, 736))) + + checkField(calldataload(add(_pubSignals, 768))) + + checkField(calldataload(add(_pubSignals, 800))) + + checkField(calldataload(add(_pubSignals, 832))) + + checkField(calldataload(add(_pubSignals, 864))) + + checkField(calldataload(add(_pubSignals, 896))) + + checkField(calldataload(add(_pubSignals, 928))) + + checkField(calldataload(add(_pubSignals, 960))) + + checkField(calldataload(add(_pubSignals, 992))) + + + // Validate all evaluations + let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) + + mstore(0, isValid) + return(0, 0x20) + } + } + } diff --git a/solidity/contracts/lib/verifier_anon_nullifier_kyc_batch.sol b/solidity/contracts/lib/verifier_anon_nullifier_kyc_batch.sol new file mode 100644 index 0000000..b97aa3c --- /dev/null +++ b/solidity/contracts/lib/verifier_anon_nullifier_kyc_batch.sol @@ -0,0 +1,387 @@ +// SPDX-License-Identifier: GPL-3.0 +/* + Copyright 2021 0KIMS association. + + This file is generated with [snarkJS](https://github.com/iden3/snarkjs). + + snarkJS is a free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + snarkJS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with snarkJS. If not, see . +*/ + +pragma solidity >=0.7.0 <0.9.0; + +contract Groth16Verifier_AnonNullifierKycBatch { + // Scalar field size + uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; + // Base field size + uint256 constant q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; + + // Verification Key data + uint256 constant alphax = 20491192805390485299153009773594534940189261866228447918068658471970481763042; + uint256 constant alphay = 9383485363053290200918347156157836566562967994039712273449902621266178545958; + uint256 constant betax1 = 4252822878758300859123897981450591353533073413197771768651442665752259397132; + uint256 constant betax2 = 6375614351688725206403948262868962793625744043794305715222011528459656738731; + uint256 constant betay1 = 21847035105528745403288232691147584728191162732299865338377159692350059136679; + uint256 constant betay2 = 10505242626370262277552901082094356697409835680220590971873171140371331206856; + uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + uint256 constant deltax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 constant deltax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 constant deltay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; + + + uint256 constant IC0x = 20853042574020946235840302632951626448584729217430463073658625252653442234470; + uint256 constant IC0y = 14503138457722137782191667133387775512378441450608154667415400997876588375756; + + uint256 constant IC1x = 9917108883241745455761018857293725080986600904966561402987858446669928171562; + uint256 constant IC1y = 13591576404881350424099489953236979715833180126901849937308367347767610003465; + + uint256 constant IC2x = 3439313319113787828822932825613902061625901916953552729570520107357795750003; + uint256 constant IC2y = 9071769450731382460996101819929952295744188293777029244789694675101186914880; + + uint256 constant IC3x = 11071390041396097409656810177854839065668652917492828205135215218787046170986; + uint256 constant IC3y = 3272310063044466086764292869007916039227746382830358278319476052921781064725; + + uint256 constant IC4x = 996881781996032055965059788092723706548950481104118223959532856028689400891; + uint256 constant IC4y = 10532644959511591332308661306141830757428321012840862531511843489701188531007; + + uint256 constant IC5x = 16385079024538141632411180902174351098878184968791691093347655199291480888415; + uint256 constant IC5y = 12145168420230320464303312360648053440022739646635064174869624146870557981618; + + uint256 constant IC6x = 3992613102026963086376267251279994644621145284197309267871587996886604272592; + uint256 constant IC6y = 14963328476320115013495064157131701351415433169672444967080683342149793144980; + + uint256 constant IC7x = 5981370305969014820267670759122547893731675070596036612273472072253851282228; + uint256 constant IC7y = 3438141511037073702365606004410722567958864390457606755249640661003617200959; + + uint256 constant IC8x = 21547361705076824058864897700975767421445572004417178472869801085917191751053; + uint256 constant IC8y = 12999813802284380841701554591228638984354832042714692917690348439711845925786; + + uint256 constant IC9x = 14925705040521825434725348380587205868708787466106833983126208243739784325880; + uint256 constant IC9y = 13758617988846944266119557597035763290845707283246935944438721816538364307440; + + uint256 constant IC10x = 16238678108997178508219583626087543367523363104143821500531018331128543816027; + uint256 constant IC10y = 20988334055882823813676265253003773967912918491946607153880822125279265295099; + + uint256 constant IC11x = 12463438669969160987739884097285949261976866404968861676769237436058385801469; + uint256 constant IC11y = 270011245713606791865522697127318460224244162144440036914608059839284140679; + + uint256 constant IC12x = 14425667004891942326901126602922354917481325657272065431210263120371031139386; + uint256 constant IC12y = 8309982229703456513092026779649997434002091050319895182314276093188954677394; + + uint256 constant IC13x = 7465033032486596700975998529561351608432568332029212554720368237664678873395; + uint256 constant IC13y = 19595443713093539422546405240457003346980791492404739217874241019739472718381; + + uint256 constant IC14x = 14691687249031531163869527355048787597122549812332779621162154509937138571924; + uint256 constant IC14y = 17802893028884323977106339050154399655146360203535885909201781361795599138777; + + uint256 constant IC15x = 11311460953090916038412938363173223681102634415830351013156281568159118324573; + uint256 constant IC15y = 989424361042903697721304390768895807648689453596077746086797179149951408171; + + uint256 constant IC16x = 8115210135502535315095755231549369443363739326778462555855100709757443031875; + uint256 constant IC16y = 3399309059585388188749745821681321969923494328608462736591564694635156883018; + + uint256 constant IC17x = 8057525237113913042507983000939528960621623812954743702785235804447181483476; + uint256 constant IC17y = 11745508255799538715267264369198317129411105677293807565792222040292163514690; + + uint256 constant IC18x = 12882807096622945037046242519935093674601153177531384614838357303812929546434; + uint256 constant IC18y = 14167183722748533864284151708151235074065479637878014422305168060669442759124; + + uint256 constant IC19x = 19157711982679260432612324639548309993214116386141443298649333176424963278008; + uint256 constant IC19y = 18887459881212198278163366740593313984610163871911225805583022177205802284106; + + uint256 constant IC20x = 6820016076303366905281218333771319642092009820489375329286304918390680797076; + uint256 constant IC20y = 2011003244794874591620399658770025487624841238441008369549360919209162431452; + + uint256 constant IC21x = 11041858300928368147282501090696352446503267451042743846924625524700949589333; + uint256 constant IC21y = 18326112349200889304757099732521649558736758992759435858884556656373804632540; + + uint256 constant IC22x = 19270053956090024762685183355862847807940837944222186876532100272229966284063; + uint256 constant IC22y = 6755707463932868859120703481720189322239061262061342349595686619636209076032; + + uint256 constant IC23x = 14053076389630026405095058736457484143951784177074765146291105887519279239631; + uint256 constant IC23y = 5781535215165614826618204367105163909125962009938863102327081807253219564177; + + uint256 constant IC24x = 16520121922742730700115206847425977584572662211415479692333894716807168534635; + uint256 constant IC24y = 1097596215960000784908553058258153084091625215200170506677504975817144320377; + + uint256 constant IC25x = 7177925932485708100888950060980021914147468071168635995447299902061247390967; + uint256 constant IC25y = 10219836500844667480405804775499348980007485977518659417779754787366552657126; + + uint256 constant IC26x = 3501572605055564424981383194400900888063129293811612920810221741230443016407; + uint256 constant IC26y = 16388010556608225219508510331953863848059248100921826015425452033600132558501; + + uint256 constant IC27x = 821629801785990279612662785124699542694089690212215734187557850876770421856; + uint256 constant IC27y = 19080762213042567735389244764183591911677853260112860780943095910556531204198; + + uint256 constant IC28x = 16852281762315476053210814715155070801137202720975023006070913982938627645876; + uint256 constant IC28y = 7213332702185063988587527288845721443807112228829510340283781784592101934378; + + uint256 constant IC29x = 4009657540500682658456131646734110816806134393092673870093501487131176269366; + uint256 constant IC29y = 4642340153685914773598767712007875167875744207496785942087827910783897016130; + + uint256 constant IC30x = 2354097312656732326431256481812991541730435396462756081659188095985189268893; + uint256 constant IC30y = 5648911243543082544815214546011075680816809894496626503218159000561356166387; + + uint256 constant IC31x = 21349175980680327148991838367425372259029351360226383721547593451385165894470; + uint256 constant IC31y = 2226069768655531699819829432398234311723723757156974454812739012506324533869; + + uint256 constant IC32x = 6889212865028125309464348326210571985659646832435844307314388021016016438758; + uint256 constant IC32y = 3898026925935534773719478862659632823086703925842749427712203456282341722035; + + + // Memory data + uint16 constant pVk = 0; + uint16 constant pPairing = 128; + + uint16 constant pLastMem = 896; + + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[32] calldata _pubSignals) public view returns (bool) { + assembly { + function checkField(v) { + if iszero(lt(v, r)) { + mstore(0, 0) + return(0, 0x20) + } + } + + // G1 function to multiply a G1 value(x,y) to value in an address + function g1_mulAccC(pR, x, y, s) { + let success + let mIn := mload(0x40) + mstore(mIn, x) + mstore(add(mIn, 32), y) + mstore(add(mIn, 64), s) + + success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + + mstore(add(mIn, 64), mload(pR)) + mstore(add(mIn, 96), mload(add(pR, 32))) + + success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64) + + if iszero(success) { + mstore(0, 0) + return(0, 0x20) + } + } + + function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk { + let _pPairing := add(pMem, pPairing) + let _pVk := add(pMem, pVk) + + mstore(_pVk, IC0x) + mstore(add(_pVk, 32), IC0y) + + // Compute the linear combination vk_x + + g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0))) + + g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32))) + + g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64))) + + g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96))) + + g1_mulAccC(_pVk, IC5x, IC5y, calldataload(add(pubSignals, 128))) + + g1_mulAccC(_pVk, IC6x, IC6y, calldataload(add(pubSignals, 160))) + + g1_mulAccC(_pVk, IC7x, IC7y, calldataload(add(pubSignals, 192))) + + g1_mulAccC(_pVk, IC8x, IC8y, calldataload(add(pubSignals, 224))) + + g1_mulAccC(_pVk, IC9x, IC9y, calldataload(add(pubSignals, 256))) + + g1_mulAccC(_pVk, IC10x, IC10y, calldataload(add(pubSignals, 288))) + + g1_mulAccC(_pVk, IC11x, IC11y, calldataload(add(pubSignals, 320))) + + g1_mulAccC(_pVk, IC12x, IC12y, calldataload(add(pubSignals, 352))) + + g1_mulAccC(_pVk, IC13x, IC13y, calldataload(add(pubSignals, 384))) + + g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416))) + + g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448))) + + g1_mulAccC(_pVk, IC16x, IC16y, calldataload(add(pubSignals, 480))) + + g1_mulAccC(_pVk, IC17x, IC17y, calldataload(add(pubSignals, 512))) + + g1_mulAccC(_pVk, IC18x, IC18y, calldataload(add(pubSignals, 544))) + + g1_mulAccC(_pVk, IC19x, IC19y, calldataload(add(pubSignals, 576))) + + g1_mulAccC(_pVk, IC20x, IC20y, calldataload(add(pubSignals, 608))) + + g1_mulAccC(_pVk, IC21x, IC21y, calldataload(add(pubSignals, 640))) + + g1_mulAccC(_pVk, IC22x, IC22y, calldataload(add(pubSignals, 672))) + + g1_mulAccC(_pVk, IC23x, IC23y, calldataload(add(pubSignals, 704))) + + g1_mulAccC(_pVk, IC24x, IC24y, calldataload(add(pubSignals, 736))) + + g1_mulAccC(_pVk, IC25x, IC25y, calldataload(add(pubSignals, 768))) + + g1_mulAccC(_pVk, IC26x, IC26y, calldataload(add(pubSignals, 800))) + + g1_mulAccC(_pVk, IC27x, IC27y, calldataload(add(pubSignals, 832))) + + g1_mulAccC(_pVk, IC28x, IC28y, calldataload(add(pubSignals, 864))) + + g1_mulAccC(_pVk, IC29x, IC29y, calldataload(add(pubSignals, 896))) + + g1_mulAccC(_pVk, IC30x, IC30y, calldataload(add(pubSignals, 928))) + + g1_mulAccC(_pVk, IC31x, IC31y, calldataload(add(pubSignals, 960))) + + g1_mulAccC(_pVk, IC32x, IC32y, calldataload(add(pubSignals, 992))) + + + // -A + mstore(_pPairing, calldataload(pA)) + mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q)) + + // B + mstore(add(_pPairing, 64), calldataload(pB)) + mstore(add(_pPairing, 96), calldataload(add(pB, 32))) + mstore(add(_pPairing, 128), calldataload(add(pB, 64))) + mstore(add(_pPairing, 160), calldataload(add(pB, 96))) + + // alpha1 + mstore(add(_pPairing, 192), alphax) + mstore(add(_pPairing, 224), alphay) + + // beta2 + mstore(add(_pPairing, 256), betax1) + mstore(add(_pPairing, 288), betax2) + mstore(add(_pPairing, 320), betay1) + mstore(add(_pPairing, 352), betay2) + + // vk_x + mstore(add(_pPairing, 384), mload(add(pMem, pVk))) + mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32)))) + + + // gamma2 + mstore(add(_pPairing, 448), gammax1) + mstore(add(_pPairing, 480), gammax2) + mstore(add(_pPairing, 512), gammay1) + mstore(add(_pPairing, 544), gammay2) + + // C + mstore(add(_pPairing, 576), calldataload(pC)) + mstore(add(_pPairing, 608), calldataload(add(pC, 32))) + + // delta2 + mstore(add(_pPairing, 640), deltax1) + mstore(add(_pPairing, 672), deltax2) + mstore(add(_pPairing, 704), deltay1) + mstore(add(_pPairing, 736), deltay2) + + + let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20) + + isOk := and(success, mload(_pPairing)) + } + + let pMem := mload(0x40) + mstore(0x40, add(pMem, pLastMem)) + + // Validate that all evaluations ∈ F + + checkField(calldataload(add(_pubSignals, 0))) + + checkField(calldataload(add(_pubSignals, 32))) + + checkField(calldataload(add(_pubSignals, 64))) + + checkField(calldataload(add(_pubSignals, 96))) + + checkField(calldataload(add(_pubSignals, 128))) + + checkField(calldataload(add(_pubSignals, 160))) + + checkField(calldataload(add(_pubSignals, 192))) + + checkField(calldataload(add(_pubSignals, 224))) + + checkField(calldataload(add(_pubSignals, 256))) + + checkField(calldataload(add(_pubSignals, 288))) + + checkField(calldataload(add(_pubSignals, 320))) + + checkField(calldataload(add(_pubSignals, 352))) + + checkField(calldataload(add(_pubSignals, 384))) + + checkField(calldataload(add(_pubSignals, 416))) + + checkField(calldataload(add(_pubSignals, 448))) + + checkField(calldataload(add(_pubSignals, 480))) + + checkField(calldataload(add(_pubSignals, 512))) + + checkField(calldataload(add(_pubSignals, 544))) + + checkField(calldataload(add(_pubSignals, 576))) + + checkField(calldataload(add(_pubSignals, 608))) + + checkField(calldataload(add(_pubSignals, 640))) + + checkField(calldataload(add(_pubSignals, 672))) + + checkField(calldataload(add(_pubSignals, 704))) + + checkField(calldataload(add(_pubSignals, 736))) + + checkField(calldataload(add(_pubSignals, 768))) + + checkField(calldataload(add(_pubSignals, 800))) + + checkField(calldataload(add(_pubSignals, 832))) + + checkField(calldataload(add(_pubSignals, 864))) + + checkField(calldataload(add(_pubSignals, 896))) + + checkField(calldataload(add(_pubSignals, 928))) + + checkField(calldataload(add(_pubSignals, 960))) + + checkField(calldataload(add(_pubSignals, 992))) + + checkField(calldataload(add(_pubSignals, 1024))) + + + // Validate all evaluations + let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) + + mstore(0, isValid) + return(0, 0x20) + } + } + } diff --git a/solidity/contracts/zeto_anon.sol b/solidity/contracts/zeto_anon.sol index 74b0dc0..de778bf 100644 --- a/solidity/contracts/zeto_anon.sol +++ b/solidity/contracts/zeto_anon.sol @@ -19,6 +19,7 @@ import {IZeto} from "./lib/interfaces/izeto.sol"; import {Groth16Verifier_CheckHashesValue} from "./lib/verifier_check_hashes_value.sol"; import {Groth16Verifier_CheckInputsOutputsValue} from "./lib/verifier_check_inputs_outputs_value.sol"; import {Groth16Verifier_Anon} from "./lib/verifier_anon.sol"; +import {Groth16Verifier_AnonBatch} from "./lib/verifier_anon_batch.sol"; import {Registry} from "./lib/registry.sol"; import {Commonlib} from "./lib/common.sol"; import {ZetoBase} from "./lib/zeto_base.sol"; @@ -36,16 +37,19 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/U /// - the sender possesses the private BabyJubjub key, whose public key is part of the pre-image of the input commitment hashes contract Zeto_Anon is IZeto, ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable { Groth16Verifier_Anon internal verifier; + Groth16Verifier_AnonBatch internal batchVerifier; function initialize( address initialOwner, Groth16Verifier_Anon _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckInputsOutputsValue _withdrawVerifier + Groth16Verifier_CheckInputsOutputsValue _withdrawVerifier, + Groth16Verifier_AnonBatch _batchVerifier ) public initializer { __ZetoBase_init(initialOwner); __ZetoFungibleWithdraw_init(_depositVerifier, _withdrawVerifier); verifier = _verifier; + batchVerifier = _batchVerifier; } function _authorizeUpgrade(address) internal override onlyOwner {} @@ -61,11 +65,19 @@ contract Zeto_Anon is IZeto, ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable { * Emits a {UTXOTransfer} event. */ function transfer( - uint256[2] memory inputs, - uint256[2] memory outputs, + uint256[] memory inputs, + uint256[] memory outputs, Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { + uint256 inputLen = inputs.length; + uint256 outputLen = outputs.length; + + require( + (inputLen <= 10 && outputsLen <= 10), + "Inputs or outputs exceeded maximum number of 10" + ); + require( validateTransactionProposal(inputs, outputs, proof), "Invalid transaction proposal" @@ -120,7 +132,10 @@ contract Zeto_Anon is IZeto, ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable { processInputsAndOutputs(inputs, [output, 0]); } - function mint(uint256[] memory utxos, bytes calldata data) public onlyOwner { + function mint( + uint256[] memory utxos, + bytes calldata data + ) public onlyOwner { _mint(utxos, data); } } diff --git a/solidity/contracts/zeto_anon_enc.sol b/solidity/contracts/zeto_anon_enc.sol index fc6ae8d..7b148b0 100644 --- a/solidity/contracts/zeto_anon_enc.sol +++ b/solidity/contracts/zeto_anon_enc.sol @@ -19,6 +19,7 @@ import {IZetoEncrypted} from "./lib/interfaces/izeto_encrypted.sol"; import {Groth16Verifier_CheckHashesValue} from "./lib/verifier_check_hashes_value.sol"; import {Groth16Verifier_CheckInputsOutputsValue} from "./lib/verifier_check_inputs_outputs_value.sol"; import {Groth16Verifier_AnonEnc} from "./lib/verifier_anon_enc.sol"; +import {Groth16Verifier_AnonEncBatch} from "./lib/verifier_anon_enc_batch.sol"; import {ZetoFungibleWithdraw} from "./lib/zeto_fungible_withdraw.sol"; import {ZetoBase} from "./lib/zeto_base.sol"; import {ZetoFungible} from "./lib/zeto_fungible.sol"; @@ -36,18 +37,26 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/U /// - the sender possesses the private BabyJubjub key, whose public key is part of the pre-image of the input commitment hashes /// - the encrypted value in the input is derived from the receiver's UTXO value and encrypted with a shared secret using /// the ECDH protocol between the sender and receiver (this guarantees data availability for the receiver) -contract Zeto_AnonEnc is IZetoEncrypted, ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable { +contract Zeto_AnonEnc is + IZetoEncrypted, + ZetoBase, + ZetoFungibleWithdraw, + UUPSUpgradeable +{ Groth16Verifier_AnonEnc internal verifier; + Groth16Verifier_AnonEncBatch internal batchVerifier; function initialize( address initialOwner, Groth16Verifier_AnonEnc _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckInputsOutputsValue _withdrawVerifier + Groth16Verifier_CheckInputsOutputsValue _withdrawVerifier, + Groth16Verifier_AnonEncBatch _batchVerifier ) public initializer { __ZetoBase_init(initialOwner); __ZetoFungibleWithdraw_init(_depositVerifier, _withdrawVerifier); verifier = _verifier; + batchVerifier = _batchVerifier; } function _authorizeUpgrade(address) internal override onlyOwner {} @@ -142,7 +151,10 @@ contract Zeto_AnonEnc is IZetoEncrypted, ZetoBase, ZetoFungibleWithdraw, UUPSUpg processInputsAndOutputs(inputs, [output, 0]); } - function mint(uint256[] memory utxos, bytes calldata data) public onlyOwner { + function mint( + uint256[] memory utxos, + bytes calldata data + ) public onlyOwner { _mint(utxos, data); } } diff --git a/solidity/contracts/zeto_anon_enc_nullifier.sol b/solidity/contracts/zeto_anon_enc_nullifier.sol index d262f08..8c2ed9d 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier.sol @@ -19,6 +19,7 @@ import {IZetoEncrypted} from "./lib/interfaces/izeto_encrypted.sol"; import {Groth16Verifier_CheckHashesValue} from "./lib/verifier_check_hashes_value.sol"; import {Groth16Verifier_CheckNullifierValue} from "./lib/verifier_check_nullifier_value.sol"; import {Groth16Verifier_AnonEncNullifier} from "./lib/verifier_anon_enc_nullifier.sol"; +import {Groth16Verifier_AnonEncNullifierBatch} from "./lib/verifier_anon_enc_nullifier_batch.sol"; import {ZetoNullifier} from "./lib/zeto_nullifier.sol"; import {ZetoFungibleWithdrawWithNullifiers} from "./lib/zeto_fungible_withdraw_nullifier.sol"; import {Registry} from "./lib/registry.sol"; @@ -40,13 +41,15 @@ contract Zeto_AnonEncNullifier is ZetoFungibleWithdrawWithNullifiers, UUPSUpgradeable { - Groth16Verifier_AnonEncNullifier verifier; + Groth16Verifier_AnonEncNullifier internal verifier; + Groth16Verifier_AnonEncNullifierBatch internal batchVerifier; function initialize( address initialOwner, Groth16Verifier_AnonEncNullifier _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckNullifierValue _withdrawVerifier + Groth16Verifier_CheckNullifierValue _withdrawVerifier, + Groth16Verifier_AnonEncNullifierBatch _batchVerifier ) public initializer { __ZetoNullifier_init(initialOwner); __ZetoFungibleWithdrawWithNullifiers_init( @@ -54,6 +57,7 @@ contract Zeto_AnonEncNullifier is _withdrawVerifier ); verifier = _verifier; + batchVerifier = _batchVerifier; } function _authorizeUpgrade(address) internal override onlyOwner {} @@ -158,7 +162,10 @@ contract Zeto_AnonEncNullifier is processInputsAndOutputs(nullifiers, [output, 0]); } - function mint(uint256[] memory utxos, bytes calldata data) public onlyOwner { + function mint( + uint256[] memory utxos, + bytes calldata data + ) public onlyOwner { _mint(utxos, data); } } diff --git a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol index 05bdb0c..223ca29 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol @@ -19,6 +19,7 @@ import {IZetoEncrypted} from "./lib/interfaces/izeto_encrypted.sol"; import {Groth16Verifier_CheckHashesValue} from "./lib/verifier_check_hashes_value.sol"; import {Groth16Verifier_CheckNullifierValue} from "./lib/verifier_check_nullifier_value.sol"; import {Groth16Verifier_AnonEncNullifierKyc} from "./lib/verifier_anon_enc_nullifier_kyc.sol"; +import {Groth16Verifier_AnonEncNullifierKycBatch} from "./lib/verifier_anon_enc_nullifier_kyc_batch.sol"; import {ZetoNullifier} from "./lib/zeto_nullifier.sol"; import {ZetoFungibleWithdrawWithNullifiers} from "./lib/zeto_fungible_withdraw_nullifier.sol"; import {Registry} from "./lib/registry.sol"; @@ -41,13 +42,15 @@ contract Zeto_AnonEncNullifierKyc is Registry, UUPSUpgradeable { - Groth16Verifier_AnonEncNullifierKyc verifier; + Groth16Verifier_AnonEncNullifierKyc internal verifier; + Groth16Verifier_AnonEncNullifierKycBatch internal batchVerifier; function initialize( address initialOwner, Groth16Verifier_AnonEncNullifierKyc _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckNullifierValue _withdrawVerifier + Groth16Verifier_CheckNullifierValue _withdrawVerifier, + Groth16Verifier_AnonEncNullifierKycBatch _batchVerifier ) public initializer { __Registry_init(); __ZetoNullifier_init(initialOwner); @@ -56,6 +59,7 @@ contract Zeto_AnonEncNullifierKyc is _withdrawVerifier ); verifier = _verifier; + batchVerifier = _batchVerifier; } function _authorizeUpgrade(address) internal override onlyOwner {} @@ -169,7 +173,10 @@ contract Zeto_AnonEncNullifierKyc is processInputsAndOutputs(nullifiers, [output, 0]); } - function mint(uint256[] memory utxos, bytes calldata data) public onlyOwner { + function mint( + uint256[] memory utxos, + bytes calldata data + ) public onlyOwner { _mint(utxos, data); } } diff --git a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol index 991b9ab..4ea2d77 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol @@ -19,6 +19,7 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/U import {Groth16Verifier_CheckHashesValue} from "./lib/verifier_check_hashes_value.sol"; import {Groth16Verifier_CheckNullifierValue} from "./lib/verifier_check_nullifier_value.sol"; import {Groth16Verifier_AnonEncNullifierNonRepudiation} from "./lib/verifier_anon_enc_nullifier_non_repudiation.sol"; +import {Groth16Verifier_AnonEncNullifierNonRepudiationBatch} from "./lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol"; import {ZetoNullifier} from "./lib/zeto_nullifier.sol"; import {ZetoFungibleWithdrawWithNullifiers} from "./lib/zeto_fungible_withdraw_nullifier.sol"; import {Registry} from "./lib/registry.sol"; @@ -48,7 +49,8 @@ contract Zeto_AnonEncNullifierNonRepudiation is bytes data ); - Groth16Verifier_AnonEncNullifierNonRepudiation verifier; + Groth16Verifier_AnonEncNullifierNonRepudiation internal verifier; + Groth16Verifier_AnonEncNullifierNonRepudiationBatch internal batchVerifier; // the arbiter public key that must be used to // encrypt the secrets of every transaction uint256[2] private arbiter; @@ -57,7 +59,8 @@ contract Zeto_AnonEncNullifierNonRepudiation is address initialOwner, Groth16Verifier_AnonEncNullifierNonRepudiation _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckNullifierValue _withdrawVerifier + Groth16Verifier_CheckNullifierValue _withdrawVerifier, + Groth16Verifier_AnonEncNullifierNonRepudiationBatch _batchVerifier ) public initializer { __ZetoNullifier_init(initialOwner); __ZetoFungibleWithdrawWithNullifiers_init( @@ -65,6 +68,7 @@ contract Zeto_AnonEncNullifierNonRepudiation is _withdrawVerifier ); verifier = _verifier; + batchVerifier = _batchVerifier; } function _authorizeUpgrade(address) internal override onlyOwner {} @@ -206,7 +210,10 @@ contract Zeto_AnonEncNullifierNonRepudiation is processInputsAndOutputs(nullifiers, [output, 0]); } - function mint(uint256[] memory utxos, bytes calldata data) public onlyOwner { + function mint( + uint256[] memory utxos, + bytes calldata data + ) public onlyOwner { _mint(utxos, data); } } diff --git a/solidity/contracts/zeto_anon_nullifier.sol b/solidity/contracts/zeto_anon_nullifier.sol index 144a64f..a7875e8 100644 --- a/solidity/contracts/zeto_anon_nullifier.sol +++ b/solidity/contracts/zeto_anon_nullifier.sol @@ -19,6 +19,7 @@ import {IZeto} from "./lib/interfaces/izeto.sol"; import {Groth16Verifier_CheckHashesValue} from "./lib/verifier_check_hashes_value.sol"; import {Groth16Verifier_CheckNullifierValue} from "./lib/verifier_check_nullifier_value.sol"; import {Groth16Verifier_AnonNullifier} from "./lib/verifier_anon_nullifier.sol"; +import {Groth16Verifier_AnonNullifierBatch} from "./lib/verifier_anon_nullifier_batch.sol"; import {ZetoNullifier} from "./lib/zeto_nullifier.sol"; import {ZetoFungibleWithdrawWithNullifiers} from "./lib/zeto_fungible_withdraw_nullifier.sol"; import {Registry} from "./lib/registry.sol"; @@ -44,13 +45,15 @@ contract Zeto_AnonNullifier is ZetoFungibleWithdrawWithNullifiers, UUPSUpgradeable { - Groth16Verifier_AnonNullifier verifier; + Groth16Verifier_AnonNullifier internal verifier; + Groth16Verifier_AnonNullifierBatch internal batchVerifier; function initialize( address initialOwner, Groth16Verifier_AnonNullifier _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckNullifierValue _withdrawVerifier + Groth16Verifier_CheckNullifierValue _withdrawVerifier, + Groth16Verifier_AnonNullifierBatch _batchVerifier ) public initializer { __ZetoNullifier_init(initialOwner); __ZetoFungibleWithdrawWithNullifiers_init( @@ -58,6 +61,7 @@ contract Zeto_AnonNullifier is _withdrawVerifier ); verifier = _verifier; + batchVerifier = _batchVerifier; } function _authorizeUpgrade(address) internal override onlyOwner {} @@ -137,7 +141,10 @@ contract Zeto_AnonNullifier is processInputsAndOutputs(nullifiers, [output, 0]); } - function mint(uint256[] memory utxos, bytes calldata data) public onlyOwner { + function mint( + uint256[] memory utxos, + bytes calldata data + ) public onlyOwner { _mint(utxos, data); } } diff --git a/solidity/contracts/zeto_anon_nullifier_kyc.sol b/solidity/contracts/zeto_anon_nullifier_kyc.sol index 0d5469b..702e6b6 100644 --- a/solidity/contracts/zeto_anon_nullifier_kyc.sol +++ b/solidity/contracts/zeto_anon_nullifier_kyc.sol @@ -19,6 +19,7 @@ import {IZeto} from "./lib/interfaces/izeto.sol"; import {Groth16Verifier_CheckHashesValue} from "./lib/verifier_check_hashes_value.sol"; import {Groth16Verifier_CheckNullifierValue} from "./lib/verifier_check_nullifier_value.sol"; import {Groth16Verifier_AnonNullifierKyc} from "./lib/verifier_anon_nullifier_kyc.sol"; +import {Groth16Verifier_AnonNullifierKycBatch} from "./lib/verifier_anon_nullifier_kyc_batch.sol"; import {ZetoNullifier} from "./lib/zeto_nullifier.sol"; import {ZetoFungibleWithdrawWithNullifiers} from "./lib/zeto_fungible_withdraw_nullifier.sol"; import {Registry} from "./lib/registry.sol"; @@ -45,13 +46,15 @@ contract Zeto_AnonNullifierKyc is Registry, UUPSUpgradeable { - Groth16Verifier_AnonNullifierKyc verifier; + Groth16Verifier_AnonNullifierKyc internal verifier; + Groth16Verifier_AnonNullifierKycBatch internal batchVerifier; function initialize( address initialOwner, Groth16Verifier_AnonNullifierKyc _verifier, Groth16Verifier_CheckHashesValue _depositVerifier, - Groth16Verifier_CheckNullifierValue _withdrawVerifier + Groth16Verifier_CheckNullifierValue _withdrawVerifier, + Groth16Verifier_AnonNullifierKycBatch _batchVerifier ) public initializer { __Registry_init(); __ZetoNullifier_init(initialOwner); @@ -60,6 +63,7 @@ contract Zeto_AnonNullifierKyc is _withdrawVerifier ); verifier = _verifier; + batchVerifier = _batchVerifier; } function _authorizeUpgrade(address) internal override onlyOwner {} @@ -144,7 +148,10 @@ contract Zeto_AnonNullifierKyc is processInputsAndOutputs(nullifiers, [output, 0]); } - function mint(uint256[] memory utxos, bytes calldata data) public onlyOwner { + function mint( + uint256[] memory utxos, + bytes calldata data + ) public onlyOwner { _mint(utxos, data); } } diff --git a/zkp/circuits/anon.circom b/zkp/circuits/anon.circom index 31d8236..5cd2421 100644 --- a/zkp/circuits/anon.circom +++ b/zkp/circuits/anon.circom @@ -15,60 +15,6 @@ // limitations under the License. pragma circom 2.1.4; -include "./lib/check-positive.circom"; -include "./lib/check-hashes.circom"; -include "./lib/check-sum.circom"; -include "./node_modules/circomlib/circuits/babyjub.circom"; - -// This version of the circuit performs the following operations: -// - derive the sender's public key from the sender's private key -// - check the input and output commitments match the expected hashes -// - check the input and output values sum to the same amount -template Zeto(nInputs, nOutputs) { - signal input inputCommitments[nInputs]; - signal input inputValues[nInputs]; - signal input inputSalts[nInputs]; - signal input outputCommitments[nOutputs]; - signal input outputValues[nOutputs]; - signal input outputSalts[nOutputs]; - signal input outputOwnerPublicKeys[nOutputs][2]; - // must be properly hashed and trimmed to be compatible with the BabyJub curve. - // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 - signal input inputOwnerPrivateKey; - - // derive the sender's public key from the secret input - // for the sender's private key. This step demonstrates - // the sender really owns the private key for the input - // UTXOs - var inputOwnerPublicKey[2]; - component pub = BabyPbk(); - pub.in <== inputOwnerPrivateKey; - inputOwnerPublicKey[0] = pub.Ax; - inputOwnerPublicKey[1] = pub.Ay; - var inputOwnerPublicKeys[nInputs][2]; - for (var i = 0; i < nInputs; i++) { - inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; - inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; - } - - component checkPositives = CheckPositive(nOutputs); - checkPositives.outputValues <== outputValues; - - component checkInputHashes = CheckHashes(nInputs); - checkInputHashes.commitments <== inputCommitments; - checkInputHashes.values <== inputValues; - checkInputHashes.salts <== inputSalts; - checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; - - component checkOutputHashes = CheckHashes(nOutputs); - checkOutputHashes.commitments <== outputCommitments; - checkOutputHashes.values <== outputValues; - checkOutputHashes.salts <== outputSalts; - checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; - - component checkSum = CheckSum(nInputs, nOutputs); - checkSum.inputValues <== inputValues; - checkSum.outputValues <== outputValues; -} +include "./basetokens/anon_base.circom"; component main { public [ inputCommitments, outputCommitments ] } = Zeto(2, 2); \ No newline at end of file diff --git a/zkp/circuits/anon_batch.circom b/zkp/circuits/anon_batch.circom new file mode 100644 index 0000000..101ee83 --- /dev/null +++ b/zkp/circuits/anon_batch.circom @@ -0,0 +1,20 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "./basetokens/anon_base.circom"; + +component main { public [ inputCommitments, outputCommitments ] } = Zeto(10, 10); \ No newline at end of file diff --git a/zkp/circuits/anon_enc.circom b/zkp/circuits/anon_enc.circom index db9d8af..d2e6480 100644 --- a/zkp/circuits/anon_enc.circom +++ b/zkp/circuits/anon_enc.circom @@ -15,88 +15,6 @@ // limitations under the License. pragma circom 2.1.4; -include "./lib/check-positive.circom"; -include "./lib/check-hashes.circom"; -include "./lib/check-sum.circom"; -include "./lib/ecdh.circom"; -include "./lib/encrypt.circom"; -include "./node_modules/circomlib/circuits/babyjub.circom"; - -// This version of the circuit performs the following operations: -// - derive the sender's public key from the sender's private key -// - check the input and output commitments match the expected hashes -// - check the input and output values sum to the same amount -// - perform encryption of the receiver's output UTXO value and salt -template Zeto(nInputs, nOutputs) { - signal input inputCommitments[nInputs]; - signal input inputValues[nInputs]; - signal input inputSalts[nInputs]; - // must be properly hashed and trimmed to be compatible with the BabyJub curve. - // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 - signal input inputOwnerPrivateKey; - signal input outputCommitments[nOutputs]; - signal input outputValues[nOutputs]; - signal input outputSalts[nOutputs]; - signal input outputOwnerPublicKeys[nOutputs][2]; - signal input encryptionNonce; - - // the output for a 2-element input (value and salt) encryption is a 4-element array - signal output cipherText[4]; - - // derive the sender's public key from the secret input - // for the sender's private key. This step demonstrates - // the sender really owns the private key for the input - // UTXOs - var inputOwnerPublicKey[2]; - component pub = BabyPbk(); - pub.in <== inputOwnerPrivateKey; - inputOwnerPublicKey[0] = pub.Ax; - inputOwnerPublicKey[1] = pub.Ay; - var inputOwnerPublicKeys[nInputs][2]; - for (var i = 0; i < nInputs; i++) { - inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; - inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; - } - - component checkPositives = CheckPositive(nOutputs); - checkPositives.outputValues <== outputValues; - - component checkInputHashes = CheckHashes(nInputs); - checkInputHashes.commitments <== inputCommitments; - checkInputHashes.values <== inputValues; - checkInputHashes.salts <== inputSalts; - checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; - - component checkOutputHashes = CheckHashes(nOutputs); - checkOutputHashes.commitments <== outputCommitments; - checkOutputHashes.values <== outputValues; - checkOutputHashes.salts <== outputSalts; - checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; - - component checkSum = CheckSum(nInputs, nOutputs); - checkSum.inputValues <== inputValues; - checkSum.outputValues <== outputValues; - - // generate shared secret - var sharedSecret[2]; - component ecdh = Ecdh(); - ecdh.privKey <== inputOwnerPrivateKey; - ecdh.pubKey[0] <== outputOwnerPublicKeys[0][0]; - ecdh.pubKey[1] <== outputOwnerPublicKeys[0][1]; - sharedSecret[0] = ecdh.sharedKey[0]; - sharedSecret[1] = ecdh.sharedKey[1]; - - // encrypt the value for the receiver - component encrypt = SymmetricEncrypt(2); - // our circuit requires that the output UTXO for the receiver must be the first in the array - encrypt.plainText[0] <== outputValues[0]; - encrypt.plainText[1] <== outputSalts[0]; - encrypt.key <== sharedSecret; - encrypt.nonce <== encryptionNonce; - encrypt.cipherText[0] ==> cipherText[0]; - encrypt.cipherText[1] ==> cipherText[1]; - encrypt.cipherText[2] ==> cipherText[2]; - encrypt.cipherText[3] ==> cipherText[3]; -} +include "./basetokens/anon_enc_base.circom"; component main { public [ inputCommitments, outputCommitments, encryptionNonce ] } = Zeto(2, 2); \ No newline at end of file diff --git a/zkp/circuits/anon_enc_batch.circom b/zkp/circuits/anon_enc_batch.circom new file mode 100644 index 0000000..7d589d5 --- /dev/null +++ b/zkp/circuits/anon_enc_batch.circom @@ -0,0 +1,20 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "./basetokens/anon_enc_base.circom"; + +component main { public [ inputCommitments, outputCommitments, encryptionNonce ] } = Zeto(10, 10); \ No newline at end of file diff --git a/zkp/circuits/anon_enc_nullifier.circom b/zkp/circuits/anon_enc_nullifier.circom index 8360a3b..76e3e8a 100644 --- a/zkp/circuits/anon_enc_nullifier.circom +++ b/zkp/circuits/anon_enc_nullifier.circom @@ -15,113 +15,6 @@ // limitations under the License. pragma circom 2.1.4; -include "./lib/check-positive.circom"; -include "./lib/check-hashes.circom"; -include "./lib/check-sum.circom"; -include "./lib/check-nullifiers.circom"; -include "./lib/check-smt-proof.circom"; -include "./lib/ecdh.circom"; -include "./lib/encrypt.circom"; -include "./node_modules/circomlib/circuits/babyjub.circom"; - -// This version of the circuit performs the following operations: -// - derive the sender's public key from the sender's private key -// - check the input and output commitments match the expected hashes -// - check the input and output values sum to the same amount -// - perform encryption of the receiver's output UTXO value and salt -// - check the nullifiers are derived from the input commitments and the sender's private key -// - check the nullifiers are included in the Merkle tree -template Zeto(nInputs, nOutputs, nSMTLevels) { - signal input nullifiers[nInputs]; - signal input inputCommitments[nInputs]; - signal input inputValues[nInputs]; - signal input inputSalts[nInputs]; - // must be properly hashed and trimmed to be compatible with the BabyJub curve. - // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 - signal input inputOwnerPrivateKey; - signal input root; - signal input merkleProof[nInputs][nSMTLevels]; - signal input enabled[nInputs]; - signal input outputCommitments[nOutputs]; - signal input outputValues[nOutputs]; - signal input outputOwnerPublicKeys[nOutputs][2]; - signal input outputSalts[nOutputs]; - signal input encryptionNonce; - - // the output for a 2-element input (value and salt) encryption is a 4-element array - signal output cipherText[4]; - - // derive the sender's public key from the secret input - // for the sender's private key. This step demonstrates - // the sender really owns the private key for the input - // UTXOs - var inputOwnerPublicKey[2]; - component pub = BabyPbk(); - pub.in <== inputOwnerPrivateKey; - inputOwnerPublicKey[0] = pub.Ax; - inputOwnerPublicKey[1] = pub.Ay; - var inputOwnerPublicKeys[nInputs][2]; - for (var i = 0; i < nInputs; i++) { - inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; - inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; - } - - component checkPositives = CheckPositive(nOutputs); - checkPositives.outputValues <== outputValues; - - component checkInputHashes = CheckHashes(nInputs); - checkInputHashes.commitments <== inputCommitments; - checkInputHashes.values <== inputValues; - checkInputHashes.salts <== inputSalts; - checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; - - component checkOutputHashes = CheckHashes(nOutputs); - checkOutputHashes.commitments <== outputCommitments; - checkOutputHashes.values <== outputValues; - checkOutputHashes.salts <== outputSalts; - checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; - - component checkNullifiers = CheckNullifiers(nInputs); - checkNullifiers.nullifiers <== nullifiers; - checkNullifiers.values <== inputValues; - checkNullifiers.salts <== inputSalts; - checkNullifiers.ownerPrivateKey <== inputOwnerPrivateKey; - - component checkSum = CheckSum(nInputs, nOutputs); - checkSum.inputValues <== inputValues; - checkSum.outputValues <== outputValues; - - // With the above steps, we demonstrated that the nullifiers - // are securely bound to the input commitments. Now we need to - // demonstrate that the input commitments belong to the Sparse - // Merkle Tree with the root `root`. - component checkSMTProof = CheckSMTProof(nInputs, nSMTLevels); - checkSMTProof.root <== root; - checkSMTProof.merkleProof <== merkleProof; - checkSMTProof.enabled <== enabled; - checkSMTProof.leafNodeIndexes <== inputCommitments; - - // generate shared secret - var sharedSecret[2]; - component ecdh = Ecdh(); - ecdh.privKey <== inputOwnerPrivateKey; - // our circuit requires that the output UTXO for the receiver must be the first in the array - ecdh.pubKey[0] <== outputOwnerPublicKeys[0][0]; - ecdh.pubKey[1] <== outputOwnerPublicKeys[0][1]; - sharedSecret[0] = ecdh.sharedKey[0]; - sharedSecret[1] = ecdh.sharedKey[1]; - - // encrypt the value for the receiver - component encrypt = SymmetricEncrypt(2); - // our circuit requires that the output UTXO for the receiver must be the first in the array - encrypt.plainText[0] <== outputValues[0]; - encrypt.plainText[1] <== outputSalts[0]; - encrypt.key <== sharedSecret; - encrypt.nonce <== encryptionNonce; - encrypt.cipherText[0] ==> cipherText[0]; - encrypt.cipherText[1] ==> cipherText[1]; - encrypt.cipherText[2] ==> cipherText[2]; - encrypt.cipherText[3] ==> cipherText[3]; -} +include "./basetokens/anon_enc_nullifier_base.circom"; component main { public [ nullifiers, outputCommitments, encryptionNonce, root, enabled ] } = Zeto(2, 2, 64); \ No newline at end of file diff --git a/zkp/circuits/anon_enc_nullifier_batch.circom b/zkp/circuits/anon_enc_nullifier_batch.circom new file mode 100644 index 0000000..7844d29 --- /dev/null +++ b/zkp/circuits/anon_enc_nullifier_batch.circom @@ -0,0 +1,20 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "./basetokens/anon_enc_nullifier_base.circom"; + +component main { public [ nullifiers, outputCommitments, encryptionNonce, root, enabled ] } = Zeto(10, 10, 64); \ No newline at end of file diff --git a/zkp/circuits/anon_enc_nullifier_kyc.circom b/zkp/circuits/anon_enc_nullifier_kyc.circom index 8a93670..41f1c3b 100644 --- a/zkp/circuits/anon_enc_nullifier_kyc.circom +++ b/zkp/circuits/anon_enc_nullifier_kyc.circom @@ -15,142 +15,6 @@ // limitations under the License. pragma circom 2.1.4; -include "./lib/check-positive.circom"; -include "./lib/check-hashes.circom"; -include "./lib/check-sum.circom"; -include "./lib/check-nullifiers.circom"; -include "./lib/check-smt-proof.circom"; -include "./lib/ecdh.circom"; -include "./lib/encrypt.circom"; -include "./node_modules/circomlib/circuits/babyjub.circom"; - -// This version of the circuit performs the following operations: -// - derive the sender's public key from the sender's private key -// - check the input and output commitments match the expected hashes -// - check the input and output values sum to the same amount -// - perform encryption of the receiver's output UTXO value and salt -// - check the nullifiers are derived from the input commitments and the sender's private key -// - check the nullifiers are included in the Merkle tree -// - check the owner public keys for inputs and outputs are included in the identities merkle tree -template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) { - signal input nullifiers[nInputs]; - signal input inputCommitments[nInputs]; - signal input inputValues[nInputs]; - signal input inputSalts[nInputs]; - // must be properly hashed and trimmed to be compatible with the BabyJub curve. - // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 - signal input inputOwnerPrivateKey; - signal input utxosRoot; - signal input utxosMerkleProof[nInputs][nUTXOSMTLevels]; - signal input enabled[nInputs]; - signal input identitiesRoot; - signal input identitiesMerkleProof[nOutputs + 1][nIdentitiesSMTLevels]; - signal input outputCommitments[nOutputs]; - signal input outputValues[nOutputs]; - signal input outputOwnerPublicKeys[nOutputs][2]; - signal input outputSalts[nOutputs]; - signal input encryptionNonce; - - // the output for a 2-element input (value and salt) encryption is a 4-element array - signal output cipherText[4]; - - // derive the sender's public key from the secret input - // for the sender's private key. This step demonstrates - // the sender really owns the private key for the input - // UTXOs - var inputOwnerPublicKey[2]; - component pub = BabyPbk(); - pub.in <== inputOwnerPrivateKey; - inputOwnerPublicKey[0] = pub.Ax; - inputOwnerPublicKey[1] = pub.Ay; - var inputOwnerPublicKeys[nInputs][2]; - for (var i = 0; i < nInputs; i++) { - inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; - inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; - } - - component checkPositives = CheckPositive(nOutputs); - checkPositives.outputValues <== outputValues; - - component checkInputHashes = CheckHashes(nInputs); - checkInputHashes.commitments <== inputCommitments; - checkInputHashes.values <== inputValues; - checkInputHashes.salts <== inputSalts; - checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; - - component checkOutputHashes = CheckHashes(nOutputs); - checkOutputHashes.commitments <== outputCommitments; - checkOutputHashes.values <== outputValues; - checkOutputHashes.salts <== outputSalts; - checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; - - component checkNullifiers = CheckNullifiers(nInputs); - checkNullifiers.nullifiers <== nullifiers; - checkNullifiers.values <== inputValues; - checkNullifiers.salts <== inputSalts; - checkNullifiers.ownerPrivateKey <== inputOwnerPrivateKey; - - component checkSum = CheckSum(nInputs, nOutputs); - checkSum.inputValues <== inputValues; - checkSum.outputValues <== outputValues; - - // With the above steps, we demonstrated that the nullifiers - // are securely bound to the input commitments. Now we need to - // demonstrate that the input commitments belong to the Sparse - // Merkle Tree with the root `root`. - component checkUTXOSMTProof = CheckSMTProof(nInputs, nUTXOSMTLevels); - checkUTXOSMTProof.root <== utxosRoot; - checkUTXOSMTProof.merkleProof <== utxosMerkleProof; - checkUTXOSMTProof.enabled <== enabled; - checkUTXOSMTProof.leafNodeIndexes <== inputCommitments; - - // Then, we need to check that the owner public keys - // for the inputs and outputs are included in the identities - // Sparse Merkle Tree with the root `identitiesRoot`. - var ownerPublicKeyHashes[nOutputs + 1]; - component hash1 = Poseidon(2); - hash1.inputs[0] <== inputOwnerPublicKey[0]; - hash1.inputs[1] <== inputOwnerPublicKey[1]; - ownerPublicKeyHashes[0] = hash1.out; - - component hashes[nOutputs]; - var identitiesMTPCheckEnabled[nOutputs + 1]; - identitiesMTPCheckEnabled[0] = 1; - for (var i = 0; i < nOutputs; i++) { - hashes[i] = Poseidon(2); - hashes[i].inputs[0] <== outputOwnerPublicKeys[i][0]; - hashes[i].inputs[1] <== outputOwnerPublicKeys[i][1]; - ownerPublicKeyHashes[i+1] = hashes[i].out; - identitiesMTPCheckEnabled[i+1] = 1; - } - - component checkIdentitiesSMTProof = CheckSMTProof(nOutputs + 1, nIdentitiesSMTLevels); - checkIdentitiesSMTProof.root <== identitiesRoot; - checkIdentitiesSMTProof.merkleProof <== identitiesMerkleProof; - checkIdentitiesSMTProof.enabled <== identitiesMTPCheckEnabled; - checkIdentitiesSMTProof.leafNodeIndexes <== ownerPublicKeyHashes; - - // generate shared secret - var sharedSecret[2]; - component ecdh = Ecdh(); - ecdh.privKey <== inputOwnerPrivateKey; - // our circuit requires that the output UTXO for the receiver must be the first in the array - ecdh.pubKey[0] <== outputOwnerPublicKeys[0][0]; - ecdh.pubKey[1] <== outputOwnerPublicKeys[0][1]; - sharedSecret[0] = ecdh.sharedKey[0]; - sharedSecret[1] = ecdh.sharedKey[1]; - - // encrypt the value for the receiver - component encrypt = SymmetricEncrypt(2); - // our circuit requires that the output UTXO for the receiver must be the first in the array - encrypt.plainText[0] <== outputValues[0]; - encrypt.plainText[1] <== outputSalts[0]; - encrypt.key <== sharedSecret; - encrypt.nonce <== encryptionNonce; - encrypt.cipherText[0] ==> cipherText[0]; - encrypt.cipherText[1] ==> cipherText[1]; - encrypt.cipherText[2] ==> cipherText[2]; - encrypt.cipherText[3] ==> cipherText[3]; -} +include "./basetokens/anon_enc_nullifier_kyc_base.circom"; component main { public [ nullifiers, outputCommitments, encryptionNonce, utxosRoot, identitiesRoot, enabled ] } = Zeto(2, 2, 64, 10); \ No newline at end of file diff --git a/zkp/circuits/anon_enc_nullifier_kyc_batch.circom b/zkp/circuits/anon_enc_nullifier_kyc_batch.circom new file mode 100644 index 0000000..a6e4ab5 --- /dev/null +++ b/zkp/circuits/anon_enc_nullifier_kyc_batch.circom @@ -0,0 +1,20 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "./basetokens/anon_enc_nullifier_kyc_base.circom"; + +component main { public [ nullifiers, outputCommitments, encryptionNonce, utxosRoot, identitiesRoot, enabled ] } = Zeto(10, 10, 64, 10); \ No newline at end of file diff --git a/zkp/circuits/anon_enc_nullifier_non_repudiation.circom b/zkp/circuits/anon_enc_nullifier_non_repudiation.circom index 2775213..be0f2b6 100644 --- a/zkp/circuits/anon_enc_nullifier_non_repudiation.circom +++ b/zkp/circuits/anon_enc_nullifier_non_repudiation.circom @@ -15,166 +15,6 @@ // limitations under the License. pragma circom 2.1.4; -include "./lib/check-positive.circom"; -include "./lib/check-hashes.circom"; -include "./lib/check-sum.circom"; -include "./lib/check-nullifiers.circom"; -include "./lib/check-smt-proof.circom"; -include "./lib/ecdh.circom"; -include "./lib/encrypt.circom"; -include "./node_modules/circomlib/circuits/babyjub.circom"; - -// This version of the circuit performs the following operations: -// - derive the sender's public key from the sender's private key -// - check the input and output commitments match the expected hashes -// - check the input and output values sum to the same amount -// - perform encryption of the receiver's output UTXO value and salt -// - check the nullifiers are derived from the input commitments and the sender's private key -// - check the nullifiers are included in the Merkle tree -// - encrypt all secrets with an authority's public key (for non-repudiation purposes) -template Zeto(nInputs, nOutputs, nSMTLevels) { - signal input nullifiers[nInputs]; - signal input inputCommitments[nInputs]; - signal input inputValues[nInputs]; - signal input inputSalts[nInputs]; - // must be properly hashed and trimmed to be compatible with the BabyJub curve. - // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 - signal input inputOwnerPrivateKey; - signal input root; - signal input merkleProof[nInputs][nSMTLevels]; - signal input enabled[nInputs]; - signal input outputCommitments[nOutputs]; - signal input outputValues[nOutputs]; - signal input outputSalts[nOutputs]; - signal input outputOwnerPublicKeys[nOutputs][2]; - signal input encryptionNonce; - signal input authorityPublicKey[2]; - - // the output for a 2-element input (value and salt) encryption is a 4-element array - signal output cipherTextReceiver[4]; - // the number of cipher text messages returned by - // the encryption template will be 3n+1 - // input length: - // - input owner public key (x, y): 2 - // - secrets (value and salt) for each input UTXOs: 2 * nInputs - // - output owner public keys (x, y): 2 * nOutputs - // - secrets (value and salt) for each output UTXOs: 2 * nOutputs - var outputElementsLength = 2 + 2 * nInputs + 2 * nOutputs + 2 * nOutputs; - var l = outputElementsLength; - while (l % 3 != 0) { - l += 1; - } - signal output cipherTextAuthority[l+1]; - - // derive the sender's public key from the secret input - // for the sender's private key. This step demonstrates - // the sender really owns the private key for the input - // UTXOs - var inputOwnerPublicKey[2]; - component pub = BabyPbk(); - pub.in <== inputOwnerPrivateKey; - inputOwnerPublicKey[0] = pub.Ax; - inputOwnerPublicKey[1] = pub.Ay; - var inputOwnerPublicKeys[nInputs][2]; - for (var i = 0; i < nInputs; i++) { - inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; - inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; - } - - component checkPositives = CheckPositive(nOutputs); - checkPositives.outputValues <== outputValues; - - component checkInputHashes = CheckHashes(nInputs); - checkInputHashes.commitments <== inputCommitments; - checkInputHashes.values <== inputValues; - checkInputHashes.salts <== inputSalts; - checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; - - component checkOutputHashes = CheckHashes(nOutputs); - checkOutputHashes.commitments <== outputCommitments; - checkOutputHashes.values <== outputValues; - checkOutputHashes.salts <== outputSalts; - checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; - - component checkNullifiers = CheckNullifiers(nInputs); - checkNullifiers.nullifiers <== nullifiers; - checkNullifiers.values <== inputValues; - checkNullifiers.salts <== inputSalts; - checkNullifiers.ownerPrivateKey <== inputOwnerPrivateKey; - - component checkSum = CheckSum(nInputs, nOutputs); - checkSum.inputValues <== inputValues; - checkSum.outputValues <== outputValues; - - // With the above steps, we demonstrated that the nullifiers - // are securely bound to the input commitments. Now we need to - // demonstrate that the input commitments belong to the Sparse - // Merkle Tree with the root `root`. - component checkSMTProof = CheckSMTProof(nInputs, nSMTLevels); - checkSMTProof.root <== root; - checkSMTProof.merkleProof <== merkleProof; - checkSMTProof.enabled <== enabled; - checkSMTProof.leafNodeIndexes <== inputCommitments; - - // generate shared secret for the receiver - var sharedSecretReceiver[2]; - component ecdh1 = Ecdh(); - ecdh1.privKey <== inputOwnerPrivateKey; - // our circuit requires that the output UTXO for the receiver must be the first in the array - ecdh1.pubKey[0] <== outputOwnerPublicKeys[0][0]; - ecdh1.pubKey[1] <== outputOwnerPublicKeys[0][1]; - sharedSecretReceiver[0] = ecdh1.sharedKey[0]; - sharedSecretReceiver[1] = ecdh1.sharedKey[1]; - - // encrypt the value for the receiver - component encrypt1 = SymmetricEncrypt(2); - // our circuit requires that the output UTXO for the receiver must be the first in the array - encrypt1.plainText[0] <== outputValues[0]; - encrypt1.plainText[1] <== outputSalts[0]; - encrypt1.key <== sharedSecretReceiver; - encrypt1.nonce <== encryptionNonce; - // the output for a 2-element input encryption is a 4-element array - encrypt1.cipherText[0] ==> cipherTextReceiver[0]; - encrypt1.cipherText[1] ==> cipherTextReceiver[1]; - encrypt1.cipherText[2] ==> cipherTextReceiver[2]; - encrypt1.cipherText[3] ==> cipherTextReceiver[3]; - - // generate shared secret for the authority - var sharedSecretAuthority[2]; - component ecdh2 = Ecdh(); - ecdh2.privKey <== inputOwnerPrivateKey; - // our circuit requires that the output UTXO for the receiver must be the first in the array - ecdh2.pubKey[0] <== authorityPublicKey[0]; - ecdh2.pubKey[1] <== authorityPublicKey[1]; - sharedSecretAuthority[0] = ecdh2.sharedKey[0]; - sharedSecretAuthority[1] = ecdh2.sharedKey[1]; - - // encrypt the values for the authority - component encrypt2 = SymmetricEncrypt(2 + 2 * nInputs + 4 * nOutputs); - encrypt2.plainText[0] <== inputOwnerPublicKey[0]; - encrypt2.plainText[1] <== inputOwnerPublicKey[1]; - var idx1 = 2; - for (var i = 0; i < nInputs; i++) { - encrypt2.plainText[idx1] <== inputValues[i]; - idx1++; - encrypt2.plainText[idx1] <== inputSalts[i]; - idx1++; - } - for (var i = 0; i < nOutputs; i++) { - encrypt2.plainText[idx1] <== outputOwnerPublicKeys[i][0]; - idx1++; - encrypt2.plainText[idx1] <== outputOwnerPublicKeys[i][1]; - idx1++; - } - for (var i = 0; i < nOutputs; i++) { - encrypt2.plainText[idx1] <== outputValues[i]; - idx1++; - encrypt2.plainText[idx1] <== outputSalts[i]; - idx1++; - } - encrypt2.key <== sharedSecretAuthority; - encrypt2.nonce <== encryptionNonce; - encrypt2.cipherText ==> cipherTextAuthority; -} +include "./basetokens/anon_enc_nullifier_non_repudiation_base.circom"; component main { public [ nullifiers, outputCommitments, encryptionNonce, root, enabled, authorityPublicKey ] } = Zeto(2, 2, 64); \ No newline at end of file diff --git a/zkp/circuits/anon_enc_nullifier_non_repudiation_batch.circom b/zkp/circuits/anon_enc_nullifier_non_repudiation_batch.circom new file mode 100644 index 0000000..797e73a --- /dev/null +++ b/zkp/circuits/anon_enc_nullifier_non_repudiation_batch.circom @@ -0,0 +1,20 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "./basetokens/anon_enc_nullifier_non_repudiation_base.circom"; + +component main { public [ nullifiers, outputCommitments, encryptionNonce, root, enabled, authorityPublicKey ] } = Zeto(10, 10, 64); \ No newline at end of file diff --git a/zkp/circuits/anon_nullifier.circom b/zkp/circuits/anon_nullifier.circom index e0f356f..283a31f 100644 --- a/zkp/circuits/anon_nullifier.circom +++ b/zkp/circuits/anon_nullifier.circom @@ -15,85 +15,6 @@ // limitations under the License. pragma circom 2.1.4; -include "./lib/check-positive.circom"; -include "./lib/check-hashes.circom"; -include "./lib/check-sum.circom"; -include "./lib/check-nullifiers.circom"; -include "./lib/check-smt-proof.circom"; -include "./node_modules/circomlib/circuits/babyjub.circom"; - -// This version of the circuit performs the following operations: -// - derive the sender's public key from the sender's private key -// - check the input and output commitments match the expected hashes -// - check the input and output values sum to the same amount -// - check the nullifiers are derived from the input commitments and the sender's private key -// - check the nullifiers are included in the Merkle tree -template Zeto(nInputs, nOutputs, nSMTLevels) { - signal input nullifiers[nInputs]; - signal input inputCommitments[nInputs]; - signal input inputValues[nInputs]; - signal input inputSalts[nInputs]; - // must be properly hashed and trimmed to be compatible with the BabyJub curve. - // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 - signal input inputOwnerPrivateKey; - signal input root; - signal input merkleProof[nInputs][nSMTLevels]; - // allows merkle proof verifications for empty input elements to be skipped - signal input enabled[nInputs]; - signal input outputCommitments[nOutputs]; - signal input outputValues[nOutputs]; - signal input outputOwnerPublicKeys[nOutputs][2]; - signal input outputSalts[nOutputs]; - - // derive the sender's public key from the secret input - // for the sender's private key. This step demonstrates - // the sender really owns the private key for the input - // UTXOs - var inputOwnerPublicKey[2]; - component pub = BabyPbk(); - pub.in <== inputOwnerPrivateKey; - inputOwnerPublicKey[0] = pub.Ax; - inputOwnerPublicKey[1] = pub.Ay; - var inputOwnerPublicKeys[nInputs][2]; - for (var i = 0; i < nInputs; i++) { - inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; - inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; - } - - component checkPositives = CheckPositive(nOutputs); - checkPositives.outputValues <== outputValues; - - component checkInputHashes = CheckHashes(nInputs); - checkInputHashes.commitments <== inputCommitments; - checkInputHashes.values <== inputValues; - checkInputHashes.salts <== inputSalts; - checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; - - component checkOutputHashes = CheckHashes(nOutputs); - checkOutputHashes.commitments <== outputCommitments; - checkOutputHashes.values <== outputValues; - checkOutputHashes.salts <== outputSalts; - checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; - - component checkNullifiers = CheckNullifiers(nInputs); - checkNullifiers.nullifiers <== nullifiers; - checkNullifiers.values <== inputValues; - checkNullifiers.salts <== inputSalts; - checkNullifiers.ownerPrivateKey <== inputOwnerPrivateKey; - - component checkSum = CheckSum(nInputs, nOutputs); - checkSum.inputValues <== inputValues; - checkSum.outputValues <== outputValues; - - // With the above steps, we demonstrated that the nullifiers - // are securely bound to the input commitments. Now we need to - // demonstrate that the input commitments belong to the Sparse - // Merkle Tree with the root `root`. - component checkSMTProof = CheckSMTProof(nInputs, nSMTLevels); - checkSMTProof.root <== root; - checkSMTProof.merkleProof <== merkleProof; - checkSMTProof.enabled <== enabled; - checkSMTProof.leafNodeIndexes <== inputCommitments; -} +include "./basetokens/anon_nullifier_base.circom"; component main { public [ nullifiers, outputCommitments, root, enabled ] } = Zeto(2, 2, 64); \ No newline at end of file diff --git a/zkp/circuits/anon_nullifier_batch.circom b/zkp/circuits/anon_nullifier_batch.circom new file mode 100644 index 0000000..930a233 --- /dev/null +++ b/zkp/circuits/anon_nullifier_batch.circom @@ -0,0 +1,20 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "./basetokens/anon_nullifier_base.circom"; + +component main { public [ nullifiers, outputCommitments, root, enabled ] } = Zeto(10, 10, 64); \ No newline at end of file diff --git a/zkp/circuits/anon_nullifier_kyc.circom b/zkp/circuits/anon_nullifier_kyc.circom index b52d27c..a29fc8e 100644 --- a/zkp/circuits/anon_nullifier_kyc.circom +++ b/zkp/circuits/anon_nullifier_kyc.circom @@ -15,115 +15,6 @@ // limitations under the License. pragma circom 2.1.4; -include "./lib/check-positive.circom"; -include "./lib/check-hashes.circom"; -include "./lib/check-sum.circom"; -include "./lib/check-nullifiers.circom"; -include "./lib/check-smt-proof.circom"; -include "./node_modules/circomlib/circuits/babyjub.circom"; -include "./node_modules/circomlib/circuits/poseidon.circom"; - -// This version of the circuit performs the following operations: -// - derive the sender's public key from the sender's private key -// - check the input and output commitments match the expected hashes -// - check the input and output values sum to the same amount -// - check the nullifiers are derived from the input commitments and the sender's private key -// - check the nullifiers are included in the Merkle tree -// - check the owner public keys for inputs and outputs are included in the identities merkle tree -template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) { - signal input nullifiers[nInputs]; - signal input inputCommitments[nInputs]; - signal input inputValues[nInputs]; - signal input inputSalts[nInputs]; - // must be properly hashed and trimmed to be compatible with the BabyJub curve. - // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 - signal input inputOwnerPrivateKey; - signal input utxosRoot; - signal input utxosMerkleProof[nInputs][nUTXOSMTLevels]; - // allows merkle proof verifications for empty input elements to be skipped - signal input enabled[nInputs]; - signal input identitiesRoot; - signal input identitiesMerkleProof[nOutputs + 1][nIdentitiesSMTLevels]; - signal input outputCommitments[nOutputs]; - signal input outputValues[nOutputs]; - signal input outputOwnerPublicKeys[nOutputs][2]; - signal input outputSalts[nOutputs]; - - // derive the sender's public key from the secret input - // for the sender's private key. This step demonstrates - // the sender really owns the private key for the input - // UTXOs - var inputOwnerPublicKey[2]; - component pub = BabyPbk(); - pub.in <== inputOwnerPrivateKey; - inputOwnerPublicKey[0] = pub.Ax; - inputOwnerPublicKey[1] = pub.Ay; - var inputOwnerPublicKeys[nInputs][2]; - for (var i = 0; i < nInputs; i++) { - inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; - inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; - } - - component checkPositives = CheckPositive(nOutputs); - checkPositives.outputValues <== outputValues; - - component checkInputHashes = CheckHashes(nInputs); - checkInputHashes.commitments <== inputCommitments; - checkInputHashes.values <== inputValues; - checkInputHashes.salts <== inputSalts; - checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; - - component checkOutputHashes = CheckHashes(nOutputs); - checkOutputHashes.commitments <== outputCommitments; - checkOutputHashes.values <== outputValues; - checkOutputHashes.salts <== outputSalts; - checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; - - component checkNullifiers = CheckNullifiers(nInputs); - checkNullifiers.nullifiers <== nullifiers; - checkNullifiers.values <== inputValues; - checkNullifiers.salts <== inputSalts; - checkNullifiers.ownerPrivateKey <== inputOwnerPrivateKey; - - component checkSum = CheckSum(nInputs, nOutputs); - checkSum.inputValues <== inputValues; - checkSum.outputValues <== outputValues; - - // With the above steps, we demonstrated that the nullifiers - // are securely bound to the input commitments. Now we need to - // demonstrate that the input commitments belong to the Sparse - // Merkle Tree with the root `root`. - component checkUTXOSMTProof = CheckSMTProof(nInputs, nUTXOSMTLevels); - checkUTXOSMTProof.root <== utxosRoot; - checkUTXOSMTProof.merkleProof <== utxosMerkleProof; - checkUTXOSMTProof.enabled <== enabled; - checkUTXOSMTProof.leafNodeIndexes <== inputCommitments; - - // Finally, we need to demonstrate that the owner public keys - // for the inputs and outputs are included in the identities - // Sparse Merkle Tree with the root `identitiesRoot`. - var ownerPublicKeyHashes[nOutputs + 1]; - component hash1 = Poseidon(2); - hash1.inputs[0] <== inputOwnerPublicKey[0]; - hash1.inputs[1] <== inputOwnerPublicKey[1]; - ownerPublicKeyHashes[0] = hash1.out; - - component hashes[nOutputs]; - var identitiesMTPCheckEnabled[nOutputs + 1]; - identitiesMTPCheckEnabled[0] = 1; - for (var i = 0; i < nOutputs; i++) { - hashes[i] = Poseidon(2); - hashes[i].inputs[0] <== outputOwnerPublicKeys[i][0]; - hashes[i].inputs[1] <== outputOwnerPublicKeys[i][1]; - ownerPublicKeyHashes[i+1] = hashes[i].out; - identitiesMTPCheckEnabled[i+1] = 1; - } - - component checkIdentitiesSMTProof = CheckSMTProof(nOutputs + 1, nIdentitiesSMTLevels); - checkIdentitiesSMTProof.root <== identitiesRoot; - checkIdentitiesSMTProof.merkleProof <== identitiesMerkleProof; - checkIdentitiesSMTProof.enabled <== identitiesMTPCheckEnabled; - checkIdentitiesSMTProof.leafNodeIndexes <== ownerPublicKeyHashes; -} +include "./basetokens/anon_nullifier_kyc_base.circom"; component main { public [ nullifiers, outputCommitments, utxosRoot, identitiesRoot, enabled ] } = Zeto(2, 2, 64, 10); \ No newline at end of file diff --git a/zkp/circuits/anon_nullifier_kyc_batch.circom b/zkp/circuits/anon_nullifier_kyc_batch.circom new file mode 100644 index 0000000..55ac0f6 --- /dev/null +++ b/zkp/circuits/anon_nullifier_kyc_batch.circom @@ -0,0 +1,20 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "./basetokens/anon_nullifier_kyc_base.circom"; + +component main { public [ nullifiers, outputCommitments, utxosRoot, identitiesRoot, enabled ] } = Zeto(10, 10, 64, 10); \ No newline at end of file diff --git a/zkp/circuits/basetokens/anon_base.circom b/zkp/circuits/basetokens/anon_base.circom new file mode 100644 index 0000000..04f46d2 --- /dev/null +++ b/zkp/circuits/basetokens/anon_base.circom @@ -0,0 +1,72 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "../lib/check-positive.circom"; +include "../lib/check-hashes.circom"; +include "../lib/check-sum.circom"; +include "../node_modules/circomlib/circuits/babyjub.circom"; + +// This version of the circuit performs the following operations: +// - derive the sender's public key from the sender's private key +// - check the input and output commitments match the expected hashes +// - check the input and output values sum to the same amount +template Zeto(nInputs, nOutputs) { + signal input inputCommitments[nInputs]; + signal input inputValues[nInputs]; + signal input inputSalts[nInputs]; + signal input outputCommitments[nOutputs]; + signal input outputValues[nOutputs]; + signal input outputSalts[nOutputs]; + signal input outputOwnerPublicKeys[nOutputs][2]; + // must be properly hashed and trimmed to be compatible with the BabyJub curve. + // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 + signal input inputOwnerPrivateKey; + + // derive the sender's public key from the secret input + // for the sender's private key. This step demonstrates + // the sender really owns the private key for the input + // UTXOs + var inputOwnerPublicKey[2]; + component pub = BabyPbk(); + pub.in <== inputOwnerPrivateKey; + inputOwnerPublicKey[0] = pub.Ax; + inputOwnerPublicKey[1] = pub.Ay; + var inputOwnerPublicKeys[nInputs][2]; + for (var i = 0; i < nInputs; i++) { + inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; + inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; + } + + component checkPositives = CheckPositive(nOutputs); + checkPositives.outputValues <== outputValues; + + component checkInputHashes = CheckHashes(nInputs); + checkInputHashes.commitments <== inputCommitments; + checkInputHashes.values <== inputValues; + checkInputHashes.salts <== inputSalts; + checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; + + component checkOutputHashes = CheckHashes(nOutputs); + checkOutputHashes.commitments <== outputCommitments; + checkOutputHashes.values <== outputValues; + checkOutputHashes.salts <== outputSalts; + checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; + + component checkSum = CheckSum(nInputs, nOutputs); + checkSum.inputValues <== inputValues; + checkSum.outputValues <== outputValues; +} diff --git a/zkp/circuits/basetokens/anon_enc_base.circom b/zkp/circuits/basetokens/anon_enc_base.circom new file mode 100644 index 0000000..86af9be --- /dev/null +++ b/zkp/circuits/basetokens/anon_enc_base.circom @@ -0,0 +1,100 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "../lib/check-positive.circom"; +include "../lib/check-hashes.circom"; +include "../lib/check-sum.circom"; +include "../lib/ecdh.circom"; +include "../lib/encrypt.circom"; +include "../node_modules/circomlib/circuits/babyjub.circom"; + +// This version of the circuit performs the following operations: +// - derive the sender's public key from the sender's private key +// - check the input and output commitments match the expected hashes +// - check the input and output values sum to the same amount +// - perform encryption of the receiver's output UTXO value and salt +template Zeto(nInputs, nOutputs) { + signal input inputCommitments[nInputs]; + signal input inputValues[nInputs]; + signal input inputSalts[nInputs]; + // must be properly hashed and trimmed to be compatible with the BabyJub curve. + // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 + signal input inputOwnerPrivateKey; + signal input outputCommitments[nOutputs]; + signal input outputValues[nOutputs]; + signal input outputSalts[nOutputs]; + signal input outputOwnerPublicKeys[nOutputs][2]; + signal input encryptionNonce; + + // the output for a 2-element input (value and salt) encryption is a 4-element array + signal output cipherText[4]; + + // derive the sender's public key from the secret input + // for the sender's private key. This step demonstrates + // the sender really owns the private key for the input + // UTXOs + var inputOwnerPublicKey[2]; + component pub = BabyPbk(); + pub.in <== inputOwnerPrivateKey; + inputOwnerPublicKey[0] = pub.Ax; + inputOwnerPublicKey[1] = pub.Ay; + var inputOwnerPublicKeys[nInputs][2]; + for (var i = 0; i < nInputs; i++) { + inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; + inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; + } + + component checkPositives = CheckPositive(nOutputs); + checkPositives.outputValues <== outputValues; + + component checkInputHashes = CheckHashes(nInputs); + checkInputHashes.commitments <== inputCommitments; + checkInputHashes.values <== inputValues; + checkInputHashes.salts <== inputSalts; + checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; + + component checkOutputHashes = CheckHashes(nOutputs); + checkOutputHashes.commitments <== outputCommitments; + checkOutputHashes.values <== outputValues; + checkOutputHashes.salts <== outputSalts; + checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; + + component checkSum = CheckSum(nInputs, nOutputs); + checkSum.inputValues <== inputValues; + checkSum.outputValues <== outputValues; + + // generate shared secret + var sharedSecret[2]; + component ecdh = Ecdh(); + ecdh.privKey <== inputOwnerPrivateKey; + ecdh.pubKey[0] <== outputOwnerPublicKeys[0][0]; + ecdh.pubKey[1] <== outputOwnerPublicKeys[0][1]; + sharedSecret[0] = ecdh.sharedKey[0]; + sharedSecret[1] = ecdh.sharedKey[1]; + + // encrypt the value for the receiver + component encrypt = SymmetricEncrypt(2); + // our circuit requires that the output UTXO for the receiver must be the first in the array + encrypt.plainText[0] <== outputValues[0]; + encrypt.plainText[1] <== outputSalts[0]; + encrypt.key <== sharedSecret; + encrypt.nonce <== encryptionNonce; + encrypt.cipherText[0] ==> cipherText[0]; + encrypt.cipherText[1] ==> cipherText[1]; + encrypt.cipherText[2] ==> cipherText[2]; + encrypt.cipherText[3] ==> cipherText[3]; +} diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_base.circom new file mode 100644 index 0000000..fba891e --- /dev/null +++ b/zkp/circuits/basetokens/anon_enc_nullifier_base.circom @@ -0,0 +1,125 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "../lib/check-positive.circom"; +include "../lib/check-hashes.circom"; +include "../lib/check-sum.circom"; +include "../lib/check-nullifiers.circom"; +include "../lib/check-smt-proof.circom"; +include "../lib/ecdh.circom"; +include "../lib/encrypt.circom"; +include "../node_modules/circomlib/circuits/babyjub.circom"; + +// This version of the circuit performs the following operations: +// - derive the sender's public key from the sender's private key +// - check the input and output commitments match the expected hashes +// - check the input and output values sum to the same amount +// - perform encryption of the receiver's output UTXO value and salt +// - check the nullifiers are derived from the input commitments and the sender's private key +// - check the nullifiers are included in the Merkle tree +template Zeto(nInputs, nOutputs, nSMTLevels) { + signal input nullifiers[nInputs]; + signal input inputCommitments[nInputs]; + signal input inputValues[nInputs]; + signal input inputSalts[nInputs]; + // must be properly hashed and trimmed to be compatible with the BabyJub curve. + // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 + signal input inputOwnerPrivateKey; + signal input root; + signal input merkleProof[nInputs][nSMTLevels]; + signal input enabled[nInputs]; + signal input outputCommitments[nOutputs]; + signal input outputValues[nOutputs]; + signal input outputOwnerPublicKeys[nOutputs][2]; + signal input outputSalts[nOutputs]; + signal input encryptionNonce; + + // the output for a 2-element input (value and salt) encryption is a 4-element array + signal output cipherText[4]; + + // derive the sender's public key from the secret input + // for the sender's private key. This step demonstrates + // the sender really owns the private key for the input + // UTXOs + var inputOwnerPublicKey[2]; + component pub = BabyPbk(); + pub.in <== inputOwnerPrivateKey; + inputOwnerPublicKey[0] = pub.Ax; + inputOwnerPublicKey[1] = pub.Ay; + var inputOwnerPublicKeys[nInputs][2]; + for (var i = 0; i < nInputs; i++) { + inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; + inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; + } + + component checkPositives = CheckPositive(nOutputs); + checkPositives.outputValues <== outputValues; + + component checkInputHashes = CheckHashes(nInputs); + checkInputHashes.commitments <== inputCommitments; + checkInputHashes.values <== inputValues; + checkInputHashes.salts <== inputSalts; + checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; + + component checkOutputHashes = CheckHashes(nOutputs); + checkOutputHashes.commitments <== outputCommitments; + checkOutputHashes.values <== outputValues; + checkOutputHashes.salts <== outputSalts; + checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; + + component checkNullifiers = CheckNullifiers(nInputs); + checkNullifiers.nullifiers <== nullifiers; + checkNullifiers.values <== inputValues; + checkNullifiers.salts <== inputSalts; + checkNullifiers.ownerPrivateKey <== inputOwnerPrivateKey; + + component checkSum = CheckSum(nInputs, nOutputs); + checkSum.inputValues <== inputValues; + checkSum.outputValues <== outputValues; + + // With the above steps, we demonstrated that the nullifiers + // are securely bound to the input commitments. Now we need to + // demonstrate that the input commitments belong to the Sparse + // Merkle Tree with the root `root`. + component checkSMTProof = CheckSMTProof(nInputs, nSMTLevels); + checkSMTProof.root <== root; + checkSMTProof.merkleProof <== merkleProof; + checkSMTProof.enabled <== enabled; + checkSMTProof.leafNodeIndexes <== inputCommitments; + + // generate shared secret + var sharedSecret[2]; + component ecdh = Ecdh(); + ecdh.privKey <== inputOwnerPrivateKey; + // our circuit requires that the output UTXO for the receiver must be the first in the array + ecdh.pubKey[0] <== outputOwnerPublicKeys[0][0]; + ecdh.pubKey[1] <== outputOwnerPublicKeys[0][1]; + sharedSecret[0] = ecdh.sharedKey[0]; + sharedSecret[1] = ecdh.sharedKey[1]; + + // encrypt the value for the receiver + component encrypt = SymmetricEncrypt(2); + // our circuit requires that the output UTXO for the receiver must be the first in the array + encrypt.plainText[0] <== outputValues[0]; + encrypt.plainText[1] <== outputSalts[0]; + encrypt.key <== sharedSecret; + encrypt.nonce <== encryptionNonce; + encrypt.cipherText[0] ==> cipherText[0]; + encrypt.cipherText[1] ==> cipherText[1]; + encrypt.cipherText[2] ==> cipherText[2]; + encrypt.cipherText[3] ==> cipherText[3]; +} diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom new file mode 100644 index 0000000..4f6ba7f --- /dev/null +++ b/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom @@ -0,0 +1,154 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "../lib/check-positive.circom"; +include "../lib/check-hashes.circom"; +include "../lib/check-sum.circom"; +include "../lib/check-nullifiers.circom"; +include "../lib/check-smt-proof.circom"; +include "../lib/ecdh.circom"; +include "../lib/encrypt.circom"; +include "../node_modules/circomlib/circuits/babyjub.circom"; + +// This version of the circuit performs the following operations: +// - derive the sender's public key from the sender's private key +// - check the input and output commitments match the expected hashes +// - check the input and output values sum to the same amount +// - perform encryption of the receiver's output UTXO value and salt +// - check the nullifiers are derived from the input commitments and the sender's private key +// - check the nullifiers are included in the Merkle tree +// - check the owner public keys for inputs and outputs are included in the identities merkle tree +template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) { + signal input nullifiers[nInputs]; + signal input inputCommitments[nInputs]; + signal input inputValues[nInputs]; + signal input inputSalts[nInputs]; + // must be properly hashed and trimmed to be compatible with the BabyJub curve. + // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 + signal input inputOwnerPrivateKey; + signal input utxosRoot; + signal input utxosMerkleProof[nInputs][nUTXOSMTLevels]; + signal input enabled[nInputs]; + signal input identitiesRoot; + signal input identitiesMerkleProof[nOutputs + 1][nIdentitiesSMTLevels]; + signal input outputCommitments[nOutputs]; + signal input outputValues[nOutputs]; + signal input outputOwnerPublicKeys[nOutputs][2]; + signal input outputSalts[nOutputs]; + signal input encryptionNonce; + + // the output for a 2-element input (value and salt) encryption is a 4-element array + signal output cipherText[4]; + + // derive the sender's public key from the secret input + // for the sender's private key. This step demonstrates + // the sender really owns the private key for the input + // UTXOs + var inputOwnerPublicKey[2]; + component pub = BabyPbk(); + pub.in <== inputOwnerPrivateKey; + inputOwnerPublicKey[0] = pub.Ax; + inputOwnerPublicKey[1] = pub.Ay; + var inputOwnerPublicKeys[nInputs][2]; + for (var i = 0; i < nInputs; i++) { + inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; + inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; + } + + component checkPositives = CheckPositive(nOutputs); + checkPositives.outputValues <== outputValues; + + component checkInputHashes = CheckHashes(nInputs); + checkInputHashes.commitments <== inputCommitments; + checkInputHashes.values <== inputValues; + checkInputHashes.salts <== inputSalts; + checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; + + component checkOutputHashes = CheckHashes(nOutputs); + checkOutputHashes.commitments <== outputCommitments; + checkOutputHashes.values <== outputValues; + checkOutputHashes.salts <== outputSalts; + checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; + + component checkNullifiers = CheckNullifiers(nInputs); + checkNullifiers.nullifiers <== nullifiers; + checkNullifiers.values <== inputValues; + checkNullifiers.salts <== inputSalts; + checkNullifiers.ownerPrivateKey <== inputOwnerPrivateKey; + + component checkSum = CheckSum(nInputs, nOutputs); + checkSum.inputValues <== inputValues; + checkSum.outputValues <== outputValues; + + // With the above steps, we demonstrated that the nullifiers + // are securely bound to the input commitments. Now we need to + // demonstrate that the input commitments belong to the Sparse + // Merkle Tree with the root `root`. + component checkUTXOSMTProof = CheckSMTProof(nInputs, nUTXOSMTLevels); + checkUTXOSMTProof.root <== utxosRoot; + checkUTXOSMTProof.merkleProof <== utxosMerkleProof; + checkUTXOSMTProof.enabled <== enabled; + checkUTXOSMTProof.leafNodeIndexes <== inputCommitments; + + // Then, we need to check that the owner public keys + // for the inputs and outputs are included in the identities + // Sparse Merkle Tree with the root `identitiesRoot`. + var ownerPublicKeyHashes[nOutputs + 1]; + component hash1 = Poseidon(2); + hash1.inputs[0] <== inputOwnerPublicKey[0]; + hash1.inputs[1] <== inputOwnerPublicKey[1]; + ownerPublicKeyHashes[0] = hash1.out; + + component hashes[nOutputs]; + var identitiesMTPCheckEnabled[nOutputs + 1]; + identitiesMTPCheckEnabled[0] = 1; + for (var i = 0; i < nOutputs; i++) { + hashes[i] = Poseidon(2); + hashes[i].inputs[0] <== outputOwnerPublicKeys[i][0]; + hashes[i].inputs[1] <== outputOwnerPublicKeys[i][1]; + ownerPublicKeyHashes[i+1] = hashes[i].out; + identitiesMTPCheckEnabled[i+1] = 1; + } + + component checkIdentitiesSMTProof = CheckSMTProof(nOutputs + 1, nIdentitiesSMTLevels); + checkIdentitiesSMTProof.root <== identitiesRoot; + checkIdentitiesSMTProof.merkleProof <== identitiesMerkleProof; + checkIdentitiesSMTProof.enabled <== identitiesMTPCheckEnabled; + checkIdentitiesSMTProof.leafNodeIndexes <== ownerPublicKeyHashes; + + // generate shared secret + var sharedSecret[2]; + component ecdh = Ecdh(); + ecdh.privKey <== inputOwnerPrivateKey; + // our circuit requires that the output UTXO for the receiver must be the first in the array + ecdh.pubKey[0] <== outputOwnerPublicKeys[0][0]; + ecdh.pubKey[1] <== outputOwnerPublicKeys[0][1]; + sharedSecret[0] = ecdh.sharedKey[0]; + sharedSecret[1] = ecdh.sharedKey[1]; + + // encrypt the value for the receiver + component encrypt = SymmetricEncrypt(2); + // our circuit requires that the output UTXO for the receiver must be the first in the array + encrypt.plainText[0] <== outputValues[0]; + encrypt.plainText[1] <== outputSalts[0]; + encrypt.key <== sharedSecret; + encrypt.nonce <== encryptionNonce; + encrypt.cipherText[0] ==> cipherText[0]; + encrypt.cipherText[1] ==> cipherText[1]; + encrypt.cipherText[2] ==> cipherText[2]; + encrypt.cipherText[3] ==> cipherText[3]; +} \ No newline at end of file diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom new file mode 100644 index 0000000..f610248 --- /dev/null +++ b/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom @@ -0,0 +1,178 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "../lib/check-positive.circom"; +include "../lib/check-hashes.circom"; +include "../lib/check-sum.circom"; +include "../lib/check-nullifiers.circom"; +include "../lib/check-smt-proof.circom"; +include "../lib/ecdh.circom"; +include "../lib/encrypt.circom"; +include "../node_modules/circomlib/circuits/babyjub.circom"; + +// This version of the circuit performs the following operations: +// - derive the sender's public key from the sender's private key +// - check the input and output commitments match the expected hashes +// - check the input and output values sum to the same amount +// - perform encryption of the receiver's output UTXO value and salt +// - check the nullifiers are derived from the input commitments and the sender's private key +// - check the nullifiers are included in the Merkle tree +// - encrypt all secrets with an authority's public key (for non-repudiation purposes) +template Zeto(nInputs, nOutputs, nSMTLevels) { + signal input nullifiers[nInputs]; + signal input inputCommitments[nInputs]; + signal input inputValues[nInputs]; + signal input inputSalts[nInputs]; + // must be properly hashed and trimmed to be compatible with the BabyJub curve. + // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 + signal input inputOwnerPrivateKey; + signal input root; + signal input merkleProof[nInputs][nSMTLevels]; + signal input enabled[nInputs]; + signal input outputCommitments[nOutputs]; + signal input outputValues[nOutputs]; + signal input outputSalts[nOutputs]; + signal input outputOwnerPublicKeys[nOutputs][2]; + signal input encryptionNonce; + signal input authorityPublicKey[2]; + + // the output for a 2-element input (value and salt) encryption is a 4-element array + signal output cipherTextReceiver[4]; + // the number of cipher text messages returned by + // the encryption template will be 3n+1 + // input length: + // - input owner public key (x, y): 2 + // - secrets (value and salt) for each input UTXOs: 2 * nInputs + // - output owner public keys (x, y): 2 * nOutputs + // - secrets (value and salt) for each output UTXOs: 2 * nOutputs + var outputElementsLength = 2 + 2 * nInputs + 2 * nOutputs + 2 * nOutputs; + var l = outputElementsLength; + while (l % 3 != 0) { + l += 1; + } + signal output cipherTextAuthority[l+1]; + + // derive the sender's public key from the secret input + // for the sender's private key. This step demonstrates + // the sender really owns the private key for the input + // UTXOs + var inputOwnerPublicKey[2]; + component pub = BabyPbk(); + pub.in <== inputOwnerPrivateKey; + inputOwnerPublicKey[0] = pub.Ax; + inputOwnerPublicKey[1] = pub.Ay; + var inputOwnerPublicKeys[nInputs][2]; + for (var i = 0; i < nInputs; i++) { + inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; + inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; + } + + component checkPositives = CheckPositive(nOutputs); + checkPositives.outputValues <== outputValues; + + component checkInputHashes = CheckHashes(nInputs); + checkInputHashes.commitments <== inputCommitments; + checkInputHashes.values <== inputValues; + checkInputHashes.salts <== inputSalts; + checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; + + component checkOutputHashes = CheckHashes(nOutputs); + checkOutputHashes.commitments <== outputCommitments; + checkOutputHashes.values <== outputValues; + checkOutputHashes.salts <== outputSalts; + checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; + + component checkNullifiers = CheckNullifiers(nInputs); + checkNullifiers.nullifiers <== nullifiers; + checkNullifiers.values <== inputValues; + checkNullifiers.salts <== inputSalts; + checkNullifiers.ownerPrivateKey <== inputOwnerPrivateKey; + + component checkSum = CheckSum(nInputs, nOutputs); + checkSum.inputValues <== inputValues; + checkSum.outputValues <== outputValues; + + // With the above steps, we demonstrated that the nullifiers + // are securely bound to the input commitments. Now we need to + // demonstrate that the input commitments belong to the Sparse + // Merkle Tree with the root `root`. + component checkSMTProof = CheckSMTProof(nInputs, nSMTLevels); + checkSMTProof.root <== root; + checkSMTProof.merkleProof <== merkleProof; + checkSMTProof.enabled <== enabled; + checkSMTProof.leafNodeIndexes <== inputCommitments; + + // generate shared secret for the receiver + var sharedSecretReceiver[2]; + component ecdh1 = Ecdh(); + ecdh1.privKey <== inputOwnerPrivateKey; + // our circuit requires that the output UTXO for the receiver must be the first in the array + ecdh1.pubKey[0] <== outputOwnerPublicKeys[0][0]; + ecdh1.pubKey[1] <== outputOwnerPublicKeys[0][1]; + sharedSecretReceiver[0] = ecdh1.sharedKey[0]; + sharedSecretReceiver[1] = ecdh1.sharedKey[1]; + + // encrypt the value for the receiver + component encrypt1 = SymmetricEncrypt(2); + // our circuit requires that the output UTXO for the receiver must be the first in the array + encrypt1.plainText[0] <== outputValues[0]; + encrypt1.plainText[1] <== outputSalts[0]; + encrypt1.key <== sharedSecretReceiver; + encrypt1.nonce <== encryptionNonce; + // the output for a 2-element input encryption is a 4-element array + encrypt1.cipherText[0] ==> cipherTextReceiver[0]; + encrypt1.cipherText[1] ==> cipherTextReceiver[1]; + encrypt1.cipherText[2] ==> cipherTextReceiver[2]; + encrypt1.cipherText[3] ==> cipherTextReceiver[3]; + + // generate shared secret for the authority + var sharedSecretAuthority[2]; + component ecdh2 = Ecdh(); + ecdh2.privKey <== inputOwnerPrivateKey; + // our circuit requires that the output UTXO for the receiver must be the first in the array + ecdh2.pubKey[0] <== authorityPublicKey[0]; + ecdh2.pubKey[1] <== authorityPublicKey[1]; + sharedSecretAuthority[0] = ecdh2.sharedKey[0]; + sharedSecretAuthority[1] = ecdh2.sharedKey[1]; + + // encrypt the values for the authority + component encrypt2 = SymmetricEncrypt(2 + 2 * nInputs + 4 * nOutputs); + encrypt2.plainText[0] <== inputOwnerPublicKey[0]; + encrypt2.plainText[1] <== inputOwnerPublicKey[1]; + var idx1 = 2; + for (var i = 0; i < nInputs; i++) { + encrypt2.plainText[idx1] <== inputValues[i]; + idx1++; + encrypt2.plainText[idx1] <== inputSalts[i]; + idx1++; + } + for (var i = 0; i < nOutputs; i++) { + encrypt2.plainText[idx1] <== outputOwnerPublicKeys[i][0]; + idx1++; + encrypt2.plainText[idx1] <== outputOwnerPublicKeys[i][1]; + idx1++; + } + for (var i = 0; i < nOutputs; i++) { + encrypt2.plainText[idx1] <== outputValues[i]; + idx1++; + encrypt2.plainText[idx1] <== outputSalts[i]; + idx1++; + } + encrypt2.key <== sharedSecretAuthority; + encrypt2.nonce <== encryptionNonce; + encrypt2.cipherText ==> cipherTextAuthority; +} \ No newline at end of file diff --git a/zkp/circuits/basetokens/anon_nullifier_base.circom b/zkp/circuits/basetokens/anon_nullifier_base.circom new file mode 100644 index 0000000..1005bbd --- /dev/null +++ b/zkp/circuits/basetokens/anon_nullifier_base.circom @@ -0,0 +1,97 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "../lib/check-positive.circom"; +include "../lib/check-hashes.circom"; +include "../lib/check-sum.circom"; +include "../lib/check-nullifiers.circom"; +include "../lib/check-smt-proof.circom"; +include "../node_modules/circomlib/circuits/babyjub.circom"; + +// This version of the circuit performs the following operations: +// - derive the sender's public key from the sender's private key +// - check the input and output commitments match the expected hashes +// - check the input and output values sum to the same amount +// - check the nullifiers are derived from the input commitments and the sender's private key +// - check the nullifiers are included in the Merkle tree +template Zeto(nInputs, nOutputs, nSMTLevels) { + signal input nullifiers[nInputs]; + signal input inputCommitments[nInputs]; + signal input inputValues[nInputs]; + signal input inputSalts[nInputs]; + // must be properly hashed and trimmed to be compatible with the BabyJub curve. + // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 + signal input inputOwnerPrivateKey; + signal input root; + signal input merkleProof[nInputs][nSMTLevels]; + // allows merkle proof verifications for empty input elements to be skipped + signal input enabled[nInputs]; + signal input outputCommitments[nOutputs]; + signal input outputValues[nOutputs]; + signal input outputOwnerPublicKeys[nOutputs][2]; + signal input outputSalts[nOutputs]; + + // derive the sender's public key from the secret input + // for the sender's private key. This step demonstrates + // the sender really owns the private key for the input + // UTXOs + var inputOwnerPublicKey[2]; + component pub = BabyPbk(); + pub.in <== inputOwnerPrivateKey; + inputOwnerPublicKey[0] = pub.Ax; + inputOwnerPublicKey[1] = pub.Ay; + var inputOwnerPublicKeys[nInputs][2]; + for (var i = 0; i < nInputs; i++) { + inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; + inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; + } + + component checkPositives = CheckPositive(nOutputs); + checkPositives.outputValues <== outputValues; + + component checkInputHashes = CheckHashes(nInputs); + checkInputHashes.commitments <== inputCommitments; + checkInputHashes.values <== inputValues; + checkInputHashes.salts <== inputSalts; + checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; + + component checkOutputHashes = CheckHashes(nOutputs); + checkOutputHashes.commitments <== outputCommitments; + checkOutputHashes.values <== outputValues; + checkOutputHashes.salts <== outputSalts; + checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; + + component checkNullifiers = CheckNullifiers(nInputs); + checkNullifiers.nullifiers <== nullifiers; + checkNullifiers.values <== inputValues; + checkNullifiers.salts <== inputSalts; + checkNullifiers.ownerPrivateKey <== inputOwnerPrivateKey; + + component checkSum = CheckSum(nInputs, nOutputs); + checkSum.inputValues <== inputValues; + checkSum.outputValues <== outputValues; + + // With the above steps, we demonstrated that the nullifiers + // are securely bound to the input commitments. Now we need to + // demonstrate that the input commitments belong to the Sparse + // Merkle Tree with the root `root`. + component checkSMTProof = CheckSMTProof(nInputs, nSMTLevels); + checkSMTProof.root <== root; + checkSMTProof.merkleProof <== merkleProof; + checkSMTProof.enabled <== enabled; + checkSMTProof.leafNodeIndexes <== inputCommitments; +} diff --git a/zkp/circuits/basetokens/anon_nullifier_kyc_base.circom b/zkp/circuits/basetokens/anon_nullifier_kyc_base.circom new file mode 100644 index 0000000..5346e2a --- /dev/null +++ b/zkp/circuits/basetokens/anon_nullifier_kyc_base.circom @@ -0,0 +1,127 @@ +// Copyright © 2024 Kaleido, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +pragma circom 2.1.4; + +include "../lib/check-positive.circom"; +include "../lib/check-hashes.circom"; +include "../lib/check-sum.circom"; +include "../lib/check-nullifiers.circom"; +include "../lib/check-smt-proof.circom"; +include "../node_modules/circomlib/circuits/babyjub.circom"; +include "../node_modules/circomlib/circuits/poseidon.circom"; + +// This version of the circuit performs the following operations: +// - derive the sender's public key from the sender's private key +// - check the input and output commitments match the expected hashes +// - check the input and output values sum to the same amount +// - check the nullifiers are derived from the input commitments and the sender's private key +// - check the nullifiers are included in the Merkle tree +// - check the owner public keys for inputs and outputs are included in the identities merkle tree +template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) { + signal input nullifiers[nInputs]; + signal input inputCommitments[nInputs]; + signal input inputValues[nInputs]; + signal input inputSalts[nInputs]; + // must be properly hashed and trimmed to be compatible with the BabyJub curve. + // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 + signal input inputOwnerPrivateKey; + signal input utxosRoot; + signal input utxosMerkleProof[nInputs][nUTXOSMTLevels]; + // allows merkle proof verifications for empty input elements to be skipped + signal input enabled[nInputs]; + signal input identitiesRoot; + signal input identitiesMerkleProof[nOutputs + 1][nIdentitiesSMTLevels]; + signal input outputCommitments[nOutputs]; + signal input outputValues[nOutputs]; + signal input outputOwnerPublicKeys[nOutputs][2]; + signal input outputSalts[nOutputs]; + + // derive the sender's public key from the secret input + // for the sender's private key. This step demonstrates + // the sender really owns the private key for the input + // UTXOs + var inputOwnerPublicKey[2]; + component pub = BabyPbk(); + pub.in <== inputOwnerPrivateKey; + inputOwnerPublicKey[0] = pub.Ax; + inputOwnerPublicKey[1] = pub.Ay; + var inputOwnerPublicKeys[nInputs][2]; + for (var i = 0; i < nInputs; i++) { + inputOwnerPublicKeys[i][0] = inputOwnerPublicKey[0]; + inputOwnerPublicKeys[i][1] = inputOwnerPublicKey[1]; + } + + component checkPositives = CheckPositive(nOutputs); + checkPositives.outputValues <== outputValues; + + component checkInputHashes = CheckHashes(nInputs); + checkInputHashes.commitments <== inputCommitments; + checkInputHashes.values <== inputValues; + checkInputHashes.salts <== inputSalts; + checkInputHashes.ownerPublicKeys <== inputOwnerPublicKeys; + + component checkOutputHashes = CheckHashes(nOutputs); + checkOutputHashes.commitments <== outputCommitments; + checkOutputHashes.values <== outputValues; + checkOutputHashes.salts <== outputSalts; + checkOutputHashes.ownerPublicKeys <== outputOwnerPublicKeys; + + component checkNullifiers = CheckNullifiers(nInputs); + checkNullifiers.nullifiers <== nullifiers; + checkNullifiers.values <== inputValues; + checkNullifiers.salts <== inputSalts; + checkNullifiers.ownerPrivateKey <== inputOwnerPrivateKey; + + component checkSum = CheckSum(nInputs, nOutputs); + checkSum.inputValues <== inputValues; + checkSum.outputValues <== outputValues; + + // With the above steps, we demonstrated that the nullifiers + // are securely bound to the input commitments. Now we need to + // demonstrate that the input commitments belong to the Sparse + // Merkle Tree with the root `root`. + component checkUTXOSMTProof = CheckSMTProof(nInputs, nUTXOSMTLevels); + checkUTXOSMTProof.root <== utxosRoot; + checkUTXOSMTProof.merkleProof <== utxosMerkleProof; + checkUTXOSMTProof.enabled <== enabled; + checkUTXOSMTProof.leafNodeIndexes <== inputCommitments; + + // Finally, we need to demonstrate that the owner public keys + // for the inputs and outputs are included in the identities + // Sparse Merkle Tree with the root `identitiesRoot`. + var ownerPublicKeyHashes[nOutputs + 1]; + component hash1 = Poseidon(2); + hash1.inputs[0] <== inputOwnerPublicKey[0]; + hash1.inputs[1] <== inputOwnerPublicKey[1]; + ownerPublicKeyHashes[0] = hash1.out; + + component hashes[nOutputs]; + var identitiesMTPCheckEnabled[nOutputs + 1]; + identitiesMTPCheckEnabled[0] = 1; + for (var i = 0; i < nOutputs; i++) { + hashes[i] = Poseidon(2); + hashes[i].inputs[0] <== outputOwnerPublicKeys[i][0]; + hashes[i].inputs[1] <== outputOwnerPublicKeys[i][1]; + ownerPublicKeyHashes[i+1] = hashes[i].out; + identitiesMTPCheckEnabled[i+1] = 1; + } + + component checkIdentitiesSMTProof = CheckSMTProof(nOutputs + 1, nIdentitiesSMTLevels); + checkIdentitiesSMTProof.root <== identitiesRoot; + checkIdentitiesSMTProof.merkleProof <== identitiesMerkleProof; + checkIdentitiesSMTProof.enabled <== identitiesMTPCheckEnabled; + checkIdentitiesSMTProof.leafNodeIndexes <== ownerPublicKeyHashes; +} \ No newline at end of file diff --git a/zkp/circuits/gen-config.json b/zkp/circuits/gen-config.json index 6e22d48..8161c27 100644 --- a/zkp/circuits/gen-config.json +++ b/zkp/circuits/gen-config.json @@ -1,30 +1,37 @@ { "anon": { "ptau": "powersOfTau28_hez_final_12", + "batchPtau": "powersOfTau28_hez_final_13", "skipSolidityGenaration": false }, "anon_enc": { "ptau": "powersOfTau28_hez_final_13", + "batchPtau": "powersOfTau28_hez_final_14", "skipSolidityGenaration": false }, "anon_nullifier": { "ptau": "powersOfTau28_hez_final_16", + "batchPtau": "powersOfTau28_hez_final_18", "skipSolidityGenaration": false }, "anon_nullifier_kyc": { "ptau": "powersOfTau28_hez_final_16", + "batchPtau": "powersOfTau28_hez_final_18", "skipSolidityGenaration": false }, "anon_enc_nullifier_non_repudiation": { "ptau": "powersOfTau28_hez_final_16", + "batchPtau": "powersOfTau28_hez_final_18", "skipSolidityGenaration": false }, "anon_enc_nullifier": { "ptau": "powersOfTau28_hez_final_16", + "batchPtau": "powersOfTau28_hez_final_18", "skipSolidityGenaration": false }, "anon_enc_nullifier_kyc": { "ptau": "powersOfTau28_hez_final_16", + "batchPtau": "powersOfTau28_hez_final_18", "skipSolidityGenaration": false }, "nf_anon": { diff --git a/zkp/circuits/gen.js b/zkp/circuits/gen.js index e6b14ed..daeda82 100644 --- a/zkp/circuits/gen.js +++ b/zkp/circuits/gen.js @@ -11,6 +11,7 @@ const circuitsRoot = process.env.CIRCUITS_ROOT || argv.circuitsRoot; const provingKeysRoot = process.env.PROVING_KEYS_ROOT || argv.provingKeysRoot; const ptauDownload = process.env.PTAU_DOWNLOAD_PATH || argv.ptauDownloadPath; const specificCircuits = argv.c; +const verbose = argv.v; const compileOnly = argv.compileOnly; const parallelLimit = parseInt(process.env.GEN_CONCURRENCY, 10) || 10; // Default to compile 10 circuits in parallel @@ -101,31 +102,49 @@ const processCircuit = async (circuit, ptau, skipSolidityGenaration) => { } log(circuit, `Compiling circuit`); - await execAsync( - `circom ${circomInput} --output ${circuitsRoot} --sym --wasm` + + const { cmOut, cmErr } = await execAsync( + `circom ${circomInput} --output ${provingKeysRoot} --r1cs` ); - if (compileOnly) { - return; + if (verbose) { + if (cmOut) { + log(circuit, 'compile output:\n' + cmOut); + } + if (cmErr) { + log(circuit, 'compile error:\n' + cmErr); + } } - await execAsync(`circom ${circomInput} --output ${provingKeysRoot} --r1cs`); - log(circuit, `Generating test proving key with ${ptau}`); - await execAsync( + const { pkOut, pkErr } = await execAsync( `npx snarkjs groth16 setup ${path.join( provingKeysRoot, `${circuit}.r1cs` )} ${ptauFile} ${zkeyOutput}` ); - - log(circuit, `Generating verification key`); - await execAsync( + if (verbose) { + if (pkOut) { + log(circuit, 'test proving key generation output:\n' + pkOut); + } + if (pkErr) { + log(circuit, 'test proving key generation error:\n' + pkErr); + } + } + log(circuit, `Exporting verification key`); + const { vkOut, vkErr } = await execAsync( `npx snarkjs zkey export verificationkey ${zkeyOutput} ${path.join( provingKeysRoot, `${circuit}-vkey.json` )}` ); - + if (verbose) { + if (vkOut) { + log(circuit, 'verification key export output:\n' + vkOut); + } + if (vkErr) { + log(circuit, 'verification key export error:\n' + vkErr); + } + } if (skipSolidityGenaration) { log(circuit, `Skipping solidity verifier generation`); return; @@ -140,10 +159,17 @@ const processCircuit = async (circuit, ptau, skipSolidityGenaration) => { 'lib', `verifier_${circuit}.sol` ); - await execAsync( + const { svOut, svErr } = await execAsync( `npx snarkjs zkey export solidityverifier ${zkeyOutput} ${solidityFile}` ); - + if (verbose) { + if (svOut) { + log(circuit, 'solidity verifier export output:\n' + svOut); + } + if (svErr) { + log(circuit, 'solidity verifier export error:\n' + svErr); + } + } log(circuit, `Modifying the contract name in the Solidity file`); const camelCaseCircuitName = toCamelCase(circuit); const solidityFileTmp = `${solidityFile}.tmp`; @@ -176,7 +202,10 @@ const run = async () => { const circuitsArray = Object.entries(circuits); const activePromises = new Set(); - for (const [circuit, { ptau, skipSolidityGenaration }] of circuitsArray) { + for (const [ + circuit, + { ptau, skipSolidityGenaration, batchPtau }, + ] of circuitsArray) { if (onlyCircuits && !onlyCircuits.includes(circuit)) { continue; } @@ -188,6 +217,19 @@ const run = async () => { await Promise.race(activePromises); } + if (batchPtau) { + const pcBatchPromise = processCircuit( + circuit + '_batch', + batchPtau, + skipSolidityGenaration + ); + activePromises.add(pcBatchPromise); + + if (activePromises.size >= parallelLimit) { + await Promise.race(activePromises); + } + } + pcPromise.finally(() => activePromises.delete(pcPromise)); } From a47c0c17136ae887faea030c803e9c3eb8ee71a7 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 25 Sep 2024 13:29:00 +0100 Subject: [PATCH 02/24] batch for fungible token with no encrypted values Signed-off-by: Chengxuan Xing --- solidity/contracts/factory.sol | 5 + solidity/contracts/lib/common.sol | 18 + solidity/contracts/lib/zeto_base.sol | 42 +- solidity/contracts/lib/zeto_common.sol | 5 +- .../contracts/lib/zeto_fungible_withdraw.sol | 4 +- .../lib/zeto_fungible_withdraw_nullifier.sol | 3 +- solidity/contracts/lib/zeto_nullifier.sol | 42 +- solidity/contracts/zeto_anon.sol | 78 ++- solidity/contracts/zeto_anon_enc.sol | 57 +- .../contracts/zeto_anon_enc_nullifier.sol | 76 ++- .../contracts/zeto_anon_enc_nullifier_kyc.sol | 83 ++- ...eto_anon_enc_nullifier_non_repudiation.sol | 102 ++-- solidity/contracts/zeto_anon_nullifier.sol | 101 ++- .../contracts/zeto_anon_nullifier_kyc.sol | 107 +++- solidity/contracts/zeto_nf_anon.sol | 13 +- solidity/contracts/zeto_nf_anon_nullifier.sol | 15 +- solidity/contracts/zkDvP.sol | 13 +- solidity/ignition/modules/zeto_anon.ts | 16 +- solidity/ignition/modules/zeto_anon_enc.ts | 19 +- .../modules/zeto_anon_enc_nullifier.ts | 37 +- .../modules/zeto_anon_enc_nullifier_kyc.ts | 13 + ...zeto_anon_enc_nullifier_non_repudiation.ts | 49 +- .../ignition/modules/zeto_anon_nullifier.ts | 34 +- .../modules/zeto_anon_nullifier_kyc.ts | 38 +- solidity/scripts/tokens/Zeto_Anon.ts | 12 +- solidity/scripts/tokens/Zeto_AnonEnc.ts | 12 +- .../scripts/tokens/Zeto_AnonEncNullifier.ts | 20 +- .../tokens/Zeto_AnonEncNullifierKyc.ts | 2 + .../Zeto_AnonEncNullifierNonRepudiation.ts | 20 +- solidity/scripts/tokens/Zeto_AnonNullifier.ts | 20 +- .../scripts/tokens/Zeto_AnonNullifierKyc.ts | 21 +- solidity/test/factory.ts | 166 +++-- solidity/test/lib/deploy.ts | 56 +- solidity/test/zeto_anon.ts | 180 ++++-- solidity/test/zeto_anon_enc.ts | 193 ++++-- solidity/test/zeto_anon_enc_nullifier.ts | 368 ++++++++--- solidity/test/zeto_anon_enc_nullifier_kyc.ts | 6 +- ...zeto_anon_enc_nullifier_non_repudiation.ts | 428 ++++++++++--- solidity/test/zeto_anon_nullifier.ts | 356 ++++++++--- solidity/test/zeto_anon_nullifier_kyc.ts | 575 ++++++++++++++---- solidity/test/zeto_nf_anon.ts | 86 ++- solidity/test/zeto_nf_anon_nullifier.ts | 183 ++++-- solidity/test/zkDvP.ts | 321 ++++++++-- zkp/circuits/gen.js | 18 +- 44 files changed, 3104 insertions(+), 909 deletions(-) diff --git a/solidity/contracts/factory.sol b/solidity/contracts/factory.sol index 735b531..533c93f 100644 --- a/solidity/contracts/factory.sol +++ b/solidity/contracts/factory.sol @@ -53,6 +53,7 @@ contract ZetoTokenFactory is Ownable { ); // the depositVerifier and withdrawVerifier are optional // for the non-fungible token implementations + // TODO batchVerifier to be implemented for non-fungible token implementations[name] = implementation; } @@ -75,6 +76,10 @@ contract ZetoTokenFactory is Ownable { args.withdrawVerifier != address(0), "Factory: withdrawVerifier address is required" ); + require( + args.batchVerifier != address(0), + "Factory: batchVerifier address is required" + ); address instance = Clones.clone(args.implementation); require( instance != address(0), diff --git a/solidity/contracts/lib/common.sol b/solidity/contracts/lib/common.sol index 1ac7fff..f99c4ce 100644 --- a/solidity/contracts/lib/common.sol +++ b/solidity/contracts/lib/common.sol @@ -25,6 +25,24 @@ library Commonlib { uint[2] pC; } + function padUintArray( + uint256[] memory arr, + uint256 targetLength, + uint256 padValue + ) internal pure returns (uint256[] memory) { + if (arr.length == targetLength) { + return arr; + } + uint256[] memory paddedArray = new uint256[](targetLength); + for (uint256 i = 0; i < arr.length; i++) { + paddedArray[i] = arr[i]; + } + for (uint256 i = arr.length; i < targetLength; i++) { + paddedArray[i] = padValue; + } + return paddedArray; + } + function getProofHash( Proof calldata proof ) internal pure returns (bytes32) { diff --git a/solidity/contracts/lib/zeto_base.sol b/solidity/contracts/lib/zeto_base.sol index 11909ab..4ea8a42 100644 --- a/solidity/contracts/lib/zeto_base.sol +++ b/solidity/contracts/lib/zeto_base.sol @@ -47,8 +47,8 @@ abstract contract ZetoBase is IZetoBase, ZetoCommon { } function validateTransactionProposal( - uint256[2] memory inputs, - uint256[2] memory outputs, + uint256[] memory inputs, + uint256[] memory outputs, Commonlib.Proof calldata proof ) internal view returns (bool) { // sort the inputs and outputs to detect duplicates @@ -100,9 +100,38 @@ abstract contract ZetoBase is IZetoBase, ZetoCommon { return true; } + function checkAndPadCommitments( + uint256[] memory inputs, + uint256[] memory outputs, + uint256 batchMax + ) internal pure returns (uint256[] memory, uint256[] memory) { + uint256 inputLen = inputs.length; + uint256 outputLen = outputs.length; + + // Check if inputs or outputs exceed batchMax and revert with custom error if necessary + if (inputLen > batchMax || outputLen > batchMax) { + revert UTXOCommitmentsExceededMaximumNumber(batchMax); + } + + // Ensure both arrays are padded to the same length + uint256 maxLength; + + if (inputLen > 2 || outputLen > 2) { + maxLength = batchMax; // Pad both to batchMax if one has more than 2 items + } else { + maxLength = 2; // Otherwise, pad both to 2 + } + + // Pad both inputs and outputs to the determined maxLength + inputs = Commonlib.padUintArray(inputs, maxLength, 0); + outputs = Commonlib.padUintArray(outputs, maxLength, 0); + + return (inputs, outputs); + } + function processInputsAndOutputs( - uint256[2] memory inputs, - uint256[2] memory outputs + uint256[] memory inputs, + uint256[] memory outputs ) internal { // accept the transaction to consume the input UTXOs and produce new UTXOs for (uint256 i = 0; i < inputs.length; ++i) { @@ -115,7 +144,10 @@ abstract contract ZetoBase is IZetoBase, ZetoCommon { // This function is used to mint new UTXOs, as an example implementation, // which is only callable by the owner. - function _mint(uint256[] memory utxos, bytes calldata data) internal virtual { + function _mint( + uint256[] memory utxos, + bytes calldata data + ) internal virtual { for (uint256 i = 0; i < utxos.length; ++i) { uint256 utxo = utxos[i]; if (_utxos[utxo] == UTXOStatus.UNSPENT) { diff --git a/solidity/contracts/lib/zeto_common.sol b/solidity/contracts/lib/zeto_common.sol index 567216e..d52cbc8 100644 --- a/solidity/contracts/lib/zeto_common.sol +++ b/solidity/contracts/lib/zeto_common.sol @@ -28,6 +28,7 @@ abstract contract ZetoCommon is OwnableUpgradeable { error UTXOAlreadySpent(uint256 utxo); error UTXODuplicate(uint256 utxo); error IdentityNotRegistered(address addr); + error UTXOCommitmentsExceededMaximumNumber(uint256 maxAllowed); // used for multi-step transaction flows that require counterparties // to upload proofs. To protect the party that uploads their proof first, @@ -49,8 +50,8 @@ abstract contract ZetoCommon is OwnableUpgradeable { } function sortInputsAndOutputs( - uint256[2] memory inputs, - uint256[2] memory outputs + uint256[] memory inputs, + uint256[] memory outputs ) internal pure returns (uint256[] memory, uint256[] memory) { uint256[] memory sortedInputs = new uint256[](inputs.length); uint256[] memory sortedOutputs = new uint256[](outputs.length); diff --git a/solidity/contracts/lib/zeto_fungible_withdraw.sol b/solidity/contracts/lib/zeto_fungible_withdraw.sol index f6b0c08..755e590 100644 --- a/solidity/contracts/lib/zeto_fungible_withdraw.sol +++ b/solidity/contracts/lib/zeto_fungible_withdraw.sol @@ -40,10 +40,12 @@ abstract contract ZetoFungibleWithdraw is ZetoFungible { function _withdraw( uint256 amount, - uint256[2] memory inputs, + uint256[] memory inputs, uint256 output, Commonlib.Proof calldata proof ) public virtual { + require((inputs.length == 2), "Withdraw must have 2 inputs"); + // construct the public inputs uint256[4] memory publicInputs; publicInputs[0] = amount; diff --git a/solidity/contracts/lib/zeto_fungible_withdraw_nullifier.sol b/solidity/contracts/lib/zeto_fungible_withdraw_nullifier.sol index e5415de..ddc20d0 100644 --- a/solidity/contracts/lib/zeto_fungible_withdraw_nullifier.sol +++ b/solidity/contracts/lib/zeto_fungible_withdraw_nullifier.sol @@ -41,11 +41,12 @@ abstract contract ZetoFungibleWithdrawWithNullifiers is ZetoFungible { function _withdrawWithNullifiers( uint256 amount, - uint256[2] memory nullifiers, + uint256[] memory nullifiers, uint256 output, uint256 root, Commonlib.Proof calldata proof ) public virtual { + require((nullifiers.length == 2), "Withdraw must have 2 nullifiers"); // construct the public inputs uint256[7] memory publicInputs; publicInputs[0] = amount; diff --git a/solidity/contracts/lib/zeto_nullifier.sol b/solidity/contracts/lib/zeto_nullifier.sol index eb81919..6c3281b 100644 --- a/solidity/contracts/lib/zeto_nullifier.sol +++ b/solidity/contracts/lib/zeto_nullifier.sol @@ -42,9 +42,38 @@ abstract contract ZetoNullifier is IZetoBase, ZetoCommon { _commitmentsTree.initialize(MAX_SMT_DEPTH); } + function checkAndPadCommitments( + uint256[] memory inputs, + uint256[] memory outputs, + uint256 batchMax + ) internal pure returns (uint256[] memory, uint256[] memory) { + uint256 inputLen = inputs.length; + uint256 outputLen = outputs.length; + + // Check if inputs or outputs exceed batchMax and revert with custom error if necessary + if (inputLen > batchMax || outputLen > batchMax) { + revert UTXOCommitmentsExceededMaximumNumber(batchMax); + } + + // Ensure both arrays are padded to the same length + uint256 maxLength; + + if (inputLen > 2 || outputLen > 2) { + maxLength = batchMax; // Pad both to batchMax if one has more than 2 items + } else { + maxLength = 2; // Otherwise, pad both to 2 + } + + // Pad both inputs and outputs to the determined maxLength + inputs = Commonlib.padUintArray(inputs, maxLength, 0); + outputs = Commonlib.padUintArray(outputs, maxLength, 0); + + return (inputs, outputs); + } + function validateTransactionProposal( - uint256[2] memory nullifiers, - uint256[2] memory outputs, + uint256[] memory nullifiers, + uint256[] memory outputs, uint256 root ) internal view returns (bool) { // sort the inputs and outputs to detect duplicates @@ -94,8 +123,8 @@ abstract contract ZetoNullifier is IZetoBase, ZetoCommon { } function processInputsAndOutputs( - uint256[2] memory nullifiers, - uint256[2] memory outputs + uint256[] memory nullifiers, + uint256[] memory outputs ) internal { for (uint256 i = 0; i < nullifiers.length; ++i) { if (nullifiers[i] != 0) { @@ -111,7 +140,10 @@ abstract contract ZetoNullifier is IZetoBase, ZetoCommon { // This function is used to mint new UTXOs, as an example implementation, // which is only callable by the owner. - function _mint(uint256[] memory utxos, bytes calldata data) internal virtual { + function _mint( + uint256[] memory utxos, + bytes calldata data + ) internal virtual { for (uint256 i = 0; i < utxos.length; ++i) { uint256 utxo = utxos[i]; if (utxo == 0) { diff --git a/solidity/contracts/zeto_anon.sol b/solidity/contracts/zeto_anon.sol index de778bf..ba14e7e 100644 --- a/solidity/contracts/zeto_anon.sol +++ b/solidity/contracts/zeto_anon.sol @@ -28,6 +28,8 @@ import {ZetoFungibleWithdraw} from "./lib/zeto_fungible_withdraw.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +uint256 constant MAX_BATCH = 10; + /// @title A sample implementation of a Zeto based fungible token with anonymity and no encryption /// @author Kaleido, Inc. /// @dev The proof has the following statements: @@ -70,31 +72,61 @@ contract Zeto_Anon is IZeto, ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable { Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { - uint256 inputLen = inputs.length; - uint256 outputLen = outputs.length; - - require( - (inputLen <= 10 && outputsLen <= 10), - "Inputs or outputs exceeded maximum number of 10" - ); + // Check and pad inputs and outputs based on the max size + (inputs, outputs) = checkAndPadCommitments(inputs, outputs, MAX_BATCH); require( validateTransactionProposal(inputs, outputs, proof), "Invalid transaction proposal" ); - // construct the public inputs - uint256[4] memory publicInputs; - publicInputs[0] = inputs[0]; - publicInputs[1] = inputs[1]; - publicInputs[2] = outputs[0]; - publicInputs[3] = outputs[1]; - // Check the proof - require( - verifier.verifyProof(proof.pA, proof.pB, proof.pC, publicInputs), - "Invalid proof" - ); + if (inputs.length > 2) { + // construct the public inputs + uint256[20] memory publicInputs; + uint256 piIndex = 0; + // copy input commitments + for (uint256 i = 0; i < inputs.length; i++) { + publicInputs[piIndex++] = inputs[i]; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + require( + batchVerifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); + } else { + // construct the public inputs + uint256[4] memory publicInputs; + uint256 piIndex = 0; + // copy input commitments + for (uint256 i = 0; i < inputs.length; i++) { + publicInputs[piIndex++] = inputs[i]; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + require( + verifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); + } processInputsAndOutputs(inputs, outputs); @@ -123,13 +155,17 @@ contract Zeto_Anon is IZeto, ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable { function withdraw( uint256 amount, - uint256[2] memory inputs, + uint256[] memory inputs, uint256 output, Commonlib.Proof calldata proof ) public { - validateTransactionProposal(inputs, [output, 0], proof); + // Check and pad inputs and outputs based on the max size + uint256[] memory outputs = new uint256[](inputs.length); + outputs[0] = output; + (inputs, outputs) = checkAndPadCommitments(inputs, outputs, MAX_BATCH); + validateTransactionProposal(inputs, outputs, proof); _withdraw(amount, inputs, output, proof); - processInputsAndOutputs(inputs, [output, 0]); + processInputsAndOutputs(inputs, outputs); } function mint( diff --git a/solidity/contracts/zeto_anon_enc.sol b/solidity/contracts/zeto_anon_enc.sol index 7b148b0..c70039a 100644 --- a/solidity/contracts/zeto_anon_enc.sol +++ b/solidity/contracts/zeto_anon_enc.sol @@ -28,6 +28,8 @@ import {Commonlib} from "./lib/common.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +uint256 constant MAX_BATCH = 10; // batch not supported + /// @title A sample implementation of a Zeto based fungible token with anonymity, and encryption /// @author Kaleido, Inc. /// @dev The proof has the following statements: @@ -72,13 +74,18 @@ contract Zeto_AnonEnc is * Emits a {UTXOTransferWithEncryptedValues} event. */ function transfer( - uint256[2] memory inputs, - uint256[2] memory outputs, + uint256[] memory inputs, + uint256[] memory outputs, uint256 encryptionNonce, uint256[4] memory encryptedValues, Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { + // Check and pad commitments + (inputs, outputs) = checkAndPadCommitments(inputs, outputs, MAX_BATCH); + if (outputs.length > 2) { + revert("batch not supported"); + } require( validateTransactionProposal(inputs, outputs, proof), "Invalid transaction proposal" @@ -86,15 +93,23 @@ contract Zeto_AnonEnc is // construct the public inputs uint256[9] memory publicInputs; - publicInputs[0] = encryptedValues[0]; // encrypted value for the receiver UTXO - publicInputs[1] = encryptedValues[1]; // encrypted salt for the receiver UTXO - publicInputs[2] = encryptedValues[2]; // parity bit for the cipher text - publicInputs[3] = encryptedValues[3]; // parity bit for the cipher text - publicInputs[4] = inputs[0]; - publicInputs[5] = inputs[1]; - publicInputs[6] = outputs[0]; - publicInputs[7] = outputs[1]; - publicInputs[8] = encryptionNonce; + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } + // copy input commitments + for (uint256 i = 0; i < inputs.length; i++) { + publicInputs[piIndex++] = inputs[i]; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; // Check the proof require( @@ -104,22 +119,16 @@ contract Zeto_AnonEnc is processInputsAndOutputs(inputs, outputs); - uint256[] memory inputArray = new uint256[](inputs.length); - uint256[] memory outputArray = new uint256[](outputs.length); uint256[] memory encryptedValuesArray = new uint256[]( encryptedValues.length ); - for (uint256 i = 0; i < inputs.length; ++i) { - inputArray[i] = inputs[i]; - outputArray[i] = outputs[i]; - } for (uint256 i = 0; i < encryptedValues.length; ++i) { encryptedValuesArray[i] = encryptedValues[i]; } emit UTXOTransferWithEncryptedValues( - inputArray, - outputArray, + inputs, + outputs, encryptionNonce, encryptedValuesArray, msg.sender, @@ -142,13 +151,17 @@ contract Zeto_AnonEnc is function withdraw( uint256 amount, - uint256[2] memory inputs, + uint256[] memory inputs, uint256 output, Commonlib.Proof calldata proof ) public { - validateTransactionProposal(inputs, [output, 0], proof); + uint256[] memory outputs = new uint256[](inputs.length); + outputs[0] = output; + // Check and pad commitments + (inputs, outputs) = checkAndPadCommitments(inputs, outputs, MAX_BATCH); + validateTransactionProposal(inputs, outputs, proof); _withdraw(amount, inputs, output, proof); - processInputsAndOutputs(inputs, [output, 0]); + processInputsAndOutputs(inputs, outputs); } function mint( diff --git a/solidity/contracts/zeto_anon_enc_nullifier.sol b/solidity/contracts/zeto_anon_enc_nullifier.sol index 8c2ed9d..f6cec53 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier.sol @@ -26,6 +26,8 @@ import {Registry} from "./lib/registry.sol"; import {Commonlib} from "./lib/common.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +uint256 constant MAX_BATCH = 10; // batch not supported + /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking /// @author Kaleido, Inc. /// @dev The proof has the following statements: @@ -77,14 +79,23 @@ contract Zeto_AnonEncNullifier is * Emits a {UTXOTransferWithEncryptedValues} event. */ function transfer( - uint256[2] memory nullifiers, - uint256[2] memory outputs, + uint256[] memory nullifiers, + uint256[] memory outputs, uint256 root, uint256 encryptionNonce, uint256[4] memory encryptedValues, Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { + // Check and pad commitments + (nullifiers, outputs) = checkAndPadCommitments( + nullifiers, + outputs, + MAX_BATCH + ); + if (outputs.length > 2) { + revert("batch not supported"); + } require( validateTransactionProposal(nullifiers, outputs, root), "Invalid transaction proposal" @@ -92,18 +103,31 @@ contract Zeto_AnonEncNullifier is // construct the public inputs uint256[12] memory publicInputs; - publicInputs[0] = encryptedValues[0]; // encrypted value for the receiver UTXO - publicInputs[1] = encryptedValues[1]; // encrypted salt for the receiver UTXO - publicInputs[2] = encryptedValues[2]; // parity bit for the cipher text - publicInputs[3] = encryptedValues[3]; // parity bit for the cipher text - publicInputs[4] = nullifiers[0]; - publicInputs[5] = nullifiers[1]; - publicInputs[6] = root; - publicInputs[7] = (nullifiers[0] == 0) ? 0 : 1; // if the first nullifier is empty, disable its MT proof verification - publicInputs[8] = (nullifiers[1] == 0) ? 0 : 1; // if the second nullifier is empty, disable its MT proof verification - publicInputs[9] = outputs[0]; - publicInputs[10] = outputs[1]; - publicInputs[11] = encryptionNonce; + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; // // Check the proof require( @@ -114,22 +138,16 @@ contract Zeto_AnonEncNullifier is // accept the transaction to consume the input UTXOs and produce new UTXOs processInputsAndOutputs(nullifiers, outputs); - uint256[] memory nullifierArray = new uint256[](nullifiers.length); - uint256[] memory outputArray = new uint256[](outputs.length); uint256[] memory encryptedValuesArray = new uint256[]( encryptedValues.length ); - for (uint256 i = 0; i < nullifiers.length; ++i) { - nullifierArray[i] = nullifiers[i]; - outputArray[i] = outputs[i]; - } for (uint256 i = 0; i < encryptedValues.length; ++i) { encryptedValuesArray[i] = encryptedValues[i]; } emit UTXOTransferWithEncryptedValues( - nullifierArray, - outputArray, + nullifiers, + outputs, encryptionNonce, encryptedValuesArray, msg.sender, @@ -152,14 +170,22 @@ contract Zeto_AnonEncNullifier is function withdraw( uint256 amount, - uint256[2] memory nullifiers, + uint256[] memory nullifiers, uint256 output, uint256 root, Commonlib.Proof calldata proof ) public { - validateTransactionProposal(nullifiers, [output, 0], root); + uint256[] memory outputs = new uint256[](nullifiers.length); + outputs[0] = output; + // Check and pad commitments + (nullifiers, outputs) = checkAndPadCommitments( + nullifiers, + outputs, + MAX_BATCH + ); + validateTransactionProposal(nullifiers, outputs, root); _withdrawWithNullifiers(amount, nullifiers, output, root, proof); - processInputsAndOutputs(nullifiers, [output, 0]); + processInputsAndOutputs(nullifiers, outputs); } function mint( diff --git a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol index 223ca29..8358811 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol @@ -26,6 +26,8 @@ import {Registry} from "./lib/registry.sol"; import {Commonlib} from "./lib/common.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +uint256 constant MAX_BATCH = 10; // batch not supported + /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking /// @author Kaleido, Inc. /// @dev The proof has the following statements: @@ -82,14 +84,23 @@ contract Zeto_AnonEncNullifierKyc is * Emits a {UTXOTransferWithEncryptedValues} event. */ function transfer( - uint256[2] memory nullifiers, - uint256[2] memory outputs, + uint256[] memory nullifiers, + uint256[] memory outputs, uint256 root, uint256 encryptionNonce, uint256[4] memory encryptedValues, Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { + // Check and pad commitments + (nullifiers, outputs) = checkAndPadCommitments( + nullifiers, + outputs, + MAX_BATCH + ); + if (outputs.length > 2) { + revert("batch not supported"); + } require( validateTransactionProposal(nullifiers, outputs, root), "Invalid transaction proposal" @@ -97,21 +108,35 @@ contract Zeto_AnonEncNullifierKyc is // construct the public inputs uint256[13] memory publicInputs; - publicInputs[0] = encryptedValues[0]; // encrypted value for the receiver UTXO - publicInputs[1] = encryptedValues[1]; // encrypted salt for the receiver UTXO - publicInputs[2] = encryptedValues[2]; // parity bit for the cipher text - publicInputs[3] = encryptedValues[3]; // parity bit for the cipher text - publicInputs[4] = nullifiers[0]; - publicInputs[5] = nullifiers[1]; - publicInputs[6] = root; - publicInputs[7] = (nullifiers[0] == 0) ? 0 : 1; // if the first nullifier is empty, disable its MT proof verification - publicInputs[8] = (nullifiers[1] == 0) ? 0 : 1; // if the second nullifier is empty, disable its MT proof verification - publicInputs[9] = getIdentitiesRoot(); - publicInputs[10] = outputs[0]; - publicInputs[11] = outputs[1]; - publicInputs[12] = encryptionNonce; - - // // Check the proof + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy identities root + publicInputs[piIndex++] = getIdentitiesRoot(); + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + + // Check the proof require( verifier.verifyProof(proof.pA, proof.pB, proof.pC, publicInputs), "Invalid proof" @@ -120,22 +145,16 @@ contract Zeto_AnonEncNullifierKyc is // accept the transaction to consume the input UTXOs and produce new UTXOs processInputsAndOutputs(nullifiers, outputs); - uint256[] memory nullifierArray = new uint256[](nullifiers.length); - uint256[] memory outputArray = new uint256[](outputs.length); uint256[] memory encryptedValuesArray = new uint256[]( encryptedValues.length ); - for (uint256 i = 0; i < nullifiers.length; ++i) { - nullifierArray[i] = nullifiers[i]; - outputArray[i] = outputs[i]; - } for (uint256 i = 0; i < encryptedValues.length; ++i) { encryptedValuesArray[i] = encryptedValues[i]; } emit UTXOTransferWithEncryptedValues( - nullifierArray, - outputArray, + nullifiers, + outputs, encryptionNonce, encryptedValuesArray, msg.sender, @@ -163,14 +182,22 @@ contract Zeto_AnonEncNullifierKyc is function withdraw( uint256 amount, - uint256[2] memory nullifiers, + uint256[] memory nullifiers, uint256 output, uint256 root, Commonlib.Proof calldata proof ) public { - validateTransactionProposal(nullifiers, [output, 0], root); + uint256[] memory outputs = new uint256[](nullifiers.length); + outputs[0] = output; + // Check and pad commitments + (nullifiers, outputs) = checkAndPadCommitments( + nullifiers, + outputs, + MAX_BATCH + ); + validateTransactionProposal(nullifiers, outputs, root); _withdrawWithNullifiers(amount, nullifiers, output, root, proof); - processInputsAndOutputs(nullifiers, [output, 0]); + processInputsAndOutputs(nullifiers, outputs); } function mint( diff --git a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol index 4ea2d77..aa7f46d 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol @@ -25,6 +25,8 @@ import {ZetoFungibleWithdrawWithNullifiers} from "./lib/zeto_fungible_withdraw_n import {Registry} from "./lib/registry.sol"; import {Commonlib} from "./lib/common.sol"; +uint256 constant MAX_BATCH = 10; // batch not supported + /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking /// @author Kaleido, Inc. /// @dev The proof has the following statements: @@ -99,8 +101,8 @@ contract Zeto_AnonEncNullifierNonRepudiation is * Emits a {UTXOTransferNonRepudiation} event. */ function transfer( - uint256[2] memory nullifiers, - uint256[2] memory outputs, + uint256[] memory nullifiers, + uint256[] memory outputs, uint256 root, uint256 encryptionNonce, uint256[4] memory encryptedValuesForReceiver, @@ -108,6 +110,15 @@ contract Zeto_AnonEncNullifierNonRepudiation is Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { + // Check and pad commitments + (nullifiers, outputs) = checkAndPadCommitments( + nullifiers, + outputs, + MAX_BATCH + ); + if (outputs.length > 2) { + revert("batch not supported"); + } require( validateTransactionProposal(nullifiers, outputs, root), "Invalid transaction proposal" @@ -115,36 +126,39 @@ contract Zeto_AnonEncNullifierNonRepudiation is // construct the public inputs uint256[30] memory publicInputs; - publicInputs[0] = encryptedValuesForReceiver[0]; // encrypted value for the receiver UTXO - publicInputs[1] = encryptedValuesForReceiver[1]; // encrypted salt for the receiver UTXO - publicInputs[2] = encryptedValuesForReceiver[2]; // parity bit for the cipher text - publicInputs[3] = encryptedValuesForReceiver[3]; // parity bit for the cipher text - publicInputs[4] = encryptedValuesForAuthority[0]; // encrypted input owner public key[0] - publicInputs[5] = encryptedValuesForAuthority[1]; // encrypted input owner public key[1] - publicInputs[6] = encryptedValuesForAuthority[2]; // encrypted input value[0] - publicInputs[7] = encryptedValuesForAuthority[3]; // encrypted input salt[0] - publicInputs[8] = encryptedValuesForAuthority[4]; // encrypted input value[1] - publicInputs[9] = encryptedValuesForAuthority[5]; // encrypted input salt[1] - publicInputs[10] = encryptedValuesForAuthority[6]; // encrypted first output owner public key[0] - publicInputs[11] = encryptedValuesForAuthority[7]; // encrypted first output owner public key[1] - publicInputs[12] = encryptedValuesForAuthority[8]; // encrypted second output owner public key[0] - publicInputs[13] = encryptedValuesForAuthority[9]; // encrypted second output owner public key[1] - publicInputs[14] = encryptedValuesForAuthority[10]; // encrypted output value[0] - publicInputs[15] = encryptedValuesForAuthority[11]; // encrypted output salt[0] - publicInputs[16] = encryptedValuesForAuthority[12]; // encrypted output value[1] - publicInputs[17] = encryptedValuesForAuthority[13]; // encrypted output salt[1] - publicInputs[18] = encryptedValuesForAuthority[14]; // parity bit for the cipher text - publicInputs[19] = encryptedValuesForAuthority[15]; // parity bit for the cipher text - publicInputs[20] = nullifiers[0]; - publicInputs[21] = nullifiers[1]; - publicInputs[22] = root; - publicInputs[23] = (nullifiers[0] == 0) ? 0 : 1; // if the first nullifier is empty, disable its MT proof verification - publicInputs[24] = (nullifiers[1] == 0) ? 0 : 1; // if the second nullifier is empty, disable its MT proof verification - publicInputs[25] = outputs[0]; - publicInputs[26] = outputs[1]; - publicInputs[27] = encryptionNonce; - publicInputs[28] = arbiter[0]; - publicInputs[29] = arbiter[1]; + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit for receiver + for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { + publicInputs[piIndex++] = encryptedValuesForReceiver[i]; + } + // copy the encrypted value, salt and parity bit for authority + for (uint256 i = 0; i < encryptedValuesForAuthority.length; ++i) { + publicInputs[piIndex++] = encryptedValuesForAuthority[i]; + } + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + + // copy arbiter pub key + publicInputs[piIndex++] = arbiter[0]; + publicInputs[piIndex++] = arbiter[1]; // // Check the proof require( @@ -155,18 +169,12 @@ contract Zeto_AnonEncNullifierNonRepudiation is // accept the transaction to consume the input UTXOs and produce new UTXOs processInputsAndOutputs(nullifiers, outputs); - uint256[] memory nullifierArray = new uint256[](nullifiers.length); - uint256[] memory outputArray = new uint256[](outputs.length); uint256[] memory encryptedValuesReceiverArray = new uint256[]( encryptedValuesForReceiver.length ); uint256[] memory encryptedValuesAuthorityArray = new uint256[]( encryptedValuesForAuthority.length ); - for (uint256 i = 0; i < nullifiers.length; ++i) { - nullifierArray[i] = nullifiers[i]; - outputArray[i] = outputs[i]; - } for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { encryptedValuesReceiverArray[i] = encryptedValuesForReceiver[i]; } @@ -175,8 +183,8 @@ contract Zeto_AnonEncNullifierNonRepudiation is } emit UTXOTransferNonRepudiation( - nullifierArray, - outputArray, + nullifiers, + outputs, encryptionNonce, encryptedValuesReceiverArray, encryptedValuesAuthorityArray, @@ -200,14 +208,22 @@ contract Zeto_AnonEncNullifierNonRepudiation is function withdraw( uint256 amount, - uint256[2] memory nullifiers, + uint256[] memory nullifiers, uint256 output, uint256 root, Commonlib.Proof calldata proof ) public { - validateTransactionProposal(nullifiers, [output, 0], root); + uint256[] memory outputs = new uint256[](nullifiers.length); + outputs[0] = output; + // Check and pad commitments + (nullifiers, outputs) = checkAndPadCommitments( + nullifiers, + outputs, + MAX_BATCH + ); + validateTransactionProposal(nullifiers, outputs, root); _withdrawWithNullifiers(amount, nullifiers, output, root, proof); - processInputsAndOutputs(nullifiers, [output, 0]); + processInputsAndOutputs(nullifiers, outputs); } function mint( diff --git a/solidity/contracts/zeto_anon_nullifier.sol b/solidity/contracts/zeto_anon_nullifier.sol index a7875e8..7235e4c 100644 --- a/solidity/contracts/zeto_anon_nullifier.sol +++ b/solidity/contracts/zeto_anon_nullifier.sol @@ -30,6 +30,7 @@ import {SmtLib} from "@iden3/contracts/lib/SmtLib.sol"; import {PoseidonUnit3L} from "@iden3/contracts/lib/Poseidon.sol"; uint256 constant MAX_SMT_DEPTH = 64; +uint256 constant MAX_BATCH = 10; /// @title A sample implementation of a Zeto based fungible token with anonymity and history masking /// @author Kaleido, Inc. @@ -78,32 +79,84 @@ contract Zeto_AnonNullifier is * Emits a {UTXOTransfer} event. */ function transfer( - uint256[2] memory nullifiers, - uint256[2] memory outputs, + uint256[] memory nullifiers, + uint256[] memory outputs, uint256 root, Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { + // Check and pad inputs and outputs based on the max size + (nullifiers, outputs) = checkAndPadCommitments( + nullifiers, + outputs, + MAX_BATCH + ); + require( validateTransactionProposal(nullifiers, outputs, root), "Invalid transaction proposal" ); - // construct the public inputs - uint256[7] memory publicInputs; - publicInputs[0] = nullifiers[0]; - publicInputs[1] = nullifiers[1]; - publicInputs[2] = root; - publicInputs[3] = (nullifiers[0] == 0) ? 0 : 1; // if the first nullifier is empty, disable its MT proof verification - publicInputs[4] = (nullifiers[1] == 0) ? 0 : 1; // if the second nullifier is empty, disable its MT proof verification - publicInputs[5] = outputs[0]; - publicInputs[6] = outputs[1]; - - // // Check the proof - require( - verifier.verifyProof(proof.pA, proof.pB, proof.pC, publicInputs), - "Invalid proof" - ); + if (nullifiers.length > 2) { + // construct the public nullifiers + uint256[31] memory publicInputs; + uint256 piIndex = 0; + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + require( + batchVerifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); + } else { + // construct the public nullifiers + uint256[7] memory publicInputs; + uint256 piIndex = 0; + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + require( + verifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); + } processInputsAndOutputs(nullifiers, outputs); @@ -131,14 +184,22 @@ contract Zeto_AnonNullifier is function withdraw( uint256 amount, - uint256[2] memory nullifiers, + uint256[] memory nullifiers, uint256 output, uint256 root, Commonlib.Proof calldata proof ) public { - validateTransactionProposal(nullifiers, [output, 0], root); + uint256[] memory outputs = new uint256[](nullifiers.length); + outputs[0] = output; + // Check and pad inputs and outputs based on the max size + (nullifiers, outputs) = checkAndPadCommitments( + nullifiers, + outputs, + MAX_BATCH + ); + validateTransactionProposal(nullifiers, outputs, root); _withdrawWithNullifiers(amount, nullifiers, output, root, proof); - processInputsAndOutputs(nullifiers, [output, 0]); + processInputsAndOutputs(nullifiers, outputs); } function mint( diff --git a/solidity/contracts/zeto_anon_nullifier_kyc.sol b/solidity/contracts/zeto_anon_nullifier_kyc.sol index 702e6b6..85c4844 100644 --- a/solidity/contracts/zeto_anon_nullifier_kyc.sol +++ b/solidity/contracts/zeto_anon_nullifier_kyc.sol @@ -30,6 +30,7 @@ import {SmtLib} from "@iden3/contracts/lib/SmtLib.sol"; import {PoseidonUnit3L} from "@iden3/contracts/lib/Poseidon.sol"; uint256 constant MAX_SMT_DEPTH = 64; +uint256 constant MAX_BATCH = 10; /// @title A sample implementation of a Zeto based fungible token with anonymity and history masking /// @author Kaleido, Inc. @@ -84,33 +85,89 @@ contract Zeto_AnonNullifierKyc is * Emits a {UTXOTransfer} event. */ function transfer( - uint256[2] memory nullifiers, - uint256[2] memory outputs, + uint256[] memory nullifiers, + uint256[] memory outputs, uint256 root, Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { + // Check and pad inputs and outputs based on the max size + (nullifiers, outputs) = checkAndPadCommitments( + nullifiers, + outputs, + MAX_BATCH + ); + require( validateTransactionProposal(nullifiers, outputs, root), "Invalid transaction proposal" ); - // construct the public inputs - uint256[8] memory publicInputs; - publicInputs[0] = nullifiers[0]; - publicInputs[1] = nullifiers[1]; - publicInputs[2] = root; - publicInputs[3] = (nullifiers[0] == 0) ? 0 : 1; // if the first nullifier is empty, disable its MT proof verification - publicInputs[4] = (nullifiers[1] == 0) ? 0 : 1; // if the second nullifier is empty, disable its MT proof verification - publicInputs[5] = getIdentitiesRoot(); - publicInputs[6] = outputs[0]; - publicInputs[7] = outputs[1]; - - // // Check the proof - require( - verifier.verifyProof(proof.pA, proof.pB, proof.pC, publicInputs), - "Invalid proof" - ); + if (nullifiers.length > 2) { + // construct the public inputs + uint256[32] memory publicInputs; + uint256 piIndex = 0; + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy identities root + publicInputs[piIndex++] = getIdentitiesRoot(); + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + require( + batchVerifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); + } else { + // construct the public inputs + uint256[8] memory publicInputs; + uint256 piIndex = 0; + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy identities root + publicInputs[piIndex++] = getIdentitiesRoot(); + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + require( + verifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); + } processInputsAndOutputs(nullifiers, outputs); @@ -138,14 +195,22 @@ contract Zeto_AnonNullifierKyc is function withdraw( uint256 amount, - uint256[2] memory nullifiers, + uint256[] memory nullifiers, uint256 output, uint256 root, Commonlib.Proof calldata proof ) public { - validateTransactionProposal(nullifiers, [output, 0], root); + uint256[] memory outputs = new uint256[](nullifiers.length); + outputs[0] = output; + // Check and pad inputs and outputs based on the max size + (nullifiers, outputs) = checkAndPadCommitments( + nullifiers, + outputs, + MAX_BATCH + ); + validateTransactionProposal(nullifiers, outputs, root); _withdrawWithNullifiers(amount, nullifiers, output, root, proof); - processInputsAndOutputs(nullifiers, [output, 0]); + processInputsAndOutputs(nullifiers, outputs); } function mint( diff --git a/solidity/contracts/zeto_nf_anon.sol b/solidity/contracts/zeto_nf_anon.sol index 7424a28..864f239 100644 --- a/solidity/contracts/zeto_nf_anon.sol +++ b/solidity/contracts/zeto_nf_anon.sol @@ -58,8 +58,12 @@ contract Zeto_NfAnon is IZeto, ZetoBase, UUPSUpgradeable { Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { + uint256[] memory inputs = new uint256[](1); + inputs[0] = input; + uint256[] memory outputs = new uint256[](1); + outputs[0] = output; require( - validateTransactionProposal([input, 0], [output, 0], proof), + validateTransactionProposal(inputs, outputs, proof), "Invalid transaction proposal" ); @@ -77,12 +81,7 @@ contract Zeto_NfAnon is IZeto, ZetoBase, UUPSUpgradeable { _utxos[input] = UTXOStatus.SPENT; _utxos[output] = UTXOStatus.UNSPENT; - uint256[] memory inputArray = new uint256[](1); - uint256[] memory outputArray = new uint256[](1); - inputArray[0] = input; - outputArray[0] = output; - - emit UTXOTransfer(inputArray, outputArray, msg.sender, data); + emit UTXOTransfer(inputs, outputs, msg.sender, data); return true; } diff --git a/solidity/contracts/zeto_nf_anon_nullifier.sol b/solidity/contracts/zeto_nf_anon_nullifier.sol index 2a758dd..5147c24 100644 --- a/solidity/contracts/zeto_nf_anon_nullifier.sol +++ b/solidity/contracts/zeto_nf_anon_nullifier.sol @@ -66,8 +66,12 @@ contract Zeto_NfAnonNullifier is IZeto, ZetoNullifier, UUPSUpgradeable { Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { + uint256[] memory nullifiers = new uint256[](1); + nullifiers[0] = nullifier; + uint256[] memory outputs = new uint256[](1); + outputs[0] = output; require( - validateTransactionProposal([nullifier, 0], [output, 0], root), + validateTransactionProposal(nullifiers, outputs, root), "Invalid transaction proposal" ); @@ -83,14 +87,9 @@ contract Zeto_NfAnonNullifier is IZeto, ZetoNullifier, UUPSUpgradeable { "Invalid proof" ); - processInputsAndOutputs([nullifier, 0], [output, 0]); + processInputsAndOutputs(nullifiers, outputs); - uint256[] memory nullifierArray = new uint256[](1); - uint256[] memory outputArray = new uint256[](1); - nullifierArray[0] = nullifier; - outputArray[0] = output; - - emit UTXOTransfer(nullifierArray, outputArray, msg.sender, data); + emit UTXOTransfer(nullifiers, outputs, msg.sender, data); return true; } diff --git a/solidity/contracts/zkDvP.sol b/solidity/contracts/zkDvP.sol index a36d2f9..a59038e 100644 --- a/solidity/contracts/zkDvP.sol +++ b/solidity/contracts/zkDvP.sol @@ -216,13 +216,14 @@ contract zkDvP { if ( !isEmptyProof(trade.paymentProof) && !isEmptyProof(trade.assetProof) ) { + uint256[] memory pIns = new uint256[](2); + pIns[0] = trade.paymentInputs[0]; + pIns[1] = trade.paymentInputs[1]; + uint256[] memory pOuts = new uint256[](2); + pOuts[0] = trade.paymentOutputs[0]; + pOuts[1] = trade.paymentOutputs[1]; require( - paymentToken.transfer( - trade.paymentInputs, - trade.paymentOutputs, - trade.paymentProof, - "" - ), + paymentToken.transfer(pIns, pOuts, trade.paymentProof, ""), "Payment branch of the trade failed" ); require( diff --git a/solidity/ignition/modules/zeto_anon.ts b/solidity/ignition/modules/zeto_anon.ts index 4e97444..94e7702 100644 --- a/solidity/ignition/modules/zeto_anon.ts +++ b/solidity/ignition/modules/zeto_anon.ts @@ -14,18 +14,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { DepositVerifierModule, WithdrawVerifierModule } from "./lib/deps"; +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { DepositVerifierModule, WithdrawVerifierModule } from './lib/deps'; -const VerifierModule = buildModule("Groth16Verifier_Anon", (m) => { +const VerifierModule = buildModule('Groth16Verifier_Anon', (m) => { const verifier = m.contract('Groth16Verifier_Anon', []); return { verifier }; }); -export default buildModule("Zeto_Anon", (m) => { +const BatchVerifierModule = buildModule('Groth16Verifier_AnonBatch', (m) => { + const batchVerifier = m.contract('Groth16Verifier_AnonBatch', []); + return { batchVerifier }; +}); + +export default buildModule('Zeto_Anon', (m) => { const { verifier } = m.useModule(VerifierModule); + const { batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule(WithdrawVerifierModule); - return { depositVerifier, withdrawVerifier, verifier }; + return { depositVerifier, withdrawVerifier, verifier, batchVerifier }; }); diff --git a/solidity/ignition/modules/zeto_anon_enc.ts b/solidity/ignition/modules/zeto_anon_enc.ts index ef63b12..350ad0a 100644 --- a/solidity/ignition/modules/zeto_anon_enc.ts +++ b/solidity/ignition/modules/zeto_anon_enc.ts @@ -14,18 +14,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { DepositVerifierModule, WithdrawVerifierModule } from "./lib/deps"; +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { DepositVerifierModule, WithdrawVerifierModule } from './lib/deps'; -const VerifierModule = buildModule("Groth16Verifier_AnonEnc", (m) => { +const VerifierModule = buildModule('Groth16Verifier_AnonEnc', (m) => { const verifier = m.contract('Groth16Verifier_AnonEnc', []); return { verifier }; }); -export default buildModule("Zeto_AnonEnc", (m) => { +const BatchVerifierModule = buildModule('Groth16Verifier_AnonEncBatch', (m) => { + const batchVerifier = m.contract('Groth16Verifier_AnonEncBatch', []); + return { batchVerifier }; +}); + +export default buildModule('Zeto_AnonEnc', (m) => { const { verifier } = m.useModule(VerifierModule); + const { batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule(WithdrawVerifierModule); - - return { depositVerifier, withdrawVerifier, verifier }; -}); \ No newline at end of file + return { depositVerifier, withdrawVerifier, verifier, batchVerifier }; +}); diff --git a/solidity/ignition/modules/zeto_anon_enc_nullifier.ts b/solidity/ignition/modules/zeto_anon_enc_nullifier.ts index 89ed5db..8bcca3e 100644 --- a/solidity/ignition/modules/zeto_anon_enc_nullifier.ts +++ b/solidity/ignition/modules/zeto_anon_enc_nullifier.ts @@ -14,19 +14,44 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { SmtLibModule, DepositVerifierModule, WithdrawNullifierVerifierModule } from "./lib/deps"; +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { + SmtLibModule, + DepositVerifierModule, + WithdrawNullifierVerifierModule, +} from './lib/deps'; -const VerifierModule = buildModule("Groth16Verifier_AnonEncNullifier", (m) => { +const VerifierModule = buildModule('Groth16Verifier_AnonEncNullifier', (m) => { const verifier = m.contract('Groth16Verifier_AnonEncNullifier', []); return { verifier }; }); -export default buildModule("Zeto_AnonEncNullifier", (m) => { +const BatchVerifierModule = buildModule( + 'Groth16Verifier_AnonEncNullifierBatch', + (m) => { + const batchVerifier = m.contract( + 'Groth16Verifier_AnonEncNullifierBatch', + [] + ); + return { batchVerifier }; + } +); + +export default buildModule('Zeto_AnonEncNullifier', (m) => { const { smtLib, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); + const { batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); - const { verifier: withdrawVerifier } = m.useModule(WithdrawNullifierVerifierModule); + const { verifier: withdrawVerifier } = m.useModule( + WithdrawNullifierVerifierModule + ); - return { depositVerifier, withdrawVerifier, verifier, smtLib, poseidon3 }; + return { + depositVerifier, + withdrawVerifier, + verifier, + batchVerifier, + smtLib, + poseidon3, + }; }); diff --git a/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts b/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts index 1dc86b6..f244fe9 100644 --- a/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +++ b/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts @@ -29,9 +29,21 @@ const VerifierModule = buildModule( } ); +const BatchVerifierModule = buildModule( + 'Groth16Verifier_AnonEncNullifierKycBatch', + (m) => { + const batchVerifier = m.contract( + 'Groth16Verifier_AnonEncNullifierKycBatch', + [] + ); + return { batchVerifier }; + } +); + export default buildModule('Zeto_AnonEncNullifierKyc', (m) => { const { smtLib, poseidon2, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); + const { batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule( WithdrawNullifierVerifierModule @@ -41,6 +53,7 @@ export default buildModule('Zeto_AnonEncNullifierKyc', (m) => { depositVerifier, withdrawVerifier, verifier, + batchVerifier, smtLib, poseidon2, poseidon3, diff --git a/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts b/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts index 3346e58..bcac005 100644 --- a/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts +++ b/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts @@ -14,19 +14,50 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { SmtLibModule, DepositVerifierModule, WithdrawNullifierVerifierModule } from "./lib/deps"; +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { + SmtLibModule, + DepositVerifierModule, + WithdrawNullifierVerifierModule, +} from './lib/deps'; -const VerifierModule = buildModule("Groth16Verifier_AnonEncNullifierNonRepudiation", (m) => { - const verifier = m.contract('Groth16Verifier_AnonEncNullifierNonRepudiation', []); - return { verifier }; -}); +const VerifierModule = buildModule( + 'Groth16Verifier_AnonEncNullifierNonRepudiation', + (m) => { + const verifier = m.contract( + 'Groth16Verifier_AnonEncNullifierNonRepudiation', + [] + ); + return { verifier }; + } +); + +const BatchVerifierModule = buildModule( + 'Groth16Verifier_AnonEncNullifierNonRepudiationBatch', + (m) => { + const batchVerifier = m.contract( + 'Groth16Verifier_AnonEncNullifierNonRepudiationBatch', + [] + ); + return { batchVerifier }; + } +); -export default buildModule("Zeto_AnonEncNullifierNonRepudiation", (m) => { +export default buildModule('Zeto_AnonEncNullifierNonRepudiation', (m) => { const { smtLib, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); + const { batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); - const { verifier: withdrawVerifier } = m.useModule(WithdrawNullifierVerifierModule); + const { verifier: withdrawVerifier } = m.useModule( + WithdrawNullifierVerifierModule + ); - return { depositVerifier, withdrawVerifier, verifier, smtLib, poseidon3 }; + return { + depositVerifier, + withdrawVerifier, + verifier, + batchVerifier, + smtLib, + poseidon3, + }; }); diff --git a/solidity/ignition/modules/zeto_anon_nullifier.ts b/solidity/ignition/modules/zeto_anon_nullifier.ts index 780d9b4..8c08f1e 100644 --- a/solidity/ignition/modules/zeto_anon_nullifier.ts +++ b/solidity/ignition/modules/zeto_anon_nullifier.ts @@ -14,19 +14,41 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { SmtLibModule, DepositVerifierModule, WithdrawNullifierVerifierModule } from "./lib/deps"; +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { + SmtLibModule, + DepositVerifierModule, + WithdrawNullifierVerifierModule, +} from './lib/deps'; -const VerifierModule = buildModule("Groth16Verifier_AnonNullifier", (m) => { +const VerifierModule = buildModule('Groth16Verifier_AnonNullifier', (m) => { const verifier = m.contract('Groth16Verifier_AnonNullifier', []); return { verifier }; }); -export default buildModule("Zeto_AnonNullifier", (m) => { +const BatchVerifierModule = buildModule( + 'Groth16Verifier_AnonNullifierBatch', + (m) => { + const batchVerifier = m.contract('Groth16Verifier_AnonNullifierBatch', []); + return { batchVerifier }; + } +); + +export default buildModule('Zeto_AnonNullifier', (m) => { const { smtLib, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); + const { batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); - const { verifier: withdrawVerifier } = m.useModule(WithdrawNullifierVerifierModule); + const { verifier: withdrawVerifier } = m.useModule( + WithdrawNullifierVerifierModule + ); - return { depositVerifier, withdrawVerifier, verifier, smtLib, poseidon3 }; + return { + depositVerifier, + withdrawVerifier, + verifier, + batchVerifier, + smtLib, + poseidon3, + }; }); diff --git a/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts b/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts index 3c44a80..1480714 100644 --- a/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts +++ b/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts @@ -14,19 +14,45 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { SmtLibModule, DepositVerifierModule, WithdrawNullifierVerifierModule } from "./lib/deps"; +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { + SmtLibModule, + DepositVerifierModule, + WithdrawNullifierVerifierModule, +} from './lib/deps'; -const VerifierModule = buildModule("Groth16Verifier_AnonNullifierKyc", (m) => { +const VerifierModule = buildModule('Groth16Verifier_AnonNullifierKyc', (m) => { const verifier = m.contract('Groth16Verifier_AnonNullifierKyc', []); return { verifier }; }); -export default buildModule("Zeto_AnonNullifierKyc", (m) => { +const BatchVerifierModule = buildModule( + 'Groth16Verifier_AnonNullifierKycBatch', + (m) => { + const batchVerifier = m.contract( + 'Groth16Verifier_AnonNullifierKycBatch', + [] + ); + return { batchVerifier }; + } +); + +export default buildModule('Zeto_AnonNullifierKyc', (m) => { const { smtLib, poseidon2, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); + const { batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); - const { verifier: withdrawVerifier } = m.useModule(WithdrawNullifierVerifierModule); + const { verifier: withdrawVerifier } = m.useModule( + WithdrawNullifierVerifierModule + ); - return { depositVerifier, withdrawVerifier, verifier, smtLib, poseidon2, poseidon3 }; + return { + depositVerifier, + withdrawVerifier, + verifier, + batchVerifier, + smtLib, + poseidon2, + poseidon3, + }; }); diff --git a/solidity/scripts/tokens/Zeto_Anon.ts b/solidity/scripts/tokens/Zeto_Anon.ts index 7320553..979e65a 100644 --- a/solidity/scripts/tokens/Zeto_Anon.ts +++ b/solidity/scripts/tokens/Zeto_Anon.ts @@ -14,20 +14,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from "hardhat"; +import { ethers, ignition } from 'hardhat'; import zetoModule from '../../ignition/modules/zeto_anon'; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); - const { depositVerifier, withdrawVerifier, verifier } = await ignition.deploy(zetoModule); + const { depositVerifier, withdrawVerifier, verifier, batchVerifier } = + await ignition.deploy(zetoModule); return { deployer, args: [ await deployer.getAddress(), verifier.target, depositVerifier.target, - withdrawVerifier.target - ] + withdrawVerifier.target, + batchVerifier.target, + ], }; -} \ No newline at end of file +} diff --git a/solidity/scripts/tokens/Zeto_AnonEnc.ts b/solidity/scripts/tokens/Zeto_AnonEnc.ts index 929a61b..1aafa6a 100644 --- a/solidity/scripts/tokens/Zeto_AnonEnc.ts +++ b/solidity/scripts/tokens/Zeto_AnonEnc.ts @@ -14,20 +14,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from "hardhat"; +import { ethers, ignition } from 'hardhat'; import zetoModule from '../../ignition/modules/zeto_anon_enc'; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); - const { depositVerifier, withdrawVerifier, verifier } = await ignition.deploy(zetoModule); + const { depositVerifier, withdrawVerifier, verifier, batchVerifier } = + await ignition.deploy(zetoModule); return { deployer, args: [ await deployer.getAddress(), verifier.target, depositVerifier.target, - withdrawVerifier.target - ] + withdrawVerifier.target, + batchVerifier.target, + ], }; -} \ No newline at end of file +} diff --git a/solidity/scripts/tokens/Zeto_AnonEncNullifier.ts b/solidity/scripts/tokens/Zeto_AnonEncNullifier.ts index 8ea1f6e..debf433 100644 --- a/solidity/scripts/tokens/Zeto_AnonEncNullifier.ts +++ b/solidity/scripts/tokens/Zeto_AnonEncNullifier.ts @@ -14,24 +14,32 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from "hardhat"; +import { ethers, ignition } from 'hardhat'; import zetoModule from '../../ignition/modules/zeto_anon_enc_nullifier'; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); - const { depositVerifier, withdrawVerifier, verifier, smtLib, poseidon3 } = await ignition.deploy(zetoModule); + const { + depositVerifier, + withdrawVerifier, + verifier, + batchVerifier, + smtLib, + poseidon3, + } = await ignition.deploy(zetoModule); return { deployer, args: [ await deployer.getAddress(), verifier.target, depositVerifier.target, - withdrawVerifier.target + withdrawVerifier.target, + batchVerifier.target, ], libraries: { SmtLib: smtLib.target, - PoseidonUnit3L: poseidon3.target - } + PoseidonUnit3L: poseidon3.target, + }, }; -} \ No newline at end of file +} diff --git a/solidity/scripts/tokens/Zeto_AnonEncNullifierKyc.ts b/solidity/scripts/tokens/Zeto_AnonEncNullifierKyc.ts index 3942746..1b69784 100644 --- a/solidity/scripts/tokens/Zeto_AnonEncNullifierKyc.ts +++ b/solidity/scripts/tokens/Zeto_AnonEncNullifierKyc.ts @@ -24,6 +24,7 @@ export async function deployDependencies() { depositVerifier, withdrawVerifier, verifier, + batchVerifier, smtLib, poseidon2, poseidon3, @@ -35,6 +36,7 @@ export async function deployDependencies() { verifier.target, depositVerifier.target, withdrawVerifier.target, + batchVerifier.target, ], libraries: { SmtLib: smtLib.target, diff --git a/solidity/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts b/solidity/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts index d07be02..9106dfa 100644 --- a/solidity/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts +++ b/solidity/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts @@ -14,24 +14,32 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from "hardhat"; +import { ethers, ignition } from 'hardhat'; import zetoModule from '../../ignition/modules/zeto_anon_enc_nullifier_non_repudiation'; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); - const { depositVerifier, withdrawVerifier, verifier, smtLib, poseidon3 } = await ignition.deploy(zetoModule); + const { + depositVerifier, + withdrawVerifier, + verifier, + batchVerifier, + smtLib, + poseidon3, + } = await ignition.deploy(zetoModule); return { deployer, args: [ await deployer.getAddress(), verifier.target, depositVerifier.target, - withdrawVerifier.target + withdrawVerifier.target, + batchVerifier.target, ], libraries: { SmtLib: smtLib.target, - PoseidonUnit3L: poseidon3.target - } + PoseidonUnit3L: poseidon3.target, + }, }; -} \ No newline at end of file +} diff --git a/solidity/scripts/tokens/Zeto_AnonNullifier.ts b/solidity/scripts/tokens/Zeto_AnonNullifier.ts index 2535f84..c439864 100644 --- a/solidity/scripts/tokens/Zeto_AnonNullifier.ts +++ b/solidity/scripts/tokens/Zeto_AnonNullifier.ts @@ -14,24 +14,32 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from "hardhat"; +import { ethers, ignition } from 'hardhat'; import zetoModule from '../../ignition/modules/zeto_anon_nullifier'; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); - const { depositVerifier, withdrawVerifier, verifier, smtLib, poseidon3 } = await ignition.deploy(zetoModule); + const { + depositVerifier, + withdrawVerifier, + verifier, + batchVerifier, + smtLib, + poseidon3, + } = await ignition.deploy(zetoModule); return { deployer, args: [ await deployer.getAddress(), verifier.target, depositVerifier.target, - withdrawVerifier.target + withdrawVerifier.target, + batchVerifier.target, ], libraries: { SmtLib: smtLib.target, - PoseidonUnit3L: poseidon3.target - } + PoseidonUnit3L: poseidon3.target, + }, }; -} \ No newline at end of file +} diff --git a/solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts b/solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts index 6b7e06b..b133950 100644 --- a/solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts +++ b/solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts @@ -14,25 +14,34 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from "hardhat"; +import { ethers, ignition } from 'hardhat'; import zetoModule from '../../ignition/modules/zeto_anon_nullifier_kyc'; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); - const { depositVerifier, withdrawVerifier, verifier, smtLib, poseidon2, poseidon3 } = await ignition.deploy(zetoModule); + const { + depositVerifier, + withdrawVerifier, + verifier, + batchVerifier, + smtLib, + poseidon2, + poseidon3, + } = await ignition.deploy(zetoModule); return { deployer, args: [ await deployer.getAddress(), verifier.target, depositVerifier.target, - withdrawVerifier.target + withdrawVerifier.target, + batchVerifier.target, ], libraries: { SmtLib: smtLib.target, PoseidonUnit2L: poseidon2.target, - PoseidonUnit3L: poseidon3.target - } + PoseidonUnit3L: poseidon3.target, + }, }; -} \ No newline at end of file +} diff --git a/solidity/test/factory.ts b/solidity/test/factory.ts index 6f14d30..b538712 100644 --- a/solidity/test/factory.ts +++ b/solidity/test/factory.ts @@ -18,7 +18,7 @@ import { ethers, network } from 'hardhat'; import { Signer } from 'ethers'; import { expect } from 'chai'; -describe("Zeto based fungible token with anonymity without encryption or nullifier", function () { +describe('Zeto based fungible token with anonymity without encryption or nullifier', function () { let deployer: Signer; let nonOwner: Signer; @@ -30,122 +30,180 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi [deployer, nonOwner] = await ethers.getSigners(); }); - it("attempting to register an implementation as a non-owner should fail", async function () { - const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + it('attempting to register an implementation as a non-owner should fail', async function () { + const Factory = await ethers.getContractFactory('ZetoTokenFactory'); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - withdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + verifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + batchVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + depositVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + withdrawVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', }; - await expect(factory.connect(nonOwner).registerImplementation("test", implInfo as any)).rejectedWith(`reverted with custom error 'OwnableUnauthorizedAccount(`); + await expect( + factory.connect(nonOwner).registerImplementation('test', implInfo as any) + ).rejectedWith(`reverted with custom error 'OwnableUnauthorizedAccount(`); }); - it("attempting to register an implementation without the required implementation value should fail", async function () { + it('attempting to register an implementation without the required implementation value should fail', async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const Factory = await ethers.getContractFactory('ZetoTokenFactory'); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: "0x0000000000000000000000000000000000000000", - verifier: "0x0000000000000000000000000000000000000000", - depositVerifier: "0x0000000000000000000000000000000000000000", - withdrawVerifier: "0x0000000000000000000000000000000000000000", + implementation: '0x0000000000000000000000000000000000000000', + verifier: '0x0000000000000000000000000000000000000000', + batchVerifier: '0x0000000000000000000000000000000000000000', + depositVerifier: '0x0000000000000000000000000000000000000000', + withdrawVerifier: '0x0000000000000000000000000000000000000000', }; - await expect(factory.connect(deployer).registerImplementation("test", implInfo as any)).rejectedWith("Factory: implementation address is required"); + await expect( + factory.connect(deployer).registerImplementation('test', implInfo as any) + ).rejectedWith('Factory: implementation address is required'); }); - it("attempting to register an implementation without the required verifier value should fail", async function () { + it('attempting to register an implementation without the required verifier value should fail', async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const Factory = await ethers.getContractFactory('ZetoTokenFactory'); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - verifier: "0x0000000000000000000000000000000000000000", - depositVerifier: "0x0000000000000000000000000000000000000000", - withdrawVerifier: "0x0000000000000000000000000000000000000000", + implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + verifier: '0x0000000000000000000000000000000000000000', + batchVerifier: '0x0000000000000000000000000000000000000000', + depositVerifier: '0x0000000000000000000000000000000000000000', + withdrawVerifier: '0x0000000000000000000000000000000000000000', }; - await expect(factory.connect(deployer).registerImplementation("test", implInfo as any)).rejectedWith("Factory: verifier address is required"); + await expect( + factory.connect(deployer).registerImplementation('test', implInfo as any) + ).rejectedWith('Factory: verifier address is required'); }); - it("attempting to register an implementation with the required values should succeed", async function () { + it('attempting to register an implementation with the required values should succeed', async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const Factory = await ethers.getContractFactory('ZetoTokenFactory'); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - depositVerifier: "0x0000000000000000000000000000000000000000", - withdrawVerifier: "0x0000000000000000000000000000000000000000", + implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + verifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + batchVerifier: '0x0000000000000000000000000000000000000000', + depositVerifier: '0x0000000000000000000000000000000000000000', + withdrawVerifier: '0x0000000000000000000000000000000000000000', }; - await expect(factory.connect(deployer).registerImplementation("test", implInfo as any)).fulfilled; + await expect( + factory.connect(deployer).registerImplementation('test', implInfo as any) + ).fulfilled; }); - it("attempting to deploy a fungible token but with a registered implementation that misses required depositVerifier should fail", async function () { + it('attempting to deploy a fungible token but with a registered implementation that misses required batchVerifier should fail', async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const Factory = await ethers.getContractFactory('ZetoTokenFactory'); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - depositVerifier: "0x0000000000000000000000000000000000000000", - withdrawVerifier: "0x0000000000000000000000000000000000000000", + implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + verifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + batchVerifier: '0x0000000000000000000000000000000000000000', + depositVerifier: '0x0000000000000000000000000000000000000000', + withdrawVerifier: '0x0000000000000000000000000000000000000000', }; - const tx1 = await factory.connect(deployer).registerImplementation("test", implInfo as any); + const tx1 = await factory + .connect(deployer) + .registerImplementation('test', implInfo as any); await tx1.wait(); - await expect(factory.connect(deployer).deployZetoFungibleToken("test", await deployer.getAddress())).rejectedWith("Factory: depositVerifier address is required"); + await expect( + factory + .connect(deployer) + .deployZetoFungibleToken('test', await deployer.getAddress()) + ).rejectedWith('Factory: depositVerifier address is required'); + }); + it('attempting to deploy a fungible token but with a registered implementation that misses required depositVerifier should fail', async function () { + // we want to test the effectiveness of the factory contract + // to create clones of the Zeto implementation contract + const Factory = await ethers.getContractFactory('ZetoTokenFactory'); + const factory = await Factory.deploy(); + await factory.waitForDeployment(); + + const implInfo = { + implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + verifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + batchVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + depositVerifier: '0x0000000000000000000000000000000000000000', + withdrawVerifier: '0x0000000000000000000000000000000000000000', + }; + const tx1 = await factory + .connect(deployer) + .registerImplementation('test', implInfo as any); + await tx1.wait(); + + await expect( + factory + .connect(deployer) + .deployZetoFungibleToken('test', await deployer.getAddress()) + ).rejectedWith('Factory: depositVerifier address is required'); }); - it("attempting to deploy a fungible token but with a registered implementation that misses required withdrawVerifier should fail", async function () { + it('attempting to deploy a fungible token but with a registered implementation that misses required withdrawVerifier should fail', async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const Factory = await ethers.getContractFactory('ZetoTokenFactory'); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - withdrawVerifier: "0x0000000000000000000000000000000000000000", + implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + verifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + batchVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + depositVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + withdrawVerifier: '0x0000000000000000000000000000000000000000', }; - const tx1 = await factory.connect(deployer).registerImplementation("test", implInfo as any); + const tx1 = await factory + .connect(deployer) + .registerImplementation('test', implInfo as any); await tx1.wait(); - await expect(factory.connect(deployer).deployZetoFungibleToken("test", await deployer.getAddress())).rejectedWith("Factory: withdrawVerifier address is required"); + await expect( + factory + .connect(deployer) + .deployZetoFungibleToken('test', await deployer.getAddress()) + ).rejectedWith('Factory: withdrawVerifier address is required'); }); - it("attempting to deploy a fungible token with a properly registered implementation should succeed", async function () { + it('attempting to deploy a fungible token with a properly registered implementation should succeed', async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const Factory = await ethers.getContractFactory('ZetoTokenFactory'); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", - withdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + verifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + batchVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + depositVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + withdrawVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', }; - const tx1 = await factory.connect(deployer).registerImplementation("test", implInfo as any); + const tx1 = await factory + .connect(deployer) + .registerImplementation('test', implInfo as any); await tx1.wait(); - await expect(factory.connect(deployer).deployZetoFungibleToken("test", await deployer.getAddress())).fulfilled; + await expect( + factory + .connect(deployer) + .deployZetoFungibleToken('test', await deployer.getAddress()) + ).fulfilled; }); -}); \ No newline at end of file +}); diff --git a/solidity/test/lib/deploy.ts b/solidity/test/lib/deploy.ts index 6fdba83..f85a955 100644 --- a/solidity/test/lib/deploy.ts +++ b/solidity/test/lib/deploy.ts @@ -1,8 +1,14 @@ // set this to turn off paramters checking in the deployment scripts process.env.TEST_DEPLOY_SCRIPTS = 'true'; -import { deployFungible as deployFungibleUpgradeable, deployNonFungible as deployNonFungibleUpgradeable } from '../../scripts/deploy_upgradeable'; -import { deployFungible as deployFungibleCloneable, deployNonFungible as deployNonFungibleCloneable } from '../../scripts/deploy_cloneable'; +import { + deployFungible as deployFungibleUpgradeable, + deployNonFungible as deployNonFungibleUpgradeable, +} from '../../scripts/deploy_upgradeable'; +import { + deployFungible as deployFungibleCloneable, + deployNonFungible as deployNonFungibleCloneable, +} from '../../scripts/deploy_cloneable'; import fungibilities from '../../scripts/tokens.json'; import { ethers } from 'hardhat'; @@ -13,7 +19,10 @@ export async function deployZeto(tokenName: string) { // the contract address is provided if (process.env.ZETO_ADDRESS && process.env.ERC20_ADDRESS) { zeto = await ethers.getContractAt(tokenName, process.env.ZETO_ADDRESS); - erc20 = await ethers.getContractAt('SampleERC20', process.env.ERC20_ADDRESS); + erc20 = await ethers.getContractAt( + 'SampleERC20', + process.env.ERC20_ADDRESS + ); deployer = (await ethers.getSigners())[0]; return { deployer, zeto, erc20 }; } @@ -27,36 +36,55 @@ export async function deployZeto(tokenName: string) { if (process.env.USE_FACTORY !== 'true') { console.log('Deploying as upgradeable contracts'); // setup via the deployment scripts - const deployFunc = isFungible ? deployFungibleUpgradeable : deployNonFungibleUpgradeable; + const deployFunc = isFungible + ? deployFungibleUpgradeable + : deployNonFungibleUpgradeable; const result = await deployFunc(tokenName); ({ deployer, zeto, erc20 } = result as any); } else { console.log('Deploying as cloneable contracts using "ZetoTokenFactory"'); let args, zetoImpl; - const deployFunc = isFungible ? deployFungibleCloneable : deployNonFungibleCloneable; + const deployFunc = isFungible + ? deployFungibleCloneable + : deployNonFungibleCloneable; const result = await deployFunc(tokenName); ({ deployer, zetoImpl, erc20, args } = result as any); - const [deployerAddr, verifier, depositVerifier, withdrawVerifier] = args; + const [ + deployerAddr, + verifier, + batchVerifier, + depositVerifier, + withdrawVerifier, + ] = args; // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory("ZetoTokenFactory"); + const Factory = await ethers.getContractFactory('ZetoTokenFactory'); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { implementation: zetoImpl.target, - depositVerifier: depositVerifier || "0x0000000000000000000000000000000000000000", - withdrawVerifier: withdrawVerifier || "0x0000000000000000000000000000000000000000", - verifier + depositVerifier: + depositVerifier || '0x0000000000000000000000000000000000000000', + withdrawVerifier: + withdrawVerifier || '0x0000000000000000000000000000000000000000', + verifier, + batchVerifier, }; - const tx1 = await factory.connect(deployer).registerImplementation(tokenName, implInfo as any); + const tx1 = await factory + .connect(deployer) + .registerImplementation(tokenName, implInfo as any); await tx1.wait(); let tx2; if (isFungible) { - tx2 = await factory.connect(deployer).deployZetoFungibleToken(tokenName, deployerAddr); + tx2 = await factory + .connect(deployer) + .deployZetoFungibleToken(tokenName, deployerAddr); } else { - tx2 = await factory.connect(deployer).deployZetoNonFungibleToken(tokenName, deployerAddr); + tx2 = await factory + .connect(deployer) + .deployZetoNonFungibleToken(tokenName, deployerAddr); } const result1 = await tx2.wait(); @@ -77,4 +105,4 @@ export async function deployZeto(tokenName: string) { } return { deployer, zeto, erc20 }; -} \ No newline at end of file +} diff --git a/solidity/test/zeto_anon.ts b/solidity/test/zeto_anon.ts index 765a94c..fd9ed68 100644 --- a/solidity/test/zeto_anon.ts +++ b/solidity/test/zeto_anon.ts @@ -17,18 +17,30 @@ import { ethers, network } from 'hardhat'; import { Signer, BigNumberish, AddressLike, ZeroAddress } from 'ethers'; import { expect } from 'chai'; -import { loadCircuit, encodeProof, Poseidon } from "zeto-js"; +import { loadCircuit, encodeProof, Poseidon } from 'zeto-js'; import { groth16 } from 'snarkjs'; import { formatPrivKeyForBabyJub, stringifyBigInts } from 'maci-crypto'; -import { User, UTXO, newUser, newUTXO, doMint, parseUTXOEvents, ZERO_UTXO } from './lib/utils'; -import { loadProvingKeys, prepareDepositProof, prepareWithdrawProof } from './utils'; +import { + User, + UTXO, + newUser, + newUTXO, + doMint, + parseUTXOEvents, + ZERO_UTXO, +} from './lib/utils'; +import { + loadProvingKeys, + prepareDepositProof, + prepareWithdrawProof, +} from './utils'; import { Zeto_Anon } from '../typechain-types'; import { deployZeto } from './lib/deploy'; const ZERO_PUBKEY = [0, 0]; const poseidonHash = Poseidon.poseidon4; -describe("Zeto based fungible token with anonymity without encryption or nullifier", function () { +describe('Zeto based fungible token with anonymity without encryption or nullifier', function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -60,7 +72,7 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi ({ provingKeyFile: provingKey } = loadProvingKeys('anon')); }); - it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { + it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -71,14 +83,17 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi await tx1.wait(); utxo100 = newUTXO(100, Alice); - const { outputCommitments, encodedProof } = await prepareDepositProof(Alice, utxo100); + const { outputCommitments, encodedProof } = await prepareDepositProof( + Alice, + utxo100 + ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, "0x"); + .deposit(100, outputCommitments[0], encodedProof, '0x'); await tx2.wait(); }); - it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { + it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // first the authority mints UTXOs to Alice utxo1 = newUTXO(10, Alice); @@ -94,7 +109,12 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi utxo4 = newUTXO(5, Alice, _txo3.salt); // Alice transfers UTXOs to Bob - const result = await doTransfer(Alice, [utxo1, utxo2], [_txo3, utxo4], [Bob, Alice]); + const result = await doTransfer( + Alice, + [utxo1, utxo2], + [_txo3, utxo4], + [Bob, Alice] + ); // check the private transfer activity is not exposed in the ERC20 contract const afterTransferBalance = await erc20.balanceOf(Alice.ethAddress); @@ -108,14 +128,19 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi // Bob uses the information received from Alice to reconstruct the UTXO sent to him const receivedValue = 25; const receivedSalt = _txo3.salt; - const hash = poseidonHash([BigInt(receivedValue), receivedSalt, Bob.babyJubPublicKey[0], Bob.babyJubPublicKey[1]]); + const hash = poseidonHash([ + BigInt(receivedValue), + receivedSalt, + Bob.babyJubPublicKey[0], + Bob.babyJubPublicKey[1], + ]); expect(incomingUTXOs[0]).to.equal(hash); // now Bob can reconstruct the UTXO using the information received from Alice utxo3 = newUTXO(receivedValue, Bob, receivedSalt); }); - it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { + it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // give Bob another UTXO to be able to spend const _utxo1 = newUTXO(20, Bob); @@ -137,16 +162,19 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi expect(afterTransferBalance).to.equal(startingBalance); }); - it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { + it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice proposes the output ERC20 tokens const outputCommitment = newUTXO(20, Alice); - const { inputCommitments, outputCommitments, encodedProof } = await prepareWithdrawProof(Alice, [utxo100, ZERO_UTXO], outputCommitment); + const { inputCommitments, outputCommitments, encodedProof } = + await prepareWithdrawProof(Alice, [utxo100, ZERO_UTXO], outputCommitment); // Alice withdraws her UTXOs to ERC20 tokens - const tx = await zeto.connect(Alice.signer).withdraw(80, inputCommitments, outputCommitments[0], encodedProof); + const tx = await zeto + .connect(Alice.signer) + .withdraw(80, inputCommitments, outputCommitments[0], encodedProof); await tx.wait(); // Alice checks her ERC20 balance @@ -162,55 +190,99 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi return; } - it("Alice attempting to withdraw spent UTXOs should fail", async function () { + it('Alice attempting to withdraw spent UTXOs should fail', async function () { // Alice proposes the output ERC20 tokens const outputCommitment = newUTXO(90, Alice); - const { inputCommitments, outputCommitments, encodedProof } = await prepareWithdrawProof(Alice, [utxo100, ZERO_UTXO], outputCommitment); - - await expect(zeto.connect(Alice.signer).withdraw(10, inputCommitments, outputCommitments[0], encodedProof)).rejectedWith("UTXOAlreadySpent"); + const { inputCommitments, outputCommitments, encodedProof } = + await prepareWithdrawProof( + Alice, + [utxo100, ZERO_UTXO], + outputCommitment + ); + + await expect( + zeto + .connect(Alice.signer) + .withdraw(10, inputCommitments, outputCommitments[0], encodedProof) + ).rejectedWith('UTXOAlreadySpent'); }); - it("mint existing unspent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo4])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing unspent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("mint existing spent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo1])).rejectedWith("UTXOAlreadySpent"); + it('mint existing spent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( + 'UTXOAlreadySpent' + ); }); - it("transfer non-existing UTXOs should fail", async function () { + it('transfer non-existing UTXOs should fail', async function () { const nonExisting1 = newUTXO(10, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); - await expect(doTransfer(Alice, [nonExisting1, nonExisting2], [nonExisting1, nonExisting2], [Alice, Alice])).rejectedWith("UTXONotMinted"); + await expect( + doTransfer( + Alice, + [nonExisting1, nonExisting2], + [nonExisting1, nonExisting2], + [Alice, Alice] + ) + ).rejectedWith('UTXONotMinted'); }); - it("transfer spent UTXOs should fail (double spend protection)", async function () { + it('transfer spent UTXOs should fail (double spend protection)', async function () { // create outputs const utxo5 = newUTXO(25, Bob); const utxo6 = newUTXO(5, Alice, utxo5.salt); - await expect(doTransfer(Alice, [utxo1, utxo2], [utxo5, utxo6], [Bob, Alice])).rejectedWith("UTXOAlreadySpent") + await expect( + doTransfer(Alice, [utxo1, utxo2], [utxo5, utxo6], [Bob, Alice]) + ).rejectedWith('UTXOAlreadySpent'); }); - it("spend by using the same UTXO as both inputs should fail", async function () { + it('spend by using the same UTXO as both inputs should fail', async function () { const utxo5 = newUTXO(20, Alice); const utxo6 = newUTXO(10, Bob, utxo5.salt); - await expect(doTransfer(Bob, [utxo7, utxo7], [utxo5, utxo6], [Alice, Bob])).rejectedWith(`UTXODuplicate(${utxo7.hash.toString()}`); + await expect( + doTransfer(Bob, [utxo7, utxo7], [utxo5, utxo6], [Alice, Bob]) + ).rejectedWith(`UTXODuplicate(${utxo7.hash.toString()}`); }); }); - async function doTransfer(signer: User, inputs: UTXO[], outputs: UTXO[], owners: User[]) { + async function doTransfer( + signer: User, + inputs: UTXO[], + outputs: UTXO[], + owners: User[] + ) { let inputCommitments: [BigNumberish, BigNumberish]; let outputCommitments: [BigNumberish, BigNumberish]; let outputOwnerAddresses: [AddressLike, AddressLike]; let encodedProof: any; - const result = await prepareProof(circuit, provingKey, signer, inputs, outputs, owners); + const result = await prepareProof( + circuit, + provingKey, + signer, + inputs, + outputs, + owners + ); inputCommitments = result.inputCommitments; outputCommitments = result.outputCommitments; - outputOwnerAddresses = owners.map(owner => owner.ethAddress || ZeroAddress) as [AddressLike, AddressLike]; + outputOwnerAddresses = owners.map( + (owner) => owner.ethAddress || ZeroAddress + ) as [AddressLike, AddressLike]; encodedProof = result.encodedProof; - return await sendTx(signer, inputCommitments, outputCommitments, outputOwnerAddresses, encodedProof); + return await sendTx( + signer, + inputCommitments, + outputCommitments, + outputOwnerAddresses, + encodedProof + ); } async function sendTx( @@ -223,7 +295,7 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi const signerAddress = await signer.signer.getAddress(); const tx = await zeto .connect(signer.signer) - .transfer(inputCommitments, outputCommitments, encodedProof, "0x"); + .transfer(inputCommitments, outputCommitments, encodedProof, '0x'); const results = await tx.wait(); console.log(`Method transfer() complete. Gas used: ${results?.gasUsed}`); @@ -239,14 +311,31 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi } }); -async function prepareProof(circuit: any, provingKey: any, signer: User, inputs: UTXO[], outputs: UTXO[], owners: User[]) { - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map((input) => input.hash) as [BigNumberish, BigNumberish]; +async function prepareProof( + circuit: any, + provingKey: any, + signer: User, + inputs: UTXO[], + outputs: UTXO[], + owners: User[] +) { + const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + (input) => input.hash + ) as [BigNumberish, BigNumberish]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map((output) => output.hash) as [BigNumberish, BigNumberish]; + const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + (output) => output.hash + ) as [BigNumberish, BigNumberish]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputSalts = outputs.map(o => o.salt || 0n); - const outputOwnerPublicKeys: [[BigNumberish, BigNumberish], [BigNumberish, BigNumberish]] = owners.map(owner => owner.babyJubPublicKey || ZERO_PUBKEY) as [[BigNumberish, BigNumberish], [BigNumberish, BigNumberish]]; + const outputSalts = outputs.map((o) => o.salt || 0n); + const outputOwnerPublicKeys: [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ] = owners.map((owner) => owner.babyJubPublicKey || ZERO_PUBKEY) as [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ]; const otherInputs = stringifyBigInts({ inputOwnerPrivateKey: formatPrivKeyForBabyJub(signer.babyJubPrivateKey), }); @@ -261,24 +350,29 @@ async function prepareProof(circuit: any, provingKey: any, signer: User, inputs: outputValues, outputSalts, outputOwnerPublicKeys, - ...otherInputs + ...otherInputs, }, true ); const timeWitnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKey, witness) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; + const { proof, publicSignals } = (await groth16.prove( + provingKey, + witness + )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; - console.log(`Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms`); + console.log( + `Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms` + ); const encodedProof = encodeProof(proof); return { inputCommitments, outputCommitments, - encodedProof + encodedProof, }; } module.exports = { prepareProof, -}; \ No newline at end of file +}; diff --git a/solidity/test/zeto_anon_enc.ts b/solidity/test/zeto_anon_enc.ts index b2e6e1f..44dcd77 100644 --- a/solidity/test/zeto_anon_enc.ts +++ b/solidity/test/zeto_anon_enc.ts @@ -17,16 +17,38 @@ import { ethers, network } from 'hardhat'; import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; import { expect } from 'chai'; -import { loadCircuit, poseidonDecrypt, encodeProof, Poseidon, newEncryptionNonce } from "zeto-js"; +import { + loadCircuit, + poseidonDecrypt, + encodeProof, + Poseidon, + newEncryptionNonce, +} from 'zeto-js'; import { groth16 } from 'snarkjs'; -import { formatPrivKeyForBabyJub, genEcdhSharedKey, stringifyBigInts } from 'maci-crypto'; -import { User, UTXO, newUser, newUTXO, doMint, ZERO_UTXO, parseUTXOEvents } from './lib/utils'; -import { loadProvingKeys, prepareDepositProof, prepareWithdrawProof } from './utils'; +import { + formatPrivKeyForBabyJub, + genEcdhSharedKey, + stringifyBigInts, +} from 'maci-crypto'; +import { + User, + UTXO, + newUser, + newUTXO, + doMint, + ZERO_UTXO, + parseUTXOEvents, +} from './lib/utils'; +import { + loadProvingKeys, + prepareDepositProof, + prepareWithdrawProof, +} from './utils'; import { deployZeto } from './lib/deploy'; const poseidonHash = Poseidon.poseidon4; -describe("Zeto based fungible token with anonymity and encryption", function () { +describe('Zeto based fungible token with anonymity and encryption', function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -57,7 +79,7 @@ describe("Zeto based fungible token with anonymity and encryption", function () ({ provingKeyFile: provingKey } = loadProvingKeys('anon_enc')); }); - it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { + it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -68,14 +90,17 @@ describe("Zeto based fungible token with anonymity and encryption", function () await tx1.wait(); utxo100 = newUTXO(100, Alice); - const { outputCommitments, encodedProof } = await prepareDepositProof(Alice, utxo100); + const { outputCommitments, encodedProof } = await prepareDepositProof( + Alice, + utxo100 + ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, "0x"); + .deposit(100, outputCommitments[0], encodedProof, '0x'); await tx2.wait(); }); - it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { + it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // first the authority mints UTXOs to Alice utxo1 = newUTXO(10, Alice); @@ -91,12 +116,17 @@ describe("Zeto based fungible token with anonymity and encryption", function () utxo4 = newUTXO(5, Alice, _utxo1.salt); // Alice transfers UTXOs to Bob - const result = await doTransfer(Alice, [utxo1, utxo2], [_utxo1, utxo4], [Bob, Alice]); + const result = await doTransfer( + Alice, + [utxo1, utxo2], + [_utxo1, utxo4], + [Bob, Alice] + ); // check the private transfer activity is not exposed in the ERC20 contract const afterTransferBalance = await erc20.balanceOf(Alice.ethAddress); expect(afterTransferBalance).to.equal(startingBalance); - + // Bob uses the information in the event to recover the incoming UTXO // first obtain the UTXO from the transaction event const events = parseUTXOEvents(zeto, result.txResult!); @@ -108,32 +138,50 @@ describe("Zeto based fungible token with anonymity and encryption", function () const senderPublicKey = Alice.babyJubPublicKey; const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, senderPublicKey); - const plainText = poseidonDecrypt(events[0].encryptedValues, sharedKey, events[0].encryptionNonce, 2); + const plainText = poseidonDecrypt( + events[0].encryptedValues, + sharedKey, + events[0].encryptionNonce, + 2 + ); expect(plainText).to.deep.equal([25n, result.plainTextSalt]); // Bob verifies that the UTXO constructed from the decrypted values matches the UTXO from the event - const hash = poseidonHash([BigInt(plainText[0]), plainText[1], Bob.babyJubPublicKey[0], Bob.babyJubPublicKey[1]]); + const hash = poseidonHash([ + BigInt(plainText[0]), + plainText[1], + Bob.babyJubPublicKey[0], + Bob.babyJubPublicKey[1], + ]); expect(hash).to.equal(incomingUTXOs[0]); // simulate Bob using the decrypted values to construct the UTXO received from the transaction utxo3 = newUTXO(Number(plainText[0]), Bob, plainText[1]); }); - it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { + it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { // propose the output UTXOs const _utxo1 = newUTXO(25, Charlie); // Bob should be able to spend the UTXO that was reconstructed from the previous transaction - await doTransfer(Bob, [utxo3, ZERO_UTXO], [_utxo1, ZERO_UTXO], [Charlie, Bob]); + await doTransfer( + Bob, + [utxo3, ZERO_UTXO], + [_utxo1, ZERO_UTXO], + [Charlie, Bob] + ); }); - it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { + it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice proposes the output ERC20 tokens const outputCommitment = newUTXO(20, Alice); - const { inputCommitments, outputCommitments, encodedProof } = await prepareWithdrawProof(Alice, [utxo100, ZERO_UTXO], outputCommitment); + const { inputCommitments, outputCommitments, encodedProof } = + await prepareWithdrawProof(Alice, [utxo100, ZERO_UTXO], outputCommitment); // Alice withdraws her UTXOs to ERC20 tokens - const tx = await zeto.connect(Alice.signer).withdraw(80, inputCommitments, outputCommitments[0], encodedProof); + const tx = await zeto + .connect(Alice.signer) + .withdraw(80, inputCommitments, outputCommitments[0], encodedProof); await tx.wait(); // Alice checks her ERC20 balance @@ -141,7 +189,7 @@ describe("Zeto based fungible token with anonymity and encryption", function () expect(endingBalance - startingBalance).to.be.equal(80); }); - describe("failure cases", function () { + describe('failure cases', function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks @@ -149,48 +197,77 @@ describe("Zeto based fungible token with anonymity and encryption", function () return; } - it("Alice attempting to withdraw spent UTXOs should fail", async function () { + it('Alice attempting to withdraw spent UTXOs should fail', async function () { // Alice proposes the output ERC20 tokens const outputCommitment = newUTXO(90, Alice); - const { inputCommitments, outputCommitments, encodedProof } = await prepareWithdrawProof(Alice, [utxo100, ZERO_UTXO], outputCommitment); - - await expect(zeto.connect(Alice.signer).withdraw(10, inputCommitments, outputCommitments[0], encodedProof)).rejectedWith("UTXOAlreadySpent"); + const { inputCommitments, outputCommitments, encodedProof } = + await prepareWithdrawProof( + Alice, + [utxo100, ZERO_UTXO], + outputCommitment + ); + + await expect( + zeto + .connect(Alice.signer) + .withdraw(10, inputCommitments, outputCommitments[0], encodedProof) + ).rejectedWith('UTXOAlreadySpent'); }); - it("mint existing unspent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo4])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing unspent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("mint existing spent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo1])).rejectedWith("UTXOAlreadySpent"); + it('mint existing spent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( + 'UTXOAlreadySpent' + ); }); - it("transfer non-existing UTXOs should fail", async function () { + it('transfer non-existing UTXOs should fail', async function () { const nonExisting1 = newUTXO(10, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); - await expect(doTransfer(Alice, [nonExisting1, nonExisting2], [nonExisting1, nonExisting2], [Alice, Alice])).rejectedWith("UTXONotMinted"); + await expect( + doTransfer( + Alice, + [nonExisting1, nonExisting2], + [nonExisting1, nonExisting2], + [Alice, Alice] + ) + ).rejectedWith('UTXONotMinted'); }); - it("transfer spent UTXOs should fail (double spend protection)", async function () { + it('transfer spent UTXOs should fail (double spend protection)', async function () { // create outputs const _utxo1 = newUTXO(25, Bob); const _utxo2 = newUTXO(5, Alice); - await expect(doTransfer(Alice, [utxo1, utxo2], [_utxo1, _utxo2], [Bob, Alice])).rejectedWith("UTXOAlreadySpent") + await expect( + doTransfer(Alice, [utxo1, utxo2], [_utxo1, _utxo2], [Bob, Alice]) + ).rejectedWith('UTXOAlreadySpent'); }); - it("spend by using the same UTXO as both inputs should fail", async function () { + it('spend by using the same UTXO as both inputs should fail', async function () { // mint a new UTXO to Bob const _utxo1 = newUTXO(20, Bob); await doMint(zeto, deployer, [_utxo1]); const _utxo2 = newUTXO(25, Alice); const _utxo3 = newUTXO(15, Bob); - await expect(doTransfer(Bob, [_utxo1, _utxo1], [_utxo2, _utxo3], [Alice, Bob])).rejectedWith(`UTXODuplicate(${_utxo1.hash.toString()}`); + await expect( + doTransfer(Bob, [_utxo1, _utxo1], [_utxo2, _utxo3], [Alice, Bob]) + ).rejectedWith(`UTXODuplicate(${_utxo1.hash.toString()}`); }); }); - async function doTransfer(signer: User, inputs: UTXO[], outputs: UTXO[], owners: User[]) { + async function doTransfer( + signer: User, + inputs: UTXO[], + outputs: UTXO[], + owners: User[] + ) { let inputCommitments: [BigNumberish, BigNumberish]; let outputCommitments: [BigNumberish, BigNumberish]; let encryptedValues: BigNumberish[]; @@ -203,18 +280,40 @@ describe("Zeto based fungible token with anonymity and encryption", function () encryptedValues = result.encryptedValues; encryptionNonce = result.encryptionNonce; - const txResult = await sendTx(signer, inputCommitments, outputCommitments, encryptedValues, encryptionNonce, encodedProof); + const txResult = await sendTx( + signer, + inputCommitments, + outputCommitments, + encryptedValues, + encryptionNonce, + encodedProof + ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { txResult, plainTextSalt: outputs[0].salt }; } - async function prepareProof(signer: User, inputs: UTXO[], outputs: UTXO[], owners: User[]) { - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map((input) => input.hash) as [BigNumberish, BigNumberish]; + async function prepareProof( + signer: User, + inputs: UTXO[], + outputs: UTXO[], + owners: User[] + ) { + const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + (input) => input.hash + ) as [BigNumberish, BigNumberish]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map((output) => output.hash) as [BigNumberish, BigNumberish]; + const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + (output) => output.hash + ) as [BigNumberish, BigNumberish]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [[BigNumberish, BigNumberish], [BigNumberish, BigNumberish]] = owners.map(owner => owner.babyJubPublicKey) as [[BigNumberish, BigNumberish], [BigNumberish, BigNumberish]]; + const outputOwnerPublicKeys: [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ] = owners.map((owner) => owner.babyJubPublicKey) as [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, @@ -231,16 +330,21 @@ describe("Zeto based fungible token with anonymity and encryption", function () outputValues, outputSalts: outputs.map((output) => output.salt || 0n), outputOwnerPublicKeys, - ...encryptInputs + ...encryptInputs, }, true ); const timeWitnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKey, witness) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; + const { proof, publicSignals } = (await groth16.prove( + provingKey, + witness + )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; - console.log(`Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms`); + console.log( + `Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms` + ); const encodedProof = encodeProof(proof); const encryptedValues = publicSignals.slice(0, 4); @@ -249,7 +353,7 @@ describe("Zeto based fungible token with anonymity and encryption", function () outputCommitments, encryptedValues, encryptionNonce, - encodedProof + encodedProof, }; } @@ -269,7 +373,7 @@ describe("Zeto based fungible token with anonymity and encryption", function () encryptionNonce, encryptedValues, encodedProof, - "0x" + '0x' ); const results: ContractTransactionReceipt | null = await tx.wait(); @@ -286,4 +390,3 @@ describe("Zeto based fungible token with anonymity and encryption", function () return results; } }); - diff --git a/solidity/test/zeto_anon_enc_nullifier.ts b/solidity/test/zeto_anon_enc_nullifier.ts index de80627..1663082 100644 --- a/solidity/test/zeto_anon_enc_nullifier.ts +++ b/solidity/test/zeto_anon_enc_nullifier.ts @@ -17,15 +17,33 @@ import { ethers, network } from 'hardhat'; import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; import { expect } from 'chai'; -import { loadCircuit, poseidonDecrypt, encodeProof, newEncryptionNonce } from "zeto-js"; +import { + loadCircuit, + poseidonDecrypt, + encodeProof, + newEncryptionNonce, +} from 'zeto-js'; import { groth16 } from 'snarkjs'; import { genEcdhSharedKey, stringifyBigInts } from 'maci-crypto'; import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; -import { UTXO, User, newUser, newUTXO, newNullifier, doMint, ZERO_UTXO, parseUTXOEvents } from './lib/utils'; -import { loadProvingKeys, prepareDepositProof, prepareNullifierWithdrawProof } from './utils'; +import { + UTXO, + User, + newUser, + newUTXO, + newNullifier, + doMint, + ZERO_UTXO, + parseUTXOEvents, +} from './lib/utils'; +import { + loadProvingKeys, + prepareDepositProof, + prepareNullifierWithdrawProof, +} from './utils'; import { deployZeto } from './lib/deploy'; -describe("Zeto based fungible token with anonymity using nullifiers and encryption", function () { +describe('Zeto based fungible token with anonymity using nullifiers and encryption', function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -58,21 +76,21 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti circuit = await loadCircuit('anon_enc_nullifier'); ({ provingKeyFile: provingKey } = loadProvingKeys('anon_enc_nullifier')); - const storage1 = new InMemoryDB(str2Bytes("")) + const storage1 = new InMemoryDB(str2Bytes('')); smtAlice = new Merkletree(storage1, true, 64); - const storage2 = new InMemoryDB(str2Bytes("")) + const storage2 = new InMemoryDB(str2Bytes('')); smtBob = new Merkletree(storage2, true, 64); }); - it("onchain SMT root should be equal to the offchain SMT root", async function () { + it('onchain SMT root should be equal to the offchain SMT root', async function () { const root = await smtAlice.root(); const onchainRoot = await zeto.getRoot(); expect(onchainRoot).to.equal(0n); expect(root.string()).to.equal(onchainRoot.toString()); }); - it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { + it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -83,17 +101,20 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti await tx1.wait(); utxo100 = newUTXO(100, Alice); - const { outputCommitments, encodedProof } = await prepareDepositProof(Alice, utxo100); + const { outputCommitments, encodedProof } = await prepareDepositProof( + Alice, + utxo100 + ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, "0x"); + .deposit(100, outputCommitments[0], encodedProof, '0x'); await tx2.wait(); await smtAlice.add(utxo100.hash, utxo100.hash); await smtBob.add(utxo100.hash, utxo100.hash); }); - it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { + it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // The authority mints a new UTXO and assigns it to Alice utxo1 = newUTXO(10, Alice); @@ -128,10 +149,21 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti // Alice generates inclusion proofs for the UTXOs to be spent const proof1 = await smtAlice.generateCircomVerifierProof(utxo1.hash, root); const proof2 = await smtAlice.generateCircomVerifierProof(utxo2.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice transfers her UTXOs to Bob - const result2 = await doTransfer(Alice, [utxo1, utxo2], [nullifier1, nullifier2], [_utxo3, utxo4], root.bigInt(), merkleProofs, [Bob, Alice]); + const result2 = await doTransfer( + Alice, + [utxo1, utxo2], + [nullifier1, nullifier2], + [_utxo3, utxo4], + root.bigInt(), + merkleProofs, + [Bob, Alice] + ); // check the private transfer activity is not exposed in the ERC20 contract const afterTransferBalance = await erc20.balanceOf(Alice.ethAddress); @@ -155,15 +187,23 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti await smtBob.add(events[0].outputs[1], events[0].outputs[1]); // Bob uses the encrypted values in the event to decrypt and recover the UTXO value and salt - const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, Alice.babyJubPublicKey); - const plainText = poseidonDecrypt(events[0].encryptedValues, sharedKey, events[0].encryptionNonce, 2); + const sharedKey = genEcdhSharedKey( + Bob.babyJubPrivateKey, + Alice.babyJubPublicKey + ); + const plainText = poseidonDecrypt( + events[0].encryptedValues, + sharedKey, + events[0].encryptionNonce, + 2 + ); expect(plainText).to.deep.equal([25n, result2.plainTextSalt]); // Bob uses the decrypted values to construct the UTXO received from the transaction utxo3 = newUTXO(Number(plainText[0]), Bob, plainText[1]); }).timeout(600000); - it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { + it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { // Bob generates the nullifiers for the UTXO to be spent const nullifier1 = newNullifier(utxo3, Bob); @@ -171,14 +211,25 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti const root = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof(utxo3.hash, root); const proof2 = await smtBob.generateCircomVerifierProof(0n, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Bob proposes the output UTXOs const utxo6 = newUTXO(10, Charlie); utxo7 = newUTXO(15, Bob); // Bob should be able to spend the UTXO that was reconstructed from the previous transaction - const result = await doTransfer(Bob, [utxo3, ZERO_UTXO], [nullifier1, ZERO_UTXO], [utxo6, utxo7], root.bigInt(), merkleProofs, [Charlie, Bob]); + const result = await doTransfer( + Bob, + [utxo3, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + [utxo6, utxo7], + root.bigInt(), + merkleProofs, + [Charlie, Bob] + ); // Bob keeps the local SMT in sync await smtBob.add(utxo6.hash, utxo6.hash); @@ -190,7 +241,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti await smtAlice.add(events[0].outputs[1], events[0].outputs[1]); }).timeout(600000); - it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { + it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice generates the nullifiers for the UTXOs to be spent @@ -198,17 +249,39 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti // Alice generates inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo100.hash, root); + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo100.hash, + root + ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice proposes the output ERC20 tokens const withdrawChangeUTXO = newUTXO(20, Alice); - const { nullifiers, outputCommitments, encodedProof } = await prepareNullifierWithdrawProof(Alice, [utxo100, ZERO_UTXO], [nullifier1, ZERO_UTXO], withdrawChangeUTXO, root.bigInt(), merkleProofs); + const { nullifiers, outputCommitments, encodedProof } = + await prepareNullifierWithdrawProof( + Alice, + [utxo100, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + withdrawChangeUTXO, + root.bigInt(), + merkleProofs + ); // Alice withdraws her UTXOs to ERC20 tokens - const tx = await zeto.connect(Alice.signer).withdraw(80, nullifiers, outputCommitments[0], root.bigInt(), encodedProof); + const tx = await zeto + .connect(Alice.signer) + .withdraw( + 80, + nullifiers, + outputCommitments[0], + root.bigInt(), + encodedProof + ); await tx.wait(); // Alice tracks the UTXO inside the SMT @@ -221,7 +294,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti expect(endingBalance - startingBalance).to.be.equal(80); }); - describe("failure cases", function () { + describe('failure cases', function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks @@ -229,34 +302,62 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti return; } - it("Alice attempting to withdraw spent UTXOs should fail", async function () { + it('Alice attempting to withdraw spent UTXOs should fail', async function () { // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); // Alice generates inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo100.hash, root); + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo100.hash, + root + ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice proposes the output ERC20 tokens const outputCommitment = newUTXO(90, Alice); - const { nullifiers, outputCommitments, encodedProof } = await prepareNullifierWithdrawProof(Alice, [utxo100, ZERO_UTXO], [nullifier1, ZERO_UTXO], outputCommitment, root.bigInt(), merkleProofs); + const { nullifiers, outputCommitments, encodedProof } = + await prepareNullifierWithdrawProof( + Alice, + [utxo100, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + outputCommitment, + root.bigInt(), + merkleProofs + ); // Alice withdraws her UTXOs to ERC20 tokens - await expect(zeto.connect(Alice.signer).withdraw(10, nullifiers, outputCommitments[0], root.bigInt(), encodedProof)).rejectedWith("UTXOAlreadySpent"); + await expect( + zeto + .connect(Alice.signer) + .withdraw( + 10, + nullifiers, + outputCommitments[0], + root.bigInt(), + encodedProof + ) + ).rejectedWith('UTXOAlreadySpent'); }); - it("mint existing unspent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo4])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing unspent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("mint existing spent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo1])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing spent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("transfer spent UTXOs should fail (double spend protection)", async function () { + it('transfer spent UTXOs should fail (double spend protection)', async function () { // create outputs const _utxo1 = newUTXO(25, Bob); const _utxo2 = newUTXO(5, Alice); @@ -267,14 +368,33 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti // generate inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo1.hash, root); - const proof2 = await smtAlice.generateCircomVerifierProof(utxo2.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; - - await expect(doTransfer(Alice, [utxo1, utxo2], [nullifier1, nullifier2], [_utxo1, _utxo2], root.bigInt(), merkleProofs, [Bob, Alice])).rejectedWith("UTXOAlreadySpent") + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo1.hash, + root + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + utxo2.hash, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; + + await expect( + doTransfer( + Alice, + [utxo1, utxo2], + [nullifier1, nullifier2], + [_utxo1, _utxo2], + root.bigInt(), + merkleProofs, + [Bob, Alice] + ) + ).rejectedWith('UTXOAlreadySpent'); }).timeout(600000); - it("transfer with existing UTXOs in the output should fail (mass conservation protection)", async function () { + it('transfer with existing UTXOs in the output should fail (mass conservation protection)', async function () { // give Bob another UTXO to be able to spend const _utxo1 = newUTXO(15, Bob); await doMint(zeto, deployer, [_utxo1]); @@ -284,13 +404,29 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti const nullifier2 = newNullifier(_utxo1, Bob); let root = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); - const proof2 = await smtBob.generateCircomVerifierProof(_utxo1.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; - - await expect(doTransfer(Bob, [utxo7, _utxo1], [nullifier1, nullifier2], [utxo1, utxo2], root.bigInt(), merkleProofs, [Alice, Alice])).rejectedWith("UTXOAlreadyOwned") + const proof2 = await smtBob.generateCircomVerifierProof( + _utxo1.hash, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; + + await expect( + doTransfer( + Bob, + [utxo7, _utxo1], + [nullifier1, nullifier2], + [utxo1, utxo2], + root.bigInt(), + merkleProofs, + [Alice, Alice] + ) + ).rejectedWith('UTXOAlreadyOwned'); }).timeout(600000); - it("spend by using the same UTXO as both inputs should fail", async function () { + it('spend by using the same UTXO as both inputs should fail', async function () { const _utxo1 = newUTXO(20, Alice); const _utxo2 = newUTXO(10, Bob); const nullifier1 = newNullifier(utxo7, Bob); @@ -299,12 +435,25 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); const proof2 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; - - await expect(doTransfer(Bob, [utxo7, utxo7], [nullifier1, nullifier2], [_utxo1, _utxo2], root.bigInt(), merkleProofs, [Alice, Bob])).rejectedWith(`UTXODuplicate`); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; + + await expect( + doTransfer( + Bob, + [utxo7, utxo7], + [nullifier1, nullifier2], + [_utxo1, _utxo2], + root.bigInt(), + merkleProofs, + [Alice, Bob] + ) + ).rejectedWith(`UTXODuplicate`); }).timeout(600000); - it("transfer non-existing UTXOs should fail", async function () { + it('transfer non-existing UTXOs should fail', async function () { const nonExisting1 = newUTXO(25, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); @@ -318,18 +467,37 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti // generate inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(nonExisting1.hash, root); - const proof2 = await smtAlice.generateCircomVerifierProof(nonExisting2.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const proof1 = await smtAlice.generateCircomVerifierProof( + nonExisting1.hash, + root + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + nonExisting2.hash, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // propose the output UTXOs const _utxo1 = newUTXO(30, Charlie); utxo7 = newUTXO(15, Bob); - await expect(doTransfer(Alice, [nonExisting1, nonExisting2], [nullifier1, nullifier2], [utxo7, _utxo1], root.bigInt(), merkleProofs, [Bob, Charlie])).rejectedWith("UTXORootNotFound"); + await expect( + doTransfer( + Alice, + [nonExisting1, nonExisting2], + [nullifier1, nullifier2], + [utxo7, _utxo1], + root.bigInt(), + merkleProofs, + [Bob, Charlie] + ) + ).rejectedWith('UTXORootNotFound'); }).timeout(600000); - it("repeated mint calls with single UTXO should not fail", async function () { + it('repeated mint calls with single UTXO should not fail', async function () { const utxo5 = newUTXO(10, Alice); await expect(doMint(zeto, deployer, [utxo5, ZERO_UTXO])).fulfilled; const utxo6 = newUTXO(20, Alice); @@ -337,32 +505,80 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti }); }); - async function doTransfer(signer: User, inputs: UTXO[], _nullifiers: UTXO[], outputs: UTXO[], root: BigInt, merkleProofs: BigInt[][], owners: User[]) { + async function doTransfer( + signer: User, + inputs: UTXO[], + _nullifiers: UTXO[], + outputs: UTXO[], + root: BigInt, + merkleProofs: BigInt[][], + owners: User[] + ) { let nullifiers: [BigNumberish, BigNumberish]; let outputCommitments: [BigNumberish, BigNumberish]; let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; - const result = await prepareProof(signer, inputs, _nullifiers, outputs, root, merkleProofs, owners); - nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [BigNumberish, BigNumberish]; + const result = await prepareProof( + signer, + inputs, + _nullifiers, + outputs, + root, + merkleProofs, + owners + ); + nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ + BigNumberish, + BigNumberish + ]; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; encryptedValues = result.encryptedValues; encryptionNonce = result.encryptionNonce; - const txResult = await sendTx(signer, nullifiers, outputCommitments, root, encryptedValues, encryptionNonce, encodedProof); + const txResult = await sendTx( + signer, + nullifiers, + outputCommitments, + root, + encryptedValues, + encryptionNonce, + encodedProof + ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { txResult, plainTextSalt: outputs[0].salt }; } - async function prepareProof(signer: User, inputs: UTXO[], _nullifiers: UTXO[], outputs: UTXO[], root: BigInt, merkleProof: BigInt[][], owners: User[]) { - const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [BigNumberish, BigNumberish]; - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map((input) => input.hash) as [BigNumberish, BigNumberish]; + async function prepareProof( + signer: User, + inputs: UTXO[], + _nullifiers: UTXO[], + outputs: UTXO[], + root: BigInt, + merkleProof: BigInt[][], + owners: User[] + ) { + const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ + BigNumberish, + BigNumberish + ]; + const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + (input) => input.hash + ) as [BigNumberish, BigNumberish]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map((output) => output.hash) as [BigNumberish, BigNumberish]; + const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + (output) => output.hash + ) as [BigNumberish, BigNumberish]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [[BigNumberish, BigNumberish], [BigNumberish, BigNumberish]] = owners.map(owner => owner.babyJubPublicKey) as [[BigNumberish, BigNumberish], [BigNumberish, BigNumberish]]; + const outputOwnerPublicKeys: [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ] = owners.map((owner) => owner.babyJubPublicKey) as [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, @@ -382,19 +598,21 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti outputValues, outputSalts: outputs.map((output) => output.salt), outputOwnerPublicKeys, - ...encryptInputs + ...encryptInputs, }; - const witness = await circuit.calculateWTNSBin( - inputObj, - true - ); + const witness = await circuit.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKey, witness) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; + const { proof, publicSignals } = (await groth16.prove( + provingKey, + witness + )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; - console.log(`Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`); + console.log( + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + ); const encodedProof = encodeProof(proof); const encryptedValues = publicSignals.slice(0, 4); @@ -403,7 +621,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti outputCommitments, encryptedValues, encryptionNonce, - encodedProof + encodedProof, }; } @@ -426,10 +644,14 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti encryptionNonce, encryptedValues, encodedProof, - "0x" + '0x' ); const results: ContractTransactionReceipt | null = await tx.wait(); - console.log(`Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${results?.gasUsed}`); + console.log( + `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ + results?.gasUsed + }` + ); return results; } }); diff --git a/solidity/test/zeto_anon_enc_nullifier_kyc.ts b/solidity/test/zeto_anon_enc_nullifier_kyc.ts index 509de0a..ffacde0 100644 --- a/solidity/test/zeto_anon_enc_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_enc_nullifier_kyc.ts @@ -134,7 +134,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, "0x"); + .deposit(100, outputCommitments[0], encodedProof, '0x'); await tx2.wait(); await smtAlice.add(utxo100.hash, utxo100.hash); @@ -394,7 +394,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ); const tx2 = await zeto .connect(unregistered.signer) - .deposit(100, outputCommitments[0], encodedProof, "0x"); + .deposit(100, outputCommitments[0], encodedProof, '0x'); await tx2.wait(); // Alice tracks the UTXO inside the SMT @@ -954,7 +954,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti encryptionNonce, encryptedValues, encodedProof, - "0x" + '0x' ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( diff --git a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts index 4cceead..dd7ecc2 100644 --- a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts +++ b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts @@ -17,15 +17,34 @@ import { ethers, network } from 'hardhat'; import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; import { expect } from 'chai'; -import { loadCircuit, poseidonDecrypt, encodeProof, Poseidon, newEncryptionNonce } from "zeto-js"; +import { + loadCircuit, + poseidonDecrypt, + encodeProof, + Poseidon, + newEncryptionNonce, +} from 'zeto-js'; import { groth16 } from 'snarkjs'; import { genEcdhSharedKey, stringifyBigInts } from 'maci-crypto'; import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; -import { UTXO, User, newUser, newUTXO, newNullifier, doMint, ZERO_UTXO, parseUTXOEvents } from './lib/utils'; -import { loadProvingKeys, prepareDepositProof, prepareNullifierWithdrawProof } from './utils'; +import { + UTXO, + User, + newUser, + newUTXO, + newNullifier, + doMint, + ZERO_UTXO, + parseUTXOEvents, +} from './lib/utils'; +import { + loadProvingKeys, + prepareDepositProof, + prepareNullifierWithdrawProof, +} from './utils'; import { deployZeto } from './lib/deploy'; -describe("Zeto based fungible token with anonymity using nullifiers and encryption for non-repudiation", function () { +describe('Zeto based fungible token with anonymity using nullifiers and encryption for non-repudiation', function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -55,29 +74,35 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti Charlie = await newUser(c); Authority = await newUser(e); - ({ deployer, zeto, erc20 } = await deployZeto('Zeto_AnonEncNullifierNonRepudiation')); + ({ deployer, zeto, erc20 } = await deployZeto( + 'Zeto_AnonEncNullifierNonRepudiation' + )); - const tx1 = await zeto.connect(deployer).setArbiter(Authority.babyJubPublicKey); + const tx1 = await zeto + .connect(deployer) + .setArbiter(Authority.babyJubPublicKey); await tx1.wait(); circuit = await loadCircuit('anon_enc_nullifier_non_repudiation'); - ({ provingKeyFile: provingKey } = loadProvingKeys('anon_enc_nullifier_non_repudiation')); + ({ provingKeyFile: provingKey } = loadProvingKeys( + 'anon_enc_nullifier_non_repudiation' + )); - const storage1 = new InMemoryDB(str2Bytes("")) + const storage1 = new InMemoryDB(str2Bytes('')); smtAlice = new Merkletree(storage1, true, 64); - const storage2 = new InMemoryDB(str2Bytes("")) + const storage2 = new InMemoryDB(str2Bytes('')); smtBob = new Merkletree(storage2, true, 64); }); - it("onchain SMT root should be equal to the offchain SMT root", async function () { + it('onchain SMT root should be equal to the offchain SMT root', async function () { const root = await smtAlice.root(); const onchainRoot = await zeto.getRoot(); expect(onchainRoot).to.equal(0n); expect(root.string()).to.equal(onchainRoot.toString()); }); - it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { + it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -88,23 +113,26 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti await tx1.wait(); utxo100 = newUTXO(100, Alice); - const { outputCommitments, encodedProof } = await prepareDepositProof(Alice, utxo100); + const { outputCommitments, encodedProof } = await prepareDepositProof( + Alice, + utxo100 + ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, "0x"); + .deposit(100, outputCommitments[0], encodedProof, '0x'); await tx2.wait(); await smtAlice.add(utxo100.hash, utxo100.hash); await smtBob.add(utxo100.hash, utxo100.hash); }); - it("mint to Alice and transfer UTXOs honestly to Bob should succeed and verifiable by the regulator", async function () { + it('mint to Alice and transfer UTXOs honestly to Bob should succeed and verifiable by the regulator', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // The authority mints a new UTXO and assigns it to Alice utxo1 = newUTXO(10, Alice); utxo2 = newUTXO(20, Alice); const result1 = await doMint(zeto, deployer, [utxo1, utxo2]); - + // check the private mint activity is not exposed in the ERC20 contract const afterMintBalance = await erc20.balanceOf(Alice.ethAddress); expect(afterMintBalance).to.equal(startingBalance); @@ -133,10 +161,21 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti // Alice generates inclusion proofs for the UTXOs to be spent const proof1 = await smtAlice.generateCircomVerifierProof(utxo1.hash, root); const proof2 = await smtAlice.generateCircomVerifierProof(utxo2.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice transfers her UTXOs to Bob - const result2 = await doTransfer(Alice, [utxo1, utxo2], [nullifier1, nullifier2], [_utxo3, utxo4], root.bigInt(), merkleProofs, [Bob, Alice]); + const result2 = await doTransfer( + Alice, + [utxo1, utxo2], + [nullifier1, nullifier2], + [_utxo3, utxo4], + root.bigInt(), + merkleProofs, + [Bob, Alice] + ); // check the private transfer activity is not exposed in the ERC20 contract const afterTransferBalance = await erc20.balanceOf(Alice.ethAddress); @@ -160,16 +199,29 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti await smtBob.add(events[0].outputs[1], events[0].outputs[1]); // Bob uses the encrypted values in the event to decrypt and recover the UTXO value and salt - const sharedKey1 = genEcdhSharedKey(Bob.babyJubPrivateKey, Alice.babyJubPublicKey); - const plainText1 = poseidonDecrypt(events[0].encryptedValuesForReceiver, sharedKey1, events[0].encryptionNonce, 2); - expect(plainText1).to.deep.equal([ - 25n, - result2.plainTextSalt, - ]); + const sharedKey1 = genEcdhSharedKey( + Bob.babyJubPrivateKey, + Alice.babyJubPublicKey + ); + const plainText1 = poseidonDecrypt( + events[0].encryptedValuesForReceiver, + sharedKey1, + events[0].encryptionNonce, + 2 + ); + expect(plainText1).to.deep.equal([25n, result2.plainTextSalt]); // The regulator uses the encrypted values in the event to decrypt and recover the UTXO value and salt - const sharedKey2 = genEcdhSharedKey(Authority.babyJubPrivateKey, Alice.babyJubPublicKey); - const plainText2 = poseidonDecrypt(events[0].encryptedValuesForAuthority, sharedKey2, events[0].encryptionNonce, 14); + const sharedKey2 = genEcdhSharedKey( + Authority.babyJubPrivateKey, + Alice.babyJubPublicKey + ); + const plainText2 = poseidonDecrypt( + events[0].encryptedValuesForAuthority, + sharedKey2, + events[0].encryptionNonce, + 14 + ); expect(plainText2).to.deep.equal([ Alice.babyJubPublicKey[0], Alice.babyJubPublicKey[1], @@ -184,23 +236,43 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti 25n, _utxo3.salt, utxo4.value, - utxo4.salt + utxo4.salt, ]); // the regulator verifies that the decrypted values are correct, against the UTXO hashes - const checkInputUTXO1 = Poseidon.poseidon4([plainText2[2], plainText2[3], plainText2[0], plainText2[1]]); + const checkInputUTXO1 = Poseidon.poseidon4([ + plainText2[2], + plainText2[3], + plainText2[0], + plainText2[1], + ]); expect(checkInputUTXO1).to.equal(utxo1.hash); // "utxo1" hash is available in the event - const checkInputUTXO2 = Poseidon.poseidon4([plainText2[4], plainText2[5], plainText2[0], plainText2[1]]); + const checkInputUTXO2 = Poseidon.poseidon4([ + plainText2[4], + plainText2[5], + plainText2[0], + plainText2[1], + ]); expect(checkInputUTXO2).to.equal(utxo2.hash); // "utxo2" hash is available in the event - const checkOutputUTXO1 = Poseidon.poseidon4([plainText2[10], plainText2[11], plainText2[6], plainText2[7]]); + const checkOutputUTXO1 = Poseidon.poseidon4([ + plainText2[10], + plainText2[11], + plainText2[6], + plainText2[7], + ]); expect(checkOutputUTXO1).to.equal(_utxo3.hash); // "_utxo3" hash is available in the event - const checkOutputUTXO2 = Poseidon.poseidon4([plainText2[12], plainText2[13], plainText2[8], plainText2[9]]); + const checkOutputUTXO2 = Poseidon.poseidon4([ + plainText2[12], + plainText2[13], + plainText2[8], + plainText2[9], + ]); expect(checkOutputUTXO2).to.equal(utxo4.hash); // "utxo4" hash is available in the event // Bob uses the decrypted values to construct the UTXO received from the transaction utxo3 = newUTXO(Number(plainText1[0]), Bob, plainText1[1]); }).timeout(600000); - it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { + it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { // Bob generates the nullifiers for the UTXO to be spent const nullifier1 = newNullifier(utxo3, Bob); @@ -208,14 +280,25 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti const root = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof(utxo3.hash, root); const proof2 = await smtBob.generateCircomVerifierProof(0n, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Bob proposes the output UTXOs const utxo6 = newUTXO(10, Charlie); utxo7 = newUTXO(15, Bob); // Bob should be able to spend the UTXO that was reconstructed from the previous transaction - const result = await doTransfer(Bob, [utxo3, ZERO_UTXO], [nullifier1, ZERO_UTXO], [utxo6, utxo7], root.bigInt(), merkleProofs, [Charlie, Bob]); + const result = await doTransfer( + Bob, + [utxo3, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + [utxo6, utxo7], + root.bigInt(), + merkleProofs, + [Charlie, Bob] + ); // Bob keeps the local SMT in sync await smtBob.add(utxo6.hash, utxo6.hash); @@ -227,24 +310,46 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti await smtAlice.add(events[0].outputs[1], events[0].outputs[1]); }).timeout(600000); - it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { + it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); // Alice generates inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo100.hash, root); + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo100.hash, + root + ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice proposes the output ERC20 tokens const withdrawChangeUTXO = newUTXO(20, Alice); - const { nullifiers, outputCommitments, encodedProof } = await prepareNullifierWithdrawProof(Alice, [utxo100, ZERO_UTXO], [nullifier1, ZERO_UTXO], withdrawChangeUTXO, root.bigInt(), merkleProofs); + const { nullifiers, outputCommitments, encodedProof } = + await prepareNullifierWithdrawProof( + Alice, + [utxo100, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + withdrawChangeUTXO, + root.bigInt(), + merkleProofs + ); // Alice withdraws her UTXOs to ERC20 tokens - const tx = await zeto.connect(Alice.signer).withdraw(80, nullifiers, outputCommitments[0], root.bigInt(), encodedProof); + const tx = await zeto + .connect(Alice.signer) + .withdraw( + 80, + nullifiers, + outputCommitments[0], + root.bigInt(), + encodedProof + ); await tx.wait(); // Alice tracks the UTXO inside the SMT @@ -257,7 +362,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti expect(endingBalance - startingBalance).to.be.equal(80); }); - describe("failure cases", function () { + describe('failure cases', function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks @@ -265,34 +370,62 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti return; } - it("Alice attempting to withdraw spent UTXOs should fail", async function () { + it('Alice attempting to withdraw spent UTXOs should fail', async function () { // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); // Alice generates inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo100.hash, root); + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo100.hash, + root + ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice proposes the output ERC20 tokens const outputCommitment = newUTXO(20, Alice); - const { nullifiers, outputCommitments, encodedProof } = await prepareNullifierWithdrawProof(Alice, [utxo100, ZERO_UTXO], [nullifier1, ZERO_UTXO], outputCommitment, root.bigInt(), merkleProofs); + const { nullifiers, outputCommitments, encodedProof } = + await prepareNullifierWithdrawProof( + Alice, + [utxo100, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + outputCommitment, + root.bigInt(), + merkleProofs + ); // Alice withdraws her UTXOs to ERC20 tokens - await expect(zeto.connect(Alice.signer).withdraw(80, nullifiers, outputCommitments[0], root.bigInt(), encodedProof)).rejectedWith("UTXOAlreadySpent"); + await expect( + zeto + .connect(Alice.signer) + .withdraw( + 80, + nullifiers, + outputCommitments[0], + root.bigInt(), + encodedProof + ) + ).rejectedWith('UTXOAlreadySpent'); }); - it("mint existing unspent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo4])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing unspent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("mint existing spent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo1])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing spent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("transfer spent UTXOs should fail (double spend protection)", async function () { + it('transfer spent UTXOs should fail (double spend protection)', async function () { // create outputs const _utxo1 = newUTXO(25, Bob); const _utxo2 = newUTXO(5, Alice); @@ -303,14 +436,33 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti // generate inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo1.hash, root); - const proof2 = await smtAlice.generateCircomVerifierProof(utxo2.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; - - await expect(doTransfer(Alice, [utxo1, utxo2], [nullifier1, nullifier2], [_utxo1, _utxo2], root.bigInt(), merkleProofs, [Bob, Alice])).rejectedWith("UTXOAlreadySpent") + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo1.hash, + root + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + utxo2.hash, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; + + await expect( + doTransfer( + Alice, + [utxo1, utxo2], + [nullifier1, nullifier2], + [_utxo1, _utxo2], + root.bigInt(), + merkleProofs, + [Bob, Alice] + ) + ).rejectedWith('UTXOAlreadySpent'); }).timeout(600000); - it("transfer with existing UTXOs in the output should fail (mass conservation protection)", async function () { + it('transfer with existing UTXOs in the output should fail (mass conservation protection)', async function () { // give Bob another UTXO to be able to spend const _utxo1 = newUTXO(15, Bob); await doMint(zeto, deployer, [_utxo1]); @@ -320,13 +472,29 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti const nullifier2 = newNullifier(_utxo1, Bob); let root = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); - const proof2 = await smtBob.generateCircomVerifierProof(_utxo1.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; - - await expect(doTransfer(Bob, [utxo7, _utxo1], [nullifier1, nullifier2], [utxo1, utxo2], root.bigInt(), merkleProofs, [Alice, Alice])).rejectedWith("UTXOAlreadyOwned") + const proof2 = await smtBob.generateCircomVerifierProof( + _utxo1.hash, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; + + await expect( + doTransfer( + Bob, + [utxo7, _utxo1], + [nullifier1, nullifier2], + [utxo1, utxo2], + root.bigInt(), + merkleProofs, + [Alice, Alice] + ) + ).rejectedWith('UTXOAlreadyOwned'); }).timeout(600000); - it("spend by using the same UTXO as both inputs should fail", async function () { + it('spend by using the same UTXO as both inputs should fail', async function () { const _utxo1 = newUTXO(20, Alice); const _utxo2 = newUTXO(10, Bob); const nullifier1 = newNullifier(utxo7, Bob); @@ -335,12 +503,25 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); const proof2 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; - - await expect(doTransfer(Bob, [utxo7, utxo7], [nullifier1, nullifier2], [_utxo1, _utxo2], root.bigInt(), merkleProofs, [Alice, Bob])).rejectedWith(`UTXODuplicate`); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; + + await expect( + doTransfer( + Bob, + [utxo7, utxo7], + [nullifier1, nullifier2], + [_utxo1, _utxo2], + root.bigInt(), + merkleProofs, + [Alice, Bob] + ) + ).rejectedWith(`UTXODuplicate`); }).timeout(600000); - it("transfer non-existing UTXOs should fail", async function () { + it('transfer non-existing UTXOs should fail', async function () { const nonExisting1 = newUTXO(25, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); @@ -354,44 +535,111 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti // generate inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(nonExisting1.hash, root); - const proof2 = await smtAlice.generateCircomVerifierProof(nonExisting2.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const proof1 = await smtAlice.generateCircomVerifierProof( + nonExisting1.hash, + root + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + nonExisting2.hash, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // propose the output UTXOs const _utxo1 = newUTXO(30, Charlie); utxo7 = newUTXO(15, Bob); - await expect(doTransfer(Alice, [nonExisting1, nonExisting2], [nullifier1, nullifier2], [utxo7, _utxo1], root.bigInt(), merkleProofs, [Bob, Charlie])).rejectedWith("UTXORootNotFound"); + await expect( + doTransfer( + Alice, + [nonExisting1, nonExisting2], + [nullifier1, nullifier2], + [utxo7, _utxo1], + root.bigInt(), + merkleProofs, + [Bob, Charlie] + ) + ).rejectedWith('UTXORootNotFound'); }).timeout(600000); }); - async function doTransfer(signer: User, inputs: UTXO[], _nullifiers: UTXO[], outputs: UTXO[], root: BigInt, merkleProofs: BigInt[][], owners: User[]) { + async function doTransfer( + signer: User, + inputs: UTXO[], + _nullifiers: UTXO[], + outputs: UTXO[], + root: BigInt, + merkleProofs: BigInt[][], + owners: User[] + ) { let nullifiers: [BigNumberish, BigNumberish]; let outputCommitments: [BigNumberish, BigNumberish]; let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; - const result = await prepareProof(signer, inputs, _nullifiers, outputs, root, merkleProofs, owners); - nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [BigNumberish, BigNumberish]; + const result = await prepareProof( + signer, + inputs, + _nullifiers, + outputs, + root, + merkleProofs, + owners + ); + nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ + BigNumberish, + BigNumberish + ]; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; encryptedValues = result.encryptedValues; encryptionNonce = result.encryptionNonce; - const txResult = await sendTx(signer, nullifiers, outputCommitments, root, encryptedValues, encryptionNonce, encodedProof); + const txResult = await sendTx( + signer, + nullifiers, + outputCommitments, + root, + encryptedValues, + encryptionNonce, + encodedProof + ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { txResult, plainTextSalt: outputs[0].salt }; } - async function prepareProof(signer: User, inputs: UTXO[], _nullifiers: UTXO[], outputs: UTXO[], root: BigInt, merkleProof: BigInt[][], owners: User[]) { - const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [BigNumberish, BigNumberish]; - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map((input) => input.hash) as [BigNumberish, BigNumberish]; + async function prepareProof( + signer: User, + inputs: UTXO[], + _nullifiers: UTXO[], + outputs: UTXO[], + root: BigInt, + merkleProof: BigInt[][], + owners: User[] + ) { + const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ + BigNumberish, + BigNumberish + ]; + const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + (input) => input.hash + ) as [BigNumberish, BigNumberish]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map((output) => output.hash) as [BigNumberish, BigNumberish]; + const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + (output) => output.hash + ) as [BigNumberish, BigNumberish]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [[BigNumberish, BigNumberish], [BigNumberish, BigNumberish]] = owners.map(owner => owner.babyJubPublicKey) as [[BigNumberish, BigNumberish], [BigNumberish, BigNumberish]]; + const outputOwnerPublicKeys: [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ] = owners.map((owner) => owner.babyJubPublicKey) as [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, @@ -412,19 +660,21 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti outputSalts: outputs.map((output) => output.salt), outputOwnerPublicKeys, authorityPublicKey: Authority.babyJubPublicKey, - ...encryptInputs + ...encryptInputs, }; - const witness = await circuit.calculateWTNSBin( - inputObj, - true - ); + const witness = await circuit.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKey, witness) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; + const { proof, publicSignals } = (await groth16.prove( + provingKey, + witness + )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; - console.log(`Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`); + console.log( + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + ); const encodedProof = encodeProof(proof); return { @@ -432,7 +682,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti outputCommitments, encryptedValues: publicSignals.slice(0, 20), encryptionNonce, - encodedProof + encodedProof, }; } @@ -458,10 +708,14 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti encryptedValuesForReceiver, encryptedValuesForRegulator, encodedProof, - "0x" + '0x' ); const results: ContractTransactionReceipt | null = await tx.wait(); - console.log(`Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${results?.gasUsed}`); + console.log( + `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ + results?.gasUsed + }` + ); return results; } }); diff --git a/solidity/test/zeto_anon_nullifier.ts b/solidity/test/zeto_anon_nullifier.ts index 82bbee4..19f1f53 100644 --- a/solidity/test/zeto_anon_nullifier.ts +++ b/solidity/test/zeto_anon_nullifier.ts @@ -17,14 +17,27 @@ import { ethers, network } from 'hardhat'; import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; import { expect } from 'chai'; -import { loadCircuit, Poseidon, encodeProof } from "zeto-js"; +import { loadCircuit, Poseidon, encodeProof } from 'zeto-js'; import { groth16 } from 'snarkjs'; import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; -import { UTXO, User, newUser, newUTXO, newNullifier, doMint, ZERO_UTXO, parseUTXOEvents } from './lib/utils'; -import { loadProvingKeys, prepareDepositProof, prepareNullifierWithdrawProof } from './utils'; +import { + UTXO, + User, + newUser, + newUTXO, + newNullifier, + doMint, + ZERO_UTXO, + parseUTXOEvents, +} from './lib/utils'; +import { + loadProvingKeys, + prepareDepositProof, + prepareNullifierWithdrawProof, +} from './utils'; import { deployZeto } from './lib/deploy'; -describe("Zeto based fungible token with anonymity using nullifiers without encryption", function () { +describe('Zeto based fungible token with anonymity using nullifiers without encryption', function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -58,21 +71,21 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr circuit = await loadCircuit('anon_nullifier'); ({ provingKeyFile: provingKey } = loadProvingKeys('anon_nullifier')); - const storage1 = new InMemoryDB(str2Bytes("")) + const storage1 = new InMemoryDB(str2Bytes('')); smtAlice = new Merkletree(storage1, true, 64); - const storage2 = new InMemoryDB(str2Bytes("")) + const storage2 = new InMemoryDB(str2Bytes('')); smtBob = new Merkletree(storage2, true, 64); }); - it("onchain SMT root should be equal to the offchain SMT root", async function () { + it('onchain SMT root should be equal to the offchain SMT root', async function () { const root = await smtAlice.root(); const onchainRoot = await zeto.getRoot(); expect(onchainRoot).to.equal(0n); expect(root.string()).to.equal(onchainRoot.toString()); }); - it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { + it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -83,17 +96,20 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr await tx1.wait(); utxo100 = newUTXO(100, Alice); - const { outputCommitments, encodedProof } = await prepareDepositProof(Alice, utxo100); + const { outputCommitments, encodedProof } = await prepareDepositProof( + Alice, + utxo100 + ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, "0x"); + .deposit(100, outputCommitments[0], encodedProof, '0x'); await tx2.wait(); await smtAlice.add(utxo100.hash, utxo100.hash); await smtBob.add(utxo100.hash, utxo100.hash); }); - it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { + it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // The authority mints a new UTXO and assigns it to Alice utxo1 = newUTXO(10, Alice); @@ -128,10 +144,21 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr // Alice generates inclusion proofs for the UTXOs to be spent const proof1 = await smtAlice.generateCircomVerifierProof(utxo1.hash, root); const proof2 = await smtAlice.generateCircomVerifierProof(utxo2.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice transfers her UTXOs to Bob - const result2 = await doTransfer(Alice, [utxo1, utxo2], [nullifier1, nullifier2], [_utxo3, utxo4], root.bigInt(), merkleProofs, [Bob, Alice]); + const result2 = await doTransfer( + Alice, + [utxo1, utxo2], + [nullifier1, nullifier2], + [_utxo3, utxo4], + root.bigInt(), + merkleProofs, + [Bob, Alice] + ); // check the private transfer activity is not exposed in the ERC20 contract const afterTransferBalance = await erc20.balanceOf(Alice.ethAddress); @@ -158,14 +185,19 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr const receivedValue = _utxo3.value!; const receivedSalt = _utxo3.salt; const incomingUTXOs: any = events[0].outputs; - const hash = Poseidon.poseidon4([BigInt(receivedValue), receivedSalt, Bob.babyJubPublicKey[0], Bob.babyJubPublicKey[1]]); + const hash = Poseidon.poseidon4([ + BigInt(receivedValue), + receivedSalt, + Bob.babyJubPublicKey[0], + Bob.babyJubPublicKey[1], + ]); expect(incomingUTXOs[0]).to.equal(hash); // Bob uses the decrypted values to construct the UTXO received from the transaction utxo3 = newUTXO(receivedValue, Bob, receivedSalt); }).timeout(600000); - it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { + it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { // Bob generates the nullifiers for the UTXO to be spent const nullifier1 = newNullifier(utxo3, Bob); @@ -173,14 +205,25 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr const root = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof(utxo3.hash, root); const proof2 = await smtBob.generateCircomVerifierProof(0n, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Bob proposes the output UTXOs const utxo6 = newUTXO(10, Charlie); utxo7 = newUTXO(15, Bob); // Bob should be able to spend the UTXO that was reconstructed from the previous transaction - const result = await doTransfer(Bob, [utxo3, ZERO_UTXO], [nullifier1, ZERO_UTXO], [utxo6, utxo7], root.bigInt(), merkleProofs, [Charlie, Bob]); + const result = await doTransfer( + Bob, + [utxo3, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + [utxo6, utxo7], + root.bigInt(), + merkleProofs, + [Charlie, Bob] + ); // Bob keeps the local SMT in sync await smtBob.add(utxo6.hash, utxo6.hash); @@ -192,7 +235,7 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr await smtAlice.add(events[0].outputs[1], events[0].outputs[1]); }).timeout(600000); - it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { + it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice generates the nullifiers for the UTXOs to be spent @@ -200,17 +243,39 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr // Alice generates inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo100.hash, root); + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo100.hash, + root + ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice proposes the output ERC20 tokens const withdrawChangesUTXO = newUTXO(20, Alice); - const { nullifiers, outputCommitments, encodedProof } = await prepareNullifierWithdrawProof(Alice, [utxo100, ZERO_UTXO], [nullifier1, ZERO_UTXO], withdrawChangesUTXO, root.bigInt(), merkleProofs); + const { nullifiers, outputCommitments, encodedProof } = + await prepareNullifierWithdrawProof( + Alice, + [utxo100, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + withdrawChangesUTXO, + root.bigInt(), + merkleProofs + ); // Alice withdraws her UTXOs to ERC20 tokens - const tx = await zeto.connect(Alice.signer).withdraw(80, nullifiers, outputCommitments[0], root.bigInt(), encodedProof); + const tx = await zeto + .connect(Alice.signer) + .withdraw( + 80, + nullifiers, + outputCommitments[0], + root.bigInt(), + encodedProof + ); await tx.wait(); // Alice tracks the UTXO inside the SMT @@ -223,7 +288,7 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr expect(endingBalance - startingBalance).to.be.equal(80); }); - describe("failure cases", function () { + describe('failure cases', function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks @@ -231,33 +296,61 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr return; } - it("Alice attempting to withdraw spent UTXOs should fail", async function () { + it('Alice attempting to withdraw spent UTXOs should fail', async function () { // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); // Alice generates inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo100.hash, root); + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo100.hash, + root + ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice proposes the output ERC20 tokens const outputCommitment = newUTXO(90, Alice); - const { nullifiers, outputCommitments, encodedProof } = await prepareNullifierWithdrawProof(Alice, [utxo100, ZERO_UTXO], [nullifier1, ZERO_UTXO], outputCommitment, root.bigInt(), merkleProofs); - - await expect(zeto.connect(Alice.signer).withdraw(10, nullifiers, outputCommitments[0], root.bigInt(), encodedProof)).rejectedWith("UTXOAlreadySpent"); + const { nullifiers, outputCommitments, encodedProof } = + await prepareNullifierWithdrawProof( + Alice, + [utxo100, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + outputCommitment, + root.bigInt(), + merkleProofs + ); + + await expect( + zeto + .connect(Alice.signer) + .withdraw( + 10, + nullifiers, + outputCommitments[0], + root.bigInt(), + encodedProof + ) + ).rejectedWith('UTXOAlreadySpent'); }); - it("mint existing unspent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo4])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing unspent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("mint existing spent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo1])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing spent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("transfer spent UTXOs should fail (double spend protection)", async function () { + it('transfer spent UTXOs should fail (double spend protection)', async function () { // create outputs const _utxo1 = newUTXO(25, Bob); const _utxo2 = newUTXO(5, Alice); @@ -268,14 +361,33 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr // generate inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo1.hash, root); - const proof2 = await smtAlice.generateCircomVerifierProof(utxo2.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; - - await expect(doTransfer(Alice, [utxo1, utxo2], [nullifier1, nullifier2], [_utxo1, _utxo2], root.bigInt(), merkleProofs, [Bob, Alice])).rejectedWith("UTXOAlreadySpent") + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo1.hash, + root + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + utxo2.hash, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; + + await expect( + doTransfer( + Alice, + [utxo1, utxo2], + [nullifier1, nullifier2], + [_utxo1, _utxo2], + root.bigInt(), + merkleProofs, + [Bob, Alice] + ) + ).rejectedWith('UTXOAlreadySpent'); }).timeout(600000); - it("transfer with existing UTXOs in the output should fail (mass conservation protection)", async function () { + it('transfer with existing UTXOs in the output should fail (mass conservation protection)', async function () { // give Bob another UTXO to be able to spend const _utxo1 = newUTXO(15, Bob); await doMint(zeto, deployer, [_utxo1]); @@ -285,13 +397,29 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr const nullifier2 = newNullifier(_utxo1, Bob); let root = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); - const proof2 = await smtBob.generateCircomVerifierProof(_utxo1.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; - - await expect(doTransfer(Bob, [utxo7, _utxo1], [nullifier1, nullifier2], [utxo1, utxo2], root.bigInt(), merkleProofs, [Alice, Alice])).rejectedWith("UTXOAlreadyOwned") + const proof2 = await smtBob.generateCircomVerifierProof( + _utxo1.hash, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; + + await expect( + doTransfer( + Bob, + [utxo7, _utxo1], + [nullifier1, nullifier2], + [utxo1, utxo2], + root.bigInt(), + merkleProofs, + [Alice, Alice] + ) + ).rejectedWith('UTXOAlreadyOwned'); }).timeout(600000); - it("spend by using the same UTXO as both inputs should fail", async function () { + it('spend by using the same UTXO as both inputs should fail', async function () { const _utxo1 = newUTXO(20, Alice); const _utxo2 = newUTXO(10, Bob); const nullifier1 = newNullifier(utxo7, Bob); @@ -300,12 +428,25 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr let root = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); const proof2 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; - - await expect(doTransfer(Bob, [utxo7, utxo7], [nullifier1, nullifier2], [_utxo1, _utxo2], root.bigInt(), merkleProofs, [Alice, Bob])).rejectedWith(`UTXODuplicate`); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; + + await expect( + doTransfer( + Bob, + [utxo7, utxo7], + [nullifier1, nullifier2], + [_utxo1, _utxo2], + root.bigInt(), + merkleProofs, + [Alice, Bob] + ) + ).rejectedWith(`UTXODuplicate`); }).timeout(600000); - it("transfer non-existing UTXOs should fail", async function () { + it('transfer non-existing UTXOs should fail', async function () { const nonExisting1 = newUTXO(25, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); @@ -319,18 +460,37 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr // generate inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(nonExisting1.hash, root); - const proof2 = await smtAlice.generateCircomVerifierProof(nonExisting2.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const proof1 = await smtAlice.generateCircomVerifierProof( + nonExisting1.hash, + root + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + nonExisting2.hash, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // propose the output UTXOs const _utxo1 = newUTXO(30, Charlie); utxo7 = newUTXO(15, Bob); - await expect(doTransfer(Alice, [nonExisting1, nonExisting2], [nullifier1, nullifier2], [utxo7, _utxo1], root.bigInt(), merkleProofs, [Bob, Charlie])).rejectedWith("UTXORootNotFound"); + await expect( + doTransfer( + Alice, + [nonExisting1, nonExisting2], + [nullifier1, nullifier2], + [utxo7, _utxo1], + root.bigInt(), + merkleProofs, + [Bob, Charlie] + ) + ).rejectedWith('UTXORootNotFound'); }).timeout(600000); - it("repeated mint calls with single UTXO should not fail", async function () { + it('repeated mint calls with single UTXO should not fail', async function () { const utxo5 = newUTXO(10, Alice); await expect(doMint(zeto, deployer, [utxo5, ZERO_UTXO])).fulfilled; const utxo6 = newUTXO(20, Alice); @@ -338,28 +498,74 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr }); }); - async function doTransfer(signer: User, inputs: UTXO[], _nullifiers: UTXO[], outputs: UTXO[], root: BigInt, merkleProofs: BigInt[][], owners: User[]) { + async function doTransfer( + signer: User, + inputs: UTXO[], + _nullifiers: UTXO[], + outputs: UTXO[], + root: BigInt, + merkleProofs: BigInt[][], + owners: User[] + ) { let nullifiers: [BigNumberish, BigNumberish]; let outputCommitments: [BigNumberish, BigNumberish]; let encodedProof: any; - const result = await prepareProof(signer, inputs, _nullifiers, outputs, root, merkleProofs, owners); - nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [BigNumberish, BigNumberish]; + const result = await prepareProof( + signer, + inputs, + _nullifiers, + outputs, + root, + merkleProofs, + owners + ); + nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ + BigNumberish, + BigNumberish + ]; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; - const txResult = await sendTx(signer, nullifiers, outputCommitments, root, encodedProof); + const txResult = await sendTx( + signer, + nullifiers, + outputCommitments, + root, + encodedProof + ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { txResult, plainTextSalt: outputs[0].salt }; } - async function prepareProof(signer: User, inputs: UTXO[], _nullifiers: UTXO[], outputs: UTXO[], root: BigInt, merkleProof: BigInt[][], owners: User[]) { - const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [BigNumberish, BigNumberish]; - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map((input) => input.hash) as [BigNumberish, BigNumberish]; + async function prepareProof( + signer: User, + inputs: UTXO[], + _nullifiers: UTXO[], + outputs: UTXO[], + root: BigInt, + merkleProof: BigInt[][], + owners: User[] + ) { + const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ + BigNumberish, + BigNumberish + ]; + const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + (input) => input.hash + ) as [BigNumberish, BigNumberish]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map((output) => output.hash) as [BigNumberish, BigNumberish]; + const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + (output) => output.hash + ) as [BigNumberish, BigNumberish]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [[BigNumberish, BigNumberish], [BigNumberish, BigNumberish]] = owners.map(owner => owner.babyJubPublicKey) as [[BigNumberish, BigNumberish], [BigNumberish, BigNumberish]]; + const outputOwnerPublicKeys: [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ] = owners.map((owner) => owner.babyJubPublicKey) as [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ]; const startWitnessCalculation = Date.now(); const inputObj = { @@ -376,23 +582,25 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr outputSalts: outputs.map((output) => output.salt), outputOwnerPublicKeys, }; - const witness = await circuit.calculateWTNSBin( - inputObj, - true - ); + const witness = await circuit.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKey, witness) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; + const { proof, publicSignals } = (await groth16.prove( + provingKey, + witness + )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; - console.log(`Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`); + console.log( + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + ); const encodedProof = encodeProof(proof); return { inputCommitments, outputCommitments, - encodedProof + encodedProof, }; } @@ -406,9 +614,13 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr const startTx = Date.now(); const tx = await zeto .connect(signer.signer) - .transfer(nullifiers, outputCommitments, root, encodedProof, "0x"); + .transfer(nullifiers, outputCommitments, root, encodedProof, '0x'); const results: ContractTransactionReceipt | null = await tx.wait(); - console.log(`Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${results?.gasUsed}`); + console.log( + `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ + results?.gasUsed + }` + ); return results; } }); diff --git a/solidity/test/zeto_anon_nullifier_kyc.ts b/solidity/test/zeto_anon_nullifier_kyc.ts index 3abaf07..62a9be7 100644 --- a/solidity/test/zeto_anon_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_nullifier_kyc.ts @@ -17,14 +17,28 @@ import { ethers, network } from 'hardhat'; import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; import { expect } from 'chai'; -import { loadCircuit, Poseidon, encodeProof, kycHash } from "zeto-js"; +import { loadCircuit, Poseidon, encodeProof, kycHash } from 'zeto-js'; import { groth16 } from 'snarkjs'; import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; -import { UTXO, User, newUser, newUTXO, newNullifier, doMint, ZERO_UTXO, parseUTXOEvents, parseRegistryEvents } from './lib/utils'; -import { loadProvingKeys, prepareDepositProof, prepareNullifierWithdrawProof } from './utils'; +import { + UTXO, + User, + newUser, + newUTXO, + newNullifier, + doMint, + ZERO_UTXO, + parseUTXOEvents, + parseRegistryEvents, +} from './lib/utils'; +import { + loadProvingKeys, + prepareDepositProof, + prepareNullifierWithdrawProof, +} from './utils'; import { deployZeto } from './lib/deploy'; -describe("Zeto based fungible token with anonymity, KYC, using nullifiers without encryption", function () { +describe('Zeto based fungible token with anonymity, KYC, using nullifiers without encryption', function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -70,13 +84,13 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou circuit = await loadCircuit('anon_nullifier_kyc'); ({ provingKeyFile: provingKey } = loadProvingKeys('anon_nullifier_kyc')); - const storage1 = new InMemoryDB(str2Bytes("alice")) + const storage1 = new InMemoryDB(str2Bytes('alice')); smtAlice = new Merkletree(storage1, true, 64); - const storage2 = new InMemoryDB(str2Bytes("bob")) + const storage2 = new InMemoryDB(str2Bytes('bob')); smtBob = new Merkletree(storage2, true, 64); - const storage3 = new InMemoryDB(str2Bytes("kyc")) + const storage3 = new InMemoryDB(str2Bytes('kyc')); smtKyc = new Merkletree(storage3, true, 10); const publicKey1 = parseRegistryEvents(zeto, result1); @@ -87,14 +101,14 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou await smtKyc.add(kycHash(publicKey3), kycHash(publicKey3)); }); - it("onchain SMT root should be equal to the offchain SMT root", async function () { + it('onchain SMT root should be equal to the offchain SMT root', async function () { const root = await smtAlice.root(); const onchainRoot = await zeto.getRoot(); expect(onchainRoot).to.equal(0n); expect(root.string()).to.equal(onchainRoot.toString()); }); - it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { + it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -111,14 +125,14 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, "0x"); + .deposit(100, outputCommitments[0], encodedProof, '0x'); await tx2.wait(); await smtAlice.add(utxo100.hash, utxo100.hash); await smtBob.add(utxo100.hash, utxo100.hash); }); - it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { + it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // The authority mints a new UTXO and assigns it to Alice utxo1 = newUTXO(10, Alice); @@ -151,22 +165,47 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou const nullifier2 = newNullifier(utxo2, Alice); // Alice generates inclusion proofs for the UTXOs to be spent - const proof1 = await smtAlice.generateCircomVerifierProof(utxo1.hash, utxosRoot); - const proof2 = await smtAlice.generateCircomVerifierProof(utxo2.hash, utxosRoot); - const utxoMerkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo1.hash, + utxosRoot + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + utxo2.hash, + utxosRoot + ); + const utxoMerkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice generates inclusion proofs for the identities in the transaction const identitiesRoot = await smtKyc.root(); - const proof3 = await smtKyc.generateCircomVerifierProof(kycHash(Alice.babyJubPublicKey), identitiesRoot); - const proof4 = await smtKyc.generateCircomVerifierProof(kycHash(Bob.babyJubPublicKey), identitiesRoot); + const proof3 = await smtKyc.generateCircomVerifierProof( + kycHash(Alice.babyJubPublicKey), + identitiesRoot + ); + const proof4 = await smtKyc.generateCircomVerifierProof( + kycHash(Bob.babyJubPublicKey), + identitiesRoot + ); const identityMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) proof4.siblings.map((s) => s.bigInt()), // identity proof for the 1st owner of the output UTXO (Bob) - proof3.siblings.map((s) => s.bigInt()) // identity proof for the 2nd owner of the output UTXO (Alice) + proof3.siblings.map((s) => s.bigInt()), // identity proof for the 2nd owner of the output UTXO (Alice) ]; // Alice transfers her UTXOs to Bob - const result2 = await doTransfer(Alice, [utxo1, utxo2], [nullifier1, nullifier2], [_utxo3, utxo4], utxosRoot.bigInt(), utxoMerkleProofs, identitiesRoot.bigInt(), identityMerkleProofs, [Bob, Alice]); + const result2 = await doTransfer( + Alice, + [utxo1, utxo2], + [nullifier1, nullifier2], + [_utxo3, utxo4], + utxosRoot.bigInt(), + utxoMerkleProofs, + identitiesRoot.bigInt(), + identityMerkleProofs, + [Bob, Alice] + ); // check the private transfer activity is not exposed in the ERC20 contract const afterTransferBalance = await erc20.balanceOf(Alice.ethAddress); @@ -193,22 +232,33 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou const receivedValue = _utxo3.value!; const receivedSalt = _utxo3.salt; const incomingUTXOs: any = events[0].outputs; - const hash = Poseidon.poseidon4([BigInt(receivedValue), receivedSalt, Bob.babyJubPublicKey[0], Bob.babyJubPublicKey[1]]); + const hash = Poseidon.poseidon4([ + BigInt(receivedValue), + receivedSalt, + Bob.babyJubPublicKey[0], + Bob.babyJubPublicKey[1], + ]); expect(incomingUTXOs[0]).to.equal(hash); // Bob uses the decrypted values to construct the UTXO received from the transaction utxo3 = newUTXO(receivedValue, Bob, receivedSalt); }).timeout(600000); - it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { + it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { // Bob generates the nullifiers for the UTXO to be spent const nullifier1 = newNullifier(utxo3, Bob); // Bob generates inclusion proofs for the UTXOs to be spent, as private input to the proof generation const utxosRoot = await smtBob.root(); - const proof1 = await smtBob.generateCircomVerifierProof(utxo3.hash, utxosRoot); + const proof1 = await smtBob.generateCircomVerifierProof( + utxo3.hash, + utxosRoot + ); const proof2 = await smtBob.generateCircomVerifierProof(0n, utxosRoot); - const utxosMerkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const utxosMerkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Bob proposes the output UTXOs utxo6 = newUTXO(10, Charlie); @@ -218,16 +268,32 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou // using a shortcut with a shared SMT for all identities, but obviously // Bob would need his own SMT instance in a real-world scenario const identitiesRoot = await smtKyc.root(); - const proof3 = await smtKyc.generateCircomVerifierProof(kycHash(Bob.babyJubPublicKey), identitiesRoot); - const proof4 = await smtKyc.generateCircomVerifierProof(kycHash(Charlie.babyJubPublicKey), identitiesRoot); + const proof3 = await smtKyc.generateCircomVerifierProof( + kycHash(Bob.babyJubPublicKey), + identitiesRoot + ); + const proof4 = await smtKyc.generateCircomVerifierProof( + kycHash(Charlie.babyJubPublicKey), + identitiesRoot + ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Bob) proof4.siblings.map((s) => s.bigInt()), // identity proof for the 1st owner of the output UTXO (Charlie) - proof3.siblings.map((s) => s.bigInt()) // identity proof for the 2nd owner of the output UTXO (Bob) + proof3.siblings.map((s) => s.bigInt()), // identity proof for the 2nd owner of the output UTXO (Bob) ]; // Bob should be able to spend the UTXO that was reconstructed from the previous transaction - const result = await doTransfer(Bob, [utxo3, ZERO_UTXO], [nullifier1, ZERO_UTXO], [utxo6, utxo7], utxosRoot.bigInt(), utxosMerkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, [Charlie, Bob]); + const result = await doTransfer( + Bob, + [utxo3, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + [utxo6, utxo7], + utxosRoot.bigInt(), + utxosMerkleProofs, + identitiesRoot.bigInt(), + identitiesMerkleProofs, + [Charlie, Bob] + ); // Bob keeps the local SMT in sync await smtBob.add(utxo6.hash, utxo6.hash); @@ -237,26 +303,47 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou const events = parseUTXOEvents(zeto, result.txResult!); await smtAlice.add(events[0].outputs[0], events[0].outputs[0]); await smtAlice.add(events[0].outputs[1], events[0].outputs[1]); - }).timeout(600000); - it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { + it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); // Alice generates inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo100.hash, root); + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo100.hash, + root + ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice proposes the output UTXO as remainder of the withdrawal withdrawChangeUTXO = newUTXO(20, Alice); - const { nullifiers, outputCommitments, encodedProof } = await prepareNullifierWithdrawProof(Alice, [utxo100, ZERO_UTXO], [nullifier1, ZERO_UTXO], withdrawChangeUTXO, root.bigInt(), merkleProofs); + const { nullifiers, outputCommitments, encodedProof } = + await prepareNullifierWithdrawProof( + Alice, + [utxo100, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + withdrawChangeUTXO, + root.bigInt(), + merkleProofs + ); // Alice withdraws her UTXOs to ERC20 tokens - const tx = await zeto.connect(Alice.signer).withdraw(80, nullifiers, outputCommitments[0], root.bigInt(), encodedProof); + const tx = await zeto + .connect(Alice.signer) + .withdraw( + 80, + nullifiers, + outputCommitments[0], + root.bigInt(), + encodedProof + ); await tx.wait(); // Alice tracks the UTXO inside the SMT @@ -269,20 +356,24 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou expect(endingBalance - startingBalance).to.be.equal(80); }); - describe("unregistered user flows", function () { + describe('unregistered user flows', function () { let storage3; let smtUnregistered: Merkletree; let unregisteredUtxo100: UTXO; before(() => { - storage3 = new InMemoryDB(str2Bytes("unregistered")); + storage3 = new InMemoryDB(str2Bytes('unregistered')); smtUnregistered = new Merkletree(storage3, true, 64); }); - it("deposit by an unregistered user should succeed", async function () { - const tx = await erc20.connect(deployer).mint(unregistered.ethAddress, 100); + it('deposit by an unregistered user should succeed', async function () { + const tx = await erc20 + .connect(deployer) + .mint(unregistered.ethAddress, 100); await tx.wait(); - const tx1 = await erc20.connect(unregistered.signer).approve(zeto.target, 100); + const tx1 = await erc20 + .connect(unregistered.signer) + .approve(zeto.target, 100); await tx1.wait(); unregisteredUtxo100 = newUTXO(100, unregistered); @@ -292,7 +383,7 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou ); const tx2 = await zeto .connect(unregistered.signer) - .deposit(100, outputCommitments[0], encodedProof, "0x"); + .deposit(100, outputCommitments[0], encodedProof, '0x'); await tx2.wait(); // Alice tracks the UTXO inside the SMT @@ -301,7 +392,7 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou await smtBob.add(unregisteredUtxo100.hash, unregisteredUtxo100.hash); }); - it("transfer from an unregistered user should fail", async function () { + it('transfer from an unregistered user should fail', async function () { // catch up the local SMT for the unregistered user await smtUnregistered.add(utxo100.hash, utxo100.hash); await smtUnregistered.add(utxo1.hash, utxo1.hash); @@ -310,53 +401,117 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou await smtUnregistered.add(utxo4.hash, utxo4.hash); await smtUnregistered.add(utxo6.hash, utxo6.hash); await smtUnregistered.add(utxo7.hash, utxo7.hash); - await smtUnregistered.add(withdrawChangeUTXO.hash, withdrawChangeUTXO.hash); - await smtUnregistered.add(unregisteredUtxo100.hash, unregisteredUtxo100.hash); + await smtUnregistered.add( + withdrawChangeUTXO.hash, + withdrawChangeUTXO.hash + ); + await smtUnregistered.add( + unregisteredUtxo100.hash, + unregisteredUtxo100.hash + ); const utxosRoot = await smtUnregistered.root(); const nullifier = newNullifier(unregisteredUtxo100, unregistered); const output1 = newUTXO(100, Bob); const output2 = newUTXO(0, unregistered); - const proof = await smtUnregistered.generateCircomVerifierProof(unregisteredUtxo100.hash, utxosRoot); - const merkleProofs = [proof.siblings.map((s) => s.bigInt()), proof.siblings.map((s) => s.bigInt())]; + const proof = await smtUnregistered.generateCircomVerifierProof( + unregisteredUtxo100.hash, + utxosRoot + ); + const merkleProofs = [ + proof.siblings.map((s) => s.bigInt()), + proof.siblings.map((s) => s.bigInt()), + ]; // add the unregistered user to the local KYC SMT, but not to the onchain SMT - await smtKyc.add(kycHash(unregistered.babyJubPublicKey), kycHash(unregistered.babyJubPublicKey)); + await smtKyc.add( + kycHash(unregistered.babyJubPublicKey), + kycHash(unregistered.babyJubPublicKey) + ); const identitiesRoot = await smtKyc.root(); - const proof3 = await smtKyc.generateCircomVerifierProof(kycHash(unregistered.babyJubPublicKey), identitiesRoot); - const proof4 = await smtKyc.generateCircomVerifierProof(kycHash(Bob.babyJubPublicKey), identitiesRoot); + const proof3 = await smtKyc.generateCircomVerifierProof( + kycHash(unregistered.babyJubPublicKey), + identitiesRoot + ); + const proof4 = await smtKyc.generateCircomVerifierProof( + kycHash(Bob.babyJubPublicKey), + identitiesRoot + ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (unregistered) proof4.siblings.map((s) => s.bigInt()), // identity proof for the 1st owner of the output UTXO (Bob) - proof3.siblings.map((s) => s.bigInt()) // identity proof for the 2nd owner of the output UTXO (unregistered) + proof3.siblings.map((s) => s.bigInt()), // identity proof for the 2nd owner of the output UTXO (unregistered) ]; - await expect(doTransfer(unregistered, [unregisteredUtxo100, ZERO_UTXO], [nullifier, ZERO_UTXO], [output1, output2], utxosRoot.bigInt(), merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, [Bob, unregistered])).rejectedWith("Invalid proof"); + await expect( + doTransfer( + unregistered, + [unregisteredUtxo100, ZERO_UTXO], + [nullifier, ZERO_UTXO], + [output1, output2], + utxosRoot.bigInt(), + merkleProofs, + identitiesRoot.bigInt(), + identitiesMerkleProofs, + [Bob, unregistered] + ) + ).rejectedWith('Invalid proof'); }); - it("the unregistered user can still withdraw their UTXOs to ERC20 tokens", async function () { + it('the unregistered user can still withdraw their UTXOs to ERC20 tokens', async function () { const startingBalance = await erc20.balanceOf(unregistered.ethAddress); // unregistered user generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(unregisteredUtxo100, unregistered); // unregistered user generates inclusion proofs for the UTXOs to be spent let root = await smtUnregistered.root(); - const proof1 = await smtUnregistered.generateCircomVerifierProof(unregisteredUtxo100.hash, root); - const proof2 = await smtUnregistered.generateCircomVerifierProof(0n, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const proof1 = await smtUnregistered.generateCircomVerifierProof( + unregisteredUtxo100.hash, + root + ); + const proof2 = await smtUnregistered.generateCircomVerifierProof( + 0n, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // unregistered user proposes the output ERC20 tokens const unregisteredWithdrawChangeUTXO = newUTXO(0, unregistered); - const { nullifiers, outputCommitments, encodedProof } = await prepareNullifierWithdrawProof(unregistered, [unregisteredUtxo100, ZERO_UTXO], [nullifier1, ZERO_UTXO], unregisteredWithdrawChangeUTXO, root.bigInt(), merkleProofs); + const { nullifiers, outputCommitments, encodedProof } = + await prepareNullifierWithdrawProof( + unregistered, + [unregisteredUtxo100, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + unregisteredWithdrawChangeUTXO, + root.bigInt(), + merkleProofs + ); // unregistered user withdraws her UTXOs to ERC20 tokens - const tx = await zeto.connect(unregistered.signer).withdraw(100, nullifiers, outputCommitments[0], root.bigInt(), encodedProof); + const tx = await zeto + .connect(unregistered.signer) + .withdraw( + 100, + nullifiers, + outputCommitments[0], + root.bigInt(), + encodedProof + ); await tx.wait(); // Alice tracks the UTXO inside the SMT - await smtAlice.add(unregisteredWithdrawChangeUTXO.hash, unregisteredWithdrawChangeUTXO.hash); + await smtAlice.add( + unregisteredWithdrawChangeUTXO.hash, + unregisteredWithdrawChangeUTXO.hash + ); // Bob also locally tracks the UTXOs inside the SMT - await smtBob.add(unregisteredWithdrawChangeUTXO.hash, unregisteredWithdrawChangeUTXO.hash); + await smtBob.add( + unregisteredWithdrawChangeUTXO.hash, + unregisteredWithdrawChangeUTXO.hash + ); // unregistered user checks her ERC20 balance const endingBalance = await erc20.balanceOf(unregistered.ethAddress); @@ -364,7 +519,7 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou }); }); - describe("failure cases", function () { + describe('failure cases', function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks @@ -372,32 +527,60 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou return; } - it("Alice attempting to withdraw spent UTXOs should fail", async function () { + it('Alice attempting to withdraw spent UTXOs should fail', async function () { // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); // Alice generates inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo100.hash, root); + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo100.hash, + root + ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice proposes the output UTXO as remainder of the withdrawal withdrawChangeUTXO = newUTXO(90, Alice); - const { nullifiers, outputCommitments, encodedProof } = await prepareNullifierWithdrawProof(Alice, [utxo100, ZERO_UTXO], [nullifier1, ZERO_UTXO], withdrawChangeUTXO, root.bigInt(), merkleProofs); - - await expect(zeto.connect(Alice.signer).withdraw(10, nullifiers, outputCommitments[0], root.bigInt(), encodedProof)).rejectedWith("UTXOAlreadySpent"); + const { nullifiers, outputCommitments, encodedProof } = + await prepareNullifierWithdrawProof( + Alice, + [utxo100, ZERO_UTXO], + [nullifier1, ZERO_UTXO], + withdrawChangeUTXO, + root.bigInt(), + merkleProofs + ); + + await expect( + zeto + .connect(Alice.signer) + .withdraw( + 10, + nullifiers, + outputCommitments[0], + root.bigInt(), + encodedProof + ) + ).rejectedWith('UTXOAlreadySpent'); }); - it("mint existing unspent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo4])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing unspent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("mint existing spent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo1])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing spent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("transfer spent UTXOs should fail (double spend protection)", async function () { + it('transfer spent UTXOs should fail (double spend protection)', async function () { // create outputs const _utxo1 = newUTXO(25, Bob); const _utxo2 = newUTXO(5, Alice); @@ -408,23 +591,50 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou // generate inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo1.hash, root); - const proof2 = await smtAlice.generateCircomVerifierProof(utxo2.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo1.hash, + root + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + utxo2.hash, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; const identitiesRoot = await smtKyc.root(); - const proof3 = await smtKyc.generateCircomVerifierProof(kycHash(Alice.babyJubPublicKey), identitiesRoot); - const proof4 = await smtKyc.generateCircomVerifierProof(kycHash(Bob.babyJubPublicKey), identitiesRoot); + const proof3 = await smtKyc.generateCircomVerifierProof( + kycHash(Alice.babyJubPublicKey), + identitiesRoot + ); + const proof4 = await smtKyc.generateCircomVerifierProof( + kycHash(Bob.babyJubPublicKey), + identitiesRoot + ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) proof4.siblings.map((s) => s.bigInt()), // identity proof for the 1st owner of the output UTXO (Bob) - proof3.siblings.map((s) => s.bigInt()) // identity proof for the 2nd owner of the output UTXO (Alice) + proof3.siblings.map((s) => s.bigInt()), // identity proof for the 2nd owner of the output UTXO (Alice) ]; - await expect(doTransfer(Alice, [utxo1, utxo2], [nullifier1, nullifier2], [_utxo1, _utxo2], root.bigInt(), merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, [Bob, Alice])).rejectedWith("UTXOAlreadySpent") + await expect( + doTransfer( + Alice, + [utxo1, utxo2], + [nullifier1, nullifier2], + [_utxo1, _utxo2], + root.bigInt(), + merkleProofs, + identitiesRoot.bigInt(), + identitiesMerkleProofs, + [Bob, Alice] + ) + ).rejectedWith('UTXOAlreadySpent'); }).timeout(600000); - it("transfer with existing UTXOs in the output should fail (mass conservation protection)", async function () { + it('transfer with existing UTXOs in the output should fail (mass conservation protection)', async function () { // give Bob another UTXO to be able to spend const _utxo1 = newUTXO(15, Bob); await doMint(zeto, deployer, [_utxo1]); @@ -434,22 +644,46 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou const nullifier2 = newNullifier(_utxo1, Bob); let root = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); - const proof2 = await smtBob.generateCircomVerifierProof(_utxo1.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const proof2 = await smtBob.generateCircomVerifierProof( + _utxo1.hash, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; const identitiesRoot = await smtKyc.root(); - const proof3 = await smtKyc.generateCircomVerifierProof(kycHash(Bob.babyJubPublicKey), identitiesRoot); - const proof4 = await smtKyc.generateCircomVerifierProof(kycHash(Alice.babyJubPublicKey), identitiesRoot); + const proof3 = await smtKyc.generateCircomVerifierProof( + kycHash(Bob.babyJubPublicKey), + identitiesRoot + ); + const proof4 = await smtKyc.generateCircomVerifierProof( + kycHash(Alice.babyJubPublicKey), + identitiesRoot + ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Bob) proof4.siblings.map((s) => s.bigInt()), // identity proof for the 1st owner of the output UTXO (Alice) - proof4.siblings.map((s) => s.bigInt()) // identity proof for the 2nd owner of the output UTXO (Alice) + proof4.siblings.map((s) => s.bigInt()), // identity proof for the 2nd owner of the output UTXO (Alice) ]; - await expect(doTransfer(Bob, [utxo7, _utxo1], [nullifier1, nullifier2], [utxo1, utxo2], root.bigInt(), merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, [Alice, Alice])).rejectedWith("UTXOAlreadyOwned") + await expect( + doTransfer( + Bob, + [utxo7, _utxo1], + [nullifier1, nullifier2], + [utxo1, utxo2], + root.bigInt(), + merkleProofs, + identitiesRoot.bigInt(), + identitiesMerkleProofs, + [Alice, Alice] + ) + ).rejectedWith('UTXOAlreadyOwned'); }).timeout(600000); - it("spend by using the same UTXO as both inputs should fail", async function () { + it('spend by using the same UTXO as both inputs should fail', async function () { const _utxo1 = newUTXO(20, Alice); const _utxo2 = newUTXO(10, Bob); const nullifier1 = newNullifier(utxo7, Bob); @@ -458,21 +692,42 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou let root = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); const proof2 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; const identitiesRoot = await smtKyc.root(); - const proof3 = await smtKyc.generateCircomVerifierProof(kycHash(Bob.babyJubPublicKey), identitiesRoot); - const proof4 = await smtKyc.generateCircomVerifierProof(kycHash(Alice.babyJubPublicKey), identitiesRoot); + const proof3 = await smtKyc.generateCircomVerifierProof( + kycHash(Bob.babyJubPublicKey), + identitiesRoot + ); + const proof4 = await smtKyc.generateCircomVerifierProof( + kycHash(Alice.babyJubPublicKey), + identitiesRoot + ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Bob) proof4.siblings.map((s) => s.bigInt()), // identity proof for the 1st owner of the output UTXO (Alice) - proof3.siblings.map((s) => s.bigInt()) // identity proof for the 2nd owner of the output UTXO (Bob) + proof3.siblings.map((s) => s.bigInt()), // identity proof for the 2nd owner of the output UTXO (Bob) ]; - await expect(doTransfer(Bob, [utxo7, utxo7], [nullifier1, nullifier2], [_utxo1, _utxo2], root.bigInt(), merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, [Alice, Bob])).rejectedWith(`UTXODuplicate`); + await expect( + doTransfer( + Bob, + [utxo7, utxo7], + [nullifier1, nullifier2], + [_utxo1, _utxo2], + root.bigInt(), + merkleProofs, + identitiesRoot.bigInt(), + identitiesMerkleProofs, + [Alice, Bob] + ) + ).rejectedWith(`UTXODuplicate`); }).timeout(600000); - it("transfer non-existing UTXOs should fail", async function () { + it('transfer non-existing UTXOs should fail', async function () { const nonExisting1 = newUTXO(25, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); @@ -486,28 +741,58 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou // generate inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(nonExisting1.hash, root); - const proof2 = await smtAlice.generateCircomVerifierProof(nonExisting2.hash, root); - const merkleProofs = [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())]; + const proof1 = await smtAlice.generateCircomVerifierProof( + nonExisting1.hash, + root + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + nonExisting2.hash, + root + ); + const merkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // propose the output UTXOs const _utxo1 = newUTXO(30, Charlie); const utxo7 = newUTXO(15, Bob); const identitiesRoot = await smtKyc.root(); - const proof3 = await smtKyc.generateCircomVerifierProof(kycHash(Alice.babyJubPublicKey), identitiesRoot); - const proof4 = await smtKyc.generateCircomVerifierProof(kycHash(Bob.babyJubPublicKey), identitiesRoot); - const proof5 = await smtKyc.generateCircomVerifierProof(kycHash(Charlie.babyJubPublicKey), identitiesRoot); + const proof3 = await smtKyc.generateCircomVerifierProof( + kycHash(Alice.babyJubPublicKey), + identitiesRoot + ); + const proof4 = await smtKyc.generateCircomVerifierProof( + kycHash(Bob.babyJubPublicKey), + identitiesRoot + ); + const proof5 = await smtKyc.generateCircomVerifierProof( + kycHash(Charlie.babyJubPublicKey), + identitiesRoot + ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) proof4.siblings.map((s) => s.bigInt()), // identity proof for the 1st owner of the output UTXO (Bob) - proof5.siblings.map((s) => s.bigInt()) // identity proof for the 2nd owner of the output UTXO (Charlie) + proof5.siblings.map((s) => s.bigInt()), // identity proof for the 2nd owner of the output UTXO (Charlie) ]; - await expect(doTransfer(Alice, [nonExisting1, nonExisting2], [nullifier1, nullifier2], [utxo7, _utxo1], root.bigInt(), merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, [Bob, Charlie])).rejectedWith("UTXORootNotFound"); + await expect( + doTransfer( + Alice, + [nonExisting1, nonExisting2], + [nullifier1, nullifier2], + [utxo7, _utxo1], + root.bigInt(), + merkleProofs, + identitiesRoot.bigInt(), + identitiesMerkleProofs, + [Bob, Charlie] + ) + ).rejectedWith('UTXORootNotFound'); }).timeout(600000); - it("repeated mint calls with single UTXO should not fail", async function () { + it('repeated mint calls with single UTXO should not fail', async function () { const utxo5 = newUTXO(10, Alice); await expect(doMint(zeto, deployer, [utxo5, ZERO_UTXO])).fulfilled; const utxo6 = newUTXO(20, Alice); @@ -515,28 +800,80 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou }); }); - async function doTransfer(signer: User, inputs: UTXO[], _nullifiers: UTXO[], outputs: UTXO[], utxosRoot: BigInt, utxosMerkleProofs: BigInt[][], identitiesRoot: BigInt, identitiesMerkleProof: BigInt[][], owners: User[]) { + async function doTransfer( + signer: User, + inputs: UTXO[], + _nullifiers: UTXO[], + outputs: UTXO[], + utxosRoot: BigInt, + utxosMerkleProofs: BigInt[][], + identitiesRoot: BigInt, + identitiesMerkleProof: BigInt[][], + owners: User[] + ) { let nullifiers: [BigNumberish, BigNumberish]; let outputCommitments: [BigNumberish, BigNumberish]; let encodedProof: any; - const result = await prepareProof(signer, inputs, _nullifiers, outputs, utxosRoot, utxosMerkleProofs, identitiesRoot, identitiesMerkleProof, owners); - nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [BigNumberish, BigNumberish]; + const result = await prepareProof( + signer, + inputs, + _nullifiers, + outputs, + utxosRoot, + utxosMerkleProofs, + identitiesRoot, + identitiesMerkleProof, + owners + ); + nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ + BigNumberish, + BigNumberish + ]; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; - const txResult = await sendTx(signer, nullifiers, outputCommitments, utxosRoot, encodedProof); + const txResult = await sendTx( + signer, + nullifiers, + outputCommitments, + utxosRoot, + encodedProof + ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { txResult, plainTextSalt: outputs[0].salt }; } - async function prepareProof(signer: User, inputs: UTXO[], _nullifiers: UTXO[], outputs: UTXO[], utxosRoot: BigInt, utxosMerkleProof: BigInt[][], identitiesRoot: BigInt, identitiesMerkleProof: BigInt[][], owners: User[]) { - const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [BigNumberish, BigNumberish]; - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map((input) => input.hash) as [BigNumberish, BigNumberish]; + async function prepareProof( + signer: User, + inputs: UTXO[], + _nullifiers: UTXO[], + outputs: UTXO[], + utxosRoot: BigInt, + utxosMerkleProof: BigInt[][], + identitiesRoot: BigInt, + identitiesMerkleProof: BigInt[][], + owners: User[] + ) { + const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ + BigNumberish, + BigNumberish + ]; + const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + (input) => input.hash + ) as [BigNumberish, BigNumberish]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map((output) => output.hash) as [BigNumberish, BigNumberish]; + const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + (output) => output.hash + ) as [BigNumberish, BigNumberish]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [[BigNumberish, BigNumberish], [BigNumberish, BigNumberish]] = owners.map(owner => owner.babyJubPublicKey) as [[BigNumberish, BigNumberish], [BigNumberish, BigNumberish]]; + const outputOwnerPublicKeys: [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ] = owners.map((owner) => owner.babyJubPublicKey) as [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ]; const startWitnessCalculation = Date.now(); const inputObj = { nullifiers, @@ -554,23 +891,25 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou outputSalts: outputs.map((output) => output.salt || 0n), outputOwnerPublicKeys, }; - const witness = await circuit.calculateWTNSBin( - inputObj, - true - ); + const witness = await circuit.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKey, witness) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; + const { proof, publicSignals } = (await groth16.prove( + provingKey, + witness + )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; - console.log(`Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`); + console.log( + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + ); const encodedProof = encodeProof(proof); return { inputCommitments, outputCommitments, - encodedProof + encodedProof, }; } @@ -584,9 +923,13 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou const startTx = Date.now(); const tx = await zeto .connect(signer.signer) - .transfer(nullifiers, outputCommitments, root, encodedProof, "0x"); + .transfer(nullifiers, outputCommitments, root, encodedProof, '0x'); const results: ContractTransactionReceipt | null = await tx.wait(); - console.log(`Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${results?.gasUsed}`); + console.log( + `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ + results?.gasUsed + }` + ); return results; } }); diff --git a/solidity/test/zeto_nf_anon.ts b/solidity/test/zeto_nf_anon.ts index c514609..30f361e 100644 --- a/solidity/test/zeto_nf_anon.ts +++ b/solidity/test/zeto_nf_anon.ts @@ -17,14 +17,14 @@ import { ethers, network } from 'hardhat'; import { Signer, BigNumberish, AddressLike } from 'ethers'; import { expect } from 'chai'; -import { loadCircuit, tokenUriHash, encodeProof } from "zeto-js"; +import { loadCircuit, tokenUriHash, encodeProof } from 'zeto-js'; import { groth16 } from 'snarkjs'; import { formatPrivKeyForBabyJub, stringifyBigInts } from 'maci-crypto'; import { User, UTXO, newUser, newAssetUTXO, doMint } from './lib/utils'; import { loadProvingKeys } from './utils'; import { deployZeto } from './lib/deploy'; -describe("Zeto based non-fungible token with anonymity without encryption or nullifiers", function () { +describe('Zeto based non-fungible token with anonymity without encryption or nullifiers', function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -52,7 +52,7 @@ describe("Zeto based non-fungible token with anonymity without encryption or nul ({ provingKeyFile: provingKey } = loadProvingKeys('nf_anon')); }); - it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { + it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { const tokenId = 1001; const uri = 'http://ipfs.io/file-hash-1'; utxo1 = newAssetUTXO(tokenId, uri, Alice); @@ -68,7 +68,7 @@ describe("Zeto based non-fungible token with anonymity without encryption or nul utxo2 = newAssetUTXO(_utxo3.tokenId!, _utxo3.uri!, Bob, _utxo3.salt); }); - it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { + it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { // propose the output UTXOs utxo3 = newAssetUTXO(utxo2.tokenId!, utxo2.uri!, Charlie); @@ -76,7 +76,7 @@ describe("Zeto based non-fungible token with anonymity without encryption or nul await doTransfer(Bob, utxo2, utxo3, Charlie); }); - describe("failure cases", function () { + describe('failure cases', function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks @@ -84,25 +84,41 @@ describe("Zeto based non-fungible token with anonymity without encryption or nul return; } - it("mint existing unspent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo3])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing unspent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo3])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("mint existing spent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo1])).rejectedWith("UTXOAlreadySpent"); + it('mint existing spent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( + 'UTXOAlreadySpent' + ); }); - it("transfer non-existing UTXOs should fail", async function () { - const nonExisting1 = newAssetUTXO(1002, 'http://ipfs.io/file-hash-2', Alice); - const nonExisting2 = newAssetUTXO(1002, 'http://ipfs.io/file-hash-2', Bob); - - await expect(doTransfer(Alice, nonExisting1, nonExisting2, Bob)).rejectedWith("UTXONotMinted"); + it('transfer non-existing UTXOs should fail', async function () { + const nonExisting1 = newAssetUTXO( + 1002, + 'http://ipfs.io/file-hash-2', + Alice + ); + const nonExisting2 = newAssetUTXO( + 1002, + 'http://ipfs.io/file-hash-2', + Bob + ); + + await expect( + doTransfer(Alice, nonExisting1, nonExisting2, Bob) + ).rejectedWith('UTXONotMinted'); }); - it("transfer spent UTXOs should fail (double spend protection)", async function () { + it('transfer spent UTXOs should fail (double spend protection)', async function () { // create outputs const _utxo4 = newAssetUTXO(utxo1.tokenId!, utxo1.uri!, Bob); - await expect(doTransfer(Alice, utxo1, _utxo4, Bob)).rejectedWith("UTXOAlreadySpent") + await expect(doTransfer(Alice, utxo1, _utxo4, Bob)).rejectedWith( + 'UTXOAlreadySpent' + ); }); }); @@ -111,7 +127,14 @@ describe("Zeto based non-fungible token with anonymity without encryption or nul let outputCommitment: BigNumberish; let outputOwnerAddress: AddressLike; let encodedProof: any; - const result = await prepareProof(circuit, provingKey, signer, input, output, to); + const result = await prepareProof( + circuit, + provingKey, + signer, + input, + output, + to + ); inputCommitment = result.inputCommitment; outputCommitment = result.outputCommitment; outputOwnerAddress = to.ethAddress as AddressLike; @@ -128,7 +151,7 @@ describe("Zeto based non-fungible token with anonymity without encryption or nul ) { const tx = await zeto .connect(signer.signer) - .transfer(inputCommitment, outputCommitment, encodedProof, "0x"); + .transfer(inputCommitment, outputCommitment, encodedProof, '0x'); const results = await tx.wait(); console.log(`Method transfer() complete. Gas used: ${results?.gasUsed}`); @@ -137,12 +160,20 @@ describe("Zeto based non-fungible token with anonymity without encryption or nul } }); -async function prepareProof(circuit: any, provingKey: any, signer: User, input: UTXO, output: UTXO, to: User) { +async function prepareProof( + circuit: any, + provingKey: any, + signer: User, + input: UTXO, + output: UTXO, + to: User +) { const tokenId = input.tokenId; const inputCommitment: BigNumberish = input.hash as BigNumberish; const inputSalt = input.salt; const outputCommitment: BigNumberish = output.hash as BigNumberish; - const outputOwnerPublicKey: [BigNumberish, BigNumberish] = to.babyJubPublicKey as [BigNumberish, BigNumberish]; + const outputOwnerPublicKey: [BigNumberish, BigNumberish] = + to.babyJubPublicKey as [BigNumberish, BigNumberish]; const otherInputs = stringifyBigInts({ inputOwnerPrivateKey: formatPrivKeyForBabyJub(signer.babyJubPrivateKey), }); @@ -157,24 +188,29 @@ async function prepareProof(circuit: any, provingKey: any, signer: User, input: outputCommitments: [outputCommitment], outputSalts: [output.salt], outputOwnerPublicKeys: [outputOwnerPublicKey], - ...otherInputs + ...otherInputs, }, true ); const timeWitnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKey, witness) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; + const { proof, publicSignals } = (await groth16.prove( + provingKey, + witness + )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; - console.log(`Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms`); + console.log( + `Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms` + ); const encodedProof = encodeProof(proof); return { inputCommitment, outputCommitment, - encodedProof + encodedProof, }; } module.exports = { prepareProof, -}; \ No newline at end of file +}; diff --git a/solidity/test/zeto_nf_anon_nullifier.ts b/solidity/test/zeto_nf_anon_nullifier.ts index f721e66..8fcd525 100644 --- a/solidity/test/zeto_nf_anon_nullifier.ts +++ b/solidity/test/zeto_nf_anon_nullifier.ts @@ -17,14 +17,22 @@ import { ethers, network } from 'hardhat'; import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; import { expect } from 'chai'; -import { loadCircuit, Poseidon, encodeProof, tokenUriHash } from "zeto-js"; +import { loadCircuit, Poseidon, encodeProof, tokenUriHash } from 'zeto-js'; import { groth16 } from 'snarkjs'; import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; -import { UTXO, User, newUser, newAssetUTXO, newAssetNullifier, doMint, parseUTXOEvents } from './lib/utils'; +import { + UTXO, + User, + newUser, + newAssetUTXO, + newAssetNullifier, + doMint, + parseUTXOEvents, +} from './lib/utils'; import { loadProvingKeys } from './utils'; import { deployZeto } from './lib/deploy'; -describe("Zeto based non-fungible token with anonymity using nullifiers without encryption", function () { +describe('Zeto based non-fungible token with anonymity using nullifiers without encryption', function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -52,21 +60,21 @@ describe("Zeto based non-fungible token with anonymity using nullifiers without circuit = await loadCircuit('nf_anon_nullifier'); ({ provingKeyFile: provingKey } = loadProvingKeys('nf_anon_nullifier')); - const storage1 = new InMemoryDB(str2Bytes("")) + const storage1 = new InMemoryDB(str2Bytes('')); smtAlice = new Merkletree(storage1, true, 64); - const storage2 = new InMemoryDB(str2Bytes("")) + const storage2 = new InMemoryDB(str2Bytes('')); smtBob = new Merkletree(storage2, true, 64); }); - it("onchain SMT root should be equal to the offchain SMT root", async function () { + it('onchain SMT root should be equal to the offchain SMT root', async function () { const root = await smtAlice.root(); const onchainRoot = await zeto.getRoot(); expect(onchainRoot).to.equal(0n); expect(root.string()).to.equal(onchainRoot.toString()); }); - it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { + it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { // The authority mints a new UTXO and assigns it to Alice const tokenId = 1001; const uri = 'http://ipfs.io/file-hash-1'; @@ -95,7 +103,15 @@ describe("Zeto based non-fungible token with anonymity using nullifiers without const merkleProof = proof1.siblings.map((s) => s.bigInt()); // Alice transfers her UTXOs to Bob - const result2 = await doTransfer(Alice, utxo1, nullifier1, _utxo3, root.bigInt(), merkleProof, Bob); + const result2 = await doTransfer( + Alice, + utxo1, + nullifier1, + _utxo3, + root.bigInt(), + merkleProof, + Bob + ); // Alice locally tracks the UTXOs inside the Sparse Merkle Tree await smtAlice.add(_utxo3.hash, _utxo3.hash); @@ -117,14 +133,20 @@ describe("Zeto based non-fungible token with anonymity using nullifiers without const receivedUri = _utxo3.uri!; const receivedSalt = _utxo3.salt; const incomingUTXOs: any = events[0].outputs; - const hash = Poseidon.poseidon5([BigInt(receivedTokenId), tokenUriHash(receivedUri), receivedSalt, Bob.babyJubPublicKey[0], Bob.babyJubPublicKey[1]]); + const hash = Poseidon.poseidon5([ + BigInt(receivedTokenId), + tokenUriHash(receivedUri), + receivedSalt, + Bob.babyJubPublicKey[0], + Bob.babyJubPublicKey[1], + ]); expect(incomingUTXOs[0]).to.equal(hash); // Bob uses the decrypted values to construct the UTXO received from the transaction utxo3 = newAssetUTXO(receivedTokenId, receivedUri, Bob, receivedSalt); }).timeout(600000); - it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { + it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { // Bob generates the nullifiers for the UTXO to be spent const nullifier1 = newAssetNullifier(utxo3, Bob); @@ -137,7 +159,15 @@ describe("Zeto based non-fungible token with anonymity using nullifiers without const utxo6 = newAssetUTXO(utxo3.tokenId!, utxo3.uri!, Charlie); // Bob should be able to spend the UTXO that was reconstructed from the previous transaction - const result = await doTransfer(Bob, utxo3, nullifier1, utxo6, root.bigInt(), merkleProof, Charlie); + const result = await doTransfer( + Bob, + utxo3, + nullifier1, + utxo6, + root.bigInt(), + merkleProof, + Charlie + ); // Bob keeps the local SMT in sync await smtBob.add(utxo6.hash, utxo6.hash); @@ -147,7 +177,7 @@ describe("Zeto based non-fungible token with anonymity using nullifiers without await smtAlice.add(events[0].outputs[0], events[0].outputs[0]); }).timeout(600000); - describe("failure cases", function () { + describe('failure cases', function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks @@ -155,15 +185,19 @@ describe("Zeto based non-fungible token with anonymity using nullifiers without return; } - it("mint existing unspent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo3])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing unspent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo3])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("mint existing spent UTXOs should fail", async function () { - await expect(doMint(zeto, deployer, [utxo1])).rejectedWith("UTXOAlreadyOwned"); + it('mint existing spent UTXOs should fail', async function () { + await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( + 'UTXOAlreadyOwned' + ); }); - it("transfer spent UTXOs should fail (double spend protection)", async function () { + it('transfer spent UTXOs should fail (double spend protection)', async function () { // Alice create outputs in an attempt to send to Charlie an already spent asset const _utxo1 = newAssetUTXO(utxo1.tokenId!, utxo1.uri!, Charlie); @@ -172,14 +206,31 @@ describe("Zeto based non-fungible token with anonymity using nullifiers without // generate inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(utxo1.hash, root); + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo1.hash, + root + ); const merkleProof = proof1.siblings.map((s) => s.bigInt()); - await expect(doTransfer(Alice, utxo1, nullifier1, _utxo1, root.bigInt(), merkleProof, Charlie)).rejectedWith("UTXOAlreadySpent") + await expect( + doTransfer( + Alice, + utxo1, + nullifier1, + _utxo1, + root.bigInt(), + merkleProof, + Charlie + ) + ).rejectedWith('UTXOAlreadySpent'); }).timeout(600000); - it("transfer non-existing UTXOs should fail", async function () { - const nonExisting1 = newAssetUTXO(1002, 'http://ipfs.io/file-hash-2', Alice); + it('transfer non-existing UTXOs should fail', async function () { + const nonExisting1 = newAssetUTXO( + 1002, + 'http://ipfs.io/file-hash-2', + Alice + ); // add to our local SMT (but they don't exist on the chain) await smtAlice.add(nonExisting1.hash, nonExisting1.hash); @@ -189,30 +240,77 @@ describe("Zeto based non-fungible token with anonymity using nullifiers without // generate inclusion proofs for the UTXOs to be spent let root = await smtAlice.root(); - const proof1 = await smtAlice.generateCircomVerifierProof(nonExisting1.hash, root); + const proof1 = await smtAlice.generateCircomVerifierProof( + nonExisting1.hash, + root + ); const merkleProof = proof1.siblings.map((s) => s.bigInt()); // propose the output UTXOs - const _utxo1 = newAssetUTXO(nonExisting1.tokenId!, nonExisting1.uri!, Charlie); - - await expect(doTransfer(Alice, nonExisting1, nullifier1, _utxo1, root.bigInt(), merkleProof, Charlie)).rejectedWith("UTXORootNotFound"); + const _utxo1 = newAssetUTXO( + nonExisting1.tokenId!, + nonExisting1.uri!, + Charlie + ); + + await expect( + doTransfer( + Alice, + nonExisting1, + nullifier1, + _utxo1, + root.bigInt(), + merkleProof, + Charlie + ) + ).rejectedWith('UTXORootNotFound'); }).timeout(600000); }); - async function doTransfer(signer: User, input: UTXO, _nullifier: UTXO, output: UTXO, root: BigInt, merkleProof: BigInt[], owner: User) { + async function doTransfer( + signer: User, + input: UTXO, + _nullifier: UTXO, + output: UTXO, + root: BigInt, + merkleProof: BigInt[], + owner: User + ) { let nullifier: BigNumberish; let outputCommitment: BigNumberish; let encodedProof: any; - const result = await prepareProof(signer, input, _nullifier, output, root, merkleProof, owner); + const result = await prepareProof( + signer, + input, + _nullifier, + output, + root, + merkleProof, + owner + ); nullifier = _nullifier.hash as BigNumberish; outputCommitment = result.outputCommitment; encodedProof = result.encodedProof; - const txResult = await sendTx(signer, nullifier, outputCommitment, root, encodedProof); + const txResult = await sendTx( + signer, + nullifier, + outputCommitment, + root, + encodedProof + ); return { txResult }; } - async function prepareProof(signer: User, input: UTXO, _nullifier: UTXO, output: UTXO, root: BigInt, merkleProof: BigInt[], owner: User) { + async function prepareProof( + signer: User, + input: UTXO, + _nullifier: UTXO, + output: UTXO, + root: BigInt, + merkleProof: BigInt[], + owner: User + ) { const nullifier = _nullifier.hash as BigNumberish; const inputCommitment: BigNumberish = input.hash as BigNumberish; const tokenId = BigInt(input.tokenId!); @@ -220,7 +318,8 @@ describe("Zeto based non-fungible token with anonymity using nullifiers without const inputSalt = input.salt!; const outputCommitment: BigNumberish = output.hash as BigNumberish; const outputSalt = output.salt!; - const outputOwnerPublicKey: [BigNumberish, BigNumberish] = owner.babyJubPublicKey as [BigNumberish, BigNumberish]; + const outputOwnerPublicKey: [BigNumberish, BigNumberish] = + owner.babyJubPublicKey as [BigNumberish, BigNumberish]; const startWitnessCalculation = Date.now(); const inputObj = { @@ -236,23 +335,25 @@ describe("Zeto based non-fungible token with anonymity using nullifiers without outputSalt, outputOwnerPublicKey, }; - const witness = await circuit.calculateWTNSBin( - inputObj, - true - ); + const witness = await circuit.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKey, witness) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; + const { proof, publicSignals } = (await groth16.prove( + provingKey, + witness + )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; - console.log(`Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`); + console.log( + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + ); const encodedProof = encodeProof(proof); return { inputCommitment, outputCommitment, - encodedProof + encodedProof, }; } @@ -266,9 +367,13 @@ describe("Zeto based non-fungible token with anonymity using nullifiers without const startTx = Date.now(); const tx = await zeto .connect(signer.signer) - .transfer(nullifier, outputCommitment, root, encodedProof, "0x"); + .transfer(nullifier, outputCommitment, root, encodedProof, '0x'); const results: ContractTransactionReceipt | null = await tx.wait(); - console.log(`Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${results?.gasUsed}`); + console.log( + `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ + results?.gasUsed + }` + ); return results; } }); diff --git a/solidity/test/zkDvP.ts b/solidity/test/zkDvP.ts index 9159fe4..f32fe97 100644 --- a/solidity/test/zkDvP.ts +++ b/solidity/test/zkDvP.ts @@ -17,15 +17,24 @@ import { ethers, ignition, network } from 'hardhat'; import { Signer, encodeBytes32String, ZeroHash } from 'ethers'; import { expect } from 'chai'; -import { loadCircuit, getProofHash } from "zeto-js"; +import { loadCircuit, getProofHash } from 'zeto-js'; import zkDvPModule from '../ignition/modules/zkDvP'; import zetoAnonTests from './zeto_anon'; import zetoNFAnonTests from './zeto_nf_anon'; -import { UTXO, User, newUser, newUTXO, doMint, newAssetUTXO, ZERO_UTXO, parseUTXOEvents } from './lib/utils'; +import { + UTXO, + User, + newUser, + newUTXO, + doMint, + newAssetUTXO, + ZERO_UTXO, + parseUTXOEvents, +} from './lib/utils'; import { loadProvingKeys } from './utils'; import { deployZeto } from './lib/deploy'; -describe("DvP flows between fungible and non-fungible tokens based on Zeto with anonymity without encryption or nullifiers", function () { +describe('DvP flows between fungible and non-fungible tokens based on Zeto with anonymity without encryption or nullifiers', function () { // users interacting with each other in the DvP transactions let Alice: User; let Bob: User; @@ -61,10 +70,17 @@ describe("DvP flows between fungible and non-fungible tokens based on Zeto with console.log(`ZK Asset contract deployed at ${zkAsset.target}`); ({ deployer, zeto: zkPayment } = await deployZeto('Zeto_Anon')); console.log(`ZK Payment contract deployed at ${zkPayment.target}`); - ({ zkDvP } = await ignition.deploy(zkDvPModule, { parameters: { zkDvP: { assetToken: zkAsset.target, paymentToken: zkPayment.target } } })); + ({ zkDvP } = await ignition.deploy(zkDvPModule, { + parameters: { + zkDvP: { + assetToken: zkAsset.target, + paymentToken: zkPayment.target, + }, + }, + })); }); - it("mint to Alice some payment tokens", async function () { + it('mint to Alice some payment tokens', async function () { payment1 = newUTXO(10, Alice); payment2 = newUTXO(20, Alice); const result = await doMint(zkPayment, deployer, [payment1, payment2]); @@ -76,7 +92,7 @@ describe("DvP flows between fungible and non-fungible tokens based on Zeto with } }); - it("mint to Bob some asset tokens", async function () { + it('mint to Bob some asset tokens', async function () { asset1 = newUTXO(10, Alice); asset2 = newUTXO(20, Alice); const result = await doMint(zkAsset, deployer, [asset1, asset2]); @@ -87,26 +103,48 @@ describe("DvP flows between fungible and non-fungible tokens based on Zeto with expect(event.args.outputs[1].toString()).to.equal(asset2.hash.toString()); }); - it("Initiating a successful DvP transaction with payment inputs", async function () { + it('Initiating a successful DvP transaction with payment inputs', async function () { const utxo1 = newUTXO(10, Alice); const utxo2 = newUTXO(20, Alice); const utxo3 = newUTXO(25, Bob); const utxo4 = newUTXO(5, Alice); - await expect(zkDvP.connect(Alice.signer).initiateTrade([utxo1.hash, utxo2.hash], [utxo3.hash, utxo4.hash], ZeroHash, 0, 0, ZeroHash)).fulfilled; + await expect( + zkDvP + .connect(Alice.signer) + .initiateTrade( + [utxo1.hash, utxo2.hash], + [utxo3.hash, utxo4.hash], + ZeroHash, + 0, + 0, + ZeroHash + ) + ).fulfilled; }); - it("Initiating a successful DvP transaction with asset inputs", async function () { + it('Initiating a successful DvP transaction with asset inputs', async function () { const utxo1 = newUTXO(10, Alice); const utxo2 = newUTXO(20, Alice); - await expect(zkDvP.connect(Alice.signer).initiateTrade([0, 0], [0, 0], ZeroHash, utxo1.hash, utxo2.hash, ZeroHash)).fulfilled; + await expect( + zkDvP + .connect(Alice.signer) + .initiateTrade( + [0, 0], + [0, 0], + ZeroHash, + utxo1.hash, + utxo2.hash, + ZeroHash + ) + ).fulfilled; }); - it("Initiating a successful DvP transaction with payment inputs and accepting by specifying asset inputs", async function () { + it('Initiating a successful DvP transaction with payment inputs and accepting by specifying asset inputs', async function () { // the authority mints some payment tokens to Alice const _utxo1 = newUTXO(100, Alice); await doMint(zkPayment, deployer, [_utxo1]); // the authority mints some asset tokens to Bob - const utxo3 = newAssetUTXO(202, "http://ipfs.io/file-hash-1", Bob); + const utxo3 = newAssetUTXO(202, 'http://ipfs.io/file-hash-1', Bob); await doMint(zkAsset, deployer, [utxo3]); // 1. Alice initiates a trade with Bob using the payment tokens @@ -116,33 +154,65 @@ describe("DvP flows between fungible and non-fungible tokens based on Zeto with // 1.2 Alice generates the proof for the trade proposal const circuit1 = await loadCircuit('anon'); const { provingKeyFile: provingKey1 } = loadProvingKeys('anon'); - const proof1 = await zetoAnonTests.prepareProof(circuit1, provingKey1, Alice, [_utxo1, ZERO_UTXO], [utxo2, ZERO_UTXO], [Bob, {}]); + const proof1 = await zetoAnonTests.prepareProof( + circuit1, + provingKey1, + Alice, + [_utxo1, ZERO_UTXO], + [utxo2, ZERO_UTXO], + [Bob, {}] + ); const hash1 = getProofHash(proof1.encodedProof); // 1.3 Alice initiates the trade with Bob - const tx1 = await zkDvP.connect(Alice.signer).initiateTrade([_utxo1.hash, 0], [utxo2.hash, 0], hash1, 0, 0, ZeroHash); + const tx1 = await zkDvP + .connect(Alice.signer) + .initiateTrade([_utxo1.hash, 0], [utxo2.hash, 0], hash1, 0, 0, ZeroHash); const result1 = await tx1.wait(); const event = zkDvP.interface.parseLog(result1.logs[0]); const tradeId = event.args.tradeId; // 2. Bob accepts the trade by using the asset tokens // 2.1 Bob generates the proposed output asset UTXO for Alice - const utxo4 = newAssetUTXO(202, "http://ipfs.io/file-hash-1", Alice); + const utxo4 = newAssetUTXO(202, 'http://ipfs.io/file-hash-1', Alice); // 2.2 Bob generates the proof for accepting the trade const circuit2 = await loadCircuit('nf_anon'); const { provingKeyFile: provingKey2 } = loadProvingKeys('nf_anon'); - const proof2 = await zetoNFAnonTests.prepareProof(circuit2, provingKey2, Bob, utxo3, utxo4, Alice); + const proof2 = await zetoNFAnonTests.prepareProof( + circuit2, + provingKey2, + Bob, + utxo3, + utxo4, + Alice + ); const hash2 = getProofHash(proof2.encodedProof); - await expect(zkDvP.connect(Bob.signer).acceptTrade(tradeId, [0, 0], [0, 0], ZeroHash, utxo3.hash, utxo4.hash, hash2)).fulfilled; + await expect( + zkDvP + .connect(Bob.signer) + .acceptTrade( + tradeId, + [0, 0], + [0, 0], + ZeroHash, + utxo3.hash, + utxo4.hash, + hash2 + ) + ).fulfilled; // 3. Alice sends her proof to complete the trade (the trade will still be pending completion) - const tx2 = await zkDvP.connect(Alice.signer).completeTrade(tradeId, proof1.encodedProof); + const tx2 = await zkDvP + .connect(Alice.signer) + .completeTrade(tradeId, proof1.encodedProof); const tx2Result = await tx2.wait(); // 4. Bob sends his proof to complete the trade (the trade will be completed) - const tx3 = await zkDvP.connect(Bob.signer).completeTrade(tradeId, proof2.encodedProof); + const tx3 = await zkDvP + .connect(Bob.signer) + .completeTrade(tradeId, proof2.encodedProof); const tx3Result = await tx3.wait(); // check that the trade is completed @@ -150,7 +220,7 @@ describe("DvP flows between fungible and non-fungible tokens based on Zeto with expect(events[0].tradeId).to.equal(tradeId); expect(events[0].trade.status).to.equal(2n); // enum for TradeStatus.Completed }); - describe("failure cases", function () { + describe('failure cases', function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks @@ -158,54 +228,162 @@ describe("DvP flows between fungible and non-fungible tokens based on Zeto with return; } - it("Initiating a DvP transaction without payment input or asset input should fail", async function () { - await expect(zkDvP.connect(Alice.signer).initiateTrade([0, 0], [0, 0], ZeroHash, 0, 0, ZeroHash)).rejectedWith("Payment inputs and asset input cannot be zero at the same time"); + it('Initiating a DvP transaction without payment input or asset input should fail', async function () { + await expect( + zkDvP + .connect(Alice.signer) + .initiateTrade([0, 0], [0, 0], ZeroHash, 0, 0, ZeroHash) + ).rejectedWith( + 'Payment inputs and asset input cannot be zero at the same time' + ); }); - it("Initiating a DvP transaction with payment input but no payment output should fail", async function () { + it('Initiating a DvP transaction with payment input but no payment output should fail', async function () { const utxo1 = newUTXO(10, Alice); const utxo2 = newUTXO(20, Alice); - await expect(zkDvP.connect(Alice.signer).initiateTrade([utxo1.hash, utxo2.hash], [0, 0], ZeroHash, 0, 0, ZeroHash)).rejectedWith("Payment outputs cannot be zero when payment inputs are non-zero"); + await expect( + zkDvP + .connect(Alice.signer) + .initiateTrade( + [utxo1.hash, utxo2.hash], + [0, 0], + ZeroHash, + 0, + 0, + ZeroHash + ) + ).rejectedWith( + 'Payment outputs cannot be zero when payment inputs are non-zero' + ); }); - it("Initiating a DvP transaction with payment inputs and asset inputs should fail", async function () { + it('Initiating a DvP transaction with payment inputs and asset inputs should fail', async function () { const utxo1 = newUTXO(10, Alice); const utxo2 = newUTXO(20, Alice); const utxo3 = newUTXO(25, Bob); const utxo4 = newUTXO(5, Alice); - await expect(zkDvP.connect(Alice.signer).initiateTrade([utxo1.hash, utxo2.hash], [utxo3.hash, utxo4.hash], ZeroHash, utxo3.hash, 0, ZeroHash)).rejectedWith("Payment inputs and asset input cannot be provided at the same time"); + await expect( + zkDvP + .connect(Alice.signer) + .initiateTrade( + [utxo1.hash, utxo2.hash], + [utxo3.hash, utxo4.hash], + ZeroHash, + utxo3.hash, + 0, + ZeroHash + ) + ).rejectedWith( + 'Payment inputs and asset input cannot be provided at the same time' + ); }); - it("Initiating a DvP transaction with asset input but no asset output should fail", async function () { + it('Initiating a DvP transaction with asset input but no asset output should fail', async function () { const utxo1 = newUTXO(10, Alice); - await expect(zkDvP.connect(Alice.signer).initiateTrade([0, 0], [0, 0], ZeroHash, utxo1.hash, 0, ZeroHash)).rejectedWith("Asset output cannot be zero when asset input is non-zero"); + await expect( + zkDvP + .connect(Alice.signer) + .initiateTrade([0, 0], [0, 0], ZeroHash, utxo1.hash, 0, ZeroHash) + ).rejectedWith( + 'Asset output cannot be zero when asset input is non-zero' + ); }); - it("Accepting a trade using an invalid trade ID should fail", async function () { - await expect(zkDvP.connect(Bob.signer).acceptTrade(1000, [0, 0], [0, 0], ZeroHash, 0, 0, ZeroHash)).rejectedWith("Trade does not exist"); + it('Accepting a trade using an invalid trade ID should fail', async function () { + await expect( + zkDvP + .connect(Bob.signer) + .acceptTrade(1000, [0, 0], [0, 0], ZeroHash, 0, 0, ZeroHash) + ).rejectedWith('Trade does not exist'); }); - it("Failing cases for accepting a trade with payment terms", async function () { - const mockProofHash = encodeBytes32String("moch proof hash"); + it('Failing cases for accepting a trade with payment terms', async function () { + const mockProofHash = encodeBytes32String('moch proof hash'); const utxo1 = newUTXO(20, Alice); const utxo2 = newUTXO(20, Bob); - const tx1 = await zkDvP.connect(Alice.signer).initiateTrade([utxo1.hash, 0], [utxo2.hash, 0], mockProofHash, 0, 0, mockProofHash); + const tx1 = await zkDvP + .connect(Alice.signer) + .initiateTrade( + [utxo1.hash, 0], + [utxo2.hash, 0], + mockProofHash, + 0, + 0, + mockProofHash + ); const result = await tx1.wait(); const event = zkDvP.interface.parseLog(result.logs[0]); const tradeId = event.args.tradeId; - const utxo3 = newAssetUTXO(25, "http://ipfs.io/file-hash-1", Bob); - await expect(zkDvP.connect(Bob.signer).acceptTrade(tradeId, [utxo1.hash, 0], [0, 0], mockProofHash, 0, 0, mockProofHash)).rejectedWith("Payment inputs already provided by the trade initiator"); - await expect(zkDvP.connect(Bob.signer).acceptTrade(tradeId, [0, 0], [utxo2.hash, 0], mockProofHash, 0, 0, mockProofHash)).rejectedWith("Payment outputs already provided by the trade initiator"); - await expect(zkDvP.connect(Bob.signer).acceptTrade(tradeId, [0, 0], [0, 0], mockProofHash, 0, 0, mockProofHash)).rejectedWith("Asset input must be provided to accept the trade"); - await expect(zkDvP.connect(Bob.signer).acceptTrade(tradeId, [0, 0], [0, 0], mockProofHash, utxo3.hash, 0, mockProofHash)).rejectedWith("Asset output must be provided to accept the trade"); + const utxo3 = newAssetUTXO(25, 'http://ipfs.io/file-hash-1', Bob); + await expect( + zkDvP + .connect(Bob.signer) + .acceptTrade( + tradeId, + [utxo1.hash, 0], + [0, 0], + mockProofHash, + 0, + 0, + mockProofHash + ) + ).rejectedWith('Payment inputs already provided by the trade initiator'); + await expect( + zkDvP + .connect(Bob.signer) + .acceptTrade( + tradeId, + [0, 0], + [utxo2.hash, 0], + mockProofHash, + 0, + 0, + mockProofHash + ) + ).rejectedWith('Payment outputs already provided by the trade initiator'); + await expect( + zkDvP + .connect(Bob.signer) + .acceptTrade( + tradeId, + [0, 0], + [0, 0], + mockProofHash, + 0, + 0, + mockProofHash + ) + ).rejectedWith('Asset input must be provided to accept the trade'); + await expect( + zkDvP + .connect(Bob.signer) + .acceptTrade( + tradeId, + [0, 0], + [0, 0], + mockProofHash, + utxo3.hash, + 0, + mockProofHash + ) + ).rejectedWith('Asset output must be provided to accept the trade'); }); - it("Failing cases for accepting a trade with asset terms", async function () { - const mockProofHash = encodeBytes32String("mock proof hash"); - const utxo1 = newAssetUTXO(100, "http://ipfs.io/file-hash-1", Alice); - const utxo2 = newAssetUTXO(202, "http://ipfs.io/file-hash-2", Bob); - const tx1 = await zkDvP.connect(Alice.signer).initiateTrade([0, 0], [0, 0], ZeroHash, utxo1.hash, utxo2.hash, mockProofHash); + it('Failing cases for accepting a trade with asset terms', async function () { + const mockProofHash = encodeBytes32String('mock proof hash'); + const utxo1 = newAssetUTXO(100, 'http://ipfs.io/file-hash-1', Alice); + const utxo2 = newAssetUTXO(202, 'http://ipfs.io/file-hash-2', Bob); + const tx1 = await zkDvP + .connect(Alice.signer) + .initiateTrade( + [0, 0], + [0, 0], + ZeroHash, + utxo1.hash, + utxo2.hash, + mockProofHash + ); const result = await tx1.wait(); const event = zkDvP.interface.parseLog(result.logs[0]); const tradeId = event.args.tradeId; @@ -214,11 +392,58 @@ describe("DvP flows between fungible and non-fungible tokens based on Zeto with const utxo4 = newUTXO(20, Bob); const utxo5 = newUTXO(25, Alice); const utxo6 = newUTXO(5, Bob); - await expect(zkDvP.connect(Bob.signer).acceptTrade(tradeId, [utxo3.hash, utxo4.hash], [utxo5.hash, utxo6.hash], mockProofHash, utxo1.hash, utxo2.hash, mockProofHash)).rejectedWith("Asset inputs already provided by the trade initiator"); - await expect(zkDvP.connect(Bob.signer).acceptTrade(tradeId, [utxo3.hash, utxo4.hash], [utxo5.hash, utxo6.hash], mockProofHash, 0, utxo2.hash, mockProofHash)).rejectedWith("Asset outputs already provided by the trade initiator"); - await expect(zkDvP.connect(Bob.signer).acceptTrade(tradeId, [0, 0], [0, 0], mockProofHash, 0, 0, mockProofHash)).rejectedWith("Payment inputs must be provided to accept the trade"); - await expect(zkDvP.connect(Bob.signer).acceptTrade(tradeId, [utxo3.hash, utxo4.hash], [0, 0], mockProofHash, 0, 0, mockProofHash)).rejectedWith("Payment outputs must be provided to accept the trade"); + await expect( + zkDvP + .connect(Bob.signer) + .acceptTrade( + tradeId, + [utxo3.hash, utxo4.hash], + [utxo5.hash, utxo6.hash], + mockProofHash, + utxo1.hash, + utxo2.hash, + mockProofHash + ) + ).rejectedWith('Asset inputs already provided by the trade initiator'); + await expect( + zkDvP + .connect(Bob.signer) + .acceptTrade( + tradeId, + [utxo3.hash, utxo4.hash], + [utxo5.hash, utxo6.hash], + mockProofHash, + 0, + utxo2.hash, + mockProofHash + ) + ).rejectedWith('Asset outputs already provided by the trade initiator'); + await expect( + zkDvP + .connect(Bob.signer) + .acceptTrade( + tradeId, + [0, 0], + [0, 0], + mockProofHash, + 0, + 0, + mockProofHash + ) + ).rejectedWith('Payment inputs must be provided to accept the trade'); + await expect( + zkDvP + .connect(Bob.signer) + .acceptTrade( + tradeId, + [utxo3.hash, utxo4.hash], + [0, 0], + mockProofHash, + 0, + 0, + mockProofHash + ) + ).rejectedWith('Payment outputs must be provided to accept the trade'); }); }); - }).timeout(600000); diff --git a/zkp/circuits/gen.js b/zkp/circuits/gen.js index daeda82..b3fb1dd 100644 --- a/zkp/circuits/gen.js +++ b/zkp/circuits/gen.js @@ -102,9 +102,8 @@ const processCircuit = async (circuit, ptau, skipSolidityGenaration) => { } log(circuit, `Compiling circuit`); - const { cmOut, cmErr } = await execAsync( - `circom ${circomInput} --output ${provingKeysRoot} --r1cs` + `circom ${circomInput} --output ${circuitsRoot} --sym --wasm` ); if (verbose) { if (cmOut) { @@ -114,6 +113,21 @@ const processCircuit = async (circuit, ptau, skipSolidityGenaration) => { log(circuit, 'compile error:\n' + cmErr); } } + if (compileOnly) { + return; + } + + const { ctOut, ctErr } = await execAsync( + `circom ${circomInput} --output ${provingKeysRoot} --r1cs` + ); + if (verbose) { + if (ctOut) { + log(circuit, 'constraint output:\n' + ctOut); + } + if (ctErr) { + log(circuit, 'constraint error:\n' + ctErr); + } + } log(circuit, `Generating test proving key with ${ptau}`); const { pkOut, pkErr } = await execAsync( From ec1d4cb4ef39c254d409f06497fcdc2b7ae45796 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 25 Sep 2024 14:36:16 +0100 Subject: [PATCH 03/24] supports batch for tokens with encrypted values Signed-off-by: Chengxuan Xing --- solidity/contracts/lib/zeto_fungible.sol | 2 +- solidity/contracts/zeto_anon_enc.sol | 92 ++++++++---- .../contracts/zeto_anon_enc_nullifier.sol | 116 ++++++++++----- .../contracts/zeto_anon_enc_nullifier_kyc.sol | 122 +++++++++++----- ...eto_anon_enc_nullifier_non_repudiation.sol | 138 +++++++++++++----- solidity/contracts/zeto_nf_anon_nullifier.sol | 2 +- ...to_anon_enc_nullifier_kyc_cost_analysis.ts | 34 +++-- ..._enc_nullifier_non_repudiation_base.circom | 4 +- 8 files changed, 346 insertions(+), 164 deletions(-) diff --git a/solidity/contracts/lib/zeto_fungible.sol b/solidity/contracts/lib/zeto_fungible.sol index 2b59285..2af433d 100644 --- a/solidity/contracts/lib/zeto_fungible.sol +++ b/solidity/contracts/lib/zeto_fungible.sol @@ -54,7 +54,7 @@ abstract contract ZetoFungible is OwnableUpgradeable { publicInputs[0] = amount; publicInputs[1] = utxo; - // // Check the proof + // Check the proof require( depositVerifier.verifyProof( proof.pA, diff --git a/solidity/contracts/zeto_anon_enc.sol b/solidity/contracts/zeto_anon_enc.sol index c70039a..0a62806 100644 --- a/solidity/contracts/zeto_anon_enc.sol +++ b/solidity/contracts/zeto_anon_enc.sol @@ -28,7 +28,7 @@ import {Commonlib} from "./lib/common.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -uint256 constant MAX_BATCH = 10; // batch not supported +uint256 constant MAX_BATCH = 10; /// @title A sample implementation of a Zeto based fungible token with anonymity, and encryption /// @author Kaleido, Inc. @@ -83,40 +83,74 @@ contract Zeto_AnonEnc is ) public returns (bool) { // Check and pad commitments (inputs, outputs) = checkAndPadCommitments(inputs, outputs, MAX_BATCH); - if (outputs.length > 2) { - revert("batch not supported"); - } require( validateTransactionProposal(inputs, outputs, proof), "Invalid transaction proposal" ); - // construct the public inputs - uint256[9] memory publicInputs; - uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit - for (uint256 i = 0; i < encryptedValues.length; ++i) { - publicInputs[piIndex++] = encryptedValues[i]; - } - // copy input commitments - for (uint256 i = 0; i < inputs.length; i++) { - publicInputs[piIndex++] = inputs[i]; - } - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + if (inputs.length > 2) { + // construct the public inputs + uint256[25] memory publicInputs; + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } + // copy input commitments + for (uint256 i = 0; i < inputs.length; i++) { + publicInputs[piIndex++] = inputs[i]; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + + // Check the proof + require( + batchVerifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); + } else { + // construct the public inputs + uint256[9] memory publicInputs; + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } + // copy input commitments + for (uint256 i = 0; i < inputs.length; i++) { + publicInputs[piIndex++] = inputs[i]; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + + // Check the proof + require( + verifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); } - - // copy encryption nonce - publicInputs[piIndex++] = encryptionNonce; - - // Check the proof - require( - verifier.verifyProof(proof.pA, proof.pB, proof.pC, publicInputs), - "Invalid proof" - ); - processInputsAndOutputs(inputs, outputs); uint256[] memory encryptedValuesArray = new uint256[]( diff --git a/solidity/contracts/zeto_anon_enc_nullifier.sol b/solidity/contracts/zeto_anon_enc_nullifier.sol index f6cec53..3cc8f23 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier.sol @@ -26,7 +26,7 @@ import {Registry} from "./lib/registry.sol"; import {Commonlib} from "./lib/common.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -uint256 constant MAX_BATCH = 10; // batch not supported +uint256 constant MAX_BATCH = 10; /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking /// @author Kaleido, Inc. @@ -93,48 +93,90 @@ contract Zeto_AnonEncNullifier is outputs, MAX_BATCH ); - if (outputs.length > 2) { - revert("batch not supported"); - } require( validateTransactionProposal(nullifiers, outputs, root), "Invalid transaction proposal" ); - - // construct the public inputs - uint256[12] memory publicInputs; - uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit - for (uint256 i = 0; i < encryptedValues.length; ++i) { - publicInputs[piIndex++] = encryptedValues[i]; - } - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } - - // copy root - publicInputs[piIndex++] = root; - - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + if (nullifiers.length > 2) { + // construct the public inputs + uint256[36] memory publicInputs; + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + + // Check the proof + require( + batchVerifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); + } else { + // construct the public inputs + uint256[12] memory publicInputs; + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + + // Check the proof + require( + verifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); } - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; - } - - // copy encryption nonce - publicInputs[piIndex++] = encryptionNonce; - - // // Check the proof - require( - verifier.verifyProof(proof.pA, proof.pB, proof.pC, publicInputs), - "Invalid proof" - ); - // accept the transaction to consume the input UTXOs and produce new UTXOs processInputsAndOutputs(nullifiers, outputs); diff --git a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol index 8358811..8f97830 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol @@ -26,7 +26,7 @@ import {Registry} from "./lib/registry.sol"; import {Commonlib} from "./lib/common.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -uint256 constant MAX_BATCH = 10; // batch not supported +uint256 constant MAX_BATCH = 10; /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking /// @author Kaleido, Inc. @@ -98,50 +98,94 @@ contract Zeto_AnonEncNullifierKyc is outputs, MAX_BATCH ); - if (outputs.length > 2) { - revert("batch not supported"); - } require( validateTransactionProposal(nullifiers, outputs, root), "Invalid transaction proposal" ); - - // construct the public inputs - uint256[13] memory publicInputs; - uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit - for (uint256 i = 0; i < encryptedValues.length; ++i) { - publicInputs[piIndex++] = encryptedValues[i]; - } - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } - - // copy root - publicInputs[piIndex++] = root; - - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + if (nullifiers.length > 2) { + // construct the public inputs + uint256[37] memory publicInputs; + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy identities root + publicInputs[piIndex++] = getIdentitiesRoot(); + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + + // Check the proof + require( + batchVerifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); + } else { + // construct the public inputs + uint256[13] memory publicInputs; + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy identities root + publicInputs[piIndex++] = getIdentitiesRoot(); + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + + // Check the proof + require( + verifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); } - // copy identities root - publicInputs[piIndex++] = getIdentitiesRoot(); - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; - } - - // copy encryption nonce - publicInputs[piIndex++] = encryptionNonce; - - // Check the proof - require( - verifier.verifyProof(proof.pA, proof.pB, proof.pC, publicInputs), - "Invalid proof" - ); - // accept the transaction to consume the input UTXOs and produce new UTXOs processInputsAndOutputs(nullifiers, outputs); diff --git a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol index aa7f46d..11c79a4 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol @@ -25,7 +25,7 @@ import {ZetoFungibleWithdrawWithNullifiers} from "./lib/zeto_fungible_withdraw_n import {Registry} from "./lib/registry.sol"; import {Commonlib} from "./lib/common.sol"; -uint256 constant MAX_BATCH = 10; // batch not supported +uint256 constant MAX_BATCH = 10; /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking /// @author Kaleido, Inc. @@ -106,7 +106,7 @@ contract Zeto_AnonEncNullifierNonRepudiation is uint256 root, uint256 encryptionNonce, uint256[4] memory encryptedValuesForReceiver, - uint256[16] memory encryptedValuesForAuthority, + uint256[] memory encryptedValuesForAuthority, Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { @@ -116,55 +116,113 @@ contract Zeto_AnonEncNullifierNonRepudiation is outputs, MAX_BATCH ); - if (outputs.length > 2) { - revert("batch not supported"); - } require( validateTransactionProposal(nullifiers, outputs, root), "Invalid transaction proposal" ); + if (nullifiers.length > 2) { + require( + (encryptedValuesForAuthority.length == 64), + "Cipher Text for Authority must have a length of 64 with input or outputs number more than 2 and less than 10" + ); + // construct the public inputs + uint256[102] memory publicInputs; + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit for receiver + for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { + publicInputs[piIndex++] = encryptedValuesForReceiver[i]; + } + // copy the encrypted value, salt and parity bit for authority + for (uint256 i = 0; i < encryptedValuesForAuthority.length; ++i) { + publicInputs[piIndex++] = encryptedValuesForAuthority[i]; + } + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } - // construct the public inputs - uint256[30] memory publicInputs; - uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit for receiver - for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { - publicInputs[piIndex++] = encryptedValuesForReceiver[i]; - } - // copy the encrypted value, salt and parity bit for authority - for (uint256 i = 0; i < encryptedValuesForAuthority.length; ++i) { - publicInputs[piIndex++] = encryptedValuesForAuthority[i]; - } - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } + // copy root + publicInputs[piIndex++] = root; - // copy root - publicInputs[piIndex++] = root; + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; - } + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; - } + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; - // copy encryption nonce - publicInputs[piIndex++] = encryptionNonce; + // copy arbiter pub key + publicInputs[piIndex++] = arbiter[0]; + publicInputs[piIndex++] = arbiter[1]; - // copy arbiter pub key - publicInputs[piIndex++] = arbiter[0]; - publicInputs[piIndex++] = arbiter[1]; + // Check the proof + require( + batchVerifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); + } else { + require( + (encryptedValuesForAuthority.length == 16), + "Cipher Text for Authority must have a length of 16 for no more than 2 inputs or outputs" + ); + // construct the public inputs + uint256[30] memory publicInputs; + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit for receiver + for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { + publicInputs[piIndex++] = encryptedValuesForReceiver[i]; + } + // copy the encrypted value, salt and parity bit for authority + for (uint256 i = 0; i < encryptedValuesForAuthority.length; ++i) { + publicInputs[piIndex++] = encryptedValuesForAuthority[i]; + } + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } - // // Check the proof - require( - verifier.verifyProof(proof.pA, proof.pB, proof.pC, publicInputs), - "Invalid proof" - ); + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + + // copy arbiter pub key + publicInputs[piIndex++] = arbiter[0]; + publicInputs[piIndex++] = arbiter[1]; + + // Check the proof + require( + verifier.verifyProof( + proof.pA, + proof.pB, + proof.pC, + publicInputs + ), + "Invalid proof" + ); + } // accept the transaction to consume the input UTXOs and produce new UTXOs processInputsAndOutputs(nullifiers, outputs); diff --git a/solidity/contracts/zeto_nf_anon_nullifier.sol b/solidity/contracts/zeto_nf_anon_nullifier.sol index 5147c24..b353e29 100644 --- a/solidity/contracts/zeto_nf_anon_nullifier.sol +++ b/solidity/contracts/zeto_nf_anon_nullifier.sol @@ -81,7 +81,7 @@ contract Zeto_NfAnonNullifier is IZeto, ZetoNullifier, UUPSUpgradeable { publicInputs[1] = root; publicInputs[2] = output; - // // Check the proof + // Check the proof require( verifier.verifyProof(proof.pA, proof.pB, proof.pC, publicInputs), "Invalid proof" diff --git a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts index a8ffced..b710f92 100644 --- a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts +++ b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts @@ -44,6 +44,7 @@ import { deployZeto } from '../lib/deploy'; const TOTAL_AMOUNT = parseInt(process.env.TOTAL_ROUNDS || '1000'); const TX_CONCURRENCY = parseInt(process.env.TX_CONCURRENCY || '30'); +const UTXO_PER_TX = parseInt(process.env.UTXO_PER_TX || '2'); describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity using nullifiers and encryption with KYC', function () { let deployer: Signer; @@ -52,8 +53,9 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin let Charlie: User; let erc20: any; let zeto: any; - const atMostHalfAmount = Math.floor(TOTAL_AMOUNT / 2); - const atLeastHalfAmount = atMostHalfAmount + (TOTAL_AMOUNT % 2); + const atMostBatchedAmount = Math.floor(TOTAL_AMOUNT / UTXO_PER_TX); + const atLeastBatchedAmount = + atMostBatchedAmount + (TOTAL_AMOUNT % UTXO_PER_TX); let unspentAliceUTXOs: UTXO[] = []; let unspentBobUTXOs: UTXO[] = []; let mintGasCostHistory: number[] = []; @@ -126,33 +128,33 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20 .connect(deployer) - .mint(Alice.ethAddress, atMostHalfAmount); // mint to alice the amount of token that can be deposited + .mint(Alice.ethAddress, atMostBatchedAmount); // mint to alice the amount of token that can be deposited await tx.wait(); const endingBalance = await erc20.balanceOf(Alice.ethAddress); - expect(endingBalance - startingBalance).to.be.equal(atMostHalfAmount); + expect(endingBalance - startingBalance).to.be.equal(atMostBatchedAmount); console.log( - `ERC20 successfully minted ${atMostHalfAmount} to Alice for deposit` + `ERC20 successfully minted ${atMostBatchedAmount} to Alice for deposit` ); const tx1 = await erc20 .connect(Alice.signer) - .approve(zeto.target, atMostHalfAmount); + .approve(zeto.target, atMostBatchedAmount); await tx1.wait(); const startingBalanceDep = await erc20.balanceOf(zeto.target); const txDep = await erc20 .connect(deployer) - .mint(zeto.target, atLeastHalfAmount); // mint to zeto contract the amount of token that can be minted + .mint(zeto.target, atLeastBatchedAmount); // mint to zeto contract the amount of token that can be minted await txDep.wait(); const endingBalanceDep = await erc20.balanceOf(zeto.target); expect(endingBalanceDep - startingBalanceDep).to.be.equal( - atLeastHalfAmount + atLeastBatchedAmount ); }); - it(`Alice deposit ${atMostHalfAmount} token`, async function () { + it(`Alice deposit ${atMostBatchedAmount} token`, async function () { let promises = []; - for (let i = 0; i < atMostHalfAmount; i++) { + for (let i = 0; i < atMostBatchedAmount; i++) { promises.push( (async () => { const utxoSingle = newUTXO(1, Alice); @@ -189,11 +191,13 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ); }).timeout(6000000000000); - it(`Zeto mint ${atMostHalfAmount + (TOTAL_AMOUNT % 2)} token to Alice in ${ - Math.floor(atLeastHalfAmount / 2) + (atLeastHalfAmount % 2) + it(`Zeto mint ${ + atMostBatchedAmount + (TOTAL_AMOUNT % 2) + } token to Alice in ${ + Math.floor(atLeastBatchedAmount / 2) + (atLeastBatchedAmount % 2) } txs`, async function () { const mintRounds = - Math.floor(atLeastHalfAmount / 2) + (atLeastHalfAmount % 2); + Math.floor(atLeastBatchedAmount / 2) + (atLeastBatchedAmount % 2); let promises = []; for (let i = 0; i < mintRounds; i++) { promises.push( @@ -201,7 +205,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin const utxo1 = newUTXO(1, Alice); let utxo2 = newUTXO(1, Alice); - if (i === mintRounds - 1 && atLeastHalfAmount % 2 === 1) { + if (i === mintRounds - 1 && atLeastBatchedAmount % 2 === 1) { utxo2 = newUTXO(0, Alice); // odd number } @@ -243,7 +247,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ); }).timeout(6000000000000); - it(`Alice transfer ${TOTAL_AMOUNT} tokens to Bob in ${atLeastHalfAmount} txs`, async function () { + it(`Alice transfer ${TOTAL_AMOUNT} tokens to Bob in ${atLeastBatchedAmount} txs`, async function () { const totalTxs = unspentAliceUTXOs.length / 2; const utxosRoot = await smtAlice.root(); // get the root before all transfer and use it for all the proofs let promises = []; diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom index f610248..0cddc73 100644 --- a/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom +++ b/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom @@ -61,8 +61,8 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { // - secrets (value and salt) for each output UTXOs: 2 * nOutputs var outputElementsLength = 2 + 2 * nInputs + 2 * nOutputs + 2 * nOutputs; var l = outputElementsLength; - while (l % 3 != 0) { - l += 1; + if (l % 3 != 0) { + l += (3 - (l % 3)); } signal output cipherTextAuthority[l+1]; From 7602dae8f22110f297cdee9f93aa383ecb5efa7d Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Thu, 26 Sep 2024 12:14:18 +0100 Subject: [PATCH 04/24] batch test for contracts Signed-off-by: Chengxuan Xing --- ...to_anon_enc_nullifier_kyc_cost_analysis.ts | 28 +- solidity/test/utils.ts | 104 +++++--- solidity/test/zeto_anon.ts | 105 ++++++-- solidity/test/zeto_anon_enc.ts | 121 +++++++-- solidity/test/zeto_anon_enc_nullifier.ts | 171 ++++++++++--- solidity/test/zeto_anon_enc_nullifier_kyc.ts | 204 ++++++++++++--- ...zeto_anon_enc_nullifier_non_repudiation.ts | 239 ++++++++++++++---- solidity/test/zeto_anon_nullifier.ts | 153 ++++++++--- solidity/test/zeto_anon_nullifier_kyc.ts | 173 ++++++++++--- 9 files changed, 1016 insertions(+), 282 deletions(-) diff --git a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts index 0115e4b..db70b54 100644 --- a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts +++ b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts @@ -413,8 +413,8 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin owners: User[], gasHistories: number[] ) { - let nullifiers: [BigNumberish, BigNumberish]; - let outputCommitments: [BigNumberish, BigNumberish]; + let nullifiers: BigNumberish[]; + let outputCommitments: BigNumberish[]; let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; @@ -470,22 +470,18 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin BigNumberish, BigNumberish ]; - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + const inputCommitments: BigNumberish[] = inputs.map( (input) => input.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + const outputCommitments: BigNumberish[] = outputs.map( (output) => output.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ] = owners.map((owner) => owner.babyJubPublicKey) as [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ]; + const outputOwnerPublicKeys: BigNumberish[][] = owners.map( + (owner) => owner.babyJubPublicKey + ) as BigNumberish[][]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, @@ -499,7 +495,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin inputSalts, inputOwnerPrivateKey: signer.formattedPrivateKey, utxosRoot, - enabled: [nullifiers[0] !== 0n ? 1 : 0, nullifiers[1] !== 0n ? 1 : 0], + enabled: nullifiers.map((n) => (n !== 0n ? 1 : 0)), utxosMerkleProof, identitiesRoot, identitiesMerkleProof, @@ -539,8 +535,8 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin async function sendTx( signer: User, - nullifiers: [BigNumberish, BigNumberish], - outputCommitments: [BigNumberish, BigNumberish], + nullifiers: BigNumberish[], + outputCommitments: BigNumberish[], root: BigNumberish, encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, diff --git a/solidity/test/utils.ts b/solidity/test/utils.ts index b969788..b932135 100644 --- a/solidity/test/utils.ts +++ b/solidity/test/utils.ts @@ -14,17 +14,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { readFileSync } from "fs"; -import * as path from "path"; +import { readFileSync } from 'fs'; +import * as path from 'path'; import { BigNumberish } from 'ethers'; import { groth16 } from 'snarkjs'; -import { loadCircuit, encodeProof } from "zeto-js"; -import { User, UTXO } from "./lib/utils"; +import { loadCircuit, encodeProof } from 'zeto-js'; +import { User, UTXO } from './lib/utils'; function provingKeysRoot() { const PROVING_KEYS_ROOT = process.env.PROVING_KEYS_ROOT; if (!PROVING_KEYS_ROOT) { - throw new Error("PROVING_KEYS_ROOT env var is not set"); + throw new Error('PROVING_KEYS_ROOT env var is not set'); } return PROVING_KEYS_ROOT; } @@ -45,46 +45,64 @@ export function loadProvingKeys(type: string) { export async function prepareDepositProof(signer: User, output: UTXO) { const outputCommitments: [BigNumberish] = [output.hash] as [BigNumberish]; const outputValues = [BigInt(output.value || 0n)]; - const outputOwnerPublicKeys: [[BigNumberish, BigNumberish]] = [signer.babyJubPublicKey] as [[BigNumberish, BigNumberish]]; + const outputOwnerPublicKeys: [[BigNumberish, BigNumberish]] = [ + signer.babyJubPublicKey, + ] as [[BigNumberish, BigNumberish]]; const inputObj = { outputCommitments, outputValues, outputSalts: [output.salt], - outputOwnerPublicKeys + outputOwnerPublicKeys, }; const circuit = await loadCircuit('check_hashes_value'); const { provingKeyFile } = loadProvingKeys('check_hashes_value'); const startWitnessCalculation = Date.now(); - const witness = await circuit.calculateWTNSBin( - inputObj, - true - ); + const witness = await circuit.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; + const { proof, publicSignals } = (await groth16.prove( + provingKeyFile, + witness + )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; - console.log(`Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`); + console.log( + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + ); const encodedProof = encodeProof(proof); return { outputCommitments, - encodedProof + encodedProof, }; } -export async function prepareNullifierWithdrawProof(signer: User, inputs: UTXO[], _nullifiers: UTXO[], output: UTXO, root: BigInt, merkleProof: BigInt[][]) { - const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [BigNumberish, BigNumberish]; - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map((input) => input.hash) as [BigNumberish, BigNumberish]; +export async function prepareNullifierWithdrawProof( + signer: User, + inputs: UTXO[], + _nullifiers: UTXO[], + output: UTXO, + root: BigInt, + merkleProof: BigInt[][] +) { + const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ + BigNumberish, + BigNumberish + ]; + const inputCommitments: BigNumberish[] = inputs.map( + (input) => input.hash + ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); const outputCommitments: [BigNumberish] = [output.hash] as [BigNumberish]; const outputValues = [BigInt(output.value || 0n)]; - const outputOwnerPublicKeys: [[BigNumberish, BigNumberish]] = [signer.babyJubPublicKey] as [[BigNumberish, BigNumberish]]; + const outputOwnerPublicKeys: [[BigNumberish, BigNumberish]] = [ + signer.babyJubPublicKey, + ] as [[BigNumberish, BigNumberish]]; const inputObj = { nullifiers, @@ -98,39 +116,49 @@ export async function prepareNullifierWithdrawProof(signer: User, inputs: UTXO[] outputCommitments, outputValues, outputSalts: [output.salt], - outputOwnerPublicKeys + outputOwnerPublicKeys, }; const circuit = await loadCircuit('check_nullifier_value'); const { provingKeyFile } = loadProvingKeys('check_nullifier_value'); const startWitnessCalculation = Date.now(); - const witness = await circuit.calculateWTNSBin( - inputObj, - true - ); + const witness = await circuit.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; + const { proof, publicSignals } = (await groth16.prove( + provingKeyFile, + witness + )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; - console.log(`Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`); + console.log( + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + ); const encodedProof = encodeProof(proof); return { nullifiers, outputCommitments, - encodedProof + encodedProof, }; } -export async function prepareWithdrawProof(signer: User, inputs: UTXO[], output: UTXO) { - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map((input) => input.hash) as [BigNumberish, BigNumberish]; +export async function prepareWithdrawProof( + signer: User, + inputs: UTXO[], + output: UTXO +) { + const inputCommitments: BigNumberish[] = inputs.map( + (input) => input.hash + ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); const outputCommitments: [BigNumberish] = [output.hash] as [BigNumberish]; const outputValues = [BigInt(output.value || 0n)]; - const outputOwnerPublicKeys: [[BigNumberish, BigNumberish]] = [signer.babyJubPublicKey] as [[BigNumberish, BigNumberish]]; + const outputOwnerPublicKeys: [[BigNumberish, BigNumberish]] = [ + signer.babyJubPublicKey, + ] as [[BigNumberish, BigNumberish]]; const inputObj = { inputCommitments, @@ -140,28 +168,30 @@ export async function prepareWithdrawProof(signer: User, inputs: UTXO[], output: outputCommitments, outputValues, outputSalts: [output.salt], - outputOwnerPublicKeys + outputOwnerPublicKeys, }; const circuit = await loadCircuit('check_inputs_outputs_value'); const { provingKeyFile } = loadProvingKeys('check_inputs_outputs_value'); const startWitnessCalculation = Date.now(); - const witness = await circuit.calculateWTNSBin( - inputObj, - true - ); + const witness = await circuit.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; + const { proof, publicSignals } = (await groth16.prove( + provingKeyFile, + witness + )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; - console.log(`Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`); + console.log( + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + ); const encodedProof = encodeProof(proof); return { inputCommitments, outputCommitments, - encodedProof + encodedProof, }; } diff --git a/solidity/test/zeto_anon.ts b/solidity/test/zeto_anon.ts index fd9ed68..2a748ac 100644 --- a/solidity/test/zeto_anon.ts +++ b/solidity/test/zeto_anon.ts @@ -54,6 +54,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi let utxo4: UTXO; let utxo7: UTXO; let circuit: any, provingKey: any; + let batchCircuit: any, batchProvingKey: any; before(async function () { if (network.name !== 'hardhat') { @@ -70,6 +71,61 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi circuit = await loadCircuit('anon'); ({ provingKeyFile: provingKey } = loadProvingKeys('anon')); + + batchCircuit = await loadCircuit('anon_batch'); + ({ provingKeyFile: batchProvingKey } = loadProvingKeys('anon_batch')); + }); + + it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + // first mint the tokens for batch testing + const inputUtxos = []; + for (let i = 0; i < 10; i++) { + // mint 10 utxos + inputUtxos.push(newUTXO(1, Alice)); + } + await doMint(zeto, deployer, inputUtxos); + + // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + const _bOut1 = newUTXO(8, Bob); + const _bOut2 = newUTXO(1, Alice); + const _bOut3 = newUTXO(1, Alice); + const outputUtxos = [_bOut1, _bOut2, _bOut3]; + const outputOwners = [Bob, Alice, Alice]; + const inflatedOutputUtxos = [...outputUtxos]; + const inflatedOutputOwners = [...outputOwners]; + for (let i = 0; i < 10 - outputUtxos.length; i++) { + inflatedOutputUtxos.push(ZERO_UTXO); + inflatedOutputOwners.push(Bob); + } + + // Alice transfers UTXOs to Bob + const result = await doTransfer( + Alice, + inputUtxos, + inflatedOutputUtxos, + inflatedOutputOwners + ); + + const events = parseUTXOEvents(zeto, result); + const incomingUTXOs: any = events[0].outputs; + // check the non-empty output hashes are correct + for (let i = 0; i < outputUtxos.length; i++) { + // Bob uses the information received from Alice to reconstruct the UTXO sent to him + const receivedValue = outputUtxos[i].value; + const receivedSalt = outputUtxos[i].salt; + const hash = poseidonHash([ + BigInt(receivedValue), + receivedSalt, + outputOwners[i].babyJubPublicKey[0], + outputOwners[i].babyJubPublicKey[1], + ]); + expect(incomingUTXOs[i]).to.equal(hash); + } + + // check empty hashes are empty + for (let i = outputUtxos.length; i < 10; i++) { + expect(incomingUTXOs[i]).to.equal(0); + } }); it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { @@ -257,13 +313,19 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi outputs: UTXO[], owners: User[] ) { - let inputCommitments: [BigNumberish, BigNumberish]; - let outputCommitments: [BigNumberish, BigNumberish]; - let outputOwnerAddresses: [AddressLike, AddressLike]; + let inputCommitments: BigNumberish[]; + let outputCommitments: BigNumberish[]; + let outputOwnerAddresses: AddressLike[]; let encodedProof: any; + let circuitToUse = circuit; + let provingKeyToUse = provingKey; + if (inputs.length > 2 || outputs.length > 2) { + circuitToUse = batchCircuit; + provingKeyToUse = batchProvingKey; + } const result = await prepareProof( - circuit, - provingKey, + circuitToUse, + provingKeyToUse, signer, inputs, outputs, @@ -287,15 +349,18 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi async function sendTx( signer: User, - inputCommitments: [BigNumberish, BigNumberish], - outputCommitments: [BigNumberish, BigNumberish], - outputOwnerAddresses: [AddressLike, AddressLike], + inputCommitments: BigNumberish[], + outputCommitments: BigNumberish[], + outputOwnerAddresses: AddressLike[], encodedProof: any ) { const signerAddress = await signer.signer.getAddress(); - const tx = await zeto - .connect(signer.signer) - .transfer(inputCommitments, outputCommitments, encodedProof, '0x'); + const tx = await zeto.connect(signer.signer).transfer( + inputCommitments.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works + outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works + encodedProof, + '0x' + ); const results = await tx.wait(); console.log(`Method transfer() complete. Gas used: ${results?.gasUsed}`); @@ -319,23 +384,19 @@ async function prepareProof( outputs: UTXO[], owners: User[] ) { - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + const inputCommitments: BigNumberish[] = inputs.map( (input) => input.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + const outputCommitments: BigNumberish[] = outputs.map( (output) => output.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); const outputSalts = outputs.map((o) => o.salt || 0n); - const outputOwnerPublicKeys: [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ] = owners.map((owner) => owner.babyJubPublicKey || ZERO_PUBKEY) as [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ]; + const outputOwnerPublicKeys: BigNumberish[][] = owners.map( + (owner) => owner.babyJubPublicKey || ZERO_PUBKEY + ) as BigNumberish[][]; const otherInputs = stringifyBigInts({ inputOwnerPrivateKey: formatPrivKeyForBabyJub(signer.babyJubPrivateKey), }); diff --git a/solidity/test/zeto_anon_enc.ts b/solidity/test/zeto_anon_enc.ts index 44dcd77..0ecf9b2 100644 --- a/solidity/test/zeto_anon_enc.ts +++ b/solidity/test/zeto_anon_enc.ts @@ -61,6 +61,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () let utxo3: UTXO; let utxo4: UTXO; let circuit: any, provingKey: any; + let batchCircuit: any, batchProvingKey: any; before(async function () { if (network.name !== 'hardhat') { @@ -77,6 +78,72 @@ describe('Zeto based fungible token with anonymity and encryption', function () circuit = await loadCircuit('anon_enc'); ({ provingKeyFile: provingKey } = loadProvingKeys('anon_enc')); + batchCircuit = await loadCircuit('anon_enc_batch'); + ({ provingKeyFile: batchProvingKey } = loadProvingKeys('anon_enc_batch')); + }); + + it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + // first mint the tokens for batch testing + const inputUtxos = []; + for (let i = 0; i < 10; i++) { + // mint 10 utxos + inputUtxos.push(newUTXO(1, Alice)); + } + await doMint(zeto, deployer, inputUtxos); + + // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + const _bOut1 = newUTXO(8, Bob); + const _bOut2 = newUTXO(1, Alice); + const _bOut3 = newUTXO(1, Alice); + const outputUtxos = [_bOut1, _bOut2, _bOut3]; + const outputOwners = [Bob, Alice, Alice]; + const inflatedOutputUtxos = [...outputUtxos]; + const inflatedOutputOwners = [...outputOwners]; + for (let i = 0; i < 10 - outputUtxos.length; i++) { + inflatedOutputUtxos.push(ZERO_UTXO); + inflatedOutputOwners.push(Bob); + } + + // Alice transfers UTXOs to Bob + const result = await doTransfer( + Alice, + inputUtxos, + inflatedOutputUtxos, + inflatedOutputOwners + ); + + const events = parseUTXOEvents(zeto, result.txResult!); + expect(events[0].inputs).to.deep.equal(inputUtxos.map((i) => i.hash)); + const incomingUTXOs: any = events[0].outputs; + // Bob reconstructs the shared key using his private key and Alice's public key (obtained out of band) + const senderPublicKey = Alice.babyJubPublicKey; + + const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, senderPublicKey); + const plainText = poseidonDecrypt( + events[0].encryptedValues, + sharedKey, + events[0].encryptionNonce, + 2 + ); + expect(plainText).to.deep.equal([8n, result.plainTextSalt]); + // only the first utxo can be decrypted + const hash = poseidonHash([ + BigInt(plainText[0]), + plainText[1], + Bob.babyJubPublicKey[0], + Bob.babyJubPublicKey[1], + ]); + expect(hash).to.equal(incomingUTXOs[0]); + + // check the non-empty output hashes are correct + for (let i = 1; i < outputUtxos.length; i++) { + expect(incomingUTXOs[i]).to.equal(outputUtxos[i].hash); + } + + // check empty hashes are empty + for (let i = outputUtxos.length; i < 10; i++) { + expect(incomingUTXOs[i]).to.equal(0); + } }); it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { @@ -268,8 +335,8 @@ describe('Zeto based fungible token with anonymity and encryption', function () outputs: UTXO[], owners: User[] ) { - let inputCommitments: [BigNumberish, BigNumberish]; - let outputCommitments: [BigNumberish, BigNumberish]; + let inputCommitments: BigNumberish[]; + let outputCommitments: BigNumberish[]; let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; @@ -298,30 +365,32 @@ describe('Zeto based fungible token with anonymity and encryption', function () outputs: UTXO[], owners: User[] ) { - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + const inputCommitments: BigNumberish[] = inputs.map( (input) => input.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + const outputCommitments: BigNumberish[] = outputs.map( (output) => output.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ] = owners.map((owner) => owner.babyJubPublicKey) as [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ]; + const outputOwnerPublicKeys: BigNumberish[][] = owners.map( + (owner) => owner.babyJubPublicKey + ) as BigNumberish[][]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, inputOwnerPrivateKey: formatPrivKeyForBabyJub(signer.babyJubPrivateKey), }); + let circuitToUse = circuit; + let provingKeyToUse = provingKey; + if (inputCommitments.length > 2 || outputCommitments.length > 2) { + circuitToUse = batchCircuit; + provingKeyToUse = batchProvingKey; + } const startWitnessCalculation = Date.now(); - const witness = await circuit.calculateWTNSBin( + const witness = await circuitToUse.calculateWTNSBin( { inputCommitments, inputValues, @@ -338,7 +407,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( - provingKey, + provingKeyToUse, witness )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; @@ -359,22 +428,20 @@ describe('Zeto based fungible token with anonymity and encryption', function () async function sendTx( signer: User, - inputCommitments: [BigNumberish, BigNumberish], - outputCommitments: [BigNumberish, BigNumberish], + inputCommitments: BigNumberish[], + outputCommitments: BigNumberish[], encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, encodedProof: any ) { - const tx = await zeto - .connect(signer.signer) - .transfer( - inputCommitments, - outputCommitments, - encryptionNonce, - encryptedValues, - encodedProof, - '0x' - ); + const tx = await zeto.connect(signer.signer).transfer( + inputCommitments.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works + outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works + encryptionNonce, + encryptedValues, + encodedProof, + '0x' + ); const results: ContractTransactionReceipt | null = await tx.wait(); for (const input of inputCommitments) { diff --git a/solidity/test/zeto_anon_enc_nullifier.ts b/solidity/test/zeto_anon_enc_nullifier.ts index 1663082..fbe155a 100644 --- a/solidity/test/zeto_anon_enc_nullifier.ts +++ b/solidity/test/zeto_anon_enc_nullifier.ts @@ -21,6 +21,7 @@ import { loadCircuit, poseidonDecrypt, encodeProof, + Poseidon, newEncryptionNonce, } from 'zeto-js'; import { groth16 } from 'snarkjs'; @@ -42,6 +43,7 @@ import { prepareNullifierWithdrawProof, } from './utils'; import { deployZeto } from './lib/deploy'; +const poseidonHash = Poseidon.poseidon4; describe('Zeto based fungible token with anonymity using nullifiers and encryption', function () { let deployer: Signer; @@ -57,6 +59,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let utxo4: UTXO; let utxo7: UTXO; let circuit: any, provingKey: any; + let batchCircuit: any, batchProvingKey: any; let smtAlice: Merkletree; let smtBob: Merkletree; @@ -73,14 +76,18 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ({ deployer, zeto, erc20 } = await deployZeto('Zeto_AnonEncNullifier')); - circuit = await loadCircuit('anon_enc_nullifier'); - ({ provingKeyFile: provingKey } = loadProvingKeys('anon_enc_nullifier')); - const storage1 = new InMemoryDB(str2Bytes('')); smtAlice = new Merkletree(storage1, true, 64); const storage2 = new InMemoryDB(str2Bytes('')); smtBob = new Merkletree(storage2, true, 64); + + circuit = await loadCircuit('anon_enc_nullifier'); + ({ provingKeyFile: provingKey } = loadProvingKeys('anon_enc_nullifier')); + batchCircuit = await loadCircuit('anon_enc_nullifier_batch'); + ({ provingKeyFile: batchProvingKey } = loadProvingKeys( + 'anon_enc_nullifier_batch' + )); }); it('onchain SMT root should be equal to the offchain SMT root', async function () { @@ -90,6 +97,103 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti expect(root.string()).to.equal(onchainRoot.toString()); }); + it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + // first mint the tokens for batch testing + const inputUtxos = []; + const nullifiers = []; + for (let i = 0; i < 10; i++) { + // mint 10 utxos + const _utxo = newUTXO(1, Alice); + nullifiers.push(newNullifier(_utxo, Alice)); + inputUtxos.push(_utxo); + } + const mintResult = await doMint(zeto, deployer, inputUtxos); + + const mintEvents = parseUTXOEvents(zeto, mintResult); + const mintedHashes = mintEvents[0].outputs; + for (let i = 0; i < mintedHashes.length; i++) { + if (mintedHashes[i] !== 0) { + await smtAlice.add(mintedHashes[i], mintedHashes[i]); + await smtBob.add(mintedHashes[i], mintedHashes[i]); + } + } + // Alice generates inclusion proofs for the UTXOs to be spent + let root = await smtAlice.root(); + const mtps = []; + for (let i = 0; i < inputUtxos.length; i++) { + const p = await smtAlice.generateCircomVerifierProof( + inputUtxos[i].hash, + root + ); + mtps.push(p.siblings.map((s) => s.bigInt())); + } + + // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + const _bOut1 = newUTXO(8, Bob); + const _bOut2 = newUTXO(1, Alice); + const _bOut3 = newUTXO(1, Alice); + const outputUtxos = [_bOut1, _bOut2, _bOut3]; + const outputOwners = [Bob, Alice, Alice]; + const inflatedOutputUtxos = [...outputUtxos]; + const inflatedOutputOwners = [...outputOwners]; + for (let i = 0; i < 10 - outputUtxos.length; i++) { + inflatedOutputUtxos.push(ZERO_UTXO); + inflatedOutputOwners.push(Bob); + } + // Alice transfers her UTXOs to Bob + const result = await doTransfer( + Alice, + inputUtxos, + nullifiers, + inflatedOutputUtxos, + root.bigInt(), + mtps, + inflatedOutputOwners + ); + + const signerAddress = await Alice.signer.getAddress(); + const events = parseUTXOEvents(zeto, result.txResult!); + expect(events[0].submitter).to.equal(signerAddress); + expect(events[0].inputs).to.deep.equal(nullifiers.map((n) => n.hash)); + + const incomingUTXOs: any = events[0].outputs; + + // Bob uses the encrypted values in the event to decrypt and recover the UTXO value and salt + const sharedKey = genEcdhSharedKey( + Bob.babyJubPrivateKey, + Alice.babyJubPublicKey + ); + const plainText = poseidonDecrypt( + events[0].encryptedValues, + sharedKey, + events[0].encryptionNonce, + 2 + ); + expect(plainText).to.deep.equal([8n, result.plainTextSalt]); + // only the first utxo can be decrypted + const hash = poseidonHash([ + BigInt(plainText[0]), + plainText[1], + Bob.babyJubPublicKey[0], + Bob.babyJubPublicKey[1], + ]); + expect(hash).to.equal(incomingUTXOs[0]); + await smtAlice.add(incomingUTXOs[0], incomingUTXOs[0]); + await smtBob.add(incomingUTXOs[0], incomingUTXOs[0]); + + // check the non-empty output hashes are correct + for (let i = 1; i < outputUtxos.length; i++) { + expect(incomingUTXOs[i]).to.equal(outputUtxos[i].hash); + await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]); + await smtBob.add(incomingUTXOs[i], incomingUTXOs[i]); + } + + // check empty hashes are empty + for (let i = outputUtxos.length; i < 10; i++) { + expect(incomingUTXOs[i]).to.equal(0); + } + }); + it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); @@ -514,8 +618,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs: BigInt[][], owners: User[] ) { - let nullifiers: [BigNumberish, BigNumberish]; - let outputCommitments: [BigNumberish, BigNumberish]; + let nullifiers: BigNumberish[]; + let outputCommitments: BigNumberish[]; let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; @@ -563,27 +667,28 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti BigNumberish, BigNumberish ]; - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + const inputCommitments: BigNumberish[] = inputs.map( (input) => input.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + const outputCommitments: BigNumberish[] = outputs.map( (output) => output.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ] = owners.map((owner) => owner.babyJubPublicKey) as [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ]; + const outputOwnerPublicKeys: BigNumberish[][] = owners.map( + (owner) => owner.babyJubPublicKey + ) as BigNumberish[][]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, }); - + let circuitToUse = circuit; + let provingKeyToUse = provingKey; + if (inputCommitments.length > 2 || outputCommitments.length > 2) { + circuitToUse = batchCircuit; + provingKeyToUse = batchProvingKey; + } const startWitnessCalculation = Date.now(); const inputObj = { nullifiers, @@ -592,20 +697,20 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti inputSalts, inputOwnerPrivateKey: signer.formattedPrivateKey, root, - enabled: [nullifiers[0] !== 0n ? 1 : 0, nullifiers[1] !== 0n ? 1 : 0], + enabled: nullifiers.map((n) => (n !== 0n ? 1 : 0)), merkleProof, outputCommitments, outputValues, - outputSalts: outputs.map((output) => output.salt), + outputSalts: outputs.map((output) => output.salt || 0n), outputOwnerPublicKeys, ...encryptInputs, }; - const witness = await circuit.calculateWTNSBin(inputObj, true); + const witness = await circuitToUse.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( - provingKey, + provingKeyToUse, witness )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; @@ -627,25 +732,23 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti async function sendTx( signer: User, - nullifiers: [BigNumberish, BigNumberish], - outputCommitments: [BigNumberish, BigNumberish], + nullifiers: BigNumberish[], + outputCommitments: BigNumberish[], root: BigNumberish, encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, encodedProof: any ) { const startTx = Date.now(); - const tx = await zeto - .connect(signer.signer) - .transfer( - nullifiers, - outputCommitments, - root, - encryptionNonce, - encryptedValues, - encodedProof, - '0x' - ); + const tx = await zeto.connect(signer.signer).transfer( + nullifiers.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works + outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works + root, + encryptionNonce, + encryptedValues, + encodedProof, + '0x' + ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ diff --git a/solidity/test/zeto_anon_enc_nullifier_kyc.ts b/solidity/test/zeto_anon_enc_nullifier_kyc.ts index ffacde0..51baa40 100644 --- a/solidity/test/zeto_anon_enc_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_enc_nullifier_kyc.ts @@ -21,6 +21,7 @@ import { loadCircuit, poseidonDecrypt, encodeProof, + Poseidon, newEncryptionNonce, kycHash, } from 'zeto-js'; @@ -44,6 +45,7 @@ import { prepareNullifierWithdrawProof, } from './utils'; import { deployZeto } from './lib/deploy'; +const poseidonHash = Poseidon.poseidon4; describe('Zeto based fungible token with anonymity using nullifiers and encryption with KYC', function () { let deployer: Signer; @@ -63,9 +65,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let utxo7: UTXO; let withdrawChangeUTXO: UTXO; let circuit: any, provingKey: any; + let batchCircuit: any, batchProvingKey: any; let smtAlice: Merkletree; let smtBob: Merkletree; let smtKyc: Merkletree; + let smtUnregistered: Merkletree; before(async function () { if (network.name !== 'hardhat') { @@ -88,11 +92,6 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const tx4 = await zeto.connect(deployer).register(Charlie.babyJubPublicKey); const result3 = await tx4.wait(); - circuit = await loadCircuit('anon_enc_nullifier_kyc'); - ({ provingKeyFile: provingKey } = loadProvingKeys( - 'anon_enc_nullifier_kyc' - )); - const storage1 = new InMemoryDB(str2Bytes('alice')); smtAlice = new Merkletree(storage1, true, 64); @@ -102,12 +101,24 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const storage3 = new InMemoryDB(str2Bytes('kyc')); smtKyc = new Merkletree(storage3, true, 10); + const storage4 = new InMemoryDB(str2Bytes('unregistered')); + smtUnregistered = new Merkletree(storage4, true, 64); + const publicKey1 = parseRegistryEvents(zeto, result1); await smtKyc.add(kycHash(publicKey1), kycHash(publicKey1)); const publicKey2 = parseRegistryEvents(zeto, result2); await smtKyc.add(kycHash(publicKey2), kycHash(publicKey2)); const publicKey3 = parseRegistryEvents(zeto, result3); await smtKyc.add(kycHash(publicKey3), kycHash(publicKey3)); + + circuit = await loadCircuit('anon_enc_nullifier_kyc'); + ({ provingKeyFile: provingKey } = loadProvingKeys( + 'anon_enc_nullifier_kyc' + )); + batchCircuit = await loadCircuit('anon_enc_nullifier_kyc_batch'); + ({ provingKeyFile: batchProvingKey } = loadProvingKeys( + 'anon_enc_nullifier_kyc_batch' + )); }); it('onchain SMT root should be equal to the offchain SMT root', async function () { @@ -117,6 +128,123 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti expect(root.string()).to.equal(onchainRoot.toString()); }); + it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + // first mint the tokens for batch testing + const inputUtxos = []; + const nullifiers = []; + for (let i = 0; i < 10; i++) { + // mint 10 utxos + const _utxo = newUTXO(1, Alice); + nullifiers.push(newNullifier(_utxo, Alice)); + inputUtxos.push(_utxo); + } + const mintResult = await doMint(zeto, deployer, inputUtxos); + + const mintEvents = parseUTXOEvents(zeto, mintResult); + const mintedHashes = mintEvents[0].outputs; + for (let i = 0; i < mintedHashes.length; i++) { + if (mintedHashes[i] !== 0) { + await smtAlice.add(mintedHashes[i], mintedHashes[i]); + await smtBob.add(mintedHashes[i], mintedHashes[i]); + await smtUnregistered.add(mintedHashes[i], mintedHashes[i]); + } + } + // Alice generates inclusion proofs for the UTXOs to be spent + let root = await smtAlice.root(); + const mtps = []; + for (let i = 0; i < inputUtxos.length; i++) { + const p = await smtAlice.generateCircomVerifierProof( + inputUtxos[i].hash, + root + ); + mtps.push(p.siblings.map((s) => s.bigInt())); + } + + // Alice generates inclusion proofs for the identities in the transaction + const identitiesRoot = await smtKyc.root(); + const aProof = await smtKyc.generateCircomVerifierProof( + kycHash(Alice.babyJubPublicKey), + identitiesRoot + ); + const aliceProof = aProof.siblings.map((s) => s.bigInt()); + const bProof = await smtKyc.generateCircomVerifierProof( + kycHash(Bob.babyJubPublicKey), + identitiesRoot + ); + const bobProof = bProof.siblings.map((s) => s.bigInt()); + + // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + const _bOut1 = newUTXO(8, Bob); + const _bOut2 = newUTXO(1, Alice); + const _bOut3 = newUTXO(1, Alice); + const outputUtxos = [_bOut1, _bOut2, _bOut3]; + const outputOwners = [Bob, Alice, Alice]; + const identityMerkleProofs = [aliceProof, bobProof, aliceProof, aliceProof]; + const inflatedOutputUtxos = [...outputUtxos]; + const inflatedOutputOwners = [...outputOwners]; + for (let i = 0; i < 10 - outputUtxos.length; i++) { + inflatedOutputUtxos.push(ZERO_UTXO); + inflatedOutputOwners.push(Bob); + identityMerkleProofs.push(bobProof); + } + // Alice transfers her UTXOs to Bob + const result = await doTransfer( + Alice, + inputUtxos, + nullifiers, + inflatedOutputUtxos, + root.bigInt(), + mtps, + identitiesRoot.bigInt(), + identityMerkleProofs, + inflatedOutputOwners + ); + + const signerAddress = await Alice.signer.getAddress(); + const events = parseUTXOEvents(zeto, result.txResult!); + expect(events[0].submitter).to.equal(signerAddress); + expect(events[0].inputs).to.deep.equal(nullifiers.map((n) => n.hash)); + + const incomingUTXOs: any = events[0].outputs; + + // Bob uses the encrypted values in the event to decrypt and recover the UTXO value and salt + const sharedKey = genEcdhSharedKey( + Bob.babyJubPrivateKey, + Alice.babyJubPublicKey + ); + const plainText = poseidonDecrypt( + events[0].encryptedValues, + sharedKey, + events[0].encryptionNonce, + 2 + ); + expect(plainText).to.deep.equal([8n, result.plainTextSalt]); + // only the first utxo can be decrypted + const hash = poseidonHash([ + BigInt(plainText[0]), + plainText[1], + Bob.babyJubPublicKey[0], + Bob.babyJubPublicKey[1], + ]); + expect(hash).to.equal(incomingUTXOs[0]); + await smtAlice.add(incomingUTXOs[0], incomingUTXOs[0]); + await smtBob.add(incomingUTXOs[0], incomingUTXOs[0]); + await smtUnregistered.add(incomingUTXOs[0], incomingUTXOs[0]); + + // check the non-empty output hashes are correct + for (let i = 1; i < outputUtxos.length; i++) { + expect(incomingUTXOs[i]).to.equal(outputUtxos[i].hash); + await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]); + await smtBob.add(incomingUTXOs[i], incomingUTXOs[i]); + await smtUnregistered.add(incomingUTXOs[i], incomingUTXOs[i]); + } + + // check empty hashes are empty + for (let i = outputUtxos.length; i < 10; i++) { + expect(incomingUTXOs[i]).to.equal(0); + } + }); + it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); @@ -368,15 +496,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti }); describe('unregistered user cases', function () { - let storage3; - let smtUnregistered: Merkletree; let unregisteredUtxo100: UTXO; - before(() => { - storage3 = new InMemoryDB(str2Bytes('unregistered')); - smtUnregistered = new Merkletree(storage3, true, 64); - }); - it('deposit by an unregistered user should succeed', async function () { const tx = await erc20 .connect(deployer) @@ -817,8 +938,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti identitiesMerkleProof: BigInt[][], owners: User[] ) { - let nullifiers: [BigNumberish, BigNumberish]; - let outputCommitments: [BigNumberish, BigNumberish]; + let nullifiers: BigNumberish[]; + let outputCommitments: BigNumberish[]; let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; @@ -871,27 +992,28 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti BigNumberish, BigNumberish ]; - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + const inputCommitments: BigNumberish[] = inputs.map( (input) => input.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + const outputCommitments: BigNumberish[] = outputs.map( (output) => output.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ] = owners.map((owner) => owner.babyJubPublicKey) as [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ]; + const outputOwnerPublicKeys: BigNumberish[][] = owners.map( + (owner) => owner.babyJubPublicKey + ) as BigNumberish[][]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, }); - + let circuitToUse = circuit; + let provingKeyToUse = provingKey; + if (inputCommitments.length > 2 || outputCommitments.length > 2) { + circuitToUse = batchCircuit; + provingKeyToUse = batchProvingKey; + } const startWitnessCalculation = Date.now(); const inputObj = { nullifiers, @@ -900,7 +1022,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti inputSalts, inputOwnerPrivateKey: signer.formattedPrivateKey, utxosRoot, - enabled: [nullifiers[0] !== 0n ? 1 : 0, nullifiers[1] !== 0n ? 1 : 0], + enabled: nullifiers.map((n) => (n !== 0n ? 1 : 0)), utxosMerkleProof, identitiesRoot, identitiesMerkleProof, @@ -910,12 +1032,12 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti outputOwnerPublicKeys, ...encryptInputs, }; - const witness = await circuit.calculateWTNSBin(inputObj, true); + const witness = await circuitToUse.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( - provingKey, + provingKeyToUse, witness )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; @@ -937,25 +1059,23 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti async function sendTx( signer: User, - nullifiers: [BigNumberish, BigNumberish], - outputCommitments: [BigNumberish, BigNumberish], + nullifiers: BigNumberish[], + outputCommitments: BigNumberish[], root: BigNumberish, encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, encodedProof: any ) { const startTx = Date.now(); - const tx = await zeto - .connect(signer.signer) - .transfer( - nullifiers, - outputCommitments, - root, - encryptionNonce, - encryptedValues, - encodedProof, - '0x' - ); + const tx = await zeto.connect(signer.signer).transfer( + nullifiers.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works + outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works + root, + encryptionNonce, + encryptedValues, + encodedProof, + '0x' + ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ diff --git a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts index dd7ecc2..d5f47a6 100644 --- a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts +++ b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts @@ -43,6 +43,7 @@ import { prepareNullifierWithdrawProof, } from './utils'; import { deployZeto } from './lib/deploy'; +const poseidonHash = Poseidon.poseidon4; describe('Zeto based fungible token with anonymity using nullifiers and encryption for non-repudiation', function () { let deployer: Signer; @@ -59,6 +60,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let utxo4: UTXO; let utxo7: UTXO; let circuit: any, provingKey: any; + let batchCircuit: any, batchProvingKey: any; let smtAlice: Merkletree; let smtBob: Merkletree; @@ -83,16 +85,22 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti .setArbiter(Authority.babyJubPublicKey); await tx1.wait(); - circuit = await loadCircuit('anon_enc_nullifier_non_repudiation'); - ({ provingKeyFile: provingKey } = loadProvingKeys( - 'anon_enc_nullifier_non_repudiation' - )); - const storage1 = new InMemoryDB(str2Bytes('')); smtAlice = new Merkletree(storage1, true, 64); const storage2 = new InMemoryDB(str2Bytes('')); smtBob = new Merkletree(storage2, true, 64); + + circuit = await loadCircuit('anon_enc_nullifier_non_repudiation'); + ({ provingKeyFile: provingKey } = loadProvingKeys( + 'anon_enc_nullifier_non_repudiation' + )); + batchCircuit = await loadCircuit( + 'anon_enc_nullifier_non_repudiation_batch' + ); + ({ provingKeyFile: batchProvingKey } = loadProvingKeys( + 'anon_enc_nullifier_non_repudiation_batch' + )); }); it('onchain SMT root should be equal to the offchain SMT root', async function () { @@ -102,6 +110,148 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti expect(root.string()).to.equal(onchainRoot.toString()); }); + it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + // first mint the tokens for batch testing + const inputUtxos = []; + const nullifiers = []; + for (let i = 0; i < 10; i++) { + // mint 10 utxos + const _utxo = newUTXO(1, Alice); + nullifiers.push(newNullifier(_utxo, Alice)); + inputUtxos.push(_utxo); + } + const mintResult = await doMint(zeto, deployer, inputUtxos); + + const mintEvents = parseUTXOEvents(zeto, mintResult); + const mintedHashes = mintEvents[0].outputs; + for (let i = 0; i < mintedHashes.length; i++) { + if (mintedHashes[i] !== 0) { + await smtAlice.add(mintedHashes[i], mintedHashes[i]); + await smtBob.add(mintedHashes[i], mintedHashes[i]); + } + } + // Alice generates inclusion proofs for the UTXOs to be spent + let root = await smtAlice.root(); + const mtps = []; + for (let i = 0; i < inputUtxos.length; i++) { + const p = await smtAlice.generateCircomVerifierProof( + inputUtxos[i].hash, + root + ); + mtps.push(p.siblings.map((s) => s.bigInt())); + } + + + // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + const _bOut1 = newUTXO(8, Bob); + const _bOut2 = newUTXO(1, Alice); + const _bOut3 = newUTXO(1, Alice); + const outputUtxos = [_bOut1, _bOut2, _bOut3]; + const outputOwners = [Bob, Alice, Alice]; + const inflatedOutputUtxos = [...outputUtxos]; + const inflatedOutputOwners = [...outputOwners]; + for (let i = 0; i < 10 - outputUtxos.length; i++) { + inflatedOutputUtxos.push(ZERO_UTXO); + inflatedOutputOwners.push(Bob); + } + // Alice transfers her UTXOs to Bob + const result = await doTransfer( + Alice, + inputUtxos, + nullifiers, + inflatedOutputUtxos, + root.bigInt(), + mtps, + inflatedOutputOwners + ); + + const signerAddress = await Alice.signer.getAddress(); + const events = parseUTXOEvents(zeto, result.txResult!); + expect(events[0].submitter).to.equal(signerAddress); + expect(events[0].inputs).to.deep.equal(nullifiers.map((n) => n.hash)); + + const incomingUTXOs: any = events[0].outputs; + + // Bob uses the encrypted values in the event to decrypt and recover the UTXO value and salt + const sharedKey = genEcdhSharedKey( + Bob.babyJubPrivateKey, + Alice.babyJubPublicKey + ); + + const plainText = poseidonDecrypt( + events[0].encryptedValuesForReceiver, + sharedKey, + events[0].encryptionNonce, + 2 + ); + expect(plainText).to.deep.equal([8n, result.plainTextSalt]); + // only the first utxo can be decrypted + const hash = poseidonHash([ + BigInt(plainText[0]), + plainText[1], + Bob.babyJubPublicKey[0], + Bob.babyJubPublicKey[1], + ]); + expect(hash).to.equal(incomingUTXOs[0]); + await smtAlice.add(incomingUTXOs[0], incomingUTXOs[0]); + await smtBob.add(incomingUTXOs[0], incomingUTXOs[0]); + + // check the non-empty output hashes are correct + for (let i = 1; i < outputUtxos.length; i++) { + expect(incomingUTXOs[i]).to.equal(outputUtxos[i].hash); + await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]); + await smtBob.add(incomingUTXOs[i], incomingUTXOs[i]); + } + + // check empty hashes are empty + for (let i = outputUtxos.length; i < 10; i++) { + expect(incomingUTXOs[i]).to.equal(0); + } + + // The regulator uses the encrypted values in the event to decrypt and recover the UTXO value and salt + const auditKey = genEcdhSharedKey( + Authority.babyJubPrivateKey, + Alice.babyJubPublicKey + ); + const auditPlainText = poseidonDecrypt( + events[0].encryptedValuesForAuthority, + auditKey, + events[0].encryptionNonce, + 62 + ); + + // check sender pub key match + expect(auditPlainText[0]).to.equal(Alice.babyJubPublicKey[0]); + expect(auditPlainText[1]).to.equal(Alice.babyJubPublicKey[1]); + // check input values salts match + for (let i = 0; i < inputUtxos.length; i++) { + const calHash = poseidonHash([ + auditPlainText[2 * i + 2], + auditPlainText[2 * i + 3], + Alice.babyJubPublicKey[0], + Alice.babyJubPublicKey[1], + ]); + expect(calHash).to.equal(inputUtxos[i].hash); + } + // check output values salts match + // check input values salts match + for (let i = 0; i < outputUtxos.length; i++) { + const calHash = poseidonHash([ + auditPlainText[2 * i + 42], + auditPlainText[2 * i + 43], + auditPlainText[2 * i + 22], + auditPlainText[2 * i + 23], + ]); + expect(calHash).to.equal(outputUtxos[i].hash); + } + + // check empty hashes are empty + for (let i = outputUtxos.length; i < 10; i++) { + expect(auditPlainText[2 * i + 42]).to.equal(0); + expect(auditPlainText[2 * i + 43]).to.equal(0); + } + }); + it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); @@ -575,8 +725,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs: BigInt[][], owners: User[] ) { - let nullifiers: [BigNumberish, BigNumberish]; - let outputCommitments: [BigNumberish, BigNumberish]; + let nullifiers: BigNumberish[]; + let outputCommitments: BigNumberish[]; let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; @@ -595,7 +745,6 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ]; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; - encryptedValues = result.encryptedValues; encryptionNonce = result.encryptionNonce; const txResult = await sendTx( @@ -603,7 +752,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti nullifiers, outputCommitments, root, - encryptedValues, + result.encryptedValuesForReceiver, + result.encryptedValuesForRegulator, encryptionNonce, encodedProof ); @@ -624,27 +774,30 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti BigNumberish, BigNumberish ]; - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + const inputCommitments: BigNumberish[] = inputs.map( (input) => input.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + const outputCommitments: BigNumberish[] = outputs.map( (output) => output.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ] = owners.map((owner) => owner.babyJubPublicKey) as [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ]; + const outputOwnerPublicKeys: BigNumberish[][] = owners.map( + (owner) => owner.babyJubPublicKey + ) as BigNumberish[][]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, }); - + let circuitToUse = circuit; + let provingKeyToUse = provingKey; + let isBatch = false; + if (inputCommitments.length > 2 || outputCommitments.length > 2) { + isBatch = true; + circuitToUse = batchCircuit; + provingKeyToUse = batchProvingKey; + } const startWitnessCalculation = Date.now(); const inputObj = { nullifiers, @@ -653,21 +806,21 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti inputSalts, inputOwnerPrivateKey: signer.formattedPrivateKey, root, - enabled: [nullifiers[0] !== 0n ? 1 : 0, nullifiers[1] !== 0n ? 1 : 0], + enabled: nullifiers.map((n) => (n !== 0n ? 1 : 0)), merkleProof, outputCommitments, outputValues, - outputSalts: outputs.map((output) => output.salt), + outputSalts: outputs.map((output) => output.salt || 0n), outputOwnerPublicKeys, authorityPublicKey: Authority.babyJubPublicKey, ...encryptInputs, }; - const witness = await circuit.calculateWTNSBin(inputObj, true); + const witness = await circuitToUse.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( - provingKey, + provingKeyToUse, witness )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; @@ -680,7 +833,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti return { inputCommitments, outputCommitments, - encryptedValues: publicSignals.slice(0, 20), + encryptedValuesForReceiver: publicSignals.slice(0, 4), + encryptedValuesForRegulator: isBatch + ? publicSignals.slice(4, 68) + : publicSignals.slice(4, 20), encryptionNonce, encodedProof, }; @@ -688,28 +844,25 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti async function sendTx( signer: User, - nullifiers: [BigNumberish, BigNumberish], - outputCommitments: [BigNumberish, BigNumberish], + nullifiers: BigNumberish[], + outputCommitments: BigNumberish[], root: BigNumberish, - encryptedValues: BigNumberish[], + encryptedValuesForReceiver: BigNumberish[], + encryptedValuesForRegulator: BigNumberish[], encryptionNonce: BigNumberish, encodedProof: any ) { const startTx = Date.now(); - const encryptedValuesForReceiver = encryptedValues.slice(0, 4); - const encryptedValuesForRegulator = encryptedValues.slice(4, 20); - const tx = await zeto - .connect(signer.signer) - .transfer( - nullifiers, - outputCommitments, - root, - encryptionNonce, - encryptedValuesForReceiver, - encryptedValuesForRegulator, - encodedProof, - '0x' - ); + const tx = await zeto.connect(signer.signer).transfer( + nullifiers.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works + outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works + root, + encryptionNonce, + encryptedValuesForReceiver, + encryptedValuesForRegulator, + encodedProof, + '0x' + ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ diff --git a/solidity/test/zeto_anon_nullifier.ts b/solidity/test/zeto_anon_nullifier.ts index 19f1f53..8ea8705 100644 --- a/solidity/test/zeto_anon_nullifier.ts +++ b/solidity/test/zeto_anon_nullifier.ts @@ -51,6 +51,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr let utxo4: UTXO; let utxo7: UTXO; let circuit: any, provingKey: any; + let batchCircuit: any, batchProvingKey: any; let smtAlice: Merkletree; let smtBob: Merkletree; @@ -68,16 +69,19 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr ({ deployer, zeto, erc20 } = await deployZeto('Zeto_AnonNullifier')); - circuit = await loadCircuit('anon_nullifier'); - ({ provingKeyFile: provingKey } = loadProvingKeys('anon_nullifier')); - const storage1 = new InMemoryDB(str2Bytes('')); smtAlice = new Merkletree(storage1, true, 64); const storage2 = new InMemoryDB(str2Bytes('')); smtBob = new Merkletree(storage2, true, 64); - }); + circuit = await loadCircuit('anon_nullifier'); + ({ provingKeyFile: provingKey } = loadProvingKeys('anon_nullifier')); + batchCircuit = await loadCircuit('anon_nullifier_batch'); + ({ provingKeyFile: batchProvingKey } = loadProvingKeys( + 'anon_nullifier_batch' + )); + }); it('onchain SMT root should be equal to the offchain SMT root', async function () { const root = await smtAlice.root(); const onchainRoot = await zeto.getRoot(); @@ -85,6 +89,88 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr expect(root.string()).to.equal(onchainRoot.toString()); }); + it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + // first mint the tokens for batch testing + const inputUtxos = []; + const nullifiers = []; + for (let i = 0; i < 10; i++) { + // mint 10 utxos + const _utxo = newUTXO(1, Alice); + nullifiers.push(newNullifier(_utxo, Alice)); + inputUtxos.push(_utxo); + } + const mintResult = await doMint(zeto, deployer, inputUtxos); + + const mintEvents = parseUTXOEvents(zeto, mintResult); + const mintedHashes = mintEvents[0].outputs; + for (let i = 0; i < mintedHashes.length; i++) { + if (mintedHashes[i] !== 0) { + await smtAlice.add(mintedHashes[i], mintedHashes[i]); + await smtBob.add(mintedHashes[i], mintedHashes[i]); + } + } + // Alice generates inclusion proofs for the UTXOs to be spent + let root = await smtAlice.root(); + const mtps = []; + for (let i = 0; i < inputUtxos.length; i++) { + const p = await smtAlice.generateCircomVerifierProof( + inputUtxos[i].hash, + root + ); + mtps.push(p.siblings.map((s) => s.bigInt())); + } + + // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + const _bOut1 = newUTXO(8, Bob); + const _bOut2 = newUTXO(1, Alice); + const _bOut3 = newUTXO(1, Alice); + const outputUtxos = [_bOut1, _bOut2, _bOut3]; + const outputOwners = [Bob, Alice, Alice]; + const inflatedOutputUtxos = [...outputUtxos]; + const inflatedOutputOwners = [...outputOwners]; + for (let i = 0; i < 10 - outputUtxos.length; i++) { + inflatedOutputUtxos.push(ZERO_UTXO); + inflatedOutputOwners.push(Bob); + } + // Alice transfers her UTXOs to Bob + const result = await doTransfer( + Alice, + inputUtxos, + nullifiers, + inflatedOutputUtxos, + root.bigInt(), + mtps, + inflatedOutputOwners + ); + + const signerAddress = await Alice.signer.getAddress(); + const events = parseUTXOEvents(zeto, result.txResult!); + expect(events[0].submitter).to.equal(signerAddress); + expect(events[0].inputs).to.deep.equal(nullifiers.map((n) => n.hash)); + + const incomingUTXOs: any = events[0].outputs; + // check the non-empty output hashes are correct + for (let i = 0; i < outputUtxos.length; i++) { + // Bob uses the information received from Alice to reconstruct the UTXO sent to him + const receivedValue = outputUtxos[i].value; + const receivedSalt = outputUtxos[i].salt; + const hash = Poseidon.poseidon4([ + BigInt(receivedValue), + receivedSalt, + outputOwners[i].babyJubPublicKey[0], + outputOwners[i].babyJubPublicKey[1], + ]); + expect(incomingUTXOs[i]).to.equal(hash); + await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]); + await smtBob.add(incomingUTXOs[i], incomingUTXOs[i]); + } + + // check empty hashes are empty + for (let i = outputUtxos.length; i < 10; i++) { + expect(incomingUTXOs[i]).to.equal(0); + } + }); + it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); @@ -507,8 +593,8 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr merkleProofs: BigInt[][], owners: User[] ) { - let nullifiers: [BigNumberish, BigNumberish]; - let outputCommitments: [BigNumberish, BigNumberish]; + let nullifiers: BigNumberish[]; + let outputCommitments: BigNumberish[]; let encodedProof: any; const result = await prepareProof( signer, @@ -519,10 +605,9 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr merkleProofs, owners ); - nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ - BigNumberish, - BigNumberish - ]; + nullifiers = _nullifiers.map( + (nullifier) => nullifier.hash + ) as BigNumberish[]; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; @@ -550,22 +635,18 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr BigNumberish, BigNumberish ]; - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + const inputCommitments: BigNumberish[] = inputs.map( (input) => input.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + const outputCommitments: BigNumberish[] = outputs.map( (output) => output.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ] = owners.map((owner) => owner.babyJubPublicKey) as [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ]; + const outputOwnerPublicKeys: BigNumberish[][] = owners.map( + (owner) => owner.babyJubPublicKey + ) as BigNumberish[][]; const startWitnessCalculation = Date.now(); const inputObj = { @@ -575,19 +656,27 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr inputSalts, inputOwnerPrivateKey: signer.formattedPrivateKey, root, - enabled: [nullifiers[0] !== 0n ? 1 : 0, nullifiers[1] !== 0n ? 1 : 0], + enabled: nullifiers.map((n) => (n !== 0n ? 1 : 0)), merkleProof, outputCommitments, outputValues, - outputSalts: outputs.map((output) => output.salt), + outputSalts: outputs.map((output) => output.salt || 0n), outputOwnerPublicKeys, }; - const witness = await circuit.calculateWTNSBin(inputObj, true); + + let circuitToUse = circuit; + let provingKeyToUse = provingKey; + if (inputCommitments.length > 2 || outputCommitments.length > 2) { + circuitToUse = batchCircuit; + provingKeyToUse = batchProvingKey; + } + + const witness = await circuitToUse.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( - provingKey, + provingKeyToUse, witness )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; @@ -606,15 +695,19 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr async function sendTx( signer: User, - nullifiers: [BigNumberish, BigNumberish], - outputCommitments: [BigNumberish, BigNumberish], + nullifiers: BigNumberish[], + outputCommitments: BigNumberish[], root: BigNumberish, encodedProof: any ) { const startTx = Date.now(); - const tx = await zeto - .connect(signer.signer) - .transfer(nullifiers, outputCommitments, root, encodedProof, '0x'); + const tx = await zeto.connect(signer.signer).transfer( + nullifiers.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works + outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works + root, + encodedProof, + '0x' + ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ diff --git a/solidity/test/zeto_anon_nullifier_kyc.ts b/solidity/test/zeto_anon_nullifier_kyc.ts index 62a9be7..3b763ad 100644 --- a/solidity/test/zeto_anon_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_nullifier_kyc.ts @@ -56,9 +56,11 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou let utxo7: UTXO; let withdrawChangeUTXO: UTXO; let circuit: any, provingKey: any; + let batchCircuit: any, batchProvingKey: any; let smtAlice: Merkletree; let smtBob: Merkletree; let smtKyc: Merkletree; + let smtUnregistered: Merkletree; before(async function () { if (network.name !== 'hardhat') { @@ -81,9 +83,6 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const tx4 = await zeto.connect(deployer).register(Charlie.babyJubPublicKey); const result3 = await tx4.wait(); - circuit = await loadCircuit('anon_nullifier_kyc'); - ({ provingKeyFile: provingKey } = loadProvingKeys('anon_nullifier_kyc')); - const storage1 = new InMemoryDB(str2Bytes('alice')); smtAlice = new Merkletree(storage1, true, 64); @@ -93,12 +92,22 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const storage3 = new InMemoryDB(str2Bytes('kyc')); smtKyc = new Merkletree(storage3, true, 10); + const storage4 = new InMemoryDB(str2Bytes('unregistered')); + smtUnregistered = new Merkletree(storage4, true, 64); + const publicKey1 = parseRegistryEvents(zeto, result1); await smtKyc.add(kycHash(publicKey1), kycHash(publicKey1)); const publicKey2 = parseRegistryEvents(zeto, result2); await smtKyc.add(kycHash(publicKey2), kycHash(publicKey2)); const publicKey3 = parseRegistryEvents(zeto, result3); await smtKyc.add(kycHash(publicKey3), kycHash(publicKey3)); + + circuit = await loadCircuit('anon_nullifier_kyc'); + ({ provingKeyFile: provingKey } = loadProvingKeys('anon_nullifier_kyc')); + batchCircuit = await loadCircuit('anon_nullifier_kyc_batch'); + ({ provingKeyFile: batchProvingKey } = loadProvingKeys( + 'anon_nullifier_kyc_batch' + )); }); it('onchain SMT root should be equal to the offchain SMT root', async function () { @@ -108,6 +117,107 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou expect(root.string()).to.equal(onchainRoot.toString()); }); + it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + // first mint the tokens for batch testing + const inputUtxos = []; + const nullifiers = []; + for (let i = 0; i < 10; i++) { + // mint 10 utxos + const _utxo = newUTXO(1, Alice); + nullifiers.push(newNullifier(_utxo, Alice)); + inputUtxos.push(_utxo); + } + const mintResult = await doMint(zeto, deployer, inputUtxos); + + const mintEvents = parseUTXOEvents(zeto, mintResult); + const mintedHashes = mintEvents[0].outputs; + for (let i = 0; i < mintedHashes.length; i++) { + if (mintedHashes[i] !== 0) { + await smtAlice.add(mintedHashes[i], mintedHashes[i]); + await smtBob.add(mintedHashes[i], mintedHashes[i]); + await smtUnregistered.add(mintedHashes[i], mintedHashes[i]); + } + } + // Alice generates inclusion proofs for the UTXOs to be spent + let root = await smtAlice.root(); + const mtps = []; + for (let i = 0; i < inputUtxos.length; i++) { + const p = await smtAlice.generateCircomVerifierProof( + inputUtxos[i].hash, + root + ); + mtps.push(p.siblings.map((s) => s.bigInt())); + } + + // Alice generates inclusion proofs for the identities in the transaction + const identitiesRoot = await smtKyc.root(); + const aProof = await smtKyc.generateCircomVerifierProof( + kycHash(Alice.babyJubPublicKey), + identitiesRoot + ); + const aliceProof = aProof.siblings.map((s) => s.bigInt()); + const bProof = await smtKyc.generateCircomVerifierProof( + kycHash(Bob.babyJubPublicKey), + identitiesRoot + ); + const bobProof = bProof.siblings.map((s) => s.bigInt()); + // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + const _bOut1 = newUTXO(8, Bob); + const _bOut2 = newUTXO(1, Alice); + const _bOut3 = newUTXO(1, Alice); + const outputUtxos = [_bOut1, _bOut2, _bOut3]; + const outputOwners = [Bob, Alice, Alice]; + const identityMerkleProofs = [aliceProof, bobProof, aliceProof, aliceProof]; + const inflatedOutputUtxos = [...outputUtxos]; + const inflatedOutputOwners = [...outputOwners]; + for (let i = 0; i < 10 - outputUtxos.length; i++) { + inflatedOutputUtxos.push(ZERO_UTXO); + inflatedOutputOwners.push(Bob); + identityMerkleProofs.push(bobProof); + } + + // Alice transfers her UTXOs to Bob + const result = await doTransfer( + Alice, + inputUtxos, + nullifiers, + inflatedOutputUtxos, + root.bigInt(), + mtps, + identitiesRoot.bigInt(), + identityMerkleProofs, + inflatedOutputOwners + ); + + const signerAddress = await Alice.signer.getAddress(); + const events = parseUTXOEvents(zeto, result.txResult!); + expect(events[0].submitter).to.equal(signerAddress); + expect(events[0].inputs).to.deep.equal(nullifiers.map((n) => n.hash)); + + const incomingUTXOs: any = events[0].outputs; + // check the non-empty output hashes are correct + for (let i = 0; i < outputUtxos.length; i++) { + // Bob uses the information received from Alice to reconstruct the UTXO sent to him + const receivedValue = outputUtxos[i].value; + const receivedSalt = outputUtxos[i].salt; + const hash = Poseidon.poseidon4([ + BigInt(receivedValue), + receivedSalt, + outputOwners[i].babyJubPublicKey[0], + outputOwners[i].babyJubPublicKey[1], + ]); + expect(incomingUTXOs[i]).to.equal(hash); + await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]); + await smtBob.add(incomingUTXOs[i], incomingUTXOs[i]); + await smtUnregistered.add(incomingUTXOs[i], incomingUTXOs[i]); + } + + // check empty hashes are empty + for (let i = outputUtxos.length; i < 10; i++) { + expect(incomingUTXOs[i]).to.equal(0); + } + }); + it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); @@ -357,15 +467,8 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou }); describe('unregistered user flows', function () { - let storage3; - let smtUnregistered: Merkletree; let unregisteredUtxo100: UTXO; - before(() => { - storage3 = new InMemoryDB(str2Bytes('unregistered')); - smtUnregistered = new Merkletree(storage3, true, 64); - }); - it('deposit by an unregistered user should succeed', async function () { const tx = await erc20 .connect(deployer) @@ -811,8 +914,8 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou identitiesMerkleProof: BigInt[][], owners: User[] ) { - let nullifiers: [BigNumberish, BigNumberish]; - let outputCommitments: [BigNumberish, BigNumberish]; + let nullifiers: BigNumberish[]; + let outputCommitments: BigNumberish[]; let encodedProof: any; const result = await prepareProof( signer, @@ -858,22 +961,18 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou BigNumberish, BigNumberish ]; - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + const inputCommitments: BigNumberish[] = inputs.map( (input) => input.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + const outputCommitments: BigNumberish[] = outputs.map( (output) => output.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ] = owners.map((owner) => owner.babyJubPublicKey) as [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ]; + const outputOwnerPublicKeys: BigNumberish[][] = owners.map( + (owner) => owner.babyJubPublicKey + ) as BigNumberish[][]; const startWitnessCalculation = Date.now(); const inputObj = { nullifiers, @@ -882,7 +981,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou inputSalts, inputOwnerPrivateKey: signer.formattedPrivateKey, utxosRoot, - enabled: [nullifiers[0] !== 0n ? 1 : 0, nullifiers[1] !== 0n ? 1 : 0], + enabled: nullifiers.map((n) => (n !== 0n ? 1 : 0)), utxosMerkleProof, identitiesRoot, identitiesMerkleProof, @@ -891,12 +990,20 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou outputSalts: outputs.map((output) => output.salt || 0n), outputOwnerPublicKeys, }; - const witness = await circuit.calculateWTNSBin(inputObj, true); + + let circuitToUse = circuit; + let provingKeyToUse = provingKey; + if (inputCommitments.length > 2 || outputCommitments.length > 2) { + circuitToUse = batchCircuit; + provingKeyToUse = batchProvingKey; + } + + const witness = await circuitToUse.calculateWTNSBin(inputObj, true); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( - provingKey, + provingKeyToUse, witness )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; @@ -915,15 +1022,19 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou async function sendTx( signer: User, - nullifiers: [BigNumberish, BigNumberish], - outputCommitments: [BigNumberish, BigNumberish], + nullifiers: BigNumberish[], + outputCommitments: BigNumberish[], root: BigNumberish, encodedProof: any ) { const startTx = Date.now(); - const tx = await zeto - .connect(signer.signer) - .transfer(nullifiers, outputCommitments, root, encodedProof, '0x'); + const tx = await zeto.connect(signer.signer).transfer( + nullifiers.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works + outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works + root, + encodedProof, + '0x' + ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ From 273cf813946ac51fbbea2a414bb322d3f5aa1bf1 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Thu, 26 Sep 2024 14:06:02 +0100 Subject: [PATCH 05/24] return encrypted values for all outputs for batching Signed-off-by: Chengxuan Xing --- solidity/contracts/lib/verifier_anon_enc.sol | 63 +- .../contracts/lib/verifier_anon_enc_batch.sol | 232 ++++++-- .../lib/verifier_anon_enc_nullifier.sol | 75 ++- .../lib/verifier_anon_enc_nullifier_batch.sol | 276 ++++++--- .../lib/verifier_anon_enc_nullifier_kyc.sol | 79 ++- .../verifier_anon_enc_nullifier_kyc_batch.sol | 280 ++++++--- ...ier_anon_enc_nullifier_non_repudiation.sol | 147 +++-- ...on_enc_nullifier_non_repudiation_batch.sol | 540 +++++++++++------- solidity/contracts/zeto_anon_enc.sol | 6 +- .../contracts/zeto_anon_enc_nullifier.sol | 6 +- .../contracts/zeto_anon_enc_nullifier_kyc.sol | 6 +- ...eto_anon_enc_nullifier_non_repudiation.sol | 6 +- ...to_anon_enc_nullifier_kyc_cost_analysis.ts | 9 +- solidity/test/zeto_anon_enc.ts | 46 +- solidity/test/zeto_anon_enc_nullifier.ts | 48 +- solidity/test/zeto_anon_enc_nullifier_kyc.ts | 49 +- ...zeto_anon_enc_nullifier_non_repudiation.ts | 51 +- solidity/test/zeto_anon_nullifier.ts | 9 +- solidity/test/zeto_anon_nullifier_kyc.ts | 9 +- zkp/circuits/basetokens/anon_enc_base.circom | 28 +- .../basetokens/anon_enc_nullifier_base.circom | 27 +- .../anon_enc_nullifier_kyc_base.circom | 27 +- ..._enc_nullifier_non_repudiation_base.circom | 29 +- 23 files changed, 1358 insertions(+), 690 deletions(-) diff --git a/solidity/contracts/lib/verifier_anon_enc.sol b/solidity/contracts/lib/verifier_anon_enc.sol index ba456da..4bfdbc2 100644 --- a/solidity/contracts/lib/verifier_anon_enc.sol +++ b/solidity/contracts/lib/verifier_anon_enc.sol @@ -43,35 +43,44 @@ contract Groth16Verifier_AnonEnc { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 5696326670703652601376328914723856805804139150397636629981154943267586835846; - uint256 constant IC0y = 17913431813079674015620165360736989993822627917830194405007674349883405519566; + uint256 constant IC0x = 15520848054661511274945320545667385548601069271438999324366330478358568711164; + uint256 constant IC0y = 21157706785088596766640646951118458870358425037843657358834285142096534241567; - uint256 constant IC1x = 2102562587253616254650248571898720579563063454685611900201869023012028011038; - uint256 constant IC1y = 858837120372047227699859025595943051604219338012183710955972141361344096680; + uint256 constant IC1x = 8426080128821983408742228948574443657002575937683949448708665466581838540418; + uint256 constant IC1y = 2961289054807278996124904978204815851370317973256653070013442261730110386382; - uint256 constant IC2x = 19871902121561448541783335513612822391415363559792595451397804594141318386828; - uint256 constant IC2y = 14203964380144242038882743638980469366132880555873818345914201687170773944754; + uint256 constant IC2x = 16846214183034172122880181483898983231574288374891417794445456783443571203454; + uint256 constant IC2y = 4795943127049292018241039074381217225273912831887247849230603976368095834324; - uint256 constant IC3x = 4534338244167504974683945726615729215678954323916000129150608047181600075942; - uint256 constant IC3y = 9004530693581096650487103914238080672423858350236817229254519649589395343912; + uint256 constant IC3x = 10240231648004351535934471246939085350017538992419843720960233896502823753829; + uint256 constant IC3y = 918298420507614225062851310351147657365217324218976043633227084147487484538; - uint256 constant IC4x = 16926200767829183396766074136228821955738540059328214039731068817771880630127; - uint256 constant IC4y = 15535238050385142389806452090946716626530242126040333805866336792975972380578; + uint256 constant IC4x = 2676903711586497323483713249304841063436832787967161822350958984717228651508; + uint256 constant IC4y = 11366926733173287985429506187405640951452084685400170840758508049511684394323; - uint256 constant IC5x = 269115022971501175992618085182824077406065858697651888560831707201556157978; - uint256 constant IC5y = 19699073094724988754117299114476621695804537148277402334737306097425629024180; + uint256 constant IC5x = 7501808156091619633948887448038018539596703524171333033985091618683129395104; + uint256 constant IC5y = 15183325431102096756416380632145698394481557936329850246257270656919651359614; - uint256 constant IC6x = 1913049492538130220079715288227546492513434304091272666779551189559174650055; - uint256 constant IC6y = 8026674512639726678535471254304139996984356128094657497323442787106936741295; + uint256 constant IC6x = 16142642127854572324146698192700027612727186725464085127687467897687720973766; + uint256 constant IC6y = 4517714220502032665709414305462814581261203269046555880307186415606032799074; - uint256 constant IC7x = 19540350047697937581651886063231839834190225823779317423395632407508094676034; - uint256 constant IC7y = 11509057717377452054369845075648430924127395960184841862468027451544630252263; + uint256 constant IC7x = 1755538289631427930924987331320419179208761530645468129027087746202210024610; + uint256 constant IC7y = 12173734026028648655823071635152323182912152859934466692190630751344902966218; - uint256 constant IC8x = 20424145427206879140473289312774507494632015321325422705294860020477582644926; - uint256 constant IC8y = 7679128631893396357290525051865682086413798390080076016853338090494897502827; + uint256 constant IC8x = 7848298938728453306694415912843236021632832336242686994829367580246363462232; + uint256 constant IC8y = 14621047188318073218187719299332281645270167229458286064175382232430986150614; - uint256 constant IC9x = 1473626294810953820540987430623254549322665071695014303081451346851945206320; - uint256 constant IC9y = 11106503043437375969357683402411680940320268283974144474358260758792518561470; + uint256 constant IC9x = 5702664871943851440604579505620421848165916037464510240027885273509338564683; + uint256 constant IC9y = 4155173472639459280548275148817066405334382784770925752738906208871756122916; + + uint256 constant IC10x = 11951237379444909975940139423428082852090010220501184525120096272922224325380; + uint256 constant IC10y = 7330212864492454320053389793155451329372996827534004209553742378250571973798; + + uint256 constant IC11x = 17758792179933266126153564380301713721054370865026967564744749205362384449189; + uint256 constant IC11y = 20123875363051656182295676194267758869550749528323178608799833168744783048873; + + uint256 constant IC12x = 16531299530766176947215740556184329586746603539886897864186093216474595540644; + uint256 constant IC12y = 8268807341917110402770543111430324212645734302589993091794921535136544275649; // Memory data @@ -80,7 +89,7 @@ contract Groth16Verifier_AnonEnc { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[9] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[12] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -142,6 +151,12 @@ contract Groth16Verifier_AnonEnc { g1_mulAccC(_pVk, IC9x, IC9y, calldataload(add(pubSignals, 256))) + g1_mulAccC(_pVk, IC10x, IC10y, calldataload(add(pubSignals, 288))) + + g1_mulAccC(_pVk, IC11x, IC11y, calldataload(add(pubSignals, 320))) + + g1_mulAccC(_pVk, IC12x, IC12y, calldataload(add(pubSignals, 352))) + // -A mstore(_pPairing, calldataload(pA)) @@ -215,6 +230,12 @@ contract Groth16Verifier_AnonEnc { checkField(calldataload(add(_pubSignals, 288))) + checkField(calldataload(add(_pubSignals, 320))) + + checkField(calldataload(add(_pubSignals, 352))) + + checkField(calldataload(add(_pubSignals, 384))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_batch.sol b/solidity/contracts/lib/verifier_anon_enc_batch.sol index 08fa76b..a89577e 100644 --- a/solidity/contracts/lib/verifier_anon_enc_batch.sol +++ b/solidity/contracts/lib/verifier_anon_enc_batch.sol @@ -43,83 +43,137 @@ contract Groth16Verifier_AnonEncBatch { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 7189741265667894171386648378312185912800151749367063899439033842829619018531; - uint256 constant IC0y = 17884484227326304060547068939975681487394009815094922588370149976422726273268; + uint256 constant IC0x = 2597671780590251694570119685565323840048843183405159335694422232267097858944; + uint256 constant IC0y = 8213860297773598587502270259232550419091407212880698106060980975459142704915; - uint256 constant IC1x = 6976989834931789878418842558738463271861881797006171069806563232198951042869; - uint256 constant IC1y = 4607620418496754938241282900428029803466093854317753547452611458077967907674; + uint256 constant IC1x = 8862483812835763900195190187644217978558523440961934857686069698277251165035; + uint256 constant IC1y = 7652510358319732081254853215291009089945882523574369846519334872331056472570; - uint256 constant IC2x = 1104559830706076731296654664075637185187356334768646358777598477822609389028; - uint256 constant IC2y = 3345550768796772178044166540721073265036018491137886953153002525534815362810; + uint256 constant IC2x = 7888217796744605716171927246027604238387016217738102223849326057462148785492; + uint256 constant IC2y = 8576582989723476354505896974449655963516713987661765330961011770238676018217; - uint256 constant IC3x = 7339167904292788453737629411047095669569958420885203529836108618320029225321; - uint256 constant IC3y = 10127811846629680704572895087773581197933131108027374452597163321161722356281; + uint256 constant IC3x = 14352528680833998697032764557955482324646413153382503495075845465567317915183; + uint256 constant IC3y = 19243011797365702752348337725258868465391417895775931958786329833019920483153; - uint256 constant IC4x = 17995410030890053741976076817185127523995916552402057091226681421315541788709; - uint256 constant IC4y = 14362557177387632374616439821157396761988637853842253785476976058551274774314; + uint256 constant IC4x = 4392487320426708391579693966075795790380185591934224629876177226656021920102; + uint256 constant IC4y = 13082952223885280332924734169956320971361821620479520152957670710665009299216; - uint256 constant IC5x = 13293531195867414094312058265307495428535040802030900847168051381875064849320; - uint256 constant IC5y = 20854607687676821128519061564661683540031633583994135645214015131023213236658; + uint256 constant IC5x = 3246410921612126522937407677617019956902523430558290131050966139863929179563; + uint256 constant IC5y = 15810399654885178166598854163407739153721316569421450866223951195409637465167; - uint256 constant IC6x = 3806382113870713333535697141069048771701877301218229542219146213062636519118; - uint256 constant IC6y = 968164612680877984576678128366936845032166057358019883376362869104455951991; + uint256 constant IC6x = 6608448200226248204694649478827679708944271084059128867495190620836363543432; + uint256 constant IC6y = 1469463329425024480904685533245022389379237452483964428569855536915085989870; - uint256 constant IC7x = 7414361066968300446965646463524768189839597644475453090614884170383834231467; - uint256 constant IC7y = 18871824017586458935577810902748110232038032948171198588195313828414014642834; + uint256 constant IC7x = 7307852231039475112593987142383601694880236463128197701708676560849024948266; + uint256 constant IC7y = 15825828005819521547988669529549429477219509748212340587417074460536404323121; - uint256 constant IC8x = 2681577168042166677173735754938968405641600798435441472230369938066386631441; - uint256 constant IC8y = 20989323624899116464465781536163070510329583651379897156356229335935295115550; + uint256 constant IC8x = 7082876175210469881576943800412028198549838067675996862482715259243907738723; + uint256 constant IC8y = 20866219759165505486220546499441896125892835863491955389574735982947973009001; - uint256 constant IC9x = 837988643285174883060701192686929019767214369278310628575501631534377414317; - uint256 constant IC9y = 1497027309281778698096450532537321682620096834272532975906513350631947481246; + uint256 constant IC9x = 16367296414927203597516613989590733068013952698060738405287535212048793073436; + uint256 constant IC9y = 13100662036162133830465657628089803359747036547046363278544562928671020462939; - uint256 constant IC10x = 13846091047999257285561818943917831947161925448727251083606199040901309455483; - uint256 constant IC10y = 21140858725718514275007364686974077359947858906470399301442263017523861516462; + uint256 constant IC10x = 12660953324410882204944497454942873011932420236908450607037711554496291551834; + uint256 constant IC10y = 5017337532572709501338492356315622676676311947680125340270552472293496948209; - uint256 constant IC11x = 15327736368672693106243983767532414151733383231820598039546845408367990407510; - uint256 constant IC11y = 8978233402234246206405919493829088814272806423483168479609950953091130281624; + uint256 constant IC11x = 12938017223692108736253470542300205103074687940280976163691951851236725973494; + uint256 constant IC11y = 17569330124188420068165415153185726437478171411764985964911950185946817551407; - uint256 constant IC12x = 2808000964050401522326265944234314863481085671375895951164989497843153038972; - uint256 constant IC12y = 11531380100407111226047699879374413435547572518965709942666525827464698301031; + uint256 constant IC12x = 20342630885581806890644137027056481970543735603633976578131518125105821917614; + uint256 constant IC12y = 15056484383544158070695679930126332525674495858173628085598715222609521785187; - uint256 constant IC13x = 7703837959548087219235606509992045716672614065853991067483742493093046292830; - uint256 constant IC13y = 2855993324665746281147411571159804015907170749504611606481193074879718553646; + uint256 constant IC13x = 8455788225496452961679299633801872615012410834148396636082678777338966830587; + uint256 constant IC13y = 14667533314468679725174123240933383024760244475242830186466272876754757134870; - uint256 constant IC14x = 902373741697942289280883575614240691556745280904627931982629145867494138505; - uint256 constant IC14y = 15733161533380354744692088486161623354470279164235678485868913277212174304447; + uint256 constant IC14x = 12149567170771778292494559727410871049802426926691679765077855282315998609309; + uint256 constant IC14y = 1380951936221823370087711818380075591504589948146383500969529833976400607862; - uint256 constant IC15x = 10994298705029863992028152134353022932251042831787422154933994573982689419045; - uint256 constant IC15y = 17398965607134011589197925374325765086901718241003855850730487379127452367799; + uint256 constant IC15x = 4766352989791691182635058002456509827848802635606176367260246470124364530595; + uint256 constant IC15y = 16021379633910943936876425379013477219651362538262135400890871107365203200691; - uint256 constant IC16x = 11892951991080935208554921924154615154971175142927057562324705784166460551163; - uint256 constant IC16y = 5691008018070641581295928491484464757049108925919901219628385025776797906143; + uint256 constant IC16x = 13432698768504751724696856885735307391004439817130841678111462400792972424486; + uint256 constant IC16y = 19500268176699315470221660540450777362459609923828512875319635638535908023564; - uint256 constant IC17x = 16385349760746062660392139502252187515058108917152683574075970755109588098255; - uint256 constant IC17y = 4006132200257192648446443543123854816490277008709107776860749056319583986723; + uint256 constant IC17x = 2027106978523088520304891108191654793258486055367592742515642621734479986878; + uint256 constant IC17y = 12885379807754498633078727887648044664952754419022086638754196996033264000769; - uint256 constant IC18x = 15737238506544786286259248091214287531404595722259507957910389449246442985860; - uint256 constant IC18y = 8774257820042718930005071001419692491634003552583131904074826546903152827936; + uint256 constant IC18x = 10949220398425644397776376483790772577269629182083303688453860881073414915560; + uint256 constant IC18y = 20057436519045729231987911965222396188122848678213106428088994494919359307386; - uint256 constant IC19x = 5261338761583986889127298709462187597480484617121164266844247211605815308980; - uint256 constant IC19y = 6461699773895519123933988281435508110784080627465540530243192163198806094903; + uint256 constant IC19x = 5846485923548152593765310696533795024730896419830093371615151423977602741415; + uint256 constant IC19y = 17772204202833804655322390479163634517799539727968468621900059788600589940328; - uint256 constant IC20x = 13036766766347670871820341262760106552456337170159401152071561005164842009774; - uint256 constant IC20y = 4274612413808318257961480446591695381400369399274465055760884716846613784526; + uint256 constant IC20x = 16215609594427567394775135826335779265030042744678385760381534305280435465518; + uint256 constant IC20y = 18603709842506682831291739646314175009181915216384941921308130259270074065385; - uint256 constant IC21x = 18562363328719873772558553506930699000799009500209416935448544000103659611256; - uint256 constant IC21y = 6385384130214162329638041686219155710711521598989619892924465023706403534836; + uint256 constant IC21x = 1766058222969804186851406321305907427335207817599904620543688044203524722607; + uint256 constant IC21y = 13804893675033551122681507240136237947277680441710440600217850520760585066138; - uint256 constant IC22x = 17307502141503920070248089676990085687750784085011485656505049451549390745686; - uint256 constant IC22y = 16334791657275865216071338891586271191049672233905856090086893120335561416428; + uint256 constant IC22x = 10941193629908240647792765252351165933874237692700406745824002033868870639031; + uint256 constant IC22y = 3638020580879185829103840161089592128597068702224187657764432052756035287255; - uint256 constant IC23x = 2382115653931008587031786671517514604327077298833478735209768652527387951249; - uint256 constant IC23y = 10812017646661427158453552758883333361569252034751344876291235951652181181624; + uint256 constant IC23x = 5930952354462594760376136142156168856897650178619630953622712543360935660800; + uint256 constant IC23y = 1039287092721675860743161800482533616450705342550210168940302819140444260018; - uint256 constant IC24x = 21260776816977489464621013688132612122819671246444567586980092869722567001366; - uint256 constant IC24y = 20734284890134842035357978897812101948609357231813112868709593640153549726412; + uint256 constant IC24x = 532646474113271627018071424500519783214891032448645307389061272582944254003; + uint256 constant IC24y = 10151057854673851550754133166208989367948300699959847868052519117382459699016; - uint256 constant IC25x = 6214032079313504274522884081468353949125435329668975592674808638707721409871; - uint256 constant IC25y = 7937870012562608748137139051862521736631851938383982008246874681096560011742; + uint256 constant IC25x = 8405375250703253790117459631087585294901701344117711232998075871750664438242; + uint256 constant IC25y = 3944328247961513119633005636272243777809959277100342011559673763007836092026; + + uint256 constant IC26x = 21614355317718094894664738157772558388158937098373656545906139451342893449131; + uint256 constant IC26y = 8071511638847832054915722800013967614757521955341169310081076405458398492749; + + uint256 constant IC27x = 270478275418174140981268275965608765397454128234005817847677613575246346435; + uint256 constant IC27y = 2168666035663772154819161912982184259884565651971605752352808469034945793397; + + uint256 constant IC28x = 19569908851449880064455947092469809211114746841722376707408325655352308844700; + uint256 constant IC28y = 3025699621270862613925776395824335832232953797690111658313929728015843768796; + + uint256 constant IC29x = 2397616016443675765741599870545252815144654843924204698241664346514355482355; + uint256 constant IC29y = 14005094129994017499220324359090683323552493484403197787371287972073964141391; + + uint256 constant IC30x = 1594026336486525641702314048066413763993325793300000100171229876791999089353; + uint256 constant IC30y = 8072633066576840209208996401111739145989116649091797339956073760079554394308; + + uint256 constant IC31x = 941465443692266427834241213682069926914266822578025045598574216227841103683; + uint256 constant IC31y = 2162285939012937035604048436417716678642325048065608592368777414167124309037; + + uint256 constant IC32x = 17755298264501538848178211159255564751361039329014714629678463389493815518413; + uint256 constant IC32y = 5373972597904315947883222328549882023096106569825979715283040233275564684452; + + uint256 constant IC33x = 18102455506412198143265025688384882255364199113479575052771971652823946543361; + uint256 constant IC33y = 10611532522259229347040295119756938634134184132433010612585681043909048550194; + + uint256 constant IC34x = 9287592647220739061864536287605711120641354785099018403519028816976992208810; + uint256 constant IC34y = 5368688991717252135366170215180249655728193010657555227283514482663613267436; + + uint256 constant IC35x = 19759330282652380493014428586685989919377111184913674764033542113439733508101; + uint256 constant IC35y = 2793822654429148772664656948523274725780698166747463520325079729154142634364; + + uint256 constant IC36x = 11049781270295565209712493670155543711476396567038998500851076991617994490106; + uint256 constant IC36y = 11993996864162381036679383108580743566026297793935046480209203450105332505905; + + uint256 constant IC37x = 11286956316213496198784831587292367873435614453135297133863480708511731868507; + uint256 constant IC37y = 15499569902989547236933665888709713545624276075502070694155608647074297062790; + + uint256 constant IC38x = 11623006485365493322989951720233690859710722576577484852549967707014267001110; + uint256 constant IC38y = 9604064454128931077040373778349956271228053422158312825986387039993421951298; + + uint256 constant IC39x = 2464723668469969175747439301173496600708067106680738792474183669780873148058; + uint256 constant IC39y = 5627731506388173033330722271769856914412098157257440317053576454763368750030; + + uint256 constant IC40x = 386775949029146918515856173542289693566462223678664899892733838474232891465; + uint256 constant IC40y = 21843306558508533555498999953845692654015104011212021286439942440993655717111; + + uint256 constant IC41x = 14998380474237577930727399192140759096552055906436435270065429803038238552107; + uint256 constant IC41y = 16246300275134921397192579770377320255339611288167554408872393937397750566904; + + uint256 constant IC42x = 2126752576878583697702142208053334270599109357577167069195979265172189209012; + uint256 constant IC42y = 4244611359849526612607201560441002012851317308605825891261545861264066872978; + + uint256 constant IC43x = 11478497790344429290280909138615535796732148307974183201168482934125997648260; + uint256 constant IC43y = 1580586981837574023152058865433485528026059123101773522208265717828608271288; // Memory data @@ -128,7 +182,7 @@ contract Groth16Verifier_AnonEncBatch { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[25] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[43] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -222,6 +276,42 @@ contract Groth16Verifier_AnonEncBatch { g1_mulAccC(_pVk, IC25x, IC25y, calldataload(add(pubSignals, 768))) + g1_mulAccC(_pVk, IC26x, IC26y, calldataload(add(pubSignals, 800))) + + g1_mulAccC(_pVk, IC27x, IC27y, calldataload(add(pubSignals, 832))) + + g1_mulAccC(_pVk, IC28x, IC28y, calldataload(add(pubSignals, 864))) + + g1_mulAccC(_pVk, IC29x, IC29y, calldataload(add(pubSignals, 896))) + + g1_mulAccC(_pVk, IC30x, IC30y, calldataload(add(pubSignals, 928))) + + g1_mulAccC(_pVk, IC31x, IC31y, calldataload(add(pubSignals, 960))) + + g1_mulAccC(_pVk, IC32x, IC32y, calldataload(add(pubSignals, 992))) + + g1_mulAccC(_pVk, IC33x, IC33y, calldataload(add(pubSignals, 1024))) + + g1_mulAccC(_pVk, IC34x, IC34y, calldataload(add(pubSignals, 1056))) + + g1_mulAccC(_pVk, IC35x, IC35y, calldataload(add(pubSignals, 1088))) + + g1_mulAccC(_pVk, IC36x, IC36y, calldataload(add(pubSignals, 1120))) + + g1_mulAccC(_pVk, IC37x, IC37y, calldataload(add(pubSignals, 1152))) + + g1_mulAccC(_pVk, IC38x, IC38y, calldataload(add(pubSignals, 1184))) + + g1_mulAccC(_pVk, IC39x, IC39y, calldataload(add(pubSignals, 1216))) + + g1_mulAccC(_pVk, IC40x, IC40y, calldataload(add(pubSignals, 1248))) + + g1_mulAccC(_pVk, IC41x, IC41y, calldataload(add(pubSignals, 1280))) + + g1_mulAccC(_pVk, IC42x, IC42y, calldataload(add(pubSignals, 1312))) + + g1_mulAccC(_pVk, IC43x, IC43y, calldataload(add(pubSignals, 1344))) + // -A mstore(_pPairing, calldataload(pA)) @@ -327,6 +417,42 @@ contract Groth16Verifier_AnonEncBatch { checkField(calldataload(add(_pubSignals, 800))) + checkField(calldataload(add(_pubSignals, 832))) + + checkField(calldataload(add(_pubSignals, 864))) + + checkField(calldataload(add(_pubSignals, 896))) + + checkField(calldataload(add(_pubSignals, 928))) + + checkField(calldataload(add(_pubSignals, 960))) + + checkField(calldataload(add(_pubSignals, 992))) + + checkField(calldataload(add(_pubSignals, 1024))) + + checkField(calldataload(add(_pubSignals, 1056))) + + checkField(calldataload(add(_pubSignals, 1088))) + + checkField(calldataload(add(_pubSignals, 1120))) + + checkField(calldataload(add(_pubSignals, 1152))) + + checkField(calldataload(add(_pubSignals, 1184))) + + checkField(calldataload(add(_pubSignals, 1216))) + + checkField(calldataload(add(_pubSignals, 1248))) + + checkField(calldataload(add(_pubSignals, 1280))) + + checkField(calldataload(add(_pubSignals, 1312))) + + checkField(calldataload(add(_pubSignals, 1344))) + + checkField(calldataload(add(_pubSignals, 1376))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier.sol index cfbe4f3..a58f3d8 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier.sol @@ -43,44 +43,53 @@ contract Groth16Verifier_AnonEncNullifier { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 19712575420668268335634440622054263372704657131549679423053748840610444649065; - uint256 constant IC0y = 21552018618280422667464008645151951952543569291144282502207358485399703168568; + uint256 constant IC0x = 7171865328513703290093700380380451739385788586354130557725671671306758284835; + uint256 constant IC0y = 15160988901383576473200213855983245130977503188173050431265741631039643989659; - uint256 constant IC1x = 21152648367462137565411101477610760889415992049938974004172633386627195379833; - uint256 constant IC1y = 17526913059347331839566720566403027766484314611214702153099182458740108823; + uint256 constant IC1x = 3084387037124888968906054526437397944607369603426340221309478427286378241883; + uint256 constant IC1y = 466692009472632412227422575571510864857515798042934045112835241921551265392; - uint256 constant IC2x = 5554249810657633166990745736699774333938659965451342592982728994998805456417; - uint256 constant IC2y = 9730676046857216859008721613182313555756289801254042508531677626774346999622; + uint256 constant IC2x = 21832264940508969407116160765601208248355133736795673808562573616973826318173; + uint256 constant IC2y = 17513865622302204578145142072242964680658195506435185515338697999465131372215; - uint256 constant IC3x = 16411770669872316544841615427270736472060848758458781353444450000872952405569; - uint256 constant IC3y = 3883712029134278704236321509155602434293779347341551692030084302663589933567; + uint256 constant IC3x = 12015675409779862456858459776469990615909895302707101975777128025909710875049; + uint256 constant IC3y = 2520892781547161601538120167223137961114737111406729888435197618701217196087; - uint256 constant IC4x = 7689756896440471053876099704125828625789315755353261183292592808881136591701; - uint256 constant IC4y = 8154637307804119872460314948142196702392444351248969101164117581937044926170; + uint256 constant IC4x = 18587338580725867825677477230134951065880542623566314115410920967489785517516; + uint256 constant IC4y = 21420226112439899782985709520125134654836350697076867144518818376075706925435; - uint256 constant IC5x = 12299330364713292827284970278663419727424821736280679334696618553775046366194; - uint256 constant IC5y = 21075649501958706881669057145213727696785798949405955661717827102964559861134; + uint256 constant IC5x = 18346549061396084692847221708184331260051262422967450576733753481236492888092; + uint256 constant IC5y = 633678319913138336192943173886371080587792382475177160197178800699073737695; - uint256 constant IC6x = 10141596242461404912518109964401084678967632289314439332839020401548328603774; - uint256 constant IC6y = 18596814881249233508292216013928301485171008828816753337887644078332357068446; + uint256 constant IC6x = 15514772902364296574205078627736326288883089283745048573804246962058079873557; + uint256 constant IC6y = 1394197625614777654031366434591548394543950554494358685957018689229660853575; - uint256 constant IC7x = 5614211990972664557080527725484506953288266319545848669045886717392583866765; - uint256 constant IC7y = 13622161010194655100671746578655460938884567062465471617156602291997657595529; + uint256 constant IC7x = 16806786020637006306786960369076775679377041920806079893283199359601728188047; + uint256 constant IC7y = 7411897025668958146789418373160957758956645515920701058704613059473583938439; - uint256 constant IC8x = 6674121637621268879341351421207312207401087947460600984859920407988595702356; - uint256 constant IC8y = 10297122448001673280362835411108103427153986449726570946470743159995277939236; + uint256 constant IC8x = 19018133878713314349758532819088967051326614327028573516334511747113847292530; + uint256 constant IC8y = 9877630889165761579247296300368869133011487886615672260442723260497640161991; - uint256 constant IC9x = 14487240002804256779858245326714020924079439763932772957979292163240955688212; - uint256 constant IC9y = 16988309562312141308802604991498243717875695442329729574872217613083014315603; + uint256 constant IC9x = 10767786868330800120105196501607321338228888213304687234183402295397263198094; + uint256 constant IC9y = 6019304260155989652844712735958857170410842538847088443761410076894957598387; - uint256 constant IC10x = 331827925163768778062537710925718807691608177755963956359629993337951014752; - uint256 constant IC10y = 2715351447505382739630038777112973934297452331505048219000306694702162071453; + uint256 constant IC10x = 1505415316604755207127167367509090828253238030863717428595372929062841294642; + uint256 constant IC10y = 15576511224449925043716733649200226332764494096523179313664988851737446263390; - uint256 constant IC11x = 13128076096956955897155413586102975697915976403573738208997121798160993905747; - uint256 constant IC11y = 6622341877451948745754498349942713396142692080087407135054018744590375773156; + uint256 constant IC11x = 11350863237254989736684670387882645815396381623210736835421534659894890674850; + uint256 constant IC11y = 16286149570223574421139051231332214489084057970766222780431895095582201480175; - uint256 constant IC12x = 6241746058410361502439758570169395071225249678440416671369691972243849981950; - uint256 constant IC12y = 9239330025746492103538814672852590060964426378580885726917297781331433247737; + uint256 constant IC12x = 7451628250668181305280701888064824846978152009744420355240144648812642407336; + uint256 constant IC12y = 15936005158368160846313683217538494908244490784117984880368453648065515023911; + + uint256 constant IC13x = 6686413412529197180696873383139717022076724166313051457947592231187870145140; + uint256 constant IC13y = 1497406026079419977690750812932970362785235177787112328312491862602145590536; + + uint256 constant IC14x = 7772549737172193473908663974458932734834195419159040157600433771144206321357; + uint256 constant IC14y = 16378591475564435647871798005772579246008315305784601998199949074907153910639; + + uint256 constant IC15x = 13119566302351156728138299811993016524473146429243176521298671852157284998237; + uint256 constant IC15y = 16574498854084276113707136023151636502896085017309379147845117906554354077783; // Memory data @@ -89,7 +98,7 @@ contract Groth16Verifier_AnonEncNullifier { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[12] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[15] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -157,6 +166,12 @@ contract Groth16Verifier_AnonEncNullifier { g1_mulAccC(_pVk, IC12x, IC12y, calldataload(add(pubSignals, 352))) + g1_mulAccC(_pVk, IC13x, IC13y, calldataload(add(pubSignals, 384))) + + g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416))) + + g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448))) + // -A mstore(_pPairing, calldataload(pA)) @@ -236,6 +251,12 @@ contract Groth16Verifier_AnonEncNullifier { checkField(calldataload(add(_pubSignals, 384))) + checkField(calldataload(add(_pubSignals, 416))) + + checkField(calldataload(add(_pubSignals, 448))) + + checkField(calldataload(add(_pubSignals, 480))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol index 1545642..53b49d2 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol @@ -43,116 +43,170 @@ contract Groth16Verifier_AnonEncNullifierBatch { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 15463228992890913407256271912655902703204304471203583418871710110367568509017; - uint256 constant IC0y = 6081643586730902920310484720784368541485121289118172242921785599841793039397; + uint256 constant IC0x = 12126744414123145446927544518860644117520956174461536844904979731739153937319; + uint256 constant IC0y = 9695184835202931902032395296633846848346566651202119425523352011687050447653; - uint256 constant IC1x = 7690092334332803225358122531593469612638564706239742127383115275750637128544; - uint256 constant IC1y = 4070716537409257501255053424367331199883828899205760134468805014488240593235; + uint256 constant IC1x = 195592937835855475172740086869646488202858994940627750986459540968521127076; + uint256 constant IC1y = 20133094631443294605453490663465191307905205631306063705224666266432847314101; - uint256 constant IC2x = 1897861027150832646882538023040630326718005087509077431813937643855057325512; - uint256 constant IC2y = 1439104093149456820519872532162098266586027883053410812354650892557521752658; + uint256 constant IC2x = 609379390311908960003738861564802384037207126281378208589622790217906675428; + uint256 constant IC2y = 14024044248311930231657958997658229326035537165238311551943681440974095988896; - uint256 constant IC3x = 4247406668949246815522915881558097313801033425260638984520747823588066294010; - uint256 constant IC3y = 384187583735544539895332388057505134919889393310645722394574257594265340544; + uint256 constant IC3x = 14475258944672930562917429258419275006330018007564140466732576979600095527986; + uint256 constant IC3y = 8383831786003410168382306689982076122231122079851574658280916054063860804082; - uint256 constant IC4x = 2163280919944916722705407124486638913202715101976337577933948527523763136316; - uint256 constant IC4y = 17743925429712862815908467894864768203059146362469259706665186071908793546304; + uint256 constant IC4x = 2753592531034501021865774444348121286705967891727631798687428893089756717516; + uint256 constant IC4y = 10956196239229551190326394756148632499327174891582324228559177700070138627435; - uint256 constant IC5x = 1619258089617143478432432741785464751663918498436908219039181629518309232037; - uint256 constant IC5y = 11630616902607787050358650172682737668169372249533372501954846248236883577037; + uint256 constant IC5x = 20694727281247008058140870402913983925603757764003248536372865152419453726184; + uint256 constant IC5y = 632675084443897428190075680269855858382656311919806104466344079557191993970; - uint256 constant IC6x = 11856397151368437471647436909385425738968114143993909218432032948582691038255; - uint256 constant IC6y = 678272634636435534137608607645423344933204026891856980589563368261431859655; + uint256 constant IC6x = 15429847497402072415689042470309154270994030517871107730087057583238557913338; + uint256 constant IC6y = 5432278756669468541861545244015645582266245449985525214546028390310773531354; - uint256 constant IC7x = 5770940534172849936200191790166968674512475692082635469024125098067660874340; - uint256 constant IC7y = 5796891932643059731209408355543252398184249413054025674322014797701901199161; + uint256 constant IC7x = 12596502105325655558267857046382181213663420017501532384280652854282498583279; + uint256 constant IC7y = 10333147987837832448849674060620143310129669614798565710383011814099409472027; - uint256 constant IC8x = 21157884469337147167484623772858155700668090233318692577599491819791268263103; - uint256 constant IC8y = 11319817801893944559243060679771033423769978982984416308930737959593420067187; + uint256 constant IC8x = 19706927842290699304337091536861015009104078371247908023635836241791720370976; + uint256 constant IC8y = 12152105452911677618830339171375361924352461862712516323327576003984499587771; - uint256 constant IC9x = 17155601633062182536973842836383359711305654711820090042777274053320592459792; - uint256 constant IC9y = 4153339199036173911292560028271096884640710297588841704979849414084725739989; + uint256 constant IC9x = 16502342806517603727453825489628207300342455950110654028899078381918045746715; + uint256 constant IC9y = 5759609699403129611200125092383023856891064107714256272998295476995274119975; - uint256 constant IC10x = 19502162444772235516642339462161346484221330878380009887837212894180467490090; - uint256 constant IC10y = 8746377545292087029262304097721851587587533642816798045978033468894796298271; + uint256 constant IC10x = 15221251781596258119997351899631148736262625069933837816302411218064388784101; + uint256 constant IC10y = 21714792109295217531628722325832557564632293527405759778556005756241745940902; - uint256 constant IC11x = 10492727340495605431811280843573770802173281509627577093132502224855941607786; - uint256 constant IC11y = 12593957599668519647646623252624235771356540353621190049672109046663132567393; + uint256 constant IC11x = 13518783476272320621059295563539618751199322165040898390459311820772920006328; + uint256 constant IC11y = 20348572405520834933650462837534509197678154321262996827351132403485707735007; - uint256 constant IC12x = 2141055855219834142007696005384065075492349785073794976665158196389003189441; - uint256 constant IC12y = 17406300413981635438953802745917216957016698564219386571963271017518080214467; + uint256 constant IC12x = 3085516350134090993142344171310595321303355811767747642909734046142759413333; + uint256 constant IC12y = 18292877018001033289323482707732762697493866308762540047493452370416598882671; - uint256 constant IC13x = 19032830625159879771752338038675350316929691880552436444519236054639916485885; - uint256 constant IC13y = 12903015174084070036198447168709051493274452823678667961495604360873262456786; + uint256 constant IC13x = 20415604312840579619461394202638369951741974304444342076923070910792744270166; + uint256 constant IC13y = 1274709640988443541674157446934369153698888932825153138931739737641414694825; - uint256 constant IC14x = 16371683632587610030576224024875254515874360648746009582599446538505985845307; - uint256 constant IC14y = 11173673008313918399612751353743129118083339259017536663266638097162487858620; + uint256 constant IC14x = 5858495509291051391546986394308939271118066275102133287209201740349735192015; + uint256 constant IC14y = 14561847678802194093246461244839677155048289046064941818821298670851532929175; - uint256 constant IC15x = 15737548200096487165947831292170304880183367558719053011425105902130220221758; - uint256 constant IC15y = 17935613113686543895175918584771321696813538867893834513577602284559153945408; + uint256 constant IC15x = 9907641005437705469547042991575734390388809601076326909237625045131034319622; + uint256 constant IC15y = 19228656501051437063502091175033925062642380193719554208510346953512647375465; - uint256 constant IC16x = 18944733370869458467936382884278952997679539994012239122340654508303854835845; - uint256 constant IC16y = 15129624232037524523766906312590739384074339500781885555180217280630980807979; + uint256 constant IC16x = 15683266867669391751788871262440210660433189459096145429401999628086509910994; + uint256 constant IC16y = 167032798777044716931677543915419096661362132560388266364782869921944477073; - uint256 constant IC17x = 766879213842683919337084764327101390445760653210017226852735122564521980106; - uint256 constant IC17y = 13257194366329105926979110483114146395805993555097867134185789623853915836985; + uint256 constant IC17x = 14379095517200257325173372890767390667862742491742696929601242603656637834384; + uint256 constant IC17y = 19300151202444669113633208264532627998474371658767796608943018449744115979864; - uint256 constant IC18x = 466834947469548587015244622123248056190476516827510567771023410872527806519; - uint256 constant IC18y = 19073602954069385500938225445649671911205643444983500612737255746611614950303; + uint256 constant IC18x = 19979595040717998606962225834005938237531481513259865988215018262605224517880; + uint256 constant IC18y = 21832910879168436184260345537048484374140139897617063690564706843941073502156; - uint256 constant IC19x = 17648949249985332116986320075129441784946087962808100600088809464478557448096; - uint256 constant IC19y = 21066315663090040597626054677994311826852899593331220450852631484801939023727; + uint256 constant IC19x = 8226426957042014569991432650455316949765932564299138456555947664857114623439; + uint256 constant IC19y = 6228408145117381653549320958239734390061251228728720735702635598241136382652; - uint256 constant IC20x = 20154598293008989566712339828669128400118781474137050820769849877249304503719; - uint256 constant IC20y = 15496920822463556703581064294717331871146167137627219477973885063073492653138; + uint256 constant IC20x = 17772049787279101603624397097351662093398629430679036525849489583491916545941; + uint256 constant IC20y = 6754896174898647897440194918577444380308237651917088540483028012130071465948; - uint256 constant IC21x = 2324404389181201284864046287742150257907858884919451986972847726132386478888; - uint256 constant IC21y = 18134091977179255262951024580719856195604717288045403200882669041767528019153; + uint256 constant IC21x = 12428668390308036975156424643882363758080198297785963375946287369862732125338; + uint256 constant IC21y = 7754229916510745472520198965378403757343034624927137610169519146053204953496; - uint256 constant IC22x = 13221158529900749092192403410247720061249921155486754588343968542295912904556; - uint256 constant IC22y = 5028152056563650345537782053038682532283749227333291047889444926654818553282; + uint256 constant IC22x = 1151593409168857067491034330441560752818628055677134980028730195638046983154; + uint256 constant IC22y = 12238796633655133229171421264868652590324604792233399738876498509127150935586; - uint256 constant IC23x = 19361641654406595295525840785289520677449987795910033166894352349186921404440; - uint256 constant IC23y = 10650981683931869840049161361062935794760639354500379916723750499138676334844; + uint256 constant IC23x = 15130553149239877848171470204612941417069785217509981487672396229892643378048; + uint256 constant IC23y = 16099406353286235569807649940674558048574755883258872577176185277811179253351; - uint256 constant IC24x = 11148283475053323553211040486718325234959050263310938469899343323289033646909; - uint256 constant IC24y = 3109004693780647674006249758989929090923302709028884287247288297028214451989; + uint256 constant IC24x = 3794745696420163629058946455956008692538593039450146927979252667276878344635; + uint256 constant IC24y = 13521345602435249413225916136398623110469993915904908805128428652627696269000; - uint256 constant IC25x = 13228357596868509323150572957775844911612210741725650349702162165507904750898; - uint256 constant IC25y = 6331432384044620993460078250696905421162322835257350537296378202567121643631; + uint256 constant IC25x = 12972999372467026203108869807300469886972394303736354207616238357759320843869; + uint256 constant IC25y = 110817155195077381550608470818272201981579466679958649026939036130976959129; - uint256 constant IC26x = 9536375111163305409151475098581692610659685731562165281574114090536689951418; - uint256 constant IC26y = 9038552082961206589631129524924598934056043439597158013469625214978143001100; + uint256 constant IC26x = 11351987952539946970678101437449176359792007487358798597473939591460664122408; + uint256 constant IC26y = 1308124816220407348542397349028779400655687187740795098032329552311132540023; - uint256 constant IC27x = 8844438162532508945581808751476500747305933630010310294265168458587341146748; - uint256 constant IC27y = 12351730175630032342235309720309605330011746933984028737009670971810498581435; + uint256 constant IC27x = 6347411655408647494979217671534610942549776678980729506377609014193036126452; + uint256 constant IC27y = 7650341917145132808217914696212924364920359501843941028327806385968924055369; - uint256 constant IC28x = 890093037798729429015514465180574619659335658459970475515347887554928607216; - uint256 constant IC28y = 3321203689472727739933204766233295262326623168468132630828838742083531545396; + uint256 constant IC28x = 2241979173525358989962235321215348074120583391280990146670854896634571001132; + uint256 constant IC28y = 12185388424274874369299686917985366094479590786809423606708624138284993838412; - uint256 constant IC29x = 894376188310087732920965947612568506834752896038979836462341779500867941506; - uint256 constant IC29y = 8608004138419721497755714589979878275974393904523232633132083164800041862950; + uint256 constant IC29x = 9735885194340002038427422932616677437854464253276355235258485361692033205001; + uint256 constant IC29y = 21257134599531732880615697459431269975454138566860287614597128553986677458275; - uint256 constant IC30x = 11044931439964914456344334341371494069878373560303210878419944483124170473203; - uint256 constant IC30y = 9803427855593328173483023013452443696485604414496416903172860867880720274417; + uint256 constant IC30x = 6412512253306584960786699140269842400589756139861876211328703556265682364873; + uint256 constant IC30y = 8581407114773955546646978840736423622848412760263687116910154515793679605244; - uint256 constant IC31x = 1684103584023867101860046558439190165716975237508236450519282487084361635734; - uint256 constant IC31y = 5133408065911135276667071999828368466267845111169710299435079940536432113214; + uint256 constant IC31x = 12178025225657053132665080940983731293612665002217512418283569056581120597462; + uint256 constant IC31y = 9607455014410621145198574027726039505738635719236281427844203271758404744637; - uint256 constant IC32x = 4338534039647724941082052989726012587859023977099240507207676336872464936054; - uint256 constant IC32y = 16897374641288201732671683609162272649324322852915208569511172322936944220689; + uint256 constant IC32x = 18085529495250116381253041145751943562444111566259228718399282295363598571826; + uint256 constant IC32y = 8782823250887339530756219046446889579146907517254987922714625664444135020715; - uint256 constant IC33x = 9170416470183524991008272907301201709743366647977411580114896261165534711616; - uint256 constant IC33y = 3690044898492576264147530421921970583305121687878000452671756007226539391733; + uint256 constant IC33x = 1684455964508238999037002157840252070214964666015086949858287180375841490215; + uint256 constant IC33y = 17317823021755689870171330660384352287541747050385661387955290054027403355027; - uint256 constant IC34x = 8334815801605428511890555908274200358088845436285928522753824970808649461924; - uint256 constant IC34y = 12560518115013611619606981133430503709544765639252741401402558626147052803884; + uint256 constant IC34x = 18856569786292380354208383060243350821329696637837390533524190265472245806265; + uint256 constant IC34y = 15170385454602492244681441975340956197395228417205548910355740362616203767205; - uint256 constant IC35x = 19825884431345163793705281160397189448823019129369075206515699595090927399070; - uint256 constant IC35y = 7994765120516944787797908101755469459475652122106465411690195168496698193539; + uint256 constant IC35x = 6785131565994547463443700779542841839255892841358327938723286020427767742379; + uint256 constant IC35y = 20646141934315263891703794412883175937007598956830529048607441435267188352006; - uint256 constant IC36x = 8596966023108930042949859388566908182935873370403952072939322045302182518981; - uint256 constant IC36y = 5807387851106953848587697067446771376304295390995987291509842895574618702671; + uint256 constant IC36x = 6142112958288288713721741987103643316152324184749373138621669384860357362760; + uint256 constant IC36y = 11477690672876208127297157941674443659023591957852535964173518338911594550233; + + uint256 constant IC37x = 11576205874089682561141608979153392853349589278479920557765688886550510217158; + uint256 constant IC37y = 20636343449556485913175020331073900113337601414770678635262733230661106311850; + + uint256 constant IC38x = 21269453497471835097480790967495702218084039255130168071556327157478305808777; + uint256 constant IC38y = 5558133198433894177562744499152791083414114634148997050934566673629137061765; + + uint256 constant IC39x = 21390235838909311153232942303825483037076887135821993796282105744561739700802; + uint256 constant IC39y = 20595831866461058789401812156840704130288771913324404760914744933513888205949; + + uint256 constant IC40x = 15108968727023597717708181716312456040954708879008242072671403834209124126750; + uint256 constant IC40y = 21642362401012076623505143315610051538418868156813229541212544750053727665811; + + uint256 constant IC41x = 4676921041249368691385772973394433123525348781391629077041073696446952307853; + uint256 constant IC41y = 3455150633426287414331416575295821544544983286252435425896827676498333277639; + + uint256 constant IC42x = 11473615547431627715479084652307953876948759423304237083348566005440424613537; + uint256 constant IC42y = 11880397112407624959975296336174025329790822775528008256584164936996730043462; + + uint256 constant IC43x = 144280706472074616974111776963484785112293106689209428729696289517621396884; + uint256 constant IC43y = 5004797331399302171724998314688238671269525162831195827603563550926662143284; + + uint256 constant IC44x = 17937416577514179595555992349206950762346371377579337327375956989789185992781; + uint256 constant IC44y = 4706562120275640760035956575698254411341146065775454615083503549390428106814; + + uint256 constant IC45x = 6028502846265846157872138351926649108917378358004468502772419077751630260813; + uint256 constant IC45y = 1610605450716392777245163633677702348842710813982929295353634279862192986405; + + uint256 constant IC46x = 20141063340663189157054944434716958785175455085953456315504103557589402942560; + uint256 constant IC46y = 9420394857968479591478925576412437572728677224019988076827804618584163934194; + + uint256 constant IC47x = 18127069780096155830535755947830466630223230157049798571956174928085658798273; + uint256 constant IC47y = 6801063294000630374892835246016369983130409633044568041486837112693654055188; + + uint256 constant IC48x = 16182149093020958269594216045958105379538178453077387255279216324992015353251; + uint256 constant IC48y = 18316160889706950958969261837790035928674150206769644239725665787161636476483; + + uint256 constant IC49x = 3949908026086772315804919653711079994687298466353733764853664258194473256369; + uint256 constant IC49y = 3942564944144782203828107633618433107646509102323544673560261314511736786477; + + uint256 constant IC50x = 11227539341683934358245829885986203493424842258885732580499528444033926111411; + uint256 constant IC50y = 2641993489708465125648367588994825770902172935404386157992408160259561200325; + + uint256 constant IC51x = 15530708669345166982359883868765494131144955712473005394067986833015574932209; + uint256 constant IC51y = 16854387299972883130761390411793023064332059279533287092365273012880855620231; + + uint256 constant IC52x = 19879013054445385110179746397531206765963581460620226886063673937947628876243; + uint256 constant IC52y = 15699452951014667449248905102891447844972474113563121447359114087748893469079; + + uint256 constant IC53x = 8194440531815176404130697978708824056023090090624701927747808763629794457402; + uint256 constant IC53y = 17019120385819361075347135636850402270968347150863260476373100439757997339675; + + uint256 constant IC54x = 20512293947868579324477132529274423882298893397674273690289712752649033483380; + uint256 constant IC54y = 3856141993745158011335649033542760011301158064001661677116221331112179681778; // Memory data @@ -161,7 +215,7 @@ contract Groth16Verifier_AnonEncNullifierBatch { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[36] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[54] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -277,6 +331,42 @@ contract Groth16Verifier_AnonEncNullifierBatch { g1_mulAccC(_pVk, IC36x, IC36y, calldataload(add(pubSignals, 1120))) + g1_mulAccC(_pVk, IC37x, IC37y, calldataload(add(pubSignals, 1152))) + + g1_mulAccC(_pVk, IC38x, IC38y, calldataload(add(pubSignals, 1184))) + + g1_mulAccC(_pVk, IC39x, IC39y, calldataload(add(pubSignals, 1216))) + + g1_mulAccC(_pVk, IC40x, IC40y, calldataload(add(pubSignals, 1248))) + + g1_mulAccC(_pVk, IC41x, IC41y, calldataload(add(pubSignals, 1280))) + + g1_mulAccC(_pVk, IC42x, IC42y, calldataload(add(pubSignals, 1312))) + + g1_mulAccC(_pVk, IC43x, IC43y, calldataload(add(pubSignals, 1344))) + + g1_mulAccC(_pVk, IC44x, IC44y, calldataload(add(pubSignals, 1376))) + + g1_mulAccC(_pVk, IC45x, IC45y, calldataload(add(pubSignals, 1408))) + + g1_mulAccC(_pVk, IC46x, IC46y, calldataload(add(pubSignals, 1440))) + + g1_mulAccC(_pVk, IC47x, IC47y, calldataload(add(pubSignals, 1472))) + + g1_mulAccC(_pVk, IC48x, IC48y, calldataload(add(pubSignals, 1504))) + + g1_mulAccC(_pVk, IC49x, IC49y, calldataload(add(pubSignals, 1536))) + + g1_mulAccC(_pVk, IC50x, IC50y, calldataload(add(pubSignals, 1568))) + + g1_mulAccC(_pVk, IC51x, IC51y, calldataload(add(pubSignals, 1600))) + + g1_mulAccC(_pVk, IC52x, IC52y, calldataload(add(pubSignals, 1632))) + + g1_mulAccC(_pVk, IC53x, IC53y, calldataload(add(pubSignals, 1664))) + + g1_mulAccC(_pVk, IC54x, IC54y, calldataload(add(pubSignals, 1696))) + // -A mstore(_pPairing, calldataload(pA)) @@ -404,6 +494,42 @@ contract Groth16Verifier_AnonEncNullifierBatch { checkField(calldataload(add(_pubSignals, 1152))) + checkField(calldataload(add(_pubSignals, 1184))) + + checkField(calldataload(add(_pubSignals, 1216))) + + checkField(calldataload(add(_pubSignals, 1248))) + + checkField(calldataload(add(_pubSignals, 1280))) + + checkField(calldataload(add(_pubSignals, 1312))) + + checkField(calldataload(add(_pubSignals, 1344))) + + checkField(calldataload(add(_pubSignals, 1376))) + + checkField(calldataload(add(_pubSignals, 1408))) + + checkField(calldataload(add(_pubSignals, 1440))) + + checkField(calldataload(add(_pubSignals, 1472))) + + checkField(calldataload(add(_pubSignals, 1504))) + + checkField(calldataload(add(_pubSignals, 1536))) + + checkField(calldataload(add(_pubSignals, 1568))) + + checkField(calldataload(add(_pubSignals, 1600))) + + checkField(calldataload(add(_pubSignals, 1632))) + + checkField(calldataload(add(_pubSignals, 1664))) + + checkField(calldataload(add(_pubSignals, 1696))) + + checkField(calldataload(add(_pubSignals, 1728))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc.sol index 377364a..a8b5c75 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc.sol @@ -43,47 +43,56 @@ contract Groth16Verifier_AnonEncNullifierKyc { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 9571444203847882263349163823295111750012388583457810565732023354927681835330; - uint256 constant IC0y = 8269430673392355800760839451470053559913816443341643262118006327992857911204; + uint256 constant IC0x = 20190008737197394450342108694091338568135578498705703052207100846737147771508; + uint256 constant IC0y = 18598201807933691587559529080991026720330392609151625239622109760005685213067; - uint256 constant IC1x = 4171425333877223863056817685674841454723358686631303251580406544847360463144; - uint256 constant IC1y = 15508434706912610115961511481609592716639093445421134335652880195025374357944; + uint256 constant IC1x = 452139730047001491535774769574376048901142363466012203113053837887098221240; + uint256 constant IC1y = 13658069816340688216031892919771477183715607138270132569610223992086459291779; - uint256 constant IC2x = 2805234997490797748511701790284534458659062187129667755544299868178828988756; - uint256 constant IC2y = 12737871927823892823240455203969207068418359360382939881586564793007265918634; + uint256 constant IC2x = 11669592363904336123147793129704111667124410995913742542844393202522824384133; + uint256 constant IC2y = 2129828274111755038359532307450490184933143179791119510470279863460174053208; - uint256 constant IC3x = 10037927645989308427370729946962854922194022862178974033089345641900642443287; - uint256 constant IC3y = 1869974150112738935511161628734764742128849823652210548167483049626273686915; + uint256 constant IC3x = 5602520055221798217852910005981059118735291244544863913087079277844381774053; + uint256 constant IC3y = 7726036063333401533144228011207326932588220311717018715578006508331000287817; - uint256 constant IC4x = 20687486203577926209406522416577489369623505298901447042889614462294165837937; - uint256 constant IC4y = 2451926520013626473243440086333573559066473857550647156934680886755185047100; + uint256 constant IC4x = 6072157368296199502061429238559064959224878744730210919572391729526656729676; + uint256 constant IC4y = 4396342922072404817552790123329348653983654878359756160338991902928904020767; - uint256 constant IC5x = 17506157096475522989244923493066068666613854999605413994180693698287006754601; - uint256 constant IC5y = 18337141315691397667266548067044460253572013083720894042089481649614687489349; + uint256 constant IC5x = 14156444020699427007396523765579676190302247297633651840365755554480657506994; + uint256 constant IC5y = 2881585601062356032052344229762934155665470619310149307816022512770496579212; - uint256 constant IC6x = 13169264733918854243504094459072017908892434194925230289069972473474865423260; - uint256 constant IC6y = 12873033270668213434072395062604551402080299183418425353301844285688316634747; + uint256 constant IC6x = 9358173501594313028986369364273485629339361346113755970129286915338770046017; + uint256 constant IC6y = 13384389474884560654773999400020608975692705219594212374206662773259083468823; - uint256 constant IC7x = 4139352737455682815820399999502807530902270791132588001997383898128565726560; - uint256 constant IC7y = 18130358037765445238866373406538395199727660880929816773059128417420908294103; + uint256 constant IC7x = 14065806997763568929014806532831294339309631956437145603843703478380691197500; + uint256 constant IC7y = 1687305135103805962026175705339802858788468976159872593451010969624096085402; - uint256 constant IC8x = 10242723724534050633824073816542552050545643197784462676335615048377039832420; - uint256 constant IC8y = 1522077533586266907104192963207500158509684879768383246564448114116860886045; + uint256 constant IC8x = 9926610124142437987886950959946429216445771850541529210620246513398511687976; + uint256 constant IC8y = 19502865377786189863697059376790350920703694340906636204501830435181993622220; - uint256 constant IC9x = 9331953561001587156072982617181494822635260561293948857418310817015123003664; - uint256 constant IC9y = 21434180133029315517714324102175079176171466970274711902142297829796086888419; + uint256 constant IC9x = 20202496612886706972728070168467780317520786329990263116983954505480252669124; + uint256 constant IC9y = 913586774577507188230910872703557858180540085501267099041510624577736818444; - uint256 constant IC10x = 9864640468360420795111662135353906469273928885319595720979255522131895987062; - uint256 constant IC10y = 4347845420812651539643028407865491584531559916191524645768616247857747093924; + uint256 constant IC10x = 266278504835704567488781146768665494860951993308633063784954130573281237215; + uint256 constant IC10y = 2705526920088398580864915394173201881547745998451271955180647659470935759026; - uint256 constant IC11x = 12816855581744969923196393315369134257252339197623955937790101684782832727528; - uint256 constant IC11y = 10852386397854977410896573210092846697497925902496902459833247615681245355742; + uint256 constant IC11x = 1150624403544560144697842282547677965958865873924009049840449265122527450897; + uint256 constant IC11y = 2724516316035952928352656968720561599106380710401940450252385609550641895905; - uint256 constant IC12x = 14713198324057425181537280290297404746877953868974288063529731081142062871032; - uint256 constant IC12y = 12697331297870828686780559216672799476293214005074082773567772130976271883336; + uint256 constant IC12x = 6415803768033221091455097928212215437695034131747853061147487425545026770551; + uint256 constant IC12y = 16246443751013967544556252590900249372263924353922568489267825578174001055; - uint256 constant IC13x = 15748313782243366848688530768530734630700786383695534160287365098087100629526; - uint256 constant IC13y = 19624787309979166735737404819294173148608360816934232838701010568600344101162; + uint256 constant IC13x = 15362136016566638974392387943924303320566554984973627142090315874098276162948; + uint256 constant IC13y = 12045497701488042756223977093441513681724756561681694654028210754872237560091; + + uint256 constant IC14x = 851199703448569646817260303478184435364430795694990453617924138405538051073; + uint256 constant IC14y = 12946466316772451490596102009978657497675437325340719204986803177959608723364; + + uint256 constant IC15x = 32697875031995482206558610095285352816496757317111207419861004689639953522; + uint256 constant IC15y = 299944843066286224755462589381457389641818411976194173762533229362772488245; + + uint256 constant IC16x = 7813691748167190362850964237044883316155748259819716238134403668032515123276; + uint256 constant IC16y = 16204491922723545729259832959950455311755157458533342319134684244887734211089; // Memory data @@ -92,7 +101,7 @@ contract Groth16Verifier_AnonEncNullifierKyc { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[13] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[16] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -162,6 +171,12 @@ contract Groth16Verifier_AnonEncNullifierKyc { g1_mulAccC(_pVk, IC13x, IC13y, calldataload(add(pubSignals, 384))) + g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416))) + + g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448))) + + g1_mulAccC(_pVk, IC16x, IC16y, calldataload(add(pubSignals, 480))) + // -A mstore(_pPairing, calldataload(pA)) @@ -243,6 +258,12 @@ contract Groth16Verifier_AnonEncNullifierKyc { checkField(calldataload(add(_pubSignals, 416))) + checkField(calldataload(add(_pubSignals, 448))) + + checkField(calldataload(add(_pubSignals, 480))) + + checkField(calldataload(add(_pubSignals, 512))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol index 4a00e5f..57fec5c 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol @@ -43,119 +43,173 @@ contract Groth16Verifier_AnonEncNullifierKycBatch { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 11662660143860874931072351186047069691934558454076806957543648503057847943513; - uint256 constant IC0y = 10038348414197657683445922076295262289652998118153787101974831249817368174353; + uint256 constant IC0x = 2557045328174556474259602364787060617413037186775787740247120052256591101057; + uint256 constant IC0y = 8545914595700052385922827053758169584458550417191596397077967009342340172963; - uint256 constant IC1x = 8988535072375717724497491246352234049328213447683207989537377224470040054966; - uint256 constant IC1y = 8166282710103471067373199268434356717037308329558570925972507352895336171600; + uint256 constant IC1x = 8900866652413972639447801185066566440613708319253275484468074220706268630752; + uint256 constant IC1y = 18117300326867814101825535845382858738704176302675336121313760471944027618579; - uint256 constant IC2x = 18432294692910581759472826919355763187872967572458291145949908209816982819688; - uint256 constant IC2y = 21529300506719821524307516873688911621260384833976448337733933552847314256874; + uint256 constant IC2x = 6893165486528724258452539284348100242940680901205710094027141947523508922556; + uint256 constant IC2y = 11428083713288237383922201052960038086381204628185844551802602980459665852296; - uint256 constant IC3x = 614735613818836283841982905943976709929041752739745042789141794733265028134; - uint256 constant IC3y = 3860703814665496245605558172188863798062943606333015527826728127069465082427; + uint256 constant IC3x = 2787509042012632529212775966824220639705355486752580713355548540317374958318; + uint256 constant IC3y = 13559075319591979484148387886304036951246196260874348065387705986067180861572; - uint256 constant IC4x = 21110382318575147474338865721398707915802737103567042212867029114347240559300; - uint256 constant IC4y = 11477828230558650608120671853203757664438453457364362308796561794776172008451; + uint256 constant IC4x = 7981603848980165083052696916252376820361500997039057002907078064409646042704; + uint256 constant IC4y = 1631170154333774225978701321671377089584774646241757146636720110297678397686; - uint256 constant IC5x = 10955202528924804812958438713742990627683883390569205805287044297181502266729; - uint256 constant IC5y = 17858987609351477507179059147091144336664455743112357073106373084043189280164; + uint256 constant IC5x = 2718945106954835265374519388993004950467939770842588234333099827036921488036; + uint256 constant IC5y = 54129075547188978676123602750315602783350522469912352491032758031739397264; - uint256 constant IC6x = 9247132710507257341694745715536030078362897235873976845653448343004216578059; - uint256 constant IC6y = 4077530447461105776970121739853125425415755933636891068527434065606633343729; + uint256 constant IC6x = 10147624070030089461943558234086476925326752621677677347469962144928874051171; + uint256 constant IC6y = 14137637656464541694095908034649703224311668569886704894187366498167267119930; - uint256 constant IC7x = 9282229099621743758927934855838604257685882618355194980012233357617245438364; - uint256 constant IC7y = 15674736937935764122279448687928959717281418334634353011570533455984105715121; + uint256 constant IC7x = 14131833902483915573002378883085094517189637884537825125543294251780418938907; + uint256 constant IC7y = 8350712732464638756493234130405621139170404316430682690462953318721564280425; - uint256 constant IC8x = 9722132009325333783456053646735667902530261615407197523392160208704603988454; - uint256 constant IC8y = 14618244177095367221394852282157340600459069670233465954719723502618367220099; + uint256 constant IC8x = 6466504309236504330936004664742363699367258661498527049422417011059950380261; + uint256 constant IC8y = 10308743258353094916300411811569013911785525949453696511480625272875805213094; - uint256 constant IC9x = 973628821824034631277519892548216364093065392435755888383034381618210105026; - uint256 constant IC9y = 19130664929693827307694622317521885236690764504040079683400014381939179764886; + uint256 constant IC9x = 15034560127374538253652390881068026376032149277012915824928102233595801597871; + uint256 constant IC9y = 14933364448090705000296248910019334925480794867671226328859117405842595498286; - uint256 constant IC10x = 18497489122159836005440235191181397682168825652742401878718303497751950476573; - uint256 constant IC10y = 184674817624142463950860554146189016898202305618730035365532664689559015024; + uint256 constant IC10x = 1435567384244739999636752756588097453785728405750034036596678824485141706320; + uint256 constant IC10y = 21045412560666440575260065642431316733861600716932140912086713771905478605642; - uint256 constant IC11x = 20742886562308807174975673124416469858072816509700038966264317699622470845864; - uint256 constant IC11y = 6892841648413503913935428607180182195114904340636618216544980552932522306183; + uint256 constant IC11x = 20660910050407044985841964548615754563198335468098466571354791341814009582143; + uint256 constant IC11y = 17161276760446539174103283658490390916497070640753169765510233658752644125327; - uint256 constant IC12x = 1554767197776271090848221696659744029443606469011424330576588038599488901790; - uint256 constant IC12y = 17824173807300533295074190605171784659758705215735044173456990718107986673990; + uint256 constant IC12x = 14297221549426245599275426280912312242758539460442195637765479076821005351090; + uint256 constant IC12y = 7045746153755160132606239721075319853671165146167794961048168331481327369378; - uint256 constant IC13x = 8926678800934477977183437663176073269804039617131246226117210958642974831665; - uint256 constant IC13y = 7759817179292182986840792444788081906199101563123339998406609301418454149912; + uint256 constant IC13x = 6709297759563652448455456777394655766655295904612361150672442940274698264117; + uint256 constant IC13y = 604939571031743874843375836514454028390240836996444630147060119881962118591; - uint256 constant IC14x = 892387531981845359273038619022215455220935019529138222295972719463971685626; - uint256 constant IC14y = 21664606451742576757250844476052733616001992300681450622144236517957407335395; + uint256 constant IC14x = 1506931283257291434315981891710633368372940860477458257990053769650899625020; + uint256 constant IC14y = 16234509187615275824159269295900874844499753487293080637471224460931211356610; - uint256 constant IC15x = 11644738412527836785033238753051417149187120228925099428899706835198503714732; - uint256 constant IC15y = 20385101286516026017516350545863829411647430450169209244102096545003646405227; + uint256 constant IC15x = 3663986373923028376047433528346986422113085036111303782126649588832018217222; + uint256 constant IC15y = 2833212771516071304842292770750586061301584725053640822674852019170921553978; - uint256 constant IC16x = 6914380489103854988747068027174251954079888530380820907417133182165125002895; - uint256 constant IC16y = 16001027808620196049156676450902737881221224855685201356892867218134413591974; + uint256 constant IC16x = 9441974398462151962861519019668159526029441202966112923894683419951453007203; + uint256 constant IC16y = 20398645667686807455795531059467229874168827249918904721471455262548811448301; - uint256 constant IC17x = 14819004697379517927442020076999128258818136109044427450238213315710239729290; - uint256 constant IC17y = 18234035980915600023635619254964104942336216004642311690220730031352749295516; + uint256 constant IC17x = 9941969049637054555017138554864083807451665108028251180781197146279496720189; + uint256 constant IC17y = 12083041856346926425137954851405721196793285382115647784815644983516676101313; - uint256 constant IC18x = 10782655998802736438708390186837190841583872252631539739869717362042994127890; - uint256 constant IC18y = 6223193220871490512854223407339053827650007826976048957711920097140884329831; + uint256 constant IC18x = 4513953042000608174347593715577667089282919422419113365380162468063688775130; + uint256 constant IC18y = 17768548800782673039169889569716085142981878050151504480878715449322827273410; - uint256 constant IC19x = 1895164154807081669060491556433373630284427382709469252391398895819775411625; - uint256 constant IC19y = 15502891301545941170843587746206524939661082838133458062213752972874935576258; + uint256 constant IC19x = 12249598222891158199710492081231845984159762606864132240852548984852903893394; + uint256 constant IC19y = 8218081839064592605577365459229129812592277515386687488909134942995986616646; - uint256 constant IC20x = 13887414818061216296960695706977042112426565238817982814880739463438328917279; - uint256 constant IC20y = 7484477067983396480837362197475960184311309962467034141451929400540619439308; + uint256 constant IC20x = 6813471708188402912338247638719280180144768836532653959906749755180831733701; + uint256 constant IC20y = 10630452899956666539442022832713171293838832707279857274903723291215504725074; - uint256 constant IC21x = 5054771292297611149580407057004026930126834333985311096593522198136005344912; - uint256 constant IC21y = 9846301605360728746360669788291305483667978418447570933133518441453812077532; + uint256 constant IC21x = 4645195348559291511944588819754123347451366573885154192985637448206304620124; + uint256 constant IC21y = 16766206162461102255042753211815836900424951725074557637817692932957001273876; - uint256 constant IC22x = 6375011858346699471620766703454180460474959318906959854737520006721913377252; - uint256 constant IC22y = 3796913124771080981656421285118700913079563083089989934442241685039240456288; + uint256 constant IC22x = 612198738216091583770089992329981011003570889532673265272801632641592335601; + uint256 constant IC22y = 21009776677696441122580148742821355608472017491940177896149934304781750294343; - uint256 constant IC23x = 12664019414260530425201012729657179596363883228871830375986018330410576140745; - uint256 constant IC23y = 7724324759234305150098870450511243647469859115829862950119746163372770734859; + uint256 constant IC23x = 7845708505520385664103122252124442232529534143144281637399707935968372058244; + uint256 constant IC23y = 15192802321724721965923896418287287881746337425062951377408799115613924493192; - uint256 constant IC24x = 8414475932517376718246446511190686353933356473167597163507393977956520237760; - uint256 constant IC24y = 18567739092665780186541027431450016060501602309168108628165515395048109525145; + uint256 constant IC24x = 11044743356250821069784980936566426424857876182337346673003368733690232366513; + uint256 constant IC24y = 21968542138387545717894491159110633336985278011066255264274935509925404276; - uint256 constant IC25x = 3120359907362450985974214561527700848503852347080997608106866995365092938990; - uint256 constant IC25y = 15598034416975435647171366075254343399116960825160529831975796905883095316090; + uint256 constant IC25x = 15739104432512218764744514918039053175648927736786942938917098136624846456654; + uint256 constant IC25y = 11473837237244115867873717433248212843653746603581652183709166795371859623666; - uint256 constant IC26x = 7618398623080814369986094262260112943677198176279294076050134118180709564420; - uint256 constant IC26y = 6351701903764767447401679181425343449080736954061708171606650791995388240779; + uint256 constant IC26x = 12659745779361797715321216070590036668890759442977154045015864656515913110821; + uint256 constant IC26y = 15436857874387771595832460190912333282587447051076428904935035331068995068691; - uint256 constant IC27x = 7660149068846033504478826117178890832918932678832205596487410124265824854510; - uint256 constant IC27y = 2491826788761961957821876406677372156214488096819322910097327511124260678669; + uint256 constant IC27x = 9203173977602946543016875848991349465294047894411764290600412715281184637502; + uint256 constant IC27y = 8557329422378274647247494844347551526466632349826006833910662893194934281525; - uint256 constant IC28x = 20794838749313203903911030270946907016433597109553720174221656385211714777857; - uint256 constant IC28y = 17812498163364921099637863734271985783984365300073299650639268105274324002530; + uint256 constant IC28x = 21043592517032634711239990905884702982054744461304587368835062757863764173274; + uint256 constant IC28y = 1631750092321340715930642498551502008794205048320252109690579472702482883693; - uint256 constant IC29x = 4470726918138395764759380807649395990732471367466166253310755622776103465819; - uint256 constant IC29y = 17507663986159322748561449962825208817145248778005235057962503024107788565141; + uint256 constant IC29x = 1965593797962209845476914161340324215049454355711575611255794847486588198621; + uint256 constant IC29y = 20420112496369531484716420634051964705303428701409013107809743921895693778420; - uint256 constant IC30x = 2282738716454269120180527219287809294651441549016730273033210373774062724582; - uint256 constant IC30y = 9623151597448060795671840649081334455274395484568727058139159897873039048540; + uint256 constant IC30x = 14459258316049621520625093813598405781231837198148192657248564100568126911436; + uint256 constant IC30y = 4189670097301689361279714226734357198747625987495488973380038361744870962865; - uint256 constant IC31x = 17305720772558963560489472259732910387932131794541742579825391441778640282514; - uint256 constant IC31y = 17978483020480616572180687903365084753182987002773905082575771176385017798184; + uint256 constant IC31x = 13108879096940415310362336426378117914756114957855406964927612281735121697971; + uint256 constant IC31y = 13922315068161235910520981793423554652810239633897980696104312477364323289837; - uint256 constant IC32x = 7571937518121766238677733127868492321558436932028274617193759428484887548524; - uint256 constant IC32y = 13639634797327254842916621072030476726854653633267901223609159210218680193213; + uint256 constant IC32x = 3672774723765929810525726446377577070495042440381259398721824519467692223036; + uint256 constant IC32y = 5504189137877852784897136813364091880095479448638215793137890720712833089772; - uint256 constant IC33x = 20491321178426427862122967005183398251779924470644678424571372683050891038410; - uint256 constant IC33y = 11866037972312670211817727171740620564847008846992179291696597777640193650198; + uint256 constant IC33x = 17130781702453148735613043990802970337134477759322098512883706161057337504002; + uint256 constant IC33y = 16351907669841445135205102522017369314355429337431004692059562467792755202730; - uint256 constant IC34x = 7405036655032262031472090543721788457203124544189082692990295451049187204918; - uint256 constant IC34y = 17405807581678636956378393569562099137850325108621234185518676366335548019795; + uint256 constant IC34x = 12031667235281243664253700834599818547380367496538162959699982743848078891598; + uint256 constant IC34y = 6616306445409952843359602511870642177994574094251005373437394528227240955856; - uint256 constant IC35x = 12328260325084982532450273571086533395727110714550084687965119377605785323469; - uint256 constant IC35y = 8142505738758504286142612135433392554621238433204631934113088648731836869316; + uint256 constant IC35x = 10731123795727845951791321856155816019889142705311580809720843346374187513971; + uint256 constant IC35y = 16068650898493671048010070098850477199748100710010759421745286594693280298357; - uint256 constant IC36x = 21455489380416043414802439866337341338095098412697364482542368506991948195301; - uint256 constant IC36y = 177380340269897070531510667485546719600921933001020617304645726088643982991; + uint256 constant IC36x = 6502894893010883942423075381722837038696334248009036389776781991138833860268; + uint256 constant IC36y = 20790809673001992281463007604198705518066093384563083477497988619198326219881; - uint256 constant IC37x = 3450411197718861866556684118720127022485036312758274952373537023832934853655; - uint256 constant IC37y = 15542683513967475831837975619927185145121842635660806931638451693301339778065; + uint256 constant IC37x = 17893528808061411108476748553695245038781846398552576836224230715924125892190; + uint256 constant IC37y = 3396165818344392654074158537612720431771510878758650774669727330733546082337; + + uint256 constant IC38x = 10897508493118616620048369575610774538686816226070866208104945341887798715990; + uint256 constant IC38y = 3477357433659395048329281632040211062291869085580053535523965138254126524307; + + uint256 constant IC39x = 6232305602842554721699996063058147937412901964622386302125531286379410216341; + uint256 constant IC39y = 865167260793798759680935843664150177300892974890677439296402891134136533334; + + uint256 constant IC40x = 1896700859908460930091624595675776615402193748854462019745978620107291409907; + uint256 constant IC40y = 19538419883460717066552832903405877575081999780942435734967867221406789589399; + + uint256 constant IC41x = 919917946864295765320845049317324032542470918660595400102049568313393745259; + uint256 constant IC41y = 4905312417092777244239947166508788614667233335337264831713809305929873826211; + + uint256 constant IC42x = 11260058824584772528807061119314472338786531909501746400162839164183738065949; + uint256 constant IC42y = 9692558976165758378143630277186357355884473671639921608383879688904015447492; + + uint256 constant IC43x = 16500664765246509026092343746736878544449617806107262161088710179454171005068; + uint256 constant IC43y = 2318970865336931978806827275921781650216283891871191849842243055051647241566; + + uint256 constant IC44x = 15266083558060117092889105437693230282542989249077821947771936425702618705353; + uint256 constant IC44y = 5933912916741823626580572218992545666034550775510312837553273107032523100335; + + uint256 constant IC45x = 58707545314175203397280970210969715660178168988171479206762359173733595778; + uint256 constant IC45y = 18337733572288419475605999960151866998282044219653232437655934170784662568961; + + uint256 constant IC46x = 586233669714266072235077089672820057713553723712257638939984508768691446266; + uint256 constant IC46y = 5805420287012844261801028660062719860928333497295759197250699480287517497513; + + uint256 constant IC47x = 18533811404590119489507085680888268159057504006917018635283187815937097547211; + uint256 constant IC47y = 4105347632669743236449600156045402810957294409584662993772317423421882395967; + + uint256 constant IC48x = 7963255695223444100125880939097224728146759221469423275545846145917825941948; + uint256 constant IC48y = 13512044941955473329651037303898509853731877911390554418237190804988526456008; + + uint256 constant IC49x = 1246040208265149753842480934506849680611118792544861176402750181192234961189; + uint256 constant IC49y = 8563441033219483164633277222289522857294420978768986809528993427373045444984; + + uint256 constant IC50x = 2588594350644268564085849031861239502254810392738869347650201531798451495394; + uint256 constant IC50y = 15910783489501827060267126604385240212657463315742131285497095914663726625032; + + uint256 constant IC51x = 13536358811202144933899812454990919546110622582416000445508880943657060919439; + uint256 constant IC51y = 13636439389086566021867409527624225391658272934816689794906398506550354679701; + + uint256 constant IC52x = 3069052660704238265078596844313226533136449247403800942357593600286959491284; + uint256 constant IC52y = 2851907145042254355715210427589229005946148117819918992483522956786765330528; + + uint256 constant IC53x = 4532058296252955609362103735166225278277027937093609645966321436167953753849; + uint256 constant IC53y = 16885038322595100901701279116331564344696993077930991807708669198697751982536; + + uint256 constant IC54x = 21657088241609806957806596139919891483933646681016763066971961683666639010914; + uint256 constant IC54y = 5540503589899208339201031551963806514853512880214799648245011777415136792427; + + uint256 constant IC55x = 3180572821870628434033407206819005535080638863627732738600363337929557825472; + uint256 constant IC55y = 12213704425579070357451089645113850518215300513830671326650618723999697008004; // Memory data @@ -164,7 +218,7 @@ contract Groth16Verifier_AnonEncNullifierKycBatch { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[37] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[55] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -282,6 +336,42 @@ contract Groth16Verifier_AnonEncNullifierKycBatch { g1_mulAccC(_pVk, IC37x, IC37y, calldataload(add(pubSignals, 1152))) + g1_mulAccC(_pVk, IC38x, IC38y, calldataload(add(pubSignals, 1184))) + + g1_mulAccC(_pVk, IC39x, IC39y, calldataload(add(pubSignals, 1216))) + + g1_mulAccC(_pVk, IC40x, IC40y, calldataload(add(pubSignals, 1248))) + + g1_mulAccC(_pVk, IC41x, IC41y, calldataload(add(pubSignals, 1280))) + + g1_mulAccC(_pVk, IC42x, IC42y, calldataload(add(pubSignals, 1312))) + + g1_mulAccC(_pVk, IC43x, IC43y, calldataload(add(pubSignals, 1344))) + + g1_mulAccC(_pVk, IC44x, IC44y, calldataload(add(pubSignals, 1376))) + + g1_mulAccC(_pVk, IC45x, IC45y, calldataload(add(pubSignals, 1408))) + + g1_mulAccC(_pVk, IC46x, IC46y, calldataload(add(pubSignals, 1440))) + + g1_mulAccC(_pVk, IC47x, IC47y, calldataload(add(pubSignals, 1472))) + + g1_mulAccC(_pVk, IC48x, IC48y, calldataload(add(pubSignals, 1504))) + + g1_mulAccC(_pVk, IC49x, IC49y, calldataload(add(pubSignals, 1536))) + + g1_mulAccC(_pVk, IC50x, IC50y, calldataload(add(pubSignals, 1568))) + + g1_mulAccC(_pVk, IC51x, IC51y, calldataload(add(pubSignals, 1600))) + + g1_mulAccC(_pVk, IC52x, IC52y, calldataload(add(pubSignals, 1632))) + + g1_mulAccC(_pVk, IC53x, IC53y, calldataload(add(pubSignals, 1664))) + + g1_mulAccC(_pVk, IC54x, IC54y, calldataload(add(pubSignals, 1696))) + + g1_mulAccC(_pVk, IC55x, IC55y, calldataload(add(pubSignals, 1728))) + // -A mstore(_pPairing, calldataload(pA)) @@ -411,6 +501,42 @@ contract Groth16Verifier_AnonEncNullifierKycBatch { checkField(calldataload(add(_pubSignals, 1184))) + checkField(calldataload(add(_pubSignals, 1216))) + + checkField(calldataload(add(_pubSignals, 1248))) + + checkField(calldataload(add(_pubSignals, 1280))) + + checkField(calldataload(add(_pubSignals, 1312))) + + checkField(calldataload(add(_pubSignals, 1344))) + + checkField(calldataload(add(_pubSignals, 1376))) + + checkField(calldataload(add(_pubSignals, 1408))) + + checkField(calldataload(add(_pubSignals, 1440))) + + checkField(calldataload(add(_pubSignals, 1472))) + + checkField(calldataload(add(_pubSignals, 1504))) + + checkField(calldataload(add(_pubSignals, 1536))) + + checkField(calldataload(add(_pubSignals, 1568))) + + checkField(calldataload(add(_pubSignals, 1600))) + + checkField(calldataload(add(_pubSignals, 1632))) + + checkField(calldataload(add(_pubSignals, 1664))) + + checkField(calldataload(add(_pubSignals, 1696))) + + checkField(calldataload(add(_pubSignals, 1728))) + + checkField(calldataload(add(_pubSignals, 1760))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol index cab4aa5..674d560 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol @@ -43,98 +43,107 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 7150602979198858324531264522050588047187864437625863115811019715531635342988; - uint256 constant IC0y = 18679352390540645799385538354080686740567422609949222164932202910206044361948; + uint256 constant IC0x = 13357693122907037228152017576645355734121761212845151058677661103609163192132; + uint256 constant IC0y = 13330988885278369125767434338537639082919338469462771561109770926455996769780; - uint256 constant IC1x = 20223737820803182000349268235929514427158015173398419989210846794808922069321; - uint256 constant IC1y = 19667519192504952779059431068168374697689187072685801450130109271314785916816; + uint256 constant IC1x = 12508620784608380390196070593153977553849768584303191369350347694786774228903; + uint256 constant IC1y = 10497463660231940953738699560093225567814393547271993966494372800288076113838; - uint256 constant IC2x = 7218856416869576295091037655873055759382316689150166584580005310257749626402; - uint256 constant IC2y = 18250824158316410204270915259713657522920241651507178610002708235185510464683; + uint256 constant IC2x = 13358213132064408118763369803680465216756629096152358454643353054476790534; + uint256 constant IC2y = 9790361827332836718478767131585804431439300890195490311537005578986541483010; - uint256 constant IC3x = 10439404763847100272263651164703534229485312727099492374093433329301042860786; - uint256 constant IC3y = 11622072859931810063779349289989468302907213687444913890818865119671330403457; + uint256 constant IC3x = 11263096887435970836664030639381921541149000469179795739631740020273500583762; + uint256 constant IC3y = 18832878831913866337749700133052402021364972422929250752553120232017053832188; - uint256 constant IC4x = 3552958783616921573961765146209426612549096385286630602708070235513481501531; - uint256 constant IC4y = 7983004287008394591564704928605579735201397516705121349773346875253626793464; + uint256 constant IC4x = 8650173660622548339501740890775948467326563125469871933001838882801234078865; + uint256 constant IC4y = 10759885712046409911388806010481069590886057315469905475498658179072397221074; - uint256 constant IC5x = 7951915017279680503511105259632243418945970352099146353813397644881747832494; - uint256 constant IC5y = 15580187666685695375077645460858502959715552703766566567151236942633699459128; + uint256 constant IC5x = 3295412410302077166334358912280077543044124527280728553051328605050569416328; + uint256 constant IC5y = 17049453399693780313254529273986739520322108517619709180649214354472986470570; - uint256 constant IC6x = 3810270046381397249153853319380867614609141932721597496641486068943447688518; - uint256 constant IC6y = 1789454555200419624433391404653719772125697252632300424422488567482953480839; + uint256 constant IC6x = 12760717566528938207556281409639493742824102965038241868422088472886397881705; + uint256 constant IC6y = 5727694270117362054335093381846045971004329934011468049227701728188501414293; - uint256 constant IC7x = 16582813285159387606825357695015456733307275683978941475967473789385465564139; - uint256 constant IC7y = 3370584196021878105671518949045188232217596798052799318361611555383941238644; + uint256 constant IC7x = 12723277170340368996181883999061862932296128028814086233379699010714790157803; + uint256 constant IC7y = 15607664248618872066986748206455003464688091118493663837165373679303271618020; - uint256 constant IC8x = 6410335958983016577852137704582430672625504797739898593884922605316966411317; - uint256 constant IC8y = 3561862755304133383761205380693974589872824992821334084854993222686099463287; + uint256 constant IC8x = 16064173409510828580097158127999109660877176304290893887184870102987627587345; + uint256 constant IC8y = 7271726669102543421625318962122042361029332639092998786351706825402022983149; - uint256 constant IC9x = 141988548012661067741546583487301665549799271673511121018755490875713551541; - uint256 constant IC9y = 11381489344212088827476994843766826329038542391607626896308015896573859623397; + uint256 constant IC9x = 17868773711481907952191801046128922109639466718556606579429717630927232401150; + uint256 constant IC9y = 13426021423653145781149475638806424172443891179898547974414561873835013472273; - uint256 constant IC10x = 2400404699093079437844767864727773463595132175554480756228013854499052897743; - uint256 constant IC10y = 16641639829319720713179419428727890115364728294133162095260244114066308681409; + uint256 constant IC10x = 17231713394258993279280128626680971151901806250026905329830445951311024978649; + uint256 constant IC10y = 16362220893399236364987780855448702890941734166928744916454228037419247631859; - uint256 constant IC11x = 18819343891508230813261093280482339631274788730864531524665810946260398413656; - uint256 constant IC11y = 939232547935730618247481870142928145681722172369345232371161962470473621455; + uint256 constant IC11x = 16393437699418494278442854388319612745568802642878330160854040391387533400112; + uint256 constant IC11y = 13190069452272446793436396301020962811004079465757898954271497706698165528700; - uint256 constant IC12x = 19857900065761502826857489987079136225805396737807491159881256000358449239287; - uint256 constant IC12y = 14866158318731160894408347837912771366289709323081067853939131732571761322111; + uint256 constant IC12x = 7378753764477002577496984973794709537014547695465562205837932080193227331968; + uint256 constant IC12y = 14590455657777965484775453020094930760042823323462890204601760753586004282684; - uint256 constant IC13x = 654111863936885718257781142757347689010710641411633200860925542163991689666; - uint256 constant IC13y = 11276189838628957949004554103071438492770960919007402030163410690856320771850; + uint256 constant IC13x = 7997905266075296348375184091609158476322609729212752317911559367095944799223; + uint256 constant IC13y = 5745139122382514585485874184483029362402802135720894805094527346018931663747; - uint256 constant IC14x = 18969339244741250740753343010366495968956160496467373979506746525890248084164; - uint256 constant IC14y = 16274901896353030323013083904924198681645770552447391614076698136484842443636; + uint256 constant IC14x = 20169661212830681667121989012648338854355631560185391751223605196103160164011; + uint256 constant IC14y = 539780066201272709523495794614709990166877660139080643626983915026896119607; - uint256 constant IC15x = 5364945303376219658991823159374369520315533888650937587824150006805793367435; - uint256 constant IC15y = 15362324963834315062007218005904228090931585348452894617514266495515429954814; + uint256 constant IC15x = 8444655896238788895878628117268993903133580378477751962708257842437863740785; + uint256 constant IC15y = 14733855077207271591160962228017111069029157259271107029728347242748253125366; - uint256 constant IC16x = 7706652216614464307929318948621370806407028558413501412600554293234571043615; - uint256 constant IC16y = 4833155926438490231386220605163689437125897398884350656367983521056280632956; + uint256 constant IC16x = 6776365740560628275599288528214364007667844204832291628305205207440991363958; + uint256 constant IC16y = 10701762678011603715205160753666433247040031283169837460596997733566638035138; - uint256 constant IC17x = 1149166998309009330377390731594951819957167640308447230581596039029228635856; - uint256 constant IC17y = 17144496829204247748601976511350134750390256256716017203573337962163783928337; + uint256 constant IC17x = 20686935058199339354516949529825885235552968174904347091970372091458356050418; + uint256 constant IC17y = 2353883119734839433183501301793327525159037748688825810403810896910943236417; - uint256 constant IC18x = 9682269424428793097631391573982450090008352352784483866555904822950699832063; - uint256 constant IC18y = 7320838209204172545348024044818590112291242261458837363572039110259358463391; + uint256 constant IC18x = 10350893931145787572953344205303374116068374532338249687895170827700639749336; + uint256 constant IC18y = 14640813458603050243659774385299057516762787203076107453683687533882345081521; - uint256 constant IC19x = 1605487566693008705655072065911584353872368504749215742640417657776546622076; - uint256 constant IC19y = 2308043445104009725610511269022057743503782008796761536470885918528911939324; + uint256 constant IC19x = 19262254897475671623941666812023122929903981731944691423683488712448697081937; + uint256 constant IC19y = 18281492578904896322558724606234848271289139471406835707367843671116366444087; - uint256 constant IC20x = 2240609051444145211347356467283693175838292400028588894056540660459977622330; - uint256 constant IC20y = 1655940193015866774646205663901575824326740364428355076410141345515995005827; + uint256 constant IC20x = 124678580367106714324365512313981313186367450591290500393061028606175892723; + uint256 constant IC20y = 19622459168604563104848042405466516563770600657501108965523163775411098672757; - uint256 constant IC21x = 4853016079991973626530212093282440895734792373602971804488540915961627345640; - uint256 constant IC21y = 7414374958276543278011110955360778512607526840415566794056500103235098338046; + uint256 constant IC21x = 7958205631716894096124215035454651749998590123970961934398635953991688058318; + uint256 constant IC21y = 16567031668980761134299018248953094686118944235178042185849152200978184065876; - uint256 constant IC22x = 17185659180162348416125174675491441752772941877249583219738075242236758265273; - uint256 constant IC22y = 9370043102883086031548478743900979288817657004984653739334919382623844393263; + uint256 constant IC22x = 7147067657100593571638515910794468040722620253353965676612345848072450126796; + uint256 constant IC22y = 8323724847034448554879418517026785309068712740584276122197233489445879426431; - uint256 constant IC23x = 1586456447948676480094847981316788894535992294417175375639442973569813126062; - uint256 constant IC23y = 2424151834815363943272735355039654154632114257560884077218826838523761765895; + uint256 constant IC23x = 4475661955736946565036382810587106183520552266697138427686452731078117767736; + uint256 constant IC23y = 748082566430464216825026197955511509465126173616326433623980484101730257065; - uint256 constant IC24x = 16231165842198799919638181935933189812441001519682385504931669473701873751266; - uint256 constant IC24y = 17612049085973824664723374650586152547680864307435248820913416068867135991070; + uint256 constant IC24x = 18871094629535557959761172513178206026645275580390985276286511649250238153689; + uint256 constant IC24y = 3733404107218228733942648054164246626605647007073122795923180610554195384488; - uint256 constant IC25x = 7483158710251990522291145254248684609165926444128647658988098156057140409708; - uint256 constant IC25y = 1673962192351811413168005836076136338181422549980142181965437293503003409802; + uint256 constant IC25x = 2384341917215847801652641900530474605831147046585978262725620402385796765901; + uint256 constant IC25y = 1287779897102903993979483791221014755426631277038764827254149422137772335222; - uint256 constant IC26x = 2039664876281990730333439428242031929108223709931553554336538537301070725071; - uint256 constant IC26y = 14005074492108126348400685560436665000589249218363273187052286031208242682152; + uint256 constant IC26x = 15719716565017700920545871521869872133915063489073625817617400592054712067072; + uint256 constant IC26y = 17002113594755025448330507151173960578194214614717460071129326081566116414394; - uint256 constant IC27x = 5496301741656297227126500517214062125367112090119824717058375335361580584725; - uint256 constant IC27y = 13909185239757464535884774658879364364060378133383923006683376996195592981431; + uint256 constant IC27x = 6069617218858857906572692060956455933260615226814802013802199283144993419830; + uint256 constant IC27y = 14473506832002574954490482003760587485980065730322794298209159874969554193911; - uint256 constant IC28x = 3408743782650195676340178066737516111388313667630761738794006191813037817996; - uint256 constant IC28y = 5303551963048672301523729843825814073653383823758311162424233522116078262138; + uint256 constant IC28x = 2095872993541208595971848766255089085389698239862455369992367968040560542101; + uint256 constant IC28y = 4401957738071377442795776346853489896120525690607490420740185454723130517217; - uint256 constant IC29x = 4211252801454076822373001217403810729274630805294678301066236345126168784094; - uint256 constant IC29y = 8461944933834378462797492913096013822156422817717577384142109454005070578383; + uint256 constant IC29x = 7948782644008604365957640378662878722460387841213619643734690098279143596558; + uint256 constant IC29y = 14151027007218971202754362938797936052279026613643428871705306564386243582804; - uint256 constant IC30x = 415070733097326475913681601424674794998572314824594858080542203826311964945; - uint256 constant IC30y = 3336540749266077408699467353801385535951064172340925708089438425128638379875; + uint256 constant IC30x = 16055935718830733652525145369258352251162204565999270815122069851184919247791; + uint256 constant IC30y = 19977921078618552717906884259146829610529552736713600023585181237533888275450; + + uint256 constant IC31x = 1724644122707053931125669268159636051378467183669651442417045949735792435846; + uint256 constant IC31y = 3780427308194609121900455938646860005350278871116671233301051665551523150347; + + uint256 constant IC32x = 8043820203766420431969217152893413732635117572573736920587519044322309584347; + uint256 constant IC32y = 7641739641928705768386491515124236050049577395892226047572150942224894388223; + + uint256 constant IC33x = 1212239584949006580410344651147309255656379781955714183101293673886799379224; + uint256 constant IC33y = 7277339251039550149206299004468645563322367249804601268562416695922597671900; // Memory data @@ -143,7 +152,7 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[30] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[33] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -247,6 +256,12 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { g1_mulAccC(_pVk, IC30x, IC30y, calldataload(add(pubSignals, 928))) + g1_mulAccC(_pVk, IC31x, IC31y, calldataload(add(pubSignals, 960))) + + g1_mulAccC(_pVk, IC32x, IC32y, calldataload(add(pubSignals, 992))) + + g1_mulAccC(_pVk, IC33x, IC33y, calldataload(add(pubSignals, 1024))) + // -A mstore(_pPairing, calldataload(pA)) @@ -362,6 +377,12 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { checkField(calldataload(add(_pubSignals, 960))) + checkField(calldataload(add(_pubSignals, 992))) + + checkField(calldataload(add(_pubSignals, 1024))) + + checkField(calldataload(add(_pubSignals, 1056))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol index 97c429e..9869d7f 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol @@ -43,314 +43,368 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 4462440718767044134998162351966451562518066257960346710377069184713247719285; - uint256 constant IC0y = 4569752707050948599946597207280276287539329707858295488707483945649429752219; + uint256 constant IC0x = 7500535726679560657579283439937225600834190844886138210173985030451455825127; + uint256 constant IC0y = 19211173094810308874479540771713108816406079403971313989572690055722645083877; - uint256 constant IC1x = 15444985678636809312978594800523174081806733286376064553166174284965990139183; - uint256 constant IC1y = 15433744612719169811415194739223495951802871404441319181779987345899861341844; + uint256 constant IC1x = 16806344774942779306505877135056695979972584080776325374989648490702215091788; + uint256 constant IC1y = 13717852534241260147752477679415199499740910779435645828418374467800679660858; - uint256 constant IC2x = 9885990037414753377583491462853432028093686282965905887310871111746174146380; - uint256 constant IC2y = 20559621090064053286923137529065108649443916661380064235986881033473985498037; + uint256 constant IC2x = 1916139503704745689898523960297546340282030595985891097786214399443735136917; + uint256 constant IC2y = 12122404471421459930376373421371017459283777741639107186061873866664653486447; - uint256 constant IC3x = 15220266112866916329409503976568109087433925172545814071973149694002321739963; - uint256 constant IC3y = 9967028147547737060550357745757741357384433858664020146728346926570784983213; + uint256 constant IC3x = 8945226882505170846621830642118253540275806857825852371695491097772334231796; + uint256 constant IC3y = 1389636172342704194880391438762811545108381346908901092092717318384913908832; - uint256 constant IC4x = 21329947211706016683568942206967750269087916034352353170682885227754293170481; - uint256 constant IC4y = 18598611223760756746575538031357011297686509434289269381366033907229098220076; + uint256 constant IC4x = 4720000354007292185275041515476297017713751894951649840732039222933062765116; + uint256 constant IC4y = 8309818417196457976518803977124233410768792858397588812533806049028635450946; - uint256 constant IC5x = 6514122334235498249799999850630828523118746412876175037603777859661056194113; - uint256 constant IC5y = 7613641592052195772596513870294777261887749836185436293599101594590688831764; + uint256 constant IC5x = 7199104912090362163502951295934008886949479686422100263952248206164211485353; + uint256 constant IC5y = 16164449005147376477866173780305393298236981184699709322090554181593827679350; - uint256 constant IC6x = 6746606194181022767983976806013080529050278399390805600511506371718262635580; - uint256 constant IC6y = 5040900530838847143133329941371911710669409792156418239777488229389953818400; + uint256 constant IC6x = 2843912041877824320322393310006824854677121908412718870409497250717312679641; + uint256 constant IC6y = 7827715582861223894170300961094503992574657276861623990874852638266967896640; - uint256 constant IC7x = 16310252749266624170922178444895128571401957143728059112218900449972972021945; - uint256 constant IC7y = 19849405078170349616501907658417816640086069293900944359599337260725978612567; + uint256 constant IC7x = 9788197829849217864440989665539682204160479875809542892572343833501260255875; + uint256 constant IC7y = 5247569753791213588728317604116866569605781288314643612798847987978242262702; - uint256 constant IC8x = 12943035592697513054598143597066138028290758819564583428418427834613361895771; - uint256 constant IC8y = 17603815873244763036387162451789002048178806753191740409503763948085037340112; + uint256 constant IC8x = 19403614296896826743998907389148525012932729658278058752132347125377187794508; + uint256 constant IC8y = 51408059167637885618869915277185071933411987649931254551240199217265772473; - uint256 constant IC9x = 12904271190452756689460709035613620779998753026875639942268876213610218682758; - uint256 constant IC9y = 3412240378584514469154301902106616900474125795462889373052017372977004157425; + uint256 constant IC9x = 17898957347147717726551222139844907465409820999669398183757701831297622051364; + uint256 constant IC9y = 14606804311053587079091541104980170172419043649146045021354605179060328431614; - uint256 constant IC10x = 6331691481693568933183361080303344249163638849089168559069564832681362334724; - uint256 constant IC10y = 8408438512114059108704924659251298284430944217379780473759408521889262932134; + uint256 constant IC10x = 6238065553035971825111581642573915748187460674313041016860739176610996811287; + uint256 constant IC10y = 10751590147133361319427145411917033750868230773510804521928398020016242616278; - uint256 constant IC11x = 8041263062859819383030208297472141365592753021388417731220753939751969377673; - uint256 constant IC11y = 15906453673686024215193939771448924145012672899421766118859189664796191133751; + uint256 constant IC11x = 7342056090265083301770626449376875008245858021255267714744154729838971358548; + uint256 constant IC11y = 12063771229441878674400687905529977776458335378826498652935943121954810198909; - uint256 constant IC12x = 7215339494632317536574335410420512887140888961605922801690610674703936791690; - uint256 constant IC12y = 5270686168977103760944011889775790356727316296740640282588783046492617013757; + uint256 constant IC12x = 373524596084282635359130976258058593421536400057319175377893806123360396467; + uint256 constant IC12y = 14760670258604012914698381006051382694275220938579164835591747586399218816080; - uint256 constant IC13x = 3217265341412273322595135399781332967556551397197686878201114947206899054156; - uint256 constant IC13y = 7503102616401391535922628018582147279050323109558452732992780862830810951818; + uint256 constant IC13x = 4418236526774264570412986270922284322939568112401699654999793989825816069711; + uint256 constant IC13y = 12557078685359827252756688576225765305779748144404144960222828895872897383337; - uint256 constant IC14x = 21246857811876870925486466013559756448469407207868226507156573943584195736416; - uint256 constant IC14y = 2733600684692003494872043879919178019288831300666309740857197105148878418766; + uint256 constant IC14x = 21257485642209101440541262855049475786452634834647714540092892434266299426011; + uint256 constant IC14y = 18971897146012196950386564090753801629516833979407747406905450423529988474842; - uint256 constant IC15x = 20600577122988085366331314426352471330562718199855297539550267926322810640841; - uint256 constant IC15y = 16231929330271171876691408231412975041329685804795284908069818974298184549413; + uint256 constant IC15x = 16611243890640899140956062160503428811483680171417457952982245891497508999752; + uint256 constant IC15y = 2098357619974235417711388971755203696100694838741344705093631948513498230315; - uint256 constant IC16x = 3013516493834933880571265579483555886116657612754656330314477838378338957763; - uint256 constant IC16y = 4496376340543514378135122386308791454382914017654185722966748034632858780883; + uint256 constant IC16x = 4355590700036993009639420381936958601889921765819122718853640409809972719842; + uint256 constant IC16y = 15175463602073829667515214966415027094817288251345304171265812183665287504979; - uint256 constant IC17x = 14566715754086819820722811868524340109011579761633272047360433652167657911302; - uint256 constant IC17y = 5888712996271153651928451024341855957619655490208576862345200510559556697910; + uint256 constant IC17x = 3620493422748381691853120643516512372163420481937656511998695848026260320105; + uint256 constant IC17y = 1560848439972110289214389319917906019630412185841375012598626009666197413134; - uint256 constant IC18x = 4481146920828229318871654483669942380846673321468443130293564421234695733769; - uint256 constant IC18y = 20271157044718789134443586019092533529315594280339405708777284721610164653084; + uint256 constant IC18x = 4700274148367693232336831513076811485967114825117923276671705061219333681346; + uint256 constant IC18y = 8511274934316204889113881570640881830545481646152519241985180723413237682003; - uint256 constant IC19x = 12058758612490882679974363077579305208323053447875272297097120038018135913052; - uint256 constant IC19y = 15251484383604866864466202236981169528921776054941270557067166534203735798927; + uint256 constant IC19x = 10806720960072981669311367059548117404871246921816956597065725827341750476273; + uint256 constant IC19y = 21158531563976094327960067597282163184193348063369449379905304051936258801577; - uint256 constant IC20x = 14361789899910818132818801031990221222431521926232911846069754141800047412360; - uint256 constant IC20y = 3150377779097660373125294170878683323827601265329891132712370470232745767578; + uint256 constant IC20x = 13369217552722105292268334414614980598650220141525004260563926888539904272102; + uint256 constant IC20y = 10402746290939719898151331031171924883633465262768729580014215146825225005360; - uint256 constant IC21x = 19363025835995411733853977290476358325305107158384513584747918019127024228124; - uint256 constant IC21y = 18971551945271501522521473636649169684106226800265391745493927350489770667653; + uint256 constant IC21x = 2148697341810656611090754811248609047453259665955486969057737541337289271335; + uint256 constant IC21y = 21029346951026375384890347577694834697467345509708861998995709086074732476094; - uint256 constant IC22x = 19094123125018762499054135540373802123371844243522347851507632970534404969456; - uint256 constant IC22y = 16670188470952100839466765185789885210730956023356075788636114796410130484092; + uint256 constant IC22x = 1873710762427086841161676812964047827943676959997358463124181840860294888033; + uint256 constant IC22y = 14063422199669868332009175714038225820046889682804461668628059329477108292348; - uint256 constant IC23x = 18122032629347733938830121928377898437942771900957000944580840182850254686544; - uint256 constant IC23y = 5216591827501717404562544133936814946372134527719938477347011881553820377662; + uint256 constant IC23x = 4174585191479732244748267274242451644545245726408387398850177431048796399643; + uint256 constant IC23y = 14857834540533954748154708389725638016379871028032553609866901793768103884602; - uint256 constant IC24x = 20338962917949833865771215887219893815884228544407317459733265502406290301230; - uint256 constant IC24y = 18217754241610423349007139096743310765887097807831672993502649666085097852143; + uint256 constant IC24x = 6796031609956705157224738682377302362835652495661082431443390587382147903750; + uint256 constant IC24y = 14336948976066433616542400938618506901234134279659317590768587486919402107031; - uint256 constant IC25x = 20415938860422927750334419431682847419560950986736944577610364321907854090207; - uint256 constant IC25y = 1811706832137740078783015389752767524932208339888912260166095247754144082605; + uint256 constant IC25x = 7569242654658133936340747585660944931268333908847730848759100510663123267137; + uint256 constant IC25y = 12043917912298666797114070456260207561319168319534634208021831159643321726059; - uint256 constant IC26x = 4009615321508047815711260104064529330703213737451287105919871546750408469276; - uint256 constant IC26y = 18353785168680766219428431427679557273060790378919012461419940007988830704229; + uint256 constant IC26x = 13619060361062972609581242432309237149941978819573786182006070973866484468920; + uint256 constant IC26y = 1778130477177295522446099216627259081346814994736312261439848974747521227458; - uint256 constant IC27x = 9111725773120243221625374051231594321895925829959250777918988474111428552809; - uint256 constant IC27y = 8767914060970317701665738928409076785543974302457898585340147516686911169299; + uint256 constant IC27x = 14582113689584039845068369999361449891331987536406378300547852053673581029; + uint256 constant IC27y = 16832763731582757514382997029476363999693114653383529374694410294769460052383; - uint256 constant IC28x = 9843768039128456379484000470399826391786235218161014147193172378749485822345; - uint256 constant IC28y = 5942986358657480708744873333864211643806585484697708152331924831769550465700; + uint256 constant IC28x = 20377066698453791023458287151938239594019822715825684621307962449389756844134; + uint256 constant IC28y = 16465755203020873308129491161826944266505991660198930428873015090822479174784; - uint256 constant IC29x = 21775778568767886964628862364878941499703483357546030912029290600060115760142; - uint256 constant IC29y = 14929316967024371538821998281577672404071550473413718889357628563929361046156; + uint256 constant IC29x = 10649285923762964369917057077121812021322905224482857478876413238735450814741; + uint256 constant IC29y = 21838478583818641080552513759450480672872225316500909643197879891174334244480; - uint256 constant IC30x = 13927585571628534987997056150531190480940393397582513342264249485661286014978; - uint256 constant IC30y = 18232879627291556798959023849791585712917959449605097433654417997703384643144; + uint256 constant IC30x = 1109087950222036174110964951435020267015623808240978786202742146115607301252; + uint256 constant IC30y = 3956368720643646860873662735333036398111077399675206246003858808777289636523; - uint256 constant IC31x = 18717068744029556727791880077138509136276808456366864775434322758401574592031; - uint256 constant IC31y = 14289080330654706444332688360679772953527061236492671656041020814456080933241; + uint256 constant IC31x = 8576714559669613458031244045461780388504756597868108986456998548724842622108; + uint256 constant IC31y = 7554628788621180844451495770327316094075077073031327580352589337679635770615; - uint256 constant IC32x = 16538883082347184299127040695141316363634496860825578138296375998653495560797; - uint256 constant IC32y = 838870550326759636834239199515684239156603027830904458425034813850430718985; + uint256 constant IC32x = 14656288601547980865604379551755939987955283217202788809494960550239721723961; + uint256 constant IC32y = 766824508218622323270303545794833087659956781279339003477101911534417865401; - uint256 constant IC33x = 19009604105059969680889512086998975232417248905100216470638342724167877756963; - uint256 constant IC33y = 6887762894722810554303309191435986523098450884585415905948255411223686038312; + uint256 constant IC33x = 3459904603095154924525955846501957568183885356393506680886387462734961216955; + uint256 constant IC33y = 17873456474529882090525128657932218280379783373738156426415490148507484791067; - uint256 constant IC34x = 16531683071318864874894878077899797406696996911006270311201733386895839734603; - uint256 constant IC34y = 8666717519577217798093188521875192145777039694421065876796414865172120401375; + uint256 constant IC34x = 9035012563148792506674112927575972384967719337164495552803038431090164998740; + uint256 constant IC34y = 4037586603668609002888775095476102814791360218227745807288646292504171369100; - uint256 constant IC35x = 6177777554055783807993222014736847207883074977905725744563635107454847595529; - uint256 constant IC35y = 4263138318324315888046557447563161181503642778249092020567460303413399452760; + uint256 constant IC35x = 2534742475005281868379587149694067952094999056981068032551302208506146526423; + uint256 constant IC35y = 12198448301468055355461438008846593911353601311542048279255721945565940970207; - uint256 constant IC36x = 4205536387120632613819296547301273289162157974895928179450315436333715150332; - uint256 constant IC36y = 20312416997511154415477343858536574450102877883177957262921784717954324572426; + uint256 constant IC36x = 11466999399869027581046875767681368679523765162159961829970347155160983383231; + uint256 constant IC36y = 14728120015413070781150170877833390889423822037559991016631039438101774487919; - uint256 constant IC37x = 12942617918080900315903228453269136398127168902964184649535351245368329432965; - uint256 constant IC37y = 19157458222473093380136466829908207278488549984635155725898745872282753655398; + uint256 constant IC37x = 14835759801275157675907480432161847097460725054043111187563905311162324019430; + uint256 constant IC37y = 8988388090647974630407822941647019946719747267832272782429673153376589466814; - uint256 constant IC38x = 12797139682577877058905772870479578076694731322444268435625480538739066576084; - uint256 constant IC38y = 20727104588637013174769304334623997926735939407551079492066161364902539626657; + uint256 constant IC38x = 19421739123622636037107042245134453960742228305647845554383597537661588927895; + uint256 constant IC38y = 15467472060760822188681708808044964192537771977244749537433758734276827106628; - uint256 constant IC39x = 16193627270614812573290129156347962719805742569353052701817456772794934381276; - uint256 constant IC39y = 10942250866161132274428730958320192333701173304290140196956890358201765926569; + uint256 constant IC39x = 19935977093502482182548979789195578560052815028405674303797001570548802038596; + uint256 constant IC39y = 6697860062510891376067995893110174455273885199850742505480547347302022477498; - uint256 constant IC40x = 12971960018139257046178803998989010317968596739040721055352793253859131510352; - uint256 constant IC40y = 19283254125631514544373761191562602608074231373915387788984894295259121506408; + uint256 constant IC40x = 15051865976796661053263397603506515712114247323956425399832997166097654770443; + uint256 constant IC40y = 4374537910217073650207037753738132179051546680623524376507665074715923417591; - uint256 constant IC41x = 4973223975910783897813848245279259988338994201214380734138076226251147962275; - uint256 constant IC41y = 20308006563490699737057375027526499910953601577265600622293092320172949802335; + uint256 constant IC41x = 19519284504040054446464895665875936024808141082948559256582980298586121967707; + uint256 constant IC41y = 15524576017614709763277884123834010483645911571052474791111550307182002039636; - uint256 constant IC42x = 17030317867513821418791571886460926935054674465473331652069943110476185476933; - uint256 constant IC42y = 20572233136020505493971200425387951894248945385198937170069383285929957457043; + uint256 constant IC42x = 14169047558741639063601425825528076715949947143481266982651402145760147350689; + uint256 constant IC42y = 11558742126368384663450582571191769475879481207234747961491402187585809030470; - uint256 constant IC43x = 7692553451176703422505793001654611374627553094893150073088893053319586919972; - uint256 constant IC43y = 12753082405115929758469368345500564751358540682206343637633766733129482166950; + uint256 constant IC43x = 5332465408258819374942719388093284211386692103588469945571877659452411471386; + uint256 constant IC43y = 11791448676918952308531355096392441407206027582305795467804432822986119027841; - uint256 constant IC44x = 12870749622804530478159602007951060728771320326463469142136290512480053201004; - uint256 constant IC44y = 14895591827941652855814380755451320737860546253193499816608439236526809467098; + uint256 constant IC44x = 13654245885227724388345981493092939387342814421366386083474600115721432266110; + uint256 constant IC44y = 5926153516600145974422289517971898358230338127793469527296139364876247557809; - uint256 constant IC45x = 89196947066260254533869499130107799131613847960990725360446302663710649562; - uint256 constant IC45y = 407076608675591844134527309673272501547629118028165689413285461476628842228; + uint256 constant IC45x = 13122586510068074078517089731879725456926231046988356228510234941204925995123; + uint256 constant IC45y = 12265238617608818055780513496240282847481054743119517968342725204221544781395; - uint256 constant IC46x = 14763410266333218926868118079821358534475399613923338328605601243110555424754; - uint256 constant IC46y = 17599204885038240804241721503294011005635060311218576426371347302446614183376; + uint256 constant IC46x = 8274528848355054591127494508072722718775015760071421827286001206942790699627; + uint256 constant IC46y = 11760918715293784379775030235331164880488442709518502275057572199465619802512; - uint256 constant IC47x = 10118726747047738678104431085895810720035635051697291562288025077298088214733; - uint256 constant IC47y = 19322776357993901409655478160822770136901958925596664461964210451717594181232; + uint256 constant IC47x = 11014810329931619965158398213406539755713461092731556060274626281453164309453; + uint256 constant IC47y = 11189323295385306543102382083746863577222972902104073927551637506494263735304; - uint256 constant IC48x = 17433596912197488142536558811210087828544024952005985935923537263724296695715; - uint256 constant IC48y = 10563946409897498644381864090366712696299250976464889740911072749915084138898; + uint256 constant IC48x = 12712508501357267278007738155943294295381520642767904828279001501481377210137; + uint256 constant IC48y = 17390657672085029832700943318373589605086952772090592854174422868227906933189; - uint256 constant IC49x = 13437595226325828138834863780845764635828817268034607359176754616642326181698; - uint256 constant IC49y = 8377501808190853158752612250000097188008118650864377354654651658326636024296; + uint256 constant IC49x = 8158155995935964817361153687378978065370076724750970984753519237713084097159; + uint256 constant IC49y = 19266736062723091675062119238987388544788241591582139615448136563045829614240; - uint256 constant IC50x = 18380606598711703423374534752675429629825934246200986774111473072918584427127; - uint256 constant IC50y = 14232575728529611668428027475223047875946997946012917158798714777202094329503; + uint256 constant IC50x = 15410549079733825403614355166850298862378845312773047869183699867090402758863; + uint256 constant IC50y = 9877816272544274288412437194652539541179097142155557486048641274060651656591; - uint256 constant IC51x = 722367671757803999310885906594262002822084370153325403880129053184420701885; - uint256 constant IC51y = 16991411294824433258874180108296453730430695993836125555989956901768262080509; + uint256 constant IC51x = 6629359193266028942713148037067952584305855665204022883127978023750323831268; + uint256 constant IC51y = 3743333996498987146147511851654428972618998595385126367990230310572340500629; - uint256 constant IC52x = 13496020518115514933800937650955414355602397955693565400373440221057424537585; - uint256 constant IC52y = 21065909895058099897589334673787294003396134826786731888651936425421401478719; + uint256 constant IC52x = 2446799394890562122022807485261900456170147937657250725501128587449798855710; + uint256 constant IC52y = 10831859484895982751194550869698635827390557779676319197690946463294137328618; - uint256 constant IC53x = 19623439250443309619091947329218651409469889127936492083551551030014415896214; - uint256 constant IC53y = 2625205233558748178418480276522280268356341127041102822640388160424014599246; + uint256 constant IC53x = 2953017421033136924678624468094000234644427178548329162920389392863998759085; + uint256 constant IC53y = 12151966610918690555352831153083558428557423274041184410708279948918928705346; - uint256 constant IC54x = 18346431934989235235833835905032456484485923699641645879365705207333658419610; - uint256 constant IC54y = 517136907682197625978064556574394476141925443618454737065827648376316242433; + uint256 constant IC54x = 8087846746377924976756683832428720847449604039113382881446326776286671798092; + uint256 constant IC54y = 7288341319881659843454388651325310716760815463129377255327335842805776878538; - uint256 constant IC55x = 3138979905429106492828819779751961380852688942103014057270129945377102144728; - uint256 constant IC55y = 4903465287653415944608220202728816459875049299077299191348062489631432289882; + uint256 constant IC55x = 13495987578579953277693326877949946772289507309011987627192310070351649046086; + uint256 constant IC55y = 7257346467449388144285371430101261259094193268967793660847530786322202968488; - uint256 constant IC56x = 3818666132496281252885342231969340100538892736272659098800199156423224696365; - uint256 constant IC56y = 16725255918872290527175982515440134508971630677817020227810816026732210759797; + uint256 constant IC56x = 17882197460124432060375387452223327434223221532213854429635214900516730297105; + uint256 constant IC56y = 6486140274455554609854267434998295186554345558025259611641091796618857591723; - uint256 constant IC57x = 15849945242555071680578608251305533796240075167241767933635389762711709136304; - uint256 constant IC57y = 19623688497762019513766109452410765776236408137598055032664841343031733872901; + uint256 constant IC57x = 18060644639329423390591461587690627453025007935899201493524474530222059353030; + uint256 constant IC57y = 13331379512282481166141130709457502487055532990062095012747890797220941533968; - uint256 constant IC58x = 15716627876476566418700698390911198187392470943729864252876805318847758555152; - uint256 constant IC58y = 21542720348956544826709230687050296321659755973899277940138213870535244729164; + uint256 constant IC58x = 7914303066558602668246205079409149593886974851237356057887630180998379164277; + uint256 constant IC58y = 11742715327474005618857155356669397308978829791791801695448436577436933235563; - uint256 constant IC59x = 21693658306551142818774093970554285626530270967824079536598117886288628593146; - uint256 constant IC59y = 924528975935198499881293343023992285582826421462419983235368422315682295343; + uint256 constant IC59x = 1737662495855912582360511320492416702002273998205249649984716218202390020969; + uint256 constant IC59y = 13418655392892450015136808325300261057784239425009576317224157000889828830049; - uint256 constant IC60x = 2378988107331033347460850151679461477793580217621829504536004163397015104074; - uint256 constant IC60y = 12839955041049287886502233201322183004427713008073313732274669695946418614228; + uint256 constant IC60x = 4834422649135352874647627764686462565699225845013283365686026069560501198404; + uint256 constant IC60y = 4757667430779664999587739264920467575683653864526511048906660419706636070768; - uint256 constant IC61x = 21832468341560924658936327710153414558584780085683422694779457426165847177089; - uint256 constant IC61y = 117312274264272090414958277926262025708715360017579806546714831556964057144; + uint256 constant IC61x = 2920992638216104155183967668094147376293386967008321931600826085803708308220; + uint256 constant IC61y = 8159758823941053250084307519757092527074157608929172237335408640809991962406; - uint256 constant IC62x = 3018238629968161579494804425259779540781422065436598113149379387035094736680; - uint256 constant IC62y = 8568458668401807393362413596709511290191073330862014248063413032803554773399; + uint256 constant IC62x = 20380022125089941982267545484277155711076109862266912429930748936390059655152; + uint256 constant IC62y = 470391815478528058241672409830369680813994569512149884965930095110810108984; - uint256 constant IC63x = 1282793573958458968971927933094471206080893678228175350336079122446958404776; - uint256 constant IC63y = 12498603528174334143768096584632542894223916853926331868937535155229078638823; + uint256 constant IC63x = 9425423724664098580536380897211772535118081412568624282696997277553286852839; + uint256 constant IC63y = 18102359130326432892074145491902162032784316084473839231833731864967644198318; - uint256 constant IC64x = 9617959971065461584955469690391462382117093995070687589510083232925219095129; - uint256 constant IC64y = 11018863524303246149442260755881908287922941691112564596126416087093604345628; + uint256 constant IC64x = 19500196743361397753441818011714661509028744136815029186609130185239906324695; + uint256 constant IC64y = 9166656329872966963508555901927598186094898417497111469308350422460271423546; - uint256 constant IC65x = 18494675724266065932303746924977017396929113474307371806359401523788727941102; - uint256 constant IC65y = 16097535133295928634162162517780143088230159419521341109791303759244723908021; + uint256 constant IC65x = 20508058021512460837118488786527087294694585061411301455950394061961904702904; + uint256 constant IC65y = 2578223733619336602943413450000425637548745859092326016651608266335574960494; - uint256 constant IC66x = 3415083099541466355922472786777524696440486815659826538362856059090168466055; - uint256 constant IC66y = 21843737062657972494870832477594000579903382696442884201323513267380462660556; + uint256 constant IC66x = 1071601579509139236412649336777516383083729411833025363285901187846951705514; + uint256 constant IC66y = 643778404700341783686316894071179800417687549225861429866927932290907352872; - uint256 constant IC67x = 4627469073003492692081267340370476560059598725588643453272534146391992363677; - uint256 constant IC67y = 3394839797037366879180540434526009043184480393900353544974252557966593979511; + uint256 constant IC67x = 21046686905022938762343110658685000333114003074832743789460482970929684291941; + uint256 constant IC67y = 16589695516620085044284865294304818658032377472492495403321572602644696285496; - uint256 constant IC68x = 16855117520614012750593394661559522115224312772742007753023953667480926227578; - uint256 constant IC68y = 17816700617479284171736370741327140530451913327152676849112278920461098914234; + uint256 constant IC68x = 15402727245438872470337281580419854325509021235549558441579332069237738542206; + uint256 constant IC68y = 12100658949812311807290740424830315786611473991678642131357227195466793178654; - uint256 constant IC69x = 3512208942781784738441229046544557918978151298191395832170296860208887519468; - uint256 constant IC69y = 2505225700037331828802591636773326790452866581901318024097244918874744068789; + uint256 constant IC69x = 5984396963935932069475014455874483850975993839370888235950954254263981029541; + uint256 constant IC69y = 8658244321663354058517608860644685738312456985966813850314182794608726926497; - uint256 constant IC70x = 11811112894872754299085263479604560501590590478241268189245643688628440648683; - uint256 constant IC70y = 18546962230916329328755427039622326464268028514850216640604830927968030769941; + uint256 constant IC70x = 13180402081920922842736886190093953231655326874611201456251342171630489279461; + uint256 constant IC70y = 18649658464519580163906798382923586107997731125760988378673369846514909161404; - uint256 constant IC71x = 17329412769385041011755512074931622014464544007921945629255020213102531435089; - uint256 constant IC71y = 8532056905413803097496014769465279358661845164966338552710370018656926026144; + uint256 constant IC71x = 11465613760655638455032324012041259936429065923953367597967854901531079869526; + uint256 constant IC71y = 1997868257671766278420414611308456329672567091454229700216047315765806631304; - uint256 constant IC72x = 12499852871185561422253376167019799648735207172681464009840294461239195188222; - uint256 constant IC72y = 20319333061740917925764368843994465380456164024362416598740064213349463358219; + uint256 constant IC72x = 17918109650394143090398200709147906843621449700067572334426785791214583511049; + uint256 constant IC72y = 5785087180604996996878479591688410688146103334006142651020815231268891900773; - uint256 constant IC73x = 13611836739262056798799919892708716022648332399944377961590069121334082918207; - uint256 constant IC73y = 1840281673669819140440191639717881323130098454217953330681420681771305528256; + uint256 constant IC73x = 736201990241690106987067004600088863457141457573681072149394616967572755929; + uint256 constant IC73y = 12537157162826621549086349254200249982552713002993943503127638231722978596924; - uint256 constant IC74x = 3080059060826164654915928266386228070871170799938996404113716331864067144292; - uint256 constant IC74y = 12503063943054595204075468765331127452619970579940584908913636468482392270520; + uint256 constant IC74x = 15785103340068683842513248354657964422095017416519973953965247557166746383423; + uint256 constant IC74y = 16150924406755343335896132050034914767928045988689480710519873684676576185028; - uint256 constant IC75x = 16433923389361333775927126833800818558680612925507786003170775000710001722305; - uint256 constant IC75y = 10503596066126211820217060014066415391057376892373743702389353058655984064889; + uint256 constant IC75x = 6404840253907413983145416199309477113029419362177186012992462488423921389989; + uint256 constant IC75y = 8735341945865532036256299477233956095055876095997087464613556071915976571146; - uint256 constant IC76x = 15065785319856470226961945722003203551387687174246998508091850983372092860681; - uint256 constant IC76y = 17896225228571809315986423739118202445046664678781781514879686360269381776743; + uint256 constant IC76x = 8724267365230902347229847202108650737209726005308343958546017169716303363251; + uint256 constant IC76y = 17777512362101876439834872855511544013815307612344519390875215243966466686025; - uint256 constant IC77x = 6870507339911801179138872152150615339958013992518264372631788950671523537614; - uint256 constant IC77y = 18037987737220811416285453912965586061676687691975309793517013459422037469273; + uint256 constant IC77x = 8918814611902546518920187003392494979454174182643529331409094384218166231650; + uint256 constant IC77y = 18184712480067856273523502143963922366841367703802154356706668556258107456291; - uint256 constant IC78x = 11822997279102317026991317765680191121052478599918882398078859661358268572609; - uint256 constant IC78y = 9534844203451570681341326976899711845339261467471924061990479104987248699193; + uint256 constant IC78x = 9421173889055624068250468682319042736523104237111924853383033602305643651409; + uint256 constant IC78y = 17076225282910336421003758619520963376827046792873380653814378558509545536194; - uint256 constant IC79x = 814895131247362788031531982991074036243262345850417573362708717291604432861; - uint256 constant IC79y = 21119163236943748654854615264754138892357106429981990456746055653318414462289; + uint256 constant IC79x = 17827953591197465637068392424066919197785406468317003450376104975572451412752; + uint256 constant IC79y = 19758205883431149738033761058476595044973262048294152716378750980720592832264; - uint256 constant IC80x = 20977523352094306502640039044972336388464193873230419392339943532501600182549; - uint256 constant IC80y = 6946114395405271880485956008591194883884526407256410182099924261288084717296; + uint256 constant IC80x = 5877455143230750188145901369572724485485689221369018527546722077858039568378; + uint256 constant IC80y = 20547529821963006488317098177150986788254986979627053843788623333737172069898; - uint256 constant IC81x = 7761194069996716601950630741239994979663258841042742617860461241304593607995; - uint256 constant IC81y = 6797191380097140836268094911544893630353880091765474528227264913999543456188; + uint256 constant IC81x = 4980820155167635856488138968291416906237146248404772197352963295674430339670; + uint256 constant IC81y = 18701181065695552777076243336927915570742707349896197585530631698642256643422; - uint256 constant IC82x = 5000779558587306016002634421106764294422377396987971375779683765476680617367; - uint256 constant IC82y = 2847606885305153491337801029460483228469102266671889774030818592958554461000; + uint256 constant IC82x = 16777939488041114754768545674514709721185376316115997064200051282595721559173; + uint256 constant IC82y = 5939768806357633468561973089882202212779962921089081983016988372615989543242; - uint256 constant IC83x = 2751416486345290827256675548931184221845108475099448535337243712621306648334; - uint256 constant IC83y = 13178855505750200729609370638681050600585376172418107165516640570458326734329; + uint256 constant IC83x = 14796363017577142791220641668352160568683008269771782264758229033250072319628; + uint256 constant IC83y = 14600699583086517418061957134181365606986549922649060599373995683203928018438; - uint256 constant IC84x = 2231240240887990908791102754456950032619892746141888228754833711047565335291; - uint256 constant IC84y = 8186246799537450893888429295287350584243812961324933766087162379650650478146; + uint256 constant IC84x = 7903707117829484574409231745320520376775440889841126591886418591988650340645; + uint256 constant IC84y = 14392470618957976023051290670419524135641225612724566454081135462717269912207; - uint256 constant IC85x = 6763520269685728106480261588448536867109810505037764388066571118455009345663; - uint256 constant IC85y = 13992198566440164726742004323044186581843713357791293320583243615794358038697; + uint256 constant IC85x = 7040254646516169238176084030015013167692487701232513069536956450947996030379; + uint256 constant IC85y = 8344217891222417433515293421374060610622682714177382471358588153225451407752; - uint256 constant IC86x = 15119414408862590555871972886368557114099256030532542417814685037330684720768; - uint256 constant IC86y = 12651960976713863505082588076208802297943780899939898803346701374131052398909; + uint256 constant IC86x = 5937292643151495064112317366294053602775514009276861609583272956389590265518; + uint256 constant IC86y = 1667993821256079901229637548974554662929109034226271574914376494716722176625; - uint256 constant IC87x = 21408174621836638638819070586317447414399450694528139169612961883475232668246; - uint256 constant IC87y = 8578504868019990506679317007240468112720944674191565915486280347133203190720; + uint256 constant IC87x = 10429545704286591237503711116064846275257778264471187604753484534805146304406; + uint256 constant IC87y = 16809620886550722377592042848589246446559282211323461249142902747003154770550; - uint256 constant IC88x = 2782647542257934843851469693770665300487229167835685576077113843718087959867; - uint256 constant IC88y = 8867931823375641744668523057812106126349767332031839302450573191270189134171; + uint256 constant IC88x = 3855121632148124520024006603503851007303555175973870246013190185424275036884; + uint256 constant IC88y = 9999821343476899711639206159041995757833047189164312873277142359741350548524; - uint256 constant IC89x = 11081787434921178311521055933193567788981208429171218116392059771404415915928; - uint256 constant IC89y = 13788691199354900700437740369989382948494894015767885728090020000181419577173; + uint256 constant IC89x = 9406573531866980696091650555832533670257258889697579436673721246944489813161; + uint256 constant IC89y = 2995301525705710804516618281453063310646626808047888632169285966532787483816; - uint256 constant IC90x = 20412142355431119883654327361709186157969186949695197008618502840030428727513; - uint256 constant IC90y = 2637978714522201963297964679788704513672820014439747969926130681129386713861; + uint256 constant IC90x = 1526457548771184118859192752374469540237852714417643375364529068991571728824; + uint256 constant IC90y = 20322188999985982433213531153742375410479264418221090198365532243908587434326; - uint256 constant IC91x = 16239438031981465694184986627702858819230905991973519513613416477752335486284; - uint256 constant IC91y = 586067010227246804824172701580729134690358529668454744500238895375711939871; + uint256 constant IC91x = 3647145737859818823186946652451283687702129427645865082018890413183344701091; + uint256 constant IC91y = 7819570647789419112121104220074887639917070518824958166839036978493127740892; - uint256 constant IC92x = 6929626034770046196919926728056089724077903835689930035058009754021646837317; - uint256 constant IC92y = 14007720231836246873596106523297514407552613621031343551101023830932032505831; + uint256 constant IC92x = 1974959570150660280056827747341994528565992841758006521675207473433735955848; + uint256 constant IC92y = 21006636613984238277559183702894457139320631222645359136557640302488911243945; - uint256 constant IC93x = 16191063119243167501349773152042552977077071420162570551428089527910135791691; - uint256 constant IC93y = 2984063520247837772995081663217075179586748361247613654084564271711901631617; + uint256 constant IC93x = 3335546558418017109432168296043479711076786715915291707849840571166448680717; + uint256 constant IC93y = 15457404158417127280242556946917664267314355206231923461676831217126476725537; - uint256 constant IC94x = 1805678180711203997152780674041106704122361139443780127259289188160052960798; - uint256 constant IC94y = 15270845587733837292535075619741580576161184393824166722506351632755753865314; + uint256 constant IC94x = 21441171890803415112590743754336383724436140530077210167567372102065803298084; + uint256 constant IC94y = 15051654224966300966100369372810644938086280718983170638538542893794943673495; - uint256 constant IC95x = 3030851989242786878227015219826255264454396167798762189510444533025354203347; - uint256 constant IC95y = 16780636433243520227559677544450077156636715628577721858217260980176889413252; + uint256 constant IC95x = 904738135681670190617377831792546580612791936292381085800842878532135505927; + uint256 constant IC95y = 6810010775466597235605200839456323606371118774128866957554172174037252045485; - uint256 constant IC96x = 4997143430537083890383903744684245387767882305763508413837134908583524834001; - uint256 constant IC96y = 8464708169272634602912508283222037851304014468407864911550343690773336631317; + uint256 constant IC96x = 12378672532176880399179863916468913697757231729062916629030598871088671023717; + uint256 constant IC96y = 20098346558210018384886078536904272236032468181896137221453087052203307445892; - uint256 constant IC97x = 19449990402403926111015018329109064212719623759776180438013078952765416102804; - uint256 constant IC97y = 21012811006445063812663363396478099871012832817952978452182474412706339501325; + uint256 constant IC97x = 14126725259373963085833115402251987636083846580379370010321611053960982580197; + uint256 constant IC97y = 8861293133079280696383738053273123495504319603270485677836319874673972340741; - uint256 constant IC98x = 21410072561093014667243485477372681620347269649123295559095808164172911680365; - uint256 constant IC98y = 19048135683243837600048166328392524449612017127669778956891490700257195759044; + uint256 constant IC98x = 2779458784793250007636797371297106252345927312270015027009754037825546332040; + uint256 constant IC98y = 6382781516595596976789302946518420311632218283496249973336315992533865353499; - uint256 constant IC99x = 21807812488351239382456202149286344533518638925893692239226566402570030214620; - uint256 constant IC99y = 3629742897674077941851845853759045237433919524958880146116523921237166952508; + uint256 constant IC99x = 12020089154866213694886153183892256324563831725367557661773856911992435489223; + uint256 constant IC99y = 10539389055710673989774401671358672778776773383822655042303695446739250113568; - uint256 constant IC100x = 12427392476134497199132588563614579041639492579857449719794721285072670141886; - uint256 constant IC100y = 12371491225153780473943451544387687913512052832901359322741447080589728901639; + uint256 constant IC100x = 1541217357497749664630897344587304428219166612596999401181554817809595193037; + uint256 constant IC100y = 1097705315439307635001054134068893470549566691614527573241133227650398108706; - uint256 constant IC101x = 18443769813381837683086382929315220708416867094711673553986325183433940633782; - uint256 constant IC101y = 13338795090806453026229937430211181391630005899559855875683874904665077837972; + uint256 constant IC101x = 6924110088498046602982308167134133247344479690753907917086285028639996233588; + uint256 constant IC101y = 16592419187624283608496871565561693292923055390111494702590350464797911661390; - uint256 constant IC102x = 7574561200290261962423462434572163854621504572881617953107242661231763189666; - uint256 constant IC102y = 21866390679404529040744442684466099062367291297634322269244096831308344158789; + uint256 constant IC102x = 14932644092780567752595039674791582086146773837645564841325716111844162761264; + uint256 constant IC102y = 14054900461629673933793648127738805887431229404561600987677415365748211518346; + + uint256 constant IC103x = 21826829410184219425839758804275334693402242173351536315267229912359886610244; + uint256 constant IC103y = 13145247716512585016535403539623870656705505496302557231425567395284656174722; + + uint256 constant IC104x = 10723865532425252680822060295606975447785125920481417815144738067876106730958; + uint256 constant IC104y = 2750060412378528512577424517240805942396359085759338556589546221101062077366; + + uint256 constant IC105x = 13610479009495437335054156071592856091793553643856975168470544018067268382616; + uint256 constant IC105y = 5028480654630813391642834424074823337367863167323445900517774159378904611046; + + uint256 constant IC106x = 8959960947101181609929281882023411146543404908305682511969412722987403935244; + uint256 constant IC106y = 17037840716498058589865158148300926307629497039776820539424257599747813331825; + + uint256 constant IC107x = 3329946637562309018196253174483297743601321674428654693366091368185353418522; + uint256 constant IC107y = 20309461139797568927934774754657461672289961695874069337325221805890193148325; + + uint256 constant IC108x = 21577763683655929280456425529518529321926379101126163313514585836300198072883; + uint256 constant IC108y = 5476543500179140115023201502972107116336322511138291020260500310257209370084; + + uint256 constant IC109x = 20879417355885501023056776335954343977316914269670342899109262163784954610784; + uint256 constant IC109y = 7790465984785624865275709254138747779403603809154540066422090152714795953712; + + uint256 constant IC110x = 10557397239732988433654681269152879173600930019783367956573509681134457260086; + uint256 constant IC110y = 7760747882631581374951580418424188763749299740883466036564477990785808278328; + + uint256 constant IC111x = 18962979274573620241177899735421077206942165151980971157684600404371127947884; + uint256 constant IC111y = 11142278777830464346481917178613961960044247071174132381659353660719810821830; + + uint256 constant IC112x = 18891312112007878933891062369102830538664709181035663177465029203528273667154; + uint256 constant IC112y = 5564943993235366369184329626770514678860068350805886001507419654572046760366; + + uint256 constant IC113x = 20501391928161541047382080445731840991833860209032196150370454452982172727784; + uint256 constant IC113y = 1207148501022258147436761504410975875343607921399296901409233799477104107651; + + uint256 constant IC114x = 17449749498261985599386064163600842115651335494726639189966941953754641382504; + uint256 constant IC114y = 9640065465839134209644253399286219771227236184332577630199068058361560772286; + + uint256 constant IC115x = 16769669983681282562871860837400140314125866994699474615399676301888014220432; + uint256 constant IC115y = 3455672321968490307111155866069820382335223916916296430573383128146984877194; + + uint256 constant IC116x = 5825437435828009010970802796811824674875997475735353556089845861417246271396; + uint256 constant IC116y = 3863895669944585830686800190438236202353815776017372741294015563475133037794; + + uint256 constant IC117x = 15887302858133980561256600445148855988791677156721478505479844704907715953945; + uint256 constant IC117y = 14864003316951019654081870944034384171499262900596502976368490439531594106016; + + uint256 constant IC118x = 13323805276305597321424783160890342818248361487605892420745100352081621727431; + uint256 constant IC118y = 19266628193531456317076591986961861635710997442851400667066787849204723280505; + + uint256 constant IC119x = 1328308549643118846463693088427234362874488580638550564357277553774477010791; + uint256 constant IC119y = 7968099729757825375814311903873299078493699569227171322917885132937350997706; + + uint256 constant IC120x = 1556864282486119668149963214488257821693266783207387782817897342258032047205; + uint256 constant IC120y = 345066057082474708144324052630651363347247004656128520678101294107524804087; // Memory data @@ -359,7 +413,7 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[102] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[120] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -607,6 +661,42 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { g1_mulAccC(_pVk, IC102x, IC102y, calldataload(add(pubSignals, 3232))) + g1_mulAccC(_pVk, IC103x, IC103y, calldataload(add(pubSignals, 3264))) + + g1_mulAccC(_pVk, IC104x, IC104y, calldataload(add(pubSignals, 3296))) + + g1_mulAccC(_pVk, IC105x, IC105y, calldataload(add(pubSignals, 3328))) + + g1_mulAccC(_pVk, IC106x, IC106y, calldataload(add(pubSignals, 3360))) + + g1_mulAccC(_pVk, IC107x, IC107y, calldataload(add(pubSignals, 3392))) + + g1_mulAccC(_pVk, IC108x, IC108y, calldataload(add(pubSignals, 3424))) + + g1_mulAccC(_pVk, IC109x, IC109y, calldataload(add(pubSignals, 3456))) + + g1_mulAccC(_pVk, IC110x, IC110y, calldataload(add(pubSignals, 3488))) + + g1_mulAccC(_pVk, IC111x, IC111y, calldataload(add(pubSignals, 3520))) + + g1_mulAccC(_pVk, IC112x, IC112y, calldataload(add(pubSignals, 3552))) + + g1_mulAccC(_pVk, IC113x, IC113y, calldataload(add(pubSignals, 3584))) + + g1_mulAccC(_pVk, IC114x, IC114y, calldataload(add(pubSignals, 3616))) + + g1_mulAccC(_pVk, IC115x, IC115y, calldataload(add(pubSignals, 3648))) + + g1_mulAccC(_pVk, IC116x, IC116y, calldataload(add(pubSignals, 3680))) + + g1_mulAccC(_pVk, IC117x, IC117y, calldataload(add(pubSignals, 3712))) + + g1_mulAccC(_pVk, IC118x, IC118y, calldataload(add(pubSignals, 3744))) + + g1_mulAccC(_pVk, IC119x, IC119y, calldataload(add(pubSignals, 3776))) + + g1_mulAccC(_pVk, IC120x, IC120y, calldataload(add(pubSignals, 3808))) + // -A mstore(_pPairing, calldataload(pA)) @@ -866,6 +956,42 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { checkField(calldataload(add(_pubSignals, 3264))) + checkField(calldataload(add(_pubSignals, 3296))) + + checkField(calldataload(add(_pubSignals, 3328))) + + checkField(calldataload(add(_pubSignals, 3360))) + + checkField(calldataload(add(_pubSignals, 3392))) + + checkField(calldataload(add(_pubSignals, 3424))) + + checkField(calldataload(add(_pubSignals, 3456))) + + checkField(calldataload(add(_pubSignals, 3488))) + + checkField(calldataload(add(_pubSignals, 3520))) + + checkField(calldataload(add(_pubSignals, 3552))) + + checkField(calldataload(add(_pubSignals, 3584))) + + checkField(calldataload(add(_pubSignals, 3616))) + + checkField(calldataload(add(_pubSignals, 3648))) + + checkField(calldataload(add(_pubSignals, 3680))) + + checkField(calldataload(add(_pubSignals, 3712))) + + checkField(calldataload(add(_pubSignals, 3744))) + + checkField(calldataload(add(_pubSignals, 3776))) + + checkField(calldataload(add(_pubSignals, 3808))) + + checkField(calldataload(add(_pubSignals, 3840))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/zeto_anon_enc.sol b/solidity/contracts/zeto_anon_enc.sol index 0a62806..23b4c72 100644 --- a/solidity/contracts/zeto_anon_enc.sol +++ b/solidity/contracts/zeto_anon_enc.sol @@ -77,7 +77,7 @@ contract Zeto_AnonEnc is uint256[] memory inputs, uint256[] memory outputs, uint256 encryptionNonce, - uint256[4] memory encryptedValues, + uint256[] memory encryptedValues, Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { @@ -90,7 +90,7 @@ contract Zeto_AnonEnc is if (inputs.length > 2) { // construct the public inputs - uint256[25] memory publicInputs; + uint256[43] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for (uint256 i = 0; i < encryptedValues.length; ++i) { @@ -121,7 +121,7 @@ contract Zeto_AnonEnc is ); } else { // construct the public inputs - uint256[9] memory publicInputs; + uint256[12] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for (uint256 i = 0; i < encryptedValues.length; ++i) { diff --git a/solidity/contracts/zeto_anon_enc_nullifier.sol b/solidity/contracts/zeto_anon_enc_nullifier.sol index 3cc8f23..9a26362 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier.sol @@ -83,7 +83,7 @@ contract Zeto_AnonEncNullifier is uint256[] memory outputs, uint256 root, uint256 encryptionNonce, - uint256[4] memory encryptedValues, + uint256[] memory encryptedValues, Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { @@ -99,7 +99,7 @@ contract Zeto_AnonEncNullifier is ); if (nullifiers.length > 2) { // construct the public inputs - uint256[36] memory publicInputs; + uint256[54] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for (uint256 i = 0; i < encryptedValues.length; ++i) { @@ -138,7 +138,7 @@ contract Zeto_AnonEncNullifier is ); } else { // construct the public inputs - uint256[12] memory publicInputs; + uint256[15] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for (uint256 i = 0; i < encryptedValues.length; ++i) { diff --git a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol index 8f97830..4fdc2f4 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol @@ -88,7 +88,7 @@ contract Zeto_AnonEncNullifierKyc is uint256[] memory outputs, uint256 root, uint256 encryptionNonce, - uint256[4] memory encryptedValues, + uint256[] memory encryptedValues, Commonlib.Proof calldata proof, bytes calldata data ) public returns (bool) { @@ -104,7 +104,7 @@ contract Zeto_AnonEncNullifierKyc is ); if (nullifiers.length > 2) { // construct the public inputs - uint256[37] memory publicInputs; + uint256[55] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for (uint256 i = 0; i < encryptedValues.length; ++i) { @@ -145,7 +145,7 @@ contract Zeto_AnonEncNullifierKyc is ); } else { // construct the public inputs - uint256[13] memory publicInputs; + uint256[16] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for (uint256 i = 0; i < encryptedValues.length; ++i) { diff --git a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol index 11c79a4..c2081c1 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol @@ -105,7 +105,7 @@ contract Zeto_AnonEncNullifierNonRepudiation is uint256[] memory outputs, uint256 root, uint256 encryptionNonce, - uint256[4] memory encryptedValuesForReceiver, + uint256[] memory encryptedValuesForReceiver, uint256[] memory encryptedValuesForAuthority, Commonlib.Proof calldata proof, bytes calldata data @@ -126,7 +126,7 @@ contract Zeto_AnonEncNullifierNonRepudiation is "Cipher Text for Authority must have a length of 64 with input or outputs number more than 2 and less than 10" ); // construct the public inputs - uint256[102] memory publicInputs; + uint256[120] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for receiver for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { @@ -177,7 +177,7 @@ contract Zeto_AnonEncNullifierNonRepudiation is "Cipher Text for Authority must have a length of 16 for no more than 2 inputs or outputs" ); // construct the public inputs - uint256[30] memory publicInputs; + uint256[33] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for receiver for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { diff --git a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts index db70b54..6db235c 100644 --- a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts +++ b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts @@ -452,7 +452,14 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin gasHistories.push(txResult?.gasUsed); } // add the clear text value so that it can be used by tests to compare with the decrypted value - return { txResult, plainTextSalt: outputs[0].salt }; + return { + txResult, + expectedPlainText: outputs.reduce((acc, o, i) => { + acc.push(BigInt(o.value || 0n) as BigNumberish); + acc.push((o.salt || 0n) as BigNumberish); + return acc; + }, [] as BigNumberish[]), + }; } async function prepareProof( diff --git a/solidity/test/zeto_anon_enc.ts b/solidity/test/zeto_anon_enc.ts index 0ecf9b2..a8fdb4f 100644 --- a/solidity/test/zeto_anon_enc.ts +++ b/solidity/test/zeto_anon_enc.ts @@ -123,26 +123,27 @@ describe('Zeto based fungible token with anonymity and encryption', function () events[0].encryptedValues, sharedKey, events[0].encryptionNonce, - 2 + 20 ); - expect(plainText).to.deep.equal([8n, result.plainTextSalt]); - // only the first utxo can be decrypted - const hash = poseidonHash([ - BigInt(plainText[0]), - plainText[1], - Bob.babyJubPublicKey[0], - Bob.babyJubPublicKey[1], - ]); - expect(hash).to.equal(incomingUTXOs[0]); + expect(plainText).to.deep.equal(result.expectedPlainText); // check the non-empty output hashes are correct - for (let i = 1; i < outputUtxos.length; i++) { - expect(incomingUTXOs[i]).to.equal(outputUtxos[i].hash); + for (let i = 0; i < outputUtxos.length; i++) { + // Bob uses the information received from Alice to reconstruct the UTXO sent to him + const hash = poseidonHash([ + BigInt(plainText[2 * i]), + plainText[2 * i + 1], + outputOwners[i].babyJubPublicKey[0], + outputOwners[i].babyJubPublicKey[1], + ]); + expect(incomingUTXOs[i]).to.equal(hash); } - // check empty hashes are empty + // check empty values, salt and hashes are empty for (let i = outputUtxos.length; i < 10; i++) { expect(incomingUTXOs[i]).to.equal(0); + expect(plainText[2 * i]).to.equal(0); + expect(plainText[2 * i + 1]).to.equal(0); } }); @@ -209,9 +210,9 @@ describe('Zeto based fungible token with anonymity and encryption', function () events[0].encryptedValues, sharedKey, events[0].encryptionNonce, - 2 + 4 ); - expect(plainText).to.deep.equal([25n, result.plainTextSalt]); + expect(plainText).to.deep.equal(result.expectedPlainText); // Bob verifies that the UTXO constructed from the decrypted values matches the UTXO from the event const hash = poseidonHash([ BigInt(plainText[0]), @@ -356,7 +357,14 @@ describe('Zeto based fungible token with anonymity and encryption', function () encodedProof ); // add the clear text value so that it can be used by tests to compare with the decrypted value - return { txResult, plainTextSalt: outputs[0].salt }; + return { + txResult, + expectedPlainText: outputs.reduce((acc, o, i) => { + acc.push(BigInt(o.value || 0n) as BigNumberish); + acc.push((o.salt || 0n) as BigNumberish); + return acc; + }, [] as BigNumberish[]), + }; } async function prepareProof( @@ -385,7 +393,9 @@ describe('Zeto based fungible token with anonymity and encryption', function () let circuitToUse = circuit; let provingKeyToUse = provingKey; + let isBatch = false; if (inputCommitments.length > 2 || outputCommitments.length > 2) { + isBatch = true; circuitToUse = batchCircuit; provingKeyToUse = batchProvingKey; } @@ -416,7 +426,9 @@ describe('Zeto based fungible token with anonymity and encryption', function () ); const encodedProof = encodeProof(proof); - const encryptedValues = publicSignals.slice(0, 4); + const encryptedValues = isBatch + ? publicSignals.slice(0, 22) + : publicSignals.slice(0, 7); return { inputCommitments, outputCommitments, diff --git a/solidity/test/zeto_anon_enc_nullifier.ts b/solidity/test/zeto_anon_enc_nullifier.ts index fbe155a..86948ef 100644 --- a/solidity/test/zeto_anon_enc_nullifier.ts +++ b/solidity/test/zeto_anon_enc_nullifier.ts @@ -167,30 +167,29 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti events[0].encryptedValues, sharedKey, events[0].encryptionNonce, - 2 + 20 ); - expect(plainText).to.deep.equal([8n, result.plainTextSalt]); - // only the first utxo can be decrypted - const hash = poseidonHash([ - BigInt(plainText[0]), - plainText[1], - Bob.babyJubPublicKey[0], - Bob.babyJubPublicKey[1], - ]); - expect(hash).to.equal(incomingUTXOs[0]); - await smtAlice.add(incomingUTXOs[0], incomingUTXOs[0]); - await smtBob.add(incomingUTXOs[0], incomingUTXOs[0]); + expect(plainText).to.deep.equal(result.expectedPlainText); // check the non-empty output hashes are correct - for (let i = 1; i < outputUtxos.length; i++) { - expect(incomingUTXOs[i]).to.equal(outputUtxos[i].hash); + for (let i = 0; i < outputUtxos.length; i++) { + // Bob uses the information received from Alice to reconstruct the UTXO sent to him + const hash = poseidonHash([ + BigInt(plainText[2 * i]), + plainText[2 * i + 1], + outputOwners[i].babyJubPublicKey[0], + outputOwners[i].babyJubPublicKey[1], + ]); + expect(incomingUTXOs[i]).to.equal(hash); await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]); await smtBob.add(incomingUTXOs[i], incomingUTXOs[i]); } - // check empty hashes are empty + // check empty values, salt and hashes are empty for (let i = outputUtxos.length; i < 10; i++) { expect(incomingUTXOs[i]).to.equal(0); + expect(plainText[2 * i]).to.equal(0); + expect(plainText[2 * i + 1]).to.equal(0); } }); @@ -299,9 +298,9 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti events[0].encryptedValues, sharedKey, events[0].encryptionNonce, - 2 + 4 ); - expect(plainText).to.deep.equal([25n, result2.plainTextSalt]); + expect(plainText).to.deep.equal(result2.expectedPlainText); // Bob uses the decrypted values to construct the UTXO received from the transaction utxo3 = newUTXO(Number(plainText[0]), Bob, plainText[1]); @@ -651,7 +650,14 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti encodedProof ); // add the clear text value so that it can be used by tests to compare with the decrypted value - return { txResult, plainTextSalt: outputs[0].salt }; + return { + txResult, + expectedPlainText: outputs.reduce((acc, o, i) => { + acc.push(BigInt(o.value || 0n) as BigNumberish); + acc.push((o.salt || 0n) as BigNumberish); + return acc; + }, [] as BigNumberish[]), + }; } async function prepareProof( @@ -685,7 +691,9 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti }); let circuitToUse = circuit; let provingKeyToUse = provingKey; + let isBatch = false; if (inputCommitments.length > 2 || outputCommitments.length > 2) { + isBatch = true; circuitToUse = batchCircuit; provingKeyToUse = batchProvingKey; } @@ -720,7 +728,9 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ); const encodedProof = encodeProof(proof); - const encryptedValues = publicSignals.slice(0, 4); + const encryptedValues = isBatch + ? publicSignals.slice(0, 22) + : publicSignals.slice(0, 7); return { inputCommitments, outputCommitments, diff --git a/solidity/test/zeto_anon_enc_nullifier_kyc.ts b/solidity/test/zeto_anon_enc_nullifier_kyc.ts index 51baa40..77d19de 100644 --- a/solidity/test/zeto_anon_enc_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_enc_nullifier_kyc.ts @@ -216,32 +216,30 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti events[0].encryptedValues, sharedKey, events[0].encryptionNonce, - 2 + 20 ); - expect(plainText).to.deep.equal([8n, result.plainTextSalt]); - // only the first utxo can be decrypted - const hash = poseidonHash([ - BigInt(plainText[0]), - plainText[1], - Bob.babyJubPublicKey[0], - Bob.babyJubPublicKey[1], - ]); - expect(hash).to.equal(incomingUTXOs[0]); - await smtAlice.add(incomingUTXOs[0], incomingUTXOs[0]); - await smtBob.add(incomingUTXOs[0], incomingUTXOs[0]); - await smtUnregistered.add(incomingUTXOs[0], incomingUTXOs[0]); + expect(plainText).to.deep.equal(result.expectedPlainText); // check the non-empty output hashes are correct - for (let i = 1; i < outputUtxos.length; i++) { - expect(incomingUTXOs[i]).to.equal(outputUtxos[i].hash); + for (let i = 0; i < outputUtxos.length; i++) { + // Bob uses the information received from Alice to reconstruct the UTXO sent to him + const hash = poseidonHash([ + BigInt(plainText[2 * i]), + plainText[2 * i + 1], + outputOwners[i].babyJubPublicKey[0], + outputOwners[i].babyJubPublicKey[1], + ]); + expect(incomingUTXOs[i]).to.equal(hash); await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]); await smtBob.add(incomingUTXOs[i], incomingUTXOs[i]); await smtUnregistered.add(incomingUTXOs[i], incomingUTXOs[i]); } - // check empty hashes are empty + // check empty values, salt and hashes are empty for (let i = outputUtxos.length; i < 10; i++) { expect(incomingUTXOs[i]).to.equal(0); + expect(plainText[2 * i]).to.equal(0); + expect(plainText[2 * i + 1]).to.equal(0); } }); @@ -374,9 +372,9 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti events[0].encryptedValues, sharedKey, events[0].encryptionNonce, - 2 + 4 ); - expect(plainText).to.deep.equal([25n, result2.plainTextSalt]); + expect(plainText).to.deep.equal(result2.expectedPlainText); // Bob uses the decrypted values to construct the UTXO received from the transaction utxo3 = newUTXO(Number(plainText[0]), Bob, plainText[1]); @@ -974,7 +972,14 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti encodedProof ); // add the clear text value so that it can be used by tests to compare with the decrypted value - return { txResult, plainTextSalt: outputs[0].salt }; + return { + txResult, + expectedPlainText: outputs.reduce((acc, o, i) => { + acc.push(BigInt(o.value || 0n) as BigNumberish); + acc.push((o.salt || 0n) as BigNumberish); + return acc; + }, [] as BigNumberish[]), + }; } async function prepareProof( @@ -1010,7 +1015,9 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti }); let circuitToUse = circuit; let provingKeyToUse = provingKey; + let isBatch = false; if (inputCommitments.length > 2 || outputCommitments.length > 2) { + isBatch = true; circuitToUse = batchCircuit; provingKeyToUse = batchProvingKey; } @@ -1047,7 +1054,9 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ); const encodedProof = encodeProof(proof); - const encryptedValues = publicSignals.slice(0, 4); + const encryptedValues = isBatch + ? publicSignals.slice(0, 22) + : publicSignals.slice(0, 7); return { inputCommitments, outputCommitments, diff --git a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts index d5f47a6..ff575b5 100644 --- a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts +++ b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts @@ -141,7 +141,6 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti mtps.push(p.siblings.map((s) => s.bigInt())); } - // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice const _bOut1 = newUTXO(8, Bob); const _bOut2 = newUTXO(1, Alice); @@ -182,30 +181,29 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti events[0].encryptedValuesForReceiver, sharedKey, events[0].encryptionNonce, - 2 + 20 ); - expect(plainText).to.deep.equal([8n, result.plainTextSalt]); - // only the first utxo can be decrypted - const hash = poseidonHash([ - BigInt(plainText[0]), - plainText[1], - Bob.babyJubPublicKey[0], - Bob.babyJubPublicKey[1], - ]); - expect(hash).to.equal(incomingUTXOs[0]); - await smtAlice.add(incomingUTXOs[0], incomingUTXOs[0]); - await smtBob.add(incomingUTXOs[0], incomingUTXOs[0]); + expect(plainText).to.deep.equal(result.expectedPlainText); // check the non-empty output hashes are correct - for (let i = 1; i < outputUtxos.length; i++) { - expect(incomingUTXOs[i]).to.equal(outputUtxos[i].hash); + for (let i = 0; i < outputUtxos.length; i++) { + // Bob uses the information received from Alice to reconstruct the UTXO sent to him + const hash = poseidonHash([ + BigInt(plainText[2 * i]), + plainText[2 * i + 1], + outputOwners[i].babyJubPublicKey[0], + outputOwners[i].babyJubPublicKey[1], + ]); + expect(incomingUTXOs[i]).to.equal(hash); await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]); await smtBob.add(incomingUTXOs[i], incomingUTXOs[i]); } - // check empty hashes are empty + // check empty values, salt and hashes are empty for (let i = outputUtxos.length; i < 10; i++) { expect(incomingUTXOs[i]).to.equal(0); + expect(plainText[2 * i]).to.equal(0); + expect(plainText[2 * i + 1]).to.equal(0); } // The regulator uses the encrypted values in the event to decrypt and recover the UTXO value and salt @@ -357,9 +355,9 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti events[0].encryptedValuesForReceiver, sharedKey1, events[0].encryptionNonce, - 2 + 4 ); - expect(plainText1).to.deep.equal([25n, result2.plainTextSalt]); + expect(plainText1).to.deep.equal(result2.expectedPlainText); // The regulator uses the encrypted values in the event to decrypt and recover the UTXO value and salt const sharedKey2 = genEcdhSharedKey( @@ -758,7 +756,14 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti encodedProof ); // add the clear text value so that it can be used by tests to compare with the decrypted value - return { txResult, plainTextSalt: outputs[0].salt }; + return { + txResult, + expectedPlainText: outputs.reduce((acc, o, i) => { + acc.push(BigInt(o.value || 0n) as BigNumberish); + acc.push((o.salt || 0n) as BigNumberish); + return acc; + }, [] as BigNumberish[]), + }; } async function prepareProof( @@ -833,10 +838,12 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti return { inputCommitments, outputCommitments, - encryptedValuesForReceiver: publicSignals.slice(0, 4), + encryptedValuesForReceiver: isBatch + ? publicSignals.slice(0, 22) + : publicSignals.slice(0, 7), encryptedValuesForRegulator: isBatch - ? publicSignals.slice(4, 68) - : publicSignals.slice(4, 20), + ? publicSignals.slice(22, 86) + : publicSignals.slice(7, 23), encryptionNonce, encodedProof, }; diff --git a/solidity/test/zeto_anon_nullifier.ts b/solidity/test/zeto_anon_nullifier.ts index 8ea8705..11c0341 100644 --- a/solidity/test/zeto_anon_nullifier.ts +++ b/solidity/test/zeto_anon_nullifier.ts @@ -619,7 +619,14 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr encodedProof ); // add the clear text value so that it can be used by tests to compare with the decrypted value - return { txResult, plainTextSalt: outputs[0].salt }; + return { + txResult, + expectedPlainText: outputs.reduce((acc, o, i) => { + acc.push(BigInt(o.value || 0n) as BigNumberish); + acc.push((o.salt || 0n) as BigNumberish); + return acc; + }, [] as BigNumberish[]), + }; } async function prepareProof( diff --git a/solidity/test/zeto_anon_nullifier_kyc.ts b/solidity/test/zeto_anon_nullifier_kyc.ts index 3b763ad..fafd18d 100644 --- a/solidity/test/zeto_anon_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_nullifier_kyc.ts @@ -943,7 +943,14 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou encodedProof ); // add the clear text value so that it can be used by tests to compare with the decrypted value - return { txResult, plainTextSalt: outputs[0].salt }; + return { + txResult, + expectedPlainText: outputs.reduce((acc, o, i) => { + acc.push(BigInt(o.value || 0n) as BigNumberish); + acc.push((o.salt || 0n) as BigNumberish); + return acc; + }, [] as BigNumberish[]), + }; } async function prepareProof( diff --git a/zkp/circuits/basetokens/anon_enc_base.circom b/zkp/circuits/basetokens/anon_enc_base.circom index 86af9be..ac5539d 100644 --- a/zkp/circuits/basetokens/anon_enc_base.circom +++ b/zkp/circuits/basetokens/anon_enc_base.circom @@ -40,8 +40,14 @@ template Zeto(nInputs, nOutputs) { signal input outputOwnerPublicKeys[nOutputs][2]; signal input encryptionNonce; - // the output for a 2-element input (value and salt) encryption is a 4-element array - signal output cipherText[4]; + // the output for encrypted output values and salts + var cLen = 2 * nOutputs; + if (cLen % 3 != 0) { + cLen += (3 - (cLen % 3)); + } + cLen++; + signal output cipherText[cLen]; + // derive the sender's public key from the secret input // for the sender's private key. This step demonstrates @@ -86,15 +92,15 @@ template Zeto(nInputs, nOutputs) { sharedSecret[0] = ecdh.sharedKey[0]; sharedSecret[1] = ecdh.sharedKey[1]; - // encrypt the value for the receiver - component encrypt = SymmetricEncrypt(2); - // our circuit requires that the output UTXO for the receiver must be the first in the array - encrypt.plainText[0] <== outputValues[0]; - encrypt.plainText[1] <== outputSalts[0]; + // encrypt the value for the output utxos + component encrypt = SymmetricEncrypt(2 * nOutputs); + for (var i = 0; i < nOutputs; i++) { + encrypt.plainText[2 * i] <== outputValues[i]; + encrypt.plainText[2 * i + 1] <== outputSalts[i]; + } encrypt.key <== sharedSecret; encrypt.nonce <== encryptionNonce; - encrypt.cipherText[0] ==> cipherText[0]; - encrypt.cipherText[1] ==> cipherText[1]; - encrypt.cipherText[2] ==> cipherText[2]; - encrypt.cipherText[3] ==> cipherText[3]; + for (var i = 0; i < cLen; i++) { + encrypt.cipherText[i] ==> cipherText[i]; + } } diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_base.circom index fba891e..8c62561 100644 --- a/zkp/circuits/basetokens/anon_enc_nullifier_base.circom +++ b/zkp/circuits/basetokens/anon_enc_nullifier_base.circom @@ -48,8 +48,13 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { signal input outputSalts[nOutputs]; signal input encryptionNonce; - // the output for a 2-element input (value and salt) encryption is a 4-element array - signal output cipherText[4]; + // the output for encrypted output values and salts + var cLen = 2 * nOutputs; + if (cLen % 3 != 0) { + cLen += (3 - (cLen % 3)); + } + cLen++; + signal output cipherText[cLen]; // derive the sender's public key from the secret input // for the sender's private key. This step demonstrates @@ -111,15 +116,15 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { sharedSecret[0] = ecdh.sharedKey[0]; sharedSecret[1] = ecdh.sharedKey[1]; - // encrypt the value for the receiver - component encrypt = SymmetricEncrypt(2); - // our circuit requires that the output UTXO for the receiver must be the first in the array - encrypt.plainText[0] <== outputValues[0]; - encrypt.plainText[1] <== outputSalts[0]; + // encrypt the value for the output utxos + component encrypt = SymmetricEncrypt(2 * nOutputs); + for (var i = 0; i < nOutputs; i++) { + encrypt.plainText[2 * i] <== outputValues[i]; + encrypt.plainText[2 * i + 1] <== outputSalts[i]; + } encrypt.key <== sharedSecret; encrypt.nonce <== encryptionNonce; - encrypt.cipherText[0] ==> cipherText[0]; - encrypt.cipherText[1] ==> cipherText[1]; - encrypt.cipherText[2] ==> cipherText[2]; - encrypt.cipherText[3] ==> cipherText[3]; + for (var i = 0; i < cLen; i++) { + encrypt.cipherText[i] ==> cipherText[i]; + } } diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom index 4f6ba7f..4231c76 100644 --- a/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom +++ b/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom @@ -51,8 +51,13 @@ template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) { signal input outputSalts[nOutputs]; signal input encryptionNonce; - // the output for a 2-element input (value and salt) encryption is a 4-element array - signal output cipherText[4]; + // the output for encrypted output values and salts + var cLen = 2 * nOutputs; + if (cLen % 3 != 0) { + cLen += (3 - (cLen % 3)); + } + cLen++; + signal output cipherText[cLen]; // derive the sender's public key from the secret input // for the sender's private key. This step demonstrates @@ -140,15 +145,15 @@ template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) { sharedSecret[0] = ecdh.sharedKey[0]; sharedSecret[1] = ecdh.sharedKey[1]; - // encrypt the value for the receiver - component encrypt = SymmetricEncrypt(2); - // our circuit requires that the output UTXO for the receiver must be the first in the array - encrypt.plainText[0] <== outputValues[0]; - encrypt.plainText[1] <== outputSalts[0]; + // encrypt the value for the output utxos + component encrypt = SymmetricEncrypt(2 * nOutputs); + for (var i = 0; i < nOutputs; i++) { + encrypt.plainText[2 * i] <== outputValues[i]; + encrypt.plainText[2 * i + 1] <== outputSalts[i]; + } encrypt.key <== sharedSecret; encrypt.nonce <== encryptionNonce; - encrypt.cipherText[0] ==> cipherText[0]; - encrypt.cipherText[1] ==> cipherText[1]; - encrypt.cipherText[2] ==> cipherText[2]; - encrypt.cipherText[3] ==> cipherText[3]; + for (var i = 0; i < cLen; i++) { + encrypt.cipherText[i] ==> cipherText[i]; + } } \ No newline at end of file diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom index 0cddc73..d31e0a1 100644 --- a/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom +++ b/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom @@ -50,8 +50,14 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { signal input encryptionNonce; signal input authorityPublicKey[2]; - // the output for a 2-element input (value and salt) encryption is a 4-element array - signal output cipherTextReceiver[4]; + // the output for encrypted output values and salts + var cLen = 2 * nOutputs; + if (cLen % 3 != 0) { + cLen += (3 - (cLen % 3)); + } + cLen++; + signal output cipherText[cLen]; + // the number of cipher text messages returned by // the encryption template will be 3n+1 // input length: @@ -126,18 +132,17 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { sharedSecretReceiver[0] = ecdh1.sharedKey[0]; sharedSecretReceiver[1] = ecdh1.sharedKey[1]; - // encrypt the value for the receiver - component encrypt1 = SymmetricEncrypt(2); - // our circuit requires that the output UTXO for the receiver must be the first in the array - encrypt1.plainText[0] <== outputValues[0]; - encrypt1.plainText[1] <== outputSalts[0]; + // encrypt the value for the output utxos + component encrypt1 = SymmetricEncrypt(2 * nOutputs); + for (var i = 0; i < nOutputs; i++) { + encrypt1.plainText[2 * i] <== outputValues[i]; + encrypt1.plainText[2 * i + 1] <== outputSalts[i]; + } encrypt1.key <== sharedSecretReceiver; encrypt1.nonce <== encryptionNonce; - // the output for a 2-element input encryption is a 4-element array - encrypt1.cipherText[0] ==> cipherTextReceiver[0]; - encrypt1.cipherText[1] ==> cipherTextReceiver[1]; - encrypt1.cipherText[2] ==> cipherTextReceiver[2]; - encrypt1.cipherText[3] ==> cipherTextReceiver[3]; + for (var i = 0; i < cLen; i++) { + encrypt1.cipherText[i] ==> cipherText[i]; + } // generate shared secret for the authority var sharedSecretAuthority[2]; From e057865ea294277182cc4ac67c193a7355be9ac0 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Thu, 26 Sep 2024 14:26:07 +0100 Subject: [PATCH 06/24] fix circuit tests due to changes Signed-off-by: Chengxuan Xing --- zkp/js/test/anon_enc.js | 120 ++++++++-- zkp/js/test/anon_enc_nullifier.js | 198 ++++++++++++---- zkp/js/test/anon_enc_nullifier_kyc.js | 16 +- .../anon_enc_nullifier_non_repudiation.js | 219 ++++++++++++++---- 4 files changed, 435 insertions(+), 118 deletions(-) diff --git a/zkp/js/test/anon_enc.js b/zkp/js/test/anon_enc.js index cb34289..689c9fd 100644 --- a/zkp/js/test/anon_enc.js +++ b/zkp/js/test/anon_enc.js @@ -17,8 +17,19 @@ const { expect } = require('chai'); const { join } = require('path'); const { wasm: wasm_tester } = require('circom_tester'); -const { genRandomSalt, genKeypair, genEcdhSharedKey, formatPrivKeyForBabyJub, stringifyBigInts } = require('maci-crypto'); -const { Poseidon, newSalt, poseidonDecrypt, newEncryptionNonce } = require('../index.js'); +const { + genRandomSalt, + genKeypair, + genEcdhSharedKey, + formatPrivKeyForBabyJub, + stringifyBigInts, +} = require('maci-crypto'); +const { + Poseidon, + newSalt, + poseidonDecrypt, + newEncryptionNonce, +} = require('../index.js'); const poseidonHash = Poseidon.poseidon4; @@ -31,7 +42,9 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../../circuits/anon_enc.circom')); + circuit = await wasm_tester( + join(__dirname, '../../circuits/anon_enc.circom') + ); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -48,16 +61,32 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...sender.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...sender.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...sender.pubKey, + ]); const inputCommitments = [input1, input2]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...receiver.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...receiver.pubKey, + ]); const salt4 = newSalt(); - const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...sender.pubKey]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt4, + ...sender.pubKey, + ]); const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); @@ -87,18 +116,27 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp // console.log('receiverPublicKey', receiverPubKey); // console.log('encryptionNonce', encryptionNonce); - expect(witness[5]).to.equal(BigInt(inputCommitments[0])); - expect(witness[6]).to.equal(BigInt(inputCommitments[1])); - expect(witness[7]).to.equal(BigInt(outputCommitments[0])); - expect(witness[8]).to.equal(BigInt(outputCommitments[1])); + expect(witness[8]).to.equal(BigInt(inputCommitments[0])); + expect(witness[9]).to.equal(BigInt(inputCommitments[1])); + expect(witness[10]).to.equal(BigInt(outputCommitments[0])); + expect(witness[11]).to.equal(BigInt(outputCommitments[1])); // take the output from the proof circuit and attempt to decrypt // as the receiver - const cipherText = witness.slice(1, 5); + const cipherText = witness.slice(1, 8); const recoveredKey = genEcdhSharedKey(receiver.privKey, sender.pubKey); - const plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); + const plainText = poseidonDecrypt( + cipherText, + recoveredKey, + encryptionNonce, + 4 + ); // use the recovered value (plainText[0]) and salt (plainText[1]) to verify the output commitment - const calculatedHash = poseidonHash([BigInt(plainText[0]), BigInt(plainText[1]), ...receiver.pubKey]); + const calculatedHash = poseidonHash([ + BigInt(plainText[0]), + BigInt(plainText[1]), + ...receiver.pubKey, + ]); expect(calculatedHash).to.equal(outputCommitments[0]); }); @@ -107,15 +145,31 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp const outputValues = [90, 35]; // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...sender.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...sender.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...sender.pubKey, + ]); const inputCommitments = [input1, input2]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...receiver.pubKey]); - const output2 = poseidonHash([BigInt(outputValues[1]), salt3, ...sender.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...receiver.pubKey, + ]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt3, + ...sender.pubKey, + ]); const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); @@ -143,7 +197,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp err = e; } // console.log(err); - expect(err).to.match(/Error in template Zeto_105 line: 78/); + expect(err).to.match(/Error in template Zeto_105 line: 84/); }); it('should failed to match output UTXO after decrypting the cipher texts from the events if using the wrong sender public keys', async () => { @@ -152,16 +206,32 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...sender.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...sender.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...sender.pubKey, + ]); const inputCommitments = [input1, input2]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...receiver.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...receiver.pubKey, + ]); const salt4 = newSalt(); - const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...sender.pubKey]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt4, + ...sender.pubKey, + ]); const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); @@ -192,6 +262,8 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp // the decryption scheme has self-checking mechanism, so it should throw an error expect(function () { poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); - }).to.throw('The last ciphertext element must match the second item of the permuted state'); + }).to.throw( + 'The last ciphertext element must match the second item of the permuted state' + ); }); }); diff --git a/zkp/js/test/anon_enc_nullifier.js b/zkp/js/test/anon_enc_nullifier.js index 95379bf..648bef6 100644 --- a/zkp/js/test/anon_enc_nullifier.js +++ b/zkp/js/test/anon_enc_nullifier.js @@ -17,9 +17,25 @@ const { expect } = require('chai'); const { join } = require('path'); const { wasm: wasm_tester } = require('circom_tester'); -const { genRandomSalt, genKeypair, genEcdhSharedKey, formatPrivKeyForBabyJub, stringifyBigInts } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); -const { Poseidon, newSalt, poseidonDecrypt, newEncryptionNonce } = require('../index.js'); +const { + genRandomSalt, + genKeypair, + genEcdhSharedKey, + formatPrivKeyForBabyJub, + stringifyBigInts, +} = require('maci-crypto'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); +const { + Poseidon, + newSalt, + poseidonDecrypt, + newEncryptionNonce, +} = require('../index.js'); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon4; @@ -35,7 +51,9 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../../circuits/anon_enc_nullifier.circom')); + circuit = await wasm_tester( + join(__dirname, '../../circuits/anon_enc_nullifier.circom') + ); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -61,14 +79,30 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the inputs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -76,14 +110,28 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); const salt4 = newSalt(); - const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...Alice.pubKey]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt4, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); @@ -99,7 +147,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], outputCommitments, outputValues, @@ -122,16 +173,21 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // console.log('outputOwnerPublicKeys', [Bob.pubKey, Alice.pubKey]); // console.log('encryptionNonce', encryptionNonce); - expect(witness[5]).to.equal(BigInt(nullifiers[0])); - expect(witness[6]).to.equal(BigInt(nullifiers[1])); - expect(witness[7]).to.equal(proof1.root.bigInt()); + expect(witness[8]).to.equal(BigInt(nullifiers[0])); + expect(witness[9]).to.equal(BigInt(nullifiers[1])); + expect(witness[10]).to.equal(proof1.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver - const cipherText = witness.slice(1, 5); // first 4 elements are the cipher text for the first encryption output + const cipherText = witness.slice(1, 8); // first 7 elements are the cipher text for the encryption output const recoveredKey = genEcdhSharedKey(Bob.privKey, Alice.pubKey); - const plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); - expect(plainText).to.deep.equal([20n, salt3]); + const plainText = poseidonDecrypt( + cipherText, + recoveredKey, + encryptionNonce, + 4 + ); + expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); }); it('should succeed for valid witness and produce an encypted value - single input', async () => { @@ -140,25 +196,44 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const inputCommitments = [input1, 0]; // create the nullifiers for the inputs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); const nullifiers = [nullifier1, 0]; // calculate the root of the SMT await smtAlice.add(input1, input1); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH + ); const proof2 = await smtAlice.generateCircomVerifierProof(0, ZERO_HASH); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); const salt4 = newSalt(); - const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...Alice.pubKey]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt4, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); @@ -174,7 +249,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym inputSalts: [salt1, 0], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 0], outputCommitments, outputValues, @@ -197,16 +275,21 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // console.log('outputOwnerPublicKeys', [receiver.pubKey, sender.pubKey]); // console.log('encryptionNonce', encryptionNonce); - expect(witness[5]).to.equal(BigInt(nullifiers[0])); - expect(witness[6]).to.equal(BigInt(nullifiers[1])); - expect(witness[7]).to.equal(proof1.root.bigInt()); + expect(witness[8]).to.equal(BigInt(nullifiers[0])); + expect(witness[9]).to.equal(BigInt(nullifiers[1])); + expect(witness[10]).to.equal(proof1.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver - const cipherText = witness.slice(1, 5); // first 4 elements are the cipher text for the first encryption output + const cipherText = witness.slice(1, 8); // first 7 elements are the cipher text for the encryption output const recoveredKey = genEcdhSharedKey(Bob.privKey, Alice.pubKey); - const plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); - expect(plainText).to.deep.equal([20n, salt3]); + const plainText = poseidonDecrypt( + cipherText, + recoveredKey, + encryptionNonce, + 4 + ); + expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); }); it('should fail to generate a witness because mass conservation is not obeyed', async () => { @@ -215,14 +298,30 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the input UTXOs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -230,13 +329,27 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); - const output2 = poseidonHash([BigInt(outputValues[1]), salt3, ...Alice.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt3, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; const sharedSecret = genEcdhSharedKey(Alice.privKey, Bob.pubKey); @@ -255,7 +368,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], outputCommitments, outputValues, @@ -270,6 +386,6 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym } // console.log(err); expect(err).to.match(/Error in template CheckSum_161 line: 44/); - expect(err).to.match(/Error in template Zeto_263 line: 92/); + expect(err).to.match(/Error in template Zeto_263 line: 97/); }); }); diff --git a/zkp/js/test/anon_enc_nullifier_kyc.js b/zkp/js/test/anon_enc_nullifier_kyc.js index 26b134b..66a5043 100644 --- a/zkp/js/test/anon_enc_nullifier_kyc.js +++ b/zkp/js/test/anon_enc_nullifier_kyc.js @@ -206,22 +206,22 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // console.log('identitiesRoot', proof3.root.bigInt()); // console.log('encryptionNonce', encryptionNonce); - expect(witness[5]).to.equal(BigInt(nullifiers[0])); - expect(witness[6]).to.equal(BigInt(nullifiers[1])); - expect(witness[7]).to.equal(proof1.root.bigInt()); - expect(witness[10]).to.equal(proof3.root.bigInt()); + expect(witness[8]).to.equal(BigInt(nullifiers[0])); + expect(witness[9]).to.equal(BigInt(nullifiers[1])); + expect(witness[10]).to.equal(proof1.root.bigInt()); + expect(witness[13]).to.equal(proof3.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver - const cipherText = witness.slice(1, 5); // first 4 elements are the cipher text for the first encryption output + const cipherText = witness.slice(1, 8); // first 7 elements are the cipher text for the encryption output const recoveredKey = genEcdhSharedKey(Bob.privKey, Alice.pubKey); const plainText = poseidonDecrypt( cipherText, recoveredKey, encryptionNonce, - 2 + 4 ); - expect(plainText).to.deep.equal([20n, salt3]); + expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); }); it('should fail if not using the right identities merkle proofs', async () => { @@ -334,7 +334,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym err = e; } // console.log(err); - expect(err).to.match(/Error in template Zeto_266 line: 131/); + expect(err).to.match(/Error in template Zeto_266 line: 136/); expect(err).to.match(/Error in template CheckSMTProof_253 line: 46/); }); }); diff --git a/zkp/js/test/anon_enc_nullifier_non_repudiation.js b/zkp/js/test/anon_enc_nullifier_non_repudiation.js index 5a3f325..3efbbc5 100644 --- a/zkp/js/test/anon_enc_nullifier_non_repudiation.js +++ b/zkp/js/test/anon_enc_nullifier_non_repudiation.js @@ -17,9 +17,25 @@ const { expect } = require('chai'); const { join } = require('path'); const { wasm: wasm_tester } = require('circom_tester'); -const { genRandomSalt, genKeypair, genEcdhSharedKey, formatPrivKeyForBabyJub, stringifyBigInts } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); -const { Poseidon, newSalt, newEncryptionNonce, poseidonDecrypt } = require('../index.js'); +const { + genRandomSalt, + genKeypair, + genEcdhSharedKey, + formatPrivKeyForBabyJub, + stringifyBigInts, +} = require('maci-crypto'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); +const { + Poseidon, + newSalt, + newEncryptionNonce, + poseidonDecrypt, +} = require('../index.js'); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon4; @@ -36,7 +52,12 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../../circuits/anon_enc_nullifier_non_repudiation.circom')); + circuit = await wasm_tester( + join( + __dirname, + '../../circuits/anon_enc_nullifier_non_repudiation.circom' + ) + ); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -66,14 +87,30 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the inputs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -81,14 +118,28 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); const salt4 = newSalt(); - const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...Alice.pubKey]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt4, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); @@ -104,7 +155,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], outputCommitments, outputValues, @@ -128,22 +182,32 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // console.log('outputOwnerPublicKeys', [Bob.pubKey, Alice.pubKey]); // console.log('encryptionNonce', encryptionNonce); - expect(witness[21]).to.equal(BigInt(nullifiers[0])); - expect(witness[22]).to.equal(BigInt(nullifiers[1])); - expect(witness[23]).to.equal(proof1.root.bigInt()); + expect(witness[24]).to.equal(BigInt(nullifiers[0])); + expect(witness[25]).to.equal(BigInt(nullifiers[1])); + expect(witness[26]).to.equal(proof1.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver - const cipherText = witness.slice(1, 5); // per the encryption scheme, the output has 16 elements + const cipherText = witness.slice(1, 8); // per the encryption scheme, the output has 7 elements const recoveredKey = genEcdhSharedKey(Bob.privKey, Alice.pubKey); - const plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); - expect(plainText).to.deep.equal([20n, salt3]); + const plainText = poseidonDecrypt( + cipherText, + recoveredKey, + encryptionNonce, + 4 + ); + expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); // take the output from the proof circuit and attempt to decrypt // as the regulator const recoveredKey2 = genEcdhSharedKey(Regulator.privKey, Alice.pubKey); - const cipherText2 = witness.slice(5, 21); // next 16 elements are the cipher text for the second encryption output - const plainText2 = poseidonDecrypt(cipherText2, recoveredKey2, encryptionNonce, 14); + const cipherText2 = witness.slice(8, 24); // next 16 elements are the cipher text for the second encryption output + const plainText2 = poseidonDecrypt( + cipherText2, + recoveredKey2, + encryptionNonce, + 14 + ); expect(plainText2).to.deep.equal([ Alice.pubKey[0], // input owner public key Alice.pubKey[1], @@ -168,25 +232,44 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const inputCommitments = [input1, 0]; // create the nullifiers for the inputs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); const nullifiers = [nullifier1, 0]; // calculate the root of the SMT await smtAlice.add(input1, input1); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH + ); const proof2 = await smtAlice.generateCircomVerifierProof(0, ZERO_HASH); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); const salt4 = newSalt(); - const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...Alice.pubKey]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt4, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); @@ -202,7 +285,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re inputSalts: [salt1, 0], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 0], outputCommitments, outputValues, @@ -226,22 +312,32 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // console.log('outputOwnerPublicKeys', [receiver.pubKey, sender.pubKey]); // console.log('encryptionNonce', encryptionNonce); - expect(witness[21]).to.equal(BigInt(nullifiers[0])); - expect(witness[22]).to.equal(BigInt(nullifiers[1])); - expect(witness[23]).to.equal(proof1.root.bigInt()); + expect(witness[24]).to.equal(BigInt(nullifiers[0])); + expect(witness[25]).to.equal(BigInt(nullifiers[1])); + expect(witness[26]).to.equal(proof1.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver - const cipherText = witness.slice(1, 5); // first 4 elements are the cipher text for the first encryption output + const cipherText = witness.slice(1, 8); // first 7 elements are the cipher text for the first encryption output const recoveredKey = genEcdhSharedKey(Bob.privKey, Alice.pubKey); - const plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); - expect(plainText).to.deep.equal([20n, salt3]); + const plainText = poseidonDecrypt( + cipherText, + recoveredKey, + encryptionNonce, + 4 + ); + expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); // take the output from the proof circuit and attempt to decrypt // as the regulator const recoveredKey2 = genEcdhSharedKey(Regulator.privKey, Alice.pubKey); - const cipherText2 = witness.slice(5, 21); // next 16 elements are the cipher text for the second encryption output - const plainText2 = poseidonDecrypt(cipherText2, recoveredKey2, encryptionNonce, 14); + const cipherText2 = witness.slice(8, 24); // next 16 elements are the cipher text for the second encryption output + const plainText2 = poseidonDecrypt( + cipherText2, + recoveredKey2, + encryptionNonce, + 14 + ); expect(plainText2).to.deep.equal([ Alice.pubKey[0], Alice.pubKey[1], @@ -266,14 +362,30 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the input UTXOs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -281,13 +393,27 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); - const output2 = poseidonHash([BigInt(outputValues[1]), salt3, ...Alice.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt3, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); @@ -305,7 +431,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], outputCommitments, outputValues, @@ -321,6 +450,6 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re } // console.log(err); expect(err).to.match(/Error in template CheckSum_161 line: 44/); - expect(err).to.match(/Error in template Zeto_264 line: 107/); + expect(err).to.match(/Error in template Zeto_264 line: 113/); }); }); From 11b9a09fdc6ed040400fe77d761385038091fe54 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Thu, 26 Sep 2024 14:50:47 +0100 Subject: [PATCH 07/24] fixing gen command Signed-off-by: Chengxuan Xing --- zkp/circuits/gen.js | 45 +++++++++++++++++++++++++++++++++++++++------ zkp/js/README.md | 1 + 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/zkp/circuits/gen.js b/zkp/circuits/gen.js index b3fb1dd..9ebd25b 100644 --- a/zkp/circuits/gen.js +++ b/zkp/circuits/gen.js @@ -5,7 +5,39 @@ const { promisify } = require('util'); const axios = require('axios'); const yargs = require('yargs/yargs'); const { hideBin } = require('yargs/helpers'); -const argv = yargs(hideBin(process.argv)).argv; +const argv = yargs(hideBin(process.argv)) + .option('c', { + alias: 'circuit', + describe: 'Specify a single circuit to build', + type: 'string', + }) + .option('v', { + alias: 'verbose', + describe: 'Enable verbose mode', + type: 'boolean', + default: false, + }) + .option('cp', { + alias: 'compileOnly', + describe: 'Compile only', + type: 'boolean', + default: false, + }) + .option('cr', { + alias: 'circuitsRoot', + describe: 'Specify the root folder for storing circuits compilation files', + type: 'string', + }) + .option('pk', { + alias: 'provingKeysRoot', + describe: 'Specify the root folder for storing generated proving keys', + type: 'string', + }) + .option('pt', { + alias: 'ptauDownloadPath', + describe: 'Specify the root folder for storing downloaded PTAU', + type: 'string', + }).argv; const circuitsRoot = process.env.CIRCUITS_ROOT || argv.circuitsRoot; const provingKeysRoot = process.env.PROVING_KEYS_ROOT || argv.provingKeysRoot; @@ -37,6 +69,7 @@ console.log( { specificCircuits, compileOnly, + verbose, parallelLimit, circuitsRoot, provingKeysRoot, @@ -102,7 +135,7 @@ const processCircuit = async (circuit, ptau, skipSolidityGenaration) => { } log(circuit, `Compiling circuit`); - const { cmOut, cmErr } = await execAsync( + const { stdout: cmOut, stderr: cmErr } = await execAsync( `circom ${circomInput} --output ${circuitsRoot} --sym --wasm` ); if (verbose) { @@ -117,7 +150,7 @@ const processCircuit = async (circuit, ptau, skipSolidityGenaration) => { return; } - const { ctOut, ctErr } = await execAsync( + const { stdout: ctOut, stderr: ctErr } = await execAsync( `circom ${circomInput} --output ${provingKeysRoot} --r1cs` ); if (verbose) { @@ -130,7 +163,7 @@ const processCircuit = async (circuit, ptau, skipSolidityGenaration) => { } log(circuit, `Generating test proving key with ${ptau}`); - const { pkOut, pkErr } = await execAsync( + const { stdout: pkOut, stderr: pkErr } = await execAsync( `npx snarkjs groth16 setup ${path.join( provingKeysRoot, `${circuit}.r1cs` @@ -145,7 +178,7 @@ const processCircuit = async (circuit, ptau, skipSolidityGenaration) => { } } log(circuit, `Exporting verification key`); - const { vkOut, vkErr } = await execAsync( + const { stdout: vkOut, stderr: vkErr } = await execAsync( `npx snarkjs zkey export verificationkey ${zkeyOutput} ${path.join( provingKeysRoot, `${circuit}-vkey.json` @@ -173,7 +206,7 @@ const processCircuit = async (circuit, ptau, skipSolidityGenaration) => { 'lib', `verifier_${circuit}.sol` ); - const { svOut, svErr } = await execAsync( + const { stdout: svOut, stderr: svErr } = await execAsync( `npx snarkjs zkey export solidityverifier ${zkeyOutput} ${solidityFile}` ); if (verbose) { diff --git a/zkp/js/README.md b/zkp/js/README.md index 86bdaf5..d2bd54d 100644 --- a/zkp/js/README.md +++ b/zkp/js/README.md @@ -39,6 +39,7 @@ npm i npm run gen ``` **run `npm run gen -- -c $circuit` for developing a single circuit** + **run `npm run gen -- -v` to show details outputs of each command** **use `GEN_CONCURRENCY` to control how many circuits to be processed in parallel, default to 10** > Refer to [generation script explanation](#generation-script-explanation) for what the script does From 20d302d4b0ab827732a3b766f8ef8937b84b64ba Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Thu, 26 Sep 2024 14:57:01 +0100 Subject: [PATCH 08/24] change ptau download folder for easy cleanup Signed-off-by: Chengxuan Xing --- zkp/js/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zkp/js/README.md b/zkp/js/README.md index d2bd54d..4d24e7f 100644 --- a/zkp/js/README.md +++ b/zkp/js/README.md @@ -31,7 +31,7 @@ npm i ```console export CIRCUITS_ROOT="$HOME/circuits" export PROVING_KEYS_ROOT="$HOME/proving-keys" - export PTAU_DOWNLOAD_PATH="$HOME/Downloads" + export PTAU_DOWNLOAD_PATH="$HOME/ptaus" mkdir -p $PROVING_KEYS_ROOT $PTAU_DOWNLOAD_PATH $CIRCUITS_ROOT ``` - run the generation script for **ALL** circuits From c629bd7474c61411ea38141b8eb6800ca64a42ff Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Thu, 26 Sep 2024 16:35:33 +0100 Subject: [PATCH 09/24] fixing cloneable contract Signed-off-by: Chengxuan Xing --- solidity/contracts/factory.sol | 1 - solidity/ignition/modules/zeto_anon.ts | 6 +- solidity/ignition/modules/zeto_anon_enc.ts | 6 +- .../modules/zeto_anon_enc_nullifier.ts | 9 +- .../modules/zeto_anon_enc_nullifier_kyc.ts | 9 +- ...zeto_anon_enc_nullifier_non_repudiation.ts | 6 +- .../ignition/modules/zeto_anon_nullifier.ts | 6 +- .../modules/zeto_anon_nullifier_kyc.ts | 9 +- solidity/scripts/deploy_cloneable.ts | 16 +- ...to_anon_enc_nullifier_kyc_cost_analysis.ts | 165 +++++++++--------- solidity/test/lib/deploy.ts | 6 +- zkp/circuits/gen.js | 2 +- 12 files changed, 121 insertions(+), 120 deletions(-) diff --git a/solidity/contracts/factory.sol b/solidity/contracts/factory.sol index 533c93f..53fded3 100644 --- a/solidity/contracts/factory.sol +++ b/solidity/contracts/factory.sol @@ -53,7 +53,6 @@ contract ZetoTokenFactory is Ownable { ); // the depositVerifier and withdrawVerifier are optional // for the non-fungible token implementations - // TODO batchVerifier to be implemented for non-fungible token implementations[name] = implementation; } diff --git a/solidity/ignition/modules/zeto_anon.ts b/solidity/ignition/modules/zeto_anon.ts index 94e7702..efbb0ae 100644 --- a/solidity/ignition/modules/zeto_anon.ts +++ b/solidity/ignition/modules/zeto_anon.ts @@ -23,13 +23,13 @@ const VerifierModule = buildModule('Groth16Verifier_Anon', (m) => { }); const BatchVerifierModule = buildModule('Groth16Verifier_AnonBatch', (m) => { - const batchVerifier = m.contract('Groth16Verifier_AnonBatch', []); - return { batchVerifier }; + const verifier = m.contract('Groth16Verifier_AnonBatch', []); + return { verifier }; }); export default buildModule('Zeto_Anon', (m) => { const { verifier } = m.useModule(VerifierModule); - const { batchVerifier } = m.useModule(BatchVerifierModule); + const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule(WithdrawVerifierModule); diff --git a/solidity/ignition/modules/zeto_anon_enc.ts b/solidity/ignition/modules/zeto_anon_enc.ts index 350ad0a..6a0ea63 100644 --- a/solidity/ignition/modules/zeto_anon_enc.ts +++ b/solidity/ignition/modules/zeto_anon_enc.ts @@ -23,13 +23,13 @@ const VerifierModule = buildModule('Groth16Verifier_AnonEnc', (m) => { }); const BatchVerifierModule = buildModule('Groth16Verifier_AnonEncBatch', (m) => { - const batchVerifier = m.contract('Groth16Verifier_AnonEncBatch', []); - return { batchVerifier }; + const verifier = m.contract('Groth16Verifier_AnonEncBatch', []); + return { verifier }; }); export default buildModule('Zeto_AnonEnc', (m) => { const { verifier } = m.useModule(VerifierModule); - const { batchVerifier } = m.useModule(BatchVerifierModule); + const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule(WithdrawVerifierModule); return { depositVerifier, withdrawVerifier, verifier, batchVerifier }; diff --git a/solidity/ignition/modules/zeto_anon_enc_nullifier.ts b/solidity/ignition/modules/zeto_anon_enc_nullifier.ts index 8bcca3e..1d2ae4c 100644 --- a/solidity/ignition/modules/zeto_anon_enc_nullifier.ts +++ b/solidity/ignition/modules/zeto_anon_enc_nullifier.ts @@ -29,18 +29,15 @@ const VerifierModule = buildModule('Groth16Verifier_AnonEncNullifier', (m) => { const BatchVerifierModule = buildModule( 'Groth16Verifier_AnonEncNullifierBatch', (m) => { - const batchVerifier = m.contract( - 'Groth16Verifier_AnonEncNullifierBatch', - [] - ); - return { batchVerifier }; + const verifier = m.contract('Groth16Verifier_AnonEncNullifierBatch', []); + return { verifier }; } ); export default buildModule('Zeto_AnonEncNullifier', (m) => { const { smtLib, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); - const { batchVerifier } = m.useModule(BatchVerifierModule); + const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule( WithdrawNullifierVerifierModule diff --git a/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts b/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts index f244fe9..c6e04bd 100644 --- a/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +++ b/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts @@ -32,18 +32,15 @@ const VerifierModule = buildModule( const BatchVerifierModule = buildModule( 'Groth16Verifier_AnonEncNullifierKycBatch', (m) => { - const batchVerifier = m.contract( - 'Groth16Verifier_AnonEncNullifierKycBatch', - [] - ); - return { batchVerifier }; + const verifier = m.contract('Groth16Verifier_AnonEncNullifierKycBatch', []); + return { verifier }; } ); export default buildModule('Zeto_AnonEncNullifierKyc', (m) => { const { smtLib, poseidon2, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); - const { batchVerifier } = m.useModule(BatchVerifierModule); + const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule( WithdrawNullifierVerifierModule diff --git a/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts b/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts index bcac005..7655983 100644 --- a/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts +++ b/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts @@ -35,18 +35,18 @@ const VerifierModule = buildModule( const BatchVerifierModule = buildModule( 'Groth16Verifier_AnonEncNullifierNonRepudiationBatch', (m) => { - const batchVerifier = m.contract( + const verifier = m.contract( 'Groth16Verifier_AnonEncNullifierNonRepudiationBatch', [] ); - return { batchVerifier }; + return { verifier }; } ); export default buildModule('Zeto_AnonEncNullifierNonRepudiation', (m) => { const { smtLib, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); - const { batchVerifier } = m.useModule(BatchVerifierModule); + const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule( WithdrawNullifierVerifierModule diff --git a/solidity/ignition/modules/zeto_anon_nullifier.ts b/solidity/ignition/modules/zeto_anon_nullifier.ts index 8c08f1e..9d68d86 100644 --- a/solidity/ignition/modules/zeto_anon_nullifier.ts +++ b/solidity/ignition/modules/zeto_anon_nullifier.ts @@ -29,15 +29,15 @@ const VerifierModule = buildModule('Groth16Verifier_AnonNullifier', (m) => { const BatchVerifierModule = buildModule( 'Groth16Verifier_AnonNullifierBatch', (m) => { - const batchVerifier = m.contract('Groth16Verifier_AnonNullifierBatch', []); - return { batchVerifier }; + const verifier = m.contract('Groth16Verifier_AnonNullifierBatch', []); + return { verifier }; } ); export default buildModule('Zeto_AnonNullifier', (m) => { const { smtLib, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); - const { batchVerifier } = m.useModule(BatchVerifierModule); + const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule( WithdrawNullifierVerifierModule diff --git a/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts b/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts index 1480714..47a7032 100644 --- a/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts +++ b/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts @@ -29,18 +29,15 @@ const VerifierModule = buildModule('Groth16Verifier_AnonNullifierKyc', (m) => { const BatchVerifierModule = buildModule( 'Groth16Verifier_AnonNullifierKycBatch', (m) => { - const batchVerifier = m.contract( - 'Groth16Verifier_AnonNullifierKycBatch', - [] - ); - return { batchVerifier }; + const verifier = m.contract('Groth16Verifier_AnonNullifierKycBatch', []); + return { verifier }; } ); export default buildModule('Zeto_AnonNullifierKyc', (m) => { const { smtLib, poseidon2, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); - const { batchVerifier } = m.useModule(BatchVerifierModule); + const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule( WithdrawNullifierVerifierModule diff --git a/solidity/scripts/deploy_cloneable.ts b/solidity/scripts/deploy_cloneable.ts index 54af872..6c6a4ef 100644 --- a/solidity/scripts/deploy_cloneable.ts +++ b/solidity/scripts/deploy_cloneable.ts @@ -1,21 +1,23 @@ -import { ethers, ignition } from "hardhat"; +import { ethers, ignition } from 'hardhat'; import erc20Module from '../ignition/modules/erc20'; -import { getLinkedContractFactory, deploy } from "./lib/common"; +import { getLinkedContractFactory, deploy } from './lib/common'; export async function deployFungible(tokenName: string) { const { erc20 } = await ignition.deploy(erc20Module); const verifiersDeployer = require(`./tokens/${tokenName}`); - const { deployer, args, libraries } = await verifiersDeployer.deployDependencies(); + const { deployer, args, libraries } = + await verifiersDeployer.deployDependencies(); let zetoFactory; if (libraries) { zetoFactory = await getLinkedContractFactory(tokenName, libraries); } else { - zetoFactory = await ethers.getContractFactory(tokenName) + zetoFactory = await ethers.getContractFactory(tokenName); } const zetoImpl: any = await zetoFactory.deploy(); await zetoImpl.waitForDeployment(); + // console.log(args); await zetoImpl.connect(deployer).initialize(...args); const tx3 = await zetoImpl.connect(deployer).setERC20(erc20.target); @@ -36,7 +38,7 @@ export async function deployNonFungible(tokenName: string) { if (libraries) { zetoFactory = await getLinkedContractFactory(tokenName, libraries); } else { - zetoFactory = await ethers.getContractFactory(tokenName) + zetoFactory = await ethers.getContractFactory(tokenName); } const zetoImpl: any = await zetoFactory.deploy(); await zetoImpl.waitForDeployment(); @@ -54,7 +56,7 @@ deploy(deployFungible, deployNonFungible) } process.exit(0); }) - .catch(error => { + .catch((error) => { console.error(error); process.exit(1); - }); \ No newline at end of file + }); diff --git a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts index 6db235c..8a13a60 100644 --- a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts +++ b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts @@ -44,9 +44,10 @@ import { } from '../utils'; import { deployZeto } from '../lib/deploy'; -const TOTAL_AMOUNT = parseInt(process.env.TOTAL_ROUNDS || '1000'); +const TOTAL_AMOUNT = parseInt(process.env.TOTAL_ROUNDS || '40'); const TX_CONCURRENCY = parseInt(process.env.TX_CONCURRENCY || '30'); -const UTXO_PER_TX = parseInt(process.env.UTXO_PER_TX || '2'); + +const UTXO_PER_TX = 10; describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity using nullifiers and encryption with KYC', function () { let deployer: Signer; @@ -55,9 +56,8 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin let Charlie: User; let erc20: any; let zeto: any; - const atMostBatchedAmount = Math.floor(TOTAL_AMOUNT / UTXO_PER_TX); - const atLeastBatchedAmount = - atMostBatchedAmount + (TOTAL_AMOUNT % UTXO_PER_TX); + const atMostHalfAmount = Math.floor(TOTAL_AMOUNT / 2); + const atLeastHalfAmount = atMostHalfAmount + (TOTAL_AMOUNT % 2); let unspentAliceUTXOs: UTXO[] = []; let unspentBobUTXOs: UTXO[] = []; let mintGasCostHistory: number[] = []; @@ -130,33 +130,33 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20 .connect(deployer) - .mint(Alice.ethAddress, atMostBatchedAmount); // mint to alice the amount of token that can be deposited + .mint(Alice.ethAddress, atMostHalfAmount); // mint to alice the amount of token that can be deposited await tx.wait(); const endingBalance = await erc20.balanceOf(Alice.ethAddress); - expect(endingBalance - startingBalance).to.be.equal(atMostBatchedAmount); + expect(endingBalance - startingBalance).to.be.equal(atMostHalfAmount); console.log( - `ERC20 successfully minted ${atMostBatchedAmount} to Alice for deposit` + `ERC20 successfully minted ${atMostHalfAmount} to Alice for deposit` ); const tx1 = await erc20 .connect(Alice.signer) - .approve(zeto.target, atMostBatchedAmount); + .approve(zeto.target, atMostHalfAmount); await tx1.wait(); const startingBalanceDep = await erc20.balanceOf(zeto.target); const txDep = await erc20 .connect(deployer) - .mint(zeto.target, atLeastBatchedAmount); // mint to zeto contract the amount of token that can be minted + .mint(zeto.target, atLeastHalfAmount); // mint to zeto contract the amount of token that can be minted await txDep.wait(); const endingBalanceDep = await erc20.balanceOf(zeto.target); expect(endingBalanceDep - startingBalanceDep).to.be.equal( - atLeastBatchedAmount + atLeastHalfAmount ); }); - it(`Alice deposit ${atMostBatchedAmount} token`, async function () { + it(`Alice deposit ${atMostHalfAmount} token`, async function () { let promises = []; - for (let i = 0; i < atMostBatchedAmount; i++) { + for (let i = 0; i < atMostHalfAmount; i++) { promises.push( (async () => { const utxoSingle = newUTXO(1, Alice); @@ -193,42 +193,34 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ); }).timeout(6000000000000); - it(`Zeto mint ${ - atMostBatchedAmount + (TOTAL_AMOUNT % 2) - } token to Alice in ${ - Math.floor(atLeastBatchedAmount / 2) + (atLeastBatchedAmount % 2) + it(`Zeto mint ${atMostHalfAmount + (TOTAL_AMOUNT % 2)} token to Alice in ${ + Math.floor(atLeastHalfAmount / UTXO_PER_TX) + + (atLeastHalfAmount % 2 !== 0 ? 1 : 0) } txs`, async function () { const mintRounds = - Math.floor(atLeastBatchedAmount / 2) + (atLeastBatchedAmount % 2); + Math.floor(atLeastHalfAmount / UTXO_PER_TX) + + (atLeastHalfAmount % 2 !== 0 ? 1 : 0); let promises = []; for (let i = 0; i < mintRounds; i++) { promises.push( (async () => { - const utxo1 = newUTXO(1, Alice); - let utxo2 = newUTXO(1, Alice); - - if (i === mintRounds - 1 && atLeastBatchedAmount % 2 === 1) { - utxo2 = newUTXO(0, Alice); // odd number + const mintUTXOs = []; + for (let j = 0; j < UTXO_PER_TX; j++) { + if ( + i !== mintRounds - 1 || + atLeastHalfAmount % 2 === 0 || + j < atLeastHalfAmount % 2 + ) { + const _new_utxo = newUTXO(1, Alice); + mintUTXOs.push(_new_utxo); + + await smtAlice.add(_new_utxo.hash, _new_utxo.hash); + await smtBob.add(_new_utxo.hash, _new_utxo.hash); + unspentAliceUTXOs.push(_new_utxo); + } } - const result1 = await doMint( - zeto, - deployer, - [utxo1, utxo2], - mintGasCostHistory - ); - const mintEvents = parseUTXOEvents(zeto, result1); - const [_utxo1, _utxo2] = mintEvents[0].outputs; - - // Add UTXOs to the sets - await smtAlice.add(_utxo1, _utxo1); - await smtBob.add(_utxo1, _utxo1); - await smtAlice.add(_utxo2, _utxo2); - await smtBob.add(_utxo2, _utxo2); - - // Save unspent UTXOs - unspentAliceUTXOs.push(utxo1); - unspentAliceUTXOs.push(utxo2); + await doMint(zeto, deployer, mintUTXOs, mintGasCostHistory); })() ); @@ -249,8 +241,19 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ); }).timeout(6000000000000); - it(`Alice transfer ${TOTAL_AMOUNT} tokens to Bob in ${atLeastBatchedAmount} txs`, async function () { - const totalTxs = Math.floor(unspentAliceUTXOs.length / 2); + it(`Alice transfer ${TOTAL_AMOUNT} tokens to Bob in ${ + Math.floor(unspentAliceUTXOs.length / UTXO_PER_TX) + + (unspentAliceUTXOs.length % UTXO_PER_TX) !== + 0 + ? 1 + : 0 + } txs`, async function () { + const totalTxs = + Math.floor(unspentAliceUTXOs.length / UTXO_PER_TX) + + (unspentAliceUTXOs.length % UTXO_PER_TX) !== + 0 + ? 1 + : 0; const utxosRoot = await smtAlice.root(); // get the root before all transfer and use it for all the proofs let promises = []; // Alice generates inclusion proofs for the identities in the transaction @@ -265,57 +268,61 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ); const identityMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) - proof4.siblings.map((s) => s.bigInt()), // identity proof for the 1st owner of the output UTXO (Bob) - proof4.siblings.map((s) => s.bigInt()), // identity proof for the 2nd owner of the output UTXO (Bob) ]; + const batchSize = UTXO_PER_TX > 2 ? 10 : 2; + + for (let i = 0; i < batchSize; i++) { + identityMerkleProofs.push(proof4.siblings.map((s) => s.bigInt())); // identity proof for the output utxos (Bob) + } + for (let i = 0; i < totalTxs; i++) { promises.push( (async () => { - const utxo1 = unspentAliceUTXOs[i * 2]; - const utxo2 = unspentAliceUTXOs[i * 2 + 1]; - - const newUtxo1 = newUTXO(1, Bob); - let newUtxo2 = newUTXO(1, Bob); - if (i === totalTxs - 1 && TOTAL_AMOUNT % 2 === 1) { - // last round - newUtxo2 = newUTXO(0, Bob); // odd number + const _inUtxos = []; + const _outUtxos = []; + const _mtps = []; + const _nullifiers = []; + for (let j = 0; j < UTXO_PER_TX; j++) { + if ( + i !== totalTxs - 1 || + unspentAliceUTXOs.length % UTXO_PER_TX === 0 || + j < unspentAliceUTXOs.length % UTXO_PER_TX + ) { + const _iUtxo = unspentAliceUTXOs[i * UTXO_PER_TX + j]; + _inUtxos.push(_iUtxo); + _nullifiers.push(newNullifier(_iUtxo, Alice)); + // Alice generates inclusion proofs for the UTXOs to be spent + const inProof = await smtAlice.generateCircomVerifierProof( + _iUtxo.hash, + utxosRoot + ); + _mtps.push(inProof.siblings.map((s) => s.bigInt())); + const _oUtox = newUTXO(1, Bob); + _outUtxos.push(_oUtox); + await smtAlice.add(_oUtox.hash, _oUtox.hash); + await smtBob.add(_oUtox.hash, _oUtox.hash); + unspentBobUTXOs.push(_oUtox); + } + } + const owners = []; + for (let i = 0; i < batchSize; i++) { + owners.push(Bob); } - const nullifier1 = newNullifier(utxo1, Alice); - const nullifier2 = newNullifier(utxo2, Alice); - // Alice generates inclusion proofs for the UTXOs to be spent - const proof1 = await smtAlice.generateCircomVerifierProof( - utxo1.hash, - utxosRoot - ); - const proof2 = await smtAlice.generateCircomVerifierProof( - utxo2.hash, - utxosRoot - ); - const utxoMerkleProofs = [ - proof1.siblings.map((s) => s.bigInt()), - proof2.siblings.map((s) => s.bigInt()), - ]; // Alice transfers her UTXOs to Bob await doTransfer( Alice, - [utxo1, utxo2], - [nullifier1, nullifier2], - [newUtxo1, newUtxo2], + _inUtxos, + _nullifiers, + _outUtxos, utxosRoot.bigInt(), - utxoMerkleProofs, + _mtps, identitiesRoot.bigInt(), identityMerkleProofs, - [Bob, Bob], + owners, transferGasCostHistory ); - await smtAlice.add(newUtxo1.hash, newUtxo1.hash); - await smtBob.add(newUtxo1.hash, newUtxo1.hash); - await smtAlice.add(newUtxo2.hash, newUtxo2.hash); - await smtBob.add(newUtxo2.hash, newUtxo2.hash); - unspentBobUTXOs.push(newUtxo1); - unspentBobUTXOs.push(newUtxo2); })() ); diff --git a/solidity/test/lib/deploy.ts b/solidity/test/lib/deploy.ts index f85a955..e893726 100644 --- a/solidity/test/lib/deploy.ts +++ b/solidity/test/lib/deploy.ts @@ -52,9 +52,9 @@ export async function deployZeto(tokenName: string) { const [ deployerAddr, verifier, - batchVerifier, depositVerifier, withdrawVerifier, + batchVerifier, ] = args; // we want to test the effectiveness of the factory contract @@ -70,8 +70,10 @@ export async function deployZeto(tokenName: string) { withdrawVerifier: withdrawVerifier || '0x0000000000000000000000000000000000000000', verifier, - batchVerifier, + batchVerifier: + batchVerifier || '0x0000000000000000000000000000000000000000', }; + // console.log(implInfo); const tx1 = await factory .connect(deployer) .registerImplementation(tokenName, implInfo as any); diff --git a/zkp/circuits/gen.js b/zkp/circuits/gen.js index 9ebd25b..e96887a 100644 --- a/zkp/circuits/gen.js +++ b/zkp/circuits/gen.js @@ -45,7 +45,7 @@ const ptauDownload = process.env.PTAU_DOWNLOAD_PATH || argv.ptauDownloadPath; const specificCircuits = argv.c; const verbose = argv.v; const compileOnly = argv.compileOnly; -const parallelLimit = parseInt(process.env.GEN_CONCURRENCY, 10) || 10; // Default to compile 10 circuits in parallel +const parallelLimit = parseInt(process.env.GEN_CONCURRENCY, 10) || 30; // Default to compile 30 circuits in parallel // check env vars if (!circuitsRoot) { From 30d6b1ed27464c81ac8c65d2b52727b00b989019 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Thu, 26 Sep 2024 16:36:49 +0100 Subject: [PATCH 10/24] revert gas cost test changes Signed-off-by: Chengxuan Xing --- ...to_anon_enc_nullifier_kyc_cost_analysis.ts | 176 ++++++++---------- 1 file changed, 81 insertions(+), 95 deletions(-) diff --git a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts index 8a13a60..8cf2e9c 100644 --- a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts +++ b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts @@ -44,11 +44,9 @@ import { } from '../utils'; import { deployZeto } from '../lib/deploy'; -const TOTAL_AMOUNT = parseInt(process.env.TOTAL_ROUNDS || '40'); +const TOTAL_AMOUNT = parseInt(process.env.TOTAL_ROUNDS || '1000'); const TX_CONCURRENCY = parseInt(process.env.TX_CONCURRENCY || '30'); -const UTXO_PER_TX = 10; - describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity using nullifiers and encryption with KYC', function () { let deployer: Signer; let Alice: User; @@ -194,33 +192,39 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin }).timeout(6000000000000); it(`Zeto mint ${atMostHalfAmount + (TOTAL_AMOUNT % 2)} token to Alice in ${ - Math.floor(atLeastHalfAmount / UTXO_PER_TX) + - (atLeastHalfAmount % 2 !== 0 ? 1 : 0) + Math.floor(atLeastHalfAmount / 2) + (atLeastHalfAmount % 2) } txs`, async function () { const mintRounds = - Math.floor(atLeastHalfAmount / UTXO_PER_TX) + - (atLeastHalfAmount % 2 !== 0 ? 1 : 0); + Math.floor(atLeastHalfAmount / 2) + (atLeastHalfAmount % 2); let promises = []; for (let i = 0; i < mintRounds; i++) { promises.push( (async () => { - const mintUTXOs = []; - for (let j = 0; j < UTXO_PER_TX; j++) { - if ( - i !== mintRounds - 1 || - atLeastHalfAmount % 2 === 0 || - j < atLeastHalfAmount % 2 - ) { - const _new_utxo = newUTXO(1, Alice); - mintUTXOs.push(_new_utxo); - - await smtAlice.add(_new_utxo.hash, _new_utxo.hash); - await smtBob.add(_new_utxo.hash, _new_utxo.hash); - unspentAliceUTXOs.push(_new_utxo); - } + const utxo1 = newUTXO(1, Alice); + let utxo2 = newUTXO(1, Alice); + + if (i === mintRounds - 1 && atLeastHalfAmount % 2 === 1) { + utxo2 = newUTXO(0, Alice); // odd number } - await doMint(zeto, deployer, mintUTXOs, mintGasCostHistory); + const result1 = await doMint( + zeto, + deployer, + [utxo1, utxo2], + mintGasCostHistory + ); + const mintEvents = parseUTXOEvents(zeto, result1); + const [_utxo1, _utxo2] = mintEvents[0].outputs; + + // Add UTXOs to the sets + await smtAlice.add(_utxo1, _utxo1); + await smtBob.add(_utxo1, _utxo1); + await smtAlice.add(_utxo2, _utxo2); + await smtBob.add(_utxo2, _utxo2); + + // Save unspent UTXOs + unspentAliceUTXOs.push(utxo1); + unspentAliceUTXOs.push(utxo2); })() ); @@ -241,19 +245,8 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ); }).timeout(6000000000000); - it(`Alice transfer ${TOTAL_AMOUNT} tokens to Bob in ${ - Math.floor(unspentAliceUTXOs.length / UTXO_PER_TX) + - (unspentAliceUTXOs.length % UTXO_PER_TX) !== - 0 - ? 1 - : 0 - } txs`, async function () { - const totalTxs = - Math.floor(unspentAliceUTXOs.length / UTXO_PER_TX) + - (unspentAliceUTXOs.length % UTXO_PER_TX) !== - 0 - ? 1 - : 0; + it(`Alice transfer ${TOTAL_AMOUNT} tokens to Bob in ${atLeastHalfAmount} txs`, async function () { + const totalTxs = Math.floor(unspentAliceUTXOs.length / 2); const utxosRoot = await smtAlice.root(); // get the root before all transfer and use it for all the proofs let promises = []; // Alice generates inclusion proofs for the identities in the transaction @@ -268,61 +261,57 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ); const identityMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) + proof4.siblings.map((s) => s.bigInt()), // identity proof for the 1st owner of the output UTXO (Bob) + proof4.siblings.map((s) => s.bigInt()), // identity proof for the 2nd owner of the output UTXO (Bob) ]; - const batchSize = UTXO_PER_TX > 2 ? 10 : 2; - - for (let i = 0; i < batchSize; i++) { - identityMerkleProofs.push(proof4.siblings.map((s) => s.bigInt())); // identity proof for the output utxos (Bob) - } - for (let i = 0; i < totalTxs; i++) { promises.push( (async () => { - const _inUtxos = []; - const _outUtxos = []; - const _mtps = []; - const _nullifiers = []; - for (let j = 0; j < UTXO_PER_TX; j++) { - if ( - i !== totalTxs - 1 || - unspentAliceUTXOs.length % UTXO_PER_TX === 0 || - j < unspentAliceUTXOs.length % UTXO_PER_TX - ) { - const _iUtxo = unspentAliceUTXOs[i * UTXO_PER_TX + j]; - _inUtxos.push(_iUtxo); - _nullifiers.push(newNullifier(_iUtxo, Alice)); - // Alice generates inclusion proofs for the UTXOs to be spent - const inProof = await smtAlice.generateCircomVerifierProof( - _iUtxo.hash, - utxosRoot - ); - _mtps.push(inProof.siblings.map((s) => s.bigInt())); - const _oUtox = newUTXO(1, Bob); - _outUtxos.push(_oUtox); - await smtAlice.add(_oUtox.hash, _oUtox.hash); - await smtBob.add(_oUtox.hash, _oUtox.hash); - unspentBobUTXOs.push(_oUtox); - } - } - const owners = []; - for (let i = 0; i < batchSize; i++) { - owners.push(Bob); + const utxo1 = unspentAliceUTXOs[i * 2]; + const utxo2 = unspentAliceUTXOs[i * 2 + 1]; + + const newUtxo1 = newUTXO(1, Bob); + let newUtxo2 = newUTXO(1, Bob); + if (i === totalTxs - 1 && TOTAL_AMOUNT % 2 === 1) { + // last round + newUtxo2 = newUTXO(0, Bob); // odd number } + const nullifier1 = newNullifier(utxo1, Alice); + const nullifier2 = newNullifier(utxo2, Alice); + // Alice generates inclusion proofs for the UTXOs to be spent + const proof1 = await smtAlice.generateCircomVerifierProof( + utxo1.hash, + utxosRoot + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + utxo2.hash, + utxosRoot + ); + const utxoMerkleProofs = [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ]; // Alice transfers her UTXOs to Bob await doTransfer( Alice, - _inUtxos, - _nullifiers, - _outUtxos, + [utxo1, utxo2], + [nullifier1, nullifier2], + [newUtxo1, newUtxo2], utxosRoot.bigInt(), - _mtps, + utxoMerkleProofs, identitiesRoot.bigInt(), identityMerkleProofs, - owners, + [Bob, Bob], transferGasCostHistory ); + await smtAlice.add(newUtxo1.hash, newUtxo1.hash); + await smtBob.add(newUtxo1.hash, newUtxo1.hash); + await smtAlice.add(newUtxo2.hash, newUtxo2.hash); + await smtBob.add(newUtxo2.hash, newUtxo2.hash); + unspentBobUTXOs.push(newUtxo1); + unspentBobUTXOs.push(newUtxo2); })() ); @@ -420,8 +409,8 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin owners: User[], gasHistories: number[] ) { - let nullifiers: BigNumberish[]; - let outputCommitments: BigNumberish[]; + let nullifiers: [BigNumberish, BigNumberish]; + let outputCommitments: [BigNumberish, BigNumberish]; let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; @@ -459,14 +448,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin gasHistories.push(txResult?.gasUsed); } // add the clear text value so that it can be used by tests to compare with the decrypted value - return { - txResult, - expectedPlainText: outputs.reduce((acc, o, i) => { - acc.push(BigInt(o.value || 0n) as BigNumberish); - acc.push((o.salt || 0n) as BigNumberish); - return acc; - }, [] as BigNumberish[]), - }; + return { txResult, plainTextSalt: outputs[0].salt }; } async function prepareProof( @@ -484,18 +466,22 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin BigNumberish, BigNumberish ]; - const inputCommitments: BigNumberish[] = inputs.map( + const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( (input) => input.hash - ) as BigNumberish[]; + ) as [BigNumberish, BigNumberish]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: BigNumberish[] = outputs.map( + const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( (output) => output.hash - ) as BigNumberish[]; + ) as [BigNumberish, BigNumberish]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: BigNumberish[][] = owners.map( - (owner) => owner.babyJubPublicKey - ) as BigNumberish[][]; + const outputOwnerPublicKeys: [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ] = owners.map((owner) => owner.babyJubPublicKey) as [ + [BigNumberish, BigNumberish], + [BigNumberish, BigNumberish] + ]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, @@ -509,7 +495,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin inputSalts, inputOwnerPrivateKey: signer.formattedPrivateKey, utxosRoot, - enabled: nullifiers.map((n) => (n !== 0n ? 1 : 0)), + enabled: [nullifiers[0] !== 0n ? 1 : 0, nullifiers[1] !== 0n ? 1 : 0], utxosMerkleProof, identitiesRoot, identitiesMerkleProof, @@ -549,8 +535,8 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin async function sendTx( signer: User, - nullifiers: BigNumberish[], - outputCommitments: BigNumberish[], + nullifiers: [BigNumberish, BigNumberish], + outputCommitments: [BigNumberish, BigNumberish], root: BigNumberish, encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, From 1b4461fd3ee5f8e6dc52820679b21a4e2481eff0 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Fri, 27 Sep 2024 07:24:25 +0100 Subject: [PATCH 11/24] fixing golang e2e Signed-off-by: Chengxuan Xing --- go-sdk/integration-test/e2e_test.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/go-sdk/integration-test/e2e_test.go b/go-sdk/integration-test/e2e_test.go index 9df7de7..94d951f 100644 --- a/go-sdk/integration-test/e2e_test.go +++ b/go-sdk/integration-test/e2e_test.go @@ -242,12 +242,12 @@ func (s *E2ETestSuite) TestZeto_2_SuccessfulProving() { assert.Equal(s.T(), 3, len(proof.Proof.A)) assert.Equal(s.T(), 3, len(proof.Proof.B)) assert.Equal(s.T(), 3, len(proof.Proof.C)) - assert.Equal(s.T(), 9, len(proof.PubSignals)) + assert.Equal(s.T(), 12, len(proof.PubSignals)) // the receiver would be able to get the encrypted values and salts // from the transaction events - encryptedValues := make([]*big.Int, 4) - for i := 0; i < 4; i++ { + encryptedValues := make([]*big.Int, 7) + for i := 0; i < 7; i++ { v, ok := new(big.Int).SetString(proof.PubSignals[i], 10) assert.True(s.T(), ok) encryptedValues[i] = v @@ -257,11 +257,14 @@ func (s *E2ETestSuite) TestZeto_2_SuccessfulProving() { // for the first output. decrypt using the receiver's private key and compare with // the UTXO hash secret := crypto.GenerateECDHSharedSecret(receiver.PrivateKey, sender.PublicKey) - decrypted, err := crypto.PoseidonDecrypt(encryptedValues, []*big.Int{secret.X, secret.Y}, encryptionNonce, 2) + decrypted, err := crypto.PoseidonDecrypt(encryptedValues, []*big.Int{secret.X, secret.Y}, encryptionNonce, 4) assert.NoError(s.T(), err) assert.Equal(s.T(), outputValues[0].String(), decrypted[0].String()) assert.Equal(s.T(), salt3.String(), decrypted[1].String()) + assert.Equal(s.T(), outputValues[1].String(), decrypted[2].String()) + assert.Equal(s.T(), salt4.String(), decrypted[3].String()) + // as the receiver, to check if the decryption was successful, we hash the decrypted // value and salt and compare with the output commitment calculatedHash, err := poseidon.Hash([]*big.Int{decrypted[0], decrypted[1], receiver.PublicKey.X, receiver.PublicKey.Y}) @@ -437,7 +440,7 @@ func (s *E2ETestSuite) TestZeto_4_SuccessfulProving() { assert.Equal(s.T(), 3, len(proof.Proof.A)) assert.Equal(s.T(), 3, len(proof.Proof.B)) assert.Equal(s.T(), 3, len(proof.Proof.C)) - assert.Equal(s.T(), 12, len(proof.PubSignals)) + assert.Equal(s.T(), 15, len(proof.PubSignals)) } func (s *E2ETestSuite) TestZeto_5_SuccessfulProving() { From 22a0cb8fe0711693c153161aafb13938a8ce53d3 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Fri, 27 Sep 2024 10:55:34 +0100 Subject: [PATCH 12/24] adding a test for go-sdk for concurrency test Signed-off-by: Chengxuan Xing --- go-sdk/integration-test/e2e_test.go | 80 +++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/go-sdk/integration-test/e2e_test.go b/go-sdk/integration-test/e2e_test.go index 94d951f..5d6d16c 100644 --- a/go-sdk/integration-test/e2e_test.go +++ b/go-sdk/integration-test/e2e_test.go @@ -499,6 +499,86 @@ func (s *E2ETestSuite) TestZeto_5_SuccessfulProving() { assert.Equal(s.T(), 3, len(proof.Proof.B)) assert.Equal(s.T(), 3, len(proof.Proof.C)) assert.Equal(s.T(), 2, len(proof.PubSignals)) + +} + +func (s *E2ETestSuite) TestZeto_5_SuccessfulProvingWithConcurrency() { + concurrency := 10 + resultChan := make(chan struct{}, concurrency) + + for i := 0; i < concurrency; i++ { + index := i + go func() { + defer func() { + resultChan <- struct{}{} + }() + calc, provingKey, err := loadCircuit("nf_anon") + assert.NoError(s.T(), err) + assert.NotNil(s.T(), calc) + + sender := testutils.NewKeypair() + receiver := testutils.NewKeypair() + + tokenId := big.NewInt(int64(index + 1)) // ensure different token uris for each run + tokenUri, err := utxo.HashTokenUri("https://example.com/token/" + tokenId.String()) + assert.NoError(s.T(), err) + + salt1 := crypto.NewSalt() + input1, err := poseidon.Hash([]*big.Int{tokenId, tokenUri, salt1, sender.PublicKey.X, sender.PublicKey.Y}) + assert.NoError(s.T(), err) + + salt3 := crypto.NewSalt() + output1, err := poseidon.Hash([]*big.Int{tokenId, tokenUri, salt3, receiver.PublicKey.X, receiver.PublicKey.Y}) + assert.NoError(s.T(), err) + + witnessInputs := map[string]interface{}{ + "tokenIds": []*big.Int{tokenId}, + "tokenUris": []*big.Int{tokenUri}, + "inputCommitments": []*big.Int{input1}, + "inputSalts": []*big.Int{salt1}, + "inputOwnerPrivateKey": sender.PrivateKeyBigInt, + "outputCommitments": []*big.Int{output1}, + "outputSalts": []*big.Int{salt3}, + "outputOwnerPublicKeys": [][]*big.Int{{receiver.PublicKey.X, receiver.PublicKey.Y}}, + } + // calculate the witness object for checking correctness + witness, err := calc.CalculateWitness(witnessInputs, true) + assert.NoError(s.T(), err) + assert.NotNil(s.T(), witness) + + assert.Equal(s.T(), 0, witness[0].Cmp(big.NewInt(1))) + assert.Equal(s.T(), 0, witness[1].Cmp(input1)) + assert.Equal(s.T(), 0, witness[2].Cmp(output1)) + assert.Equal(s.T(), 0, witness[3].Cmp(tokenId)) + assert.Equal(s.T(), 0, witness[4].Cmp(tokenUri)) + + // generate the witness binary to feed into the prover + startTime := time.Now() + witnessBin, err := calc.CalculateWTNSBin(witnessInputs, true) + assert.NoError(s.T(), err) + assert.NotNil(s.T(), witnessBin) + + proof, err := prover.Groth16Prover(provingKey, witnessBin) + elapsedTime := time.Since(startTime) + fmt.Printf("Proving time: %s\n", elapsedTime) + fmt.Printf("token uri from witness: %s\n", witness[3]) + assert.NoError(s.T(), err) + assert.Equal(s.T(), 3, len(proof.Proof.A)) + assert.Equal(s.T(), 3, len(proof.Proof.B)) + assert.Equal(s.T(), 3, len(proof.Proof.C)) + assert.Equal(s.T(), 2, len(proof.PubSignals)) + + }() + } + count := 0 + for { + <-resultChan + count++ + if count == concurrency { + break + } + } + } func (s *E2ETestSuite) TestZeto_6_SuccessfulProving() { From ccd8f7bc12feeb17e544d8ce4f31189153a38590 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Fri, 27 Sep 2024 14:33:58 +0100 Subject: [PATCH 13/24] use an ephemeral private key to generate ECDH key Signed-off-by: Chengxuan Xing --- .../lib/interfaces/izeto_encrypted.sol | 1 + solidity/contracts/lib/verifier_anon_enc.sol | 68 ++- .../contracts/lib/verifier_anon_enc_batch.sol | 192 +++---- .../lib/verifier_anon_enc_nullifier.sol | 80 +-- .../lib/verifier_anon_enc_nullifier_batch.sol | 236 +++++---- .../lib/verifier_anon_enc_nullifier_kyc.sol | 84 +-- .../verifier_anon_enc_nullifier_kyc_batch.sol | 240 +++++---- ...ier_anon_enc_nullifier_non_repudiation.sol | 152 +++--- ...on_enc_nullifier_non_repudiation_batch.sol | 500 +++++++++--------- solidity/contracts/zeto_anon_enc.sol | 14 +- .../contracts/zeto_anon_enc_nullifier.sol | 14 +- .../contracts/zeto_anon_enc_nullifier_kyc.sol | 14 +- ...eto_anon_enc_nullifier_non_repudiation.sol | 15 +- ...to_anon_enc_nullifier_kyc_cost_analysis.ts | 1 + solidity/test/lib/utils.ts | 6 +- solidity/test/zeto_anon_enc.ts | 35 +- solidity/test/zeto_anon_enc_nullifier.ts | 40 +- solidity/test/zeto_anon_enc_nullifier_kyc.ts | 39 +- ...zeto_anon_enc_nullifier_non_repudiation.ts | 48 +- zkp/circuits/basetokens/anon_enc_base.circom | 12 +- .../basetokens/anon_enc_nullifier_base.circom | 13 +- .../anon_enc_nullifier_kyc_base.circom | 13 +- ..._enc_nullifier_non_repudiation_base.circom | 19 +- zkp/js/test/anon_enc.js | 35 +- zkp/js/test/anon_enc_nullifier.js | 25 +- zkp/js/test/anon_enc_nullifier_kyc.js | 16 +- .../anon_enc_nullifier_non_repudiation.js | 40 +- 27 files changed, 1111 insertions(+), 841 deletions(-) diff --git a/solidity/contracts/lib/interfaces/izeto_encrypted.sol b/solidity/contracts/lib/interfaces/izeto_encrypted.sol index 798e740..a3627df 100644 --- a/solidity/contracts/lib/interfaces/izeto_encrypted.sol +++ b/solidity/contracts/lib/interfaces/izeto_encrypted.sol @@ -22,6 +22,7 @@ interface IZetoEncrypted is IZetoBase { uint256[] inputs, uint256[] outputs, uint256 encryptionNonce, + uint256[2] ecdhPublicKey, uint256[] encryptedValues, address indexed submitter, bytes data diff --git a/solidity/contracts/lib/verifier_anon_enc.sol b/solidity/contracts/lib/verifier_anon_enc.sol index 4bfdbc2..98778e8 100644 --- a/solidity/contracts/lib/verifier_anon_enc.sol +++ b/solidity/contracts/lib/verifier_anon_enc.sol @@ -43,44 +43,50 @@ contract Groth16Verifier_AnonEnc { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 15520848054661511274945320545667385548601069271438999324366330478358568711164; - uint256 constant IC0y = 21157706785088596766640646951118458870358425037843657358834285142096534241567; + uint256 constant IC0x = 19738436812852754138717560068465488575650466935897866784235851363188283681055; + uint256 constant IC0y = 20276710811895297863478242769429631408343958016139841779904405850032032045827; - uint256 constant IC1x = 8426080128821983408742228948574443657002575937683949448708665466581838540418; - uint256 constant IC1y = 2961289054807278996124904978204815851370317973256653070013442261730110386382; + uint256 constant IC1x = 12004009131111215646999120161880487388502192413854826301881504538550543450502; + uint256 constant IC1y = 5034584841161295539588326933292197987831538710023697101766083868565246659218; - uint256 constant IC2x = 16846214183034172122880181483898983231574288374891417794445456783443571203454; - uint256 constant IC2y = 4795943127049292018241039074381217225273912831887247849230603976368095834324; + uint256 constant IC2x = 11744025093458990804167237970026144007871637967897648400215565295861061328335; + uint256 constant IC2y = 2248857409928028413263909113804746755226258898653477806239821342300643857095; - uint256 constant IC3x = 10240231648004351535934471246939085350017538992419843720960233896502823753829; - uint256 constant IC3y = 918298420507614225062851310351147657365217324218976043633227084147487484538; + uint256 constant IC3x = 1027866460885921739427963398134501038455918532796341088945078011511621442676; + uint256 constant IC3y = 5958883990350165479676838573621528879534261429892979129692820679034946644717; - uint256 constant IC4x = 2676903711586497323483713249304841063436832787967161822350958984717228651508; - uint256 constant IC4y = 11366926733173287985429506187405640951452084685400170840758508049511684394323; + uint256 constant IC4x = 21477343731350881336427671728879526073055001513676414044100634074555163654487; + uint256 constant IC4y = 975839980071906751516077094474212502568600329809457289967004593943814041533; - uint256 constant IC5x = 7501808156091619633948887448038018539596703524171333033985091618683129395104; - uint256 constant IC5y = 15183325431102096756416380632145698394481557936329850246257270656919651359614; + uint256 constant IC5x = 10745395673337059701699795673419720732231823654131369713589820865994307217089; + uint256 constant IC5y = 991956397633440927392694166348862131981180374714009247953939276179698863313; - uint256 constant IC6x = 16142642127854572324146698192700027612727186725464085127687467897687720973766; - uint256 constant IC6y = 4517714220502032665709414305462814581261203269046555880307186415606032799074; + uint256 constant IC6x = 1672993394090581484120407360563051967903199184399912366269853108749767520052; + uint256 constant IC6y = 2164345873917124991571819758981721198425688586574947724181752888003788143824; - uint256 constant IC7x = 1755538289631427930924987331320419179208761530645468129027087746202210024610; - uint256 constant IC7y = 12173734026028648655823071635152323182912152859934466692190630751344902966218; + uint256 constant IC7x = 12851905556792884689855342999140438817587827047283740173600609203898826077791; + uint256 constant IC7y = 2928106356023086030701978715110626259062951617739902988557680022327927922648; - uint256 constant IC8x = 7848298938728453306694415912843236021632832336242686994829367580246363462232; - uint256 constant IC8y = 14621047188318073218187719299332281645270167229458286064175382232430986150614; + uint256 constant IC8x = 1706366517711033642836339515106072692739807158278497001454479300738236232683; + uint256 constant IC8y = 16700903182897452990475040323204325018874215917926885692984146211640664248939; - uint256 constant IC9x = 5702664871943851440604579505620421848165916037464510240027885273509338564683; - uint256 constant IC9y = 4155173472639459280548275148817066405334382784770925752738906208871756122916; + uint256 constant IC9x = 19101508791113451928961082481025527911094003843281774332989233416940984939257; + uint256 constant IC9y = 21697565471392202731806697866311578445068434145060675485941899096932688363780; - uint256 constant IC10x = 11951237379444909975940139423428082852090010220501184525120096272922224325380; - uint256 constant IC10y = 7330212864492454320053389793155451329372996827534004209553742378250571973798; + uint256 constant IC10x = 19730275336196180738068616492761799716598666564420842355043346059462631887595; + uint256 constant IC10y = 16685285536790785249111663346085181130998577327076396224848784078816064185361; - uint256 constant IC11x = 17758792179933266126153564380301713721054370865026967564744749205362384449189; - uint256 constant IC11y = 20123875363051656182295676194267758869550749528323178608799833168744783048873; + uint256 constant IC11x = 7617913501130858003386168099320868449737268059133253154619134544472248055105; + uint256 constant IC11y = 7972962376779726951865679647174563612838286095297842951560535589126110704430; - uint256 constant IC12x = 16531299530766176947215740556184329586746603539886897864186093216474595540644; - uint256 constant IC12y = 8268807341917110402770543111430324212645734302589993091794921535136544275649; + uint256 constant IC12x = 12544403142863928402358237586570057011271857580491825726062907284786959213913; + uint256 constant IC12y = 6822386508465769764381472926650183520080357052212751223638195245287957269971; + + uint256 constant IC13x = 18940507486165234508918415676788929441013178061873512240392411069614035082362; + uint256 constant IC13y = 16781396210596043591429632308560467689975084335009897683626466396650016291114; + + uint256 constant IC14x = 558712144346877070501655608109394614280454755351878785357769476496746188097; + uint256 constant IC14y = 11446848258088708077539993154875274206911247468515662688034438075323420564863; // Memory data @@ -89,7 +95,7 @@ contract Groth16Verifier_AnonEnc { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[12] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[14] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -157,6 +163,10 @@ contract Groth16Verifier_AnonEnc { g1_mulAccC(_pVk, IC12x, IC12y, calldataload(add(pubSignals, 352))) + g1_mulAccC(_pVk, IC13x, IC13y, calldataload(add(pubSignals, 384))) + + g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416))) + // -A mstore(_pPairing, calldataload(pA)) @@ -236,6 +246,10 @@ contract Groth16Verifier_AnonEnc { checkField(calldataload(add(_pubSignals, 384))) + checkField(calldataload(add(_pubSignals, 416))) + + checkField(calldataload(add(_pubSignals, 448))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_batch.sol b/solidity/contracts/lib/verifier_anon_enc_batch.sol index a89577e..8ab1444 100644 --- a/solidity/contracts/lib/verifier_anon_enc_batch.sol +++ b/solidity/contracts/lib/verifier_anon_enc_batch.sol @@ -43,137 +43,143 @@ contract Groth16Verifier_AnonEncBatch { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 2597671780590251694570119685565323840048843183405159335694422232267097858944; - uint256 constant IC0y = 8213860297773598587502270259232550419091407212880698106060980975459142704915; + uint256 constant IC0x = 20457956958473860293835648951879045856677043407243648302743877859875552209247; + uint256 constant IC0y = 7776079367720380762099625163992180745418333944870070120747012066006122461055; - uint256 constant IC1x = 8862483812835763900195190187644217978558523440961934857686069698277251165035; - uint256 constant IC1y = 7652510358319732081254853215291009089945882523574369846519334872331056472570; + uint256 constant IC1x = 17549927933267135940045377484490257666333216840197555674091687873774886451412; + uint256 constant IC1y = 7777359099725353892523896849960626230014517620518326885856442970545242754330; - uint256 constant IC2x = 7888217796744605716171927246027604238387016217738102223849326057462148785492; - uint256 constant IC2y = 8576582989723476354505896974449655963516713987661765330961011770238676018217; + uint256 constant IC2x = 7266608593144975111773315460187555514472943754137342878861656981647216925655; + uint256 constant IC2y = 7636964277306973569988198676997644948196306801511281373794086341883402123046; - uint256 constant IC3x = 14352528680833998697032764557955482324646413153382503495075845465567317915183; - uint256 constant IC3y = 19243011797365702752348337725258868465391417895775931958786329833019920483153; + uint256 constant IC3x = 9096435126897708624638220924873430238007027646650523572103562570436206417938; + uint256 constant IC3y = 14049119430819940315256289700787051688993481620336037917299625578452740380713; - uint256 constant IC4x = 4392487320426708391579693966075795790380185591934224629876177226656021920102; - uint256 constant IC4y = 13082952223885280332924734169956320971361821620479520152957670710665009299216; + uint256 constant IC4x = 19211209105469507152755702318350737580106120225074705315095711078638533754748; + uint256 constant IC4y = 1437142373109547513907085005044999690512181331035758157869645400244652499489; - uint256 constant IC5x = 3246410921612126522937407677617019956902523430558290131050966139863929179563; - uint256 constant IC5y = 15810399654885178166598854163407739153721316569421450866223951195409637465167; + uint256 constant IC5x = 12222905540180851820029190045981739566801977585854566585169005829892609954692; + uint256 constant IC5y = 14549045090416232419147266612622733246416508607001040845687387258340095192145; - uint256 constant IC6x = 6608448200226248204694649478827679708944271084059128867495190620836363543432; - uint256 constant IC6y = 1469463329425024480904685533245022389379237452483964428569855536915085989870; + uint256 constant IC6x = 4735648591293575660142988753722749059395263946926604330150825908832092033660; + uint256 constant IC6y = 5187710164061334113526020240024773205825970196964734893386927402857187063177; - uint256 constant IC7x = 7307852231039475112593987142383601694880236463128197701708676560849024948266; - uint256 constant IC7y = 15825828005819521547988669529549429477219509748212340587417074460536404323121; + uint256 constant IC7x = 20334714858185797595805821522541184085655033208922578178233244305037077766407; + uint256 constant IC7y = 21884104557410710051678839643792559542224546576654807003963346710937702613433; - uint256 constant IC8x = 7082876175210469881576943800412028198549838067675996862482715259243907738723; - uint256 constant IC8y = 20866219759165505486220546499441896125892835863491955389574735982947973009001; + uint256 constant IC8x = 12671237970713394931979048957648855653558007432570267806897915769288839520123; + uint256 constant IC8y = 4028373755039302223794864114025699218021876780916423938758276516753277379453; - uint256 constant IC9x = 16367296414927203597516613989590733068013952698060738405287535212048793073436; - uint256 constant IC9y = 13100662036162133830465657628089803359747036547046363278544562928671020462939; + uint256 constant IC9x = 19637480449400017323866327155419553724800176004889528445729832747387029990732; + uint256 constant IC9y = 525358805582402449177466576244443358066620040494539217258836672038268689113; - uint256 constant IC10x = 12660953324410882204944497454942873011932420236908450607037711554496291551834; - uint256 constant IC10y = 5017337532572709501338492356315622676676311947680125340270552472293496948209; + uint256 constant IC10x = 6683362214807778519679644869917831149252215801168763967482464355615388504337; + uint256 constant IC10y = 15911582188051515386082475757956470459072857999270068218265114981181419149798; - uint256 constant IC11x = 12938017223692108736253470542300205103074687940280976163691951851236725973494; - uint256 constant IC11y = 17569330124188420068165415153185726437478171411764985964911950185946817551407; + uint256 constant IC11x = 7859451747924816063864464353448322211274971735004975283586730285633565348026; + uint256 constant IC11y = 17702245455909972873350844621328458039040233256650474440765159766665422983185; - uint256 constant IC12x = 20342630885581806890644137027056481970543735603633976578131518125105821917614; - uint256 constant IC12y = 15056484383544158070695679930126332525674495858173628085598715222609521785187; + uint256 constant IC12x = 17887434247668828848829621275742692134834354053329422702672025565942351615005; + uint256 constant IC12y = 19945940161431857227380726528931717092781378075558615731197842417099001986329; - uint256 constant IC13x = 8455788225496452961679299633801872615012410834148396636082678777338966830587; - uint256 constant IC13y = 14667533314468679725174123240933383024760244475242830186466272876754757134870; + uint256 constant IC13x = 910850375080581916368615482730337187006033352469590595640777417750447607608; + uint256 constant IC13y = 3677732807370305265286062294483845790891493712292966367578729792298898100014; - uint256 constant IC14x = 12149567170771778292494559727410871049802426926691679765077855282315998609309; - uint256 constant IC14y = 1380951936221823370087711818380075591504589948146383500969529833976400607862; + uint256 constant IC14x = 11394244343739019725843491923239602248858664538230688052482501626207869677474; + uint256 constant IC14y = 1017367602106140109792711511707675118068578981870871058707753729139351086426; - uint256 constant IC15x = 4766352989791691182635058002456509827848802635606176367260246470124364530595; - uint256 constant IC15y = 16021379633910943936876425379013477219651362538262135400890871107365203200691; + uint256 constant IC15x = 17580806813370218190519612135500080594692941405328154589071627093917036218026; + uint256 constant IC15y = 18866852522884155432837625970655651869537802178823630974722600494142936431895; - uint256 constant IC16x = 13432698768504751724696856885735307391004439817130841678111462400792972424486; - uint256 constant IC16y = 19500268176699315470221660540450777362459609923828512875319635638535908023564; + uint256 constant IC16x = 20953225053977698883461234417640671125664833305435259995743410489766786811017; + uint256 constant IC16y = 8745430177680780508827153481916758574808937829385814074304854361662865188531; - uint256 constant IC17x = 2027106978523088520304891108191654793258486055367592742515642621734479986878; - uint256 constant IC17y = 12885379807754498633078727887648044664952754419022086638754196996033264000769; + uint256 constant IC17x = 9298865247055097659456332331836095871429324408895784837764325710955588923525; + uint256 constant IC17y = 18720021835177849144326529233199949902692218020852609953397883057041365406716; - uint256 constant IC18x = 10949220398425644397776376483790772577269629182083303688453860881073414915560; - uint256 constant IC18y = 20057436519045729231987911965222396188122848678213106428088994494919359307386; + uint256 constant IC18x = 9803064636763855724556507831841530068201342991085473117961961761604449353617; + uint256 constant IC18y = 13010891856001121057287490847830065709739845170631999382717458902000410392837; - uint256 constant IC19x = 5846485923548152593765310696533795024730896419830093371615151423977602741415; - uint256 constant IC19y = 17772204202833804655322390479163634517799539727968468621900059788600589940328; + uint256 constant IC19x = 21429702633296602456819134246535066068702583232025542423089522744073299522839; + uint256 constant IC19y = 16335398909778845583628705821336521443514985762107953814101622209643140854940; - uint256 constant IC20x = 16215609594427567394775135826335779265030042744678385760381534305280435465518; - uint256 constant IC20y = 18603709842506682831291739646314175009181915216384941921308130259270074065385; + uint256 constant IC20x = 9751542436554156396205960938972482822138196952556898887285337815279532559334; + uint256 constant IC20y = 9329149151981556656299798990823114535761565475856550151911761396342936373057; - uint256 constant IC21x = 1766058222969804186851406321305907427335207817599904620543688044203524722607; - uint256 constant IC21y = 13804893675033551122681507240136237947277680441710440600217850520760585066138; + uint256 constant IC21x = 14466501034453509375016805523060731169089523248364937671766094317200453715291; + uint256 constant IC21y = 3150099584380216663313553181132841756309020309096428653543390538998378851140; - uint256 constant IC22x = 10941193629908240647792765252351165933874237692700406745824002033868870639031; - uint256 constant IC22y = 3638020580879185829103840161089592128597068702224187657764432052756035287255; + uint256 constant IC22x = 16625780749334367102987241113400718766807362610198271097525872106126093250001; + uint256 constant IC22y = 5641529405852880889432838060723510427373153385823065644704426576587683782342; - uint256 constant IC23x = 5930952354462594760376136142156168856897650178619630953622712543360935660800; - uint256 constant IC23y = 1039287092721675860743161800482533616450705342550210168940302819140444260018; + uint256 constant IC23x = 10482129844561687653238400541792795523853495600910564159314860391063236893865; + uint256 constant IC23y = 7030587236238761457314153006466652546041803446772298811234377000319902316049; - uint256 constant IC24x = 532646474113271627018071424500519783214891032448645307389061272582944254003; - uint256 constant IC24y = 10151057854673851550754133166208989367948300699959847868052519117382459699016; + uint256 constant IC24x = 17777485010211018490416436586755225220290461571556946002064191567301479196124; + uint256 constant IC24y = 11093041903680853786134545279581284881559712502787103346113529896350026702353; - uint256 constant IC25x = 8405375250703253790117459631087585294901701344117711232998075871750664438242; - uint256 constant IC25y = 3944328247961513119633005636272243777809959277100342011559673763007836092026; + uint256 constant IC25x = 8367464038675137240637235032183962189203318091597084436727361402785690352415; + uint256 constant IC25y = 2101341872045901587244350434302489380465478959052054782990815843504622375785; - uint256 constant IC26x = 21614355317718094894664738157772558388158937098373656545906139451342893449131; - uint256 constant IC26y = 8071511638847832054915722800013967614757521955341169310081076405458398492749; + uint256 constant IC26x = 9445937682034499200116555117283984556173406956968330905166247396248067476298; + uint256 constant IC26y = 2448614491980710495634177417350604360553528335606412536811403268782338557447; - uint256 constant IC27x = 270478275418174140981268275965608765397454128234005817847677613575246346435; - uint256 constant IC27y = 2168666035663772154819161912982184259884565651971605752352808469034945793397; + uint256 constant IC27x = 9086407649402987466727626417229484253386649160044225932044624305425853693602; + uint256 constant IC27y = 16892875124856684788049611363643986883200311062034370427528822921971214937498; - uint256 constant IC28x = 19569908851449880064455947092469809211114746841722376707408325655352308844700; - uint256 constant IC28y = 3025699621270862613925776395824335832232953797690111658313929728015843768796; + uint256 constant IC28x = 19759427378006359186636323808841855999743290454170215751803319675288637666224; + uint256 constant IC28y = 20893980529463838942352241569178910211287945093872561634827722552883873929734; - uint256 constant IC29x = 2397616016443675765741599870545252815144654843924204698241664346514355482355; - uint256 constant IC29y = 14005094129994017499220324359090683323552493484403197787371287972073964141391; + uint256 constant IC29x = 20762860574071906476558223570053048914958814270667058249400227402836777574107; + uint256 constant IC29y = 19285928520739540943739493948094407121565948163149835902863321883358878361412; - uint256 constant IC30x = 1594026336486525641702314048066413763993325793300000100171229876791999089353; - uint256 constant IC30y = 8072633066576840209208996401111739145989116649091797339956073760079554394308; + uint256 constant IC30x = 12982919139442164278755036181367896103036089671229752387322345416049000267478; + uint256 constant IC30y = 17389857939362238519664807858488982461046972261625678287174111944494040978382; - uint256 constant IC31x = 941465443692266427834241213682069926914266822578025045598574216227841103683; - uint256 constant IC31y = 2162285939012937035604048436417716678642325048065608592368777414167124309037; + uint256 constant IC31x = 9296346158583058002982031757345378508628673444232747679337799561444313658756; + uint256 constant IC31y = 11401838933643317672245148437030692400996215400094297130676326454765266124841; - uint256 constant IC32x = 17755298264501538848178211159255564751361039329014714629678463389493815518413; - uint256 constant IC32y = 5373972597904315947883222328549882023096106569825979715283040233275564684452; + uint256 constant IC32x = 17286803510413442586833249596325847372150963129796326293518898027419455799100; + uint256 constant IC32y = 4729548357749587914597883649741039045459375769895691014012698567505454373958; - uint256 constant IC33x = 18102455506412198143265025688384882255364199113479575052771971652823946543361; - uint256 constant IC33y = 10611532522259229347040295119756938634134184132433010612585681043909048550194; + uint256 constant IC33x = 6225792172100833912708432866127247904116640232886664169969642733255064660000; + uint256 constant IC33y = 6060274113179975560638082875287670984249765738465535446839477668985817135251; - uint256 constant IC34x = 9287592647220739061864536287605711120641354785099018403519028816976992208810; - uint256 constant IC34y = 5368688991717252135366170215180249655728193010657555227283514482663613267436; + uint256 constant IC34x = 16100121312513859528075023932696721282346572050314892547292307235056414188134; + uint256 constant IC34y = 6824112582626629583841600764613110508332283077963956905469078903373189725192; - uint256 constant IC35x = 19759330282652380493014428586685989919377111184913674764033542113439733508101; - uint256 constant IC35y = 2793822654429148772664656948523274725780698166747463520325079729154142634364; + uint256 constant IC35x = 11468809176406819854117038840765685383176557932415559413642626064953024788160; + uint256 constant IC35y = 16327061741308268552699959019077558460768707604967044367693906400037465494103; - uint256 constant IC36x = 11049781270295565209712493670155543711476396567038998500851076991617994490106; - uint256 constant IC36y = 11993996864162381036679383108580743566026297793935046480209203450105332505905; + uint256 constant IC36x = 5716872441568503762359414274128330720939141110087485826855142892018711170418; + uint256 constant IC36y = 7316500402322451089160627546884883276088294973708881737262802199173885883354; - uint256 constant IC37x = 11286956316213496198784831587292367873435614453135297133863480708511731868507; - uint256 constant IC37y = 15499569902989547236933665888709713545624276075502070694155608647074297062790; + uint256 constant IC37x = 9431394354834930743420189375253905724350514021300926223621405654335394524267; + uint256 constant IC37y = 11668870674753647472543361195789115138286174053139833262874235003443925126227; - uint256 constant IC38x = 11623006485365493322989951720233690859710722576577484852549967707014267001110; - uint256 constant IC38y = 9604064454128931077040373778349956271228053422158312825986387039993421951298; + uint256 constant IC38x = 14101909265881417922398903228902866393379197230150540763468879683182339922162; + uint256 constant IC38y = 843475656712384462124393918543099201607219961246272351220447766498200318270; - uint256 constant IC39x = 2464723668469969175747439301173496600708067106680738792474183669780873148058; - uint256 constant IC39y = 5627731506388173033330722271769856914412098157257440317053576454763368750030; + uint256 constant IC39x = 17242818561206755627772388888524159835848637302855005274392040904535533841946; + uint256 constant IC39y = 12913556443462307175824182946682086865851661751785096241603862402616588100667; - uint256 constant IC40x = 386775949029146918515856173542289693566462223678664899892733838474232891465; - uint256 constant IC40y = 21843306558508533555498999953845692654015104011212021286439942440993655717111; + uint256 constant IC40x = 6664878326271511977250217125393597499868106283996944372518621978598175145743; + uint256 constant IC40y = 15144441784853392110035931444169830357580673626108453163006810316899221105706; - uint256 constant IC41x = 14998380474237577930727399192140759096552055906436435270065429803038238552107; - uint256 constant IC41y = 16246300275134921397192579770377320255339611288167554408872393937397750566904; + uint256 constant IC41x = 20086904197250387625003182009808914102381910432954527190317655483755132971479; + uint256 constant IC41y = 9880446798565027167349769495326314796659653140515047806702697356581078693719; - uint256 constant IC42x = 2126752576878583697702142208053334270599109357577167069195979265172189209012; - uint256 constant IC42y = 4244611359849526612607201560441002012851317308605825891261545861264066872978; + uint256 constant IC42x = 18568474479778525057620296750285011467433857421622424398667327542936804538421; + uint256 constant IC42y = 14380361583263936802601888969067954059567919690190840045459166931846792356148; - uint256 constant IC43x = 11478497790344429290280909138615535796732148307974183201168482934125997648260; - uint256 constant IC43y = 1580586981837574023152058865433485528026059123101773522208265717828608271288; + uint256 constant IC43x = 11544583223021191345047659621978897446635170548746961836374819427837461939803; + uint256 constant IC43y = 20547960814800065359605548667632876088577519108660285624683924957618216127059; + + uint256 constant IC44x = 1912392906994463411087577566286247817866473791206599813185663829653003728024; + uint256 constant IC44y = 13446395032386279021226716525374023030656189163839742618918207180265011638965; + + uint256 constant IC45x = 20845023561343448705561071146769639912487817477708421585464830888518785779848; + uint256 constant IC45y = 20173847817888474799536463971101765819441189334369434652846457077165068620476; // Memory data @@ -182,7 +188,7 @@ contract Groth16Verifier_AnonEncBatch { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[43] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[45] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -312,6 +318,10 @@ contract Groth16Verifier_AnonEncBatch { g1_mulAccC(_pVk, IC43x, IC43y, calldataload(add(pubSignals, 1344))) + g1_mulAccC(_pVk, IC44x, IC44y, calldataload(add(pubSignals, 1376))) + + g1_mulAccC(_pVk, IC45x, IC45y, calldataload(add(pubSignals, 1408))) + // -A mstore(_pPairing, calldataload(pA)) @@ -453,6 +463,10 @@ contract Groth16Verifier_AnonEncBatch { checkField(calldataload(add(_pubSignals, 1376))) + checkField(calldataload(add(_pubSignals, 1408))) + + checkField(calldataload(add(_pubSignals, 1440))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier.sol index a58f3d8..1066709 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier.sol @@ -43,53 +43,59 @@ contract Groth16Verifier_AnonEncNullifier { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 7171865328513703290093700380380451739385788586354130557725671671306758284835; - uint256 constant IC0y = 15160988901383576473200213855983245130977503188173050431265741631039643989659; + uint256 constant IC0x = 13678166000771296028716088649707013760829674700385759642860494154368687998709; + uint256 constant IC0y = 4961949307578461931371517116082474097036228012924437637706038382049417537984; - uint256 constant IC1x = 3084387037124888968906054526437397944607369603426340221309478427286378241883; - uint256 constant IC1y = 466692009472632412227422575571510864857515798042934045112835241921551265392; + uint256 constant IC1x = 2204542029006441412514570505771624273632312485515492234810839886974792880667; + uint256 constant IC1y = 8838327314784458145079277879579686434474366816781852809532023511523475680067; - uint256 constant IC2x = 21832264940508969407116160765601208248355133736795673808562573616973826318173; - uint256 constant IC2y = 17513865622302204578145142072242964680658195506435185515338697999465131372215; + uint256 constant IC2x = 984190429201041857120978307904591089984674147895365854199554277248567756762; + uint256 constant IC2y = 3050029555075507159624174573918069927104375767401967689538452364062362998517; - uint256 constant IC3x = 12015675409779862456858459776469990615909895302707101975777128025909710875049; - uint256 constant IC3y = 2520892781547161601538120167223137961114737111406729888435197618701217196087; + uint256 constant IC3x = 21506409996536555473783344664168479995150262432075358365354580674108412355016; + uint256 constant IC3y = 8599911080815734217762783325275263009654132851986193429393340059137893076967; - uint256 constant IC4x = 18587338580725867825677477230134951065880542623566314115410920967489785517516; - uint256 constant IC4y = 21420226112439899782985709520125134654836350697076867144518818376075706925435; + uint256 constant IC4x = 21788371071589958280155010312074207167387644784801032467524251563813069925789; + uint256 constant IC4y = 16017891759091634551485035996787768674890884884580084418250378977472667646747; - uint256 constant IC5x = 18346549061396084692847221708184331260051262422967450576733753481236492888092; - uint256 constant IC5y = 633678319913138336192943173886371080587792382475177160197178800699073737695; + uint256 constant IC5x = 3474370977150635979281388957540044901593079765869405148003508855938907161523; + uint256 constant IC5y = 1692620058877250578859346926736402992006465899480571464739489531519910165301; - uint256 constant IC6x = 15514772902364296574205078627736326288883089283745048573804246962058079873557; - uint256 constant IC6y = 1394197625614777654031366434591548394543950554494358685957018689229660853575; + uint256 constant IC6x = 14149094746002062391808802496591387377487466349382127931670045723541741558711; + uint256 constant IC6y = 9222799121270749610505345007770793977124321191496588693556191863593480045856; - uint256 constant IC7x = 16806786020637006306786960369076775679377041920806079893283199359601728188047; - uint256 constant IC7y = 7411897025668958146789418373160957758956645515920701058704613059473583938439; + uint256 constant IC7x = 9273799284822923793575807137996194733339480428254374206006757400032173797727; + uint256 constant IC7y = 16315220931561659393515402681962417396004656325450070112470349917711135971087; - uint256 constant IC8x = 19018133878713314349758532819088967051326614327028573516334511747113847292530; - uint256 constant IC8y = 9877630889165761579247296300368869133011487886615672260442723260497640161991; + uint256 constant IC8x = 13451103343875903897343428704678468946853158159536827119528221805472272905108; + uint256 constant IC8y = 628496243328949807277588354970478320528811318471137680004273397631887655072; - uint256 constant IC9x = 10767786868330800120105196501607321338228888213304687234183402295397263198094; - uint256 constant IC9y = 6019304260155989652844712735958857170410842538847088443761410076894957598387; + uint256 constant IC9x = 6067287962006180781386150709214909947659323356695103529191319139769289637925; + uint256 constant IC9y = 16647921353576036963239701670325188480964660838840086346922477502515004451615; - uint256 constant IC10x = 1505415316604755207127167367509090828253238030863717428595372929062841294642; - uint256 constant IC10y = 15576511224449925043716733649200226332764494096523179313664988851737446263390; + uint256 constant IC10x = 15848788386796371774620049439750702816210500764159641257483786168422723885757; + uint256 constant IC10y = 2191844892636187267255601718549938310559896531080551525090520220356407282435; - uint256 constant IC11x = 11350863237254989736684670387882645815396381623210736835421534659894890674850; - uint256 constant IC11y = 16286149570223574421139051231332214489084057970766222780431895095582201480175; + uint256 constant IC11x = 14155351394916282563155442681342138258045803790992757138692337650812573648549; + uint256 constant IC11y = 13266490918112647274657614801341765344560672830045160509793915078708246250887; - uint256 constant IC12x = 7451628250668181305280701888064824846978152009744420355240144648812642407336; - uint256 constant IC12y = 15936005158368160846313683217538494908244490784117984880368453648065515023911; + uint256 constant IC12x = 18767528343784802461760910070202494978333037674357891557627291028834187942428; + uint256 constant IC12y = 2927451585647610372373530792444084065279855596561951798131860222437462568234; - uint256 constant IC13x = 6686413412529197180696873383139717022076724166313051457947592231187870145140; - uint256 constant IC13y = 1497406026079419977690750812932970362785235177787112328312491862602145590536; + uint256 constant IC13x = 46434084833796288510223843828494589085103466116172276944447838961663746010; + uint256 constant IC13y = 17636599523219034821248614860068790067885311644103576308478366993062879504561; - uint256 constant IC14x = 7772549737172193473908663974458932734834195419159040157600433771144206321357; - uint256 constant IC14y = 16378591475564435647871798005772579246008315305784601998199949074907153910639; + uint256 constant IC14x = 13671330670802655872327601166524587591429531249226018939856821915010408000292; + uint256 constant IC14y = 14848201027494371390631351773542387913617409380236048186961677579174143126419; - uint256 constant IC15x = 13119566302351156728138299811993016524473146429243176521298671852157284998237; - uint256 constant IC15y = 16574498854084276113707136023151636502896085017309379147845117906554354077783; + uint256 constant IC15x = 13578759613269241915934553713856919923847539014199632158899353697877937136841; + uint256 constant IC15y = 17992517964952134073344784861755363143409916374751756941628545297594318465106; + + uint256 constant IC16x = 4798600103275234744393502044369757486319055145576852517168958875299506874579; + uint256 constant IC16y = 12020210555699713650678704885293163425712608070382809856857547063740548212273; + + uint256 constant IC17x = 8618416541017467104007817741983279564391984799200957332901530860654534366392; + uint256 constant IC17y = 1215959756736848284315621954972208648259065888449655282927680963058074494048; // Memory data @@ -98,7 +104,7 @@ contract Groth16Verifier_AnonEncNullifier { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[15] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[17] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -172,6 +178,10 @@ contract Groth16Verifier_AnonEncNullifier { g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448))) + g1_mulAccC(_pVk, IC16x, IC16y, calldataload(add(pubSignals, 480))) + + g1_mulAccC(_pVk, IC17x, IC17y, calldataload(add(pubSignals, 512))) + // -A mstore(_pPairing, calldataload(pA)) @@ -257,6 +267,10 @@ contract Groth16Verifier_AnonEncNullifier { checkField(calldataload(add(_pubSignals, 480))) + checkField(calldataload(add(_pubSignals, 512))) + + checkField(calldataload(add(_pubSignals, 544))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol index 53b49d2..3a0b434 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol @@ -43,170 +43,176 @@ contract Groth16Verifier_AnonEncNullifierBatch { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 12126744414123145446927544518860644117520956174461536844904979731739153937319; - uint256 constant IC0y = 9695184835202931902032395296633846848346566651202119425523352011687050447653; + uint256 constant IC0x = 10645351421275030769212842451599777004533318201294902462005034101795836667735; + uint256 constant IC0y = 19773846574370070068526112402756882493172867027564763871401825452271772896770; - uint256 constant IC1x = 195592937835855475172740086869646488202858994940627750986459540968521127076; - uint256 constant IC1y = 20133094631443294605453490663465191307905205631306063705224666266432847314101; + uint256 constant IC1x = 21045668564796633627967971401776840306235180091510629996956077562174112854797; + uint256 constant IC1y = 9692641105892987460288991259626904081160606632602573786680505922597146001820; - uint256 constant IC2x = 609379390311908960003738861564802384037207126281378208589622790217906675428; - uint256 constant IC2y = 14024044248311930231657958997658229326035537165238311551943681440974095988896; + uint256 constant IC2x = 6986710375170555089687323877472514817724381470286988221636916919623639919267; + uint256 constant IC2y = 11825153705848256829640073197891287269133258372909893963327355565129252469538; - uint256 constant IC3x = 14475258944672930562917429258419275006330018007564140466732576979600095527986; - uint256 constant IC3y = 8383831786003410168382306689982076122231122079851574658280916054063860804082; + uint256 constant IC3x = 21589139179301699049569868901784946727171433740472463820916197439162935213931; + uint256 constant IC3y = 551980383756225690231265441795287943646681755160849513598947577957901960769; - uint256 constant IC4x = 2753592531034501021865774444348121286705967891727631798687428893089756717516; - uint256 constant IC4y = 10956196239229551190326394756148632499327174891582324228559177700070138627435; + uint256 constant IC4x = 7848148325988989144014232092764440426513779624118010875067911492016597507427; + uint256 constant IC4y = 874964876333419237750792570559364811284638715362980586388785676601037939603; - uint256 constant IC5x = 20694727281247008058140870402913983925603757764003248536372865152419453726184; - uint256 constant IC5y = 632675084443897428190075680269855858382656311919806104466344079557191993970; + uint256 constant IC5x = 5030538897432365602364477809726773513224377789278422573056864982899918308435; + uint256 constant IC5y = 6538658663213062852245653828011736921546820135242837798372228475915946407294; - uint256 constant IC6x = 15429847497402072415689042470309154270994030517871107730087057583238557913338; - uint256 constant IC6y = 5432278756669468541861545244015645582266245449985525214546028390310773531354; + uint256 constant IC6x = 1134488520285628584172609693922141497292325051235162469824971135714986508423; + uint256 constant IC6y = 13421809311905703563334091581498477650119249056168469733417655945944292140800; - uint256 constant IC7x = 12596502105325655558267857046382181213663420017501532384280652854282498583279; - uint256 constant IC7y = 10333147987837832448849674060620143310129669614798565710383011814099409472027; + uint256 constant IC7x = 15809369401596210985478473064948224599188521859155115813447540322319418684429; + uint256 constant IC7y = 748154560614039972265932322980194959340014814655278777140312658340634440738; - uint256 constant IC8x = 19706927842290699304337091536861015009104078371247908023635836241791720370976; - uint256 constant IC8y = 12152105452911677618830339171375361924352461862712516323327576003984499587771; + uint256 constant IC8x = 16422634041753847419090532487213130865873369386359797042255555793689963416641; + uint256 constant IC8y = 13345489373898517826619448768139131981126393410240491128775416736099748551986; - uint256 constant IC9x = 16502342806517603727453825489628207300342455950110654028899078381918045746715; - uint256 constant IC9y = 5759609699403129611200125092383023856891064107714256272998295476995274119975; + uint256 constant IC9x = 9023891455582583354799282243974737937216662894041709294412517055346091405216; + uint256 constant IC9y = 19721049929631439090338791564588794157023579033738842201236698580157965105980; - uint256 constant IC10x = 15221251781596258119997351899631148736262625069933837816302411218064388784101; - uint256 constant IC10y = 21714792109295217531628722325832557564632293527405759778556005756241745940902; + uint256 constant IC10x = 16791613249768019763130155513839129939686345377917856464443567247489567026164; + uint256 constant IC10y = 15270069150558256924307484622069492276980978114465458770799437465145659888704; - uint256 constant IC11x = 13518783476272320621059295563539618751199322165040898390459311820772920006328; - uint256 constant IC11y = 20348572405520834933650462837534509197678154321262996827351132403485707735007; + uint256 constant IC11x = 9565236675475260845883610238852228330283848177620410368151292023129362514150; + uint256 constant IC11y = 12882180919417442528934412844769993736456066787664071079858702514787733345580; - uint256 constant IC12x = 3085516350134090993142344171310595321303355811767747642909734046142759413333; - uint256 constant IC12y = 18292877018001033289323482707732762697493866308762540047493452370416598882671; + uint256 constant IC12x = 18889158444844545745822687387379205884168164919645495138937434791246868284441; + uint256 constant IC12y = 4463993601421177726480051615090675190432895924456563349702780067665853863063; - uint256 constant IC13x = 20415604312840579619461394202638369951741974304444342076923070910792744270166; - uint256 constant IC13y = 1274709640988443541674157446934369153698888932825153138931739737641414694825; + uint256 constant IC13x = 15654824613646082563998075951610876530965463902310927076566046041401790190883; + uint256 constant IC13y = 17897729347904120645817815694494907164306296387380224653473061731475087083629; - uint256 constant IC14x = 5858495509291051391546986394308939271118066275102133287209201740349735192015; - uint256 constant IC14y = 14561847678802194093246461244839677155048289046064941818821298670851532929175; + uint256 constant IC14x = 9914952707022185044859485843755152355827023461798918762873853737142122912923; + uint256 constant IC14y = 12223117364915343804298414875843316912398960926175366191900849476327091675443; - uint256 constant IC15x = 9907641005437705469547042991575734390388809601076326909237625045131034319622; - uint256 constant IC15y = 19228656501051437063502091175033925062642380193719554208510346953512647375465; + uint256 constant IC15x = 4530178371631031025262966851421025083373895413001645547669158623799333125120; + uint256 constant IC15y = 14847450682708930563109693216793086242583142312601249669264886719333269385228; - uint256 constant IC16x = 15683266867669391751788871262440210660433189459096145429401999628086509910994; - uint256 constant IC16y = 167032798777044716931677543915419096661362132560388266364782869921944477073; + uint256 constant IC16x = 20686192905301290185660609077917244772970221404992626008004711488059672116510; + uint256 constant IC16y = 14265228262044037282704321826983234216621387716914500339084109632125396447817; - uint256 constant IC17x = 14379095517200257325173372890767390667862742491742696929601242603656637834384; - uint256 constant IC17y = 19300151202444669113633208264532627998474371658767796608943018449744115979864; + uint256 constant IC17x = 17184296579665233138664538393593533408797018385395879255045965137088911002633; + uint256 constant IC17y = 5794545279126857667791925152005171752799892805442052280969080353648295951877; - uint256 constant IC18x = 19979595040717998606962225834005938237531481513259865988215018262605224517880; - uint256 constant IC18y = 21832910879168436184260345537048484374140139897617063690564706843941073502156; + uint256 constant IC18x = 12283677454922856060911771154661643414034804829779437509272866105959185262393; + uint256 constant IC18y = 11418437498830438374304711347669336909061511813254033588733923242783698973381; - uint256 constant IC19x = 8226426957042014569991432650455316949765932564299138456555947664857114623439; - uint256 constant IC19y = 6228408145117381653549320958239734390061251228728720735702635598241136382652; + uint256 constant IC19x = 233410113256358208167749654377889109662917637067643192371866364989155032597; + uint256 constant IC19y = 12489787345918568886208972254163440419069461589228081734396525205615115646823; - uint256 constant IC20x = 17772049787279101603624397097351662093398629430679036525849489583491916545941; - uint256 constant IC20y = 6754896174898647897440194918577444380308237651917088540483028012130071465948; + uint256 constant IC20x = 19922851833540760840323478915538105324832288698966396321587996988043948108076; + uint256 constant IC20y = 10009437256472029856043218169660264477908251912118684527903236010503598851905; - uint256 constant IC21x = 12428668390308036975156424643882363758080198297785963375946287369862732125338; - uint256 constant IC21y = 7754229916510745472520198965378403757343034624927137610169519146053204953496; + uint256 constant IC21x = 8576754828850430389792536700359043190882873416990199648102622011137214624344; + uint256 constant IC21y = 4068078849091371850291208205320805744942525044974109855286604207667579180916; - uint256 constant IC22x = 1151593409168857067491034330441560752818628055677134980028730195638046983154; - uint256 constant IC22y = 12238796633655133229171421264868652590324604792233399738876498509127150935586; + uint256 constant IC22x = 19720349134069389994319317515114599480576251259055426609291868076253917408190; + uint256 constant IC22y = 17491915401609613751947047987004497358908114555334188876708093723103785538658; - uint256 constant IC23x = 15130553149239877848171470204612941417069785217509981487672396229892643378048; - uint256 constant IC23y = 16099406353286235569807649940674558048574755883258872577176185277811179253351; + uint256 constant IC23x = 7234542443296093769067891602273037388908886094779444443372875052814418213738; + uint256 constant IC23y = 2298362372262249126601288098107811726732535043084050139693826893330484043384; - uint256 constant IC24x = 3794745696420163629058946455956008692538593039450146927979252667276878344635; - uint256 constant IC24y = 13521345602435249413225916136398623110469993915904908805128428652627696269000; + uint256 constant IC24x = 15208114325793531028606742636462558162754988632195033802710190832208321334839; + uint256 constant IC24y = 11228155327966805755480600454789239990152846144317355172501847758906396211607; - uint256 constant IC25x = 12972999372467026203108869807300469886972394303736354207616238357759320843869; - uint256 constant IC25y = 110817155195077381550608470818272201981579466679958649026939036130976959129; + uint256 constant IC25x = 10754029893239883996357951951628952208784365734832249102641651831368516446554; + uint256 constant IC25y = 1512088372644426222104577554197067771438352753703259964417078053825961713151; - uint256 constant IC26x = 11351987952539946970678101437449176359792007487358798597473939591460664122408; - uint256 constant IC26y = 1308124816220407348542397349028779400655687187740795098032329552311132540023; + uint256 constant IC26x = 8965801610689595002595405380643107571231801526473821486939465596524456163563; + uint256 constant IC26y = 1990575800156351430249196431321287695225190689306325346684717577132046431696; - uint256 constant IC27x = 6347411655408647494979217671534610942549776678980729506377609014193036126452; - uint256 constant IC27y = 7650341917145132808217914696212924364920359501843941028327806385968924055369; + uint256 constant IC27x = 658799463109049530635389082698553628347185965072273064330390643365460948483; + uint256 constant IC27y = 13405677562890064873561226033606712934771098608476724815623119529809072464467; - uint256 constant IC28x = 2241979173525358989962235321215348074120583391280990146670854896634571001132; - uint256 constant IC28y = 12185388424274874369299686917985366094479590786809423606708624138284993838412; + uint256 constant IC28x = 4670655359096776733553081707580682502588844748490083471633629023138096830770; + uint256 constant IC28y = 6488838101003408268756670018808136583339021091391323196295144950220700805022; - uint256 constant IC29x = 9735885194340002038427422932616677437854464253276355235258485361692033205001; - uint256 constant IC29y = 21257134599531732880615697459431269975454138566860287614597128553986677458275; + uint256 constant IC29x = 1180261368895845469822817411490892166215039187401084649877621394704393314521; + uint256 constant IC29y = 1595293418801543000842631962609502350103032468055613957656853561575554047309; - uint256 constant IC30x = 6412512253306584960786699140269842400589756139861876211328703556265682364873; - uint256 constant IC30y = 8581407114773955546646978840736423622848412760263687116910154515793679605244; + uint256 constant IC30x = 5725599681638513867016777243382848042025457023850387857074973591421703130467; + uint256 constant IC30y = 4748358959923203058463512303427588038076292680303181970622439573870368895155; - uint256 constant IC31x = 12178025225657053132665080940983731293612665002217512418283569056581120597462; - uint256 constant IC31y = 9607455014410621145198574027726039505738635719236281427844203271758404744637; + uint256 constant IC31x = 2831823426676598609658562094849647686826880490121941019646351323030466610253; + uint256 constant IC31y = 21281681591843671212111112787927911584393264086933269718285923299781025930183; - uint256 constant IC32x = 18085529495250116381253041145751943562444111566259228718399282295363598571826; - uint256 constant IC32y = 8782823250887339530756219046446889579146907517254987922714625664444135020715; + uint256 constant IC32x = 15628714637902002845692835315528619606830497872595777646425845531920921400266; + uint256 constant IC32y = 11029956528040516226392608549108249971969362564800280651245935215718627917626; - uint256 constant IC33x = 1684455964508238999037002157840252070214964666015086949858287180375841490215; - uint256 constant IC33y = 17317823021755689870171330660384352287541747050385661387955290054027403355027; + uint256 constant IC33x = 9741166931188394303452044647985267874563858336310297156862728995780923050539; + uint256 constant IC33y = 6856253999079830481815920937335629800513686843192893986891527925012405183234; - uint256 constant IC34x = 18856569786292380354208383060243350821329696637837390533524190265472245806265; - uint256 constant IC34y = 15170385454602492244681441975340956197395228417205548910355740362616203767205; + uint256 constant IC34x = 5340412578893639027320892120181771247600027415070143114023481697402168083877; + uint256 constant IC34y = 9878785258591337618411677581553129429961809222004088126614464671926218373919; - uint256 constant IC35x = 6785131565994547463443700779542841839255892841358327938723286020427767742379; - uint256 constant IC35y = 20646141934315263891703794412883175937007598956830529048607441435267188352006; + uint256 constant IC35x = 7830802881076272422242002885628397049146608767124814001915399705546480478018; + uint256 constant IC35y = 10271233937081179488796109492342220509920605765038327265765714123716270784734; - uint256 constant IC36x = 6142112958288288713721741987103643316152324184749373138621669384860357362760; - uint256 constant IC36y = 11477690672876208127297157941674443659023591957852535964173518338911594550233; + uint256 constant IC36x = 20568695072909926090785472199131742449061946847819876557253030954218241038760; + uint256 constant IC36y = 8090253717659426926034994325565773534226744105745394292903914691628468035246; - uint256 constant IC37x = 11576205874089682561141608979153392853349589278479920557765688886550510217158; - uint256 constant IC37y = 20636343449556485913175020331073900113337601414770678635262733230661106311850; + uint256 constant IC37x = 4360593488861012363063576337873090659969383301282071100663777774474540251412; + uint256 constant IC37y = 13508974920574837809802168852314929870859132568397534363560268700023166572893; - uint256 constant IC38x = 21269453497471835097480790967495702218084039255130168071556327157478305808777; - uint256 constant IC38y = 5558133198433894177562744499152791083414114634148997050934566673629137061765; + uint256 constant IC38x = 8168819567987017334417818056594040000893675129075330554707633927655599399207; + uint256 constant IC38y = 21554364355211946772896514721212726528098242209156762958769350026161400782521; - uint256 constant IC39x = 21390235838909311153232942303825483037076887135821993796282105744561739700802; - uint256 constant IC39y = 20595831866461058789401812156840704130288771913324404760914744933513888205949; + uint256 constant IC39x = 9076190532075581219228461167043852103071119206540332157010085453015207330636; + uint256 constant IC39y = 3356337988822620456051098873656377101773884966760489577022762536150452531973; - uint256 constant IC40x = 15108968727023597717708181716312456040954708879008242072671403834209124126750; - uint256 constant IC40y = 21642362401012076623505143315610051538418868156813229541212544750053727665811; + uint256 constant IC40x = 1738890537986340641563232846815778379914302770951790146367744788596111766203; + uint256 constant IC40y = 11680744043960758529481344360760385090686529128760223022815305468253390838058; - uint256 constant IC41x = 4676921041249368691385772973394433123525348781391629077041073696446952307853; - uint256 constant IC41y = 3455150633426287414331416575295821544544983286252435425896827676498333277639; + uint256 constant IC41x = 11032519278078035374450371251480117616307375430434303273522473430480466273898; + uint256 constant IC41y = 11759444777541376334762679081562192846943888334241598365174416412382416775371; - uint256 constant IC42x = 11473615547431627715479084652307953876948759423304237083348566005440424613537; - uint256 constant IC42y = 11880397112407624959975296336174025329790822775528008256584164936996730043462; + uint256 constant IC42x = 975484287630296320123562370594436328585623119435685348496746244589960426282; + uint256 constant IC42y = 16306932306324030391394601010083896325087656834393554589950134417361741693871; - uint256 constant IC43x = 144280706472074616974111776963484785112293106689209428729696289517621396884; - uint256 constant IC43y = 5004797331399302171724998314688238671269525162831195827603563550926662143284; + uint256 constant IC43x = 20799943769577155751147517300197228323261634403323343777907580029956076446788; + uint256 constant IC43y = 1582030258433952612426737479742105317880911936406371291174661209030848912117; - uint256 constant IC44x = 17937416577514179595555992349206950762346371377579337327375956989789185992781; - uint256 constant IC44y = 4706562120275640760035956575698254411341146065775454615083503549390428106814; + uint256 constant IC44x = 3908730706265324626495762736382090512637335740407382692274982098972015427593; + uint256 constant IC44y = 5154443680021960787510375550446891195833558907011270847949752866056543144710; - uint256 constant IC45x = 6028502846265846157872138351926649108917378358004468502772419077751630260813; - uint256 constant IC45y = 1610605450716392777245163633677702348842710813982929295353634279862192986405; + uint256 constant IC45x = 20422043385069297179239469706704066046244123188430264658044861269153295485013; + uint256 constant IC45y = 17509293807050079024428031793068504906531529399685577643741547856609753098825; - uint256 constant IC46x = 20141063340663189157054944434716958785175455085953456315504103557589402942560; - uint256 constant IC46y = 9420394857968479591478925576412437572728677224019988076827804618584163934194; + uint256 constant IC46x = 19377904175261504733149287710614929387142186881520208018631868270226707238243; + uint256 constant IC46y = 19584370567070657365983874417025970012162180256418183204070215232820650535367; - uint256 constant IC47x = 18127069780096155830535755947830466630223230157049798571956174928085658798273; - uint256 constant IC47y = 6801063294000630374892835246016369983130409633044568041486837112693654055188; + uint256 constant IC47x = 15124599472592999515315943698451703704951186669815756069476650692212183790929; + uint256 constant IC47y = 21398072253702860808041845648657417165878223226624391728708768110703783597013; - uint256 constant IC48x = 16182149093020958269594216045958105379538178453077387255279216324992015353251; - uint256 constant IC48y = 18316160889706950958969261837790035928674150206769644239725665787161636476483; + uint256 constant IC48x = 4079937364778920306442594024315627391052523545523540009281519905055199997783; + uint256 constant IC48y = 10201888942110078166950344165524145021781867737465046769820965073997280386548; - uint256 constant IC49x = 3949908026086772315804919653711079994687298466353733764853664258194473256369; - uint256 constant IC49y = 3942564944144782203828107633618433107646509102323544673560261314511736786477; + uint256 constant IC49x = 19356092471412258141029087355553408270673707906855194680708731257168363831435; + uint256 constant IC49y = 1061038648054283783341854542745595029053821005560616425434165472291015715453; - uint256 constant IC50x = 11227539341683934358245829885986203493424842258885732580499528444033926111411; - uint256 constant IC50y = 2641993489708465125648367588994825770902172935404386157992408160259561200325; + uint256 constant IC50x = 21343028396534167722522087334655271551240992456400214147277830321036266408423; + uint256 constant IC50y = 11846669440179039761703317955616648733553305301080432399933270821945580221008; - uint256 constant IC51x = 15530708669345166982359883868765494131144955712473005394067986833015574932209; - uint256 constant IC51y = 16854387299972883130761390411793023064332059279533287092365273012880855620231; + uint256 constant IC51x = 10292521103864911829516118733430078449161529689024076122421368624813287114332; + uint256 constant IC51y = 5262830170148138781879618635618998979151463825944890441891322091482955700449; - uint256 constant IC52x = 19879013054445385110179746397531206765963581460620226886063673937947628876243; - uint256 constant IC52y = 15699452951014667449248905102891447844972474113563121447359114087748893469079; + uint256 constant IC52x = 20153037745608603454973876932832386367398863709960474763581636423278843777558; + uint256 constant IC52y = 8131864189330604204685933794116391572936378578510887245069112518537895076359; - uint256 constant IC53x = 8194440531815176404130697978708824056023090090624701927747808763629794457402; - uint256 constant IC53y = 17019120385819361075347135636850402270968347150863260476373100439757997339675; + uint256 constant IC53x = 17187738837796036200075504264487161589801857077194488751149858577446279014274; + uint256 constant IC53y = 12080362734230497576274130333255296516249494013550225996752358008099406447652; - uint256 constant IC54x = 20512293947868579324477132529274423882298893397674273690289712752649033483380; - uint256 constant IC54y = 3856141993745158011335649033542760011301158064001661677116221331112179681778; + uint256 constant IC54x = 11847067467241475596668453029782243247363206460914528357997382225539958278828; + uint256 constant IC54y = 21086520617081063638758857193949011421080843371947185288143683110611184659837; + + uint256 constant IC55x = 5996420344908801778003389639638044198976138220876658841634453433483910911772; + uint256 constant IC55y = 1497970572715261788820528550447484475853291992758033288069899941602871818952; + + uint256 constant IC56x = 4707714975194514186283567202803559015209693536722913628673628779812487347123; + uint256 constant IC56y = 8107985637246170799012634655180246560278288486829178920536350781113786554058; // Memory data @@ -215,7 +221,7 @@ contract Groth16Verifier_AnonEncNullifierBatch { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[54] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[56] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -367,6 +373,10 @@ contract Groth16Verifier_AnonEncNullifierBatch { g1_mulAccC(_pVk, IC54x, IC54y, calldataload(add(pubSignals, 1696))) + g1_mulAccC(_pVk, IC55x, IC55y, calldataload(add(pubSignals, 1728))) + + g1_mulAccC(_pVk, IC56x, IC56y, calldataload(add(pubSignals, 1760))) + // -A mstore(_pPairing, calldataload(pA)) @@ -530,6 +540,10 @@ contract Groth16Verifier_AnonEncNullifierBatch { checkField(calldataload(add(_pubSignals, 1728))) + checkField(calldataload(add(_pubSignals, 1760))) + + checkField(calldataload(add(_pubSignals, 1792))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc.sol index a8b5c75..d0d0e0b 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc.sol @@ -43,56 +43,62 @@ contract Groth16Verifier_AnonEncNullifierKyc { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 20190008737197394450342108694091338568135578498705703052207100846737147771508; - uint256 constant IC0y = 18598201807933691587559529080991026720330392609151625239622109760005685213067; + uint256 constant IC0x = 15510813880661462106018872737660609981812361161360225919247077268694414066204; + uint256 constant IC0y = 3273104381472301566282116664311590746314861956272520926873509575735905240319; - uint256 constant IC1x = 452139730047001491535774769574376048901142363466012203113053837887098221240; - uint256 constant IC1y = 13658069816340688216031892919771477183715607138270132569610223992086459291779; + uint256 constant IC1x = 13491681648148788435689221543902213270283437913261488005306555856507875118485; + uint256 constant IC1y = 2808146101579469802466416404016575911891728776617600866872460209262742827298; - uint256 constant IC2x = 11669592363904336123147793129704111667124410995913742542844393202522824384133; - uint256 constant IC2y = 2129828274111755038359532307450490184933143179791119510470279863460174053208; + uint256 constant IC2x = 4725690937934659890215005371779681247012771736776651374911909283856555247990; + uint256 constant IC2y = 18321810493651809990909231408699263823551531357876718809194078272222655927537; - uint256 constant IC3x = 5602520055221798217852910005981059118735291244544863913087079277844381774053; - uint256 constant IC3y = 7726036063333401533144228011207326932588220311717018715578006508331000287817; + uint256 constant IC3x = 8958459661740944314305843955312561986747476993485058073196137338394860261170; + uint256 constant IC3y = 2437947121733860719471348909661252826832073454682168662626787097673523785627; - uint256 constant IC4x = 6072157368296199502061429238559064959224878744730210919572391729526656729676; - uint256 constant IC4y = 4396342922072404817552790123329348653983654878359756160338991902928904020767; + uint256 constant IC4x = 9451517300068142777511290574255154988100826100902983372883665735584552715828; + uint256 constant IC4y = 8619494869961996685562554417413284715040248852855616958676788456000592520314; - uint256 constant IC5x = 14156444020699427007396523765579676190302247297633651840365755554480657506994; - uint256 constant IC5y = 2881585601062356032052344229762934155665470619310149307816022512770496579212; + uint256 constant IC5x = 11979127296661119548762239476028183940430281334958083280546357773273520336461; + uint256 constant IC5y = 14876079694076565848273795501795074691202817530277907689935757800793104883839; - uint256 constant IC6x = 9358173501594313028986369364273485629339361346113755970129286915338770046017; - uint256 constant IC6y = 13384389474884560654773999400020608975692705219594212374206662773259083468823; + uint256 constant IC6x = 18475773985808507485148294010988879922821184305104367237479764157201546691326; + uint256 constant IC6y = 2850090538560055751503986121052040852671655864735358716840252120446691440704; - uint256 constant IC7x = 14065806997763568929014806532831294339309631956437145603843703478380691197500; - uint256 constant IC7y = 1687305135103805962026175705339802858788468976159872593451010969624096085402; + uint256 constant IC7x = 19811465473699014198715355967511549441553654782745492609261172832801365651601; + uint256 constant IC7y = 14870600544910155067451163725422044515921665391516780888059632287167180121205; - uint256 constant IC8x = 9926610124142437987886950959946429216445771850541529210620246513398511687976; - uint256 constant IC8y = 19502865377786189863697059376790350920703694340906636204501830435181993622220; + uint256 constant IC8x = 18563696230702476723728375853876157474970068550727434636342868022005576134363; + uint256 constant IC8y = 14388176320387786090092160119445811376873598328744301280591832433356922265122; - uint256 constant IC9x = 20202496612886706972728070168467780317520786329990263116983954505480252669124; - uint256 constant IC9y = 913586774577507188230910872703557858180540085501267099041510624577736818444; + uint256 constant IC9x = 11968161318939536287355505921566622267097175647130446571778130558246374942130; + uint256 constant IC9y = 17035629199023956978380320405701548422256095088150323734083362574539700979748; - uint256 constant IC10x = 266278504835704567488781146768665494860951993308633063784954130573281237215; - uint256 constant IC10y = 2705526920088398580864915394173201881547745998451271955180647659470935759026; + uint256 constant IC10x = 6410206309031762314294667109249209264272987325572542136076892695058459306807; + uint256 constant IC10y = 482381398754193931307654362683142689426055567274660023737349665299694375107; - uint256 constant IC11x = 1150624403544560144697842282547677965958865873924009049840449265122527450897; - uint256 constant IC11y = 2724516316035952928352656968720561599106380710401940450252385609550641895905; + uint256 constant IC11x = 21722979850283689312457149615911951102070483117187707419687509883557528229724; + uint256 constant IC11y = 12631428830081777702977793500448863584294718325066681881436933861921735534957; - uint256 constant IC12x = 6415803768033221091455097928212215437695034131747853061147487425545026770551; - uint256 constant IC12y = 16246443751013967544556252590900249372263924353922568489267825578174001055; + uint256 constant IC12x = 4213751153858869170897807199037433362203968810814722651333773235333110630864; + uint256 constant IC12y = 16122011455192910143632741314231760101414290432223179448777617803201467621504; - uint256 constant IC13x = 15362136016566638974392387943924303320566554984973627142090315874098276162948; - uint256 constant IC13y = 12045497701488042756223977093441513681724756561681694654028210754872237560091; + uint256 constant IC13x = 9554837226992446701228515303642079637807357890017383384812440314038449036838; + uint256 constant IC13y = 21278693557448139173734004799254900498966524290247139602851908625613299172864; - uint256 constant IC14x = 851199703448569646817260303478184435364430795694990453617924138405538051073; - uint256 constant IC14y = 12946466316772451490596102009978657497675437325340719204986803177959608723364; + uint256 constant IC14x = 21776500713311364990401539077316370261564522412596186807180057925462702413253; + uint256 constant IC14y = 1568240173320516553013947629299718284044658941775257081542601515693979514240; - uint256 constant IC15x = 32697875031995482206558610095285352816496757317111207419861004689639953522; - uint256 constant IC15y = 299944843066286224755462589381457389641818411976194173762533229362772488245; + uint256 constant IC15x = 21564273127276639904217256917910112212934525318645740398461486168827007311543; + uint256 constant IC15y = 13966086613725475985651402580739572931083145387135567185433524377871781733319; - uint256 constant IC16x = 7813691748167190362850964237044883316155748259819716238134403668032515123276; - uint256 constant IC16y = 16204491922723545729259832959950455311755157458533342319134684244887734211089; + uint256 constant IC16x = 5814620384816433324722377794717911120049565607978997516640971611103253573951; + uint256 constant IC16y = 11257037619337374908153737141021522383307369817181402888470764219459897276361; + + uint256 constant IC17x = 19994952937395086016308786261883552107726289076502224155095304083545548173808; + uint256 constant IC17y = 3001631091913078426548462975826877675412536962038521582563185880104933764982; + + uint256 constant IC18x = 9191783136958454841559750054191334746979556656626644038950166417489988792934; + uint256 constant IC18y = 11880320083627745669929133143013437330294790783517525604948234660913864147042; // Memory data @@ -101,7 +107,7 @@ contract Groth16Verifier_AnonEncNullifierKyc { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[16] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[18] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -177,6 +183,10 @@ contract Groth16Verifier_AnonEncNullifierKyc { g1_mulAccC(_pVk, IC16x, IC16y, calldataload(add(pubSignals, 480))) + g1_mulAccC(_pVk, IC17x, IC17y, calldataload(add(pubSignals, 512))) + + g1_mulAccC(_pVk, IC18x, IC18y, calldataload(add(pubSignals, 544))) + // -A mstore(_pPairing, calldataload(pA)) @@ -264,6 +274,10 @@ contract Groth16Verifier_AnonEncNullifierKyc { checkField(calldataload(add(_pubSignals, 512))) + checkField(calldataload(add(_pubSignals, 544))) + + checkField(calldataload(add(_pubSignals, 576))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol index 57fec5c..8b476ee 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol @@ -43,173 +43,179 @@ contract Groth16Verifier_AnonEncNullifierKycBatch { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 2557045328174556474259602364787060617413037186775787740247120052256591101057; - uint256 constant IC0y = 8545914595700052385922827053758169584458550417191596397077967009342340172963; + uint256 constant IC0x = 17504848062868348026374002498224723996748756089276549138002654517982016255538; + uint256 constant IC0y = 16387507367412557460257377765383794801476813095817061623259001184927071106034; - uint256 constant IC1x = 8900866652413972639447801185066566440613708319253275484468074220706268630752; - uint256 constant IC1y = 18117300326867814101825535845382858738704176302675336121313760471944027618579; + uint256 constant IC1x = 2856069502693004785127392038262393497974744695634372998401820715110377580575; + uint256 constant IC1y = 15561059156075398193317869131598022491610304991667406081651699520146364765780; - uint256 constant IC2x = 6893165486528724258452539284348100242940680901205710094027141947523508922556; - uint256 constant IC2y = 11428083713288237383922201052960038086381204628185844551802602980459665852296; + uint256 constant IC2x = 3859389872830912436200600964789102024361491814219596610803029929946644931037; + uint256 constant IC2y = 1379316890215683508391001779822326692301880648522444673041390804439970054068; - uint256 constant IC3x = 2787509042012632529212775966824220639705355486752580713355548540317374958318; - uint256 constant IC3y = 13559075319591979484148387886304036951246196260874348065387705986067180861572; + uint256 constant IC3x = 8415946265759935198667780399036578786314201446216726794902855492967332252013; + uint256 constant IC3y = 15809101762048384534955622139547502714750399693643041128184833018326642991512; - uint256 constant IC4x = 7981603848980165083052696916252376820361500997039057002907078064409646042704; - uint256 constant IC4y = 1631170154333774225978701321671377089584774646241757146636720110297678397686; + uint256 constant IC4x = 20535800429315416894612599549205808164074195628326052033986955795418689069905; + uint256 constant IC4y = 11366931152943347478625131981318793312836195302128744391498974801567323524615; - uint256 constant IC5x = 2718945106954835265374519388993004950467939770842588234333099827036921488036; - uint256 constant IC5y = 54129075547188978676123602750315602783350522469912352491032758031739397264; + uint256 constant IC5x = 15829477644400158320246641877331704309264586925310327196539914283139342353644; + uint256 constant IC5y = 9934659057803690299249584984817022967602349279267611443853677220761678388542; - uint256 constant IC6x = 10147624070030089461943558234086476925326752621677677347469962144928874051171; - uint256 constant IC6y = 14137637656464541694095908034649703224311668569886704894187366498167267119930; + uint256 constant IC6x = 18918146804733231422333304863438872219739334678962399068661097122605973950262; + uint256 constant IC6y = 2343376008553314523127702902049483169606988764179316258282911398991407702768; - uint256 constant IC7x = 14131833902483915573002378883085094517189637884537825125543294251780418938907; - uint256 constant IC7y = 8350712732464638756493234130405621139170404316430682690462953318721564280425; + uint256 constant IC7x = 5231213558934753070201601921131975968358823135926337144767682276145542464989; + uint256 constant IC7y = 4665602492217868979300129137374085100174413837649811540289188169123300996478; - uint256 constant IC8x = 6466504309236504330936004664742363699367258661498527049422417011059950380261; - uint256 constant IC8y = 10308743258353094916300411811569013911785525949453696511480625272875805213094; + uint256 constant IC8x = 12336799161694575597638898320521434723260248461665346045536341492377334909750; + uint256 constant IC8y = 4637784107473356705217888916047150724972967899841641299327891030782008485610; - uint256 constant IC9x = 15034560127374538253652390881068026376032149277012915824928102233595801597871; - uint256 constant IC9y = 14933364448090705000296248910019334925480794867671226328859117405842595498286; + uint256 constant IC9x = 13827078590544495241328131801668858903611645676710343835547244977983692125329; + uint256 constant IC9y = 21410062214257392592742258923502999657896516248971868238962723630823346174229; - uint256 constant IC10x = 1435567384244739999636752756588097453785728405750034036596678824485141706320; - uint256 constant IC10y = 21045412560666440575260065642431316733861600716932140912086713771905478605642; + uint256 constant IC10x = 16648148804443180403693863299061946840717694348838543762562820313123418826667; + uint256 constant IC10y = 8195801067000683311584686635958018789966651244321576016528996434560391429285; - uint256 constant IC11x = 20660910050407044985841964548615754563198335468098466571354791341814009582143; - uint256 constant IC11y = 17161276760446539174103283658490390916497070640753169765510233658752644125327; + uint256 constant IC11x = 13818449178804543430163997020412248802763660211216674889312893590596745982432; + uint256 constant IC11y = 17048611745560760119354806941150155291932280127893448128213081928960037394954; - uint256 constant IC12x = 14297221549426245599275426280912312242758539460442195637765479076821005351090; - uint256 constant IC12y = 7045746153755160132606239721075319853671165146167794961048168331481327369378; + uint256 constant IC12x = 18033428927728964864971192997985346363885015121354210336522092315091747298594; + uint256 constant IC12y = 13365128640778017290772474101327304322106191025175089654914826009997183501245; - uint256 constant IC13x = 6709297759563652448455456777394655766655295904612361150672442940274698264117; - uint256 constant IC13y = 604939571031743874843375836514454028390240836996444630147060119881962118591; + uint256 constant IC13x = 4017576198307072663210157991121703896022494186654317864998385350827601491277; + uint256 constant IC13y = 6717755372091993174391999198308039571277228379267328284322681839457836069352; - uint256 constant IC14x = 1506931283257291434315981891710633368372940860477458257990053769650899625020; - uint256 constant IC14y = 16234509187615275824159269295900874844499753487293080637471224460931211356610; + uint256 constant IC14x = 18951077169344637293936120179113270077592805538523267528595076165889093420379; + uint256 constant IC14y = 16024951146607749589423441411795299622228655287243270569258657281947614692069; - uint256 constant IC15x = 3663986373923028376047433528346986422113085036111303782126649588832018217222; - uint256 constant IC15y = 2833212771516071304842292770750586061301584725053640822674852019170921553978; + uint256 constant IC15x = 1360708969957543383913365577994960778540930930157623031832678872345741108091; + uint256 constant IC15y = 19188784503212735203818937702066709460520133020564105345650189896442261576792; - uint256 constant IC16x = 9441974398462151962861519019668159526029441202966112923894683419951453007203; - uint256 constant IC16y = 20398645667686807455795531059467229874168827249918904721471455262548811448301; + uint256 constant IC16x = 2310084532603556369969881218026228249965185308444498344685656131291285072090; + uint256 constant IC16y = 2684005466847837835929849832608810195680937122019646046234472921562603046979; - uint256 constant IC17x = 9941969049637054555017138554864083807451665108028251180781197146279496720189; - uint256 constant IC17y = 12083041856346926425137954851405721196793285382115647784815644983516676101313; + uint256 constant IC17x = 15033210889123591887211381884005556788119507851747650399577670617675067962985; + uint256 constant IC17y = 21635465298217685594774739863370705370837990509418620255911645885375058632522; - uint256 constant IC18x = 4513953042000608174347593715577667089282919422419113365380162468063688775130; - uint256 constant IC18y = 17768548800782673039169889569716085142981878050151504480878715449322827273410; + uint256 constant IC18x = 20964847427539155244303558143809704974415302350648268606966770643146458239040; + uint256 constant IC18y = 4976852868551769830359648093452564906077147425657133752050439032094469178040; - uint256 constant IC19x = 12249598222891158199710492081231845984159762606864132240852548984852903893394; - uint256 constant IC19y = 8218081839064592605577365459229129812592277515386687488909134942995986616646; + uint256 constant IC19x = 5954934735275902994859735641635771081547956714325915040567497876417048394143; + uint256 constant IC19y = 12342305689282435518046032667069855834926960332665248810505225445852009809853; - uint256 constant IC20x = 6813471708188402912338247638719280180144768836532653959906749755180831733701; - uint256 constant IC20y = 10630452899956666539442022832713171293838832707279857274903723291215504725074; + uint256 constant IC20x = 17941161690977931098269864811397641132700593252578476448070438328580593719549; + uint256 constant IC20y = 10992171856448189204497970359711415772839335327634080553352925596600238931744; - uint256 constant IC21x = 4645195348559291511944588819754123347451366573885154192985637448206304620124; - uint256 constant IC21y = 16766206162461102255042753211815836900424951725074557637817692932957001273876; + uint256 constant IC21x = 2425648535044684031614952373699012963219840911718726909909891256136645080412; + uint256 constant IC21y = 21518967218854415204283336476228379728243999731939483558032968206724325807574; - uint256 constant IC22x = 612198738216091583770089992329981011003570889532673265272801632641592335601; - uint256 constant IC22y = 21009776677696441122580148742821355608472017491940177896149934304781750294343; + uint256 constant IC22x = 280260936926782546013980159100142770253473969473128400047541356265542999741; + uint256 constant IC22y = 10134098037208287844145086332209993231553540105278897499267027143835982878853; - uint256 constant IC23x = 7845708505520385664103122252124442232529534143144281637399707935968372058244; - uint256 constant IC23y = 15192802321724721965923896418287287881746337425062951377408799115613924493192; + uint256 constant IC23x = 20630322258542475647304370850837690639747200948464440858494114988984663473167; + uint256 constant IC23y = 5471360679957290184735041392000798787632877792653590599469301208859338904086; - uint256 constant IC24x = 11044743356250821069784980936566426424857876182337346673003368733690232366513; - uint256 constant IC24y = 21968542138387545717894491159110633336985278011066255264274935509925404276; + uint256 constant IC24x = 5111371584357786162832771597844547131550671201855188104706039744961582660796; + uint256 constant IC24y = 653040201219489798026416604261073895543507016306735716151353126125677369141; - uint256 constant IC25x = 15739104432512218764744514918039053175648927736786942938917098136624846456654; - uint256 constant IC25y = 11473837237244115867873717433248212843653746603581652183709166795371859623666; + uint256 constant IC25x = 6978336124426926881856591004162044830754073908007920213323571023785613542961; + uint256 constant IC25y = 20414386314498291861276120712979377062332720562156578484901224643232480540249; - uint256 constant IC26x = 12659745779361797715321216070590036668890759442977154045015864656515913110821; - uint256 constant IC26y = 15436857874387771595832460190912333282587447051076428904935035331068995068691; + uint256 constant IC26x = 16345303897992857692859745636449950638729953287455034304026858435009952917186; + uint256 constant IC26y = 5878643236005185094442864082149593891339348972501610978330490869945951001658; - uint256 constant IC27x = 9203173977602946543016875848991349465294047894411764290600412715281184637502; - uint256 constant IC27y = 8557329422378274647247494844347551526466632349826006833910662893194934281525; + uint256 constant IC27x = 17523481398586847238194919850947265455706770941799970175927495066504128872273; + uint256 constant IC27y = 7471700472916472025019136320781313792713403580172746538799171676063158368084; - uint256 constant IC28x = 21043592517032634711239990905884702982054744461304587368835062757863764173274; - uint256 constant IC28y = 1631750092321340715930642498551502008794205048320252109690579472702482883693; + uint256 constant IC28x = 2094161036937708942704900106707404659693176539918526900245846886917959088539; + uint256 constant IC28y = 7880341502494899999695463060452869823744265572482012990875757815234964862638; - uint256 constant IC29x = 1965593797962209845476914161340324215049454355711575611255794847486588198621; - uint256 constant IC29y = 20420112496369531484716420634051964705303428701409013107809743921895693778420; + uint256 constant IC29x = 12227797433782018797845158251242806466077383214640501764299030787081960976752; + uint256 constant IC29y = 14223507300666949267825712869946068457643885067211133573755649286573564767881; - uint256 constant IC30x = 14459258316049621520625093813598405781231837198148192657248564100568126911436; - uint256 constant IC30y = 4189670097301689361279714226734357198747625987495488973380038361744870962865; + uint256 constant IC30x = 453540649793160026316799015062804977909721800597914418509950105119312342297; + uint256 constant IC30y = 12324285493695239709623854660026174408162078281863628396002540780982541880744; - uint256 constant IC31x = 13108879096940415310362336426378117914756114957855406964927612281735121697971; - uint256 constant IC31y = 13922315068161235910520981793423554652810239633897980696104312477364323289837; + uint256 constant IC31x = 5580542283201294383971258676804392634747059901485539537837867891173931906725; + uint256 constant IC31y = 18893651463971054272255885924027852040285006550612275136101519628602670404805; - uint256 constant IC32x = 3672774723765929810525726446377577070495042440381259398721824519467692223036; - uint256 constant IC32y = 5504189137877852784897136813364091880095479448638215793137890720712833089772; + uint256 constant IC32x = 16053348515324942000894930414520400209998037357589282973515627559839553719937; + uint256 constant IC32y = 18721430601727038239377701583956253836579793295356933421370242456531250291255; - uint256 constant IC33x = 17130781702453148735613043990802970337134477759322098512883706161057337504002; - uint256 constant IC33y = 16351907669841445135205102522017369314355429337431004692059562467792755202730; + uint256 constant IC33x = 4207348331894209505377454332648293135047961513011552219208614177339885764996; + uint256 constant IC33y = 15578406702422632993441451980677291008648229741735120457430480166703313489087; - uint256 constant IC34x = 12031667235281243664253700834599818547380367496538162959699982743848078891598; - uint256 constant IC34y = 6616306445409952843359602511870642177994574094251005373437394528227240955856; + uint256 constant IC34x = 5638734168306965054319883075296665200673266975989878680177302242980003365757; + uint256 constant IC34y = 3054907442264710302362313978881788880782770809199005375546833629175395917303; - uint256 constant IC35x = 10731123795727845951791321856155816019889142705311580809720843346374187513971; - uint256 constant IC35y = 16068650898493671048010070098850477199748100710010759421745286594693280298357; + uint256 constant IC35x = 5861570516229947654739252134966410588166542172364647012821598504829520960520; + uint256 constant IC35y = 21826590176415498013503020647935392823956167012515420325697166485087109341456; - uint256 constant IC36x = 6502894893010883942423075381722837038696334248009036389776781991138833860268; - uint256 constant IC36y = 20790809673001992281463007604198705518066093384563083477497988619198326219881; + uint256 constant IC36x = 1163146016516187472740589974531980564637857783215779188095003814133427992849; + uint256 constant IC36y = 17100204026966532131401470450964759258544383909937911336093084512571070125508; - uint256 constant IC37x = 17893528808061411108476748553695245038781846398552576836224230715924125892190; - uint256 constant IC37y = 3396165818344392654074158537612720431771510878758650774669727330733546082337; + uint256 constant IC37x = 13527708705374185300712814674442001942903598446797709282125997239238565392928; + uint256 constant IC37y = 8474355221953601073926090123462985374466496924904865143135852117705069140058; - uint256 constant IC38x = 10897508493118616620048369575610774538686816226070866208104945341887798715990; - uint256 constant IC38y = 3477357433659395048329281632040211062291869085580053535523965138254126524307; + uint256 constant IC38x = 3808640281749836669607683401869874661662588536151452683315635118821978939890; + uint256 constant IC38y = 14861507266593989874827115625593671744007071304920501849993048803704385010084; - uint256 constant IC39x = 6232305602842554721699996063058147937412901964622386302125531286379410216341; - uint256 constant IC39y = 865167260793798759680935843664150177300892974890677439296402891134136533334; + uint256 constant IC39x = 10194236907116302439622331517082527947776970543332709847028804137863312401718; + uint256 constant IC39y = 11329005164482137625321319303919030985281584614017669696906810224293393629880; - uint256 constant IC40x = 1896700859908460930091624595675776615402193748854462019745978620107291409907; - uint256 constant IC40y = 19538419883460717066552832903405877575081999780942435734967867221406789589399; + uint256 constant IC40x = 2175048060656940005354125903390105829157228568052786493865600961302899409802; + uint256 constant IC40y = 20845091066389805874005537483311906148961944629004027128749165572499641740969; - uint256 constant IC41x = 919917946864295765320845049317324032542470918660595400102049568313393745259; - uint256 constant IC41y = 4905312417092777244239947166508788614667233335337264831713809305929873826211; + uint256 constant IC41x = 6513207037911904919854905415439872520001395253442037570879540199844544797917; + uint256 constant IC41y = 21768663552313415329491685534136927428823171722456684854961607216944874160246; - uint256 constant IC42x = 11260058824584772528807061119314472338786531909501746400162839164183738065949; - uint256 constant IC42y = 9692558976165758378143630277186357355884473671639921608383879688904015447492; + uint256 constant IC42x = 11143666812126252087435576182566526363905627516668442800728196103096410140946; + uint256 constant IC42y = 6535255151577129566349664645385780221288149031850600269892969667152281389934; - uint256 constant IC43x = 16500664765246509026092343746736878544449617806107262161088710179454171005068; - uint256 constant IC43y = 2318970865336931978806827275921781650216283891871191849842243055051647241566; + uint256 constant IC43x = 12216019667254591633256543770210142244306955316534898670848792497815288748407; + uint256 constant IC43y = 20932736431997402628568150442959172684450592121020005476297963810554983857496; - uint256 constant IC44x = 15266083558060117092889105437693230282542989249077821947771936425702618705353; - uint256 constant IC44y = 5933912916741823626580572218992545666034550775510312837553273107032523100335; + uint256 constant IC44x = 5933919850098763144777134426689808617420104756103652617673006846516543746028; + uint256 constant IC44y = 1846818467291984087215401520026387243511815581026231594023176708787928601743; - uint256 constant IC45x = 58707545314175203397280970210969715660178168988171479206762359173733595778; - uint256 constant IC45y = 18337733572288419475605999960151866998282044219653232437655934170784662568961; + uint256 constant IC45x = 3550325488317807172294579797915663005069767530335953601988476431803051781127; + uint256 constant IC45y = 19986059169930216696958502893247191080629716230489353335542951478141806211020; - uint256 constant IC46x = 586233669714266072235077089672820057713553723712257638939984508768691446266; - uint256 constant IC46y = 5805420287012844261801028660062719860928333497295759197250699480287517497513; + uint256 constant IC46x = 11680897079617705713544415674593237825122414254090279751291301975595017258239; + uint256 constant IC46y = 7192914150142927503252523063820936177103915826937857509316891503321565576065; - uint256 constant IC47x = 18533811404590119489507085680888268159057504006917018635283187815937097547211; - uint256 constant IC47y = 4105347632669743236449600156045402810957294409584662993772317423421882395967; + uint256 constant IC47x = 2194944632260890612597133046164513345176661225427381736733616125225090009231; + uint256 constant IC47y = 20125380079300917290749136763381143149180127581158653088913932492057416883412; - uint256 constant IC48x = 7963255695223444100125880939097224728146759221469423275545846145917825941948; - uint256 constant IC48y = 13512044941955473329651037303898509853731877911390554418237190804988526456008; + uint256 constant IC48x = 14422798646426772067663722833900085260897269980290313415292189180250359352601; + uint256 constant IC48y = 771703103591355791449427823813448842147352355458537942689020853074754641443; - uint256 constant IC49x = 1246040208265149753842480934506849680611118792544861176402750181192234961189; - uint256 constant IC49y = 8563441033219483164633277222289522857294420978768986809528993427373045444984; + uint256 constant IC49x = 14615753219316385282263522991969142859295978879684495081642174089355734612047; + uint256 constant IC49y = 10726284617382468267788691700905497860909038954300000561095095525698258734795; - uint256 constant IC50x = 2588594350644268564085849031861239502254810392738869347650201531798451495394; - uint256 constant IC50y = 15910783489501827060267126604385240212657463315742131285497095914663726625032; + uint256 constant IC50x = 17101999512384579394851655687877848773235007944785753742455387481074274316188; + uint256 constant IC50y = 423071507367238120356829746625486510755573336530662107346332180257030287264; - uint256 constant IC51x = 13536358811202144933899812454990919546110622582416000445508880943657060919439; - uint256 constant IC51y = 13636439389086566021867409527624225391658272934816689794906398506550354679701; + uint256 constant IC51x = 9792926841156931454106301139947287811673122135247907827156714190812449701109; + uint256 constant IC51y = 5970908732417123977436766989527347543081758023388968529325238154277565717740; - uint256 constant IC52x = 3069052660704238265078596844313226533136449247403800942357593600286959491284; - uint256 constant IC52y = 2851907145042254355715210427589229005946148117819918992483522956786765330528; + uint256 constant IC52x = 12706145721666739923414163788987123312746958734319163889121620419699709488765; + uint256 constant IC52y = 4306164917367554262618109318601467317114306696451610147982033625958115348490; - uint256 constant IC53x = 4532058296252955609362103735166225278277027937093609645966321436167953753849; - uint256 constant IC53y = 16885038322595100901701279116331564344696993077930991807708669198697751982536; + uint256 constant IC53x = 13221349951903657044803747239233265785265507566859952375028444203437980813346; + uint256 constant IC53y = 10565134479636684577025748158266609122295088659249500688010380999868051230260; - uint256 constant IC54x = 21657088241609806957806596139919891483933646681016763066971961683666639010914; - uint256 constant IC54y = 5540503589899208339201031551963806514853512880214799648245011777415136792427; + uint256 constant IC54x = 15936621239909675935495995025933386182121678876586173688942468329781025961453; + uint256 constant IC54y = 8675648856225262437745421036662111826559370347795735779137840613949393851040; - uint256 constant IC55x = 3180572821870628434033407206819005535080638863627732738600363337929557825472; - uint256 constant IC55y = 12213704425579070357451089645113850518215300513830671326650618723999697008004; + uint256 constant IC55x = 11377869237069746467451540359369426085441126079383682910319711789669692949250; + uint256 constant IC55y = 946844900758779719927195974669359561147197227462088657885137274383506599072; + + uint256 constant IC56x = 12391847394251081516284908202445344119027771364094180939362656437074203234144; + uint256 constant IC56y = 17991701997444862400258460727205796587715059621570231928646294725920133917550; + + uint256 constant IC57x = 19273211338074274131409088982613123292043184587862073818414163136972356711192; + uint256 constant IC57y = 10596141629335780563818878207994516764687494527269573265381148633833675620704; // Memory data @@ -218,7 +224,7 @@ contract Groth16Verifier_AnonEncNullifierKycBatch { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[55] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[57] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -372,6 +378,10 @@ contract Groth16Verifier_AnonEncNullifierKycBatch { g1_mulAccC(_pVk, IC55x, IC55y, calldataload(add(pubSignals, 1728))) + g1_mulAccC(_pVk, IC56x, IC56y, calldataload(add(pubSignals, 1760))) + + g1_mulAccC(_pVk, IC57x, IC57y, calldataload(add(pubSignals, 1792))) + // -A mstore(_pPairing, calldataload(pA)) @@ -537,6 +547,10 @@ contract Groth16Verifier_AnonEncNullifierKycBatch { checkField(calldataload(add(_pubSignals, 1760))) + checkField(calldataload(add(_pubSignals, 1792))) + + checkField(calldataload(add(_pubSignals, 1824))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol index 674d560..db4a35b 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol @@ -43,107 +43,113 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 13357693122907037228152017576645355734121761212845151058677661103609163192132; - uint256 constant IC0y = 13330988885278369125767434338537639082919338469462771561109770926455996769780; + uint256 constant IC0x = 8571612681709558591409185853049833232841945740979669245942718805770032380418; + uint256 constant IC0y = 4189972351843195639401511415729412827254667296452453166826430868050312666905; - uint256 constant IC1x = 12508620784608380390196070593153977553849768584303191369350347694786774228903; - uint256 constant IC1y = 10497463660231940953738699560093225567814393547271993966494372800288076113838; + uint256 constant IC1x = 4163740772828829266948194278669903507270319410466548340505259749580941875041; + uint256 constant IC1y = 4119446895718161137464133993105876329337486109593397680414165178003511399535; - uint256 constant IC2x = 13358213132064408118763369803680465216756629096152358454643353054476790534; - uint256 constant IC2y = 9790361827332836718478767131585804431439300890195490311537005578986541483010; + uint256 constant IC2x = 1076665331615643748649917182793093461933091169232882102136380819852321722787; + uint256 constant IC2y = 11284503990410994128723740643198043818221559941282509486314256803757489591946; - uint256 constant IC3x = 11263096887435970836664030639381921541149000469179795739631740020273500583762; - uint256 constant IC3y = 18832878831913866337749700133052402021364972422929250752553120232017053832188; + uint256 constant IC3x = 20720114473613646302534567518924514429086709487011736661545515973142187548453; + uint256 constant IC3y = 17881405175937038896607983645804770283084154449564661605735065995699141192505; - uint256 constant IC4x = 8650173660622548339501740890775948467326563125469871933001838882801234078865; - uint256 constant IC4y = 10759885712046409911388806010481069590886057315469905475498658179072397221074; + uint256 constant IC4x = 5058311354879615329327412393999176658691695524125090568857298819368005651394; + uint256 constant IC4y = 7506574827555802057910760574778092163919955480247054085361894121784002252830; - uint256 constant IC5x = 3295412410302077166334358912280077543044124527280728553051328605050569416328; - uint256 constant IC5y = 17049453399693780313254529273986739520322108517619709180649214354472986470570; + uint256 constant IC5x = 4284934050995860133235888204711867898087349447121328188587245745046901467086; + uint256 constant IC5y = 18042265561341689884529821061557150842299623224487371136883307679833549634472; - uint256 constant IC6x = 12760717566528938207556281409639493742824102965038241868422088472886397881705; - uint256 constant IC6y = 5727694270117362054335093381846045971004329934011468049227701728188501414293; + uint256 constant IC6x = 8436223819170601999808340736212420134796433124838266991859940948334516183700; + uint256 constant IC6y = 965469023392244424047133803910012874468660808661173287907624735824491612338; - uint256 constant IC7x = 12723277170340368996181883999061862932296128028814086233379699010714790157803; - uint256 constant IC7y = 15607664248618872066986748206455003464688091118493663837165373679303271618020; + uint256 constant IC7x = 17588366209171655946560951185513081113173736203853793660486480146448415654591; + uint256 constant IC7y = 1192465391990703989331087184113754948028256726783406259933657503974466671665; - uint256 constant IC8x = 16064173409510828580097158127999109660877176304290893887184870102987627587345; - uint256 constant IC8y = 7271726669102543421625318962122042361029332639092998786351706825402022983149; + uint256 constant IC8x = 168966490099400379038975776147802839111482559083939093660476845657869053000; + uint256 constant IC8y = 1234470853915082062457367730786282590549318011417803333419252501540769751197; - uint256 constant IC9x = 17868773711481907952191801046128922109639466718556606579429717630927232401150; - uint256 constant IC9y = 13426021423653145781149475638806424172443891179898547974414561873835013472273; + uint256 constant IC9x = 3709604944634147209334455029878639800199471874775000621752061808394762166395; + uint256 constant IC9y = 9146687878469641700004378116117843217732228553171960469531573926524537911901; - uint256 constant IC10x = 17231713394258993279280128626680971151901806250026905329830445951311024978649; - uint256 constant IC10y = 16362220893399236364987780855448702890941734166928744916454228037419247631859; + uint256 constant IC10x = 12725725961256189035553204906513379120207000192517003228780502858372555519592; + uint256 constant IC10y = 20292338833910734262099065452288541371398942933488897458632976213407533951394; - uint256 constant IC11x = 16393437699418494278442854388319612745568802642878330160854040391387533400112; - uint256 constant IC11y = 13190069452272446793436396301020962811004079465757898954271497706698165528700; + uint256 constant IC11x = 18955639050018384739189429546452452431567306058614310337052018081807684495533; + uint256 constant IC11y = 3304188715918731862810019389584924243200498693827699728455473963148534993495; - uint256 constant IC12x = 7378753764477002577496984973794709537014547695465562205837932080193227331968; - uint256 constant IC12y = 14590455657777965484775453020094930760042823323462890204601760753586004282684; + uint256 constant IC12x = 18175421830211350230098848584803964644934745149377427048998467617030485113172; + uint256 constant IC12y = 14516289575097451038041879045497099667944480990058270446604032532147417160386; - uint256 constant IC13x = 7997905266075296348375184091609158476322609729212752317911559367095944799223; - uint256 constant IC13y = 5745139122382514585485874184483029362402802135720894805094527346018931663747; + uint256 constant IC13x = 20703913633544089237739676885979485067605692382925341307919172314076756892406; + uint256 constant IC13y = 642930538082700406509620387268174629787369194800127820783409323121394077548; - uint256 constant IC14x = 20169661212830681667121989012648338854355631560185391751223605196103160164011; - uint256 constant IC14y = 539780066201272709523495794614709990166877660139080643626983915026896119607; + uint256 constant IC14x = 5011985779844308735211947324326280728516252153066838956403905029573499193895; + uint256 constant IC14y = 10890146971840553265423526563604361341331666839182598881878766582517239983251; - uint256 constant IC15x = 8444655896238788895878628117268993903133580378477751962708257842437863740785; - uint256 constant IC15y = 14733855077207271591160962228017111069029157259271107029728347242748253125366; + uint256 constant IC15x = 10821352802689599315752371964308636751309190981228103389002201289657631324349; + uint256 constant IC15y = 7196475991672579618238102963540480092819420293201416958700828001607337766762; - uint256 constant IC16x = 6776365740560628275599288528214364007667844204832291628305205207440991363958; - uint256 constant IC16y = 10701762678011603715205160753666433247040031283169837460596997733566638035138; + uint256 constant IC16x = 16200509200921126318540421002813270144204087623594429819464886812910956032273; + uint256 constant IC16y = 12398863974686923220636271491718432049670009085477532893845695959848586110538; - uint256 constant IC17x = 20686935058199339354516949529825885235552968174904347091970372091458356050418; - uint256 constant IC17y = 2353883119734839433183501301793327525159037748688825810403810896910943236417; + uint256 constant IC17x = 3722494493562374096779548613322724174942518073757700482997308659102304388980; + uint256 constant IC17y = 1266037034894012479954726512477114287010783787937671206541425973092739793928; - uint256 constant IC18x = 10350893931145787572953344205303374116068374532338249687895170827700639749336; - uint256 constant IC18y = 14640813458603050243659774385299057516762787203076107453683687533882345081521; + uint256 constant IC18x = 14949633667701557044321074055882819212965657262091409079548889004592979056224; + uint256 constant IC18y = 4896877872529145361529000973306993006588200977028415965890239754111837780610; - uint256 constant IC19x = 19262254897475671623941666812023122929903981731944691423683488712448697081937; - uint256 constant IC19y = 18281492578904896322558724606234848271289139471406835707367843671116366444087; + uint256 constant IC19x = 19600655870806765152484750663334645204399011582493937511443218392447908725013; + uint256 constant IC19y = 17754765216538248708160638759828253274305335189767407100129601709943833446645; - uint256 constant IC20x = 124678580367106714324365512313981313186367450591290500393061028606175892723; - uint256 constant IC20y = 19622459168604563104848042405466516563770600657501108965523163775411098672757; + uint256 constant IC20x = 20500642209489343563675058328337586996965591983608904858579339496029535993114; + uint256 constant IC20y = 4013612443393979029985464677605180813213756206695459820247058152658294141186; - uint256 constant IC21x = 7958205631716894096124215035454651749998590123970961934398635953991688058318; - uint256 constant IC21y = 16567031668980761134299018248953094686118944235178042185849152200978184065876; + uint256 constant IC21x = 7845584120307877467433491117843293698555121947251554311374427191080399715335; + uint256 constant IC21y = 18711522093316415746857079798828891651730762350856485483697348191660532852948; - uint256 constant IC22x = 7147067657100593571638515910794468040722620253353965676612345848072450126796; - uint256 constant IC22y = 8323724847034448554879418517026785309068712740584276122197233489445879426431; + uint256 constant IC22x = 12527418680107472024559886062863784854086212477370792890464899129756012223359; + uint256 constant IC22y = 14485094404442660396587300748219223593828251711389859449675270566460567859630; - uint256 constant IC23x = 4475661955736946565036382810587106183520552266697138427686452731078117767736; - uint256 constant IC23y = 748082566430464216825026197955511509465126173616326433623980484101730257065; + uint256 constant IC23x = 2374481620185698836020312696466603934621248128981543987727551892572305009444; + uint256 constant IC23y = 3107640763405757286345011943165042777559207875175588446352412264129435124284; - uint256 constant IC24x = 18871094629535557959761172513178206026645275580390985276286511649250238153689; - uint256 constant IC24y = 3733404107218228733942648054164246626605647007073122795923180610554195384488; + uint256 constant IC24x = 352836510995482130410749321611349182913869955181037073971088654324262657538; + uint256 constant IC24y = 10575715137538690696679961984361209302740638120913882703031704359365094149120; - uint256 constant IC25x = 2384341917215847801652641900530474605831147046585978262725620402385796765901; - uint256 constant IC25y = 1287779897102903993979483791221014755426631277038764827254149422137772335222; + uint256 constant IC25x = 3864900267012451409819388180515893211458404339871060710177620481064569630228; + uint256 constant IC25y = 641317257750219804481626218147534142962247182372429704342221253818145479534; - uint256 constant IC26x = 15719716565017700920545871521869872133915063489073625817617400592054712067072; - uint256 constant IC26y = 17002113594755025448330507151173960578194214614717460071129326081566116414394; + uint256 constant IC26x = 16079626542421778998718365530171073924884753502101679935783606660432640673050; + uint256 constant IC26y = 12610874584620513420871225487222612101246696013526558071069853825308942977472; - uint256 constant IC27x = 6069617218858857906572692060956455933260615226814802013802199283144993419830; - uint256 constant IC27y = 14473506832002574954490482003760587485980065730322794298209159874969554193911; + uint256 constant IC27x = 15564183914008527870451816263430121365010910584399326747649241522998927982710; + uint256 constant IC27y = 9310727885966353124231888075067724840862534920133017880046124759395997376119; - uint256 constant IC28x = 2095872993541208595971848766255089085389698239862455369992367968040560542101; - uint256 constant IC28y = 4401957738071377442795776346853489896120525690607490420740185454723130517217; + uint256 constant IC28x = 5858868713515319592309521711701051336825077256643072256184630439606079470243; + uint256 constant IC28y = 21763693642515833043829823082891009326312542712282974539414548933954053972366; - uint256 constant IC29x = 7948782644008604365957640378662878722460387841213619643734690098279143596558; - uint256 constant IC29y = 14151027007218971202754362938797936052279026613643428871705306564386243582804; + uint256 constant IC29x = 2267072142710394267785251333917023575138580220304645280510759865233629259514; + uint256 constant IC29y = 6847574567340777057974207710090179891213211101510895215166536480521144684536; - uint256 constant IC30x = 16055935718830733652525145369258352251162204565999270815122069851184919247791; - uint256 constant IC30y = 19977921078618552717906884259146829610529552736713600023585181237533888275450; + uint256 constant IC30x = 2775387542501250317450085465990653835994847735739342327610585386819314392309; + uint256 constant IC30y = 6496689167510393229055140502702806194342807614260668591022841589821989278326; - uint256 constant IC31x = 1724644122707053931125669268159636051378467183669651442417045949735792435846; - uint256 constant IC31y = 3780427308194609121900455938646860005350278871116671233301051665551523150347; + uint256 constant IC31x = 1720127258124102351023626080697799543086781758010538392575993703209842655123; + uint256 constant IC31y = 11464393770291359854991381353189019086430715171543842295218850565441402138453; - uint256 constant IC32x = 8043820203766420431969217152893413732635117572573736920587519044322309584347; - uint256 constant IC32y = 7641739641928705768386491515124236050049577395892226047572150942224894388223; + uint256 constant IC32x = 5775340660326796190718199400618054551012073967006234068471234008078886524131; + uint256 constant IC32y = 11492423277455925604320894185275809923924417874855079451325251044107376402058; - uint256 constant IC33x = 1212239584949006580410344651147309255656379781955714183101293673886799379224; - uint256 constant IC33y = 7277339251039550149206299004468645563322367249804601268562416695922597671900; + uint256 constant IC33x = 1883989236545183396911270005628214060507716233705894981367212667458226321188; + uint256 constant IC33y = 6285132610013107218246782621300082173877300940626476215092030432506329407343; + + uint256 constant IC34x = 1970835801922583310463821681650902598490412604240847378299403490158878378771; + uint256 constant IC34y = 2645173405599237655242503972801246968260683155764579097820353770413386724954; + + uint256 constant IC35x = 13002452596664868205033653166611933658513745221555170825882755664006719154849; + uint256 constant IC35y = 19932557513178190957639255543609719543999931993959491177552616421670733371515; // Memory data @@ -152,7 +158,7 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[33] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[35] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -262,6 +268,10 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { g1_mulAccC(_pVk, IC33x, IC33y, calldataload(add(pubSignals, 1024))) + g1_mulAccC(_pVk, IC34x, IC34y, calldataload(add(pubSignals, 1056))) + + g1_mulAccC(_pVk, IC35x, IC35y, calldataload(add(pubSignals, 1088))) + // -A mstore(_pPairing, calldataload(pA)) @@ -383,6 +393,10 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { checkField(calldataload(add(_pubSignals, 1056))) + checkField(calldataload(add(_pubSignals, 1088))) + + checkField(calldataload(add(_pubSignals, 1120))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol index 9869d7f..5e995c2 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol @@ -43,368 +43,374 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 7500535726679560657579283439937225600834190844886138210173985030451455825127; - uint256 constant IC0y = 19211173094810308874479540771713108816406079403971313989572690055722645083877; + uint256 constant IC0x = 20398885015768833332435514336964973976263734491391782320221636024367620289115; + uint256 constant IC0y = 8760835549406711390430046441333902733068272568041812008555362565381985990710; - uint256 constant IC1x = 16806344774942779306505877135056695979972584080776325374989648490702215091788; - uint256 constant IC1y = 13717852534241260147752477679415199499740910779435645828418374467800679660858; + uint256 constant IC1x = 15315605634345520221594901833340731648539098476635067124604417401816633098280; + uint256 constant IC1y = 18875481744024803967130877640606367550634507494816655989709080357596788978921; - uint256 constant IC2x = 1916139503704745689898523960297546340282030595985891097786214399443735136917; - uint256 constant IC2y = 12122404471421459930376373421371017459283777741639107186061873866664653486447; + uint256 constant IC2x = 10962558348260500070125706894259971541167145467351319491925539411774900588601; + uint256 constant IC2y = 16601107315381967963398321942565536087855575926769980532500430171288641149706; - uint256 constant IC3x = 8945226882505170846621830642118253540275806857825852371695491097772334231796; - uint256 constant IC3y = 1389636172342704194880391438762811545108381346908901092092717318384913908832; + uint256 constant IC3x = 18475625424065444377526467442879892691346993576926641400252057909354715020520; + uint256 constant IC3y = 5570779199529089240384429665547038107113778168312973926935467604368072144859; - uint256 constant IC4x = 4720000354007292185275041515476297017713751894951649840732039222933062765116; - uint256 constant IC4y = 8309818417196457976518803977124233410768792858397588812533806049028635450946; + uint256 constant IC4x = 12003603435929767609640740501741465520898550578391236732459853783209598118503; + uint256 constant IC4y = 21287389848894417757842456521269215543206633036722526542637082684866616725026; - uint256 constant IC5x = 7199104912090362163502951295934008886949479686422100263952248206164211485353; - uint256 constant IC5y = 16164449005147376477866173780305393298236981184699709322090554181593827679350; + uint256 constant IC5x = 16840622873140202158533898138836978466004638442476124140850223791289880425510; + uint256 constant IC5y = 16147374693160502375339099085890249533432723241379457525415914453825601256105; - uint256 constant IC6x = 2843912041877824320322393310006824854677121908412718870409497250717312679641; - uint256 constant IC6y = 7827715582861223894170300961094503992574657276861623990874852638266967896640; + uint256 constant IC6x = 10922534285726085349626725286024278545350745500943686555961961430428328170831; + uint256 constant IC6y = 17801907563951581873842206396614430051085862140891239610878751328147139398224; - uint256 constant IC7x = 9788197829849217864440989665539682204160479875809542892572343833501260255875; - uint256 constant IC7y = 5247569753791213588728317604116866569605781288314643612798847987978242262702; + uint256 constant IC7x = 331533077669271837542455354026657408296474159772588569980133360793953588422; + uint256 constant IC7y = 9103463863071197611784166906531332917576254622849362524121180110117456533069; - uint256 constant IC8x = 19403614296896826743998907389148525012932729658278058752132347125377187794508; - uint256 constant IC8y = 51408059167637885618869915277185071933411987649931254551240199217265772473; + uint256 constant IC8x = 1865270289986565648030272005350494412030737310888662960603725468437583839045; + uint256 constant IC8y = 5168731334140760077585432793223542273657702638524355741528172557608047773243; - uint256 constant IC9x = 17898957347147717726551222139844907465409820999669398183757701831297622051364; - uint256 constant IC9y = 14606804311053587079091541104980170172419043649146045021354605179060328431614; + uint256 constant IC9x = 3277668742872605246896958350495282290039028512536403198566600094820133380601; + uint256 constant IC9y = 11548134866222263490983336323267387497453017563577235428259392653353170740228; - uint256 constant IC10x = 6238065553035971825111581642573915748187460674313041016860739176610996811287; - uint256 constant IC10y = 10751590147133361319427145411917033750868230773510804521928398020016242616278; + uint256 constant IC10x = 20343899097903959164080020030959738138438209828365962870678026736411952444518; + uint256 constant IC10y = 18241230243866061566530568767693990648888177623730544199159541431564688547664; - uint256 constant IC11x = 7342056090265083301770626449376875008245858021255267714744154729838971358548; - uint256 constant IC11y = 12063771229441878674400687905529977776458335378826498652935943121954810198909; + uint256 constant IC11x = 18479080697822444282808646490885520664323704346435449476552304886743787892206; + uint256 constant IC11y = 10139472841380487331908635773929403103370787709096270215815907980023763072383; - uint256 constant IC12x = 373524596084282635359130976258058593421536400057319175377893806123360396467; - uint256 constant IC12y = 14760670258604012914698381006051382694275220938579164835591747586399218816080; + uint256 constant IC12x = 7375071963957521661574772155015348920375467454004644085503515451387651253868; + uint256 constant IC12y = 680622443357119797312759019286589347494777919660280748745769283268744477767; - uint256 constant IC13x = 4418236526774264570412986270922284322939568112401699654999793989825816069711; - uint256 constant IC13y = 12557078685359827252756688576225765305779748144404144960222828895872897383337; + uint256 constant IC13x = 20928512346024599565379862378053010205103529624732469610004212071686003884618; + uint256 constant IC13y = 12777237064601503857474701530361007157755022330838118894288280461077493883234; - uint256 constant IC14x = 21257485642209101440541262855049475786452634834647714540092892434266299426011; - uint256 constant IC14y = 18971897146012196950386564090753801629516833979407747406905450423529988474842; + uint256 constant IC14x = 20215979655021165699740284902466766331879386548705420668698611902993193196821; + uint256 constant IC14y = 5454494944883837327717984330153680614890130807469187939076618039392266803526; - uint256 constant IC15x = 16611243890640899140956062160503428811483680171417457952982245891497508999752; - uint256 constant IC15y = 2098357619974235417711388971755203696100694838741344705093631948513498230315; + uint256 constant IC15x = 16610757470953874686097820386675825645978737617296312820939415523500447671164; + uint256 constant IC15y = 17053198518466695305661450842037763672380967690529864675235198194354739837578; - uint256 constant IC16x = 4355590700036993009639420381936958601889921765819122718853640409809972719842; - uint256 constant IC16y = 15175463602073829667515214966415027094817288251345304171265812183665287504979; + uint256 constant IC16x = 7021622070573750596885766617388283553956890610541052396513288850367448110100; + uint256 constant IC16y = 6114392586859271235645114839938047171434877615814594170864572178977383372407; - uint256 constant IC17x = 3620493422748381691853120643516512372163420481937656511998695848026260320105; - uint256 constant IC17y = 1560848439972110289214389319917906019630412185841375012598626009666197413134; + uint256 constant IC17x = 18459359463196906750101803805134866382360201461188304774448611358995256596840; + uint256 constant IC17y = 14007625778685852933723465741181309355968565910753244359577777672045616277137; - uint256 constant IC18x = 4700274148367693232336831513076811485967114825117923276671705061219333681346; - uint256 constant IC18y = 8511274934316204889113881570640881830545481646152519241985180723413237682003; + uint256 constant IC18x = 7330613818141406804940328879539668161285542141708646544472883265275803137368; + uint256 constant IC18y = 19570907243334664960642666427068124823092150141493731223283710915189363126832; - uint256 constant IC19x = 10806720960072981669311367059548117404871246921816956597065725827341750476273; - uint256 constant IC19y = 21158531563976094327960067597282163184193348063369449379905304051936258801577; + uint256 constant IC19x = 9530892759024679222091985804368326262171718592635243454567293130557251969047; + uint256 constant IC19y = 20263638443330181950631894972447101639689486260265734291214084508704827866548; - uint256 constant IC20x = 13369217552722105292268334414614980598650220141525004260563926888539904272102; - uint256 constant IC20y = 10402746290939719898151331031171924883633465262768729580014215146825225005360; + uint256 constant IC20x = 21492153821525822904803526861240598727441310215107218029376265013963147676489; + uint256 constant IC20y = 502594198159436453726935618971082597142287309989906794190341784921422339916; - uint256 constant IC21x = 2148697341810656611090754811248609047453259665955486969057737541337289271335; - uint256 constant IC21y = 21029346951026375384890347577694834697467345509708861998995709086074732476094; + uint256 constant IC21x = 15798655019826890172280994249307099268633685893387868522071914098840618980746; + uint256 constant IC21y = 9865580643218739852550182537841554506407534691779093345251461358765368533081; - uint256 constant IC22x = 1873710762427086841161676812964047827943676959997358463124181840860294888033; - uint256 constant IC22y = 14063422199669868332009175714038225820046889682804461668628059329477108292348; + uint256 constant IC22x = 9262644737694534244503575499632833741011259499675081222582659620091148766369; + uint256 constant IC22y = 17829158260856649086040752926832563690987995169338414680915643143753365451485; - uint256 constant IC23x = 4174585191479732244748267274242451644545245726408387398850177431048796399643; - uint256 constant IC23y = 14857834540533954748154708389725638016379871028032553609866901793768103884602; + uint256 constant IC23x = 767427525167412798768462408347891975741696251882921471679209788902053962065; + uint256 constant IC23y = 9360321964248771008965379121408795049906860133653177877513370550553860602359; - uint256 constant IC24x = 6796031609956705157224738682377302362835652495661082431443390587382147903750; - uint256 constant IC24y = 14336948976066433616542400938618506901234134279659317590768587486919402107031; + uint256 constant IC24x = 7786254248901535368236062985935014246141906126091291758303070830619809790455; + uint256 constant IC24y = 15025602502360337407211193978486991033023302472472303105205348826550862766378; - uint256 constant IC25x = 7569242654658133936340747585660944931268333908847730848759100510663123267137; - uint256 constant IC25y = 12043917912298666797114070456260207561319168319534634208021831159643321726059; + uint256 constant IC25x = 20376814909736590102689274175464771739519361897508968663857399939939467761746; + uint256 constant IC25y = 18340559477147122569467996779410760395165001230806178247110494310289841720537; - uint256 constant IC26x = 13619060361062972609581242432309237149941978819573786182006070973866484468920; - uint256 constant IC26y = 1778130477177295522446099216627259081346814994736312261439848974747521227458; + uint256 constant IC26x = 17800994066466363067198961919801915552853100965461744930922160641034176453079; + uint256 constant IC26y = 11918718588660896453075495143576186269549924286348704983691507495540561352019; - uint256 constant IC27x = 14582113689584039845068369999361449891331987536406378300547852053673581029; - uint256 constant IC27y = 16832763731582757514382997029476363999693114653383529374694410294769460052383; + uint256 constant IC27x = 10495844589130271445411795532350212687148206439414758058425774817980091558078; + uint256 constant IC27y = 3494978241826843004186765681928340113056098318445349482707900888809525865171; - uint256 constant IC28x = 20377066698453791023458287151938239594019822715825684621307962449389756844134; - uint256 constant IC28y = 16465755203020873308129491161826944266505991660198930428873015090822479174784; + uint256 constant IC28x = 20329221239610639460850266826770122360410480669429683437161438632801452984688; + uint256 constant IC28y = 13325118939278722300248798703713461390907142887100386207394332404509360818229; - uint256 constant IC29x = 10649285923762964369917057077121812021322905224482857478876413238735450814741; - uint256 constant IC29y = 21838478583818641080552513759450480672872225316500909643197879891174334244480; + uint256 constant IC29x = 12897465742634214723211721847980238099991600737191512918883180628333622743554; + uint256 constant IC29y = 13304925469466439321898247029253073765192398716030503013714107143636603607906; - uint256 constant IC30x = 1109087950222036174110964951435020267015623808240978786202742146115607301252; - uint256 constant IC30y = 3956368720643646860873662735333036398111077399675206246003858808777289636523; + uint256 constant IC30x = 3728130262415523090729235919946974586185137970063359588939872286876625136493; + uint256 constant IC30y = 14771688134121403834335967763740512078191577317706752331343549579035385958709; - uint256 constant IC31x = 8576714559669613458031244045461780388504756597868108986456998548724842622108; - uint256 constant IC31y = 7554628788621180844451495770327316094075077073031327580352589337679635770615; + uint256 constant IC31x = 309463102665483487525623430433722736802876355256461289138906293824541435851; + uint256 constant IC31y = 15440284034320752324934879788863035779438696415839435144159725677942059358772; - uint256 constant IC32x = 14656288601547980865604379551755939987955283217202788809494960550239721723961; - uint256 constant IC32y = 766824508218622323270303545794833087659956781279339003477101911534417865401; + uint256 constant IC32x = 14874627100849713195956866716712422130773012822921712980126817380305557112989; + uint256 constant IC32y = 6034198970906453277502921605205656989195513861047377686972535256526728977522; - uint256 constant IC33x = 3459904603095154924525955846501957568183885356393506680886387462734961216955; - uint256 constant IC33y = 17873456474529882090525128657932218280379783373738156426415490148507484791067; + uint256 constant IC33x = 11107672369575925651481862387260117983088123111549845873405637302180349800279; + uint256 constant IC33y = 10568297561768518170888258393353730530385221216950201609602973790908216086946; - uint256 constant IC34x = 9035012563148792506674112927575972384967719337164495552803038431090164998740; - uint256 constant IC34y = 4037586603668609002888775095476102814791360218227745807288646292504171369100; + uint256 constant IC34x = 14684299057059841495037682570704680406383086174803782260386407359432100599538; + uint256 constant IC34y = 11152062318265802473168635756972384550160042515815736512929853653838105751730; - uint256 constant IC35x = 2534742475005281868379587149694067952094999056981068032551302208506146526423; - uint256 constant IC35y = 12198448301468055355461438008846593911353601311542048279255721945565940970207; + uint256 constant IC35x = 7964669613018186154282201873005697772570493436392438832158420656550699705808; + uint256 constant IC35y = 8480007516003872225998687925542992424280369876779625586268945610144785079322; - uint256 constant IC36x = 11466999399869027581046875767681368679523765162159961829970347155160983383231; - uint256 constant IC36y = 14728120015413070781150170877833390889423822037559991016631039438101774487919; + uint256 constant IC36x = 6102388244357299192279272514989765096421054021486426720861254445375136730529; + uint256 constant IC36y = 10223341738771326597029397231819264615059470907930257959851418535961979794756; - uint256 constant IC37x = 14835759801275157675907480432161847097460725054043111187563905311162324019430; - uint256 constant IC37y = 8988388090647974630407822941647019946719747267832272782429673153376589466814; + uint256 constant IC37x = 17747724122258681544307894859161096131187042240812342374675413662284777650570; + uint256 constant IC37y = 9447921843955672491730801571768397553100060711565611665491792741322826455925; - uint256 constant IC38x = 19421739123622636037107042245134453960742228305647845554383597537661588927895; - uint256 constant IC38y = 15467472060760822188681708808044964192537771977244749537433758734276827106628; + uint256 constant IC38x = 15062075394349200592236768533299480001698270034045492855202484126445527440549; + uint256 constant IC38y = 10551599627884253506095842408377009135339550400712051052819390120807480633210; - uint256 constant IC39x = 19935977093502482182548979789195578560052815028405674303797001570548802038596; - uint256 constant IC39y = 6697860062510891376067995893110174455273885199850742505480547347302022477498; + uint256 constant IC39x = 12937767602608237309886455850812184365660472931012933355472185679573920403960; + uint256 constant IC39y = 11305859327137032518104088758884657978321977050757439060524401986102535072004; - uint256 constant IC40x = 15051865976796661053263397603506515712114247323956425399832997166097654770443; - uint256 constant IC40y = 4374537910217073650207037753738132179051546680623524376507665074715923417591; + uint256 constant IC40x = 17668443563673170817501275247756556708079215453545562843435748809974423374346; + uint256 constant IC40y = 2843872391810990764590040691676990430604204150851713296832900760269287518493; - uint256 constant IC41x = 19519284504040054446464895665875936024808141082948559256582980298586121967707; - uint256 constant IC41y = 15524576017614709763277884123834010483645911571052474791111550307182002039636; + uint256 constant IC41x = 19553727569336049429702749034388746833696332407432999799759564373100272997289; + uint256 constant IC41y = 17032647689065532199532540988676372158592678082588157891042419506069001886629; - uint256 constant IC42x = 14169047558741639063601425825528076715949947143481266982651402145760147350689; - uint256 constant IC42y = 11558742126368384663450582571191769475879481207234747961491402187585809030470; + uint256 constant IC42x = 2349635590953727423709115709996069823504303147307363034594360091576405952712; + uint256 constant IC42y = 13255393805788349816156400329463530615674950275071273844021785362378501004281; - uint256 constant IC43x = 5332465408258819374942719388093284211386692103588469945571877659452411471386; - uint256 constant IC43y = 11791448676918952308531355096392441407206027582305795467804432822986119027841; + uint256 constant IC43x = 10463480754130576697791130727443494084540016352062602974070496625567587892565; + uint256 constant IC43y = 18543645871837613080027348925092308461821718045592455286844010480845348759262; - uint256 constant IC44x = 13654245885227724388345981493092939387342814421366386083474600115721432266110; - uint256 constant IC44y = 5926153516600145974422289517971898358230338127793469527296139364876247557809; + uint256 constant IC44x = 11996999816349738680220525310668603227864827674371652229824392630530737583342; + uint256 constant IC44y = 17865503555717365419519222221024480322333563857329265182112769876182032214530; - uint256 constant IC45x = 13122586510068074078517089731879725456926231046988356228510234941204925995123; - uint256 constant IC45y = 12265238617608818055780513496240282847481054743119517968342725204221544781395; + uint256 constant IC45x = 17193880719441273727465191787759906853486350795279041567426093472724046631896; + uint256 constant IC45y = 8985280251072798544313868273369385731936693130413049932085493298595530801545; - uint256 constant IC46x = 8274528848355054591127494508072722718775015760071421827286001206942790699627; - uint256 constant IC46y = 11760918715293784379775030235331164880488442709518502275057572199465619802512; + uint256 constant IC46x = 16635452308494234540633769759681205422951522409715430713777868483340786024882; + uint256 constant IC46y = 6165308805029156236792599522159803176528318280471374837336234743447882968769; - uint256 constant IC47x = 11014810329931619965158398213406539755713461092731556060274626281453164309453; - uint256 constant IC47y = 11189323295385306543102382083746863577222972902104073927551637506494263735304; + uint256 constant IC47x = 14565893495171737824116524285337183041814427128057848332677147039409097384682; + uint256 constant IC47y = 19191914404607103062990820459205468505828216116787224625928653527748944893771; - uint256 constant IC48x = 12712508501357267278007738155943294295381520642767904828279001501481377210137; - uint256 constant IC48y = 17390657672085029832700943318373589605086952772090592854174422868227906933189; + uint256 constant IC48x = 15030285227261627804208167134759630375118046716022522883678922697079571336509; + uint256 constant IC48y = 7503443151884068092801908553949616060548585322227005946712480043150525602756; - uint256 constant IC49x = 8158155995935964817361153687378978065370076724750970984753519237713084097159; - uint256 constant IC49y = 19266736062723091675062119238987388544788241591582139615448136563045829614240; + uint256 constant IC49x = 2890175944366323604069005554180620856445075185687866766556862475537913733035; + uint256 constant IC49y = 21402420557796229817923793018565970959405396000319224601736428615482893082396; - uint256 constant IC50x = 15410549079733825403614355166850298862378845312773047869183699867090402758863; - uint256 constant IC50y = 9877816272544274288412437194652539541179097142155557486048641274060651656591; + uint256 constant IC50x = 6446914869243532867752832288063700479888013956768941059009832724315725474770; + uint256 constant IC50y = 14652836518560420905054215443772041046326481461713988259420995897791772027335; - uint256 constant IC51x = 6629359193266028942713148037067952584305855665204022883127978023750323831268; - uint256 constant IC51y = 3743333996498987146147511851654428972618998595385126367990230310572340500629; + uint256 constant IC51x = 20041054044922899471372214960784727126767141441682485381267343533007187189700; + uint256 constant IC51y = 5526007658621064711850808319114366455442657479327278550827782768153697644654; - uint256 constant IC52x = 2446799394890562122022807485261900456170147937657250725501128587449798855710; - uint256 constant IC52y = 10831859484895982751194550869698635827390557779676319197690946463294137328618; + uint256 constant IC52x = 19150639418559678633621673271005536488825394733429832397648005054576424091014; + uint256 constant IC52y = 13984556545715703169646102729022380397336382782894007865612905771831095295296; - uint256 constant IC53x = 2953017421033136924678624468094000234644427178548329162920389392863998759085; - uint256 constant IC53y = 12151966610918690555352831153083558428557423274041184410708279948918928705346; + uint256 constant IC53x = 7157675053183322685547346667769945432615647738230118724652857748596189223290; + uint256 constant IC53y = 11406818468931995926497158430724140943351284270578137825740925365572254319833; - uint256 constant IC54x = 8087846746377924976756683832428720847449604039113382881446326776286671798092; - uint256 constant IC54y = 7288341319881659843454388651325310716760815463129377255327335842805776878538; + uint256 constant IC54x = 13413395589113329435069363794257051770588243749397133025194455389776552832266; + uint256 constant IC54y = 18233492425162685277447440590422870943915646330630395570277383458526028719702; - uint256 constant IC55x = 13495987578579953277693326877949946772289507309011987627192310070351649046086; - uint256 constant IC55y = 7257346467449388144285371430101261259094193268967793660847530786322202968488; + uint256 constant IC55x = 11952969371705892508039078595347162569714637318342951353674798196734068921335; + uint256 constant IC55y = 17072403296706399069822100288172183781186939920866427122577444670244961508596; - uint256 constant IC56x = 17882197460124432060375387452223327434223221532213854429635214900516730297105; - uint256 constant IC56y = 6486140274455554609854267434998295186554345558025259611641091796618857591723; + uint256 constant IC56x = 2118693461836778808738007872772687490056511524520363073731001411247110829293; + uint256 constant IC56y = 2930578182584430387349990034734645194355190762303962197681784927324157767427; - uint256 constant IC57x = 18060644639329423390591461587690627453025007935899201493524474530222059353030; - uint256 constant IC57y = 13331379512282481166141130709457502487055532990062095012747890797220941533968; + uint256 constant IC57x = 9850888974164836644806074613473914979118549706918015407591606605920957510385; + uint256 constant IC57y = 18510923419022297133210506403756827855224768858039616569110963137973036074293; - uint256 constant IC58x = 7914303066558602668246205079409149593886974851237356057887630180998379164277; - uint256 constant IC58y = 11742715327474005618857155356669397308978829791791801695448436577436933235563; + uint256 constant IC58x = 7680502953712527585452810373510828175981522566334906875774440006428086663061; + uint256 constant IC58y = 9984402657382852559233618398572701968495333370527250809744332096495402817906; - uint256 constant IC59x = 1737662495855912582360511320492416702002273998205249649984716218202390020969; - uint256 constant IC59y = 13418655392892450015136808325300261057784239425009576317224157000889828830049; + uint256 constant IC59x = 9971952665103757705290396101836783610733947621587296689840942397746954948178; + uint256 constant IC59y = 6171933113084897041853553717861240724524487414429421887412843104784536822729; - uint256 constant IC60x = 4834422649135352874647627764686462565699225845013283365686026069560501198404; - uint256 constant IC60y = 4757667430779664999587739264920467575683653864526511048906660419706636070768; + uint256 constant IC60x = 1894970037721544823266180756477097282078493985171782117701139712260687171349; + uint256 constant IC60y = 20802443255406523093685514560897575533065136634058648762686198863412788235051; - uint256 constant IC61x = 2920992638216104155183967668094147376293386967008321931600826085803708308220; - uint256 constant IC61y = 8159758823941053250084307519757092527074157608929172237335408640809991962406; + uint256 constant IC61x = 14647611976255331732189909477071956053401253876621377232295105124828449894550; + uint256 constant IC61y = 10612760931337654003207678809383480625135298470454874458848689207733841513901; - uint256 constant IC62x = 20380022125089941982267545484277155711076109862266912429930748936390059655152; - uint256 constant IC62y = 470391815478528058241672409830369680813994569512149884965930095110810108984; + uint256 constant IC62x = 15486999347499633100408424234852699928663420526783822219457642399335370261191; + uint256 constant IC62y = 17624028074589110683344988184041764656070639524071735597826456305834513408575; - uint256 constant IC63x = 9425423724664098580536380897211772535118081412568624282696997277553286852839; - uint256 constant IC63y = 18102359130326432892074145491902162032784316084473839231833731864967644198318; + uint256 constant IC63x = 21603968141203809804733464426223218723145308921390735902862374430796163893437; + uint256 constant IC63y = 12685866074688517416706851433860046151609411429249614319934028211656779093722; - uint256 constant IC64x = 19500196743361397753441818011714661509028744136815029186609130185239906324695; - uint256 constant IC64y = 9166656329872966963508555901927598186094898417497111469308350422460271423546; + uint256 constant IC64x = 1046122314972882606184113090452035669584193225454910874960181096914198073826; + uint256 constant IC64y = 4522039592034110691270673792892435417553608490889054520542290139228754848801; - uint256 constant IC65x = 20508058021512460837118488786527087294694585061411301455950394061961904702904; - uint256 constant IC65y = 2578223733619336602943413450000425637548745859092326016651608266335574960494; + uint256 constant IC65x = 13035371595510200987803597311671910559224293626060011302128581137178967290243; + uint256 constant IC65y = 18830037631194349191542716841718817355162930256730764640626960726748372847218; - uint256 constant IC66x = 1071601579509139236412649336777516383083729411833025363285901187846951705514; - uint256 constant IC66y = 643778404700341783686316894071179800417687549225861429866927932290907352872; + uint256 constant IC66x = 11950442787460356177621351254827857533412939982736316190878754664098050765208; + uint256 constant IC66y = 16150201220852844581384356336547863968702182834518676827175830177434863814501; - uint256 constant IC67x = 21046686905022938762343110658685000333114003074832743789460482970929684291941; - uint256 constant IC67y = 16589695516620085044284865294304818658032377472492495403321572602644696285496; + uint256 constant IC67x = 20758523767849643456314396275456680240452060960515409885132834869350530289798; + uint256 constant IC67y = 9180668518849076532950714593995434318394487105716270941016212649899242171112; - uint256 constant IC68x = 15402727245438872470337281580419854325509021235549558441579332069237738542206; - uint256 constant IC68y = 12100658949812311807290740424830315786611473991678642131357227195466793178654; + uint256 constant IC68x = 5239278122882626846000034818719607483588013591008859718576594969685784951529; + uint256 constant IC68y = 16306375534893717492693980667466940162734803891429931218929779024470110752159; - uint256 constant IC69x = 5984396963935932069475014455874483850975993839370888235950954254263981029541; - uint256 constant IC69y = 8658244321663354058517608860644685738312456985966813850314182794608726926497; + uint256 constant IC69x = 60040486841753522275129553244986521720979211457807828932951905425041640787; + uint256 constant IC69y = 9013885853500799266613282362724270334971361901923177194953249026990006689605; - uint256 constant IC70x = 13180402081920922842736886190093953231655326874611201456251342171630489279461; - uint256 constant IC70y = 18649658464519580163906798382923586107997731125760988378673369846514909161404; + uint256 constant IC70x = 3520249371201081358738325450683322011291109901952732241702333015561336288161; + uint256 constant IC70y = 18571821682640518866100332525102940846461499834568262264437879828385375105108; - uint256 constant IC71x = 11465613760655638455032324012041259936429065923953367597967854901531079869526; - uint256 constant IC71y = 1997868257671766278420414611308456329672567091454229700216047315765806631304; + uint256 constant IC71x = 14313639399800139199585954736173381872520673739030820800682032934005717684144; + uint256 constant IC71y = 3873738781990898520371107288664303859758528408013610044232401063651557203496; - uint256 constant IC72x = 17918109650394143090398200709147906843621449700067572334426785791214583511049; - uint256 constant IC72y = 5785087180604996996878479591688410688146103334006142651020815231268891900773; + uint256 constant IC72x = 3588438931500741098390661182906071821897973231262009720141137513211007473808; + uint256 constant IC72y = 11445567214009722347895826509290373622016848620807880454187293786604118285973; - uint256 constant IC73x = 736201990241690106987067004600088863457141457573681072149394616967572755929; - uint256 constant IC73y = 12537157162826621549086349254200249982552713002993943503127638231722978596924; + uint256 constant IC73x = 2341663678515785718688583881989080576799426214321970054342598530455026540090; + uint256 constant IC73y = 10898551623756196270043548498605764990771251725313522289028629126229406564514; - uint256 constant IC74x = 15785103340068683842513248354657964422095017416519973953965247557166746383423; - uint256 constant IC74y = 16150924406755343335896132050034914767928045988689480710519873684676576185028; + uint256 constant IC74x = 10684014331978661435946478567030472039294264967610460884326767352769522133123; + uint256 constant IC74y = 854119106587083427067980557942817732138886457716725083548902802354969929358; - uint256 constant IC75x = 6404840253907413983145416199309477113029419362177186012992462488423921389989; - uint256 constant IC75y = 8735341945865532036256299477233956095055876095997087464613556071915976571146; + uint256 constant IC75x = 13497339556002563926467246166377386456466739950114835902554508186662442134551; + uint256 constant IC75y = 12753106675892979423891727974145445633321357154954055195984227422417556508959; - uint256 constant IC76x = 8724267365230902347229847202108650737209726005308343958546017169716303363251; - uint256 constant IC76y = 17777512362101876439834872855511544013815307612344519390875215243966466686025; + uint256 constant IC76x = 7774835372381558796423729580947043830702308268025754626584332156703610750503; + uint256 constant IC76y = 14203298106327530218806048813273065303839358433340231490525185945170851807940; - uint256 constant IC77x = 8918814611902546518920187003392494979454174182643529331409094384218166231650; - uint256 constant IC77y = 18184712480067856273523502143963922366841367703802154356706668556258107456291; + uint256 constant IC77x = 19545759579126933165965793934664009550429674048412263363091454659028184179658; + uint256 constant IC77y = 11302797849180179875243350965470533075771601838768468782249102284526348187133; - uint256 constant IC78x = 9421173889055624068250468682319042736523104237111924853383033602305643651409; - uint256 constant IC78y = 17076225282910336421003758619520963376827046792873380653814378558509545536194; + uint256 constant IC78x = 14193464378621339496604009848895004408369571339181960046782090752306882241961; + uint256 constant IC78y = 6484449968910059532146867780125026231176630832791850308953414492952771635499; - uint256 constant IC79x = 17827953591197465637068392424066919197785406468317003450376104975572451412752; - uint256 constant IC79y = 19758205883431149738033761058476595044973262048294152716378750980720592832264; + uint256 constant IC79x = 17305463374036637081854536292140592306238729820744197923450769615349158588525; + uint256 constant IC79y = 2366947258804585636412792570360953242716933294696498476165980179964806807801; - uint256 constant IC80x = 5877455143230750188145901369572724485485689221369018527546722077858039568378; - uint256 constant IC80y = 20547529821963006488317098177150986788254986979627053843788623333737172069898; + uint256 constant IC80x = 11644588760990236876974912094327482731330759171085779877760966244660949932674; + uint256 constant IC80y = 16717001929129944897228127170201919488207427269569562624299499922450998064837; - uint256 constant IC81x = 4980820155167635856488138968291416906237146248404772197352963295674430339670; - uint256 constant IC81y = 18701181065695552777076243336927915570742707349896197585530631698642256643422; + uint256 constant IC81x = 724082024714563899320516369116997202804668922001066953873870802079656345689; + uint256 constant IC81y = 17557960635497551802288681184045596103944099446986078832471651543412766732744; - uint256 constant IC82x = 16777939488041114754768545674514709721185376316115997064200051282595721559173; - uint256 constant IC82y = 5939768806357633468561973089882202212779962921089081983016988372615989543242; + uint256 constant IC82x = 6596352912146189908988099882899119672498806752388198673623080609786281259610; + uint256 constant IC82y = 18035500837389320080377905012757992412314398206362531451239286617622311925437; - uint256 constant IC83x = 14796363017577142791220641668352160568683008269771782264758229033250072319628; - uint256 constant IC83y = 14600699583086517418061957134181365606986549922649060599373995683203928018438; + uint256 constant IC83x = 16631660089292596437929735643986247934416470401628156900784389015699713002; + uint256 constant IC83y = 2635767000339984531883587499098961427757077068630087973741805051230224013392; - uint256 constant IC84x = 7903707117829484574409231745320520376775440889841126591886418591988650340645; - uint256 constant IC84y = 14392470618957976023051290670419524135641225612724566454081135462717269912207; + uint256 constant IC84x = 5876327941930077445025148929177089211360275962634597911047042806290892764074; + uint256 constant IC84y = 17938531246750806242276832784966088783463732575152171627376559096461846521088; - uint256 constant IC85x = 7040254646516169238176084030015013167692487701232513069536956450947996030379; - uint256 constant IC85y = 8344217891222417433515293421374060610622682714177382471358588153225451407752; + uint256 constant IC85x = 21312636100772271594592644523541307710683074761727366815747826021298291888468; + uint256 constant IC85y = 7421436386901827459832792092825762488783821819857689719337910400123529566738; - uint256 constant IC86x = 5937292643151495064112317366294053602775514009276861609583272956389590265518; - uint256 constant IC86y = 1667993821256079901229637548974554662929109034226271574914376494716722176625; + uint256 constant IC86x = 13215324987321691031772609770563399056688470467435168488147082075626816153868; + uint256 constant IC86y = 14888837507923092258863896708522213041360152502546481231183073367563873350073; - uint256 constant IC87x = 10429545704286591237503711116064846275257778264471187604753484534805146304406; - uint256 constant IC87y = 16809620886550722377592042848589246446559282211323461249142902747003154770550; + uint256 constant IC87x = 6782458554677592896601343428120296606105347911152463672066686092290133219042; + uint256 constant IC87y = 6610194029049829155534400706154149450122421296213161328612992820424687757671; - uint256 constant IC88x = 3855121632148124520024006603503851007303555175973870246013190185424275036884; - uint256 constant IC88y = 9999821343476899711639206159041995757833047189164312873277142359741350548524; + uint256 constant IC88x = 5229346161475995291620655532880773970638849301439085610332183730863383189456; + uint256 constant IC88y = 19547951565566988874761384832662443890458326819107923315751591820484906706305; - uint256 constant IC89x = 9406573531866980696091650555832533670257258889697579436673721246944489813161; - uint256 constant IC89y = 2995301525705710804516618281453063310646626808047888632169285966532787483816; + uint256 constant IC89x = 3659964792835045678035508292792194934195590139072531185393672834896972186298; + uint256 constant IC89y = 21226437955494237076797331447188110291792274150511615595634742162397809255516; - uint256 constant IC90x = 1526457548771184118859192752374469540237852714417643375364529068991571728824; - uint256 constant IC90y = 20322188999985982433213531153742375410479264418221090198365532243908587434326; + uint256 constant IC90x = 7771763540920451739810673751513397443683328223505186604456359287919167842023; + uint256 constant IC90y = 10159880526458521318375792498071543983590609264247748517361447745066616696128; - uint256 constant IC91x = 3647145737859818823186946652451283687702129427645865082018890413183344701091; - uint256 constant IC91y = 7819570647789419112121104220074887639917070518824958166839036978493127740892; + uint256 constant IC91x = 14154795557739663913583616074426332188731595283385202347574073810131906203836; + uint256 constant IC91y = 12203129601625017656197217217372897565151527359848884209093727223778339027517; - uint256 constant IC92x = 1974959570150660280056827747341994528565992841758006521675207473433735955848; - uint256 constant IC92y = 21006636613984238277559183702894457139320631222645359136557640302488911243945; + uint256 constant IC92x = 10738399901382872337595176413673752131211701830603878221714501188665324438302; + uint256 constant IC92y = 12493555322610738351393993928785621283529827889399625271093048235841089900259; - uint256 constant IC93x = 3335546558418017109432168296043479711076786715915291707849840571166448680717; - uint256 constant IC93y = 15457404158417127280242556946917664267314355206231923461676831217126476725537; + uint256 constant IC93x = 7408953403999731091117865921461861997684197151241883257811923700543204464115; + uint256 constant IC93y = 9299432411017731167652874257788259203742865296372881847259579313757551571729; - uint256 constant IC94x = 21441171890803415112590743754336383724436140530077210167567372102065803298084; - uint256 constant IC94y = 15051654224966300966100369372810644938086280718983170638538542893794943673495; + uint256 constant IC94x = 18422129420097620042984495498230299182702591843727580921742834550014603326589; + uint256 constant IC94y = 11638705919332427113493318048792048023843627334605525601456271898817463094951; - uint256 constant IC95x = 904738135681670190617377831792546580612791936292381085800842878532135505927; - uint256 constant IC95y = 6810010775466597235605200839456323606371118774128866957554172174037252045485; + uint256 constant IC95x = 16535211571765963422123382836500396482285512573798137764798822989181389348670; + uint256 constant IC95y = 3241351689099640979899441731138474616249937600462608927226065129179824602380; - uint256 constant IC96x = 12378672532176880399179863916468913697757231729062916629030598871088671023717; - uint256 constant IC96y = 20098346558210018384886078536904272236032468181896137221453087052203307445892; + uint256 constant IC96x = 1727850598356882453627022836371640348562047483926224016665142968335293915822; + uint256 constant IC96y = 8106842976470740257882344828424526205969547206399648341483258455751144028275; - uint256 constant IC97x = 14126725259373963085833115402251987636083846580379370010321611053960982580197; - uint256 constant IC97y = 8861293133079280696383738053273123495504319603270485677836319874673972340741; + uint256 constant IC97x = 12663844262536728422821315979850492033719180818687139907133012539392933350973; + uint256 constant IC97y = 16809134972453363483567174132705692712009523723740204436757547122959526755070; - uint256 constant IC98x = 2779458784793250007636797371297106252345927312270015027009754037825546332040; - uint256 constant IC98y = 6382781516595596976789302946518420311632218283496249973336315992533865353499; + uint256 constant IC98x = 17384166984895715671698181113758994947836873247831235044846919308377545500674; + uint256 constant IC98y = 19797124975688696386227645451586729192717684323380345853344637253874967132603; - uint256 constant IC99x = 12020089154866213694886153183892256324563831725367557661773856911992435489223; - uint256 constant IC99y = 10539389055710673989774401671358672778776773383822655042303695446739250113568; + uint256 constant IC99x = 12816715946759916189607838256859758693184109024274030332470102570031171858704; + uint256 constant IC99y = 618298541945036003719359416706890807778853756415874772736926960166064079770; - uint256 constant IC100x = 1541217357497749664630897344587304428219166612596999401181554817809595193037; - uint256 constant IC100y = 1097705315439307635001054134068893470549566691614527573241133227650398108706; + uint256 constant IC100x = 21722247786068135693179998046207808648985563270699045338204192745730542249075; + uint256 constant IC100y = 2350417950627670801454243672678383580162873004151891076124710687108400141992; - uint256 constant IC101x = 6924110088498046602982308167134133247344479690753907917086285028639996233588; - uint256 constant IC101y = 16592419187624283608496871565561693292923055390111494702590350464797911661390; + uint256 constant IC101x = 2876092575883565033612966063909692068659500969369049858221307490982846711892; + uint256 constant IC101y = 4868211217559834253603566981382552580120868560189279766676032742126501662777; - uint256 constant IC102x = 14932644092780567752595039674791582086146773837645564841325716111844162761264; - uint256 constant IC102y = 14054900461629673933793648127738805887431229404561600987677415365748211518346; + uint256 constant IC102x = 9569415055544659251941769126513488266261460571433664749750891184819981816921; + uint256 constant IC102y = 12868474606777886209227239522672271755076420172850556292313699435596683674676; - uint256 constant IC103x = 21826829410184219425839758804275334693402242173351536315267229912359886610244; - uint256 constant IC103y = 13145247716512585016535403539623870656705505496302557231425567395284656174722; + uint256 constant IC103x = 9785900663110466844915708355465930135667834852707627397022625006894351481671; + uint256 constant IC103y = 9086551453940428043262299329847795657792496576406488146051358480500329781760; - uint256 constant IC104x = 10723865532425252680822060295606975447785125920481417815144738067876106730958; - uint256 constant IC104y = 2750060412378528512577424517240805942396359085759338556589546221101062077366; + uint256 constant IC104x = 6260941115529778646412825281709898751434947446735129157556102507460170240029; + uint256 constant IC104y = 2356456736476190395411087805821749720992012609794824936051338838951651697498; - uint256 constant IC105x = 13610479009495437335054156071592856091793553643856975168470544018067268382616; - uint256 constant IC105y = 5028480654630813391642834424074823337367863167323445900517774159378904611046; + uint256 constant IC105x = 9521265334811060218410966757446383466652181342397641281386440036537341499085; + uint256 constant IC105y = 14659317177050397219638748429321689598733551205180840128793153160634171136145; - uint256 constant IC106x = 8959960947101181609929281882023411146543404908305682511969412722987403935244; - uint256 constant IC106y = 17037840716498058589865158148300926307629497039776820539424257599747813331825; + uint256 constant IC106x = 1830754514774508569654278664366356212788487432921519643384550329286850395000; + uint256 constant IC106y = 10480392049184929749668381244172726256850388323835729913980035384224389597382; - uint256 constant IC107x = 3329946637562309018196253174483297743601321674428654693366091368185353418522; - uint256 constant IC107y = 20309461139797568927934774754657461672289961695874069337325221805890193148325; + uint256 constant IC107x = 10673991325341928148292390870528128202274313466717499916473336114919473166085; + uint256 constant IC107y = 16902847351543211064544452734827488073646906000487594690474862344919101986532; - uint256 constant IC108x = 21577763683655929280456425529518529321926379101126163313514585836300198072883; - uint256 constant IC108y = 5476543500179140115023201502972107116336322511138291020260500310257209370084; + uint256 constant IC108x = 18574713766525905062177883606380831732097664201102349391928354083582507270930; + uint256 constant IC108y = 5505789930810008073979884281044068131670720699333040420620096484224516509997; - uint256 constant IC109x = 20879417355885501023056776335954343977316914269670342899109262163784954610784; - uint256 constant IC109y = 7790465984785624865275709254138747779403603809154540066422090152714795953712; + uint256 constant IC109x = 2548243908269881929039331142370024416641479554690096656256752138867757693255; + uint256 constant IC109y = 17794578842823404964499151153794613822047064081114069411496491100702890987233; - uint256 constant IC110x = 10557397239732988433654681269152879173600930019783367956573509681134457260086; - uint256 constant IC110y = 7760747882631581374951580418424188763749299740883466036564477990785808278328; + uint256 constant IC110x = 1287028022870692709184376064984894045388167800441810518515127655856771452970; + uint256 constant IC110y = 18146250915770505199665686320854246832911496561575163201498730018329742521022; - uint256 constant IC111x = 18962979274573620241177899735421077206942165151980971157684600404371127947884; - uint256 constant IC111y = 11142278777830464346481917178613961960044247071174132381659353660719810821830; + uint256 constant IC111x = 223266659812834488639938999193058706003180654759361622624879454184571040839; + uint256 constant IC111y = 7921134752372248161422070452965152364328095214127501496567272972415134334507; - uint256 constant IC112x = 18891312112007878933891062369102830538664709181035663177465029203528273667154; - uint256 constant IC112y = 5564943993235366369184329626770514678860068350805886001507419654572046760366; + uint256 constant IC112x = 4986886591168415390208020303901486193511613848311548742792248441562221880572; + uint256 constant IC112y = 398708160860002162876351965806040229208597954841262698538042173456260265388; - uint256 constant IC113x = 20501391928161541047382080445731840991833860209032196150370454452982172727784; - uint256 constant IC113y = 1207148501022258147436761504410975875343607921399296901409233799477104107651; + uint256 constant IC113x = 1972316390133394085415528566709166892855586247526819391605487727021814219036; + uint256 constant IC113y = 21846326779147723547291946346749343908769311219838841832174278087687576381093; - uint256 constant IC114x = 17449749498261985599386064163600842115651335494726639189966941953754641382504; - uint256 constant IC114y = 9640065465839134209644253399286219771227236184332577630199068058361560772286; + uint256 constant IC114x = 11633824032001357766360049915491114803946152033703778975486826406988789361997; + uint256 constant IC114y = 12068277527503880072488338615521060855197750075235560666111746066176276274071; - uint256 constant IC115x = 16769669983681282562871860837400140314125866994699474615399676301888014220432; - uint256 constant IC115y = 3455672321968490307111155866069820382335223916916296430573383128146984877194; + uint256 constant IC115x = 9695549320569501424789762510503704496192792359860202202906838823792202094327; + uint256 constant IC115y = 9555015718426613777599636203511074951660455319087632077629003163798952312269; - uint256 constant IC116x = 5825437435828009010970802796811824674875997475735353556089845861417246271396; - uint256 constant IC116y = 3863895669944585830686800190438236202353815776017372741294015563475133037794; + uint256 constant IC116x = 19359786186218096935146671653840806244176006894885125254756764933849499335249; + uint256 constant IC116y = 2387949876298345492407912880156795197312532823086163057993861484253831187814; - uint256 constant IC117x = 15887302858133980561256600445148855988791677156721478505479844704907715953945; - uint256 constant IC117y = 14864003316951019654081870944034384171499262900596502976368490439531594106016; + uint256 constant IC117x = 8534641047101882977161212463831263024046689722581888033371843611341594576393; + uint256 constant IC117y = 4085733623069074774475876905548194556959671444566312611122290117145938831556; - uint256 constant IC118x = 13323805276305597321424783160890342818248361487605892420745100352081621727431; - uint256 constant IC118y = 19266628193531456317076591986961861635710997442851400667066787849204723280505; + uint256 constant IC118x = 11392183584793611701022770853888419866359434507207446261013060110372778448750; + uint256 constant IC118y = 12039010283391208083623000651344396645738122752565598033556255024269728099686; - uint256 constant IC119x = 1328308549643118846463693088427234362874488580638550564357277553774477010791; - uint256 constant IC119y = 7968099729757825375814311903873299078493699569227171322917885132937350997706; + uint256 constant IC119x = 17799233217419218904947249719416254357206668472185292700130295367605789579775; + uint256 constant IC119y = 13357433285894857035918176715028754547770195229276863023502097143080160022945; - uint256 constant IC120x = 1556864282486119668149963214488257821693266783207387782817897342258032047205; - uint256 constant IC120y = 345066057082474708144324052630651363347247004656128520678101294107524804087; + uint256 constant IC120x = 4920886769503826804793409665884631809047006805062602388421875677124768046721; + uint256 constant IC120y = 18507588985777018307425077806242545993958240881877622815039150778856527681587; + + uint256 constant IC121x = 6964785589591486238080181833921462796610700077253539345330356770429293030717; + uint256 constant IC121y = 8503635953992332063607539325685434941643852119905312172589719060858125831267; + + uint256 constant IC122x = 8689872876956874390437091630997622342586358922128817789446107383199284524641; + uint256 constant IC122y = 6343146446211206573118957886118759897919995460983539671234308923132170936394; // Memory data @@ -413,7 +419,7 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[120] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[122] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -697,6 +703,10 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { g1_mulAccC(_pVk, IC120x, IC120y, calldataload(add(pubSignals, 3808))) + g1_mulAccC(_pVk, IC121x, IC121y, calldataload(add(pubSignals, 3840))) + + g1_mulAccC(_pVk, IC122x, IC122y, calldataload(add(pubSignals, 3872))) + // -A mstore(_pPairing, calldataload(pA)) @@ -992,6 +1002,10 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { checkField(calldataload(add(_pubSignals, 3840))) + checkField(calldataload(add(_pubSignals, 3872))) + + checkField(calldataload(add(_pubSignals, 3904))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/zeto_anon_enc.sol b/solidity/contracts/zeto_anon_enc.sol index 23b4c72..76e8473 100644 --- a/solidity/contracts/zeto_anon_enc.sol +++ b/solidity/contracts/zeto_anon_enc.sol @@ -77,6 +77,7 @@ contract Zeto_AnonEnc is uint256[] memory inputs, uint256[] memory outputs, uint256 encryptionNonce, + uint256[2] memory ecdhPublicKey, uint256[] memory encryptedValues, Commonlib.Proof calldata proof, bytes calldata data @@ -90,12 +91,16 @@ contract Zeto_AnonEnc is if (inputs.length > 2) { // construct the public inputs - uint256[43] memory publicInputs; + uint256[45] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for (uint256 i = 0; i < encryptedValues.length; ++i) { publicInputs[piIndex++] = encryptedValues[i]; } + // copy the ecdh public key + for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { + publicInputs[piIndex++] = ecdhPublicKey[i]; + } // copy input commitments for (uint256 i = 0; i < inputs.length; i++) { publicInputs[piIndex++] = inputs[i]; @@ -121,12 +126,16 @@ contract Zeto_AnonEnc is ); } else { // construct the public inputs - uint256[12] memory publicInputs; + uint256[14] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for (uint256 i = 0; i < encryptedValues.length; ++i) { publicInputs[piIndex++] = encryptedValues[i]; } + // copy the ecdh public key + for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { + publicInputs[piIndex++] = ecdhPublicKey[i]; + } // copy input commitments for (uint256 i = 0; i < inputs.length; i++) { publicInputs[piIndex++] = inputs[i]; @@ -164,6 +173,7 @@ contract Zeto_AnonEnc is inputs, outputs, encryptionNonce, + ecdhPublicKey, encryptedValuesArray, msg.sender, data diff --git a/solidity/contracts/zeto_anon_enc_nullifier.sol b/solidity/contracts/zeto_anon_enc_nullifier.sol index 9a26362..50bdba9 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier.sol @@ -83,6 +83,7 @@ contract Zeto_AnonEncNullifier is uint256[] memory outputs, uint256 root, uint256 encryptionNonce, + uint256[2] memory ecdhPublicKey, uint256[] memory encryptedValues, Commonlib.Proof calldata proof, bytes calldata data @@ -99,12 +100,16 @@ contract Zeto_AnonEncNullifier is ); if (nullifiers.length > 2) { // construct the public inputs - uint256[54] memory publicInputs; + uint256[56] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for (uint256 i = 0; i < encryptedValues.length; ++i) { publicInputs[piIndex++] = encryptedValues[i]; } + // copy the ecdh public key + for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { + publicInputs[piIndex++] = ecdhPublicKey[i]; + } // copy input commitments for (uint256 i = 0; i < nullifiers.length; i++) { publicInputs[piIndex++] = nullifiers[i]; @@ -138,12 +143,16 @@ contract Zeto_AnonEncNullifier is ); } else { // construct the public inputs - uint256[15] memory publicInputs; + uint256[17] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for (uint256 i = 0; i < encryptedValues.length; ++i) { publicInputs[piIndex++] = encryptedValues[i]; } + // copy the ecdh public key + for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { + publicInputs[piIndex++] = ecdhPublicKey[i]; + } // copy input commitments for (uint256 i = 0; i < nullifiers.length; i++) { publicInputs[piIndex++] = nullifiers[i]; @@ -191,6 +200,7 @@ contract Zeto_AnonEncNullifier is nullifiers, outputs, encryptionNonce, + ecdhPublicKey, encryptedValuesArray, msg.sender, data diff --git a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol index 4fdc2f4..84d67ea 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol @@ -88,6 +88,7 @@ contract Zeto_AnonEncNullifierKyc is uint256[] memory outputs, uint256 root, uint256 encryptionNonce, + uint256[2] memory ecdhPublicKey, uint256[] memory encryptedValues, Commonlib.Proof calldata proof, bytes calldata data @@ -104,12 +105,16 @@ contract Zeto_AnonEncNullifierKyc is ); if (nullifiers.length > 2) { // construct the public inputs - uint256[55] memory publicInputs; + uint256[57] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for (uint256 i = 0; i < encryptedValues.length; ++i) { publicInputs[piIndex++] = encryptedValues[i]; } + // copy the ecdh public key + for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { + publicInputs[piIndex++] = ecdhPublicKey[i]; + } // copy input commitments for (uint256 i = 0; i < nullifiers.length; i++) { publicInputs[piIndex++] = nullifiers[i]; @@ -145,12 +150,16 @@ contract Zeto_AnonEncNullifierKyc is ); } else { // construct the public inputs - uint256[16] memory publicInputs; + uint256[18] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for (uint256 i = 0; i < encryptedValues.length; ++i) { publicInputs[piIndex++] = encryptedValues[i]; } + // copy the ecdh public key + for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { + publicInputs[piIndex++] = ecdhPublicKey[i]; + } // copy input commitments for (uint256 i = 0; i < nullifiers.length; i++) { publicInputs[piIndex++] = nullifiers[i]; @@ -200,6 +209,7 @@ contract Zeto_AnonEncNullifierKyc is nullifiers, outputs, encryptionNonce, + ecdhPublicKey, encryptedValuesArray, msg.sender, data diff --git a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol index c2081c1..731665c 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol @@ -45,6 +45,7 @@ contract Zeto_AnonEncNullifierNonRepudiation is uint256[] inputs, uint256[] outputs, uint256 encryptionNonce, + uint256[2] ecdhPublicKey, uint256[] encryptedValuesForReceiver, uint256[] encryptedValuesForAuthority, address indexed submitter, @@ -105,6 +106,7 @@ contract Zeto_AnonEncNullifierNonRepudiation is uint256[] memory outputs, uint256 root, uint256 encryptionNonce, + uint256[2] memory ecdhPublicKey, uint256[] memory encryptedValuesForReceiver, uint256[] memory encryptedValuesForAuthority, Commonlib.Proof calldata proof, @@ -126,12 +128,16 @@ contract Zeto_AnonEncNullifierNonRepudiation is "Cipher Text for Authority must have a length of 64 with input or outputs number more than 2 and less than 10" ); // construct the public inputs - uint256[120] memory publicInputs; + uint256[122] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for receiver for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { publicInputs[piIndex++] = encryptedValuesForReceiver[i]; } + // copy the ecdh public key + for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { + publicInputs[piIndex++] = ecdhPublicKey[i]; + } // copy the encrypted value, salt and parity bit for authority for (uint256 i = 0; i < encryptedValuesForAuthority.length; ++i) { publicInputs[piIndex++] = encryptedValuesForAuthority[i]; @@ -177,12 +183,16 @@ contract Zeto_AnonEncNullifierNonRepudiation is "Cipher Text for Authority must have a length of 16 for no more than 2 inputs or outputs" ); // construct the public inputs - uint256[33] memory publicInputs; + uint256[35] memory publicInputs; uint256 piIndex = 0; // copy the encrypted value, salt and parity bit for receiver for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { publicInputs[piIndex++] = encryptedValuesForReceiver[i]; } + // copy the ecdh public key + for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { + publicInputs[piIndex++] = ecdhPublicKey[i]; + } // copy the encrypted value, salt and parity bit for authority for (uint256 i = 0; i < encryptedValuesForAuthority.length; ++i) { publicInputs[piIndex++] = encryptedValuesForAuthority[i]; @@ -244,6 +254,7 @@ contract Zeto_AnonEncNullifierNonRepudiation is nullifiers, outputs, encryptionNonce, + ecdhPublicKey, encryptedValuesReceiverArray, encryptedValuesAuthorityArray, msg.sender, diff --git a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts index 8cf2e9c..8f8bd2e 100644 --- a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts +++ b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts @@ -550,6 +550,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin outputCommitments, root, encryptionNonce, + ecdhPublicKey, encryptedValues, encodedProof, '0x' diff --git a/solidity/test/lib/utils.ts b/solidity/test/lib/utils.ts index 126524a..5218e8b 100644 --- a/solidity/test/lib/utils.ts +++ b/solidity/test/lib/utils.ts @@ -125,7 +125,8 @@ export function parseUTXOEvents(zetoTokenContract: any, result: ContractTransact outputs: event?.args.outputs, encryptedValues: event?.args.encryptedValues, encryptionNonce: event?.args.encryptionNonce, - submitter: event?.args.submitter + submitter: event?.args.submitter, + ecdhPublicKey: event?.args.ecdhPublicKey }; returnValues.push(transfer); } else if (event?.name === 'UTXOTransferNonRepudiation') { @@ -135,7 +136,8 @@ export function parseUTXOEvents(zetoTokenContract: any, result: ContractTransact encryptedValuesForReceiver: event?.args.encryptedValuesForReceiver, encryptedValuesForAuthority: event?.args.encryptedValuesForAuthority, encryptionNonce: event?.args.encryptionNonce, - submitter: event?.args.submitter + submitter: event?.args.submitter, + ecdhPublicKey: event?.args.ecdhPublicKey }; returnValues.push(transfer); } else if (event?.name === 'UTXOMint') { diff --git a/solidity/test/zeto_anon_enc.ts b/solidity/test/zeto_anon_enc.ts index a8fdb4f..17cf971 100644 --- a/solidity/test/zeto_anon_enc.ts +++ b/solidity/test/zeto_anon_enc.ts @@ -26,6 +26,7 @@ import { } from 'zeto-js'; import { groth16 } from 'snarkjs'; import { + genKeypair, formatPrivKeyForBabyJub, genEcdhSharedKey, stringifyBigInts, @@ -115,10 +116,10 @@ describe('Zeto based fungible token with anonymity and encryption', function () const events = parseUTXOEvents(zeto, result.txResult!); expect(events[0].inputs).to.deep.equal(inputUtxos.map((i) => i.hash)); const incomingUTXOs: any = events[0].outputs; - // Bob reconstructs the shared key using his private key and Alice's public key (obtained out of band) - const senderPublicKey = Alice.babyJubPublicKey; + const ecdhPublicKey = events[0].ecdhPublicKey; + // Bob reconstructs the shared key using his private key and ephemeral public key - const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, senderPublicKey); + const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); const plainText = poseidonDecrypt( events[0].encryptedValues, sharedKey, @@ -202,10 +203,10 @@ describe('Zeto based fungible token with anonymity and encryption', function () expect(events[0].outputs).to.deep.equal([_utxo1.hash, utxo4.hash]); const incomingUTXOs: any = events[0].outputs; - // Bob reconstructs the shared key using his private key and Alice's public key (obtained out of band) - const senderPublicKey = Alice.babyJubPublicKey; + const ecdhPublicKey = events[0].ecdhPublicKey; + // Bob reconstructs the shared key using his private key and ephemeral public key - const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, senderPublicKey); + const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); const plainText = poseidonDecrypt( events[0].encryptedValues, sharedKey, @@ -341,7 +342,14 @@ describe('Zeto based fungible token with anonymity and encryption', function () let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; - const result = await prepareProof(signer, inputs, outputs, owners); + const ephemeralKeypair = genKeypair(); + const result = await prepareProof( + signer, + inputs, + outputs, + owners, + ephemeralKeypair.privKey + ); inputCommitments = result.inputCommitments; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; @@ -354,7 +362,8 @@ describe('Zeto based fungible token with anonymity and encryption', function () outputCommitments, encryptedValues, encryptionNonce, - encodedProof + encodedProof, + ephemeralKeypair.pubKey ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { @@ -371,7 +380,8 @@ describe('Zeto based fungible token with anonymity and encryption', function () signer: User, inputs: UTXO[], outputs: UTXO[], - owners: User[] + owners: User[], + ephemeralPrivateKey: BigInt ) { const inputCommitments: BigNumberish[] = inputs.map( (input) => input.hash @@ -388,7 +398,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, - inputOwnerPrivateKey: formatPrivKeyForBabyJub(signer.babyJubPrivateKey), + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralPrivateKey), }); let circuitToUse = circuit; @@ -405,6 +415,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () inputCommitments, inputValues, inputSalts, + inputOwnerPrivateKey: formatPrivKeyForBabyJub(signer.babyJubPrivateKey), outputCommitments, outputValues, outputSalts: outputs.map((output) => output.salt || 0n), @@ -444,12 +455,14 @@ describe('Zeto based fungible token with anonymity and encryption', function () outputCommitments: BigNumberish[], encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, - encodedProof: any + encodedProof: any, + ecdhPublicKey: BigInt[] ) { const tx = await zeto.connect(signer.signer).transfer( inputCommitments.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works encryptionNonce, + ecdhPublicKey, encryptedValues, encodedProof, '0x' diff --git a/solidity/test/zeto_anon_enc_nullifier.ts b/solidity/test/zeto_anon_enc_nullifier.ts index 86948ef..338973e 100644 --- a/solidity/test/zeto_anon_enc_nullifier.ts +++ b/solidity/test/zeto_anon_enc_nullifier.ts @@ -25,7 +25,12 @@ import { newEncryptionNonce, } from 'zeto-js'; import { groth16 } from 'snarkjs'; -import { genEcdhSharedKey, stringifyBigInts } from 'maci-crypto'; +import { + genKeypair, + formatPrivKeyForBabyJub, + genEcdhSharedKey, + stringifyBigInts, +} from 'maci-crypto'; import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; import { UTXO, @@ -158,11 +163,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const incomingUTXOs: any = events[0].outputs; - // Bob uses the encrypted values in the event to decrypt and recover the UTXO value and salt - const sharedKey = genEcdhSharedKey( - Bob.babyJubPrivateKey, - Alice.babyJubPublicKey - ); + const ecdhPublicKey = events[0].ecdhPublicKey; + // Bob reconstructs the shared key using his private key and ephemeral public key + + const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); const plainText = poseidonDecrypt( events[0].encryptedValues, sharedKey, @@ -289,11 +293,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti await smtBob.add(events[0].outputs[0], events[0].outputs[0]); await smtBob.add(events[0].outputs[1], events[0].outputs[1]); - // Bob uses the encrypted values in the event to decrypt and recover the UTXO value and salt - const sharedKey = genEcdhSharedKey( - Bob.babyJubPrivateKey, - Alice.babyJubPublicKey - ); + const ecdhPublicKey = events[0].ecdhPublicKey; + // Bob reconstructs the shared key using his private key and ephemeral public key + + const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); const plainText = poseidonDecrypt( events[0].encryptedValues, sharedKey, @@ -622,6 +625,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; + const ephemeralKeypair = genKeypair(); const result = await prepareProof( signer, inputs, @@ -629,7 +633,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti outputs, root, merkleProofs, - owners + owners, + ephemeralKeypair.privKey ); nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, @@ -647,7 +652,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti root, encryptedValues, encryptionNonce, - encodedProof + encodedProof, + ephemeralKeypair.pubKey ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { @@ -667,7 +673,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti outputs: UTXO[], root: BigInt, merkleProof: BigInt[][], - owners: User[] + owners: User[], + ephemeralPrivateKey: BigInt ) { const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, @@ -688,6 +695,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralPrivateKey), }); let circuitToUse = circuit; let provingKeyToUse = provingKey; @@ -747,7 +755,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti root: BigNumberish, encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, - encodedProof: any + encodedProof: any, + ecdhPublicKey: BigInt[] ) { const startTx = Date.now(); const tx = await zeto.connect(signer.signer).transfer( @@ -755,6 +764,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works root, encryptionNonce, + ecdhPublicKey, encryptedValues, encodedProof, '0x' diff --git a/solidity/test/zeto_anon_enc_nullifier_kyc.ts b/solidity/test/zeto_anon_enc_nullifier_kyc.ts index 77d19de..8bc552f 100644 --- a/solidity/test/zeto_anon_enc_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_enc_nullifier_kyc.ts @@ -26,7 +26,12 @@ import { kycHash, } from 'zeto-js'; import { groth16 } from 'snarkjs'; -import { genEcdhSharedKey, stringifyBigInts } from 'maci-crypto'; +import { + genKeypair, + formatPrivKeyForBabyJub, + genEcdhSharedKey, + stringifyBigInts, +} from 'maci-crypto'; import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; import { UTXO, @@ -207,11 +212,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const incomingUTXOs: any = events[0].outputs; - // Bob uses the encrypted values in the event to decrypt and recover the UTXO value and salt - const sharedKey = genEcdhSharedKey( - Bob.babyJubPrivateKey, - Alice.babyJubPublicKey - ); + const ecdhPublicKey = events[0].ecdhPublicKey; + // Bob reconstructs the shared key using his private key and ephemeral public key + + const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); const plainText = poseidonDecrypt( events[0].encryptedValues, sharedKey, @@ -363,11 +367,9 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti await smtBob.add(events[0].outputs[0], events[0].outputs[0]); await smtBob.add(events[0].outputs[1], events[0].outputs[1]); - // Bob uses the encrypted values in the event to decrypt and recover the UTXO value and salt - const sharedKey = genEcdhSharedKey( - Bob.babyJubPrivateKey, - Alice.babyJubPublicKey - ); + const ecdhPublicKey = events[0].ecdhPublicKey; + // Bob reconstructs the shared key using his private key and ephemeral public key + const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); const plainText = poseidonDecrypt( events[0].encryptedValues, sharedKey, @@ -941,6 +943,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; + const ephemeralKeypair = genKeypair(); const result = await prepareProof( signer, inputs, @@ -950,7 +953,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti utxosMerkleProof, identitiesRoot, identitiesMerkleProof, - owners + owners, + ephemeralKeypair.privKey ); nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ @@ -969,7 +973,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti utxosRoot, encryptedValues, encryptionNonce, - encodedProof + encodedProof, + ephemeralKeypair.pubKey ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { @@ -991,7 +996,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti utxosMerkleProof: BigInt[][], identitiesRoot: BigInt, identitiesMerkleProof: BigInt[][], - owners: User[] + owners: User[], + ephemeralPrivateKey: BigInt ) { const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, @@ -1012,6 +1018,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralPrivateKey), }); let circuitToUse = circuit; let provingKeyToUse = provingKey; @@ -1073,7 +1080,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti root: BigNumberish, encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, - encodedProof: any + encodedProof: any, + ecdhPublicKey: BigInt[] ) { const startTx = Date.now(); const tx = await zeto.connect(signer.signer).transfer( @@ -1081,6 +1089,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works root, encryptionNonce, + ecdhPublicKey, encryptedValues, encodedProof, '0x' diff --git a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts index ff575b5..2a42868 100644 --- a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts +++ b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts @@ -25,7 +25,12 @@ import { newEncryptionNonce, } from 'zeto-js'; import { groth16 } from 'snarkjs'; -import { genEcdhSharedKey, stringifyBigInts } from 'maci-crypto'; +import { + genKeypair, + formatPrivKeyForBabyJub, + genEcdhSharedKey, + stringifyBigInts, +} from 'maci-crypto'; import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; import { UTXO, @@ -171,11 +176,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const incomingUTXOs: any = events[0].outputs; - // Bob uses the encrypted values in the event to decrypt and recover the UTXO value and salt - const sharedKey = genEcdhSharedKey( - Bob.babyJubPrivateKey, - Alice.babyJubPublicKey - ); + const ecdhPublicKey = events[0].ecdhPublicKey; + // Bob reconstructs the shared key using his private key and ephemeral public key + + const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); const plainText = poseidonDecrypt( events[0].encryptedValuesForReceiver, @@ -209,7 +213,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti // The regulator uses the encrypted values in the event to decrypt and recover the UTXO value and salt const auditKey = genEcdhSharedKey( Authority.babyJubPrivateKey, - Alice.babyJubPublicKey + ecdhPublicKey ); const auditPlainText = poseidonDecrypt( events[0].encryptedValuesForAuthority, @@ -346,11 +350,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti await smtBob.add(events[0].outputs[0], events[0].outputs[0]); await smtBob.add(events[0].outputs[1], events[0].outputs[1]); - // Bob uses the encrypted values in the event to decrypt and recover the UTXO value and salt - const sharedKey1 = genEcdhSharedKey( - Bob.babyJubPrivateKey, - Alice.babyJubPublicKey - ); + const ecdhPublicKey = events[0].ecdhPublicKey; + // Bob reconstructs the shared key using his private key and ephemeral public key + + const sharedKey1 = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); const plainText1 = poseidonDecrypt( events[0].encryptedValuesForReceiver, sharedKey1, @@ -362,7 +365,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti // The regulator uses the encrypted values in the event to decrypt and recover the UTXO value and salt const sharedKey2 = genEcdhSharedKey( Authority.babyJubPrivateKey, - Alice.babyJubPublicKey + ecdhPublicKey ); const plainText2 = poseidonDecrypt( events[0].encryptedValuesForAuthority, @@ -728,6 +731,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; + const ephemeralKeypair = genKeypair(); const result = await prepareProof( signer, inputs, @@ -735,7 +739,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti outputs, root, merkleProofs, - owners + owners, + ephemeralKeypair.privKey ); nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, @@ -753,7 +758,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti result.encryptedValuesForReceiver, result.encryptedValuesForRegulator, encryptionNonce, - encodedProof + encodedProof, + ephemeralKeypair.pubKey ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { @@ -773,7 +779,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti outputs: UTXO[], root: BigInt, merkleProof: BigInt[][], - owners: User[] + owners: User[], + ephemeralPrivateKey: BigInt ) { const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, @@ -794,6 +801,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralPrivateKey), }); let circuitToUse = circuit; let provingKeyToUse = provingKey; @@ -842,8 +850,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ? publicSignals.slice(0, 22) : publicSignals.slice(0, 7), encryptedValuesForRegulator: isBatch - ? publicSignals.slice(22, 86) - : publicSignals.slice(7, 23), + ? publicSignals.slice(24, 88) + : publicSignals.slice(9, 25), encryptionNonce, encodedProof, }; @@ -857,7 +865,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti encryptedValuesForReceiver: BigNumberish[], encryptedValuesForRegulator: BigNumberish[], encryptionNonce: BigNumberish, - encodedProof: any + encodedProof: any, + ecdhPublicKey: BigInt[] ) { const startTx = Date.now(); const tx = await zeto.connect(signer.signer).transfer( @@ -865,6 +874,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works root, encryptionNonce, + ecdhPublicKey, encryptedValuesForReceiver, encryptedValuesForRegulator, encodedProof, diff --git a/zkp/circuits/basetokens/anon_enc_base.circom b/zkp/circuits/basetokens/anon_enc_base.circom index ac5539d..433ea15 100644 --- a/zkp/circuits/basetokens/anon_enc_base.circom +++ b/zkp/circuits/basetokens/anon_enc_base.circom @@ -34,6 +34,8 @@ template Zeto(nInputs, nOutputs) { // must be properly hashed and trimmed to be compatible with the BabyJub curve. // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 signal input inputOwnerPrivateKey; + // an ephemeral private key that is used to generated the shared ECDH key for encryption + signal input ecdhPrivateKey; signal input outputCommitments[nOutputs]; signal input outputValues[nOutputs]; signal input outputSalts[nOutputs]; @@ -49,6 +51,9 @@ template Zeto(nInputs, nOutputs) { signal output cipherText[cLen]; + // the output for the public key of the ephemeral private key used in generating ECDH shared key + signal output ecdhPublicKey[2]; + // derive the sender's public key from the secret input // for the sender's private key. This step demonstrates // the sender really owns the private key for the input @@ -86,7 +91,7 @@ template Zeto(nInputs, nOutputs) { // generate shared secret var sharedSecret[2]; component ecdh = Ecdh(); - ecdh.privKey <== inputOwnerPrivateKey; + ecdh.privKey <== ecdhPrivateKey; ecdh.pubKey[0] <== outputOwnerPublicKeys[0][0]; ecdh.pubKey[1] <== outputOwnerPublicKeys[0][1]; sharedSecret[0] = ecdh.sharedKey[0]; @@ -103,4 +108,9 @@ template Zeto(nInputs, nOutputs) { for (var i = 0; i < cLen; i++) { encrypt.cipherText[i] ==> cipherText[i]; } + + component ecdhPub = BabyPbk(); + ecdhPub.in <== ecdhPrivateKey; + ecdhPublicKey[0] <== ecdhPub.Ax; + ecdhPublicKey[1] <== ecdhPub.Ay; } diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_base.circom index 8c62561..7a6811e 100644 --- a/zkp/circuits/basetokens/anon_enc_nullifier_base.circom +++ b/zkp/circuits/basetokens/anon_enc_nullifier_base.circom @@ -39,6 +39,8 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { // must be properly hashed and trimmed to be compatible with the BabyJub curve. // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 signal input inputOwnerPrivateKey; + // an ephemeral private key that is used to generated the shared ECDH key for encryption + signal input ecdhPrivateKey; signal input root; signal input merkleProof[nInputs][nSMTLevels]; signal input enabled[nInputs]; @@ -56,6 +58,9 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { cLen++; signal output cipherText[cLen]; + // the output for the public key of the ephemeral private key used in generating ECDH shared key + signal output ecdhPublicKey[2]; + // derive the sender's public key from the secret input // for the sender's private key. This step demonstrates // the sender really owns the private key for the input @@ -109,8 +114,7 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { // generate shared secret var sharedSecret[2]; component ecdh = Ecdh(); - ecdh.privKey <== inputOwnerPrivateKey; - // our circuit requires that the output UTXO for the receiver must be the first in the array + ecdh.privKey <== ecdhPrivateKey; ecdh.pubKey[0] <== outputOwnerPublicKeys[0][0]; ecdh.pubKey[1] <== outputOwnerPublicKeys[0][1]; sharedSecret[0] = ecdh.sharedKey[0]; @@ -127,4 +131,9 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { for (var i = 0; i < cLen; i++) { encrypt.cipherText[i] ==> cipherText[i]; } + + component ecdhPub = BabyPbk(); + ecdhPub.in <== ecdhPrivateKey; + ecdhPublicKey[0] <== ecdhPub.Ax; + ecdhPublicKey[1] <== ecdhPub.Ay; } diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom index 4231c76..dcfe91a 100644 --- a/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom +++ b/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom @@ -40,6 +40,8 @@ template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) { // must be properly hashed and trimmed to be compatible with the BabyJub curve. // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 signal input inputOwnerPrivateKey; + // an ephemeral private key that is used to generated the shared ECDH key for encryption + signal input ecdhPrivateKey; signal input utxosRoot; signal input utxosMerkleProof[nInputs][nUTXOSMTLevels]; signal input enabled[nInputs]; @@ -59,6 +61,9 @@ template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) { cLen++; signal output cipherText[cLen]; + // the output for the public key of the ephemeral private key used in generating ECDH shared key + signal output ecdhPublicKey[2]; + // derive the sender's public key from the secret input // for the sender's private key. This step demonstrates // the sender really owns the private key for the input @@ -138,8 +143,7 @@ template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) { // generate shared secret var sharedSecret[2]; component ecdh = Ecdh(); - ecdh.privKey <== inputOwnerPrivateKey; - // our circuit requires that the output UTXO for the receiver must be the first in the array + ecdh.privKey <== ecdhPrivateKey; ecdh.pubKey[0] <== outputOwnerPublicKeys[0][0]; ecdh.pubKey[1] <== outputOwnerPublicKeys[0][1]; sharedSecret[0] = ecdh.sharedKey[0]; @@ -156,4 +160,9 @@ template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) { for (var i = 0; i < cLen; i++) { encrypt.cipherText[i] ==> cipherText[i]; } + + component ecdhPub = BabyPbk(); + ecdhPub.in <== ecdhPrivateKey; + ecdhPublicKey[0] <== ecdhPub.Ax; + ecdhPublicKey[1] <== ecdhPub.Ay; } \ No newline at end of file diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom index d31e0a1..6adc30e 100644 --- a/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom +++ b/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom @@ -40,6 +40,8 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { // must be properly hashed and trimmed to be compatible with the BabyJub curve. // Reference: https://github.com/iden3/circomlib/blob/master/test/babyjub.js#L103 signal input inputOwnerPrivateKey; + // an ephemeral private key that is used to generated the shared ECDH key for encryption + signal input ecdhPrivateKey; signal input root; signal input merkleProof[nInputs][nSMTLevels]; signal input enabled[nInputs]; @@ -58,6 +60,9 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { cLen++; signal output cipherText[cLen]; + // the output for the public key of the ephemeral private key used in generating ECDH shared key + signal output ecdhPublicKey[2]; + // the number of cipher text messages returned by // the encryption template will be 3n+1 // input length: @@ -125,8 +130,7 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { // generate shared secret for the receiver var sharedSecretReceiver[2]; component ecdh1 = Ecdh(); - ecdh1.privKey <== inputOwnerPrivateKey; - // our circuit requires that the output UTXO for the receiver must be the first in the array + ecdh1.privKey <== ecdhPrivateKey; ecdh1.pubKey[0] <== outputOwnerPublicKeys[0][0]; ecdh1.pubKey[1] <== outputOwnerPublicKeys[0][1]; sharedSecretReceiver[0] = ecdh1.sharedKey[0]; @@ -147,17 +151,22 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { // generate shared secret for the authority var sharedSecretAuthority[2]; component ecdh2 = Ecdh(); - ecdh2.privKey <== inputOwnerPrivateKey; - // our circuit requires that the output UTXO for the receiver must be the first in the array + ecdh2.privKey <== ecdhPrivateKey; ecdh2.pubKey[0] <== authorityPublicKey[0]; ecdh2.pubKey[1] <== authorityPublicKey[1]; sharedSecretAuthority[0] = ecdh2.sharedKey[0]; sharedSecretAuthority[1] = ecdh2.sharedKey[1]; + component ecdhPub = BabyPbk(); + ecdhPub.in <== ecdhPrivateKey; + ecdhPublicKey[0] <== ecdhPub.Ax; + ecdhPublicKey[1] <== ecdhPub.Ay; + // encrypt the values for the authority component encrypt2 = SymmetricEncrypt(2 + 2 * nInputs + 4 * nOutputs); encrypt2.plainText[0] <== inputOwnerPublicKey[0]; encrypt2.plainText[1] <== inputOwnerPublicKey[1]; + var idx1 = 2; for (var i = 0; i < nInputs; i++) { encrypt2.plainText[idx1] <== inputValues[i]; @@ -180,4 +189,6 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { encrypt2.key <== sharedSecretAuthority; encrypt2.nonce <== encryptionNonce; encrypt2.cipherText ==> cipherTextAuthority; + + } \ No newline at end of file diff --git a/zkp/js/test/anon_enc.js b/zkp/js/test/anon_enc.js index 689c9fd..0f6c9c1 100644 --- a/zkp/js/test/anon_enc.js +++ b/zkp/js/test/anon_enc.js @@ -90,9 +90,10 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, - inputOwnerPrivateKey: formatPrivKeyForBabyJub(sender.privKey), + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); const witness = await circuit.calculateWitness( @@ -100,6 +101,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp inputCommitments, inputValues, inputSalts: [salt1, salt2], + inputOwnerPrivateKey: formatPrivKeyForBabyJub(sender.privKey), outputCommitments, outputValues, outputSalts: [salt3, salt4], @@ -110,21 +112,26 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp ); // console.log('witness', witness.slice(0, 15)); - // console.log('salt3', salt3); + // console.log('senderPublicKey', sender.pubKey); + // console.log('receiverPublicKey', receiver.pubKey); + // console.log('ephemeralPubkey', ephemeralKeypair.pubKey); // console.log('inputCommitments', inputCommitments); - // console.log('senderPublicKey', senderPubKey); - // console.log('receiverPublicKey', receiverPubKey); // console.log('encryptionNonce', encryptionNonce); - expect(witness[8]).to.equal(BigInt(inputCommitments[0])); - expect(witness[9]).to.equal(BigInt(inputCommitments[1])); - expect(witness[10]).to.equal(BigInt(outputCommitments[0])); - expect(witness[11]).to.equal(BigInt(outputCommitments[1])); + expect(witness[8]).to.equal(BigInt(ephemeralKeypair.pubKey[0])); + expect(witness[9]).to.equal(BigInt(ephemeralKeypair.pubKey[1])); + expect(witness[10]).to.equal(BigInt(inputCommitments[0])); + expect(witness[11]).to.equal(BigInt(inputCommitments[1])); + expect(witness[12]).to.equal(BigInt(outputCommitments[0])); + expect(witness[13]).to.equal(BigInt(outputCommitments[1])); // take the output from the proof circuit and attempt to decrypt // as the receiver const cipherText = witness.slice(1, 8); - const recoveredKey = genEcdhSharedKey(receiver.privKey, sender.pubKey); + const recoveredKey = genEcdhSharedKey( + receiver.privKey, + ephemeralKeypair.pubKey + ); const plainText = poseidonDecrypt( cipherText, recoveredKey, @@ -173,9 +180,10 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, - inputOwnerPrivateKey: formatPrivKeyForBabyJub(sender.privKey), + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); let err; @@ -185,6 +193,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp inputCommitments, inputValues, inputSalts: [salt1, salt2], + inputOwnerPrivateKey: formatPrivKeyForBabyJub(sender.privKey), outputCommitments, outputValues, outputSalts: [salt3, salt3], @@ -197,7 +206,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp err = e; } // console.log(err); - expect(err).to.match(/Error in template Zeto_105 line: 84/); + expect(err).to.match(/Error in template Zeto_105 line: 89/); }); it('should failed to match output UTXO after decrypting the cipher texts from the events if using the wrong sender public keys', async () => { @@ -235,9 +244,10 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, - inputOwnerPrivateKey: formatPrivKeyForBabyJub(sender.privKey), + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); const witness = await circuit.calculateWitness( @@ -245,6 +255,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp inputCommitments, inputValues, inputSalts: [salt1, salt2], + inputOwnerPrivateKey: formatPrivKeyForBabyJub(sender.privKey), outputCommitments, outputValues, outputSalts: [salt3, salt4], diff --git a/zkp/js/test/anon_enc_nullifier.js b/zkp/js/test/anon_enc_nullifier.js index 648bef6..3e71f07 100644 --- a/zkp/js/test/anon_enc_nullifier.js +++ b/zkp/js/test/anon_enc_nullifier.js @@ -135,8 +135,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); const witness = await circuit.calculateWitness( @@ -173,14 +175,14 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // console.log('outputOwnerPublicKeys', [Bob.pubKey, Alice.pubKey]); // console.log('encryptionNonce', encryptionNonce); - expect(witness[8]).to.equal(BigInt(nullifiers[0])); - expect(witness[9]).to.equal(BigInt(nullifiers[1])); - expect(witness[10]).to.equal(proof1.root.bigInt()); + expect(witness[10]).to.equal(BigInt(nullifiers[0])); + expect(witness[11]).to.equal(BigInt(nullifiers[1])); + expect(witness[12]).to.equal(proof1.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver const cipherText = witness.slice(1, 8); // first 7 elements are the cipher text for the encryption output - const recoveredKey = genEcdhSharedKey(Bob.privKey, Alice.pubKey); + const recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); const plainText = poseidonDecrypt( cipherText, recoveredKey, @@ -237,8 +239,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); const witness = await circuit.calculateWitness( @@ -275,14 +279,14 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // console.log('outputOwnerPublicKeys', [receiver.pubKey, sender.pubKey]); // console.log('encryptionNonce', encryptionNonce); - expect(witness[8]).to.equal(BigInt(nullifiers[0])); - expect(witness[9]).to.equal(BigInt(nullifiers[1])); - expect(witness[10]).to.equal(proof1.root.bigInt()); + expect(witness[10]).to.equal(BigInt(nullifiers[0])); + expect(witness[11]).to.equal(BigInt(nullifiers[1])); + expect(witness[12]).to.equal(proof1.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver const cipherText = witness.slice(1, 8); // first 7 elements are the cipher text for the encryption output - const recoveredKey = genEcdhSharedKey(Bob.privKey, Alice.pubKey); + const recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); const plainText = poseidonDecrypt( cipherText, recoveredKey, @@ -352,10 +356,11 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym ]); const outputCommitments = [output1, output2]; - const sharedSecret = genEcdhSharedKey(Alice.privKey, Bob.pubKey); const encryptionNonce = genRandomSalt(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); let err; @@ -386,6 +391,6 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym } // console.log(err); expect(err).to.match(/Error in template CheckSum_161 line: 44/); - expect(err).to.match(/Error in template Zeto_263 line: 97/); + expect(err).to.match(/Error in template Zeto_263 line: 102/); }); }); diff --git a/zkp/js/test/anon_enc_nullifier_kyc.js b/zkp/js/test/anon_enc_nullifier_kyc.js index 66a5043..9f86de7 100644 --- a/zkp/js/test/anon_enc_nullifier_kyc.js +++ b/zkp/js/test/anon_enc_nullifier_kyc.js @@ -150,8 +150,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); // generate the merkle proof for the transacting identities @@ -206,15 +208,15 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // console.log('identitiesRoot', proof3.root.bigInt()); // console.log('encryptionNonce', encryptionNonce); - expect(witness[8]).to.equal(BigInt(nullifiers[0])); - expect(witness[9]).to.equal(BigInt(nullifiers[1])); - expect(witness[10]).to.equal(proof1.root.bigInt()); - expect(witness[13]).to.equal(proof3.root.bigInt()); + expect(witness[10]).to.equal(BigInt(nullifiers[0])); + expect(witness[11]).to.equal(BigInt(nullifiers[1])); + expect(witness[12]).to.equal(proof1.root.bigInt()); + expect(witness[15]).to.equal(proof3.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver const cipherText = witness.slice(1, 8); // first 7 elements are the cipher text for the encryption output - const recoveredKey = genEcdhSharedKey(Bob.privKey, Alice.pubKey); + const recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); const plainText = poseidonDecrypt( cipherText, recoveredKey, @@ -297,8 +299,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym const identitiesRoot = proof3.root.bigInt(); const encryptionNonce = genRandomSalt(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); let err; @@ -334,7 +338,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym err = e; } // console.log(err); - expect(err).to.match(/Error in template Zeto_266 line: 136/); + expect(err).to.match(/Error in template Zeto_266 line: 141/); expect(err).to.match(/Error in template CheckSMTProof_253 line: 46/); }); }); diff --git a/zkp/js/test/anon_enc_nullifier_non_repudiation.js b/zkp/js/test/anon_enc_nullifier_non_repudiation.js index 3efbbc5..2257fbc 100644 --- a/zkp/js/test/anon_enc_nullifier_non_repudiation.js +++ b/zkp/js/test/anon_enc_nullifier_non_repudiation.js @@ -42,7 +42,7 @@ const poseidonHash = Poseidon.poseidon4; const poseidonHash3 = Poseidon.poseidon3; describe('main circuit tests for Zeto fungible tokens with encryption for non-repudiation and anonymity using nullifiers', () => { - let circuit, smtAlice, smtBob; + let circuit, smtAlice; const Alice = {}; const Bob = {}; @@ -143,8 +143,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); const witness = await circuit.calculateWitness( @@ -182,14 +184,14 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // console.log('outputOwnerPublicKeys', [Bob.pubKey, Alice.pubKey]); // console.log('encryptionNonce', encryptionNonce); - expect(witness[24]).to.equal(BigInt(nullifiers[0])); - expect(witness[25]).to.equal(BigInt(nullifiers[1])); - expect(witness[26]).to.equal(proof1.root.bigInt()); + expect(witness[26]).to.equal(BigInt(nullifiers[0])); + expect(witness[27]).to.equal(BigInt(nullifiers[1])); + expect(witness[28]).to.equal(proof1.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver const cipherText = witness.slice(1, 8); // per the encryption scheme, the output has 7 elements - const recoveredKey = genEcdhSharedKey(Bob.privKey, Alice.pubKey); + const recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); const plainText = poseidonDecrypt( cipherText, recoveredKey, @@ -200,8 +202,11 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // take the output from the proof circuit and attempt to decrypt // as the regulator - const recoveredKey2 = genEcdhSharedKey(Regulator.privKey, Alice.pubKey); - const cipherText2 = witness.slice(8, 24); // next 16 elements are the cipher text for the second encryption output + const recoveredKey2 = genEcdhSharedKey( + Regulator.privKey, + ephemeralKeypair.pubKey + ); + const cipherText2 = witness.slice(10, 26); // next 16 elements are the cipher text for the second encryption output const plainText2 = poseidonDecrypt( cipherText2, recoveredKey2, @@ -273,8 +278,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); const witness = await circuit.calculateWitness( @@ -312,14 +319,14 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // console.log('outputOwnerPublicKeys', [receiver.pubKey, sender.pubKey]); // console.log('encryptionNonce', encryptionNonce); - expect(witness[24]).to.equal(BigInt(nullifiers[0])); - expect(witness[25]).to.equal(BigInt(nullifiers[1])); - expect(witness[26]).to.equal(proof1.root.bigInt()); + expect(witness[26]).to.equal(BigInt(nullifiers[0])); + expect(witness[27]).to.equal(BigInt(nullifiers[1])); + expect(witness[28]).to.equal(proof1.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver const cipherText = witness.slice(1, 8); // first 7 elements are the cipher text for the first encryption output - const recoveredKey = genEcdhSharedKey(Bob.privKey, Alice.pubKey); + const recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); const plainText = poseidonDecrypt( cipherText, recoveredKey, @@ -330,8 +337,11 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // take the output from the proof circuit and attempt to decrypt // as the regulator - const recoveredKey2 = genEcdhSharedKey(Regulator.privKey, Alice.pubKey); - const cipherText2 = witness.slice(8, 24); // next 16 elements are the cipher text for the second encryption output + const recoveredKey2 = genEcdhSharedKey( + Regulator.privKey, + ephemeralKeypair.pubKey + ); + const cipherText2 = witness.slice(10, 26); // next 16 elements are the cipher text for the second encryption output const plainText2 = poseidonDecrypt( cipherText2, recoveredKey2, @@ -417,8 +427,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); let err; @@ -450,6 +462,6 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re } // console.log(err); expect(err).to.match(/Error in template CheckSum_161 line: 44/); - expect(err).to.match(/Error in template Zeto_264 line: 113/); + expect(err).to.match(/Error in template Zeto_264 line: 118/); }); }); From 2254d92867518b11e08eaba70816108a6e27afd4 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Fri, 27 Sep 2024 14:53:03 +0100 Subject: [PATCH 14/24] fixing golang e2e Signed-off-by: Chengxuan Xing --- go-sdk/integration-test/e2e_test.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/go-sdk/integration-test/e2e_test.go b/go-sdk/integration-test/e2e_test.go index 5d6d16c..b3ab14d 100644 --- a/go-sdk/integration-test/e2e_test.go +++ b/go-sdk/integration-test/e2e_test.go @@ -217,6 +217,7 @@ func (s *E2ETestSuite) TestZeto_2_SuccessfulProving() { outputCommitments := []*big.Int{output1, output2} encryptionNonce := crypto.NewEncryptionNonce() + ephemeralKeypair := testutils.NewKeypair() witnessInputs := map[string]interface{}{ "inputCommitments": inputCommitments, @@ -228,6 +229,7 @@ func (s *E2ETestSuite) TestZeto_2_SuccessfulProving() { "outputSalts": []*big.Int{salt3, salt4}, "outputOwnerPublicKeys": [][]*big.Int{{receiver.PublicKey.X, receiver.PublicKey.Y}, {sender.PublicKey.X, sender.PublicKey.Y}}, "encryptionNonce": encryptionNonce, + "ecdhPrivateKey": ephemeralKeypair.PrivateKey.Scalar().BigInt(), } startTime := time.Now() @@ -242,7 +244,7 @@ func (s *E2ETestSuite) TestZeto_2_SuccessfulProving() { assert.Equal(s.T(), 3, len(proof.Proof.A)) assert.Equal(s.T(), 3, len(proof.Proof.B)) assert.Equal(s.T(), 3, len(proof.Proof.C)) - assert.Equal(s.T(), 12, len(proof.PubSignals)) + assert.Equal(s.T(), 14, len(proof.PubSignals)) // the receiver would be able to get the encrypted values and salts // from the transaction events @@ -256,7 +258,7 @@ func (s *E2ETestSuite) TestZeto_2_SuccessfulProving() { // the first two elements in the public signals are the encrypted value and salt // for the first output. decrypt using the receiver's private key and compare with // the UTXO hash - secret := crypto.GenerateECDHSharedSecret(receiver.PrivateKey, sender.PublicKey) + secret := crypto.GenerateECDHSharedSecret(receiver.PrivateKey, ephemeralKeypair.PublicKey) decrypted, err := crypto.PoseidonDecrypt(encryptedValues, []*big.Int{secret.X, secret.Y}, encryptionNonce, 4) assert.NoError(s.T(), err) assert.Equal(s.T(), outputValues[0].String(), decrypted[0].String()) @@ -403,6 +405,7 @@ func (s *E2ETestSuite) TestZeto_4_SuccessfulProving() { outputCommitments := []*big.Int{output1, output2} encryptionNonce := crypto.NewEncryptionNonce() + ephemeralKeypair := testutils.NewKeypair() proof1Siblings := make([]*big.Int, len(circomProof1.Siblings)-1) for i, s := range circomProof1.Siblings[0 : len(circomProof1.Siblings)-1] { @@ -426,6 +429,7 @@ func (s *E2ETestSuite) TestZeto_4_SuccessfulProving() { "outputSalts": []*big.Int{salt3, salt4}, "outputOwnerPublicKeys": [][]*big.Int{{receiver.PublicKey.X, receiver.PublicKey.Y}, {sender.PublicKey.X, sender.PublicKey.Y}}, "encryptionNonce": encryptionNonce, + "ecdhPrivateKey": ephemeralKeypair.PrivateKey.Scalar().BigInt(), } startTime := time.Now() @@ -440,7 +444,7 @@ func (s *E2ETestSuite) TestZeto_4_SuccessfulProving() { assert.Equal(s.T(), 3, len(proof.Proof.A)) assert.Equal(s.T(), 3, len(proof.Proof.B)) assert.Equal(s.T(), 3, len(proof.Proof.C)) - assert.Equal(s.T(), 15, len(proof.PubSignals)) + assert.Equal(s.T(), 17, len(proof.PubSignals)) } func (s *E2ETestSuite) TestZeto_5_SuccessfulProving() { From 1e9addbf37c9065099a1660a08abdf6c7e58e7b8 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Sun, 29 Sep 2024 09:12:21 +0100 Subject: [PATCH 15/24] fixing gas cost test Signed-off-by: Chengxuan Xing --- ...to_anon_enc_nullifier_kyc_cost_analysis.ts | 237 ++++++++++-------- 1 file changed, 136 insertions(+), 101 deletions(-) diff --git a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts index 8f8bd2e..9bc82a9 100644 --- a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts +++ b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts @@ -20,7 +20,11 @@ import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; import { expect } from 'chai'; import { loadCircuit, encodeProof, newEncryptionNonce, kycHash } from 'zeto-js'; import { groth16 } from 'snarkjs'; -import { stringifyBigInts } from 'maci-crypto'; +import { + genKeypair, + formatPrivKeyForBabyJub, + stringifyBigInts, +} from 'maci-crypto'; import AsyncLock from 'async-lock'; const lock = new AsyncLock(); import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; @@ -34,7 +38,6 @@ import { doDeposit, doWithdraw, ZERO_UTXO, - parseUTXOEvents, parseRegistryEvents, } from '../lib/utils'; import { @@ -45,7 +48,8 @@ import { import { deployZeto } from '../lib/deploy'; const TOTAL_AMOUNT = parseInt(process.env.TOTAL_ROUNDS || '1000'); -const TX_CONCURRENCY = parseInt(process.env.TX_CONCURRENCY || '30'); +const TX_CONCURRENCY = parseInt(process.env.TX_CONCURRENCY || '1'); +const UTXO_PER_TX = 10; describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity using nullifiers and encryption with KYC', function () { let deployer: Signer; @@ -56,6 +60,9 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin let zeto: any; const atMostHalfAmount = Math.floor(TOTAL_AMOUNT / 2); const atLeastHalfAmount = atMostHalfAmount + (TOTAL_AMOUNT % 2); + const mintCount = + Math.floor(atLeastHalfAmount / UTXO_PER_TX) + + (atLeastHalfAmount % UTXO_PER_TX !== 0 ? 1 : 0); let unspentAliceUTXOs: UTXO[] = []; let unspentBobUTXOs: UTXO[] = []; let mintGasCostHistory: number[] = []; @@ -63,9 +70,13 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin let transferGasCostHistory: number[] = []; let withdrawGasCostHistory: number[] = []; let circuit: any, provingKey: any; + let batchCircuit: any, batchProvingKey: any; let smtAlice: Merkletree; let smtBob: Merkletree; let smtKyc: Merkletree; + const transferCount = + Math.floor(TOTAL_AMOUNT / UTXO_PER_TX) + + (TOTAL_AMOUNT % UTXO_PER_TX !== 0 ? 1 : 0); const date = new Date(); const reportPrefix = date.toISOString(); @@ -90,11 +101,6 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin const tx4 = await zeto.connect(deployer).register(Charlie.babyJubPublicKey); const result3 = await tx4.wait(); - circuit = await loadCircuit('anon_enc_nullifier_kyc'); - ({ provingKeyFile: provingKey } = loadProvingKeys( - 'anon_enc_nullifier_kyc' - )); - const storage1 = new InMemoryDB(str2Bytes('alice')); smtAlice = new Merkletree(storage1, true, 64); @@ -110,6 +116,15 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin await smtKyc.add(kycHash(publicKey2), kycHash(publicKey2)); const publicKey3 = parseRegistryEvents(zeto, result3); await smtKyc.add(kycHash(publicKey3), kycHash(publicKey3)); + + circuit = await loadCircuit('anon_enc_nullifier_kyc'); + ({ provingKeyFile: provingKey } = loadProvingKeys( + 'anon_enc_nullifier_kyc' + )); + batchCircuit = await loadCircuit('anon_enc_nullifier_kyc_batch'); + ({ provingKeyFile: batchProvingKey } = loadProvingKeys( + 'anon_enc_nullifier_kyc_batch' + )); }); after(function () { @@ -191,40 +206,27 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ); }).timeout(6000000000000); - it(`Zeto mint ${atMostHalfAmount + (TOTAL_AMOUNT % 2)} token to Alice in ${ - Math.floor(atLeastHalfAmount / 2) + (atLeastHalfAmount % 2) - } txs`, async function () { - const mintRounds = - Math.floor(atLeastHalfAmount / 2) + (atLeastHalfAmount % 2); + it(`Zeto mint ${atLeastHalfAmount} token to Alice in ${mintCount} txs`, async function () { let promises = []; - for (let i = 0; i < mintRounds; i++) { + for (let i = 0; i < mintCount; i++) { promises.push( (async () => { - const utxo1 = newUTXO(1, Alice); - let utxo2 = newUTXO(1, Alice); - - if (i === mintRounds - 1 && atLeastHalfAmount % 2 === 1) { - utxo2 = newUTXO(0, Alice); // odd number + const mintUTXOs = []; + for (let j = 0; j < UTXO_PER_TX; j++) { + if ( + i !== mintCount - 1 || + atLeastHalfAmount % UTXO_PER_TX === 0 || + j < atLeastHalfAmount % UTXO_PER_TX + ) { + const _new_utxo = newUTXO(1, Alice); + mintUTXOs.push(_new_utxo); + await smtAlice.add(_new_utxo.hash, _new_utxo.hash); + await smtBob.add(_new_utxo.hash, _new_utxo.hash); + unspentAliceUTXOs.push(_new_utxo); + } } - const result1 = await doMint( - zeto, - deployer, - [utxo1, utxo2], - mintGasCostHistory - ); - const mintEvents = parseUTXOEvents(zeto, result1); - const [_utxo1, _utxo2] = mintEvents[0].outputs; - - // Add UTXOs to the sets - await smtAlice.add(_utxo1, _utxo1); - await smtBob.add(_utxo1, _utxo1); - await smtAlice.add(_utxo2, _utxo2); - await smtBob.add(_utxo2, _utxo2); - - // Save unspent UTXOs - unspentAliceUTXOs.push(utxo1); - unspentAliceUTXOs.push(utxo2); + await doMint(zeto, deployer, mintUTXOs, mintGasCostHistory); })() ); @@ -234,7 +236,6 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin promises = []; // Reset promises for the next batch } } - // Run any remaining promises that didn’t fill the batch if (promises.length > 0) { await Promise.all(promises); @@ -245,8 +246,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ); }).timeout(6000000000000); - it(`Alice transfer ${TOTAL_AMOUNT} tokens to Bob in ${atLeastHalfAmount} txs`, async function () { - const totalTxs = Math.floor(unspentAliceUTXOs.length / 2); + it(`Alice transfer ${TOTAL_AMOUNT} tokens to Bob in ${transferCount} txs`, async function () { const utxosRoot = await smtAlice.root(); // get the root before all transfer and use it for all the proofs let promises = []; // Alice generates inclusion proofs for the identities in the transaction @@ -261,57 +261,67 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ); const identityMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) - proof4.siblings.map((s) => s.bigInt()), // identity proof for the 1st owner of the output UTXO (Bob) - proof4.siblings.map((s) => s.bigInt()), // identity proof for the 2nd owner of the output UTXO (Bob) ]; - for (let i = 0; i < totalTxs; i++) { + const batchSize = UTXO_PER_TX > 2 ? 10 : 2; + + for (let i = 0; i < batchSize; i++) { + identityMerkleProofs.push(proof4.siblings.map((s) => s.bigInt())); // identity proof for the output utxos (Bob) + } + + for (let i = 0; i < transferCount; i++) { promises.push( (async () => { - const utxo1 = unspentAliceUTXOs[i * 2]; - const utxo2 = unspentAliceUTXOs[i * 2 + 1]; - - const newUtxo1 = newUTXO(1, Bob); - let newUtxo2 = newUTXO(1, Bob); - if (i === totalTxs - 1 && TOTAL_AMOUNT % 2 === 1) { - // last round - newUtxo2 = newUTXO(0, Bob); // odd number + const _inUtxos = []; + const _outUtxos = []; + const _mtps = []; + const _nullifiers = []; + for (let j = 0; j < UTXO_PER_TX; j++) { + if ( + i !== transferCount - 1 || + unspentAliceUTXOs.length % UTXO_PER_TX === 0 || + j < unspentAliceUTXOs.length % UTXO_PER_TX + ) { + const _iUtxo = unspentAliceUTXOs[i * UTXO_PER_TX + j]; + _inUtxos.push(_iUtxo); + _nullifiers.push(newNullifier(_iUtxo, Alice)); + // Alice generates inclusion proofs for the UTXOs to be spent + const inProof = await smtAlice.generateCircomVerifierProof( + _iUtxo.hash, + utxosRoot + ); + _mtps.push(inProof.siblings.map((s) => s.bigInt())); + const _oUtox = newUTXO(1, Bob); + _outUtxos.push(_oUtox); + unspentBobUTXOs.push(_oUtox); + } else { + // _inUtxos.push(ZERO_UTXO); + // const inProof = await smtAlice.generateCircomVerifierProof( + // BigInt(0), + // utxosRoot + // ); + // _mtps.push(inProof.siblings.map((s) => s.bigInt())); + // _nullifiers.push(ZERO_UTXO); + } + } + const owners = []; + for (let i = 0; i < batchSize; i++) { + owners.push(Bob); } - const nullifier1 = newNullifier(utxo1, Alice); - const nullifier2 = newNullifier(utxo2, Alice); - // Alice generates inclusion proofs for the UTXOs to be spent - const proof1 = await smtAlice.generateCircomVerifierProof( - utxo1.hash, - utxosRoot - ); - const proof2 = await smtAlice.generateCircomVerifierProof( - utxo2.hash, - utxosRoot - ); - const utxoMerkleProofs = [ - proof1.siblings.map((s) => s.bigInt()), - proof2.siblings.map((s) => s.bigInt()), - ]; // Alice transfers her UTXOs to Bob await doTransfer( Alice, - [utxo1, utxo2], - [nullifier1, nullifier2], - [newUtxo1, newUtxo2], + _inUtxos, + _nullifiers, + _outUtxos, utxosRoot.bigInt(), - utxoMerkleProofs, + _mtps, identitiesRoot.bigInt(), identityMerkleProofs, - [Bob, Bob], + owners, transferGasCostHistory ); - await smtAlice.add(newUtxo1.hash, newUtxo1.hash); - await smtBob.add(newUtxo1.hash, newUtxo1.hash); - await smtAlice.add(newUtxo2.hash, newUtxo2.hash); - await smtBob.add(newUtxo2.hash, newUtxo2.hash); - unspentBobUTXOs.push(newUtxo1); - unspentBobUTXOs.push(newUtxo2); })() ); @@ -326,6 +336,12 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin if (promises.length > 0) { await Promise.all(promises); } + + for (let i = 0; i < unspentBobUTXOs.length; i++) { + const _oUtox = unspentBobUTXOs[i]; + await smtAlice.add(_oUtox.hash, _oUtox.hash); + await smtBob.add(_oUtox.hash, _oUtox.hash); + } writeGasCostsToCSV( `${reportPrefix}transfer_gas_costs.csv`, transferGasCostHistory @@ -409,11 +425,12 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin owners: User[], gasHistories: number[] ) { - let nullifiers: [BigNumberish, BigNumberish]; - let outputCommitments: [BigNumberish, BigNumberish]; + let nullifiers: BigNumberish[]; + let outputCommitments: BigNumberish[]; let encryptedValues: BigNumberish[]; let encryptionNonce: BigNumberish; let encodedProof: any; + const ephemeralKeypair = genKeypair(); const result = await prepareProof( signer, inputs, @@ -423,7 +440,8 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin utxosMerkleProof, identitiesRoot, identitiesMerkleProof, - owners + owners, + ephemeralKeypair.privKey ); nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ @@ -442,13 +460,21 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin utxosRoot, encryptedValues, encryptionNonce, - encodedProof + encodedProof, + ephemeralKeypair.pubKey ); if (txResult?.gasUsed && Array.isArray(gasHistories)) { gasHistories.push(txResult?.gasUsed); } // add the clear text value so that it can be used by tests to compare with the decrypted value - return { txResult, plainTextSalt: outputs[0].salt }; + return { + txResult, + expectedPlainText: outputs.reduce((acc, o, i) => { + acc.push(BigInt(o.value || 0n) as BigNumberish); + acc.push((o.salt || 0n) as BigNumberish); + return acc; + }, [] as BigNumberish[]), + }; } async function prepareProof( @@ -460,31 +486,29 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin utxosMerkleProof: BigInt[][], identitiesRoot: BigInt, identitiesMerkleProof: BigInt[][], - owners: User[] + owners: User[], + ephemeralPrivateKey: BigInt ) { const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, BigNumberish ]; - const inputCommitments: [BigNumberish, BigNumberish] = inputs.map( + const inputCommitments: BigNumberish[] = inputs.map( (input) => input.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); - const outputCommitments: [BigNumberish, BigNumberish] = outputs.map( + const outputCommitments: BigNumberish[] = outputs.map( (output) => output.hash - ) as [BigNumberish, BigNumberish]; + ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); - const outputOwnerPublicKeys: [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ] = owners.map((owner) => owner.babyJubPublicKey) as [ - [BigNumberish, BigNumberish], - [BigNumberish, BigNumberish] - ]; + const outputOwnerPublicKeys: BigNumberish[][] = owners.map( + (owner) => owner.babyJubPublicKey + ) as BigNumberish[][]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralPrivateKey), }); const startWitnessCalculation = Date.now(); @@ -495,7 +519,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin inputSalts, inputOwnerPrivateKey: signer.formattedPrivateKey, utxosRoot, - enabled: [nullifiers[0] !== 0n ? 1 : 0, nullifiers[1] !== 0n ? 1 : 0], + enabled: nullifiers.map((n) => (n !== 0n ? 1 : 0)), utxosMerkleProof, identitiesRoot, identitiesMerkleProof, @@ -505,15 +529,23 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin outputOwnerPublicKeys, ...encryptInputs, }; + let circuitToUse = circuit; + let provingKeyToUse = provingKey; + let isBatch = false; + if (inputCommitments.length > 2 || outputCommitments.length > 2) { + isBatch = true; + circuitToUse = batchCircuit; + provingKeyToUse = batchProvingKey; + } const witness = await lock.acquire('proofGen', async () => { // this lock is added for https://github.com/hyperledger-labs/zeto/issues/80, which only happens for Transfer circuit, not deposit/mint - return circuit.calculateWTNSBin(inputObj, true); + return circuitToUse.calculateWTNSBin(inputObj, true); }); const timeWithnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( - provingKey, + provingKeyToUse, witness )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; @@ -523,7 +555,9 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ); const encodedProof = encodeProof(proof); - const encryptedValues = publicSignals.slice(0, 4); + const encryptedValues = isBatch + ? publicSignals.slice(0, 22) + : publicSignals.slice(0, 7); return { inputCommitments, outputCommitments, @@ -535,12 +569,13 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin async function sendTx( signer: User, - nullifiers: [BigNumberish, BigNumberish], - outputCommitments: [BigNumberish, BigNumberish], + nullifiers: BigNumberish[], + outputCommitments: BigNumberish[], root: BigNumberish, encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, - encodedProof: any + encodedProof: any, + ecdhPublicKey: BigInt[] ) { const startTx = Date.now(); const tx = await zeto From 66f07b8bd0453f01ad2936f30c39318b22ecfcaa Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Tue, 1 Oct 2024 09:14:38 +0100 Subject: [PATCH 16/24] adding prettier Signed-off-by: Chengxuan Xing --- solidity/.prettierrc | 3 + solidity/package.json | 6 +- solidity/test/factory.ts | 16 +- ...to_anon_enc_nullifier_kyc_cost_analysis.ts | 68 +++---- solidity/test/lib/deploy.ts | 2 +- solidity/test/lib/utils.ts | 117 +++++++++--- solidity/test/utils.ts | 26 +-- solidity/test/zeto_anon.ts | 48 ++--- solidity/test/zeto_anon_enc.ts | 52 +++--- solidity/test/zeto_anon_enc_nullifier.ts | 88 ++++----- solidity/test/zeto_anon_enc_nullifier_kyc.ts | 156 ++++++++-------- ...zeto_anon_enc_nullifier_non_repudiation.ts | 102 +++++------ solidity/test/zeto_anon_nullifier.ts | 84 ++++----- solidity/test/zeto_anon_nullifier_kyc.ts | 150 ++++++++-------- solidity/test/zeto_nf_anon.ts | 24 +-- solidity/test/zeto_nf_anon_nullifier.ts | 40 ++--- solidity/test/zkDvP.ts | 112 +++++++----- zkp/js/.prettierrc | 3 + zkp/js/integration-test/anon.js | 31 +++- zkp/js/integration-test/anon_enc.js | 37 +++- zkp/js/integration-test/anon_enc_nullifier.js | 84 +++++++-- .../anon_enc_nullifier_kyc.js | 16 +- .../anon_enc_nullifier_non_repudiation.js | 85 +++++++-- zkp/js/integration-test/anon_nullifier.js | 65 +++++-- zkp/js/integration-test/anon_nullifier_kyc.js | 84 +++++++-- zkp/js/integration-test/check_hashes_value.js | 18 +- .../check_inputs_outputs_value.js | 29 ++- .../integration-test/check_nullifier_value.js | 63 +++++-- zkp/js/integration-test/check_nullifiers.js | 31 +++- zkp/js/integration-test/nf_anon.js | 27 ++- zkp/js/integration-test/nf_anon_nullifier.js | 43 ++++- zkp/js/integration-test/utils.js | 10 +- zkp/js/lib/util.js | 28 ++- zkp/js/package.json | 4 + zkp/js/test/anon.js | 58 ++++-- zkp/js/test/anon_enc.js | 14 +- zkp/js/test/anon_enc_nullifier.js | 22 +-- zkp/js/test/anon_enc_nullifier_kyc.js | 24 +-- .../anon_enc_nullifier_non_repudiation.js | 32 ++-- zkp/js/test/anon_nullifier.js | 153 +++++++++++++--- zkp/js/test/anon_nullifier_kyc.js | 143 ++++++++++++--- zkp/js/test/check_hashes_value.js | 50 ++++-- zkp/js/test/check_inputs_outputs_value.js | 38 +++- zkp/js/test/check_nullifier_value.js | 88 +++++++-- zkp/js/test/check_nullifiers.js | 56 ++++-- zkp/js/test/lib/check-hashes-tokenid-uri.js | 26 ++- zkp/js/test/lib/check-hashes.js | 24 ++- .../test/lib/check-nullifier-tokenid-uri.js | 33 +++- zkp/js/test/lib/check-nullifiers.js | 26 ++- zkp/js/test/lib/check-positive.js | 17 +- zkp/js/test/lib/check-smt-proof.js | 20 ++- zkp/js/test/lib/check-sum.js | 8 +- zkp/js/test/lib/ecdh.js | 7 +- zkp/js/test/lib/encrypt.js | 25 ++- zkp/js/test/lib/poseidon-ex.js | 4 +- zkp/js/test/nf_anon.js | 70 ++++++-- zkp/js/test/nf_anon_nullifier.js | 167 ++++++++++++++---- 57 files changed, 1978 insertions(+), 879 deletions(-) create mode 100644 solidity/.prettierrc create mode 100644 zkp/js/.prettierrc diff --git a/solidity/.prettierrc b/solidity/.prettierrc new file mode 100644 index 0000000..544138b --- /dev/null +++ b/solidity/.prettierrc @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} diff --git a/solidity/package.json b/solidity/package.json index 50ee394..f80d20f 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -3,7 +3,10 @@ "version": "0.0.1", "description": "Zero knowledge proof based UTXO tokens toolkit for fungible or non-fungible assets", "main": "index.js", - "scripts": { + "scripts": { + "prettier": "npx prettier test --check", + "prettier:fix": "npm run prettier -- --write", + "pretest": "npm run prettier:fix", "test": "npx hardhat test" }, "keywords": [], @@ -17,6 +20,7 @@ "circomlibjs": "^0.1.7", "hardhat": "^2.22.2", "maci-crypto": "1.1.1", + "prettier": "^3.3.3", "snarkjs": "^0.7.3", "zeto-js": "file:../zkp/js" }, diff --git a/solidity/test/factory.ts b/solidity/test/factory.ts index b538712..037573a 100644 --- a/solidity/test/factory.ts +++ b/solidity/test/factory.ts @@ -43,7 +43,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi withdrawVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', }; await expect( - factory.connect(nonOwner).registerImplementation('test', implInfo as any) + factory.connect(nonOwner).registerImplementation('test', implInfo as any), ).rejectedWith(`reverted with custom error 'OwnableUnauthorizedAccount(`); }); @@ -62,7 +62,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi withdrawVerifier: '0x0000000000000000000000000000000000000000', }; await expect( - factory.connect(deployer).registerImplementation('test', implInfo as any) + factory.connect(deployer).registerImplementation('test', implInfo as any), ).rejectedWith('Factory: implementation address is required'); }); @@ -81,7 +81,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi withdrawVerifier: '0x0000000000000000000000000000000000000000', }; await expect( - factory.connect(deployer).registerImplementation('test', implInfo as any) + factory.connect(deployer).registerImplementation('test', implInfo as any), ).rejectedWith('Factory: verifier address is required'); }); @@ -100,7 +100,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi withdrawVerifier: '0x0000000000000000000000000000000000000000', }; await expect( - factory.connect(deployer).registerImplementation('test', implInfo as any) + factory.connect(deployer).registerImplementation('test', implInfo as any), ).fulfilled; }); @@ -126,7 +126,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi await expect( factory .connect(deployer) - .deployZetoFungibleToken('test', await deployer.getAddress()) + .deployZetoFungibleToken('test', await deployer.getAddress()), ).rejectedWith('Factory: depositVerifier address is required'); }); it('attempting to deploy a fungible token but with a registered implementation that misses required depositVerifier should fail', async function () { @@ -151,7 +151,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi await expect( factory .connect(deployer) - .deployZetoFungibleToken('test', await deployer.getAddress()) + .deployZetoFungibleToken('test', await deployer.getAddress()), ).rejectedWith('Factory: depositVerifier address is required'); }); @@ -177,7 +177,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi await expect( factory .connect(deployer) - .deployZetoFungibleToken('test', await deployer.getAddress()) + .deployZetoFungibleToken('test', await deployer.getAddress()), ).rejectedWith('Factory: withdrawVerifier address is required'); }); @@ -203,7 +203,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi await expect( factory .connect(deployer) - .deployZetoFungibleToken('test', await deployer.getAddress()) + .deployZetoFungibleToken('test', await deployer.getAddress()), ).fulfilled; }); }); diff --git a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts index 9bc82a9..7e15617 100644 --- a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts +++ b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts @@ -119,11 +119,11 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin circuit = await loadCircuit('anon_enc_nullifier_kyc'); ({ provingKeyFile: provingKey } = loadProvingKeys( - 'anon_enc_nullifier_kyc' + 'anon_enc_nullifier_kyc', )); batchCircuit = await loadCircuit('anon_enc_nullifier_kyc_batch'); ({ provingKeyFile: batchProvingKey } = loadProvingKeys( - 'anon_enc_nullifier_kyc_batch' + 'anon_enc_nullifier_kyc_batch', )); }); @@ -149,7 +149,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin const endingBalance = await erc20.balanceOf(Alice.ethAddress); expect(endingBalance - startingBalance).to.be.equal(atMostHalfAmount); console.log( - `ERC20 successfully minted ${atMostHalfAmount} to Alice for deposit` + `ERC20 successfully minted ${atMostHalfAmount} to Alice for deposit`, ); const tx1 = await erc20 .connect(Alice.signer) @@ -163,7 +163,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin await txDep.wait(); const endingBalanceDep = await erc20.balanceOf(zeto.target); expect(endingBalanceDep - startingBalanceDep).to.be.equal( - atLeastHalfAmount + atLeastHalfAmount, ); }); @@ -181,12 +181,12 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin 1, outputCommitments[0], encodedProof, - depositGasCostHistory + depositGasCostHistory, ); await smtAlice.add(utxoSingle.hash, utxoSingle.hash); await smtBob.add(utxoSingle.hash, utxoSingle.hash); unspentAliceUTXOs.push(utxoSingle); - })() + })(), ); // If we reach the concurrency limit, wait for the current batch to finish @@ -202,7 +202,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin } writeGasCostsToCSV( `${reportPrefix}deposit_gas_costs.csv`, - depositGasCostHistory + depositGasCostHistory, ); }).timeout(6000000000000); @@ -227,7 +227,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin } await doMint(zeto, deployer, mintUTXOs, mintGasCostHistory); - })() + })(), ); // If we reach the concurrency limit, wait for the current batch to finish @@ -242,7 +242,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin } writeGasCostsToCSV( `${reportPrefix}mint_gas_costs.csv`, - mintGasCostHistory + mintGasCostHistory, ); }).timeout(6000000000000); @@ -253,11 +253,11 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identityMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) @@ -288,7 +288,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin // Alice generates inclusion proofs for the UTXOs to be spent const inProof = await smtAlice.generateCircomVerifierProof( _iUtxo.hash, - utxosRoot + utxosRoot, ); _mtps.push(inProof.siblings.map((s) => s.bigInt())); const _oUtox = newUTXO(1, Bob); @@ -320,9 +320,9 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin identitiesRoot.bigInt(), identityMerkleProofs, owners, - transferGasCostHistory + transferGasCostHistory, ); - })() + })(), ); // If we reach the concurrency limit, wait for the current batch to finish @@ -344,7 +344,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin } writeGasCostsToCSV( `${reportPrefix}transfer_gas_costs.csv`, - transferGasCostHistory + transferGasCostHistory, ); }).timeout(6000000000000); @@ -362,7 +362,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin const proof1 = await smtBob.generateCircomVerifierProof( utxoToWithdraw.hash, - root + root, ); const proof2 = await smtBob.generateCircomVerifierProof(0n, root); const merkleProofs = [ @@ -376,7 +376,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin [nullifier1, ZERO_UTXO], newUTXO(0, Bob), root.bigInt(), - merkleProofs + merkleProofs, ); // Bob withdraws UTXOs to ERC20 tokens @@ -388,9 +388,9 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin outputCommitments[0], root.bigInt(), encodedProof, - withdrawGasCostHistory + withdrawGasCostHistory, ); - })() + })(), ); } // If we reach the concurrency limit, wait for the current batch to finish @@ -405,7 +405,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin } writeGasCostsToCSV( `${reportPrefix}withdraw_gas_costs.csv`, - withdrawGasCostHistory + withdrawGasCostHistory, ); // Bob checks ERC20 balance const endingBalance = await erc20.balanceOf(Bob.ethAddress); @@ -423,7 +423,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin identitiesRoot: BigInt, identitiesMerkleProof: BigInt[][], owners: User[], - gasHistories: number[] + gasHistories: number[], ) { let nullifiers: BigNumberish[]; let outputCommitments: BigNumberish[]; @@ -441,12 +441,12 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin identitiesRoot, identitiesMerkleProof, owners, - ephemeralKeypair.privKey + ephemeralKeypair.privKey, ); nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, - BigNumberish + BigNumberish, ]; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; @@ -461,7 +461,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin encryptedValues, encryptionNonce, encodedProof, - ephemeralKeypair.pubKey + ephemeralKeypair.pubKey, ); if (txResult?.gasUsed && Array.isArray(gasHistories)) { gasHistories.push(txResult?.gasUsed); @@ -487,23 +487,23 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin identitiesRoot: BigInt, identitiesMerkleProof: BigInt[][], owners: User[], - ephemeralPrivateKey: BigInt + ephemeralPrivateKey: BigInt, ) { const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, - BigNumberish + BigNumberish, ]; const inputCommitments: BigNumberish[] = inputs.map( - (input) => input.hash + (input) => input.hash, ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); const outputCommitments: BigNumberish[] = outputs.map( - (output) => output.hash + (output) => output.hash, ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); const outputOwnerPublicKeys: BigNumberish[][] = owners.map( - (owner) => owner.babyJubPublicKey + (owner) => owner.babyJubPublicKey, ) as BigNumberish[][]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ @@ -546,12 +546,12 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKeyToUse, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`, ); const encodedProof = encodeProof(proof); @@ -575,7 +575,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, encodedProof: any, - ecdhPublicKey: BigInt[] + ecdhPublicKey: BigInt[], ) { const startTx = Date.now(); const tx = await zeto @@ -588,13 +588,13 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ecdhPublicKey, encryptedValues, encodedProof, - '0x' + '0x', ); const result: ContractTransactionReceipt | null = await tx.wait(); console.log( `Transfer transaction took: ${Date.now() - startTx}ms. Gas used: ${ result?.gasUsed - }` + }`, ); return result; } diff --git a/solidity/test/lib/deploy.ts b/solidity/test/lib/deploy.ts index e893726..a84821d 100644 --- a/solidity/test/lib/deploy.ts +++ b/solidity/test/lib/deploy.ts @@ -21,7 +21,7 @@ export async function deployZeto(tokenName: string) { zeto = await ethers.getContractAt(tokenName, process.env.ZETO_ADDRESS); erc20 = await ethers.getContractAt( 'SampleERC20', - process.env.ERC20_ADDRESS + process.env.ERC20_ADDRESS, ); deployer = (await ethers.getSigners())[0]; return { deployer, zeto, erc20 }; diff --git a/solidity/test/lib/utils.ts b/solidity/test/lib/utils.ts index 5218e8b..5b918c3 100644 --- a/solidity/test/lib/utils.ts +++ b/solidity/test/lib/utils.ts @@ -14,9 +14,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ContractTransactionReceipt, Signer, BigNumberish, AddressLike } from 'ethers'; -import { genKeypair, formatPrivKeyForBabyJub, genEcdhSharedKey } from 'maci-crypto'; -import { Poseidon, newSalt, tokenUriHash } from "zeto-js"; +import { + ContractTransactionReceipt, + Signer, + BigNumberish, + AddressLike, +} from 'ethers'; +import { + genKeypair, + formatPrivKeyForBabyJub, + genEcdhSharedKey, +} from 'maci-crypto'; +import { Poseidon, newSalt, tokenUriHash } from 'zeto-js'; const poseidonHash3 = Poseidon.poseidon3; const poseidonHash4 = Poseidon.poseidon4; @@ -55,60 +64,115 @@ export async function newUser(signer: Signer) { export function newUTXO(value: number, owner: User, salt?: BigInt): UTXO { if (!salt) salt = newSalt(); - const hash = poseidonHash4([BigInt(value), salt, owner.babyJubPublicKey[0], owner.babyJubPublicKey[1]]); + const hash = poseidonHash4([ + BigInt(value), + salt, + owner.babyJubPublicKey[0], + owner.babyJubPublicKey[1], + ]); return { value, hash, salt }; } -export function newAssetUTXO(tokenId: number, uri: string, owner: User, salt?: BigInt): UTXO { +export function newAssetUTXO( + tokenId: number, + uri: string, + owner: User, + salt?: BigInt, +): UTXO { if (!salt) salt = newSalt(); - const hash = poseidonHash5([BigInt(tokenId), tokenUriHash(uri), salt, owner.babyJubPublicKey[0], owner.babyJubPublicKey[1]]); + const hash = poseidonHash5([ + BigInt(tokenId), + tokenUriHash(uri), + salt, + owner.babyJubPublicKey[0], + owner.babyJubPublicKey[1], + ]); return { tokenId, uri, hash, salt }; } export function newNullifier(utxo: UTXO, owner: User): UTXO { - const hash = poseidonHash3([BigInt(utxo.value!), utxo.salt, owner.formattedPrivateKey]); + const hash = poseidonHash3([ + BigInt(utxo.value!), + utxo.salt, + owner.formattedPrivateKey, + ]); return { value: utxo.value, hash, salt: utxo.salt }; } export function newAssetNullifier(utxo: UTXO, owner: User): UTXO { - const hash = poseidonHash4([BigInt(utxo.tokenId!), tokenUriHash(utxo.uri), utxo.salt, owner.formattedPrivateKey]); + const hash = poseidonHash4([ + BigInt(utxo.tokenId!), + tokenUriHash(utxo.uri), + utxo.salt, + owner.formattedPrivateKey, + ]); return { tokenId: utxo.tokenId, uri: utxo.uri, hash, salt: utxo.salt }; } -export async function doMint(zetoTokenContract: any, minter: Signer, outputs: UTXO[], gasHistories?:number[]): Promise { - const outputCommitments = outputs.map((output) => output.hash) as BigNumberish[]; +export async function doMint( + zetoTokenContract: any, + minter: Signer, + outputs: UTXO[], + gasHistories?: number[], +): Promise { + const outputCommitments = outputs.map( + (output) => output.hash, + ) as BigNumberish[]; const tx = await zetoTokenContract .connect(minter) - .mint(outputCommitments, "0x"); + .mint(outputCommitments, '0x'); const result = await tx.wait(); console.log(`Method mint() complete. Gas used: ${result?.gasUsed}`); if (result?.gasUsed && Array.isArray(gasHistories)) { - gasHistories.push(result?.gasUsed) + gasHistories.push(result?.gasUsed); } return result; } -export async function doDeposit(zetoTokenContract: any, depositUser: Signer, amount:any, commitment: any, proof: any, gasHistories?:number[]): Promise { - const tx = await zetoTokenContract.connect(depositUser).deposit(amount, commitment, proof, "0x"); +export async function doDeposit( + zetoTokenContract: any, + depositUser: Signer, + amount: any, + commitment: any, + proof: any, + gasHistories?: number[], +): Promise { + const tx = await zetoTokenContract + .connect(depositUser) + .deposit(amount, commitment, proof, '0x'); const result = await tx.wait(); console.log(`Method deposit() complete. Gas used: ${result?.gasUsed}`); if (result?.gasUsed && Array.isArray(gasHistories)) { - gasHistories.push(result?.gasUsed) + gasHistories.push(result?.gasUsed); } return result; } -export async function doWithdraw(zetoTokenContract: any, withdrawUser: Signer, amount:any, nullifiers:any, commitment: any, root:any, proof: any, gasHistories?:number[]): Promise { - const tx = await zetoTokenContract.connect(withdrawUser).withdraw(amount, nullifiers, commitment, root, proof); +export async function doWithdraw( + zetoTokenContract: any, + withdrawUser: Signer, + amount: any, + nullifiers: any, + commitment: any, + root: any, + proof: any, + gasHistories?: number[], +): Promise { + const tx = await zetoTokenContract + .connect(withdrawUser) + .withdraw(amount, nullifiers, commitment, root, proof); const result = await tx.wait(); console.log(`Method withdraw() complete. Gas used: ${result?.gasUsed}`); if (result?.gasUsed && Array.isArray(gasHistories)) { - gasHistories.push(result?.gasUsed) + gasHistories.push(result?.gasUsed); } return result; } -export function parseUTXOEvents(zetoTokenContract: any, result: ContractTransactionReceipt) { +export function parseUTXOEvents( + zetoTokenContract: any, + result: ContractTransactionReceipt, +) { let returnValues: any[] = []; for (const log of result.logs || []) { const event = zetoTokenContract.interface.parseLog(log as any); @@ -116,7 +180,7 @@ export function parseUTXOEvents(zetoTokenContract: any, result: ContractTransact const transfer = { inputs: event?.args.inputs, outputs: event?.args.outputs, - submitter: event?.args.submitter + submitter: event?.args.submitter, }; returnValues.push(transfer); } else if (event?.name === 'UTXOTransferWithEncryptedValues') { @@ -126,7 +190,7 @@ export function parseUTXOEvents(zetoTokenContract: any, result: ContractTransact encryptedValues: event?.args.encryptedValues, encryptionNonce: event?.args.encryptionNonce, submitter: event?.args.submitter, - ecdhPublicKey: event?.args.ecdhPublicKey + ecdhPublicKey: event?.args.ecdhPublicKey, }; returnValues.push(transfer); } else if (event?.name === 'UTXOTransferNonRepudiation') { @@ -137,14 +201,14 @@ export function parseUTXOEvents(zetoTokenContract: any, result: ContractTransact encryptedValuesForAuthority: event?.args.encryptedValuesForAuthority, encryptionNonce: event?.args.encryptionNonce, submitter: event?.args.submitter, - ecdhPublicKey: event?.args.ecdhPublicKey + ecdhPublicKey: event?.args.ecdhPublicKey, }; returnValues.push(transfer); } else if (event?.name === 'UTXOMint') { const mint = { outputs: event?.args.outputs, receivers: event?.args.receivers, - submitter: event?.args.submitter + submitter: event?.args.submitter, }; returnValues.push(mint); } else if (event?.name === 'TradeCompleted') { @@ -158,7 +222,10 @@ export function parseUTXOEvents(zetoTokenContract: any, result: ContractTransact return returnValues; } -export function parseRegistryEvents(registryContract: any, result: ContractTransactionReceipt) { +export function parseRegistryEvents( + registryContract: any, + result: ContractTransactionReceipt, +) { for (const log of result.logs || []) { const event = registryContract.interface.parseLog(log as any); if (event?.name === 'IdentityRegistered') { @@ -166,4 +233,4 @@ export function parseRegistryEvents(registryContract: any, result: ContractTrans } } return null; -} \ No newline at end of file +} diff --git a/solidity/test/utils.ts b/solidity/test/utils.ts index b932135..d1c715b 100644 --- a/solidity/test/utils.ts +++ b/solidity/test/utils.ts @@ -33,8 +33,8 @@ export function loadProvingKeys(type: string) { const provingKeyFile = path.join(provingKeysRoot(), `${type}.zkey`); const verificationKey = JSON.parse( new TextDecoder().decode( - readFileSync(path.join(provingKeysRoot(), `${type}-vkey.json`)) - ) + readFileSync(path.join(provingKeysRoot(), `${type}-vkey.json`)), + ), ); return { provingKeyFile, @@ -66,12 +66,12 @@ export async function prepareDepositProof(signer: User, output: UTXO) { const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKeyFile, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`, ); const encodedProof = encodeProof(proof); @@ -87,14 +87,14 @@ export async function prepareNullifierWithdrawProof( _nullifiers: UTXO[], output: UTXO, root: BigInt, - merkleProof: BigInt[][] + merkleProof: BigInt[][], ) { const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, - BigNumberish + BigNumberish, ]; const inputCommitments: BigNumberish[] = inputs.map( - (input) => input.hash + (input) => input.hash, ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); @@ -128,12 +128,12 @@ export async function prepareNullifierWithdrawProof( const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKeyFile, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`, ); const encodedProof = encodeProof(proof); @@ -147,10 +147,10 @@ export async function prepareNullifierWithdrawProof( export async function prepareWithdrawProof( signer: User, inputs: UTXO[], - output: UTXO + output: UTXO, ) { const inputCommitments: BigNumberish[] = inputs.map( - (input) => input.hash + (input) => input.hash, ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); @@ -180,12 +180,12 @@ export async function prepareWithdrawProof( const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKeyFile, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`, ); const encodedProof = encodeProof(proof); diff --git a/solidity/test/zeto_anon.ts b/solidity/test/zeto_anon.ts index 2a748ac..fd3a52d 100644 --- a/solidity/test/zeto_anon.ts +++ b/solidity/test/zeto_anon.ts @@ -103,7 +103,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi Alice, inputUtxos, inflatedOutputUtxos, - inflatedOutputOwners + inflatedOutputOwners, ); const events = parseUTXOEvents(zeto, result); @@ -141,7 +141,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi utxo100 = newUTXO(100, Alice); const { outputCommitments, encodedProof } = await prepareDepositProof( Alice, - utxo100 + utxo100, ); const tx2 = await zeto .connect(Alice.signer) @@ -169,7 +169,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi Alice, [utxo1, utxo2], [_txo3, utxo4], - [Bob, Alice] + [Bob, Alice], ); // check the private transfer activity is not exposed in the ERC20 contract @@ -254,25 +254,25 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi await prepareWithdrawProof( Alice, [utxo100, ZERO_UTXO], - outputCommitment + outputCommitment, ); await expect( zeto .connect(Alice.signer) - .withdraw(10, inputCommitments, outputCommitments[0], encodedProof) + .withdraw(10, inputCommitments, outputCommitments[0], encodedProof), ).rejectedWith('UTXOAlreadySpent'); }); it('mint existing unspent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); it('mint existing spent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadySpent' + 'UTXOAlreadySpent', ); }); @@ -284,8 +284,8 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi Alice, [nonExisting1, nonExisting2], [nonExisting1, nonExisting2], - [Alice, Alice] - ) + [Alice, Alice], + ), ).rejectedWith('UTXONotMinted'); }); @@ -294,7 +294,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi const utxo5 = newUTXO(25, Bob); const utxo6 = newUTXO(5, Alice, utxo5.salt); await expect( - doTransfer(Alice, [utxo1, utxo2], [utxo5, utxo6], [Bob, Alice]) + doTransfer(Alice, [utxo1, utxo2], [utxo5, utxo6], [Bob, Alice]), ).rejectedWith('UTXOAlreadySpent'); }); @@ -302,7 +302,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi const utxo5 = newUTXO(20, Alice); const utxo6 = newUTXO(10, Bob, utxo5.salt); await expect( - doTransfer(Bob, [utxo7, utxo7], [utxo5, utxo6], [Alice, Bob]) + doTransfer(Bob, [utxo7, utxo7], [utxo5, utxo6], [Alice, Bob]), ).rejectedWith(`UTXODuplicate(${utxo7.hash.toString()}`); }); }); @@ -311,7 +311,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi signer: User, inputs: UTXO[], outputs: UTXO[], - owners: User[] + owners: User[], ) { let inputCommitments: BigNumberish[]; let outputCommitments: BigNumberish[]; @@ -329,12 +329,12 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi signer, inputs, outputs, - owners + owners, ); inputCommitments = result.inputCommitments; outputCommitments = result.outputCommitments; outputOwnerAddresses = owners.map( - (owner) => owner.ethAddress || ZeroAddress + (owner) => owner.ethAddress || ZeroAddress, ) as [AddressLike, AddressLike]; encodedProof = result.encodedProof; @@ -343,7 +343,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi inputCommitments, outputCommitments, outputOwnerAddresses, - encodedProof + encodedProof, ); } @@ -352,14 +352,14 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi inputCommitments: BigNumberish[], outputCommitments: BigNumberish[], outputOwnerAddresses: AddressLike[], - encodedProof: any + encodedProof: any, ) { const signerAddress = await signer.signer.getAddress(); const tx = await zeto.connect(signer.signer).transfer( inputCommitments.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works encodedProof, - '0x' + '0x', ); const results = await tx.wait(); console.log(`Method transfer() complete. Gas used: ${results?.gasUsed}`); @@ -382,20 +382,20 @@ async function prepareProof( signer: User, inputs: UTXO[], outputs: UTXO[], - owners: User[] + owners: User[], ) { const inputCommitments: BigNumberish[] = inputs.map( - (input) => input.hash + (input) => input.hash, ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); const outputCommitments: BigNumberish[] = outputs.map( - (output) => output.hash + (output) => output.hash, ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); const outputSalts = outputs.map((o) => o.salt || 0n); const outputOwnerPublicKeys: BigNumberish[][] = owners.map( - (owner) => owner.babyJubPublicKey || ZERO_PUBKEY + (owner) => owner.babyJubPublicKey || ZERO_PUBKEY, ) as BigNumberish[][]; const otherInputs = stringifyBigInts({ inputOwnerPrivateKey: formatPrivKeyForBabyJub(signer.babyJubPrivateKey), @@ -413,18 +413,18 @@ async function prepareProof( outputOwnerPublicKeys, ...otherInputs, }, - true + true, ); const timeWitnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKey, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms` + `Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms`, ); const encodedProof = encodeProof(proof); return { diff --git a/solidity/test/zeto_anon_enc.ts b/solidity/test/zeto_anon_enc.ts index 17cf971..e813f71 100644 --- a/solidity/test/zeto_anon_enc.ts +++ b/solidity/test/zeto_anon_enc.ts @@ -110,7 +110,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () Alice, inputUtxos, inflatedOutputUtxos, - inflatedOutputOwners + inflatedOutputOwners, ); const events = parseUTXOEvents(zeto, result.txResult!); @@ -124,7 +124,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () events[0].encryptedValues, sharedKey, events[0].encryptionNonce, - 20 + 20, ); expect(plainText).to.deep.equal(result.expectedPlainText); @@ -161,7 +161,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () utxo100 = newUTXO(100, Alice); const { outputCommitments, encodedProof } = await prepareDepositProof( Alice, - utxo100 + utxo100, ); const tx2 = await zeto .connect(Alice.signer) @@ -189,7 +189,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () Alice, [utxo1, utxo2], [_utxo1, utxo4], - [Bob, Alice] + [Bob, Alice], ); // check the private transfer activity is not exposed in the ERC20 contract @@ -211,7 +211,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () events[0].encryptedValues, sharedKey, events[0].encryptionNonce, - 4 + 4, ); expect(plainText).to.deep.equal(result.expectedPlainText); // Bob verifies that the UTXO constructed from the decrypted values matches the UTXO from the event @@ -235,7 +235,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () Bob, [utxo3, ZERO_UTXO], [_utxo1, ZERO_UTXO], - [Charlie, Bob] + [Charlie, Bob], ); }); @@ -274,25 +274,25 @@ describe('Zeto based fungible token with anonymity and encryption', function () await prepareWithdrawProof( Alice, [utxo100, ZERO_UTXO], - outputCommitment + outputCommitment, ); await expect( zeto .connect(Alice.signer) - .withdraw(10, inputCommitments, outputCommitments[0], encodedProof) + .withdraw(10, inputCommitments, outputCommitments[0], encodedProof), ).rejectedWith('UTXOAlreadySpent'); }); it('mint existing unspent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); it('mint existing spent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadySpent' + 'UTXOAlreadySpent', ); }); @@ -304,8 +304,8 @@ describe('Zeto based fungible token with anonymity and encryption', function () Alice, [nonExisting1, nonExisting2], [nonExisting1, nonExisting2], - [Alice, Alice] - ) + [Alice, Alice], + ), ).rejectedWith('UTXONotMinted'); }); @@ -314,7 +314,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () const _utxo1 = newUTXO(25, Bob); const _utxo2 = newUTXO(5, Alice); await expect( - doTransfer(Alice, [utxo1, utxo2], [_utxo1, _utxo2], [Bob, Alice]) + doTransfer(Alice, [utxo1, utxo2], [_utxo1, _utxo2], [Bob, Alice]), ).rejectedWith('UTXOAlreadySpent'); }); @@ -326,7 +326,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () const _utxo2 = newUTXO(25, Alice); const _utxo3 = newUTXO(15, Bob); await expect( - doTransfer(Bob, [_utxo1, _utxo1], [_utxo2, _utxo3], [Alice, Bob]) + doTransfer(Bob, [_utxo1, _utxo1], [_utxo2, _utxo3], [Alice, Bob]), ).rejectedWith(`UTXODuplicate(${_utxo1.hash.toString()}`); }); }); @@ -335,7 +335,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () signer: User, inputs: UTXO[], outputs: UTXO[], - owners: User[] + owners: User[], ) { let inputCommitments: BigNumberish[]; let outputCommitments: BigNumberish[]; @@ -348,7 +348,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () inputs, outputs, owners, - ephemeralKeypair.privKey + ephemeralKeypair.privKey, ); inputCommitments = result.inputCommitments; outputCommitments = result.outputCommitments; @@ -363,7 +363,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () encryptedValues, encryptionNonce, encodedProof, - ephemeralKeypair.pubKey + ephemeralKeypair.pubKey, ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { @@ -381,19 +381,19 @@ describe('Zeto based fungible token with anonymity and encryption', function () inputs: UTXO[], outputs: UTXO[], owners: User[], - ephemeralPrivateKey: BigInt + ephemeralPrivateKey: BigInt, ) { const inputCommitments: BigNumberish[] = inputs.map( - (input) => input.hash + (input) => input.hash, ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); const outputCommitments: BigNumberish[] = outputs.map( - (output) => output.hash + (output) => output.hash, ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); const outputOwnerPublicKeys: BigNumberish[][] = owners.map( - (owner) => owner.babyJubPublicKey + (owner) => owner.babyJubPublicKey, ) as BigNumberish[][]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ @@ -422,18 +422,18 @@ describe('Zeto based fungible token with anonymity and encryption', function () outputOwnerPublicKeys, ...encryptInputs, }, - true + true, ); const timeWitnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKeyToUse, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms` + `Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms`, ); const encodedProof = encodeProof(proof); @@ -456,7 +456,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, encodedProof: any, - ecdhPublicKey: BigInt[] + ecdhPublicKey: BigInt[], ) { const tx = await zeto.connect(signer.signer).transfer( inputCommitments.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works @@ -465,7 +465,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () ecdhPublicKey, encryptedValues, encodedProof, - '0x' + '0x', ); const results: ContractTransactionReceipt | null = await tx.wait(); diff --git a/solidity/test/zeto_anon_enc_nullifier.ts b/solidity/test/zeto_anon_enc_nullifier.ts index 338973e..99a2977 100644 --- a/solidity/test/zeto_anon_enc_nullifier.ts +++ b/solidity/test/zeto_anon_enc_nullifier.ts @@ -91,7 +91,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ({ provingKeyFile: provingKey } = loadProvingKeys('anon_enc_nullifier')); batchCircuit = await loadCircuit('anon_enc_nullifier_batch'); ({ provingKeyFile: batchProvingKey } = loadProvingKeys( - 'anon_enc_nullifier_batch' + 'anon_enc_nullifier_batch', )); }); @@ -128,7 +128,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti for (let i = 0; i < inputUtxos.length; i++) { const p = await smtAlice.generateCircomVerifierProof( inputUtxos[i].hash, - root + root, ); mtps.push(p.siblings.map((s) => s.bigInt())); } @@ -153,7 +153,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti inflatedOutputUtxos, root.bigInt(), mtps, - inflatedOutputOwners + inflatedOutputOwners, ); const signerAddress = await Alice.signer.getAddress(); @@ -171,7 +171,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti events[0].encryptedValues, sharedKey, events[0].encryptionNonce, - 20 + 20, ); expect(plainText).to.deep.equal(result.expectedPlainText); @@ -210,7 +210,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti utxo100 = newUTXO(100, Alice); const { outputCommitments, encodedProof } = await prepareDepositProof( Alice, - utxo100 + utxo100, ); const tx2 = await zeto .connect(Alice.signer) @@ -269,7 +269,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [_utxo3, utxo4], root.bigInt(), merkleProofs, - [Bob, Alice] + [Bob, Alice], ); // check the private transfer activity is not exposed in the ERC20 contract @@ -301,7 +301,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti events[0].encryptedValues, sharedKey, events[0].encryptionNonce, - 4 + 4, ); expect(plainText).to.deep.equal(result2.expectedPlainText); @@ -334,7 +334,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [utxo6, utxo7], root.bigInt(), merkleProofs, - [Charlie, Bob] + [Charlie, Bob], ); // Bob keeps the local SMT in sync @@ -357,7 +357,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo100.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); const merkleProofs = [ @@ -375,7 +375,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [nullifier1, ZERO_UTXO], withdrawChangeUTXO, root.bigInt(), - merkleProofs + merkleProofs, ); // Alice withdraws her UTXOs to ERC20 tokens @@ -386,7 +386,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti nullifiers, outputCommitments[0], root.bigInt(), - encodedProof + encodedProof, ); await tx.wait(); @@ -416,7 +416,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo100.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); const merkleProofs = [ @@ -434,7 +434,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [nullifier1, ZERO_UTXO], outputCommitment, root.bigInt(), - merkleProofs + merkleProofs, ); // Alice withdraws her UTXOs to ERC20 tokens @@ -446,20 +446,20 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti nullifiers, outputCommitments[0], root.bigInt(), - encodedProof - ) + encodedProof, + ), ).rejectedWith('UTXOAlreadySpent'); }); it('mint existing unspent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); it('mint existing spent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); @@ -476,11 +476,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo1.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof( utxo2.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -495,8 +495,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [_utxo1, _utxo2], root.bigInt(), merkleProofs, - [Bob, Alice] - ) + [Bob, Alice], + ), ).rejectedWith('UTXOAlreadySpent'); }).timeout(600000); @@ -512,7 +512,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); const proof2 = await smtBob.generateCircomVerifierProof( _utxo1.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -527,8 +527,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [utxo1, utxo2], root.bigInt(), merkleProofs, - [Alice, Alice] - ) + [Alice, Alice], + ), ).rejectedWith('UTXOAlreadyOwned'); }).timeout(600000); @@ -554,8 +554,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [_utxo1, _utxo2], root.bigInt(), merkleProofs, - [Alice, Bob] - ) + [Alice, Bob], + ), ).rejectedWith(`UTXODuplicate`); }).timeout(600000); @@ -575,11 +575,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( nonExisting1.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof( nonExisting2.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -598,8 +598,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [utxo7, _utxo1], root.bigInt(), merkleProofs, - [Bob, Charlie] - ) + [Bob, Charlie], + ), ).rejectedWith('UTXORootNotFound'); }).timeout(600000); @@ -618,7 +618,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti outputs: UTXO[], root: BigInt, merkleProofs: BigInt[][], - owners: User[] + owners: User[], ) { let nullifiers: BigNumberish[]; let outputCommitments: BigNumberish[]; @@ -634,11 +634,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti root, merkleProofs, owners, - ephemeralKeypair.privKey + ephemeralKeypair.privKey, ); nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, - BigNumberish + BigNumberish, ]; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; @@ -653,7 +653,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti encryptedValues, encryptionNonce, encodedProof, - ephemeralKeypair.pubKey + ephemeralKeypair.pubKey, ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { @@ -674,23 +674,23 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti root: BigInt, merkleProof: BigInt[][], owners: User[], - ephemeralPrivateKey: BigInt + ephemeralPrivateKey: BigInt, ) { const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, - BigNumberish + BigNumberish, ]; const inputCommitments: BigNumberish[] = inputs.map( - (input) => input.hash + (input) => input.hash, ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); const outputCommitments: BigNumberish[] = outputs.map( - (output) => output.hash + (output) => output.hash, ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); const outputOwnerPublicKeys: BigNumberish[][] = owners.map( - (owner) => owner.babyJubPublicKey + (owner) => owner.babyJubPublicKey, ) as BigNumberish[][]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ @@ -727,12 +727,12 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKeyToUse, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`, ); const encodedProof = encodeProof(proof); @@ -756,7 +756,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, encodedProof: any, - ecdhPublicKey: BigInt[] + ecdhPublicKey: BigInt[], ) { const startTx = Date.now(); const tx = await zeto.connect(signer.signer).transfer( @@ -767,13 +767,13 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ecdhPublicKey, encryptedValues, encodedProof, - '0x' + '0x', ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ results?.gasUsed - }` + }`, ); return results; } diff --git a/solidity/test/zeto_anon_enc_nullifier_kyc.ts b/solidity/test/zeto_anon_enc_nullifier_kyc.ts index 8bc552f..dcc8832 100644 --- a/solidity/test/zeto_anon_enc_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_enc_nullifier_kyc.ts @@ -118,11 +118,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti circuit = await loadCircuit('anon_enc_nullifier_kyc'); ({ provingKeyFile: provingKey } = loadProvingKeys( - 'anon_enc_nullifier_kyc' + 'anon_enc_nullifier_kyc', )); batchCircuit = await loadCircuit('anon_enc_nullifier_kyc_batch'); ({ provingKeyFile: batchProvingKey } = loadProvingKeys( - 'anon_enc_nullifier_kyc_batch' + 'anon_enc_nullifier_kyc_batch', )); }); @@ -160,7 +160,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti for (let i = 0; i < inputUtxos.length; i++) { const p = await smtAlice.generateCircomVerifierProof( inputUtxos[i].hash, - root + root, ); mtps.push(p.siblings.map((s) => s.bigInt())); } @@ -169,12 +169,12 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const identitiesRoot = await smtKyc.root(); const aProof = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const aliceProof = aProof.siblings.map((s) => s.bigInt()); const bProof = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const bobProof = bProof.siblings.map((s) => s.bigInt()); @@ -202,7 +202,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti mtps, identitiesRoot.bigInt(), identityMerkleProofs, - inflatedOutputOwners + inflatedOutputOwners, ); const signerAddress = await Alice.signer.getAddress(); @@ -220,7 +220,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti events[0].encryptedValues, sharedKey, events[0].encryptionNonce, - 20 + 20, ); expect(plainText).to.deep.equal(result.expectedPlainText); @@ -260,7 +260,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti utxo100 = newUTXO(100, Alice); const { outputCommitments, encodedProof } = await prepareDepositProof( Alice, - utxo100 + utxo100, ); const tx2 = await zeto .connect(Alice.signer) @@ -306,11 +306,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti // Alice generates inclusion proofs for the UTXOs to be spent const proof1 = await smtAlice.generateCircomVerifierProof( utxo1.hash, - utxosRoot + utxosRoot, ); const proof2 = await smtAlice.generateCircomVerifierProof( utxo2.hash, - utxosRoot + utxosRoot, ); const utxoMerkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -321,11 +321,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identityMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) @@ -343,7 +343,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti utxoMerkleProofs, identitiesRoot.bigInt(), identityMerkleProofs, - [Bob, Alice] + [Bob, Alice], ); // check the private transfer activity is not exposed in the ERC20 contract @@ -374,7 +374,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti events[0].encryptedValues, sharedKey, events[0].encryptionNonce, - 4 + 4, ); expect(plainText).to.deep.equal(result2.expectedPlainText); @@ -390,7 +390,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const utxosRoot = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof( utxo3.hash, - utxosRoot + utxosRoot, ); const proof2 = await smtBob.generateCircomVerifierProof(0n, utxosRoot); const utxosMerkleProofs = [ @@ -407,11 +407,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Charlie.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Bob) @@ -429,7 +429,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti utxosMerkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, - [Charlie, Bob] + [Charlie, Bob], ); // Bob keeps the local SMT in sync @@ -452,7 +452,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo100.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); const merkleProofs = [ @@ -470,7 +470,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [nullifier1, ZERO_UTXO], withdrawChangeUTXO, root.bigInt(), - merkleProofs + merkleProofs, ); // Alice withdraws her UTXOs to ERC20 tokens @@ -481,7 +481,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti nullifiers, outputCommitments[0], root.bigInt(), - encodedProof + encodedProof, ); await tx.wait(); @@ -511,7 +511,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti unregisteredUtxo100 = newUTXO(100, unregistered); const { outputCommitments, encodedProof } = await prepareDepositProof( unregistered, - unregisteredUtxo100 + unregisteredUtxo100, ); const tx2 = await zeto .connect(unregistered.signer) @@ -535,11 +535,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti await smtUnregistered.add(utxo7.hash, utxo7.hash); await smtUnregistered.add( withdrawChangeUTXO.hash, - withdrawChangeUTXO.hash + withdrawChangeUTXO.hash, ); await smtUnregistered.add( unregisteredUtxo100.hash, - unregisteredUtxo100.hash + unregisteredUtxo100.hash, ); const utxosRoot = await smtUnregistered.root(); @@ -548,7 +548,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const output2 = newUTXO(0, unregistered); const proof = await smtUnregistered.generateCircomVerifierProof( unregisteredUtxo100.hash, - utxosRoot + utxosRoot, ); const merkleProofs = [ proof.siblings.map((s) => s.bigInt()), @@ -558,16 +558,16 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti // add the unregistered user to the local KYC SMT, but not to the onchain SMT await smtKyc.add( kycHash(unregistered.babyJubPublicKey), - kycHash(unregistered.babyJubPublicKey) + kycHash(unregistered.babyJubPublicKey), ); const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(unregistered.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (unregistered) @@ -584,8 +584,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, - [Bob, unregistered] - ) + [Bob, unregistered], + ), ).rejectedWith('Invalid proof'); }); @@ -598,11 +598,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtUnregistered.root(); const proof1 = await smtUnregistered.generateCircomVerifierProof( unregisteredUtxo100.hash, - root + root, ); const proof2 = await smtUnregistered.generateCircomVerifierProof( 0n, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -619,7 +619,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [nullifier1, ZERO_UTXO], unregisteredWithdrawChangeUTXO, root.bigInt(), - merkleProofs + merkleProofs, ); // unregistered user withdraws her UTXOs to ERC20 tokens @@ -630,19 +630,19 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti nullifiers, outputCommitments[0], root.bigInt(), - encodedProof + encodedProof, ); await tx.wait(); // Alice tracks the UTXO inside the SMT await smtAlice.add( unregisteredWithdrawChangeUTXO.hash, - unregisteredWithdrawChangeUTXO.hash + unregisteredWithdrawChangeUTXO.hash, ); // Bob also locally tracks the UTXOs inside the SMT await smtBob.add( unregisteredWithdrawChangeUTXO.hash, - unregisteredWithdrawChangeUTXO.hash + unregisteredWithdrawChangeUTXO.hash, ); // unregistered user checks her ERC20 balance @@ -667,7 +667,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo100.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); const merkleProofs = [ @@ -685,7 +685,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [nullifier1, ZERO_UTXO], withdrawChangeUTXO, root.bigInt(), - merkleProofs + merkleProofs, ); // Alice withdraws her UTXOs to ERC20 tokens @@ -697,20 +697,20 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti nullifiers, outputCommitments[0], root.bigInt(), - encodedProof - ) + encodedProof, + ), ).rejectedWith('UTXOAlreadySpent'); }); it('mint existing unspent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); it('mint existing spent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); @@ -727,11 +727,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo1.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof( utxo2.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -741,11 +741,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) @@ -763,8 +763,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, - [Bob, Alice] - ) + [Bob, Alice], + ), ).rejectedWith('UTXOAlreadySpent'); }).timeout(600000); @@ -780,7 +780,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); const proof2 = await smtBob.generateCircomVerifierProof( _utxo1.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -790,11 +790,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Bob) @@ -812,8 +812,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, - [Alice, Alice] - ) + [Alice, Alice], + ), ).rejectedWith('UTXOAlreadyOwned'); }).timeout(600000); @@ -834,11 +834,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Bob) @@ -856,8 +856,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, - [Alice, Bob] - ) + [Alice, Bob], + ), ).rejectedWith(`UTXODuplicate`); }).timeout(600000); @@ -877,11 +877,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( nonExisting1.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof( nonExisting2.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -895,15 +895,15 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof5 = await smtKyc.generateCircomVerifierProof( kycHash(Charlie.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) @@ -921,8 +921,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, - [Bob, Charlie] - ) + [Bob, Charlie], + ), ).rejectedWith('UTXORootNotFound'); }).timeout(600000); }); @@ -936,7 +936,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti utxosMerkleProof: BigInt[][], identitiesRoot: BigInt, identitiesMerkleProof: BigInt[][], - owners: User[] + owners: User[], ) { let nullifiers: BigNumberish[]; let outputCommitments: BigNumberish[]; @@ -954,12 +954,12 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti identitiesRoot, identitiesMerkleProof, owners, - ephemeralKeypair.privKey + ephemeralKeypair.privKey, ); nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, - BigNumberish + BigNumberish, ]; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; @@ -974,7 +974,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti encryptedValues, encryptionNonce, encodedProof, - ephemeralKeypair.pubKey + ephemeralKeypair.pubKey, ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { @@ -997,23 +997,23 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti identitiesRoot: BigInt, identitiesMerkleProof: BigInt[][], owners: User[], - ephemeralPrivateKey: BigInt + ephemeralPrivateKey: BigInt, ) { const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, - BigNumberish + BigNumberish, ]; const inputCommitments: BigNumberish[] = inputs.map( - (input) => input.hash + (input) => input.hash, ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); const outputCommitments: BigNumberish[] = outputs.map( - (output) => output.hash + (output) => output.hash, ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); const outputOwnerPublicKeys: BigNumberish[][] = owners.map( - (owner) => owner.babyJubPublicKey + (owner) => owner.babyJubPublicKey, ) as BigNumberish[][]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ @@ -1052,12 +1052,12 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKeyToUse, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`, ); const encodedProof = encodeProof(proof); @@ -1081,7 +1081,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti encryptedValues: BigNumberish[], encryptionNonce: BigNumberish, encodedProof: any, - ecdhPublicKey: BigInt[] + ecdhPublicKey: BigInt[], ) { const startTx = Date.now(); const tx = await zeto.connect(signer.signer).transfer( @@ -1092,13 +1092,13 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ecdhPublicKey, encryptedValues, encodedProof, - '0x' + '0x', ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ results?.gasUsed - }` + }`, ); return results; } diff --git a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts index 2a42868..49d093a 100644 --- a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts +++ b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts @@ -82,7 +82,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti Authority = await newUser(e); ({ deployer, zeto, erc20 } = await deployZeto( - 'Zeto_AnonEncNullifierNonRepudiation' + 'Zeto_AnonEncNullifierNonRepudiation', )); const tx1 = await zeto @@ -98,13 +98,13 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti circuit = await loadCircuit('anon_enc_nullifier_non_repudiation'); ({ provingKeyFile: provingKey } = loadProvingKeys( - 'anon_enc_nullifier_non_repudiation' + 'anon_enc_nullifier_non_repudiation', )); batchCircuit = await loadCircuit( - 'anon_enc_nullifier_non_repudiation_batch' + 'anon_enc_nullifier_non_repudiation_batch', ); ({ provingKeyFile: batchProvingKey } = loadProvingKeys( - 'anon_enc_nullifier_non_repudiation_batch' + 'anon_enc_nullifier_non_repudiation_batch', )); }); @@ -141,7 +141,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti for (let i = 0; i < inputUtxos.length; i++) { const p = await smtAlice.generateCircomVerifierProof( inputUtxos[i].hash, - root + root, ); mtps.push(p.siblings.map((s) => s.bigInt())); } @@ -166,7 +166,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti inflatedOutputUtxos, root.bigInt(), mtps, - inflatedOutputOwners + inflatedOutputOwners, ); const signerAddress = await Alice.signer.getAddress(); @@ -185,7 +185,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti events[0].encryptedValuesForReceiver, sharedKey, events[0].encryptionNonce, - 20 + 20, ); expect(plainText).to.deep.equal(result.expectedPlainText); @@ -213,13 +213,13 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti // The regulator uses the encrypted values in the event to decrypt and recover the UTXO value and salt const auditKey = genEcdhSharedKey( Authority.babyJubPrivateKey, - ecdhPublicKey + ecdhPublicKey, ); const auditPlainText = poseidonDecrypt( events[0].encryptedValuesForAuthority, auditKey, events[0].encryptionNonce, - 62 + 62, ); // check sender pub key match @@ -267,7 +267,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti utxo100 = newUTXO(100, Alice); const { outputCommitments, encodedProof } = await prepareDepositProof( Alice, - utxo100 + utxo100, ); const tx2 = await zeto .connect(Alice.signer) @@ -326,7 +326,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [_utxo3, utxo4], root.bigInt(), merkleProofs, - [Bob, Alice] + [Bob, Alice], ); // check the private transfer activity is not exposed in the ERC20 contract @@ -358,20 +358,20 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti events[0].encryptedValuesForReceiver, sharedKey1, events[0].encryptionNonce, - 4 + 4, ); expect(plainText1).to.deep.equal(result2.expectedPlainText); // The regulator uses the encrypted values in the event to decrypt and recover the UTXO value and salt const sharedKey2 = genEcdhSharedKey( Authority.babyJubPrivateKey, - ecdhPublicKey + ecdhPublicKey, ); const plainText2 = poseidonDecrypt( events[0].encryptedValuesForAuthority, sharedKey2, events[0].encryptionNonce, - 14 + 14, ); expect(plainText2).to.deep.equal([ Alice.babyJubPublicKey[0], @@ -448,7 +448,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [utxo6, utxo7], root.bigInt(), merkleProofs, - [Charlie, Bob] + [Charlie, Bob], ); // Bob keeps the local SMT in sync @@ -470,7 +470,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo100.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); const merkleProofs = [ @@ -488,7 +488,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [nullifier1, ZERO_UTXO], withdrawChangeUTXO, root.bigInt(), - merkleProofs + merkleProofs, ); // Alice withdraws her UTXOs to ERC20 tokens @@ -499,7 +499,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti nullifiers, outputCommitments[0], root.bigInt(), - encodedProof + encodedProof, ); await tx.wait(); @@ -529,7 +529,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo100.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); const merkleProofs = [ @@ -547,7 +547,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [nullifier1, ZERO_UTXO], outputCommitment, root.bigInt(), - merkleProofs + merkleProofs, ); // Alice withdraws her UTXOs to ERC20 tokens @@ -559,20 +559,20 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti nullifiers, outputCommitments[0], root.bigInt(), - encodedProof - ) + encodedProof, + ), ).rejectedWith('UTXOAlreadySpent'); }); it('mint existing unspent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); it('mint existing spent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); @@ -589,11 +589,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo1.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof( utxo2.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -608,8 +608,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [_utxo1, _utxo2], root.bigInt(), merkleProofs, - [Bob, Alice] - ) + [Bob, Alice], + ), ).rejectedWith('UTXOAlreadySpent'); }).timeout(600000); @@ -625,7 +625,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); const proof2 = await smtBob.generateCircomVerifierProof( _utxo1.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -640,8 +640,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [utxo1, utxo2], root.bigInt(), merkleProofs, - [Alice, Alice] - ) + [Alice, Alice], + ), ).rejectedWith('UTXOAlreadyOwned'); }).timeout(600000); @@ -667,8 +667,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [_utxo1, _utxo2], root.bigInt(), merkleProofs, - [Alice, Bob] - ) + [Alice, Bob], + ), ).rejectedWith(`UTXODuplicate`); }).timeout(600000); @@ -688,11 +688,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( nonExisting1.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof( nonExisting2.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -711,8 +711,8 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti [utxo7, _utxo1], root.bigInt(), merkleProofs, - [Bob, Charlie] - ) + [Bob, Charlie], + ), ).rejectedWith('UTXORootNotFound'); }).timeout(600000); }); @@ -724,7 +724,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti outputs: UTXO[], root: BigInt, merkleProofs: BigInt[][], - owners: User[] + owners: User[], ) { let nullifiers: BigNumberish[]; let outputCommitments: BigNumberish[]; @@ -740,11 +740,11 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti root, merkleProofs, owners, - ephemeralKeypair.privKey + ephemeralKeypair.privKey, ); nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, - BigNumberish + BigNumberish, ]; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; @@ -759,7 +759,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti result.encryptedValuesForRegulator, encryptionNonce, encodedProof, - ephemeralKeypair.pubKey + ephemeralKeypair.pubKey, ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { @@ -780,23 +780,23 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti root: BigInt, merkleProof: BigInt[][], owners: User[], - ephemeralPrivateKey: BigInt + ephemeralPrivateKey: BigInt, ) { const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, - BigNumberish + BigNumberish, ]; const inputCommitments: BigNumberish[] = inputs.map( - (input) => input.hash + (input) => input.hash, ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); const outputCommitments: BigNumberish[] = outputs.map( - (output) => output.hash + (output) => output.hash, ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); const outputOwnerPublicKeys: BigNumberish[][] = owners.map( - (owner) => owner.babyJubPublicKey + (owner) => owner.babyJubPublicKey, ) as BigNumberish[][]; const encryptionNonce: BigNumberish = newEncryptionNonce() as BigNumberish; const encryptInputs = stringifyBigInts({ @@ -834,12 +834,12 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKeyToUse, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`, ); const encodedProof = encodeProof(proof); @@ -866,7 +866,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti encryptedValuesForRegulator: BigNumberish[], encryptionNonce: BigNumberish, encodedProof: any, - ecdhPublicKey: BigInt[] + ecdhPublicKey: BigInt[], ) { const startTx = Date.now(); const tx = await zeto.connect(signer.signer).transfer( @@ -878,13 +878,13 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti encryptedValuesForReceiver, encryptedValuesForRegulator, encodedProof, - '0x' + '0x', ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ results?.gasUsed - }` + }`, ); return results; } diff --git a/solidity/test/zeto_anon_nullifier.ts b/solidity/test/zeto_anon_nullifier.ts index 11c0341..72a63bb 100644 --- a/solidity/test/zeto_anon_nullifier.ts +++ b/solidity/test/zeto_anon_nullifier.ts @@ -79,7 +79,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr ({ provingKeyFile: provingKey } = loadProvingKeys('anon_nullifier')); batchCircuit = await loadCircuit('anon_nullifier_batch'); ({ provingKeyFile: batchProvingKey } = loadProvingKeys( - 'anon_nullifier_batch' + 'anon_nullifier_batch', )); }); it('onchain SMT root should be equal to the offchain SMT root', async function () { @@ -115,7 +115,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr for (let i = 0; i < inputUtxos.length; i++) { const p = await smtAlice.generateCircomVerifierProof( inputUtxos[i].hash, - root + root, ); mtps.push(p.siblings.map((s) => s.bigInt())); } @@ -140,7 +140,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr inflatedOutputUtxos, root.bigInt(), mtps, - inflatedOutputOwners + inflatedOutputOwners, ); const signerAddress = await Alice.signer.getAddress(); @@ -184,7 +184,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr utxo100 = newUTXO(100, Alice); const { outputCommitments, encodedProof } = await prepareDepositProof( Alice, - utxo100 + utxo100, ); const tx2 = await zeto .connect(Alice.signer) @@ -243,7 +243,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr [_utxo3, utxo4], root.bigInt(), merkleProofs, - [Bob, Alice] + [Bob, Alice], ); // check the private transfer activity is not exposed in the ERC20 contract @@ -308,7 +308,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr [utxo6, utxo7], root.bigInt(), merkleProofs, - [Charlie, Bob] + [Charlie, Bob], ); // Bob keeps the local SMT in sync @@ -331,7 +331,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo100.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); const merkleProofs = [ @@ -349,7 +349,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr [nullifier1, ZERO_UTXO], withdrawChangesUTXO, root.bigInt(), - merkleProofs + merkleProofs, ); // Alice withdraws her UTXOs to ERC20 tokens @@ -360,7 +360,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr nullifiers, outputCommitments[0], root.bigInt(), - encodedProof + encodedProof, ); await tx.wait(); @@ -390,7 +390,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo100.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); const merkleProofs = [ @@ -408,7 +408,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr [nullifier1, ZERO_UTXO], outputCommitment, root.bigInt(), - merkleProofs + merkleProofs, ); await expect( @@ -419,20 +419,20 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr nullifiers, outputCommitments[0], root.bigInt(), - encodedProof - ) + encodedProof, + ), ).rejectedWith('UTXOAlreadySpent'); }); it('mint existing unspent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); it('mint existing spent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); @@ -449,11 +449,11 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo1.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof( utxo2.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -468,8 +468,8 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr [_utxo1, _utxo2], root.bigInt(), merkleProofs, - [Bob, Alice] - ) + [Bob, Alice], + ), ).rejectedWith('UTXOAlreadySpent'); }).timeout(600000); @@ -485,7 +485,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); const proof2 = await smtBob.generateCircomVerifierProof( _utxo1.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -500,8 +500,8 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr [utxo1, utxo2], root.bigInt(), merkleProofs, - [Alice, Alice] - ) + [Alice, Alice], + ), ).rejectedWith('UTXOAlreadyOwned'); }).timeout(600000); @@ -527,8 +527,8 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr [_utxo1, _utxo2], root.bigInt(), merkleProofs, - [Alice, Bob] - ) + [Alice, Bob], + ), ).rejectedWith(`UTXODuplicate`); }).timeout(600000); @@ -548,11 +548,11 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( nonExisting1.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof( nonExisting2.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -571,8 +571,8 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr [utxo7, _utxo1], root.bigInt(), merkleProofs, - [Bob, Charlie] - ) + [Bob, Charlie], + ), ).rejectedWith('UTXORootNotFound'); }).timeout(600000); @@ -591,7 +591,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr outputs: UTXO[], root: BigInt, merkleProofs: BigInt[][], - owners: User[] + owners: User[], ) { let nullifiers: BigNumberish[]; let outputCommitments: BigNumberish[]; @@ -603,10 +603,10 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr outputs, root, merkleProofs, - owners + owners, ); nullifiers = _nullifiers.map( - (nullifier) => nullifier.hash + (nullifier) => nullifier.hash, ) as BigNumberish[]; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; @@ -616,7 +616,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr nullifiers, outputCommitments, root, - encodedProof + encodedProof, ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { @@ -636,23 +636,23 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr outputs: UTXO[], root: BigInt, merkleProof: BigInt[][], - owners: User[] + owners: User[], ) { const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, - BigNumberish + BigNumberish, ]; const inputCommitments: BigNumberish[] = inputs.map( - (input) => input.hash + (input) => input.hash, ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); const outputCommitments: BigNumberish[] = outputs.map( - (output) => output.hash + (output) => output.hash, ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); const outputOwnerPublicKeys: BigNumberish[][] = owners.map( - (owner) => owner.babyJubPublicKey + (owner) => owner.babyJubPublicKey, ) as BigNumberish[][]; const startWitnessCalculation = Date.now(); @@ -684,12 +684,12 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKeyToUse, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`, ); const encodedProof = encodeProof(proof); @@ -705,7 +705,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr nullifiers: BigNumberish[], outputCommitments: BigNumberish[], root: BigNumberish, - encodedProof: any + encodedProof: any, ) { const startTx = Date.now(); const tx = await zeto.connect(signer.signer).transfer( @@ -713,13 +713,13 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works root, encodedProof, - '0x' + '0x', ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ results?.gasUsed - }` + }`, ); return results; } diff --git a/solidity/test/zeto_anon_nullifier_kyc.ts b/solidity/test/zeto_anon_nullifier_kyc.ts index fafd18d..c0a4dfd 100644 --- a/solidity/test/zeto_anon_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_nullifier_kyc.ts @@ -106,7 +106,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou ({ provingKeyFile: provingKey } = loadProvingKeys('anon_nullifier_kyc')); batchCircuit = await loadCircuit('anon_nullifier_kyc_batch'); ({ provingKeyFile: batchProvingKey } = loadProvingKeys( - 'anon_nullifier_kyc_batch' + 'anon_nullifier_kyc_batch', )); }); @@ -144,7 +144,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou for (let i = 0; i < inputUtxos.length; i++) { const p = await smtAlice.generateCircomVerifierProof( inputUtxos[i].hash, - root + root, ); mtps.push(p.siblings.map((s) => s.bigInt())); } @@ -153,12 +153,12 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const identitiesRoot = await smtKyc.root(); const aProof = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const aliceProof = aProof.siblings.map((s) => s.bigInt()); const bProof = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const bobProof = bProof.siblings.map((s) => s.bigInt()); // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice @@ -186,7 +186,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou mtps, identitiesRoot.bigInt(), identityMerkleProofs, - inflatedOutputOwners + inflatedOutputOwners, ); const signerAddress = await Alice.signer.getAddress(); @@ -231,7 +231,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou utxo100 = newUTXO(100, Alice); const { outputCommitments, encodedProof } = await prepareDepositProof( Alice, - utxo100 + utxo100, ); const tx2 = await zeto .connect(Alice.signer) @@ -277,11 +277,11 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou // Alice generates inclusion proofs for the UTXOs to be spent const proof1 = await smtAlice.generateCircomVerifierProof( utxo1.hash, - utxosRoot + utxosRoot, ); const proof2 = await smtAlice.generateCircomVerifierProof( utxo2.hash, - utxosRoot + utxosRoot, ); const utxoMerkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -292,11 +292,11 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identityMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) @@ -314,7 +314,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou utxoMerkleProofs, identitiesRoot.bigInt(), identityMerkleProofs, - [Bob, Alice] + [Bob, Alice], ); // check the private transfer activity is not exposed in the ERC20 contract @@ -362,7 +362,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const utxosRoot = await smtBob.root(); const proof1 = await smtBob.generateCircomVerifierProof( utxo3.hash, - utxosRoot + utxosRoot, ); const proof2 = await smtBob.generateCircomVerifierProof(0n, utxosRoot); const utxosMerkleProofs = [ @@ -380,11 +380,11 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Charlie.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Bob) @@ -402,7 +402,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou utxosMerkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, - [Charlie, Bob] + [Charlie, Bob], ); // Bob keeps the local SMT in sync @@ -424,7 +424,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo100.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); const merkleProofs = [ @@ -441,7 +441,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou [nullifier1, ZERO_UTXO], withdrawChangeUTXO, root.bigInt(), - merkleProofs + merkleProofs, ); // Alice withdraws her UTXOs to ERC20 tokens @@ -452,7 +452,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou nullifiers, outputCommitments[0], root.bigInt(), - encodedProof + encodedProof, ); await tx.wait(); @@ -482,7 +482,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou unregisteredUtxo100 = newUTXO(100, unregistered); const { outputCommitments, encodedProof } = await prepareDepositProof( unregistered, - unregisteredUtxo100 + unregisteredUtxo100, ); const tx2 = await zeto .connect(unregistered.signer) @@ -506,11 +506,11 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou await smtUnregistered.add(utxo7.hash, utxo7.hash); await smtUnregistered.add( withdrawChangeUTXO.hash, - withdrawChangeUTXO.hash + withdrawChangeUTXO.hash, ); await smtUnregistered.add( unregisteredUtxo100.hash, - unregisteredUtxo100.hash + unregisteredUtxo100.hash, ); const utxosRoot = await smtUnregistered.root(); @@ -519,7 +519,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const output2 = newUTXO(0, unregistered); const proof = await smtUnregistered.generateCircomVerifierProof( unregisteredUtxo100.hash, - utxosRoot + utxosRoot, ); const merkleProofs = [ proof.siblings.map((s) => s.bigInt()), @@ -529,16 +529,16 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou // add the unregistered user to the local KYC SMT, but not to the onchain SMT await smtKyc.add( kycHash(unregistered.babyJubPublicKey), - kycHash(unregistered.babyJubPublicKey) + kycHash(unregistered.babyJubPublicKey), ); const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(unregistered.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (unregistered) @@ -555,8 +555,8 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, - [Bob, unregistered] - ) + [Bob, unregistered], + ), ).rejectedWith('Invalid proof'); }); @@ -569,11 +569,11 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou let root = await smtUnregistered.root(); const proof1 = await smtUnregistered.generateCircomVerifierProof( unregisteredUtxo100.hash, - root + root, ); const proof2 = await smtUnregistered.generateCircomVerifierProof( 0n, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -590,7 +590,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou [nullifier1, ZERO_UTXO], unregisteredWithdrawChangeUTXO, root.bigInt(), - merkleProofs + merkleProofs, ); // unregistered user withdraws her UTXOs to ERC20 tokens @@ -601,19 +601,19 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou nullifiers, outputCommitments[0], root.bigInt(), - encodedProof + encodedProof, ); await tx.wait(); // Alice tracks the UTXO inside the SMT await smtAlice.add( unregisteredWithdrawChangeUTXO.hash, - unregisteredWithdrawChangeUTXO.hash + unregisteredWithdrawChangeUTXO.hash, ); // Bob also locally tracks the UTXOs inside the SMT await smtBob.add( unregisteredWithdrawChangeUTXO.hash, - unregisteredWithdrawChangeUTXO.hash + unregisteredWithdrawChangeUTXO.hash, ); // unregistered user checks her ERC20 balance @@ -638,7 +638,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo100.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof(0n, root); const merkleProofs = [ @@ -655,7 +655,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou [nullifier1, ZERO_UTXO], withdrawChangeUTXO, root.bigInt(), - merkleProofs + merkleProofs, ); await expect( @@ -666,20 +666,20 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou nullifiers, outputCommitments[0], root.bigInt(), - encodedProof - ) + encodedProof, + ), ).rejectedWith('UTXOAlreadySpent'); }); it('mint existing unspent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); it('mint existing spent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); @@ -696,11 +696,11 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo1.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof( utxo2.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -710,11 +710,11 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) @@ -732,8 +732,8 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, - [Bob, Alice] - ) + [Bob, Alice], + ), ).rejectedWith('UTXOAlreadySpent'); }).timeout(600000); @@ -749,7 +749,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const proof1 = await smtBob.generateCircomVerifierProof(utxo7.hash, root); const proof2 = await smtBob.generateCircomVerifierProof( _utxo1.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -759,11 +759,11 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Bob) @@ -781,8 +781,8 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, - [Alice, Alice] - ) + [Alice, Alice], + ), ).rejectedWith('UTXOAlreadyOwned'); }).timeout(600000); @@ -803,11 +803,11 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Bob) @@ -825,8 +825,8 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, - [Alice, Bob] - ) + [Alice, Bob], + ), ).rejectedWith(`UTXODuplicate`); }).timeout(600000); @@ -846,11 +846,11 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( nonExisting1.hash, - root + root, ); const proof2 = await smtAlice.generateCircomVerifierProof( nonExisting2.hash, - root + root, ); const merkleProofs = [ proof1.siblings.map((s) => s.bigInt()), @@ -864,15 +864,15 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const identitiesRoot = await smtKyc.root(); const proof3 = await smtKyc.generateCircomVerifierProof( kycHash(Alice.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof4 = await smtKyc.generateCircomVerifierProof( kycHash(Bob.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const proof5 = await smtKyc.generateCircomVerifierProof( kycHash(Charlie.babyJubPublicKey), - identitiesRoot + identitiesRoot, ); const identitiesMerkleProofs = [ proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (Alice) @@ -890,8 +890,8 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou merkleProofs, identitiesRoot.bigInt(), identitiesMerkleProofs, - [Bob, Charlie] - ) + [Bob, Charlie], + ), ).rejectedWith('UTXORootNotFound'); }).timeout(600000); @@ -912,7 +912,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou utxosMerkleProofs: BigInt[][], identitiesRoot: BigInt, identitiesMerkleProof: BigInt[][], - owners: User[] + owners: User[], ) { let nullifiers: BigNumberish[]; let outputCommitments: BigNumberish[]; @@ -926,11 +926,11 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou utxosMerkleProofs, identitiesRoot, identitiesMerkleProof, - owners + owners, ); nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, - BigNumberish + BigNumberish, ]; outputCommitments = result.outputCommitments; encodedProof = result.encodedProof; @@ -940,7 +940,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou nullifiers, outputCommitments, utxosRoot, - encodedProof + encodedProof, ); // add the clear text value so that it can be used by tests to compare with the decrypted value return { @@ -962,23 +962,23 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou utxosMerkleProof: BigInt[][], identitiesRoot: BigInt, identitiesMerkleProof: BigInt[][], - owners: User[] + owners: User[], ) { const nullifiers = _nullifiers.map((nullifier) => nullifier.hash) as [ BigNumberish, - BigNumberish + BigNumberish, ]; const inputCommitments: BigNumberish[] = inputs.map( - (input) => input.hash + (input) => input.hash, ) as BigNumberish[]; const inputValues = inputs.map((input) => BigInt(input.value || 0n)); const inputSalts = inputs.map((input) => input.salt || 0n); const outputCommitments: BigNumberish[] = outputs.map( - (output) => output.hash + (output) => output.hash, ) as BigNumberish[]; const outputValues = outputs.map((output) => BigInt(output.value || 0n)); const outputOwnerPublicKeys: BigNumberish[][] = owners.map( - (owner) => owner.babyJubPublicKey + (owner) => owner.babyJubPublicKey, ) as BigNumberish[][]; const startWitnessCalculation = Date.now(); const inputObj = { @@ -1011,12 +1011,12 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKeyToUse, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`, ); const encodedProof = encodeProof(proof); @@ -1032,7 +1032,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou nullifiers: BigNumberish[], outputCommitments: BigNumberish[], root: BigNumberish, - encodedProof: any + encodedProof: any, ) { const startTx = Date.now(); const tx = await zeto.connect(signer.signer).transfer( @@ -1040,13 +1040,13 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works root, encodedProof, - '0x' + '0x', ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ results?.gasUsed - }` + }`, ); return results; } diff --git a/solidity/test/zeto_nf_anon.ts b/solidity/test/zeto_nf_anon.ts index 30f361e..747939c 100644 --- a/solidity/test/zeto_nf_anon.ts +++ b/solidity/test/zeto_nf_anon.ts @@ -86,13 +86,13 @@ describe('Zeto based non-fungible token with anonymity without encryption or nul it('mint existing unspent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo3])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); it('mint existing spent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadySpent' + 'UTXOAlreadySpent', ); }); @@ -100,16 +100,16 @@ describe('Zeto based non-fungible token with anonymity without encryption or nul const nonExisting1 = newAssetUTXO( 1002, 'http://ipfs.io/file-hash-2', - Alice + Alice, ); const nonExisting2 = newAssetUTXO( 1002, 'http://ipfs.io/file-hash-2', - Bob + Bob, ); await expect( - doTransfer(Alice, nonExisting1, nonExisting2, Bob) + doTransfer(Alice, nonExisting1, nonExisting2, Bob), ).rejectedWith('UTXONotMinted'); }); @@ -117,7 +117,7 @@ describe('Zeto based non-fungible token with anonymity without encryption or nul // create outputs const _utxo4 = newAssetUTXO(utxo1.tokenId!, utxo1.uri!, Bob); await expect(doTransfer(Alice, utxo1, _utxo4, Bob)).rejectedWith( - 'UTXOAlreadySpent' + 'UTXOAlreadySpent', ); }); }); @@ -133,7 +133,7 @@ describe('Zeto based non-fungible token with anonymity without encryption or nul signer, input, output, - to + to, ); inputCommitment = result.inputCommitment; outputCommitment = result.outputCommitment; @@ -147,7 +147,7 @@ describe('Zeto based non-fungible token with anonymity without encryption or nul signer: User, inputCommitment: BigNumberish, outputCommitment: BigNumberish, - encodedProof: any + encodedProof: any, ) { const tx = await zeto .connect(signer.signer) @@ -166,7 +166,7 @@ async function prepareProof( signer: User, input: UTXO, output: UTXO, - to: User + to: User, ) { const tokenId = input.tokenId; const inputCommitment: BigNumberish = input.hash as BigNumberish; @@ -190,18 +190,18 @@ async function prepareProof( outputOwnerPublicKeys: [outputOwnerPublicKey], ...otherInputs, }, - true + true, ); const timeWitnessCalculation = Date.now() - startWitnessCalculation; const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKey, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms` + `Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms`, ); const encodedProof = encodeProof(proof); return { diff --git a/solidity/test/zeto_nf_anon_nullifier.ts b/solidity/test/zeto_nf_anon_nullifier.ts index 8fcd525..e825fd1 100644 --- a/solidity/test/zeto_nf_anon_nullifier.ts +++ b/solidity/test/zeto_nf_anon_nullifier.ts @@ -110,7 +110,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without _utxo3, root.bigInt(), merkleProof, - Bob + Bob, ); // Alice locally tracks the UTXOs inside the Sparse Merkle Tree @@ -166,7 +166,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without utxo6, root.bigInt(), merkleProof, - Charlie + Charlie, ); // Bob keeps the local SMT in sync @@ -187,13 +187,13 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without it('mint existing unspent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo3])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); it('mint existing spent UTXOs should fail', async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadyOwned' + 'UTXOAlreadyOwned', ); }); @@ -208,7 +208,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( utxo1.hash, - root + root, ); const merkleProof = proof1.siblings.map((s) => s.bigInt()); @@ -220,8 +220,8 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without _utxo1, root.bigInt(), merkleProof, - Charlie - ) + Charlie, + ), ).rejectedWith('UTXOAlreadySpent'); }).timeout(600000); @@ -229,7 +229,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without const nonExisting1 = newAssetUTXO( 1002, 'http://ipfs.io/file-hash-2', - Alice + Alice, ); // add to our local SMT (but they don't exist on the chain) @@ -242,7 +242,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without let root = await smtAlice.root(); const proof1 = await smtAlice.generateCircomVerifierProof( nonExisting1.hash, - root + root, ); const merkleProof = proof1.siblings.map((s) => s.bigInt()); @@ -250,7 +250,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without const _utxo1 = newAssetUTXO( nonExisting1.tokenId!, nonExisting1.uri!, - Charlie + Charlie, ); await expect( @@ -261,8 +261,8 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without _utxo1, root.bigInt(), merkleProof, - Charlie - ) + Charlie, + ), ).rejectedWith('UTXORootNotFound'); }).timeout(600000); }); @@ -274,7 +274,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without output: UTXO, root: BigInt, merkleProof: BigInt[], - owner: User + owner: User, ) { let nullifier: BigNumberish; let outputCommitment: BigNumberish; @@ -286,7 +286,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without output, root, merkleProof, - owner + owner, ); nullifier = _nullifier.hash as BigNumberish; outputCommitment = result.outputCommitment; @@ -297,7 +297,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without nullifier, outputCommitment, root, - encodedProof + encodedProof, ); return { txResult }; } @@ -309,7 +309,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without output: UTXO, root: BigInt, merkleProof: BigInt[], - owner: User + owner: User, ) { const nullifier = _nullifier.hash as BigNumberish; const inputCommitment: BigNumberish = input.hash as BigNumberish; @@ -341,12 +341,12 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without const startProofGeneration = Date.now(); const { proof, publicSignals } = (await groth16.prove( provingKey, - witness + witness, )) as { proof: BigNumberish[]; publicSignals: BigNumberish[] }; const timeProofGeneration = Date.now() - startProofGeneration; console.log( - `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.` + `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`, ); const encodedProof = encodeProof(proof); @@ -362,7 +362,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without nullifier: BigNumberish, outputCommitment: BigNumberish, root: BigNumberish, - encodedProof: any + encodedProof: any, ) { const startTx = Date.now(); const tx = await zeto @@ -372,7 +372,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without console.log( `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ results?.gasUsed - }` + }`, ); return results; } diff --git a/solidity/test/zkDvP.ts b/solidity/test/zkDvP.ts index 9690db0..4002063 100644 --- a/solidity/test/zkDvP.ts +++ b/solidity/test/zkDvP.ts @@ -117,8 +117,8 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with ZeroHash, 0, 0, - ZeroHash - ) + ZeroHash, + ), ).fulfilled; }); @@ -134,8 +134,8 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with ZeroHash, utxo1.hash, utxo2.hash, - ZeroHash - ) + ZeroHash, + ), ).fulfilled; }); @@ -160,7 +160,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with Alice, [_utxo1, ZERO_UTXO], [utxo2, ZERO_UTXO], - [Bob, {}] + [Bob, {}], ); const hash1 = getProofHash(proof1.encodedProof); @@ -185,7 +185,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with Bob, utxo3, utxo4, - Alice + Alice, ); const hash2 = getProofHash(proof2.encodedProof); @@ -199,8 +199,8 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with ZeroHash, utxo3.hash, utxo4.hash, - hash2 - ) + hash2, + ), ).fulfilled; // 3. Alice sends her proof to complete the trade (the trade will still be pending completion) @@ -232,9 +232,9 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with await expect( zkDvP .connect(Alice.signer) - .initiateTrade([0, 0], [0, 0], ZeroHash, 0, 0, ZeroHash) + .initiateTrade([0, 0], [0, 0], ZeroHash, 0, 0, ZeroHash), ).rejectedWith( - 'Payment inputs and asset input cannot be zero at the same time' + 'Payment inputs and asset input cannot be zero at the same time', ); }); @@ -250,10 +250,10 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with ZeroHash, 0, 0, - ZeroHash - ) + ZeroHash, + ), ).rejectedWith( - 'Payment outputs cannot be zero when payment inputs are non-zero' + 'Payment outputs cannot be zero when payment inputs are non-zero', ); }); @@ -271,10 +271,10 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with ZeroHash, utxo3.hash, 0, - ZeroHash - ) + ZeroHash, + ), ).rejectedWith( - 'Payment inputs and asset input cannot be provided at the same time' + 'Payment inputs and asset input cannot be provided at the same time', ); }); @@ -283,9 +283,9 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with await expect( zkDvP .connect(Alice.signer) - .initiateTrade([0, 0], [0, 0], ZeroHash, utxo1.hash, 0, ZeroHash) + .initiateTrade([0, 0], [0, 0], ZeroHash, utxo1.hash, 0, ZeroHash), ).rejectedWith( - 'Asset output cannot be zero when asset input is non-zero' + 'Asset output cannot be zero when asset input is non-zero', ); }); @@ -293,7 +293,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with await expect( zkDvP .connect(Bob.signer) - .acceptTrade(1000, [0, 0], [0, 0], ZeroHash, 0, 0, ZeroHash) + .acceptTrade(1000, [0, 0], [0, 0], ZeroHash, 0, 0, ZeroHash), ).rejectedWith('Trade does not exist'); }); @@ -309,7 +309,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with mockProofHash, 0, 0, - mockProofHash + mockProofHash, ); const result = await tx1.wait(); const event = zkDvP.interface.parseLog(result.logs[0]); @@ -326,8 +326,8 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with mockProofHash, 0, 0, - mockProofHash - ) + mockProofHash, + ), ).rejectedWith('Payment inputs already provided by the trade initiator'); await expect( zkDvP @@ -339,8 +339,8 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with mockProofHash, 0, 0, - mockProofHash - ) + mockProofHash, + ), ).rejectedWith('Payment outputs already provided by the trade initiator'); await expect( zkDvP @@ -352,8 +352,8 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with mockProofHash, 0, 0, - mockProofHash - ) + mockProofHash, + ), ).rejectedWith('Asset input must be provided to accept the trade'); await expect( zkDvP @@ -365,8 +365,8 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with mockProofHash, utxo3.hash, 0, - mockProofHash - ) + mockProofHash, + ), ).rejectedWith('Asset output must be provided to accept the trade'); }); @@ -382,7 +382,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with ZeroHash, utxo1.hash, utxo2.hash, - mockProofHash + mockProofHash, ); const result = await tx1.wait(); const event = zkDvP.interface.parseLog(result.logs[0]); @@ -402,8 +402,8 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with mockProofHash, utxo1.hash, utxo2.hash, - mockProofHash - ) + mockProofHash, + ), ).rejectedWith('Asset inputs already provided by the trade initiator'); await expect( zkDvP @@ -415,8 +415,8 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with mockProofHash, 0, utxo2.hash, - mockProofHash - ) + mockProofHash, + ), ).rejectedWith('Asset outputs already provided by the trade initiator'); await expect( zkDvP @@ -428,8 +428,8 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with mockProofHash, 0, 0, - mockProofHash - ) + mockProofHash, + ), ).rejectedWith('Payment inputs must be provided to accept the trade'); await expect( zkDvP @@ -441,21 +441,47 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with mockProofHash, 0, 0, - mockProofHash - ) + mockProofHash, + ), ).rejectedWith('Payment outputs must be provided to accept the trade'); }); - it("test proof locking", async function () { + it('test proof locking', async function () { const circuit1 = await loadCircuit('anon'); const { provingKeyFile: provingKey1 } = loadProvingKeys('anon'); const utxo1 = newUTXO(100, Alice); - const proof = await zetoAnonTests.prepareProof(circuit1, provingKey1, Alice, [utxo1, ZERO_UTXO], [utxo1, ZERO_UTXO], [Alice, {}]); + const proof = await zetoAnonTests.prepareProof( + circuit1, + provingKey1, + Alice, + [utxo1, ZERO_UTXO], + [utxo1, ZERO_UTXO], + [Alice, {}], + ); - await expect(zkPayment.connect(Alice.signer).lockProof(proof.encodedProof, await Alice.signer.getAddress())).fulfilled; - await expect(zkPayment.connect(Bob.signer).lockProof(proof.encodedProof, await Bob.signer.getAddress())).rejectedWith("Proof already locked by another party"); - await expect(zkPayment.connect(Alice.signer).lockProof(proof.encodedProof, await Bob.signer.getAddress())).fulfilled; - await expect(zkPayment.connect(Bob.signer).lockProof(proof.encodedProof, "0x0000000000000000000000000000000000000000")).fulfilled; + await expect( + zkPayment + .connect(Alice.signer) + .lockProof(proof.encodedProof, await Alice.signer.getAddress()), + ).fulfilled; + await expect( + zkPayment + .connect(Bob.signer) + .lockProof(proof.encodedProof, await Bob.signer.getAddress()), + ).rejectedWith('Proof already locked by another party'); + await expect( + zkPayment + .connect(Alice.signer) + .lockProof(proof.encodedProof, await Bob.signer.getAddress()), + ).fulfilled; + await expect( + zkPayment + .connect(Bob.signer) + .lockProof( + proof.encodedProof, + '0x0000000000000000000000000000000000000000', + ), + ).fulfilled; }); }); }).timeout(600000); diff --git a/zkp/js/.prettierrc b/zkp/js/.prettierrc new file mode 100644 index 0000000..544138b --- /dev/null +++ b/zkp/js/.prettierrc @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} diff --git a/zkp/js/integration-test/anon.js b/zkp/js/integration-test/anon.js index 6fc3b05..80a9c40 100644 --- a/zkp/js/integration-test/anon.js +++ b/zkp/js/integration-test/anon.js @@ -16,7 +16,11 @@ const { expect } = require('chai'); const { groth16 } = require('snarkjs'); -const { genKeypair, formatPrivKeyForBabyJub, stringifyBigInts } = require('maci-crypto'); +const { + genKeypair, + formatPrivKeyForBabyJub, + stringifyBigInts, +} = require('maci-crypto'); const { Poseidon, newSalt, loadCircuit } = require('../index.js'); const { loadProvingKeys } = require('./utils.js'); @@ -47,14 +51,26 @@ describe('main circuit tests for Zeto fungible tokens with anonymity without enc const outputValues = [115, 0]; // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...sender.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...sender.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...sender.pubKey, + ]); const inputCommitments = [input1, input2]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...receiver.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...receiver.pubKey, + ]); const outputCommitments = [output1, 0]; const otherInputs = stringifyBigInts({ @@ -73,10 +89,13 @@ describe('main circuit tests for Zeto fungible tokens with anonymity without enc outputOwnerPublicKeys: [receiver.pubKey, ZERO_PUBKEY], ...otherInputs, }, - true + true, ); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness); + const { proof, publicSignals } = await groth16.prove( + provingKeyFile, + witness, + ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); const success = await groth16.verify(verificationKey, publicSignals, proof); diff --git a/zkp/js/integration-test/anon_enc.js b/zkp/js/integration-test/anon_enc.js index dc218f4..579a3bc 100644 --- a/zkp/js/integration-test/anon_enc.js +++ b/zkp/js/integration-test/anon_enc.js @@ -16,8 +16,18 @@ const { expect } = require('chai'); const { groth16 } = require('snarkjs'); -const { genRandomSalt, genKeypair, formatPrivKeyForBabyJub, stringifyBigInts } = require('maci-crypto'); -const { Poseidon, newSalt, loadCircuit, newEncryptionNonce } = require('../index.js'); +const { + genRandomSalt, + genKeypair, + formatPrivKeyForBabyJub, + stringifyBigInts, +} = require('maci-crypto'); +const { + Poseidon, + newSalt, + loadCircuit, + newEncryptionNonce, +} = require('../index.js'); const { loadProvingKeys } = require('./utils.js'); const ZERO_PUBKEY = [0, 0]; @@ -47,18 +57,27 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp const outputValues = [115, 0]; // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...sender.pubKey, + ]); const inputCommitments = [input1, 0]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...receiver.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...receiver.pubKey, + ]); const outputCommitments = [output1, 0]; const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, - inputOwnerPrivateKey: formatPrivKeyForBabyJub(sender.privKey), + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); const startTime = Date.now(); @@ -67,16 +86,20 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp inputCommitments, inputValues, inputSalts: [salt1, 0], + inputOwnerPrivateKey: formatPrivKeyForBabyJub(sender.privKey), outputCommitments, outputValues, outputSalts: [salt3, 0], outputOwnerPublicKeys: [receiver.pubKey, ZERO_PUBKEY], ...encryptInputs, }, - true + true, ); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness); + const { proof, publicSignals } = await groth16.prove( + provingKeyFile, + witness, + ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); const success = await groth16.verify(verificationKey, publicSignals, proof); diff --git a/zkp/js/integration-test/anon_enc_nullifier.js b/zkp/js/integration-test/anon_enc_nullifier.js index ddcda65..64768b1 100644 --- a/zkp/js/integration-test/anon_enc_nullifier.js +++ b/zkp/js/integration-test/anon_enc_nullifier.js @@ -16,9 +16,24 @@ const { expect } = require('chai'); const { groth16 } = require('snarkjs'); -const { genRandomSalt, genKeypair, formatPrivKeyForBabyJub, stringifyBigInts } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); -const { Poseidon, newSalt, loadCircuit, newEncryptionNonce } = require('../index.js'); +const { + genRandomSalt, + genKeypair, + formatPrivKeyForBabyJub, + stringifyBigInts, +} = require('maci-crypto'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); +const { + Poseidon, + newSalt, + loadCircuit, + newEncryptionNonce, +} = require('../index.js'); const { loadProvingKeys } = require('./utils.js'); const SMT_HEIGHT = 64; @@ -34,7 +49,8 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym before(async () => { circuit = await loadCircuit('anon_enc_nullifier'); - ({ provingKeyFile, verificationKey } = loadProvingKeys('anon_enc_nullifier')); + ({ provingKeyFile, verificationKey } = + loadProvingKeys('anon_enc_nullifier')); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -60,14 +76,30 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // create two input UTXOs, each has their own salt, but same owner const senderPrivateKey = formatPrivKeyForBabyJub(Alice.privKey); const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the input UTXOs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -75,18 +107,34 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH, + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); - const output2 = poseidonHash([BigInt(outputValues[1]), salt3, ...Alice.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt3, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); const startTime = Date.now(); @@ -98,7 +146,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], outputCommitments, outputValues, @@ -106,10 +157,13 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], ...encryptInputs, }, - true + true, ); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness); + const { proof, publicSignals } = await groth16.prove( + provingKeyFile, + witness, + ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); const success = await groth16.verify(verificationKey, publicSignals, proof); diff --git a/zkp/js/integration-test/anon_enc_nullifier_kyc.js b/zkp/js/integration-test/anon_enc_nullifier_kyc.js index 8338f81..eda8e7e 100644 --- a/zkp/js/integration-test/anon_enc_nullifier_kyc.js +++ b/zkp/js/integration-test/anon_enc_nullifier_kyc.js @@ -52,7 +52,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym before(async () => { circuit = await loadCircuit('anon_enc_nullifier_kyc'); ({ provingKeyFile, verificationKey } = loadProvingKeys( - 'anon_enc_nullifier_kyc' + 'anon_enc_nullifier_kyc', )); let keypair = genKeypair(); @@ -125,11 +125,11 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH + ZERO_HASH, ); const proof2 = await smtAlice.generateCircomVerifierProof( input2, - ZERO_HASH + ZERO_HASH, ); const utxosRoot = proof1.root.bigInt(); @@ -151,17 +151,19 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // generate the merkle proof for the transacting identities const proof3 = await smtKYC.generateCircomVerifierProof( kycHash(Alice.pubKey), - ZERO_HASH + ZERO_HASH, ); const proof4 = await smtKYC.generateCircomVerifierProof( kycHash(Bob.pubKey), - ZERO_HASH + ZERO_HASH, ); const identitiesRoot = proof3.root.bigInt(); const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); const startTime = Date.now(); @@ -190,12 +192,12 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], ...encryptInputs, }, - true + true, ); const { proof, publicSignals } = await groth16.prove( provingKeyFile, - witness + witness, ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); diff --git a/zkp/js/integration-test/anon_enc_nullifier_non_repudiation.js b/zkp/js/integration-test/anon_enc_nullifier_non_repudiation.js index 0a72e19..930b13c 100644 --- a/zkp/js/integration-test/anon_enc_nullifier_non_repudiation.js +++ b/zkp/js/integration-test/anon_enc_nullifier_non_repudiation.js @@ -16,9 +16,24 @@ const { expect } = require('chai'); const { groth16 } = require('snarkjs'); -const { genRandomSalt, genKeypair, formatPrivKeyForBabyJub, stringifyBigInts } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); -const { Poseidon, newSalt, loadCircuit, newEncryptionNonce } = require('../index.js'); +const { + genRandomSalt, + genKeypair, + formatPrivKeyForBabyJub, + stringifyBigInts, +} = require('maci-crypto'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); +const { + Poseidon, + newSalt, + loadCircuit, + newEncryptionNonce, +} = require('../index.js'); const { loadProvingKeys } = require('./utils.js'); const SMT_HEIGHT = 64; @@ -35,7 +50,9 @@ describe('main circuit tests for Zeto fungible tokens with encryption fro non-re before(async () => { circuit = await loadCircuit('anon_enc_nullifier_non_repudiation'); - ({ provingKeyFile, verificationKey } = loadProvingKeys('anon_enc_nullifier_non_repudiation')); + ({ provingKeyFile, verificationKey } = loadProvingKeys( + 'anon_enc_nullifier_non_repudiation', + )); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -65,14 +82,30 @@ describe('main circuit tests for Zeto fungible tokens with encryption fro non-re // create two input UTXOs, each has their own salt, but same owner const senderPrivateKey = formatPrivKeyForBabyJub(Alice.privKey); const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the input UTXOs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -80,18 +113,34 @@ describe('main circuit tests for Zeto fungible tokens with encryption fro non-re await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH, + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); - const output2 = poseidonHash([BigInt(outputValues[1]), salt3, ...Alice.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt3, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; const encryptionNonce = newEncryptionNonce(); + const ephemeralKeypair = genKeypair(); const encryptInputs = stringifyBigInts({ encryptionNonce, + ecdhPrivateKey: formatPrivKeyForBabyJub(ephemeralKeypair.privKey), }); const startTime = Date.now(); @@ -103,7 +152,10 @@ describe('main circuit tests for Zeto fungible tokens with encryption fro non-re inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], outputCommitments, outputValues, @@ -112,10 +164,13 @@ describe('main circuit tests for Zeto fungible tokens with encryption fro non-re authorityPublicKey: Regulator.pubKey, ...encryptInputs, }, - true + true, ); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness); + const { proof, publicSignals } = await groth16.prove( + provingKeyFile, + witness, + ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); const success = await groth16.verify(verificationKey, publicSignals, proof); diff --git a/zkp/js/integration-test/anon_nullifier.js b/zkp/js/integration-test/anon_nullifier.js index 0b05b77..6fd55c6 100644 --- a/zkp/js/integration-test/anon_nullifier.js +++ b/zkp/js/integration-test/anon_nullifier.js @@ -17,7 +17,12 @@ const { expect } = require('chai'); const { groth16 } = require('snarkjs'); const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); const { Poseidon, newSalt, loadCircuit } = require('../index.js'); const { loadProvingKeys } = require('./utils.js'); @@ -60,14 +65,30 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli // create two input UTXOs, each has their own salt, but same owner const senderPrivateKey = formatPrivKeyForBabyJub(Alice.privKey); const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the input UTXOs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -75,13 +96,27 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH, + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); - const output2 = poseidonHash([BigInt(outputValues[1]), salt3, ...Alice.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt3, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; const startTime = Date.now(); @@ -93,17 +128,23 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], outputCommitments, outputValues, outputSalts: [salt3, salt3], outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], }, - true + true, ); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness); + const { proof, publicSignals } = await groth16.prove( + provingKeyFile, + witness, + ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); const success = await groth16.verify(verificationKey, publicSignals, proof); diff --git a/zkp/js/integration-test/anon_nullifier_kyc.js b/zkp/js/integration-test/anon_nullifier_kyc.js index 58818d7..002961c 100644 --- a/zkp/js/integration-test/anon_nullifier_kyc.js +++ b/zkp/js/integration-test/anon_nullifier_kyc.js @@ -17,7 +17,12 @@ const { expect } = require('chai'); const { groth16 } = require('snarkjs'); const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); const { Poseidon, newSalt, loadCircuit, kycHash } = require('../index.js'); const { loadProvingKeys } = require('./utils.js'); @@ -36,7 +41,8 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using before(async () => { circuit = await loadCircuit('anon_nullifier_kyc'); - ({ provingKeyFile, verificationKey } = loadProvingKeys('anon_nullifier_kyc')); + ({ provingKeyFile, verificationKey } = + loadProvingKeys('anon_nullifier_kyc')); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -74,14 +80,30 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the inputs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -89,20 +111,40 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH, + ); const utxosRoot = proof1.root.bigInt(); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); const salt4 = newSalt(); - const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...Alice.pubKey]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt4, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; // generate the merkle proof for the transacting identities - const proof3 = await smtKYC.generateCircomVerifierProof(kycHash(Alice.pubKey), ZERO_HASH); - const proof4 = await smtKYC.generateCircomVerifierProof(kycHash(Bob.pubKey), ZERO_HASH); + const proof3 = await smtKYC.generateCircomVerifierProof( + kycHash(Alice.pubKey), + ZERO_HASH, + ); + const proof4 = await smtKYC.generateCircomVerifierProof( + kycHash(Bob.pubKey), + ZERO_HASH, + ); const identitiesRoot = proof3.root.bigInt(); const startTime = Date.now(); @@ -114,19 +156,29 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, utxosRoot, - utxosMerkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + utxosMerkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], identitiesRoot, - identitiesMerkleProof: [proof3.siblings.map((s) => s.bigInt()), proof4.siblings.map((s) => s.bigInt()), proof3.siblings.map((s) => s.bigInt())], + identitiesMerkleProof: [ + proof3.siblings.map((s) => s.bigInt()), + proof4.siblings.map((s) => s.bigInt()), + proof3.siblings.map((s) => s.bigInt()), + ], outputCommitments, outputValues, outputSalts: [salt3, salt4], outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], }, - true + true, ); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness); + const { proof, publicSignals } = await groth16.prove( + provingKeyFile, + witness, + ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); const success = await groth16.verify(verificationKey, publicSignals, proof); diff --git a/zkp/js/integration-test/check_hashes_value.js b/zkp/js/integration-test/check_hashes_value.js index 59db750..d32cb4d 100644 --- a/zkp/js/integration-test/check_hashes_value.js +++ b/zkp/js/integration-test/check_hashes_value.js @@ -37,7 +37,11 @@ describe('check-hashes-value circuit tests', () => { // create the output UTXO const salt1 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt1, ...sender.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt1, + ...sender.pubKey, + ]); const outputCommitments = [output1]; let witness = await circuit.calculateWitness( @@ -47,7 +51,7 @@ describe('check-hashes-value circuit tests', () => { outputSalts: [salt1], outputOwnerPublicKeys: [sender.pubKey], }, - true + true, ); expect(witness[1]).to.equal(BigInt(200)); // index 1 is the output, for the calculated value @@ -59,11 +63,15 @@ describe('check-hashes-value circuit tests', () => { outputSalts: [salt1], outputOwnerPublicKeys: [sender.pubKey], }, - true + true, ); - const { provingKeyFile, verificationKey } = loadProvingKeys('check_hashes_value'); + const { provingKeyFile, verificationKey } = + loadProvingKeys('check_hashes_value'); const startTime = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness); + const { proof, publicSignals } = await groth16.prove( + provingKeyFile, + witness, + ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); const success = await groth16.verify(verificationKey, publicSignals, proof); expect(success, true); diff --git a/zkp/js/integration-test/check_inputs_outputs_value.js b/zkp/js/integration-test/check_inputs_outputs_value.js index 04746ca..c4db4d1 100644 --- a/zkp/js/integration-test/check_inputs_outputs_value.js +++ b/zkp/js/integration-test/check_inputs_outputs_value.js @@ -32,7 +32,9 @@ describe('check_inputs_outputs_value circuit tests', () => { before(async () => { circuit = await loadCircuit('check_inputs_outputs_value'); - ({ provingKeyFile, verificationKey } = loadProvingKeys('check_inputs_outputs_value')); + ({ provingKeyFile, verificationKey } = loadProvingKeys( + 'check_inputs_outputs_value', + )); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -51,14 +53,26 @@ describe('check_inputs_outputs_value circuit tests', () => { // create two input UTXOs, each has their own salt, but same owner const senderPrivateKey = formatPrivKeyForBabyJub(Alice.privKey); const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Alice.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Alice.pubKey, + ]); const outputCommitments = [output1]; const startTime = Date.now(); @@ -73,10 +87,13 @@ describe('check_inputs_outputs_value circuit tests', () => { outputSalts: [salt3], outputOwnerPublicKeys: [Alice.pubKey], }, - true + true, ); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness); + const { proof, publicSignals } = await groth16.prove( + provingKeyFile, + witness, + ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); const success = await groth16.verify(verificationKey, publicSignals, proof); diff --git a/zkp/js/integration-test/check_nullifier_value.js b/zkp/js/integration-test/check_nullifier_value.js index 7ed8d3a..3042e1c 100644 --- a/zkp/js/integration-test/check_nullifier_value.js +++ b/zkp/js/integration-test/check_nullifier_value.js @@ -17,7 +17,12 @@ const { expect } = require('chai'); const { groth16 } = require('snarkjs'); const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); const { Poseidon, newSalt, loadCircuit } = require('../index.js'); const { loadProvingKeys } = require('./utils.js'); @@ -33,7 +38,9 @@ describe('check_nullifier_value circuit tests', () => { before(async () => { circuit = await loadCircuit('check_nullifier_value'); - ({ provingKeyFile, verificationKey } = loadProvingKeys('check_nullifier_value')); + ({ provingKeyFile, verificationKey } = loadProvingKeys( + 'check_nullifier_value', + )); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -52,14 +59,30 @@ describe('check_nullifier_value circuit tests', () => { // create two input UTXOs, each has their own salt, but same owner const senderPrivateKey = formatPrivKeyForBabyJub(Alice.privKey); const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the input UTXOs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -67,12 +90,22 @@ describe('check_nullifier_value circuit tests', () => { await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH, + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Alice.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Alice.pubKey, + ]); const outputCommitments = [output1]; const startTime = Date.now(); @@ -84,17 +117,23 @@ describe('check_nullifier_value circuit tests', () => { inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], outputCommitments, outputValues, outputSalts: [salt3], outputOwnerPublicKeys: [Alice.pubKey], }, - true + true, ); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness); + const { proof, publicSignals } = await groth16.prove( + provingKeyFile, + witness, + ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); const success = await groth16.verify(verificationKey, publicSignals, proof); diff --git a/zkp/js/integration-test/check_nullifiers.js b/zkp/js/integration-test/check_nullifiers.js index d648689..93b7f34 100644 --- a/zkp/js/integration-test/check_nullifiers.js +++ b/zkp/js/integration-test/check_nullifiers.js @@ -48,14 +48,30 @@ describe('check-nullifiers circuit tests', () => { // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash4([BigInt(inputValues[0]), salt1, ...sender.pubKey]); + const input1 = poseidonHash4([ + BigInt(inputValues[0]), + salt1, + ...sender.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash4([BigInt(inputValues[1]), salt2, ...sender.pubKey]); + const input2 = poseidonHash4([ + BigInt(inputValues[1]), + salt2, + ...sender.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the input UTXOs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; const witness = await circuit.calculateWTNSBin( @@ -66,11 +82,14 @@ describe('check-nullifiers circuit tests', () => { inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, }, - true + true, ); const startTime = Date.now(); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness); + const { proof, publicSignals } = await groth16.prove( + provingKeyFile, + witness, + ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); const success = await groth16.verify(verificationKey, publicSignals, proof); expect(success, true); diff --git a/zkp/js/integration-test/nf_anon.js b/zkp/js/integration-test/nf_anon.js index 2fe7e36..f039326 100644 --- a/zkp/js/integration-test/nf_anon.js +++ b/zkp/js/integration-test/nf_anon.js @@ -16,7 +16,11 @@ const { expect } = require('chai'); const { groth16 } = require('snarkjs'); -const { genKeypair, formatPrivKeyForBabyJub, stringifyBigInts } = require('maci-crypto'); +const { + genKeypair, + formatPrivKeyForBabyJub, + stringifyBigInts, +} = require('maci-crypto'); const { Poseidon, newSalt, loadCircuit, tokenUriHash } = require('../index.js'); const { loadProvingKeys } = require('./utils.js'); @@ -47,12 +51,22 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(tokenIds[0]), tokenUris[0], salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(tokenIds[0]), + tokenUris[0], + salt1, + ...sender.pubKey, + ]); const inputCommitments = [input1]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(tokenIds[0]), tokenUris[0], salt3, ...receiver.pubKey]); + const output1 = poseidonHash([ + BigInt(tokenIds[0]), + tokenUris[0], + salt3, + ...receiver.pubKey, + ]); const outputCommitments = [output1]; const otherInputs = stringifyBigInts({ @@ -71,10 +85,13 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without outputOwnerPublicKeys: [receiver.pubKey], ...otherInputs, }, - true + true, ); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness); + const { proof, publicSignals } = await groth16.prove( + provingKeyFile, + witness, + ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); const success = await groth16.verify(verificationKey, publicSignals, proof); diff --git a/zkp/js/integration-test/nf_anon_nullifier.js b/zkp/js/integration-test/nf_anon_nullifier.js index 468afac..9fa7d77 100644 --- a/zkp/js/integration-test/nf_anon_nullifier.js +++ b/zkp/js/integration-test/nf_anon_nullifier.js @@ -17,7 +17,12 @@ const { expect } = require('chai'); const { groth16 } = require('snarkjs'); const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); const { Poseidon, newSalt, tokenUriHash, loadCircuit } = require('../index.js'); const { loadProvingKeys } = require('./utils.js'); @@ -34,7 +39,8 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n before(async () => { circuit = await loadCircuit('nf_anon_nullifier'); - ({ provingKeyFile, verificationKey } = loadProvingKeys('nf_anon_nullifier')); + ({ provingKeyFile, verificationKey } = + loadProvingKeys('nf_anon_nullifier')); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -60,20 +66,38 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(tokenId), tokenUri, salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(tokenId), + tokenUri, + salt1, + ...Alice.pubKey, + ]); // create the nullifiers for the inputs - const nullifier1 = poseidonHash4([BigInt(tokenId), tokenUri, salt1, senderPrivateKey]); + const nullifier1 = poseidonHash4([ + BigInt(tokenId), + tokenUri, + salt1, + senderPrivateKey, + ]); // calculate the root of the SMT await smtAlice.add(input1, input1); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(tokenId), tokenUri, salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(tokenId), + tokenUri, + salt3, + ...Bob.pubKey, + ]); const startTime = Date.now(); const witness = await circuit.calculateWTNSBin( @@ -90,10 +114,13 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n outputSalt: salt3, outputOwnerPublicKey: Bob.pubKey, }, - true + true, ); - const { proof, publicSignals } = await groth16.prove(provingKeyFile, witness); + const { proof, publicSignals } = await groth16.prove( + provingKeyFile, + witness, + ); console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); const success = await groth16.verify(verificationKey, publicSignals, proof); diff --git a/zkp/js/integration-test/utils.js b/zkp/js/integration-test/utils.js index 81c37f1..f66cd8c 100644 --- a/zkp/js/integration-test/utils.js +++ b/zkp/js/integration-test/utils.js @@ -14,13 +14,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -const path = require("path"); -const { readFileSync } = require("fs"); +const path = require('path'); +const { readFileSync } = require('fs'); function provingKeysRoot() { const PROVING_KEYS_ROOT = process.env.PROVING_KEYS_ROOT; if (!PROVING_KEYS_ROOT) { - throw new Error("PROVING_KEYS_ROOT env var is not set"); + throw new Error('PROVING_KEYS_ROOT env var is not set'); } return PROVING_KEYS_ROOT; } @@ -29,8 +29,8 @@ function loadProvingKeys(type) { const provingKeyFile = path.join(provingKeysRoot(), `${type}.zkey`); const verificationKey = JSON.parse( new TextDecoder().decode( - readFileSync(path.join(provingKeysRoot(), `${type}-vkey.json`)) - ) + readFileSync(path.join(provingKeysRoot(), `${type}-vkey.json`)), + ), ); return { provingKeyFile, diff --git a/zkp/js/lib/util.js b/zkp/js/lib/util.js index f89934d..ef62fe9 100644 --- a/zkp/js/lib/util.js +++ b/zkp/js/lib/util.js @@ -33,7 +33,9 @@ function newEncryptionNonce() { const two128 = BigInt('340282366920938463463374607431768211456'); // Field modulus for BN254 -const F = BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617'); +const F = BigInt( + '21888242871839275222246405745257275088548364400416034343698204186575808495617', +); // Implements the encryption and decryption functions using Poseidon hash // as described: https://drive.google.com/file/d/1EVrP3DzoGbmzkRmYnyEDcIQcXVU7GlOd/view @@ -109,10 +111,22 @@ function poseidonDecrypt(ciphertext, key, nonce, length) { // If length > 3, check if the last (3 - (l mod 3)) elements of the message are 0 if (length > 3) { if (length % 3 === 2) { - checkEqual(message[message.length - 1], 0n, 'The last element of the message must be 0'); + checkEqual( + message[message.length - 1], + 0n, + 'The last element of the message must be 0', + ); } else if (length % 3 === 1) { - checkEqual(message[message.length - 1], 0n, 'The last element of the message must be 0'); - checkEqual(message[message.length - 2], 0n, 'The second to last element of the message must be 0'); + checkEqual( + message[message.length - 1], + 0n, + 'The last element of the message must be 0', + ); + checkEqual( + message[message.length - 2], + 0n, + 'The second to last element of the message must be 0', + ); } } @@ -120,7 +134,11 @@ function poseidonDecrypt(ciphertext, key, nonce, length) { state = poseidon(state, 4); // Check the last ciphertext element - checkEqual(ciphertext[ciphertext.length - 1], state[1], 'The last ciphertext element must match the second item of the permuted state'); + checkEqual( + ciphertext[ciphertext.length - 1], + state[1], + 'The last ciphertext element must match the second item of the permuted state', + ); return message.slice(0, length); } diff --git a/zkp/js/package.json b/zkp/js/package.json index ebc5117..ac13d06 100644 --- a/zkp/js/package.json +++ b/zkp/js/package.json @@ -5,6 +5,9 @@ "license": "Apache-2.0", "main": "index.js", "scripts": { + "prettier": "npx prettier integration-test lib test --check", + "prettier:fix": "npm run prettier -- --write", + "pretest": "npm run prettier:fix", "test": "mocha --exit test/*.js test/lib/*.js", "test:e2e": "mocha --exit integration-test/*.js" }, @@ -19,6 +22,7 @@ "circom_tester": "^0.0.20", "circomlibjs": "^0.1.7", "mocha": "^10.2.0", + "prettier": "^3.3.3", "snarkjs": "^0.7.4" } } diff --git a/zkp/js/test/anon.js b/zkp/js/test/anon.js index 4e0925e..6af8070 100644 --- a/zkp/js/test/anon.js +++ b/zkp/js/test/anon.js @@ -17,7 +17,11 @@ const { expect } = require('chai'); const { join } = require('path'); const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, formatPrivKeyForBabyJub, stringifyBigInts } = require('maci-crypto'); +const { + genKeypair, + formatPrivKeyForBabyJub, + stringifyBigInts, +} = require('maci-crypto'); const { Poseidon, newSalt } = require('../index.js'); const poseidonHash = Poseidon.poseidon4; @@ -48,15 +52,31 @@ describe('main circuit tests for Zeto fungible tokens with anonymity without enc // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...sender.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...sender.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...sender.pubKey, + ]); const inputCommitments = [input1, input2]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...receiver.pubKey]); - const output2 = poseidonHash([BigInt(outputValues[1]), salt3, ...sender.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...receiver.pubKey, + ]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt3, + ...sender.pubKey, + ]); const outputCommitments = [output1, output2]; const otherInputs = stringifyBigInts({ @@ -74,7 +94,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity without enc outputOwnerPublicKeys: [receiver.pubKey, sender.pubKey], ...otherInputs, }, - true + true, ); // console.log('witness', witness.slice(0, 15)); @@ -95,15 +115,31 @@ describe('main circuit tests for Zeto fungible tokens with anonymity without enc const outputValues = [90, 35]; // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...sender.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...sender.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...sender.pubKey, + ]); const inputCommitments = [input1, input2]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...receiver.pubKey]); - const output2 = poseidonHash([BigInt(outputValues[1]), salt3, ...sender.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...receiver.pubKey, + ]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt3, + ...sender.pubKey, + ]); const outputCommitments = [output1, output2]; const otherInputs = stringifyBigInts({ @@ -123,7 +159,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity without enc outputOwnerPublicKeys: [receiver.pubKey, sender.pubKey], ...otherInputs, }, - true + true, ); } catch (e) { err = e; diff --git a/zkp/js/test/anon_enc.js b/zkp/js/test/anon_enc.js index 0f6c9c1..3411cc1 100644 --- a/zkp/js/test/anon_enc.js +++ b/zkp/js/test/anon_enc.js @@ -43,7 +43,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/anon_enc.circom') + join(__dirname, '../../circuits/anon_enc.circom'), ); let keypair = genKeypair(); @@ -108,7 +108,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp outputOwnerPublicKeys: [receiver.pubKey, sender.pubKey], ...encryptInputs, }, - true + true, ); // console.log('witness', witness.slice(0, 15)); @@ -130,13 +130,13 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp const cipherText = witness.slice(1, 8); const recoveredKey = genEcdhSharedKey( receiver.privKey, - ephemeralKeypair.pubKey + ephemeralKeypair.pubKey, ); const plainText = poseidonDecrypt( cipherText, recoveredKey, encryptionNonce, - 4 + 4, ); // use the recovered value (plainText[0]) and salt (plainText[1]) to verify the output commitment const calculatedHash = poseidonHash([ @@ -200,7 +200,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp outputOwnerPublicKeys: [receiver.pubKey, sender.pubKey], ...encryptInputs, }, - true + true, ); } catch (e) { err = e; @@ -262,7 +262,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp outputOwnerPublicKeys: [receiver.pubKey, sender.pubKey], ...encryptInputs, }, - true + true, ); // take the output from the proof circuit and attempt to decrypt @@ -274,7 +274,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp expect(function () { poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); }).to.throw( - 'The last ciphertext element must match the second item of the permuted state' + 'The last ciphertext element must match the second item of the permuted state', ); }); }); diff --git a/zkp/js/test/anon_enc_nullifier.js b/zkp/js/test/anon_enc_nullifier.js index 3e71f07..42a4179 100644 --- a/zkp/js/test/anon_enc_nullifier.js +++ b/zkp/js/test/anon_enc_nullifier.js @@ -52,7 +52,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/anon_enc_nullifier.circom') + join(__dirname, '../../circuits/anon_enc_nullifier.circom'), ); let keypair = genKeypair(); @@ -112,11 +112,11 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH + ZERO_HASH, ); const proof2 = await smtAlice.generateCircomVerifierProof( input2, - ZERO_HASH + ZERO_HASH, ); // create two output UTXOs, they share the same salt, and different owner @@ -160,7 +160,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], ...encryptInputs, }, - true + true, ); // console.log('witness', witness.slice(0, 15)); @@ -187,7 +187,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym cipherText, recoveredKey, encryptionNonce, - 4 + 4, ); expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); }); @@ -219,7 +219,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH + ZERO_HASH, ); const proof2 = await smtAlice.generateCircomVerifierProof(0, ZERO_HASH); @@ -264,7 +264,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], ...encryptInputs, }, - true + true, ); // console.log('witness', witness); @@ -291,7 +291,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym cipherText, recoveredKey, encryptionNonce, - 4 + 4, ); expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); }); @@ -335,11 +335,11 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH + ZERO_HASH, ); const proof2 = await smtAlice.generateCircomVerifierProof( input2, - ZERO_HASH + ZERO_HASH, ); // create two output UTXOs, they share the same salt, and different owner @@ -384,7 +384,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], ...encryptInputs, }, - true + true, ); } catch (e) { err = e; diff --git a/zkp/js/test/anon_enc_nullifier_kyc.js b/zkp/js/test/anon_enc_nullifier_kyc.js index 9f86de7..21a4d31 100644 --- a/zkp/js/test/anon_enc_nullifier_kyc.js +++ b/zkp/js/test/anon_enc_nullifier_kyc.js @@ -54,7 +54,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/anon_enc_nullifier_kyc.circom') + join(__dirname, '../../circuits/anon_enc_nullifier_kyc.circom'), ); let keypair = genKeypair(); @@ -126,11 +126,11 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH + ZERO_HASH, ); const proof2 = await smtAlice.generateCircomVerifierProof( input2, - ZERO_HASH + ZERO_HASH, ); const utxosRoot = proof1.root.bigInt(); @@ -159,11 +159,11 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // generate the merkle proof for the transacting identities const proof3 = await smtKYC.generateCircomVerifierProof( poseidonHash2(Alice.pubKey), - ZERO_HASH + ZERO_HASH, ); const proof4 = await smtKYC.generateCircomVerifierProof( poseidonHash2(Bob.pubKey), - ZERO_HASH + ZERO_HASH, ); const identitiesRoot = proof3.root.bigInt(); @@ -192,7 +192,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], ...encryptInputs, }, - true + true, ); // console.log('witness', witness.slice(0, 25)); @@ -221,7 +221,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym cipherText, recoveredKey, encryptionNonce, - 4 + 4, ); expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); }); @@ -265,11 +265,11 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH + ZERO_HASH, ); const proof2 = await smtAlice.generateCircomVerifierProof( input2, - ZERO_HASH + ZERO_HASH, ); const utxosRoot = proof1.root.bigInt(); @@ -290,11 +290,11 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym // generate the merkle proof for the transacting identities const proof3 = await smtKYC.generateCircomVerifierProof( poseidonHash2(Alice.pubKey), - ZERO_HASH + ZERO_HASH, ); const proof4 = await smtKYC.generateCircomVerifierProof( poseidonHash2(Bob.pubKey), - ZERO_HASH + ZERO_HASH, ); const identitiesRoot = proof3.root.bigInt(); @@ -332,7 +332,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], ...encryptInputs, }, - true + true, ); } catch (e) { err = e; diff --git a/zkp/js/test/anon_enc_nullifier_non_repudiation.js b/zkp/js/test/anon_enc_nullifier_non_repudiation.js index 2257fbc..b9daf3d 100644 --- a/zkp/js/test/anon_enc_nullifier_non_repudiation.js +++ b/zkp/js/test/anon_enc_nullifier_non_repudiation.js @@ -55,8 +55,8 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re circuit = await wasm_tester( join( __dirname, - '../../circuits/anon_enc_nullifier_non_repudiation.circom' - ) + '../../circuits/anon_enc_nullifier_non_repudiation.circom', + ), ); let keypair = genKeypair(); @@ -120,11 +120,11 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH + ZERO_HASH, ); const proof2 = await smtAlice.generateCircomVerifierProof( input2, - ZERO_HASH + ZERO_HASH, ); // create two output UTXOs, they share the same salt, and different owner @@ -169,7 +169,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re authorityPublicKey: Regulator.pubKey, ...encryptInputs, }, - true + true, ); // console.log('witness', witness.slice(0, 25)); @@ -196,7 +196,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re cipherText, recoveredKey, encryptionNonce, - 4 + 4, ); expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); @@ -204,14 +204,14 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // as the regulator const recoveredKey2 = genEcdhSharedKey( Regulator.privKey, - ephemeralKeypair.pubKey + ephemeralKeypair.pubKey, ); const cipherText2 = witness.slice(10, 26); // next 16 elements are the cipher text for the second encryption output const plainText2 = poseidonDecrypt( cipherText2, recoveredKey2, encryptionNonce, - 14 + 14, ); expect(plainText2).to.deep.equal([ Alice.pubKey[0], // input owner public key @@ -258,7 +258,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH + ZERO_HASH, ); const proof2 = await smtAlice.generateCircomVerifierProof(0, ZERO_HASH); @@ -304,7 +304,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re authorityPublicKey: Regulator.pubKey, ...encryptInputs, }, - true + true, ); // console.log('witness', witness); @@ -331,7 +331,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re cipherText, recoveredKey, encryptionNonce, - 4 + 4, ); expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); @@ -339,14 +339,14 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // as the regulator const recoveredKey2 = genEcdhSharedKey( Regulator.privKey, - ephemeralKeypair.pubKey + ephemeralKeypair.pubKey, ); const cipherText2 = witness.slice(10, 26); // next 16 elements are the cipher text for the second encryption output const plainText2 = poseidonDecrypt( cipherText2, recoveredKey2, encryptionNonce, - 14 + 14, ); expect(plainText2).to.deep.equal([ Alice.pubKey[0], @@ -405,11 +405,11 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH + ZERO_HASH, ); const proof2 = await smtAlice.generateCircomVerifierProof( input2, - ZERO_HASH + ZERO_HASH, ); // create two output UTXOs, they share the same salt, and different owner @@ -455,7 +455,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re authorityPublicKey: Regulator.pubKey, ...encryptInputs, }, - true + true, ); } catch (e) { err = e; diff --git a/zkp/js/test/anon_nullifier.js b/zkp/js/test/anon_nullifier.js index 84fae95..deec1c7 100644 --- a/zkp/js/test/anon_nullifier.js +++ b/zkp/js/test/anon_nullifier.js @@ -18,7 +18,12 @@ const { expect } = require('chai'); const { join } = require('path'); const { wasm: wasm_tester } = require('circom_tester'); const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); const { Poseidon, newSalt } = require('../index.js'); const SMT_HEIGHT = 64; @@ -35,7 +40,9 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../../circuits/anon_nullifier.circom')); + circuit = await wasm_tester( + join(__dirname, '../../circuits/anon_nullifier.circom'), + ); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -61,14 +68,30 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the inputs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -76,14 +99,28 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH, + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); const salt4 = newSalt(); - const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...Alice.pubKey]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt4, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; const witness = await circuit.calculateWitness( @@ -94,14 +131,17 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], outputCommitments, outputValues, outputSalts: [salt3, salt4], outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], }, - true + true, ); // console.log('witness', witness.slice(0, 10)); @@ -126,25 +166,44 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const inputCommitments = [input1, 0]; // create the nullifiers for the inputs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); const nullifiers = [nullifier1, 0]; // calculate the root of the SMT await smtAlice.add(input1, input1); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); const proof2 = await smtAlice.generateCircomVerifierProof(0, ZERO_HASH); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); const salt4 = newSalt(); - const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...Alice.pubKey]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt4, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; const witness = await circuit.calculateWitness( @@ -155,14 +214,17 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli inputSalts: [salt1, 0], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 0], outputCommitments, outputValues, outputSalts: [salt3, salt4], outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], }, - true + true, ); expect(witness[1]).to.equal(BigInt(nullifiers[0])); @@ -176,14 +238,30 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the input UTXOs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -191,13 +269,27 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH, + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); - const output2 = poseidonHash([BigInt(outputValues[1]), salt3, ...Alice.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt3, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; let err; @@ -210,14 +302,17 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], outputCommitments, outputValues, outputSalts: [salt3, salt3], outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], }, - true + true, ); } catch (e) { err = e; diff --git a/zkp/js/test/anon_nullifier_kyc.js b/zkp/js/test/anon_nullifier_kyc.js index f5b7143..94d67ba 100644 --- a/zkp/js/test/anon_nullifier_kyc.js +++ b/zkp/js/test/anon_nullifier_kyc.js @@ -18,7 +18,12 @@ const { expect } = require('chai'); const { join } = require('path'); const { wasm: wasm_tester } = require('circom_tester'); const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); const { Poseidon, newSalt, kycHash } = require('../index.js'); const SMT_HEIGHT_UTXO = 64; @@ -37,7 +42,9 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../../circuits/anon_nullifier_kyc.circom')); + circuit = await wasm_tester( + join(__dirname, '../../circuits/anon_nullifier_kyc.circom'), + ); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -75,14 +82,30 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the inputs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -90,20 +113,40 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH, + ); const utxosRoot = proof1.root.bigInt(); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); const salt4 = newSalt(); - const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...Alice.pubKey]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt4, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; // generate the merkle proof for the transacting identities - const proof3 = await smtKYC.generateCircomVerifierProof(poseidonHash2(Alice.pubKey), ZERO_HASH); - const proof4 = await smtKYC.generateCircomVerifierProof(poseidonHash2(Bob.pubKey), ZERO_HASH); + const proof3 = await smtKYC.generateCircomVerifierProof( + poseidonHash2(Alice.pubKey), + ZERO_HASH, + ); + const proof4 = await smtKYC.generateCircomVerifierProof( + poseidonHash2(Bob.pubKey), + ZERO_HASH, + ); const identitiesRoot = proof3.root.bigInt(); const witness = await circuit.calculateWitness( @@ -114,16 +157,23 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, utxosRoot, - utxosMerkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + utxosMerkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], identitiesRoot, - identitiesMerkleProof: [proof3.siblings.map((s) => s.bigInt()), proof4.siblings.map((s) => s.bigInt()), proof3.siblings.map((s) => s.bigInt())], + identitiesMerkleProof: [ + proof3.siblings.map((s) => s.bigInt()), + proof4.siblings.map((s) => s.bigInt()), + proof3.siblings.map((s) => s.bigInt()), + ], outputCommitments, outputValues, outputSalts: [salt3, salt4], outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], }, - true + true, ); // console.log('witness', witness.slice(0, 20)); @@ -150,14 +200,30 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the inputs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -165,20 +231,40 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH, + ); const utxosRoot = proof1.root.bigInt(); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Bob.pubKey, + ]); const salt4 = newSalt(); - const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...Alice.pubKey]); + const output2 = poseidonHash([ + BigInt(outputValues[1]), + salt4, + ...Alice.pubKey, + ]); const outputCommitments = [output1, output2]; // generate the merkle proof for the transacting identities - const proof3 = await smtKYC.generateCircomVerifierProof(poseidonHash2(Alice.pubKey), ZERO_HASH); - const proof4 = await smtKYC.generateCircomVerifierProof(poseidonHash2(Bob.pubKey), ZERO_HASH); + const proof3 = await smtKYC.generateCircomVerifierProof( + poseidonHash2(Alice.pubKey), + ZERO_HASH, + ); + const proof4 = await smtKYC.generateCircomVerifierProof( + poseidonHash2(Bob.pubKey), + ZERO_HASH, + ); const identitiesRoot = proof3.root.bigInt(); let error; @@ -191,7 +277,10 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, utxosRoot, - utxosMerkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + utxosMerkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], identitiesRoot, identitiesMerkleProof: [ @@ -204,7 +293,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using outputSalts: [salt3, salt4], outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey], }, - true + true, ); } catch (e) { error = e; diff --git a/zkp/js/test/check_hashes_value.js b/zkp/js/test/check_hashes_value.js index 8f3e684..ea1590f 100644 --- a/zkp/js/test/check_hashes_value.js +++ b/zkp/js/test/check_hashes_value.js @@ -30,7 +30,9 @@ describe('check_hashes_value circuit tests', () => { before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../../circuits/check_hashes_value.circom')); + circuit = await wasm_tester( + join(__dirname, '../../circuits/check_hashes_value.circom'), + ); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -42,7 +44,11 @@ describe('check_hashes_value circuit tests', () => { // create the output UTXO const salt1 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt1, ...sender.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt1, + ...sender.pubKey, + ]); const outputCommitments = [output1]; let witness = await circuit.calculateWitness( @@ -52,7 +58,7 @@ describe('check_hashes_value circuit tests', () => { outputSalts: [salt1], outputOwnerPublicKeys: [sender.pubKey], }, - true + true, ); expect(witness[1]).to.equal(BigInt(200)); // index 1 is the output, for the calculated value @@ -64,7 +70,7 @@ describe('check_hashes_value circuit tests', () => { outputSalts: [salt1], outputOwnerPublicKeys: [sender.pubKey], }, - true + true, ); }); @@ -73,7 +79,11 @@ describe('check_hashes_value circuit tests', () => { // create the output UTXO const salt1 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0] + 100), salt1, ...sender.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0] + 100), + salt1, + ...sender.pubKey, + ]); const outputCommitments = [output1]; let error; @@ -85,7 +95,7 @@ describe('check_hashes_value circuit tests', () => { outputSalts: [salt1], outputOwnerPublicKeys: [sender.pubKey], }, - true + true, ); } catch (e) { error = e; @@ -101,7 +111,11 @@ describe('check_hashes_value circuit tests', () => { // create the output UTXO const salt1 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt1, ...sender.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt1, + ...sender.pubKey, + ]); const outputCommitments = [output1]; let error; @@ -113,7 +127,7 @@ describe('check_hashes_value circuit tests', () => { outputSalts: [salt1], outputOwnerPublicKeys: [sender.pubKey], }, - true + true, ); } catch (e) { error = e; @@ -126,11 +140,17 @@ describe('check_hashes_value circuit tests', () => { // in the finite field used in the Poseidion hash implementation, -100n is equivalent to // 21888242871839275222246405745257275088548364400416034343698204186575808495517n. This number // is considered negative by the circuit, because we allow the range of 0 to (2**40 - 1) - const outputValues = [21888242871839275222246405745257275088548364400416034343698204186575808495518n]; + const outputValues = [ + 21888242871839275222246405745257275088548364400416034343698204186575808495518n, + ]; // create the output UTXO const salt1 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt1, ...sender.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt1, + ...sender.pubKey, + ]); const outputCommitments = [output1]; let error; @@ -142,7 +162,7 @@ describe('check_hashes_value circuit tests', () => { outputSalts: [salt1], outputOwnerPublicKeys: [sender.pubKey], }, - true + true, ); } catch (e) { error = e; @@ -156,7 +176,11 @@ describe('check_hashes_value circuit tests', () => { // create the output UTXO const salt1 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt1, ...sender.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt1, + ...sender.pubKey, + ]); const outputCommitments = [output1]; let error; @@ -168,7 +192,7 @@ describe('check_hashes_value circuit tests', () => { outputSalts: [salt1], outputOwnerPublicKeys: [sender.pubKey], }, - true + true, ); } catch (e) { error = e; diff --git a/zkp/js/test/check_inputs_outputs_value.js b/zkp/js/test/check_inputs_outputs_value.js index ecf012e..efd226e 100644 --- a/zkp/js/test/check_inputs_outputs_value.js +++ b/zkp/js/test/check_inputs_outputs_value.js @@ -33,7 +33,9 @@ describe('check_inputs_outputs_value circuit tests', () => { before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../../circuits/check_inputs_outputs_value.circom')); + circuit = await wasm_tester( + join(__dirname, '../../circuits/check_inputs_outputs_value.circom'), + ); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -51,14 +53,26 @@ describe('check_inputs_outputs_value circuit tests', () => { // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create output UTXOs const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Alice.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Alice.pubKey, + ]); const outputCommitments = [output1]; const witness = await circuit.calculateWitness( @@ -72,7 +86,7 @@ describe('check_inputs_outputs_value circuit tests', () => { outputSalts: [salt3], outputOwnerPublicKeys: [Alice.pubKey], }, - true + true, ); // console.log('witness', witness.slice(0, 10)); @@ -97,12 +111,20 @@ describe('check_inputs_outputs_value circuit tests', () => { // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const inputCommitments = [input1, 0]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Alice.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Alice.pubKey, + ]); const outputCommitments = [output1]; const witness = await circuit.calculateWitness( @@ -116,7 +138,7 @@ describe('check_inputs_outputs_value circuit tests', () => { outputSalts: [salt3], outputOwnerPublicKeys: [Alice.pubKey], }, - true + true, ); expect(witness[1]).to.equal(BigInt(62)); diff --git a/zkp/js/test/check_nullifier_value.js b/zkp/js/test/check_nullifier_value.js index ff22446..934a891 100644 --- a/zkp/js/test/check_nullifier_value.js +++ b/zkp/js/test/check_nullifier_value.js @@ -18,7 +18,12 @@ const { expect } = require('chai'); const { join } = require('path'); const { wasm: wasm_tester } = require('circom_tester'); const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); const { Poseidon, newSalt } = require('../index.js'); const SMT_HEIGHT = 64; @@ -34,7 +39,9 @@ describe('check_nullifier_value circuit tests', () => { before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../../circuits/check_nullifier_value.circom')); + circuit = await wasm_tester( + join(__dirname, '../../circuits/check_nullifier_value.circom'), + ); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -52,14 +59,30 @@ describe('check_nullifier_value circuit tests', () => { // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...Alice.pubKey, + ]); const inputCommitments = [input1, input2]; // create the nullifiers for the inputs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; // calculate the root of the SMT @@ -67,12 +90,22 @@ describe('check_nullifier_value circuit tests', () => { await smtAlice.add(input2, input2); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); - const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); + const proof2 = await smtAlice.generateCircomVerifierProof( + input2, + ZERO_HASH, + ); // create output UTXOs const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Alice.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Alice.pubKey, + ]); const outputCommitments = [output1]; const witness = await circuit.calculateWitness( @@ -83,14 +116,17 @@ describe('check_nullifier_value circuit tests', () => { inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 1], outputCommitments, outputValues, outputSalts: [salt3], outputOwnerPublicKeys: [Alice.pubKey], }, - true + true, ); // console.log('witness', witness.slice(0, 10)); @@ -116,23 +152,38 @@ describe('check_nullifier_value circuit tests', () => { // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...Alice.pubKey, + ]); const inputCommitments = [input1, 0]; // create the nullifiers for the inputs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); const nullifiers = [nullifier1, 0]; // calculate the root of the SMT await smtAlice.add(input1, input1); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); const proof2 = await smtAlice.generateCircomVerifierProof(0, ZERO_HASH); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Alice.pubKey]); + const output1 = poseidonHash([ + BigInt(outputValues[0]), + salt3, + ...Alice.pubKey, + ]); const outputCommitments = [output1]; const witness = await circuit.calculateWitness( @@ -143,14 +194,17 @@ describe('check_nullifier_value circuit tests', () => { inputSalts: [salt1, 0], inputOwnerPrivateKey: senderPrivateKey, root: proof1.root.bigInt(), - merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())], + merkleProof: [ + proof1.siblings.map((s) => s.bigInt()), + proof2.siblings.map((s) => s.bigInt()), + ], enabled: [1, 0], outputCommitments, outputValues, outputSalts: [salt3], outputOwnerPublicKeys: [Alice.pubKey], }, - true + true, ); expect(witness[1]).to.equal(BigInt(62)); diff --git a/zkp/js/test/check_nullifiers.js b/zkp/js/test/check_nullifiers.js index 97913c8..7fdb3f3 100644 --- a/zkp/js/test/check_nullifiers.js +++ b/zkp/js/test/check_nullifiers.js @@ -32,7 +32,9 @@ describe('check_nullifiers circuit tests', () => { before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../../circuits/check_nullifiers.circom')); + circuit = await wasm_tester( + join(__dirname, '../../circuits/check_nullifiers.circom'), + ); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -49,14 +51,30 @@ describe('check_nullifiers circuit tests', () => { // create two input UTXOs const salt1 = newSalt(); - const input1 = poseidonHash4([BigInt(inputValues[0]), salt1, ...sender.pubKey]); + const input1 = poseidonHash4([ + BigInt(inputValues[0]), + salt1, + ...sender.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash4([BigInt(inputValues[1]), salt2, ...sender.pubKey]); + const input2 = poseidonHash4([ + BigInt(inputValues[1]), + salt2, + ...sender.pubKey, + ]); const inputCommitments = [input1, input2]; // create two input nullifiers, corresponding to the input UTXOs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; const witness = await circuit.calculateWitness( @@ -67,7 +85,7 @@ describe('check_nullifiers circuit tests', () => { inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, }, - true + true, ); // console.log('nullifiers', nullifiers); @@ -90,14 +108,30 @@ describe('check_nullifiers circuit tests', () => { // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash4([BigInt(inputValues[0]), salt1, ...sender.pubKey]); + const input1 = poseidonHash4([ + BigInt(inputValues[0]), + salt1, + ...sender.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash4([BigInt(inputValues[1]), salt2, ...sender.pubKey]); + const input2 = poseidonHash4([ + BigInt(inputValues[1]), + salt2, + ...sender.pubKey, + ]); const inputCommitments = [input1, input2]; // create two input nullifiers, corresponding to the input UTXOs - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); - const nullifier2 = poseidonHash3([BigInt(inputValues[1] + 1), salt2, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); + const nullifier2 = poseidonHash3([ + BigInt(inputValues[1] + 1), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; let err; @@ -110,7 +144,7 @@ describe('check_nullifiers circuit tests', () => { inputSalts: [salt1, salt2], inputOwnerPrivateKey: senderPrivateKey, }, - true + true, ); } catch (e) { err = e; diff --git a/zkp/js/test/lib/check-hashes-tokenid-uri.js b/zkp/js/test/lib/check-hashes-tokenid-uri.js index 155596f..c10f29f 100644 --- a/zkp/js/test/lib/check-hashes-tokenid-uri.js +++ b/zkp/js/test/lib/check-hashes-tokenid-uri.js @@ -31,7 +31,9 @@ describe('check-hashes-tokenid-uri circuit tests', () => { before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../circuits/check-hashes-tokenid-uri.circom')); + circuit = await wasm_tester( + join(__dirname, '../circuits/check-hashes-tokenid-uri.circom'), + ); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -48,7 +50,12 @@ describe('check-hashes-tokenid-uri circuit tests', () => { // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(tokenIds[0]), tokenUris[0], salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(tokenIds[0]), + tokenUris[0], + salt1, + ...sender.pubKey, + ]); const commitments = [input1]; const witness = await circuit.calculateWitness( @@ -59,7 +66,7 @@ describe('check-hashes-tokenid-uri circuit tests', () => { salts: [salt1], ownerPublicKeys: [sender.pubKey], }, - true + true, ); // console.log(witness.slice(0, 20)); @@ -86,7 +93,12 @@ describe('check-hashes-tokenid-uri circuit tests', () => { // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(tokenIds[0]), tokenUris, salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(tokenIds[0]), + tokenUris, + salt1, + ...sender.pubKey, + ]); const commitments = [input1 + BigInt(1)]; let error; @@ -99,12 +111,14 @@ describe('check-hashes-tokenid-uri circuit tests', () => { salts: [salt1], ownerPublicKeys: [sender.pubKey], }, - true + true, ); } catch (e) { error = e; } // console.log(error); - expect(error).to.match(/Error in template CheckHashesForTokenIdAndUri_74 line: 58/); + expect(error).to.match( + /Error in template CheckHashesForTokenIdAndUri_74 line: 58/, + ); }); }); diff --git a/zkp/js/test/lib/check-hashes.js b/zkp/js/test/lib/check-hashes.js index 36d94df..ce5da0e 100644 --- a/zkp/js/test/lib/check-hashes.js +++ b/zkp/js/test/lib/check-hashes.js @@ -33,7 +33,9 @@ describe('check-hashes circuit tests', () => { before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../circuits/check-hashes.circom')); + circuit = await wasm_tester( + join(__dirname, '../circuits/check-hashes.circom'), + ); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -61,7 +63,7 @@ describe('check-hashes circuit tests', () => { salts: [salt1, salt2], ownerPublicKeys: [sender.pubKey, sender.pubKey], }, - true + true, ); // console.log(witness.slice(0, 10)); @@ -88,7 +90,7 @@ describe('check-hashes circuit tests', () => { salts: [salt1, 0], ownerPublicKeys: [sender.pubKey, [0n, 0n]], }, - true + true, ); expect(witness[1]).to.equal(BigInt(commitments[0])); @@ -112,7 +114,7 @@ describe('check-hashes circuit tests', () => { salts: [0, salt1], ownerPublicKeys: [[0n, 0n], sender.pubKey], }, - true + true, ); expect(witness[1]).to.equal(BigInt(commitments[0])); @@ -128,9 +130,17 @@ describe('check-hashes circuit tests', () => { // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(inputValues[0]), + salt1, + ...sender.pubKey, + ]); const salt2 = newSalt(); - const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...sender.pubKey]); + const input2 = poseidonHash([ + BigInt(inputValues[1]), + salt2, + ...sender.pubKey, + ]); const inputCommitments = [input1 + BigInt(1), input2]; let error; @@ -142,7 +152,7 @@ describe('check-hashes circuit tests', () => { salts: [salt1, salt2], ownerPublicKeys: [sender.pubKey, sender.pubKey], }, - true + true, ); } catch (e) { error = e; diff --git a/zkp/js/test/lib/check-nullifier-tokenid-uri.js b/zkp/js/test/lib/check-nullifier-tokenid-uri.js index 702802d..e96fde2 100644 --- a/zkp/js/test/lib/check-nullifier-tokenid-uri.js +++ b/zkp/js/test/lib/check-nullifier-tokenid-uri.js @@ -19,7 +19,12 @@ const { join } = require('path'); const { wasm: wasm_tester } = require('circom_tester'); const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); const { Poseidon, newSalt, tokenUriHash } = require('../../index.js'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon5; @@ -34,7 +39,9 @@ describe('check-nullifier-tokenid-uri circuit tests', () => { before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../circuits/check-nullifier-tokenid-uri.circom')); + circuit = await wasm_tester( + join(__dirname, '../circuits/check-nullifier-tokenid-uri.circom'), + ); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -54,7 +61,12 @@ describe('check-nullifier-tokenid-uri circuit tests', () => { const tokenUri = tokenUriHash('http://ipfs.io/some-file-hash'); const salt1 = newSalt(); - const nullifier1 = poseidonHash4([BigInt(tokenId), tokenUri, salt1, senderPrivateKey]); + const nullifier1 = poseidonHash4([ + BigInt(tokenId), + tokenUri, + salt1, + senderPrivateKey, + ]); const witness = await circuit.calculateWitness( { @@ -64,7 +76,7 @@ describe('check-nullifier-tokenid-uri circuit tests', () => { salts: [salt1], ownerPrivateKey: senderPrivateKey, }, - true + true, ); // console.log('tokenUri', tokenUri); @@ -83,7 +95,12 @@ describe('check-nullifier-tokenid-uri circuit tests', () => { const tokenUri = tokenUriHash('http://ipfs.io/some-file-hash'); const salt1 = newSalt(); - const nullifier1 = poseidonHash4([BigInt(tokenId), tokenUri, salt1, senderPrivateKey]); + const nullifier1 = poseidonHash4([ + BigInt(tokenId), + tokenUri, + salt1, + senderPrivateKey, + ]); let error; try { @@ -95,12 +112,14 @@ describe('check-nullifier-tokenid-uri circuit tests', () => { salts: [salt1], ownerPrivateKey: senderPrivateKey, }, - true + true, ); } catch (e) { error = e; } // console.log(error); - expect(error).to.match(/Error in template CheckNullifierForTokenIdAndUri_74 line: 58/); + expect(error).to.match( + /Error in template CheckNullifierForTokenIdAndUri_74 line: 58/, + ); }); }); diff --git a/zkp/js/test/lib/check-nullifiers.js b/zkp/js/test/lib/check-nullifiers.js index b348e91..cb2efdf 100644 --- a/zkp/js/test/lib/check-nullifiers.js +++ b/zkp/js/test/lib/check-nullifiers.js @@ -30,7 +30,9 @@ describe('check-nullifiers circuit tests', () => { before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../circuits/check-nullifiers.circom')); + circuit = await wasm_tester( + join(__dirname, '../circuits/check-nullifiers.circom'), + ); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -43,9 +45,17 @@ describe('check-nullifiers circuit tests', () => { // create two input nullifiers, corresponding to the input UTXOs const salt1 = newSalt(); - const nullifier1 = poseidonHash3([BigInt(values[0]), salt1, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(values[0]), + salt1, + senderPrivateKey, + ]); const salt2 = newSalt(); - const nullifier2 = poseidonHash3([BigInt(values[1]), salt2, senderPrivateKey]); + const nullifier2 = poseidonHash3([ + BigInt(values[1]), + salt2, + senderPrivateKey, + ]); const nullifiers = [nullifier1, nullifier2]; const witness = await circuit.calculateWitness( @@ -55,7 +65,7 @@ describe('check-nullifiers circuit tests', () => { salts: [salt1, salt2], ownerPrivateKey: senderPrivateKey, }, - true + true, ); // console.log(witness.slice(0, 10)); @@ -75,7 +85,11 @@ describe('check-nullifiers circuit tests', () => { // create two input nullifiers, corresponding to the input UTXOs const salt1 = newSalt(); - const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]); + const nullifier1 = poseidonHash3([ + BigInt(inputValues[0]), + salt1, + senderPrivateKey, + ]); const nullifiers = [nullifier1, 0]; const witness = await circuit.calculateWitness( @@ -85,7 +99,7 @@ describe('check-nullifiers circuit tests', () => { salts: [salt1, 0], ownerPrivateKey: senderPrivateKey, }, - true + true, ); expect(witness[1]).to.equal(BigInt(nullifiers[0])); diff --git a/zkp/js/test/lib/check-positive.js b/zkp/js/test/lib/check-positive.js index c45b61c..9e4de9a 100644 --- a/zkp/js/test/lib/check-positive.js +++ b/zkp/js/test/lib/check-positive.js @@ -26,7 +26,9 @@ describe('check-positive circuit tests', () => { before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../circuits/check-positive.circom')); + circuit = await wasm_tester( + join(__dirname, '../circuits/check-positive.circom'), + ); }); it('should succeed to generate a witness using the MAX_VALUE for output', async () => { @@ -38,7 +40,7 @@ describe('check-positive circuit tests', () => { { outputValues, }, - true + true, ); } catch (e) { error = e; @@ -58,7 +60,7 @@ describe('check-positive circuit tests', () => { { outputValues, }, - true + true, ); } catch (e) { error = e; @@ -71,7 +73,10 @@ describe('check-positive circuit tests', () => { // in the finite field used in the Poseidion hash implementation, -100n is equivalent to // 21888242871839275222246405745257275088548364400416034343698204186575808495517n. This number // is considered negative by the circuit, because we allow the range of 0 to (2**40 - 1) - const outputValues = [21888242871839275222246405745257275088548364400416034343698204186575808495518n, 225]; + const outputValues = [ + 21888242871839275222246405745257275088548364400416034343698204186575808495518n, + 225, + ]; let error; try { @@ -79,7 +84,7 @@ describe('check-positive circuit tests', () => { { outputValues, }, - true + true, ); } catch (e) { error = e; @@ -97,7 +102,7 @@ describe('check-positive circuit tests', () => { { outputValues, }, - true + true, ); } catch (e) { error = e; diff --git a/zkp/js/test/lib/check-smt-proof.js b/zkp/js/test/lib/check-smt-proof.js index e66443d..f2e05e7 100644 --- a/zkp/js/test/lib/check-smt-proof.js +++ b/zkp/js/test/lib/check-smt-proof.js @@ -19,7 +19,12 @@ const { join } = require('path'); const { wasm: wasm_tester } = require('circom_tester'); const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); const { Poseidon, newSalt, tokenUriHash } = require('../../index.js'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon5; @@ -34,7 +39,9 @@ describe('check-smt-proof circuit tests', () => { before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../circuits/check-smt-proof.circom')); + circuit = await wasm_tester( + join(__dirname, '../circuits/check-smt-proof.circom'), + ); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -55,7 +62,12 @@ describe('check-smt-proof circuit tests', () => { // create two input UTXOs const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(tokenId), tokenUri, salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(tokenId), + tokenUri, + salt1, + ...sender.pubKey, + ]); // calculate the root of the SMT await smt.add(input1, input1); @@ -70,7 +82,7 @@ describe('check-smt-proof circuit tests', () => { merkleProof: [proof1.siblings.map((s) => s.bigInt())], enabled: [1], }, - true + true, ); // console.log('inputCommitment', input1); diff --git a/zkp/js/test/lib/check-sum.js b/zkp/js/test/lib/check-sum.js index ea4f1a9..b287b93 100644 --- a/zkp/js/test/lib/check-sum.js +++ b/zkp/js/test/lib/check-sum.js @@ -24,7 +24,9 @@ describe('check-sum circuit tests', () => { before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../circuits/check-sum.circom')); + circuit = await wasm_tester( + join(__dirname, '../circuits/check-sum.circom'), + ); }); it('should return true for valid witness', async () => { @@ -36,7 +38,7 @@ describe('check-sum circuit tests', () => { inputValues, outputValues, }, - true + true, ); // console.log(witness.slice(0, 5)); expect(witness[0]).to.equal(BigInt(1)); @@ -53,7 +55,7 @@ describe('check-sum circuit tests', () => { inputValues, outputValues, }, - true + true, ); } catch (e) { error = e; diff --git a/zkp/js/test/lib/ecdh.js b/zkp/js/test/lib/ecdh.js index 3688b29..07fd479 100644 --- a/zkp/js/test/lib/ecdh.js +++ b/zkp/js/test/lib/ecdh.js @@ -17,7 +17,12 @@ const { expect } = require('chai'); const { join } = require('path'); const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, genEcdhSharedKey, formatPrivKeyForBabyJub, stringifyBigInts } = require('maci-crypto'); +const { + genKeypair, + genEcdhSharedKey, + formatPrivKeyForBabyJub, + stringifyBigInts, +} = require('maci-crypto'); describe('Ecdh circuit tests', () => { let circuit; diff --git a/zkp/js/test/lib/encrypt.js b/zkp/js/test/lib/encrypt.js index daabc14..54339aa 100644 --- a/zkp/js/test/lib/encrypt.js +++ b/zkp/js/test/lib/encrypt.js @@ -18,7 +18,11 @@ const { expect } = require('chai'); const { join } = require('path'); const crypto = require('crypto'); const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, genEcdhSharedKey, stringifyBigInts } = require('maci-crypto'); +const { + genKeypair, + genEcdhSharedKey, + stringifyBigInts, +} = require('maci-crypto'); const { poseidonEncrypt, poseidonDecrypt } = require('../../lib/util.js'); describe('Encryption circuit tests', () => { @@ -43,7 +47,11 @@ describe('Encryption circuit tests', () => { const hex = crypto.randomBytes(16).toString('hex'); const nonce = BigInt(`0x${hex}`); - const result = await poseidonEncrypt([1234567890n, 2345678901n], key, nonce); + const result = await poseidonEncrypt( + [1234567890n, 2345678901n], + key, + nonce, + ); const recoveredKey = genEcdhSharedKey(receiverPrivKey, senderPubKey); const plainText = await poseidonDecrypt(result, recoveredKey, nonce, 2); @@ -55,11 +63,20 @@ describe('Encryption circuit tests', () => { const hex = crypto.randomBytes(16).toString('hex'); const nonce = BigInt(`0x${hex}`); - const result = await poseidonEncrypt([1234567890n, 2345678901n, 3456789012n, 4567890123n], key, nonce); + const result = await poseidonEncrypt( + [1234567890n, 2345678901n, 3456789012n, 4567890123n], + key, + nonce, + ); const recoveredKey = genEcdhSharedKey(receiverPrivKey, senderPubKey); const plainText = await poseidonDecrypt(result, recoveredKey, nonce, 4); - expect(plainText).to.deep.equal([1234567890n, 2345678901n, 3456789012n, 4567890123n]); + expect(plainText).to.deep.equal([ + 1234567890n, + 2345678901n, + 3456789012n, + 4567890123n, + ]); }); it('should generate the cipher text in the proof circuit, which can be decrypted by the receiver', async () => { diff --git a/zkp/js/test/lib/poseidon-ex.js b/zkp/js/test/lib/poseidon-ex.js index 5ff5e8b..bc32b9f 100644 --- a/zkp/js/test/lib/poseidon-ex.js +++ b/zkp/js/test/lib/poseidon-ex.js @@ -23,7 +23,9 @@ describe('PoseidonEx circuit tests', () => { let circuit; before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../circuits/poseidon-ex.circom')); + circuit = await wasm_tester( + join(__dirname, '../circuits/poseidon-ex.circom'), + ); }); it('should generate the states matching JS lib', async () => { diff --git a/zkp/js/test/nf_anon.js b/zkp/js/test/nf_anon.js index 150c217..3fb5922 100644 --- a/zkp/js/test/nf_anon.js +++ b/zkp/js/test/nf_anon.js @@ -17,7 +17,11 @@ const { expect } = require('chai'); const { join } = require('path'); const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, formatPrivKeyForBabyJub, stringifyBigInts } = require('maci-crypto'); +const { + genKeypair, + formatPrivKeyForBabyJub, + stringifyBigInts, +} = require('maci-crypto'); const { Poseidon, newSalt, tokenUriHash } = require('../index.js'); const poseidonHash = Poseidon.poseidon5; @@ -31,7 +35,9 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../../circuits/nf_anon.circom')); + circuit = await wasm_tester( + join(__dirname, '../../circuits/nf_anon.circom'), + ); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -48,12 +54,22 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(tokenIds[0]), tokenUris[0], salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(tokenIds[0]), + tokenUris[0], + salt1, + ...sender.pubKey, + ]); const inputCommitments = [input1]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(tokenIds[0]), tokenUris[0], salt3, ...receiver.pubKey]); + const output1 = poseidonHash([ + BigInt(tokenIds[0]), + tokenUris[0], + salt3, + ...receiver.pubKey, + ]); const outputCommitments = [output1]; const otherInputs = stringifyBigInts({ @@ -71,7 +87,7 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without outputOwnerPublicKeys: [receiver.pubKey], ...otherInputs, }, - true + true, ); // console.log('witness', witness.slice(0, 15)); @@ -97,12 +113,22 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(inputTokenIds[0]), tokenUris, salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(inputTokenIds[0]), + tokenUris, + salt1, + ...sender.pubKey, + ]); const inputCommitments = [input1]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(outputTokenIds[0]), tokenUris, salt3, ...receiver.pubKey]); + const output1 = poseidonHash([ + BigInt(outputTokenIds[0]), + tokenUris, + salt3, + ...receiver.pubKey, + ]); const outputCommitments = [output1]; const otherInputs = stringifyBigInts({ @@ -122,29 +148,43 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without outputOwnerPublicKeys: [receiver.pubKey], ...otherInputs, }, - true + true, ); } catch (e) { error = e; } // console.log(error); expect(error).to.match(/Error in template Zeto_87 line: 66/); - expect(error).to.match(/Error in template CheckHashesForTokenIdAndUri_86 line: 58/); + expect(error).to.match( + /Error in template CheckHashesForTokenIdAndUri_86 line: 58/, + ); }); it('should fail to generate a witness because token URI changed', async () => { const tokenIds = [1001]; const inputTokenUris = [tokenUriHash('http://ipfs.io/some-file-hash')]; - const outputTokenUris = [tokenUriHash('http://ipfs.io/some-other-file-hash')]; + const outputTokenUris = [ + tokenUriHash('http://ipfs.io/some-other-file-hash'), + ]; // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(tokenIds[0]), inputTokenUris, salt1, ...sender.pubKey]); + const input1 = poseidonHash([ + BigInt(tokenIds[0]), + inputTokenUris, + salt1, + ...sender.pubKey, + ]); const inputCommitments = [input1]; // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(tokenIds[0]), outputTokenUris, salt3, ...receiver.pubKey]); + const output1 = poseidonHash([ + BigInt(tokenIds[0]), + outputTokenUris, + salt3, + ...receiver.pubKey, + ]); const outputCommitments = [output1]; const otherInputs = stringifyBigInts({ @@ -164,13 +204,15 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without outputOwnerPublicKeys: [receiver.pubKey], ...otherInputs, }, - true + true, ); } catch (e) { error = e; } // console.log(error); expect(error).to.match(/Error in template Zeto_87 line: 66/); - expect(error).to.match(/Error in template CheckHashesForTokenIdAndUri_86 line: 58/); + expect(error).to.match( + /Error in template CheckHashesForTokenIdAndUri_86 line: 58/, + ); }); }); diff --git a/zkp/js/test/nf_anon_nullifier.js b/zkp/js/test/nf_anon_nullifier.js index 1c47b5a..035b0b6 100644 --- a/zkp/js/test/nf_anon_nullifier.js +++ b/zkp/js/test/nf_anon_nullifier.js @@ -18,7 +18,12 @@ const { expect } = require('chai'); const { join } = require('path'); const { wasm: wasm_tester } = require('circom_tester'); const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree'); +const { + Merkletree, + InMemoryDB, + str2Bytes, + ZERO_HASH, +} = require('@iden3/js-merkletree'); const { Poseidon, newSalt, tokenUriHash } = require('../index.js'); const SMT_HEIGHT = 64; @@ -35,7 +40,9 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../../circuits/nf_anon_nullifier.circom')); + circuit = await wasm_tester( + join(__dirname, '../../circuits/nf_anon_nullifier.circom'), + ); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -61,20 +68,38 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(tokenId), tokenUri, salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(tokenId), + tokenUri, + salt1, + ...Alice.pubKey, + ]); // create the nullifiers for the inputs - const nullifier1 = poseidonHash4([BigInt(tokenId), tokenUri, salt1, senderPrivateKey]); + const nullifier1 = poseidonHash4([ + BigInt(tokenId), + tokenUri, + salt1, + senderPrivateKey, + ]); // calculate the root of the SMT await smtAlice.add(input1, input1); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(tokenId), tokenUri, salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(tokenId), + tokenUri, + salt3, + ...Bob.pubKey, + ]); const witness = await circuit.calculateWitness( { @@ -90,7 +115,7 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n outputSalt: salt3, outputOwnerPublicKey: Bob.pubKey, }, - true + true, ); // console.log('witness', witness.slice(0, 15)); @@ -114,20 +139,38 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n // create two input UTXOs const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(tokenId), tokenUri, salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(tokenId), + tokenUri, + salt1, + ...Alice.pubKey, + ]); // create two input nullifiers, corresponding to the input UTXOs - const nullifier1 = poseidonHash4([BigInt(tokenId), tokenUri, salt1, senderPrivateKey]); + const nullifier1 = poseidonHash4([ + BigInt(tokenId), + tokenUri, + salt1, + senderPrivateKey, + ]); // calculate the root of the SMT await smtAlice.add(input1, input1); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const output1 = poseidonHash([BigInt(tokenId + 1), tokenUri, salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(tokenId + 1), + tokenUri, + salt3, + ...Bob.pubKey, + ]); let err; try { @@ -145,14 +188,16 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n outputSalt: salt3, outputOwnerPublicKey: Bob.pubKey, }, - true + true, ); } catch (e) { err = e; } // console.log(err); expect(err).to.match(/Error in template Zeto_319 line: 76/); - expect(err).to.match(/Error in template CheckHashesForTokenIdAndUri_86 line: 58/); + expect(err).to.match( + /Error in template CheckHashesForTokenIdAndUri_86 line: 58/, + ); }); it('should fail to generate a witness because token URI changed', async () => { @@ -161,21 +206,39 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n // create two input UTXOs const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(tokenId), tokenUri, salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(tokenId), + tokenUri, + salt1, + ...Alice.pubKey, + ]); // create two input nullifiers, corresponding to the input UTXOs - const nullifier1 = poseidonHash4([BigInt(tokenId), tokenUri, salt1, senderPrivateKey]); + const nullifier1 = poseidonHash4([ + BigInt(tokenId), + tokenUri, + salt1, + senderPrivateKey, + ]); // calculate the root of the SMT await smtAlice.add(input1, input1); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); const tokenUriBad = tokenUriHash('http://ipfs.io/some-other-file-hash'); - const output1 = poseidonHash([BigInt(tokenId), tokenUriBad, salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(tokenId), + tokenUriBad, + salt3, + ...Bob.pubKey, + ]); let err; try { @@ -193,14 +256,16 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n outputSalt: salt3, outputOwnerPublicKey: Bob.pubKey, }, - true + true, ); } catch (e) { err = e; } // console.log(err); expect(err).to.match(/Error in template Zeto_319 line: 76/); - expect(err).to.match(/Error in template CheckHashesForTokenIdAndUri_86 line: 58/); + expect(err).to.match( + /Error in template CheckHashesForTokenIdAndUri_86 line: 58/, + ); }); it('should fail to generate a witness because of invalid input commitments', async () => { @@ -209,21 +274,39 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n // create two input UTXOs const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(tokenId), tokenUri, salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(tokenId), + tokenUri, + salt1, + ...Alice.pubKey, + ]); // create two input nullifiers, corresponding to the input UTXOs - const nullifier1 = poseidonHash4([BigInt(tokenId), tokenUri, salt1, senderPrivateKey]); + const nullifier1 = poseidonHash4([ + BigInt(tokenId), + tokenUri, + salt1, + senderPrivateKey, + ]); // calculate the root of the SMT await smtAlice.add(input1, input1); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); const tokenUriBad = tokenUriHash('http://ipfs.io/some-other-file-hash'); - const output1 = poseidonHash([BigInt(tokenId), tokenUriBad, salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(tokenId), + tokenUriBad, + salt3, + ...Bob.pubKey, + ]); let err; try { @@ -241,13 +324,15 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n outputSalt: salt3, outputOwnerPublicKey: Bob.pubKey, }, - true + true, ); } catch (e) { err = e; } // console.log(err); - expect(err).to.match(/Error in template CheckHashesForTokenIdAndUri_86 line: 58/); + expect(err).to.match( + /Error in template CheckHashesForTokenIdAndUri_86 line: 58/, + ); }); it('should fail to generate a witness because of invalid output commitments', async () => { @@ -256,21 +341,39 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n // create two input UTXOs const salt1 = newSalt(); - const input1 = poseidonHash([BigInt(tokenId), tokenUri, salt1, ...Alice.pubKey]); + const input1 = poseidonHash([ + BigInt(tokenId), + tokenUri, + salt1, + ...Alice.pubKey, + ]); // create two input nullifiers, corresponding to the input UTXOs - const nullifier1 = poseidonHash4([BigInt(tokenId), tokenUri, salt1, senderPrivateKey]); + const nullifier1 = poseidonHash4([ + BigInt(tokenId), + tokenUri, + salt1, + senderPrivateKey, + ]); // calculate the root of the SMT await smtAlice.add(input1, input1); // generate the merkle proof for the inputs - const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH); + const proof1 = await smtAlice.generateCircomVerifierProof( + input1, + ZERO_HASH, + ); // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); const tokenUriBad = tokenUriHash('http://ipfs.io/some-other-file-hash'); - const output1 = poseidonHash([BigInt(tokenId), tokenUriBad, salt3, ...Bob.pubKey]); + const output1 = poseidonHash([ + BigInt(tokenId), + tokenUriBad, + salt3, + ...Bob.pubKey, + ]); let err; try { @@ -288,12 +391,14 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n outputSalt: salt3, outputOwnerPublicKey: Bob.pubKey, }, - true + true, ); } catch (e) { err = e; } // console.log(err); - expect(err).to.match(/Error in template CheckHashesForTokenIdAndUri_86 line: 58/); + expect(err).to.match( + /Error in template CheckHashesForTokenIdAndUri_86 line: 58/, + ); }); }); From be4a5931bda049bd2b3d01024a1a0aa8613a4808 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Tue, 1 Oct 2024 09:17:05 +0100 Subject: [PATCH 17/24] lint all files Signed-off-by: Chengxuan Xing --- solidity/ignition/modules/erc20.ts | 4 +- solidity/ignition/modules/lib/deps.ts | 49 +++++++++++-------- .../modules/zeto_anon_enc_nullifier.ts | 4 +- .../modules/zeto_anon_enc_nullifier_kyc.ts | 6 +-- ...zeto_anon_enc_nullifier_non_repudiation.ts | 10 ++-- .../ignition/modules/zeto_anon_nullifier.ts | 4 +- .../modules/zeto_anon_nullifier_kyc.ts | 4 +- solidity/ignition/modules/zeto_nf_anon.ts | 8 +-- .../modules/zeto_nf_anon_nullifier.ts | 8 +-- solidity/ignition/modules/zkDvP.ts | 10 ++-- solidity/package.json | 2 +- solidity/scripts/deploy_upgradeable.ts | 22 +++++---- solidity/scripts/lib/common.ts | 18 +++++-- solidity/scripts/tokens/Zeto_NfAnon.ts | 9 ++-- .../scripts/tokens/Zeto_NfAnonNullifier.ts | 13 ++--- 15 files changed, 92 insertions(+), 79 deletions(-) diff --git a/solidity/ignition/modules/erc20.ts b/solidity/ignition/modules/erc20.ts index 73d6a89..404bc0c 100644 --- a/solidity/ignition/modules/erc20.ts +++ b/solidity/ignition/modules/erc20.ts @@ -14,9 +14,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; -export default buildModule("SampleERC20", (m) => { +export default buildModule('SampleERC20', (m) => { const owner = m.getAccount(0); const erc20 = m.contract('SampleERC20', [owner], { from: owner }); return { erc20 }; diff --git a/solidity/ignition/modules/lib/deps.ts b/solidity/ignition/modules/lib/deps.ts index 39a4a84..1ebd192 100644 --- a/solidity/ignition/modules/lib/deps.ts +++ b/solidity/ignition/modules/lib/deps.ts @@ -14,11 +14,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { poseidonContract } from "circomlibjs"; -import { Artifact } from "hardhat/types"; +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { poseidonContract } from 'circomlibjs'; +import { Artifact } from 'hardhat/types'; -export const SmtLibModule = buildModule("SmtLib", (m) => { +export const SmtLibModule = buildModule('SmtLib', (m) => { const poseidon2 = m.library('Poseidon2', PoseidonArtifact(2)); const poseidon3 = m.library('Poseidon3', PoseidonArtifact(3)); const smtLib = m.contract('SmtLib', [], { @@ -30,33 +30,42 @@ export const SmtLibModule = buildModule("SmtLib", (m) => { return { smtLib, poseidon2, poseidon3 }; }); -export const DepositVerifierModule = buildModule("Groth16Verifier_CheckHashesValue", (m) => { - const verifier = m.contract('Groth16Verifier_CheckHashesValue', []); - return { verifier }; -}); +export const DepositVerifierModule = buildModule( + 'Groth16Verifier_CheckHashesValue', + (m) => { + const verifier = m.contract('Groth16Verifier_CheckHashesValue', []); + return { verifier }; + }, +); -export const WithdrawNullifierVerifierModule = buildModule("Groth16Verifier_CheckNullifierValue", (m) => { - const verifier = m.contract('Groth16Verifier_CheckNullifierValue', []); - return { verifier }; -}); +export const WithdrawNullifierVerifierModule = buildModule( + 'Groth16Verifier_CheckNullifierValue', + (m) => { + const verifier = m.contract('Groth16Verifier_CheckNullifierValue', []); + return { verifier }; + }, +); -export const WithdrawVerifierModule = buildModule("Groth16Verifier_CheckInputsOutputsValue", (m) => { - const verifier = m.contract('Groth16Verifier_CheckInputsOutputsValue', []); - return { verifier }; -}); +export const WithdrawVerifierModule = buildModule( + 'Groth16Verifier_CheckInputsOutputsValue', + (m) => { + const verifier = m.contract('Groth16Verifier_CheckInputsOutputsValue', []); + return { verifier }; + }, +); function PoseidonArtifact(param: number): Artifact { const abi = poseidonContract.generateABI(param); const bytecode = poseidonContract.createCode(param); const artifact: Artifact = { - _format: "hh-sol-artifact-1", + _format: 'hh-sol-artifact-1', contractName: `Poseidon${param}`, - sourceName: "", + sourceName: '', abi: abi, bytecode: bytecode, - deployedBytecode: "", // "0x"-prefixed hex string + deployedBytecode: '', // "0x"-prefixed hex string linkReferences: {}, - deployedLinkReferences: {} + deployedLinkReferences: {}, }; return artifact; } diff --git a/solidity/ignition/modules/zeto_anon_enc_nullifier.ts b/solidity/ignition/modules/zeto_anon_enc_nullifier.ts index 1d2ae4c..d8cbecc 100644 --- a/solidity/ignition/modules/zeto_anon_enc_nullifier.ts +++ b/solidity/ignition/modules/zeto_anon_enc_nullifier.ts @@ -31,7 +31,7 @@ const BatchVerifierModule = buildModule( (m) => { const verifier = m.contract('Groth16Verifier_AnonEncNullifierBatch', []); return { verifier }; - } + }, ); export default buildModule('Zeto_AnonEncNullifier', (m) => { @@ -40,7 +40,7 @@ export default buildModule('Zeto_AnonEncNullifier', (m) => { const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule( - WithdrawNullifierVerifierModule + WithdrawNullifierVerifierModule, ); return { diff --git a/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts b/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts index c6e04bd..7356b9c 100644 --- a/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +++ b/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts @@ -26,7 +26,7 @@ const VerifierModule = buildModule( (m) => { const verifier = m.contract('Groth16Verifier_AnonEncNullifierKyc', []); return { verifier }; - } + }, ); const BatchVerifierModule = buildModule( @@ -34,7 +34,7 @@ const BatchVerifierModule = buildModule( (m) => { const verifier = m.contract('Groth16Verifier_AnonEncNullifierKycBatch', []); return { verifier }; - } + }, ); export default buildModule('Zeto_AnonEncNullifierKyc', (m) => { @@ -43,7 +43,7 @@ export default buildModule('Zeto_AnonEncNullifierKyc', (m) => { const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule( - WithdrawNullifierVerifierModule + WithdrawNullifierVerifierModule, ); return { diff --git a/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts b/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts index 7655983..f1b772d 100644 --- a/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts +++ b/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts @@ -26,10 +26,10 @@ const VerifierModule = buildModule( (m) => { const verifier = m.contract( 'Groth16Verifier_AnonEncNullifierNonRepudiation', - [] + [], ); return { verifier }; - } + }, ); const BatchVerifierModule = buildModule( @@ -37,10 +37,10 @@ const BatchVerifierModule = buildModule( (m) => { const verifier = m.contract( 'Groth16Verifier_AnonEncNullifierNonRepudiationBatch', - [] + [], ); return { verifier }; - } + }, ); export default buildModule('Zeto_AnonEncNullifierNonRepudiation', (m) => { @@ -49,7 +49,7 @@ export default buildModule('Zeto_AnonEncNullifierNonRepudiation', (m) => { const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule( - WithdrawNullifierVerifierModule + WithdrawNullifierVerifierModule, ); return { diff --git a/solidity/ignition/modules/zeto_anon_nullifier.ts b/solidity/ignition/modules/zeto_anon_nullifier.ts index 9d68d86..267a1a1 100644 --- a/solidity/ignition/modules/zeto_anon_nullifier.ts +++ b/solidity/ignition/modules/zeto_anon_nullifier.ts @@ -31,7 +31,7 @@ const BatchVerifierModule = buildModule( (m) => { const verifier = m.contract('Groth16Verifier_AnonNullifierBatch', []); return { verifier }; - } + }, ); export default buildModule('Zeto_AnonNullifier', (m) => { @@ -40,7 +40,7 @@ export default buildModule('Zeto_AnonNullifier', (m) => { const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule( - WithdrawNullifierVerifierModule + WithdrawNullifierVerifierModule, ); return { diff --git a/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts b/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts index 47a7032..6b4b748 100644 --- a/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts +++ b/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts @@ -31,7 +31,7 @@ const BatchVerifierModule = buildModule( (m) => { const verifier = m.contract('Groth16Verifier_AnonNullifierKycBatch', []); return { verifier }; - } + }, ); export default buildModule('Zeto_AnonNullifierKyc', (m) => { @@ -40,7 +40,7 @@ export default buildModule('Zeto_AnonNullifierKyc', (m) => { const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); const { verifier: withdrawVerifier } = m.useModule( - WithdrawNullifierVerifierModule + WithdrawNullifierVerifierModule, ); return { diff --git a/solidity/ignition/modules/zeto_nf_anon.ts b/solidity/ignition/modules/zeto_nf_anon.ts index 3944a09..2e208cc 100644 --- a/solidity/ignition/modules/zeto_nf_anon.ts +++ b/solidity/ignition/modules/zeto_nf_anon.ts @@ -14,15 +14,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; -const VerifierModule = buildModule("Groth16Verifier_NfAnon", (m) => { +const VerifierModule = buildModule('Groth16Verifier_NfAnon', (m) => { const verifier = m.contract('Groth16Verifier_NfAnon', []); return { verifier }; }); -export default buildModule("Zeto_NfAnon", (m) => { +export default buildModule('Zeto_NfAnon', (m) => { const { verifier } = m.useModule(VerifierModule); return { verifier }; -}); \ No newline at end of file +}); diff --git a/solidity/ignition/modules/zeto_nf_anon_nullifier.ts b/solidity/ignition/modules/zeto_nf_anon_nullifier.ts index 3c760f5..32aaee6 100644 --- a/solidity/ignition/modules/zeto_nf_anon_nullifier.ts +++ b/solidity/ignition/modules/zeto_nf_anon_nullifier.ts @@ -14,15 +14,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -import { SmtLibModule } from "./lib/deps"; +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { SmtLibModule } from './lib/deps'; -const VerifierModule = buildModule("Groth16Verifier_NfAnonNullifier", (m) => { +const VerifierModule = buildModule('Groth16Verifier_NfAnonNullifier', (m) => { const verifier = m.contract('Groth16Verifier_NfAnonNullifier', []); return { verifier }; }); -export default buildModule("Zeto_NfAnonNullifier", (m) => { +export default buildModule('Zeto_NfAnonNullifier', (m) => { const { smtLib, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); diff --git a/solidity/ignition/modules/zkDvP.ts b/solidity/ignition/modules/zkDvP.ts index 0fea4a6..16bf5f8 100644 --- a/solidity/ignition/modules/zkDvP.ts +++ b/solidity/ignition/modules/zkDvP.ts @@ -14,14 +14,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; -export default buildModule("zkDvP", (m) => { - const paymentTokenAddress = m.getParameter("paymentToken"); +export default buildModule('zkDvP', (m) => { + const paymentTokenAddress = m.getParameter('paymentToken'); const paymentToken = m.contractAt('Zeto_Anon', paymentTokenAddress); - const assetTokenAddress = m.getParameter("assetToken"); + const assetTokenAddress = m.getParameter('assetToken'); const assetToken = m.contractAt('Zeto_NfAnon', assetTokenAddress); const zkDvP = m.contract('zkDvP', [paymentToken, assetToken]); return { zkDvP }; -}); \ No newline at end of file +}); diff --git a/solidity/package.json b/solidity/package.json index f80d20f..1de53fd 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -4,7 +4,7 @@ "description": "Zero knowledge proof based UTXO tokens toolkit for fungible or non-fungible assets", "main": "index.js", "scripts": { - "prettier": "npx prettier test --check", + "prettier": "npx prettier scripts ignition test --check", "prettier:fix": "npm run prettier -- --write", "pretest": "npm run prettier:fix", "test": "npx hardhat test" diff --git a/solidity/scripts/deploy_upgradeable.ts b/solidity/scripts/deploy_upgradeable.ts index 0527dde..8844a67 100644 --- a/solidity/scripts/deploy_upgradeable.ts +++ b/solidity/scripts/deploy_upgradeable.ts @@ -1,23 +1,24 @@ -import { ethers, ignition, upgrades } from "hardhat"; +import { ethers, ignition, upgrades } from 'hardhat'; import erc20Module from '../ignition/modules/erc20'; -import { getLinkedContractFactory, deploy } from "./lib/common"; +import { getLinkedContractFactory, deploy } from './lib/common'; export async function deployFungible(tokenName: string) { const { erc20 } = await ignition.deploy(erc20Module); const verifiersDeployer = require(`./tokens/${tokenName}`); - const { deployer, args, libraries } = await verifiersDeployer.deployDependencies(); + const { deployer, args, libraries } = + await verifiersDeployer.deployDependencies(); let zetoFactory; const opts = { kind: 'uups', initializer: 'initialize', - unsafeAllow: ['delegatecall'] + unsafeAllow: ['delegatecall'], }; if (libraries) { zetoFactory = await getLinkedContractFactory(tokenName, libraries); opts.unsafeAllow.push('external-library-linking'); } else { - zetoFactory = await ethers.getContractFactory(tokenName) + zetoFactory = await ethers.getContractFactory(tokenName); } const proxy = await upgrades.deployProxy(zetoFactory, args, opts as any); @@ -36,19 +37,20 @@ export async function deployFungible(tokenName: string) { export async function deployNonFungible(tokenName: string) { const verifiersDeployer = require(`./tokens/${tokenName}`); - const { deployer, args, libraries } = await verifiersDeployer.deployDependencies(); + const { deployer, args, libraries } = + await verifiersDeployer.deployDependencies(); let zetoFactory; const opts = { kind: 'uups', initializer: 'initialize', - unsafeAllow: ['delegatecall'] + unsafeAllow: ['delegatecall'], }; if (libraries) { zetoFactory = await getLinkedContractFactory(tokenName, libraries); opts.unsafeAllow.push('external-library-linking'); } else { - zetoFactory = await ethers.getContractFactory(tokenName) + zetoFactory = await ethers.getContractFactory(tokenName); } const proxy = await upgrades.deployProxy(zetoFactory, args, opts as any); @@ -68,7 +70,7 @@ deploy(deployFungible, deployNonFungible) } process.exit(0); }) - .catch(error => { + .catch((error) => { console.error(error); process.exit(1); - }); \ No newline at end of file + }); diff --git a/solidity/scripts/lib/common.ts b/solidity/scripts/lib/common.ts index 0c60920..314c974 100644 --- a/solidity/scripts/lib/common.ts +++ b/solidity/scripts/lib/common.ts @@ -14,13 +14,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { artifacts, ethers } from "hardhat"; +import { artifacts, ethers } from 'hardhat'; import fungibilities from '../tokens.json'; -export async function getLinkedContractFactory(contractName: string, libraries: any) { +export async function getLinkedContractFactory( + contractName: string, + libraries: any, +) { const cArtifact = await artifacts.readArtifact(contractName); const linkedBytecode = linkBytecode(cArtifact, libraries); - const ContractFactory = await ethers.getContractFactory(cArtifact.abi, linkedBytecode); + const ContractFactory = await ethers.getContractFactory( + cArtifact.abi, + linkedBytecode, + ); return ContractFactory; } @@ -32,7 +38,9 @@ export function deploy(deployFungible: Function, deployNonFungible: Function) { const zeto = process.env.ZETO_NAME; if (!zeto) { - throw new Error('Please provide a Zeto token contract name with the environment variable ZETO_NAME'); + throw new Error( + 'Please provide a Zeto token contract name with the environment variable ZETO_NAME', + ); } const fungibility = (fungibilities as any)[zeto]; if (!fungibility) { @@ -45,7 +53,7 @@ export function deploy(deployFungible: Function, deployNonFungible: Function) { console.log(`Deploying non-fungible Zeto token: ${zeto}`); return deployNonFungible(zeto); } -}; +} // linkBytecode: performs linking by replacing placeholders with deployed addresses // Recommended workaround from Hardhat team until linking feature is implemented diff --git a/solidity/scripts/tokens/Zeto_NfAnon.ts b/solidity/scripts/tokens/Zeto_NfAnon.ts index 8073260..835c66b 100644 --- a/solidity/scripts/tokens/Zeto_NfAnon.ts +++ b/solidity/scripts/tokens/Zeto_NfAnon.ts @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from "hardhat"; +import { ethers, ignition } from 'hardhat'; import zetoModule from '../../ignition/modules/zeto_nf_anon'; export async function deployDependencies() { @@ -23,9 +23,6 @@ export async function deployDependencies() { const { verifier } = await ignition.deploy(zetoModule); return { deployer, - args: [ - await deployer.getAddress(), - verifier.target - ] + args: [await deployer.getAddress(), verifier.target], }; -} \ No newline at end of file +} diff --git a/solidity/scripts/tokens/Zeto_NfAnonNullifier.ts b/solidity/scripts/tokens/Zeto_NfAnonNullifier.ts index ffa6488..cf171e9 100644 --- a/solidity/scripts/tokens/Zeto_NfAnonNullifier.ts +++ b/solidity/scripts/tokens/Zeto_NfAnonNullifier.ts @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from "hardhat"; +import { ethers, ignition } from 'hardhat'; import zetoModule from '../../ignition/modules/zeto_nf_anon_nullifier'; export async function deployDependencies() { @@ -23,13 +23,10 @@ export async function deployDependencies() { const { verifier, smtLib, poseidon3 } = await ignition.deploy(zetoModule); return { deployer, - args: [ - await deployer.getAddress(), - verifier.target - ], + args: [await deployer.getAddress(), verifier.target], libraries: { SmtLib: smtLib.target, - PoseidonUnit3L: poseidon3.target - } + PoseidonUnit3L: poseidon3.target, + }, }; -} \ No newline at end of file +} From 6879293b485ef56d17d706b4c6f107248ea7ce45 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Tue, 1 Oct 2024 09:24:05 +0100 Subject: [PATCH 18/24] refactor and use double quotes Signed-off-by: Chengxuan Xing --- solidity/.prettierrc | 3 - solidity/contracts/lib/zeto_base.sol | 29 ---- solidity/contracts/lib/zeto_common.sol | 27 +++ solidity/contracts/lib/zeto_nullifier.sol | 29 ---- solidity/ignition/modules/erc20.ts | 6 +- solidity/ignition/modules/lib/deps.ts | 32 ++-- solidity/ignition/modules/zeto_anon.ts | 14 +- solidity/ignition/modules/zeto_anon_enc.ts | 14 +- .../modules/zeto_anon_enc_nullifier.ts | 14 +- .../modules/zeto_anon_enc_nullifier_kyc.ts | 14 +- ...zeto_anon_enc_nullifier_non_repudiation.ts | 14 +- .../ignition/modules/zeto_anon_nullifier.ts | 14 +- .../modules/zeto_anon_nullifier_kyc.ts | 14 +- solidity/ignition/modules/zeto_nf_anon.ts | 8 +- .../modules/zeto_nf_anon_nullifier.ts | 10 +- solidity/ignition/modules/zkDvP.ts | 14 +- solidity/package.json | 2 +- solidity/scripts/deploy_cloneable.ts | 8 +- solidity/scripts/deploy_upgradeable.ts | 24 +-- solidity/scripts/lib/common.ts | 14 +- solidity/scripts/tokens/Zeto_Anon.ts | 4 +- solidity/scripts/tokens/Zeto_AnonEnc.ts | 4 +- .../scripts/tokens/Zeto_AnonEncNullifier.ts | 4 +- .../tokens/Zeto_AnonEncNullifierKyc.ts | 4 +- .../Zeto_AnonEncNullifierNonRepudiation.ts | 4 +- solidity/scripts/tokens/Zeto_AnonNullifier.ts | 4 +- .../scripts/tokens/Zeto_AnonNullifierKyc.ts | 4 +- solidity/scripts/tokens/Zeto_NfAnon.ts | 4 +- .../scripts/tokens/Zeto_NfAnonNullifier.ts | 4 +- solidity/test/factory.ts | 156 +++++++++--------- ...to_anon_enc_nullifier_kyc_cost_analysis.ts | 58 +++---- solidity/test/lib/deploy.ts | 28 ++-- solidity/test/lib/utils.ts | 22 +-- solidity/test/utils.ts | 26 +-- solidity/test/zeto_anon.ts | 74 ++++----- solidity/test/zeto_anon_enc.ts | 72 ++++---- solidity/test/zeto_anon_enc_nullifier.ts | 86 +++++----- solidity/test/zeto_anon_enc_nullifier_kyc.ts | 100 +++++------ ...zeto_anon_enc_nullifier_non_repudiation.ts | 84 +++++----- solidity/test/zeto_anon_nullifier.ts | 84 +++++----- solidity/test/zeto_anon_nullifier_kyc.ts | 100 +++++------ solidity/test/zeto_nf_anon.ts | 62 +++---- solidity/test/zeto_nf_anon_nullifier.ts | 64 +++---- solidity/test/zkDvP.ts | 114 ++++++------- zkp/js/.prettierrc | 3 - zkp/js/integration-test/anon.js | 20 +-- zkp/js/integration-test/anon_enc.js | 20 +-- zkp/js/integration-test/anon_enc_nullifier.js | 26 +-- .../anon_enc_nullifier_kyc.js | 28 ++-- .../anon_enc_nullifier_non_repudiation.js | 26 +-- zkp/js/integration-test/anon_nullifier.js | 26 +-- zkp/js/integration-test/anon_nullifier_kyc.js | 28 ++-- zkp/js/integration-test/check_hashes_value.js | 20 +-- .../check_inputs_outputs_value.js | 24 +-- .../integration-test/check_nullifier_value.js | 24 +-- zkp/js/integration-test/check_nullifiers.js | 20 +-- zkp/js/integration-test/nf_anon.js | 22 +-- zkp/js/integration-test/nf_anon_nullifier.js | 28 ++-- zkp/js/integration-test/utils.js | 6 +- zkp/js/lib/util.js | 46 +++--- zkp/js/test/anon.js | 18 +- zkp/js/test/anon_enc.js | 22 +-- zkp/js/test/anon_enc_nullifier.js | 26 +-- zkp/js/test/anon_enc_nullifier_kyc.js | 26 +-- .../anon_enc_nullifier_non_repudiation.js | 26 +-- zkp/js/test/anon_nullifier.js | 26 +-- zkp/js/test/anon_nullifier_kyc.js | 26 +-- zkp/js/test/check_hashes_value.js | 24 +-- zkp/js/test/check_inputs_outputs_value.js | 22 +-- zkp/js/test/check_nullifier_value.js | 22 +-- zkp/js/test/check_nullifiers.js | 18 +- zkp/js/test/lib/check-hashes-tokenid-uri.js | 24 +-- zkp/js/test/lib/check-hashes.js | 24 +-- .../test/lib/check-nullifier-tokenid-uri.js | 26 +-- zkp/js/test/lib/check-nullifiers.js | 18 +- zkp/js/test/lib/check-positive.js | 18 +- zkp/js/test/lib/check-smt-proof.js | 22 +-- zkp/js/test/lib/check-sum.js | 14 +- zkp/js/test/lib/ecdh.js | 14 +- zkp/js/test/lib/encrypt.js | 28 ++-- zkp/js/test/lib/poseidon-ex.js | 14 +- zkp/js/test/lib/poseidon.js | 14 +- zkp/js/test/nf_anon.js | 28 ++-- zkp/js/test/nf_anon_nullifier.js | 46 +++--- 84 files changed, 1173 insertions(+), 1210 deletions(-) delete mode 100644 solidity/.prettierrc delete mode 100644 zkp/js/.prettierrc diff --git a/solidity/.prettierrc b/solidity/.prettierrc deleted file mode 100644 index 544138b..0000000 --- a/solidity/.prettierrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "singleQuote": true -} diff --git a/solidity/contracts/lib/zeto_base.sol b/solidity/contracts/lib/zeto_base.sol index 4ea8a42..35f4e0e 100644 --- a/solidity/contracts/lib/zeto_base.sol +++ b/solidity/contracts/lib/zeto_base.sol @@ -100,35 +100,6 @@ abstract contract ZetoBase is IZetoBase, ZetoCommon { return true; } - function checkAndPadCommitments( - uint256[] memory inputs, - uint256[] memory outputs, - uint256 batchMax - ) internal pure returns (uint256[] memory, uint256[] memory) { - uint256 inputLen = inputs.length; - uint256 outputLen = outputs.length; - - // Check if inputs or outputs exceed batchMax and revert with custom error if necessary - if (inputLen > batchMax || outputLen > batchMax) { - revert UTXOCommitmentsExceededMaximumNumber(batchMax); - } - - // Ensure both arrays are padded to the same length - uint256 maxLength; - - if (inputLen > 2 || outputLen > 2) { - maxLength = batchMax; // Pad both to batchMax if one has more than 2 items - } else { - maxLength = 2; // Otherwise, pad both to 2 - } - - // Pad both inputs and outputs to the determined maxLength - inputs = Commonlib.padUintArray(inputs, maxLength, 0); - outputs = Commonlib.padUintArray(outputs, maxLength, 0); - - return (inputs, outputs); - } - function processInputsAndOutputs( uint256[] memory inputs, uint256[] memory outputs diff --git a/solidity/contracts/lib/zeto_common.sol b/solidity/contracts/lib/zeto_common.sol index d476315..6d1e121 100644 --- a/solidity/contracts/lib/zeto_common.sol +++ b/solidity/contracts/lib/zeto_common.sol @@ -56,7 +56,34 @@ abstract contract ZetoCommon is OwnableUpgradeable { ); lockedProofs[proofHash] = delegate; } + function checkAndPadCommitments( + uint256[] memory inputs, + uint256[] memory outputs, + uint256 batchMax + ) internal pure returns (uint256[] memory, uint256[] memory) { + uint256 inputLen = inputs.length; + uint256 outputLen = outputs.length; + + // Check if inputs or outputs exceed batchMax and revert with custom error if necessary + if (inputLen > batchMax || outputLen > batchMax) { + revert UTXOCommitmentsExceededMaximumNumber(batchMax); + } + + // Ensure both arrays are padded to the same length + uint256 maxLength; + if (inputLen > 2 || outputLen > 2) { + maxLength = batchMax; // Pad both to batchMax if one has more than 2 items + } else { + maxLength = 2; // Otherwise, pad both to 2 + } + + // Pad both inputs and outputs to the determined maxLength + inputs = Commonlib.padUintArray(inputs, maxLength, 0); + outputs = Commonlib.padUintArray(outputs, maxLength, 0); + + return (inputs, outputs); + } function sortInputsAndOutputs( uint256[] memory inputs, uint256[] memory outputs diff --git a/solidity/contracts/lib/zeto_nullifier.sol b/solidity/contracts/lib/zeto_nullifier.sol index 6c3281b..519d450 100644 --- a/solidity/contracts/lib/zeto_nullifier.sol +++ b/solidity/contracts/lib/zeto_nullifier.sol @@ -42,35 +42,6 @@ abstract contract ZetoNullifier is IZetoBase, ZetoCommon { _commitmentsTree.initialize(MAX_SMT_DEPTH); } - function checkAndPadCommitments( - uint256[] memory inputs, - uint256[] memory outputs, - uint256 batchMax - ) internal pure returns (uint256[] memory, uint256[] memory) { - uint256 inputLen = inputs.length; - uint256 outputLen = outputs.length; - - // Check if inputs or outputs exceed batchMax and revert with custom error if necessary - if (inputLen > batchMax || outputLen > batchMax) { - revert UTXOCommitmentsExceededMaximumNumber(batchMax); - } - - // Ensure both arrays are padded to the same length - uint256 maxLength; - - if (inputLen > 2 || outputLen > 2) { - maxLength = batchMax; // Pad both to batchMax if one has more than 2 items - } else { - maxLength = 2; // Otherwise, pad both to 2 - } - - // Pad both inputs and outputs to the determined maxLength - inputs = Commonlib.padUintArray(inputs, maxLength, 0); - outputs = Commonlib.padUintArray(outputs, maxLength, 0); - - return (inputs, outputs); - } - function validateTransactionProposal( uint256[] memory nullifiers, uint256[] memory outputs, diff --git a/solidity/ignition/modules/erc20.ts b/solidity/ignition/modules/erc20.ts index 404bc0c..69b24b7 100644 --- a/solidity/ignition/modules/erc20.ts +++ b/solidity/ignition/modules/erc20.ts @@ -14,10 +14,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -export default buildModule('SampleERC20', (m) => { +export default buildModule("SampleERC20", (m) => { const owner = m.getAccount(0); - const erc20 = m.contract('SampleERC20', [owner], { from: owner }); + const erc20 = m.contract("SampleERC20", [owner], { from: owner }); return { erc20 }; }); diff --git a/solidity/ignition/modules/lib/deps.ts b/solidity/ignition/modules/lib/deps.ts index 1ebd192..dff5af0 100644 --- a/solidity/ignition/modules/lib/deps.ts +++ b/solidity/ignition/modules/lib/deps.ts @@ -14,14 +14,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; -import { poseidonContract } from 'circomlibjs'; -import { Artifact } from 'hardhat/types'; +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +import { poseidonContract } from "circomlibjs"; +import { Artifact } from "hardhat/types"; -export const SmtLibModule = buildModule('SmtLib', (m) => { - const poseidon2 = m.library('Poseidon2', PoseidonArtifact(2)); - const poseidon3 = m.library('Poseidon3', PoseidonArtifact(3)); - const smtLib = m.contract('SmtLib', [], { +export const SmtLibModule = buildModule("SmtLib", (m) => { + const poseidon2 = m.library("Poseidon2", PoseidonArtifact(2)); + const poseidon3 = m.library("Poseidon3", PoseidonArtifact(3)); + const smtLib = m.contract("SmtLib", [], { libraries: { PoseidonUnit2L: poseidon2, PoseidonUnit3L: poseidon3, @@ -31,25 +31,25 @@ export const SmtLibModule = buildModule('SmtLib', (m) => { }); export const DepositVerifierModule = buildModule( - 'Groth16Verifier_CheckHashesValue', + "Groth16Verifier_CheckHashesValue", (m) => { - const verifier = m.contract('Groth16Verifier_CheckHashesValue', []); + const verifier = m.contract("Groth16Verifier_CheckHashesValue", []); return { verifier }; }, ); export const WithdrawNullifierVerifierModule = buildModule( - 'Groth16Verifier_CheckNullifierValue', + "Groth16Verifier_CheckNullifierValue", (m) => { - const verifier = m.contract('Groth16Verifier_CheckNullifierValue', []); + const verifier = m.contract("Groth16Verifier_CheckNullifierValue", []); return { verifier }; }, ); export const WithdrawVerifierModule = buildModule( - 'Groth16Verifier_CheckInputsOutputsValue', + "Groth16Verifier_CheckInputsOutputsValue", (m) => { - const verifier = m.contract('Groth16Verifier_CheckInputsOutputsValue', []); + const verifier = m.contract("Groth16Verifier_CheckInputsOutputsValue", []); return { verifier }; }, ); @@ -58,12 +58,12 @@ function PoseidonArtifact(param: number): Artifact { const abi = poseidonContract.generateABI(param); const bytecode = poseidonContract.createCode(param); const artifact: Artifact = { - _format: 'hh-sol-artifact-1', + _format: "hh-sol-artifact-1", contractName: `Poseidon${param}`, - sourceName: '', + sourceName: "", abi: abi, bytecode: bytecode, - deployedBytecode: '', // "0x"-prefixed hex string + deployedBytecode: "", // "0x"-prefixed hex string linkReferences: {}, deployedLinkReferences: {}, }; diff --git a/solidity/ignition/modules/zeto_anon.ts b/solidity/ignition/modules/zeto_anon.ts index efbb0ae..10ca1a0 100644 --- a/solidity/ignition/modules/zeto_anon.ts +++ b/solidity/ignition/modules/zeto_anon.ts @@ -14,20 +14,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; -import { DepositVerifierModule, WithdrawVerifierModule } from './lib/deps'; +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +import { DepositVerifierModule, WithdrawVerifierModule } from "./lib/deps"; -const VerifierModule = buildModule('Groth16Verifier_Anon', (m) => { - const verifier = m.contract('Groth16Verifier_Anon', []); +const VerifierModule = buildModule("Groth16Verifier_Anon", (m) => { + const verifier = m.contract("Groth16Verifier_Anon", []); return { verifier }; }); -const BatchVerifierModule = buildModule('Groth16Verifier_AnonBatch', (m) => { - const verifier = m.contract('Groth16Verifier_AnonBatch', []); +const BatchVerifierModule = buildModule("Groth16Verifier_AnonBatch", (m) => { + const verifier = m.contract("Groth16Verifier_AnonBatch", []); return { verifier }; }); -export default buildModule('Zeto_Anon', (m) => { +export default buildModule("Zeto_Anon", (m) => { const { verifier } = m.useModule(VerifierModule); const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); diff --git a/solidity/ignition/modules/zeto_anon_enc.ts b/solidity/ignition/modules/zeto_anon_enc.ts index 6a0ea63..85c1e26 100644 --- a/solidity/ignition/modules/zeto_anon_enc.ts +++ b/solidity/ignition/modules/zeto_anon_enc.ts @@ -14,20 +14,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; -import { DepositVerifierModule, WithdrawVerifierModule } from './lib/deps'; +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +import { DepositVerifierModule, WithdrawVerifierModule } from "./lib/deps"; -const VerifierModule = buildModule('Groth16Verifier_AnonEnc', (m) => { - const verifier = m.contract('Groth16Verifier_AnonEnc', []); +const VerifierModule = buildModule("Groth16Verifier_AnonEnc", (m) => { + const verifier = m.contract("Groth16Verifier_AnonEnc", []); return { verifier }; }); -const BatchVerifierModule = buildModule('Groth16Verifier_AnonEncBatch', (m) => { - const verifier = m.contract('Groth16Verifier_AnonEncBatch', []); +const BatchVerifierModule = buildModule("Groth16Verifier_AnonEncBatch", (m) => { + const verifier = m.contract("Groth16Verifier_AnonEncBatch", []); return { verifier }; }); -export default buildModule('Zeto_AnonEnc', (m) => { +export default buildModule("Zeto_AnonEnc", (m) => { const { verifier } = m.useModule(VerifierModule); const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); const { verifier: depositVerifier } = m.useModule(DepositVerifierModule); diff --git a/solidity/ignition/modules/zeto_anon_enc_nullifier.ts b/solidity/ignition/modules/zeto_anon_enc_nullifier.ts index d8cbecc..837df68 100644 --- a/solidity/ignition/modules/zeto_anon_enc_nullifier.ts +++ b/solidity/ignition/modules/zeto_anon_enc_nullifier.ts @@ -14,27 +14,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; import { SmtLibModule, DepositVerifierModule, WithdrawNullifierVerifierModule, -} from './lib/deps'; +} from "./lib/deps"; -const VerifierModule = buildModule('Groth16Verifier_AnonEncNullifier', (m) => { - const verifier = m.contract('Groth16Verifier_AnonEncNullifier', []); +const VerifierModule = buildModule("Groth16Verifier_AnonEncNullifier", (m) => { + const verifier = m.contract("Groth16Verifier_AnonEncNullifier", []); return { verifier }; }); const BatchVerifierModule = buildModule( - 'Groth16Verifier_AnonEncNullifierBatch', + "Groth16Verifier_AnonEncNullifierBatch", (m) => { - const verifier = m.contract('Groth16Verifier_AnonEncNullifierBatch', []); + const verifier = m.contract("Groth16Verifier_AnonEncNullifierBatch", []); return { verifier }; }, ); -export default buildModule('Zeto_AnonEncNullifier', (m) => { +export default buildModule("Zeto_AnonEncNullifier", (m) => { const { smtLib, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); diff --git a/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts b/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts index 7356b9c..d6d8476 100644 --- a/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +++ b/solidity/ignition/modules/zeto_anon_enc_nullifier_kyc.ts @@ -14,30 +14,30 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; import { SmtLibModule, DepositVerifierModule, WithdrawNullifierVerifierModule, -} from './lib/deps'; +} from "./lib/deps"; const VerifierModule = buildModule( - 'Groth16Verifier_AnonEncNullifierKyc', + "Groth16Verifier_AnonEncNullifierKyc", (m) => { - const verifier = m.contract('Groth16Verifier_AnonEncNullifierKyc', []); + const verifier = m.contract("Groth16Verifier_AnonEncNullifierKyc", []); return { verifier }; }, ); const BatchVerifierModule = buildModule( - 'Groth16Verifier_AnonEncNullifierKycBatch', + "Groth16Verifier_AnonEncNullifierKycBatch", (m) => { - const verifier = m.contract('Groth16Verifier_AnonEncNullifierKycBatch', []); + const verifier = m.contract("Groth16Verifier_AnonEncNullifierKycBatch", []); return { verifier }; }, ); -export default buildModule('Zeto_AnonEncNullifierKyc', (m) => { +export default buildModule("Zeto_AnonEncNullifierKyc", (m) => { const { smtLib, poseidon2, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); diff --git a/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts b/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts index f1b772d..0c4a412 100644 --- a/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts +++ b/solidity/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts @@ -14,18 +14,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; import { SmtLibModule, DepositVerifierModule, WithdrawNullifierVerifierModule, -} from './lib/deps'; +} from "./lib/deps"; const VerifierModule = buildModule( - 'Groth16Verifier_AnonEncNullifierNonRepudiation', + "Groth16Verifier_AnonEncNullifierNonRepudiation", (m) => { const verifier = m.contract( - 'Groth16Verifier_AnonEncNullifierNonRepudiation', + "Groth16Verifier_AnonEncNullifierNonRepudiation", [], ); return { verifier }; @@ -33,17 +33,17 @@ const VerifierModule = buildModule( ); const BatchVerifierModule = buildModule( - 'Groth16Verifier_AnonEncNullifierNonRepudiationBatch', + "Groth16Verifier_AnonEncNullifierNonRepudiationBatch", (m) => { const verifier = m.contract( - 'Groth16Verifier_AnonEncNullifierNonRepudiationBatch', + "Groth16Verifier_AnonEncNullifierNonRepudiationBatch", [], ); return { verifier }; }, ); -export default buildModule('Zeto_AnonEncNullifierNonRepudiation', (m) => { +export default buildModule("Zeto_AnonEncNullifierNonRepudiation", (m) => { const { smtLib, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); diff --git a/solidity/ignition/modules/zeto_anon_nullifier.ts b/solidity/ignition/modules/zeto_anon_nullifier.ts index 267a1a1..ad2f1fb 100644 --- a/solidity/ignition/modules/zeto_anon_nullifier.ts +++ b/solidity/ignition/modules/zeto_anon_nullifier.ts @@ -14,27 +14,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; import { SmtLibModule, DepositVerifierModule, WithdrawNullifierVerifierModule, -} from './lib/deps'; +} from "./lib/deps"; -const VerifierModule = buildModule('Groth16Verifier_AnonNullifier', (m) => { - const verifier = m.contract('Groth16Verifier_AnonNullifier', []); +const VerifierModule = buildModule("Groth16Verifier_AnonNullifier", (m) => { + const verifier = m.contract("Groth16Verifier_AnonNullifier", []); return { verifier }; }); const BatchVerifierModule = buildModule( - 'Groth16Verifier_AnonNullifierBatch', + "Groth16Verifier_AnonNullifierBatch", (m) => { - const verifier = m.contract('Groth16Verifier_AnonNullifierBatch', []); + const verifier = m.contract("Groth16Verifier_AnonNullifierBatch", []); return { verifier }; }, ); -export default buildModule('Zeto_AnonNullifier', (m) => { +export default buildModule("Zeto_AnonNullifier", (m) => { const { smtLib, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); diff --git a/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts b/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts index 6b4b748..c7cca0e 100644 --- a/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts +++ b/solidity/ignition/modules/zeto_anon_nullifier_kyc.ts @@ -14,27 +14,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; import { SmtLibModule, DepositVerifierModule, WithdrawNullifierVerifierModule, -} from './lib/deps'; +} from "./lib/deps"; -const VerifierModule = buildModule('Groth16Verifier_AnonNullifierKyc', (m) => { - const verifier = m.contract('Groth16Verifier_AnonNullifierKyc', []); +const VerifierModule = buildModule("Groth16Verifier_AnonNullifierKyc", (m) => { + const verifier = m.contract("Groth16Verifier_AnonNullifierKyc", []); return { verifier }; }); const BatchVerifierModule = buildModule( - 'Groth16Verifier_AnonNullifierKycBatch', + "Groth16Verifier_AnonNullifierKycBatch", (m) => { - const verifier = m.contract('Groth16Verifier_AnonNullifierKycBatch', []); + const verifier = m.contract("Groth16Verifier_AnonNullifierKycBatch", []); return { verifier }; }, ); -export default buildModule('Zeto_AnonNullifierKyc', (m) => { +export default buildModule("Zeto_AnonNullifierKyc", (m) => { const { smtLib, poseidon2, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); const { verifier: batchVerifier } = m.useModule(BatchVerifierModule); diff --git a/solidity/ignition/modules/zeto_nf_anon.ts b/solidity/ignition/modules/zeto_nf_anon.ts index 2e208cc..a1f8230 100644 --- a/solidity/ignition/modules/zeto_nf_anon.ts +++ b/solidity/ignition/modules/zeto_nf_anon.ts @@ -14,14 +14,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -const VerifierModule = buildModule('Groth16Verifier_NfAnon', (m) => { - const verifier = m.contract('Groth16Verifier_NfAnon', []); +const VerifierModule = buildModule("Groth16Verifier_NfAnon", (m) => { + const verifier = m.contract("Groth16Verifier_NfAnon", []); return { verifier }; }); -export default buildModule('Zeto_NfAnon', (m) => { +export default buildModule("Zeto_NfAnon", (m) => { const { verifier } = m.useModule(VerifierModule); return { verifier }; diff --git a/solidity/ignition/modules/zeto_nf_anon_nullifier.ts b/solidity/ignition/modules/zeto_nf_anon_nullifier.ts index 32aaee6..6f3cc2c 100644 --- a/solidity/ignition/modules/zeto_nf_anon_nullifier.ts +++ b/solidity/ignition/modules/zeto_nf_anon_nullifier.ts @@ -14,15 +14,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; -import { SmtLibModule } from './lib/deps'; +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; +import { SmtLibModule } from "./lib/deps"; -const VerifierModule = buildModule('Groth16Verifier_NfAnonNullifier', (m) => { - const verifier = m.contract('Groth16Verifier_NfAnonNullifier', []); +const VerifierModule = buildModule("Groth16Verifier_NfAnonNullifier", (m) => { + const verifier = m.contract("Groth16Verifier_NfAnonNullifier", []); return { verifier }; }); -export default buildModule('Zeto_NfAnonNullifier', (m) => { +export default buildModule("Zeto_NfAnonNullifier", (m) => { const { smtLib, poseidon3 } = m.useModule(SmtLibModule); const { verifier } = m.useModule(VerifierModule); diff --git a/solidity/ignition/modules/zkDvP.ts b/solidity/ignition/modules/zkDvP.ts index 16bf5f8..90327ee 100644 --- a/solidity/ignition/modules/zkDvP.ts +++ b/solidity/ignition/modules/zkDvP.ts @@ -14,14 +14,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; +import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; -export default buildModule('zkDvP', (m) => { - const paymentTokenAddress = m.getParameter('paymentToken'); - const paymentToken = m.contractAt('Zeto_Anon', paymentTokenAddress); - const assetTokenAddress = m.getParameter('assetToken'); - const assetToken = m.contractAt('Zeto_NfAnon', assetTokenAddress); +export default buildModule("zkDvP", (m) => { + const paymentTokenAddress = m.getParameter("paymentToken"); + const paymentToken = m.contractAt("Zeto_Anon", paymentTokenAddress); + const assetTokenAddress = m.getParameter("assetToken"); + const assetToken = m.contractAt("Zeto_NfAnon", assetTokenAddress); - const zkDvP = m.contract('zkDvP', [paymentToken, assetToken]); + const zkDvP = m.contract("zkDvP", [paymentToken, assetToken]); return { zkDvP }; }); diff --git a/solidity/package.json b/solidity/package.json index 1de53fd..212dea8 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -4,7 +4,7 @@ "description": "Zero knowledge proof based UTXO tokens toolkit for fungible or non-fungible assets", "main": "index.js", "scripts": { - "prettier": "npx prettier scripts ignition test --check", + "prettier": "npx prettier contracts scripts ignition test --check", "prettier:fix": "npm run prettier -- --write", "pretest": "npm run prettier:fix", "test": "npx hardhat test" diff --git a/solidity/scripts/deploy_cloneable.ts b/solidity/scripts/deploy_cloneable.ts index 6c6a4ef..9803f77 100644 --- a/solidity/scripts/deploy_cloneable.ts +++ b/solidity/scripts/deploy_cloneable.ts @@ -1,6 +1,6 @@ -import { ethers, ignition } from 'hardhat'; -import erc20Module from '../ignition/modules/erc20'; -import { getLinkedContractFactory, deploy } from './lib/common'; +import { ethers, ignition } from "hardhat"; +import erc20Module from "../ignition/modules/erc20"; +import { getLinkedContractFactory, deploy } from "./lib/common"; export async function deployFungible(tokenName: string) { const { erc20 } = await ignition.deploy(erc20Module); @@ -51,7 +51,7 @@ export async function deployNonFungible(tokenName: string) { deploy(deployFungible, deployNonFungible) .then(() => { - if (process.env.TEST_DEPLOY_SCRIPTS == 'true') { + if (process.env.TEST_DEPLOY_SCRIPTS == "true") { return; } process.exit(0); diff --git a/solidity/scripts/deploy_upgradeable.ts b/solidity/scripts/deploy_upgradeable.ts index 8844a67..f3cf753 100644 --- a/solidity/scripts/deploy_upgradeable.ts +++ b/solidity/scripts/deploy_upgradeable.ts @@ -1,6 +1,6 @@ -import { ethers, ignition, upgrades } from 'hardhat'; -import erc20Module from '../ignition/modules/erc20'; -import { getLinkedContractFactory, deploy } from './lib/common'; +import { ethers, ignition, upgrades } from "hardhat"; +import erc20Module from "../ignition/modules/erc20"; +import { getLinkedContractFactory, deploy } from "./lib/common"; export async function deployFungible(tokenName: string) { const { erc20 } = await ignition.deploy(erc20Module); @@ -10,13 +10,13 @@ export async function deployFungible(tokenName: string) { let zetoFactory; const opts = { - kind: 'uups', - initializer: 'initialize', - unsafeAllow: ['delegatecall'], + kind: "uups", + initializer: "initialize", + unsafeAllow: ["delegatecall"], }; if (libraries) { zetoFactory = await getLinkedContractFactory(tokenName, libraries); - opts.unsafeAllow.push('external-library-linking'); + opts.unsafeAllow.push("external-library-linking"); } else { zetoFactory = await ethers.getContractFactory(tokenName); } @@ -42,13 +42,13 @@ export async function deployNonFungible(tokenName: string) { let zetoFactory; const opts = { - kind: 'uups', - initializer: 'initialize', - unsafeAllow: ['delegatecall'], + kind: "uups", + initializer: "initialize", + unsafeAllow: ["delegatecall"], }; if (libraries) { zetoFactory = await getLinkedContractFactory(tokenName, libraries); - opts.unsafeAllow.push('external-library-linking'); + opts.unsafeAllow.push("external-library-linking"); } else { zetoFactory = await ethers.getContractFactory(tokenName); } @@ -65,7 +65,7 @@ export async function deployNonFungible(tokenName: string) { deploy(deployFungible, deployNonFungible) .then(() => { - if (process.env.TEST_DEPLOY_SCRIPTS == 'true') { + if (process.env.TEST_DEPLOY_SCRIPTS == "true") { return; } process.exit(0); diff --git a/solidity/scripts/lib/common.ts b/solidity/scripts/lib/common.ts index 314c974..2f5c762 100644 --- a/solidity/scripts/lib/common.ts +++ b/solidity/scripts/lib/common.ts @@ -14,8 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { artifacts, ethers } from 'hardhat'; -import fungibilities from '../tokens.json'; +import { artifacts, ethers } from "hardhat"; +import fungibilities from "../tokens.json"; export async function getLinkedContractFactory( contractName: string, @@ -31,22 +31,22 @@ export async function getLinkedContractFactory( } export function deploy(deployFungible: Function, deployNonFungible: Function) { - if (process.env.TEST_DEPLOY_SCRIPTS == 'true') { - console.log('Skipping the deploy command in test environment'); + if (process.env.TEST_DEPLOY_SCRIPTS == "true") { + console.log("Skipping the deploy command in test environment"); return Promise.resolve(); } const zeto = process.env.ZETO_NAME; if (!zeto) { throw new Error( - 'Please provide a Zeto token contract name with the environment variable ZETO_NAME', + "Please provide a Zeto token contract name with the environment variable ZETO_NAME", ); } const fungibility = (fungibilities as any)[zeto]; if (!fungibility) { - throw new Error('Invalid Zeto token contract name'); + throw new Error("Invalid Zeto token contract name"); } - if (fungibility === 'fungible') { + if (fungibility === "fungible") { console.log(`Deploying fungible Zeto token: ${zeto}`); return deployFungible(zeto); } else { diff --git a/solidity/scripts/tokens/Zeto_Anon.ts b/solidity/scripts/tokens/Zeto_Anon.ts index 979e65a..cdfadab 100644 --- a/solidity/scripts/tokens/Zeto_Anon.ts +++ b/solidity/scripts/tokens/Zeto_Anon.ts @@ -14,8 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from 'hardhat'; -import zetoModule from '../../ignition/modules/zeto_anon'; +import { ethers, ignition } from "hardhat"; +import zetoModule from "../../ignition/modules/zeto_anon"; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); diff --git a/solidity/scripts/tokens/Zeto_AnonEnc.ts b/solidity/scripts/tokens/Zeto_AnonEnc.ts index 1aafa6a..a89fb70 100644 --- a/solidity/scripts/tokens/Zeto_AnonEnc.ts +++ b/solidity/scripts/tokens/Zeto_AnonEnc.ts @@ -14,8 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from 'hardhat'; -import zetoModule from '../../ignition/modules/zeto_anon_enc'; +import { ethers, ignition } from "hardhat"; +import zetoModule from "../../ignition/modules/zeto_anon_enc"; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); diff --git a/solidity/scripts/tokens/Zeto_AnonEncNullifier.ts b/solidity/scripts/tokens/Zeto_AnonEncNullifier.ts index debf433..6d50ea9 100644 --- a/solidity/scripts/tokens/Zeto_AnonEncNullifier.ts +++ b/solidity/scripts/tokens/Zeto_AnonEncNullifier.ts @@ -14,8 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from 'hardhat'; -import zetoModule from '../../ignition/modules/zeto_anon_enc_nullifier'; +import { ethers, ignition } from "hardhat"; +import zetoModule from "../../ignition/modules/zeto_anon_enc_nullifier"; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); diff --git a/solidity/scripts/tokens/Zeto_AnonEncNullifierKyc.ts b/solidity/scripts/tokens/Zeto_AnonEncNullifierKyc.ts index 1b69784..ac876ab 100644 --- a/solidity/scripts/tokens/Zeto_AnonEncNullifierKyc.ts +++ b/solidity/scripts/tokens/Zeto_AnonEncNullifierKyc.ts @@ -14,8 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from 'hardhat'; -import zetoModule from '../../ignition/modules/zeto_anon_enc_nullifier_kyc'; +import { ethers, ignition } from "hardhat"; +import zetoModule from "../../ignition/modules/zeto_anon_enc_nullifier_kyc"; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); diff --git a/solidity/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts b/solidity/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts index 9106dfa..dec2a96 100644 --- a/solidity/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts +++ b/solidity/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts @@ -14,8 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from 'hardhat'; -import zetoModule from '../../ignition/modules/zeto_anon_enc_nullifier_non_repudiation'; +import { ethers, ignition } from "hardhat"; +import zetoModule from "../../ignition/modules/zeto_anon_enc_nullifier_non_repudiation"; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); diff --git a/solidity/scripts/tokens/Zeto_AnonNullifier.ts b/solidity/scripts/tokens/Zeto_AnonNullifier.ts index c439864..e64650c 100644 --- a/solidity/scripts/tokens/Zeto_AnonNullifier.ts +++ b/solidity/scripts/tokens/Zeto_AnonNullifier.ts @@ -14,8 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from 'hardhat'; -import zetoModule from '../../ignition/modules/zeto_anon_nullifier'; +import { ethers, ignition } from "hardhat"; +import zetoModule from "../../ignition/modules/zeto_anon_nullifier"; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); diff --git a/solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts b/solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts index b133950..05e10b6 100644 --- a/solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts +++ b/solidity/scripts/tokens/Zeto_AnonNullifierKyc.ts @@ -14,8 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from 'hardhat'; -import zetoModule from '../../ignition/modules/zeto_anon_nullifier_kyc'; +import { ethers, ignition } from "hardhat"; +import zetoModule from "../../ignition/modules/zeto_anon_nullifier_kyc"; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); diff --git a/solidity/scripts/tokens/Zeto_NfAnon.ts b/solidity/scripts/tokens/Zeto_NfAnon.ts index 835c66b..e18dce2 100644 --- a/solidity/scripts/tokens/Zeto_NfAnon.ts +++ b/solidity/scripts/tokens/Zeto_NfAnon.ts @@ -14,8 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from 'hardhat'; -import zetoModule from '../../ignition/modules/zeto_nf_anon'; +import { ethers, ignition } from "hardhat"; +import zetoModule from "../../ignition/modules/zeto_nf_anon"; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); diff --git a/solidity/scripts/tokens/Zeto_NfAnonNullifier.ts b/solidity/scripts/tokens/Zeto_NfAnonNullifier.ts index cf171e9..ff308e7 100644 --- a/solidity/scripts/tokens/Zeto_NfAnonNullifier.ts +++ b/solidity/scripts/tokens/Zeto_NfAnonNullifier.ts @@ -14,8 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition } from 'hardhat'; -import zetoModule from '../../ignition/modules/zeto_nf_anon_nullifier'; +import { ethers, ignition } from "hardhat"; +import zetoModule from "../../ignition/modules/zeto_nf_anon_nullifier"; export async function deployDependencies() { const [deployer] = await ethers.getSigners(); diff --git a/solidity/test/factory.ts b/solidity/test/factory.ts index 037573a..5f0cb50 100644 --- a/solidity/test/factory.ts +++ b/solidity/test/factory.ts @@ -14,196 +14,196 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, network } from 'hardhat'; -import { Signer } from 'ethers'; -import { expect } from 'chai'; +import { ethers, network } from "hardhat"; +import { Signer } from "ethers"; +import { expect } from "chai"; -describe('Zeto based fungible token with anonymity without encryption or nullifier', function () { +describe("Zeto based fungible token with anonymity without encryption or nullifier", function () { let deployer: Signer; let nonOwner: Signer; before(async function () { - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { // accommodate for longer block times on public networks this.timeout(120000); } [deployer, nonOwner] = await ethers.getSigners(); }); - it('attempting to register an implementation as a non-owner should fail', async function () { - const Factory = await ethers.getContractFactory('ZetoTokenFactory'); + it("attempting to register an implementation as a non-owner should fail", async function () { + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - verifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - batchVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - depositVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - withdrawVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + batchVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + withdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", }; await expect( - factory.connect(nonOwner).registerImplementation('test', implInfo as any), + factory.connect(nonOwner).registerImplementation("test", implInfo as any), ).rejectedWith(`reverted with custom error 'OwnableUnauthorizedAccount(`); }); - it('attempting to register an implementation without the required implementation value should fail', async function () { + it("attempting to register an implementation without the required implementation value should fail", async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory('ZetoTokenFactory'); + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: '0x0000000000000000000000000000000000000000', - verifier: '0x0000000000000000000000000000000000000000', - batchVerifier: '0x0000000000000000000000000000000000000000', - depositVerifier: '0x0000000000000000000000000000000000000000', - withdrawVerifier: '0x0000000000000000000000000000000000000000', + implementation: "0x0000000000000000000000000000000000000000", + verifier: "0x0000000000000000000000000000000000000000", + batchVerifier: "0x0000000000000000000000000000000000000000", + depositVerifier: "0x0000000000000000000000000000000000000000", + withdrawVerifier: "0x0000000000000000000000000000000000000000", }; await expect( - factory.connect(deployer).registerImplementation('test', implInfo as any), - ).rejectedWith('Factory: implementation address is required'); + factory.connect(deployer).registerImplementation("test", implInfo as any), + ).rejectedWith("Factory: implementation address is required"); }); - it('attempting to register an implementation without the required verifier value should fail', async function () { + it("attempting to register an implementation without the required verifier value should fail", async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory('ZetoTokenFactory'); + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - verifier: '0x0000000000000000000000000000000000000000', - batchVerifier: '0x0000000000000000000000000000000000000000', - depositVerifier: '0x0000000000000000000000000000000000000000', - withdrawVerifier: '0x0000000000000000000000000000000000000000', + implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + verifier: "0x0000000000000000000000000000000000000000", + batchVerifier: "0x0000000000000000000000000000000000000000", + depositVerifier: "0x0000000000000000000000000000000000000000", + withdrawVerifier: "0x0000000000000000000000000000000000000000", }; await expect( - factory.connect(deployer).registerImplementation('test', implInfo as any), - ).rejectedWith('Factory: verifier address is required'); + factory.connect(deployer).registerImplementation("test", implInfo as any), + ).rejectedWith("Factory: verifier address is required"); }); - it('attempting to register an implementation with the required values should succeed', async function () { + it("attempting to register an implementation with the required values should succeed", async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory('ZetoTokenFactory'); + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - verifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - batchVerifier: '0x0000000000000000000000000000000000000000', - depositVerifier: '0x0000000000000000000000000000000000000000', - withdrawVerifier: '0x0000000000000000000000000000000000000000', + implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + batchVerifier: "0x0000000000000000000000000000000000000000", + depositVerifier: "0x0000000000000000000000000000000000000000", + withdrawVerifier: "0x0000000000000000000000000000000000000000", }; await expect( - factory.connect(deployer).registerImplementation('test', implInfo as any), + factory.connect(deployer).registerImplementation("test", implInfo as any), ).fulfilled; }); - it('attempting to deploy a fungible token but with a registered implementation that misses required batchVerifier should fail', async function () { + it("attempting to deploy a fungible token but with a registered implementation that misses required batchVerifier should fail", async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory('ZetoTokenFactory'); + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - verifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - batchVerifier: '0x0000000000000000000000000000000000000000', - depositVerifier: '0x0000000000000000000000000000000000000000', - withdrawVerifier: '0x0000000000000000000000000000000000000000', + implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + batchVerifier: "0x0000000000000000000000000000000000000000", + depositVerifier: "0x0000000000000000000000000000000000000000", + withdrawVerifier: "0x0000000000000000000000000000000000000000", }; const tx1 = await factory .connect(deployer) - .registerImplementation('test', implInfo as any); + .registerImplementation("test", implInfo as any); await tx1.wait(); await expect( factory .connect(deployer) - .deployZetoFungibleToken('test', await deployer.getAddress()), - ).rejectedWith('Factory: depositVerifier address is required'); + .deployZetoFungibleToken("test", await deployer.getAddress()), + ).rejectedWith("Factory: depositVerifier address is required"); }); - it('attempting to deploy a fungible token but with a registered implementation that misses required depositVerifier should fail', async function () { + it("attempting to deploy a fungible token but with a registered implementation that misses required depositVerifier should fail", async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory('ZetoTokenFactory'); + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - verifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - batchVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - depositVerifier: '0x0000000000000000000000000000000000000000', - withdrawVerifier: '0x0000000000000000000000000000000000000000', + implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + batchVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + depositVerifier: "0x0000000000000000000000000000000000000000", + withdrawVerifier: "0x0000000000000000000000000000000000000000", }; const tx1 = await factory .connect(deployer) - .registerImplementation('test', implInfo as any); + .registerImplementation("test", implInfo as any); await tx1.wait(); await expect( factory .connect(deployer) - .deployZetoFungibleToken('test', await deployer.getAddress()), - ).rejectedWith('Factory: depositVerifier address is required'); + .deployZetoFungibleToken("test", await deployer.getAddress()), + ).rejectedWith("Factory: depositVerifier address is required"); }); - it('attempting to deploy a fungible token but with a registered implementation that misses required withdrawVerifier should fail', async function () { + it("attempting to deploy a fungible token but with a registered implementation that misses required withdrawVerifier should fail", async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory('ZetoTokenFactory'); + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - verifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - batchVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - depositVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - withdrawVerifier: '0x0000000000000000000000000000000000000000', + implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + batchVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + withdrawVerifier: "0x0000000000000000000000000000000000000000", }; const tx1 = await factory .connect(deployer) - .registerImplementation('test', implInfo as any); + .registerImplementation("test", implInfo as any); await tx1.wait(); await expect( factory .connect(deployer) - .deployZetoFungibleToken('test', await deployer.getAddress()), - ).rejectedWith('Factory: withdrawVerifier address is required'); + .deployZetoFungibleToken("test", await deployer.getAddress()), + ).rejectedWith("Factory: withdrawVerifier address is required"); }); - it('attempting to deploy a fungible token with a properly registered implementation should succeed', async function () { + it("attempting to deploy a fungible token with a properly registered implementation should succeed", async function () { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory('ZetoTokenFactory'); + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { - implementation: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - verifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - batchVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - depositVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', - withdrawVerifier: '0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1', + implementation: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + verifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + batchVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + depositVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", + withdrawVerifier: "0xae92d5aD7583AD66E49A0c67BAd18F6ba52dDDc1", }; const tx1 = await factory .connect(deployer) - .registerImplementation('test', implInfo as any); + .registerImplementation("test", implInfo as any); await tx1.wait(); await expect( factory .connect(deployer) - .deployZetoFungibleToken('test', await deployer.getAddress()), + .deployZetoFungibleToken("test", await deployer.getAddress()), ).fulfilled; }); }); diff --git a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts index 7e15617..de486ba 100644 --- a/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts +++ b/solidity/test/gas_cost/zeto_anon_enc_nullifier_kyc_cost_analysis.ts @@ -13,21 +13,21 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -import fs from 'fs'; -import path from 'path'; -import { ethers, network } from 'hardhat'; -import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; -import { expect } from 'chai'; -import { loadCircuit, encodeProof, newEncryptionNonce, kycHash } from 'zeto-js'; -import { groth16 } from 'snarkjs'; +import fs from "fs"; +import path from "path"; +import { ethers, network } from "hardhat"; +import { ContractTransactionReceipt, Signer, BigNumberish } from "ethers"; +import { expect } from "chai"; +import { loadCircuit, encodeProof, newEncryptionNonce, kycHash } from "zeto-js"; +import { groth16 } from "snarkjs"; import { genKeypair, formatPrivKeyForBabyJub, stringifyBigInts, -} from 'maci-crypto'; -import AsyncLock from 'async-lock'; +} from "maci-crypto"; +import AsyncLock from "async-lock"; const lock = new AsyncLock(); -import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; +import { Merkletree, InMemoryDB, str2Bytes } from "@iden3/js-merkletree"; import { UTXO, User, @@ -39,19 +39,19 @@ import { doWithdraw, ZERO_UTXO, parseRegistryEvents, -} from '../lib/utils'; +} from "../lib/utils"; import { loadProvingKeys, prepareDepositProof, prepareNullifierWithdrawProof, -} from '../utils'; -import { deployZeto } from '../lib/deploy'; +} from "../utils"; +import { deployZeto } from "../lib/deploy"; -const TOTAL_AMOUNT = parseInt(process.env.TOTAL_ROUNDS || '1000'); -const TX_CONCURRENCY = parseInt(process.env.TX_CONCURRENCY || '1'); +const TOTAL_AMOUNT = parseInt(process.env.TOTAL_ROUNDS || "1000"); +const TX_CONCURRENCY = parseInt(process.env.TX_CONCURRENCY || "1"); const UTXO_PER_TX = 10; -describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity using nullifiers and encryption with KYC', function () { +describe.skip("(Gas cost analysis) Zeto based fungible token with anonymity using nullifiers and encryption with KYC", function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -82,7 +82,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin const reportPrefix = date.toISOString(); before(async function () { - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { // accommodate for longer block times on public networks this.timeout(120000); } @@ -92,7 +92,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin Bob = await newUser(b); Charlie = await newUser(c); - ({ deployer, zeto, erc20 } = await deployZeto('Zeto_AnonEncNullifierKyc')); + ({ deployer, zeto, erc20 } = await deployZeto("Zeto_AnonEncNullifierKyc")); const tx2 = await zeto.connect(deployer).register(Alice.babyJubPublicKey); const result1 = await tx2.wait(); @@ -101,13 +101,13 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin const tx4 = await zeto.connect(deployer).register(Charlie.babyJubPublicKey); const result3 = await tx4.wait(); - const storage1 = new InMemoryDB(str2Bytes('alice')); + const storage1 = new InMemoryDB(str2Bytes("alice")); smtAlice = new Merkletree(storage1, true, 64); - const storage2 = new InMemoryDB(str2Bytes('bob')); + const storage2 = new InMemoryDB(str2Bytes("bob")); smtBob = new Merkletree(storage2, true, 64); - const storage3 = new InMemoryDB(str2Bytes('kyc')); + const storage3 = new InMemoryDB(str2Bytes("kyc")); smtKyc = new Merkletree(storage3, true, 10); const publicKey1 = parseRegistryEvents(zeto, result1); @@ -117,13 +117,13 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin const publicKey3 = parseRegistryEvents(zeto, result3); await smtKyc.add(kycHash(publicKey3), kycHash(publicKey3)); - circuit = await loadCircuit('anon_enc_nullifier_kyc'); + circuit = await loadCircuit("anon_enc_nullifier_kyc"); ({ provingKeyFile: provingKey } = loadProvingKeys( - 'anon_enc_nullifier_kyc', + "anon_enc_nullifier_kyc", )); - batchCircuit = await loadCircuit('anon_enc_nullifier_kyc_batch'); + batchCircuit = await loadCircuit("anon_enc_nullifier_kyc_batch"); ({ provingKeyFile: batchProvingKey } = loadProvingKeys( - 'anon_enc_nullifier_kyc_batch', + "anon_enc_nullifier_kyc_batch", )); }); @@ -537,7 +537,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin circuitToUse = batchCircuit; provingKeyToUse = batchProvingKey; } - const witness = await lock.acquire('proofGen', async () => { + const witness = await lock.acquire("proofGen", async () => { // this lock is added for https://github.com/hyperledger-labs/zeto/issues/80, which only happens for Transfer circuit, not deposit/mint return circuitToUse.calculateWTNSBin(inputObj, true); }); @@ -588,7 +588,7 @@ describe.skip('(Gas cost analysis) Zeto based fungible token with anonymity usin ecdhPublicKey, encryptedValues, encodedProof, - '0x', + "0x", ); const result: ContractTransactionReceipt | null = await tx.wait(); console.log( @@ -604,10 +604,10 @@ function writeGasCostsToCSV(filename: string, gasCosts: number[]) { const filePath = path.join(__dirname, filename); // Prepare the CSV content - const csvData = gasCosts.join(',\n') + '\n'; // Each value in a new line + const csvData = gasCosts.join(",\n") + "\n"; // Each value in a new line // Write the CSV content to a file (overwrite if file exists) - fs.writeFileSync(filePath, 'gas_costs,\n' + csvData, 'utf8'); + fs.writeFileSync(filePath, "gas_costs,\n" + csvData, "utf8"); console.log(`Gas costs written to ${filePath}`); } diff --git a/solidity/test/lib/deploy.ts b/solidity/test/lib/deploy.ts index a84821d..ef0da82 100644 --- a/solidity/test/lib/deploy.ts +++ b/solidity/test/lib/deploy.ts @@ -1,16 +1,16 @@ // set this to turn off paramters checking in the deployment scripts -process.env.TEST_DEPLOY_SCRIPTS = 'true'; +process.env.TEST_DEPLOY_SCRIPTS = "true"; import { deployFungible as deployFungibleUpgradeable, deployNonFungible as deployNonFungibleUpgradeable, -} from '../../scripts/deploy_upgradeable'; +} from "../../scripts/deploy_upgradeable"; import { deployFungible as deployFungibleCloneable, deployNonFungible as deployNonFungibleCloneable, -} from '../../scripts/deploy_cloneable'; -import fungibilities from '../../scripts/tokens.json'; -import { ethers } from 'hardhat'; +} from "../../scripts/deploy_cloneable"; +import fungibilities from "../../scripts/tokens.json"; +import { ethers } from "hardhat"; export async function deployZeto(tokenName: string) { let zeto, erc20, deployer; @@ -20,7 +20,7 @@ export async function deployZeto(tokenName: string) { if (process.env.ZETO_ADDRESS && process.env.ERC20_ADDRESS) { zeto = await ethers.getContractAt(tokenName, process.env.ZETO_ADDRESS); erc20 = await ethers.getContractAt( - 'SampleERC20', + "SampleERC20", process.env.ERC20_ADDRESS, ); deployer = (await ethers.getSigners())[0]; @@ -29,12 +29,12 @@ export async function deployZeto(tokenName: string) { let isFungible = false; const fungibility = (fungibilities as any)[tokenName]; - if (fungibility === 'fungible') { + if (fungibility === "fungible") { isFungible = true; } - if (process.env.USE_FACTORY !== 'true') { - console.log('Deploying as upgradeable contracts'); + if (process.env.USE_FACTORY !== "true") { + console.log("Deploying as upgradeable contracts"); // setup via the deployment scripts const deployFunc = isFungible ? deployFungibleUpgradeable @@ -59,19 +59,19 @@ export async function deployZeto(tokenName: string) { // we want to test the effectiveness of the factory contract // to create clones of the Zeto implementation contract - const Factory = await ethers.getContractFactory('ZetoTokenFactory'); + const Factory = await ethers.getContractFactory("ZetoTokenFactory"); const factory = await Factory.deploy(); await factory.waitForDeployment(); const implInfo = { implementation: zetoImpl.target, depositVerifier: - depositVerifier || '0x0000000000000000000000000000000000000000', + depositVerifier || "0x0000000000000000000000000000000000000000", withdrawVerifier: - withdrawVerifier || '0x0000000000000000000000000000000000000000', + withdrawVerifier || "0x0000000000000000000000000000000000000000", verifier, batchVerifier: - batchVerifier || '0x0000000000000000000000000000000000000000', + batchVerifier || "0x0000000000000000000000000000000000000000", }; // console.log(implInfo); const tx1 = await factory @@ -93,7 +93,7 @@ export async function deployZeto(tokenName: string) { let zetoAddress; for (const log of result1!.logs) { const event = factory.interface.parseLog(log as any); - if (event?.name === 'ZetoTokenDeployed') { + if (event?.name === "ZetoTokenDeployed") { zetoAddress = event!.args!.zetoToken; } } diff --git a/solidity/test/lib/utils.ts b/solidity/test/lib/utils.ts index 5b918c3..0034d11 100644 --- a/solidity/test/lib/utils.ts +++ b/solidity/test/lib/utils.ts @@ -19,13 +19,13 @@ import { Signer, BigNumberish, AddressLike, -} from 'ethers'; +} from "ethers"; import { genKeypair, formatPrivKeyForBabyJub, genEcdhSharedKey, -} from 'maci-crypto'; -import { Poseidon, newSalt, tokenUriHash } from 'zeto-js'; +} from "maci-crypto"; +import { Poseidon, newSalt, tokenUriHash } from "zeto-js"; const poseidonHash3 = Poseidon.poseidon3; const poseidonHash4 = Poseidon.poseidon4; @@ -120,7 +120,7 @@ export async function doMint( ) as BigNumberish[]; const tx = await zetoTokenContract .connect(minter) - .mint(outputCommitments, '0x'); + .mint(outputCommitments, "0x"); const result = await tx.wait(); console.log(`Method mint() complete. Gas used: ${result?.gasUsed}`); if (result?.gasUsed && Array.isArray(gasHistories)) { @@ -139,7 +139,7 @@ export async function doDeposit( ): Promise { const tx = await zetoTokenContract .connect(depositUser) - .deposit(amount, commitment, proof, '0x'); + .deposit(amount, commitment, proof, "0x"); const result = await tx.wait(); console.log(`Method deposit() complete. Gas used: ${result?.gasUsed}`); if (result?.gasUsed && Array.isArray(gasHistories)) { @@ -176,14 +176,14 @@ export function parseUTXOEvents( let returnValues: any[] = []; for (const log of result.logs || []) { const event = zetoTokenContract.interface.parseLog(log as any); - if (event?.name === 'UTXOTransfer') { + if (event?.name === "UTXOTransfer") { const transfer = { inputs: event?.args.inputs, outputs: event?.args.outputs, submitter: event?.args.submitter, }; returnValues.push(transfer); - } else if (event?.name === 'UTXOTransferWithEncryptedValues') { + } else if (event?.name === "UTXOTransferWithEncryptedValues") { const transfer = { inputs: event?.args.inputs, outputs: event?.args.outputs, @@ -193,7 +193,7 @@ export function parseUTXOEvents( ecdhPublicKey: event?.args.ecdhPublicKey, }; returnValues.push(transfer); - } else if (event?.name === 'UTXOTransferNonRepudiation') { + } else if (event?.name === "UTXOTransferNonRepudiation") { const transfer = { inputs: event?.args.inputs, outputs: event?.args.outputs, @@ -204,14 +204,14 @@ export function parseUTXOEvents( ecdhPublicKey: event?.args.ecdhPublicKey, }; returnValues.push(transfer); - } else if (event?.name === 'UTXOMint') { + } else if (event?.name === "UTXOMint") { const mint = { outputs: event?.args.outputs, receivers: event?.args.receivers, submitter: event?.args.submitter, }; returnValues.push(mint); - } else if (event?.name === 'TradeCompleted') { + } else if (event?.name === "TradeCompleted") { const e = { tradeId: event?.args.tradeId, trade: event?.args.trade, @@ -228,7 +228,7 @@ export function parseRegistryEvents( ) { for (const log of result.logs || []) { const event = registryContract.interface.parseLog(log as any); - if (event?.name === 'IdentityRegistered') { + if (event?.name === "IdentityRegistered") { return event?.args.publicKey; } } diff --git a/solidity/test/utils.ts b/solidity/test/utils.ts index d1c715b..300659f 100644 --- a/solidity/test/utils.ts +++ b/solidity/test/utils.ts @@ -14,17 +14,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { readFileSync } from 'fs'; -import * as path from 'path'; -import { BigNumberish } from 'ethers'; -import { groth16 } from 'snarkjs'; -import { loadCircuit, encodeProof } from 'zeto-js'; -import { User, UTXO } from './lib/utils'; +import { readFileSync } from "fs"; +import * as path from "path"; +import { BigNumberish } from "ethers"; +import { groth16 } from "snarkjs"; +import { loadCircuit, encodeProof } from "zeto-js"; +import { User, UTXO } from "./lib/utils"; function provingKeysRoot() { const PROVING_KEYS_ROOT = process.env.PROVING_KEYS_ROOT; if (!PROVING_KEYS_ROOT) { - throw new Error('PROVING_KEYS_ROOT env var is not set'); + throw new Error("PROVING_KEYS_ROOT env var is not set"); } return PROVING_KEYS_ROOT; } @@ -56,8 +56,8 @@ export async function prepareDepositProof(signer: User, output: UTXO) { outputOwnerPublicKeys, }; - const circuit = await loadCircuit('check_hashes_value'); - const { provingKeyFile } = loadProvingKeys('check_hashes_value'); + const circuit = await loadCircuit("check_hashes_value"); + const { provingKeyFile } = loadProvingKeys("check_hashes_value"); const startWitnessCalculation = Date.now(); const witness = await circuit.calculateWTNSBin(inputObj, true); @@ -118,8 +118,8 @@ export async function prepareNullifierWithdrawProof( outputSalts: [output.salt], outputOwnerPublicKeys, }; - const circuit = await loadCircuit('check_nullifier_value'); - const { provingKeyFile } = loadProvingKeys('check_nullifier_value'); + const circuit = await loadCircuit("check_nullifier_value"); + const { provingKeyFile } = loadProvingKeys("check_nullifier_value"); const startWitnessCalculation = Date.now(); const witness = await circuit.calculateWTNSBin(inputObj, true); @@ -170,8 +170,8 @@ export async function prepareWithdrawProof( outputSalts: [output.salt], outputOwnerPublicKeys, }; - const circuit = await loadCircuit('check_inputs_outputs_value'); - const { provingKeyFile } = loadProvingKeys('check_inputs_outputs_value'); + const circuit = await loadCircuit("check_inputs_outputs_value"); + const { provingKeyFile } = loadProvingKeys("check_inputs_outputs_value"); const startWitnessCalculation = Date.now(); const witness = await circuit.calculateWTNSBin(inputObj, true); diff --git a/solidity/test/zeto_anon.ts b/solidity/test/zeto_anon.ts index fd3a52d..dc7fe65 100644 --- a/solidity/test/zeto_anon.ts +++ b/solidity/test/zeto_anon.ts @@ -14,12 +14,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, network } from 'hardhat'; -import { Signer, BigNumberish, AddressLike, ZeroAddress } from 'ethers'; -import { expect } from 'chai'; -import { loadCircuit, encodeProof, Poseidon } from 'zeto-js'; -import { groth16 } from 'snarkjs'; -import { formatPrivKeyForBabyJub, stringifyBigInts } from 'maci-crypto'; +import { ethers, network } from "hardhat"; +import { Signer, BigNumberish, AddressLike, ZeroAddress } from "ethers"; +import { expect } from "chai"; +import { loadCircuit, encodeProof, Poseidon } from "zeto-js"; +import { groth16 } from "snarkjs"; +import { formatPrivKeyForBabyJub, stringifyBigInts } from "maci-crypto"; import { User, UTXO, @@ -28,19 +28,19 @@ import { doMint, parseUTXOEvents, ZERO_UTXO, -} from './lib/utils'; +} from "./lib/utils"; import { loadProvingKeys, prepareDepositProof, prepareWithdrawProof, -} from './utils'; -import { Zeto_Anon } from '../typechain-types'; -import { deployZeto } from './lib/deploy'; +} from "./utils"; +import { Zeto_Anon } from "../typechain-types"; +import { deployZeto } from "./lib/deploy"; const ZERO_PUBKEY = [0, 0]; const poseidonHash = Poseidon.poseidon4; -describe('Zeto based fungible token with anonymity without encryption or nullifier', function () { +describe("Zeto based fungible token with anonymity without encryption or nullifier", function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -57,7 +57,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi let batchCircuit: any, batchProvingKey: any; before(async function () { - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { // accommodate for longer block times on public networks this.timeout(120000); } @@ -67,16 +67,16 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi Bob = await newUser(b); Charlie = await newUser(c); - ({ deployer, zeto, erc20 } = await deployZeto('Zeto_Anon')); + ({ deployer, zeto, erc20 } = await deployZeto("Zeto_Anon")); - circuit = await loadCircuit('anon'); - ({ provingKeyFile: provingKey } = loadProvingKeys('anon')); + circuit = await loadCircuit("anon"); + ({ provingKeyFile: provingKey } = loadProvingKeys("anon")); - batchCircuit = await loadCircuit('anon_batch'); - ({ provingKeyFile: batchProvingKey } = loadProvingKeys('anon_batch')); + batchCircuit = await loadCircuit("anon_batch"); + ({ provingKeyFile: batchProvingKey } = loadProvingKeys("anon_batch")); }); - it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; for (let i = 0; i < 10; i++) { @@ -128,7 +128,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi } }); - it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { + it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -145,11 +145,11 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, '0x'); + .deposit(100, outputCommitments[0], encodedProof, "0x"); await tx2.wait(); }); - it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { + it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // first the authority mints UTXOs to Alice utxo1 = newUTXO(10, Alice); @@ -196,7 +196,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi utxo3 = newUTXO(receivedValue, Bob, receivedSalt); }); - it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { + it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // give Bob another UTXO to be able to spend const _utxo1 = newUTXO(20, Bob); @@ -218,7 +218,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi expect(afterTransferBalance).to.equal(startingBalance); }); - it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { + it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice proposes the output ERC20 tokens @@ -238,15 +238,15 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi expect(endingBalance - startingBalance).to.be.equal(80); }); - describe('failure cases', function () { + describe("failure cases", function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { return; } - it('Alice attempting to withdraw spent UTXOs should fail', async function () { + it("Alice attempting to withdraw spent UTXOs should fail", async function () { // Alice proposes the output ERC20 tokens const outputCommitment = newUTXO(90, Alice); @@ -261,22 +261,22 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi zeto .connect(Alice.signer) .withdraw(10, inputCommitments, outputCommitments[0], encodedProof), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }); - it('mint existing unspent UTXOs should fail', async function () { + it("mint existing unspent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('mint existing spent UTXOs should fail', async function () { + it("mint existing spent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadySpent', + "UTXOAlreadySpent", ); }); - it('transfer non-existing UTXOs should fail', async function () { + it("transfer non-existing UTXOs should fail", async function () { const nonExisting1 = newUTXO(10, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); await expect( @@ -286,19 +286,19 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi [nonExisting1, nonExisting2], [Alice, Alice], ), - ).rejectedWith('UTXONotMinted'); + ).rejectedWith("UTXONotMinted"); }); - it('transfer spent UTXOs should fail (double spend protection)', async function () { + it("transfer spent UTXOs should fail (double spend protection)", async function () { // create outputs const utxo5 = newUTXO(25, Bob); const utxo6 = newUTXO(5, Alice, utxo5.salt); await expect( doTransfer(Alice, [utxo1, utxo2], [utxo5, utxo6], [Bob, Alice]), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }); - it('spend by using the same UTXO as both inputs should fail', async function () { + it("spend by using the same UTXO as both inputs should fail", async function () { const utxo5 = newUTXO(20, Alice); const utxo6 = newUTXO(10, Bob, utxo5.salt); await expect( @@ -359,7 +359,7 @@ describe('Zeto based fungible token with anonymity without encryption or nullifi inputCommitments.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works encodedProof, - '0x', + "0x", ); const results = await tx.wait(); console.log(`Method transfer() complete. Gas used: ${results?.gasUsed}`); diff --git a/solidity/test/zeto_anon_enc.ts b/solidity/test/zeto_anon_enc.ts index e813f71..b912edd 100644 --- a/solidity/test/zeto_anon_enc.ts +++ b/solidity/test/zeto_anon_enc.ts @@ -14,23 +14,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, network } from 'hardhat'; -import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; -import { expect } from 'chai'; +import { ethers, network } from "hardhat"; +import { ContractTransactionReceipt, Signer, BigNumberish } from "ethers"; +import { expect } from "chai"; import { loadCircuit, poseidonDecrypt, encodeProof, Poseidon, newEncryptionNonce, -} from 'zeto-js'; -import { groth16 } from 'snarkjs'; +} from "zeto-js"; +import { groth16 } from "snarkjs"; import { genKeypair, formatPrivKeyForBabyJub, genEcdhSharedKey, stringifyBigInts, -} from 'maci-crypto'; +} from "maci-crypto"; import { User, UTXO, @@ -39,17 +39,17 @@ import { doMint, ZERO_UTXO, parseUTXOEvents, -} from './lib/utils'; +} from "./lib/utils"; import { loadProvingKeys, prepareDepositProof, prepareWithdrawProof, -} from './utils'; -import { deployZeto } from './lib/deploy'; +} from "./utils"; +import { deployZeto } from "./lib/deploy"; const poseidonHash = Poseidon.poseidon4; -describe('Zeto based fungible token with anonymity and encryption', function () { +describe("Zeto based fungible token with anonymity and encryption", function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -65,7 +65,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () let batchCircuit: any, batchProvingKey: any; before(async function () { - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { // accommodate for longer block times on public networks this.timeout(120000); } @@ -75,15 +75,15 @@ describe('Zeto based fungible token with anonymity and encryption', function () Bob = await newUser(b); Charlie = await newUser(c); - ({ deployer, zeto, erc20 } = await deployZeto('Zeto_AnonEnc')); + ({ deployer, zeto, erc20 } = await deployZeto("Zeto_AnonEnc")); - circuit = await loadCircuit('anon_enc'); - ({ provingKeyFile: provingKey } = loadProvingKeys('anon_enc')); - batchCircuit = await loadCircuit('anon_enc_batch'); - ({ provingKeyFile: batchProvingKey } = loadProvingKeys('anon_enc_batch')); + circuit = await loadCircuit("anon_enc"); + ({ provingKeyFile: provingKey } = loadProvingKeys("anon_enc")); + batchCircuit = await loadCircuit("anon_enc_batch"); + ({ provingKeyFile: batchProvingKey } = loadProvingKeys("anon_enc_batch")); }); - it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; for (let i = 0; i < 10; i++) { @@ -148,7 +148,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () } }); - it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { + it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -165,11 +165,11 @@ describe('Zeto based fungible token with anonymity and encryption', function () ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, '0x'); + .deposit(100, outputCommitments[0], encodedProof, "0x"); await tx2.wait(); }); - it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { + it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // first the authority mints UTXOs to Alice utxo1 = newUTXO(10, Alice); @@ -227,7 +227,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () utxo3 = newUTXO(Number(plainText[0]), Bob, plainText[1]); }); - it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { + it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { // propose the output UTXOs const _utxo1 = newUTXO(25, Charlie); // Bob should be able to spend the UTXO that was reconstructed from the previous transaction @@ -239,7 +239,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () ); }); - it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { + it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice proposes the output ERC20 tokens const outputCommitment = newUTXO(20, Alice); @@ -258,15 +258,15 @@ describe('Zeto based fungible token with anonymity and encryption', function () expect(endingBalance - startingBalance).to.be.equal(80); }); - describe('failure cases', function () { + describe("failure cases", function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { return; } - it('Alice attempting to withdraw spent UTXOs should fail', async function () { + it("Alice attempting to withdraw spent UTXOs should fail", async function () { // Alice proposes the output ERC20 tokens const outputCommitment = newUTXO(90, Alice); @@ -281,22 +281,22 @@ describe('Zeto based fungible token with anonymity and encryption', function () zeto .connect(Alice.signer) .withdraw(10, inputCommitments, outputCommitments[0], encodedProof), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }); - it('mint existing unspent UTXOs should fail', async function () { + it("mint existing unspent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('mint existing spent UTXOs should fail', async function () { + it("mint existing spent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadySpent', + "UTXOAlreadySpent", ); }); - it('transfer non-existing UTXOs should fail', async function () { + it("transfer non-existing UTXOs should fail", async function () { const nonExisting1 = newUTXO(10, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); await expect( @@ -306,19 +306,19 @@ describe('Zeto based fungible token with anonymity and encryption', function () [nonExisting1, nonExisting2], [Alice, Alice], ), - ).rejectedWith('UTXONotMinted'); + ).rejectedWith("UTXONotMinted"); }); - it('transfer spent UTXOs should fail (double spend protection)', async function () { + it("transfer spent UTXOs should fail (double spend protection)", async function () { // create outputs const _utxo1 = newUTXO(25, Bob); const _utxo2 = newUTXO(5, Alice); await expect( doTransfer(Alice, [utxo1, utxo2], [_utxo1, _utxo2], [Bob, Alice]), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }); - it('spend by using the same UTXO as both inputs should fail', async function () { + it("spend by using the same UTXO as both inputs should fail", async function () { // mint a new UTXO to Bob const _utxo1 = newUTXO(20, Bob); await doMint(zeto, deployer, [_utxo1]); @@ -465,7 +465,7 @@ describe('Zeto based fungible token with anonymity and encryption', function () ecdhPublicKey, encryptedValues, encodedProof, - '0x', + "0x", ); const results: ContractTransactionReceipt | null = await tx.wait(); diff --git a/solidity/test/zeto_anon_enc_nullifier.ts b/solidity/test/zeto_anon_enc_nullifier.ts index 99a2977..d621def 100644 --- a/solidity/test/zeto_anon_enc_nullifier.ts +++ b/solidity/test/zeto_anon_enc_nullifier.ts @@ -14,24 +14,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, network } from 'hardhat'; -import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; -import { expect } from 'chai'; +import { ethers, network } from "hardhat"; +import { ContractTransactionReceipt, Signer, BigNumberish } from "ethers"; +import { expect } from "chai"; import { loadCircuit, poseidonDecrypt, encodeProof, Poseidon, newEncryptionNonce, -} from 'zeto-js'; -import { groth16 } from 'snarkjs'; +} from "zeto-js"; +import { groth16 } from "snarkjs"; import { genKeypair, formatPrivKeyForBabyJub, genEcdhSharedKey, stringifyBigInts, -} from 'maci-crypto'; -import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; +} from "maci-crypto"; +import { Merkletree, InMemoryDB, str2Bytes } from "@iden3/js-merkletree"; import { UTXO, User, @@ -41,16 +41,16 @@ import { doMint, ZERO_UTXO, parseUTXOEvents, -} from './lib/utils'; +} from "./lib/utils"; import { loadProvingKeys, prepareDepositProof, prepareNullifierWithdrawProof, -} from './utils'; -import { deployZeto } from './lib/deploy'; +} from "./utils"; +import { deployZeto } from "./lib/deploy"; const poseidonHash = Poseidon.poseidon4; -describe('Zeto based fungible token with anonymity using nullifiers and encryption', function () { +describe("Zeto based fungible token with anonymity using nullifiers and encryption", function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -69,7 +69,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let smtBob: Merkletree; before(async function () { - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { // accommodate for longer block times on public networks this.timeout(120000); } @@ -79,30 +79,30 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti Bob = await newUser(b); Charlie = await newUser(c); - ({ deployer, zeto, erc20 } = await deployZeto('Zeto_AnonEncNullifier')); + ({ deployer, zeto, erc20 } = await deployZeto("Zeto_AnonEncNullifier")); - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, 64); - const storage2 = new InMemoryDB(str2Bytes('')); + const storage2 = new InMemoryDB(str2Bytes("")); smtBob = new Merkletree(storage2, true, 64); - circuit = await loadCircuit('anon_enc_nullifier'); - ({ provingKeyFile: provingKey } = loadProvingKeys('anon_enc_nullifier')); - batchCircuit = await loadCircuit('anon_enc_nullifier_batch'); + circuit = await loadCircuit("anon_enc_nullifier"); + ({ provingKeyFile: provingKey } = loadProvingKeys("anon_enc_nullifier")); + batchCircuit = await loadCircuit("anon_enc_nullifier_batch"); ({ provingKeyFile: batchProvingKey } = loadProvingKeys( - 'anon_enc_nullifier_batch', + "anon_enc_nullifier_batch", )); }); - it('onchain SMT root should be equal to the offchain SMT root', async function () { + it("onchain SMT root should be equal to the offchain SMT root", async function () { const root = await smtAlice.root(); const onchainRoot = await zeto.getRoot(); expect(onchainRoot).to.equal(0n); expect(root.string()).to.equal(onchainRoot.toString()); }); - it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; const nullifiers = []; @@ -197,7 +197,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti } }); - it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { + it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -214,14 +214,14 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, '0x'); + .deposit(100, outputCommitments[0], encodedProof, "0x"); await tx2.wait(); await smtAlice.add(utxo100.hash, utxo100.hash); await smtBob.add(utxo100.hash, utxo100.hash); }); - it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { + it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // The authority mints a new UTXO and assigns it to Alice utxo1 = newUTXO(10, Alice); @@ -309,7 +309,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti utxo3 = newUTXO(Number(plainText[0]), Bob, plainText[1]); }).timeout(600000); - it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { + it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { // Bob generates the nullifiers for the UTXO to be spent const nullifier1 = newNullifier(utxo3, Bob); @@ -347,7 +347,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti await smtAlice.add(events[0].outputs[1], events[0].outputs[1]); }).timeout(600000); - it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { + it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice generates the nullifiers for the UTXOs to be spent @@ -400,15 +400,15 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti expect(endingBalance - startingBalance).to.be.equal(80); }); - describe('failure cases', function () { + describe("failure cases", function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { return; } - it('Alice attempting to withdraw spent UTXOs should fail', async function () { + it("Alice attempting to withdraw spent UTXOs should fail", async function () { // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); @@ -448,22 +448,22 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti root.bigInt(), encodedProof, ), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }); - it('mint existing unspent UTXOs should fail', async function () { + it("mint existing unspent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('mint existing spent UTXOs should fail', async function () { + it("mint existing spent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('transfer spent UTXOs should fail (double spend protection)', async function () { + it("transfer spent UTXOs should fail (double spend protection)", async function () { // create outputs const _utxo1 = newUTXO(25, Bob); const _utxo2 = newUTXO(5, Alice); @@ -497,10 +497,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs, [Bob, Alice], ), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }).timeout(600000); - it('transfer with existing UTXOs in the output should fail (mass conservation protection)', async function () { + it("transfer with existing UTXOs in the output should fail (mass conservation protection)", async function () { // give Bob another UTXO to be able to spend const _utxo1 = newUTXO(15, Bob); await doMint(zeto, deployer, [_utxo1]); @@ -529,10 +529,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs, [Alice, Alice], ), - ).rejectedWith('UTXOAlreadyOwned'); + ).rejectedWith("UTXOAlreadyOwned"); }).timeout(600000); - it('spend by using the same UTXO as both inputs should fail', async function () { + it("spend by using the same UTXO as both inputs should fail", async function () { const _utxo1 = newUTXO(20, Alice); const _utxo2 = newUTXO(10, Bob); const nullifier1 = newNullifier(utxo7, Bob); @@ -559,7 +559,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ).rejectedWith(`UTXODuplicate`); }).timeout(600000); - it('transfer non-existing UTXOs should fail', async function () { + it("transfer non-existing UTXOs should fail", async function () { const nonExisting1 = newUTXO(25, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); @@ -600,10 +600,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs, [Bob, Charlie], ), - ).rejectedWith('UTXORootNotFound'); + ).rejectedWith("UTXORootNotFound"); }).timeout(600000); - it('repeated mint calls with single UTXO should not fail', async function () { + it("repeated mint calls with single UTXO should not fail", async function () { const utxo5 = newUTXO(10, Alice); await expect(doMint(zeto, deployer, [utxo5, ZERO_UTXO])).fulfilled; const utxo6 = newUTXO(20, Alice); @@ -767,7 +767,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ecdhPublicKey, encryptedValues, encodedProof, - '0x', + "0x", ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( diff --git a/solidity/test/zeto_anon_enc_nullifier_kyc.ts b/solidity/test/zeto_anon_enc_nullifier_kyc.ts index dcc8832..c801e9c 100644 --- a/solidity/test/zeto_anon_enc_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_enc_nullifier_kyc.ts @@ -14,9 +14,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, network } from 'hardhat'; -import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; -import { expect } from 'chai'; +import { ethers, network } from "hardhat"; +import { ContractTransactionReceipt, Signer, BigNumberish } from "ethers"; +import { expect } from "chai"; import { loadCircuit, poseidonDecrypt, @@ -24,15 +24,15 @@ import { Poseidon, newEncryptionNonce, kycHash, -} from 'zeto-js'; -import { groth16 } from 'snarkjs'; +} from "zeto-js"; +import { groth16 } from "snarkjs"; import { genKeypair, formatPrivKeyForBabyJub, genEcdhSharedKey, stringifyBigInts, -} from 'maci-crypto'; -import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; +} from "maci-crypto"; +import { Merkletree, InMemoryDB, str2Bytes } from "@iden3/js-merkletree"; import { UTXO, User, @@ -43,16 +43,16 @@ import { ZERO_UTXO, parseUTXOEvents, parseRegistryEvents, -} from './lib/utils'; +} from "./lib/utils"; import { loadProvingKeys, prepareDepositProof, prepareNullifierWithdrawProof, -} from './utils'; -import { deployZeto } from './lib/deploy'; +} from "./utils"; +import { deployZeto } from "./lib/deploy"; const poseidonHash = Poseidon.poseidon4; -describe('Zeto based fungible token with anonymity using nullifiers and encryption with KYC', function () { +describe("Zeto based fungible token with anonymity using nullifiers and encryption with KYC", function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -77,7 +77,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let smtUnregistered: Merkletree; before(async function () { - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { // accommodate for longer block times on public networks this.timeout(120000); } @@ -88,7 +88,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti Charlie = await newUser(c); unregistered = await newUser(e); - ({ deployer, zeto, erc20 } = await deployZeto('Zeto_AnonEncNullifierKyc')); + ({ deployer, zeto, erc20 } = await deployZeto("Zeto_AnonEncNullifierKyc")); const tx2 = await zeto.connect(deployer).register(Alice.babyJubPublicKey); const result1 = await tx2.wait(); @@ -97,16 +97,16 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const tx4 = await zeto.connect(deployer).register(Charlie.babyJubPublicKey); const result3 = await tx4.wait(); - const storage1 = new InMemoryDB(str2Bytes('alice')); + const storage1 = new InMemoryDB(str2Bytes("alice")); smtAlice = new Merkletree(storage1, true, 64); - const storage2 = new InMemoryDB(str2Bytes('bob')); + const storage2 = new InMemoryDB(str2Bytes("bob")); smtBob = new Merkletree(storage2, true, 64); - const storage3 = new InMemoryDB(str2Bytes('kyc')); + const storage3 = new InMemoryDB(str2Bytes("kyc")); smtKyc = new Merkletree(storage3, true, 10); - const storage4 = new InMemoryDB(str2Bytes('unregistered')); + const storage4 = new InMemoryDB(str2Bytes("unregistered")); smtUnregistered = new Merkletree(storage4, true, 64); const publicKey1 = parseRegistryEvents(zeto, result1); @@ -116,24 +116,24 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti const publicKey3 = parseRegistryEvents(zeto, result3); await smtKyc.add(kycHash(publicKey3), kycHash(publicKey3)); - circuit = await loadCircuit('anon_enc_nullifier_kyc'); + circuit = await loadCircuit("anon_enc_nullifier_kyc"); ({ provingKeyFile: provingKey } = loadProvingKeys( - 'anon_enc_nullifier_kyc', + "anon_enc_nullifier_kyc", )); - batchCircuit = await loadCircuit('anon_enc_nullifier_kyc_batch'); + batchCircuit = await loadCircuit("anon_enc_nullifier_kyc_batch"); ({ provingKeyFile: batchProvingKey } = loadProvingKeys( - 'anon_enc_nullifier_kyc_batch', + "anon_enc_nullifier_kyc_batch", )); }); - it('onchain SMT root should be equal to the offchain SMT root', async function () { + it("onchain SMT root should be equal to the offchain SMT root", async function () { const root = await smtAlice.root(); const onchainRoot = await zeto.getRoot(); expect(onchainRoot).to.equal(0n); expect(root.string()).to.equal(onchainRoot.toString()); }); - it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; const nullifiers = []; @@ -247,7 +247,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti } }); - it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { + it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -264,14 +264,14 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, '0x'); + .deposit(100, outputCommitments[0], encodedProof, "0x"); await tx2.wait(); await smtAlice.add(utxo100.hash, utxo100.hash); await smtBob.add(utxo100.hash, utxo100.hash); }); - it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { + it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // The authority mints a new UTXO and assigns it to Alice utxo1 = newUTXO(10, Alice); @@ -382,7 +382,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti utxo3 = newUTXO(Number(plainText[0]), Bob, plainText[1]); }).timeout(600000); - it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { + it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { // Bob generates the nullifiers for the UTXO to be spent const nullifier1 = newNullifier(utxo3, Bob); @@ -442,7 +442,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti await smtAlice.add(events[0].outputs[1], events[0].outputs[1]); }).timeout(600000); - it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { + it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice generates the nullifiers for the UTXOs to be spent @@ -495,10 +495,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti expect(endingBalance - startingBalance).to.be.equal(80); }); - describe('unregistered user cases', function () { + describe("unregistered user cases", function () { let unregisteredUtxo100: UTXO; - it('deposit by an unregistered user should succeed', async function () { + it("deposit by an unregistered user should succeed", async function () { const tx = await erc20 .connect(deployer) .mint(unregistered.ethAddress, 100); @@ -515,7 +515,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ); const tx2 = await zeto .connect(unregistered.signer) - .deposit(100, outputCommitments[0], encodedProof, '0x'); + .deposit(100, outputCommitments[0], encodedProof, "0x"); await tx2.wait(); // Alice tracks the UTXO inside the SMT @@ -524,7 +524,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti await smtBob.add(unregisteredUtxo100.hash, unregisteredUtxo100.hash); }); - it('transfer from an unregistered user should fail', async function () { + it("transfer from an unregistered user should fail", async function () { // catch up the local SMT for the unregistered user await smtUnregistered.add(utxo100.hash, utxo100.hash); await smtUnregistered.add(utxo1.hash, utxo1.hash); @@ -586,10 +586,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti identitiesMerkleProofs, [Bob, unregistered], ), - ).rejectedWith('Invalid proof'); + ).rejectedWith("Invalid proof"); }); - it('the unregistered user can still withdraw their UTXOs to ERC20 tokens', async function () { + it("the unregistered user can still withdraw their UTXOs to ERC20 tokens", async function () { const startingBalance = await erc20.balanceOf(unregistered.ethAddress); // unregistered user generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(unregisteredUtxo100, unregistered); @@ -651,15 +651,15 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti }); }); - describe('failure cases', function () { + describe("failure cases", function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { return; } - it('Alice attempting to withdraw spent UTXOs should fail', async function () { + it("Alice attempting to withdraw spent UTXOs should fail", async function () { // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); @@ -699,22 +699,22 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti root.bigInt(), encodedProof, ), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }); - it('mint existing unspent UTXOs should fail', async function () { + it("mint existing unspent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('mint existing spent UTXOs should fail', async function () { + it("mint existing spent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('transfer spent UTXOs should fail (double spend protection)', async function () { + it("transfer spent UTXOs should fail (double spend protection)", async function () { // create outputs const _utxo1 = newUTXO(25, Bob); const _utxo2 = newUTXO(5, Alice); @@ -765,10 +765,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti identitiesMerkleProofs, [Bob, Alice], ), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }).timeout(600000); - it('transfer with existing UTXOs in the output should fail (mass conservation protection)', async function () { + it("transfer with existing UTXOs in the output should fail (mass conservation protection)", async function () { // give Bob another UTXO to be able to spend const _utxo1 = newUTXO(15, Bob); await doMint(zeto, deployer, [_utxo1]); @@ -814,10 +814,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti identitiesMerkleProofs, [Alice, Alice], ), - ).rejectedWith('UTXOAlreadyOwned'); + ).rejectedWith("UTXOAlreadyOwned"); }).timeout(600000); - it('spend by using the same UTXO as both inputs should fail', async function () { + it("spend by using the same UTXO as both inputs should fail", async function () { const _utxo1 = newUTXO(20, Alice); const _utxo2 = newUTXO(10, Bob); const nullifier1 = newNullifier(utxo7, Bob); @@ -861,7 +861,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ).rejectedWith(`UTXODuplicate`); }).timeout(600000); - it('transfer non-existing UTXOs should fail', async function () { + it("transfer non-existing UTXOs should fail", async function () { const nonExisting1 = newUTXO(25, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); @@ -923,7 +923,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti identitiesMerkleProofs, [Bob, Charlie], ), - ).rejectedWith('UTXORootNotFound'); + ).rejectedWith("UTXORootNotFound"); }).timeout(600000); }); @@ -1092,7 +1092,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ecdhPublicKey, encryptedValues, encodedProof, - '0x', + "0x", ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( diff --git a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts index 49d093a..a7c785a 100644 --- a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts +++ b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts @@ -14,24 +14,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, network } from 'hardhat'; -import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; -import { expect } from 'chai'; +import { ethers, network } from "hardhat"; +import { ContractTransactionReceipt, Signer, BigNumberish } from "ethers"; +import { expect } from "chai"; import { loadCircuit, poseidonDecrypt, encodeProof, Poseidon, newEncryptionNonce, -} from 'zeto-js'; -import { groth16 } from 'snarkjs'; +} from "zeto-js"; +import { groth16 } from "snarkjs"; import { genKeypair, formatPrivKeyForBabyJub, genEcdhSharedKey, stringifyBigInts, -} from 'maci-crypto'; -import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; +} from "maci-crypto"; +import { Merkletree, InMemoryDB, str2Bytes } from "@iden3/js-merkletree"; import { UTXO, User, @@ -41,16 +41,16 @@ import { doMint, ZERO_UTXO, parseUTXOEvents, -} from './lib/utils'; +} from "./lib/utils"; import { loadProvingKeys, prepareDepositProof, prepareNullifierWithdrawProof, -} from './utils'; -import { deployZeto } from './lib/deploy'; +} from "./utils"; +import { deployZeto } from "./lib/deploy"; const poseidonHash = Poseidon.poseidon4; -describe('Zeto based fungible token with anonymity using nullifiers and encryption for non-repudiation', function () { +describe("Zeto based fungible token with anonymity using nullifiers and encryption for non-repudiation", function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -70,7 +70,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti let smtBob: Merkletree; before(async function () { - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { // accommodate for longer block times on public networks this.timeout(120000); } @@ -82,7 +82,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti Authority = await newUser(e); ({ deployer, zeto, erc20 } = await deployZeto( - 'Zeto_AnonEncNullifierNonRepudiation', + "Zeto_AnonEncNullifierNonRepudiation", )); const tx1 = await zeto @@ -90,32 +90,32 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti .setArbiter(Authority.babyJubPublicKey); await tx1.wait(); - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, 64); - const storage2 = new InMemoryDB(str2Bytes('')); + const storage2 = new InMemoryDB(str2Bytes("")); smtBob = new Merkletree(storage2, true, 64); - circuit = await loadCircuit('anon_enc_nullifier_non_repudiation'); + circuit = await loadCircuit("anon_enc_nullifier_non_repudiation"); ({ provingKeyFile: provingKey } = loadProvingKeys( - 'anon_enc_nullifier_non_repudiation', + "anon_enc_nullifier_non_repudiation", )); batchCircuit = await loadCircuit( - 'anon_enc_nullifier_non_repudiation_batch', + "anon_enc_nullifier_non_repudiation_batch", ); ({ provingKeyFile: batchProvingKey } = loadProvingKeys( - 'anon_enc_nullifier_non_repudiation_batch', + "anon_enc_nullifier_non_repudiation_batch", )); }); - it('onchain SMT root should be equal to the offchain SMT root', async function () { + it("onchain SMT root should be equal to the offchain SMT root", async function () { const root = await smtAlice.root(); const onchainRoot = await zeto.getRoot(); expect(onchainRoot).to.equal(0n); expect(root.string()).to.equal(onchainRoot.toString()); }); - it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; const nullifiers = []; @@ -254,7 +254,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti } }); - it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { + it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -271,14 +271,14 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, '0x'); + .deposit(100, outputCommitments[0], encodedProof, "0x"); await tx2.wait(); await smtAlice.add(utxo100.hash, utxo100.hash); await smtBob.add(utxo100.hash, utxo100.hash); }); - it('mint to Alice and transfer UTXOs honestly to Bob should succeed and verifiable by the regulator', async function () { + it("mint to Alice and transfer UTXOs honestly to Bob should succeed and verifiable by the regulator", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // The authority mints a new UTXO and assigns it to Alice utxo1 = newUTXO(10, Alice); @@ -423,7 +423,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti utxo3 = newUTXO(Number(plainText1[0]), Bob, plainText1[1]); }).timeout(600000); - it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { + it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { // Bob generates the nullifiers for the UTXO to be spent const nullifier1 = newNullifier(utxo3, Bob); @@ -461,7 +461,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti await smtAlice.add(events[0].outputs[1], events[0].outputs[1]); }).timeout(600000); - it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { + it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); @@ -513,15 +513,15 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti expect(endingBalance - startingBalance).to.be.equal(80); }); - describe('failure cases', function () { + describe("failure cases", function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { return; } - it('Alice attempting to withdraw spent UTXOs should fail', async function () { + it("Alice attempting to withdraw spent UTXOs should fail", async function () { // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); @@ -561,22 +561,22 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti root.bigInt(), encodedProof, ), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }); - it('mint existing unspent UTXOs should fail', async function () { + it("mint existing unspent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('mint existing spent UTXOs should fail', async function () { + it("mint existing spent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('transfer spent UTXOs should fail (double spend protection)', async function () { + it("transfer spent UTXOs should fail (double spend protection)", async function () { // create outputs const _utxo1 = newUTXO(25, Bob); const _utxo2 = newUTXO(5, Alice); @@ -610,10 +610,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs, [Bob, Alice], ), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }).timeout(600000); - it('transfer with existing UTXOs in the output should fail (mass conservation protection)', async function () { + it("transfer with existing UTXOs in the output should fail (mass conservation protection)", async function () { // give Bob another UTXO to be able to spend const _utxo1 = newUTXO(15, Bob); await doMint(zeto, deployer, [_utxo1]); @@ -642,10 +642,10 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs, [Alice, Alice], ), - ).rejectedWith('UTXOAlreadyOwned'); + ).rejectedWith("UTXOAlreadyOwned"); }).timeout(600000); - it('spend by using the same UTXO as both inputs should fail', async function () { + it("spend by using the same UTXO as both inputs should fail", async function () { const _utxo1 = newUTXO(20, Alice); const _utxo2 = newUTXO(10, Bob); const nullifier1 = newNullifier(utxo7, Bob); @@ -672,7 +672,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti ).rejectedWith(`UTXODuplicate`); }).timeout(600000); - it('transfer non-existing UTXOs should fail', async function () { + it("transfer non-existing UTXOs should fail", async function () { const nonExisting1 = newUTXO(25, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); @@ -713,7 +713,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti merkleProofs, [Bob, Charlie], ), - ).rejectedWith('UTXORootNotFound'); + ).rejectedWith("UTXORootNotFound"); }).timeout(600000); }); @@ -878,7 +878,7 @@ describe('Zeto based fungible token with anonymity using nullifiers and encrypti encryptedValuesForReceiver, encryptedValuesForRegulator, encodedProof, - '0x', + "0x", ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( diff --git a/solidity/test/zeto_anon_nullifier.ts b/solidity/test/zeto_anon_nullifier.ts index 72a63bb..9a32bfe 100644 --- a/solidity/test/zeto_anon_nullifier.ts +++ b/solidity/test/zeto_anon_nullifier.ts @@ -14,12 +14,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, network } from 'hardhat'; -import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; -import { expect } from 'chai'; -import { loadCircuit, Poseidon, encodeProof } from 'zeto-js'; -import { groth16 } from 'snarkjs'; -import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; +import { ethers, network } from "hardhat"; +import { ContractTransactionReceipt, Signer, BigNumberish } from "ethers"; +import { expect } from "chai"; +import { loadCircuit, Poseidon, encodeProof } from "zeto-js"; +import { groth16 } from "snarkjs"; +import { Merkletree, InMemoryDB, str2Bytes } from "@iden3/js-merkletree"; import { UTXO, User, @@ -29,15 +29,15 @@ import { doMint, ZERO_UTXO, parseUTXOEvents, -} from './lib/utils'; +} from "./lib/utils"; import { loadProvingKeys, prepareDepositProof, prepareNullifierWithdrawProof, -} from './utils'; -import { deployZeto } from './lib/deploy'; +} from "./utils"; +import { deployZeto } from "./lib/deploy"; -describe('Zeto based fungible token with anonymity using nullifiers without encryption', function () { +describe("Zeto based fungible token with anonymity using nullifiers without encryption", function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -56,7 +56,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr let smtBob: Merkletree; before(async function () { - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { // accommodate for longer block times on public networks this.timeout(120000); } @@ -67,29 +67,29 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr Bob = await newUser(b); Charlie = await newUser(c); - ({ deployer, zeto, erc20 } = await deployZeto('Zeto_AnonNullifier')); + ({ deployer, zeto, erc20 } = await deployZeto("Zeto_AnonNullifier")); - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, 64); - const storage2 = new InMemoryDB(str2Bytes('')); + const storage2 = new InMemoryDB(str2Bytes("")); smtBob = new Merkletree(storage2, true, 64); - circuit = await loadCircuit('anon_nullifier'); - ({ provingKeyFile: provingKey } = loadProvingKeys('anon_nullifier')); - batchCircuit = await loadCircuit('anon_nullifier_batch'); + circuit = await loadCircuit("anon_nullifier"); + ({ provingKeyFile: provingKey } = loadProvingKeys("anon_nullifier")); + batchCircuit = await loadCircuit("anon_nullifier_batch"); ({ provingKeyFile: batchProvingKey } = loadProvingKeys( - 'anon_nullifier_batch', + "anon_nullifier_batch", )); }); - it('onchain SMT root should be equal to the offchain SMT root', async function () { + it("onchain SMT root should be equal to the offchain SMT root", async function () { const root = await smtAlice.root(); const onchainRoot = await zeto.getRoot(); expect(onchainRoot).to.equal(0n); expect(root.string()).to.equal(onchainRoot.toString()); }); - it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; const nullifiers = []; @@ -171,7 +171,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr } }); - it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { + it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -188,14 +188,14 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, '0x'); + .deposit(100, outputCommitments[0], encodedProof, "0x"); await tx2.wait(); await smtAlice.add(utxo100.hash, utxo100.hash); await smtBob.add(utxo100.hash, utxo100.hash); }); - it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { + it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // The authority mints a new UTXO and assigns it to Alice utxo1 = newUTXO(10, Alice); @@ -283,7 +283,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr utxo3 = newUTXO(receivedValue, Bob, receivedSalt); }).timeout(600000); - it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { + it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { // Bob generates the nullifiers for the UTXO to be spent const nullifier1 = newNullifier(utxo3, Bob); @@ -321,7 +321,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr await smtAlice.add(events[0].outputs[1], events[0].outputs[1]); }).timeout(600000); - it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { + it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice generates the nullifiers for the UTXOs to be spent @@ -374,15 +374,15 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr expect(endingBalance - startingBalance).to.be.equal(80); }); - describe('failure cases', function () { + describe("failure cases", function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { return; } - it('Alice attempting to withdraw spent UTXOs should fail', async function () { + it("Alice attempting to withdraw spent UTXOs should fail", async function () { // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); @@ -421,22 +421,22 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr root.bigInt(), encodedProof, ), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }); - it('mint existing unspent UTXOs should fail', async function () { + it("mint existing unspent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('mint existing spent UTXOs should fail', async function () { + it("mint existing spent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('transfer spent UTXOs should fail (double spend protection)', async function () { + it("transfer spent UTXOs should fail (double spend protection)", async function () { // create outputs const _utxo1 = newUTXO(25, Bob); const _utxo2 = newUTXO(5, Alice); @@ -470,10 +470,10 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr merkleProofs, [Bob, Alice], ), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }).timeout(600000); - it('transfer with existing UTXOs in the output should fail (mass conservation protection)', async function () { + it("transfer with existing UTXOs in the output should fail (mass conservation protection)", async function () { // give Bob another UTXO to be able to spend const _utxo1 = newUTXO(15, Bob); await doMint(zeto, deployer, [_utxo1]); @@ -502,10 +502,10 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr merkleProofs, [Alice, Alice], ), - ).rejectedWith('UTXOAlreadyOwned'); + ).rejectedWith("UTXOAlreadyOwned"); }).timeout(600000); - it('spend by using the same UTXO as both inputs should fail', async function () { + it("spend by using the same UTXO as both inputs should fail", async function () { const _utxo1 = newUTXO(20, Alice); const _utxo2 = newUTXO(10, Bob); const nullifier1 = newNullifier(utxo7, Bob); @@ -532,7 +532,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr ).rejectedWith(`UTXODuplicate`); }).timeout(600000); - it('transfer non-existing UTXOs should fail', async function () { + it("transfer non-existing UTXOs should fail", async function () { const nonExisting1 = newUTXO(25, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); @@ -573,10 +573,10 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr merkleProofs, [Bob, Charlie], ), - ).rejectedWith('UTXORootNotFound'); + ).rejectedWith("UTXORootNotFound"); }).timeout(600000); - it('repeated mint calls with single UTXO should not fail', async function () { + it("repeated mint calls with single UTXO should not fail", async function () { const utxo5 = newUTXO(10, Alice); await expect(doMint(zeto, deployer, [utxo5, ZERO_UTXO])).fulfilled; const utxo6 = newUTXO(20, Alice); @@ -713,7 +713,7 @@ describe('Zeto based fungible token with anonymity using nullifiers without encr outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works root, encodedProof, - '0x', + "0x", ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( diff --git a/solidity/test/zeto_anon_nullifier_kyc.ts b/solidity/test/zeto_anon_nullifier_kyc.ts index c0a4dfd..72bc1ac 100644 --- a/solidity/test/zeto_anon_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_nullifier_kyc.ts @@ -14,12 +14,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, network } from 'hardhat'; -import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; -import { expect } from 'chai'; -import { loadCircuit, Poseidon, encodeProof, kycHash } from 'zeto-js'; -import { groth16 } from 'snarkjs'; -import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; +import { ethers, network } from "hardhat"; +import { ContractTransactionReceipt, Signer, BigNumberish } from "ethers"; +import { expect } from "chai"; +import { loadCircuit, Poseidon, encodeProof, kycHash } from "zeto-js"; +import { groth16 } from "snarkjs"; +import { Merkletree, InMemoryDB, str2Bytes } from "@iden3/js-merkletree"; import { UTXO, User, @@ -30,15 +30,15 @@ import { ZERO_UTXO, parseUTXOEvents, parseRegistryEvents, -} from './lib/utils'; +} from "./lib/utils"; import { loadProvingKeys, prepareDepositProof, prepareNullifierWithdrawProof, -} from './utils'; -import { deployZeto } from './lib/deploy'; +} from "./utils"; +import { deployZeto } from "./lib/deploy"; -describe('Zeto based fungible token with anonymity, KYC, using nullifiers without encryption', function () { +describe("Zeto based fungible token with anonymity, KYC, using nullifiers without encryption", function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -63,7 +63,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou let smtUnregistered: Merkletree; before(async function () { - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { // accommodate for longer block times on public networks this.timeout(120000); } @@ -74,7 +74,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou Charlie = await newUser(c); unregistered = await newUser(e); - ({ deployer, zeto, erc20 } = await deployZeto('Zeto_AnonNullifierKyc')); + ({ deployer, zeto, erc20 } = await deployZeto("Zeto_AnonNullifierKyc")); const tx2 = await zeto.connect(deployer).register(Alice.babyJubPublicKey); const result1 = await tx2.wait(); @@ -83,16 +83,16 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const tx4 = await zeto.connect(deployer).register(Charlie.babyJubPublicKey); const result3 = await tx4.wait(); - const storage1 = new InMemoryDB(str2Bytes('alice')); + const storage1 = new InMemoryDB(str2Bytes("alice")); smtAlice = new Merkletree(storage1, true, 64); - const storage2 = new InMemoryDB(str2Bytes('bob')); + const storage2 = new InMemoryDB(str2Bytes("bob")); smtBob = new Merkletree(storage2, true, 64); - const storage3 = new InMemoryDB(str2Bytes('kyc')); + const storage3 = new InMemoryDB(str2Bytes("kyc")); smtKyc = new Merkletree(storage3, true, 10); - const storage4 = new InMemoryDB(str2Bytes('unregistered')); + const storage4 = new InMemoryDB(str2Bytes("unregistered")); smtUnregistered = new Merkletree(storage4, true, 64); const publicKey1 = parseRegistryEvents(zeto, result1); @@ -102,22 +102,22 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou const publicKey3 = parseRegistryEvents(zeto, result3); await smtKyc.add(kycHash(publicKey3), kycHash(publicKey3)); - circuit = await loadCircuit('anon_nullifier_kyc'); - ({ provingKeyFile: provingKey } = loadProvingKeys('anon_nullifier_kyc')); - batchCircuit = await loadCircuit('anon_nullifier_kyc_batch'); + circuit = await loadCircuit("anon_nullifier_kyc"); + ({ provingKeyFile: provingKey } = loadProvingKeys("anon_nullifier_kyc")); + batchCircuit = await loadCircuit("anon_nullifier_kyc_batch"); ({ provingKeyFile: batchProvingKey } = loadProvingKeys( - 'anon_nullifier_kyc_batch', + "anon_nullifier_kyc_batch", )); }); - it('onchain SMT root should be equal to the offchain SMT root', async function () { + it("onchain SMT root should be equal to the offchain SMT root", async function () { const root = await smtAlice.root(); const onchainRoot = await zeto.getRoot(); expect(onchainRoot).to.equal(0n); expect(root.string()).to.equal(onchainRoot.toString()); }); - it('(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed', async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; const nullifiers = []; @@ -218,7 +218,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou } }); - it('mint ERC20 tokens to Alice to deposit to Zeto should succeed', async function () { + it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100); await tx.wait(); @@ -235,14 +235,14 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou ); const tx2 = await zeto .connect(Alice.signer) - .deposit(100, outputCommitments[0], encodedProof, '0x'); + .deposit(100, outputCommitments[0], encodedProof, "0x"); await tx2.wait(); await smtAlice.add(utxo100.hash, utxo100.hash); await smtBob.add(utxo100.hash, utxo100.hash); }); - it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { + it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // The authority mints a new UTXO and assigns it to Alice utxo1 = newUTXO(10, Alice); @@ -354,7 +354,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou utxo3 = newUTXO(receivedValue, Bob, receivedSalt); }).timeout(600000); - it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { + it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { // Bob generates the nullifiers for the UTXO to be spent const nullifier1 = newNullifier(utxo3, Bob); @@ -415,7 +415,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou await smtAlice.add(events[0].outputs[1], events[0].outputs[1]); }).timeout(600000); - it('Alice withdraws her UTXOs to ERC20 tokens should succeed', async function () { + it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () { const startingBalance = await erc20.balanceOf(Alice.ethAddress); // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); @@ -466,10 +466,10 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou expect(endingBalance - startingBalance).to.be.equal(80); }); - describe('unregistered user flows', function () { + describe("unregistered user flows", function () { let unregisteredUtxo100: UTXO; - it('deposit by an unregistered user should succeed', async function () { + it("deposit by an unregistered user should succeed", async function () { const tx = await erc20 .connect(deployer) .mint(unregistered.ethAddress, 100); @@ -486,7 +486,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou ); const tx2 = await zeto .connect(unregistered.signer) - .deposit(100, outputCommitments[0], encodedProof, '0x'); + .deposit(100, outputCommitments[0], encodedProof, "0x"); await tx2.wait(); // Alice tracks the UTXO inside the SMT @@ -495,7 +495,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou await smtBob.add(unregisteredUtxo100.hash, unregisteredUtxo100.hash); }); - it('transfer from an unregistered user should fail', async function () { + it("transfer from an unregistered user should fail", async function () { // catch up the local SMT for the unregistered user await smtUnregistered.add(utxo100.hash, utxo100.hash); await smtUnregistered.add(utxo1.hash, utxo1.hash); @@ -557,10 +557,10 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou identitiesMerkleProofs, [Bob, unregistered], ), - ).rejectedWith('Invalid proof'); + ).rejectedWith("Invalid proof"); }); - it('the unregistered user can still withdraw their UTXOs to ERC20 tokens', async function () { + it("the unregistered user can still withdraw their UTXOs to ERC20 tokens", async function () { const startingBalance = await erc20.balanceOf(unregistered.ethAddress); // unregistered user generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(unregisteredUtxo100, unregistered); @@ -622,15 +622,15 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou }); }); - describe('failure cases', function () { + describe("failure cases", function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { return; } - it('Alice attempting to withdraw spent UTXOs should fail', async function () { + it("Alice attempting to withdraw spent UTXOs should fail", async function () { // Alice generates the nullifiers for the UTXOs to be spent const nullifier1 = newNullifier(utxo100, Alice); @@ -668,22 +668,22 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou root.bigInt(), encodedProof, ), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }); - it('mint existing unspent UTXOs should fail', async function () { + it("mint existing unspent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo4])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('mint existing spent UTXOs should fail', async function () { + it("mint existing spent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('transfer spent UTXOs should fail (double spend protection)', async function () { + it("transfer spent UTXOs should fail (double spend protection)", async function () { // create outputs const _utxo1 = newUTXO(25, Bob); const _utxo2 = newUTXO(5, Alice); @@ -734,10 +734,10 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou identitiesMerkleProofs, [Bob, Alice], ), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }).timeout(600000); - it('transfer with existing UTXOs in the output should fail (mass conservation protection)', async function () { + it("transfer with existing UTXOs in the output should fail (mass conservation protection)", async function () { // give Bob another UTXO to be able to spend const _utxo1 = newUTXO(15, Bob); await doMint(zeto, deployer, [_utxo1]); @@ -783,10 +783,10 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou identitiesMerkleProofs, [Alice, Alice], ), - ).rejectedWith('UTXOAlreadyOwned'); + ).rejectedWith("UTXOAlreadyOwned"); }).timeout(600000); - it('spend by using the same UTXO as both inputs should fail', async function () { + it("spend by using the same UTXO as both inputs should fail", async function () { const _utxo1 = newUTXO(20, Alice); const _utxo2 = newUTXO(10, Bob); const nullifier1 = newNullifier(utxo7, Bob); @@ -830,7 +830,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou ).rejectedWith(`UTXODuplicate`); }).timeout(600000); - it('transfer non-existing UTXOs should fail', async function () { + it("transfer non-existing UTXOs should fail", async function () { const nonExisting1 = newUTXO(25, Alice); const nonExisting2 = newUTXO(20, Alice, nonExisting1.salt); @@ -892,10 +892,10 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou identitiesMerkleProofs, [Bob, Charlie], ), - ).rejectedWith('UTXORootNotFound'); + ).rejectedWith("UTXORootNotFound"); }).timeout(600000); - it('repeated mint calls with single UTXO should not fail', async function () { + it("repeated mint calls with single UTXO should not fail", async function () { const utxo5 = newUTXO(10, Alice); await expect(doMint(zeto, deployer, [utxo5, ZERO_UTXO])).fulfilled; const utxo6 = newUTXO(20, Alice); @@ -1040,7 +1040,7 @@ describe('Zeto based fungible token with anonymity, KYC, using nullifiers withou outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works root, encodedProof, - '0x', + "0x", ); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( diff --git a/solidity/test/zeto_nf_anon.ts b/solidity/test/zeto_nf_anon.ts index 747939c..9fa70e2 100644 --- a/solidity/test/zeto_nf_anon.ts +++ b/solidity/test/zeto_nf_anon.ts @@ -14,17 +14,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, network } from 'hardhat'; -import { Signer, BigNumberish, AddressLike } from 'ethers'; -import { expect } from 'chai'; -import { loadCircuit, tokenUriHash, encodeProof } from 'zeto-js'; -import { groth16 } from 'snarkjs'; -import { formatPrivKeyForBabyJub, stringifyBigInts } from 'maci-crypto'; -import { User, UTXO, newUser, newAssetUTXO, doMint } from './lib/utils'; -import { loadProvingKeys } from './utils'; -import { deployZeto } from './lib/deploy'; - -describe('Zeto based non-fungible token with anonymity without encryption or nullifiers', function () { +import { ethers, network } from "hardhat"; +import { Signer, BigNumberish, AddressLike } from "ethers"; +import { expect } from "chai"; +import { loadCircuit, tokenUriHash, encodeProof } from "zeto-js"; +import { groth16 } from "snarkjs"; +import { formatPrivKeyForBabyJub, stringifyBigInts } from "maci-crypto"; +import { User, UTXO, newUser, newAssetUTXO, doMint } from "./lib/utils"; +import { loadProvingKeys } from "./utils"; +import { deployZeto } from "./lib/deploy"; + +describe("Zeto based non-fungible token with anonymity without encryption or nullifiers", function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -36,7 +36,7 @@ describe('Zeto based non-fungible token with anonymity without encryption or nul let circuit: any, provingKey: any; before(async function () { - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { // accommodate for longer block times on public networks this.timeout(120000); } @@ -46,15 +46,15 @@ describe('Zeto based non-fungible token with anonymity without encryption or nul Bob = await newUser(b); Charlie = await newUser(c); - ({ deployer, zeto } = await deployZeto('Zeto_NfAnon')); + ({ deployer, zeto } = await deployZeto("Zeto_NfAnon")); - circuit = await loadCircuit('nf_anon'); - ({ provingKeyFile: provingKey } = loadProvingKeys('nf_anon')); + circuit = await loadCircuit("nf_anon"); + ({ provingKeyFile: provingKey } = loadProvingKeys("nf_anon")); }); - it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { + it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { const tokenId = 1001; - const uri = 'http://ipfs.io/file-hash-1'; + const uri = "http://ipfs.io/file-hash-1"; utxo1 = newAssetUTXO(tokenId, uri, Alice); await doMint(zeto, deployer, [utxo1]); @@ -68,7 +68,7 @@ describe('Zeto based non-fungible token with anonymity without encryption or nul utxo2 = newAssetUTXO(_utxo3.tokenId!, _utxo3.uri!, Bob, _utxo3.salt); }); - it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { + it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { // propose the output UTXOs utxo3 = newAssetUTXO(utxo2.tokenId!, utxo2.uri!, Charlie); @@ -76,48 +76,48 @@ describe('Zeto based non-fungible token with anonymity without encryption or nul await doTransfer(Bob, utxo2, utxo3, Charlie); }); - describe('failure cases', function () { + describe("failure cases", function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { return; } - it('mint existing unspent UTXOs should fail', async function () { + it("mint existing unspent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo3])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('mint existing spent UTXOs should fail', async function () { + it("mint existing spent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadySpent', + "UTXOAlreadySpent", ); }); - it('transfer non-existing UTXOs should fail', async function () { + it("transfer non-existing UTXOs should fail", async function () { const nonExisting1 = newAssetUTXO( 1002, - 'http://ipfs.io/file-hash-2', + "http://ipfs.io/file-hash-2", Alice, ); const nonExisting2 = newAssetUTXO( 1002, - 'http://ipfs.io/file-hash-2', + "http://ipfs.io/file-hash-2", Bob, ); await expect( doTransfer(Alice, nonExisting1, nonExisting2, Bob), - ).rejectedWith('UTXONotMinted'); + ).rejectedWith("UTXONotMinted"); }); - it('transfer spent UTXOs should fail (double spend protection)', async function () { + it("transfer spent UTXOs should fail (double spend protection)", async function () { // create outputs const _utxo4 = newAssetUTXO(utxo1.tokenId!, utxo1.uri!, Bob); await expect(doTransfer(Alice, utxo1, _utxo4, Bob)).rejectedWith( - 'UTXOAlreadySpent', + "UTXOAlreadySpent", ); }); }); @@ -151,7 +151,7 @@ describe('Zeto based non-fungible token with anonymity without encryption or nul ) { const tx = await zeto .connect(signer.signer) - .transfer(inputCommitment, outputCommitment, encodedProof, '0x'); + .transfer(inputCommitment, outputCommitment, encodedProof, "0x"); const results = await tx.wait(); console.log(`Method transfer() complete. Gas used: ${results?.gasUsed}`); diff --git a/solidity/test/zeto_nf_anon_nullifier.ts b/solidity/test/zeto_nf_anon_nullifier.ts index e825fd1..d05dd1d 100644 --- a/solidity/test/zeto_nf_anon_nullifier.ts +++ b/solidity/test/zeto_nf_anon_nullifier.ts @@ -14,12 +14,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, network } from 'hardhat'; -import { ContractTransactionReceipt, Signer, BigNumberish } from 'ethers'; -import { expect } from 'chai'; -import { loadCircuit, Poseidon, encodeProof, tokenUriHash } from 'zeto-js'; -import { groth16 } from 'snarkjs'; -import { Merkletree, InMemoryDB, str2Bytes } from '@iden3/js-merkletree'; +import { ethers, network } from "hardhat"; +import { ContractTransactionReceipt, Signer, BigNumberish } from "ethers"; +import { expect } from "chai"; +import { loadCircuit, Poseidon, encodeProof, tokenUriHash } from "zeto-js"; +import { groth16 } from "snarkjs"; +import { Merkletree, InMemoryDB, str2Bytes } from "@iden3/js-merkletree"; import { UTXO, User, @@ -28,11 +28,11 @@ import { newAssetNullifier, doMint, parseUTXOEvents, -} from './lib/utils'; -import { loadProvingKeys } from './utils'; -import { deployZeto } from './lib/deploy'; +} from "./lib/utils"; +import { loadProvingKeys } from "./utils"; +import { deployZeto } from "./lib/deploy"; -describe('Zeto based non-fungible token with anonymity using nullifiers without encryption', function () { +describe("Zeto based non-fungible token with anonymity using nullifiers without encryption", function () { let deployer: Signer; let Alice: User; let Bob: User; @@ -45,7 +45,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without let smtBob: Merkletree; before(async function () { - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { // accommodate for longer block times on public networks this.timeout(120000); } @@ -55,29 +55,29 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without Bob = await newUser(b); Charlie = await newUser(c); - ({ deployer, zeto } = await deployZeto('Zeto_NfAnonNullifier')); + ({ deployer, zeto } = await deployZeto("Zeto_NfAnonNullifier")); - circuit = await loadCircuit('nf_anon_nullifier'); - ({ provingKeyFile: provingKey } = loadProvingKeys('nf_anon_nullifier')); + circuit = await loadCircuit("nf_anon_nullifier"); + ({ provingKeyFile: provingKey } = loadProvingKeys("nf_anon_nullifier")); - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, 64); - const storage2 = new InMemoryDB(str2Bytes('')); + const storage2 = new InMemoryDB(str2Bytes("")); smtBob = new Merkletree(storage2, true, 64); }); - it('onchain SMT root should be equal to the offchain SMT root', async function () { + it("onchain SMT root should be equal to the offchain SMT root", async function () { const root = await smtAlice.root(); const onchainRoot = await zeto.getRoot(); expect(onchainRoot).to.equal(0n); expect(root.string()).to.equal(onchainRoot.toString()); }); - it('mint to Alice and transfer UTXOs honestly to Bob should succeed', async function () { + it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () { // The authority mints a new UTXO and assigns it to Alice const tokenId = 1001; - const uri = 'http://ipfs.io/file-hash-1'; + const uri = "http://ipfs.io/file-hash-1"; utxo1 = newAssetUTXO(tokenId, uri, Alice); const result1 = await doMint(zeto, deployer, [utxo1]); @@ -146,7 +146,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without utxo3 = newAssetUTXO(receivedTokenId, receivedUri, Bob, receivedSalt); }).timeout(600000); - it('Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed', async function () { + it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { // Bob generates the nullifiers for the UTXO to be spent const nullifier1 = newAssetNullifier(utxo3, Bob); @@ -177,27 +177,27 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without await smtAlice.add(events[0].outputs[0], events[0].outputs[0]); }).timeout(600000); - describe('failure cases', function () { + describe("failure cases", function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { return; } - it('mint existing unspent UTXOs should fail', async function () { + it("mint existing unspent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo3])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('mint existing spent UTXOs should fail', async function () { + it("mint existing spent UTXOs should fail", async function () { await expect(doMint(zeto, deployer, [utxo1])).rejectedWith( - 'UTXOAlreadyOwned', + "UTXOAlreadyOwned", ); }); - it('transfer spent UTXOs should fail (double spend protection)', async function () { + it("transfer spent UTXOs should fail (double spend protection)", async function () { // Alice create outputs in an attempt to send to Charlie an already spent asset const _utxo1 = newAssetUTXO(utxo1.tokenId!, utxo1.uri!, Charlie); @@ -222,13 +222,13 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without merkleProof, Charlie, ), - ).rejectedWith('UTXOAlreadySpent'); + ).rejectedWith("UTXOAlreadySpent"); }).timeout(600000); - it('transfer non-existing UTXOs should fail', async function () { + it("transfer non-existing UTXOs should fail", async function () { const nonExisting1 = newAssetUTXO( 1002, - 'http://ipfs.io/file-hash-2', + "http://ipfs.io/file-hash-2", Alice, ); @@ -263,7 +263,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without merkleProof, Charlie, ), - ).rejectedWith('UTXORootNotFound'); + ).rejectedWith("UTXORootNotFound"); }).timeout(600000); }); @@ -367,7 +367,7 @@ describe('Zeto based non-fungible token with anonymity using nullifiers without const startTx = Date.now(); const tx = await zeto .connect(signer.signer) - .transfer(nullifier, outputCommitment, root, encodedProof, '0x'); + .transfer(nullifier, outputCommitment, root, encodedProof, "0x"); const results: ContractTransactionReceipt | null = await tx.wait(); console.log( `Time to execute transaction: ${Date.now() - startTx}ms. Gas used: ${ diff --git a/solidity/test/zkDvP.ts b/solidity/test/zkDvP.ts index 4002063..2c96007 100644 --- a/solidity/test/zkDvP.ts +++ b/solidity/test/zkDvP.ts @@ -14,13 +14,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { ethers, ignition, network } from 'hardhat'; -import { Signer, encodeBytes32String, ZeroHash } from 'ethers'; -import { expect } from 'chai'; -import { loadCircuit, getProofHash } from 'zeto-js'; -import zkDvPModule from '../ignition/modules/zkDvP'; -import zetoAnonTests from './zeto_anon'; -import zetoNFAnonTests from './zeto_nf_anon'; +import { ethers, ignition, network } from "hardhat"; +import { Signer, encodeBytes32String, ZeroHash } from "ethers"; +import { expect } from "chai"; +import { loadCircuit, getProofHash } from "zeto-js"; +import zkDvPModule from "../ignition/modules/zkDvP"; +import zetoAnonTests from "./zeto_anon"; +import zetoNFAnonTests from "./zeto_nf_anon"; import { UTXO, User, @@ -30,11 +30,11 @@ import { newAssetUTXO, ZERO_UTXO, parseUTXOEvents, -} from './lib/utils'; -import { loadProvingKeys } from './utils'; -import { deployZeto } from './lib/deploy'; +} from "./lib/utils"; +import { loadProvingKeys } from "./utils"; +import { deployZeto } from "./lib/deploy"; -describe('DvP flows between fungible and non-fungible tokens based on Zeto with anonymity without encryption or nullifiers', function () { +describe("DvP flows between fungible and non-fungible tokens based on Zeto with anonymity without encryption or nullifiers", function () { // users interacting with each other in the DvP transactions let Alice: User; let Bob: User; @@ -56,7 +56,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with let deployer: Signer; before(async function () { - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { // accommodate for longer block times on public networks this.timeout(120000); } @@ -66,9 +66,9 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with Bob = await newUser(b); Charlie = await newUser(c); - ({ deployer, zeto: zkAsset } = await deployZeto('Zeto_NfAnon')); + ({ deployer, zeto: zkAsset } = await deployZeto("Zeto_NfAnon")); console.log(`ZK Asset contract deployed at ${zkAsset.target}`); - ({ deployer, zeto: zkPayment } = await deployZeto('Zeto_Anon')); + ({ deployer, zeto: zkPayment } = await deployZeto("Zeto_Anon")); console.log(`ZK Payment contract deployed at ${zkPayment.target}`); ({ zkDvP } = await ignition.deploy(zkDvPModule, { parameters: { @@ -80,7 +80,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with })); }); - it('mint to Alice some payment tokens', async function () { + it("mint to Alice some payment tokens", async function () { payment1 = newUTXO(10, Alice); payment2 = newUTXO(20, Alice); const result = await doMint(zkPayment, deployer, [payment1, payment2]); @@ -92,7 +92,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with } }); - it('mint to Bob some asset tokens', async function () { + it("mint to Bob some asset tokens", async function () { asset1 = newUTXO(10, Alice); asset2 = newUTXO(20, Alice); const result = await doMint(zkAsset, deployer, [asset1, asset2]); @@ -103,7 +103,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with expect(event.args.outputs[1].toString()).to.equal(asset2.hash.toString()); }); - it('Initiating a successful DvP transaction with payment inputs', async function () { + it("Initiating a successful DvP transaction with payment inputs", async function () { const utxo1 = newUTXO(10, Alice); const utxo2 = newUTXO(20, Alice); const utxo3 = newUTXO(25, Bob); @@ -122,7 +122,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with ).fulfilled; }); - it('Initiating a successful DvP transaction with asset inputs', async function () { + it("Initiating a successful DvP transaction with asset inputs", async function () { const utxo1 = newUTXO(10, Alice); const utxo2 = newUTXO(20, Alice); await expect( @@ -139,12 +139,12 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with ).fulfilled; }); - it('Initiating a successful DvP transaction with payment inputs and accepting by specifying asset inputs', async function () { + it("Initiating a successful DvP transaction with payment inputs and accepting by specifying asset inputs", async function () { // the authority mints some payment tokens to Alice const _utxo1 = newUTXO(100, Alice); await doMint(zkPayment, deployer, [_utxo1]); // the authority mints some asset tokens to Bob - const utxo3 = newAssetUTXO(202, 'http://ipfs.io/file-hash-1', Bob); + const utxo3 = newAssetUTXO(202, "http://ipfs.io/file-hash-1", Bob); await doMint(zkAsset, deployer, [utxo3]); // 1. Alice initiates a trade with Bob using the payment tokens @@ -152,8 +152,8 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with const utxo2 = newUTXO(100, Bob); // 1.2 Alice generates the proof for the trade proposal - const circuit1 = await loadCircuit('anon'); - const { provingKeyFile: provingKey1 } = loadProvingKeys('anon'); + const circuit1 = await loadCircuit("anon"); + const { provingKeyFile: provingKey1 } = loadProvingKeys("anon"); const proof1 = await zetoAnonTests.prepareProof( circuit1, provingKey1, @@ -174,11 +174,11 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with // 2. Bob accepts the trade by using the asset tokens // 2.1 Bob generates the proposed output asset UTXO for Alice - const utxo4 = newAssetUTXO(202, 'http://ipfs.io/file-hash-1', Alice); + const utxo4 = newAssetUTXO(202, "http://ipfs.io/file-hash-1", Alice); // 2.2 Bob generates the proof for accepting the trade - const circuit2 = await loadCircuit('nf_anon'); - const { provingKeyFile: provingKey2 } = loadProvingKeys('nf_anon'); + const circuit2 = await loadCircuit("nf_anon"); + const { provingKeyFile: provingKey2 } = loadProvingKeys("nf_anon"); const proof2 = await zetoNFAnonTests.prepareProof( circuit2, provingKey2, @@ -220,25 +220,25 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with expect(events[0].tradeId).to.equal(tradeId); expect(events[0].trade.status).to.equal(2n); // enum for TradeStatus.Completed }); - describe('failure cases', function () { + describe("failure cases", function () { // the following failure cases rely on the hardhat network // to return the details of the errors. This is not possible // on non-hardhat networks - if (network.name !== 'hardhat') { + if (network.name !== "hardhat") { return; } - it('Initiating a DvP transaction without payment input or asset input should fail', async function () { + it("Initiating a DvP transaction without payment input or asset input should fail", async function () { await expect( zkDvP .connect(Alice.signer) .initiateTrade([0, 0], [0, 0], ZeroHash, 0, 0, ZeroHash), ).rejectedWith( - 'Payment inputs and asset input cannot be zero at the same time', + "Payment inputs and asset input cannot be zero at the same time", ); }); - it('Initiating a DvP transaction with payment input but no payment output should fail', async function () { + it("Initiating a DvP transaction with payment input but no payment output should fail", async function () { const utxo1 = newUTXO(10, Alice); const utxo2 = newUTXO(20, Alice); await expect( @@ -253,11 +253,11 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with ZeroHash, ), ).rejectedWith( - 'Payment outputs cannot be zero when payment inputs are non-zero', + "Payment outputs cannot be zero when payment inputs are non-zero", ); }); - it('Initiating a DvP transaction with payment inputs and asset inputs should fail', async function () { + it("Initiating a DvP transaction with payment inputs and asset inputs should fail", async function () { const utxo1 = newUTXO(10, Alice); const utxo2 = newUTXO(20, Alice); const utxo3 = newUTXO(25, Bob); @@ -274,31 +274,31 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with ZeroHash, ), ).rejectedWith( - 'Payment inputs and asset input cannot be provided at the same time', + "Payment inputs and asset input cannot be provided at the same time", ); }); - it('Initiating a DvP transaction with asset input but no asset output should fail', async function () { + it("Initiating a DvP transaction with asset input but no asset output should fail", async function () { const utxo1 = newUTXO(10, Alice); await expect( zkDvP .connect(Alice.signer) .initiateTrade([0, 0], [0, 0], ZeroHash, utxo1.hash, 0, ZeroHash), ).rejectedWith( - 'Asset output cannot be zero when asset input is non-zero', + "Asset output cannot be zero when asset input is non-zero", ); }); - it('Accepting a trade using an invalid trade ID should fail', async function () { + it("Accepting a trade using an invalid trade ID should fail", async function () { await expect( zkDvP .connect(Bob.signer) .acceptTrade(1000, [0, 0], [0, 0], ZeroHash, 0, 0, ZeroHash), - ).rejectedWith('Trade does not exist'); + ).rejectedWith("Trade does not exist"); }); - it('Failing cases for accepting a trade with payment terms', async function () { - const mockProofHash = encodeBytes32String('moch proof hash'); + it("Failing cases for accepting a trade with payment terms", async function () { + const mockProofHash = encodeBytes32String("moch proof hash"); const utxo1 = newUTXO(20, Alice); const utxo2 = newUTXO(20, Bob); const tx1 = await zkDvP @@ -315,7 +315,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with const event = zkDvP.interface.parseLog(result.logs[0]); const tradeId = event.args.tradeId; - const utxo3 = newAssetUTXO(25, 'http://ipfs.io/file-hash-1', Bob); + const utxo3 = newAssetUTXO(25, "http://ipfs.io/file-hash-1", Bob); await expect( zkDvP .connect(Bob.signer) @@ -328,7 +328,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with 0, mockProofHash, ), - ).rejectedWith('Payment inputs already provided by the trade initiator'); + ).rejectedWith("Payment inputs already provided by the trade initiator"); await expect( zkDvP .connect(Bob.signer) @@ -341,7 +341,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with 0, mockProofHash, ), - ).rejectedWith('Payment outputs already provided by the trade initiator'); + ).rejectedWith("Payment outputs already provided by the trade initiator"); await expect( zkDvP .connect(Bob.signer) @@ -354,7 +354,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with 0, mockProofHash, ), - ).rejectedWith('Asset input must be provided to accept the trade'); + ).rejectedWith("Asset input must be provided to accept the trade"); await expect( zkDvP .connect(Bob.signer) @@ -367,13 +367,13 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with 0, mockProofHash, ), - ).rejectedWith('Asset output must be provided to accept the trade'); + ).rejectedWith("Asset output must be provided to accept the trade"); }); - it('Failing cases for accepting a trade with asset terms', async function () { - const mockProofHash = encodeBytes32String('mock proof hash'); - const utxo1 = newAssetUTXO(100, 'http://ipfs.io/file-hash-1', Alice); - const utxo2 = newAssetUTXO(202, 'http://ipfs.io/file-hash-2', Bob); + it("Failing cases for accepting a trade with asset terms", async function () { + const mockProofHash = encodeBytes32String("mock proof hash"); + const utxo1 = newAssetUTXO(100, "http://ipfs.io/file-hash-1", Alice); + const utxo2 = newAssetUTXO(202, "http://ipfs.io/file-hash-2", Bob); const tx1 = await zkDvP .connect(Alice.signer) .initiateTrade( @@ -404,7 +404,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with utxo2.hash, mockProofHash, ), - ).rejectedWith('Asset inputs already provided by the trade initiator'); + ).rejectedWith("Asset inputs already provided by the trade initiator"); await expect( zkDvP .connect(Bob.signer) @@ -417,7 +417,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with utxo2.hash, mockProofHash, ), - ).rejectedWith('Asset outputs already provided by the trade initiator'); + ).rejectedWith("Asset outputs already provided by the trade initiator"); await expect( zkDvP .connect(Bob.signer) @@ -430,7 +430,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with 0, mockProofHash, ), - ).rejectedWith('Payment inputs must be provided to accept the trade'); + ).rejectedWith("Payment inputs must be provided to accept the trade"); await expect( zkDvP .connect(Bob.signer) @@ -443,12 +443,12 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with 0, mockProofHash, ), - ).rejectedWith('Payment outputs must be provided to accept the trade'); + ).rejectedWith("Payment outputs must be provided to accept the trade"); }); - it('test proof locking', async function () { - const circuit1 = await loadCircuit('anon'); - const { provingKeyFile: provingKey1 } = loadProvingKeys('anon'); + it("test proof locking", async function () { + const circuit1 = await loadCircuit("anon"); + const { provingKeyFile: provingKey1 } = loadProvingKeys("anon"); const utxo1 = newUTXO(100, Alice); const proof = await zetoAnonTests.prepareProof( circuit1, @@ -468,7 +468,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with zkPayment .connect(Bob.signer) .lockProof(proof.encodedProof, await Bob.signer.getAddress()), - ).rejectedWith('Proof already locked by another party'); + ).rejectedWith("Proof already locked by another party"); await expect( zkPayment .connect(Alice.signer) @@ -479,7 +479,7 @@ describe('DvP flows between fungible and non-fungible tokens based on Zeto with .connect(Bob.signer) .lockProof( proof.encodedProof, - '0x0000000000000000000000000000000000000000', + "0x0000000000000000000000000000000000000000", ), ).fulfilled; }); diff --git a/zkp/js/.prettierrc b/zkp/js/.prettierrc deleted file mode 100644 index 544138b..0000000 --- a/zkp/js/.prettierrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "singleQuote": true -} diff --git a/zkp/js/integration-test/anon.js b/zkp/js/integration-test/anon.js index 80a9c40..d356ef6 100644 --- a/zkp/js/integration-test/anon.js +++ b/zkp/js/integration-test/anon.js @@ -14,28 +14,28 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); const { genKeypair, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); -const { Poseidon, newSalt, loadCircuit } = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +} = require("maci-crypto"); +const { Poseidon, newSalt, loadCircuit } = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const ZERO_PUBKEY = [0, 0]; const poseidonHash = Poseidon.poseidon4; -describe('main circuit tests for Zeto fungible tokens with anonymity without encryption', () => { +describe("main circuit tests for Zeto fungible tokens with anonymity without encryption", () => { let circuit, provingKeyFile, verificationKey; const sender = {}; const receiver = {}; before(async () => { - circuit = await loadCircuit('anon'); - ({ provingKeyFile, verificationKey } = loadProvingKeys('anon')); + circuit = await loadCircuit("anon"); + ({ provingKeyFile, verificationKey } = loadProvingKeys("anon")); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -46,7 +46,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity without enc receiver.pubKey = keypair.pubKey; }); - it('should generate a valid proof that can be verified successfully', async () => { + it("should generate a valid proof that can be verified successfully", async () => { const inputValues = [15, 100]; const outputValues = [115, 0]; // create two input UTXOs, each has their own salt, but same owner @@ -96,7 +96,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity without enc provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); // console.log('inputCommitments', inputCommitments); diff --git a/zkp/js/integration-test/anon_enc.js b/zkp/js/integration-test/anon_enc.js index 579a3bc..af6c0d8 100644 --- a/zkp/js/integration-test/anon_enc.js +++ b/zkp/js/integration-test/anon_enc.js @@ -14,34 +14,34 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); const { genRandomSalt, genKeypair, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); +} = require("maci-crypto"); const { Poseidon, newSalt, loadCircuit, newEncryptionNonce, -} = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +} = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const ZERO_PUBKEY = [0, 0]; const poseidonHash = Poseidon.poseidon4; -describe('main circuit tests for Zeto fungible tokens with anonymity with encryption', () => { +describe("main circuit tests for Zeto fungible tokens with anonymity with encryption", () => { let circuit, provingKeyFile, verificationKey; const sender = {}; const receiver = {}; before(async () => { - circuit = await loadCircuit('anon_enc'); - ({ provingKeyFile, verificationKey } = loadProvingKeys('anon_enc')); + circuit = await loadCircuit("anon_enc"); + ({ provingKeyFile, verificationKey } = loadProvingKeys("anon_enc")); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -52,7 +52,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp receiver.pubKey = keypair.pubKey; }); - it('should generate a valid proof that can be verified successfully', async () => { + it("should generate a valid proof that can be verified successfully", async () => { const inputValues = [115, 0]; const outputValues = [115, 0]; // create two input UTXOs, each has their own salt, but same owner @@ -100,7 +100,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); // console.log('inputCommitments', inputCommitments); diff --git a/zkp/js/integration-test/anon_enc_nullifier.js b/zkp/js/integration-test/anon_enc_nullifier.js index 64768b1..521e372 100644 --- a/zkp/js/integration-test/anon_enc_nullifier.js +++ b/zkp/js/integration-test/anon_enc_nullifier.js @@ -14,33 +14,33 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); const { genRandomSalt, genKeypair, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); +} = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); +} = require("@iden3/js-merkletree"); const { Poseidon, newSalt, loadCircuit, newEncryptionNonce, -} = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +} = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon4; const poseidonHash3 = Poseidon.poseidon3; -describe('main circuit tests for Zeto fungible tokens with encryption and anonymity using nullifiers', () => { +describe("main circuit tests for Zeto fungible tokens with encryption and anonymity using nullifiers", () => { let circuit, provingKeyFile, verificationKey, smtAlice, smtBob; const Alice = {}; @@ -48,9 +48,9 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym let senderPrivateKey; before(async () => { - circuit = await loadCircuit('anon_enc_nullifier'); + circuit = await loadCircuit("anon_enc_nullifier"); ({ provingKeyFile, verificationKey } = - loadProvingKeys('anon_enc_nullifier')); + loadProvingKeys("anon_enc_nullifier")); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -62,15 +62,15 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym Bob.pubKey = keypair.pubKey; // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT); // initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree - const storage2 = new InMemoryDB(str2Bytes('')); + const storage2 = new InMemoryDB(str2Bytes("")); smtBob = new Merkletree(storage2, true, SMT_HEIGHT); }); - it('should generate a valid proof that can be verified successfully', async () => { + it("should generate a valid proof that can be verified successfully", async () => { const inputValues = [15, 100]; const outputValues = [80, 35]; // create two input UTXOs, each has their own salt, but same owner @@ -164,7 +164,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); // console.log('nullifiers', nullifiers); diff --git a/zkp/js/integration-test/anon_enc_nullifier_kyc.js b/zkp/js/integration-test/anon_enc_nullifier_kyc.js index eda8e7e..0f4c210 100644 --- a/zkp/js/integration-test/anon_enc_nullifier_kyc.js +++ b/zkp/js/integration-test/anon_enc_nullifier_kyc.js @@ -14,27 +14,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); const { genKeypair, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); +} = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); +} = require("@iden3/js-merkletree"); const { Poseidon, newSalt, loadCircuit, newEncryptionNonce, kycHash, -} = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +} = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const SMT_HEIGHT_UTXO = 64; const SMT_HEIGHT_IDENTITY = 10; @@ -42,7 +42,7 @@ const poseidonHash = Poseidon.poseidon4; const poseidonHash2 = Poseidon.poseidon2; const poseidonHash3 = Poseidon.poseidon3; -describe('main circuit tests for Zeto fungible tokens with encryption and anonymity using nullifiers with KYC', () => { +describe("main circuit tests for Zeto fungible tokens with encryption and anonymity using nullifiers with KYC", () => { let circuit, provingKeyFile, verificationKey, smtAlice, smtKYC, smtBob; const Alice = {}; @@ -50,9 +50,9 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym let senderPrivateKey; before(async () => { - circuit = await loadCircuit('anon_enc_nullifier_kyc'); + circuit = await loadCircuit("anon_enc_nullifier_kyc"); ({ provingKeyFile, verificationKey } = loadProvingKeys( - 'anon_enc_nullifier_kyc', + "anon_enc_nullifier_kyc", )); let keypair = genKeypair(); @@ -65,15 +65,15 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym Bob.pubKey = keypair.pubKey; // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('alice')); + const storage1 = new InMemoryDB(str2Bytes("alice")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT_UTXO); // initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree - const storage2 = new InMemoryDB(str2Bytes('bob')); + const storage2 = new InMemoryDB(str2Bytes("bob")); smtBob = new Merkletree(storage2, true, SMT_HEIGHT_UTXO); // initialize the local storage for the sender to manage identities in the Spart Merkle Tree - const storage3 = new InMemoryDB(str2Bytes('kyc')); + const storage3 = new InMemoryDB(str2Bytes("kyc")); smtKYC = new Merkletree(storage3, true, SMT_HEIGHT_IDENTITY); // calculate the identity hash for Alice @@ -85,7 +85,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym await smtKYC.add(identity2, identity2); }); - it('should generate a valid proof that can be verified successfully', async () => { + it("should generate a valid proof that can be verified successfully", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; @@ -199,7 +199,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); // console.log('nullifiers', nullifiers); diff --git a/zkp/js/integration-test/anon_enc_nullifier_non_repudiation.js b/zkp/js/integration-test/anon_enc_nullifier_non_repudiation.js index 930b13c..21e4271 100644 --- a/zkp/js/integration-test/anon_enc_nullifier_non_repudiation.js +++ b/zkp/js/integration-test/anon_enc_nullifier_non_repudiation.js @@ -14,33 +14,33 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); const { genRandomSalt, genKeypair, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); +} = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); +} = require("@iden3/js-merkletree"); const { Poseidon, newSalt, loadCircuit, newEncryptionNonce, -} = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +} = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon4; const poseidonHash3 = Poseidon.poseidon3; -describe('main circuit tests for Zeto fungible tokens with encryption fro non-repudiation and anonymity using nullifiers', () => { +describe("main circuit tests for Zeto fungible tokens with encryption fro non-repudiation and anonymity using nullifiers", () => { let circuit, provingKeyFile, verificationKey, smtAlice, smtBob; const Alice = {}; @@ -49,9 +49,9 @@ describe('main circuit tests for Zeto fungible tokens with encryption fro non-re let senderPrivateKey; before(async () => { - circuit = await loadCircuit('anon_enc_nullifier_non_repudiation'); + circuit = await loadCircuit("anon_enc_nullifier_non_repudiation"); ({ provingKeyFile, verificationKey } = loadProvingKeys( - 'anon_enc_nullifier_non_repudiation', + "anon_enc_nullifier_non_repudiation", )); let keypair = genKeypair(); @@ -68,15 +68,15 @@ describe('main circuit tests for Zeto fungible tokens with encryption fro non-re Regulator.pubKey = keypair.pubKey; // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT); // initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree - const storage2 = new InMemoryDB(str2Bytes('')); + const storage2 = new InMemoryDB(str2Bytes("")); smtBob = new Merkletree(storage2, true, SMT_HEIGHT); }); - it('should generate a valid proof that can be verified successfully', async () => { + it("should generate a valid proof that can be verified successfully", async () => { const inputValues = [15, 100]; const outputValues = [80, 35]; // create two input UTXOs, each has their own salt, but same owner @@ -171,7 +171,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption fro non-re provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); // console.log('nullifiers', nullifiers); diff --git a/zkp/js/integration-test/anon_nullifier.js b/zkp/js/integration-test/anon_nullifier.js index 6fd55c6..b4782c2 100644 --- a/zkp/js/integration-test/anon_nullifier.js +++ b/zkp/js/integration-test/anon_nullifier.js @@ -14,23 +14,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); -const { Poseidon, newSalt, loadCircuit } = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +} = require("@iden3/js-merkletree"); +const { Poseidon, newSalt, loadCircuit } = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon4; const poseidonHash3 = Poseidon.poseidon3; -describe('main circuit tests for Zeto fungible tokens with anonymity using nullifiers and without encryption', () => { +describe("main circuit tests for Zeto fungible tokens with anonymity using nullifiers and without encryption", () => { let circuit, provingKeyFile, verificationKey, smtAlice, smtBob; const Alice = {}; @@ -38,8 +38,8 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli let senderPrivateKey; before(async () => { - circuit = await loadCircuit('anon_nullifier'); - ({ provingKeyFile, verificationKey } = loadProvingKeys('anon_nullifier')); + circuit = await loadCircuit("anon_nullifier"); + ({ provingKeyFile, verificationKey } = loadProvingKeys("anon_nullifier")); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -51,15 +51,15 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli Bob.pubKey = keypair.pubKey; // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT); // initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree - const storage2 = new InMemoryDB(str2Bytes('')); + const storage2 = new InMemoryDB(str2Bytes("")); smtBob = new Merkletree(storage2, true, SMT_HEIGHT); }); - it('should generate a valid proof that can be verified successfully', async () => { + it("should generate a valid proof that can be verified successfully", async () => { const inputValues = [15, 100]; const outputValues = [80, 35]; // create two input UTXOs, each has their own salt, but same owner @@ -145,7 +145,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); // console.log('nullifiers', nullifiers); diff --git a/zkp/js/integration-test/anon_nullifier_kyc.js b/zkp/js/integration-test/anon_nullifier_kyc.js index 002961c..3268202 100644 --- a/zkp/js/integration-test/anon_nullifier_kyc.js +++ b/zkp/js/integration-test/anon_nullifier_kyc.js @@ -14,17 +14,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); -const { Poseidon, newSalt, loadCircuit, kycHash } = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +} = require("@iden3/js-merkletree"); +const { Poseidon, newSalt, loadCircuit, kycHash } = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const SMT_HEIGHT_UTXO = 64; const SMT_HEIGHT_IDENTITY = 10; @@ -32,7 +32,7 @@ const poseidonHash = Poseidon.poseidon4; const poseidonHash2 = Poseidon.poseidon2; const poseidonHash3 = Poseidon.poseidon3; -describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using nullifiers and without encryption', () => { +describe("main circuit tests for Zeto fungible tokens with anonymity, KYC, using nullifiers and without encryption", () => { let circuit, provingKeyFile, verificationKey, smtAlice, smtKYC, smtBob; const Alice = {}; @@ -40,9 +40,9 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using let senderPrivateKey; before(async () => { - circuit = await loadCircuit('anon_nullifier_kyc'); + circuit = await loadCircuit("anon_nullifier_kyc"); ({ provingKeyFile, verificationKey } = - loadProvingKeys('anon_nullifier_kyc')); + loadProvingKeys("anon_nullifier_kyc")); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -54,15 +54,15 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using Bob.pubKey = keypair.pubKey; // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('alice')); + const storage1 = new InMemoryDB(str2Bytes("alice")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT_UTXO); // initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree - const storage2 = new InMemoryDB(str2Bytes('bob')); + const storage2 = new InMemoryDB(str2Bytes("bob")); smtBob = new Merkletree(storage2, true, SMT_HEIGHT_UTXO); // initialize the local storage for the sender to manage identities in the Spart Merkle Tree - const storage3 = new InMemoryDB(str2Bytes('kyc')); + const storage3 = new InMemoryDB(str2Bytes("kyc")); smtKYC = new Merkletree(storage3, true, SMT_HEIGHT_IDENTITY); // calculate the identity hash for Alice @@ -74,7 +74,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using await smtKYC.add(identity2, identity2); }); - it('should generate a valid proof that can be verified successfully', async () => { + it("should generate a valid proof that can be verified successfully", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; @@ -179,7 +179,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); // console.log('nullifiers', nullifiers); diff --git a/zkp/js/integration-test/check_hashes_value.js b/zkp/js/integration-test/check_hashes_value.js index d32cb4d..3a78f7c 100644 --- a/zkp/js/integration-test/check_hashes_value.js +++ b/zkp/js/integration-test/check_hashes_value.js @@ -14,25 +14,25 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); -const { genKeypair } = require('maci-crypto'); -const { Poseidon, newSalt, loadCircuit } = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); +const { genKeypair } = require("maci-crypto"); +const { Poseidon, newSalt, loadCircuit } = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const poseidonHash = Poseidon.poseidon4; -describe('check-hashes-value circuit tests', () => { +describe("check-hashes-value circuit tests", () => { let circuit; const sender = {}; before(async () => { - circuit = await loadCircuit('check_hashes_value'); + circuit = await loadCircuit("check_hashes_value"); let keypair = genKeypair(); sender.privKey = keypair.privKey; sender.pubKey = keypair.pubKey; }); - it('should return true for valid witness', async () => { + it("should return true for valid witness", async () => { const outputValues = [200]; // create the output UTXO @@ -66,13 +66,13 @@ describe('check-hashes-value circuit tests', () => { true, ); const { provingKeyFile, verificationKey } = - loadProvingKeys('check_hashes_value'); + loadProvingKeys("check_hashes_value"); const startTime = Date.now(); const { proof, publicSignals } = await groth16.prove( provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); expect(success, true); // console.log('output commitments', outputCommitments); diff --git a/zkp/js/integration-test/check_inputs_outputs_value.js b/zkp/js/integration-test/check_inputs_outputs_value.js index c4db4d1..6932f75 100644 --- a/zkp/js/integration-test/check_inputs_outputs_value.js +++ b/zkp/js/integration-test/check_inputs_outputs_value.js @@ -14,26 +14,26 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes } = require('@iden3/js-merkletree'); -const { Poseidon, newSalt, loadCircuit } = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); +const { Merkletree, InMemoryDB, str2Bytes } = require("@iden3/js-merkletree"); +const { Poseidon, newSalt, loadCircuit } = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon4; -describe('check_inputs_outputs_value circuit tests', () => { +describe("check_inputs_outputs_value circuit tests", () => { let circuit, provingKeyFile, verificationKey, smtAlice; const Alice = {}; let senderPrivateKey; before(async () => { - circuit = await loadCircuit('check_inputs_outputs_value'); + circuit = await loadCircuit("check_inputs_outputs_value"); ({ provingKeyFile, verificationKey } = loadProvingKeys( - 'check_inputs_outputs_value', + "check_inputs_outputs_value", )); let keypair = genKeypair(); @@ -42,11 +42,11 @@ describe('check_inputs_outputs_value circuit tests', () => { senderPrivateKey = formatPrivKeyForBabyJub(Alice.privKey); // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT); }); - it('should generate a valid proof that can be verified successfully', async () => { + it("should generate a valid proof that can be verified successfully", async () => { const inputValues = [15, 100]; const outputValues = [35]; @@ -94,7 +94,7 @@ describe('check_inputs_outputs_value circuit tests', () => { provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); // console.log('nullifiers', nullifiers); diff --git a/zkp/js/integration-test/check_nullifier_value.js b/zkp/js/integration-test/check_nullifier_value.js index 3042e1c..3716d01 100644 --- a/zkp/js/integration-test/check_nullifier_value.js +++ b/zkp/js/integration-test/check_nullifier_value.js @@ -14,32 +14,32 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); -const { Poseidon, newSalt, loadCircuit } = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +} = require("@iden3/js-merkletree"); +const { Poseidon, newSalt, loadCircuit } = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon4; const poseidonHash3 = Poseidon.poseidon3; -describe('check_nullifier_value circuit tests', () => { +describe("check_nullifier_value circuit tests", () => { let circuit, provingKeyFile, verificationKey, smtAlice; const Alice = {}; let senderPrivateKey; before(async () => { - circuit = await loadCircuit('check_nullifier_value'); + circuit = await loadCircuit("check_nullifier_value"); ({ provingKeyFile, verificationKey } = loadProvingKeys( - 'check_nullifier_value', + "check_nullifier_value", )); let keypair = genKeypair(); @@ -48,11 +48,11 @@ describe('check_nullifier_value circuit tests', () => { senderPrivateKey = formatPrivKeyForBabyJub(Alice.privKey); // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT); }); - it('should generate a valid proof that can be verified successfully', async () => { + it("should generate a valid proof that can be verified successfully", async () => { const inputValues = [15, 100]; const outputValues = [35]; @@ -134,7 +134,7 @@ describe('check_nullifier_value circuit tests', () => { provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); // console.log('nullifiers', nullifiers); diff --git a/zkp/js/integration-test/check_nullifiers.js b/zkp/js/integration-test/check_nullifiers.js index 93b7f34..324ee63 100644 --- a/zkp/js/integration-test/check_nullifiers.js +++ b/zkp/js/integration-test/check_nullifiers.js @@ -14,24 +14,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Poseidon, newSalt, loadCircuit } = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); +const { Poseidon, newSalt, loadCircuit } = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const poseidonHash4 = Poseidon.poseidon4; const poseidonHash3 = Poseidon.poseidon3; -describe('check-nullifiers circuit tests', () => { +describe("check-nullifiers circuit tests", () => { let circuit, provingKeyFile, verificationKey; const sender = {}; const receiver = {}; let senderPrivateKey; before(async () => { - circuit = await loadCircuit('check_nullifiers'); - ({ provingKeyFile, verificationKey } = loadProvingKeys('check_nullifiers')); + circuit = await loadCircuit("check_nullifiers"); + ({ provingKeyFile, verificationKey } = loadProvingKeys("check_nullifiers")); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -43,7 +43,7 @@ describe('check-nullifiers circuit tests', () => { receiver.pubKey = keypair.pubKey; }); - it('should generate a valid proof using groth16 that can be verified successfully', async () => { + it("should generate a valid proof using groth16 that can be verified successfully", async () => { const inputValues = [15, 100]; // create two input UTXOs, each has their own salt, but same owner @@ -90,7 +90,7 @@ describe('check-nullifiers circuit tests', () => { provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); expect(success, true); }).timeout(20000); diff --git a/zkp/js/integration-test/nf_anon.js b/zkp/js/integration-test/nf_anon.js index f039326..709ad24 100644 --- a/zkp/js/integration-test/nf_anon.js +++ b/zkp/js/integration-test/nf_anon.js @@ -14,27 +14,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); const { genKeypair, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); -const { Poseidon, newSalt, loadCircuit, tokenUriHash } = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +} = require("maci-crypto"); +const { Poseidon, newSalt, loadCircuit, tokenUriHash } = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const poseidonHash = Poseidon.poseidon5; -describe('main circuit tests for Zeto non-fungible tokens with anonymity without encryption', () => { +describe("main circuit tests for Zeto non-fungible tokens with anonymity without encryption", () => { let circuit, provingKeyFile, verificationKey; const sender = {}; const receiver = {}; before(async () => { - circuit = await loadCircuit('nf_anon'); - ({ provingKeyFile, verificationKey } = loadProvingKeys('nf_anon')); + circuit = await loadCircuit("nf_anon"); + ({ provingKeyFile, verificationKey } = loadProvingKeys("nf_anon")); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -45,9 +45,9 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without receiver.pubKey = keypair.pubKey; }); - it('should generate a valid proof that can be verified successfully', async () => { + it("should generate a valid proof that can be verified successfully", async () => { const tokenIds = [1001]; - const tokenUris = [tokenUriHash('http://ipfs.io/some-file-hash')]; + const tokenUris = [tokenUriHash("http://ipfs.io/some-file-hash")]; // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); @@ -92,7 +92,7 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); // console.log('inputCommitments', inputCommitments); diff --git a/zkp/js/integration-test/nf_anon_nullifier.js b/zkp/js/integration-test/nf_anon_nullifier.js index 9fa7d77..465fd49 100644 --- a/zkp/js/integration-test/nf_anon_nullifier.js +++ b/zkp/js/integration-test/nf_anon_nullifier.js @@ -14,23 +14,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { groth16 } = require('snarkjs'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); +const { expect } = require("chai"); +const { groth16 } = require("snarkjs"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); -const { Poseidon, newSalt, tokenUriHash, loadCircuit } = require('../index.js'); -const { loadProvingKeys } = require('./utils.js'); +} = require("@iden3/js-merkletree"); +const { Poseidon, newSalt, tokenUriHash, loadCircuit } = require("../index.js"); +const { loadProvingKeys } = require("./utils.js"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon5; const poseidonHash4 = Poseidon.poseidon4; -describe('main circuit tests for Zeto non-fungible tokens with anonymity using nullifiers and without encryption', () => { +describe("main circuit tests for Zeto non-fungible tokens with anonymity using nullifiers and without encryption", () => { let circuit, provingKeyFile, verificationKey, smtAlice, smtBob; const Alice = {}; @@ -38,9 +38,9 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n let senderPrivateKey; before(async () => { - circuit = await loadCircuit('nf_anon_nullifier'); + circuit = await loadCircuit("nf_anon_nullifier"); ({ provingKeyFile, verificationKey } = - loadProvingKeys('nf_anon_nullifier')); + loadProvingKeys("nf_anon_nullifier")); let keypair = genKeypair(); Alice.privKey = keypair.privKey; @@ -52,17 +52,17 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n Bob.pubKey = keypair.pubKey; // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT); // initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree - const storage2 = new InMemoryDB(str2Bytes('')); + const storage2 = new InMemoryDB(str2Bytes("")); smtBob = new Merkletree(storage2, true, SMT_HEIGHT); }); - it('should generate a valid proof that can be verified successfully', async () => { + it("should generate a valid proof that can be verified successfully", async () => { const tokenId = 1001; - const tokenUri = tokenUriHash('http://ipfs.io/some-file-hash'); + const tokenUri = tokenUriHash("http://ipfs.io/some-file-hash"); // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); @@ -121,7 +121,7 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n provingKeyFile, witness, ); - console.log('Proving time: ', (Date.now() - startTime) / 1000, 's'); + console.log("Proving time: ", (Date.now() - startTime) / 1000, "s"); const success = await groth16.verify(verificationKey, publicSignals, proof); // console.log('nullifiers', nullifier1); diff --git a/zkp/js/integration-test/utils.js b/zkp/js/integration-test/utils.js index f66cd8c..56143f7 100644 --- a/zkp/js/integration-test/utils.js +++ b/zkp/js/integration-test/utils.js @@ -14,13 +14,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -const path = require('path'); -const { readFileSync } = require('fs'); +const path = require("path"); +const { readFileSync } = require("fs"); function provingKeysRoot() { const PROVING_KEYS_ROOT = process.env.PROVING_KEYS_ROOT; if (!PROVING_KEYS_ROOT) { - throw new Error('PROVING_KEYS_ROOT env var is not set'); + throw new Error("PROVING_KEYS_ROOT env var is not set"); } return PROVING_KEYS_ROOT; } diff --git a/zkp/js/lib/util.js b/zkp/js/lib/util.js index ef62fe9..a4e829d 100644 --- a/zkp/js/lib/util.js +++ b/zkp/js/lib/util.js @@ -14,10 +14,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { genRandomSalt } = require('maci-crypto'); -const { poseidon4: poseidon, poseidon2 } = require('poseidon-lite'); -const { solidityPackedKeccak256 } = require('ethers'); -const { createHash, randomBytes } = require('crypto'); +const { genRandomSalt } = require("maci-crypto"); +const { poseidon4: poseidon, poseidon2 } = require("poseidon-lite"); +const { solidityPackedKeccak256 } = require("ethers"); +const { createHash, randomBytes } = require("crypto"); function newSalt() { return genRandomSalt(); @@ -26,15 +26,15 @@ function newSalt() { // per the encryption scheme in ../circuits/lib/encrypt.circom, // the nonce must not be larger than 2^128 function newEncryptionNonce() { - const hex = randomBytes(16).toString('hex'); + const hex = randomBytes(16).toString("hex"); const nonce = BigInt(`0x${hex}`); return nonce; } -const two128 = BigInt('340282366920938463463374607431768211456'); +const two128 = BigInt("340282366920938463463374607431768211456"); // Field modulus for BN254 const F = BigInt( - '21888242871839275222246405745257275088548364400416034343698204186575808495617', + "21888242871839275222246405745257275088548364400416034343698204186575808495617", ); // Implements the encryption and decryption functions using Poseidon hash @@ -114,18 +114,18 @@ function poseidonDecrypt(ciphertext, key, nonce, length) { checkEqual( message[message.length - 1], 0n, - 'The last element of the message must be 0', + "The last element of the message must be 0", ); } else if (length % 3 === 1) { checkEqual( message[message.length - 1], 0n, - 'The last element of the message must be 0', + "The last element of the message must be 0", ); checkEqual( message[message.length - 2], 0n, - 'The second to last element of the message must be 0', + "The second to last element of the message must be 0", ); } } @@ -137,7 +137,7 @@ function poseidonDecrypt(ciphertext, key, nonce, length) { checkEqual( ciphertext[ciphertext.length - 1], state[1], - 'The last ciphertext element must match the second item of the permuted state', + "The last ciphertext element must match the second item of the permuted state", ); return message.slice(0, length); @@ -162,24 +162,24 @@ function addMod(a, b) { function validateInputs(msg, key, nonce, length) { if (!Array.isArray(msg)) { - throw new Error('The message must be an array'); + throw new Error("The message must be an array"); } for (let i = 0; i < msg.length; i += 1) { - if (typeof msg[i] !== 'bigint') { - throw new Error('Each message element must be a BigInt'); + if (typeof msg[i] !== "bigint") { + throw new Error("Each message element must be a BigInt"); } } if (key.length !== 2) { - throw new Error('The key must be an array of two elements'); + throw new Error("The key must be an array of two elements"); } - if (typeof key[0] !== 'bigint' || typeof key[1] !== 'bigint') { - throw new Error('The key must be an array of two BigInts'); + if (typeof key[0] !== "bigint" || typeof key[1] !== "bigint") { + throw new Error("The key must be an array of two BigInts"); } - if (typeof nonce !== 'bigint') { - throw new Error('The nonce must be a BigInt'); + if (typeof nonce !== "bigint") { + throw new Error("The nonce must be a BigInt"); } if (length && length < 1) { - throw new Error('The length must be at least 1'); + throw new Error("The length must be at least 1"); } } @@ -207,15 +207,15 @@ function getProofHash(encodedProof) { BigInt(encodedProof.pC[0]), BigInt(encodedProof.pC[1]), ]; - const hash = solidityPackedKeccak256(['uint[8]'], [flat]); + const hash = solidityPackedKeccak256(["uint[8]"], [flat]); return hash; } function tokenUriHash(tokenUri) { - const hash = createHash('sha256').update(tokenUri).digest('hex'); + const hash = createHash("sha256").update(tokenUri).digest("hex"); // to fit the result within the range of the Finite Field used in the poseidon hash, // use 253 bit long numbers. we need to remove the most significant three bits. - return BigInt.asUintN(253, '0x' + hash); + return BigInt.asUintN(253, "0x" + hash); } function kycHash(bjjPublicKey) { diff --git a/zkp/js/test/anon.js b/zkp/js/test/anon.js index 6af8070..79506bd 100644 --- a/zkp/js/test/anon.js +++ b/zkp/js/test/anon.js @@ -14,19 +14,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); const { genKeypair, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); -const { Poseidon, newSalt } = require('../index.js'); +} = require("maci-crypto"); +const { Poseidon, newSalt } = require("../index.js"); const poseidonHash = Poseidon.poseidon4; -describe('main circuit tests for Zeto fungible tokens with anonymity without encryption', () => { +describe("main circuit tests for Zeto fungible tokens with anonymity without encryption", () => { let circuit; const sender = {}; @@ -35,7 +35,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity without enc before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../../circuits/anon.circom')); + circuit = await wasm_tester(join(__dirname, "../../circuits/anon.circom")); let keypair = genKeypair(); sender.privKey = keypair.privKey; @@ -46,7 +46,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity without enc receiver.pubKey = keypair.pubKey; }); - it('should succeed for valid witness', async () => { + it("should succeed for valid witness", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; @@ -110,7 +110,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity without enc expect(witness[4]).to.equal(BigInt(outputCommitments[1])); }); - it('should fail to generate a witness because mass conservation is not obeyed', async () => { + it("should fail to generate a witness because mass conservation is not obeyed", async () => { const inputValues = [15, 100]; const outputValues = [90, 35]; // create two input UTXOs, each has their own salt, but same owner diff --git a/zkp/js/test/anon_enc.js b/zkp/js/test/anon_enc.js index 3411cc1..ef3d4bd 100644 --- a/zkp/js/test/anon_enc.js +++ b/zkp/js/test/anon_enc.js @@ -14,26 +14,26 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); const { genRandomSalt, genKeypair, genEcdhSharedKey, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); +} = require("maci-crypto"); const { Poseidon, newSalt, poseidonDecrypt, newEncryptionNonce, -} = require('../index.js'); +} = require("../index.js"); const poseidonHash = Poseidon.poseidon4; -describe('main circuit tests for Zeto fungible tokens with anonymity with encryption', () => { +describe("main circuit tests for Zeto fungible tokens with anonymity with encryption", () => { let circuit; const sender = {}; @@ -43,7 +43,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/anon_enc.circom'), + join(__dirname, "../../circuits/anon_enc.circom"), ); let keypair = genKeypair(); @@ -55,7 +55,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp receiver.pubKey = keypair.pubKey; }); - it('should succeed for valid witness and produce an encypted value', async () => { + it("should succeed for valid witness and produce an encypted value", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; @@ -147,7 +147,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp expect(calculatedHash).to.equal(outputCommitments[0]); }); - it('should fail to generate a witness because mass conservation is not obeyed', async () => { + it("should fail to generate a witness because mass conservation is not obeyed", async () => { const inputValues = [15, 100]; const outputValues = [90, 35]; // create two input UTXOs, each has their own salt, but same owner @@ -209,7 +209,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp expect(err).to.match(/Error in template Zeto_105 line: 89/); }); - it('should failed to match output UTXO after decrypting the cipher texts from the events if using the wrong sender public keys', async () => { + it("should failed to match output UTXO after decrypting the cipher texts from the events if using the wrong sender public keys", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; @@ -274,7 +274,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity with encryp expect(function () { poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); }).to.throw( - 'The last ciphertext element must match the second item of the permuted state', + "The last ciphertext element must match the second item of the permuted state", ); }); }); diff --git a/zkp/js/test/anon_enc_nullifier.js b/zkp/js/test/anon_enc_nullifier.js index 42a4179..06bd024 100644 --- a/zkp/js/test/anon_enc_nullifier.js +++ b/zkp/js/test/anon_enc_nullifier.js @@ -14,34 +14,34 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); const { genRandomSalt, genKeypair, genEcdhSharedKey, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); +} = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); +} = require("@iden3/js-merkletree"); const { Poseidon, newSalt, poseidonDecrypt, newEncryptionNonce, -} = require('../index.js'); +} = require("../index.js"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon4; const poseidonHash3 = Poseidon.poseidon3; -describe('main circuit tests for Zeto fungible tokens with encryption and anonymity using nullifiers', () => { +describe("main circuit tests for Zeto fungible tokens with encryption and anonymity using nullifiers", () => { let circuit, smtAlice, smtBob; const Alice = {}; @@ -52,7 +52,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/anon_enc_nullifier.circom'), + join(__dirname, "../../circuits/anon_enc_nullifier.circom"), ); let keypair = genKeypair(); @@ -65,15 +65,15 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym Bob.pubKey = keypair.pubKey; // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT); // initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree - const storage2 = new InMemoryDB(str2Bytes('')); + const storage2 = new InMemoryDB(str2Bytes("")); smtBob = new Merkletree(storage2, true, SMT_HEIGHT); }); - it('should succeed for valid witness and produce an encypted value', async () => { + it("should succeed for valid witness and produce an encypted value", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; @@ -192,7 +192,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); }); - it('should succeed for valid witness and produce an encypted value - single input', async () => { + it("should succeed for valid witness and produce an encypted value - single input", async () => { const inputValues = [72, 0]; const outputValues = [20, 52]; @@ -296,7 +296,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); }); - it('should fail to generate a witness because mass conservation is not obeyed', async () => { + it("should fail to generate a witness because mass conservation is not obeyed", async () => { const inputValues = [15, 100]; const outputValues = [90, 35]; diff --git a/zkp/js/test/anon_enc_nullifier_kyc.js b/zkp/js/test/anon_enc_nullifier_kyc.js index 21a4d31..5c034d1 100644 --- a/zkp/js/test/anon_enc_nullifier_kyc.js +++ b/zkp/js/test/anon_enc_nullifier_kyc.js @@ -14,28 +14,28 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); const { genRandomSalt, genKeypair, genEcdhSharedKey, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); +} = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); +} = require("@iden3/js-merkletree"); const { Poseidon, newSalt, poseidonDecrypt, newEncryptionNonce, -} = require('../index.js'); +} = require("../index.js"); const SMT_HEIGHT_UTXO = 64; const SMT_HEIGHT_IDENTITY = 10; @@ -43,7 +43,7 @@ const poseidonHash = Poseidon.poseidon4; const poseidonHash2 = Poseidon.poseidon2; const poseidonHash3 = Poseidon.poseidon3; -describe('main circuit tests for Zeto fungible tokens with encryption and anonymity using nullifiers with KYC', () => { +describe("main circuit tests for Zeto fungible tokens with encryption and anonymity using nullifiers with KYC", () => { let circuit, smtAlice, smtKYC, smtBob; const Alice = {}; @@ -54,7 +54,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/anon_enc_nullifier_kyc.circom'), + join(__dirname, "../../circuits/anon_enc_nullifier_kyc.circom"), ); let keypair = genKeypair(); @@ -67,15 +67,15 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym Bob.pubKey = keypair.pubKey; // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('alice')); + const storage1 = new InMemoryDB(str2Bytes("alice")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT_UTXO); // initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree - const storage2 = new InMemoryDB(str2Bytes('bob')); + const storage2 = new InMemoryDB(str2Bytes("bob")); smtBob = new Merkletree(storage2, true, SMT_HEIGHT_UTXO); // initialize the local storage for the sender to manage identities in the Spart Merkle Tree - const storage3 = new InMemoryDB(str2Bytes('kyc')); + const storage3 = new InMemoryDB(str2Bytes("kyc")); smtKYC = new Merkletree(storage3, true, SMT_HEIGHT_IDENTITY); // calculate the identity hash for Alice @@ -87,7 +87,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym await smtKYC.add(identity2, identity2); }); - it('should succeed for valid witness and produce an encypted value', async () => { + it("should succeed for valid witness and produce an encypted value", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; @@ -226,7 +226,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption and anonym expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); }); - it('should fail if not using the right identities merkle proofs', async () => { + it("should fail if not using the right identities merkle proofs", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; diff --git a/zkp/js/test/anon_enc_nullifier_non_repudiation.js b/zkp/js/test/anon_enc_nullifier_non_repudiation.js index b9daf3d..0254773 100644 --- a/zkp/js/test/anon_enc_nullifier_non_repudiation.js +++ b/zkp/js/test/anon_enc_nullifier_non_repudiation.js @@ -14,34 +14,34 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); const { genRandomSalt, genKeypair, genEcdhSharedKey, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); +} = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); +} = require("@iden3/js-merkletree"); const { Poseidon, newSalt, newEncryptionNonce, poseidonDecrypt, -} = require('../index.js'); +} = require("../index.js"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon4; const poseidonHash3 = Poseidon.poseidon3; -describe('main circuit tests for Zeto fungible tokens with encryption for non-repudiation and anonymity using nullifiers', () => { +describe("main circuit tests for Zeto fungible tokens with encryption for non-repudiation and anonymity using nullifiers", () => { let circuit, smtAlice; const Alice = {}; @@ -55,7 +55,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re circuit = await wasm_tester( join( __dirname, - '../../circuits/anon_enc_nullifier_non_repudiation.circom', + "../../circuits/anon_enc_nullifier_non_repudiation.circom", ), ); @@ -73,15 +73,15 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re Regulator.pubKey = keypair.pubKey; // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT); // initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree - const storage2 = new InMemoryDB(str2Bytes('')); + const storage2 = new InMemoryDB(str2Bytes("")); smtBob = new Merkletree(storage2, true, SMT_HEIGHT); }); - it('should succeed for valid witness, produce an encypted value and regulator is able to decrypt', async () => { + it("should succeed for valid witness, produce an encypted value and regulator is able to decrypt", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; @@ -231,7 +231,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re ]); }); - it('should succeed for valid witness and produce an encypted value - single input', async () => { + it("should succeed for valid witness and produce an encypted value - single input", async () => { const inputValues = [72, 0]; const outputValues = [20, 52]; @@ -366,7 +366,7 @@ describe('main circuit tests for Zeto fungible tokens with encryption for non-re ]); }); - it('should fail to generate a witness because mass conservation is not obeyed', async () => { + it("should fail to generate a witness because mass conservation is not obeyed", async () => { const inputValues = [15, 100]; const outputValues = [90, 35]; diff --git a/zkp/js/test/anon_nullifier.js b/zkp/js/test/anon_nullifier.js index deec1c7..82f4353 100644 --- a/zkp/js/test/anon_nullifier.js +++ b/zkp/js/test/anon_nullifier.js @@ -14,23 +14,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); -const { Poseidon, newSalt } = require('../index.js'); +} = require("@iden3/js-merkletree"); +const { Poseidon, newSalt } = require("../index.js"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon4; const poseidonHash3 = Poseidon.poseidon3; -describe('main circuit tests for Zeto fungible tokens with anonymity using nullifiers and without encryption', () => { +describe("main circuit tests for Zeto fungible tokens with anonymity using nullifiers and without encryption", () => { let circuit, smtAlice, smtBob; const Alice = {}; @@ -41,7 +41,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/anon_nullifier.circom'), + join(__dirname, "../../circuits/anon_nullifier.circom"), ); let keypair = genKeypair(); @@ -54,15 +54,15 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli Bob.pubKey = keypair.pubKey; // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT); // initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree - const storage2 = new InMemoryDB(str2Bytes('')); + const storage2 = new InMemoryDB(str2Bytes("")); smtBob = new Merkletree(storage2, true, SMT_HEIGHT); }); - it('should succeed for valid witness', async () => { + it("should succeed for valid witness", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; @@ -160,7 +160,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli expect(witness[3]).to.equal(proof1.root.bigInt()); }); - it('should succeed for valid witness - single input', async () => { + it("should succeed for valid witness - single input", async () => { const inputValues = [72, 0]; const outputValues = [20, 52]; @@ -232,7 +232,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli expect(witness[3]).to.equal(proof1.root.bigInt()); }); - it('should fail to generate a witness because mass conservation is not obeyed', async () => { + it("should fail to generate a witness because mass conservation is not obeyed", async () => { const inputValues = [15, 100]; const outputValues = [90, 35]; diff --git a/zkp/js/test/anon_nullifier_kyc.js b/zkp/js/test/anon_nullifier_kyc.js index 94d67ba..2156486 100644 --- a/zkp/js/test/anon_nullifier_kyc.js +++ b/zkp/js/test/anon_nullifier_kyc.js @@ -14,17 +14,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); -const { Poseidon, newSalt, kycHash } = require('../index.js'); +} = require("@iden3/js-merkletree"); +const { Poseidon, newSalt, kycHash } = require("../index.js"); const SMT_HEIGHT_UTXO = 64; const SMT_HEIGHT_IDENTITY = 10; @@ -32,7 +32,7 @@ const poseidonHash = Poseidon.poseidon4; const poseidonHash2 = Poseidon.poseidon2; const poseidonHash3 = Poseidon.poseidon3; -describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using nullifiers and without encryption', () => { +describe("main circuit tests for Zeto fungible tokens with anonymity, KYC, using nullifiers and without encryption", () => { let circuit, smtAlice, smtKYC, smtBob; const Alice = {}; @@ -43,7 +43,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/anon_nullifier_kyc.circom'), + join(__dirname, "../../circuits/anon_nullifier_kyc.circom"), ); let keypair = genKeypair(); @@ -56,15 +56,15 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using Bob.pubKey = keypair.pubKey; // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('alice')); + const storage1 = new InMemoryDB(str2Bytes("alice")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT_UTXO); // initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree - const storage2 = new InMemoryDB(str2Bytes('bob')); + const storage2 = new InMemoryDB(str2Bytes("bob")); smtBob = new Merkletree(storage2, true, SMT_HEIGHT_UTXO); // initialize the local storage for the sender to manage identities in the Spart Merkle Tree - const storage3 = new InMemoryDB(str2Bytes('kyc')); + const storage3 = new InMemoryDB(str2Bytes("kyc")); smtKYC = new Merkletree(storage3, true, SMT_HEIGHT_IDENTITY); // calculate the identity hash for Alice @@ -76,7 +76,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using await smtKYC.add(identity2, identity2); }); - it('should succeed for valid witness', async () => { + it("should succeed for valid witness", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; @@ -194,7 +194,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity, KYC, using expect(witness[6]).to.equal(proof3.root.bigInt()); }); - it('should fail if not using the right identities merkle proofs', async () => { + it("should fail if not using the right identities merkle proofs", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; diff --git a/zkp/js/test/check_hashes_value.js b/zkp/js/test/check_hashes_value.js index ea1590f..ced0828 100644 --- a/zkp/js/test/check_hashes_value.js +++ b/zkp/js/test/check_hashes_value.js @@ -14,16 +14,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair } = require('maci-crypto'); -const { Poseidon, newSalt } = require('../index.js'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { genKeypair } = require("maci-crypto"); +const { Poseidon, newSalt } = require("../index.js"); const MAX_VALUE = 2n ** 40n - 1n; const poseidonHash = Poseidon.poseidon4; -describe('check_hashes_value circuit tests', () => { +describe("check_hashes_value circuit tests", () => { let circuit; const sender = {}; @@ -31,7 +31,7 @@ describe('check_hashes_value circuit tests', () => { this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/check_hashes_value.circom'), + join(__dirname, "../../circuits/check_hashes_value.circom"), ); let keypair = genKeypair(); @@ -39,7 +39,7 @@ describe('check_hashes_value circuit tests', () => { sender.pubKey = keypair.pubKey; }); - it('should return true for valid witness', async () => { + it("should return true for valid witness", async () => { const outputValues = [200]; // create the output UTXO @@ -74,7 +74,7 @@ describe('check_hashes_value circuit tests', () => { ); }); - it('should fail to generate a witness because of invalid output commitments', async () => { + it("should fail to generate a witness because of invalid output commitments", async () => { const outputValues = [200]; // create the output UTXO @@ -104,7 +104,7 @@ describe('check_hashes_value circuit tests', () => { expect(error).to.match(/Error in template Zeto_79 line: 35/); // hash check failed }); - it('should fail to generate a witness because of negative values in output commitments', async () => { + it("should fail to generate a witness because of negative values in output commitments", async () => { // in the finite field used in the Poseidion hash implementation, -100n is equivalent to // 21888242871839275222246405745257275088548364400416034343698204186575808495517n const outputValues = [-100]; @@ -136,7 +136,7 @@ describe('check_hashes_value circuit tests', () => { expect(error).to.match(/Error in template Zeto_79 line: 29/); // positive range check failed }); - it('should fail to generate a witness because of using the inverse of a negative value in output commitments', async () => { + it("should fail to generate a witness because of using the inverse of a negative value in output commitments", async () => { // in the finite field used in the Poseidion hash implementation, -100n is equivalent to // 21888242871839275222246405745257275088548364400416034343698204186575808495517n. This number // is considered negative by the circuit, because we allow the range of 0 to (2**40 - 1) @@ -171,7 +171,7 @@ describe('check_hashes_value circuit tests', () => { expect(error).to.match(/Error in template Zeto_79 line: 29/); // positive range check failed }); - it('should fail to generate a witness because a larger than MAX_VALUE is used in output', async () => { + it("should fail to generate a witness because a larger than MAX_VALUE is used in output", async () => { const outputValues = [MAX_VALUE + 1n]; // create the output UTXO diff --git a/zkp/js/test/check_inputs_outputs_value.js b/zkp/js/test/check_inputs_outputs_value.js index efd226e..1a0f2b1 100644 --- a/zkp/js/test/check_inputs_outputs_value.js +++ b/zkp/js/test/check_inputs_outputs_value.js @@ -14,17 +14,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Merkletree, InMemoryDB, str2Bytes } = require('@iden3/js-merkletree'); -const { Poseidon, newSalt } = require('../index.js'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); +const { Merkletree, InMemoryDB, str2Bytes } = require("@iden3/js-merkletree"); +const { Poseidon, newSalt } = require("../index.js"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon4; -describe('check_inputs_outputs_value circuit tests', () => { +describe("check_inputs_outputs_value circuit tests", () => { let circuit, smtAlice; const Alice = {}; @@ -34,7 +34,7 @@ describe('check_inputs_outputs_value circuit tests', () => { this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/check_inputs_outputs_value.circom'), + join(__dirname, "../../circuits/check_inputs_outputs_value.circom"), ); let keypair = genKeypair(); @@ -43,11 +43,11 @@ describe('check_inputs_outputs_value circuit tests', () => { senderPrivateKey = formatPrivKeyForBabyJub(Alice.privKey); // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT); }); - it('should succeed for valid witness', async () => { + it("should succeed for valid witness", async () => { const inputValues = [32, 40]; const outputValues = [2]; @@ -105,7 +105,7 @@ describe('check_inputs_outputs_value circuit tests', () => { expect(witness[3]).to.equal(BigInt(inputCommitments[1])); }); - it('should succeed for valid witness - single input', async () => { + it("should succeed for valid witness - single input", async () => { const inputValues = [72, 0]; const outputValues = [10]; diff --git a/zkp/js/test/check_nullifier_value.js b/zkp/js/test/check_nullifier_value.js index 934a891..8c5ad50 100644 --- a/zkp/js/test/check_nullifier_value.js +++ b/zkp/js/test/check_nullifier_value.js @@ -14,23 +14,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); -const { Poseidon, newSalt } = require('../index.js'); +} = require("@iden3/js-merkletree"); +const { Poseidon, newSalt } = require("../index.js"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon4; const poseidonHash3 = Poseidon.poseidon3; -describe('check_nullifier_value circuit tests', () => { +describe("check_nullifier_value circuit tests", () => { let circuit, smtAlice; const Alice = {}; @@ -40,7 +40,7 @@ describe('check_nullifier_value circuit tests', () => { this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/check_nullifier_value.circom'), + join(__dirname, "../../circuits/check_nullifier_value.circom"), ); let keypair = genKeypair(); @@ -49,11 +49,11 @@ describe('check_nullifier_value circuit tests', () => { senderPrivateKey = formatPrivKeyForBabyJub(Alice.privKey); // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT); }); - it('should succeed for valid witness', async () => { + it("should succeed for valid witness", async () => { const inputValues = [32, 40]; const outputValues = [2]; @@ -146,7 +146,7 @@ describe('check_nullifier_value circuit tests', () => { expect(witness[4]).to.equal(proof1.root.bigInt()); }); - it('should succeed for valid witness - single input', async () => { + it("should succeed for valid witness - single input", async () => { const inputValues = [72, 0]; const outputValues = [10]; diff --git a/zkp/js/test/check_nullifiers.js b/zkp/js/test/check_nullifiers.js index 7fdb3f3..c52001a 100644 --- a/zkp/js/test/check_nullifiers.js +++ b/zkp/js/test/check_nullifiers.js @@ -14,16 +14,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Poseidon, newSalt } = require('../index.js'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); +const { Poseidon, newSalt } = require("../index.js"); const poseidonHash4 = Poseidon.poseidon4; const poseidonHash3 = Poseidon.poseidon3; -describe('check_nullifiers circuit tests', () => { +describe("check_nullifiers circuit tests", () => { let circuit; const sender = {}; const receiver = {}; @@ -33,7 +33,7 @@ describe('check_nullifiers circuit tests', () => { this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/check_nullifiers.circom'), + join(__dirname, "../../circuits/check_nullifiers.circom"), ); let keypair = genKeypair(); @@ -46,7 +46,7 @@ describe('check_nullifiers circuit tests', () => { receiver.pubKey = keypair.pubKey; }); - it('should return true for valid witness', async () => { + it("should return true for valid witness", async () => { const inputValues = [32, 40]; // create two input UTXOs @@ -103,7 +103,7 @@ describe('check_nullifiers circuit tests', () => { expect(witness[6]).to.equal(BigInt(inputValues[1])); }); - it('should fail to generate a witness because incorrect values are not used', async () => { + it("should fail to generate a witness because incorrect values are not used", async () => { const inputValues = [15, 100]; // create two input UTXOs, each has their own salt, but same owner diff --git a/zkp/js/test/lib/check-hashes-tokenid-uri.js b/zkp/js/test/lib/check-hashes-tokenid-uri.js index c10f29f..f3b17a5 100644 --- a/zkp/js/test/lib/check-hashes-tokenid-uri.js +++ b/zkp/js/test/lib/check-hashes-tokenid-uri.js @@ -14,16 +14,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { readFileSync } = require('fs'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair } = require('maci-crypto'); -const { Poseidon, newSalt, tokenUriHash } = require('../../index.js'); +const { expect } = require("chai"); +const { readFileSync } = require("fs"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { genKeypair } = require("maci-crypto"); +const { Poseidon, newSalt, tokenUriHash } = require("../../index.js"); const poseidonHash = Poseidon.poseidon5; -describe('check-hashes-tokenid-uri circuit tests', () => { +describe("check-hashes-tokenid-uri circuit tests", () => { let circuit; const sender = {}; const receiver = {}; @@ -32,7 +32,7 @@ describe('check-hashes-tokenid-uri circuit tests', () => { this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../circuits/check-hashes-tokenid-uri.circom'), + join(__dirname, "../circuits/check-hashes-tokenid-uri.circom"), ); let keypair = genKeypair(); @@ -44,9 +44,9 @@ describe('check-hashes-tokenid-uri circuit tests', () => { receiver.pubKey = keypair.pubKey; }); - it('should return true for valid witness', async () => { + it("should return true for valid witness", async () => { const tokenIds = [1001]; - const tokenUris = [tokenUriHash('http://ipfs.io/some-file-hash')]; + const tokenUris = [tokenUriHash("http://ipfs.io/some-file-hash")]; // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); @@ -87,9 +87,9 @@ describe('check-hashes-tokenid-uri circuit tests', () => { expect(witness[6]).to.equal(salt1); }); - it('should fail to generate a witness because of invalid commitments', async () => { + it("should fail to generate a witness because of invalid commitments", async () => { const tokenIds = [1001]; - const tokenUris = [tokenUriHash('http://ipfs.io/some-file-hash')]; + const tokenUris = [tokenUriHash("http://ipfs.io/some-file-hash")]; // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); diff --git a/zkp/js/test/lib/check-hashes.js b/zkp/js/test/lib/check-hashes.js index ce5da0e..da11891 100644 --- a/zkp/js/test/lib/check-hashes.js +++ b/zkp/js/test/lib/check-hashes.js @@ -14,18 +14,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { readFileSync } = require('fs'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair } = require('maci-crypto'); -const { Poseidon, newSalt } = require('../../index.js'); +const { expect } = require("chai"); +const { readFileSync } = require("fs"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { genKeypair } = require("maci-crypto"); +const { Poseidon, newSalt } = require("../../index.js"); const MAX_VALUE = 2n ** 40n - 1n; const ZERO_PUBKEY = [0n, 0n]; const poseidonHash = Poseidon.poseidon4; -describe('check-hashes circuit tests', () => { +describe("check-hashes circuit tests", () => { let circuit; const sender = {}; const receiver = {}; @@ -34,7 +34,7 @@ describe('check-hashes circuit tests', () => { this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../circuits/check-hashes.circom'), + join(__dirname, "../circuits/check-hashes.circom"), ); let keypair = genKeypair(); @@ -46,7 +46,7 @@ describe('check-hashes circuit tests', () => { receiver.pubKey = keypair.pubKey; }); - it('should return true for valid witness', async () => { + it("should return true for valid witness", async () => { const values = [32, 40]; // create two input UTXOs, each has their own salt, but same owner @@ -75,7 +75,7 @@ describe('check-hashes circuit tests', () => { expect(witness[4]).to.equal(BigInt(sender.pubKey[1])); }); - it('should return true for valid witness using a single input value', async () => { + it("should return true for valid witness using a single input value", async () => { const values = [72, 0]; // create two input UTXOs, each has their own salt, but same owner @@ -99,7 +99,7 @@ describe('check-hashes circuit tests', () => { expect(witness[4]).to.equal(BigInt(sender.pubKey[1])); }); - it('should return true for valid witness using a single input value', async () => { + it("should return true for valid witness using a single input value", async () => { const values = [0, 72]; // create two input UTXOs, each has their own salt, but same owner @@ -125,7 +125,7 @@ describe('check-hashes circuit tests', () => { expect(witness[6]).to.equal(BigInt(sender.pubKey[1])); }); - it('should fail to generate a witness because of invalid input commitments', async () => { + it("should fail to generate a witness because of invalid input commitments", async () => { const inputValues = [25, 100]; // create two input UTXOs, each has their own salt, but same owner diff --git a/zkp/js/test/lib/check-nullifier-tokenid-uri.js b/zkp/js/test/lib/check-nullifier-tokenid-uri.js index e96fde2..a26e994 100644 --- a/zkp/js/test/lib/check-nullifier-tokenid-uri.js +++ b/zkp/js/test/lib/check-nullifier-tokenid-uri.js @@ -14,23 +14,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Poseidon, newSalt, tokenUriHash } = require('../../index.js'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); +const { Poseidon, newSalt, tokenUriHash } = require("../../index.js"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); +} = require("@iden3/js-merkletree"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon5; const poseidonHash4 = Poseidon.poseidon4; -describe('check-nullifier-tokenid-uri circuit tests', () => { +describe("check-nullifier-tokenid-uri circuit tests", () => { let circuit, smt; const sender = {}; const receiver = {}; @@ -40,7 +40,7 @@ describe('check-nullifier-tokenid-uri circuit tests', () => { this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../circuits/check-nullifier-tokenid-uri.circom'), + join(__dirname, "../circuits/check-nullifier-tokenid-uri.circom"), ); let keypair = genKeypair(); @@ -52,13 +52,13 @@ describe('check-nullifier-tokenid-uri circuit tests', () => { receiver.privKey = keypair.privKey; receiver.pubKey = keypair.pubKey; - const storage = new InMemoryDB(str2Bytes('')); + const storage = new InMemoryDB(str2Bytes("")); smt = new Merkletree(storage, true, SMT_HEIGHT); }); - it('should return true for valid witness', async () => { + it("should return true for valid witness", async () => { const tokenId = 1001; - const tokenUri = tokenUriHash('http://ipfs.io/some-file-hash'); + const tokenUri = tokenUriHash("http://ipfs.io/some-file-hash"); const salt1 = newSalt(); const nullifier1 = poseidonHash4([ @@ -90,9 +90,9 @@ describe('check-nullifier-tokenid-uri circuit tests', () => { expect(witness[4]).to.equal(salt1); }); - it('should fail to calculate witness due to invalid nullifier', async () => { + it("should fail to calculate witness due to invalid nullifier", async () => { const tokenId = 1001; - const tokenUri = tokenUriHash('http://ipfs.io/some-file-hash'); + const tokenUri = tokenUriHash("http://ipfs.io/some-file-hash"); const salt1 = newSalt(); const nullifier1 = poseidonHash4([ diff --git a/zkp/js/test/lib/check-nullifiers.js b/zkp/js/test/lib/check-nullifiers.js index cb2efdf..239602e 100644 --- a/zkp/js/test/lib/check-nullifiers.js +++ b/zkp/js/test/lib/check-nullifiers.js @@ -14,15 +14,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Poseidon, newSalt } = require('../../index.js'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); +const { Poseidon, newSalt } = require("../../index.js"); const poseidonHash3 = Poseidon.poseidon3; -describe('check-nullifiers circuit tests', () => { +describe("check-nullifiers circuit tests", () => { let circuit, smt; const sender = {}; let senderPrivateKey; @@ -31,7 +31,7 @@ describe('check-nullifiers circuit tests', () => { this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../circuits/check-nullifiers.circom'), + join(__dirname, "../circuits/check-nullifiers.circom"), ); let keypair = genKeypair(); @@ -40,7 +40,7 @@ describe('check-nullifiers circuit tests', () => { senderPrivateKey = formatPrivKeyForBabyJub(sender.privKey); }); - it('should return true for valid witness', async () => { + it("should return true for valid witness", async () => { const values = [32, 40]; // create two input nullifiers, corresponding to the input UTXOs @@ -80,7 +80,7 @@ describe('check-nullifiers circuit tests', () => { expect(witness[4]).to.equal(BigInt(values[1])); }); - it('should return true for valid witness - single input', async () => { + it("should return true for valid witness - single input", async () => { const inputValues = [72, 0]; // create two input nullifiers, corresponding to the input UTXOs diff --git a/zkp/js/test/lib/check-positive.js b/zkp/js/test/lib/check-positive.js index 9e4de9a..4c76b39 100644 --- a/zkp/js/test/lib/check-positive.js +++ b/zkp/js/test/lib/check-positive.js @@ -14,24 +14,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); const MAX_VALUE = 2n ** 40n - 1n; -describe('check-positive circuit tests', () => { +describe("check-positive circuit tests", () => { let circuit; before(async function () { this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../circuits/check-positive.circom'), + join(__dirname, "../circuits/check-positive.circom"), ); }); - it('should succeed to generate a witness using the MAX_VALUE for output', async () => { + it("should succeed to generate a witness using the MAX_VALUE for output", async () => { const outputValues = [MAX_VALUE, 100]; let error; @@ -49,7 +49,7 @@ describe('check-positive circuit tests', () => { expect(error).to.be.undefined; }); - it('should fail to generate a witness because of negative values in output commitments', async () => { + it("should fail to generate a witness because of negative values in output commitments", async () => { // in the finite field used in the Poseidion hash implementation, -100n is equivalent to // 21888242871839275222246405745257275088548364400416034343698204186575808495517n const outputValues = [-100, 225]; @@ -69,7 +69,7 @@ describe('check-positive circuit tests', () => { expect(error).to.match(/Error in template CheckPositive_3 line: 39/); // positive range check failed }); - it('should fail to generate a witness because of using the inverse of a negative value in output commitments', async () => { + it("should fail to generate a witness because of using the inverse of a negative value in output commitments", async () => { // in the finite field used in the Poseidion hash implementation, -100n is equivalent to // 21888242871839275222246405745257275088548364400416034343698204186575808495517n. This number // is considered negative by the circuit, because we allow the range of 0 to (2**40 - 1) @@ -93,7 +93,7 @@ describe('check-positive circuit tests', () => { expect(error).to.match(/Error in template CheckPositive_3 line: 39/); // positive range check failed }); - it('should fail to generate a witness because a larger than MAX_VALUE is used in output', async () => { + it("should fail to generate a witness because a larger than MAX_VALUE is used in output", async () => { const outputValues = [MAX_VALUE + 1n, 99]; let error; diff --git a/zkp/js/test/lib/check-smt-proof.js b/zkp/js/test/lib/check-smt-proof.js index f2e05e7..70971bc 100644 --- a/zkp/js/test/lib/check-smt-proof.js +++ b/zkp/js/test/lib/check-smt-proof.js @@ -14,23 +14,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); -const { Poseidon, newSalt, tokenUriHash } = require('../../index.js'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); +const { Poseidon, newSalt, tokenUriHash } = require("../../index.js"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); +} = require("@iden3/js-merkletree"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon5; const poseidonHash4 = Poseidon.poseidon4; -describe('check-smt-proof circuit tests', () => { +describe("check-smt-proof circuit tests", () => { let circuit, smt; const sender = {}; const receiver = {}; @@ -40,7 +40,7 @@ describe('check-smt-proof circuit tests', () => { this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../circuits/check-smt-proof.circom'), + join(__dirname, "../circuits/check-smt-proof.circom"), ); let keypair = genKeypair(); @@ -52,13 +52,13 @@ describe('check-smt-proof circuit tests', () => { receiver.privKey = keypair.privKey; receiver.pubKey = keypair.pubKey; - const storage = new InMemoryDB(str2Bytes('')); + const storage = new InMemoryDB(str2Bytes("")); smt = new Merkletree(storage, true, SMT_HEIGHT); }); - it('should return true for valid witness', async () => { + it("should return true for valid witness", async () => { const tokenId = 1001; - const tokenUri = tokenUriHash('http://ipfs.io/some-file-hash'); + const tokenUri = tokenUriHash("http://ipfs.io/some-file-hash"); // create two input UTXOs const salt1 = newSalt(); diff --git a/zkp/js/test/lib/check-sum.js b/zkp/js/test/lib/check-sum.js index b287b93..1b7ceec 100644 --- a/zkp/js/test/lib/check-sum.js +++ b/zkp/js/test/lib/check-sum.js @@ -14,22 +14,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); -describe('check-sum circuit tests', () => { +describe("check-sum circuit tests", () => { let circuit; before(async function () { this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../circuits/check-sum.circom'), + join(__dirname, "../circuits/check-sum.circom"), ); }); - it('should return true for valid witness', async () => { + it("should return true for valid witness", async () => { const inputValues = [32, 40]; const outputValues = [20, 52]; @@ -44,7 +44,7 @@ describe('check-sum circuit tests', () => { expect(witness[0]).to.equal(BigInt(1)); }); - it('should fail if sums are not equal', async () => { + it("should fail if sums are not equal", async () => { const inputValues = [32, 40]; const outputValues = [20, 50]; diff --git a/zkp/js/test/lib/ecdh.js b/zkp/js/test/lib/ecdh.js index 07fd479..58c2d9a 100644 --- a/zkp/js/test/lib/ecdh.js +++ b/zkp/js/test/lib/ecdh.js @@ -14,23 +14,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); const { genKeypair, genEcdhSharedKey, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); +} = require("maci-crypto"); -describe('Ecdh circuit tests', () => { +describe("Ecdh circuit tests", () => { let circuit; let senderPrivKey, senderPubKey, receiverPrivKey, receiverPubKey; before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../circuits/ecdh.circom')); + circuit = await wasm_tester(join(__dirname, "../circuits/ecdh.circom")); let keypair = genKeypair(); senderPrivKey = keypair.privKey; @@ -41,7 +41,7 @@ describe('Ecdh circuit tests', () => { receiverPubKey = keypair.pubKey; }); - it('should generate the shared secret in the proof circuit, which can be reproduced by the receiver', async () => { + it("should generate the shared secret in the proof circuit, which can be reproduced by the receiver", async () => { const circuitInputs = stringifyBigInts({ privKey: formatPrivKeyForBabyJub(senderPrivKey), pubKey: receiverPubKey, diff --git a/zkp/js/test/lib/encrypt.js b/zkp/js/test/lib/encrypt.js index 54339aa..f22154f 100644 --- a/zkp/js/test/lib/encrypt.js +++ b/zkp/js/test/lib/encrypt.js @@ -14,24 +14,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const crypto = require('crypto'); -const { wasm: wasm_tester } = require('circom_tester'); +const { expect } = require("chai"); +const { join } = require("path"); +const crypto = require("crypto"); +const { wasm: wasm_tester } = require("circom_tester"); const { genKeypair, genEcdhSharedKey, stringifyBigInts, -} = require('maci-crypto'); -const { poseidonEncrypt, poseidonDecrypt } = require('../../lib/util.js'); +} = require("maci-crypto"); +const { poseidonEncrypt, poseidonDecrypt } = require("../../lib/util.js"); -describe('Encryption circuit tests', () => { +describe("Encryption circuit tests", () => { let circuit; let senderPrivKey, senderPubKey, receiverPrivKey, receiverPubKey; before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../circuits/encrypt.circom')); + circuit = await wasm_tester(join(__dirname, "../circuits/encrypt.circom")); let keypair = genKeypair(); senderPrivKey = keypair.privKey; @@ -42,9 +42,9 @@ describe('Encryption circuit tests', () => { receiverPubKey = keypair.pubKey; }); - it('using poseidonEncrypt() to generate the cipher text, and poseidonDecrypt() to recover the plain text', async () => { + it("using poseidonEncrypt() to generate the cipher text, and poseidonDecrypt() to recover the plain text", async () => { const key = genEcdhSharedKey(senderPrivKey, receiverPubKey); - const hex = crypto.randomBytes(16).toString('hex'); + const hex = crypto.randomBytes(16).toString("hex"); const nonce = BigInt(`0x${hex}`); const result = await poseidonEncrypt( @@ -58,9 +58,9 @@ describe('Encryption circuit tests', () => { expect(plainText).to.deep.equal([1234567890n, 2345678901n]); }); - it('using poseidonEncrypt() to generate the cipher text with inputs longer than 3, and poseidonDecrypt() to recover the plain text', async () => { + it("using poseidonEncrypt() to generate the cipher text with inputs longer than 3, and poseidonDecrypt() to recover the plain text", async () => { const key = genEcdhSharedKey(senderPrivKey, receiverPubKey); - const hex = crypto.randomBytes(16).toString('hex'); + const hex = crypto.randomBytes(16).toString("hex"); const nonce = BigInt(`0x${hex}`); const result = await poseidonEncrypt( @@ -79,9 +79,9 @@ describe('Encryption circuit tests', () => { ]); }); - it('should generate the cipher text in the proof circuit, which can be decrypted by the receiver', async () => { + it("should generate the cipher text in the proof circuit, which can be decrypted by the receiver", async () => { const key = genEcdhSharedKey(senderPrivKey, receiverPubKey); - const hex = crypto.randomBytes(16).toString('hex'); + const hex = crypto.randomBytes(16).toString("hex"); const nonce = BigInt(`0x${hex}`); const circuitInputs = stringifyBigInts({ diff --git a/zkp/js/test/lib/poseidon-ex.js b/zkp/js/test/lib/poseidon-ex.js index bc32b9f..96d9ede 100644 --- a/zkp/js/test/lib/poseidon-ex.js +++ b/zkp/js/test/lib/poseidon-ex.js @@ -14,21 +14,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { poseidon4 } = require('poseidon-lite'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { poseidon4 } = require("poseidon-lite"); -describe('PoseidonEx circuit tests', () => { +describe("PoseidonEx circuit tests", () => { let circuit; before(async function () { this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../circuits/poseidon-ex.circom'), + join(__dirname, "../circuits/poseidon-ex.circom"), ); }); - it('should generate the states matching JS lib', async () => { + it("should generate the states matching JS lib", async () => { const inputs = [1234567890, 2345678901, 3456789012, 4567890123]; const witness = await circuit.calculateWitness({ inputs }); diff --git a/zkp/js/test/lib/poseidon.js b/zkp/js/test/lib/poseidon.js index 9e5f1cf..ce994cc 100644 --- a/zkp/js/test/lib/poseidon.js +++ b/zkp/js/test/lib/poseidon.js @@ -14,19 +14,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { poseidon3 } = require('poseidon-lite'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { poseidon3 } = require("poseidon-lite"); -describe('Poseidon circuit tests', () => { +describe("Poseidon circuit tests", () => { let circuit; before(async function () { this.timeout(60000); - circuit = await wasm_tester(join(__dirname, '../circuits/poseidon.circom')); + circuit = await wasm_tester(join(__dirname, "../circuits/poseidon.circom")); }); - it('should generate the states matching JS lib', async () => { + it("should generate the states matching JS lib", async () => { const messages = [1234567890, 2345678901, 3456789012]; const circuitInputs = { diff --git a/zkp/js/test/nf_anon.js b/zkp/js/test/nf_anon.js index 3fb5922..7c46d6d 100644 --- a/zkp/js/test/nf_anon.js +++ b/zkp/js/test/nf_anon.js @@ -14,19 +14,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); const { genKeypair, formatPrivKeyForBabyJub, stringifyBigInts, -} = require('maci-crypto'); -const { Poseidon, newSalt, tokenUriHash } = require('../index.js'); +} = require("maci-crypto"); +const { Poseidon, newSalt, tokenUriHash } = require("../index.js"); const poseidonHash = Poseidon.poseidon5; -describe('main circuit tests for Zeto non-fungible tokens with anonymity without encryption', () => { +describe("main circuit tests for Zeto non-fungible tokens with anonymity without encryption", () => { let circuit; const sender = {}; @@ -36,7 +36,7 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/nf_anon.circom'), + join(__dirname, "../../circuits/nf_anon.circom"), ); let keypair = genKeypair(); @@ -48,9 +48,9 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without receiver.pubKey = keypair.pubKey; }); - it('should succeed for valid witness and produce an encypted value', async () => { + it("should succeed for valid witness and produce an encypted value", async () => { const tokenIds = [1001]; - const tokenUris = [tokenUriHash('http://ipfs.io/some-file-hash')]; + const tokenUris = [tokenUriHash("http://ipfs.io/some-file-hash")]; // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); @@ -106,10 +106,10 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without expect(witness[4]).to.equal(tokenUris[0]); }); - it('should fail to generate a witness because token Id changed', async () => { + it("should fail to generate a witness because token Id changed", async () => { const inputTokenIds = [1001]; const outputTokenIds = [1002]; - const tokenUris = [tokenUriHash('http://ipfs.io/some-file-hash')]; + const tokenUris = [tokenUriHash("http://ipfs.io/some-file-hash")]; // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); @@ -160,11 +160,11 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity without ); }); - it('should fail to generate a witness because token URI changed', async () => { + it("should fail to generate a witness because token URI changed", async () => { const tokenIds = [1001]; - const inputTokenUris = [tokenUriHash('http://ipfs.io/some-file-hash')]; + const inputTokenUris = [tokenUriHash("http://ipfs.io/some-file-hash")]; const outputTokenUris = [ - tokenUriHash('http://ipfs.io/some-other-file-hash'), + tokenUriHash("http://ipfs.io/some-other-file-hash"), ]; // create two input UTXOs, each has their own salt, but same owner diff --git a/zkp/js/test/nf_anon_nullifier.js b/zkp/js/test/nf_anon_nullifier.js index 035b0b6..27f7c2b 100644 --- a/zkp/js/test/nf_anon_nullifier.js +++ b/zkp/js/test/nf_anon_nullifier.js @@ -14,23 +14,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { expect } = require('chai'); -const { join } = require('path'); -const { wasm: wasm_tester } = require('circom_tester'); -const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto'); +const { expect } = require("chai"); +const { join } = require("path"); +const { wasm: wasm_tester } = require("circom_tester"); +const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto"); const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH, -} = require('@iden3/js-merkletree'); -const { Poseidon, newSalt, tokenUriHash } = require('../index.js'); +} = require("@iden3/js-merkletree"); +const { Poseidon, newSalt, tokenUriHash } = require("../index.js"); const SMT_HEIGHT = 64; const poseidonHash = Poseidon.poseidon5; const poseidonHash4 = Poseidon.poseidon4; -describe('main circuit tests for Zeto non-fungible tokens with anonymity using nullifiers and without encryption', () => { +describe("main circuit tests for Zeto non-fungible tokens with anonymity using nullifiers and without encryption", () => { let circuit, smtAlice, smtBob; const Alice = {}; @@ -41,7 +41,7 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n this.timeout(60000); circuit = await wasm_tester( - join(__dirname, '../../circuits/nf_anon_nullifier.circom'), + join(__dirname, "../../circuits/nf_anon_nullifier.circom"), ); let keypair = genKeypair(); @@ -54,17 +54,17 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n Bob.pubKey = keypair.pubKey; // initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree - const storage1 = new InMemoryDB(str2Bytes('')); + const storage1 = new InMemoryDB(str2Bytes("")); smtAlice = new Merkletree(storage1, true, SMT_HEIGHT); // initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree - const storage2 = new InMemoryDB(str2Bytes('')); + const storage2 = new InMemoryDB(str2Bytes("")); smtBob = new Merkletree(storage2, true, SMT_HEIGHT); }); - it('should succeed for valid witness', async () => { + it("should succeed for valid witness", async () => { const tokenId = 1001; - const tokenUri = tokenUriHash('http://ipfs.io/some-file-hash'); + const tokenUri = tokenUriHash("http://ipfs.io/some-file-hash"); // create two input UTXOs, each has their own salt, but same owner const salt1 = newSalt(); @@ -133,9 +133,9 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n expect(witness[3]).to.equal(BigInt(output1)); }); - it('should fail to generate a witness because token ID changed', async () => { + it("should fail to generate a witness because token ID changed", async () => { const tokenId = 1001; - const tokenUri = tokenUriHash('http://ipfs.io/some-file-hash'); + const tokenUri = tokenUriHash("http://ipfs.io/some-file-hash"); // create two input UTXOs const salt1 = newSalt(); @@ -200,9 +200,9 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n ); }); - it('should fail to generate a witness because token URI changed', async () => { + it("should fail to generate a witness because token URI changed", async () => { const tokenId = 1001; - const tokenUri = tokenUriHash('http://ipfs.io/some-file-hash'); + const tokenUri = tokenUriHash("http://ipfs.io/some-file-hash"); // create two input UTXOs const salt1 = newSalt(); @@ -232,7 +232,7 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const tokenUriBad = tokenUriHash('http://ipfs.io/some-other-file-hash'); + const tokenUriBad = tokenUriHash("http://ipfs.io/some-other-file-hash"); const output1 = poseidonHash([ BigInt(tokenId), tokenUriBad, @@ -268,9 +268,9 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n ); }); - it('should fail to generate a witness because of invalid input commitments', async () => { + it("should fail to generate a witness because of invalid input commitments", async () => { const tokenId = 1001; - const tokenUri = tokenUriHash('http://ipfs.io/some-file-hash'); + const tokenUri = tokenUriHash("http://ipfs.io/some-file-hash"); // create two input UTXOs const salt1 = newSalt(); @@ -300,7 +300,7 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const tokenUriBad = tokenUriHash('http://ipfs.io/some-other-file-hash'); + const tokenUriBad = tokenUriHash("http://ipfs.io/some-other-file-hash"); const output1 = poseidonHash([ BigInt(tokenId), tokenUriBad, @@ -335,9 +335,9 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n ); }); - it('should fail to generate a witness because of invalid output commitments', async () => { + it("should fail to generate a witness because of invalid output commitments", async () => { const tokenId = 1001; - const tokenUri = tokenUriHash('http://ipfs.io/some-file-hash'); + const tokenUri = tokenUriHash("http://ipfs.io/some-file-hash"); // create two input UTXOs const salt1 = newSalt(); @@ -367,7 +367,7 @@ describe('main circuit tests for Zeto non-fungible tokens with anonymity using n // create two output UTXOs, they share the same salt, and different owner const salt3 = newSalt(); - const tokenUriBad = tokenUriHash('http://ipfs.io/some-other-file-hash'); + const tokenUriBad = tokenUriHash("http://ipfs.io/some-other-file-hash"); const output1 = poseidonHash([ BigInt(tokenId), tokenUriBad, From c32f72594452ed4d106beb647e764ef928964c53 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Tue, 1 Oct 2024 09:53:12 +0100 Subject: [PATCH 19/24] add comments and rename variable Signed-off-by: Chengxuan Xing --- solidity/contracts/lib/zeto_common.sol | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/solidity/contracts/lib/zeto_common.sol b/solidity/contracts/lib/zeto_common.sol index 6d1e121..03d607e 100644 --- a/solidity/contracts/lib/zeto_common.sol +++ b/solidity/contracts/lib/zeto_common.sol @@ -28,7 +28,7 @@ abstract contract ZetoCommon is OwnableUpgradeable { error UTXOAlreadySpent(uint256 utxo); error UTXODuplicate(uint256 utxo); error IdentityNotRegistered(address addr); - error UTXOCommitmentsExceededMaximumNumber(uint256 maxAllowed); + error UTXOArrayTooLarge(uint256 maxAllowed); // used for multi-step transaction flows that require counterparties // to upload proofs. To protect the party that uploads their proof first, @@ -66,13 +66,18 @@ abstract contract ZetoCommon is OwnableUpgradeable { // Check if inputs or outputs exceed batchMax and revert with custom error if necessary if (inputLen > batchMax || outputLen > batchMax) { - revert UTXOCommitmentsExceededMaximumNumber(batchMax); + revert UTXOArrayTooLarge(batchMax); } // Ensure both arrays are padded to the same length uint256 maxLength; + // By default all tokens supports at least a circuit with 2 inputs and 2 outputs + // which has a shorter proof generation time and should cover most use cases. + // In addition, tokens can support circuits with bigger inputs if (inputLen > 2 || outputLen > 2) { + // check whether a batch circuit is required + maxLength = batchMax; // Pad both to batchMax if one has more than 2 items } else { maxLength = 2; // Otherwise, pad both to 2 From 759c610cae68a449b9c6c77c6b09ed35c1d2e5d9 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Tue, 1 Oct 2024 11:25:45 +0100 Subject: [PATCH 20/24] refactor for readability Signed-off-by: Chengxuan Xing --- solidity/contracts/zeto_anon.sol | 70 +++++--- solidity/contracts/zeto_anon_enc.sol | 115 +++++++----- .../contracts/zeto_anon_enc_nullifier.sol | 140 ++++++++------- .../contracts/zeto_anon_enc_nullifier_kyc.sol | 147 ++++++++------- ...eto_anon_enc_nullifier_non_repudiation.sol | 168 +++++++++--------- solidity/contracts/zeto_anon_nullifier.sol | 95 ++++++---- .../contracts/zeto_anon_nullifier_kyc.sol | 103 ++++++----- 7 files changed, 467 insertions(+), 371 deletions(-) diff --git a/solidity/contracts/zeto_anon.sol b/solidity/contracts/zeto_anon.sol index ba14e7e..70b8ed6 100644 --- a/solidity/contracts/zeto_anon.sol +++ b/solidity/contracts/zeto_anon.sol @@ -29,6 +29,8 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; uint256 constant MAX_BATCH = 10; +uint256 constant INPUT_SIZE = 4; +uint256 constant BATCH_INPUT_SIZE = 20; /// @title A sample implementation of a Zeto based fungible token with anonymity and no encryption /// @author Kaleido, Inc. @@ -56,6 +58,26 @@ contract Zeto_Anon is IZeto, ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable { function _authorizeUpgrade(address) internal override onlyOwner {} + function constructPublicInputs( + uint256[] memory inputs, + uint256[] memory outputs, + uint256 size + ) internal returns (uint256[] memory publicInputs) { + publicInputs = new uint256[](size); + uint256 piIndex = 0; + // copy input commitments + for (uint256 i = 0; i < inputs.length; i++) { + publicInputs[piIndex++] = inputs[i]; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + return publicInputs; + } + /** * @dev the main function of the contract. * @@ -81,48 +103,46 @@ contract Zeto_Anon is IZeto, ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable { ); // Check the proof - if (inputs.length > 2) { - // construct the public inputs - uint256[20] memory publicInputs; - uint256 piIndex = 0; - // copy input commitments - for (uint256 i = 0; i < inputs.length; i++) { - publicInputs[piIndex++] = inputs[i]; - } - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + if (inputs.length > 2 || outputs.length > 2) { + uint256[] memory publicInputs = constructPublicInputs( + inputs, + outputs, + BATCH_INPUT_SIZE + ); + // construct the public inputs for batchVerifier + uint256[BATCH_INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } + // Check the proof using batchVerifier require( batchVerifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); } else { - // construct the public inputs - uint256[4] memory publicInputs; - uint256 piIndex = 0; - // copy input commitments - for (uint256 i = 0; i < inputs.length; i++) { - publicInputs[piIndex++] = inputs[i]; - } - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + uint256[] memory publicInputs = constructPublicInputs( + inputs, + outputs, + INPUT_SIZE + ); + // construct the public inputs for verifier + uint256[INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } + // Check the proof require( verifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); diff --git a/solidity/contracts/zeto_anon_enc.sol b/solidity/contracts/zeto_anon_enc.sol index 76e8473..0d6f57c 100644 --- a/solidity/contracts/zeto_anon_enc.sol +++ b/solidity/contracts/zeto_anon_enc.sol @@ -29,6 +29,8 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; uint256 constant MAX_BATCH = 10; +uint256 constant INPUT_SIZE = 14; +uint256 constant BATCH_INPUT_SIZE = 45; /// @title A sample implementation of a Zeto based fungible token with anonymity, and encryption /// @author Kaleido, Inc. @@ -63,6 +65,40 @@ contract Zeto_AnonEnc is function _authorizeUpgrade(address) internal override onlyOwner {} + function constructPublicInputs( + uint256[] memory inputs, + uint256[] memory outputs, + uint256 encryptionNonce, + uint256[2] memory ecdhPublicKey, + uint256[] memory encryptedValues, + uint256 size + ) internal returns (uint256[] memory publicInputs) { + publicInputs = new uint256[](size); + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } + // copy the ecdh public key + for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { + publicInputs[piIndex++] = ecdhPublicKey[i]; + } + // copy input commitments + for (uint256 i = 0; i < inputs.length; i++) { + publicInputs[piIndex++] = inputs[i]; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + + return publicInputs; + } + /** * @dev the main function of the contract. * @@ -89,77 +125,58 @@ contract Zeto_AnonEnc is "Invalid transaction proposal" ); - if (inputs.length > 2) { - // construct the public inputs - uint256[45] memory publicInputs; - uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit - for (uint256 i = 0; i < encryptedValues.length; ++i) { - publicInputs[piIndex++] = encryptedValues[i]; - } - // copy the ecdh public key - for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { - publicInputs[piIndex++] = ecdhPublicKey[i]; - } - // copy input commitments - for (uint256 i = 0; i < inputs.length; i++) { - publicInputs[piIndex++] = inputs[i]; - } - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + // Check the proof + if (inputs.length > 2 || outputs.length > 2) { + uint256[] memory publicInputs = constructPublicInputs( + inputs, + outputs, + encryptionNonce, + ecdhPublicKey, + encryptedValues, + BATCH_INPUT_SIZE + ); + // construct the public inputs for batchVerifier + uint256[BATCH_INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } - // copy encryption nonce - publicInputs[piIndex++] = encryptionNonce; - - // Check the proof + // Check the proof using batchVerifier require( batchVerifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); } else { - // construct the public inputs - uint256[14] memory publicInputs; - uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit - for (uint256 i = 0; i < encryptedValues.length; ++i) { - publicInputs[piIndex++] = encryptedValues[i]; - } - // copy the ecdh public key - for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { - publicInputs[piIndex++] = ecdhPublicKey[i]; - } - // copy input commitments - for (uint256 i = 0; i < inputs.length; i++) { - publicInputs[piIndex++] = inputs[i]; - } - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + uint256[] memory publicInputs = constructPublicInputs( + inputs, + outputs, + encryptionNonce, + ecdhPublicKey, + encryptedValues, + INPUT_SIZE + ); + // construct the public inputs for verifier + uint256[INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } - - // copy encryption nonce - publicInputs[piIndex++] = encryptionNonce; - // Check the proof require( verifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); } + processInputsAndOutputs(inputs, outputs); uint256[] memory encryptedValuesArray = new uint256[]( diff --git a/solidity/contracts/zeto_anon_enc_nullifier.sol b/solidity/contracts/zeto_anon_enc_nullifier.sol index 50bdba9..2a70fa5 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier.sol @@ -27,6 +27,8 @@ import {Commonlib} from "./lib/common.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; uint256 constant MAX_BATCH = 10; +uint256 constant INPUT_SIZE = 17; +uint256 constant BATCH_INPUT_SIZE = 56; /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking /// @author Kaleido, Inc. @@ -64,6 +66,48 @@ contract Zeto_AnonEncNullifier is function _authorizeUpgrade(address) internal override onlyOwner {} + function constructPublicInputs( + uint256[] memory nullifiers, + uint256[] memory outputs, + uint256 root, + uint256 encryptionNonce, + uint256[2] memory ecdhPublicKey, + uint256[] memory encryptedValues, + uint256 size + ) internal returns (uint256[] memory publicInputs) { + publicInputs = new uint256[](size); + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } + // copy the ecdh public key + for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { + publicInputs[piIndex++] = ecdhPublicKey[i]; + } + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + return publicInputs; + } + /** * @dev the main function of the contract, which transfers values from one account (represented by Babyjubjub public keys) * to one or more receiver accounts (also represented by Babyjubjub public keys). One of the two nullifiers may be zero @@ -98,89 +142,55 @@ contract Zeto_AnonEncNullifier is validateTransactionProposal(nullifiers, outputs, root), "Invalid transaction proposal" ); - if (nullifiers.length > 2) { - // construct the public inputs - uint256[56] memory publicInputs; - uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit - for (uint256 i = 0; i < encryptedValues.length; ++i) { - publicInputs[piIndex++] = encryptedValues[i]; - } - // copy the ecdh public key - for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { - publicInputs[piIndex++] = ecdhPublicKey[i]; - } - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } - - // copy root - publicInputs[piIndex++] = root; - - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; - } - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + // Check the proof + if (nullifiers.length > 2 || outputs.length > 2) { + uint256[] memory publicInputs = constructPublicInputs( + nullifiers, + outputs, + root, + encryptionNonce, + ecdhPublicKey, + encryptedValues, + BATCH_INPUT_SIZE + ); + // construct the public inputs for batchVerifier + uint256[BATCH_INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } - // copy encryption nonce - publicInputs[piIndex++] = encryptionNonce; - - // Check the proof + // Check the proof using batchVerifier require( batchVerifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); } else { - // construct the public inputs - uint256[17] memory publicInputs; - uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit - for (uint256 i = 0; i < encryptedValues.length; ++i) { - publicInputs[piIndex++] = encryptedValues[i]; - } - // copy the ecdh public key - for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { - publicInputs[piIndex++] = ecdhPublicKey[i]; - } - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } - - // copy root - publicInputs[piIndex++] = root; - - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; - } - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + uint256[] memory publicInputs = constructPublicInputs( + nullifiers, + outputs, + root, + encryptionNonce, + ecdhPublicKey, + encryptedValues, + INPUT_SIZE + ); + // construct the public inputs for verifier + uint256[INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } - - // copy encryption nonce - publicInputs[piIndex++] = encryptionNonce; - // Check the proof require( verifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); diff --git a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol index 84d67ea..f1790ad 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol @@ -27,6 +27,8 @@ import {Commonlib} from "./lib/common.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; uint256 constant MAX_BATCH = 10; +uint256 constant INPUT_SIZE = 18; +uint256 constant BATCH_INPUT_SIZE = 57; /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking /// @author Kaleido, Inc. @@ -69,6 +71,52 @@ contract Zeto_AnonEncNullifierKyc is function register(uint256[2] memory publicKey) public onlyOwner { _register(publicKey); } + + function constructPublicInputs( + uint256[] memory nullifiers, + uint256[] memory outputs, + uint256 root, + uint256 encryptionNonce, + uint256[2] memory ecdhPublicKey, + uint256[] memory encryptedValues, + uint256 size + ) internal returns (uint256[] memory publicInputs) { + publicInputs = new uint256[](size); + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } + // copy the ecdh public key + for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { + publicInputs[piIndex++] = ecdhPublicKey[i]; + } + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy identities root + publicInputs[piIndex++] = getIdentitiesRoot(); + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + + return publicInputs; + } + /** * @dev the main function of the contract, which transfers values from one account (represented by Babyjubjub public keys) * to one or more receiver accounts (also represented by Babyjubjub public keys). One of the two nullifiers may be zero @@ -103,93 +151,56 @@ contract Zeto_AnonEncNullifierKyc is validateTransactionProposal(nullifiers, outputs, root), "Invalid transaction proposal" ); - if (nullifiers.length > 2) { - // construct the public inputs - uint256[57] memory publicInputs; - uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit - for (uint256 i = 0; i < encryptedValues.length; ++i) { - publicInputs[piIndex++] = encryptedValues[i]; - } - // copy the ecdh public key - for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { - publicInputs[piIndex++] = ecdhPublicKey[i]; - } - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } - - // copy root - publicInputs[piIndex++] = root; - - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; - } - // copy identities root - publicInputs[piIndex++] = getIdentitiesRoot(); - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + // Check the proof + if (nullifiers.length > 2 || outputs.length > 2) { + uint256[] memory publicInputs = constructPublicInputs( + nullifiers, + outputs, + root, + encryptionNonce, + ecdhPublicKey, + encryptedValues, + BATCH_INPUT_SIZE + ); + // construct the public inputs for batchVerifier + uint256[BATCH_INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } - // copy encryption nonce - publicInputs[piIndex++] = encryptionNonce; - - // Check the proof + // Check the proof using batchVerifier require( batchVerifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); } else { - // construct the public inputs - uint256[18] memory publicInputs; - uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit - for (uint256 i = 0; i < encryptedValues.length; ++i) { - publicInputs[piIndex++] = encryptedValues[i]; - } - // copy the ecdh public key - for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { - publicInputs[piIndex++] = ecdhPublicKey[i]; - } - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } - - // copy root - publicInputs[piIndex++] = root; - - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; - } - - // copy identities root - publicInputs[piIndex++] = getIdentitiesRoot(); - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + uint256[] memory publicInputs = constructPublicInputs( + nullifiers, + outputs, + root, + encryptionNonce, + ecdhPublicKey, + encryptedValues, + INPUT_SIZE + ); + // construct the public inputs for verifier + uint256[INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } - - // copy encryption nonce - publicInputs[piIndex++] = encryptionNonce; - // Check the proof require( verifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); diff --git a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol index 731665c..3326f84 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol @@ -26,6 +26,8 @@ import {Registry} from "./lib/registry.sol"; import {Commonlib} from "./lib/common.sol"; uint256 constant MAX_BATCH = 10; +uint256 constant INPUT_SIZE = 35; +uint256 constant BATCH_INPUT_SIZE = 122; /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking /// @author Kaleido, Inc. @@ -84,6 +86,57 @@ contract Zeto_AnonEncNullifierNonRepudiation is return arbiter; } + function constructPublicInputs( + uint256[] memory nullifiers, + uint256[] memory outputs, + uint256 root, + uint256 encryptionNonce, + uint256[2] memory ecdhPublicKey, + uint256[] memory encryptedValuesForReceiver, + uint256[] memory encryptedValuesForAuthority, + uint256 size + ) internal returns (uint256[] memory publicInputs) { + publicInputs = new uint256[](size); + uint256 piIndex = 0; + // copy the encrypted value, salt and parity bit for receiver + for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { + publicInputs[piIndex++] = encryptedValuesForReceiver[i]; + } + // copy the ecdh public key + for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { + publicInputs[piIndex++] = ecdhPublicKey[i]; + } + // copy the encrypted value, salt and parity bit for authority + for (uint256 i = 0; i < encryptedValuesForAuthority.length; ++i) { + publicInputs[piIndex++] = encryptedValuesForAuthority[i]; + } + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + // copy encryption nonce + publicInputs[piIndex++] = encryptionNonce; + + // copy arbiter pub key + publicInputs[piIndex++] = arbiter[0]; + publicInputs[piIndex++] = arbiter[1]; + return publicInputs; + } + /** * @dev the main function of the contract, which transfers values from one account (represented by Babyjubjub public keys) * to one or more receiver accounts (also represented by Babyjubjub public keys). One of the two nullifiers may be zero @@ -122,58 +175,36 @@ contract Zeto_AnonEncNullifierNonRepudiation is validateTransactionProposal(nullifiers, outputs, root), "Invalid transaction proposal" ); - if (nullifiers.length > 2) { + + // Check the proof + if (nullifiers.length > 2 || outputs.length > 2) { require( (encryptedValuesForAuthority.length == 64), "Cipher Text for Authority must have a length of 64 with input or outputs number more than 2 and less than 10" ); - // construct the public inputs - uint256[122] memory publicInputs; - uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit for receiver - for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { - publicInputs[piIndex++] = encryptedValuesForReceiver[i]; - } - // copy the ecdh public key - for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { - publicInputs[piIndex++] = ecdhPublicKey[i]; - } - // copy the encrypted value, salt and parity bit for authority - for (uint256 i = 0; i < encryptedValuesForAuthority.length; ++i) { - publicInputs[piIndex++] = encryptedValuesForAuthority[i]; - } - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } - - // copy root - publicInputs[piIndex++] = root; - - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; - } - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + uint256[] memory publicInputs = constructPublicInputs( + nullifiers, + outputs, + root, + encryptionNonce, + ecdhPublicKey, + encryptedValuesForReceiver, + encryptedValuesForAuthority, + BATCH_INPUT_SIZE + ); + // construct the public inputs for batchVerifier + uint256[BATCH_INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } - // copy encryption nonce - publicInputs[piIndex++] = encryptionNonce; - - // copy arbiter pub key - publicInputs[piIndex++] = arbiter[0]; - publicInputs[piIndex++] = arbiter[1]; - - // Check the proof + // Check the proof using batchVerifier require( batchVerifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); @@ -182,53 +213,28 @@ contract Zeto_AnonEncNullifierNonRepudiation is (encryptedValuesForAuthority.length == 16), "Cipher Text for Authority must have a length of 16 for no more than 2 inputs or outputs" ); - // construct the public inputs - uint256[35] memory publicInputs; - uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit for receiver - for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { - publicInputs[piIndex++] = encryptedValuesForReceiver[i]; - } - // copy the ecdh public key - for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { - publicInputs[piIndex++] = ecdhPublicKey[i]; - } - // copy the encrypted value, salt and parity bit for authority - for (uint256 i = 0; i < encryptedValuesForAuthority.length; ++i) { - publicInputs[piIndex++] = encryptedValuesForAuthority[i]; - } - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } - - // copy root - publicInputs[piIndex++] = root; - - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; - } - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + uint256[] memory publicInputs = constructPublicInputs( + nullifiers, + outputs, + root, + encryptionNonce, + ecdhPublicKey, + encryptedValuesForReceiver, + encryptedValuesForAuthority, + INPUT_SIZE + ); + // construct the public inputs for verifier + uint256[INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } - - // copy encryption nonce - publicInputs[piIndex++] = encryptionNonce; - - // copy arbiter pub key - publicInputs[piIndex++] = arbiter[0]; - publicInputs[piIndex++] = arbiter[1]; - // Check the proof require( verifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); diff --git a/solidity/contracts/zeto_anon_nullifier.sol b/solidity/contracts/zeto_anon_nullifier.sol index 7235e4c..fa771d3 100644 --- a/solidity/contracts/zeto_anon_nullifier.sol +++ b/solidity/contracts/zeto_anon_nullifier.sol @@ -31,6 +31,8 @@ import {PoseidonUnit3L} from "@iden3/contracts/lib/Poseidon.sol"; uint256 constant MAX_SMT_DEPTH = 64; uint256 constant MAX_BATCH = 10; +uint256 constant INPUT_SIZE = 7; +uint256 constant BATCH_INPUT_SIZE = 31; /// @title A sample implementation of a Zeto based fungible token with anonymity and history masking /// @author Kaleido, Inc. @@ -67,6 +69,34 @@ contract Zeto_AnonNullifier is function _authorizeUpgrade(address) internal override onlyOwner {} + function constructPublicInputs( + uint256[] memory nullifiers, + uint256[] memory outputs, + uint256 root, + uint256 size + ) internal returns (uint256[] memory publicInputs) { + publicInputs = new uint256[](size); + uint256 piIndex = 0; + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + return publicInputs; + } + /** * @dev the main function of the contract. * @@ -97,62 +127,49 @@ contract Zeto_AnonNullifier is "Invalid transaction proposal" ); - if (nullifiers.length > 2) { - // construct the public nullifiers - uint256[31] memory publicInputs; - uint256 piIndex = 0; - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } - // copy root - publicInputs[piIndex++] = root; - - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; - } - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + // Check the proof + if (nullifiers.length > 2 || outputs.length > 2) { + uint256[] memory publicInputs = constructPublicInputs( + nullifiers, + outputs, + root, + BATCH_INPUT_SIZE + ); + // construct the public inputs for batchVerifier + uint256[BATCH_INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } + // Check the proof using batchVerifier require( batchVerifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); } else { - // construct the public nullifiers - uint256[7] memory publicInputs; - uint256 piIndex = 0; - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } - // copy root - publicInputs[piIndex++] = root; - - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; - } - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + uint256[] memory publicInputs = constructPublicInputs( + nullifiers, + outputs, + root, + INPUT_SIZE + ); + // construct the public inputs for verifier + uint256[INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } + // Check the proof require( verifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); diff --git a/solidity/contracts/zeto_anon_nullifier_kyc.sol b/solidity/contracts/zeto_anon_nullifier_kyc.sol index 85c4844..46c5141 100644 --- a/solidity/contracts/zeto_anon_nullifier_kyc.sol +++ b/solidity/contracts/zeto_anon_nullifier_kyc.sol @@ -31,6 +31,8 @@ import {PoseidonUnit3L} from "@iden3/contracts/lib/Poseidon.sol"; uint256 constant MAX_SMT_DEPTH = 64; uint256 constant MAX_BATCH = 10; +uint256 constant INPUT_SIZE = 8; +uint256 constant BATCH_INPUT_SIZE = 32; /// @title A sample implementation of a Zeto based fungible token with anonymity and history masking /// @author Kaleido, Inc. @@ -73,6 +75,37 @@ contract Zeto_AnonNullifierKyc is _register(publicKey); } + function constructPublicInputs( + uint256[] memory nullifiers, + uint256[] memory outputs, + uint256 root, + uint256 size + ) internal returns (uint256[] memory publicInputs) { + publicInputs = new uint256[](size); + uint256 piIndex = 0; + // copy input commitments + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = nullifiers[i]; + } + // copy root + publicInputs[piIndex++] = root; + + // populate enables + for (uint256 i = 0; i < nullifiers.length; i++) { + publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + } + + // copy identities root + publicInputs[piIndex++] = getIdentitiesRoot(); + + // copy output commitments + for (uint256 i = 0; i < outputs.length; i++) { + publicInputs[piIndex++] = outputs[i]; + } + + return publicInputs; + } + /** * @dev the main function of the contract. * @@ -103,67 +136,49 @@ contract Zeto_AnonNullifierKyc is "Invalid transaction proposal" ); - if (nullifiers.length > 2) { - // construct the public inputs - uint256[32] memory publicInputs; - uint256 piIndex = 0; - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } - // copy root - publicInputs[piIndex++] = root; - - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; + // Check the proof + if (nullifiers.length > 2 || outputs.length > 2) { + uint256[] memory publicInputs = constructPublicInputs( + nullifiers, + outputs, + root, + BATCH_INPUT_SIZE + ); + // construct the public inputs for batchVerifier + uint256[BATCH_INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } - // copy identities root - publicInputs[piIndex++] = getIdentitiesRoot(); - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; - } + // Check the proof using batchVerifier require( batchVerifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); } else { - // construct the public inputs - uint256[8] memory publicInputs; - uint256 piIndex = 0; - // copy input commitments - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = nullifiers[i]; - } - // copy root - publicInputs[piIndex++] = root; - - // populate enables - for (uint256 i = 0; i < nullifiers.length; i++) { - publicInputs[piIndex++] = (nullifiers[i] == 0) ? 0 : 1; - } - - // copy identities root - publicInputs[piIndex++] = getIdentitiesRoot(); - - // copy output commitments - for (uint256 i = 0; i < outputs.length; i++) { - publicInputs[piIndex++] = outputs[i]; + uint256[] memory publicInputs = constructPublicInputs( + nullifiers, + outputs, + root, + INPUT_SIZE + ); + // construct the public inputs for verifier + uint256[INPUT_SIZE] memory fixedSizeInput; + for (uint256 i = 0; i < fixedSizeInput.length; i++) { + fixedSizeInput[i] = publicInputs[i]; } + // Check the proof require( verifier.verifyProof( proof.pA, proof.pB, proof.pC, - publicInputs + fixedSizeInput ), "Invalid proof" ); From 63979e96ac013d3667a4b673dd7469cc68de7909 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 2 Oct 2024 14:14:17 +0100 Subject: [PATCH 21/24] fixing encryption for output utxos Signed-off-by: Chengxuan Xing --- solidity/contracts/lib/verifier_anon_enc.sol | 69 +- .../contracts/lib/verifier_anon_enc_batch.sol | 312 ++++++--- .../lib/verifier_anon_enc_nullifier.sol | 81 +-- .../lib/verifier_anon_enc_nullifier_batch.sol | 356 ++++++---- .../lib/verifier_anon_enc_nullifier_kyc.sol | 85 +-- .../verifier_anon_enc_nullifier_kyc_batch.sol | 360 ++++++---- ...ier_anon_enc_nullifier_non_repudiation.sol | 153 ++--- ...on_enc_nullifier_non_repudiation_batch.sol | 620 +++++++++++------- solidity/contracts/zeto_anon_enc.sol | 13 +- .../contracts/zeto_anon_enc_nullifier.sol | 12 +- .../contracts/zeto_anon_enc_nullifier_kyc.sol | 12 +- ...eto_anon_enc_nullifier_non_repudiation.sol | 12 +- solidity/test/zeto_anon.ts | 10 +- solidity/test/zeto_anon_enc.ts | 54 +- solidity/test/zeto_anon_enc_nullifier.ts | 54 +- solidity/test/zeto_anon_enc_nullifier_kyc.ts | 69 +- ...zeto_anon_enc_nullifier_non_repudiation.ts | 69 +- solidity/test/zeto_anon_nullifier.ts | 8 +- solidity/test/zeto_anon_nullifier_kyc.ts | 21 +- zkp/circuits/basetokens/anon_enc_base.circom | 49 +- .../basetokens/anon_enc_nullifier_base.circom | 48 +- .../anon_enc_nullifier_kyc_base.circom | 48 +- ..._enc_nullifier_non_repudiation_base.circom | 88 +-- zkp/circuits/gen-config.json | 4 +- zkp/circuits/lib/encrypt-outputs.circom | 52 ++ zkp/js/test/anon_enc.js | 48 +- zkp/js/test/anon_enc_nullifier.js | 52 +- zkp/js/test/anon_enc_nullifier_kyc.js | 34 +- .../anon_enc_nullifier_non_repudiation.js | 76 ++- 29 files changed, 1728 insertions(+), 1141 deletions(-) create mode 100644 zkp/circuits/lib/encrypt-outputs.circom diff --git a/solidity/contracts/lib/verifier_anon_enc.sol b/solidity/contracts/lib/verifier_anon_enc.sol index 98778e8..38dcde2 100644 --- a/solidity/contracts/lib/verifier_anon_enc.sol +++ b/solidity/contracts/lib/verifier_anon_enc.sol @@ -43,50 +43,53 @@ contract Groth16Verifier_AnonEnc { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 19738436812852754138717560068465488575650466935897866784235851363188283681055; - uint256 constant IC0y = 20276710811895297863478242769429631408343958016139841779904405850032032045827; + uint256 constant IC0x = 6079617742568787541094179325682887909945808244704810735243959827192832415778; + uint256 constant IC0y = 16787571520225799670519045007682168421960853837217519526390259473913021713340; - uint256 constant IC1x = 12004009131111215646999120161880487388502192413854826301881504538550543450502; - uint256 constant IC1y = 5034584841161295539588326933292197987831538710023697101766083868565246659218; + uint256 constant IC1x = 2505991522311752156778455090661523584559854297926222384064524634600878278709; + uint256 constant IC1y = 8255748774878977400056431504849025092327157890018362555157613902790081047915; - uint256 constant IC2x = 11744025093458990804167237970026144007871637967897648400215565295861061328335; - uint256 constant IC2y = 2248857409928028413263909113804746755226258898653477806239821342300643857095; + uint256 constant IC2x = 3236965350244914412491796468123964009504328184224919569631341853652111094664; + uint256 constant IC2y = 5018817446917809174563002251706876062136577540211251783213972233922309257208; - uint256 constant IC3x = 1027866460885921739427963398134501038455918532796341088945078011511621442676; - uint256 constant IC3y = 5958883990350165479676838573621528879534261429892979129692820679034946644717; + uint256 constant IC3x = 20635473822198152490889178203795297168128816692310934597308737609178622412295; + uint256 constant IC3y = 21686381794875901264921303819775850606785172748503700974135282319021418270312; - uint256 constant IC4x = 21477343731350881336427671728879526073055001513676414044100634074555163654487; - uint256 constant IC4y = 975839980071906751516077094474212502568600329809457289967004593943814041533; + uint256 constant IC4x = 1802657464311138049888005009951146706506829170163571227091060253925154095179; + uint256 constant IC4y = 6464223263536811410457882731522205111712402908223512049836366029568020386091; - uint256 constant IC5x = 10745395673337059701699795673419720732231823654131369713589820865994307217089; - uint256 constant IC5y = 991956397633440927392694166348862131981180374714009247953939276179698863313; + uint256 constant IC5x = 19683038061393177247346161878002523504516242525587093858171051169964965175309; + uint256 constant IC5y = 11941559534567530881898628022677745180708901756040014021900468886305142561737; - uint256 constant IC6x = 1672993394090581484120407360563051967903199184399912366269853108749767520052; - uint256 constant IC6y = 2164345873917124991571819758981721198425688586574947724181752888003788143824; + uint256 constant IC6x = 15831016304560225046433682948470755223605261989966252819923716158997718599877; + uint256 constant IC6y = 10152669751914951883087310745426443490134580294923111749465612194458531720480; - uint256 constant IC7x = 12851905556792884689855342999140438817587827047283740173600609203898826077791; - uint256 constant IC7y = 2928106356023086030701978715110626259062951617739902988557680022327927922648; + uint256 constant IC7x = 9223895744540988597347383517954906051269131434601393127779914476155588638987; + uint256 constant IC7y = 4057097817924275113774337560125840582168668507218738756759091312261450180548; - uint256 constant IC8x = 1706366517711033642836339515106072692739807158278497001454479300738236232683; - uint256 constant IC8y = 16700903182897452990475040323204325018874215917926885692984146211640664248939; + uint256 constant IC8x = 21887069730271477339395447000828431935392336781494270340838992528947889565081; + uint256 constant IC8y = 2844201003524278672997973600529290000831521001613305325326949178045719277021; - uint256 constant IC9x = 19101508791113451928961082481025527911094003843281774332989233416940984939257; - uint256 constant IC9y = 21697565471392202731806697866311578445068434145060675485941899096932688363780; + uint256 constant IC9x = 4808414835523320523628320681520047895479955081528791196030370521667222450937; + uint256 constant IC9y = 7797923313705195871120077961543496501027976338844390403835230583395399970416; - uint256 constant IC10x = 19730275336196180738068616492761799716598666564420842355043346059462631887595; - uint256 constant IC10y = 16685285536790785249111663346085181130998577327076396224848784078816064185361; + uint256 constant IC10x = 16211172993626747621391823991207229208028328331008628770505605774793950633700; + uint256 constant IC10y = 1746841007064125740967254557870472532226722619400114330227028935555178320068; - uint256 constant IC11x = 7617913501130858003386168099320868449737268059133253154619134544472248055105; - uint256 constant IC11y = 7972962376779726951865679647174563612838286095297842951560535589126110704430; + uint256 constant IC11x = 16227183149439187186179102228002824287668616602328858751082873976570526170116; + uint256 constant IC11y = 9130539427162880676961016387612035890807345274623521216630692667632198253838; - uint256 constant IC12x = 12544403142863928402358237586570057011271857580491825726062907284786959213913; - uint256 constant IC12y = 6822386508465769764381472926650183520080357052212751223638195245287957269971; + uint256 constant IC12x = 21716508817418550410875346202260448235027234519728647013970503004924891373972; + uint256 constant IC12y = 17548855966889182106362129512160022419387113158178611749412734874189761681682; - uint256 constant IC13x = 18940507486165234508918415676788929441013178061873512240392411069614035082362; - uint256 constant IC13y = 16781396210596043591429632308560467689975084335009897683626466396650016291114; + uint256 constant IC13x = 4196241592017627542929377456411216126324404517576014546207377205111904423400; + uint256 constant IC13y = 15225817043451991271351666619621568203461001025671068346305503483918132477767; - uint256 constant IC14x = 558712144346877070501655608109394614280454755351878785357769476496746188097; - uint256 constant IC14y = 11446848258088708077539993154875274206911247468515662688034438075323420564863; + uint256 constant IC14x = 19892615000249065498152255196451223590291375775646942741981105696311293768977; + uint256 constant IC14y = 8090737511599560169511450830471484005709823693720459500304471799924206103331; + + uint256 constant IC15x = 8663346001839375986622551340093804693770355108507981331683176599016183492970; + uint256 constant IC15y = 16427003456838313815469615381585105215654274650877521404992073085959518425353; // Memory data @@ -95,7 +98,7 @@ contract Groth16Verifier_AnonEnc { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[14] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[15] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -167,6 +170,8 @@ contract Groth16Verifier_AnonEnc { g1_mulAccC(_pVk, IC14x, IC14y, calldataload(add(pubSignals, 416))) + g1_mulAccC(_pVk, IC15x, IC15y, calldataload(add(pubSignals, 448))) + // -A mstore(_pPairing, calldataload(pA)) @@ -250,6 +255,8 @@ contract Groth16Verifier_AnonEnc { checkField(calldataload(add(_pubSignals, 448))) + checkField(calldataload(add(_pubSignals, 480))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_batch.sol b/solidity/contracts/lib/verifier_anon_enc_batch.sol index 8ab1444..6fc797a 100644 --- a/solidity/contracts/lib/verifier_anon_enc_batch.sol +++ b/solidity/contracts/lib/verifier_anon_enc_batch.sol @@ -43,143 +43,197 @@ contract Groth16Verifier_AnonEncBatch { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 20457956958473860293835648951879045856677043407243648302743877859875552209247; - uint256 constant IC0y = 7776079367720380762099625163992180745418333944870070120747012066006122461055; + uint256 constant IC0x = 3908746068902036584695182673403181376603479880324582148825114321243612891671; + uint256 constant IC0y = 21162112828786064616543713929918229698704770647235889713363318394799662440150; - uint256 constant IC1x = 17549927933267135940045377484490257666333216840197555674091687873774886451412; - uint256 constant IC1y = 7777359099725353892523896849960626230014517620518326885856442970545242754330; + uint256 constant IC1x = 3642379909743718720667223972616632947803472137181052841764599881302381778193; + uint256 constant IC1y = 5700062060799493168353325536337066888282356197708377158048176553718887961221; - uint256 constant IC2x = 7266608593144975111773315460187555514472943754137342878861656981647216925655; - uint256 constant IC2y = 7636964277306973569988198676997644948196306801511281373794086341883402123046; + uint256 constant IC2x = 13883714266251598676630037212091956816674874202970543751742190275360370015; + uint256 constant IC2y = 9013128711267905194310867088026059129312846054368138240183884595232062235239; - uint256 constant IC3x = 9096435126897708624638220924873430238007027646650523572103562570436206417938; - uint256 constant IC3y = 14049119430819940315256289700787051688993481620336037917299625578452740380713; + uint256 constant IC3x = 3005999804264520883776168981440280516015224374225093267192929039128816329831; + uint256 constant IC3y = 20748599987202621944902199730230404932808959329574406094906500495616797482469; - uint256 constant IC4x = 19211209105469507152755702318350737580106120225074705315095711078638533754748; - uint256 constant IC4y = 1437142373109547513907085005044999690512181331035758157869645400244652499489; + uint256 constant IC4x = 19481090858272465556740330791144452263528458359409223764958298903470626687214; + uint256 constant IC4y = 18792415692033093623283621756130887804607686318819520564109279885343725019638; - uint256 constant IC5x = 12222905540180851820029190045981739566801977585854566585169005829892609954692; - uint256 constant IC5y = 14549045090416232419147266612622733246416508607001040845687387258340095192145; + uint256 constant IC5x = 12448969713894488523025375084312693267106761955829181487340902708351392804318; + uint256 constant IC5y = 4451943501205517819821482547357035849886373691344816307731343919638734214628; - uint256 constant IC6x = 4735648591293575660142988753722749059395263946926604330150825908832092033660; - uint256 constant IC6y = 5187710164061334113526020240024773205825970196964734893386927402857187063177; + uint256 constant IC6x = 17381664162004153834575790930999161722881655179006604605262793792758642679983; + uint256 constant IC6y = 5955073198925403000259868133683281308276206242749187044627128494389698388722; - uint256 constant IC7x = 20334714858185797595805821522541184085655033208922578178233244305037077766407; - uint256 constant IC7y = 21884104557410710051678839643792559542224546576654807003963346710937702613433; + uint256 constant IC7x = 7540844870141797048815373798751154886101709148125189742954623501252821997380; + uint256 constant IC7y = 6253525261723826648073142578082080126084448733139026722678777735052950257090; - uint256 constant IC8x = 12671237970713394931979048957648855653558007432570267806897915769288839520123; - uint256 constant IC8y = 4028373755039302223794864114025699218021876780916423938758276516753277379453; + uint256 constant IC8x = 19805839997705144135889984708566038603472574945344324622837596914064713396199; + uint256 constant IC8y = 1336803162223913469717834381642344031253707528449013464685678590395405372864; - uint256 constant IC9x = 19637480449400017323866327155419553724800176004889528445729832747387029990732; - uint256 constant IC9y = 525358805582402449177466576244443358066620040494539217258836672038268689113; + uint256 constant IC9x = 18743451807103506072320740175279990367359976354617847354453015666990198214627; + uint256 constant IC9y = 18527226988684050908269162438789430990161014050520725276204980965985853219204; - uint256 constant IC10x = 6683362214807778519679644869917831149252215801168763967482464355615388504337; - uint256 constant IC10y = 15911582188051515386082475757956470459072857999270068218265114981181419149798; + uint256 constant IC10x = 20716469926257138332742504820777058284131343022612153237415866833385089623853; + uint256 constant IC10y = 20438179848204046204482294061221996035662916929180980887567963634980416073069; - uint256 constant IC11x = 7859451747924816063864464353448322211274971735004975283586730285633565348026; - uint256 constant IC11y = 17702245455909972873350844621328458039040233256650474440765159766665422983185; + uint256 constant IC11x = 6378167574020817442894921644749771291392288745723612491815802933722465022623; + uint256 constant IC11y = 13612187135216559754197989941297002639880538077933633423488138677161003311657; - uint256 constant IC12x = 17887434247668828848829621275742692134834354053329422702672025565942351615005; - uint256 constant IC12y = 19945940161431857227380726528931717092781378075558615731197842417099001986329; + uint256 constant IC12x = 15333385857097851253178637621370818801581137753864660693323273112058689282911; + uint256 constant IC12y = 3929171055883544259875892994148070720031202423901700713626233026945678946404; - uint256 constant IC13x = 910850375080581916368615482730337187006033352469590595640777417750447607608; - uint256 constant IC13y = 3677732807370305265286062294483845790891493712292966367578729792298898100014; + uint256 constant IC13x = 5588270864149004230690874713552426810100689407611735740482460767687752844001; + uint256 constant IC13y = 5975921942596934133040578610353947807735217388309529074679824658469199227349; - uint256 constant IC14x = 11394244343739019725843491923239602248858664538230688052482501626207869677474; - uint256 constant IC14y = 1017367602106140109792711511707675118068578981870871058707753729139351086426; + uint256 constant IC14x = 17482138958808661765571534232744989982797890714926530202803582580847984111828; + uint256 constant IC14y = 12783807925168095357228813653429913560592232717199060728813868234026459712035; - uint256 constant IC15x = 17580806813370218190519612135500080594692941405328154589071627093917036218026; - uint256 constant IC15y = 18866852522884155432837625970655651869537802178823630974722600494142936431895; + uint256 constant IC15x = 2785449574867979821310147122748672312371896423551839609838567027349197532486; + uint256 constant IC15y = 12187886123456423597181467422649464574165143241869537436961826041334507459920; - uint256 constant IC16x = 20953225053977698883461234417640671125664833305435259995743410489766786811017; - uint256 constant IC16y = 8745430177680780508827153481916758574808937829385814074304854361662865188531; + uint256 constant IC16x = 5307653834074549453349104857138757249380008569841090576026761463649739707176; + uint256 constant IC16y = 5556978340130369354792430826031648726565387972967466131395649033860118288313; - uint256 constant IC17x = 9298865247055097659456332331836095871429324408895784837764325710955588923525; - uint256 constant IC17y = 18720021835177849144326529233199949902692218020852609953397883057041365406716; + uint256 constant IC17x = 6380884202734787460830258794401534351853688368379241837874778247355337094508; + uint256 constant IC17y = 2160697878844498790334940441069541742178686519044433750614891120647951902322; - uint256 constant IC18x = 9803064636763855724556507831841530068201342991085473117961961761604449353617; - uint256 constant IC18y = 13010891856001121057287490847830065709739845170631999382717458902000410392837; + uint256 constant IC18x = 11994658167418635971949537753955340743184967862844314723032425494876612243720; + uint256 constant IC18y = 3010975013890706788598968771755991435380467529700332035057295090132482159402; - uint256 constant IC19x = 21429702633296602456819134246535066068702583232025542423089522744073299522839; - uint256 constant IC19y = 16335398909778845583628705821336521443514985762107953814101622209643140854940; + uint256 constant IC19x = 18784528983632535501290508098053725269371240085820529055982172140023060191393; + uint256 constant IC19y = 13647276251296256634937664644156826048778671296470861936367346727458948097363; - uint256 constant IC20x = 9751542436554156396205960938972482822138196952556898887285337815279532559334; - uint256 constant IC20y = 9329149151981556656299798990823114535761565475856550151911761396342936373057; + uint256 constant IC20x = 19901565685179060322212685217062886072478782615405857789940282464218702015624; + uint256 constant IC20y = 8752686505194012942840032413932954407921719670319213528230352404437455645753; - uint256 constant IC21x = 14466501034453509375016805523060731169089523248364937671766094317200453715291; - uint256 constant IC21y = 3150099584380216663313553181132841756309020309096428653543390538998378851140; + uint256 constant IC21x = 4049510686026776133189723815304253783453454878162320427646942186291582655461; + uint256 constant IC21y = 18008014605111680985940242802309637149257979280274959365104112879196086525621; - uint256 constant IC22x = 16625780749334367102987241113400718766807362610198271097525872106126093250001; - uint256 constant IC22y = 5641529405852880889432838060723510427373153385823065644704426576587683782342; + uint256 constant IC22x = 3643744528885984116890759777109742229700033784333065122839897449308536196557; + uint256 constant IC22y = 4187499643711670495859597326881223383699311901708594243258745295267681297968; - uint256 constant IC23x = 10482129844561687653238400541792795523853495600910564159314860391063236893865; - uint256 constant IC23y = 7030587236238761457314153006466652546041803446772298811234377000319902316049; + uint256 constant IC23x = 20142636948800246848499978068189374630932385609008355413915058826347340990557; + uint256 constant IC23y = 2224975576037599199629130082723271968226763768088257626452852292819197114424; - uint256 constant IC24x = 17777485010211018490416436586755225220290461571556946002064191567301479196124; - uint256 constant IC24y = 11093041903680853786134545279581284881559712502787103346113529896350026702353; + uint256 constant IC24x = 4189346926624797283351494372365410510941844835138208871087521071924041718500; + uint256 constant IC24y = 11678467025169017527080715443224734827743662587027824067762559460965643371449; - uint256 constant IC25x = 8367464038675137240637235032183962189203318091597084436727361402785690352415; - uint256 constant IC25y = 2101341872045901587244350434302489380465478959052054782990815843504622375785; + uint256 constant IC25x = 2835866165380135068127599110412553728305300563836464493980711777954637073906; + uint256 constant IC25y = 11418211775598851998087357475845197564261451852151861450865404775845026864433; - uint256 constant IC26x = 9445937682034499200116555117283984556173406956968330905166247396248067476298; - uint256 constant IC26y = 2448614491980710495634177417350604360553528335606412536811403268782338557447; + uint256 constant IC26x = 6184995568126332874855666630338561271853258126973506922385207751979385498602; + uint256 constant IC26y = 9678587807318338281788726652574496054471104584648159494751436934262734541814; - uint256 constant IC27x = 9086407649402987466727626417229484253386649160044225932044624305425853693602; - uint256 constant IC27y = 16892875124856684788049611363643986883200311062034370427528822921971214937498; + uint256 constant IC27x = 15565834122743701828678116147681974875652599334101211815506693273501585368760; + uint256 constant IC27y = 442538129585699161258548075040705114030290071054990071615328502434649120437; - uint256 constant IC28x = 19759427378006359186636323808841855999743290454170215751803319675288637666224; - uint256 constant IC28y = 20893980529463838942352241569178910211287945093872561634827722552883873929734; + uint256 constant IC28x = 3192581844028425535035916103212522902617678210751909712329481309981427694695; + uint256 constant IC28y = 875090420003136105575970258064025129997516670755032293104717805554449855436; - uint256 constant IC29x = 20762860574071906476558223570053048914958814270667058249400227402836777574107; - uint256 constant IC29y = 19285928520739540943739493948094407121565948163149835902863321883358878361412; + uint256 constant IC29x = 19129803414895534287249239378206036763496633362660702877511049376065173879685; + uint256 constant IC29y = 13476877444667980639577177516354785556257475458010264623920927454232463257207; - uint256 constant IC30x = 12982919139442164278755036181367896103036089671229752387322345416049000267478; - uint256 constant IC30y = 17389857939362238519664807858488982461046972261625678287174111944494040978382; + uint256 constant IC30x = 19637362155422132622327186678387575499173188069611530140664361817836309117089; + uint256 constant IC30y = 12746409854715557430503825810930174826627242326994531239895244410729264842917; - uint256 constant IC31x = 9296346158583058002982031757345378508628673444232747679337799561444313658756; - uint256 constant IC31y = 11401838933643317672245148437030692400996215400094297130676326454765266124841; + uint256 constant IC31x = 16328912677341901807792509296560206281257420836520156102014658082160481348555; + uint256 constant IC31y = 8459082892838654273483879375304068831177002387638017901977261066723911428821; - uint256 constant IC32x = 17286803510413442586833249596325847372150963129796326293518898027419455799100; - uint256 constant IC32y = 4729548357749587914597883649741039045459375769895691014012698567505454373958; + uint256 constant IC32x = 14034854298585741434170328517907747523331147800071615806238407880893507944298; + uint256 constant IC32y = 7677200450078323156871969319025444105783009677563714672945142925630687465585; - uint256 constant IC33x = 6225792172100833912708432866127247904116640232886664169969642733255064660000; - uint256 constant IC33y = 6060274113179975560638082875287670984249765738465535446839477668985817135251; + uint256 constant IC33x = 14501072824190539624914743253079070280250538860117203479232126487148710641455; + uint256 constant IC33y = 16167992375464116570684842429142537304944706449068534932195849898107426884478; - uint256 constant IC34x = 16100121312513859528075023932696721282346572050314892547292307235056414188134; - uint256 constant IC34y = 6824112582626629583841600764613110508332283077963956905469078903373189725192; + uint256 constant IC34x = 5503113010689888257682320859656620694303594044205780087948618736092887957433; + uint256 constant IC34y = 1696576415970418474450210124757065887772837815866971931349726049769328195003; - uint256 constant IC35x = 11468809176406819854117038840765685383176557932415559413642626064953024788160; - uint256 constant IC35y = 16327061741308268552699959019077558460768707604967044367693906400037465494103; + uint256 constant IC35x = 19214195187847873310589726397831481907391292243012217437911869663034067503887; + uint256 constant IC35y = 9805467215740856344169239336698580758111080655230710098273992409379459002166; - uint256 constant IC36x = 5716872441568503762359414274128330720939141110087485826855142892018711170418; - uint256 constant IC36y = 7316500402322451089160627546884883276088294973708881737262802199173885883354; + uint256 constant IC36x = 2824456631103843669798437055745012788573969191567997729053271364215315472198; + uint256 constant IC36y = 13210219118852365274638175699060587136493568715489361220574973518671149360830; - uint256 constant IC37x = 9431394354834930743420189375253905724350514021300926223621405654335394524267; - uint256 constant IC37y = 11668870674753647472543361195789115138286174053139833262874235003443925126227; + uint256 constant IC37x = 11806481874674376764400918831538020092220367856078576427943414721863895872584; + uint256 constant IC37y = 1126182565826373196793339854507275444810683313777655057798659711783831535129; - uint256 constant IC38x = 14101909265881417922398903228902866393379197230150540763468879683182339922162; - uint256 constant IC38y = 843475656712384462124393918543099201607219961246272351220447766498200318270; + uint256 constant IC38x = 12907395246775078964695235303299684888761112015317926640682209536722683179970; + uint256 constant IC38y = 17810240919535582525306841683818586703251299768563907071136830231386496006481; - uint256 constant IC39x = 17242818561206755627772388888524159835848637302855005274392040904535533841946; - uint256 constant IC39y = 12913556443462307175824182946682086865851661751785096241603862402616588100667; + uint256 constant IC39x = 17953909650597556894054352688798883115945121384051215064284235724397668654955; + uint256 constant IC39y = 13868992413127277275852535983401633335127263080721107747010259640411782217018; - uint256 constant IC40x = 6664878326271511977250217125393597499868106283996944372518621978598175145743; - uint256 constant IC40y = 15144441784853392110035931444169830357580673626108453163006810316899221105706; + uint256 constant IC40x = 18452672392295991040358492725963563156958402350081327237035645703595669202145; + uint256 constant IC40y = 11005267617141936063457180323889422859839808292113083196215725053413990289581; - uint256 constant IC41x = 20086904197250387625003182009808914102381910432954527190317655483755132971479; - uint256 constant IC41y = 9880446798565027167349769495326314796659653140515047806702697356581078693719; + uint256 constant IC41x = 17946873002177093051195262691330301617336977974010801103245788627534677577351; + uint256 constant IC41y = 16139796083075326250719854294605911968674896065038419671645428862228038091678; - uint256 constant IC42x = 18568474479778525057620296750285011467433857421622424398667327542936804538421; - uint256 constant IC42y = 14380361583263936802601888969067954059567919690190840045459166931846792356148; + uint256 constant IC42x = 5111397968235238332889036830227772356073950460888121488319801054320635436116; + uint256 constant IC42y = 20126877650675869342714256575239930124479211219283818759347984503206238828307; - uint256 constant IC43x = 11544583223021191345047659621978897446635170548746961836374819427837461939803; - uint256 constant IC43y = 20547960814800065359605548667632876088577519108660285624683924957618216127059; + uint256 constant IC43x = 15577716111736423524314066239481646978059221029696172444899093153756766882663; + uint256 constant IC43y = 1882481077141013113637554586855942932004581120336227655362544837109420362087; - uint256 constant IC44x = 1912392906994463411087577566286247817866473791206599813185663829653003728024; - uint256 constant IC44y = 13446395032386279021226716525374023030656189163839742618918207180265011638965; + uint256 constant IC44x = 8002207922749820785367626599773500821408568962350573677120091804299338076164; + uint256 constant IC44y = 4349078923495179616645080177079492735428786142729957153306733080220170105442; - uint256 constant IC45x = 20845023561343448705561071146769639912487817477708421585464830888518785779848; - uint256 constant IC45y = 20173847817888474799536463971101765819441189334369434652846457077165068620476; + uint256 constant IC45x = 18441600711752353062180825497817050541555822005558821568453023287455608310394; + uint256 constant IC45y = 6416009464597275160567435185449771745423054271079755029789158059043365752903; + + uint256 constant IC46x = 14092536542972186697794938073105318364618372411217087001912379181513116038578; + uint256 constant IC46y = 6915383375856867729473839705813161763964779725107660715856712463379573140538; + + uint256 constant IC47x = 17158487437315882139821485017999180800503814926388843639611073513525549132901; + uint256 constant IC47y = 4429408683260349034652925083312216193990954298346463687111904624060815262917; + + uint256 constant IC48x = 3894268030249209499477219755529510826505048492171170075244819528783816018950; + uint256 constant IC48y = 7624449612306353256481523141589168146964283570927922448005793884356945743541; + + uint256 constant IC49x = 2879903388769375388864978492549156271072122372264964992937081397289611351099; + uint256 constant IC49y = 2293590991962647844941952134955325970988544992429589088487943316187569970984; + + uint256 constant IC50x = 12919709609239979981636352053788922219478857416525759799138206817584928562369; + uint256 constant IC50y = 14836049567116014267843850012075892801447453733869024281915617688581220558191; + + uint256 constant IC51x = 763839195084499434891469437185541300454664672090741450855014240752484631041; + uint256 constant IC51y = 9067748818656011510924592898496372151514937193974550909843638885339488286464; + + uint256 constant IC52x = 3671159513272968818143393692773242997264310034906138662167947465059141188953; + uint256 constant IC52y = 5992372490740298946418458652958235484496577113448890395742452518043316209831; + + uint256 constant IC53x = 14752468970553446165055418939963620165645481039190653184028781955590932019663; + uint256 constant IC53y = 13602415345116961361486713666845157930319884913254722970150122034256792375891; + + uint256 constant IC54x = 5547973682947408039996168490267734295620817217937711575875612846207168705930; + uint256 constant IC54y = 1918514152899230992458940695194225161889379459601704182659875096307986684605; + + uint256 constant IC55x = 679887516886724778127471600180439877584093980737395592616133171342583758513; + uint256 constant IC55y = 8352201394168531248618467666702687234040530811067203410289324437655297694803; + + uint256 constant IC56x = 17544853847589823116800694008933471467297135010824087035709723539032570705536; + uint256 constant IC56y = 8864575927894913800601743571398347523212536745003501446294055561733569909365; + + uint256 constant IC57x = 2496168280855643738727620876530580168098962365131910848630447384544330182659; + uint256 constant IC57y = 10990402612417964640564193796460901114653180089925666474012910550334812115843; + + uint256 constant IC58x = 10229070342672799012496852192766333061425138877942229915999360470050629255994; + uint256 constant IC58y = 6765694676136184470134212249544791768884120464124594017266794746785806260667; + + uint256 constant IC59x = 15807821231740066210147893568369331798735344432795832027394420750219942185900; + uint256 constant IC59y = 6760223102321380418036718494886836729173433114703543456433986174390102910930; + + uint256 constant IC60x = 14819374468504311081864250741777844866365249186097301524285476049706195166128; + uint256 constant IC60y = 6146117414386626951125929842647069972302993155770755896539505045758996575874; + + uint256 constant IC61x = 17251815556152386496259216370538509798062455962341612838689196751688413591935; + uint256 constant IC61y = 11875765802989746483881648485855343245577413942918675488651690374569095118334; + + uint256 constant IC62x = 20800661164952129033157405872159184314174315843329633112524517864715608206596; + uint256 constant IC62y = 21829732780229162843374774921212052602583329914292743573368799594491352555167; + + uint256 constant IC63x = 21342378743798699061991894488476560795684400968203499616358951245153720325541; + uint256 constant IC63y = 19870126064041049008134398111667610858164378394136143440856102921211634375855; // Memory data @@ -188,7 +242,7 @@ contract Groth16Verifier_AnonEncBatch { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[45] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[63] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -322,6 +376,42 @@ contract Groth16Verifier_AnonEncBatch { g1_mulAccC(_pVk, IC45x, IC45y, calldataload(add(pubSignals, 1408))) + g1_mulAccC(_pVk, IC46x, IC46y, calldataload(add(pubSignals, 1440))) + + g1_mulAccC(_pVk, IC47x, IC47y, calldataload(add(pubSignals, 1472))) + + g1_mulAccC(_pVk, IC48x, IC48y, calldataload(add(pubSignals, 1504))) + + g1_mulAccC(_pVk, IC49x, IC49y, calldataload(add(pubSignals, 1536))) + + g1_mulAccC(_pVk, IC50x, IC50y, calldataload(add(pubSignals, 1568))) + + g1_mulAccC(_pVk, IC51x, IC51y, calldataload(add(pubSignals, 1600))) + + g1_mulAccC(_pVk, IC52x, IC52y, calldataload(add(pubSignals, 1632))) + + g1_mulAccC(_pVk, IC53x, IC53y, calldataload(add(pubSignals, 1664))) + + g1_mulAccC(_pVk, IC54x, IC54y, calldataload(add(pubSignals, 1696))) + + g1_mulAccC(_pVk, IC55x, IC55y, calldataload(add(pubSignals, 1728))) + + g1_mulAccC(_pVk, IC56x, IC56y, calldataload(add(pubSignals, 1760))) + + g1_mulAccC(_pVk, IC57x, IC57y, calldataload(add(pubSignals, 1792))) + + g1_mulAccC(_pVk, IC58x, IC58y, calldataload(add(pubSignals, 1824))) + + g1_mulAccC(_pVk, IC59x, IC59y, calldataload(add(pubSignals, 1856))) + + g1_mulAccC(_pVk, IC60x, IC60y, calldataload(add(pubSignals, 1888))) + + g1_mulAccC(_pVk, IC61x, IC61y, calldataload(add(pubSignals, 1920))) + + g1_mulAccC(_pVk, IC62x, IC62y, calldataload(add(pubSignals, 1952))) + + g1_mulAccC(_pVk, IC63x, IC63y, calldataload(add(pubSignals, 1984))) + // -A mstore(_pPairing, calldataload(pA)) @@ -467,6 +557,42 @@ contract Groth16Verifier_AnonEncBatch { checkField(calldataload(add(_pubSignals, 1440))) + checkField(calldataload(add(_pubSignals, 1472))) + + checkField(calldataload(add(_pubSignals, 1504))) + + checkField(calldataload(add(_pubSignals, 1536))) + + checkField(calldataload(add(_pubSignals, 1568))) + + checkField(calldataload(add(_pubSignals, 1600))) + + checkField(calldataload(add(_pubSignals, 1632))) + + checkField(calldataload(add(_pubSignals, 1664))) + + checkField(calldataload(add(_pubSignals, 1696))) + + checkField(calldataload(add(_pubSignals, 1728))) + + checkField(calldataload(add(_pubSignals, 1760))) + + checkField(calldataload(add(_pubSignals, 1792))) + + checkField(calldataload(add(_pubSignals, 1824))) + + checkField(calldataload(add(_pubSignals, 1856))) + + checkField(calldataload(add(_pubSignals, 1888))) + + checkField(calldataload(add(_pubSignals, 1920))) + + checkField(calldataload(add(_pubSignals, 1952))) + + checkField(calldataload(add(_pubSignals, 1984))) + + checkField(calldataload(add(_pubSignals, 2016))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier.sol index 1066709..faf9dc9 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier.sol @@ -43,59 +43,62 @@ contract Groth16Verifier_AnonEncNullifier { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 13678166000771296028716088649707013760829674700385759642860494154368687998709; - uint256 constant IC0y = 4961949307578461931371517116082474097036228012924437637706038382049417537984; + uint256 constant IC0x = 13186961142855695713215508993146324875923985095596320679393949609083204313149; + uint256 constant IC0y = 20971345401241718044712794959871979099146385615338124541387235060520049379158; - uint256 constant IC1x = 2204542029006441412514570505771624273632312485515492234810839886974792880667; - uint256 constant IC1y = 8838327314784458145079277879579686434474366816781852809532023511523475680067; + uint256 constant IC1x = 5596617714573916358922180002027668014235338143603477528528486901732341689174; + uint256 constant IC1y = 18169906134045908750217506289430594471297692054976720067363254769322149496903; - uint256 constant IC2x = 984190429201041857120978307904591089984674147895365854199554277248567756762; - uint256 constant IC2y = 3050029555075507159624174573918069927104375767401967689538452364062362998517; + uint256 constant IC2x = 375179729015950750015201049819310173893173497990919017908984027536413071576; + uint256 constant IC2y = 9424775450378236225311877676427856463800505168584546278019795903879869653255; - uint256 constant IC3x = 21506409996536555473783344664168479995150262432075358365354580674108412355016; - uint256 constant IC3y = 8599911080815734217762783325275263009654132851986193429393340059137893076967; + uint256 constant IC3x = 11274430801917269579049341224818927549055426765888901159013230738656035062422; + uint256 constant IC3y = 3189755612751098000468491357364886513239164449226908543912757934476464389054; - uint256 constant IC4x = 21788371071589958280155010312074207167387644784801032467524251563813069925789; - uint256 constant IC4y = 16017891759091634551485035996787768674890884884580084418250378977472667646747; + uint256 constant IC4x = 20929082467182106010914967176636813721095808918472812976664580721651732592348; + uint256 constant IC4y = 13590940037054105258652229041095817375779493944187485965073911187461107846297; - uint256 constant IC5x = 3474370977150635979281388957540044901593079765869405148003508855938907161523; - uint256 constant IC5y = 1692620058877250578859346926736402992006465899480571464739489531519910165301; + uint256 constant IC5x = 13232903067874280762878913491749076796638411641135301821217124752900497650520; + uint256 constant IC5y = 3098408428950175562313109379843251475966975308784566531924231123690657805627; - uint256 constant IC6x = 14149094746002062391808802496591387377487466349382127931670045723541741558711; - uint256 constant IC6y = 9222799121270749610505345007770793977124321191496588693556191863593480045856; + uint256 constant IC6x = 6246173062073750433581743829955768134424088785068454722924323050885412449600; + uint256 constant IC6y = 19219797486656797848241452853177083334642108284872282760570063002556809975661; - uint256 constant IC7x = 9273799284822923793575807137996194733339480428254374206006757400032173797727; - uint256 constant IC7y = 16315220931561659393515402681962417396004656325450070112470349917711135971087; + uint256 constant IC7x = 7453233983387318661178651932408006745309306355452771434255874320002345253711; + uint256 constant IC7y = 9225001627794595551093094182805061487091405736825352117536572235256477135677; - uint256 constant IC8x = 13451103343875903897343428704678468946853158159536827119528221805472272905108; - uint256 constant IC8y = 628496243328949807277588354970478320528811318471137680004273397631887655072; + uint256 constant IC8x = 18342465191764991960466571178007119480650524152275745666268158024405812199371; + uint256 constant IC8y = 12952848418572949914293934585650902172593934866286184499401182404379354207308; - uint256 constant IC9x = 6067287962006180781386150709214909947659323356695103529191319139769289637925; - uint256 constant IC9y = 16647921353576036963239701670325188480964660838840086346922477502515004451615; + uint256 constant IC9x = 9865405396995605199540055955768414603837675331688896447120522579824006040717; + uint256 constant IC9y = 19780045876054499971685641070283582330825263831247355373985460286779094262264; - uint256 constant IC10x = 15848788386796371774620049439750702816210500764159641257483786168422723885757; - uint256 constant IC10y = 2191844892636187267255601718549938310559896531080551525090520220356407282435; + uint256 constant IC10x = 19595303252376026127217163146415569608768471715197052008834274372310839720444; + uint256 constant IC10y = 118607393237836195014459739357325723385136249376902204893027498109959871584; - uint256 constant IC11x = 14155351394916282563155442681342138258045803790992757138692337650812573648549; - uint256 constant IC11y = 13266490918112647274657614801341765344560672830045160509793915078708246250887; + uint256 constant IC11x = 14505445839213666867181925900312891080180471300047244470868724103662016936466; + uint256 constant IC11y = 8841540133735299700679385674925623888182536990207983700647391803724470593625; - uint256 constant IC12x = 18767528343784802461760910070202494978333037674357891557627291028834187942428; - uint256 constant IC12y = 2927451585647610372373530792444084065279855596561951798131860222437462568234; + uint256 constant IC12x = 17491806486925694090025037935952274750032487113907267345258320361047408402586; + uint256 constant IC12y = 1299775985616705819045782683673965249739119990810775663165842759710720368768; - uint256 constant IC13x = 46434084833796288510223843828494589085103466116172276944447838961663746010; - uint256 constant IC13y = 17636599523219034821248614860068790067885311644103576308478366993062879504561; + uint256 constant IC13x = 2270224360723690085561517855283974802332585316034921071624378238994917207079; + uint256 constant IC13y = 12346141516383459727665484086270025563450972574925331732910641920207254881460; - uint256 constant IC14x = 13671330670802655872327601166524587591429531249226018939856821915010408000292; - uint256 constant IC14y = 14848201027494371390631351773542387913617409380236048186961677579174143126419; + uint256 constant IC14x = 2460509720145727619652883837556354165845594415190962737066020164551557782850; + uint256 constant IC14y = 12480583572017155822139074478020051792583435518998022982330227104337616279638; - uint256 constant IC15x = 13578759613269241915934553713856919923847539014199632158899353697877937136841; - uint256 constant IC15y = 17992517964952134073344784861755363143409916374751756941628545297594318465106; + uint256 constant IC15x = 3608520538986533549379033082470322428007088119504637299209003462374579975341; + uint256 constant IC15y = 7125340262944938150922347154445399409927865833082601906083584655496504213715; - uint256 constant IC16x = 4798600103275234744393502044369757486319055145576852517168958875299506874579; - uint256 constant IC16y = 12020210555699713650678704885293163425712608070382809856857547063740548212273; + uint256 constant IC16x = 10863329340364357981065813447263390610581921934757348839254709621258220859473; + uint256 constant IC16y = 9303767501074237621020019883109009688980715688480379081729567337958391321447; - uint256 constant IC17x = 8618416541017467104007817741983279564391984799200957332901530860654534366392; - uint256 constant IC17y = 1215959756736848284315621954972208648259065888449655282927680963058074494048; + uint256 constant IC17x = 14968062744234559305514412119756084736307973845644354760349844299511302369319; + uint256 constant IC17y = 9547759371520547375314740617427158285485474648064774946183459006586566861867; + + uint256 constant IC18x = 18307132294771339489413059804025476799828377546071575207221277869890977064793; + uint256 constant IC18y = 2199179456506455466086743042037945964332715037288852243652629899356627255755; // Memory data @@ -104,7 +107,7 @@ contract Groth16Verifier_AnonEncNullifier { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[17] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[18] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -182,6 +185,8 @@ contract Groth16Verifier_AnonEncNullifier { g1_mulAccC(_pVk, IC17x, IC17y, calldataload(add(pubSignals, 512))) + g1_mulAccC(_pVk, IC18x, IC18y, calldataload(add(pubSignals, 544))) + // -A mstore(_pPairing, calldataload(pA)) @@ -271,6 +276,8 @@ contract Groth16Verifier_AnonEncNullifier { checkField(calldataload(add(_pubSignals, 544))) + checkField(calldataload(add(_pubSignals, 576))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol index 3a0b434..a74c8f9 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_batch.sol @@ -43,176 +43,230 @@ contract Groth16Verifier_AnonEncNullifierBatch { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 10645351421275030769212842451599777004533318201294902462005034101795836667735; - uint256 constant IC0y = 19773846574370070068526112402756882493172867027564763871401825452271772896770; + uint256 constant IC0x = 15541712691897739747724830300506738262081962743737466099607307479041362351151; + uint256 constant IC0y = 15309799118687561062851562419208761963425326551696680678239287738208909024469; - uint256 constant IC1x = 21045668564796633627967971401776840306235180091510629996956077562174112854797; - uint256 constant IC1y = 9692641105892987460288991259626904081160606632602573786680505922597146001820; + uint256 constant IC1x = 12004066118121267476589554896909877287920971467382352176843746954792752500122; + uint256 constant IC1y = 7206764879432615417714949819409956497578875830297354760497237983805982197325; - uint256 constant IC2x = 6986710375170555089687323877472514817724381470286988221636916919623639919267; - uint256 constant IC2y = 11825153705848256829640073197891287269133258372909893963327355565129252469538; + uint256 constant IC2x = 799639163124225172098935137771473826429681232551382892742052034006481996153; + uint256 constant IC2y = 19460212393596922532627580662240966771232896727700198582151473552927560553889; - uint256 constant IC3x = 21589139179301699049569868901784946727171433740472463820916197439162935213931; - uint256 constant IC3y = 551980383756225690231265441795287943646681755160849513598947577957901960769; + uint256 constant IC3x = 18044350123603547886233505234824835771276375069050425360565411842776328391967; + uint256 constant IC3y = 1576307986547670127474732693850143662396449202007408662651643215890624339590; - uint256 constant IC4x = 7848148325988989144014232092764440426513779624118010875067911492016597507427; - uint256 constant IC4y = 874964876333419237750792570559364811284638715362980586388785676601037939603; + uint256 constant IC4x = 20400451647704478477749132993829457719981743294312779765310610728208160269079; + uint256 constant IC4y = 13745658125866723760491826360953130191933571020637214849003136419490483471618; - uint256 constant IC5x = 5030538897432365602364477809726773513224377789278422573056864982899918308435; - uint256 constant IC5y = 6538658663213062852245653828011736921546820135242837798372228475915946407294; + uint256 constant IC5x = 21648241602395290828104735702321830963639705642419053639842578212816043889120; + uint256 constant IC5y = 10179313856185307487415998272527907126366740786494446493789947311539305678053; - uint256 constant IC6x = 1134488520285628584172609693922141497292325051235162469824971135714986508423; - uint256 constant IC6y = 13421809311905703563334091581498477650119249056168469733417655945944292140800; + uint256 constant IC6x = 3266888133196656674176137519937215957510568740238920535204121170594142622560; + uint256 constant IC6y = 581807064662727539042969124018393695993024464972930142746805292963483764953; - uint256 constant IC7x = 15809369401596210985478473064948224599188521859155115813447540322319418684429; - uint256 constant IC7y = 748154560614039972265932322980194959340014814655278777140312658340634440738; + uint256 constant IC7x = 5782731932588123426638937014276981925622231980747761293158670051075134173058; + uint256 constant IC7y = 458530253552218801975310357315165518597333443362171356430274561658414761950; - uint256 constant IC8x = 16422634041753847419090532487213130865873369386359797042255555793689963416641; - uint256 constant IC8y = 13345489373898517826619448768139131981126393410240491128775416736099748551986; + uint256 constant IC8x = 548417836864289418463262487062535242640735442612835114756201932820067573481; + uint256 constant IC8y = 2725681563128474659874007033711084055442148149698768488522707436838354023653; - uint256 constant IC9x = 9023891455582583354799282243974737937216662894041709294412517055346091405216; - uint256 constant IC9y = 19721049929631439090338791564588794157023579033738842201236698580157965105980; + uint256 constant IC9x = 8616702659111468433065736804187627618320987671315404885064661690736085080484; + uint256 constant IC9y = 7087234574242487191257150935672471494420269714381737926190856770920046787505; - uint256 constant IC10x = 16791613249768019763130155513839129939686345377917856464443567247489567026164; - uint256 constant IC10y = 15270069150558256924307484622069492276980978114465458770799437465145659888704; + uint256 constant IC10x = 20167815511788284222998097079028719792269656943773089939369231400752958985405; + uint256 constant IC10y = 9404517860139883423870033333986444177106503920145114499080334948982539603563; - uint256 constant IC11x = 9565236675475260845883610238852228330283848177620410368151292023129362514150; - uint256 constant IC11y = 12882180919417442528934412844769993736456066787664071079858702514787733345580; + uint256 constant IC11x = 1225817578886650460062531786383208026059122829420759086444588384070049592508; + uint256 constant IC11y = 11517528485210636107743904361440850052045320470911699770542860487162122450992; - uint256 constant IC12x = 18889158444844545745822687387379205884168164919645495138937434791246868284441; - uint256 constant IC12y = 4463993601421177726480051615090675190432895924456563349702780067665853863063; + uint256 constant IC12x = 17670597734429577409649305751860763996652171996727040662400736475421233889240; + uint256 constant IC12y = 17738127465063980814155958209108854058529581644039192769715341582606425405655; - uint256 constant IC13x = 15654824613646082563998075951610876530965463902310927076566046041401790190883; - uint256 constant IC13y = 17897729347904120645817815694494907164306296387380224653473061731475087083629; + uint256 constant IC13x = 929501530331525055050523975910356956002521580711546356352545747027797467464; + uint256 constant IC13y = 13640717087941957737899250122156624646568466250990204802363767034434488937293; - uint256 constant IC14x = 9914952707022185044859485843755152355827023461798918762873853737142122912923; - uint256 constant IC14y = 12223117364915343804298414875843316912398960926175366191900849476327091675443; + uint256 constant IC14x = 18848953267508570424067614897329234899322972096731866125127364941150981569281; + uint256 constant IC14y = 20823402513185587475650998954455654732818037454973951576534750188849254169455; - uint256 constant IC15x = 4530178371631031025262966851421025083373895413001645547669158623799333125120; - uint256 constant IC15y = 14847450682708930563109693216793086242583142312601249669264886719333269385228; + uint256 constant IC15x = 1500916762917981320137086365080717319893029971740154971104077473585000855704; + uint256 constant IC15y = 16450861685356903953750824971500662259636788991629523821174021104020823271668; - uint256 constant IC16x = 20686192905301290185660609077917244772970221404992626008004711488059672116510; - uint256 constant IC16y = 14265228262044037282704321826983234216621387716914500339084109632125396447817; + uint256 constant IC16x = 7896452761877752610994779284082958157057343429510624631113102306128671104330; + uint256 constant IC16y = 11835738009486031602232155722324145803064919243303340007952171062163921173904; - uint256 constant IC17x = 17184296579665233138664538393593533408797018385395879255045965137088911002633; - uint256 constant IC17y = 5794545279126857667791925152005171752799892805442052280969080353648295951877; + uint256 constant IC17x = 10025475874790213804420276568943869945361292747999892043167699468353487701613; + uint256 constant IC17y = 5107313052045121773802855222374277248047247722671994362633810734440920871478; - uint256 constant IC18x = 12283677454922856060911771154661643414034804829779437509272866105959185262393; - uint256 constant IC18y = 11418437498830438374304711347669336909061511813254033588733923242783698973381; + uint256 constant IC18x = 19945822408866478915965045838495679811500722732215092398900155158736008963418; + uint256 constant IC18y = 13773067490301179219537121121299653350694808450630171555491523667462586880278; - uint256 constant IC19x = 233410113256358208167749654377889109662917637067643192371866364989155032597; - uint256 constant IC19y = 12489787345918568886208972254163440419069461589228081734396525205615115646823; + uint256 constant IC19x = 4763437325608066345807300028857485637369762732123976021601638339153509382024; + uint256 constant IC19y = 5047697368859449964614854146008748593463758126500575129574554875185564520393; - uint256 constant IC20x = 19922851833540760840323478915538105324832288698966396321587996988043948108076; - uint256 constant IC20y = 10009437256472029856043218169660264477908251912118684527903236010503598851905; + uint256 constant IC20x = 19142875394805921284571633134030409276483104720336088876339486260571557017538; + uint256 constant IC20y = 20255895849223763729597350362071522806384158657022013733318416119165993678780; - uint256 constant IC21x = 8576754828850430389792536700359043190882873416990199648102622011137214624344; - uint256 constant IC21y = 4068078849091371850291208205320805744942525044974109855286604207667579180916; + uint256 constant IC21x = 2389668560232905520261975748906012326901650226854014060862917742678195465447; + uint256 constant IC21y = 1899098024654651685978763707976166438522410162625384041320426996598176775065; - uint256 constant IC22x = 19720349134069389994319317515114599480576251259055426609291868076253917408190; - uint256 constant IC22y = 17491915401609613751947047987004497358908114555334188876708093723103785538658; + uint256 constant IC22x = 6468619651569256820909467366831560164190083450291238480576398203441710278018; + uint256 constant IC22y = 16494512224582383876680610529582940807905463103020385179212536970251178153298; - uint256 constant IC23x = 7234542443296093769067891602273037388908886094779444443372875052814418213738; - uint256 constant IC23y = 2298362372262249126601288098107811726732535043084050139693826893330484043384; + uint256 constant IC23x = 6792394873949265205498601290765446513706573500098286743228958428707859264887; + uint256 constant IC23y = 3135195861055228915763886314109310178681888946796444049220917208236247667817; - uint256 constant IC24x = 15208114325793531028606742636462558162754988632195033802710190832208321334839; - uint256 constant IC24y = 11228155327966805755480600454789239990152846144317355172501847758906396211607; + uint256 constant IC24x = 9266604700268833025757822337601913610118953450980230617421387823387114321039; + uint256 constant IC24y = 684776033451391807773496036368435775473676587377239740534880627484043892051; - uint256 constant IC25x = 10754029893239883996357951951628952208784365734832249102641651831368516446554; - uint256 constant IC25y = 1512088372644426222104577554197067771438352753703259964417078053825961713151; + uint256 constant IC25x = 6905787635551118817416367019947024312211514839412196182473354054946296976287; + uint256 constant IC25y = 9073773280350094183697313232253045968953858264899014207423369407816895664304; - uint256 constant IC26x = 8965801610689595002595405380643107571231801526473821486939465596524456163563; - uint256 constant IC26y = 1990575800156351430249196431321287695225190689306325346684717577132046431696; + uint256 constant IC26x = 13306637200231533830503220504568727374426654473422967256521181232143642535746; + uint256 constant IC26y = 9905287965352985711803653987262566304924826103036042068850824213540722333093; - uint256 constant IC27x = 658799463109049530635389082698553628347185965072273064330390643365460948483; - uint256 constant IC27y = 13405677562890064873561226033606712934771098608476724815623119529809072464467; + uint256 constant IC27x = 13975571818634919306071529987892580265578815964293765017855321641621531903221; + uint256 constant IC27y = 5300859849766378300999776680322915197886702696720082887610869004009914021574; - uint256 constant IC28x = 4670655359096776733553081707580682502588844748490083471633629023138096830770; - uint256 constant IC28y = 6488838101003408268756670018808136583339021091391323196295144950220700805022; + uint256 constant IC28x = 15461548506058574530210271008631392910173946216984069691869311297773744026787; + uint256 constant IC28y = 13706208504159530911524812257232455305935489038658391834074042379348195879714; - uint256 constant IC29x = 1180261368895845469822817411490892166215039187401084649877621394704393314521; - uint256 constant IC29y = 1595293418801543000842631962609502350103032468055613957656853561575554047309; + uint256 constant IC29x = 8730611225090083996184886288677544700541764038521483864314195520451147229096; + uint256 constant IC29y = 11247481622713393315035873003152287222935085324856747705316784771296595673366; - uint256 constant IC30x = 5725599681638513867016777243382848042025457023850387857074973591421703130467; - uint256 constant IC30y = 4748358959923203058463512303427588038076292680303181970622439573870368895155; + uint256 constant IC30x = 12650481169811028554568125651506265674590913621862836202688125356346247992372; + uint256 constant IC30y = 11452734649780361705780105715683639426183710853645312057068180259423538723332; - uint256 constant IC31x = 2831823426676598609658562094849647686826880490121941019646351323030466610253; - uint256 constant IC31y = 21281681591843671212111112787927911584393264086933269718285923299781025930183; + uint256 constant IC31x = 18801255147353589786966703415517609079978518336487219754042258413444127518119; + uint256 constant IC31y = 19893166553319303558130971297012299399136641547281031132305685314905030998930; - uint256 constant IC32x = 15628714637902002845692835315528619606830497872595777646425845531920921400266; - uint256 constant IC32y = 11029956528040516226392608549108249971969362564800280651245935215718627917626; + uint256 constant IC32x = 10511687321004525154566058994742879585718001333240678753787240216198612873446; + uint256 constant IC32y = 21035585223167373046736315494645287448501555304653780177687173952982331918799; - uint256 constant IC33x = 9741166931188394303452044647985267874563858336310297156862728995780923050539; - uint256 constant IC33y = 6856253999079830481815920937335629800513686843192893986891527925012405183234; + uint256 constant IC33x = 7272484077050364841806145255927549145744398473472937793159247950835711431776; + uint256 constant IC33y = 3332943818971710197352806450726589823168559481693067793695706760634701210734; - uint256 constant IC34x = 5340412578893639027320892120181771247600027415070143114023481697402168083877; - uint256 constant IC34y = 9878785258591337618411677581553129429961809222004088126614464671926218373919; + uint256 constant IC34x = 12398213457650840610919110725829163032033234989484701088276123492267294936747; + uint256 constant IC34y = 4259608936469531783501826512477567753342186953120203533262526878892490390409; - uint256 constant IC35x = 7830802881076272422242002885628397049146608767124814001915399705546480478018; - uint256 constant IC35y = 10271233937081179488796109492342220509920605765038327265765714123716270784734; + uint256 constant IC35x = 4238837052442157737602628064961876774504833160472421163269905967426095404243; + uint256 constant IC35y = 21848250279969602266847007164039196603684130099783052248041812103563139729559; - uint256 constant IC36x = 20568695072909926090785472199131742449061946847819876557253030954218241038760; - uint256 constant IC36y = 8090253717659426926034994325565773534226744105745394292903914691628468035246; + uint256 constant IC36x = 8492386204394865359133830740481874229340648359828275939759590994351412630307; + uint256 constant IC36y = 13755056518831659966384164241356011630642775799391196790093432317593236841492; - uint256 constant IC37x = 4360593488861012363063576337873090659969383301282071100663777774474540251412; - uint256 constant IC37y = 13508974920574837809802168852314929870859132568397534363560268700023166572893; + uint256 constant IC37x = 18652871069353668812559074416592618031978091090456771959148689261399017168933; + uint256 constant IC37y = 15197528527915159071043184850412060787519053445044144817887906567947217106528; - uint256 constant IC38x = 8168819567987017334417818056594040000893675129075330554707633927655599399207; - uint256 constant IC38y = 21554364355211946772896514721212726528098242209156762958769350026161400782521; + uint256 constant IC38x = 18242990479342094711988513795259571447690442758966541403071663580322034914731; + uint256 constant IC38y = 4694277002709134888384606306080013611889134864643132473497507757053371561787; - uint256 constant IC39x = 9076190532075581219228461167043852103071119206540332157010085453015207330636; - uint256 constant IC39y = 3356337988822620456051098873656377101773884966760489577022762536150452531973; + uint256 constant IC39x = 1301764858559868397372439245835039661364048076417031411065499735289989905777; + uint256 constant IC39y = 21374552920703964634170919159603713823469086788065336308759639968042414346907; - uint256 constant IC40x = 1738890537986340641563232846815778379914302770951790146367744788596111766203; - uint256 constant IC40y = 11680744043960758529481344360760385090686529128760223022815305468253390838058; + uint256 constant IC40x = 5703909713412030602521704551948720598115811456049201510641793049756078930084; + uint256 constant IC40y = 11343360379848634277868929278610347535014796127961282265684057695864199303693; - uint256 constant IC41x = 11032519278078035374450371251480117616307375430434303273522473430480466273898; - uint256 constant IC41y = 11759444777541376334762679081562192846943888334241598365174416412382416775371; + uint256 constant IC41x = 21676266146672888828908790051178127819023353821226367259237036360300088838150; + uint256 constant IC41y = 20282295604827307954821629408550991162593461788632176338109233694336422372280; - uint256 constant IC42x = 975484287630296320123562370594436328585623119435685348496746244589960426282; - uint256 constant IC42y = 16306932306324030391394601010083896325087656834393554589950134417361741693871; + uint256 constant IC42x = 15900351677039192970235086696274291816056092279722947753810633865422331110510; + uint256 constant IC42y = 7552633138863201012843937997990540379972533897372099813912374675845082336737; - uint256 constant IC43x = 20799943769577155751147517300197228323261634403323343777907580029956076446788; - uint256 constant IC43y = 1582030258433952612426737479742105317880911936406371291174661209030848912117; + uint256 constant IC43x = 16986114726426059742163302482011322086275381379115213583913103602213591705633; + uint256 constant IC43y = 923269388364919243684772277727900792509753326830815519333165313425426159812; - uint256 constant IC44x = 3908730706265324626495762736382090512637335740407382692274982098972015427593; - uint256 constant IC44y = 5154443680021960787510375550446891195833558907011270847949752866056543144710; + uint256 constant IC44x = 18186660967945754210000520490901640298568718480270307043999757416860784824435; + uint256 constant IC44y = 2504159044950004032445503102664948854687012926668096130852117535309632169266; - uint256 constant IC45x = 20422043385069297179239469706704066046244123188430264658044861269153295485013; - uint256 constant IC45y = 17509293807050079024428031793068504906531529399685577643741547856609753098825; + uint256 constant IC45x = 4991552688486276616511273377000905780037528993680569787454736501968017275936; + uint256 constant IC45y = 20329730207244190194399341946823927144025883223552266872518685163447033251710; - uint256 constant IC46x = 19377904175261504733149287710614929387142186881520208018631868270226707238243; - uint256 constant IC46y = 19584370567070657365983874417025970012162180256418183204070215232820650535367; + uint256 constant IC46x = 15588669292822971027212746772468059587153741804272380842071129604935726444761; + uint256 constant IC46y = 13246615605370923171385971348275178771325109931221712502857728544047515567676; - uint256 constant IC47x = 15124599472592999515315943698451703704951186669815756069476650692212183790929; - uint256 constant IC47y = 21398072253702860808041845648657417165878223226624391728708768110703783597013; + uint256 constant IC47x = 14296275320715004191013745886745046991602044572941193816257113343670653624832; + uint256 constant IC47y = 2601284390982903491762982344917578099649417178108163508683943707962860500350; - uint256 constant IC48x = 4079937364778920306442594024315627391052523545523540009281519905055199997783; - uint256 constant IC48y = 10201888942110078166950344165524145021781867737465046769820965073997280386548; + uint256 constant IC48x = 16950244266549700135382898829621258093653503205489322996191500320120085510969; + uint256 constant IC48y = 6966954670688364311601206395118660404689846194634462521411331768192803520094; - uint256 constant IC49x = 19356092471412258141029087355553408270673707906855194680708731257168363831435; - uint256 constant IC49y = 1061038648054283783341854542745595029053821005560616425434165472291015715453; + uint256 constant IC49x = 1793479366619778804560203910817313900980767350800954690294822254090714032064; + uint256 constant IC49y = 1048215802761854722044182044883578100910289257829996092498059084505962374306; - uint256 constant IC50x = 21343028396534167722522087334655271551240992456400214147277830321036266408423; - uint256 constant IC50y = 11846669440179039761703317955616648733553305301080432399933270821945580221008; + uint256 constant IC50x = 13856521648827555085850487426366910290801355375443444343366086110228301059830; + uint256 constant IC50y = 535324682486169534839214155712250670348408259872174356460556327634867645044; - uint256 constant IC51x = 10292521103864911829516118733430078449161529689024076122421368624813287114332; - uint256 constant IC51y = 5262830170148138781879618635618998979151463825944890441891322091482955700449; + uint256 constant IC51x = 20532896844819862719302461052830608965671775711098369002889100226843723304065; + uint256 constant IC51y = 10165245834300535034995935060162142357012127635762461585340813984120842283399; - uint256 constant IC52x = 20153037745608603454973876932832386367398863709960474763581636423278843777558; - uint256 constant IC52y = 8131864189330604204685933794116391572936378578510887245069112518537895076359; + uint256 constant IC52x = 21706945700397762273061470570984677242168625760414490349459981827557223393761; + uint256 constant IC52y = 13018625219030750006251531760542205498208625774314240956959696899549810023416; - uint256 constant IC53x = 17187738837796036200075504264487161589801857077194488751149858577446279014274; - uint256 constant IC53y = 12080362734230497576274130333255296516249494013550225996752358008099406447652; + uint256 constant IC53x = 19949734495316122589728542702311543846078135806716613800415036271605233348941; + uint256 constant IC53y = 17610569332553481342822721120848436097030885514608311144321720352640822032227; - uint256 constant IC54x = 11847067467241475596668453029782243247363206460914528357997382225539958278828; - uint256 constant IC54y = 21086520617081063638758857193949011421080843371947185288143683110611184659837; + uint256 constant IC54x = 15423868577682089147254397346746037852568986160806737601551331562387468734411; + uint256 constant IC54y = 7375518587880462511927311850962084418893297203604477887361607048862711107346; - uint256 constant IC55x = 5996420344908801778003389639638044198976138220876658841634453433483910911772; - uint256 constant IC55y = 1497970572715261788820528550447484475853291992758033288069899941602871818952; + uint256 constant IC55x = 12577671908654509512753921257679284932649171016080486414752763526622624937379; + uint256 constant IC55y = 2822986953532073626384807171487787273923093456830811642298968906173084618252; - uint256 constant IC56x = 4707714975194514186283567202803559015209693536722913628673628779812487347123; - uint256 constant IC56y = 8107985637246170799012634655180246560278288486829178920536350781113786554058; + uint256 constant IC56x = 7101901272264342721235744390437490009744607361279923026192561192184716770940; + uint256 constant IC56y = 1960330795533000366229628853474316049039025107856221183882939857657751805495; + + uint256 constant IC57x = 7691495400094693753216268714788131116165195526618960887994162298184250615269; + uint256 constant IC57y = 20266934251235402524075097510808143546332698370015625975778871109777745169355; + + uint256 constant IC58x = 15308904568004806838333292069495967804191763022342145474464916816147736254990; + uint256 constant IC58y = 12725832748756479321212289733196376490749108660151710901111018005353112155462; + + uint256 constant IC59x = 15202083440469925507799278476974817171471136169349172236985101212482195929767; + uint256 constant IC59y = 13450805176974038818560776381803544848148900879794845768978747920698467277057; + + uint256 constant IC60x = 11105808131601383970258936055037294705639455246096494991661486358952307565964; + uint256 constant IC60y = 4381323687858725316139856902510988167456513753163202489496574375897393705657; + + uint256 constant IC61x = 8712061720494230564725748030948956762561835865570911224942084365139103338532; + uint256 constant IC61y = 20285562077593608041077226666405665601710539151360160642396404391092949958418; + + uint256 constant IC62x = 9793790434502609829423745560658992632851959811916953980186746842770443206739; + uint256 constant IC62y = 7049665340999458484091999269052279156744379198095613680285782390224484723907; + + uint256 constant IC63x = 4126142035587342662096948813543352742407412826025778459020396617635592493463; + uint256 constant IC63y = 17515973803942265832645666042755095987623520928417041957879643390144752197189; + + uint256 constant IC64x = 19247207862201928049665157665966019429648008517374964258403393747624217085558; + uint256 constant IC64y = 5883119913118532891547653021528280926034817697092548148689106955497551603595; + + uint256 constant IC65x = 8041509421060849686321537689107142871225800893472016045323498838246681453229; + uint256 constant IC65y = 3431923506157888786210165459510810556282026588990305561706761506851510698262; + + uint256 constant IC66x = 19580268285267533656844592406379164013624739067439830993341391612509642621927; + uint256 constant IC66y = 14902911267050146103685190334259509182241627230366165452249801112538718673687; + + uint256 constant IC67x = 15527274115915464115840466780647508348661881376611401367550382868666494632303; + uint256 constant IC67y = 16457150041848329656504960671583325903799422628454043853964249079520392949405; + + uint256 constant IC68x = 21360934675735574499842804934486737587647946913478237997427557917461866800518; + uint256 constant IC68y = 3799185647303562495398103200645762690993666519764820510890059834232915650469; + + uint256 constant IC69x = 21429820736360022235130570460476701866598520552579156149951166264823616821429; + uint256 constant IC69y = 361471616885532291366819177862707657818109317339903791558184848883482018256; + + uint256 constant IC70x = 4028171144463242594484910650076389944546055584021258386802730822642903745154; + uint256 constant IC70y = 14353333781585149641734409678186313452154764769422803611820129948675659195341; + + uint256 constant IC71x = 16167712066996997001640295311841282891533462998152861578318014485638243031653; + uint256 constant IC71y = 4540890500480426359230206672050314265507235790009506090520239337837566320050; + + uint256 constant IC72x = 11923159010491824506757683051348000555951003334946594947386901785606478040661; + uint256 constant IC72y = 2572782218313973361494279590352442403461305126205802617863303903726721978152; + + uint256 constant IC73x = 3796899408203311135956653735456167417545890607362679618739784778181219318165; + uint256 constant IC73y = 363766308721047788110619408621332404986888948818292081892407097360922064560; + + uint256 constant IC74x = 4898407241626997455459623174269752843105586315823889518182507405465293557808; + uint256 constant IC74y = 13252560933289697433715523346383499877463019419230616412590992686705641632815; // Memory data @@ -221,7 +275,7 @@ contract Groth16Verifier_AnonEncNullifierBatch { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[56] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[74] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -377,6 +431,42 @@ contract Groth16Verifier_AnonEncNullifierBatch { g1_mulAccC(_pVk, IC56x, IC56y, calldataload(add(pubSignals, 1760))) + g1_mulAccC(_pVk, IC57x, IC57y, calldataload(add(pubSignals, 1792))) + + g1_mulAccC(_pVk, IC58x, IC58y, calldataload(add(pubSignals, 1824))) + + g1_mulAccC(_pVk, IC59x, IC59y, calldataload(add(pubSignals, 1856))) + + g1_mulAccC(_pVk, IC60x, IC60y, calldataload(add(pubSignals, 1888))) + + g1_mulAccC(_pVk, IC61x, IC61y, calldataload(add(pubSignals, 1920))) + + g1_mulAccC(_pVk, IC62x, IC62y, calldataload(add(pubSignals, 1952))) + + g1_mulAccC(_pVk, IC63x, IC63y, calldataload(add(pubSignals, 1984))) + + g1_mulAccC(_pVk, IC64x, IC64y, calldataload(add(pubSignals, 2016))) + + g1_mulAccC(_pVk, IC65x, IC65y, calldataload(add(pubSignals, 2048))) + + g1_mulAccC(_pVk, IC66x, IC66y, calldataload(add(pubSignals, 2080))) + + g1_mulAccC(_pVk, IC67x, IC67y, calldataload(add(pubSignals, 2112))) + + g1_mulAccC(_pVk, IC68x, IC68y, calldataload(add(pubSignals, 2144))) + + g1_mulAccC(_pVk, IC69x, IC69y, calldataload(add(pubSignals, 2176))) + + g1_mulAccC(_pVk, IC70x, IC70y, calldataload(add(pubSignals, 2208))) + + g1_mulAccC(_pVk, IC71x, IC71y, calldataload(add(pubSignals, 2240))) + + g1_mulAccC(_pVk, IC72x, IC72y, calldataload(add(pubSignals, 2272))) + + g1_mulAccC(_pVk, IC73x, IC73y, calldataload(add(pubSignals, 2304))) + + g1_mulAccC(_pVk, IC74x, IC74y, calldataload(add(pubSignals, 2336))) + // -A mstore(_pPairing, calldataload(pA)) @@ -544,6 +634,42 @@ contract Groth16Verifier_AnonEncNullifierBatch { checkField(calldataload(add(_pubSignals, 1792))) + checkField(calldataload(add(_pubSignals, 1824))) + + checkField(calldataload(add(_pubSignals, 1856))) + + checkField(calldataload(add(_pubSignals, 1888))) + + checkField(calldataload(add(_pubSignals, 1920))) + + checkField(calldataload(add(_pubSignals, 1952))) + + checkField(calldataload(add(_pubSignals, 1984))) + + checkField(calldataload(add(_pubSignals, 2016))) + + checkField(calldataload(add(_pubSignals, 2048))) + + checkField(calldataload(add(_pubSignals, 2080))) + + checkField(calldataload(add(_pubSignals, 2112))) + + checkField(calldataload(add(_pubSignals, 2144))) + + checkField(calldataload(add(_pubSignals, 2176))) + + checkField(calldataload(add(_pubSignals, 2208))) + + checkField(calldataload(add(_pubSignals, 2240))) + + checkField(calldataload(add(_pubSignals, 2272))) + + checkField(calldataload(add(_pubSignals, 2304))) + + checkField(calldataload(add(_pubSignals, 2336))) + + checkField(calldataload(add(_pubSignals, 2368))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc.sol index d0d0e0b..28ccb58 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc.sol @@ -43,62 +43,65 @@ contract Groth16Verifier_AnonEncNullifierKyc { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 15510813880661462106018872737660609981812361161360225919247077268694414066204; - uint256 constant IC0y = 3273104381472301566282116664311590746314861956272520926873509575735905240319; + uint256 constant IC0x = 2101445661096098500695499442371715160299284047295600659193099820707553551716; + uint256 constant IC0y = 10362879292510370007927168062017727280133719396001750595095720484543761937055; - uint256 constant IC1x = 13491681648148788435689221543902213270283437913261488005306555856507875118485; - uint256 constant IC1y = 2808146101579469802466416404016575911891728776617600866872460209262742827298; + uint256 constant IC1x = 143037762769493157940690903021326562009140250481843982993339451380506111112; + uint256 constant IC1y = 5850994117884549024505108566192301773206758871667705635196392926890246740094; - uint256 constant IC2x = 4725690937934659890215005371779681247012771736776651374911909283856555247990; - uint256 constant IC2y = 18321810493651809990909231408699263823551531357876718809194078272222655927537; + uint256 constant IC2x = 21813414019198417877692314192484775736547859346727104349558513373498856059230; + uint256 constant IC2y = 2522359220036345152243657054788318972655111072255771948581803079042603993301; - uint256 constant IC3x = 8958459661740944314305843955312561986747476993485058073196137338394860261170; - uint256 constant IC3y = 2437947121733860719471348909661252826832073454682168662626787097673523785627; + uint256 constant IC3x = 3642928053401683423636966839904409755796906574849977901631326846791604046471; + uint256 constant IC3y = 21342445322203542212288318163142656601643460551843210178616475323984654192012; - uint256 constant IC4x = 9451517300068142777511290574255154988100826100902983372883665735584552715828; - uint256 constant IC4y = 8619494869961996685562554417413284715040248852855616958676788456000592520314; + uint256 constant IC4x = 10005624193996015715845272947969078652505475841653860612541539286408237186741; + uint256 constant IC4y = 8904668934230071817938248601102806407300259595587825875979446618284551881798; - uint256 constant IC5x = 11979127296661119548762239476028183940430281334958083280546357773273520336461; - uint256 constant IC5y = 14876079694076565848273795501795074691202817530277907689935757800793104883839; + uint256 constant IC5x = 4252604032686906795471745181458877873145270931075368231855398520653841980516; + uint256 constant IC5y = 21710466343194080959922243660216080363878294570140318703482360573828751790132; - uint256 constant IC6x = 18475773985808507485148294010988879922821184305104367237479764157201546691326; - uint256 constant IC6y = 2850090538560055751503986121052040852671655864735358716840252120446691440704; + uint256 constant IC6x = 21301141460740028752408572822391426289464989302071188166913060202180940988455; + uint256 constant IC6y = 19571676789991163684635350354000657181719351575287433267350738257251835171196; - uint256 constant IC7x = 19811465473699014198715355967511549441553654782745492609261172832801365651601; - uint256 constant IC7y = 14870600544910155067451163725422044515921665391516780888059632287167180121205; + uint256 constant IC7x = 12031095088505961172125554815052019308363370950934499659459823010382728830404; + uint256 constant IC7y = 6869644737539853676148140674560430289067409680413722597764382512270023560944; - uint256 constant IC8x = 18563696230702476723728375853876157474970068550727434636342868022005576134363; - uint256 constant IC8y = 14388176320387786090092160119445811376873598328744301280591832433356922265122; + uint256 constant IC8x = 20163449202495063406210816242374997127502597539370613167595680071171744317171; + uint256 constant IC8y = 11311366342624928419808643428679835067737902214072968887326856985785061221989; - uint256 constant IC9x = 11968161318939536287355505921566622267097175647130446571778130558246374942130; - uint256 constant IC9y = 17035629199023956978380320405701548422256095088150323734083362574539700979748; + uint256 constant IC9x = 20698154213044287145676865513874256178804659016537470440369493061237612324504; + uint256 constant IC9y = 12576926955739265870067258776164424157413587517100533852524125074069389730429; - uint256 constant IC10x = 6410206309031762314294667109249209264272987325572542136076892695058459306807; - uint256 constant IC10y = 482381398754193931307654362683142689426055567274660023737349665299694375107; + uint256 constant IC10x = 11250523527047526834561439432041993034618624117093627991251605415769407539362; + uint256 constant IC10y = 17907468386432017490406891338161172700049188051055797951575053338510272395621; - uint256 constant IC11x = 21722979850283689312457149615911951102070483117187707419687509883557528229724; - uint256 constant IC11y = 12631428830081777702977793500448863584294718325066681881436933861921735534957; + uint256 constant IC11x = 8392487640466665715586586820304552751372406587365016338472815868126769111363; + uint256 constant IC11y = 6769196229708914020554422274469711603854641440745296821149294696298801249778; - uint256 constant IC12x = 4213751153858869170897807199037433362203968810814722651333773235333110630864; - uint256 constant IC12y = 16122011455192910143632741314231760101414290432223179448777617803201467621504; + uint256 constant IC12x = 3883805730491052680861024631760450959945162359260332304450632449880829036103; + uint256 constant IC12y = 13574781871549139653032780834396648028021364679469558695322726717428805133591; - uint256 constant IC13x = 9554837226992446701228515303642079637807357890017383384812440314038449036838; - uint256 constant IC13y = 21278693557448139173734004799254900498966524290247139602851908625613299172864; + uint256 constant IC13x = 3712095324570700375376338806022166258376894208640379288213960762053951689172; + uint256 constant IC13y = 20667719539217338681893327405360317533667499726179320338206898066726796607014; - uint256 constant IC14x = 21776500713311364990401539077316370261564522412596186807180057925462702413253; - uint256 constant IC14y = 1568240173320516553013947629299718284044658941775257081542601515693979514240; + uint256 constant IC14x = 3097002507960051703213654685251518413705854628664643617796684420014836169179; + uint256 constant IC14y = 12701929720942225064139703316349909986762394364130937720922269085242517640274; - uint256 constant IC15x = 21564273127276639904217256917910112212934525318645740398461486168827007311543; - uint256 constant IC15y = 13966086613725475985651402580739572931083145387135567185433524377871781733319; + uint256 constant IC15x = 14600660667929898830470559105890512997029916614670512099159679675748869035704; + uint256 constant IC15y = 11017585299166644609325141450109253861938541098664061213432681471286424623722; - uint256 constant IC16x = 5814620384816433324722377794717911120049565607978997516640971611103253573951; - uint256 constant IC16y = 11257037619337374908153737141021522383307369817181402888470764219459897276361; + uint256 constant IC16x = 15678106707089202971157200369157139252269515864413961042809314235350595765085; + uint256 constant IC16y = 18308747354515602916311996757245707217558859904146913241865192280844067110351; - uint256 constant IC17x = 19994952937395086016308786261883552107726289076502224155095304083545548173808; - uint256 constant IC17y = 3001631091913078426548462975826877675412536962038521582563185880104933764982; + uint256 constant IC17x = 18510565052285649086504893109924312402387845770317503709170022754101172187130; + uint256 constant IC17y = 2452319668579540529914143443180602151977125142307989050494730386258239185071; - uint256 constant IC18x = 9191783136958454841559750054191334746979556656626644038950166417489988792934; - uint256 constant IC18y = 11880320083627745669929133143013437330294790783517525604948234660913864147042; + uint256 constant IC18x = 6571849919808570688932630589125994276436770884363895777898406143060638649747; + uint256 constant IC18y = 9204693645690522821608807373559664233868880905201664235940525915891765403736; + + uint256 constant IC19x = 2486942122466912773652128335545419024673810068929266047399593034274357966587; + uint256 constant IC19y = 14679120849869353894947197179192282119128588573415730456983400522947595480010; // Memory data @@ -107,7 +110,7 @@ contract Groth16Verifier_AnonEncNullifierKyc { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[18] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[19] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -187,6 +190,8 @@ contract Groth16Verifier_AnonEncNullifierKyc { g1_mulAccC(_pVk, IC18x, IC18y, calldataload(add(pubSignals, 544))) + g1_mulAccC(_pVk, IC19x, IC19y, calldataload(add(pubSignals, 576))) + // -A mstore(_pPairing, calldataload(pA)) @@ -278,6 +283,8 @@ contract Groth16Verifier_AnonEncNullifierKyc { checkField(calldataload(add(_pubSignals, 576))) + checkField(calldataload(add(_pubSignals, 608))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol index 8b476ee..43db952 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_kyc_batch.sol @@ -43,179 +43,233 @@ contract Groth16Verifier_AnonEncNullifierKycBatch { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 17504848062868348026374002498224723996748756089276549138002654517982016255538; - uint256 constant IC0y = 16387507367412557460257377765383794801476813095817061623259001184927071106034; + uint256 constant IC0x = 5879424562730631873560665784311981595213572976855664375149709980743092774122; + uint256 constant IC0y = 13206866748476381944629292199003231744773785152598965076883128035599867853787; - uint256 constant IC1x = 2856069502693004785127392038262393497974744695634372998401820715110377580575; - uint256 constant IC1y = 15561059156075398193317869131598022491610304991667406081651699520146364765780; + uint256 constant IC1x = 15282169789980326971904550824335238386817848748909013580290859998714153769728; + uint256 constant IC1y = 7499960709101510675913166010109648378980965365673629087882118678621184270437; - uint256 constant IC2x = 3859389872830912436200600964789102024361491814219596610803029929946644931037; - uint256 constant IC2y = 1379316890215683508391001779822326692301880648522444673041390804439970054068; + uint256 constant IC2x = 3578459586325224532056059944917518839394519128400975273626895213233025670336; + uint256 constant IC2y = 17272773564081154461128353182642362910499205594170594449333417484297773873573; - uint256 constant IC3x = 8415946265759935198667780399036578786314201446216726794902855492967332252013; - uint256 constant IC3y = 15809101762048384534955622139547502714750399693643041128184833018326642991512; + uint256 constant IC3x = 197034807531520429878206256088701311239327312308013073003098805299375721937; + uint256 constant IC3y = 14059242108758834267366855334344521020229378447514273990452780096596776533082; - uint256 constant IC4x = 20535800429315416894612599549205808164074195628326052033986955795418689069905; - uint256 constant IC4y = 11366931152943347478625131981318793312836195302128744391498974801567323524615; + uint256 constant IC4x = 18305198359557417602536694816075366899249880978881100999493998698728306888415; + uint256 constant IC4y = 16089041801360961313466420448295896469125318371148849197946752990398785394011; - uint256 constant IC5x = 15829477644400158320246641877331704309264586925310327196539914283139342353644; - uint256 constant IC5y = 9934659057803690299249584984817022967602349279267611443853677220761678388542; + uint256 constant IC5x = 11885137273538506752867177832041138715922297357352324574957641675330052864331; + uint256 constant IC5y = 4067584364717025687436527377627439802168472956336329842601632426166677343993; - uint256 constant IC6x = 18918146804733231422333304863438872219739334678962399068661097122605973950262; - uint256 constant IC6y = 2343376008553314523127702902049483169606988764179316258282911398991407702768; + uint256 constant IC6x = 8148601523579419011847384792699764594853373827476934294033693993504233772399; + uint256 constant IC6y = 16057316536979538282443076509777020106755449805698416567876341226059866009954; - uint256 constant IC7x = 5231213558934753070201601921131975968358823135926337144767682276145542464989; - uint256 constant IC7y = 4665602492217868979300129137374085100174413837649811540289188169123300996478; + uint256 constant IC7x = 12037768234901220602199856820113797877041049700441298954046885550050522178585; + uint256 constant IC7y = 9363281685682409209234935650420670943610610069381323832800642807907230747168; - uint256 constant IC8x = 12336799161694575597638898320521434723260248461665346045536341492377334909750; - uint256 constant IC8y = 4637784107473356705217888916047150724972967899841641299327891030782008485610; + uint256 constant IC8x = 14646872255043112970272036075814269541536317995327049583097986395960777389618; + uint256 constant IC8y = 1621333485711245705745205228004099054244081268449139556613989487296116782949; - uint256 constant IC9x = 13827078590544495241328131801668858903611645676710343835547244977983692125329; - uint256 constant IC9y = 21410062214257392592742258923502999657896516248971868238962723630823346174229; + uint256 constant IC9x = 19775316132999776498759542735860347212819060939265685412419414428073052134627; + uint256 constant IC9y = 4608687134445774707008293385324355359543041753591954775503016630583162119042; - uint256 constant IC10x = 16648148804443180403693863299061946840717694348838543762562820313123418826667; - uint256 constant IC10y = 8195801067000683311584686635958018789966651244321576016528996434560391429285; + uint256 constant IC10x = 16099052095232546719802260030800595737783250507579665289906231650137389523504; + uint256 constant IC10y = 7893724112620136209815945904734616456952347632915844876449990186798682877525; - uint256 constant IC11x = 13818449178804543430163997020412248802763660211216674889312893590596745982432; - uint256 constant IC11y = 17048611745560760119354806941150155291932280127893448128213081928960037394954; + uint256 constant IC11x = 3056912874178986288838663096512087996708267905193213375559390706386163682872; + uint256 constant IC11y = 1514638771682044463329095778824526109809967853966651241302585519766107582756; - uint256 constant IC12x = 18033428927728964864971192997985346363885015121354210336522092315091747298594; - uint256 constant IC12y = 13365128640778017290772474101327304322106191025175089654914826009997183501245; + uint256 constant IC12x = 1404092927951756013597895730140839291183947294471377019561596136610998130440; + uint256 constant IC12y = 15623773051151761186326761145515739573945050760726055768708771248158561498228; - uint256 constant IC13x = 4017576198307072663210157991121703896022494186654317864998385350827601491277; - uint256 constant IC13y = 6717755372091993174391999198308039571277228379267328284322681839457836069352; + uint256 constant IC13x = 9576441620339730381094895314906773263527201645034383465123334083291711765836; + uint256 constant IC13y = 9896797057488658161314137120206713724873513455207329772040002436841046850406; - uint256 constant IC14x = 18951077169344637293936120179113270077592805538523267528595076165889093420379; - uint256 constant IC14y = 16024951146607749589423441411795299622228655287243270569258657281947614692069; + uint256 constant IC14x = 145601496683190083773803860467138899082020258784010268473738963322069542566; + uint256 constant IC14y = 14007087225913531300142045107727112841821984494863605846003202076964654741568; - uint256 constant IC15x = 1360708969957543383913365577994960778540930930157623031832678872345741108091; - uint256 constant IC15y = 19188784503212735203818937702066709460520133020564105345650189896442261576792; + uint256 constant IC15x = 3372190984533446456890699363025326068027012148844883516925962272413560151770; + uint256 constant IC15y = 18560741302432737159517852251417424897074073126740660059701111852146993979497; - uint256 constant IC16x = 2310084532603556369969881218026228249965185308444498344685656131291285072090; - uint256 constant IC16y = 2684005466847837835929849832608810195680937122019646046234472921562603046979; + uint256 constant IC16x = 19912215255388771485574384336706417867653797205425596845949286583447854648271; + uint256 constant IC16y = 6995001075253251586380762968020241732919934674913639077980014146525990206684; - uint256 constant IC17x = 15033210889123591887211381884005556788119507851747650399577670617675067962985; - uint256 constant IC17y = 21635465298217685594774739863370705370837990509418620255911645885375058632522; + uint256 constant IC17x = 5483240527666558072645510304792558005910843928871145092828007065898455887913; + uint256 constant IC17y = 15440416814938865094565024254546293466987704590811833158431184937033918781241; - uint256 constant IC18x = 20964847427539155244303558143809704974415302350648268606966770643146458239040; - uint256 constant IC18y = 4976852868551769830359648093452564906077147425657133752050439032094469178040; + uint256 constant IC18x = 14782297685341202881645774424037665327184105702945875674725280843137690447600; + uint256 constant IC18y = 1620384386022682838962458121754764532173602828878779213885935960925184731325; - uint256 constant IC19x = 5954934735275902994859735641635771081547956714325915040567497876417048394143; - uint256 constant IC19y = 12342305689282435518046032667069855834926960332665248810505225445852009809853; + uint256 constant IC19x = 1171688358275105292783738617724244003790699210255866338784729067962221252746; + uint256 constant IC19y = 14281912851508071024054994668242637687301935221249367382342439540731810886364; - uint256 constant IC20x = 17941161690977931098269864811397641132700593252578476448070438328580593719549; - uint256 constant IC20y = 10992171856448189204497970359711415772839335327634080553352925596600238931744; + uint256 constant IC20x = 20347527434246834723282148235319426299066672911747060033126978550391175449445; + uint256 constant IC20y = 5303220787428916539470377959086980264518321061473367573230745434641333240835; - uint256 constant IC21x = 2425648535044684031614952373699012963219840911718726909909891256136645080412; - uint256 constant IC21y = 21518967218854415204283336476228379728243999731939483558032968206724325807574; + uint256 constant IC21x = 19179731889554897057776804513279793130466426954972425189219331958526076016887; + uint256 constant IC21y = 4445528599037546946777217693890113870365663777965295532448953807555220602911; - uint256 constant IC22x = 280260936926782546013980159100142770253473969473128400047541356265542999741; - uint256 constant IC22y = 10134098037208287844145086332209993231553540105278897499267027143835982878853; + uint256 constant IC22x = 11806165497541944446376391657387565359407103613171987109320808599242802716209; + uint256 constant IC22y = 14737637212042438668460307240543825758060318730491247469945951452640347707548; - uint256 constant IC23x = 20630322258542475647304370850837690639747200948464440858494114988984663473167; - uint256 constant IC23y = 5471360679957290184735041392000798787632877792653590599469301208859338904086; + uint256 constant IC23x = 13851363581844588948052079333589972202899416739082046495735113810033698241162; + uint256 constant IC23y = 7198459307783162593588249279195591466526828528293563672399089446016016248828; - uint256 constant IC24x = 5111371584357786162832771597844547131550671201855188104706039744961582660796; - uint256 constant IC24y = 653040201219489798026416604261073895543507016306735716151353126125677369141; + uint256 constant IC24x = 7323586796583915538517203253475425596568875649851764668132652747576897356674; + uint256 constant IC24y = 9729449148236190158990275233658468848836238158974702870478357903438559769579; - uint256 constant IC25x = 6978336124426926881856591004162044830754073908007920213323571023785613542961; - uint256 constant IC25y = 20414386314498291861276120712979377062332720562156578484901224643232480540249; + uint256 constant IC25x = 13062739373677177356285877655756540319700401112341451458289018760065571317356; + uint256 constant IC25y = 6988216302343924340288284552829649507771461236411942619714230419889112890232; - uint256 constant IC26x = 16345303897992857692859745636449950638729953287455034304026858435009952917186; - uint256 constant IC26y = 5878643236005185094442864082149593891339348972501610978330490869945951001658; + uint256 constant IC26x = 2464215550608163570038501219646000285436003972199334545314794238287607467824; + uint256 constant IC26y = 16620971382566073073128670286766287985754203816896866852368294400912265894110; - uint256 constant IC27x = 17523481398586847238194919850947265455706770941799970175927495066504128872273; - uint256 constant IC27y = 7471700472916472025019136320781313792713403580172746538799171676063158368084; + uint256 constant IC27x = 20940040750330519406230306223206959132162605675817097713078739721349293057417; + uint256 constant IC27y = 21287713070208274602768525363434407364711158919815391235905594775885332798341; - uint256 constant IC28x = 2094161036937708942704900106707404659693176539918526900245846886917959088539; - uint256 constant IC28y = 7880341502494899999695463060452869823744265572482012990875757815234964862638; + uint256 constant IC28x = 6401729451874095801187728414284491748130061433879980220338030275579186819738; + uint256 constant IC28y = 13937574244579894959948501614829150203297890136818974290229078781393132607873; - uint256 constant IC29x = 12227797433782018797845158251242806466077383214640501764299030787081960976752; - uint256 constant IC29y = 14223507300666949267825712869946068457643885067211133573755649286573564767881; + uint256 constant IC29x = 9368391468110987658570378975892753259540418036926848523586290852343199284773; + uint256 constant IC29y = 107729344928419472941901678296319367646979433201813012887361138123247414839; - uint256 constant IC30x = 453540649793160026316799015062804977909721800597914418509950105119312342297; - uint256 constant IC30y = 12324285493695239709623854660026174408162078281863628396002540780982541880744; + uint256 constant IC30x = 2465894890831381993380825656243358825257823266694928961517668757124215052934; + uint256 constant IC30y = 15873045630070953074394329139768616105680399126773880505061342476653353822689; - uint256 constant IC31x = 5580542283201294383971258676804392634747059901485539537837867891173931906725; - uint256 constant IC31y = 18893651463971054272255885924027852040285006550612275136101519628602670404805; + uint256 constant IC31x = 7084362018026161779770911586531273766785690156040435490420195876990482099784; + uint256 constant IC31y = 2394109909281977185888124670377335145609878915972731855891616452361034008333; - uint256 constant IC32x = 16053348515324942000894930414520400209998037357589282973515627559839553719937; - uint256 constant IC32y = 18721430601727038239377701583956253836579793295356933421370242456531250291255; + uint256 constant IC32x = 17050076019156816070944281280708943910838920040776857008320640503046547150705; + uint256 constant IC32y = 15441033341296752528073976522603243961612433476509181204526290320086756678144; - uint256 constant IC33x = 4207348331894209505377454332648293135047961513011552219208614177339885764996; - uint256 constant IC33y = 15578406702422632993441451980677291008648229741735120457430480166703313489087; + uint256 constant IC33x = 17007360840996458735533259298276500721591653279705741864746192509196970296979; + uint256 constant IC33y = 12686223349904100427859931074755256614188491863578850524425378118131427547603; - uint256 constant IC34x = 5638734168306965054319883075296665200673266975989878680177302242980003365757; - uint256 constant IC34y = 3054907442264710302362313978881788880782770809199005375546833629175395917303; + uint256 constant IC34x = 7174987464014142375128567768481998931345937721829236042612567921367171113916; + uint256 constant IC34y = 10609882706640379435056873300851937306890039989866004929634236687903425161370; - uint256 constant IC35x = 5861570516229947654739252134966410588166542172364647012821598504829520960520; - uint256 constant IC35y = 21826590176415498013503020647935392823956167012515420325697166485087109341456; + uint256 constant IC35x = 20885845815333350431275596172977175238706110033489472890774307126717679622248; + uint256 constant IC35y = 17135686419293960728794078095089698333457463514785430109646825105502189336669; - uint256 constant IC36x = 1163146016516187472740589974531980564637857783215779188095003814133427992849; - uint256 constant IC36y = 17100204026966532131401470450964759258544383909937911336093084512571070125508; + uint256 constant IC36x = 9664385680491244785981775913431166433938498751667358805274275141467748961484; + uint256 constant IC36y = 16332287488121385056121855611920427331672197271015405247318684627848158882262; - uint256 constant IC37x = 13527708705374185300712814674442001942903598446797709282125997239238565392928; - uint256 constant IC37y = 8474355221953601073926090123462985374466496924904865143135852117705069140058; + uint256 constant IC37x = 15913940110854022852039504331149734321941602181835159950530732042560603305642; + uint256 constant IC37y = 13777192189726860016802262305494521208478001078062908762352000876574019828737; - uint256 constant IC38x = 3808640281749836669607683401869874661662588536151452683315635118821978939890; - uint256 constant IC38y = 14861507266593989874827115625593671744007071304920501849993048803704385010084; + uint256 constant IC38x = 12185388915386862382750652679425907611744048678894608940766319281177016330242; + uint256 constant IC38y = 11388932634998818972372804947505502471386893327502266656159412742925186744156; - uint256 constant IC39x = 10194236907116302439622331517082527947776970543332709847028804137863312401718; - uint256 constant IC39y = 11329005164482137625321319303919030985281584614017669696906810224293393629880; + uint256 constant IC39x = 5318225103964474198489064177399855799456337524169256962784459861800216008249; + uint256 constant IC39y = 14693450832931138489723451342673318007939221559303114206375131645927124667178; - uint256 constant IC40x = 2175048060656940005354125903390105829157228568052786493865600961302899409802; - uint256 constant IC40y = 20845091066389805874005537483311906148961944629004027128749165572499641740969; + uint256 constant IC40x = 4539243343942623689570251191768100792555822101624054774825384133860358252096; + uint256 constant IC40y = 7000277072004524055112142174982168227316352091208263052411492677723204147201; - uint256 constant IC41x = 6513207037911904919854905415439872520001395253442037570879540199844544797917; - uint256 constant IC41y = 21768663552313415329491685534136927428823171722456684854961607216944874160246; + uint256 constant IC41x = 6570604828233255163987182543549279371016809764127851071270147347934510731037; + uint256 constant IC41y = 17877458349499320502633124552480378264058983829327733078020944292262113498032; - uint256 constant IC42x = 11143666812126252087435576182566526363905627516668442800728196103096410140946; - uint256 constant IC42y = 6535255151577129566349664645385780221288149031850600269892969667152281389934; + uint256 constant IC42x = 20473872403685799935913837068751302263965756852764538003563229844964853952896; + uint256 constant IC42y = 14453693115236959093382101734403849518452527195272893059887284625808299545272; - uint256 constant IC43x = 12216019667254591633256543770210142244306955316534898670848792497815288748407; - uint256 constant IC43y = 20932736431997402628568150442959172684450592121020005476297963810554983857496; + uint256 constant IC43x = 179332133019483352438736556438835523968308233835571076021869431262538088841; + uint256 constant IC43y = 21084723578643159210550665732319238098045251334026347455884481703971893467477; - uint256 constant IC44x = 5933919850098763144777134426689808617420104756103652617673006846516543746028; - uint256 constant IC44y = 1846818467291984087215401520026387243511815581026231594023176708787928601743; + uint256 constant IC44x = 6519245332321709834372618981635946116314695901293520552659744932664932571858; + uint256 constant IC44y = 9553619290856814915870116705308451598280045588238540889066732336668200195537; - uint256 constant IC45x = 3550325488317807172294579797915663005069767530335953601988476431803051781127; - uint256 constant IC45y = 19986059169930216696958502893247191080629716230489353335542951478141806211020; + uint256 constant IC45x = 17098401875622299082871013024128477847005619368976977771475382962032361024522; + uint256 constant IC45y = 16711078716343061402442750765152909900789642769078913703416407681486602210531; - uint256 constant IC46x = 11680897079617705713544415674593237825122414254090279751291301975595017258239; - uint256 constant IC46y = 7192914150142927503252523063820936177103915826937857509316891503321565576065; + uint256 constant IC46x = 6937301436998009285639202261617257662054184175035299414644515067014280276964; + uint256 constant IC46y = 13412747294496809883486271133731861953691100148664645738700749132634631608997; - uint256 constant IC47x = 2194944632260890612597133046164513345176661225427381736733616125225090009231; - uint256 constant IC47y = 20125380079300917290749136763381143149180127581158653088913932492057416883412; + uint256 constant IC47x = 17251101177466634404443311467132387586379227953585655692707127242790857814231; + uint256 constant IC47y = 32257460652713777703856951582453790239735732365781343371118959671852356494; - uint256 constant IC48x = 14422798646426772067663722833900085260897269980290313415292189180250359352601; - uint256 constant IC48y = 771703103591355791449427823813448842147352355458537942689020853074754641443; + uint256 constant IC48x = 453359389862300317138205574315956647398789221013682535590200718760411858323; + uint256 constant IC48y = 12215660590080857007159353422330437862387740196299978651691652936335774702882; - uint256 constant IC49x = 14615753219316385282263522991969142859295978879684495081642174089355734612047; - uint256 constant IC49y = 10726284617382468267788691700905497860909038954300000561095095525698258734795; + uint256 constant IC49x = 13636743361866170840377237612947726735204038302483096074368054786666685953195; + uint256 constant IC49y = 1404676530495469308352138721426302146045719996446356694900958006899504769898; - uint256 constant IC50x = 17101999512384579394851655687877848773235007944785753742455387481074274316188; - uint256 constant IC50y = 423071507367238120356829746625486510755573336530662107346332180257030287264; + uint256 constant IC50x = 6918788721383830371056271655744737593186437739010102936644481559276561787888; + uint256 constant IC50y = 3145930382218912939068735275559282673416206862818243206096217871999892204055; - uint256 constant IC51x = 9792926841156931454106301139947287811673122135247907827156714190812449701109; - uint256 constant IC51y = 5970908732417123977436766989527347543081758023388968529325238154277565717740; + uint256 constant IC51x = 3130812576532245412344213636666430939233954508715036438531282599785303888120; + uint256 constant IC51y = 12638671175273949730705239111814852209407283415272117295269734572775765002752; - uint256 constant IC52x = 12706145721666739923414163788987123312746958734319163889121620419699709488765; - uint256 constant IC52y = 4306164917367554262618109318601467317114306696451610147982033625958115348490; + uint256 constant IC52x = 10685875146445011461742284952763738571177731891982079198663348694402647405887; + uint256 constant IC52y = 8804518745723901478761359698953547104817786749784981253214284229160017198613; - uint256 constant IC53x = 13221349951903657044803747239233265785265507566859952375028444203437980813346; - uint256 constant IC53y = 10565134479636684577025748158266609122295088659249500688010380999868051230260; + uint256 constant IC53x = 20356422202910078499466233407220602392996353698947129037914752294314441521979; + uint256 constant IC53y = 12341505800666039726647642369806900907171401046256443281976478320185405546510; - uint256 constant IC54x = 15936621239909675935495995025933386182121678876586173688942468329781025961453; - uint256 constant IC54y = 8675648856225262437745421036662111826559370347795735779137840613949393851040; + uint256 constant IC54x = 18888410617119335703265049400236908967880231581094392176138244827031551448084; + uint256 constant IC54y = 14703600171645145074092717976923536856751011588829788080513083721549359490915; - uint256 constant IC55x = 11377869237069746467451540359369426085441126079383682910319711789669692949250; - uint256 constant IC55y = 946844900758779719927195974669359561147197227462088657885137274383506599072; + uint256 constant IC55x = 9139933829013975729932767940105346648472763059585218042515535725324925300708; + uint256 constant IC55y = 9035126453163676347404515495522257784660517669211308097846825350810671514050; - uint256 constant IC56x = 12391847394251081516284908202445344119027771364094180939362656437074203234144; - uint256 constant IC56y = 17991701997444862400258460727205796587715059621570231928646294725920133917550; + uint256 constant IC56x = 16805216642060232239806458278045945563759453156092815642832654202399345331469; + uint256 constant IC56y = 16195117201742272275205642165848969713997209938681512172560555859793361066641; - uint256 constant IC57x = 19273211338074274131409088982613123292043184587862073818414163136972356711192; - uint256 constant IC57y = 10596141629335780563818878207994516764687494527269573265381148633833675620704; + uint256 constant IC57x = 14432795835860635317192599110876979776021227976713244509387348724736478965818; + uint256 constant IC57y = 2261277026432232749652728598112671195687697376372442265420855576717426239367; + + uint256 constant IC58x = 18988365762278509991919793866822703031767326961150015214334532923046884467072; + uint256 constant IC58y = 19316032093341265221242837019522075912460038712742656856976255161022717799293; + + uint256 constant IC59x = 11599328628785806782044241002749534811867428529524396134455388421901872046398; + uint256 constant IC59y = 14619917552527905729476568744185523912015434998642833355371059807619892609155; + + uint256 constant IC60x = 12970497412633149236620211657305192135277913186555572451418836618314360759077; + uint256 constant IC60y = 1535577522461044270097258412071009752049795294677712965767379674769842237874; + + uint256 constant IC61x = 16308302680176784246305193447120497869389849465306309331472801130297223731250; + uint256 constant IC61y = 5045808378861381077608639873267624614673859039956914189704301231382082230903; + + uint256 constant IC62x = 7614300032801510129936567013327252517766986398776187358029812463847907675610; + uint256 constant IC62y = 843028173085863976591548286083503526126799553429854908040003115547529382055; + + uint256 constant IC63x = 2305356977905353068532348127807280458408372305687029871425764875582080747207; + uint256 constant IC63y = 11369807553091069259993055000449612405152154303288384321485662380454736384661; + + uint256 constant IC64x = 5893655752232338928880238258827141723569138756601823772221555929721274837767; + uint256 constant IC64y = 762627208092203787014413477906318870348178681190360427769983760118925140877; + + uint256 constant IC65x = 7647050923225457883297743290621393989245647154580932694210685595827869846975; + uint256 constant IC65y = 6430806084903190813114000641169996717167510218721465751246980030700445398359; + + uint256 constant IC66x = 10705759571794772559379223851331014817700674885465595035867220237046106842609; + uint256 constant IC66y = 7575242100365466110879455572056523744009175131712325621201550128707014694573; + + uint256 constant IC67x = 19335371568205325600215177798281256377744361599419598912087908330327748044026; + uint256 constant IC67y = 18744946889655449235399670789159468543539893777461000723720969641977783074229; + + uint256 constant IC68x = 9767942356930193944620098079884247644024369691632397734905144035492042213721; + uint256 constant IC68y = 11085556109902571980824189630955599575123617802526024300718206179448320548625; + + uint256 constant IC69x = 13561415355142249310381619037303986562854893588893292551203587367077511859228; + uint256 constant IC69y = 1464204294678453347403309758878730755684248437324144097986974213671657291740; + + uint256 constant IC70x = 2978997668350654766587871166804311940266365978582703006605099063381084149576; + uint256 constant IC70y = 4691523802837523050382298118755178847780158086994967423520861950486681484572; + + uint256 constant IC71x = 13787610941587889897421513807604767014830351081556468843341653766152135431648; + uint256 constant IC71y = 799692903698551254826261186128856317901438765767986583443960026939465662552; + + uint256 constant IC72x = 5657017403698293692969857796776966712277738573977778673163309275184923732657; + uint256 constant IC72y = 13494088133970364611964768081664124413588123681546171311645509845722766195409; + + uint256 constant IC73x = 15024370789171219079614745803857855731467108973725111688470085615714055290512; + uint256 constant IC73y = 5751357237078772693350680556024857842294310641081411422830969005029413202669; + + uint256 constant IC74x = 7767473419872803360280996619556374816181543250685563965702004358978764765995; + uint256 constant IC74y = 15787806098561035204238058185216611790078178948682839778120573240231960752797; + + uint256 constant IC75x = 20801429324948292817168863560873473171225815932214644882221971484645218719171; + uint256 constant IC75y = 32314334472142699140647959677929936627127548500320734326413014995862964849; // Memory data @@ -224,7 +278,7 @@ contract Groth16Verifier_AnonEncNullifierKycBatch { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[57] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[75] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -382,6 +436,42 @@ contract Groth16Verifier_AnonEncNullifierKycBatch { g1_mulAccC(_pVk, IC57x, IC57y, calldataload(add(pubSignals, 1792))) + g1_mulAccC(_pVk, IC58x, IC58y, calldataload(add(pubSignals, 1824))) + + g1_mulAccC(_pVk, IC59x, IC59y, calldataload(add(pubSignals, 1856))) + + g1_mulAccC(_pVk, IC60x, IC60y, calldataload(add(pubSignals, 1888))) + + g1_mulAccC(_pVk, IC61x, IC61y, calldataload(add(pubSignals, 1920))) + + g1_mulAccC(_pVk, IC62x, IC62y, calldataload(add(pubSignals, 1952))) + + g1_mulAccC(_pVk, IC63x, IC63y, calldataload(add(pubSignals, 1984))) + + g1_mulAccC(_pVk, IC64x, IC64y, calldataload(add(pubSignals, 2016))) + + g1_mulAccC(_pVk, IC65x, IC65y, calldataload(add(pubSignals, 2048))) + + g1_mulAccC(_pVk, IC66x, IC66y, calldataload(add(pubSignals, 2080))) + + g1_mulAccC(_pVk, IC67x, IC67y, calldataload(add(pubSignals, 2112))) + + g1_mulAccC(_pVk, IC68x, IC68y, calldataload(add(pubSignals, 2144))) + + g1_mulAccC(_pVk, IC69x, IC69y, calldataload(add(pubSignals, 2176))) + + g1_mulAccC(_pVk, IC70x, IC70y, calldataload(add(pubSignals, 2208))) + + g1_mulAccC(_pVk, IC71x, IC71y, calldataload(add(pubSignals, 2240))) + + g1_mulAccC(_pVk, IC72x, IC72y, calldataload(add(pubSignals, 2272))) + + g1_mulAccC(_pVk, IC73x, IC73y, calldataload(add(pubSignals, 2304))) + + g1_mulAccC(_pVk, IC74x, IC74y, calldataload(add(pubSignals, 2336))) + + g1_mulAccC(_pVk, IC75x, IC75y, calldataload(add(pubSignals, 2368))) + // -A mstore(_pPairing, calldataload(pA)) @@ -551,6 +641,42 @@ contract Groth16Verifier_AnonEncNullifierKycBatch { checkField(calldataload(add(_pubSignals, 1824))) + checkField(calldataload(add(_pubSignals, 1856))) + + checkField(calldataload(add(_pubSignals, 1888))) + + checkField(calldataload(add(_pubSignals, 1920))) + + checkField(calldataload(add(_pubSignals, 1952))) + + checkField(calldataload(add(_pubSignals, 1984))) + + checkField(calldataload(add(_pubSignals, 2016))) + + checkField(calldataload(add(_pubSignals, 2048))) + + checkField(calldataload(add(_pubSignals, 2080))) + + checkField(calldataload(add(_pubSignals, 2112))) + + checkField(calldataload(add(_pubSignals, 2144))) + + checkField(calldataload(add(_pubSignals, 2176))) + + checkField(calldataload(add(_pubSignals, 2208))) + + checkField(calldataload(add(_pubSignals, 2240))) + + checkField(calldataload(add(_pubSignals, 2272))) + + checkField(calldataload(add(_pubSignals, 2304))) + + checkField(calldataload(add(_pubSignals, 2336))) + + checkField(calldataload(add(_pubSignals, 2368))) + + checkField(calldataload(add(_pubSignals, 2400))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol index db4a35b..a775c34 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation.sol @@ -43,113 +43,116 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 8571612681709558591409185853049833232841945740979669245942718805770032380418; - uint256 constant IC0y = 4189972351843195639401511415729412827254667296452453166826430868050312666905; + uint256 constant IC0x = 8057537538640622222416842419905762659147748243137900544099061706952707594111; + uint256 constant IC0y = 8731981744072173739134934379536464047347956448625887529218395527245367273442; - uint256 constant IC1x = 4163740772828829266948194278669903507270319410466548340505259749580941875041; - uint256 constant IC1y = 4119446895718161137464133993105876329337486109593397680414165178003511399535; + uint256 constant IC1x = 13250391499801206058752325385748725651438580685948497755705985174286533588176; + uint256 constant IC1y = 17376470924583594134721848963606099909955670274886726224341736312004090778629; - uint256 constant IC2x = 1076665331615643748649917182793093461933091169232882102136380819852321722787; - uint256 constant IC2y = 11284503990410994128723740643198043818221559941282509486314256803757489591946; + uint256 constant IC2x = 4137078207367155783079430878165837975928656616188358222976908119972289100967; + uint256 constant IC2y = 7570425245107981847428823663996045482214847700032537926709137463962373297602; - uint256 constant IC3x = 20720114473613646302534567518924514429086709487011736661545515973142187548453; - uint256 constant IC3y = 17881405175937038896607983645804770283084154449564661605735065995699141192505; + uint256 constant IC3x = 21875113754814476717668388767642541716892288132274022391202777610333680464764; + uint256 constant IC3y = 12358447610442788224082654939901986616533104883915337902865169052070517094957; - uint256 constant IC4x = 5058311354879615329327412393999176658691695524125090568857298819368005651394; - uint256 constant IC4y = 7506574827555802057910760574778092163919955480247054085361894121784002252830; + uint256 constant IC4x = 19543922092817287680456874357828139195532654968788246826589202752488873066566; + uint256 constant IC4y = 3949253493376987346277103901185964169916249223261456862684099340595712357824; - uint256 constant IC5x = 4284934050995860133235888204711867898087349447121328188587245745046901467086; - uint256 constant IC5y = 18042265561341689884529821061557150842299623224487371136883307679833549634472; + uint256 constant IC5x = 18181183110903921590699007561097924430913394008585648794852924143528933317932; + uint256 constant IC5y = 7711997087094892385912414244603757930043066139296400501341180882618675044246; - uint256 constant IC6x = 8436223819170601999808340736212420134796433124838266991859940948334516183700; - uint256 constant IC6y = 965469023392244424047133803910012874468660808661173287907624735824491612338; + uint256 constant IC6x = 7137240539141442440306085053950553675579764927177162142043064175086488616780; + uint256 constant IC6y = 13363847928672326829000387655005462347075172449243251119285639834404359501314; - uint256 constant IC7x = 17588366209171655946560951185513081113173736203853793660486480146448415654591; - uint256 constant IC7y = 1192465391990703989331087184113754948028256726783406259933657503974466671665; + uint256 constant IC7x = 20400880282477659913345317263705469474333828382164139098386218289000985798631; + uint256 constant IC7y = 763738122430876330371552476723707061095772018063988184775433489234424052612; - uint256 constant IC8x = 168966490099400379038975776147802839111482559083939093660476845657869053000; - uint256 constant IC8y = 1234470853915082062457367730786282590549318011417803333419252501540769751197; + uint256 constant IC8x = 4166322176734392072842315361421643372713101222189854399845407462320580945822; + uint256 constant IC8y = 16072436503992646710546099300833223000623825738116507083014812241765619517875; - uint256 constant IC9x = 3709604944634147209334455029878639800199471874775000621752061808394762166395; - uint256 constant IC9y = 9146687878469641700004378116117843217732228553171960469531573926524537911901; + uint256 constant IC9x = 7833725746847772776634744179268022000383759178460763840791500002087723139959; + uint256 constant IC9y = 8720331182270406067524683394619402841532011768113389600538851900450934116244; - uint256 constant IC10x = 12725725961256189035553204906513379120207000192517003228780502858372555519592; - uint256 constant IC10y = 20292338833910734262099065452288541371398942933488897458632976213407533951394; + uint256 constant IC10x = 7280060257745141941819875132568570724442349310306473121796057502123483619837; + uint256 constant IC10y = 6157960360053732092509642253477838513518372592938360299331275658930593155992; - uint256 constant IC11x = 18955639050018384739189429546452452431567306058614310337052018081807684495533; - uint256 constant IC11y = 3304188715918731862810019389584924243200498693827699728455473963148534993495; + uint256 constant IC11x = 4147125947775185370048279958510311467897346628909911162589227793729272699941; + uint256 constant IC11y = 6385255516740552331279616186006407767930976562596172178800449481815679614189; - uint256 constant IC12x = 18175421830211350230098848584803964644934745149377427048998467617030485113172; - uint256 constant IC12y = 14516289575097451038041879045497099667944480990058270446604032532147417160386; + uint256 constant IC12x = 19512803346925299194089641114698441080391067211653901079526218381910339362615; + uint256 constant IC12y = 1077393081416496492374337174355906633090027938414245040846552073346429490004; - uint256 constant IC13x = 20703913633544089237739676885979485067605692382925341307919172314076756892406; - uint256 constant IC13y = 642930538082700406509620387268174629787369194800127820783409323121394077548; + uint256 constant IC13x = 8288309408330054258706642124434496564250798247092038321284502176065274287111; + uint256 constant IC13y = 15774239590024844214954064732913336305140370560987618725127870868208160316000; - uint256 constant IC14x = 5011985779844308735211947324326280728516252153066838956403905029573499193895; - uint256 constant IC14y = 10890146971840553265423526563604361341331666839182598881878766582517239983251; + uint256 constant IC14x = 7763864224858668678007706065940863845505863544445877259652697857428903176596; + uint256 constant IC14y = 18292989255066937731812120268099855796553812277847905572179855877951257017601; - uint256 constant IC15x = 10821352802689599315752371964308636751309190981228103389002201289657631324349; - uint256 constant IC15y = 7196475991672579618238102963540480092819420293201416958700828001607337766762; + uint256 constant IC15x = 20582272086549854424081011194499750419105220032803672952534340036444858290005; + uint256 constant IC15y = 20268844482500338925780686491633355490444398814210728177154239785898937375496; - uint256 constant IC16x = 16200509200921126318540421002813270144204087623594429819464886812910956032273; - uint256 constant IC16y = 12398863974686923220636271491718432049670009085477532893845695959848586110538; + uint256 constant IC16x = 5748393047160856405557773130679523497468090997757160771324565428255710804847; + uint256 constant IC16y = 9464996734470477384083865916038743513254986113834694214831418118029501282513; - uint256 constant IC17x = 3722494493562374096779548613322724174942518073757700482997308659102304388980; - uint256 constant IC17y = 1266037034894012479954726512477114287010783787937671206541425973092739793928; + uint256 constant IC17x = 9246205565618104342527441892676735883227622284119896042327539766513771757202; + uint256 constant IC17y = 7187654057470465243751261967375429066647706637695188481506184754688400552256; - uint256 constant IC18x = 14949633667701557044321074055882819212965657262091409079548889004592979056224; - uint256 constant IC18y = 4896877872529145361529000973306993006588200977028415965890239754111837780610; + uint256 constant IC18x = 10455404062726226538852275103735270618305762523504725899233869182243063857892; + uint256 constant IC18y = 15517918059300133828049839803926827669133981093252379216282186241401266257106; - uint256 constant IC19x = 19600655870806765152484750663334645204399011582493937511443218392447908725013; - uint256 constant IC19y = 17754765216538248708160638759828253274305335189767407100129601709943833446645; + uint256 constant IC19x = 13781805865764836090949734383455291109646254739313063778322202270505178610719; + uint256 constant IC19y = 9002822957910944113691141310480041966388279251077131182922138764866310746713; - uint256 constant IC20x = 20500642209489343563675058328337586996965591983608904858579339496029535993114; - uint256 constant IC20y = 4013612443393979029985464677605180813213756206695459820247058152658294141186; + uint256 constant IC20x = 14629587080912681942215665474406962843231080153632578489134578391948234384917; + uint256 constant IC20y = 21808106686097193916122767901122335566291811157316898737919422793938241016546; - uint256 constant IC21x = 7845584120307877467433491117843293698555121947251554311374427191080399715335; - uint256 constant IC21y = 18711522093316415746857079798828891651730762350856485483697348191660532852948; + uint256 constant IC21x = 15458646090990733073323203799822737864385159154151596332678685424418420425918; + uint256 constant IC21y = 20359449070594312493099965412567742849787647653500202318295353190027762143564; - uint256 constant IC22x = 12527418680107472024559886062863784854086212477370792890464899129756012223359; - uint256 constant IC22y = 14485094404442660396587300748219223593828251711389859449675270566460567859630; + uint256 constant IC22x = 20365589441307811528415601606888599278790688702492960299677322513209526781056; + uint256 constant IC22y = 8605995224572415081065664334094954398042581697973971225355905086529911883496; - uint256 constant IC23x = 2374481620185698836020312696466603934621248128981543987727551892572305009444; - uint256 constant IC23y = 3107640763405757286345011943165042777559207875175588446352412264129435124284; + uint256 constant IC23x = 9773510918620729430022724361175086296911938510940606450766632356578777247687; + uint256 constant IC23y = 18392220924417089279289379557542870300445626974450017375088588516448912432947; - uint256 constant IC24x = 352836510995482130410749321611349182913869955181037073971088654324262657538; - uint256 constant IC24y = 10575715137538690696679961984361209302740638120913882703031704359365094149120; + uint256 constant IC24x = 12394317554620290098380173183959711433787736169529947043524250984119931647901; + uint256 constant IC24y = 5954730513003767902550957708981427941847291659362695245891325167921616407393; - uint256 constant IC25x = 3864900267012451409819388180515893211458404339871060710177620481064569630228; - uint256 constant IC25y = 641317257750219804481626218147534142962247182372429704342221253818145479534; + uint256 constant IC25x = 9344483116155935090722478842314215558341324408206736944158461545892279711092; + uint256 constant IC25y = 15977810123771960746078592838158738183755117702131086632455579237796573683261; - uint256 constant IC26x = 16079626542421778998718365530171073924884753502101679935783606660432640673050; - uint256 constant IC26y = 12610874584620513420871225487222612101246696013526558071069853825308942977472; + uint256 constant IC26x = 21540423779951349572776927011475865857287597230133117454929577622460757864735; + uint256 constant IC26y = 983205674124325573706331337505266116328986466725444047565878194955651523018; - uint256 constant IC27x = 15564183914008527870451816263430121365010910584399326747649241522998927982710; - uint256 constant IC27y = 9310727885966353124231888075067724840862534920133017880046124759395997376119; + uint256 constant IC27x = 3738268915452992697603501468711653590373945891871834180066062737506839529633; + uint256 constant IC27y = 13350967605928813139833286596664924446762134116431553239287290595160461990965; - uint256 constant IC28x = 5858868713515319592309521711701051336825077256643072256184630439606079470243; - uint256 constant IC28y = 21763693642515833043829823082891009326312542712282974539414548933954053972366; + uint256 constant IC28x = 15880715580764459524149770440034460363689191149222477279742596724990156952476; + uint256 constant IC28y = 13920684666632138498656410468121341557706020986822863920213756409596323160523; - uint256 constant IC29x = 2267072142710394267785251333917023575138580220304645280510759865233629259514; - uint256 constant IC29y = 6847574567340777057974207710090179891213211101510895215166536480521144684536; + uint256 constant IC29x = 8741275422291842973138788483122014694985039241198758071551440280432629368411; + uint256 constant IC29y = 2869672824790805893309668534807018825898201984368792567655749361464837748469; - uint256 constant IC30x = 2775387542501250317450085465990653835994847735739342327610585386819314392309; - uint256 constant IC30y = 6496689167510393229055140502702806194342807614260668591022841589821989278326; + uint256 constant IC30x = 10954960864649307953546188158188183555194502885417120292979417202628775017044; + uint256 constant IC30y = 8182360700621865929408839976584474523934429158017169686152062618186891541874; - uint256 constant IC31x = 1720127258124102351023626080697799543086781758010538392575993703209842655123; - uint256 constant IC31y = 11464393770291359854991381353189019086430715171543842295218850565441402138453; + uint256 constant IC31x = 13273218044875262256464456783575476773524247410752443820505518400030695612322; + uint256 constant IC31y = 10387476507610691933717235597861716820258047612961953162690006133386990638; - uint256 constant IC32x = 5775340660326796190718199400618054551012073967006234068471234008078886524131; - uint256 constant IC32y = 11492423277455925604320894185275809923924417874855079451325251044107376402058; + uint256 constant IC32x = 16552876838752962003299213508027232691202796779255527364177740353755993125446; + uint256 constant IC32y = 19357411399326439227805433938647951397066922097652071065227301312334948320287; - uint256 constant IC33x = 1883989236545183396911270005628214060507716233705894981367212667458226321188; - uint256 constant IC33y = 6285132610013107218246782621300082173877300940626476215092030432506329407343; + uint256 constant IC33x = 4128603196778452665350779980852390500008719336175099687613529178840682261522; + uint256 constant IC33y = 11406474965025065501393523817421409021371000580693836259572627358610624875352; - uint256 constant IC34x = 1970835801922583310463821681650902598490412604240847378299403490158878378771; - uint256 constant IC34y = 2645173405599237655242503972801246968260683155764579097820353770413386724954; + uint256 constant IC34x = 4678386423393258668536460102234876985486640647220281736104506526514272827829; + uint256 constant IC34y = 3697705148227107432461547780846151198382979667185773502461490419125913561334; - uint256 constant IC35x = 13002452596664868205033653166611933658513745221555170825882755664006719154849; - uint256 constant IC35y = 19932557513178190957639255543609719543999931993959491177552616421670733371515; + uint256 constant IC35x = 17180456370675229549227047775199150143955525246378786394260153405900240729964; + uint256 constant IC35y = 15567888362324569160588361337798916873071625105048435214001594968701253855975; + + uint256 constant IC36x = 2073635269098804184389993890844562692137535644326662953482800651583784760087; + uint256 constant IC36y = 20671782324713030553032672627143393683592164401889452812172378477284127169433; // Memory data @@ -158,7 +161,7 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[35] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[36] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -272,6 +275,8 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { g1_mulAccC(_pVk, IC35x, IC35y, calldataload(add(pubSignals, 1088))) + g1_mulAccC(_pVk, IC36x, IC36y, calldataload(add(pubSignals, 1120))) + // -A mstore(_pPairing, calldataload(pA)) @@ -397,6 +402,8 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiation { checkField(calldataload(add(_pubSignals, 1120))) + checkField(calldataload(add(_pubSignals, 1152))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol index 5e995c2..d05b101 100644 --- a/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol +++ b/solidity/contracts/lib/verifier_anon_enc_nullifier_non_repudiation_batch.sol @@ -43,374 +43,428 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930; - uint256 constant IC0x = 20398885015768833332435514336964973976263734491391782320221636024367620289115; - uint256 constant IC0y = 8760835549406711390430046441333902733068272568041812008555362565381985990710; + uint256 constant IC0x = 15407706254613279627791016491826810721911491822710963986774622517053132729580; + uint256 constant IC0y = 1805632836214500340391452066737694639765667212578931547617264034020285750701; - uint256 constant IC1x = 15315605634345520221594901833340731648539098476635067124604417401816633098280; - uint256 constant IC1y = 18875481744024803967130877640606367550634507494816655989709080357596788978921; + uint256 constant IC1x = 12821534719138537198532444002554031694030004474448548558174173525308428865380; + uint256 constant IC1y = 16100555060990923582912440517737572880715681619367677996800456420591818921733; - uint256 constant IC2x = 10962558348260500070125706894259971541167145467351319491925539411774900588601; - uint256 constant IC2y = 16601107315381967963398321942565536087855575926769980532500430171288641149706; + uint256 constant IC2x = 19999188985157500333348642492909256262241132348222154142098286302751036485991; + uint256 constant IC2y = 13891016588899628087903018123991554945099531915363993406375122549666510217951; - uint256 constant IC3x = 18475625424065444377526467442879892691346993576926641400252057909354715020520; - uint256 constant IC3y = 5570779199529089240384429665547038107113778168312973926935467604368072144859; + uint256 constant IC3x = 5236501882007261930379213159240153583231904639358516496469680654352096021983; + uint256 constant IC3y = 131286341428586483131745567147778051866154993289664367256654350949133767539; - uint256 constant IC4x = 12003603435929767609640740501741465520898550578391236732459853783209598118503; - uint256 constant IC4y = 21287389848894417757842456521269215543206633036722526542637082684866616725026; + uint256 constant IC4x = 13031379193251564782668249404185952615518652293211055572218896317297428215970; + uint256 constant IC4y = 12531648883473527960684815946038096146009876015680130110552669402090700031581; - uint256 constant IC5x = 16840622873140202158533898138836978466004638442476124140850223791289880425510; - uint256 constant IC5y = 16147374693160502375339099085890249533432723241379457525415914453825601256105; + uint256 constant IC5x = 249517902580972123255235069761820702500099802857788653199373883101297093418; + uint256 constant IC5y = 9426143095754458931148749482110374505683726223561537220065087228245498193973; - uint256 constant IC6x = 10922534285726085349626725286024278545350745500943686555961961430428328170831; - uint256 constant IC6y = 17801907563951581873842206396614430051085862140891239610878751328147139398224; + uint256 constant IC6x = 11937088219557001031554255713808194650716140341315011752561816019037702317615; + uint256 constant IC6y = 11805615638835769807572175661095860213222281476822119066594064069294076054157; - uint256 constant IC7x = 331533077669271837542455354026657408296474159772588569980133360793953588422; - uint256 constant IC7y = 9103463863071197611784166906531332917576254622849362524121180110117456533069; + uint256 constant IC7x = 17107928218354552230086883764820754611904012722216371079972981530875043775026; + uint256 constant IC7y = 6517917040893167283406669540169834797529004319826693163480805089778661455196; - uint256 constant IC8x = 1865270289986565648030272005350494412030737310888662960603725468437583839045; - uint256 constant IC8y = 5168731334140760077585432793223542273657702638524355741528172557608047773243; + uint256 constant IC8x = 5798291948455405435907242488837952165287260462163703490320368057113712302123; + uint256 constant IC8y = 10205294764297064282852736153986442782661866424259137752085772412144786447122; - uint256 constant IC9x = 3277668742872605246896958350495282290039028512536403198566600094820133380601; - uint256 constant IC9y = 11548134866222263490983336323267387497453017563577235428259392653353170740228; + uint256 constant IC9x = 4014558556655174606371455170701418495631481890446457872658440603602755015579; + uint256 constant IC9y = 20544619293311264701925037884007219720008121701687691597221325792413869421084; - uint256 constant IC10x = 20343899097903959164080020030959738138438209828365962870678026736411952444518; - uint256 constant IC10y = 18241230243866061566530568767693990648888177623730544199159541431564688547664; + uint256 constant IC10x = 3248739597529206167395953409996715430225587593822074328553757230035062349795; + uint256 constant IC10y = 1229491527758687700836223775470035145444996954596639784744332401804828652173; - uint256 constant IC11x = 18479080697822444282808646490885520664323704346435449476552304886743787892206; - uint256 constant IC11y = 10139472841380487331908635773929403103370787709096270215815907980023763072383; + uint256 constant IC11x = 1179433201264389394915892323440022502845985551423499877894157310285587356367; + uint256 constant IC11y = 8501780610178354758333534593629181355274671340366635630321679501861963870046; - uint256 constant IC12x = 7375071963957521661574772155015348920375467454004644085503515451387651253868; - uint256 constant IC12y = 680622443357119797312759019286589347494777919660280748745769283268744477767; + uint256 constant IC12x = 1886547226293616231194722783249458694007008452292559371175738927500183510247; + uint256 constant IC12y = 4243078325022536196528838144760686391905899879797844839081675939827674593404; - uint256 constant IC13x = 20928512346024599565379862378053010205103529624732469610004212071686003884618; - uint256 constant IC13y = 12777237064601503857474701530361007157755022330838118894288280461077493883234; + uint256 constant IC13x = 15526596102013053188578780494126114643002787046917797102377582267014291979884; + uint256 constant IC13y = 6307823340936967798849511940579136294738726013504647726114030494313201767320; - uint256 constant IC14x = 20215979655021165699740284902466766331879386548705420668698611902993193196821; - uint256 constant IC14y = 5454494944883837327717984330153680614890130807469187939076618039392266803526; + uint256 constant IC14x = 10287600644438239217004517384851276191851535603211592770411503882582277355453; + uint256 constant IC14y = 21499570662186289189446171749048597874766400019882004232191134240798657411226; - uint256 constant IC15x = 16610757470953874686097820386675825645978737617296312820939415523500447671164; - uint256 constant IC15y = 17053198518466695305661450842037763672380967690529864675235198194354739837578; + uint256 constant IC15x = 3251186223766693300299218962708533362507177334856799776007015165586669517083; + uint256 constant IC15y = 3784796813796291130660891296519822807192838576733454833924146845404996693267; - uint256 constant IC16x = 7021622070573750596885766617388283553956890610541052396513288850367448110100; - uint256 constant IC16y = 6114392586859271235645114839938047171434877615814594170864572178977383372407; + uint256 constant IC16x = 16232766572809801789996521705720401414844622718865943280711266125212021390191; + uint256 constant IC16y = 14425938319993047445177828726253282147105523112226178463589576156607186094540; - uint256 constant IC17x = 18459359463196906750101803805134866382360201461188304774448611358995256596840; - uint256 constant IC17y = 14007625778685852933723465741181309355968565910753244359577777672045616277137; + uint256 constant IC17x = 227448070636782533749647699362537326234540830600718996912672017483052082849; + uint256 constant IC17y = 16086554678300571817490880823984442321673838928170999432192264807044853771523; - uint256 constant IC18x = 7330613818141406804940328879539668161285542141708646544472883265275803137368; - uint256 constant IC18y = 19570907243334664960642666427068124823092150141493731223283710915189363126832; + uint256 constant IC18x = 1098785026163464313115296136568636342300991168472127878722425967083579049779; + uint256 constant IC18y = 8934065560999496407110211865989324782568549827960988936272412983847535600007; - uint256 constant IC19x = 9530892759024679222091985804368326262171718592635243454567293130557251969047; - uint256 constant IC19y = 20263638443330181950631894972447101639689486260265734291214084508704827866548; + uint256 constant IC19x = 8449962214686142098447255675266537307102897417165010963018753312356433151519; + uint256 constant IC19y = 16847643894847044436780431908053692384738761292088775826166172335149945156467; - uint256 constant IC20x = 21492153821525822904803526861240598727441310215107218029376265013963147676489; - uint256 constant IC20y = 502594198159436453726935618971082597142287309989906794190341784921422339916; + uint256 constant IC20x = 16611921344561802252512793867040260036328287730898518225127913816929835358157; + uint256 constant IC20y = 2944782103190540833124940138754333763337915004706612569400516681215464794556; - uint256 constant IC21x = 15798655019826890172280994249307099268633685893387868522071914098840618980746; - uint256 constant IC21y = 9865580643218739852550182537841554506407534691779093345251461358765368533081; + uint256 constant IC21x = 2857961995890891935415531299289810584269122984274092736632659806388833379636; + uint256 constant IC21y = 20812076525663693852466851920614360144594079854043603101952719763138044133537; - uint256 constant IC22x = 9262644737694534244503575499632833741011259499675081222582659620091148766369; - uint256 constant IC22y = 17829158260856649086040752926832563690987995169338414680915643143753365451485; + uint256 constant IC22x = 10387899103619476234215870784997482771049554291834713916735854282581156831661; + uint256 constant IC22y = 18909604894580378193662673417766001433158531992273944493373545963648836256986; - uint256 constant IC23x = 767427525167412798768462408347891975741696251882921471679209788902053962065; - uint256 constant IC23y = 9360321964248771008965379121408795049906860133653177877513370550553860602359; + uint256 constant IC23x = 14171866277822649091228875399480716425712926779189170236391216676837631003623; + uint256 constant IC23y = 3006848157104397261749762658887413480779144031776291946585164452121401053531; - uint256 constant IC24x = 7786254248901535368236062985935014246141906126091291758303070830619809790455; - uint256 constant IC24y = 15025602502360337407211193978486991033023302472472303105205348826550862766378; + uint256 constant IC24x = 9554826779955855752182295090899329700655153913328303724586325059007468628018; + uint256 constant IC24y = 20680421401456007598605190734984928820121287554513287764730175173611417980976; - uint256 constant IC25x = 20376814909736590102689274175464771739519361897508968663857399939939467761746; - uint256 constant IC25y = 18340559477147122569467996779410760395165001230806178247110494310289841720537; + uint256 constant IC25x = 14248468415818985282101875475954004469697830653279664022614431906874655572538; + uint256 constant IC25y = 15889355508039628384908751256270892760423555538201377140807260770490817502996; - uint256 constant IC26x = 17800994066466363067198961919801915552853100965461744930922160641034176453079; - uint256 constant IC26y = 11918718588660896453075495143576186269549924286348704983691507495540561352019; + uint256 constant IC26x = 14503308583214801290231844165147101322811597353588628912814019648159353232027; + uint256 constant IC26y = 9724832390816706957630238414163133055489954147012987092310178158791392489073; - uint256 constant IC27x = 10495844589130271445411795532350212687148206439414758058425774817980091558078; - uint256 constant IC27y = 3494978241826843004186765681928340113056098318445349482707900888809525865171; + uint256 constant IC27x = 2705549009712213691354836535780104845596544975608667966534212190398401892432; + uint256 constant IC27y = 6334243706534311354143209779623449521307658546037901891006457947026865698020; - uint256 constant IC28x = 20329221239610639460850266826770122360410480669429683437161438632801452984688; - uint256 constant IC28y = 13325118939278722300248798703713461390907142887100386207394332404509360818229; + uint256 constant IC28x = 8680521766903470202982970326981314216175568153032256834507063147873851128898; + uint256 constant IC28y = 3986228740055977117612698547676444019283893411172053476175786095819813951489; - uint256 constant IC29x = 12897465742634214723211721847980238099991600737191512918883180628333622743554; - uint256 constant IC29y = 13304925469466439321898247029253073765192398716030503013714107143636603607906; + uint256 constant IC29x = 13522231082689348428734389394105363320664835431888709221295418385906362669533; + uint256 constant IC29y = 7350576050668915672910966635738671447138155995362753319202585186026321131302; - uint256 constant IC30x = 3728130262415523090729235919946974586185137970063359588939872286876625136493; - uint256 constant IC30y = 14771688134121403834335967763740512078191577317706752331343549579035385958709; + uint256 constant IC30x = 18079856292099446690604233476290595813176647548649981586108068661128790769516; + uint256 constant IC30y = 13401228843567200093774989793764941657532140859355659314450441860375892663821; - uint256 constant IC31x = 309463102665483487525623430433722736802876355256461289138906293824541435851; - uint256 constant IC31y = 15440284034320752324934879788863035779438696415839435144159725677942059358772; + uint256 constant IC31x = 20437594559922333631699503278047484925495166635102871592527880011498729673339; + uint256 constant IC31y = 7238820582593090684569422620766942163514101134141727932245457407177640406446; - uint256 constant IC32x = 14874627100849713195956866716712422130773012822921712980126817380305557112989; - uint256 constant IC32y = 6034198970906453277502921605205656989195513861047377686972535256526728977522; + uint256 constant IC32x = 4995726310820629443186257045209610627474441399190479186932496742751516237931; + uint256 constant IC32y = 13594647265153279736529389786832847856441067627186593841560225552068363017902; - uint256 constant IC33x = 11107672369575925651481862387260117983088123111549845873405637302180349800279; - uint256 constant IC33y = 10568297561768518170888258393353730530385221216950201609602973790908216086946; + uint256 constant IC33x = 16836983824885519253485048503511430534371663143076029530303087066949020215811; + uint256 constant IC33y = 4636170333813342107103560388064993572893588029404194683145661661160673930454; - uint256 constant IC34x = 14684299057059841495037682570704680406383086174803782260386407359432100599538; - uint256 constant IC34y = 11152062318265802473168635756972384550160042515815736512929853653838105751730; + uint256 constant IC34x = 13933307545003680242930668215676045339127653861280698067207962155270409542985; + uint256 constant IC34y = 9003414234427310136062415607240565538629402513544180912547734540203945866480; - uint256 constant IC35x = 7964669613018186154282201873005697772570493436392438832158420656550699705808; - uint256 constant IC35y = 8480007516003872225998687925542992424280369876779625586268945610144785079322; + uint256 constant IC35x = 7245717542010326173968802477651445570898290038897805371044903742143821043547; + uint256 constant IC35y = 2065626563632180857996597593695612627640477364807181866222125453835183573368; - uint256 constant IC36x = 6102388244357299192279272514989765096421054021486426720861254445375136730529; - uint256 constant IC36y = 10223341738771326597029397231819264615059470907930257959851418535961979794756; + uint256 constant IC36x = 12442072207857591741961040417591631023963566326743600910376192360566024567553; + uint256 constant IC36y = 15595673500569791404379118652853652653796796652784503945271245125688526192092; - uint256 constant IC37x = 17747724122258681544307894859161096131187042240812342374675413662284777650570; - uint256 constant IC37y = 9447921843955672491730801571768397553100060711565611665491792741322826455925; + uint256 constant IC37x = 7763185648976943187823768946366339035722421324185050721445533926990616786901; + uint256 constant IC37y = 11948342688520596764409482868423198758187634222544732191984628622416776629512; - uint256 constant IC38x = 15062075394349200592236768533299480001698270034045492855202484126445527440549; - uint256 constant IC38y = 10551599627884253506095842408377009135339550400712051052819390120807480633210; + uint256 constant IC38x = 20334660401602223280165892495074755252042394630980037818462985719424221236377; + uint256 constant IC38y = 13729492476192326869572718974650262398629575450063826498069969398621443528369; - uint256 constant IC39x = 12937767602608237309886455850812184365660472931012933355472185679573920403960; - uint256 constant IC39y = 11305859327137032518104088758884657978321977050757439060524401986102535072004; + uint256 constant IC39x = 20447828951902422560956283459421116771914923336835151014851775639610225008076; + uint256 constant IC39y = 7648443527736451807930755436590563217566850730301036564771896838104615408184; - uint256 constant IC40x = 17668443563673170817501275247756556708079215453545562843435748809974423374346; - uint256 constant IC40y = 2843872391810990764590040691676990430604204150851713296832900760269287518493; + uint256 constant IC40x = 11291767081610629786843809417519203599371224381339214617802519773377062256507; + uint256 constant IC40y = 1017314710713164063631855642844781527849804649822817029641217915294101871683; - uint256 constant IC41x = 19553727569336049429702749034388746833696332407432999799759564373100272997289; - uint256 constant IC41y = 17032647689065532199532540988676372158592678082588157891042419506069001886629; + uint256 constant IC41x = 20686515513462127782380402279537195800991865490761941280798070331875191362991; + uint256 constant IC41y = 13619820263004096948708855548475007387893496734752550056458068193542545510378; - uint256 constant IC42x = 2349635590953727423709115709996069823504303147307363034594360091576405952712; - uint256 constant IC42y = 13255393805788349816156400329463530615674950275071273844021785362378501004281; + uint256 constant IC42x = 11082132592845356030118676224360424049306438693381434182946322816869038679346; + uint256 constant IC42y = 3852032638638706636303480795638113484675090912580591385855086556715158066333; - uint256 constant IC43x = 10463480754130576697791130727443494084540016352062602974070496625567587892565; - uint256 constant IC43y = 18543645871837613080027348925092308461821718045592455286844010480845348759262; + uint256 constant IC43x = 8592486674919551797992537313463612050516345382458619728349753653180531140052; + uint256 constant IC43y = 17368081079279826965185067183138322261198582010758690745593971066482206778626; - uint256 constant IC44x = 11996999816349738680220525310668603227864827674371652229824392630530737583342; - uint256 constant IC44y = 17865503555717365419519222221024480322333563857329265182112769876182032214530; + uint256 constant IC44x = 7990215583610635227940148928563434514056880379617871103100183076055946921572; + uint256 constant IC44y = 12067404451024785117620409767989978227195190448931140404614214854154363210329; - uint256 constant IC45x = 17193880719441273727465191787759906853486350795279041567426093472724046631896; - uint256 constant IC45y = 8985280251072798544313868273369385731936693130413049932085493298595530801545; + uint256 constant IC45x = 331152549542508101446600814178970174858846094298076424095654770282505407956; + uint256 constant IC45y = 12641750796398203736222237801218421097149331729614444870332376985716231065669; - uint256 constant IC46x = 16635452308494234540633769759681205422951522409715430713777868483340786024882; - uint256 constant IC46y = 6165308805029156236792599522159803176528318280471374837336234743447882968769; + uint256 constant IC46x = 1498480962422330154194482504998698557152143880836176710140245895934090175347; + uint256 constant IC46y = 7375318566747138116843509666074022704205708232292326726479880537906062973203; - uint256 constant IC47x = 14565893495171737824116524285337183041814427128057848332677147039409097384682; - uint256 constant IC47y = 19191914404607103062990820459205468505828216116787224625928653527748944893771; + uint256 constant IC47x = 1699314611170335354077102139467765822473061880960779851439518756812580998095; + uint256 constant IC47y = 8883302754501885396422087411001660033138099347421313735547896958735503590723; - uint256 constant IC48x = 15030285227261627804208167134759630375118046716022522883678922697079571336509; - uint256 constant IC48y = 7503443151884068092801908553949616060548585322227005946712480043150525602756; + uint256 constant IC48x = 4597821992052683266178547522089040143364154085336019103667611022826948192111; + uint256 constant IC48y = 10052013625748875046129016861558387048018250521504914100315007951178019650155; - uint256 constant IC49x = 2890175944366323604069005554180620856445075185687866766556862475537913733035; - uint256 constant IC49y = 21402420557796229817923793018565970959405396000319224601736428615482893082396; + uint256 constant IC49x = 14180682672068515148379034742692823048197897764415305618509529666281020735612; + uint256 constant IC49y = 14567856836016314260137139431939640762794082483451763043398797126659368527376; - uint256 constant IC50x = 6446914869243532867752832288063700479888013956768941059009832724315725474770; - uint256 constant IC50y = 14652836518560420905054215443772041046326481461713988259420995897791772027335; + uint256 constant IC50x = 15584723159734470807937598899985473701200472162133379764364909143224058961950; + uint256 constant IC50y = 8927690493037339142419340798814988298583779097758697171785161664860574122101; - uint256 constant IC51x = 20041054044922899471372214960784727126767141441682485381267343533007187189700; - uint256 constant IC51y = 5526007658621064711850808319114366455442657479327278550827782768153697644654; + uint256 constant IC51x = 16802647937613012869135987269776094089928220285561442016443185735676763831431; + uint256 constant IC51y = 2959984124316433004010775131546641339187169868263900891474654058771118182013; - uint256 constant IC52x = 19150639418559678633621673271005536488825394733429832397648005054576424091014; - uint256 constant IC52y = 13984556545715703169646102729022380397336382782894007865612905771831095295296; + uint256 constant IC52x = 8688884723408400714438530601405778789869090183121779311639634453295927139564; + uint256 constant IC52y = 6325160675508654190517072826471506275901269930305473410670203624176980158054; - uint256 constant IC53x = 7157675053183322685547346667769945432615647738230118724652857748596189223290; - uint256 constant IC53y = 11406818468931995926497158430724140943351284270578137825740925365572254319833; + uint256 constant IC53x = 16576828376530775578207635573112218973235379366403877355848325378179553039666; + uint256 constant IC53y = 17426417469708747921716925286746435573354665667581481189893469966167221582394; - uint256 constant IC54x = 13413395589113329435069363794257051770588243749397133025194455389776552832266; - uint256 constant IC54y = 18233492425162685277447440590422870943915646330630395570277383458526028719702; + uint256 constant IC54x = 16081827276790159159732749776812035810935540329268854126244314800438781840368; + uint256 constant IC54y = 7812724939235873854013496471063123157022325024551555231583197131290209710549; - uint256 constant IC55x = 11952969371705892508039078595347162569714637318342951353674798196734068921335; - uint256 constant IC55y = 17072403296706399069822100288172183781186939920866427122577444670244961508596; + uint256 constant IC55x = 6635015586786669482614868296521793858291003501632293979650938657797054792438; + uint256 constant IC55y = 17643442048413475002015321165159206215034963517308660412573199295916300352564; - uint256 constant IC56x = 2118693461836778808738007872772687490056511524520363073731001411247110829293; - uint256 constant IC56y = 2930578182584430387349990034734645194355190762303962197681784927324157767427; + uint256 constant IC56x = 18410666348864717924684660607353802212414212240675016236745153976826795158534; + uint256 constant IC56y = 16665540827826014763952889794731175615983429706120681200953050146218940613267; - uint256 constant IC57x = 9850888974164836644806074613473914979118549706918015407591606605920957510385; - uint256 constant IC57y = 18510923419022297133210506403756827855224768858039616569110963137973036074293; + uint256 constant IC57x = 5920722363524444529293189167692533582967270176772682973927036601166873767019; + uint256 constant IC57y = 12726510624057778298917200831045081316026187420438714360562711479492785797875; - uint256 constant IC58x = 7680502953712527585452810373510828175981522566334906875774440006428086663061; - uint256 constant IC58y = 9984402657382852559233618398572701968495333370527250809744332096495402817906; + uint256 constant IC58x = 949880545125243211431720661583012725139476704863071313764024918842183271602; + uint256 constant IC58y = 1640340577396708183394177743170255997733743356690258368447299163675137137371; - uint256 constant IC59x = 9971952665103757705290396101836783610733947621587296689840942397746954948178; - uint256 constant IC59y = 6171933113084897041853553717861240724524487414429421887412843104784536822729; + uint256 constant IC59x = 699245505582035840275049804849672340519960532217770210336903508529550846106; + uint256 constant IC59y = 4110041707706528628934051098067865830442124409963667440145922891236630934011; - uint256 constant IC60x = 1894970037721544823266180756477097282078493985171782117701139712260687171349; - uint256 constant IC60y = 20802443255406523093685514560897575533065136634058648762686198863412788235051; + uint256 constant IC60x = 2705182811466159932332775985912264407703014202620937803123219374572175498211; + uint256 constant IC60y = 7024678763647961948952777864271839760087426108115916279336571461469207720971; - uint256 constant IC61x = 14647611976255331732189909477071956053401253876621377232295105124828449894550; - uint256 constant IC61y = 10612760931337654003207678809383480625135298470454874458848689207733841513901; + uint256 constant IC61x = 13790485501716369250157760211795061409798725104058416201785092729106555718243; + uint256 constant IC61y = 2995643192333485031905552629231284354663864285455365332909954202938615441027; - uint256 constant IC62x = 15486999347499633100408424234852699928663420526783822219457642399335370261191; - uint256 constant IC62y = 17624028074589110683344988184041764656070639524071735597826456305834513408575; + uint256 constant IC62x = 7716654327876148805119168131535509088331150093732510803545121911674899176498; + uint256 constant IC62y = 2572737393963915423011100364189296650235201956349393326391451289668374800033; - uint256 constant IC63x = 21603968141203809804733464426223218723145308921390735902862374430796163893437; - uint256 constant IC63y = 12685866074688517416706851433860046151609411429249614319934028211656779093722; + uint256 constant IC63x = 9407416070002568181666901587549581630332317899462941999491333142881354898169; + uint256 constant IC63y = 14716863487109498867717057746375312523424193196878342957788984971250167017195; - uint256 constant IC64x = 1046122314972882606184113090452035669584193225454910874960181096914198073826; - uint256 constant IC64y = 4522039592034110691270673792892435417553608490889054520542290139228754848801; + uint256 constant IC64x = 5410133880611549651484374624648278701455321188167345926986929640633916634836; + uint256 constant IC64y = 20049942290726496994351362695781233784070155164971513699614354999530286173893; - uint256 constant IC65x = 13035371595510200987803597311671910559224293626060011302128581137178967290243; - uint256 constant IC65y = 18830037631194349191542716841718817355162930256730764640626960726748372847218; + uint256 constant IC65x = 3694405469587082926069409639491395449303254998893257144810332300242055754316; + uint256 constant IC65y = 4879420170591203929223396928858788719604718675892556258083339166142522833375; - uint256 constant IC66x = 11950442787460356177621351254827857533412939982736316190878754664098050765208; - uint256 constant IC66y = 16150201220852844581384356336547863968702182834518676827175830177434863814501; + uint256 constant IC66x = 8360390425846388958015016195243553131251532358540210799224862175209839729424; + uint256 constant IC66y = 686432576563840905057595122938954184796118258331648415325778684272628461415; - uint256 constant IC67x = 20758523767849643456314396275456680240452060960515409885132834869350530289798; - uint256 constant IC67y = 9180668518849076532950714593995434318394487105716270941016212649899242171112; + uint256 constant IC67x = 17546712108346834046687798395256418981879288843417367084767005731206147165845; + uint256 constant IC67y = 11065550600176509275676561557678278169671776819078585297018556158427201729595; - uint256 constant IC68x = 5239278122882626846000034818719607483588013591008859718576594969685784951529; - uint256 constant IC68y = 16306375534893717492693980667466940162734803891429931218929779024470110752159; + uint256 constant IC68x = 8196937164584612656880245959291145383233679955144017204949411491384153671818; + uint256 constant IC68y = 1020372992935935946592852736837981861311112416190186944438070878025720756829; - uint256 constant IC69x = 60040486841753522275129553244986521720979211457807828932951905425041640787; - uint256 constant IC69y = 9013885853500799266613282362724270334971361901923177194953249026990006689605; + uint256 constant IC69x = 11945396313078737667120892972727312433076198146705479957352094013019420951318; + uint256 constant IC69y = 11257566793363205159497746101963616634985726781591427565068900231082481179730; - uint256 constant IC70x = 3520249371201081358738325450683322011291109901952732241702333015561336288161; - uint256 constant IC70y = 18571821682640518866100332525102940846461499834568262264437879828385375105108; + uint256 constant IC70x = 11906205291684963950565201972041617205340760485520122734668268607813851969378; + uint256 constant IC70y = 13335015831610998205156766490589806904153942776847254076149073899432112381514; - uint256 constant IC71x = 14313639399800139199585954736173381872520673739030820800682032934005717684144; - uint256 constant IC71y = 3873738781990898520371107288664303859758528408013610044232401063651557203496; + uint256 constant IC71x = 20473233196264729824827172523385152947690197688257169336321375995408103340875; + uint256 constant IC71y = 4171705257480291306230221203348860100765286134719914625726005060241075821038; - uint256 constant IC72x = 3588438931500741098390661182906071821897973231262009720141137513211007473808; - uint256 constant IC72y = 11445567214009722347895826509290373622016848620807880454187293786604118285973; + uint256 constant IC72x = 7927559128611977488888733234677814187738627927545658521089220012077828238252; + uint256 constant IC72y = 2654337640081594334009687272578726061098996848154156332928103044732728630558; - uint256 constant IC73x = 2341663678515785718688583881989080576799426214321970054342598530455026540090; - uint256 constant IC73y = 10898551623756196270043548498605764990771251725313522289028629126229406564514; + uint256 constant IC73x = 18213641457184771072621725540817750638796965373623944522312479542616850196885; + uint256 constant IC73y = 6016435997518949372065807347692413703805573818812039706705594161480956218284; - uint256 constant IC74x = 10684014331978661435946478567030472039294264967610460884326767352769522133123; - uint256 constant IC74y = 854119106587083427067980557942817732138886457716725083548902802354969929358; + uint256 constant IC74x = 18765451601960566573885826872535316693691062874593714576833802280528202760570; + uint256 constant IC74y = 8412765659911324528241150769045867186804092393728614078430339867215879598598; - uint256 constant IC75x = 13497339556002563926467246166377386456466739950114835902554508186662442134551; - uint256 constant IC75y = 12753106675892979423891727974145445633321357154954055195984227422417556508959; + uint256 constant IC75x = 477834198854576804681288566640320704494271023478665554723150809089682439181; + uint256 constant IC75y = 13341324182469669357205635889278915727066193338415311008139523525991803372698; - uint256 constant IC76x = 7774835372381558796423729580947043830702308268025754626584332156703610750503; - uint256 constant IC76y = 14203298106327530218806048813273065303839358433340231490525185945170851807940; + uint256 constant IC76x = 3470731540357564685302187305676581033791995282421733055521780483325592957775; + uint256 constant IC76y = 15133078636183988596683956496231206030568424634123523621437806148322650539688; - uint256 constant IC77x = 19545759579126933165965793934664009550429674048412263363091454659028184179658; - uint256 constant IC77y = 11302797849180179875243350965470533075771601838768468782249102284526348187133; + uint256 constant IC77x = 15205063991798645201886131812913990541963857761186766038920538282961374822621; + uint256 constant IC77y = 11767817589991381410467932798155911131009662924443858651013859566799210108201; - uint256 constant IC78x = 14193464378621339496604009848895004408369571339181960046782090752306882241961; - uint256 constant IC78y = 6484449968910059532146867780125026231176630832791850308953414492952771635499; + uint256 constant IC78x = 6561239745020770761089536274114876851684455122702320104109965183140077354889; + uint256 constant IC78y = 9990696516807444304488408551606266283579296839818008500154230465124248726507; - uint256 constant IC79x = 17305463374036637081854536292140592306238729820744197923450769615349158588525; - uint256 constant IC79y = 2366947258804585636412792570360953242716933294696498476165980179964806807801; + uint256 constant IC79x = 11724772851116968656297355417505544057267832442410682874367962967319856489533; + uint256 constant IC79y = 3906533012469190973492042387546107187908437520975805631652585869464302231640; - uint256 constant IC80x = 11644588760990236876974912094327482731330759171085779877760966244660949932674; - uint256 constant IC80y = 16717001929129944897228127170201919488207427269569562624299499922450998064837; + uint256 constant IC80x = 7930541695362534289848062679470531395525395444584893125940218010560306501994; + uint256 constant IC80y = 13994814195450228565908232524112302783098434904473751223637429708525484103450; - uint256 constant IC81x = 724082024714563899320516369116997202804668922001066953873870802079656345689; - uint256 constant IC81y = 17557960635497551802288681184045596103944099446986078832471651543412766732744; + uint256 constant IC81x = 13132179635176614943968573869338385200594963389326875117628532839205458949138; + uint256 constant IC81y = 405548391191859965971006213498623577007469961396117239795449564899339224768; - uint256 constant IC82x = 6596352912146189908988099882899119672498806752388198673623080609786281259610; - uint256 constant IC82y = 18035500837389320080377905012757992412314398206362531451239286617622311925437; + uint256 constant IC82x = 18667040248825667322713274856616232236396643635828722195556118251106315217435; + uint256 constant IC82y = 4603728992719232705063317217811897381883138936799140105215877308008515347198; - uint256 constant IC83x = 16631660089292596437929735643986247934416470401628156900784389015699713002; - uint256 constant IC83y = 2635767000339984531883587499098961427757077068630087973741805051230224013392; + uint256 constant IC83x = 21113841097871004552415432135112579100333737090031424470211426083680842037682; + uint256 constant IC83y = 11931228233790432310950702243526185546787413458302844954735600713209049772488; - uint256 constant IC84x = 5876327941930077445025148929177089211360275962634597911047042806290892764074; - uint256 constant IC84y = 17938531246750806242276832784966088783463732575152171627376559096461846521088; + uint256 constant IC84x = 20114569317044702934026106981607723616609679970446227822214346521849281128186; + uint256 constant IC84y = 21621494457908024140606326407206486803323810035268576975615378819790844920191; - uint256 constant IC85x = 21312636100772271594592644523541307710683074761727366815747826021298291888468; - uint256 constant IC85y = 7421436386901827459832792092825762488783821819857689719337910400123529566738; + uint256 constant IC85x = 19036807926154831789555703695655139289001578955130984018835662024770977951980; + uint256 constant IC85y = 16521655433252014319058134055817412719334766298330632814017430666750884031681; - uint256 constant IC86x = 13215324987321691031772609770563399056688470467435168488147082075626816153868; - uint256 constant IC86y = 14888837507923092258863896708522213041360152502546481231183073367563873350073; + uint256 constant IC86x = 14975807860548230879425938928494255779742665726259393646292585729962569213394; + uint256 constant IC86y = 3293392971518938712944872948582396020623815270030676237104088138536694006356; - uint256 constant IC87x = 6782458554677592896601343428120296606105347911152463672066686092290133219042; - uint256 constant IC87y = 6610194029049829155534400706154149450122421296213161328612992820424687757671; + uint256 constant IC87x = 636254275621362488806461458158925004919531848164193097829706325052968892408; + uint256 constant IC87y = 14222623693884840942910339628909969797623785105744454962598987243531118552214; - uint256 constant IC88x = 5229346161475995291620655532880773970638849301439085610332183730863383189456; - uint256 constant IC88y = 19547951565566988874761384832662443890458326819107923315751591820484906706305; + uint256 constant IC88x = 5890422223290371593959727357893967642654478725736641894870776568957968813430; + uint256 constant IC88y = 21763182775884637385153192839510884543136494408827382473284648200777342914129; - uint256 constant IC89x = 3659964792835045678035508292792194934195590139072531185393672834896972186298; - uint256 constant IC89y = 21226437955494237076797331447188110291792274150511615595634742162397809255516; + uint256 constant IC89x = 7149194864365943026646684614241643351450211998335008872277371189396920908713; + uint256 constant IC89y = 4580655496815552590239466464458221040695177187293168332385065282674733336824; - uint256 constant IC90x = 7771763540920451739810673751513397443683328223505186604456359287919167842023; - uint256 constant IC90y = 10159880526458521318375792498071543983590609264247748517361447745066616696128; + uint256 constant IC90x = 14928859714169641663917139575906095134887188803281198925263928389359331886076; + uint256 constant IC90y = 16681311850963175904615749014024761249752035128876326676851148564351889437644; - uint256 constant IC91x = 14154795557739663913583616074426332188731595283385202347574073810131906203836; - uint256 constant IC91y = 12203129601625017656197217217372897565151527359848884209093727223778339027517; + uint256 constant IC91x = 3087282391126570501496074164612140603124224844073694276762135769076127738050; + uint256 constant IC91y = 271220548660735571973770638839815415163646466472847004957090701655255121781; - uint256 constant IC92x = 10738399901382872337595176413673752131211701830603878221714501188665324438302; - uint256 constant IC92y = 12493555322610738351393993928785621283529827889399625271093048235841089900259; + uint256 constant IC92x = 5155348108209718270961674829262565193797740669344913416167498226503399293781; + uint256 constant IC92y = 2883229394830858161400871862760335658621173449728571932590939268447809449634; - uint256 constant IC93x = 7408953403999731091117865921461861997684197151241883257811923700543204464115; - uint256 constant IC93y = 9299432411017731167652874257788259203742865296372881847259579313757551571729; + uint256 constant IC93x = 10261682070240546448121694856467158759980201228572458413668058415549500253129; + uint256 constant IC93y = 3517919799935106105157877511074736568451992083466241912117075659975798892418; - uint256 constant IC94x = 18422129420097620042984495498230299182702591843727580921742834550014603326589; - uint256 constant IC94y = 11638705919332427113493318048792048023843627334605525601456271898817463094951; + uint256 constant IC94x = 2410064472025323717743691805237849249774522480824096186849321112235885897013; + uint256 constant IC94y = 16321306342149339358374578893596732909222680458340921419263240886309079645334; - uint256 constant IC95x = 16535211571765963422123382836500396482285512573798137764798822989181389348670; - uint256 constant IC95y = 3241351689099640979899441731138474616249937600462608927226065129179824602380; + uint256 constant IC95x = 21590966021307972227222350759130688631401981807828495769294466938026620029429; + uint256 constant IC95y = 16841965240008941507517066839317685693053720539559792813592873710834759070500; - uint256 constant IC96x = 1727850598356882453627022836371640348562047483926224016665142968335293915822; - uint256 constant IC96y = 8106842976470740257882344828424526205969547206399648341483258455751144028275; + uint256 constant IC96x = 18491895583840762708761752050517224669252808631694959239827406587020502964257; + uint256 constant IC96y = 115262940492933303933465188608928007163132674746813114088629549031028933474; - uint256 constant IC97x = 12663844262536728422821315979850492033719180818687139907133012539392933350973; - uint256 constant IC97y = 16809134972453363483567174132705692712009523723740204436757547122959526755070; + uint256 constant IC97x = 14391265599688161995602335132798044037715409742962564947829361667812883833428; + uint256 constant IC97y = 20518087835005998728140331981530259296120636457989473481690209922306348305147; - uint256 constant IC98x = 17384166984895715671698181113758994947836873247831235044846919308377545500674; - uint256 constant IC98y = 19797124975688696386227645451586729192717684323380345853344637253874967132603; + uint256 constant IC98x = 19715379695935966610097954303842511519077913332519222889244535799019625504639; + uint256 constant IC98y = 13144194099439902353626995097665056345848382663290148134760103562472299082801; - uint256 constant IC99x = 12816715946759916189607838256859758693184109024274030332470102570031171858704; - uint256 constant IC99y = 618298541945036003719359416706890807778853756415874772736926960166064079770; + uint256 constant IC99x = 19158238821784234929970587550167653093608160977355377402371573852274318734534; + uint256 constant IC99y = 13992463370141985697908873354422009457935866505392003486934620987045128615983; - uint256 constant IC100x = 21722247786068135693179998046207808648985563270699045338204192745730542249075; - uint256 constant IC100y = 2350417950627670801454243672678383580162873004151891076124710687108400141992; + uint256 constant IC100x = 14724059706071744161240551034926811662092241991709320704666302965817156737535; + uint256 constant IC100y = 3951876048989504351827578983877721419517152472683909730783076623576700331926; - uint256 constant IC101x = 2876092575883565033612966063909692068659500969369049858221307490982846711892; - uint256 constant IC101y = 4868211217559834253603566981382552580120868560189279766676032742126501662777; + uint256 constant IC101x = 10271629111899795298856960592192368871413049682517937942000637144738988346610; + uint256 constant IC101y = 5443872355812403788849731310041422383281487330190819193651129497334763043412; - uint256 constant IC102x = 9569415055544659251941769126513488266261460571433664749750891184819981816921; - uint256 constant IC102y = 12868474606777886209227239522672271755076420172850556292313699435596683674676; + uint256 constant IC102x = 14151610918439130889093525433923788986710048310741777368395475382304975116266; + uint256 constant IC102y = 20398350377412501738844048371471341463818936057945966683578695213772180372919; - uint256 constant IC103x = 9785900663110466844915708355465930135667834852707627397022625006894351481671; - uint256 constant IC103y = 9086551453940428043262299329847795657792496576406488146051358480500329781760; + uint256 constant IC103x = 18642717901047973669529289674401530907531050223707548461915971771209590821113; + uint256 constant IC103y = 13129457520015824739523618571166267259076486759275727709388508331397073480693; - uint256 constant IC104x = 6260941115529778646412825281709898751434947446735129157556102507460170240029; - uint256 constant IC104y = 2356456736476190395411087805821749720992012609794824936051338838951651697498; + uint256 constant IC104x = 14665381862213039367403088586219392326049164781061419991682254406742344812116; + uint256 constant IC104y = 3595747496964685270867505209015968932372783204585029793809655635046587156437; - uint256 constant IC105x = 9521265334811060218410966757446383466652181342397641281386440036537341499085; - uint256 constant IC105y = 14659317177050397219638748429321689598733551205180840128793153160634171136145; + uint256 constant IC105x = 20892157371514893257645079510112666584365613257389071625290401569726903146447; + uint256 constant IC105y = 2291450820246146155407461522239468892511201569505073158556915849671596571994; - uint256 constant IC106x = 1830754514774508569654278664366356212788487432921519643384550329286850395000; - uint256 constant IC106y = 10480392049184929749668381244172726256850388323835729913980035384224389597382; + uint256 constant IC106x = 3014871886211163829502001911772091435620013348092845567333550456268882381516; + uint256 constant IC106y = 9234423757425192531614338424702867343275932058663022711060076855414857496956; - uint256 constant IC107x = 10673991325341928148292390870528128202274313466717499916473336114919473166085; - uint256 constant IC107y = 16902847351543211064544452734827488073646906000487594690474862344919101986532; + uint256 constant IC107x = 16577724228857263781953137909403905534891837046233589178744877659673557792785; + uint256 constant IC107y = 12508671406519037750854989325853663694723020826305882996181376208118451620143; - uint256 constant IC108x = 18574713766525905062177883606380831732097664201102349391928354083582507270930; - uint256 constant IC108y = 5505789930810008073979884281044068131670720699333040420620096484224516509997; + uint256 constant IC108x = 4150909807989459251480245337138416261342731907867466663344211901714185039746; + uint256 constant IC108y = 2169769775955205020647483529809162143086614391054962410650696544622272956453; - uint256 constant IC109x = 2548243908269881929039331142370024416641479554690096656256752138867757693255; - uint256 constant IC109y = 17794578842823404964499151153794613822047064081114069411496491100702890987233; + uint256 constant IC109x = 3111887453268437204331662130356947182926383335744412582791949440567897507841; + uint256 constant IC109y = 727505704185460892176927249002780726288443574389753381662208302305329644203; - uint256 constant IC110x = 1287028022870692709184376064984894045388167800441810518515127655856771452970; - uint256 constant IC110y = 18146250915770505199665686320854246832911496561575163201498730018329742521022; + uint256 constant IC110x = 4306251710570350649834610818830734576656293268945640534180626575302774193090; + uint256 constant IC110y = 12229026335578421912782929506143561806389622707643350141258969323410043013276; - uint256 constant IC111x = 223266659812834488639938999193058706003180654759361622624879454184571040839; - uint256 constant IC111y = 7921134752372248161422070452965152364328095214127501496567272972415134334507; + uint256 constant IC111x = 10724870606586056255512411866209458420908028386178343525414585255196652435926; + uint256 constant IC111y = 5429265768966467597462329363115840971439438324061440864774070816491772126646; - uint256 constant IC112x = 4986886591168415390208020303901486193511613848311548742792248441562221880572; - uint256 constant IC112y = 398708160860002162876351965806040229208597954841262698538042173456260265388; + uint256 constant IC112x = 3527543037193200901409343494788320343753171735202398297516156782129318607237; + uint256 constant IC112y = 12421887997580427102580555498760056236373788136030208087973515726861526125174; - uint256 constant IC113x = 1972316390133394085415528566709166892855586247526819391605487727021814219036; - uint256 constant IC113y = 21846326779147723547291946346749343908769311219838841832174278087687576381093; + uint256 constant IC113x = 7376630664430451105005470061356514200583901476269219202543930500958558228183; + uint256 constant IC113y = 9645085522175603998941786443086580171286497248825427720299574774617600244088; - uint256 constant IC114x = 11633824032001357766360049915491114803946152033703778975486826406988789361997; - uint256 constant IC114y = 12068277527503880072488338615521060855197750075235560666111746066176276274071; + uint256 constant IC114x = 17338137839635982277991906074653239533155644333219644464761798281431294280269; + uint256 constant IC114y = 6290334265050211472079737607789073489502527164934493911925515663785327431569; - uint256 constant IC115x = 9695549320569501424789762510503704496192792359860202202906838823792202094327; - uint256 constant IC115y = 9555015718426613777599636203511074951660455319087632077629003163798952312269; + uint256 constant IC115x = 2704389566854574058675609155167056191210743070062729676639930090383694578266; + uint256 constant IC115y = 7813676377320242603154277010299246889725917320140677864755622354509157929183; - uint256 constant IC116x = 19359786186218096935146671653840806244176006894885125254756764933849499335249; - uint256 constant IC116y = 2387949876298345492407912880156795197312532823086163057993861484253831187814; + uint256 constant IC116x = 18469559339974281217341024845818313593388425525430363359078671973442474535148; + uint256 constant IC116y = 14689801898811424260521960988741276607192917439354253019525038784384084630226; - uint256 constant IC117x = 8534641047101882977161212463831263024046689722581888033371843611341594576393; - uint256 constant IC117y = 4085733623069074774475876905548194556959671444566312611122290117145938831556; + uint256 constant IC117x = 16402703267539350941323400413560176995694187103047434576119933660058797151600; + uint256 constant IC117y = 2784826682847529525990998098967821698451903232105891120025418617357403364473; - uint256 constant IC118x = 11392183584793611701022770853888419866359434507207446261013060110372778448750; - uint256 constant IC118y = 12039010283391208083623000651344396645738122752565598033556255024269728099686; + uint256 constant IC118x = 969014865944161842084299466003103150689237689706260765037890531357026634931; + uint256 constant IC118y = 6329558406260245201014176166491667018182838496882161888340850941834187106668; - uint256 constant IC119x = 17799233217419218904947249719416254357206668472185292700130295367605789579775; - uint256 constant IC119y = 13357433285894857035918176715028754547770195229276863023502097143080160022945; + uint256 constant IC119x = 16640532691766040187717503481739902297688758891615808780548179293898023187388; + uint256 constant IC119y = 16504776601348750957685246330212640437524940303506152619427941454744698733484; - uint256 constant IC120x = 4920886769503826804793409665884631809047006805062602388421875677124768046721; - uint256 constant IC120y = 18507588985777018307425077806242545993958240881877622815039150778856527681587; + uint256 constant IC120x = 8273162784311594190344081659053045168089584599175196348331832659477720672780; + uint256 constant IC120y = 5821425617963677350702153242908209513238899812649634759387804492457188734196; - uint256 constant IC121x = 6964785589591486238080181833921462796610700077253539345330356770429293030717; - uint256 constant IC121y = 8503635953992332063607539325685434941643852119905312172589719060858125831267; + uint256 constant IC121x = 431906966595776681371029448760864721988551351231193776520393897314576303709; + uint256 constant IC121y = 8702138831021286191962531583052213672845531574809502129829529459553690805358; - uint256 constant IC122x = 8689872876956874390437091630997622342586358922128817789446107383199284524641; - uint256 constant IC122y = 6343146446211206573118957886118759897919995460983539671234308923132170936394; + uint256 constant IC122x = 1410266164306244794305370951529663180823316614384089587942175632959524759905; + uint256 constant IC122y = 14920546026468776515567646597084079553889125991407394164687634040570545756098; + + uint256 constant IC123x = 12309536445851925810513909384510103261515956535668344311747426508204566806310; + uint256 constant IC123y = 13744993004501439515247126391669668450865257149400028875822462285781048886869; + + uint256 constant IC124x = 9415482638707163687932265162796247936570305676530917790590980668624899566787; + uint256 constant IC124y = 21124463989116201422088887527797104494335837104081908864991070154148703837699; + + uint256 constant IC125x = 14918995992655271689867896090772893874032683598951697169263508967975447696547; + uint256 constant IC125y = 7531235987714539211903518886970350691292724847274846213735488737800951921574; + + uint256 constant IC126x = 659764501489444248190099494920370762968605374544632596579303040509347743912; + uint256 constant IC126y = 11803519384877816897709440997701941076555121987247701995039174154470762554824; + + uint256 constant IC127x = 19585672717231500855540802309320362856132177568688663344439189646513832609623; + uint256 constant IC127y = 5150630292675188733803864299768712059177442573837352374775428243831450131264; + + uint256 constant IC128x = 9155422505324942635466936402234093327126640317973196531929960220423081125636; + uint256 constant IC128y = 1132465359520060482465620414384650664369396179863519151911628029399018023233; + + uint256 constant IC129x = 6412067070188191206313576697597954657675545034647020144248694718755324805615; + uint256 constant IC129y = 6386915259274818120083639886119718144099940527126836384693703533190267632761; + + uint256 constant IC130x = 19737628089735963496443090482324415390780715134529916428370509324619707511786; + uint256 constant IC130y = 5077084655026381719341859801241451441731414124235602628635645148448163518119; + + uint256 constant IC131x = 12293127671780104221271565448165814216173136261432126278488950939243790221431; + uint256 constant IC131y = 6642512188247340556620625316942538156592625511551409831964859449475937209961; + + uint256 constant IC132x = 1798043292764608090975672112703630653136215805563370145237014819565458422979; + uint256 constant IC132y = 21687148062363711295925780902503054829890024574067991267573904889220906876600; + + uint256 constant IC133x = 4529392218357174417699147827137281935916947311229652132219119313523580192764; + uint256 constant IC133y = 4733953237490399775017512096113933713784650689037761984287562289708936384358; + + uint256 constant IC134x = 14214002012662218265809925298869712237550619236331963061105329915294991617539; + uint256 constant IC134y = 17121763666873517782646044837366652818285206685312235727066011813711345408437; + + uint256 constant IC135x = 9266509597275034201508175144195970926209811708631599372000953456110862815645; + uint256 constant IC135y = 21278684439347810521198014846683852642935595295062434704316223688822331119877; + + uint256 constant IC136x = 12395456059435207793972164585436949483196671128868708309038683147671019448409; + uint256 constant IC136y = 8918309779009409678520962946627496599219654034550213506869495872488001468076; + + uint256 constant IC137x = 18861853067527573731773852077727112989998264356359923368924656779173162053723; + uint256 constant IC137y = 15941973470207367711894935827547693521536808914464978524480638199148145002729; + + uint256 constant IC138x = 16059280136896388151504464169198584910311488493527399684382578759827447744071; + uint256 constant IC138y = 18918277708416945600712768709484098142306394509000917049386746426804174408123; + + uint256 constant IC139x = 6677870054144222691152638974103459565036534535634910318263037361417096935495; + uint256 constant IC139y = 15271678086193340446877116444868853230751898603997001444418564149426246481723; + + uint256 constant IC140x = 8075190630223360275889737609695539630564859017613074224424630497049897728097; + uint256 constant IC140y = 6088959624789235896159879130942091614931585607864890603372195920943354116300; // Memory data @@ -419,7 +473,7 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { uint16 constant pLastMem = 896; - function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[122] calldata _pubSignals) public view returns (bool) { + function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[140] calldata _pubSignals) public view returns (bool) { assembly { function checkField(v) { if iszero(lt(v, r)) { @@ -707,6 +761,42 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { g1_mulAccC(_pVk, IC122x, IC122y, calldataload(add(pubSignals, 3872))) + g1_mulAccC(_pVk, IC123x, IC123y, calldataload(add(pubSignals, 3904))) + + g1_mulAccC(_pVk, IC124x, IC124y, calldataload(add(pubSignals, 3936))) + + g1_mulAccC(_pVk, IC125x, IC125y, calldataload(add(pubSignals, 3968))) + + g1_mulAccC(_pVk, IC126x, IC126y, calldataload(add(pubSignals, 4000))) + + g1_mulAccC(_pVk, IC127x, IC127y, calldataload(add(pubSignals, 4032))) + + g1_mulAccC(_pVk, IC128x, IC128y, calldataload(add(pubSignals, 4064))) + + g1_mulAccC(_pVk, IC129x, IC129y, calldataload(add(pubSignals, 4096))) + + g1_mulAccC(_pVk, IC130x, IC130y, calldataload(add(pubSignals, 4128))) + + g1_mulAccC(_pVk, IC131x, IC131y, calldataload(add(pubSignals, 4160))) + + g1_mulAccC(_pVk, IC132x, IC132y, calldataload(add(pubSignals, 4192))) + + g1_mulAccC(_pVk, IC133x, IC133y, calldataload(add(pubSignals, 4224))) + + g1_mulAccC(_pVk, IC134x, IC134y, calldataload(add(pubSignals, 4256))) + + g1_mulAccC(_pVk, IC135x, IC135y, calldataload(add(pubSignals, 4288))) + + g1_mulAccC(_pVk, IC136x, IC136y, calldataload(add(pubSignals, 4320))) + + g1_mulAccC(_pVk, IC137x, IC137y, calldataload(add(pubSignals, 4352))) + + g1_mulAccC(_pVk, IC138x, IC138y, calldataload(add(pubSignals, 4384))) + + g1_mulAccC(_pVk, IC139x, IC139y, calldataload(add(pubSignals, 4416))) + + g1_mulAccC(_pVk, IC140x, IC140y, calldataload(add(pubSignals, 4448))) + // -A mstore(_pPairing, calldataload(pA)) @@ -1006,6 +1096,42 @@ contract Groth16Verifier_AnonEncNullifierNonRepudiationBatch { checkField(calldataload(add(_pubSignals, 3904))) + checkField(calldataload(add(_pubSignals, 3936))) + + checkField(calldataload(add(_pubSignals, 3968))) + + checkField(calldataload(add(_pubSignals, 4000))) + + checkField(calldataload(add(_pubSignals, 4032))) + + checkField(calldataload(add(_pubSignals, 4064))) + + checkField(calldataload(add(_pubSignals, 4096))) + + checkField(calldataload(add(_pubSignals, 4128))) + + checkField(calldataload(add(_pubSignals, 4160))) + + checkField(calldataload(add(_pubSignals, 4192))) + + checkField(calldataload(add(_pubSignals, 4224))) + + checkField(calldataload(add(_pubSignals, 4256))) + + checkField(calldataload(add(_pubSignals, 4288))) + + checkField(calldataload(add(_pubSignals, 4320))) + + checkField(calldataload(add(_pubSignals, 4352))) + + checkField(calldataload(add(_pubSignals, 4384))) + + checkField(calldataload(add(_pubSignals, 4416))) + + checkField(calldataload(add(_pubSignals, 4448))) + + checkField(calldataload(add(_pubSignals, 4480))) + // Validate all evaluations let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem) diff --git a/solidity/contracts/zeto_anon_enc.sol b/solidity/contracts/zeto_anon_enc.sol index 0d6f57c..b95e125 100644 --- a/solidity/contracts/zeto_anon_enc.sol +++ b/solidity/contracts/zeto_anon_enc.sol @@ -29,8 +29,8 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; uint256 constant MAX_BATCH = 10; -uint256 constant INPUT_SIZE = 14; -uint256 constant BATCH_INPUT_SIZE = 45; +uint256 constant INPUT_SIZE = 15; +uint256 constant BATCH_INPUT_SIZE = 63; /// @title A sample implementation of a Zeto based fungible token with anonymity, and encryption /// @author Kaleido, Inc. @@ -75,14 +75,15 @@ contract Zeto_AnonEnc is ) internal returns (uint256[] memory publicInputs) { publicInputs = new uint256[](size); uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit - for (uint256 i = 0; i < encryptedValues.length; ++i) { - publicInputs[piIndex++] = encryptedValues[i]; - } // copy the ecdh public key for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { publicInputs[piIndex++] = ecdhPublicKey[i]; } + + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } // copy input commitments for (uint256 i = 0; i < inputs.length; i++) { publicInputs[piIndex++] = inputs[i]; diff --git a/solidity/contracts/zeto_anon_enc_nullifier.sol b/solidity/contracts/zeto_anon_enc_nullifier.sol index 2a70fa5..bcfeedf 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier.sol @@ -27,8 +27,8 @@ import {Commonlib} from "./lib/common.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; uint256 constant MAX_BATCH = 10; -uint256 constant INPUT_SIZE = 17; -uint256 constant BATCH_INPUT_SIZE = 56; +uint256 constant INPUT_SIZE = 18; +uint256 constant BATCH_INPUT_SIZE = 74; /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking /// @author Kaleido, Inc. @@ -77,14 +77,14 @@ contract Zeto_AnonEncNullifier is ) internal returns (uint256[] memory publicInputs) { publicInputs = new uint256[](size); uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit - for (uint256 i = 0; i < encryptedValues.length; ++i) { - publicInputs[piIndex++] = encryptedValues[i]; - } // copy the ecdh public key for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { publicInputs[piIndex++] = ecdhPublicKey[i]; } + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } // copy input commitments for (uint256 i = 0; i < nullifiers.length; i++) { publicInputs[piIndex++] = nullifiers[i]; diff --git a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol index f1790ad..b130b64 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_kyc.sol @@ -27,8 +27,8 @@ import {Commonlib} from "./lib/common.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; uint256 constant MAX_BATCH = 10; -uint256 constant INPUT_SIZE = 18; -uint256 constant BATCH_INPUT_SIZE = 57; +uint256 constant INPUT_SIZE = 19; +uint256 constant BATCH_INPUT_SIZE = 75; /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking /// @author Kaleido, Inc. @@ -83,14 +83,14 @@ contract Zeto_AnonEncNullifierKyc is ) internal returns (uint256[] memory publicInputs) { publicInputs = new uint256[](size); uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit - for (uint256 i = 0; i < encryptedValues.length; ++i) { - publicInputs[piIndex++] = encryptedValues[i]; - } // copy the ecdh public key for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { publicInputs[piIndex++] = ecdhPublicKey[i]; } + // copy the encrypted value, salt and parity bit + for (uint256 i = 0; i < encryptedValues.length; ++i) { + publicInputs[piIndex++] = encryptedValues[i]; + } // copy input commitments for (uint256 i = 0; i < nullifiers.length; i++) { publicInputs[piIndex++] = nullifiers[i]; diff --git a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol index 3326f84..7940786 100644 --- a/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +++ b/solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol @@ -26,8 +26,8 @@ import {Registry} from "./lib/registry.sol"; import {Commonlib} from "./lib/common.sol"; uint256 constant MAX_BATCH = 10; -uint256 constant INPUT_SIZE = 35; -uint256 constant BATCH_INPUT_SIZE = 122; +uint256 constant INPUT_SIZE = 36; +uint256 constant BATCH_INPUT_SIZE = 140; /// @title A sample implementation of a Zeto based fungible token with anonymity, encryption and history masking /// @author Kaleido, Inc. @@ -98,14 +98,14 @@ contract Zeto_AnonEncNullifierNonRepudiation is ) internal returns (uint256[] memory publicInputs) { publicInputs = new uint256[](size); uint256 piIndex = 0; - // copy the encrypted value, salt and parity bit for receiver - for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { - publicInputs[piIndex++] = encryptedValuesForReceiver[i]; - } // copy the ecdh public key for (uint256 i = 0; i < ecdhPublicKey.length; ++i) { publicInputs[piIndex++] = ecdhPublicKey[i]; } + // copy the encrypted value, salt and parity bit for receiver + for (uint256 i = 0; i < encryptedValuesForReceiver.length; ++i) { + publicInputs[piIndex++] = encryptedValuesForReceiver[i]; + } // copy the encrypted value, salt and parity bit for authority for (uint256 i = 0; i < encryptedValuesForAuthority.length; ++i) { publicInputs[piIndex++] = encryptedValuesForAuthority[i]; diff --git a/solidity/test/zeto_anon.ts b/solidity/test/zeto_anon.ts index dc7fe65..f309be4 100644 --- a/solidity/test/zeto_anon.ts +++ b/solidity/test/zeto_anon.ts @@ -76,7 +76,7 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi ({ provingKeyFile: batchProvingKey } = loadProvingKeys("anon_batch")); }); - it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob and Charlie should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; for (let i = 0; i < 10; i++) { @@ -85,12 +85,12 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi } await doMint(zeto, deployer, inputUtxos); - // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + // Alice proposes the output UTXOs, 1 utxo to bob, 1 utxo to charlie and 1 utxo to alice const _bOut1 = newUTXO(8, Bob); - const _bOut2 = newUTXO(1, Alice); + const _bOut2 = newUTXO(1, Charlie); const _bOut3 = newUTXO(1, Alice); const outputUtxos = [_bOut1, _bOut2, _bOut3]; - const outputOwners = [Bob, Alice, Alice]; + const outputOwners = [Bob, Charlie, Alice]; const inflatedOutputUtxos = [...outputUtxos]; const inflatedOutputOwners = [...outputOwners]; for (let i = 0; i < 10 - outputUtxos.length; i++) { @@ -98,7 +98,7 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi inflatedOutputOwners.push(Bob); } - // Alice transfers UTXOs to Bob + // Alice transfers UTXOs to Bob and Charlie const result = await doTransfer( Alice, inputUtxos, diff --git a/solidity/test/zeto_anon_enc.ts b/solidity/test/zeto_anon_enc.ts index b912edd..7cad834 100644 --- a/solidity/test/zeto_anon_enc.ts +++ b/solidity/test/zeto_anon_enc.ts @@ -83,7 +83,7 @@ describe("Zeto based fungible token with anonymity and encryption", function () ({ provingKeyFile: batchProvingKey } = loadProvingKeys("anon_enc_batch")); }); - it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob and Charlie should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; for (let i = 0; i < 10; i++) { @@ -92,12 +92,12 @@ describe("Zeto based fungible token with anonymity and encryption", function () } await doMint(zeto, deployer, inputUtxos); - // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + // Alice proposes the output UTXOs, 1 utxo to bob, 1 utxo to charlie and 1 utxo to alice const _bOut1 = newUTXO(8, Bob); - const _bOut2 = newUTXO(1, Alice); + const _bOut2 = newUTXO(1, Charlie); const _bOut3 = newUTXO(1, Alice); const outputUtxos = [_bOut1, _bOut2, _bOut3]; - const outputOwners = [Bob, Alice, Alice]; + const outputOwners = [Bob, Charlie, Alice]; const inflatedOutputUtxos = [...outputUtxos]; const inflatedOutputOwners = [...outputOwners]; for (let i = 0; i < 10 - outputUtxos.length; i++) { @@ -117,25 +117,28 @@ describe("Zeto based fungible token with anonymity and encryption", function () expect(events[0].inputs).to.deep.equal(inputUtxos.map((i) => i.hash)); const incomingUTXOs: any = events[0].outputs; const ecdhPublicKey = events[0].ecdhPublicKey; - // Bob reconstructs the shared key using his private key and ephemeral public key - - const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); - const plainText = poseidonDecrypt( - events[0].encryptedValues, - sharedKey, - events[0].encryptionNonce, - 20, - ); - expect(plainText).to.deep.equal(result.expectedPlainText); // check the non-empty output hashes are correct for (let i = 0; i < outputUtxos.length; i++) { - // Bob uses the information received from Alice to reconstruct the UTXO sent to him + const utxoOwner = outputOwners[i]; + const sharedKey = genEcdhSharedKey( + utxoOwner.babyJubPrivateKey, + ecdhPublicKey, + ); + const plainText = poseidonDecrypt( + events[0].encryptedValues.slice(4 * i, 4 * i + 4), + sharedKey, + events[0].encryptionNonce, + 2, + ); + expect(plainText).to.deep.equal( + result.expectedPlainText.slice(2 * i, 2 * i + 2), + ); const hash = poseidonHash([ - BigInt(plainText[2 * i]), - plainText[2 * i + 1], - outputOwners[i].babyJubPublicKey[0], - outputOwners[i].babyJubPublicKey[1], + BigInt(plainText[0]), + plainText[1], + utxoOwner.babyJubPublicKey[0], + utxoOwner.babyJubPublicKey[1], ]); expect(incomingUTXOs[i]).to.equal(hash); } @@ -143,8 +146,6 @@ describe("Zeto based fungible token with anonymity and encryption", function () // check empty values, salt and hashes are empty for (let i = outputUtxos.length; i < 10; i++) { expect(incomingUTXOs[i]).to.equal(0); - expect(plainText[2 * i]).to.equal(0); - expect(plainText[2 * i + 1]).to.equal(0); } }); @@ -208,12 +209,12 @@ describe("Zeto based fungible token with anonymity and encryption", function () const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); const plainText = poseidonDecrypt( - events[0].encryptedValues, + events[0].encryptedValues.slice(0, 4), sharedKey, events[0].encryptionNonce, - 4, + 2, ); - expect(plainText).to.deep.equal(result.expectedPlainText); + expect(plainText).to.deep.equal(result.expectedPlainText.slice(0, 2)); // Bob verifies that the UTXO constructed from the decrypted values matches the UTXO from the event const hash = poseidonHash([ BigInt(plainText[0]), @@ -436,10 +437,11 @@ describe("Zeto based fungible token with anonymity and encryption", function () `Witness calculation time: ${timeWitnessCalculation}ms, Proof generation time: ${timeProofGeneration}ms`, ); + // console.log(publicSignals); const encodedProof = encodeProof(proof); const encryptedValues = isBatch - ? publicSignals.slice(0, 22) - : publicSignals.slice(0, 7); + ? publicSignals.slice(2, 42) + : publicSignals.slice(2, 10); return { inputCommitments, outputCommitments, diff --git a/solidity/test/zeto_anon_enc_nullifier.ts b/solidity/test/zeto_anon_enc_nullifier.ts index d621def..390d143 100644 --- a/solidity/test/zeto_anon_enc_nullifier.ts +++ b/solidity/test/zeto_anon_enc_nullifier.ts @@ -102,7 +102,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti expect(root.string()).to.equal(onchainRoot.toString()); }); - it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob and Charlie should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; const nullifiers = []; @@ -133,12 +133,12 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti mtps.push(p.siblings.map((s) => s.bigInt())); } - // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + // Alice proposes the output UTXOs, 1 utxo to bob, 1 utxo to charlie and 1 utxo to alice const _bOut1 = newUTXO(8, Bob); - const _bOut2 = newUTXO(1, Alice); + const _bOut2 = newUTXO(1, Charlie); const _bOut3 = newUTXO(1, Alice); const outputUtxos = [_bOut1, _bOut2, _bOut3]; - const outputOwners = [Bob, Alice, Alice]; + const outputOwners = [Bob, Charlie, Alice]; const inflatedOutputUtxos = [...outputUtxos]; const inflatedOutputOwners = [...outputOwners]; for (let i = 0; i < 10 - outputUtxos.length; i++) { @@ -164,25 +164,28 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti const incomingUTXOs: any = events[0].outputs; const ecdhPublicKey = events[0].ecdhPublicKey; - // Bob reconstructs the shared key using his private key and ephemeral public key - - const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); - const plainText = poseidonDecrypt( - events[0].encryptedValues, - sharedKey, - events[0].encryptionNonce, - 20, - ); - expect(plainText).to.deep.equal(result.expectedPlainText); // check the non-empty output hashes are correct for (let i = 0; i < outputUtxos.length; i++) { - // Bob uses the information received from Alice to reconstruct the UTXO sent to him + const utxoOwner = outputOwners[i]; + const sharedKey = genEcdhSharedKey( + utxoOwner.babyJubPrivateKey, + ecdhPublicKey, + ); + const plainText = poseidonDecrypt( + events[0].encryptedValues.slice(4 * i, 4 * i + 4), + sharedKey, + events[0].encryptionNonce, + 2, + ); + expect(plainText).to.deep.equal( + result.expectedPlainText.slice(2 * i, 2 * i + 2), + ); const hash = poseidonHash([ - BigInt(plainText[2 * i]), - plainText[2 * i + 1], - outputOwners[i].babyJubPublicKey[0], - outputOwners[i].babyJubPublicKey[1], + BigInt(plainText[0]), + plainText[1], + utxoOwner.babyJubPublicKey[0], + utxoOwner.babyJubPublicKey[1], ]); expect(incomingUTXOs[i]).to.equal(hash); await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]); @@ -192,8 +195,6 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti // check empty values, salt and hashes are empty for (let i = outputUtxos.length; i < 10; i++) { expect(incomingUTXOs[i]).to.equal(0); - expect(plainText[2 * i]).to.equal(0); - expect(plainText[2 * i + 1]).to.equal(0); } }); @@ -298,12 +299,12 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); const plainText = poseidonDecrypt( - events[0].encryptedValues, + events[0].encryptedValues.slice(0, 4), sharedKey, events[0].encryptionNonce, - 4, + 2, ); - expect(plainText).to.deep.equal(result2.expectedPlainText); + expect(plainText).to.deep.equal(result2.expectedPlainText.slice(0, 2)); // Bob uses the decrypted values to construct the UTXO received from the transaction utxo3 = newUTXO(Number(plainText[0]), Bob, plainText[1]); @@ -735,10 +736,11 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`, ); + // console.log(publicSignals); const encodedProof = encodeProof(proof); const encryptedValues = isBatch - ? publicSignals.slice(0, 22) - : publicSignals.slice(0, 7); + ? publicSignals.slice(2, 42) + : publicSignals.slice(2, 10); return { inputCommitments, outputCommitments, diff --git a/solidity/test/zeto_anon_enc_nullifier_kyc.ts b/solidity/test/zeto_anon_enc_nullifier_kyc.ts index c801e9c..f08aeb0 100644 --- a/solidity/test/zeto_anon_enc_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_enc_nullifier_kyc.ts @@ -133,7 +133,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti expect(root.string()).to.equal(onchainRoot.toString()); }); - it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob and Charlie should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; const nullifiers = []; @@ -178,13 +178,24 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti ); const bobProof = bProof.siblings.map((s) => s.bigInt()); - // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + const cProof = await smtKyc.generateCircomVerifierProof( + kycHash(Charlie.babyJubPublicKey), + identitiesRoot, + ); + const charlieProof = cProof.siblings.map((s) => s.bigInt()); + + // Alice proposes the output UTXOs, 1 utxo to bob, 1 utxo to charlie and 1 utxo to alice const _bOut1 = newUTXO(8, Bob); - const _bOut2 = newUTXO(1, Alice); + const _bOut2 = newUTXO(1, Charlie); const _bOut3 = newUTXO(1, Alice); const outputUtxos = [_bOut1, _bOut2, _bOut3]; - const outputOwners = [Bob, Alice, Alice]; - const identityMerkleProofs = [aliceProof, bobProof, aliceProof, aliceProof]; + const outputOwners = [Bob, Charlie, Alice]; + const identityMerkleProofs = [ + aliceProof, + bobProof, + charlieProof, + aliceProof, + ]; const inflatedOutputUtxos = [...outputUtxos]; const inflatedOutputOwners = [...outputOwners]; for (let i = 0; i < 10 - outputUtxos.length; i++) { @@ -213,25 +224,27 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti const incomingUTXOs: any = events[0].outputs; const ecdhPublicKey = events[0].ecdhPublicKey; - // Bob reconstructs the shared key using his private key and ephemeral public key - - const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); - const plainText = poseidonDecrypt( - events[0].encryptedValues, - sharedKey, - events[0].encryptionNonce, - 20, - ); - expect(plainText).to.deep.equal(result.expectedPlainText); - // check the non-empty output hashes are correct for (let i = 0; i < outputUtxos.length; i++) { - // Bob uses the information received from Alice to reconstruct the UTXO sent to him + const utxoOwner = outputOwners[i]; + const sharedKey = genEcdhSharedKey( + utxoOwner.babyJubPrivateKey, + ecdhPublicKey, + ); + const plainText = poseidonDecrypt( + events[0].encryptedValues.slice(4 * i, 4 * i + 4), + sharedKey, + events[0].encryptionNonce, + 2, + ); + expect(plainText).to.deep.equal( + result.expectedPlainText.slice(2 * i, 2 * i + 2), + ); const hash = poseidonHash([ - BigInt(plainText[2 * i]), - plainText[2 * i + 1], - outputOwners[i].babyJubPublicKey[0], - outputOwners[i].babyJubPublicKey[1], + BigInt(plainText[0]), + plainText[1], + utxoOwner.babyJubPublicKey[0], + utxoOwner.babyJubPublicKey[1], ]); expect(incomingUTXOs[i]).to.equal(hash); await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]); @@ -242,8 +255,6 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti // check empty values, salt and hashes are empty for (let i = outputUtxos.length; i < 10; i++) { expect(incomingUTXOs[i]).to.equal(0); - expect(plainText[2 * i]).to.equal(0); - expect(plainText[2 * i + 1]).to.equal(0); } }); @@ -369,14 +380,15 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti const ecdhPublicKey = events[0].ecdhPublicKey; // Bob reconstructs the shared key using his private key and ephemeral public key + const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); const plainText = poseidonDecrypt( - events[0].encryptedValues, + events[0].encryptedValues.slice(0, 4), sharedKey, events[0].encryptionNonce, - 4, + 2, ); - expect(plainText).to.deep.equal(result2.expectedPlainText); + expect(plainText).to.deep.equal(result2.expectedPlainText.slice(0, 2)); // Bob uses the decrypted values to construct the UTXO received from the transaction utxo3 = newUTXO(Number(plainText[0]), Bob, plainText[1]); @@ -1060,10 +1072,11 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti `Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`, ); + // console.log(publicSignals); const encodedProof = encodeProof(proof); const encryptedValues = isBatch - ? publicSignals.slice(0, 22) - : publicSignals.slice(0, 7); + ? publicSignals.slice(2, 42) + : publicSignals.slice(2, 10); return { inputCommitments, outputCommitments, diff --git a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts index a7c785a..5c235f3 100644 --- a/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts +++ b/solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts @@ -115,7 +115,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti expect(root.string()).to.equal(onchainRoot.toString()); }); - it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob and Charlie should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; const nullifiers = []; @@ -146,12 +146,12 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti mtps.push(p.siblings.map((s) => s.bigInt())); } - // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + // Alice proposes the output UTXOs, 1 utxo to bob, 1 utxo to charlie and 1 utxo to alice const _bOut1 = newUTXO(8, Bob); - const _bOut2 = newUTXO(1, Alice); + const _bOut2 = newUTXO(1, Charlie); const _bOut3 = newUTXO(1, Alice); const outputUtxos = [_bOut1, _bOut2, _bOut3]; - const outputOwners = [Bob, Alice, Alice]; + const outputOwners = [Bob, Charlie, Alice]; const inflatedOutputUtxos = [...outputUtxos]; const inflatedOutputOwners = [...outputOwners]; for (let i = 0; i < 10 - outputUtxos.length; i++) { @@ -177,26 +177,28 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti const incomingUTXOs: any = events[0].outputs; const ecdhPublicKey = events[0].ecdhPublicKey; - // Bob reconstructs the shared key using his private key and ephemeral public key - - const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); - - const plainText = poseidonDecrypt( - events[0].encryptedValuesForReceiver, - sharedKey, - events[0].encryptionNonce, - 20, - ); - expect(plainText).to.deep.equal(result.expectedPlainText); // check the non-empty output hashes are correct for (let i = 0; i < outputUtxos.length; i++) { - // Bob uses the information received from Alice to reconstruct the UTXO sent to him + const utxoOwner = outputOwners[i]; + const sharedKey = genEcdhSharedKey( + utxoOwner.babyJubPrivateKey, + ecdhPublicKey, + ); + const plainText = poseidonDecrypt( + events[0].encryptedValuesForReceiver.slice(4 * i, 4 * i + 4), + sharedKey, + events[0].encryptionNonce, + 2, + ); + expect(plainText).to.deep.equal( + result.expectedPlainText.slice(2 * i, 2 * i + 2), + ); const hash = poseidonHash([ - BigInt(plainText[2 * i]), - plainText[2 * i + 1], - outputOwners[i].babyJubPublicKey[0], - outputOwners[i].babyJubPublicKey[1], + BigInt(plainText[0]), + plainText[1], + utxoOwner.babyJubPublicKey[0], + utxoOwner.babyJubPublicKey[1], ]); expect(incomingUTXOs[i]).to.equal(hash); await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]); @@ -206,10 +208,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti // check empty values, salt and hashes are empty for (let i = outputUtxos.length; i < 10; i++) { expect(incomingUTXOs[i]).to.equal(0); - expect(plainText[2 * i]).to.equal(0); - expect(plainText[2 * i + 1]).to.equal(0); } - // The regulator uses the encrypted values in the event to decrypt and recover the UTXO value and salt const auditKey = genEcdhSharedKey( Authority.babyJubPrivateKey, @@ -353,14 +352,17 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti const ecdhPublicKey = events[0].ecdhPublicKey; // Bob reconstructs the shared key using his private key and ephemeral public key - const sharedKey1 = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); + const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey); const plainText1 = poseidonDecrypt( - events[0].encryptedValuesForReceiver, - sharedKey1, + events[0].encryptedValuesForReceiver.slice(0, 4), + sharedKey, events[0].encryptionNonce, - 4, + 2, ); - expect(plainText1).to.deep.equal(result2.expectedPlainText); + expect(plainText1).to.deep.equal(result2.expectedPlainText.slice(0, 2)); + + // Bob uses the decrypted values to construct the UTXO received from the transaction + utxo3 = newUTXO(Number(plainText1[0]), Bob, plainText1[1]); // The regulator uses the encrypted values in the event to decrypt and recover the UTXO value and salt const sharedKey2 = genEcdhSharedKey( @@ -418,9 +420,6 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti plainText2[9], ]); expect(checkOutputUTXO2).to.equal(utxo4.hash); // "utxo4" hash is available in the event - - // Bob uses the decrypted values to construct the UTXO received from the transaction - utxo3 = newUTXO(Number(plainText1[0]), Bob, plainText1[1]); }).timeout(600000); it("Bob transfers UTXOs, previously received from Alice, honestly to Charlie should succeed", async function () { @@ -847,11 +846,11 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti inputCommitments, outputCommitments, encryptedValuesForReceiver: isBatch - ? publicSignals.slice(0, 22) - : publicSignals.slice(0, 7), + ? publicSignals.slice(2, 42) + : publicSignals.slice(2, 10), encryptedValuesForRegulator: isBatch - ? publicSignals.slice(24, 88) - : publicSignals.slice(9, 25), + ? publicSignals.slice(42, 106) + : publicSignals.slice(10, 26), encryptionNonce, encodedProof, }; diff --git a/solidity/test/zeto_anon_nullifier.ts b/solidity/test/zeto_anon_nullifier.ts index 9a32bfe..3c99cd8 100644 --- a/solidity/test/zeto_anon_nullifier.ts +++ b/solidity/test/zeto_anon_nullifier.ts @@ -89,7 +89,7 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr expect(root.string()).to.equal(onchainRoot.toString()); }); - it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob and Charlie should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; const nullifiers = []; @@ -120,12 +120,12 @@ describe("Zeto based fungible token with anonymity using nullifiers without encr mtps.push(p.siblings.map((s) => s.bigInt())); } - // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + // Alice proposes the output UTXOs, 1 utxo to bob, 1 utxo to charlie and 1 utxo to alice const _bOut1 = newUTXO(8, Bob); - const _bOut2 = newUTXO(1, Alice); + const _bOut2 = newUTXO(1, Charlie); const _bOut3 = newUTXO(1, Alice); const outputUtxos = [_bOut1, _bOut2, _bOut3]; - const outputOwners = [Bob, Alice, Alice]; + const outputOwners = [Bob, Charlie, Alice]; const inflatedOutputUtxos = [...outputUtxos]; const inflatedOutputOwners = [...outputOwners]; for (let i = 0; i < 10 - outputUtxos.length; i++) { diff --git a/solidity/test/zeto_anon_nullifier_kyc.ts b/solidity/test/zeto_anon_nullifier_kyc.ts index 72bc1ac..9198c7f 100644 --- a/solidity/test/zeto_anon_nullifier_kyc.ts +++ b/solidity/test/zeto_anon_nullifier_kyc.ts @@ -117,7 +117,7 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou expect(root.string()).to.equal(onchainRoot.toString()); }); - it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob should succeed", async function () { + it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob and Charlie should succeed", async function () { // first mint the tokens for batch testing const inputUtxos = []; const nullifiers = []; @@ -161,13 +161,24 @@ describe("Zeto based fungible token with anonymity, KYC, using nullifiers withou identitiesRoot, ); const bobProof = bProof.siblings.map((s) => s.bigInt()); - // Alice proposes the output UTXOs, 1 utxo to bob, 2 utxos to alice + + const cProof = await smtKyc.generateCircomVerifierProof( + kycHash(Charlie.babyJubPublicKey), + identitiesRoot, + ); + const charlieProof = cProof.siblings.map((s) => s.bigInt()); + // Alice proposes the output UTXOs, 1 utxo to bob, 1 utxo to charlie and 1 utxo to alice const _bOut1 = newUTXO(8, Bob); - const _bOut2 = newUTXO(1, Alice); + const _bOut2 = newUTXO(1, Charlie); const _bOut3 = newUTXO(1, Alice); const outputUtxos = [_bOut1, _bOut2, _bOut3]; - const outputOwners = [Bob, Alice, Alice]; - const identityMerkleProofs = [aliceProof, bobProof, aliceProof, aliceProof]; + const outputOwners = [Bob, Charlie, Alice]; + const identityMerkleProofs = [ + aliceProof, + bobProof, + charlieProof, + aliceProof, + ]; const inflatedOutputUtxos = [...outputUtxos]; const inflatedOutputOwners = [...outputOwners]; for (let i = 0; i < 10 - outputUtxos.length; i++) { diff --git a/zkp/circuits/basetokens/anon_enc_base.circom b/zkp/circuits/basetokens/anon_enc_base.circom index 433ea15..fd3de0e 100644 --- a/zkp/circuits/basetokens/anon_enc_base.circom +++ b/zkp/circuits/basetokens/anon_enc_base.circom @@ -18,8 +18,7 @@ pragma circom 2.1.4; include "../lib/check-positive.circom"; include "../lib/check-hashes.circom"; include "../lib/check-sum.circom"; -include "../lib/ecdh.circom"; -include "../lib/encrypt.circom"; +include "../lib/encrypt-outputs.circom"; include "../node_modules/circomlib/circuits/babyjub.circom"; // This version of the circuit performs the following operations: @@ -42,18 +41,12 @@ template Zeto(nInputs, nOutputs) { signal input outputOwnerPublicKeys[nOutputs][2]; signal input encryptionNonce; - // the output for encrypted output values and salts - var cLen = 2 * nOutputs; - if (cLen % 3 != 0) { - cLen += (3 - (cLen % 3)); - } - cLen++; - signal output cipherText[cLen]; - - // the output for the public key of the ephemeral private key used in generating ECDH shared key signal output ecdhPublicKey[2]; + // the output for the list of encrypted output UTXOs cipher texts + signal output cipherTexts[nOutputs][4]; + // derive the sender's public key from the secret input // for the sender's private key. This step demonstrates // the sender really owns the private key for the input @@ -88,29 +81,13 @@ template Zeto(nInputs, nOutputs) { checkSum.inputValues <== inputValues; checkSum.outputValues <== outputValues; - // generate shared secret - var sharedSecret[2]; - component ecdh = Ecdh(); - ecdh.privKey <== ecdhPrivateKey; - ecdh.pubKey[0] <== outputOwnerPublicKeys[0][0]; - ecdh.pubKey[1] <== outputOwnerPublicKeys[0][1]; - sharedSecret[0] = ecdh.sharedKey[0]; - sharedSecret[1] = ecdh.sharedKey[1]; - - // encrypt the value for the output utxos - component encrypt = SymmetricEncrypt(2 * nOutputs); - for (var i = 0; i < nOutputs; i++) { - encrypt.plainText[2 * i] <== outputValues[i]; - encrypt.plainText[2 * i + 1] <== outputSalts[i]; - } - encrypt.key <== sharedSecret; - encrypt.nonce <== encryptionNonce; - for (var i = 0; i < cLen; i++) { - encrypt.cipherText[i] ==> cipherText[i]; - } - - component ecdhPub = BabyPbk(); - ecdhPub.in <== ecdhPrivateKey; - ecdhPublicKey[0] <== ecdhPub.Ax; - ecdhPublicKey[1] <== ecdhPub.Ay; + component encryptOutputs = EncryptOutputs(nOutputs); + encryptOutputs.ecdhPrivateKey <== ecdhPrivateKey; + encryptOutputs.encryptionNonce <== encryptionNonce; + encryptOutputs.outputValues <== outputValues; + encryptOutputs.outputSalts <== outputSalts; + encryptOutputs.outputOwnerPublicKeys <== outputOwnerPublicKeys; + + encryptOutputs.ecdhPublicKey ==> ecdhPublicKey; + encryptOutputs.cipherTexts ==> cipherTexts; } diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_base.circom index 7a6811e..2b228c3 100644 --- a/zkp/circuits/basetokens/anon_enc_nullifier_base.circom +++ b/zkp/circuits/basetokens/anon_enc_nullifier_base.circom @@ -20,8 +20,7 @@ include "../lib/check-hashes.circom"; include "../lib/check-sum.circom"; include "../lib/check-nullifiers.circom"; include "../lib/check-smt-proof.circom"; -include "../lib/ecdh.circom"; -include "../lib/encrypt.circom"; +include "../lib/encrypt-outputs.circom"; include "../node_modules/circomlib/circuits/babyjub.circom"; // This version of the circuit performs the following operations: @@ -50,16 +49,11 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { signal input outputSalts[nOutputs]; signal input encryptionNonce; - // the output for encrypted output values and salts - var cLen = 2 * nOutputs; - if (cLen % 3 != 0) { - cLen += (3 - (cLen % 3)); - } - cLen++; - signal output cipherText[cLen]; - // the output for the public key of the ephemeral private key used in generating ECDH shared key signal output ecdhPublicKey[2]; + + // the output for the list of encrypted output UTXOs cipher texts + signal output cipherTexts[nOutputs][4]; // derive the sender's public key from the secret input // for the sender's private key. This step demonstrates @@ -111,29 +105,13 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { checkSMTProof.enabled <== enabled; checkSMTProof.leafNodeIndexes <== inputCommitments; - // generate shared secret - var sharedSecret[2]; - component ecdh = Ecdh(); - ecdh.privKey <== ecdhPrivateKey; - ecdh.pubKey[0] <== outputOwnerPublicKeys[0][0]; - ecdh.pubKey[1] <== outputOwnerPublicKeys[0][1]; - sharedSecret[0] = ecdh.sharedKey[0]; - sharedSecret[1] = ecdh.sharedKey[1]; - - // encrypt the value for the output utxos - component encrypt = SymmetricEncrypt(2 * nOutputs); - for (var i = 0; i < nOutputs; i++) { - encrypt.plainText[2 * i] <== outputValues[i]; - encrypt.plainText[2 * i + 1] <== outputSalts[i]; - } - encrypt.key <== sharedSecret; - encrypt.nonce <== encryptionNonce; - for (var i = 0; i < cLen; i++) { - encrypt.cipherText[i] ==> cipherText[i]; - } - - component ecdhPub = BabyPbk(); - ecdhPub.in <== ecdhPrivateKey; - ecdhPublicKey[0] <== ecdhPub.Ax; - ecdhPublicKey[1] <== ecdhPub.Ay; + component encryptOutputs = EncryptOutputs(nOutputs); + encryptOutputs.ecdhPrivateKey <== ecdhPrivateKey; + encryptOutputs.encryptionNonce <== encryptionNonce; + encryptOutputs.outputValues <== outputValues; + encryptOutputs.outputSalts <== outputSalts; + encryptOutputs.outputOwnerPublicKeys <== outputOwnerPublicKeys; + + encryptOutputs.ecdhPublicKey ==> ecdhPublicKey; + encryptOutputs.cipherTexts ==> cipherTexts; } diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom index dcfe91a..2de3bcd 100644 --- a/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom +++ b/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom @@ -20,8 +20,7 @@ include "../lib/check-hashes.circom"; include "../lib/check-sum.circom"; include "../lib/check-nullifiers.circom"; include "../lib/check-smt-proof.circom"; -include "../lib/ecdh.circom"; -include "../lib/encrypt.circom"; +include "../lib/encrypt-outputs.circom"; include "../node_modules/circomlib/circuits/babyjub.circom"; // This version of the circuit performs the following operations: @@ -53,16 +52,11 @@ template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) { signal input outputSalts[nOutputs]; signal input encryptionNonce; - // the output for encrypted output values and salts - var cLen = 2 * nOutputs; - if (cLen % 3 != 0) { - cLen += (3 - (cLen % 3)); - } - cLen++; - signal output cipherText[cLen]; - // the output for the public key of the ephemeral private key used in generating ECDH shared key signal output ecdhPublicKey[2]; + + // the output for the list of encrypted output UTXOs cipher texts + signal output cipherTexts[nOutputs][4]; // derive the sender's public key from the secret input // for the sender's private key. This step demonstrates @@ -140,29 +134,13 @@ template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) { checkIdentitiesSMTProof.enabled <== identitiesMTPCheckEnabled; checkIdentitiesSMTProof.leafNodeIndexes <== ownerPublicKeyHashes; - // generate shared secret - var sharedSecret[2]; - component ecdh = Ecdh(); - ecdh.privKey <== ecdhPrivateKey; - ecdh.pubKey[0] <== outputOwnerPublicKeys[0][0]; - ecdh.pubKey[1] <== outputOwnerPublicKeys[0][1]; - sharedSecret[0] = ecdh.sharedKey[0]; - sharedSecret[1] = ecdh.sharedKey[1]; - - // encrypt the value for the output utxos - component encrypt = SymmetricEncrypt(2 * nOutputs); - for (var i = 0; i < nOutputs; i++) { - encrypt.plainText[2 * i] <== outputValues[i]; - encrypt.plainText[2 * i + 1] <== outputSalts[i]; - } - encrypt.key <== sharedSecret; - encrypt.nonce <== encryptionNonce; - for (var i = 0; i < cLen; i++) { - encrypt.cipherText[i] ==> cipherText[i]; - } - - component ecdhPub = BabyPbk(); - ecdhPub.in <== ecdhPrivateKey; - ecdhPublicKey[0] <== ecdhPub.Ax; - ecdhPublicKey[1] <== ecdhPub.Ay; + component encryptOutputs = EncryptOutputs(nOutputs); + encryptOutputs.ecdhPrivateKey <== ecdhPrivateKey; + encryptOutputs.encryptionNonce <== encryptionNonce; + encryptOutputs.outputValues <== outputValues; + encryptOutputs.outputSalts <== outputSalts; + encryptOutputs.outputOwnerPublicKeys <== outputOwnerPublicKeys; + + encryptOutputs.ecdhPublicKey ==> ecdhPublicKey; + encryptOutputs.cipherTexts ==> cipherTexts; } \ No newline at end of file diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom index 6adc30e..a06e420 100644 --- a/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom +++ b/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom @@ -20,8 +20,7 @@ include "../lib/check-hashes.circom"; include "../lib/check-sum.circom"; include "../lib/check-nullifiers.circom"; include "../lib/check-smt-proof.circom"; -include "../lib/ecdh.circom"; -include "../lib/encrypt.circom"; +include "../lib/encrypt-outputs.circom"; include "../node_modules/circomlib/circuits/babyjub.circom"; // This version of the circuit performs the following operations: @@ -52,16 +51,11 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { signal input encryptionNonce; signal input authorityPublicKey[2]; - // the output for encrypted output values and salts - var cLen = 2 * nOutputs; - if (cLen % 3 != 0) { - cLen += (3 - (cLen % 3)); - } - cLen++; - signal output cipherText[cLen]; - // the output for the public key of the ephemeral private key used in generating ECDH shared key signal output ecdhPublicKey[2]; + + // the output for the list of encrypted output UTXOs cipher texts + signal output cipherTexts[nOutputs][4]; // the number of cipher text messages returned by // the encryption template will be 3n+1 @@ -127,68 +121,52 @@ template Zeto(nInputs, nOutputs, nSMTLevels) { checkSMTProof.enabled <== enabled; checkSMTProof.leafNodeIndexes <== inputCommitments; - // generate shared secret for the receiver - var sharedSecretReceiver[2]; - component ecdh1 = Ecdh(); - ecdh1.privKey <== ecdhPrivateKey; - ecdh1.pubKey[0] <== outputOwnerPublicKeys[0][0]; - ecdh1.pubKey[1] <== outputOwnerPublicKeys[0][1]; - sharedSecretReceiver[0] = ecdh1.sharedKey[0]; - sharedSecretReceiver[1] = ecdh1.sharedKey[1]; - - // encrypt the value for the output utxos - component encrypt1 = SymmetricEncrypt(2 * nOutputs); - for (var i = 0; i < nOutputs; i++) { - encrypt1.plainText[2 * i] <== outputValues[i]; - encrypt1.plainText[2 * i + 1] <== outputSalts[i]; - } - encrypt1.key <== sharedSecretReceiver; - encrypt1.nonce <== encryptionNonce; - for (var i = 0; i < cLen; i++) { - encrypt1.cipherText[i] ==> cipherText[i]; - } + // Generate cipher text for output utxos + component encryptOutputs = EncryptOutputs(nOutputs); + encryptOutputs.ecdhPrivateKey <== ecdhPrivateKey; + encryptOutputs.encryptionNonce <== encryptionNonce; + encryptOutputs.outputValues <== outputValues; + encryptOutputs.outputSalts <== outputSalts; + encryptOutputs.outputOwnerPublicKeys <== outputOwnerPublicKeys; + + encryptOutputs.ecdhPublicKey ==> ecdhPublicKey; + encryptOutputs.cipherTexts ==> cipherTexts; // generate shared secret for the authority var sharedSecretAuthority[2]; - component ecdh2 = Ecdh(); - ecdh2.privKey <== ecdhPrivateKey; - ecdh2.pubKey[0] <== authorityPublicKey[0]; - ecdh2.pubKey[1] <== authorityPublicKey[1]; - sharedSecretAuthority[0] = ecdh2.sharedKey[0]; - sharedSecretAuthority[1] = ecdh2.sharedKey[1]; - - component ecdhPub = BabyPbk(); - ecdhPub.in <== ecdhPrivateKey; - ecdhPublicKey[0] <== ecdhPub.Ax; - ecdhPublicKey[1] <== ecdhPub.Ay; + component ecdhAuth = Ecdh(); + ecdhAuth.privKey <== ecdhPrivateKey; + ecdhAuth.pubKey[0] <== authorityPublicKey[0]; + ecdhAuth.pubKey[1] <== authorityPublicKey[1]; + sharedSecretAuthority[0] = ecdhAuth.sharedKey[0]; + sharedSecretAuthority[1] = ecdhAuth.sharedKey[1]; + // encrypt the values for the authority - component encrypt2 = SymmetricEncrypt(2 + 2 * nInputs + 4 * nOutputs); - encrypt2.plainText[0] <== inputOwnerPublicKey[0]; - encrypt2.plainText[1] <== inputOwnerPublicKey[1]; + component encryptAuth = SymmetricEncrypt(2 + 2 * nInputs + 4 * nOutputs); + encryptAuth.plainText[0] <== inputOwnerPublicKey[0]; + encryptAuth.plainText[1] <== inputOwnerPublicKey[1]; var idx1 = 2; for (var i = 0; i < nInputs; i++) { - encrypt2.plainText[idx1] <== inputValues[i]; + encryptAuth.plainText[idx1] <== inputValues[i]; idx1++; - encrypt2.plainText[idx1] <== inputSalts[i]; + encryptAuth.plainText[idx1] <== inputSalts[i]; idx1++; } for (var i = 0; i < nOutputs; i++) { - encrypt2.plainText[idx1] <== outputOwnerPublicKeys[i][0]; + encryptAuth.plainText[idx1] <== outputOwnerPublicKeys[i][0]; idx1++; - encrypt2.plainText[idx1] <== outputOwnerPublicKeys[i][1]; + encryptAuth.plainText[idx1] <== outputOwnerPublicKeys[i][1]; idx1++; } for (var i = 0; i < nOutputs; i++) { - encrypt2.plainText[idx1] <== outputValues[i]; + encryptAuth.plainText[idx1] <== outputValues[i]; idx1++; - encrypt2.plainText[idx1] <== outputSalts[i]; + encryptAuth.plainText[idx1] <== outputSalts[i]; idx1++; } - encrypt2.key <== sharedSecretAuthority; - encrypt2.nonce <== encryptionNonce; - encrypt2.cipherText ==> cipherTextAuthority; - - + encryptAuth.key <== sharedSecretAuthority; + encryptAuth.nonce <== encryptionNonce; + encryptAuth.cipherText ==> cipherTextAuthority; } \ No newline at end of file diff --git a/zkp/circuits/gen-config.json b/zkp/circuits/gen-config.json index 8161c27..8bfe490 100644 --- a/zkp/circuits/gen-config.json +++ b/zkp/circuits/gen-config.json @@ -5,8 +5,8 @@ "skipSolidityGenaration": false }, "anon_enc": { - "ptau": "powersOfTau28_hez_final_13", - "batchPtau": "powersOfTau28_hez_final_14", + "ptau": "powersOfTau28_hez_final_14", + "batchPtau": "powersOfTau28_hez_final_16", "skipSolidityGenaration": false }, "anon_nullifier": { diff --git a/zkp/circuits/lib/encrypt-outputs.circom b/zkp/circuits/lib/encrypt-outputs.circom new file mode 100644 index 0000000..67f7535 --- /dev/null +++ b/zkp/circuits/lib/encrypt-outputs.circom @@ -0,0 +1,52 @@ +pragma circom 2.1.4; + +include "./ecdh.circom"; +include "./encrypt.circom"; +include "../node_modules/circomlib/circuits/babyjub.circom"; + +// encrypts a list of output UTXO values & salts +// with the corresponding shared ECDH keys for their +// owners. A single ephemeral private key is used +// to generate ECDH shared keys for different owners +template EncryptOutputs(numOutputs) { + signal input ecdhPrivateKey; + signal input encryptionNonce; + signal input outputValues[numOutputs]; + signal input outputSalts[numOutputs]; + signal input outputOwnerPublicKeys[numOutputs][2]; + + // the output for the public key of the ephemeral private key used in generating ECDH shared key + signal output ecdhPublicKey[2]; + + // the output for the list of encrypted output UTXOs cipher texts + signal output cipherTexts[numOutputs][4]; + + component ecdh[numOutputs]; + component encrypt[numOutputs]; + + for (var i = 0; i < numOutputs; i++) { + // generate shared secret + var sharedSecret[2]; + ecdh[i] = Ecdh(); + ecdh[i].privKey <== ecdhPrivateKey; + ecdh[i].pubKey[0] <== outputOwnerPublicKeys[i][0]; + ecdh[i].pubKey[1] <== outputOwnerPublicKeys[i][1]; + sharedSecret[0] = ecdh[i].sharedKey[0]; + sharedSecret[1] = ecdh[i].sharedKey[1]; + + // encrypt the value for the output UTXOs + encrypt[i] = SymmetricEncrypt(2); + encrypt[i].plainText[0] <== outputValues[i]; + encrypt[i].plainText[1] <== outputSalts[i]; + encrypt[i].key <== sharedSecret; + encrypt[i].nonce <== encryptionNonce; + for (var j = 0; j < 4; j++) { + encrypt[i].cipherText[j] ==> cipherTexts[i][j]; + } + } + + component ecdhPub = BabyPbk(); + ecdhPub.in <== ecdhPrivateKey; + ecdhPublicKey[0] <== ecdhPub.Ax; + ecdhPublicKey[1] <== ecdhPub.Ay; +} diff --git a/zkp/js/test/anon_enc.js b/zkp/js/test/anon_enc.js index ef3d4bd..6d56628 100644 --- a/zkp/js/test/anon_enc.js +++ b/zkp/js/test/anon_enc.js @@ -111,40 +111,60 @@ describe("main circuit tests for Zeto fungible tokens with anonymity with encryp true, ); - // console.log('witness', witness.slice(0, 15)); + // console.log("witness", witness.slice(0, 15)); // console.log('senderPublicKey', sender.pubKey); // console.log('receiverPublicKey', receiver.pubKey); // console.log('ephemeralPubkey', ephemeralKeypair.pubKey); // console.log('inputCommitments', inputCommitments); // console.log('encryptionNonce', encryptionNonce); - expect(witness[8]).to.equal(BigInt(ephemeralKeypair.pubKey[0])); - expect(witness[9]).to.equal(BigInt(ephemeralKeypair.pubKey[1])); - expect(witness[10]).to.equal(BigInt(inputCommitments[0])); - expect(witness[11]).to.equal(BigInt(inputCommitments[1])); - expect(witness[12]).to.equal(BigInt(outputCommitments[0])); - expect(witness[13]).to.equal(BigInt(outputCommitments[1])); + expect(witness[1]).to.equal(BigInt(ephemeralKeypair.pubKey[0])); + expect(witness[2]).to.equal(BigInt(ephemeralKeypair.pubKey[1])); + expect(witness[11]).to.equal(BigInt(inputCommitments[0])); + expect(witness[12]).to.equal(BigInt(inputCommitments[1])); + expect(witness[13]).to.equal(BigInt(outputCommitments[0])); + expect(witness[14]).to.equal(BigInt(outputCommitments[1])); // take the output from the proof circuit and attempt to decrypt // as the receiver - const cipherText = witness.slice(1, 8); - const recoveredKey = genEcdhSharedKey( + // decrypting the first utxo should succeed + let cipherText = witness.slice(3, 7); + let recoveredKey = genEcdhSharedKey( receiver.privKey, ephemeralKeypair.pubKey, ); - const plainText = poseidonDecrypt( + let plainText = poseidonDecrypt( cipherText, recoveredKey, encryptionNonce, - 4, + 2, ); // use the recovered value (plainText[0]) and salt (plainText[1]) to verify the output commitment - const calculatedHash = poseidonHash([ + let calculatedHash = poseidonHash([ BigInt(plainText[0]), BigInt(plainText[1]), ...receiver.pubKey, ]); expect(calculatedHash).to.equal(outputCommitments[0]); + + // decrypting the second utxo should fail as it belongs to the sender + cipherText = witness.slice(7, 11); + recoveredKey = genEcdhSharedKey(receiver.privKey, ephemeralKeypair.pubKey); + expect(function () { + plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); + }).to.throw( + "The last ciphertext element must match the second item of the permuted state", + ); + + // decrypt using the sender's key should success + recoveredKey = genEcdhSharedKey(sender.privKey, ephemeralKeypair.pubKey); + plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); + calculatedHash = poseidonHash([ + BigInt(plainText[0]), + BigInt(plainText[1]), + ...sender.pubKey, + ]); + expect(calculatedHash).to.equal(outputCommitments[1]); }); it("should fail to generate a witness because mass conservation is not obeyed", async () => { @@ -206,7 +226,7 @@ describe("main circuit tests for Zeto fungible tokens with anonymity with encryp err = e; } // console.log(err); - expect(err).to.match(/Error in template Zeto_105 line: 89/); + expect(err).to.match(/Error in template Zeto_106 line: 82/); }); it("should failed to match output UTXO after decrypting the cipher texts from the events if using the wrong sender public keys", async () => { @@ -268,7 +288,7 @@ describe("main circuit tests for Zeto fungible tokens with anonymity with encryp // take the output from the proof circuit and attempt to decrypt // as the receiver, but without using the correct sender public key const wrongSender = genKeypair(); - const cipherText = witness.slice(1, 5); + const cipherText = witness.slice(3, 7); const recoveredKey = genEcdhSharedKey(receiver.privKey, wrongSender.pubKey); // the decryption scheme has self-checking mechanism, so it should throw an error expect(function () { diff --git a/zkp/js/test/anon_enc_nullifier.js b/zkp/js/test/anon_enc_nullifier.js index 06bd024..4b9c465 100644 --- a/zkp/js/test/anon_enc_nullifier.js +++ b/zkp/js/test/anon_enc_nullifier.js @@ -175,21 +175,36 @@ describe("main circuit tests for Zeto fungible tokens with encryption and anonym // console.log('outputOwnerPublicKeys', [Bob.pubKey, Alice.pubKey]); // console.log('encryptionNonce', encryptionNonce); - expect(witness[10]).to.equal(BigInt(nullifiers[0])); - expect(witness[11]).to.equal(BigInt(nullifiers[1])); - expect(witness[12]).to.equal(proof1.root.bigInt()); + expect(witness[11]).to.equal(BigInt(nullifiers[0])); + expect(witness[12]).to.equal(BigInt(nullifiers[1])); + expect(witness[13]).to.equal(proof1.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver - const cipherText = witness.slice(1, 8); // first 7 elements are the cipher text for the encryption output - const recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); - const plainText = poseidonDecrypt( + // decrypting the first utxo should succeed + let cipherText = witness.slice(3, 7); + let recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); + let plainText = poseidonDecrypt( cipherText, recoveredKey, encryptionNonce, - 4, + 2, ); - expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); + expect(plainText).to.deep.equal([20n, salt3]); + + // decrypting the second utxo should fail as it belongs to the sender + cipherText = witness.slice(7, 11); + recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); + expect(function () { + plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); + }).to.throw( + "The last ciphertext element must match the second item of the permuted state", + ); + + // decrypt using the sender's key should success + recoveredKey = genEcdhSharedKey(Alice.privKey, ephemeralKeypair.pubKey); + plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); + expect(plainText).to.deep.equal([52n, salt4]); }); it("should succeed for valid witness and produce an encypted value - single input", async () => { @@ -279,21 +294,22 @@ describe("main circuit tests for Zeto fungible tokens with encryption and anonym // console.log('outputOwnerPublicKeys', [receiver.pubKey, sender.pubKey]); // console.log('encryptionNonce', encryptionNonce); - expect(witness[10]).to.equal(BigInt(nullifiers[0])); - expect(witness[11]).to.equal(BigInt(nullifiers[1])); - expect(witness[12]).to.equal(proof1.root.bigInt()); + expect(witness[11]).to.equal(BigInt(nullifiers[0])); + expect(witness[12]).to.equal(BigInt(nullifiers[1])); + expect(witness[13]).to.equal(proof1.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver - const cipherText = witness.slice(1, 8); // first 7 elements are the cipher text for the encryption output - const recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); - const plainText = poseidonDecrypt( + // decrypting the first utxo should succeed + let cipherText = witness.slice(3, 7); + let recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); + let plainText = poseidonDecrypt( cipherText, recoveredKey, encryptionNonce, - 4, + 2, ); - expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); + expect(plainText).to.deep.equal([20n, salt3]); }); it("should fail to generate a witness because mass conservation is not obeyed", async () => { @@ -389,8 +405,8 @@ describe("main circuit tests for Zeto fungible tokens with encryption and anonym } catch (e) { err = e; } - // console.log(err); + console.log(err); expect(err).to.match(/Error in template CheckSum_161 line: 44/); - expect(err).to.match(/Error in template Zeto_263 line: 102/); + expect(err).to.match(/Error in template Zeto_264 line: 96/); }); }); diff --git a/zkp/js/test/anon_enc_nullifier_kyc.js b/zkp/js/test/anon_enc_nullifier_kyc.js index 5c034d1..3a6ebd9 100644 --- a/zkp/js/test/anon_enc_nullifier_kyc.js +++ b/zkp/js/test/anon_enc_nullifier_kyc.js @@ -208,22 +208,36 @@ describe("main circuit tests for Zeto fungible tokens with encryption and anonym // console.log('identitiesRoot', proof3.root.bigInt()); // console.log('encryptionNonce', encryptionNonce); - expect(witness[10]).to.equal(BigInt(nullifiers[0])); - expect(witness[11]).to.equal(BigInt(nullifiers[1])); - expect(witness[12]).to.equal(proof1.root.bigInt()); - expect(witness[15]).to.equal(proof3.root.bigInt()); + expect(witness[11]).to.equal(BigInt(nullifiers[0])); + expect(witness[12]).to.equal(BigInt(nullifiers[1])); + expect(witness[13]).to.equal(proof1.root.bigInt()); + expect(witness[16]).to.equal(proof3.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver - const cipherText = witness.slice(1, 8); // first 7 elements are the cipher text for the encryption output - const recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); - const plainText = poseidonDecrypt( + let cipherText = witness.slice(3, 7); + let recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); + let plainText = poseidonDecrypt( cipherText, recoveredKey, encryptionNonce, - 4, + 2, ); - expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); + expect(plainText).to.deep.equal([20n, salt3]); + + // decrypting the second utxo should fail as it belongs to the sender + cipherText = witness.slice(7, 11); + recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); + expect(function () { + plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); + }).to.throw( + "The last ciphertext element must match the second item of the permuted state", + ); + + // decrypt using the sender's key should success + recoveredKey = genEcdhSharedKey(Alice.privKey, ephemeralKeypair.pubKey); + plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); + expect(plainText).to.deep.equal([52n, salt4]); }); it("should fail if not using the right identities merkle proofs", async () => { @@ -338,7 +352,7 @@ describe("main circuit tests for Zeto fungible tokens with encryption and anonym err = e; } // console.log(err); - expect(err).to.match(/Error in template Zeto_266 line: 141/); + expect(err).to.match(/Error in template Zeto_267 line: 135/); expect(err).to.match(/Error in template CheckSMTProof_253 line: 46/); }); }); diff --git a/zkp/js/test/anon_enc_nullifier_non_repudiation.js b/zkp/js/test/anon_enc_nullifier_non_repudiation.js index 0254773..8581b4f 100644 --- a/zkp/js/test/anon_enc_nullifier_non_repudiation.js +++ b/zkp/js/test/anon_enc_nullifier_non_repudiation.js @@ -55,8 +55,8 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re circuit = await wasm_tester( join( __dirname, - "../../circuits/anon_enc_nullifier_non_repudiation.circom", - ), + "../../circuits/anon_enc_nullifier_non_repudiation.circom" + ) ); let keypair = genKeypair(); @@ -120,11 +120,11 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH, + ZERO_HASH ); const proof2 = await smtAlice.generateCircomVerifierProof( input2, - ZERO_HASH, + ZERO_HASH ); // create two output UTXOs, they share the same salt, and different owner @@ -169,7 +169,7 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re authorityPublicKey: Regulator.pubKey, ...encryptInputs, }, - true, + true ); // console.log('witness', witness.slice(0, 25)); @@ -184,34 +184,48 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re // console.log('outputOwnerPublicKeys', [Bob.pubKey, Alice.pubKey]); // console.log('encryptionNonce', encryptionNonce); - expect(witness[26]).to.equal(BigInt(nullifiers[0])); - expect(witness[27]).to.equal(BigInt(nullifiers[1])); - expect(witness[28]).to.equal(proof1.root.bigInt()); + expect(witness[27]).to.equal(BigInt(nullifiers[0])); + expect(witness[28]).to.equal(BigInt(nullifiers[1])); + expect(witness[29]).to.equal(proof1.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver - const cipherText = witness.slice(1, 8); // per the encryption scheme, the output has 7 elements - const recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); - const plainText = poseidonDecrypt( + let cipherText = witness.slice(3, 7); + let recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); + let plainText = poseidonDecrypt( cipherText, recoveredKey, encryptionNonce, - 4, + 2 ); - expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); + expect(plainText).to.deep.equal([20n, salt3]); + + // decrypting the second utxo should fail as it belongs to the sender + cipherText = witness.slice(7, 11); + recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); + expect(function () { + plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); + }).to.throw( + "The last ciphertext element must match the second item of the permuted state" + ); + + // decrypt using the sender's key should success + recoveredKey = genEcdhSharedKey(Alice.privKey, ephemeralKeypair.pubKey); + plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); + expect(plainText).to.deep.equal([52n, salt4]); // take the output from the proof circuit and attempt to decrypt // as the regulator const recoveredKey2 = genEcdhSharedKey( Regulator.privKey, - ephemeralKeypair.pubKey, + ephemeralKeypair.pubKey ); - const cipherText2 = witness.slice(10, 26); // next 16 elements are the cipher text for the second encryption output + const cipherText2 = witness.slice(11, 27); // next 16 elements are the cipher text for the second encryption output const plainText2 = poseidonDecrypt( cipherText2, recoveredKey2, encryptionNonce, - 14, + 14 ); expect(plainText2).to.deep.equal([ Alice.pubKey[0], // input owner public key @@ -258,7 +272,7 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH, + ZERO_HASH ); const proof2 = await smtAlice.generateCircomVerifierProof(0, ZERO_HASH); @@ -304,7 +318,7 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re authorityPublicKey: Regulator.pubKey, ...encryptInputs, }, - true, + true ); // console.log('witness', witness); @@ -319,34 +333,34 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re // console.log('outputOwnerPublicKeys', [receiver.pubKey, sender.pubKey]); // console.log('encryptionNonce', encryptionNonce); - expect(witness[26]).to.equal(BigInt(nullifiers[0])); - expect(witness[27]).to.equal(BigInt(nullifiers[1])); - expect(witness[28]).to.equal(proof1.root.bigInt()); + expect(witness[27]).to.equal(BigInt(nullifiers[0])); + expect(witness[28]).to.equal(BigInt(nullifiers[1])); + expect(witness[29]).to.equal(proof1.root.bigInt()); // take the output from the proof circuit and attempt to decrypt // as the receiver - const cipherText = witness.slice(1, 8); // first 7 elements are the cipher text for the first encryption output + const cipherText = witness.slice(3, 7); const recoveredKey = genEcdhSharedKey(Bob.privKey, ephemeralKeypair.pubKey); const plainText = poseidonDecrypt( cipherText, recoveredKey, encryptionNonce, - 4, + 2 ); - expect(plainText).to.deep.equal([20n, salt3, 52n, salt4]); + expect(plainText).to.deep.equal([20n, salt3]); // take the output from the proof circuit and attempt to decrypt // as the regulator const recoveredKey2 = genEcdhSharedKey( Regulator.privKey, - ephemeralKeypair.pubKey, + ephemeralKeypair.pubKey ); - const cipherText2 = witness.slice(10, 26); // next 16 elements are the cipher text for the second encryption output + const cipherText2 = witness.slice(11, 27); // next 16 elements are the cipher text for the second encryption output const plainText2 = poseidonDecrypt( cipherText2, recoveredKey2, encryptionNonce, - 14, + 14 ); expect(plainText2).to.deep.equal([ Alice.pubKey[0], @@ -405,11 +419,11 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH, + ZERO_HASH ); const proof2 = await smtAlice.generateCircomVerifierProof( input2, - ZERO_HASH, + ZERO_HASH ); // create two output UTXOs, they share the same salt, and different owner @@ -455,13 +469,13 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re authorityPublicKey: Regulator.pubKey, ...encryptInputs, }, - true, + true ); } catch (e) { err = e; } // console.log(err); expect(err).to.match(/Error in template CheckSum_161 line: 44/); - expect(err).to.match(/Error in template Zeto_264 line: 118/); + expect(err).to.match(/Error in template Zeto_265 line: 112/); }); }); From 2b60412dd0229847b8f4c32721ccf82ea9accb03 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 2 Oct 2024 14:20:45 +0100 Subject: [PATCH 22/24] comment out debug log Signed-off-by: Chengxuan Xing --- zkp/js/test/anon_enc_nullifier.js | 2 +- .../anon_enc_nullifier_non_repudiation.js | 34 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/zkp/js/test/anon_enc_nullifier.js b/zkp/js/test/anon_enc_nullifier.js index 4b9c465..efbfc3f 100644 --- a/zkp/js/test/anon_enc_nullifier.js +++ b/zkp/js/test/anon_enc_nullifier.js @@ -405,7 +405,7 @@ describe("main circuit tests for Zeto fungible tokens with encryption and anonym } catch (e) { err = e; } - console.log(err); + // console.log(err); expect(err).to.match(/Error in template CheckSum_161 line: 44/); expect(err).to.match(/Error in template Zeto_264 line: 96/); }); diff --git a/zkp/js/test/anon_enc_nullifier_non_repudiation.js b/zkp/js/test/anon_enc_nullifier_non_repudiation.js index 8581b4f..d543b34 100644 --- a/zkp/js/test/anon_enc_nullifier_non_repudiation.js +++ b/zkp/js/test/anon_enc_nullifier_non_repudiation.js @@ -55,8 +55,8 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re circuit = await wasm_tester( join( __dirname, - "../../circuits/anon_enc_nullifier_non_repudiation.circom" - ) + "../../circuits/anon_enc_nullifier_non_repudiation.circom", + ), ); let keypair = genKeypair(); @@ -120,11 +120,11 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH + ZERO_HASH, ); const proof2 = await smtAlice.generateCircomVerifierProof( input2, - ZERO_HASH + ZERO_HASH, ); // create two output UTXOs, they share the same salt, and different owner @@ -169,7 +169,7 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re authorityPublicKey: Regulator.pubKey, ...encryptInputs, }, - true + true, ); // console.log('witness', witness.slice(0, 25)); @@ -196,7 +196,7 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re cipherText, recoveredKey, encryptionNonce, - 2 + 2, ); expect(plainText).to.deep.equal([20n, salt3]); @@ -206,7 +206,7 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re expect(function () { plainText = poseidonDecrypt(cipherText, recoveredKey, encryptionNonce, 2); }).to.throw( - "The last ciphertext element must match the second item of the permuted state" + "The last ciphertext element must match the second item of the permuted state", ); // decrypt using the sender's key should success @@ -218,14 +218,14 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re // as the regulator const recoveredKey2 = genEcdhSharedKey( Regulator.privKey, - ephemeralKeypair.pubKey + ephemeralKeypair.pubKey, ); const cipherText2 = witness.slice(11, 27); // next 16 elements are the cipher text for the second encryption output const plainText2 = poseidonDecrypt( cipherText2, recoveredKey2, encryptionNonce, - 14 + 14, ); expect(plainText2).to.deep.equal([ Alice.pubKey[0], // input owner public key @@ -272,7 +272,7 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH + ZERO_HASH, ); const proof2 = await smtAlice.generateCircomVerifierProof(0, ZERO_HASH); @@ -318,7 +318,7 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re authorityPublicKey: Regulator.pubKey, ...encryptInputs, }, - true + true, ); // console.log('witness', witness); @@ -345,7 +345,7 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re cipherText, recoveredKey, encryptionNonce, - 2 + 2, ); expect(plainText).to.deep.equal([20n, salt3]); @@ -353,14 +353,14 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re // as the regulator const recoveredKey2 = genEcdhSharedKey( Regulator.privKey, - ephemeralKeypair.pubKey + ephemeralKeypair.pubKey, ); const cipherText2 = witness.slice(11, 27); // next 16 elements are the cipher text for the second encryption output const plainText2 = poseidonDecrypt( cipherText2, recoveredKey2, encryptionNonce, - 14 + 14, ); expect(plainText2).to.deep.equal([ Alice.pubKey[0], @@ -419,11 +419,11 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re // generate the merkle proof for the inputs const proof1 = await smtAlice.generateCircomVerifierProof( input1, - ZERO_HASH + ZERO_HASH, ); const proof2 = await smtAlice.generateCircomVerifierProof( input2, - ZERO_HASH + ZERO_HASH, ); // create two output UTXOs, they share the same salt, and different owner @@ -469,7 +469,7 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re authorityPublicKey: Regulator.pubKey, ...encryptInputs, }, - true + true, ); } catch (e) { err = e; From 81dc7451659158c33d54e0635a8a853075678854 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 2 Oct 2024 15:18:47 +0100 Subject: [PATCH 23/24] fixing golang e2e Signed-off-by: Chengxuan Xing --- go-sdk/integration-test/e2e_test.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/go-sdk/integration-test/e2e_test.go b/go-sdk/integration-test/e2e_test.go index b3ab14d..7376fda 100644 --- a/go-sdk/integration-test/e2e_test.go +++ b/go-sdk/integration-test/e2e_test.go @@ -244,13 +244,13 @@ func (s *E2ETestSuite) TestZeto_2_SuccessfulProving() { assert.Equal(s.T(), 3, len(proof.Proof.A)) assert.Equal(s.T(), 3, len(proof.Proof.B)) assert.Equal(s.T(), 3, len(proof.Proof.C)) - assert.Equal(s.T(), 14, len(proof.PubSignals)) + assert.Equal(s.T(), 15, len(proof.PubSignals)) // the receiver would be able to get the encrypted values and salts // from the transaction events - encryptedValues := make([]*big.Int, 7) - for i := 0; i < 7; i++ { - v, ok := new(big.Int).SetString(proof.PubSignals[i], 10) + encryptedValues := make([]*big.Int, 4) + for i := 0; i < 4; i++ { + v, ok := new(big.Int).SetString(proof.PubSignals[i+2], 10) assert.True(s.T(), ok) encryptedValues[i] = v } @@ -259,14 +259,11 @@ func (s *E2ETestSuite) TestZeto_2_SuccessfulProving() { // for the first output. decrypt using the receiver's private key and compare with // the UTXO hash secret := crypto.GenerateECDHSharedSecret(receiver.PrivateKey, ephemeralKeypair.PublicKey) - decrypted, err := crypto.PoseidonDecrypt(encryptedValues, []*big.Int{secret.X, secret.Y}, encryptionNonce, 4) + decrypted, err := crypto.PoseidonDecrypt(encryptedValues, []*big.Int{secret.X, secret.Y}, encryptionNonce, 2) assert.NoError(s.T(), err) assert.Equal(s.T(), outputValues[0].String(), decrypted[0].String()) assert.Equal(s.T(), salt3.String(), decrypted[1].String()) - assert.Equal(s.T(), outputValues[1].String(), decrypted[2].String()) - assert.Equal(s.T(), salt4.String(), decrypted[3].String()) - // as the receiver, to check if the decryption was successful, we hash the decrypted // value and salt and compare with the output commitment calculatedHash, err := poseidon.Hash([]*big.Int{decrypted[0], decrypted[1], receiver.PublicKey.X, receiver.PublicKey.Y}) @@ -444,7 +441,7 @@ func (s *E2ETestSuite) TestZeto_4_SuccessfulProving() { assert.Equal(s.T(), 3, len(proof.Proof.A)) assert.Equal(s.T(), 3, len(proof.Proof.B)) assert.Equal(s.T(), 3, len(proof.Proof.C)) - assert.Equal(s.T(), 17, len(proof.PubSignals)) + assert.Equal(s.T(), 18, len(proof.PubSignals)) } func (s *E2ETestSuite) TestZeto_5_SuccessfulProving() { From a79aa0f771a310a65655a2faf14962939bf08ab2 Mon Sep 17 00:00:00 2001 From: Chengxuan Xing Date: Wed, 2 Oct 2024 15:35:01 +0100 Subject: [PATCH 24/24] disable result caching for golang e2e Signed-off-by: Chengxuan Xing --- go-sdk/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/go-sdk/Makefile b/go-sdk/Makefile index 1c372c2..e1f5d6b 100644 --- a/go-sdk/Makefile +++ b/go-sdk/Makefile @@ -19,11 +19,10 @@ lint: ${LINT} GOGC=20 $(LINT) run -v --timeout 5m ${LINT}: $(VGO) install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.0 - go-mod-tidy: .ALWAYS $(VGO) mod tidy e2e: test - $(VGO) test -v ./integration-test + $(VGO) test -count=1 -v ./integration-test .ALWAYS: ; clean: $(VGO) clean