miksi-core/circuits/deposit.circom
circuits/deposit.circomRaw
1/*
2
3# deposit.circom
4
5 +----------+ +----------+
6PUB_nullifier+------>+ | | |
7 | | | SMT |
8PUB_coinCode+------->+ | | Poseidon +<------+PUB_rootOld
9 | Poseidon +-+----------->+ Verifier |
10PUB_amount+--------->+ | | | Non |
11 | | | | Existance+<------+PRI_siblings
12PRI_secret+--------->+ | | | | +
13 +----------+ | +----------+ |
14 | |
15 | |
16 | +----------+ |
17 | | | |
18 | | | |
19 +----+ | | SMT +<---------+
20PUB_commitment+----> == +<--------+----------->+ Poseidon |
21 +----+ | Verifier |
22 | +<------+PUB_rootNew
23 | |
24 +----------+
25
26
27*/
28
29include "../node_modules/circomlib/circuits/comparators.circom";
30include "../node_modules/circomlib/circuits/poseidon.circom";
31include "../node_modules/circomlib/circuits/smt/smtverifier.circom";
32
33template Deposit(nLevels) {
34 signal input coinCode;
35 signal input amount;
36 signal private input secret;
37 signal private input nullifier;
38 signal private input oldKey;
39 signal private input oldValue;
40 signal private input siblingsOld[nLevels];
41 signal private input siblingsNew[nLevels];
42 signal input rootOld;
43 signal input rootNew;
44 signal input commitment;
45 signal input key;
46
47 component hash = Poseidon(4, 6, 8, 57);
48 hash.inputs[0] <== coinCode;
49 hash.inputs[1] <== amount;
50 hash.inputs[2] <== secret;
51 hash.inputs[3] <== nullifier; // nullifier
52
53 component comCheck = IsEqual();
54 comCheck.in[0] <== hash.out;
55 comCheck.in[1] <== commitment;
56 comCheck.out === 1;
57
58 // TODO instead of 2 siblings input, get siblingsOld from
59 // siblingsNew[len-1] both siblingsOld & siblingsNew have same values
60 // except for one, can be merged into one, to ensure that the circuit
61 // checks that the leaf non existing under rootOld is in the same
62 // position than the check that the leaf exists under the rootNew
63
64 // check that nLevels-1 siblings match from siblingsOld & siblingsNew
65 component siblEq[nLevels];
66 signal count[nLevels];
67 for (var i=0; i<nLevels; i++) {
68 siblEq[i] = IsEqual();
69 siblEq[i].in[0] <== siblingsOld[i];
70 siblEq[i].in[1] <== siblingsNew[i];
71 if (i==0) {
72 count[0] <== siblEq[i].out;
73 } else {
74 count[i] <== siblEq[i].out + count[i-1];
75 }
76 }
77 component countCheck = IsEqual();
78 countCheck.in[0] <== count[nLevels-1];
79 countCheck.in[1] <== nLevels-1;
80 countCheck.out === 1;
81
82 component smtOld = SMTVerifier(nLevels);
83 smtOld.enabled <== 1;
84 smtOld.fnc <== 1;
85 smtOld.root <== rootOld;
86 for (var i=0; i<nLevels; i++) {
87 smtOld.siblings[i] <== siblingsOld[i];
88 }
89 /* smtOld.oldKey <== 1; */
90 smtOld.oldKey <== oldKey;
91 smtOld.oldValue <== oldValue;
92 smtOld.isOld0 <== 0;
93 smtOld.key <== key;
94 smtOld.value <== hash.out;
95
96 component smtNew = SMTVerifier(nLevels);
97 smtNew.enabled <== 1;
98 smtNew.fnc <== 0;
99 smtNew.root <== rootNew;
100 for (var i=0; i<nLevels; i++) {
101 smtNew.siblings[i] <== siblingsNew[i];
102 }
103 smtNew.oldKey <== 0;
104 smtNew.oldValue <== 0;
105 smtNew.isOld0 <== 0;
106 smtNew.key <== key;
107 smtNew.value <== hash.out;
108}
109
110component main = Deposit(17); // 16 real levels (due circom leaf protection)