@@ -18,6 +18,91 @@ using namespace ethsnarks;
1818namespace Loopring
1919{
2020
21+ class TransformRingSettlementDataGadget : public GadgetT
22+ {
23+ public:
24+
25+ const unsigned int ringSize = 25 * 8 ;
26+
27+ VariableArrayT data;
28+ Bitstream transformedData;
29+ unsigned int numRings;
30+
31+ std::vector<XorArrayGadget> xorGadgets;
32+
33+ TransformRingSettlementDataGadget (
34+ ProtoboardT& pb,
35+ const std::string& prefix
36+ ) :
37+ GadgetT (pb, prefix)
38+ {
39+ numRings = 0 ;
40+ }
41+
42+ VariableArrayT result ()
43+ {
44+ return flatten (transformedData.data );
45+ }
46+
47+ void generate_r1cs_witness ()
48+ {
49+ for (unsigned int i = 0 ; i < xorGadgets.size (); i++)
50+ {
51+ xorGadgets[i].generate_r1cs_witness ();
52+ }
53+ }
54+
55+ void generate_r1cs_constraints (unsigned int numRings, const VariableArrayT& data)
56+ {
57+ this ->numRings = numRings;
58+ this ->data = data;
59+ assert (numRings > 0 );
60+ assert (numRings * ringSize == data.size ());
61+
62+ // XOR compress
63+ Bitstream compressedData;
64+ compressedData.add (subArray (data, 0 , ringSize));
65+ for (unsigned int i = 1 ; i < numRings; i++)
66+ {
67+ unsigned int previousRingStart = (i - 1 ) * ringSize;
68+ unsigned int ringStart = i * ringSize;
69+
70+ xorGadgets.emplace_back (pb, subArray (data, previousRingStart, 5 * 8 ),
71+ subArray (data, ringStart, 5 * 8 ),
72+ std::string (" xor_" ) + std::to_string (i));
73+ xorGadgets.back ().generate_r1cs_constraints ();
74+ compressedData.add (xorGadgets.back ().result ());
75+ compressedData.add (subArray (data, ringStart + 5 * 8 , ringSize - 5 * 8 ));
76+ }
77+
78+ // Transform
79+ struct Range
80+ {
81+ unsigned int offset;
82+ unsigned int length;
83+ };
84+ std::vector<std::vector<Range>> ranges;
85+ ranges.push_back ({{0 , 40 }}); // ringMatcherID + fFee + tokenID
86+ ranges.push_back ({{40 , 40 }}); // orderA.orderID + orderB.orderID
87+ ranges.push_back ({{80 , 40 }}); // orderA.accountID + orderB.accountID
88+ ranges.push_back ({{120 , 8 }, {160 , 8 }}); // orderA.tokenS + orderB.tokenS
89+ ranges.push_back ({{128 , 24 },{168 , 24 }}); // orderA.fillS + orderB.fillS
90+ ranges.push_back ({{152 , 8 }}); // orderA.data
91+ ranges.push_back ({{192 , 8 }}); // orderB.data
92+ for (const std::vector<Range>& subRanges : ranges)
93+ {
94+ for (unsigned int i = 0 ; i < numRings; i++)
95+ {
96+ for (const Range& subRange : subRanges)
97+ {
98+ unsigned int ringStart = i * ringSize;
99+ transformedData.add (subArray (flatten (compressedData.data ), ringStart + subRange.offset , subRange.length ));
100+ }
101+ }
102+ }
103+ }
104+ };
105+
21106class RingSettlementGadget : public GadgetT
22107{
23108public:
@@ -49,6 +134,9 @@ class RingSettlementGadget : public GadgetT
49134 OrderGadget orderA;
50135 OrderGadget orderB;
51136
137+ ForceNotEqualGadget accountA_neq_ringMatcher;
138+ ForceNotEqualGadget accountB_neq_ringMatcher;
139+
52140 OrderMatchingGadget orderMatching;
53141
54142 TernaryGadget uFillS_A;
@@ -147,6 +235,9 @@ class RingSettlementGadget : public GadgetT
147235 orderA (pb, params, constants, _exchangeID, FMT(prefix, " .orderA" )),
148236 orderB (pb, params, constants, _exchangeID, FMT(prefix, " .orderB" )),
149237
238+ accountA_neq_ringMatcher (pb, orderA.accountID.packed, minerAccountID.packed, FMT(prefix, " .accountA_neq_ringMatcher" )),
239+ accountB_neq_ringMatcher (pb, orderB.accountID.packed, minerAccountID.packed, FMT(prefix, " .accountB_neq_ringMatcher" )),
240+
150241 // Match orders
151242 orderMatching (pb, constants, _timestamp, orderA, orderB, FMT(prefix, " .orderMatching" )),
152243
@@ -350,11 +441,16 @@ class RingSettlementGadget : public GadgetT
350441 orderA.generate_r1cs_witness (ringSettlement.ring .orderA ,
351442 ringSettlement.accountUpdate_A .before ,
352443 ringSettlement.balanceUpdateS_A .before ,
353- ringSettlement.balanceUpdateB_A .before );
444+ ringSettlement.balanceUpdateB_A .before ,
445+ ringSettlement.tradeHistoryUpdate_A .before );
354446 orderB.generate_r1cs_witness (ringSettlement.ring .orderB ,
355447 ringSettlement.accountUpdate_B .before ,
356448 ringSettlement.balanceUpdateS_B .before ,
357- ringSettlement.balanceUpdateB_B .before );
449+ ringSettlement.balanceUpdateB_B .before ,
450+ ringSettlement.tradeHistoryUpdate_B .before );
451+
452+ accountA_neq_ringMatcher.generate_r1cs_witness ();
453+ accountB_neq_ringMatcher.generate_r1cs_witness ();
358454
359455 // Match orders
360456 orderMatching.generate_r1cs_witness ();
@@ -457,6 +553,9 @@ class RingSettlementGadget : public GadgetT
457553 orderA.generate_r1cs_constraints ();
458554 orderB.generate_r1cs_constraints ();
459555
556+ accountA_neq_ringMatcher.generate_r1cs_constraints ();
557+ accountB_neq_ringMatcher.generate_r1cs_constraints ();
558+
460559 // Match orders
461560 orderMatching.generate_r1cs_constraints ();
462561
@@ -529,6 +628,8 @@ class RingSettlementCircuit : public GadgetT
529628 std::vector<RingSettlementGadget*> ringSettlements;
530629
531630 libsnark::dual_variable_gadget<FieldT> publicDataHash;
631+ Bitstream dataAvailabityData;
632+ TransformRingSettlementDataGadget transformData;
532633 PublicDataGadget publicData;
533634
534635 Constants constants;
@@ -555,6 +656,7 @@ class RingSettlementCircuit : public GadgetT
555656 GadgetT (pb, prefix),
556657
557658 publicDataHash (pb, 256 , FMT(prefix, " .publicDataHash" )),
659+ transformData (pb, FMT(prefix, " .transformData" )),
558660 publicData (pb, publicDataHash, FMT(prefix, " .publicData" )),
559661
560662 constants (pb, FMT(prefix, " .constants" )),
@@ -644,7 +746,7 @@ class RingSettlementCircuit : public GadgetT
644746 if (onchainDataAvailability)
645747 {
646748 // Store data from ring settlement
647- publicData .add (ringSettlements.back ()->getPublicData ());
749+ dataAvailabityData .add (ringSettlements.back ()->getPublicData ());
648750 }
649751 }
650752
@@ -662,6 +764,13 @@ class RingSettlementCircuit : public GadgetT
662764 FMT (annotation_prefix, " .updateAccount_O" ));
663765 updateAccount_O->generate_r1cs_constraints ();
664766
767+ if (onchainDataAvailability)
768+ {
769+ // Transform the data
770+ transformData.generate_r1cs_constraints (numRings, flattenReverse (dataAvailabityData.data ));
771+ publicData.add (flattenReverse ({transformData.result ()}));
772+ }
773+
665774 // Check the input hash
666775 publicDataHash.generate_r1cs_constraints (true );
667776 publicData.generate_r1cs_constraints ();
@@ -715,6 +824,10 @@ class RingSettlementCircuit : public GadgetT
715824 updateAccount_P->generate_r1cs_witness (block.accountUpdate_P .proof );
716825 updateAccount_O->generate_r1cs_witness (block.accountUpdate_O .proof );
717826
827+ if (onchainDataAvailability)
828+ {
829+ transformData.generate_r1cs_witness ();
830+ }
718831 publicData.generate_r1cs_witness ();
719832
720833 return true ;
0 commit comments