Skip to content

Commit 20d1930

Browse files
authored
Small test improvements (#30)
1 parent 02f8aed commit 20d1930

File tree

2 files changed

+255
-68
lines changed

2 files changed

+255
-68
lines changed

Gadgets/MatchingGadgets.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -437,26 +437,6 @@ class OrderMatchingGadget : public GadgetT
437437
requireValid.generate_r1cs_constraints();
438438
}
439439

440-
const VariableT& getFillA_S() const
441-
{
442-
return fillS_A;
443-
}
444-
445-
const VariableT& getFillA_B() const
446-
{
447-
return fillS_B;
448-
}
449-
450-
const VariableT& getFillB_S() const
451-
{
452-
return fillS_B;
453-
}
454-
455-
const VariableT& getFillB_B() const
456-
{
457-
return fillS_A;
458-
}
459-
460440
const VariableT& getFilledAfter_A() const
461441
{
462442
return requireOrderFillsA.getFilledAfter();

test/MatchingTests.cpp

Lines changed: 255 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,51 @@
33

44
#include "../Gadgets/MatchingGadgets.h"
55

6+
struct OrderState
7+
{
8+
Order order;
9+
Account account;
10+
BalanceLeaf balanceLeafS;
11+
BalanceLeaf balanceLeafB;
12+
TradeHistoryLeaf tradeHistoryLeaf;
13+
};
14+
15+
OrderState setOrderState(const OrderState& orderState,
16+
const FieldT& orderID,
17+
const FieldT& amountS, const FieldT& amountB, bool buy,
18+
const FieldT& balanceS,
19+
const FieldT& filled, bool cancelled, const FieldT& tradeHistoryOrderID,
20+
bool allOrNone = false)
21+
{
22+
OrderState newOrderState(orderState);
23+
newOrderState.order.orderID = orderID;
24+
newOrderState.order.amountS = amountS;
25+
newOrderState.order.amountB = amountB;
26+
newOrderState.order.buy = buy ? 1 : 0;
27+
newOrderState.order.allOrNone = allOrNone ? 1 : 0;
28+
newOrderState.balanceLeafS.balance = balanceS;
29+
newOrderState.balanceLeafB.balance = 0;
30+
newOrderState.tradeHistoryLeaf.filled = filled;
31+
newOrderState.tradeHistoryLeaf.cancelled = cancelled ? 1 : 0;
32+
newOrderState.tradeHistoryLeaf.orderID = tradeHistoryOrderID;
33+
return newOrderState;
34+
};
35+
36+
bool lt(const FieldT& A, const FieldT& B)
37+
{
38+
return toBigInt(A) < toBigInt(B);
39+
}
40+
41+
bool lte(const FieldT& A, const FieldT& B)
42+
{
43+
return toBigInt(A) <= toBigInt(B);
44+
}
45+
46+
FieldT muldiv(const FieldT& V, const FieldT& N, const FieldT& D)
47+
{
48+
return toFieldElement(validate(toBigInt(V) * toBigInt(N)) / toBigInt(D));
49+
}
50+
651
TEST_CASE("RequireFillRate", "[RequireFillRateGadget]")
752
{
853
unsigned int maxLength = NUM_BITS_AMOUNT;
@@ -129,6 +174,212 @@ TEST_CASE("RequireFillRate", "[RequireFillRateGadget]")
129174
}}
130175
}
131176

