-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds merkle extension directory (#124)
* Add EVM webb anchor contracts w/ CHAIN_ID * zkutil script * Add old evm files and wasm project for merkle extension * update toml * Add yarn lock
- Loading branch information
Showing
26 changed files
with
10,162 additions
and
7,457 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,6 @@ runtime/target | |
/*/**/target | ||
.vscode | ||
node_modules | ||
build | ||
cache | ||
artifacts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
include "../node_modules/circomlib/circuits/mimcsponge.circom"; | ||
|
||
// Computes MiMC([left, right]) | ||
template HashLeftRight() { | ||
signal input left; | ||
signal input right; | ||
signal output hash; | ||
|
||
component hasher = MiMCSponge(2, 1); | ||
hasher.ins[0] <== left; | ||
hasher.ins[1] <== right; | ||
hasher.k <== 0; | ||
hash <== hasher.outs[0]; | ||
} | ||
|
||
// if s == 0 returns [in[0], in[1]] | ||
// if s == 1 returns [in[1], in[0]] | ||
template DualMux() { | ||
signal input in[2]; | ||
signal input s; | ||
signal output out[2]; | ||
|
||
s * (1 - s) === 0 | ||
out[0] <== (in[1] - in[0])*s + in[0]; | ||
out[1] <== (in[0] - in[1])*s + in[1]; | ||
} | ||
|
||
// Verifies that merkle proof is correct for given merkle root and a leaf | ||
// pathIndices input is an array of 0/1 selectors telling whether given pathElement is on the left or right side of merkle path | ||
template MerkleTreeChecker(levels) { | ||
signal input leaf; | ||
signal input root; | ||
signal input pathElements[levels]; | ||
signal input pathIndices[levels]; | ||
|
||
component selectors[levels]; | ||
component hashers[levels]; | ||
|
||
for (var i = 0; i < levels; i++) { | ||
selectors[i] = DualMux(); | ||
selectors[i].in[0] <== i == 0 ? leaf : hashers[i - 1].hash; | ||
selectors[i].in[1] <== pathElements[i]; | ||
selectors[i].s <== pathIndices[i]; | ||
|
||
hashers[i] = HashLeftRight(); | ||
hashers[i].left <== selectors[i].out[0]; | ||
hashers[i].right <== selectors[i].out[1]; | ||
} | ||
|
||
root === hashers[levels - 1].hash; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
include "../node_modules/circomlib/circuits/bitify.circom"; | ||
include "../node_modules/circomlib/circuits/pedersen.circom"; | ||
include "merkleTree.circom"; | ||
|
||
// computes Pedersen(nullifier + secret) | ||
template CommitmentHasher() { | ||
signal input nullifier; | ||
signal input secret; | ||
signal output commitment; | ||
signal output nullifierHash; | ||
|
||
component commitmentHasher = Pedersen(496); | ||
component nullifierHasher = Pedersen(248); | ||
component nullifierBits = Num2Bits(248); | ||
component secretBits = Num2Bits(248); | ||
nullifierBits.in <== nullifier; | ||
secretBits.in <== secret; | ||
for (var i = 0; i < 248; i++) { | ||
nullifierHasher.in[i] <== nullifierBits.out[i]; | ||
commitmentHasher.in[i] <== nullifierBits.out[i]; | ||
commitmentHasher.in[i + 248] <== secretBits.out[i]; | ||
} | ||
|
||
commitment <== commitmentHasher.out[0]; | ||
nullifierHash <== nullifierHasher.out[0]; | ||
} | ||
|
||
// Verifies that commitment that corresponds to given secret and nullifier is included in the merkle tree of deposits | ||
template Withdraw(levels) { | ||
signal input root; | ||
signal input nullifierHash; | ||
signal input recipient; // not taking part in any computations | ||
signal input relayer; // not taking part in any computations | ||
signal input fee; // not taking part in any computations | ||
signal input refund; // not taking part in any computations | ||
signal private input nullifier; | ||
signal private input secret; | ||
signal private input pathElements[levels]; | ||
signal private input pathIndices[levels]; | ||
|
||
component hasher = CommitmentHasher(); | ||
hasher.nullifier <== nullifier; | ||
hasher.secret <== secret; | ||
hasher.nullifierHash === nullifierHash; | ||
|
||
component tree = MerkleTreeChecker(levels); | ||
tree.leaf <== hasher.commitment; | ||
tree.root <== root; | ||
for (var i = 0; i < levels; i++) { | ||
tree.pathElements[i] <== pathElements[i]; | ||
tree.pathIndices[i] <== pathIndices[i]; | ||
} | ||
|
||
// Add hidden signals to make sure that tampering with recipient or fee will invalidate the snark proof | ||
// Most likely it is not required, but it's better to stay on the safe side and it only takes 2 constraints | ||
// Squares are used to prevent optimizer from removing those constraints | ||
signal recipientSquare; | ||
signal feeSquare; | ||
signal relayerSquare; | ||
signal refundSquare; | ||
recipientSquare <== recipient * recipient; | ||
feeSquare <== fee * fee; | ||
relayerSquare <== relayer * relayer; | ||
refundSquare <== refund * refund; | ||
} | ||
|
||
component main = Withdraw(20); |
Oops, something went wrong.