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