177+
TEST_CASE("RequireFillLimit", "[RequireFillLimitGadget]")
178+
{
179+
unsigned int numIterations = 1024;
180+
181+
RingSettlementBlock block = getRingSettlementBlock();
182+
REQUIRE(block.ringSettlements.size() > 0);
183+
const RingSettlement& ringSettlement = block.ringSettlements[0];
184+
185+
const Order& order = ringSettlement.ring.orderA;
186+
const Account& account = ringSettlement.accountUpdate_A.before;
187+
const BalanceLeaf& balanceLeafS = ringSettlement.balanceUpdateS_A.before;
188+
const BalanceLeaf& balanceLeafB = ringSettlement.balanceUpdateB_A.before;
189+
const TradeHistoryLeaf& tradeHistoryLeaf = ringSettlement.tradeHistoryUpdate_A.before;
190+
const OrderState _orderState = {order, account, balanceLeafS, balanceLeafB, tradeHistoryLeaf};
191+
192+
unsigned int numTradeHistoryLeafs = pow(2, NUM_BITS_TRADING_HISTORY);
193+
const FieldT orderID = rand() % numTradeHistoryLeafs;
194+
195+
enum class Expected
196+
{
197+
Valid,
198+
Invalid,
199+
Automatic
200+
};
201+
auto checkFillLimitChecked = [_orderState](const FieldT& _amountS, const FieldT& _amountB, bool _buy, unsigned int _orderID,
202+
unsigned int _tradeHistoryOrderID, const FieldT& _filled, bool _cancelled,
203+
const FieldT& _fillAmountS, const FieldT& _fillAmountB,
204+
Expected expected = Expected::Automatic)
205+
{
206+
protoboard<FieldT> pb;
207+
208+
OrderState orderState = setOrderState(
209+
_orderState,
210+
_orderID,
211+
_amountS, _amountB, _buy,
212+
getMaxFieldElement(NUM_BITS_AMOUNT),
213+
_filled, _cancelled, _tradeHistoryOrderID
214+
);
215+
216+
VariableT fillAmountS = make_variable(pb, _fillAmountS, "fillAmountS");
217+
VariableT fillAmountB = make_variable(pb, _fillAmountB, "fillAmountB");
218+
219+
Constants constants(pb, "constants");
220+
221+
VariableT exchangeID = make_variable(pb, 0, "exchangeID");
222+
VariableT timestamp = make_variable(pb, 0, "timestamp");
223+
224+
jubjub::Params params;
225+
OrderGadget order(pb, params, constants, exchangeID, ".order");
226+
order.generate_r1cs_witness(orderState.order, orderState.account, orderState.balanceLeafS, orderState.balanceLeafB, orderState.tradeHistoryLeaf);
227+
228+
RequireFillLimitGadget requireFillLimit(pb, constants, order, fillAmountS, fillAmountB, "requireFillRateGadget");
229+
requireFillLimit.generate_r1cs_constraints();
230+
requireFillLimit.generate_r1cs_witness();
231+
232+
// Simulate
233+
FieldT limit;
234+
FieldT filledAfter;
235+
if (_buy)
236+
{
237+
limit = (pb.val(order.tradeHistory.getCancelled()) == 1) ? pb.val(order.tradeHistory.getFilled()) : _amountB;
238+
filledAfter = pb.val(order.tradeHistory.getFilled()) + _fillAmountB;
239+
}
240+
else
241+
{
242+
limit = (pb.val(order.tradeHistory.getCancelled()) == 1) ? pb.val(order.tradeHistory.getFilled()) : _amountS;
243+
filledAfter = pb.val(order.tradeHistory.getFilled()) + _fillAmountS;
244+
}
245+
bool expectedAutomaticValid = lte(filledAfter, limit);
246+
247+
bool expectedValid = false;
248+
if (expected == Expected::Automatic)
249+
{
250+
expectedValid = expectedAutomaticValid;
251+
}
252+
else
253+
{
254+
expectedValid = (expected == Expected::Valid) ? true : false;
255+
}
256+
REQUIRE(expectedAutomaticValid == expectedValid);
257+
258+
REQUIRE(pb.is_satisfied() == expectedValid);
259+
if (expectedValid)
260+
{
261+
REQUIRE((pb.val(requireFillLimit.getFilledAfter()) == filledAfter));
262+
}
263+
};
264+
265+
unsigned int n = NUM_BITS_AMOUNT;
266+
FieldT maxAmount = getMaxFieldElement(NUM_BITS_AMOUNT);
267+
268+
SECTION("order: 1/1, fill: 1/1")
269+
{
270+
checkFillLimitChecked(1, 1, true, 0,
271+
0, 0, false,
272+
1, 1, Expected::Valid);
273+
}
274+
275+
SECTION("order: max/max, fill: max/max")
276+
{
277+
checkFillLimitChecked(maxAmount, maxAmount, true, 0,
278+
0, 0, false,
279+
1, 1, Expected::Valid);
280+
}
281+
282+
SECTION("order: 1/1, fill: max/max")
283+
{
284+
checkFillLimitChecked(1, 1, true, 0,
285+
0, 0, false,
286+
maxAmount, maxAmount, Expected::Invalid);
287+
}
288+
289+
SECTION("order: max/max, fill: 1/1")
290+
{
291+
checkFillLimitChecked(maxAmount, maxAmount, true, 0,
292+
0, 0, false,
293+
1, 1, Expected::Valid);
294+
}
295+
296+
SECTION("order: max/1, fill: max/1")
297+
{
298+
checkFillLimitChecked(maxAmount, 1, true, 0,
299+
0, 0, false,
300+
maxAmount, 1, Expected::Valid);
301+
}
302+
303+
SECTION("order: 1/max, fill: 1/max")
304+
{
305+
checkFillLimitChecked(1, maxAmount, true, 0,
306+
0, 0, false,
307+
1, maxAmount, Expected::Valid);
308+
}
309+
310+
SECTION("cancelled")
311+
{
312+
unsigned int orderID = rand() % NUM_BITS_ORDERID;
313+
checkFillLimitChecked(1, 1, true, orderID,
314+
orderID, 0, true,
315+
1, 1, Expected::Invalid);
316+
}
317+
318+
SECTION("reused")
319+
{
320+
unsigned int orderID = rand() % NUM_BITS_TRADING_HISTORY;
321+
for (unsigned int i = 0; i < 2; i++)
322+
{
323+
checkFillLimitChecked(maxAmount, maxAmount, true, orderID + numTradeHistoryLeafs,
324+
orderID, maxAmount, i % 2,
325+
maxAmount, maxAmount, Expected::Valid);
326+
}
327+
}
328+
329+
SECTION("trimmed")
330+
{
331+
unsigned int orderID = rand() % NUM_BITS_TRADING_HISTORY;
332+
checkFillLimitChecked(1, 1, true, orderID,
333+
orderID + numTradeHistoryLeafs, maxAmount, false,
334+
1, 1, Expected::Invalid);
335+
}
336+
337+
SECTION("Fill limits")
338+
{
339+
unsigned int orderID = rand() % NUM_BITS_TRADING_HISTORY;
340+
unsigned int amountS = 1000;
341+
unsigned int amountB = 100;
342+
343+
// buy order
344+
for(unsigned int filled = 0; filled < amountB * 2; filled += 10)
345+
{
346+
for(unsigned int fillB = 0; fillB < amountB * 2; fillB += 10)
347+
{
348+
bool expectedValid = (filled + fillB <= amountB);
349+
checkFillLimitChecked(amountS, amountB, true, orderID,
350+
orderID, filled, false,
351+
fillB * 9, fillB,
352+
expectedValid ? Expected::Valid : Expected::Invalid);
353+
}
354+
}
355+
356+
// sell order
357+
for(unsigned int filled = 0; filled < amountS * 2; filled += 100)
358+
{
359+
for(unsigned int fillS = 0; fillS < amountS * 2; fillS += 100)
360+
{
361+
bool expectedValid = (filled + fillS <= amountS);
362+
checkFillLimitChecked(amountS, amountB, false, orderID,
363+
orderID, filled, false,
364+
fillS, fillS / 9,
365+
expectedValid ? Expected::Valid : Expected::Invalid);
366+
}
367+
}
368+
}
369+
370+
SECTION("Random")
371+
{
372+
for (unsigned int i = 0; i < numIterations; i++)
373+
{
374+
bool buy = i % 2;
375+
bool cancelled = i % 5;
376+
checkFillLimitChecked(getRandomFieldElement(n), getRandomFieldElement(n), buy, rand() % NUM_BITS_ORDERID,
377+
rand() % NUM_BITS_ORDERID, getRandomFieldElement(n), cancelled,
378+
getRandomFieldElement(n), getRandomFieldElement(n));
379+
}
380+
}
381+
}
382+
132383
TEST_CASE("FeeCalculator", "[FeeCalculatorGadget]")
133384
{
134385
unsigned int maxLength = NUM_BITS_AMOUNT;
@@ -216,14 +467,6 @@ TEST_CASE("FeeCalculator", "[FeeCalculatorGadget]")
216467
}
217468
}
218469

