44#include " ../Utils/Constants.h"
55#include " ../Utils/Data.h"
66
7- #include " ../ThirdParty/BigInt .hpp"
7+ #include " ../ThirdParty/BigIntHeader .hpp"
88#include " ethsnarks.hpp"
99#include " utils.hpp"
1010#include " gadgets/sha256_many.hpp"
@@ -17,181 +17,169 @@ namespace Loopring
1717class DepositGadget : public GadgetT
1818{
1919public:
20- const Constants& constants;
2120
22- VariableArrayT accountID;
23- VariableArrayT tokenID;
21+ // User state
22+ BalanceGadget balanceBefore;
23+ AccountGadget accountBefore;
2424
25- libsnark::dual_variable_gadget<FieldT> amount;
26- libsnark::dual_variable_gadget<FieldT> publicKeyX;
27- libsnark::dual_variable_gadget<FieldT> publicKeyY;
25+ // Inputs
26+ DualVariableGadget accountID;
27+ DualVariableGadget tokenID;
28+ DualVariableGadget amount;
29+ DualVariableGadget publicKeyX;
30+ DualVariableGadget publicKeyY;
2831
29- BalanceState balanceBefore;
30- AccountState accountBefore ;
31- VariableT uncappedBalanceAfter ;
32- MinGadget cappedBalanceAfter;
33- BalanceState balanceAfter;
32+ // Calculate the new balance
33+ UnsafeAddGadget uncappedBalanceAfter ;
34+ MinGadget balanceAfter ;
35+
36+ // Update User
3437 UpdateBalanceGadget updateBalance;
35- AccountState accountAfter;
3638 UpdateAccountGadget updateAccount;
3739
3840 DepositGadget (
3941 ProtoboardT& pb,
40- const Constants& _constants ,
42+ const Constants& constants ,
4143 const VariableT& root,
4244 const std::string& prefix
4345 ) :
4446 GadgetT (pb, prefix),
4547
46- constants (_constants),
47-
48- accountID (make_var_array(pb, NUM_BITS_ACCOUNT, FMT(prefix, " .accountID" ))),
49- tokenID (make_var_array(pb, NUM_BITS_TOKEN, FMT(prefix, " .tokenID" ))),
48+ // User state
49+ balanceBefore (pb, FMT(prefix, " .balanceBefore" )),
50+ accountBefore (pb, FMT(prefix, " .accountBefore" )),
5051
52+ // Inputs
53+ accountID (pb, NUM_BITS_ACCOUNT, FMT(prefix, " .accountID" )),
54+ tokenID (pb, NUM_BITS_TOKEN, FMT(prefix, " .tokenID" )),
5155 amount (pb, NUM_BITS_AMOUNT, FMT(prefix, " .amount" )),
5256 publicKeyX (pb, 256 , FMT(prefix, " .publicKeyX" )),
5357 publicKeyY (pb, 256 , FMT(prefix, " .publicKeyY" )),
5458
55- // Balance
56- balanceBefore ({
57- make_variable (pb, FMT (prefix, " .before.balance" )),
58- make_variable (pb, FMT (prefix, " .tradingHistoryRoot" ))
59- }),
60- uncappedBalanceAfter (make_variable(pb, FMT(prefix, " .uncappedBalanceAfter" ))),
61- cappedBalanceAfter (pb, uncappedBalanceAfter, constants.maxAmount, NUM_BITS_AMOUNT + 1 , FMT(prefix, " .cappedBalanceAfter" )),
62- balanceAfter ({
63- cappedBalanceAfter.result (),
64- balanceBefore.tradingHistory
65- }),
66- // Account
67- accountBefore ({
68- make_variable (pb, FMT (prefix, " .publicKeyX_before" )),
69- make_variable (pb, FMT (prefix, " .publicKeyY_before" )),
70- make_variable (pb, FMT (prefix, " .nonce" )),
71- make_variable (pb, FMT (prefix, " .balancesRoot_before" ))
72- }),
73- // Update balance
74- updateBalance (pb, accountBefore.balancesRoot, tokenID, balanceBefore, balanceAfter, FMT(prefix, " .updateBalance" )),
75- accountAfter ({
76- publicKeyX.packed ,
77- publicKeyY.packed ,
78- accountBefore.nonce ,
79- updateBalance.getNewRoot ()
80- }),
81- // Update account
82- updateAccount (pb, root, accountID, accountBefore, accountAfter, FMT(prefix, " .updateAccount" ))
59+ // Calculate the new balance
60+ uncappedBalanceAfter (pb, balanceBefore.balance, amount.packed, FMT(prefix, " .uncappedBalanceAfter" )),
61+ balanceAfter (pb, uncappedBalanceAfter.result(), constants.maxAmount, NUM_BITS_AMOUNT + 1 , FMT(prefix, " .balanceAfter" )),
62+
63+ // Update User
64+ updateBalance (pb, accountBefore.balancesRoot, tokenID.bits,
65+ {balanceBefore.balance , balanceBefore.tradingHistory },
66+ {balanceAfter.result (), balanceBefore.tradingHistory },
67+ FMT (prefix, " .updateBalance" )),
68+ updateAccount(pb, root, accountID.bits,
69+ {accountBefore.publicKey .x , accountBefore.publicKey .y , accountBefore.nonce , accountBefore.balancesRoot },
70+ {publicKeyX.packed , publicKeyY.packed , accountBefore.nonce , updateBalance.result ()},
71+ FMT (prefix, " .updateAccount" ))
8372 {
8473
8574 }
8675
87- const VariableT getNewAccountsRoot () const
88- {
89- return updateAccount.result ();
90- }
91-
92- const std::vector<VariableArrayT> getOnchainData () const
93- {
94- return {constants.accountPadding , accountID,
95- publicKeyX.bits , publicKeyY.bits ,
96- tokenID,
97- amount.bits };
98- }
99-
10076 void generate_r1cs_witness (const Deposit& deposit)
10177 {
102- accountID.fill_with_bits_of_field_element (pb, deposit.accountUpdate .accountID );
103- tokenID.fill_with_bits_of_field_element (pb, deposit.balanceUpdate .tokenID );
104-
105- amount.bits .fill_with_bits_of_field_element (pb, deposit.amount );
106- amount.generate_r1cs_witness_from_bits ();
107- publicKeyX.bits .fill_with_bits_of_field_element (pb, deposit.accountUpdate .after .publicKey .x );
108- publicKeyX.generate_r1cs_witness_from_bits ();
109- publicKeyY.bits .fill_with_bits_of_field_element (pb, deposit.accountUpdate .after .publicKey .y );
110- publicKeyY.generate_r1cs_witness_from_bits ();
111-
112- pb.val (balanceBefore.balance ) = deposit.balanceUpdate .before .balance ;
113- pb.val (balanceBefore.tradingHistory ) = deposit.balanceUpdate .before .tradingHistoryRoot ;
114-
115- pb.val (uncappedBalanceAfter) = deposit.balanceUpdate .before .balance + deposit.amount ;
116- cappedBalanceAfter.generate_r1cs_witness ();
117-
118- pb.val (accountBefore.publicKeyX ) = deposit.accountUpdate .before .publicKey .x ;
119- pb.val (accountBefore.publicKeyY ) = deposit.accountUpdate .before .publicKey .y ;
120- pb.val (accountBefore.nonce ) = deposit.accountUpdate .before .nonce ;
121- pb.val (accountBefore.balancesRoot ) = deposit.accountUpdate .before .balancesRoot ;
122-
78+ // User state
79+ balanceBefore.generate_r1cs_witness (deposit.balanceUpdate .before );
80+ accountBefore.generate_r1cs_witness (deposit.accountUpdate .before );
81+
82+ // Inputs
83+ accountID.generate_r1cs_witness (pb, deposit.accountUpdate .accountID );
84+ tokenID.generate_r1cs_witness (pb, deposit.balanceUpdate .tokenID );
85+ amount.generate_r1cs_witness (pb, deposit.amount );
86+ publicKeyX.generate_r1cs_witness (pb, deposit.accountUpdate .after .publicKey .x );
87+ publicKeyY.generate_r1cs_witness (pb, deposit.accountUpdate .after .publicKey .y );
88+
89+ // Calculate the new balance
90+ uncappedBalanceAfter.generate_r1cs_witness ();
91+ balanceAfter.generate_r1cs_witness ();
92+
93+ // Update User
12394 updateBalance.generate_r1cs_witness (deposit.balanceUpdate .proof );
12495 updateAccount.generate_r1cs_witness (deposit.accountUpdate .proof );
12596 }
12697
12798 void generate_r1cs_constraints ()
12899 {
100+ // Inputs
101+ accountID.generate_r1cs_constraints (true );
102+ tokenID.generate_r1cs_constraints (true );
129103 amount.generate_r1cs_constraints (true );
130104 publicKeyX.generate_r1cs_constraints (true );
131105 publicKeyY.generate_r1cs_constraints (true );
132106
133- pb.add_r1cs_constraint (ConstraintT (balanceBefore.balance + amount.packed , 1 , uncappedBalanceAfter), " balanceBefore + amount == uncappedBalanceAfter" );
134- cappedBalanceAfter.generate_r1cs_constraints ();
107+ // Calculate the new balance
108+ uncappedBalanceAfter.generate_r1cs_constraints ();
109+ balanceAfter.generate_r1cs_constraints ();
135110
111+ // Update User
136112 updateBalance.generate_r1cs_constraints ();
137113 updateAccount.generate_r1cs_constraints ();
138114 }
115+
116+ const std::vector<VariableArrayT> getOnchainData (const Constants& constants) const
117+ {
118+ return {constants.padding_0000 , accountID.bits ,
119+ publicKeyX.bits , publicKeyY.bits ,
120+ tokenID.bits ,
121+ amount.bits };
122+ }
123+
124+ const VariableT getNewAccountsRoot () const
125+ {
126+ return updateAccount.result ();
127+ }
139128};
140129
141130class DepositCircuit : public GadgetT
142131{
143132public:
144133
145- unsigned int numAccounts;
146- std::vector<DepositGadget> deposits;
147-
148134 PublicDataGadget publicData;
149-
150135 Constants constants;
151136
152- libsnark::dual_variable_gadget<FieldT> exchangeID;
153- libsnark::dual_variable_gadget<FieldT> merkleRootBefore ;
154- libsnark::dual_variable_gadget<FieldT> merkleRootAfter ;
155-
156- VariableArrayT depositBlockHashStart;
157- libsnark::dual_variable_gadget<FieldT> startIndex;
158- libsnark::dual_variable_gadget<FieldT> count;
137+ // Inputs
138+ DualVariableGadget exchangeID ;
139+ DualVariableGadget merkleRootBefore ;
140+ DualVariableGadget merkleRootAfter;
141+ DualVariableGadget depositBlockHashStart;
142+ DualVariableGadget startIndex;
143+ DualVariableGadget count;
159144
145+ // Deposits
146+ unsigned int numDeposits;
147+ std::vector<DepositGadget> deposits;
160148 std::vector<sha256_many> hashers;
161149
162150 DepositCircuit (ProtoboardT& pb, const std::string& prefix) :
163151 GadgetT (pb, prefix),
164152
165153 publicData (pb, FMT(prefix, " .publicData" )),
166-
167154 constants (pb, FMT(prefix, " .constants" )),
168155
169- exchangeID (pb, 32 , FMT(prefix, " .exchangeID" )),
156+ // Inputs
157+ exchangeID (pb, NUM_BITS_EXCHANGE_ID, FMT(prefix, " .exchangeID" )),
170158 merkleRootBefore (pb, 256 , FMT(prefix, " .merkleRootBefore" )),
171159 merkleRootAfter (pb, 256 , FMT(prefix, " .merkleRootAfter" )),
172-
173- depositBlockHashStart (make_var_array(pb, 256 , FMT(prefix, " .depositBlockHashStart" ))),
160+ depositBlockHashStart (pb, 256 , FMT(prefix, " .depositBlockHashStart" )),
174161 startIndex (pb, 32 , FMT(prefix, " .startIndex" )),
175162 count (pb, 32 , FMT(prefix, " .count" ))
176163 {
177164
178165 }
179166
180- void generate_r1cs_constraints (int numAccounts )
167+ void generate_r1cs_constraints (int numDeposits )
181168 {
182- this ->numAccounts = numAccounts ;
169+ this ->numDeposits = numDeposits ;
183170
184171 constants.generate_r1cs_constraints ();
185172
173+ // Inputs
186174 exchangeID.generate_r1cs_constraints (true );
187175 merkleRootBefore.generate_r1cs_constraints (true );
188176 merkleRootAfter.generate_r1cs_constraints (true );
177+ depositBlockHashStart.generate_r1cs_constraints (true );
178+ startIndex.generate_r1cs_constraints (true );
179+ count.generate_r1cs_constraints (true );
189180
190- publicData.add (exchangeID.bits );
191- publicData.add (merkleRootBefore.bits );
192- publicData.add (merkleRootAfter.bits );
193- publicData.add (reverse (depositBlockHashStart));
194- for (size_t j = 0 ; j < numAccounts; j++)
181+ // Deposits
182+ for (size_t j = 0 ; j < numDeposits; j++)
195183 {
196184 VariableT depositAccountsRoot = (j == 0 ) ? merkleRootBefore.packed : deposits.back ().getNewAccountsRoot ();
197185 deposits.emplace_back (
@@ -202,73 +190,61 @@ class DepositCircuit : public GadgetT
202190 );
203191 deposits.back ().generate_r1cs_constraints ();
204192
205- VariableArrayT depositBlockHash = (j == 0 ) ? depositBlockHashStart : hashers.back ().result ().bits ;
206-
207193 // Hash data from deposit
208- std::vector<VariableArrayT> depositData = deposits.back ().getOnchainData ();
194+ std::vector<VariableArrayT> depositData = deposits.back ().getOnchainData (constants );
209195 std::vector<VariableArrayT> hashBits;
210- hashBits.push_back (reverse (depositBlockHash ));
196+ hashBits.push_back (reverse ((j == 0 ) ? depositBlockHashStart. bits : hashers. back (). result (). bits ));
211197 hashBits.insert (hashBits.end (), depositData.begin (), depositData.end ());
212198 hashers.emplace_back (pb, flattenReverse (hashBits), std::string (" hash_" ) + std::to_string (j));
213199 hashers.back ().generate_r1cs_constraints ();
214200 }
215201
216- // Add the block hash
202+ // Public data
203+ publicData.add (exchangeID.bits );
204+ publicData.add (merkleRootBefore.bits );
205+ publicData.add (merkleRootAfter.bits );
206+ publicData.add (reverse (depositBlockHashStart.bits ));
217207 publicData.add (reverse (hashers.back ().result ().bits ));
218208 publicData.add (startIndex.bits );
219209 publicData.add (count.bits );
220-
221- // Check the input hash
222210 publicData.generate_r1cs_constraints ();
223211
224212 // Check the new merkle root
225213 forceEqual (pb, deposits.back ().getNewAccountsRoot (), merkleRootAfter.packed , " newMerkleRoot" );
226214 }
227215
228- void printInfo ()
229- {
230- std::cout << pb.num_constraints () << " constraints (" << (pb.num_constraints () / numAccounts) << " /deposit)" << std::endl;
231- }
232-
233216 bool generateWitness (const DepositBlock& block)
234217 {
235218 constants.generate_r1cs_witness ();
236219
237- exchangeID.bits .fill_with_bits_of_field_element (pb, block.exchangeID );
238- exchangeID.generate_r1cs_witness_from_bits ();
239-
240- merkleRootBefore.bits .fill_with_bits_of_field_element (pb, block.merkleRootBefore );
241- merkleRootBefore.generate_r1cs_witness_from_bits ();
242- merkleRootAfter.bits .fill_with_bits_of_field_element (pb, block.merkleRootAfter );
243- merkleRootAfter.generate_r1cs_witness_from_bits ();
244-
245- // Store the starting hash
246- for (unsigned int i = 0 ; i < 256 ; i++)
247- {
248- pb.val (depositBlockHashStart[255 - i]) = block.startHash .test_bit (i);
249- }
220+ // Inputs
221+ exchangeID.generate_r1cs_witness (pb, block.exchangeID );
222+ merkleRootBefore.generate_r1cs_witness (pb, block.merkleRootBefore );
223+ merkleRootAfter.generate_r1cs_witness (pb, block.merkleRootAfter );
224+ depositBlockHashStart.generate_r1cs_witness (pb, block.startHash );
225+ startIndex.generate_r1cs_witness (pb, block.startIndex );
226+ count.generate_r1cs_witness (pb, block.count );
250227 // printBits("start hash input: 0x", depositBlockHashStart.get_bits(pb), true);
251228
252- startIndex.bits .fill_with_bits_of_field_element (pb, block.startIndex );
253- startIndex.generate_r1cs_witness_from_bits ();
254- count.bits .fill_with_bits_of_field_element (pb, block.count );
255- count.generate_r1cs_witness_from_bits ();
256-
229+ // Deposits
230+ assert (deposits.size () == hashers.size ());
257231 for (unsigned int i = 0 ; i < block.deposits .size (); i++)
258232 {
259233 deposits[i].generate_r1cs_witness (block.deposits [i]);
234+ hashers[i].generate_r1cs_witness ();
260235 }
236+ // printBits("DepositBlockHash: 0x", hashers.back().result().bits.get_bits(pb));
261237
262- for (auto & hasher : hashers)
263- {
264- hasher.generate_r1cs_witness ();
265- }
266- printBits (" DepositBlockHash: 0x" , hashers.back ().result ().bits .get_bits (pb));
267-
238+ // Public data
268239 publicData.generate_r1cs_witness ();
269240
270241 return true ;
271242 }
243+
244+ void printInfo ()
245+ {
246+ std::cout << pb.num_constraints () << " constraints (" << (pb.num_constraints () / numDeposits) << " /deposit)" << std::endl;
247+ }
272248};
273249
274250}
0 commit comments