diff --git a/.vscode/settings.json b/.vscode/settings.json
index 87b5da09..279a0077 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -2,5 +2,37 @@
"yaml.format.singleQuote": false,
"prettier.enable": true,
"prettier.jsxSingleQuote": false,
- "yaml.format.enable": true
+ "yaml.format.enable": true,
+ "cSpell.words": [
+ "babyjub",
+ "Babyjubjub",
+ "circom",
+ "circomlib",
+ "circomlibjs",
+ "Commonlib",
+ "ECDH",
+ "fflonk",
+ "Groth",
+ "iden",
+ "izeto",
+ "Jubjub",
+ "keypair",
+ "maci",
+ "merkletree",
+ "ptau",
+ "ptaus",
+ "rapidsnark",
+ "snarkjs",
+ "solidityverifier",
+ "supplypike",
+ "tokenid",
+ "UTXO",
+ "UTXOs",
+ "UTXOSMT",
+ "UUPS",
+ "verificationkey",
+ "vkey",
+ "WTNS",
+ "zeto"
+ ]
}
\ No newline at end of file
diff --git a/doc-site/docs/assets/paladin-icon-light.png b/doc-site/docs/assets/paladin-icon-light.png
deleted file mode 100644
index 5222675c..00000000
Binary files a/doc-site/docs/assets/paladin-icon-light.png and /dev/null differ
diff --git a/doc-site/docs/assets/paladin-logo-dark.svg b/doc-site/docs/assets/paladin-logo-dark.svg
deleted file mode 100644
index d326b322..00000000
--- a/doc-site/docs/assets/paladin-logo-dark.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
diff --git a/doc-site/docs/assets/paladin-logo-light.svg b/doc-site/docs/assets/paladin-logo-light.svg
deleted file mode 100644
index d075c322..00000000
--- a/doc-site/docs/assets/paladin-logo-light.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
diff --git a/doc-site/docs/assets/zeto-icon.jpeg b/doc-site/docs/assets/zeto-icon.jpeg
new file mode 100644
index 00000000..d77ebe28
Binary files /dev/null and b/doc-site/docs/assets/zeto-icon.jpeg differ
diff --git a/doc-site/docs/assets/zeto-logo-dark.jpg b/doc-site/docs/assets/zeto-logo-dark.jpg
new file mode 100644
index 00000000..b992c1df
Binary files /dev/null and b/doc-site/docs/assets/zeto-logo-dark.jpg differ
diff --git a/doc-site/docs/assets/zeto-logo-light.jpg b/doc-site/docs/assets/zeto-logo-light.jpg
new file mode 100644
index 00000000..b992c1df
Binary files /dev/null and b/doc-site/docs/assets/zeto-logo-light.jpg differ
diff --git a/doc-site/docs/assets/zeto-logo.png b/doc-site/docs/assets/zeto-logo.png
new file mode 100644
index 00000000..571db4a7
Binary files /dev/null and b/doc-site/docs/assets/zeto-logo.png differ
diff --git a/doc-site/docs/stylesheets/zeto.css b/doc-site/docs/stylesheets/zeto.css
index b4a3d712..ecd8d188 100644
--- a/doc-site/docs/stylesheets/zeto.css
+++ b/doc-site/docs/stylesheets/zeto.css
@@ -43,4 +43,5 @@
display: none;
}
+.md-header__button.md-logo img[alt=zeto] { height: 2rem; }
img[alt=pqc] { width: 75px; border-radius: 15px; }
\ No newline at end of file
diff --git a/doc-site/mkdocs.yml b/doc-site/mkdocs.yml
index f62a436e..79c053c2 100644
--- a/doc-site/mkdocs.yml
+++ b/doc-site/mkdocs.yml
@@ -4,9 +4,9 @@ repo_url: https://github.com/hyperledger-labs/zeto
theme:
name: material
custom_dir: overrides
- logo: assets/paladin-logo-light.svg
- logo_dark: assets/paladin-logo-dark.svg
- favicon: assets/paladin-icon-light.png
+ logo: assets/zeto-logo-light.jpg
+ logo_dark: assets/zeto-logo-dark.jpg
+ favicon: assets/zeto-icon.jpg
icon:
repo: fontawesome/brands/github
palette:
diff --git a/doc-site/overrides/partials/logo.html b/doc-site/overrides/partials/logo.html
index 15a370c1..29a0cbb6 100644
--- a/doc-site/overrides/partials/logo.html
+++ b/doc-site/overrides/partials/logo.html
@@ -21,5 +21,5 @@
-->
-
-
+
+
diff --git a/go-sdk/go.mod b/go-sdk/go.mod
index 67be85c9..e6aad9a9 100644
--- a/go-sdk/go.mod
+++ b/go-sdk/go.mod
@@ -2,7 +2,7 @@ module github.com/hyperledger-labs/zeto/go-sdk
go 1.23.0
-toolchain go1.23.1
+toolchain go1.23.7
require (
github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e
diff --git a/solidity/contracts/verifiers/verifier_anon_nullifier_kyc.sol b/solidity/contracts/verifiers/verifier_anon_nullifier_kyc.sol
index 2b385504..ce117dfa 100644
--- a/solidity/contracts/verifiers/verifier_anon_nullifier_kyc.sol
+++ b/solidity/contracts/verifiers/verifier_anon_nullifier_kyc.sol
@@ -43,8 +43,8 @@ contract Groth16Verifier_AnonNullifierKyc {
uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
- uint256 constant IC0x = 17336513663167332377949169478575466284101907029078607810833872321788374659601;
- uint256 constant IC0y = 10397020245967735952916558183702669414774017177600319015152617686952244560097;
+ uint256 constant IC0x = 1368020126977316196213187057636983114330468061731699977744344817587788882990;
+ uint256 constant IC0y = 7686063895143330261591855899880142399404728944441362517893141962995856727929;
uint256 constant IC1x = 14502254530076089964675033671517993862419783705089359180705605116873724842019;
uint256 constant IC1y = 9049190990509151956509627927047158802465613185726643157556086701266946091568;
@@ -52,17 +52,17 @@ contract Groth16Verifier_AnonNullifierKyc {
uint256 constant IC2x = 3455128039314231841012773119366413118715790719104028464745205146228319556246;
uint256 constant IC2y = 13175890403996370630092498196483049850968580675778268285842736204668575597675;
- uint256 constant IC3x = 21609063410160746920311288333521282110904871128213587386326528382033849936047;
- uint256 constant IC3y = 19053685498975284212451452487100951511472691870576100676350891466084386725324;
+ uint256 constant IC3x = 13393887812211802083177209056510129401898394892926768888874562627657192399962;
+ uint256 constant IC3y = 9042351346749284573092801161759462514076637268352518870596537996458419743091;
- uint256 constant IC4x = 20839558467714218135816548507020277920013840149039689464195289045825016957066;
- uint256 constant IC4y = 18171040984983395519673410253443945069876908714083596530196234237277378369754;
+ uint256 constant IC4x = 19203333608926332054415117565053561595496895142521866494460868409916811713957;
+ uint256 constant IC4y = 4334310208006613584617716058867417381004655491738058483537403401767079516612;
- uint256 constant IC5x = 10186020517678246646201919013132136611100376409259802036221169773081382803557;
- uint256 constant IC5y = 2024398128793281448742186646024870038510529605597905826731951443459182184482;
+ uint256 constant IC5x = 8459703094760317168584339428426828704909860684147786556335328845261416934167;
+ uint256 constant IC5y = 5466581123301380049065739652342512947564262375698860839217249516144678047196;
- uint256 constant IC6x = 6817038550232615580081523910729732019328824723898271013459916846209181496148;
- uint256 constant IC6y = 5007540534237292740105202068038033915182587070518049525579057126474202747048;
+ uint256 constant IC6x = 15924950080287000946685929883765297309673360990922044949928505866624182997859;
+ uint256 constant IC6y = 5360581200037747345688259956951448973597185992056174685326726615654044407192;
uint256 constant IC7x = 9672280002529117458221100657711877410026000365131526255571070587277130104994;
uint256 constant IC7y = 8600285172183660002776649258511861921290142756223662537727755349462907425056;
diff --git a/solidity/contracts/verifiers/verifier_anon_nullifier_kyc_batch.sol b/solidity/contracts/verifiers/verifier_anon_nullifier_kyc_batch.sol
index b806e45f..ae84d105 100644
--- a/solidity/contracts/verifiers/verifier_anon_nullifier_kyc_batch.sol
+++ b/solidity/contracts/verifiers/verifier_anon_nullifier_kyc_batch.sol
@@ -43,8 +43,8 @@ contract Groth16Verifier_AnonNullifierKycBatch {
uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
- uint256 constant IC0x = 5903479180487694997279265064344131881874542681454350742852120100073440524296;
- uint256 constant IC0y = 9530657098554586749733666785385875949917582344806050500162894090355413522611;
+ uint256 constant IC0x = 17956394547302156521165787305425039553395368579665815878321069616384660821974;
+ uint256 constant IC0y = 6992882796389782419988913396487952889902510842290875072729183489463067562180;
uint256 constant IC1x = 20973102971231858407268823830547921302985922314772564832818590542439356456221;
uint256 constant IC1y = 8755463976472172454997983726165070757321336399692622916062903478185835201876;
@@ -76,41 +76,41 @@ contract Groth16Verifier_AnonNullifierKycBatch {
uint256 constant IC10x = 10027027914330943530569092473741094434086563269833520803780904295572828067751;
uint256 constant IC10y = 421990751027288915733155885330259124989116330315517655643992915427432279442;
- uint256 constant IC11x = 599244215281404141046456725437495318313391113948484631072822414812570716776;
- uint256 constant IC11y = 10068255294045654417350386146388876221615727778457099371804026702882247474491;
+ uint256 constant IC11x = 11892755591860674046473115755992830180366136817328130148390945571128812998539;
+ uint256 constant IC11y = 9268798073089241248606702568568173938283201894666754305960489893725720318606;
- uint256 constant IC12x = 21556964792859825649107667215781058705147965296731829911281160087820610838533;
- uint256 constant IC12y = 13889886910952233505246502579980063028755614337122208662602852777579996569369;
+ uint256 constant IC12x = 10152555671693387741890273303761544089843267797975508348153732359110012549852;
+ uint256 constant IC12y = 6851215785130794843983404241253819330754997644123241414047997028799190421511;
- uint256 constant IC13x = 20336517095597583565227873677117826914448174923218395440417472253759155911879;
- uint256 constant IC13y = 13787294756325562052369133551051867132268321423810906151242602397719118060605;
+ uint256 constant IC13x = 15926389673646585067450607026615448882721273998707051750117711890545377843835;
+ uint256 constant IC13y = 6092524264858685061882637835001794548781930013420575912363384400816087682216;
- uint256 constant IC14x = 723470074228247172376833529746853811390760610497044842304414745837297007793;
- uint256 constant IC14y = 20473431670688220490381842545562296561006547604975254617604046916777297966342;
+ uint256 constant IC14x = 13758282793278046562484444741285107092317198764383609568883044140011006548296;
+ uint256 constant IC14y = 13297381771926142142906590533466958927079262003147219405302530238513936419715;
- uint256 constant IC15x = 15002382818055737103129754932077118357634513012564080449864984893716211852169;
- uint256 constant IC15y = 20986355934261372161815389867821841925843222171872598595602774389117273842363;
+ uint256 constant IC15x = 8974123089488822435414123220888650328624602168169290172017148632209729116247;
+ uint256 constant IC15y = 7022946489738753214417591939848011153517681920411366193658001703205231678394;
- uint256 constant IC16x = 12194141240267141280402887975844644072507435166373817904521349435520239196563;
- uint256 constant IC16y = 14593389642349486216409486354692535004279895256912795030101019816199908203510;
+ uint256 constant IC16x = 20285092191624000431458767079646131768817472892775292620424272081037439332800;
+ uint256 constant IC16y = 14677998525481291699643046995288705154622139789585886228695961572520744332931;
- uint256 constant IC17x = 21015394223495022989411464000109008933122362273422924620851048926767533637678;
- uint256 constant IC17y = 19949217149297160174771427449019144865727740578144251352593703549274424714243;
+ uint256 constant IC17x = 8653881030606523422653589889738043954964914655770505886480501697282389807422;
+ uint256 constant IC17y = 17802396532844609366494957607232915674517758974199893104755207809450698359725;
- uint256 constant IC18x = 3943681362690863707194051007800503356665352728683045015484432282818996793654;
- uint256 constant IC18y = 5926512517402465313700496622240148434683755798658418845914485987943511193577;
+ uint256 constant IC18x = 14222398084106517583634417674989764066430290828203827716243250821844511251642;
+ uint256 constant IC18y = 6595930713961692153773738963013914489592721577697364968088466912149388548163;
- uint256 constant IC19x = 18521510625410973039043143625576116776310762869742273135122587764220766348395;
- uint256 constant IC19y = 7566293396936121921157226464680078121529744119588821801602132955535815373956;
+ uint256 constant IC19x = 12301660154151583884980964450898433820033490381713715854436873218466423853515;
+ uint256 constant IC19y = 4868266765264225304664047279128447863928184956669291516153146669883676129155;
- uint256 constant IC20x = 6955777603382581542780895326909850846348823267515133043834193460373252526587;
- uint256 constant IC20y = 5404988211516657994220064031142977435521957627605222735616136075971916277477;
+ uint256 constant IC20x = 5600239864290768624288046938500983244220814692930262847591352146343383885481;
+ uint256 constant IC20y = 2725094490550109268734974010025210344524901385710087689968146552059031411979;
- uint256 constant IC21x = 15342762311956869996626100728582941890438868605264297782193785457846632248470;
- uint256 constant IC21y = 20548254230250891011773309995179021079622280572238402743503817964378124498364;
+ uint256 constant IC21x = 6506763475723656181886384700320184865762413529344881749723025499240876882623;
+ uint256 constant IC21y = 10863601731071513803837079879724831979468910760425582740082420817744191562393;
- uint256 constant IC22x = 13468425754230748688976754818188805414992261059993406476820218042607689692919;
- uint256 constant IC22y = 19259260110764955907957588951746942381445285741917061612123980235317042412735;
+ uint256 constant IC22x = 11014910699225719219658528849253210342134261845924428798796231729535338732066;
+ uint256 constant IC22y = 11833382714481648781585346617218200770199760228872321410398030590697079674233;
uint256 constant IC23x = 7617190663029341979667377709868897026767966101370820487323419742367227464607;
uint256 constant IC23y = 5828305386936705254095338960335559624881719900670519001227372129217412593638;
diff --git a/zkp/circuits/basetokens/anon_base.circom b/zkp/circuits/basetokens/anon_base.circom
index 8a01e6f5..e23b33bf 100644
--- a/zkp/circuits/basetokens/anon_base.circom
+++ b/zkp/circuits/basetokens/anon_base.circom
@@ -43,12 +43,24 @@ template Zeto(nInputs, nOutputs) {
var inputOwnerPubKeyAx, inputOwnerPubKeyAy;
(inputOwnerPubKeyAx, inputOwnerPubKeyAy) = BabyPbk()(in <== inputOwnerPrivateKey);
- var inputOwnerPublicKeys[nInputs][2];
+ CheckPositive(nOutputs)(outputValues <== outputValues);
+
+ CommitmentInputs() inAuxInputs[nInputs];
for (var i = 0; i < nInputs; i++) {
- inputOwnerPublicKeys[i]= [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
+ inAuxInputs[i].value <== inputValues[i];
+ inAuxInputs[i].salt <== inputSalts[i];
+ inAuxInputs[i].ownerPublicKey <== [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
}
- CheckPositive(nOutputs)(outputValues <== outputValues);
- CheckHashes(nInputs)(commitments <== inputCommitments, values <== inputValues, salts <== inputSalts, ownerPublicKeys <== inputOwnerPublicKeys);
- CheckHashes(nOutputs)(commitments <== outputCommitments, values <== outputValues, salts <== outputSalts, ownerPublicKeys <== outputOwnerPublicKeys);
+
+ CommitmentInputs() outAuxInputs[nOutputs];
+ for (var i = 0; i < nOutputs; i++) {
+ outAuxInputs[i].value <== outputValues[i];
+ outAuxInputs[i].salt <== outputSalts[i];
+ outAuxInputs[i].ownerPublicKey <== outputOwnerPublicKeys[i];
+ }
+
+ CheckHashes(nInputs)(commitmentHashes <== inputCommitments, commitmentInputs <== inAuxInputs);
+ CheckHashes(nOutputs)(commitmentHashes <== outputCommitments, commitmentInputs <== outAuxInputs);
+
CheckSum(nInputs, nOutputs)(inputValues <== inputValues, outputValues <== outputValues);
}
diff --git a/zkp/circuits/basetokens/anon_enc_base.circom b/zkp/circuits/basetokens/anon_enc_base.circom
index 9c3e3da6..5eabedc9 100644
--- a/zkp/circuits/basetokens/anon_enc_base.circom
+++ b/zkp/circuits/basetokens/anon_enc_base.circom
@@ -55,18 +55,26 @@ template Zeto(nInputs, nOutputs) {
var inputOwnerPubKeyAx, inputOwnerPubKeyAy;
(inputOwnerPubKeyAx, inputOwnerPubKeyAy) = BabyPbk()(in <== inputOwnerPrivateKey);
- var inputOwnerPublicKeys[nInputs][2];
+ CheckPositive(nOutputs)(outputValues <== outputValues);
+
+ CommitmentInputs() inAuxInputs[nInputs];
for (var i = 0; i < nInputs; i++) {
- inputOwnerPublicKeys[i]= [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
+ inAuxInputs[i].value <== inputValues[i];
+ inAuxInputs[i].salt <== inputSalts[i];
+ inAuxInputs[i].ownerPublicKey <== [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
}
- CheckPositive(nOutputs)(outputValues <== outputValues);
-
- CheckHashes(nInputs)(commitments <== inputCommitments, values <== inputValues, salts <== inputSalts, ownerPublicKeys <== inputOwnerPublicKeys);
+ CommitmentInputs() outAuxInputs[nOutputs];
+ for (var i = 0; i < nOutputs; i++) {
+ outAuxInputs[i].value <== outputValues[i];
+ outAuxInputs[i].salt <== outputSalts[i];
+ outAuxInputs[i].ownerPublicKey <== outputOwnerPublicKeys[i];
+ }
- CheckHashes(nOutputs)(commitments <== outputCommitments, values <== outputValues, salts <== outputSalts, ownerPublicKeys <== outputOwnerPublicKeys);
+ CheckHashes(nInputs)(commitmentHashes <== inputCommitments, commitmentInputs <== inAuxInputs);
+ CheckHashes(nOutputs)(commitmentHashes <== outputCommitments, commitmentInputs <== outAuxInputs);
CheckSum(nInputs, nOutputs)(inputValues <== inputValues, outputValues <== outputValues);
- (ecdhPublicKey,cipherTexts ) <== EncryptOutputs(nOutputs)(ecdhPrivateKey <== ecdhPrivateKey, outputValues <== outputValues, outputSalts <== outputSalts, outputOwnerPublicKeys <== outputOwnerPublicKeys, encryptionNonce <== encryptionNonce);
+ (ecdhPublicKey,cipherTexts ) <== EncryptOutputs(nOutputs)(ecdhPrivateKey <== ecdhPrivateKey, encryptionNonce <== encryptionNonce, commitmentInputs <== outAuxInputs);
}
diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_base.circom
index ba863623..fa0d39aa 100644
--- a/zkp/circuits/basetokens/anon_enc_nullifier_base.circom
+++ b/zkp/circuits/basetokens/anon_enc_nullifier_base.circom
@@ -62,16 +62,24 @@ template Zeto(nInputs, nOutputs, nSMTLevels) {
var inputOwnerPubKeyAx, inputOwnerPubKeyAy;
(inputOwnerPubKeyAx, inputOwnerPubKeyAy) = BabyPbk()(in <== inputOwnerPrivateKey);
- var inputOwnerPublicKeys[nInputs][2];
+ CheckPositive(nOutputs)(outputValues <== outputValues);
+
+ CommitmentInputs() inAuxInputs[nInputs];
for (var i = 0; i < nInputs; i++) {
- inputOwnerPublicKeys[i]= [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
+ inAuxInputs[i].value <== inputValues[i];
+ inAuxInputs[i].salt <== inputSalts[i];
+ inAuxInputs[i].ownerPublicKey <== [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
}
- CheckPositive(nOutputs)(outputValues <== outputValues);
-
- CheckHashes(nInputs)(commitments <== inputCommitments, values <== inputValues, salts <== inputSalts, ownerPublicKeys <== inputOwnerPublicKeys);
+ CommitmentInputs() outAuxInputs[nOutputs];
+ for (var i = 0; i < nOutputs; i++) {
+ outAuxInputs[i].value <== outputValues[i];
+ outAuxInputs[i].salt <== outputSalts[i];
+ outAuxInputs[i].ownerPublicKey <== outputOwnerPublicKeys[i];
+ }
- CheckHashes(nOutputs)(commitments <== outputCommitments, values <== outputValues, salts <== outputSalts, ownerPublicKeys <== outputOwnerPublicKeys);
+ CheckHashes(nInputs)(commitmentHashes <== inputCommitments, commitmentInputs <== inAuxInputs);
+ CheckHashes(nOutputs)(commitmentHashes <== outputCommitments, commitmentInputs <== outAuxInputs);
CheckNullifiers(nInputs)(nullifiers <== nullifiers, values <== inputValues, salts <== inputSalts, ownerPrivateKey <== inputOwnerPrivateKey);
@@ -84,5 +92,5 @@ template Zeto(nInputs, nOutputs, nSMTLevels) {
// Merkle Tree with the root `root`.
CheckSMTProof(nInputs, nSMTLevels)(root <== root, merkleProof <== merkleProof, enabled <== enabled, leafNodeIndexes <== inputCommitments, leafNodeValues <== inputCommitments);
- (ecdhPublicKey, cipherTexts) <== EncryptOutputs(nOutputs)(ecdhPrivateKey <== ecdhPrivateKey, outputValues <== outputValues, outputSalts <== outputSalts, outputOwnerPublicKeys <== outputOwnerPublicKeys, encryptionNonce <== encryptionNonce);
+ (ecdhPublicKey, cipherTexts) <== EncryptOutputs(nOutputs)(ecdhPrivateKey <== ecdhPrivateKey, encryptionNonce <== encryptionNonce, commitmentInputs <== outAuxInputs);
}
diff --git a/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom b/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom
index 8450f2bd..3fa689fc 100644
--- a/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom
+++ b/zkp/circuits/basetokens/anon_enc_nullifier_kyc_base.circom
@@ -65,16 +65,24 @@ template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) {
var inputOwnerPubKeyAx, inputOwnerPubKeyAy;
(inputOwnerPubKeyAx, inputOwnerPubKeyAy) = BabyPbk()(in <== inputOwnerPrivateKey);
- var inputOwnerPublicKeys[nInputs][2];
+ CheckPositive(nOutputs)(outputValues <== outputValues);
+
+ CommitmentInputs() inAuxInputs[nInputs];
for (var i = 0; i < nInputs; i++) {
- inputOwnerPublicKeys[i]= [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
+ inAuxInputs[i].value <== inputValues[i];
+ inAuxInputs[i].salt <== inputSalts[i];
+ inAuxInputs[i].ownerPublicKey <== [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
}
- CheckPositive(nOutputs)(outputValues <== outputValues);
-
- CheckHashes(nInputs)(commitments <== inputCommitments, values <== inputValues, salts <== inputSalts, ownerPublicKeys <== inputOwnerPublicKeys);
+ CommitmentInputs() outAuxInputs[nOutputs];
+ for (var i = 0; i < nOutputs; i++) {
+ outAuxInputs[i].value <== outputValues[i];
+ outAuxInputs[i].salt <== outputSalts[i];
+ outAuxInputs[i].ownerPublicKey <== outputOwnerPublicKeys[i];
+ }
- CheckHashes(nOutputs)(commitments <== outputCommitments, values <== outputValues, salts <== outputSalts, ownerPublicKeys <== outputOwnerPublicKeys);
+ CheckHashes(nInputs)(commitmentHashes <== inputCommitments, commitmentInputs <== inAuxInputs);
+ CheckHashes(nOutputs)(commitmentHashes <== outputCommitments, commitmentInputs <== outAuxInputs);
CheckNullifiers(nInputs)(nullifiers <== nullifiers, values <== inputValues, salts <== inputSalts, ownerPrivateKey <== inputOwnerPrivateKey);
@@ -101,5 +109,5 @@ template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) {
CheckSMTProof(nOutputs + 1, nIdentitiesSMTLevels)(root <== identitiesRoot, merkleProof <== identitiesMerkleProof, enabled <== identitiesMTPCheckEnabled, leafNodeIndexes <== ownerPublicKeyHashes, leafNodeValues <== ownerPublicKeyHashes);
- (ecdhPublicKey, cipherTexts) <== EncryptOutputs(nOutputs)(ecdhPrivateKey <== ecdhPrivateKey, outputValues <== outputValues, outputSalts <== outputSalts, outputOwnerPublicKeys <== outputOwnerPublicKeys, encryptionNonce <== encryptionNonce);
+ (ecdhPublicKey, cipherTexts) <== EncryptOutputs(nOutputs)(ecdhPrivateKey <== ecdhPrivateKey, encryptionNonce <== encryptionNonce, commitmentInputs <== outAuxInputs);
}
\ 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 001a10b5..5aebb884 100644
--- a/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom
+++ b/zkp/circuits/basetokens/anon_enc_nullifier_non_repudiation_base.circom
@@ -78,16 +78,24 @@ template Zeto(nInputs, nOutputs, nSMTLevels) {
var inputOwnerPubKeyAx, inputOwnerPubKeyAy;
(inputOwnerPubKeyAx, inputOwnerPubKeyAy) = BabyPbk()(in <== inputOwnerPrivateKey);
- var inputOwnerPublicKeys[nInputs][2];
+ CheckPositive(nOutputs)(outputValues <== outputValues);
+
+ CommitmentInputs() inAuxInputs[nInputs];
for (var i = 0; i < nInputs; i++) {
- inputOwnerPublicKeys[i] = [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
+ inAuxInputs[i].value <== inputValues[i];
+ inAuxInputs[i].salt <== inputSalts[i];
+ inAuxInputs[i].ownerPublicKey <== [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
}
- CheckPositive(nOutputs)(outputValues <== outputValues);
-
- CheckHashes(nInputs)(commitments <== inputCommitments, values <== inputValues, salts <== inputSalts, ownerPublicKeys <== inputOwnerPublicKeys);
+ CommitmentInputs() outAuxInputs[nOutputs];
+ for (var i = 0; i < nOutputs; i++) {
+ outAuxInputs[i].value <== outputValues[i];
+ outAuxInputs[i].salt <== outputSalts[i];
+ outAuxInputs[i].ownerPublicKey <== outputOwnerPublicKeys[i];
+ }
- CheckHashes(nOutputs)(commitments <== outputCommitments, values <== outputValues, salts <== outputSalts, ownerPublicKeys <== outputOwnerPublicKeys);
+ CheckHashes(nInputs)(commitmentHashes <== inputCommitments, commitmentInputs <== inAuxInputs);
+ CheckHashes(nOutputs)(commitmentHashes <== outputCommitments, commitmentInputs <== outAuxInputs);
CheckNullifiers(nInputs)(nullifiers <== nullifiers, values <== inputValues, salts <== inputSalts, ownerPrivateKey <== inputOwnerPrivateKey);
@@ -100,7 +108,7 @@ template Zeto(nInputs, nOutputs, nSMTLevels) {
CheckSMTProof(nInputs, nSMTLevels)(root <== root, merkleProof <== merkleProof, enabled <== enabled, leafNodeIndexes <== inputCommitments, leafNodeValues <== inputCommitments);
// Generate cipher text for output utxos
- (ecdhPublicKey, cipherTexts) <== EncryptOutputs(nOutputs)(ecdhPrivateKey <== ecdhPrivateKey, outputValues <== outputValues, outputSalts <== outputSalts, outputOwnerPublicKeys <== outputOwnerPublicKeys, encryptionNonce <== encryptionNonce);
+ (ecdhPublicKey, cipherTexts) <== EncryptOutputs(nOutputs)(ecdhPrivateKey <== ecdhPrivateKey, encryptionNonce <== encryptionNonce, commitmentInputs <== outAuxInputs);
// generate shared secret for the authority
var sharedSecretAuthority[2];
diff --git a/zkp/circuits/basetokens/anon_nullifier_base.circom b/zkp/circuits/basetokens/anon_nullifier_base.circom
index 550e30bb..9ff1b0a9 100644
--- a/zkp/circuits/basetokens/anon_nullifier_base.circom
+++ b/zkp/circuits/basetokens/anon_nullifier_base.circom
@@ -54,16 +54,24 @@ template Zeto(nInputs, nOutputs, nSMTLevels) {
var inputOwnerPubKeyAx, inputOwnerPubKeyAy;
(inputOwnerPubKeyAx, inputOwnerPubKeyAy) = BabyPbk()(in <== inputOwnerPrivateKey);
- var inputOwnerPublicKeys[nInputs][2];
+ CheckPositive(nOutputs)(outputValues <== outputValues);
+
+ CommitmentInputs() inAuxInputs[nInputs];
for (var i = 0; i < nInputs; i++) {
- inputOwnerPublicKeys[i] = [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
+ inAuxInputs[i].value <== inputValues[i];
+ inAuxInputs[i].salt <== inputSalts[i];
+ inAuxInputs[i].ownerPublicKey <== [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
}
- CheckPositive(nOutputs)(outputValues <== outputValues);
-
- CheckHashes(nInputs)(commitments <== inputCommitments, values <== inputValues, salts <== inputSalts, ownerPublicKeys <== inputOwnerPublicKeys);
+ CommitmentInputs() outAuxInputs[nOutputs];
+ for (var i = 0; i < nOutputs; i++) {
+ outAuxInputs[i].value <== outputValues[i];
+ outAuxInputs[i].salt <== outputSalts[i];
+ outAuxInputs[i].ownerPublicKey <== outputOwnerPublicKeys[i];
+ }
- CheckHashes(nOutputs)(commitments <== outputCommitments, values <== outputValues, salts <== outputSalts, ownerPublicKeys <== outputOwnerPublicKeys);
+ CheckHashes(nInputs)(commitmentHashes <== inputCommitments, commitmentInputs <== inAuxInputs);
+ CheckHashes(nOutputs)(commitmentHashes <== outputCommitments, commitmentInputs <== outAuxInputs);
CheckNullifiers(nInputs)(nullifiers <== nullifiers, values <== inputValues, salts <== inputSalts, ownerPrivateKey <== inputOwnerPrivateKey);
diff --git a/zkp/circuits/basetokens/anon_nullifier_kyc_base.circom b/zkp/circuits/basetokens/anon_nullifier_kyc_base.circom
index 3e83d932..d77889d5 100644
--- a/zkp/circuits/basetokens/anon_nullifier_kyc_base.circom
+++ b/zkp/circuits/basetokens/anon_nullifier_kyc_base.circom
@@ -56,16 +56,24 @@ template Zeto(nInputs, nOutputs, nUTXOSMTLevels, nIdentitiesSMTLevels) {
var inputOwnerPubKeyAx, inputOwnerPubKeyAy;
(inputOwnerPubKeyAx, inputOwnerPubKeyAy) = BabyPbk()(in <== inputOwnerPrivateKey);
- var inputOwnerPublicKeys[nInputs][2];
+ CheckPositive(nOutputs)(outputValues <== outputValues);
+
+ CommitmentInputs() inAuxInputs[nInputs];
for (var i = 0; i < nInputs; i++) {
- inputOwnerPublicKeys[i] = [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
+ inAuxInputs[i].value <== inputValues[i];
+ inAuxInputs[i].salt <== inputSalts[i];
+ inAuxInputs[i].ownerPublicKey <== [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
}
- CheckPositive(nOutputs)(outputValues <== outputValues);
-
- CheckHashes(nInputs)(commitments <== inputCommitments, values <== inputValues, salts <== inputSalts, ownerPublicKeys <== inputOwnerPublicKeys);
+ CommitmentInputs() outAuxInputs[nOutputs];
+ for (var i = 0; i < nOutputs; i++) {
+ outAuxInputs[i].value <== outputValues[i];
+ outAuxInputs[i].salt <== outputSalts[i];
+ outAuxInputs[i].ownerPublicKey <== outputOwnerPublicKeys[i];
+ }
- CheckHashes(nOutputs)(commitments <== outputCommitments, values <== outputValues, salts <== outputSalts, ownerPublicKeys <== outputOwnerPublicKeys);
+ CheckHashes(nInputs)(commitmentHashes <== inputCommitments, commitmentInputs <== inAuxInputs);
+ CheckHashes(nOutputs)(commitmentHashes <== outputCommitments, commitmentInputs <== outAuxInputs);
CheckNullifiers(nInputs)(nullifiers <== nullifiers, values <== inputValues, salts <== inputSalts, ownerPrivateKey <== inputOwnerPrivateKey);
diff --git a/zkp/circuits/check_nullifiers.circom b/zkp/circuits/check_nullifiers.circom
index 3dd7616e..4bab5d5c 100644
--- a/zkp/circuits/check_nullifiers.circom
+++ b/zkp/circuits/check_nullifiers.circom
@@ -25,11 +25,11 @@ include "./node_modules/circomlib/circuits/babyjub.circom";
// commitment = hash(value, salt, ownerPublicKey1, ownerPublicKey2)
// nullifier = hash(value, salt, ownerPrivatekey)
//
-template Zeto(numInputs) {
- signal input nullifiers[numInputs];
- signal input inputCommitments[numInputs];
- signal input inputValues[numInputs];
- signal input inputSalts[numInputs];
+template Zeto(nInputs) {
+ 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;
@@ -41,14 +41,16 @@ template Zeto(numInputs) {
var inputOwnerPubKeyAx, inputOwnerPubKeyAy;
(inputOwnerPubKeyAx, inputOwnerPubKeyAy) = BabyPbk()(in <== inputOwnerPrivateKey);
- var inputOwnerPublicKeys[numInputs][2];
- for (var i = 0; i < numInputs; i++) {
- inputOwnerPublicKeys[i] = [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
+ CommitmentInputs() auxInputs[nInputs];
+ for (var i = 0; i < nInputs; i++) {
+ auxInputs[i].value <== inputValues[i];
+ auxInputs[i].salt <== inputSalts[i];
+ auxInputs[i].ownerPublicKey <== [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
}
- CheckHashes(numInputs)(commitments <== inputCommitments, values <== inputValues, salts <== inputSalts, ownerPublicKeys <== inputOwnerPublicKeys);
+ CheckHashes(nInputs)(commitmentHashes <== inputCommitments, commitmentInputs <== auxInputs);
- CheckNullifiers(numInputs)(nullifiers <== nullifiers, values <== inputValues, salts <== inputSalts, ownerPrivateKey <== inputOwnerPrivateKey);
+ CheckNullifiers(nInputs)(nullifiers <== nullifiers, values <== inputValues, salts <== inputSalts, ownerPrivateKey <== inputOwnerPrivateKey);
}
component main { public [ nullifiers, inputCommitments ] } = Zeto(2);
\ No newline at end of file
diff --git a/zkp/circuits/deposit.circom b/zkp/circuits/deposit.circom
index 32c86f42..c822f91d 100644
--- a/zkp/circuits/deposit.circom
+++ b/zkp/circuits/deposit.circom
@@ -27,7 +27,14 @@ template Zeto(nOutputs) {
CheckPositive(nOutputs)(outputValues <== outputValues);
- CheckHashes(nOutputs)(commitments <== outputCommitments, values <== outputValues, salts <== outputSalts, ownerPublicKeys <== outputOwnerPublicKeys);
+ CommitmentInputs() auxInputs[nOutputs];
+ for (var i = 0; i < nOutputs; i++) {
+ auxInputs[i].value <== outputValues[i];
+ auxInputs[i].salt <== outputSalts[i];
+ auxInputs[i].ownerPublicKey <== outputOwnerPublicKeys[i];
+ }
+
+ CheckHashes(nOutputs)(commitmentHashes <== outputCommitments, commitmentInputs <== auxInputs);
// calculate the sum of output values and set to the output
var sumOutputs = 0;
diff --git a/zkp/circuits/lib/burn-nullifiers.circom b/zkp/circuits/lib/burn-nullifiers.circom
index d1b859b0..4e014568 100644
--- a/zkp/circuits/lib/burn-nullifiers.circom
+++ b/zkp/circuits/lib/burn-nullifiers.circom
@@ -61,11 +61,21 @@ template BurnNullifiers(numInputs, nSMTLevels) {
CheckPositive(1)(outputValues <== [outputValue]);
- CheckHashes(numInputs)(commitments <== inputCommitments, values <== inputValues, salts <== inputSalts, ownerPublicKeys <== ownerPublicKeys);
+ CommitmentInputs() inAuxInputs[numInputs];
+ for (var i = 0; i < numInputs; i++) {
+ inAuxInputs[i].value <== inputValues[i];
+ inAuxInputs[i].salt <== inputSalts[i];
+ inAuxInputs[i].ownerPublicKey <== [ownerPubKeyAx, ownerPubKeyAy];
+ }
+ CheckHashes(numInputs)(commitmentHashes <== inputCommitments, commitmentInputs <== inAuxInputs);
CheckNullifiers(numInputs)(nullifiers <== nullifiers, values <== inputValues, salts <== inputSalts, ownerPrivateKey <== ownerPrivateKey);
- CheckHashes(1)(commitments <== [outputCommitment], values <== [outputValue], salts <== [outputSalt], ownerPublicKeys <== [[ownerPubKeyAx, ownerPubKeyAy]]);
+ CommitmentInputs() outAuxInputs[1];
+ outAuxInputs[0].value <== outputValue;
+ outAuxInputs[0].salt <== outputSalt;
+ outAuxInputs[0].ownerPublicKey <== [ownerPubKeyAx, ownerPubKeyAy];
+ CheckHashes(1)(commitmentHashes <== [outputCommitment], commitmentInputs <== outAuxInputs);
// With the above steps, we demonstrated that the nullifiers
// are securely bound to the input commitments. Now we need to
diff --git a/zkp/circuits/lib/burn.circom b/zkp/circuits/lib/burn.circom
index 1af64881..58c65e87 100644
--- a/zkp/circuits/lib/burn.circom
+++ b/zkp/circuits/lib/burn.circom
@@ -52,9 +52,19 @@ template Burn(numInputs) {
CheckPositive(1)(outputValues <== [outputValue]);
- CheckHashes(numInputs)(commitments <== inputCommitments, values <== inputValues, salts <== inputSalts, ownerPublicKeys <== ownerPublicKeys);
+ CommitmentInputs() inAuxInputs[numInputs];
+ for (var i = 0; i < numInputs; i++) {
+ inAuxInputs[i].value <== inputValues[i];
+ inAuxInputs[i].salt <== inputSalts[i];
+ inAuxInputs[i].ownerPublicKey <== [ownerPubKeyAx, ownerPubKeyAy];
+ }
+ CheckHashes(numInputs)(commitmentHashes <== inputCommitments, commitmentInputs <== inAuxInputs);
- CheckHashes(1)(commitments <== [outputCommitment], values <== [outputValue], salts <== [outputSalt], ownerPublicKeys <== [[ownerPubKeyAx, ownerPubKeyAy]]);
+ CommitmentInputs() outAuxInputs[1];
+ outAuxInputs[0].value <== outputValue;
+ outAuxInputs[0].salt <== outputSalt;
+ outAuxInputs[0].ownerPublicKey <== [ownerPubKeyAx, ownerPubKeyAy];
+ CheckHashes(1)(commitmentHashes <== [outputCommitment], commitmentInputs <== outAuxInputs);
// check that the sum of input values is greater than or equal to the sum of output values
var sumInputs = 0;
diff --git a/zkp/circuits/lib/buses.circom b/zkp/circuits/lib/buses.circom
new file mode 100644
index 00000000..861e289d
--- /dev/null
+++ b/zkp/circuits/lib/buses.circom
@@ -0,0 +1,33 @@
+// Copyright © 2025 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.2.2;
+
+bus CommitmentInputs(){
+ signal value;
+ signal salt;
+ signal ownerPublicKey[2];
+}
+
+template CheckPositiveValues(nInputs) {
+ input CommitmentInputs() commitmentInputs[nInputs];
+
+ // check that the output values are within the expected range. we don't allow negative values
+ for (var i = 0; i < nInputs; i++) {
+ var greaterEqThanZero;
+ greaterEqThanZero = GreaterEqThan(100)(in <== [commitmentInputs[i].value, 0]);
+ greaterEqThanZero === 1;
+ }
+}
\ No newline at end of file
diff --git a/zkp/circuits/lib/check-hashes-tokenid-uri.circom b/zkp/circuits/lib/check-hashes-tokenid-uri.circom
index 27b52f36..9f38b9bf 100644
--- a/zkp/circuits/lib/check-hashes-tokenid-uri.circom
+++ b/zkp/circuits/lib/check-hashes-tokenid-uri.circom
@@ -26,15 +26,15 @@ include "../node_modules/circomlib/circuits/comparators.circom";
// tokenIds: array of token ids, as preimages for the input hashes and output hashes
// tokenUris: array of token uris, as preimages for the input hashes and output hashes
//
-template CheckHashesForTokenIdAndUri(numInputs) {
- signal input tokenIds[numInputs];
- signal input tokenUris[numInputs];
- signal input commitments[numInputs];
- signal input salts[numInputs];
- signal input ownerPublicKeys[numInputs][2];
+template CheckHashesForTokenIdAndUri(nInputs) {
+ signal input tokenIds[nInputs];
+ signal input tokenUris[nInputs];
+ signal input commitments[nInputs];
+ signal input salts[nInputs];
+ signal input ownerPublicKeys[nInputs][2];
// hash the input values
- for (var i = 0; i < numInputs; i++) {
+ for (var i = 0; i < nInputs; i++) {
// perform the hash calculation even though they are not needed when the input
// commitment at the current index is 0; this is because in zkp circuits we
// must always perform the same computation (have the the same constraints)
diff --git a/zkp/circuits/lib/check-hashes.circom b/zkp/circuits/lib/check-hashes.circom
index 6ec354bb..898ff94a 100644
--- a/zkp/circuits/lib/check-hashes.circom
+++ b/zkp/circuits/lib/check-hashes.circom
@@ -17,33 +17,31 @@ pragma circom 2.2.2;
include "../node_modules/circomlib/circuits/poseidon.circom";
include "../node_modules/circomlib/circuits/comparators.circom";
+include "./buses.circom";
// CheckHashes is a circuit that checks the integrity of transactions of Fungible Tokens
// - check that the commitments are the hash of the values, salts and owner public keys
//
// commitment = hash(value, salt, owner public key)
//
-template CheckHashes(numInputs) {
- signal input commitments[numInputs];
- signal input values[numInputs];
- signal input salts[numInputs];
- signal input ownerPublicKeys[numInputs][2];
+template CheckHashes(nInputs) {
+ signal input commitmentHashes[nInputs];
+ input CommitmentInputs() commitmentInputs[nInputs];
// hash the input values
- for (var i = 0; i < numInputs; i++) {
+ for (var i = 0; i < nInputs; i++) {
// perform the hash calculation even though they are not needed when the input
// commitment at the current index is 0; this is because in zkp circuits we
// must always perform the same computation (have the the same constraints)
var calculatedHash;
- calculatedHash = Poseidon(4)([values[i], salts[i], ownerPublicKeys[i][0], ownerPublicKeys[i][1]]);
+ calculatedHash = Poseidon(4)([commitmentInputs[i].value, commitmentInputs[i].salt, commitmentInputs[i].ownerPublicKey[0], commitmentInputs[i].ownerPublicKey[1]]);
// check that the input commitments match the calculated hashes
var isCommitmentZero;
- isCommitmentZero = IsZero()(in <== commitments[i]);
+ isCommitmentZero = IsZero()(in <== commitmentHashes[i]);
var isHashEqual;
- isHashEqual = IsEqual()(in <== [commitments[i], (1 - isCommitmentZero) * calculatedHash /* ensure when commitment is 0, compare with 0 */]);
-
+ isHashEqual = IsEqual()(in <== [commitmentHashes[i], (1 - isCommitmentZero) * calculatedHash /* ensure when commitment is 0, compare with 0 */]);
isHashEqual === 1;
}
}
diff --git a/zkp/circuits/lib/check-inputs-outputs-value-base.circom b/zkp/circuits/lib/check-inputs-outputs-value-base.circom
index a9d48f93..33cb9390 100644
--- a/zkp/circuits/lib/check-inputs-outputs-value-base.circom
+++ b/zkp/circuits/lib/check-inputs-outputs-value-base.circom
@@ -30,17 +30,17 @@ include "../node_modules/circomlib/circuits/comparators.circom";
//
// commitment = hash(value, salt, owner public key)
//
-template CheckInputsOutputsValue(numInputs, numOutputs) {
- signal input inputCommitments[numInputs];
- signal input inputValues[numInputs];
- signal input inputSalts[numInputs];
+template CheckInputsOutputsValue(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[numOutputs];
- signal input outputValues[numOutputs];
- signal input outputSalts[numOutputs];
- signal input outputOwnerPublicKeys[numOutputs][2];
+ signal input outputCommitments[nOutputs];
+ signal input outputValues[nOutputs];
+ signal input outputSalts[nOutputs];
+ signal input outputOwnerPublicKeys[nOutputs][2];
signal output out;
// derive the sender's public key from the secret input
@@ -50,24 +50,32 @@ template CheckInputsOutputsValue(numInputs, numOutputs) {
var inputOwnerPubKeyAx, inputOwnerPubKeyAy;
(inputOwnerPubKeyAx, inputOwnerPubKeyAy) = BabyPbk()(in <== inputOwnerPrivateKey);
- var inputOwnerPublicKeys[numInputs][2];
- for (var i = 0; i < numInputs; i++) {
- inputOwnerPublicKeys[i] = [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
- }
+ CheckPositive(nOutputs)(outputValues <== outputValues);
- CheckPositive(numOutputs)(outputValues <== outputValues);
+ CommitmentInputs() inAuxInputs[nInputs];
+ for (var i = 0; i < nInputs; i++) {
+ inAuxInputs[i].value <== inputValues[i];
+ inAuxInputs[i].salt <== inputSalts[i];
+ inAuxInputs[i].ownerPublicKey <== [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
+ }
- CheckHashes(numInputs)(commitments <== inputCommitments, values <== inputValues, salts <== inputSalts, ownerPublicKeys <== inputOwnerPublicKeys);
+ CommitmentInputs() outAuxInputs[nOutputs];
+ for (var i = 0; i < nOutputs; i++) {
+ outAuxInputs[i].value <== outputValues[i];
+ outAuxInputs[i].salt <== outputSalts[i];
+ outAuxInputs[i].ownerPublicKey <== outputOwnerPublicKeys[i];
+ }
- CheckHashes(numOutputs)(commitments <== outputCommitments, values <== outputValues, salts <== outputSalts, ownerPublicKeys <== outputOwnerPublicKeys);
+ CheckHashes(nInputs)(commitmentHashes <== inputCommitments, commitmentInputs <== inAuxInputs);
+ CheckHashes(nOutputs)(commitmentHashes <== outputCommitments, commitmentInputs <== outAuxInputs);
// check that the sum of input values is greater than or equal to the sum of output values
var sumInputs = 0;
- for (var i = 0; i < numInputs; i++) {
+ for (var i = 0; i < nInputs; i++) {
sumInputs = sumInputs + inputValues[i];
}
var sumOutputs = 0;
- for (var i = 0; i < numOutputs; i++) {
+ for (var i = 0; i < nOutputs; i++) {
sumOutputs = sumOutputs + outputValues[i];
}
diff --git a/zkp/circuits/lib/check-nullifiers-tokenid-uri.circom b/zkp/circuits/lib/check-nullifiers-tokenid-uri.circom
index 08bb4c7a..333358c7 100644
--- a/zkp/circuits/lib/check-nullifiers-tokenid-uri.circom
+++ b/zkp/circuits/lib/check-nullifiers-tokenid-uri.circom
@@ -28,17 +28,17 @@ include "../node_modules/circomlib/circuits/smt/smtverifier.circom";
// commitment = hash(tokenId, uri, salt, ownerPublicKey1, ownerPublicKey2)
// nullifier = hash(tokenId, uri, salt, ownerPrivatekey)
//
-template CheckNullifiersForTokenIdAndUri(numInputs) {
- signal input tokenIds[numInputs];
- signal input tokenUris[numInputs];
- signal input nullifiers[numInputs];
- signal input salts[numInputs];
+template CheckNullifiersForTokenIdAndUri(nInputs) {
+ signal input tokenIds[nInputs];
+ signal input tokenUris[nInputs];
+ signal input nullifiers[nInputs];
+ signal input salts[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 ownerPrivateKey;
// calculate the nullifier values from the input values
- for (var i = 0; i < numInputs; i++) {
+ for (var i = 0; i < nInputs; i++) {
var calculatedHash;
calculatedHash = Poseidon(4)([tokenIds[i], tokenUris[i], salts[i], ownerPrivateKey]);
diff --git a/zkp/circuits/lib/check-nullifiers-value-base.circom b/zkp/circuits/lib/check-nullifiers-value-base.circom
index b89a32ae..2f26d533 100644
--- a/zkp/circuits/lib/check-nullifiers-value-base.circom
+++ b/zkp/circuits/lib/check-nullifiers-value-base.circom
@@ -32,21 +32,21 @@ include "./check-smt-proof.circom";
// commitment = hash(value, salt, owner public key)
// nullifier = hash(value, salt, ownerPrivatekey)
//
-template CheckNullifiersInputsOutputsValue(numInputs, numOutputs, nSMTLevels) {
- signal input nullifiers[numInputs];
- signal input inputCommitments[numInputs];
- signal input inputValues[numInputs];
- signal input inputSalts[numInputs];
+template CheckNullifiersInputsOutputsValue(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[numInputs][nSMTLevels];
- signal input enabled[numInputs];
- signal input outputCommitments[numOutputs];
- signal input outputValues[numOutputs];
- signal input outputSalts[numOutputs];
- signal input outputOwnerPublicKeys[numOutputs][2];
+ 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 output out;
// derive the sender's public key from the secret input
@@ -56,32 +56,40 @@ template CheckNullifiersInputsOutputsValue(numInputs, numOutputs, nSMTLevels) {
var inputOwnerPubKeyAx, inputOwnerPubKeyAy;
(inputOwnerPubKeyAx, inputOwnerPubKeyAy) = BabyPbk()(in <== inputOwnerPrivateKey);
- var inputOwnerPublicKeys[numInputs][2];
- for (var i = 0; i < numInputs; i++) {
- inputOwnerPublicKeys[i] = [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
- }
+ CheckPositive(nOutputs)(outputValues <== outputValues);
- CheckPositive(numOutputs)(outputValues <== outputValues);
+ CommitmentInputs() inAuxInputs[nInputs];
+ for (var i = 0; i < nInputs; i++) {
+ inAuxInputs[i].value <== inputValues[i];
+ inAuxInputs[i].salt <== inputSalts[i];
+ inAuxInputs[i].ownerPublicKey <== [inputOwnerPubKeyAx, inputOwnerPubKeyAy];
+ }
- CheckHashes(numInputs)(commitments <== inputCommitments, values <== inputValues, salts <== inputSalts, ownerPublicKeys <== inputOwnerPublicKeys);
+ CommitmentInputs() outAuxInputs[nOutputs];
+ for (var i = 0; i < nOutputs; i++) {
+ outAuxInputs[i].value <== outputValues[i];
+ outAuxInputs[i].salt <== outputSalts[i];
+ outAuxInputs[i].ownerPublicKey <== outputOwnerPublicKeys[i];
+ }
- CheckNullifiers(numInputs)(nullifiers <== nullifiers, values <== inputValues, salts <== inputSalts, ownerPrivateKey <== inputOwnerPrivateKey);
+ CheckHashes(nInputs)(commitmentHashes <== inputCommitments, commitmentInputs <== inAuxInputs);
- CheckHashes(numOutputs)(commitments <== outputCommitments, values <== outputValues, salts <== outputSalts, ownerPublicKeys <== outputOwnerPublicKeys);
+ CheckNullifiers(nInputs)(nullifiers <== nullifiers, values <== inputValues, salts <== inputSalts, ownerPrivateKey <== inputOwnerPrivateKey);
+ CheckHashes(nOutputs)(commitmentHashes <== outputCommitments, commitmentInputs <== outAuxInputs);
// 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`.
- CheckSMTProof(numInputs, nSMTLevels)(root <== root, merkleProof <== merkleProof, enabled <== enabled, leafNodeIndexes <== inputCommitments, leafNodeValues <== inputCommitments);
+ CheckSMTProof(nInputs, nSMTLevels)(root <== root, merkleProof <== merkleProof, enabled <== enabled, leafNodeIndexes <== inputCommitments, leafNodeValues <== inputCommitments);
// check that the sum of input values equals the sum of output values
var sumInputs = 0;
- for (var i = 0; i < numInputs; i++) {
+ for (var i = 0; i < nInputs; i++) {
sumInputs = sumInputs + inputValues[i];
}
var sumOutputs = 0;
- for (var i = 0; i < numOutputs; i++) {
+ for (var i = 0; i < nOutputs; i++) {
sumOutputs = sumOutputs + outputValues[i];
}
diff --git a/zkp/circuits/lib/check-nullifiers.circom b/zkp/circuits/lib/check-nullifiers.circom
index a3c33a9f..81a91322 100644
--- a/zkp/circuits/lib/check-nullifiers.circom
+++ b/zkp/circuits/lib/check-nullifiers.circom
@@ -27,17 +27,17 @@ include "../node_modules/circomlib/circuits/smt/smtverifier.circom";
// commitment = hash(value, salt, ownerPublicKey1, ownerPublicKey2)
// nullifier = hash(value, salt, ownerPrivatekey)
//
-template CheckNullifiers(numInputs) {
- signal input nullifiers[numInputs];
- signal input values[numInputs];
- signal input salts[numInputs];
+template CheckNullifiers(nInputs) {
+ signal input nullifiers[nInputs];
+ signal input values[nInputs];
+ signal input salts[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 ownerPrivateKey;
// calculate the nullifier values from the input values
- for (var i = 0; i < numInputs; i++) {
+ for (var i = 0; i < nInputs; i++) {
var calculatedHash;
calculatedHash = Poseidon(3)(inputs <== [values[i], salts[i], ownerPrivateKey]);
diff --git a/zkp/circuits/lib/check-positive.circom b/zkp/circuits/lib/check-positive.circom
index 9777e2b4..9b0ad71d 100644
--- a/zkp/circuits/lib/check-positive.circom
+++ b/zkp/circuits/lib/check-positive.circom
@@ -25,11 +25,11 @@ include "../node_modules/circomlib/circuits/smt/smtverifier.circom";
//
// outputValues: array of values, as preimages for the output hashes, for the output utxos
//
-template CheckPositive(numOutputs) {
- signal input outputValues[numOutputs];
+template CheckPositive(nOutputs) {
+ signal input outputValues[nOutputs];
// check that the output values are within the expected range. we don't allow negative values
- for (var i = 0; i < numOutputs; i++) {
+ for (var i = 0; i < nOutputs; i++) {
var greaterEqThanZero;
greaterEqThanZero = GreaterEqThan(100)(in <== [outputValues[i], 0]);
diff --git a/zkp/circuits/lib/check-smt-proof.circom b/zkp/circuits/lib/check-smt-proof.circom
index 661a75a5..80e314bb 100644
--- a/zkp/circuits/lib/check-smt-proof.circom
+++ b/zkp/circuits/lib/check-smt-proof.circom
@@ -20,14 +20,14 @@ include "../node_modules/circomlib/circuits/smt/smtverifier.circom";
// CheckSMTProof is a general purpose circuit that checks the membership
// inclusion proof of a set of hashes in a Sparse Merkle Tree
//
-template CheckSMTProof(numInputs, nSMTLevels) {
- signal input leafNodeIndexes[numInputs];
- signal input leafNodeValues[numInputs];
+template CheckSMTProof(nInputs, nSMTLevels) {
+ signal input leafNodeIndexes[nInputs];
+ signal input leafNodeValues[nInputs];
signal input root;
- signal input merkleProof[numInputs][nSMTLevels];
- signal input enabled[numInputs];
+ signal input merkleProof[nInputs][nSMTLevels];
+ signal input enabled[nInputs];
- for (var i = 0; i < numInputs; i++) {
+ for (var i = 0; i < nInputs; i++) {
var siblings[nSMTLevels];
for (var j = 0; j < nSMTLevels; j++) {
siblings[j] = merkleProof[i][j];
diff --git a/zkp/circuits/lib/check-sum.circom b/zkp/circuits/lib/check-sum.circom
index df804dca..8a199aeb 100644
--- a/zkp/circuits/lib/check-sum.circom
+++ b/zkp/circuits/lib/check-sum.circom
@@ -20,17 +20,17 @@ include "../node_modules/circomlib/circuits/comparators.circom";
// CheckSum is a circuit that checks that the sum of input values equals the sum of output values
//
-template CheckSum(numInputs, numOutputs) {
- signal input inputValues[numInputs];
- signal input outputValues[numOutputs];
+template CheckSum(nInputs, nOutputs) {
+ signal input inputValues[nInputs];
+ signal input outputValues[nOutputs];
// check that the sum of input values equals the sum of output values
var sumInputs = 0;
- for (var i = 0; i < numInputs; i++) {
+ for (var i = 0; i < nInputs; i++) {
sumInputs = sumInputs + inputValues[i];
}
var sumOutputs = 0;
- for (var i = 0; i < numOutputs; i++) {
+ for (var i = 0; i < nOutputs; i++) {
sumOutputs = sumOutputs + outputValues[i];
}
diff --git a/zkp/circuits/lib/encrypt-outputs.circom b/zkp/circuits/lib/encrypt-outputs.circom
index 90bba05c..fcc149c5 100644
--- a/zkp/circuits/lib/encrypt-outputs.circom
+++ b/zkp/circuits/lib/encrypt-outputs.circom
@@ -3,31 +3,31 @@ pragma circom 2.2.2;
include "./ecdh.circom";
include "./encrypt.circom";
include "../node_modules/circomlib/circuits/babyjub.circom";
+include "./buses.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) {
+template EncryptOutputs(nOutputs) {
signal input ecdhPrivateKey;
signal input encryptionNonce;
- signal input outputValues[numOutputs];
- signal input outputSalts[numOutputs];
- signal input outputOwnerPublicKeys[numOutputs][2];
+ input CommitmentInputs() commitmentInputs[nOutputs];
+
// 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];
+ signal output cipherTexts[nOutputs][4];
- for (var i = 0; i < numOutputs; i++) {
+ for (var i = 0; i < nOutputs; i++) {
// generate shared secret
var sharedSecret[2];
- sharedSecret = Ecdh()(privKey <== ecdhPrivateKey, pubKey <== outputOwnerPublicKeys[i]);
+ sharedSecret = Ecdh()(privKey <== ecdhPrivateKey, pubKey <== commitmentInputs[i].ownerPublicKey);
// encrypt the value for the output UTXOs
- cipherTexts[i] <== SymmetricEncrypt(2)(plainText <== [outputValues[i], outputSalts[i]], key <== sharedSecret, nonce <== encryptionNonce);
+ cipherTexts[i] <== SymmetricEncrypt(2)(plainText <== [commitmentInputs[i].value, commitmentInputs[i].salt], key <== sharedSecret, nonce <== encryptionNonce);
}
(ecdhPublicKey[0], ecdhPublicKey[1]) <== BabyPbk()(in <== ecdhPrivateKey);
diff --git a/zkp/circuits/scripts/gen-config.json b/zkp/circuits/scripts/gen-config.json
index 54db1677..f07acfe6 100644
--- a/zkp/circuits/scripts/gen-config.json
+++ b/zkp/circuits/scripts/gen-config.json
@@ -3,88 +3,71 @@
"circuits": {
"anon": {
"ptau": "powersOfTau28_hez_final_13",
- "batchPtau": "powersOfTau28_hez_final_15",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_15"
},
"anon_enc": {
"ptau": "powersOfTau28_hez_final_15",
- "batchPtau": "powersOfTau28_hez_final_17",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_17"
},
"anon_nullifier_transfer": {
"ptau": "powersOfTau28_hez_final_17",
- "batchPtau": "powersOfTau28_hez_final_19",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_19"
},
"anon_nullifier_transferLocked": {
"ptau": "powersOfTau28_hez_final_17",
- "batchPtau": "powersOfTau28_hez_final_19",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_19"
},
"anon_nullifier_qurrency_transfer": {
"ptau": "powersOfTau28_hez_final_22",
- "batchPtau": "powersOfTau28_hez_final_22",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_22"
},
"anon_nullifier_kyc": {
"ptau": "powersOfTau28_hez_final_17",
- "batchPtau": "powersOfTau28_hez_final_19",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_19"
},
"anon_enc_nullifier_non_repudiation": {
"ptau": "powersOfTau28_hez_final_17",
- "batchPtau": "powersOfTau28_hez_final_19",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_19"
},
"anon_enc_nullifier": {
"ptau": "powersOfTau28_hez_final_17",
- "batchPtau": "powersOfTau28_hez_final_19",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_19"
},
"anon_enc_nullifier_kyc": {
"ptau": "powersOfTau28_hez_final_17",
- "batchPtau": "powersOfTau28_hez_final_20",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_20"
},
"nf_anon": {
- "ptau": "powersOfTau28_hez_final_13",
- "skipSolidityGenaration": false
+ "ptau": "powersOfTau28_hez_final_13"
},
"nf_anon_nullifier_transfer": {
- "ptau": "powersOfTau28_hez_final_16",
- "skipSolidityGenaration": false
+ "ptau": "powersOfTau28_hez_final_16"
},
"nf_anon_nullifier_transferLocked": {
- "ptau": "powersOfTau28_hez_final_16",
- "skipSolidityGenaration": false
+ "ptau": "powersOfTau28_hez_final_16"
},
"deposit": {
- "ptau": "powersOfTau28_hez_final_11",
- "skipSolidityGenaration": false
+ "ptau": "powersOfTau28_hez_final_11"
},
"withdraw": {
"ptau": "powersOfTau28_hez_final_13",
- "batchPtau": "powersOfTau28_hez_final_14",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_14"
},
"withdraw_nullifier": {
"ptau": "powersOfTau28_hez_final_17",
- "batchPtau": "powersOfTau28_hez_final_19",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_19"
},
"check_nullifiers": {
"ptau": "powersOfTau28_hez_final_13",
- "skipSolidityGenaration": true
+ "skipSolidityGeneration": true
},
"burn": {
"ptau": "powersOfTau28_hez_final_13",
- "batchPtau": "powersOfTau28_hez_final_14",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_14"
},
"burn_nullifier": {
"ptau": "powersOfTau28_hez_final_17",
- "batchPtau": "powersOfTau28_hez_final_19",
- "skipSolidityGenaration": false
+ "batchPtau": "powersOfTau28_hez_final_19"
}
}
}
diff --git a/zkp/circuits/scripts/gen.js b/zkp/circuits/scripts/gen.js
index a9af75f9..1b253ecc 100644
--- a/zkp/circuits/scripts/gen.js
+++ b/zkp/circuits/scripts/gen.js
@@ -1,43 +1,43 @@
-const fs = require("fs");
-const path = require("path");
-const { exec } = require("child_process");
-const { promisify } = require("util");
-const axios = require("axios");
-const yargs = require("yargs/yargs");
+const fs = require('fs');
+const path = require('path');
+const { exec } = require('child_process');
+const { promisify } = require('util');
+const axios = require('axios');
+const yargs = require('yargs/yargs');
const blake = require('blakejs');
-const { hideBin } = require("yargs/helpers");
+const { hideBin } = require('yargs/helpers');
const argv = yargs(hideBin(process.argv))
- .option("c", {
- alias: "circuit",
- describe: "Specify a single circuit to build",
- type: "string",
+ .option('c', {
+ alias: 'circuit',
+ describe: 'Specify a single circuit to build',
+ type: 'string',
})
- .option("v", {
- alias: "verbose",
- describe: "Enable verbose mode",
- type: "boolean",
+ .option('v', {
+ alias: 'verbose',
+ describe: 'Enable verbose mode',
+ type: 'boolean',
default: false,
})
- .option("cp", {
- alias: "compileOnly",
- describe: "Compile only",
- type: "boolean",
+ .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('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('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",
+ .option('pt', {
+ alias: 'ptauDownloadPath',
+ describe: 'Specify the root folder for storing downloaded PTAU',
+ type: 'string',
}).argv;
const circuitsRoot = process.env.CIRCUITS_ROOT || argv.circuitsRoot;
@@ -50,22 +50,22 @@ const parallelLimit = parseInt(process.env.GEN_CONCURRENCY, 10) || 8; // Default
// check env vars
if (!circuitsRoot) {
- console.error("Error: CIRCUITS_ROOT is not set.");
+ console.error('Error: CIRCUITS_ROOT is not set.');
process.exit(1);
}
if (!compileOnly && !provingKeysRoot) {
- console.error("Error: PROVING_KEYS_ROOT is not set.");
+ console.error('Error: PROVING_KEYS_ROOT is not set.');
process.exit(1);
}
if (!compileOnly && !ptauDownload) {
- console.error("Error: PTAU_DOWNLOAD_PATH is not set.");
+ console.error('Error: PTAU_DOWNLOAD_PATH is not set.');
process.exit(1);
}
console.log(
- "Generating circuits with the following settings:\n" +
+ 'Generating circuits with the following settings:\n' +
JSON.stringify(
{
specificCircuits,
@@ -77,21 +77,21 @@ console.log(
ptauDownload,
},
null,
- 2,
+ 2
) +
- "\n",
+ '\n'
);
// load configuration
-const genConfig = require("./gen-config.json");
+const genConfig = require('./gen-config.json');
const circuits = genConfig.circuits;
const toCamelCase = (str) => {
return str
- .split("_")
+ .split('_')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
- .join("");
+ .join('');
};
// util functions
@@ -102,50 +102,45 @@ const timestamp = () => new Date().toISOString();
const logPrefix = (circuit) => `[${timestamp()}] [${circuit}]`;
const log = (circuit, message) => {
- console.log(logPrefix(circuit) + " " + message);
+ console.log(logPrefix(circuit) + ' ' + message);
};
const calculateHash = async (ptauFile) => {
- return new Promise ((resolve, reject) => {
+ return new Promise((resolve, reject) => {
const context = blake.blake2bInit(64, null);
const ptauStream = fs.createReadStream(ptauFile);
- ptauStream.on('data', chunk => {
+ ptauStream.on('data', (chunk) => {
blake.blake2bUpdate(context, chunk);
});
ptauStream.on('end', () => {
const computedHashBytes = blake.blake2bFinal(context);
- const computedHash = Buffer.from(computedHashBytes).toString("hex");
+ const computedHash = Buffer.from(computedHashBytes).toString('hex');
resolve(computedHash);
});
- ptauStream.on('error', err => {
+ ptauStream.on('error', (err) => {
reject(err);
});
});
};
const downloadAndVerifyPtau = async (ptau) => {
-
const ptauFile = path.join(ptauDownload, `${ptau}.ptau`);
if (!compileOnly && !fs.existsSync(ptauFile)) {
log(ptau, `PTAU file does not exist, downloading and verifying`);
try {
- const response = await axios.get(
- `https://storage.googleapis.com/zkevm/ptau/${ptau}.ptau`,
- {
- responseType: "stream",
- },
- );
+ const response = await axios.get(`https://storage.googleapis.com/zkevm/ptau/${ptau}.ptau`, {
+ responseType: 'stream',
+ });
const writer = fs.createWriteStream(ptauFile);
response.data.pipe(writer);
await new Promise((resolve, reject) => {
- writer.on("finish", resolve);
- writer.on("error", reject);
+ writer.on('finish', resolve);
+ writer.on('error', reject);
});
-
} catch (error) {
log(ptau, `Failed to download PTAU file: ${error}`);
process.exit(1);
@@ -153,10 +148,9 @@ const downloadAndVerifyPtau = async (ptau) => {
// Compute blake2b hash and compare to expected value
try {
-
const computedHash = await calculateHash(ptauFile);
- const ptauHashes = require("./ptau_valid_hashes.json");
+ const ptauHashes = require('./ptau_valid_hashes.json');
const expectedHash = ptauHashes[`${ptau}`];
if (verbose) {
@@ -167,7 +161,7 @@ const downloadAndVerifyPtau = async (ptau) => {
if (expectedHash != computedHash) {
throw new Error(`${ptau} Expected PTAU hash ${expectedHash}, got ${computedHash}`);
} else {
- log(ptau, "Verification successful");
+ log(ptau, 'Verification successful');
}
} catch (error) {
log(ptau, `Failed to validate PTAU file: ${error}`);
@@ -177,8 +171,8 @@ const downloadAndVerifyPtau = async (ptau) => {
};
// main circuit process logic
-const processCircuit = async (circuit, ptau, skipSolidityGenaration) => {
- const circomInput = path.join(__dirname, "../", `${circuit}.circom`);
+const processCircuit = async (circuit, ptau, skipSolidityGeneration) => {
+ const circomInput = path.join(__dirname, '../', `${circuit}.circom`);
const ptauFile = path.join(ptauDownload, `${ptau}.ptau`);
const zkeyOutput = path.join(provingKeysRoot, `${circuit}.zkey`);
@@ -188,103 +182,73 @@ const processCircuit = async (circuit, ptau, skipSolidityGenaration) => {
}
log(circuit, `Compiling circuit`);
- const { stdout: cmOut, stderr: cmErr } = await execAsync(
- `circom ${circomInput} --output ${circuitsRoot} --sym --wasm`,
- );
+ const { stdout: cmOut, stderr: cmErr } = await execAsync(`circom ${circomInput} --output ${circuitsRoot} --sym --wasm`);
if (verbose) {
if (cmOut) {
- log(circuit, "compile output:\n" + cmOut);
+ log(circuit, 'compile output:\n' + cmOut);
}
if (cmErr) {
- log(circuit, "compile error:\n" + cmErr);
+ log(circuit, 'compile error:\n' + cmErr);
}
}
if (compileOnly) {
return;
}
- const { stdout: ctOut, stderr: ctErr } = await execAsync(
- `circom ${circomInput} --output ${provingKeysRoot} --r1cs`,
- );
+ const { stdout: ctOut, stderr: ctErr } = await execAsync(`circom ${circomInput} --output ${provingKeysRoot} --r1cs`);
if (verbose) {
if (ctOut) {
- log(circuit, "constraint generation output:\n" + ctOut);
- const { stdout: csOut } = await execAsync(
- `npx snarkjs r1cs print ${provingKeysRoot}/${circuit}.r1cs ${circuitsRoot}/${circuit}.sym `,
- );
+ log(circuit, 'constraint generation output:\n' + ctOut);
+ const { stdout: csOut } = await execAsync(`npx snarkjs r1cs print ${provingKeysRoot}/${circuit}.r1cs ${circuitsRoot}/${circuit}.sym `);
// log(circuit, "constraints:\n" + csOut);
}
if (ctErr) {
- log(circuit, "constraint error:\n" + ctErr);
+ log(circuit, 'constraint error:\n' + ctErr);
}
}
log(circuit, `Generating test proving key with ${ptau}`);
- const { stdout: pkOut, stderr: pkErr } = await execAsync(
- `npx snarkjs groth16 setup ${path.join(
- provingKeysRoot,
- `${circuit}.r1cs`,
- )} ${ptauFile} ${zkeyOutput}`,
- );
+ const { stdout: pkOut, stderr: pkErr } = await execAsync(`npx snarkjs groth16 setup ${path.join(provingKeysRoot, `${circuit}.r1cs`)} ${ptauFile} ${zkeyOutput}`);
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, 'test proving key generation error:\n' + pkErr);
}
}
log(circuit, `Exporting verification key`);
- const { stdout: vkOut, stderr: vkErr } = await execAsync(
- `npx snarkjs zkey export verificationkey ${zkeyOutput} ${path.join(
- provingKeysRoot,
- `${circuit}-vkey.json`,
- )}`,
- );
+ const { stdout: vkOut, stderr: 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);
+ log(circuit, 'verification key export error:\n' + vkErr);
}
}
- if (skipSolidityGenaration) {
+ if (skipSolidityGeneration) {
log(circuit, `Skipping solidity verifier generation`);
return;
}
log(circuit, `Generating solidity verifier`);
- const solidityFile = path.join(
- __dirname,
- "..",
- "..",
- "..",
- "solidity",
- "contracts",
- "verifiers",
- `verifier_${circuit}.sol`,
- );
- const { stdout: svOut, stderr: svErr } = await execAsync(
- `npx snarkjs zkey export solidityverifier ${zkeyOutput} ${solidityFile}`,
- );
+ const solidityFile = path.join(__dirname, '..', '..', '..', 'solidity', 'contracts', 'verifiers', `verifier_${circuit}.sol`);
+ const { stdout: svOut, stderr: svErr } = await execAsync(`npx snarkjs zkey export solidityverifier ${zkeyOutput} ${solidityFile}`);
if (verbose) {
if (svOut) {
- log(circuit, "solidity verifier export output:\n" + svOut);
+ log(circuit, 'solidity verifier export output:\n' + svOut);
}
if (svErr) {
- log(circuit, "solidity verifier export error:\n" + 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`;
- const fileContent = fs.readFileSync(solidityFile, "utf8");
- const updatedContent = fileContent.replace(
- " Groth16Verifier ",
- ` Groth16Verifier_${camelCaseCircuitName} `,
- );
+ const fileContent = fs.readFileSync(solidityFile, 'utf8');
+ const updatedContent = fileContent.replace(' Groth16Verifier ', ` Groth16Verifier_${camelCaseCircuitName} `);
fs.writeFileSync(solidityFileTmp, updatedContent);
fs.renameSync(solidityFileTmp, solidityFile);
log(circuit, `Circuit process complete`);
@@ -310,34 +274,32 @@ const run = async () => {
const activePromises = new Set();
let snarkjsVersion;
- // first check cirom version and snarkjs version matches the one in the package.json
+ // first check circom version and snarkjs version matches the one in the package.json
try {
- const { stdout: circomVersion } = await execAsync("circom --version");
+ const { stdout: circomVersion } = await execAsync('circom --version');
// Trigger error to get snarkjs version
try {
- await execAsync("npx snarkjs --version");
+ await execAsync('npx snarkjs --version');
} catch (error) {
// Extract snarkjs version from error message
snarkjsVersion = error.stdout.match(/snarkjs@([\d.]+)/)?.[1];
if (!snarkjsVersion) {
- throw new Error("Failed to extract SnarkJS version from error output.");
+ throw new Error('Failed to extract SnarkJS version from error output.');
}
}
- const { stdout: packageJson } = await execAsync("cat package.json");
+ const { stdout: packageJson } = await execAsync('cat package.json');
const packageJsonObj = JSON.parse(packageJson);
const expectedCircomVersion = genConfig.circomVersion;
// Sanitize and extract version numbers
- const circomVersionTrimmed = circomVersion
- .trim()
- .replace("circom compiler ", "");
+ const circomVersionTrimmed = circomVersion.trim().replace('circom compiler ', '');
let hasMismatch = false;
if (circomVersionTrimmed !== expectedCircomVersion) {
console.error(
`Error: circom version mismatch with the version in gen-config.json :\n` +
`\tExpected circom: ${expectedCircomVersion}, got: ${circomVersionTrimmed}\n` +
- `\tFollow https://docs.circom.io/getting-started/installation/ to update your circom\n`,
+ `\tFollow https://docs.circom.io/getting-started/installation/ to update your circom\n`
);
hasMismatch = true;
}
@@ -346,7 +308,7 @@ const run = async () => {
console.error(
`Error: snarkjs version mismatch with package.json:\n` +
`\tExpected snarkjs: ${packageJsonObj.devDependencies.snarkjs}, got: ${snarkjsVersion}\n` +
- `\tUse npm to update your snarkjs node module\n`,
+ `\tUse npm to update your snarkjs node module\n`
);
hasMismatch = true;
}
@@ -354,7 +316,7 @@ const run = async () => {
process.exit(1);
}
- console.log("Version check passed.");
+ console.log('Version check passed.');
} catch (error) {
console.error(`An error occurred: ${error.message}`);
process.exit(1);
@@ -362,10 +324,7 @@ const run = async () => {
// Download all PTAU files that we need
var allPtaus = new Set();
- for (const [
- circuit,
- { ptau, skipSolidityGenaration, batchPtau },
- ] of circuitsArray) {
+ for (const [circuit, { ptau, batchPtau }] of circuitsArray) {
if (onlyCircuits && !onlyCircuits.includes(circuit)) {
continue;
}
@@ -384,15 +343,12 @@ const run = async () => {
await downloadAndVerifyPtau(p);
}
- for (const [
- circuit,
- { ptau, skipSolidityGenaration, batchPtau },
- ] of circuitsArray) {
+ for (const [circuit, { ptau, skipSolidityGeneration, batchPtau }] of circuitsArray) {
if (onlyCircuits && !onlyCircuits.includes(circuit)) {
continue;
}
- const pcPromise = processCircuit(circuit, ptau, skipSolidityGenaration);
+ const pcPromise = processCircuit(circuit, ptau, skipSolidityGeneration);
activePromises.add(pcPromise);
if (activePromises.size >= parallelLimit) {
@@ -400,11 +356,7 @@ const run = async () => {
}
if (batchPtau) {
- const pcBatchPromise = processCircuit(
- circuit + "_batch",
- batchPtau,
- skipSolidityGenaration,
- );
+ const pcBatchPromise = processCircuit(circuit + '_batch', batchPtau, skipSolidityGeneration);
activePromises.add(pcBatchPromise);
if (activePromises.size >= parallelLimit) {
diff --git a/zkp/js/lib/util.js b/zkp/js/lib/util.js
index ef541b7a..b4bfc70c 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");
// The ciphertext is produced inside the ZKP circuit. The following are
// the index of the ciphertext in the witness array, which is dependent on the circuit.
@@ -35,14 +35,16 @@ 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');
+const F = BigInt(
+ "21888242871839275222246405745257275088548364400416034343698204186575808495617",
+);
// Implements the encryption and decryption functions using Poseidon hash
// as described: https://drive.google.com/file/d/1EVrP3DzoGbmzkRmYnyEDcIQcXVU7GlOd/view
@@ -118,10 +120,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",
+ );
}
}
@@ -129,7 +143,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);
}
@@ -153,24 +171,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");
}
}
@@ -198,15 +216,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_enc_nullifier_kyc.js b/zkp/js/test/anon_enc_nullifier_kyc.js
index fb0e9b5d..5b4f1e6d 100644
--- a/zkp/js/test/anon_enc_nullifier_kyc.js
+++ b/zkp/js/test/anon_enc_nullifier_kyc.js
@@ -87,7 +87,8 @@ 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 function() {
+ this.timeout(60000);
const inputValues = [32, 40];
const outputValues = [20, 52];
@@ -352,7 +353,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_267 line: 102/);
+ expect(err).to.match(/Error in template Zeto_267 line: 110/);
expect(err).to.match(/Error in template CheckSMTProof_253 line: 38/);
});
});
diff --git a/zkp/js/test/anon_enc_nullifier_non_repudiation.js b/zkp/js/test/anon_enc_nullifier_non_repudiation.js
index 3423e403..4b1396ae 100644
--- a/zkp/js/test/anon_enc_nullifier_non_repudiation.js
+++ b/zkp/js/test/anon_enc_nullifier_non_repudiation.js
@@ -81,7 +81,8 @@ describe("main circuit tests for Zeto fungible tokens with encryption for non-re
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 function() {
+ this.timeout(60000);
const inputValues = [32, 40];
const outputValues = [20, 52];
diff --git a/zkp/js/test/anon_nullifier_qurrency.js b/zkp/js/test/anon_nullifier_qurrency.js
index 90cc44dd..2a925e95 100644
--- a/zkp/js/test/anon_nullifier_qurrency.js
+++ b/zkp/js/test/anon_nullifier_qurrency.js
@@ -14,13 +14,18 @@
// 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 { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto');
-const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree');
-const { Poseidon, newSalt } = require('../index.js');
+const { expect } = require("chai");
+const { join } = require("path");
+const crypto = require("crypto");
+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");
const SMT_HEIGHT = 64;
const poseidonHash = Poseidon.poseidon4;
@@ -29,11 +34,18 @@ const poseidonHash3 = Poseidon.poseidon3;
// a message is a 256-bit number, each as a separate signal
// using 1665 instead of 1 as this is the constant used by Kyber
const m = [
- 1665, 1665, 0, 1665, 0, 1665, 1665, 0, 1665, 0, 0, 1665, 1665, 1665, 1665, 0, 0, 1665, 0, 0, 0, 1665, 1665, 0, 1665, 0, 1665, 0, 0, 1665, 1665, 0, 0, 1665, 0, 0, 1665, 1665, 1665, 0, 0, 0, 0, 0, 0,
- 1665, 0, 0, 1665, 0, 0, 1665, 0, 1665, 1665, 0, 1665, 1665, 0, 0, 1665, 1665, 1665, 0, 0, 0, 0, 0, 0, 1665, 0, 0, 1665, 1665, 0, 0, 0, 1665, 1665, 0, 1665, 1665, 1665, 1665, 0, 1665, 1665, 0, 1665,
- 1665, 1665, 1665, 0, 1665, 1665, 0, 0, 0, 1665, 1665, 0, 1665, 1665, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1665, 1665, 0, 1665, 0, 1665, 1665, 0, 1665, 0, 0, 1665, 1665, 1665, 1665, 0,
+ 0, 1665, 0, 0, 0, 1665, 1665, 0, 1665, 0, 1665, 0, 0, 1665, 1665, 0, 0, 1665,
+ 0, 0, 1665, 1665, 1665, 0, 0, 0, 0, 0, 0, 1665, 0, 0, 1665, 0, 0, 1665, 0,
+ 1665, 1665, 0, 1665, 1665, 0, 0, 1665, 1665, 1665, 0, 0, 0, 0, 0, 0, 1665, 0,
+ 0, 1665, 1665, 0, 0, 0, 1665, 1665, 0, 1665, 1665, 1665, 1665, 0, 1665, 1665,
+ 0, 1665, 1665, 1665, 1665, 0, 1665, 1665, 0, 0, 0, 1665, 1665, 0, 1665, 1665,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
// dummy randomness. keep this as is so that the circuit will generate the same
@@ -41,36 +53,70 @@ const m = [
// ciphertext in the witness array. For real world usage, this should be replaced with
// a random number generated by a proper random number generator.
const randomness = [
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
// this is the encrypted result from the message above, using the dummy randomness
// and the built-in Kyber public key inside the circuit (lib/kyber/kyber.circom)
const hack = [
- 153, 180, 68, 235, 189, 233, 191, 4, 236, 89, 22, 35, 178, 239, 102, 163, 71, 123, 55, 19, 165, 82, 197, 168, 222, 159, 54, 198, 122, 202, 46, 61, 71, 249, 202, 155, 165, 186, 117, 41, 235, 141, 35,
- 149, 53, 129, 42, 95, 212, 128, 192, 80, 112, 120, 127, 192, 205, 189, 251, 33, 173, 173, 209, 111, 0, 208, 195, 74, 118, 98, 48, 178, 40, 203, 127, 185, 133, 93, 106, 112, 154, 50, 56, 184, 51, 20,
- 48, 2, 153, 106, 230, 56, 31, 252, 43, 23, 133, 140, 101, 183, 92, 250, 234, 28, 192, 208, 54, 250, 254, 120, 214, 74, 140, 53, 236, 105, 36, 182, 61, 100, 161, 226, 69, 83, 148, 134, 252, 102, 226,
- 97, 203, 135, 10, 211, 251, 52, 154, 236, 218, 31, 236, 237, 252, 36, 25, 28, 150, 249, 52, 121, 152, 78, 9, 180, 23, 211, 126, 133, 153, 69, 197, 208, 190, 241, 118, 207, 183, 27, 127, 51, 78, 77,
- 203, 153, 57, 21, 165, 163, 218, 41, 72, 219, 42, 130, 246, 112, 178, 196, 125, 46, 249, 103, 12, 28, 209, 111, 134, 22, 178, 180, 248, 88, 239, 238, 183, 191, 191, 235, 219, 239, 102, 91, 90, 37,
- 218, 170, 234, 76, 91, 208, 38, 23, 74, 215, 14, 49, 149, 60, 145, 150, 3, 11, 251, 182, 73, 231, 14, 95, 217, 195, 182, 171, 2, 171, 19, 234, 75, 157, 205, 141, 181, 171, 227, 213, 212, 44, 159,
- 98, 183, 226, 99, 144, 219, 130, 92, 110, 65, 184, 4, 2, 228, 3, 159, 193, 180, 197, 79, 248, 55, 139, 73, 238, 189, 48, 102, 251, 155, 199, 19, 14, 205, 136, 186, 253, 214, 230, 253, 171, 217, 157,
- 23, 191, 73, 242, 132, 144, 134, 38, 255, 202, 79, 191, 124, 17, 103, 7, 55, 166, 5, 16, 82, 103, 169, 250, 141, 231, 235, 218, 185, 26, 125, 37, 95, 68, 72, 248, 78, 214, 49, 88, 204, 17, 106, 221,
- 149, 143, 225, 254, 230, 120, 5, 166, 34, 200, 9, 60, 204, 9, 72, 205, 85, 231, 104, 186, 17, 172, 183, 67, 222, 23, 184, 112, 235, 253, 54, 150, 70, 42, 73, 68, 233, 174, 108, 200, 42, 240, 108,
- 88, 54, 31, 217, 176, 29, 139, 231, 201, 132, 118, 104, 205, 47, 226, 184, 119, 199, 152, 49, 164, 123, 255, 16, 176, 83, 10, 140, 215, 228, 222, 202, 64, 88, 213, 123, 106, 246, 53, 208, 42, 2, 43,
- 80, 203, 8, 155, 12, 216, 15, 221, 82, 20, 137, 22, 99, 66, 254, 146, 238, 82, 139, 25, 202, 33, 89, 156, 30, 48, 226, 103, 130, 148, 197, 126, 23, 131, 211, 75, 155, 62, 231, 73, 32, 151, 196, 231,
- 226, 0, 249, 180, 140, 111, 18, 4, 60, 240, 76, 199, 81, 248, 84, 10, 117, 15, 191, 189, 209, 163, 146, 37, 185, 128, 54, 214, 175, 96, 215, 150, 138, 140, 228, 102, 60, 133, 11, 185, 130, 110, 160,
- 121, 197, 129, 57, 150, 43, 222, 191, 64, 80, 107, 122, 33, 132, 67, 85, 141, 97, 124, 82, 173, 216, 224, 102, 220, 210, 24, 51, 192, 167, 135, 19, 212, 218, 170, 74, 105, 104, 58, 237, 203, 181,
- 197, 77, 23, 92, 210, 143, 195, 129, 37, 205, 61, 98, 61, 112, 36, 245, 192, 225, 83, 81, 159, 134, 235, 86, 221, 172, 191, 213, 5, 131, 183, 118, 196, 78, 206, 255, 9, 32, 58, 10, 189, 63, 95, 45,
- 85, 106, 74, 115, 51, 112, 123, 59, 45, 148, 13, 237, 84, 223, 249, 210, 176, 16, 228, 207, 248, 180, 91, 210, 71, 150, 167, 205, 123, 140, 39, 66, 3, 110, 249, 38, 86, 41, 181, 163, 96, 211, 181,
- 98, 58, 133, 136, 250, 23, 117, 4, 207, 219, 168, 118, 85, 200, 123, 30, 143, 56, 117, 197, 242, 205, 130, 45, 200, 77, 51, 56, 31, 41, 151, 118, 118, 162, 204, 65, 112, 243, 109, 142, 224, 81, 250,
- 103, 25, 91, 9, 189, 105, 23, 75, 95, 167, 149, 49, 103, 76, 105, 74, 67, 75, 3, 43, 103, 30, 157, 71, 34, 103, 136, 198, 229, 206, 182, 11, 255, 246, 247, 16, 221, 142, 40, 137, 89, 63, 23, 151,
- 111, 31, 74, 70, 38, 210, 240, 18, 209, 62, 111, 84, 203, 151, 195, 212, 18, 203, 83, 2, 98, 120, 73, 251, 3, 220, 241, 162, 8, 76, 55, 163, 201, 118, 42,
+ 153, 180, 68, 235, 189, 233, 191, 4, 236, 89, 22, 35, 178, 239, 102, 163, 71,
+ 123, 55, 19, 165, 82, 197, 168, 222, 159, 54, 198, 122, 202, 46, 61, 71, 249,
+ 202, 155, 165, 186, 117, 41, 235, 141, 35, 149, 53, 129, 42, 95, 212, 128,
+ 192, 80, 112, 120, 127, 192, 205, 189, 251, 33, 173, 173, 209, 111, 0, 208,
+ 195, 74, 118, 98, 48, 178, 40, 203, 127, 185, 133, 93, 106, 112, 154, 50, 56,
+ 184, 51, 20, 48, 2, 153, 106, 230, 56, 31, 252, 43, 23, 133, 140, 101, 183,
+ 92, 250, 234, 28, 192, 208, 54, 250, 254, 120, 214, 74, 140, 53, 236, 105, 36,
+ 182, 61, 100, 161, 226, 69, 83, 148, 134, 252, 102, 226, 97, 203, 135, 10,
+ 211, 251, 52, 154, 236, 218, 31, 236, 237, 252, 36, 25, 28, 150, 249, 52, 121,
+ 152, 78, 9, 180, 23, 211, 126, 133, 153, 69, 197, 208, 190, 241, 118, 207,
+ 183, 27, 127, 51, 78, 77, 203, 153, 57, 21, 165, 163, 218, 41, 72, 219, 42,
+ 130, 246, 112, 178, 196, 125, 46, 249, 103, 12, 28, 209, 111, 134, 22, 178,
+ 180, 248, 88, 239, 238, 183, 191, 191, 235, 219, 239, 102, 91, 90, 37, 218,
+ 170, 234, 76, 91, 208, 38, 23, 74, 215, 14, 49, 149, 60, 145, 150, 3, 11, 251,
+ 182, 73, 231, 14, 95, 217, 195, 182, 171, 2, 171, 19, 234, 75, 157, 205, 141,
+ 181, 171, 227, 213, 212, 44, 159, 98, 183, 226, 99, 144, 219, 130, 92, 110,
+ 65, 184, 4, 2, 228, 3, 159, 193, 180, 197, 79, 248, 55, 139, 73, 238, 189, 48,
+ 102, 251, 155, 199, 19, 14, 205, 136, 186, 253, 214, 230, 253, 171, 217, 157,
+ 23, 191, 73, 242, 132, 144, 134, 38, 255, 202, 79, 191, 124, 17, 103, 7, 55,
+ 166, 5, 16, 82, 103, 169, 250, 141, 231, 235, 218, 185, 26, 125, 37, 95, 68,
+ 72, 248, 78, 214, 49, 88, 204, 17, 106, 221, 149, 143, 225, 254, 230, 120, 5,
+ 166, 34, 200, 9, 60, 204, 9, 72, 205, 85, 231, 104, 186, 17, 172, 183, 67,
+ 222, 23, 184, 112, 235, 253, 54, 150, 70, 42, 73, 68, 233, 174, 108, 200, 42,
+ 240, 108, 88, 54, 31, 217, 176, 29, 139, 231, 201, 132, 118, 104, 205, 47,
+ 226, 184, 119, 199, 152, 49, 164, 123, 255, 16, 176, 83, 10, 140, 215, 228,
+ 222, 202, 64, 88, 213, 123, 106, 246, 53, 208, 42, 2, 43, 80, 203, 8, 155, 12,
+ 216, 15, 221, 82, 20, 137, 22, 99, 66, 254, 146, 238, 82, 139, 25, 202, 33,
+ 89, 156, 30, 48, 226, 103, 130, 148, 197, 126, 23, 131, 211, 75, 155, 62, 231,
+ 73, 32, 151, 196, 231, 226, 0, 249, 180, 140, 111, 18, 4, 60, 240, 76, 199,
+ 81, 248, 84, 10, 117, 15, 191, 189, 209, 163, 146, 37, 185, 128, 54, 214, 175,
+ 96, 215, 150, 138, 140, 228, 102, 60, 133, 11, 185, 130, 110, 160, 121, 197,
+ 129, 57, 150, 43, 222, 191, 64, 80, 107, 122, 33, 132, 67, 85, 141, 97, 124,
+ 82, 173, 216, 224, 102, 220, 210, 24, 51, 192, 167, 135, 19, 212, 218, 170,
+ 74, 105, 104, 58, 237, 203, 181, 197, 77, 23, 92, 210, 143, 195, 129, 37, 205,
+ 61, 98, 61, 112, 36, 245, 192, 225, 83, 81, 159, 134, 235, 86, 221, 172, 191,
+ 213, 5, 131, 183, 118, 196, 78, 206, 255, 9, 32, 58, 10, 189, 63, 95, 45, 85,
+ 106, 74, 115, 51, 112, 123, 59, 45, 148, 13, 237, 84, 223, 249, 210, 176, 16,
+ 228, 207, 248, 180, 91, 210, 71, 150, 167, 205, 123, 140, 39, 66, 3, 110, 249,
+ 38, 86, 41, 181, 163, 96, 211, 181, 98, 58, 133, 136, 250, 23, 117, 4, 207,
+ 219, 168, 118, 85, 200, 123, 30, 143, 56, 117, 197, 242, 205, 130, 45, 200,
+ 77, 51, 56, 31, 41, 151, 118, 118, 162, 204, 65, 112, 243, 109, 142, 224, 81,
+ 250, 103, 25, 91, 9, 189, 105, 23, 75, 95, 167, 149, 49, 103, 76, 105, 74, 67,
+ 75, 3, 43, 103, 30, 157, 71, 34, 103, 136, 198, 229, 206, 182, 11, 255, 246,
+ 247, 16, 221, 142, 40, 137, 89, 63, 23, 151, 111, 31, 74, 70, 38, 210, 240,
+ 18, 209, 62, 111, 84, 203, 151, 195, 212, 18, 203, 83, 2, 98, 120, 73, 251, 3,
+ 220, 241, 162, 8, 76, 55, 163, 201, 118, 42,
];
-describe('main circuit tests for Zeto fungible tokens with anonymity using nullifiers and Kyber encryption for auditability', () => {
+describe("main circuit tests for Zeto fungible tokens with anonymity using nullifiers and Kyber encryption for auditability", () => {
let circuit, smtAlice, smtBob;
const Alice = {};
@@ -80,7 +126,9 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli
before(async function () {
this.timeout(120000);
- circuit = await wasm_tester(join(__dirname, '../../circuits/anon_nullifier_qurrency_transfer.circom'));
+ circuit = await wasm_tester(
+ join(__dirname, "../../circuits/anon_nullifier_qurrency_transfer.circom"),
+ );
let keypair = genKeypair();
Alice.privKey = keypair.privKey;
@@ -92,15 +140,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 - input size = 2', async function () {
+ it("should succeed for valid witness - input size = 2", async function () {
this.timeout(120000);
const inputValues = [32, 40];
@@ -108,15 +156,31 @@ 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];
const inputSalts = [salt1, salt2];
// 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
@@ -124,14 +188,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 outputSalts = [salt3, salt4];
const enabled = [1, 1];
@@ -144,7 +222,10 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli
inputSalts: inputSalts,
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,
outputCommitments,
outputValues,
@@ -153,7 +234,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli
randomness,
m,
},
- true
+ true,
);
// console.log('witness[1-11]', witness.slice(1, 12));
@@ -197,7 +278,7 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli
});
});
-describe('batch circuit tests for Zeto fungible tokens with anonymity using nullifiers and Kyber encryption for auditability', () => {
+describe("batch circuit tests for Zeto fungible tokens with anonymity using nullifiers and Kyber encryption for auditability", () => {
let circuit, smtAlice, smtBob;
const Alice = {};
@@ -207,7 +288,12 @@ describe('batch circuit tests for Zeto fungible tokens with anonymity using null
before(async function () {
this.timeout(120000);
- circuit = await wasm_tester(join(__dirname, '../../circuits/anon_nullifier_qurrency_transfer_batch.circom'));
+ circuit = await wasm_tester(
+ join(
+ __dirname,
+ "../../circuits/anon_nullifier_qurrency_transfer_batch.circom",
+ ),
+ );
let keypair = genKeypair();
Alice.privKey = keypair.privKey;
@@ -219,15 +305,15 @@ describe('batch circuit tests for Zeto fungible tokens with anonymity using null
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 - input size = 10', async function () {
+ it("should succeed for valid witness - input size = 10", async function () {
this.timeout(120000);
const inputValues = [32, 40, 0, 0, 0, 0, 0, 0, 0, 0];
@@ -235,15 +321,31 @@ describe('batch circuit tests for Zeto fungible tokens with anonymity using null
// 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, 0, 0, 0, 0, 0, 0, 0, 0];
const inputSalts = [salt1, salt2, 0, 0, 0, 0, 0, 0, 0, 0];
// 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, 0, 0, 0, 0, 0, 0, 0, 0];
// calculate the root of the SMT
@@ -251,14 +353,28 @@ describe('batch circuit tests for Zeto fungible tokens with anonymity using null
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, 0, 0, 0, 0, 0, 0, 0, 0];
const outputSalts = [salt3, salt4, 0, 0, 0, 0, 0, 0, 0, 0];
const enabled = [1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
@@ -278,11 +394,22 @@ describe('batch circuit tests for Zeto fungible tokens with anonymity using null
outputCommitments,
outputValues,
outputSalts: outputSalts,
- outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey, Alice.pubKey, Alice.pubKey, Alice.pubKey, Alice.pubKey, Alice.pubKey, Alice.pubKey, Alice.pubKey, Alice.pubKey],
+ outputOwnerPublicKeys: [
+ Bob.pubKey,
+ Alice.pubKey,
+ Alice.pubKey,
+ Alice.pubKey,
+ Alice.pubKey,
+ Alice.pubKey,
+ Alice.pubKey,
+ Alice.pubKey,
+ Alice.pubKey,
+ Alice.pubKey,
+ ],
randomness,
m,
},
- true
+ true,
);
//////
@@ -314,11 +441,11 @@ function hashCiphertext(ciphertext) {
for (let i = 0; i < ciphertext.length; i++) {
buff.writeUInt8(parseInt(ciphertext[i].toString()), i);
}
- const hash = crypto.createHash('sha256').update(buff).digest('hex');
+ const hash = crypto.createHash("sha256").update(buff).digest("hex");
// compare this with the console.log printout in Solidity
- console.log('ciphertext hash', hash);
+ console.log("ciphertext hash", hash);
- const hashBuffer = Buffer.from(hash, 'hex');
+ const hashBuffer = Buffer.from(hash, "hex");
const computed_pubSignals = [BigInt(0), BigInt(0)];
// Calculate h0: sum of the first 16 bytes
for (let i = 0; i < 16; i++) {
@@ -329,8 +456,8 @@ function hashCiphertext(ciphertext) {
computed_pubSignals[1] += BigInt(hashBuffer[i] * 2 ** (8 * (i - 16)));
}
// compare these with the console.log printout in Solidity
- console.log('computed_pubSignals[0]: ', computed_pubSignals[0]);
- console.log('computed_pubSignals[1]: ', computed_pubSignals[1]);
+ console.log("computed_pubSignals[0]: ", computed_pubSignals[0]);
+ console.log("computed_pubSignals[1]: ", computed_pubSignals[1]);
return computed_pubSignals;
}
diff --git a/zkp/js/test/burn.js b/zkp/js/test/burn.js
index 54a01ef0..7a6dff2b 100644
--- a/zkp/js/test/burn.js
+++ b/zkp/js/test/burn.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 poseidonHash = Poseidon.poseidon4;
-describe('burn circuit tests', () => {
+describe("burn circuit tests", () => {
let circuit;
const Alice = {};
@@ -31,7 +31,7 @@ describe('burn circuit tests', () => {
before(async function () {
this.timeout(60000);
- circuit = await wasm_tester(join(__dirname, '../../circuits/burn.circom'));
+ circuit = await wasm_tester(join(__dirname, "../../circuits/burn.circom"));
let keypair = genKeypair();
Alice.privKey = keypair.privKey;
@@ -39,7 +39,7 @@ describe('burn circuit tests', () => {
senderPrivateKey = formatPrivKeyForBabyJub(Alice.privKey);
});
- it('should succeed for valid witness', async () => {
+ it("should succeed for valid witness", async () => {
const values = [32, 40];
// create two input UTXOs, each has their own salt, but same owner
@@ -62,7 +62,7 @@ describe('burn circuit tests', () => {
outputValue: 70,
outputSalt: salt3,
},
- true
+ true,
);
// console.log('witness', witness.slice(0, 10));
@@ -74,7 +74,7 @@ describe('burn circuit tests', () => {
expect(witness[2]).to.equal(BigInt(inputCommitments[1]));
});
- it('should succeed for valid witness - single input', async () => {
+ it("should succeed for valid witness - single input", async () => {
const values = [72, 0];
// create two input UTXOs, each has their own salt, but same owner
@@ -95,14 +95,14 @@ describe('burn circuit tests', () => {
outputValue: 70,
outputSalt: salt3,
},
- true
+ true,
);
expect(witness[1]).to.equal(BigInt(inputCommitments[0]));
expect(witness[2]).to.equal(BigInt(inputCommitments[1]));
});
- it('should fail if output is greater than sum of the inputs', async () => {
+ it("should fail if output is greater than sum of the inputs", async () => {
const values = [32, 40];
// create two input UTXOs, each has their own salt, but same owner
@@ -127,12 +127,12 @@ describe('burn circuit tests', () => {
outputValue: 80,
outputSalt: salt3,
},
- true
+ true,
);
} catch (e) {
// console.log(e);
error = e;
}
- expect(error).to.match(/Error in template Burn_94 line: 66/);
+ expect(error).to.match(/Error in template Burn_94 line: 76/);
});
});
diff --git a/zkp/js/test/burn_nullifier.js b/zkp/js/test/burn_nullifier.js
index c0554e07..612c91d7 100644
--- a/zkp/js/test/burn_nullifier.js
+++ b/zkp/js/test/burn_nullifier.js
@@ -14,18 +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 } = require('../index.js');
-const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree');
+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 {
+ Merkletree,
+ InMemoryDB,
+ str2Bytes,
+ ZERO_HASH,
+} = require("@iden3/js-merkletree");
const SMT_HEIGHT = 64;
const poseidonHash = Poseidon.poseidon4;
const poseidonHash3 = Poseidon.poseidon3;
-describe('burn_nullifier circuit tests', () => {
+describe("burn_nullifier circuit tests", () => {
let circuit, smtAlice;
const Alice = {};
@@ -34,7 +39,9 @@ describe('burn_nullifier circuit tests', () => {
before(async function () {
this.timeout(60000);
- circuit = await wasm_tester(join(__dirname, '../../circuits/burn_nullifier.circom'));
+ circuit = await wasm_tester(
+ join(__dirname, "../../circuits/burn_nullifier.circom"),
+ );
let keypair = genKeypair();
Alice.privKey = keypair.privKey;
@@ -42,11 +49,11 @@ describe('burn_nullifier 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 values = [32, 40];
// create two input UTXOs, each has their own salt, but same owner
@@ -60,8 +67,16 @@ describe('burn_nullifier circuit tests', () => {
const outputCommitment = poseidonHash([BigInt(70), salt3, ...Alice.pubKey]);
// create the nullifiers for the inputs
- const nullifier1 = poseidonHash3([BigInt(values[0]), salt1, senderPrivateKey]);
- const nullifier2 = poseidonHash3([BigInt(values[1]), salt2, senderPrivateKey]);
+ const nullifier1 = poseidonHash3([
+ BigInt(values[0]),
+ salt1,
+ senderPrivateKey,
+ ]);
+ const nullifier2 = poseidonHash3([
+ BigInt(values[1]),
+ salt2,
+ senderPrivateKey,
+ ]);
const nullifiers = [nullifier1, nullifier2];
// calculate the root of the SMT
@@ -69,8 +84,14 @@ describe('burn_nullifier 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,
+ );
const witness = await circuit.calculateWitness(
{
@@ -80,13 +101,16 @@ describe('burn_nullifier circuit tests', () => {
inputSalts: [salt1, salt2],
ownerPrivateKey: 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],
outputCommitment,
outputValue: 70,
outputSalt: salt3,
},
- true
+ true,
);
// console.log('witness', witness.slice(0, 10));
@@ -99,7 +123,7 @@ describe('burn_nullifier circuit tests', () => {
expect(witness[2]).to.equal(BigInt(nullifiers[1]));
});
- it('should succeed for valid witness - single input', async () => {
+ it("should succeed for valid witness - single input", async () => {
const values = [72, 0];
// create two input UTXOs, each has their own salt, but same owner
@@ -108,7 +132,11 @@ describe('burn_nullifier circuit tests', () => {
const inputCommitments = [input1, 0];
// create the nullifiers for the inputs
- const nullifier1 = poseidonHash3([BigInt(values[0]), salt1, senderPrivateKey]);
+ const nullifier1 = poseidonHash3([
+ BigInt(values[0]),
+ salt1,
+ senderPrivateKey,
+ ]);
const nullifiers = [nullifier1, 0];
const salt3 = newSalt();
@@ -118,7 +146,10 @@ describe('burn_nullifier circuit tests', () => {
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);
const witness = await circuit.calculateWitness(
@@ -129,20 +160,23 @@ describe('burn_nullifier circuit tests', () => {
inputSalts: [salt1, 0],
ownerPrivateKey: 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],
outputCommitment,
outputValue: 70,
outputSalt: salt3,
},
- true
+ true,
);
expect(witness[1]).to.equal(BigInt(nullifiers[0]));
expect(witness[2]).to.equal(BigInt(nullifiers[1]));
});
- it('should fail if the output UTXO has a bigger value', async () => {
+ it("should fail if the output UTXO has a bigger value", async () => {
const values = [32, 40];
// create two input UTXOs, each has their own salt, but same owner
@@ -156,8 +190,16 @@ describe('burn_nullifier circuit tests', () => {
const outputCommitment = poseidonHash([BigInt(80), salt3, ...Alice.pubKey]);
// create the nullifiers for the inputs
- const nullifier1 = poseidonHash3([BigInt(values[0]), salt1, senderPrivateKey]);
- const nullifier2 = poseidonHash3([BigInt(values[1]), salt2, senderPrivateKey]);
+ const nullifier1 = poseidonHash3([
+ BigInt(values[0]),
+ salt1,
+ senderPrivateKey,
+ ]);
+ const nullifier2 = poseidonHash3([
+ BigInt(values[1]),
+ salt2,
+ senderPrivateKey,
+ ]);
const nullifiers = [nullifier1, nullifier2];
// calculate the root of the SMT
@@ -165,8 +207,14 @@ describe('burn_nullifier 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,
+ );
let error;
try {
@@ -178,18 +226,21 @@ describe('burn_nullifier circuit tests', () => {
inputSalts: [salt1, salt2],
ownerPrivateKey: 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],
outputCommitment,
outputValue: 80,
outputSalt: salt3,
},
- true
+ true,
);
} catch (e) {
// console.log('error', e);
error = e;
}
- expect(error).to.match(/Error in template BurnNullifiers_251 line: 83/);
+ expect(error).to.match(/Error in template BurnNullifiers_251 line: 93/);
});
});
diff --git a/zkp/js/test/check_nullifiers.js b/zkp/js/test/check_nullifiers.js
index 86efb235..97183edf 100644
--- a/zkp/js/test/check_nullifiers.js
+++ b/zkp/js/test/check_nullifiers.js
@@ -150,6 +150,6 @@ describe("check_nullifiers circuit tests", () => {
err = e;
}
// console.log(err);
- expect(err).to.match(/Error in template Zeto_159 line: 51/);
+ expect(err).to.match(/Error in template Zeto_159 line: 53/);
});
});
diff --git a/zkp/js/test/circuits/check-hashes.circom b/zkp/js/test/circuits/check-hashes.circom
index 9e07994e..15358792 100644
--- a/zkp/js/test/circuits/check-hashes.circom
+++ b/zkp/js/test/circuits/check-hashes.circom
@@ -17,4 +17,4 @@ pragma circom 2.2.2;
include "../../../circuits/lib/check-hashes.circom";
-component main {public [ commitments, ownerPublicKeys ]} = CheckHashes(2);
\ No newline at end of file
+component main {public [ commitmentHashes ]} = CheckHashes(2);
\ No newline at end of file
diff --git a/zkp/js/test/deposit.js b/zkp/js/test/deposit.js
index 06d7e2b6..af628755 100644
--- a/zkp/js/test/deposit.js
+++ b/zkp/js/test/deposit.js
@@ -133,7 +133,7 @@ describe("deposit circuit tests", () => {
error = e;
}
// console.log(error);
- expect(error).to.match(/Error in template CheckHashes_80 line: 47/); // hash check failed
+ expect(error).to.match(/Error in template CheckHashes_80 line: 45/); // hash check failed
});
it("should fail to generate a witness because of negative values in output commitments", async () => {
diff --git a/zkp/js/test/lib/check-hashes.js b/zkp/js/test/lib/check-hashes.js
index cded1dcb..c40f0920 100644
--- a/zkp/js/test/lib/check-hashes.js
+++ b/zkp/js/test/lib/check-hashes.js
@@ -1,4 +1,4 @@
-// Copyright © 2024 Kaleido, Inc.
+// Copyright © 2025 Kaleido, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
@@ -15,7 +15,6 @@
// 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");
@@ -52,25 +51,36 @@ describe("check-hashes circuit tests", () => {
const input1 = poseidonHash([BigInt(values[0]), salt1, ...sender.pubKey]);
const salt2 = newSalt();
const input2 = poseidonHash([BigInt(values[1]), salt2, ...sender.pubKey]);
- const commitments = [input1, input2];
+ const commitmentHashes = [input1, input2];
const witness = await circuit.calculateWitness(
{
- commitments,
- values,
- salts: [salt1, salt2],
- ownerPublicKeys: [sender.pubKey, sender.pubKey],
+ commitmentHashes,
+ commitmentInputs: [
+ BigInt(values[0]),
+ salt1,
+ ...sender.pubKey,
+ BigInt(values[1]),
+ salt2,
+ ...sender.pubKey,
+ ],
},
true,
);
// console.log(witness.slice(0, 10));
- // console.log('commitments', commitments);
+ // console.log('commitmentHashes', commitmentHashes);
// console.log('sender public key', sender.pubKey);
- expect(witness[1]).to.equal(BigInt(commitments[0]));
- expect(witness[2]).to.equal(BigInt(commitments[1]));
- expect(witness[3]).to.equal(BigInt(sender.pubKey[0]));
- expect(witness[4]).to.equal(BigInt(sender.pubKey[1]));
+ expect(witness[1]).to.equal(BigInt(commitmentHashes[0]));
+ expect(witness[2]).to.equal(BigInt(commitmentHashes[1]));
+ expect(witness[3]).to.equal(BigInt(values[0]));
+ expect(witness[4]).to.equal(salt1);
+ expect(witness[5]).to.equal(BigInt(sender.pubKey[0]));
+ expect(witness[6]).to.equal(BigInt(sender.pubKey[1]));
+ expect(witness[7]).to.equal(BigInt(values[1]));
+ expect(witness[8]).to.equal(salt2);
+ expect(witness[9]).to.equal(BigInt(sender.pubKey[0]));
+ expect(witness[10]).to.equal(BigInt(sender.pubKey[1]));
});
it("should return true for valid witness using a single input value", async () => {
@@ -79,22 +89,28 @@ describe("check-hashes circuit tests", () => {
// create two input UTXOs, each has their own salt, but same owner
const salt1 = newSalt();
const input1 = poseidonHash([BigInt(values[0]), salt1, ...sender.pubKey]);
- const commitments = [input1, 0];
+ const commitmentHashes = [input1, 0];
const witness = await circuit.calculateWitness(
{
- commitments,
- values,
- salts: [salt1, 0],
- ownerPublicKeys: [sender.pubKey, [0n, 0n]],
+ commitmentHashes,
+ commitmentInputs: [
+ BigInt(values[0]),
+ salt1,
+ ...sender.pubKey,
+ BigInt(values[1]),
+ 0,
+ 0n,
+ 0n,
+ ],
},
true,
);
- expect(witness[1]).to.equal(BigInt(commitments[0]));
- expect(witness[2]).to.equal(BigInt(commitments[1]));
- expect(witness[3]).to.equal(BigInt(sender.pubKey[0]));
- expect(witness[4]).to.equal(BigInt(sender.pubKey[1]));
+ expect(witness[1]).to.equal(BigInt(commitmentHashes[0]));
+ expect(witness[2]).to.equal(BigInt(commitmentHashes[1]));
+ expect(witness[5]).to.equal(BigInt(sender.pubKey[0]));
+ expect(witness[6]).to.equal(BigInt(sender.pubKey[1]));
});
it("should return true for valid witness using a single input value", async () => {
@@ -103,27 +119,35 @@ describe("check-hashes circuit tests", () => {
// create two input UTXOs, each has their own salt, but same owner
const salt1 = newSalt();
const input1 = poseidonHash([BigInt(values[1]), salt1, ...sender.pubKey]);
- const commitments = [0n, input1];
+ const commitmentHashes = [0n, input1];
const witness = await circuit.calculateWitness(
{
- commitments,
- values,
- salts: [0, salt1],
- ownerPublicKeys: [[0n, 0n], sender.pubKey],
+ commitmentHashes,
+ commitmentInputs: [
+ BigInt(values[0]),
+ 0,
+ 0n,
+ 0n,
+ BigInt(values[1]),
+ salt1,
+ ...sender.pubKey,
+ ],
},
true,
);
- expect(witness[1]).to.equal(BigInt(commitments[0]));
- expect(witness[2]).to.equal(BigInt(commitments[1]));
+ expect(witness[1]).to.equal(BigInt(commitmentHashes[0]));
+ expect(witness[2]).to.equal(BigInt(commitmentHashes[1]));
expect(witness[3]).to.equal(0n);
expect(witness[4]).to.equal(0n);
- expect(witness[5]).to.equal(BigInt(sender.pubKey[0]));
- expect(witness[6]).to.equal(BigInt(sender.pubKey[1]));
+ expect(witness[5]).to.equal(0n);
+ expect(witness[6]).to.equal(0n);
+ expect(witness[9]).to.equal(BigInt(sender.pubKey[0]));
+ expect(witness[10]).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 commitmentHashes", async () => {
const inputValues = [25, 100];
// create two input UTXOs, each has their own salt, but same owner
@@ -139,16 +163,21 @@ describe("check-hashes circuit tests", () => {
salt2,
...sender.pubKey,
]);
- const inputCommitments = [input1 + BigInt(1), input2];
+ const commitmentHashes = [input1 + BigInt(1), input2];
let error;
try {
await circuit.calculateWitness(
{
- commitments: inputCommitments,
- values: inputValues,
- salts: [salt1, salt2],
- ownerPublicKeys: [sender.pubKey, sender.pubKey],
+ commitmentHashes,
+ commitmentInputs: [
+ BigInt(inputValues[0]),
+ salt1,
+ ...sender.pubKey,
+ BigInt(inputValues[1]),
+ salt2,
+ ...sender.pubKey,
+ ],
},
true,
);
@@ -156,6 +185,6 @@ describe("check-hashes circuit tests", () => {
error = e;
}
// console.log(error);
- expect(error).to.match(/Error in template CheckHashes_76 line: 47/); // hash check failed
+ expect(error).to.match(/Error in template CheckHashes_76 line: 45/); // hash check failed
});
});