219-
struct OrderState
220-
{
221-
Order order;
222-
Account account;
223-
BalanceLeaf balanceLeafS;
224-
BalanceLeaf balanceLeafB;
225-
TradeHistoryLeaf tradeHistoryLeaf;
226-
};
227470

228471
namespace Simulator
229472
{
@@ -246,21 +489,6 @@ namespace Simulator
246489
bool valid;
247490
};
248491

249-
bool lt(const FieldT& A, const FieldT& B)
250-
{
251-
return toBigInt(A) < toBigInt(B);
252-
}
253-
254-
bool lte(const FieldT& A, const FieldT& B)
255-
{
256-
return toBigInt(A) <= toBigInt(B);
257-
}
258-
259-
FieldT muldiv(const FieldT& V, const FieldT& N, const FieldT& D)
260-
{
261-
return toFieldElement(validate(toBigInt(V) * toBigInt(N)) / toBigInt(D));
262-
}
263-
264492
TradeHistory getTradeHistory(const OrderState& orderState)
265493
{
266494
FieldT filled = lt(orderState.tradeHistoryLeaf.orderID, orderState.order.orderID) ? 0 : orderState.tradeHistoryLeaf.filled;
@@ -351,27 +579,6 @@ namespace Simulator
351579

352580
TEST_CASE("OrderMatching", "[OrderMatchingGadget]")
353581
{
354-
auto setOrderState = [](const OrderState& orderState,
355-
const FieldT& orderID,
356-
const FieldT& amountS, const FieldT& amountB, bool buy,
357-
const FieldT& balanceS,
358-
const FieldT& filled, bool cancelled, const FieldT& tradeHistoryOrderID,
359-
bool allOrNone = false)
360-
{
361-
OrderState newOrderState(orderState);
362-
newOrderState.order.orderID = orderID;
363-
newOrderState.order.amountS = amountS;
364-
newOrderState.order.amountB = amountB;
365-
newOrderState.order.buy = buy ? 1 : 0;
366-
newOrderState.order.allOrNone = allOrNone ? 1 : 0;
367-
newOrderState.balanceLeafS.balance = balanceS;
368-
newOrderState.balanceLeafB.balance = 0;
369-
newOrderState.tradeHistoryLeaf.filled = filled;
370-
newOrderState.tradeHistoryLeaf.cancelled = cancelled ? 1 : 0;
371-
newOrderState.tradeHistoryLeaf.orderID = tradeHistoryOrderID;
372-
return newOrderState;
373-
};
374-
375582
enum class ExpectedValid
376583
{
377584
Valid,
@@ -427,10 +634,10 @@ TEST_CASE("OrderMatching", "[OrderMatchingGadget]")
427634
REQUIRE(pb.is_satisfied() == (expectedSatisfied && expectedValidValue));
428635
if (expectedSatisfied && expectedValidValue)
429636
{
430-
REQUIRE((pb.val(orderMatching.getFillA_S()) == pb.val(expectedFillS_A)));
431-
REQUIRE((pb.val(orderMatching.getFillA_B()) == pb.val(expectedFillS_B)));
432-
REQUIRE((pb.val(orderMatching.getFillB_S()) == pb.val(expectedFillS_B)));
433-
REQUIRE((pb.val(orderMatching.getFillB_B()) == pb.val(expectedFillS_A)));
637+
auto tradeHistory_A = Simulator::getTradeHistory(orderStateA);
638+
REQUIRE((pb.val(orderMatching.getFilledAfter_A()) == (tradeHistory_A.filled + (orderStateA.order.buy == 1 ? pb.val(expectedFillS_B) : pb.val(expectedFillS_A)))));
639+
auto tradeHistory_B = Simulator::getTradeHistory(orderStateB);
640+
REQUIRE((pb.val(orderMatching.getFilledAfter_B()) == (tradeHistory_B.filled + (orderStateB.order.buy == 1 ? pb.val(expectedFillS_A) : pb.val(expectedFillS_B)))));
434641
}
435642
};
436643

0 commit comments

Comments
 (0)