From 5abd0a5b754171515eec0a891a92276486cf681e Mon Sep 17 00:00:00 2001 From: Antony-SS Date: Thu, 29 Jun 2023 09:35:11 -0500 Subject: [PATCH 01/11] Dependencies Update: @types/node update --- package-lock.json | 16 ++++++++-------- package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index c64eb62b5..77b90286c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,7 @@ "prettier": "^2.2.1", "shelljs": "^0.8.5", "solc": "^0.8.0", - "typescript": "4.9.5", + "typescript": "^4.9.5", "winston": "^3.3.3", "yargs": "^15.4.1", "zkp-utils": "^1.0.8" @@ -47,7 +47,7 @@ "@types/json-diff": "^0.7.0", "@types/lodash.clonedeep": "^4.5.6", "@types/mocha": "^9.1.0", - "@types/node": "^17.0.19", + "@types/node": "^17.0.45", "@types/prettier": "^2.4.4", "chai-as-promised": "^7.1.1", "chai-http": "^4.3.0", @@ -2272,9 +2272,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "17.0.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.19.tgz", - "integrity": "sha512-PfeQhvcMR4cPFVuYfBN4ifG7p9c+Dlh3yUZR6k+5yQK7wX3gDgVxBly4/WkBRs9x4dmcy1TVl08SY67wwtEvmA==", + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", "dev": true }, "node_modules/@types/normalize-package-data": { @@ -14094,9 +14094,9 @@ "dev": true }, "@types/node": { - "version": "17.0.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.19.tgz", - "integrity": "sha512-PfeQhvcMR4cPFVuYfBN4ifG7p9c+Dlh3yUZR6k+5yQK7wX3gDgVxBly4/WkBRs9x4dmcy1TVl08SY67wwtEvmA==", + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", "dev": true }, "@types/normalize-package-data": { diff --git a/package.json b/package.json index 65e7f899b..569381f13 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "@types/json-diff": "^0.7.0", "@types/lodash.clonedeep": "^4.5.6", "@types/mocha": "^9.1.0", - "@types/node": "^17.0.19", + "@types/node": "^17.0.45", "@types/prettier": "^2.4.4", "chai-as-promised": "^7.1.1", "chai-http": "^4.3.0", From c898d062c8bd2a78c22083b653f143d31766e3dd Mon Sep 17 00:00:00 2001 From: Antony-SS Date: Thu, 29 Jun 2023 13:07:35 -0500 Subject: [PATCH 02/11] Adding Test Contract --- test_contracts/Assign.zol | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 test_contracts/Assign.zol diff --git a/test_contracts/Assign.zol b/test_contracts/Assign.zol new file mode 100644 index 000000000..17dec032d --- /dev/null +++ b/test_contracts/Assign.zol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: CC0 + +pragma solidity ^0.8.0; + +contract Assign { + + secret uint256 private a; // <--- secret + + function assign(secret uint256 value) public { // <--- secret + a = value; + } +} \ No newline at end of file From 8a07c84c3551a69fa644809126c1f2da0bc0a7be Mon Sep 17 00:00:00 2001 From: Antony-SS Date: Fri, 30 Jun 2023 16:09:40 -0500 Subject: [PATCH 03/11] sdfg --- contracts/verify/Verifier.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/verify/Verifier.sol b/contracts/verify/Verifier.sol index 52d3e434a..638a11b4d 100644 --- a/contracts/verify/Verifier.sol +++ b/contracts/verify/Verifier.sol @@ -49,7 +49,7 @@ contract Verifier is Ownable { uint256 private r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; function validateInputs(uint256[] memory _inputs) public view { - for (uint i = 0; i < _inputs.length; i++) { + for (uint i = 0; i < _inputs.length; i++) { // Should use pre increment instead of post to save gas require(_inputs[i] < r, "Inputs must be less than r."); } } From 61b3173c0eaacb7d56e0c11e2543aa8a2922f82a Mon Sep 17 00:00:00 2001 From: Antony-SS Date: Fri, 30 Jun 2023 17:57:31 -0500 Subject: [PATCH 04/11] Gas Savings: i++ to ++i in Verifier --- contracts/verify/Verifier.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/verify/Verifier.sol b/contracts/verify/Verifier.sol index 638a11b4d..83fb059b1 100644 --- a/contracts/verify/Verifier.sol +++ b/contracts/verify/Verifier.sol @@ -49,7 +49,7 @@ contract Verifier is Ownable { uint256 private r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; function validateInputs(uint256[] memory _inputs) public view { - for (uint i = 0; i < _inputs.length; i++) { // Should use pre increment instead of post to save gas + for (uint i = 0; i < _inputs.length; ++i) { require(_inputs[i] < r, "Inputs must be less than r."); } } @@ -92,7 +92,7 @@ contract Verifier is Ownable { require(vk.gamma_abc.length == _publicInputs.length + 1, "Length of inputs[] or vk.query is incorrect!"); Pairing.G1Point memory sm_qpih; - for (uint i = 0; i < _publicInputs.length; i++) { + for (uint i = 0; i < _publicInputs.length; ++i) { sm_qpih = Pairing.scalar_mul(vk.gamma_abc[i+1], _publicInputs[i]); vk_dot_inputs = Pairing.addition( vk_dot_inputs, From c5a9ee569477ce6dabf09b2e1811c293993b6925 Mon Sep 17 00:00:00 2001 From: Antony-SS Date: Mon, 10 Jul 2023 12:44:20 -0500 Subject: [PATCH 05/11] Gas Savings: i++ to ++i in Pairing Contract --- contracts/verify/Pairing.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/verify/Pairing.sol b/contracts/verify/Pairing.sol index d652b75a8..93f03e790 100644 --- a/contracts/verify/Pairing.sol +++ b/contracts/verify/Pairing.sol @@ -90,7 +90,7 @@ library Pairing { uint elements = p1.length; uint inputSize = elements * 6; uint[] memory input = new uint[](inputSize); - for (uint i = 0; i < elements; i++) + for (uint i = 0; i < elements; ++i) { input[i * 6 + 0] = p1[i].X; input[i * 6 + 1] = p1[i].Y; From b241af574b7d23921f8f084aa0120bb44ad9cde8 Mon Sep 17 00:00:00 2001 From: Antony-SS Date: Mon, 10 Jul 2023 12:45:43 -0500 Subject: [PATCH 06/11] Deleting Files that shouldn't be tracked --- test_contracts/Assign.zol | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 test_contracts/Assign.zol diff --git a/test_contracts/Assign.zol b/test_contracts/Assign.zol deleted file mode 100644 index 17dec032d..000000000 --- a/test_contracts/Assign.zol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: CC0 - -pragma solidity ^0.8.0; - -contract Assign { - - secret uint256 private a; // <--- secret - - function assign(secret uint256 value) public { // <--- secret - a = value; - } -} \ No newline at end of file From 6da228dceb3175e4a21aa42bdb497b8a3dfa054e Mon Sep 17 00:00:00 2001 From: Antony-SS Date: Mon, 10 Jul 2023 12:47:55 -0500 Subject: [PATCH 07/11] Adding "test-contracts" file to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 973ce80b6..371305122 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ node_modules/ proving-files/ zapps/ test-zapps/ +test-contracts/ \ No newline at end of file From 8462aca238e0229e0f6b50851e0f45f076768e3d Mon Sep 17 00:00:00 2001 From: Antony-SS Date: Mon, 10 Jul 2023 15:08:24 -0500 Subject: [PATCH 08/11] Gas Savings: Change Memory to Calldata in Verifier --- contracts/verify/Verifier.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/verify/Verifier.sol b/contracts/verify/Verifier.sol index 83fb059b1..3ea375c52 100644 --- a/contracts/verify/Verifier.sol +++ b/contracts/verify/Verifier.sol @@ -48,7 +48,7 @@ contract Verifier is Ownable { uint256 private r = 21888242871839275222246405745257275088548364400416034343698204186575808495617; - function validateInputs(uint256[] memory _inputs) public view { + function validateInputs(uint256[] calldata _inputs) public view { for (uint i = 0; i < _inputs.length; ++i) { require(_inputs[i] < r, "Inputs must be less than r."); } @@ -63,7 +63,7 @@ contract Verifier is Ownable { } } - function verificationCalculation(uint256[] memory _proof, uint256[] memory _publicInputs, uint256[] memory _vk) public returns (uint) { + function verificationCalculation(uint256[] calldata _proof, uint256[] calldata _publicInputs, uint256[] calldata _vk) public returns (uint) { Proof_G16 memory proof; Pairing.G1Point memory vk_dot_inputs; From 9768915f1fe43b3c35c8f8915ac0129d250ea726 Mon Sep 17 00:00:00 2001 From: Antony-SS Date: Wed, 12 Jul 2023 12:33:30 -0500 Subject: [PATCH 09/11] Gas Opt: ++i in MiMC.sol --- contracts/merkle-tree/MiMC.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/merkle-tree/MiMC.sol b/contracts/merkle-tree/MiMC.sol index a58d3f46f..0fda80cd4 100644 --- a/contracts/merkle-tree/MiMC.sol +++ b/contracts/merkle-tree/MiMC.sol @@ -68,7 +68,7 @@ contract MiMC uint256 r = in_k; uint256 localQ = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001; uint256 i; - for( i = 0; i < in_x.length; i++ ) + for( i = 0; i < in_x.length; ++i ) { r = (r + (in_x[i] % localQ) + MiMCp(in_x[i], r, in_seed, round_count)) % localQ; } From e0917774d6e0f06bdc68d33428c1a2f2e5afc467 Mon Sep 17 00:00:00 2001 From: Antony-SS Date: Wed, 12 Jul 2023 12:34:06 -0500 Subject: [PATCH 10/11] Gas Opt: Marking constants, caching in MerkleTree --- contracts/merkle-tree/MerkleTree.sol | 49 +++++++++++++++------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/contracts/merkle-tree/MerkleTree.sol b/contracts/merkle-tree/MerkleTree.sol index de3c300f0..9b32e99c7 100644 --- a/contracts/merkle-tree/MerkleTree.sol +++ b/contracts/merkle-tree/MerkleTree.sol @@ -51,9 +51,9 @@ contract MerkleTree is MiMC { // event Output(uint[] input, uint[] output, uint prevNodeIndex, uint nodeIndex); // for debugging only - uint public zero = 0; - uint public treeHeight = 32; // - uint public treeWidth = 2 ** treeHeight; + uint public constant zero = 0; + uint public constant treeHeight = 32; + uint public constant treeWidth = uint64(2 ** treeHeight); uint public leafCount; // the number of leaves currently in the tree /** @@ -85,7 +85,7 @@ contract MerkleTree is MiMC { } else { pow1 = pow2; pow2 = pow2 << 1; - exp1++; + ++exp1; } } } @@ -97,19 +97,20 @@ contract MerkleTree is MiMC { @return root - the root of the merkle tree, after the insert. */ function insertLeaf(uint leafValue) public returns (uint root) { - + // Cache variables so they aren't continually read from storage + (uint treeHeight_, uint treeWidth_, uint leafCount_) = (treeHeight, treeWidth, leafCount); // check that space exists in the tree: - require(treeWidth > leafCount, "There is no space left in the tree."); + require(treeWidth_ > leafCount_, "There is no space left in the tree."); - uint slot = getFrontierSlot(leafCount); - uint nodeIndex = leafCount + treeWidth - 1; + uint slot = getFrontierSlot(leafCount_); + uint nodeIndex = leafCount_ + treeWidth_ - 1; uint prevNodeIndex; uint nodeValue = leafValue; // nodeValue is the hash, which iteratively gets overridden to the top of the tree until it becomes the root. uint[] memory input = new uint[](2); //input of the hash fuction uint[] memory output = new uint[](1); // output of the hash function - for (uint level = 0; level < treeHeight; level++) { + for (uint level = 0; level < treeHeight_; ++level) { if (level == slot) frontier[slot] = nodeValue; @@ -139,9 +140,9 @@ contract MerkleTree is MiMC { root = nodeValue; root = uint(bytes32(root)); - emit NewLeaf(leafCount, leafValue, root); // this event is what the merkle-tree microservice's filter will listen for. + emit NewLeaf(leafCount_, leafValue, root); // this event is what the merkle-tree microservice's filter will listen for. - leafCount++; // the incrememnting of leafCount costs us 20k for the first leaf, and 5k thereafter + ++leafCount; // the incrememnting of leafCount costs us 20k for the first leaf, and 5k thereafter return root; //the root of the tree } @@ -152,15 +153,17 @@ contract MerkleTree is MiMC { @return root - the root of the merkle tree, after all the inserts. */ function insertLeaves(uint[] memory leafValues) public returns (uint root) { + // read pertinent vars into memory from storage in one operation + (uint treeHeight_, uint treeWidth_, uint leafCount_) = (treeHeight, treeWidth, leafCount); uint numberOfLeaves = leafValues.length; // check that space exists in the tree: - require(treeWidth > leafCount, "There is no space left in the tree."); - if (numberOfLeaves > treeWidth - leafCount) { - uint numberOfExcessLeaves = numberOfLeaves - (treeWidth - leafCount); + require(treeWidth_ > leafCount_, "There is no space left in the tree."); + if (numberOfLeaves > treeWidth_ - leafCount_) { + uint numberOfExcessLeaves = numberOfLeaves - (treeWidth_ - leafCount_); // remove the excess leaves, because we only want to emit those we've added as an event: - for (uint xs = 0; xs < numberOfExcessLeaves; xs++) { + for (uint xs = 0; xs < numberOfExcessLeaves; ++xs) { /* CAUTION!!! This attempts to succinctly achieve leafValues.pop() on a **memory** dynamic array. Not thoroughly tested! Credit: https://ethereum.stackexchange.com/a/51897/45916 @@ -170,7 +173,7 @@ contract MerkleTree is MiMC { mstore(leafValues, sub(mload(leafValues), 1)) } } - numberOfLeaves = treeWidth - leafCount; + numberOfLeaves = treeWidth_ - leafCount_; } uint slot; @@ -182,9 +185,9 @@ contract MerkleTree is MiMC { uint[] memory output = new uint[](1); // the output of the hash // consider each new leaf in turn, from left to right: - for (uint leafIndex = leafCount; leafIndex < leafCount + numberOfLeaves; leafIndex++) { - nodeValue = leafValues[leafIndex - leafCount]; - nodeIndex = leafIndex + treeWidth - 1; // convert the leafIndex to a nodeIndex + for (uint leafIndex = leafCount_; leafIndex < leafCount_ + numberOfLeaves; ++leafIndex) { + nodeValue = leafValues[leafIndex - leafCount_]; + nodeIndex = leafIndex + treeWidth_ - 1; // convert the leafIndex to a nodeIndex slot = getFrontierSlot(leafIndex); // determine at which level we will next need to store a nodeValue @@ -194,7 +197,7 @@ contract MerkleTree is MiMC { } // hash up to the level whose nodeValue we'll store in the frontier slot: - for (uint level = 1; level <= slot; level++) { + for (uint level = 1; level <= slot; ++level) { if (nodeIndex % 2 == 0) { // even nodeIndex input[0] = frontier[level - 1]; //replace with push? @@ -221,7 +224,7 @@ contract MerkleTree is MiMC { } // So far we've added all leaves, and hashed up to a particular level of the tree. We now need to continue hashing from that level until the root: - for (uint level = slot + 1; level <= treeHeight; level++) { + for (uint level = slot + 1; level <= treeHeight_; ++level) { if (nodeIndex % 2 == 0) { // even nodeIndex @@ -250,9 +253,9 @@ contract MerkleTree is MiMC { root = nodeValue; root = uint(bytes32(root)); - emit NewLeaves(leafCount, leafValues, root); // this event is what the merkle-tree microservice's filter will listen for. + emit NewLeaves(leafCount_, leafValues, root); // this event is what the merkle-tree microservice's filter will listen for. - leafCount += numberOfLeaves; // the incrememnting of leafCount costs us 20k for the first leaf, and 5k thereafter + leafCount += numberOfLeaves; // the incrementing of leafCount costs us 20k for the first leaf, and 5k thereafter return root; //the root of the tree } From 149719fcd122daeac12826303935974d567f1750 Mon Sep 17 00:00:00 2001 From: Antony-SS Date: Wed, 12 Jul 2023 13:49:23 -0500 Subject: [PATCH 11/11] Gas Opt: Adding unchecked, indexed --- contracts/merkle-tree/MerkleTree.sol | 16 +++++++++++----- contracts/merkle-tree/MiMC.sol | 4 ++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/contracts/merkle-tree/MerkleTree.sol b/contracts/merkle-tree/MerkleTree.sol index 9b32e99c7..44a9a5aeb 100644 --- a/contracts/merkle-tree/MerkleTree.sol +++ b/contracts/merkle-tree/MerkleTree.sol @@ -46,8 +46,8 @@ contract MerkleTree is MiMC { /** These events are what the merkle-tree microservice's filters will listen for. */ - event NewLeaf(uint leafIndex, uint leafValue, uint root); - event NewLeaves(uint minLeafIndex, uint[] leafValues, uint root); + event NewLeaf(uint indexed leafIndex, uint indexed leafValue, uint indexed root); + event NewLeaves(uint indexed minLeafIndex, uint[] leafValues, uint indexed root); // event Output(uint[] input, uint[] output, uint prevNodeIndex, uint nodeIndex); // for debugging only @@ -110,7 +110,7 @@ contract MerkleTree is MiMC { uint[] memory input = new uint[](2); //input of the hash fuction uint[] memory output = new uint[](1); // output of the hash function - for (uint level = 0; level < treeHeight_; ++level) { + for (uint level = 0; level < treeHeight_;) { if (level == slot) frontier[slot] = nodeValue; @@ -135,6 +135,9 @@ contract MerkleTree is MiMC { nodeIndex = nodeIndex / 2; // move one row up the tree // emit Output(input, output, prevNodeIndex, nodeIndex); // for debugging only } + unchecked { + ++level; // GAS OPT: we know this won't overflow + } } root = nodeValue; @@ -224,7 +227,7 @@ contract MerkleTree is MiMC { } // So far we've added all leaves, and hashed up to a particular level of the tree. We now need to continue hashing from that level until the root: - for (uint level = slot + 1; level <= treeHeight_; ++level) { + for (uint level = slot + 1; level <= treeHeight_;) { if (nodeIndex % 2 == 0) { // even nodeIndex @@ -247,7 +250,10 @@ contract MerkleTree is MiMC { nodeIndex = nodeIndex / 2; // the parentIndex, but will become the nodeIndex of the next level // emit Output(input, output, prevNodeIndex, nodeIndex); // for debugging only } - + + unchecked { + ++level; + } } root = nodeValue; diff --git a/contracts/merkle-tree/MiMC.sol b/contracts/merkle-tree/MiMC.sol index 0fda80cd4..d4f44f849 100644 --- a/contracts/merkle-tree/MiMC.sol +++ b/contracts/merkle-tree/MiMC.sol @@ -67,8 +67,8 @@ contract MiMC { uint256 r = in_k; uint256 localQ = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001; - uint256 i; - for( i = 0; i < in_x.length; ++i ) + + for(uint256 i = 0; i < in_x.length; ++i ) { r = (r + (in_x[i] % localQ) + MiMCp(in_x[i], r, in_seed, round_count)) % localQ; }