From c8b3eccd4ac95fc52c0c212d1f0de3ac69d7dda0 Mon Sep 17 00:00:00 2001 From: Brechtpd Date: Wed, 19 Jun 2019 19:38:20 +0200 Subject: [PATCH 1/7] Added transformation of ring data to make the it easier to compress --- Circuits/RingSettlementCircuit.h | 112 ++++++++++++++++++++++++++++++- Gadgets/MathGadgets.h | 103 ++++++++++++++++++++++++++++ Gadgets/OrderGadgets.h | 9 +-- Utils/Data.h | 8 --- 4 files changed, 217 insertions(+), 15 deletions(-) diff --git a/Circuits/RingSettlementCircuit.h b/Circuits/RingSettlementCircuit.h index 2781de6..f185922 100644 --- a/Circuits/RingSettlementCircuit.h +++ b/Circuits/RingSettlementCircuit.h @@ -18,6 +18,90 @@ using namespace ethsnarks; namespace Loopring { +class TransformRingSettlementDataGadget : public GadgetT +{ +public: + + const unsigned int ringSize = 25 * 8; + + VariableArrayT data; + Bitstream transformedData; + unsigned int numRings; + + std::vector xorGadgets; + + TransformRingSettlementDataGadget( + ProtoboardT& pb, + const std::string& prefix + ) : + GadgetT(pb, prefix) + { + numRings = 0; + } + + VariableArrayT result() + { + return flatten(transformedData.data); + } + + void generate_r1cs_witness() + { + for (unsigned int i = 0; i < xorGadgets.size(); i++) + { + xorGadgets[i].generate_r1cs_witness(); + } + } + + void generate_r1cs_constraints(unsigned int numRings, const VariableArrayT& data) + { + this->numRings = numRings; + this->data = data; + assert(numRings > 0); + assert(numRings * ringSize == data.size); + + // XOR compress + Bitstream compressedData; + compressedData.add(subArray(data, 0, ringSize)); + for (unsigned int i = 1; i < numRings; i++) + { + unsigned int previousRingStart = (i - 1) * ringSize; + unsigned int ringStart = i * ringSize; + + xorGadgets.emplace_back(pb, subArray(data, previousRingStart, 5 * 8), + subArray(data, ringStart, 5 * 8), + std::string("xor_") + std::to_string(i)); + xorGadgets.back().generate_r1cs_constraints(); + compressedData.add(xorGadgets.back().result()); + compressedData.add(subArray(data, ringStart + 5 * 8, ringSize - 5 * 8)); + } + + // Transform + struct Range + { + unsigned int offset; + unsigned int length; + }; + std::vector ranges; + ranges.push_back({0, 40}); // ringMatcherID + fFee + tokenID + ranges.push_back({40, 40}); // orderA.orderID + orderB.orderID + ranges.push_back({80, 40}); // orderA.accountID + orderB.accountID + ranges.push_back({120, 8}); // orderA.tokenS + ranges.push_back({128, 24}); // orderA.fillS + ranges.push_back({152, 8}); // orderA.data + ranges.push_back({160, 8}); // orderB.tokenS + ranges.push_back({168, 24}); // orderB.fillS + ranges.push_back({192, 8}); // orderB.data + for (const Range& range : ranges) + { + for (unsigned int i = 0; i < numRings; i++) + { + unsigned int ringStart = i * ringSize; + transformedData.add(subArray(flatten(compressedData.data), ringStart + range.offset, range.length)); + } + } + } +}; + class RingSettlementGadget : public GadgetT { public: @@ -49,6 +133,9 @@ class RingSettlementGadget : public GadgetT OrderGadget orderA; OrderGadget orderB; + ForceNotEqualGadget accountA_neq_ringMatcher; + ForceNotEqualGadget accountB_neq_ringMatcher; + OrderMatchingGadget orderMatching; TernaryGadget uFillS_A; @@ -147,6 +234,9 @@ class RingSettlementGadget : public GadgetT orderA(pb, params, constants, _exchangeID, FMT(prefix, ".orderA")), orderB(pb, params, constants, _exchangeID, FMT(prefix, ".orderB")), + accountA_neq_ringMatcher(pb, orderA.accountID.packed, minerAccountID.packed, FMT(prefix, ".accountA_neq_ringMatcher")), + accountB_neq_ringMatcher(pb, orderB.accountID.packed, minerAccountID.packed, FMT(prefix, ".accountB_neq_ringMatcher")), + // Match orders orderMatching(pb, constants, _timestamp, orderA, orderB, FMT(prefix, ".orderMatching")), @@ -350,11 +440,16 @@ class RingSettlementGadget : public GadgetT orderA.generate_r1cs_witness(ringSettlement.ring.orderA, ringSettlement.accountUpdate_A.before, ringSettlement.balanceUpdateS_A.before, - ringSettlement.balanceUpdateB_A.before); + ringSettlement.balanceUpdateB_A.before, + ringSettlement.tradeHistoryUpdate_A.before); orderB.generate_r1cs_witness(ringSettlement.ring.orderB, ringSettlement.accountUpdate_B.before, ringSettlement.balanceUpdateS_B.before, - ringSettlement.balanceUpdateB_B.before); + ringSettlement.balanceUpdateB_B.before, + ringSettlement.tradeHistoryUpdate_B.before); + + accountA_neq_ringMatcher.generate_r1cs_witness(); + accountB_neq_ringMatcher.generate_r1cs_witness(); // Match orders orderMatching.generate_r1cs_witness(); @@ -457,6 +552,9 @@ class RingSettlementGadget : public GadgetT orderA.generate_r1cs_constraints(); orderB.generate_r1cs_constraints(); + accountA_neq_ringMatcher.generate_r1cs_constraints(); + accountB_neq_ringMatcher.generate_r1cs_constraints(); + // Match orders orderMatching.generate_r1cs_constraints(); @@ -529,6 +627,8 @@ class RingSettlementCircuit : public GadgetT std::vector ringSettlements; libsnark::dual_variable_gadget publicDataHash; + Bitstream dataAvailabityData; + TransformRingSettlementDataGadget transformData; PublicDataGadget publicData; Constants constants; @@ -555,6 +655,7 @@ class RingSettlementCircuit : public GadgetT GadgetT(pb, prefix), publicDataHash(pb, 256, FMT(prefix, ".publicDataHash")), + transformData(pb, FMT(prefix, ".transformData")), publicData(pb, publicDataHash, FMT(prefix, ".publicData")), constants(pb, FMT(prefix, ".constants")), @@ -644,7 +745,7 @@ class RingSettlementCircuit : public GadgetT if (onchainDataAvailability) { // Store data from ring settlement - publicData.add(ringSettlements.back()->getPublicData()); + dataAvailabityData.add(ringSettlements.back()->getPublicData()); } } @@ -662,7 +763,11 @@ class RingSettlementCircuit : public GadgetT FMT(annotation_prefix, ".updateAccount_O")); updateAccount_O->generate_r1cs_constraints(); + // Transform the data + transformData.generate_r1cs_constraints(numRings, flattenReverse(dataAvailabityData.data)); + // Check the input hash + publicData.add(flattenReverse({transformData.result()})); publicDataHash.generate_r1cs_constraints(true); publicData.generate_r1cs_constraints(); @@ -715,6 +820,7 @@ class RingSettlementCircuit : public GadgetT updateAccount_P->generate_r1cs_witness(block.accountUpdate_P.proof); updateAccount_O->generate_r1cs_witness(block.accountUpdate_O.proof); + transformData.generate_r1cs_witness(); publicData.generate_r1cs_witness(); return true; diff --git a/Gadgets/MathGadgets.h b/Gadgets/MathGadgets.h index c50b28a..e3e5d8f 100644 --- a/Gadgets/MathGadgets.h +++ b/Gadgets/MathGadgets.h @@ -497,6 +497,92 @@ class NotGadget : public GadgetT } }; +class XorGadget : public GadgetT +{ +public: + VariableT A; + VariableT B; + VariableT C; + + XorGadget( + ProtoboardT& pb, + const VariableT& _A, + const VariableT& _B, + const std::string& prefix + ) : + GadgetT(pb, prefix), + + A(_A), + B(_B), + + C(make_variable(pb, FMT(prefix, ".C"))) + { + + } + + const VariableT& result() const + { + return C; + } + + void generate_r1cs_witness() + { + pb.val(C) = pb.val(A) + pb.val(B) - ((pb.val(A) == FieldT::one() && pb.val(B) == FieldT::one()) ? 2 : 0); + } + + void generate_r1cs_constraints() + { + pb.add_r1cs_constraint(ConstraintT(2 * A, B, A + B - C), FMT(annotation_prefix, ".A ^ B == C")); + } +}; + +class XorArrayGadget : public GadgetT +{ +public: + VariableArrayT A; + VariableArrayT B; + VariableArrayT C; + + XorArrayGadget( + ProtoboardT& pb, + VariableArrayT _A, + VariableArrayT _B, + const std::string& prefix + ) : + GadgetT(pb, prefix), + + A(_A), + B(_B), + + C(make_var_array(pb, A.size(), FMT(prefix, ".C"))) + { + assert(A.size() == B.size()); + } + + const VariableArrayT& result() const + { + return C; + } + + void generate_r1cs_witness() + { + for (unsigned int i = 0; i < C.size(); i++) + { + pb.val(C[i]) = pb.val(A[i]) + pb.val(B[i]) - ((pb.val(A[i]) == FieldT::one() && pb.val(B[i]) == FieldT::one()) ? 2 : 0); + } + // printBits("A: ", A.get_bits(pb)); + // printBits("B: ", B.get_bits(pb)); + // printBits("C: ", C.get_bits(pb)); + } + + void generate_r1cs_constraints() + { + for (unsigned int i = 0; i < C.size(); i++) + { + pb.add_r1cs_constraint(ConstraintT(2 * A[i], B[i], A[i] + B[i] - C[i]), FMT(annotation_prefix, ".A ^ B == C")); + } + } +}; class EqualGadget : public GadgetT { @@ -1030,6 +1116,23 @@ class SignatureVerifier : public GadgetT } }; +class Bitstream +{ +public: + + std::vector data; + + void add(const VariableArrayT& bits) + { + data.push_back(bits); + } + + void add(const std::vector& bits) + { + data.insert(data.end(), bits.begin(), bits.end()); + } +}; + class PublicDataGadget : public GadgetT { public: diff --git a/Gadgets/OrderGadgets.h b/Gadgets/OrderGadgets.h index b4aacee..363bdea 100644 --- a/Gadgets/OrderGadgets.h +++ b/Gadgets/OrderGadgets.h @@ -137,7 +137,8 @@ class OrderGadget : public GadgetT } void generate_r1cs_witness(const Order& order, const Account& account, - const BalanceLeaf& balanceLeafS, const BalanceLeaf& balanceLeafB) + const BalanceLeaf& balanceLeafS, const BalanceLeaf& balanceLeafB, + const TradeHistoryLeaf& tradeHistoryLeaf) { exchangeID.bits.fill_with_bits_of_field_element(pb, order.exchangeID); exchangeID.generate_r1cs_witness_from_bits(); @@ -184,9 +185,9 @@ class OrderGadget : public GadgetT amountS_notZero.generate_r1cs_witness(); amountB_notZero.generate_r1cs_witness(); - pb.val(tradeHistoryFilled) = order.tradeHistoryFilled; - pb.val(tradeHistoryCancelled) = order.tradeHistoryCancelled; - pb.val(tradeHistoryOrderID) = order.tradeHistoryOrderID; + pb.val(tradeHistoryFilled) = tradeHistoryLeaf.filled; + pb.val(tradeHistoryCancelled) = tradeHistoryLeaf.cancelled; + pb.val(tradeHistoryOrderID) = tradeHistoryLeaf.orderID; tradeHistory.generate_r1cs_witness(); diff --git a/Utils/Data.h b/Utils/Data.h index 3fd6ed1..a038570 100644 --- a/Utils/Data.h +++ b/Utils/Data.h @@ -171,10 +171,6 @@ class Order ethsnarks::FieldT rebateBips; Signature signature; - - ethsnarks::FieldT tradeHistoryFilled; - ethsnarks::FieldT tradeHistoryCancelled; - ethsnarks::FieldT tradeHistoryOrderID; }; void from_json(const json& j, Order& order) @@ -200,10 +196,6 @@ void from_json(const json& j, Order& order) order.rebateBips = ethsnarks::FieldT(j.at("rebateBips")); order.signature = j.at("signature").get(); - - order.tradeHistoryFilled = ethsnarks::FieldT(j.at("tradeHistoryFilled").get().c_str()); - order.tradeHistoryCancelled = ethsnarks::FieldT(j.at("tradeHistoryCancelled")); - order.tradeHistoryOrderID = ethsnarks::FieldT(j.at("tradeHistoryOrderID")); } class Ring From bb0302bbe59f79c79d4497b3a5840bcdc80f237a Mon Sep 17 00:00:00 2001 From: Brechtpd Date: Wed, 19 Jun 2019 23:45:46 +0200 Subject: [PATCH 2/7] Fixed ring settlement without DA --- Circuits/RingSettlementCircuit.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Circuits/RingSettlementCircuit.h b/Circuits/RingSettlementCircuit.h index f185922..af23708 100644 --- a/Circuits/RingSettlementCircuit.h +++ b/Circuits/RingSettlementCircuit.h @@ -57,7 +57,7 @@ class TransformRingSettlementDataGadget : public GadgetT this->numRings = numRings; this->data = data; assert(numRings > 0); - assert(numRings * ringSize == data.size); + assert(numRings * ringSize == data.size()); // XOR compress Bitstream compressedData; @@ -763,11 +763,14 @@ class RingSettlementCircuit : public GadgetT FMT(annotation_prefix, ".updateAccount_O")); updateAccount_O->generate_r1cs_constraints(); - // Transform the data - transformData.generate_r1cs_constraints(numRings, flattenReverse(dataAvailabityData.data)); + if (onchainDataAvailability) + { + // Transform the data + transformData.generate_r1cs_constraints(numRings, flattenReverse(dataAvailabityData.data)); + publicData.add(flattenReverse({transformData.result()})); + } // Check the input hash - publicData.add(flattenReverse({transformData.result()})); publicDataHash.generate_r1cs_constraints(true); publicData.generate_r1cs_constraints(); @@ -820,7 +823,10 @@ class RingSettlementCircuit : public GadgetT updateAccount_P->generate_r1cs_witness(block.accountUpdate_P.proof); updateAccount_O->generate_r1cs_witness(block.accountUpdate_O.proof); - transformData.generate_r1cs_witness(); + if (onchainDataAvailability) + { + transformData.generate_r1cs_witness(); + } publicData.generate_r1cs_witness(); return true; From bc5dbf6d14212b084393d5ff7d93cf887455553d Mon Sep 17 00:00:00 2001 From: Brechtpd Date: Thu, 20 Jun 2019 00:51:03 +0200 Subject: [PATCH 3/7] Renamed numElements to blockSize for consistency --- main.cpp | 14 +++++++------- service.cpp | 24 ++++++++++++------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/main.cpp b/main.cpp index 9df4222..da7edb6 100644 --- a/main.cpp +++ b/main.cpp @@ -287,10 +287,10 @@ int main (int argc, char **argv) // Read meta data int blockType = input["blockType"].get(); - unsigned int numElements = input["numElements"].get(); + unsigned int blockSize = input["blockSize"].get(); bool onchainDataAvailability = input["onchainDataAvailability"].get(); std::string strOnchainDataAvailability = onchainDataAvailability ? "_DA_" : "_"; - std::string postFix = strOnchainDataAvailability + std::to_string(numElements); + std::string postFix = strOnchainDataAvailability + std::to_string(blockSize); std::cout << "Building circuit... " << std::endl; std::string baseFilename = "keys/"; @@ -300,7 +300,7 @@ int main (int argc, char **argv) case 0: { baseFilename += "trade" + postFix; - if (!trade(mode, onchainDataAvailability, numElements, input, pb)) + if (!trade(mode, onchainDataAvailability, blockSize, input, pb)) { return 1; } @@ -309,7 +309,7 @@ int main (int argc, char **argv) case 1: { baseFilename += "deposit" + postFix; - if (!deposit(mode, numElements, input, pb)) + if (!deposit(mode, blockSize, input, pb)) { return 1; } @@ -318,7 +318,7 @@ int main (int argc, char **argv) case 2: { baseFilename += "withdraw_onchain" + postFix; - if (!onchainWithdraw(mode, onchainDataAvailability, numElements, input, pb)) + if (!onchainWithdraw(mode, onchainDataAvailability, blockSize, input, pb)) { return 1; } @@ -327,7 +327,7 @@ int main (int argc, char **argv) case 3: { baseFilename += "withdraw_offchain" + postFix; - if (!offchainWithdraw(mode, onchainDataAvailability, numElements, input, pb)) + if (!offchainWithdraw(mode, onchainDataAvailability, blockSize, input, pb)) { return 1; } @@ -336,7 +336,7 @@ int main (int argc, char **argv) case 4: { baseFilename += "cancel" + postFix; - if (!cancel(mode, onchainDataAvailability, numElements, input, pb)) + if (!cancel(mode, onchainDataAvailability, blockSize, input, pb)) { return 1; } diff --git a/service.cpp b/service.cpp index edc16de..c53567f 100644 --- a/service.cpp +++ b/service.cpp @@ -209,10 +209,10 @@ bool cancel(Mode mode, bool onchainDataAvailability, unsigned int numCancels, co std::string generateBaseFileName(const json& input) { // Read meta data int blockType = input["blockType"].get(); - unsigned int numElements = input["numElements"].get(); + unsigned int blockSize = input["blockSize"].get(); bool onchainDataAvailability = input["onchainDataAvailability"].get(); std::string strOnchainDataAvailability = onchainDataAvailability ? "_DA_" : "_"; - std::string postFix = strOnchainDataAvailability + std::to_string(numElements); + std::string postFix = strOnchainDataAvailability + std::to_string(blockSize); std::string baseFilename = "keys/"; switch(blockType) { @@ -253,14 +253,14 @@ std::string generateBaseFileName(const json& input) { int runCircuit(Mode mode, const json& input, ethsnarks::ProtoboardT& pb) { // Read meta data int blockType = input["blockType"].get(); - unsigned int numElements = input["numElements"].get(); + unsigned int blockSize = input["blockSize"].get(); bool onchainDataAvailability = input["onchainDataAvailability"].get(); switch(blockType) { case 0: { - if (!trade(mode, onchainDataAvailability, numElements, input, pb)) + if (!trade(mode, onchainDataAvailability, blockSize, input, pb)) { return 1; } @@ -268,7 +268,7 @@ int runCircuit(Mode mode, const json& input, ethsnarks::ProtoboardT& pb) { } case 1: { - if (!deposit(mode, numElements, input, pb)) + if (!deposit(mode, blockSize, input, pb)) { return 1; } @@ -276,7 +276,7 @@ int runCircuit(Mode mode, const json& input, ethsnarks::ProtoboardT& pb) { } case 2: { - if (!onchainWithdraw(mode, onchainDataAvailability, numElements, input, pb)) + if (!onchainWithdraw(mode, onchainDataAvailability, blockSize, input, pb)) { return 1; } @@ -284,7 +284,7 @@ int runCircuit(Mode mode, const json& input, ethsnarks::ProtoboardT& pb) { } case 3: { - if (!offchainWithdraw(mode, onchainDataAvailability, numElements, input, pb)) + if (!offchainWithdraw(mode, onchainDataAvailability, blockSize, input, pb)) { return 1; } @@ -292,7 +292,7 @@ int runCircuit(Mode mode, const json& input, ethsnarks::ProtoboardT& pb) { } case 4: { - if (!cancel(mode, onchainDataAvailability, numElements, input, pb)) + if (!cancel(mode, onchainDataAvailability, blockSize, input, pb)) { return 1; } @@ -309,11 +309,11 @@ int runCircuit(Mode mode, const json& input, ethsnarks::ProtoboardT& pb) { bool validateBlock(char* inputJson) { ethsnarks::ppT::init_public_params(); - + json input = json::parse(inputJson); ethsnarks::ProtoboardT pb; runCircuit(Mode::Validate, input, pb); - + // Check if the inputs are valid for the circuit if (!pb.is_satisfied()) { @@ -324,7 +324,7 @@ bool validateBlock(char* inputJson) { bool createKeyPair(char* inputJson) { ethsnarks::ppT::init_public_params(); - + json input = json::parse(inputJson); std::string baseFilename = generateBaseFileName(input); ethsnarks::ProtoboardT pb; @@ -367,7 +367,7 @@ ProofResult generateProof(char* inputJson) { std::string proofJsonStr = generateProof(pb, (baseFilename + "_pk.raw").c_str()); clock_gettime(CLOCK_MONOTONIC, &time2); timespec duration = diff(time1,time2); - + if (!proofJsonStr.empty()) { res.success = false; res.errorMessage = "Failed to generate Proof:" + baseFilename + "_pk.raw"; From ab38bf393af10ef8e9c55b2a0e914e075ec6f822 Mon Sep 17 00:00:00 2001 From: Brechtpd Date: Fri, 21 Jun 2019 05:33:56 +0200 Subject: [PATCH 4/7] More flexible ring data transformation --- Circuits/RingSettlementCircuit.h | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Circuits/RingSettlementCircuit.h b/Circuits/RingSettlementCircuit.h index af23708..9c70597 100644 --- a/Circuits/RingSettlementCircuit.h +++ b/Circuits/RingSettlementCircuit.h @@ -81,22 +81,24 @@ class TransformRingSettlementDataGadget : public GadgetT unsigned int offset; unsigned int length; }; - std::vector ranges; - ranges.push_back({0, 40}); // ringMatcherID + fFee + tokenID - ranges.push_back({40, 40}); // orderA.orderID + orderB.orderID - ranges.push_back({80, 40}); // orderA.accountID + orderB.accountID - ranges.push_back({120, 8}); // orderA.tokenS - ranges.push_back({128, 24}); // orderA.fillS - ranges.push_back({152, 8}); // orderA.data - ranges.push_back({160, 8}); // orderB.tokenS - ranges.push_back({168, 24}); // orderB.fillS - ranges.push_back({192, 8}); // orderB.data - for (const Range& range : ranges) + std::vector> ranges; + ranges.push_back({{0, 40}}); // ringMatcherID + fFee + tokenID + ranges.push_back({{40, 40}}); // orderA.orderID + orderB.orderID + ranges.push_back({{80, 40}}); // orderA.accountID + orderB.accountID + ranges.push_back({{120, 8}, {160, 8}}); // orderA.tokenS + orderB.tokenS + ranges.push_back({{152, 8}}); // orderA.data + ranges.push_back({{192, 8}}); // orderB.data + ranges.push_back({{128, 24}}); // orderA.fillS + ranges.push_back({{168, 24}}); // orderB.fillS + for (const std::vector& subRanges : ranges) { for (unsigned int i = 0; i < numRings; i++) { - unsigned int ringStart = i * ringSize; - transformedData.add(subArray(flatten(compressedData.data), ringStart + range.offset, range.length)); + for (const Range& subRange : subRanges) + { + unsigned int ringStart = i * ringSize; + transformedData.add(subArray(flatten(compressedData.data), ringStart + subRange.offset, subRange.length)); + } } } } From 349a5f8d0756808331b9b596d2213d9ad2f2f2a1 Mon Sep 17 00:00:00 2001 From: Brechtpd Date: Sat, 22 Jun 2019 21:29:35 +0200 Subject: [PATCH 5/7] Small data transform change --- Circuits/RingSettlementCircuit.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Circuits/RingSettlementCircuit.h b/Circuits/RingSettlementCircuit.h index 9c70597..92cb8de 100644 --- a/Circuits/RingSettlementCircuit.h +++ b/Circuits/RingSettlementCircuit.h @@ -82,14 +82,13 @@ class TransformRingSettlementDataGadget : public GadgetT unsigned int length; }; std::vector> ranges; - ranges.push_back({{0, 40}}); // ringMatcherID + fFee + tokenID - ranges.push_back({{40, 40}}); // orderA.orderID + orderB.orderID - ranges.push_back({{80, 40}}); // orderA.accountID + orderB.accountID - ranges.push_back({{120, 8}, {160, 8}}); // orderA.tokenS + orderB.tokenS - ranges.push_back({{152, 8}}); // orderA.data - ranges.push_back({{192, 8}}); // orderB.data - ranges.push_back({{128, 24}}); // orderA.fillS - ranges.push_back({{168, 24}}); // orderB.fillS + ranges.push_back({{0, 40}}); // ringMatcherID + fFee + tokenID + ranges.push_back({{40, 40}}); // orderA.orderID + orderB.orderID + ranges.push_back({{80, 40}}); // orderA.accountID + orderB.accountID + ranges.push_back({{120, 8}, {160, 8}}); // orderA.tokenS + orderB.tokenS + ranges.push_back({{128, 24},{168, 24}}); // orderA.fillS + orderB.fillS + ranges.push_back({{152, 8}}); // orderA.data + ranges.push_back({{192, 8}}); // orderB.data for (const std::vector& subRanges : ranges) { for (unsigned int i = 0; i < numRings; i++) From 82d6741a0a3bf56a2df7eba8990a57aa3c7c089c Mon Sep 17 00:00:00 2001 From: Brechtpd Date: Wed, 26 Jun 2019 05:16:57 +0200 Subject: [PATCH 6/7] Misc improvements when accounts are the same in requests --- Circuits/OffchainWithdrawalCircuit.h | 7 ++-- Circuits/OrderCancellationCircuit.h | 7 ++-- Circuits/RingSettlementCircuit.h | 49 +++++++++++++++------------- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/Circuits/OffchainWithdrawalCircuit.h b/Circuits/OffchainWithdrawalCircuit.h index 3734c91..37c0dd2 100644 --- a/Circuits/OffchainWithdrawalCircuit.h +++ b/Circuits/OffchainWithdrawalCircuit.h @@ -42,6 +42,7 @@ class OffchainWithdrawalGadget : public GadgetT AccountState accountWalletBefore; VariableT balanceF_O_before; + VariableT tradingHistoryRootF_O; MulDivGadget feeToWallet; UnsafeSubGadget feeToOperator; @@ -127,6 +128,7 @@ class OffchainWithdrawalGadget : public GadgetT // Operator balanceF_O_before(make_variable(pb, FMT(prefix, ".balanceF_O_before"))), + tradingHistoryRootF_O(make_variable(pb, FMT(prefix, ".tradingHistoryRootF_O"))), // Split the fee between wallet and operator feeToWallet(pb, constants, fFee.value(), walletSplitPercentage.value.packed, constants._100, FMT(prefix, ".feeToWallet")), @@ -178,8 +180,8 @@ class OffchainWithdrawalGadget : public GadgetT // Update Operator updateBalanceF_O(pb, operatorBalancesRoot, feeTokenID, - {balanceF_O_before, constants.emptyTradeHistory}, - {feePaymentOperator.Y, constants.emptyTradeHistory}, + {balanceF_O_before, tradingHistoryRootF_O}, + {feePaymentOperator.Y, tradingHistoryRootF_O}, FMT(prefix, ".updateBalanceF_O")), // Signature @@ -252,6 +254,7 @@ class OffchainWithdrawalGadget : public GadgetT // Operator pb.val(balanceF_O_before) = withdrawal.balanceUpdateF_O.before.balance; + pb.val(tradingHistoryRootF_O) = withdrawal.balanceUpdateF_O.before.tradingHistoryRoot; // Fee payments calculations feeToWallet.generate_r1cs_witness(); diff --git a/Circuits/OrderCancellationCircuit.h b/Circuits/OrderCancellationCircuit.h index c67852e..8bbb58a 100644 --- a/Circuits/OrderCancellationCircuit.h +++ b/Circuits/OrderCancellationCircuit.h @@ -51,6 +51,7 @@ class OrderCancellationGadget : public GadgetT VariableT balancesRoot_W_before; VariableT balanceF_W_before; VariableT nonce_W; + VariableT tradingHistoryRootF_W; VariableT balanceF_O_before; VariableT tradingHistoryRootF_O; @@ -120,6 +121,7 @@ class OrderCancellationGadget : public GadgetT balancesRoot_W_before(make_variable(pb, FMT(prefix, ".balancesRoot_W_before"))), balanceF_W_before(make_variable(pb, FMT(prefix, ".balanceF_W_before"))), nonce_W(make_variable(pb, FMT(prefix, ".nonce_W"))), + tradingHistoryRootF_W(make_variable(pb, FMT(prefix, ".tradingHistoryRootF_W"))), balanceF_O_before(make_variable(pb, FMT(prefix, ".balanceF_O_before"))), tradingHistoryRootF_O(make_variable(pb, FMT(prefix, ".tradingHistoryRootF_O"))), @@ -160,8 +162,8 @@ class OrderCancellationGadget : public GadgetT // Wallet balance updateBalanceF_W(pb, balancesRoot_W_before, feeTokenID, - {balanceF_W_before, constants.emptyTradeHistory}, - {feePaymentWallet.Y, constants.emptyTradeHistory}, + {balanceF_W_before, tradingHistoryRootF_W}, + {feePaymentWallet.Y, tradingHistoryRootF_W}, FMT(prefix, ".updateBalanceF_W")), // Wallet account updateAccount_W(pb, updateAccount_A.result(), walletAccountID, @@ -240,6 +242,7 @@ class OrderCancellationGadget : public GadgetT pb.val(balancesRoot_W_before) = cancellation.accountUpdate_W.before.balancesRoot; pb.val(balanceF_W_before) = cancellation.balanceUpdateF_W.before.balance; pb.val(nonce_W) = cancellation.accountUpdate_W.before.nonce; + pb.val(tradingHistoryRootF_W) = cancellation.balanceUpdateF_W.before.tradingHistoryRoot; pb.val(balanceF_O_before) = cancellation.balanceUpdateF_O.before.balance; pb.val(tradingHistoryRootF_O) = cancellation.balanceUpdateF_O.before.tradingHistoryRoot; diff --git a/Circuits/RingSettlementCircuit.h b/Circuits/RingSettlementCircuit.h index 92cb8de..0a99036 100644 --- a/Circuits/RingSettlementCircuit.h +++ b/Circuits/RingSettlementCircuit.h @@ -115,6 +115,10 @@ class RingSettlementGadget : public GadgetT const VariableT tradingHistoryRootB_A; const VariableT tradingHistoryRootS_B; const VariableT tradingHistoryRootB_B; + const VariableT tradingHistoryRootA_M; + const VariableT tradingHistoryRootB_M; + const VariableT tradingHistoryRootO_M; + const VariableT tradingHistoryRoot_O; const VariableT balancesRootA; const VariableT balancesRootB; @@ -134,9 +138,6 @@ class RingSettlementGadget : public GadgetT OrderGadget orderA; OrderGadget orderB; - ForceNotEqualGadget accountA_neq_ringMatcher; - ForceNotEqualGadget accountB_neq_ringMatcher; - OrderMatchingGadget orderMatching; TernaryGadget uFillS_A; @@ -235,9 +236,6 @@ class RingSettlementGadget : public GadgetT orderA(pb, params, constants, _exchangeID, FMT(prefix, ".orderA")), orderB(pb, params, constants, _exchangeID, FMT(prefix, ".orderB")), - accountA_neq_ringMatcher(pb, orderA.accountID.packed, minerAccountID.packed, FMT(prefix, ".accountA_neq_ringMatcher")), - accountB_neq_ringMatcher(pb, orderB.accountID.packed, minerAccountID.packed, FMT(prefix, ".accountB_neq_ringMatcher")), - // Match orders orderMatching(pb, constants, _timestamp, orderA, orderB, FMT(prefix, ".orderMatching")), @@ -291,6 +289,10 @@ class RingSettlementGadget : public GadgetT tradingHistoryRootB_A(make_variable(pb, FMT(prefix, ".tradingHistoryRootB_A"))), tradingHistoryRootS_B(make_variable(pb, FMT(prefix, ".tradingHistoryRootS_B"))), tradingHistoryRootB_B(make_variable(pb, FMT(prefix, ".tradingHistoryRootB_B"))), + tradingHistoryRootA_M(make_variable(pb, FMT(prefix, ".tradingHistoryRootA_M"))), + tradingHistoryRootB_M(make_variable(pb, FMT(prefix, ".tradingHistoryRootB_M"))), + tradingHistoryRootO_M(make_variable(pb, FMT(prefix, ".tradingHistoryRootO_M"))), + tradingHistoryRoot_O(make_variable(pb, FMT(prefix, ".tradingHistoryRoot_O"))), // Initial balances roots balancesRootA(make_variable(pb, FMT(prefix, ".balancesRootA"))), @@ -341,16 +343,16 @@ class RingSettlementGadget : public GadgetT // Update Ring-Matcher updateBalanceA_M(pb, balancesRootM, orderA.tokenB.bits, - {balanceA_M.front(), constants.emptyTradeHistory}, - {balanceA_M.back(), constants.emptyTradeHistory}, + {balanceA_M.front(), tradingHistoryRootA_M}, + {balanceA_M.back(), tradingHistoryRootA_M}, FMT(prefix, ".updateBalanceA_M")), updateBalanceB_M(pb, updateBalanceA_M.getNewRoot(), orderB.tokenB.bits, - {balanceB_M.front(), constants.emptyTradeHistory}, - {balanceB_M.back(), constants.emptyTradeHistory}, + {balanceB_M.front(), tradingHistoryRootB_M}, + {balanceB_M.back(), tradingHistoryRootB_M}, FMT(prefix, ".updateBalanceB_M")), updateBalanceO_M(pb, updateBalanceB_M.getNewRoot(), tokenID, - {balanceO_M.front(), constants.emptyTradeHistory}, - {balanceO_M.back(), constants.emptyTradeHistory}, + {balanceO_M.front(), tradingHistoryRootO_M}, + {balanceO_M.back(), tradingHistoryRootO_M}, FMT(prefix, ".updateBalanceO_M")), updateAccount_M(pb, updateAccount_B.result(), minerAccountID.bits, {publicKey.x, publicKey.y, nonce_before.packed, balancesRootM}, @@ -369,8 +371,8 @@ class RingSettlementGadget : public GadgetT // Update Operator updateBalanceF_O(pb, _operatorBalancesRoot, tokenID, - {balanceF_O.front(), constants.emptyTradeHistory}, - {balanceF_O.back(), constants.emptyTradeHistory}, + {balanceF_O.front(), tradingHistoryRoot_O}, + {balanceF_O.back(), tradingHistoryRoot_O}, FMT(prefix, ".updateBalanceF_O")), // Signatures @@ -449,9 +451,6 @@ class RingSettlementGadget : public GadgetT ringSettlement.balanceUpdateB_B.before, ringSettlement.tradeHistoryUpdate_B.before); - accountA_neq_ringMatcher.generate_r1cs_witness(); - accountB_neq_ringMatcher.generate_r1cs_witness(); - // Match orders orderMatching.generate_r1cs_witness(); @@ -503,6 +502,10 @@ class RingSettlementGadget : public GadgetT pb.val(tradingHistoryRootB_A) = ringSettlement.balanceUpdateB_A.before.tradingHistoryRoot; pb.val(tradingHistoryRootS_B) = ringSettlement.balanceUpdateS_B.before.tradingHistoryRoot; pb.val(tradingHistoryRootB_B) = ringSettlement.balanceUpdateB_B.before.tradingHistoryRoot; + pb.val(tradingHistoryRootA_M) = ringSettlement.balanceUpdateA_M.before.tradingHistoryRoot; + pb.val(tradingHistoryRootB_M) = ringSettlement.balanceUpdateB_M.before.tradingHistoryRoot; + pb.val(tradingHistoryRootO_M) = ringSettlement.balanceUpdateO_M.before.tradingHistoryRoot; + pb.val(tradingHistoryRoot_O) = ringSettlement.balanceUpdateF_O.before.tradingHistoryRoot; // Initial balances roots pb.val(balancesRootA) = ringSettlement.balanceUpdateS_A.rootBefore; @@ -553,9 +556,6 @@ class RingSettlementGadget : public GadgetT orderA.generate_r1cs_constraints(); orderB.generate_r1cs_constraints(); - accountA_neq_ringMatcher.generate_r1cs_constraints(); - accountB_neq_ringMatcher.generate_r1cs_constraints(); - // Match orders orderMatching.generate_r1cs_constraints(); @@ -650,6 +650,7 @@ class RingSettlementCircuit : public GadgetT libsnark::dual_variable_gadget operatorAccountID; const jubjub::VariablePointT publicKey; const VariableT balancesRootO_before; + const VariableT nonce_O; UpdateAccountGadget* updateAccount_O; RingSettlementCircuit(ProtoboardT& pb, const std::string& prefix) : @@ -672,7 +673,8 @@ class RingSettlementCircuit : public GadgetT operatorAccountID(pb, TREE_DEPTH_ACCOUNTS, FMT(prefix, ".operatorAccountID")), publicKey(pb, FMT(prefix, ".publicKey")), - balancesRootO_before(make_variable(pb, FMT(prefix, ".balancesRootO_before"))) + balancesRootO_before(make_variable(pb, FMT(prefix, ".balancesRootO_before"))), + nonce_O(make_variable(pb, FMT(prefix, ".nonce_O"))) { this->updateAccount_P = nullptr; this->updateAccount_O = nullptr; @@ -759,8 +761,8 @@ class RingSettlementCircuit : public GadgetT // Update the operator updateAccount_O = new UpdateAccountGadget(pb, updateAccount_P->result(), operatorAccountID.bits, - {publicKey.x, publicKey.y, constants.zero, balancesRootO_before}, - {publicKey.x, publicKey.y, constants.zero, ringSettlements.back()->getNewOperatorBalancesRoot()}, + {publicKey.x, publicKey.y, nonce_O, balancesRootO_before}, + {publicKey.x, publicKey.y, nonce_O, ringSettlements.back()->getNewOperatorBalancesRoot()}, FMT(annotation_prefix, ".updateAccount_O")); updateAccount_O->generate_r1cs_constraints(); @@ -815,6 +817,7 @@ class RingSettlementCircuit : public GadgetT pb.val(publicKey.x) = block.accountUpdate_O.before.publicKey.x; pb.val(publicKey.y) = block.accountUpdate_O.before.publicKey.y; pb.val(balancesRootO_before) = block.accountUpdate_O.before.balancesRoot; + pb.val(nonce_O) = block.accountUpdate_O.before.nonce; pb.val(balancesRootP_before) = block.accountUpdate_P.before.balancesRoot; for(unsigned int i = 0; i < block.ringSettlements.size(); i++) From d398746bb8d1062627d676ec35066d58208cd9a1 Mon Sep 17 00:00:00 2001 From: Brechtpd Date: Thu, 27 Jun 2019 23:57:59 +0200 Subject: [PATCH 7/7] Small refactor (miner -> ringMatcher) --- Circuits/RingSettlementCircuit.h | 24 ++++++++++++------------ Utils/Data.h | 8 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Circuits/RingSettlementCircuit.h b/Circuits/RingSettlementCircuit.h index 0a99036..b110998 100644 --- a/Circuits/RingSettlementCircuit.h +++ b/Circuits/RingSettlementCircuit.h @@ -127,7 +127,7 @@ class RingSettlementGadget : public GadgetT VariableT blockexchangeID; const jubjub::VariablePointT publicKey; - libsnark::dual_variable_gadget minerAccountID; + libsnark::dual_variable_gadget ringMatcherAccountID; VariableArrayT tokenID; libsnark::dual_variable_gadget fee; FloatGadget fFee; @@ -202,7 +202,7 @@ class RingSettlementGadget : public GadgetT UpdateBalanceGadget updateBalanceF_O; const VariableArrayT message; - SignatureVerifier minerSignatureVerifier; + SignatureVerifier ringMatcherSignatureVerifier; SignatureVerifier dualAuthASignatureVerifier; SignatureVerifier dualAuthBSignatureVerifier; @@ -225,7 +225,7 @@ class RingSettlementGadget : public GadgetT constants(_constants), publicKey(pb, FMT(prefix, ".publicKey")), - minerAccountID(pb, NUM_BITS_ACCOUNT, FMT(prefix, ".minerAccountID")), + ringMatcherAccountID(pb, NUM_BITS_ACCOUNT, FMT(prefix, ".ringMatcherAccountID")), tokenID(make_var_array(pb, TREE_DEPTH_TOKENS, FMT(prefix, ".tokenID"))), fee(pb, NUM_BITS_AMOUNT, FMT(prefix, ".fee")), fFee(pb, constants, Float12Encoding, FMT(prefix, ".fFee")), @@ -354,7 +354,7 @@ class RingSettlementGadget : public GadgetT {balanceO_M.front(), tradingHistoryRootO_M}, {balanceO_M.back(), tradingHistoryRootO_M}, FMT(prefix, ".updateBalanceO_M")), - updateAccount_M(pb, updateAccount_B.result(), minerAccountID.bits, + updateAccount_M(pb, updateAccount_B.result(), ringMatcherAccountID.bits, {publicKey.x, publicKey.y, nonce_before.packed, balancesRootM}, {publicKey.x, publicKey.y, nonce_after.result(), updateBalanceO_M.getNewRoot()}, FMT(prefix, ".updateAccount_M")), @@ -377,11 +377,11 @@ class RingSettlementGadget : public GadgetT // Signatures message(flatten({orderA.getHash(), orderB.getHash(), - minerAccountID.bits, tokenID, fee.bits, + ringMatcherAccountID.bits, tokenID, fee.bits, orderA.feeBips.bits, orderB.feeBips.bits, orderA.rebateBips.bits, orderB.rebateBips.bits, nonce_before.bits, constants.padding_0})), - minerSignatureVerifier(pb, params, publicKey, message, FMT(prefix, ".minerSignatureVerifier")), + ringMatcherSignatureVerifier(pb, params, publicKey, message, FMT(prefix, ".ringMatcherSignatureVerifier")), dualAuthASignatureVerifier(pb, params, orderA.dualAuthPublicKey, message, FMT(prefix, ".dualAuthASignatureVerifier")), dualAuthBSignatureVerifier(pb, params, orderB.dualAuthPublicKey, message, FMT(prefix, ".dualAuthBSignatureVerifier")) { @@ -407,7 +407,7 @@ class RingSettlementGadget : public GadgetT { return { - minerAccountID.bits, + ringMatcherAccountID.bits, fFee.bits(), tokenID, @@ -429,8 +429,8 @@ class RingSettlementGadget : public GadgetT pb.val(publicKey.x) = ringSettlement.accountUpdate_M.before.publicKey.x; pb.val(publicKey.y) = ringSettlement.accountUpdate_M.before.publicKey.y; - minerAccountID.bits.fill_with_bits_of_field_element(pb, ringSettlement.ring.minerAccountID); - minerAccountID.generate_r1cs_witness_from_bits(); + ringMatcherAccountID.bits.fill_with_bits_of_field_element(pb, ringSettlement.ring.ringMatcherAccountID); + ringMatcherAccountID.generate_r1cs_witness_from_bits(); tokenID.fill_with_bits_of_field_element(pb, ringSettlement.ring.tokenID); fee.bits.fill_with_bits_of_field_element(pb, ringSettlement.ring.fee); fee.generate_r1cs_witness_from_bits(); @@ -538,7 +538,7 @@ class RingSettlementGadget : public GadgetT updateBalanceF_O.generate_r1cs_witness(ringSettlement.balanceUpdateF_O.proof); // Signatures - minerSignatureVerifier.generate_r1cs_witness(ringSettlement.ring.minerSignature); + ringMatcherSignatureVerifier.generate_r1cs_witness(ringSettlement.ring.ringMatcherSignature); dualAuthASignatureVerifier.generate_r1cs_witness(ringSettlement.ring.dualAuthASignature); dualAuthBSignatureVerifier.generate_r1cs_witness(ringSettlement.ring.dualAuthBSignature); } @@ -546,7 +546,7 @@ class RingSettlementGadget : public GadgetT void generate_r1cs_constraints() { - minerAccountID.generate_r1cs_constraints(true); + ringMatcherAccountID.generate_r1cs_constraints(true); fee.generate_r1cs_constraints(true); fFee.generate_r1cs_constraints(); ensureAccuracyFee.generate_r1cs_constraints(); @@ -612,7 +612,7 @@ class RingSettlementGadget : public GadgetT updateBalanceF_O.generate_r1cs_constraints(); // Signatures - minerSignatureVerifier.generate_r1cs_constraints(); + ringMatcherSignatureVerifier.generate_r1cs_constraints(); dualAuthASignatureVerifier.generate_r1cs_constraints(); dualAuthBSignatureVerifier.generate_r1cs_constraints(); } diff --git a/Utils/Data.h b/Utils/Data.h index a038570..18fec17 100644 --- a/Utils/Data.h +++ b/Utils/Data.h @@ -204,12 +204,12 @@ class Ring Order orderA; Order orderB; - ethsnarks::FieldT minerAccountID; + ethsnarks::FieldT ringMatcherAccountID; ethsnarks::FieldT tokenID; ethsnarks::FieldT fee; ethsnarks::FieldT nonce; - Signature minerSignature; + Signature ringMatcherSignature; Signature dualAuthASignature; Signature dualAuthBSignature; }; @@ -219,12 +219,12 @@ void from_json(const json& j, Ring& ring) ring.orderA = j.at("orderA").get(); ring.orderB = j.at("orderB").get(); - ring.minerAccountID = ethsnarks::FieldT(j.at("minerAccountID")); + ring.ringMatcherAccountID = ethsnarks::FieldT(j.at("ringMatcherAccountID")); ring.tokenID = ethsnarks::FieldT(j.at("tokenID")); ring.fee = ethsnarks::FieldT(j.at("fee").get().c_str()); ring.nonce = ethsnarks::FieldT(j.at("nonce")); - ring.minerSignature = j.at("minerSignature").get(); + ring.ringMatcherSignature = j.at("ringMatcherSignature").get(); ring.dualAuthASignature = j.at("dualAuthASignature").get(); ring.dualAuthBSignature = j.at("dualAuthBSignature").get(); }