mirror of
				https://github.com/tornadocash/tornado-core.git
				synced 2025-10-30 22:18:54 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			74 lines
		
	
	
		
			No EOL
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			74 lines
		
	
	
		
			No EOL
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| include "../node_modules/circomlib/circuits/bitify.circom";
 | |
| include "../node_modules/circomlib/circuits/mimcsponge.circom";
 | |
| 
 | |
| // Computes MiMC(left + right)
 | |
| template HashLeftRight(rounds) {
 | |
|     signal input left;
 | |
|     signal input right;
 | |
| 
 | |
|     signal output hash;
 | |
| 
 | |
|     component hasher = MiMCSponge(2, rounds, 1);
 | |
|     hasher.ins[0] <== left;
 | |
|     hasher.ins[1] <== right;
 | |
|     hasher.k <== 0;
 | |
| 
 | |
|     hash <== hasher.outs[0];
 | |
| }
 | |
| 
 | |
| // if pathIndex == 0 returns (left = inputElement, right = pathElement)
 | |
| // if pathIndex == 1 returns (left = pathElement, right = inputElement)
 | |
| template Selector() {
 | |
|     signal input inputElement;
 | |
|     signal input pathElement;
 | |
|     signal input pathIndex;
 | |
| 
 | |
|     signal output left;
 | |
|     signal output right;
 | |
| 
 | |
|     signal leftSelector1;
 | |
|     signal leftSelector2;
 | |
|     signal rightSelector1;
 | |
|     signal rightSelector2;
 | |
| 
 | |
|     pathIndex * (1-pathIndex) === 0
 | |
| 
 | |
|     leftSelector1 <== (1 - pathIndex) * inputElement;
 | |
|     leftSelector2 <== (pathIndex) * pathElement;
 | |
|     rightSelector1 <== (pathIndex) * inputElement;
 | |
|     rightSelector2 <== (1 - pathIndex) * pathElement;
 | |
| 
 | |
|     left <== leftSelector1 + leftSelector2;
 | |
|     right <== rightSelector1 + rightSelector2;
 | |
| }
 | |
| 
 | |
| // Verifies that merkle proof is correct for given merkle root and a leaf
 | |
| // pathIndex input is an array of 0/1 selectors telling whether given pathElement is on the left or right side of merkle path
 | |
| template MerkleTree(levels, rounds) {
 | |
|     signal input leaf;
 | |
|     signal input root;
 | |
|     signal private input pathElements[levels];
 | |
|     signal private input pathIndex[levels];
 | |
| 
 | |
|     component selectors[levels];
 | |
|     component hashers[levels];
 | |
| 
 | |
|     for (var i = 0; i < levels; i++) {
 | |
|         selectors[i] = Selector();
 | |
|         hashers[i] = HashLeftRight(rounds);
 | |
| 
 | |
|         selectors[i].pathElement <== pathElements[i];
 | |
|         selectors[i].pathIndex <== pathIndex[i];
 | |
| 
 | |
|         hashers[i].left <== selectors[i].left;
 | |
|         hashers[i].right <== selectors[i].right;
 | |
|     }
 | |
| 
 | |
|     selectors[0].inputElement <== leaf;
 | |
| 
 | |
|     for (var i = 1; i < levels; i++) {
 | |
|         selectors[i].inputElement <== hashers[i-1].hash;
 | |
|     }
 | |
| 
 | |
|     root === hashers[levels - 1].hash;
 | |
| } | 
