rippled
Check_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2017 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/protocol/Feature.h>
21 #include <ripple/protocol/jss.h>
22 #include <test/jtx.h>
23 
24 namespace ripple {
25 namespace test {
26 namespace jtx {
27 
30 {
31 private:
33 
34 public:
35  explicit expiration(NetClock::time_point const& expiry)
36  : expry_{expiry.time_since_epoch().count()}
37  {
38  }
39 
40  void
41  operator()(Env&, JTx& jt) const
42  {
44  }
45 };
46 
49 {
50 private:
52 
53 public:
54  explicit source_tag(std::uint32_t tag) : tag_{tag}
55  {
56  }
57 
58  void
59  operator()(Env&, JTx& jt) const
60  {
62  }
63 };
64 
66 class dest_tag
67 {
68 private:
70 
71 public:
72  explicit dest_tag(std::uint32_t tag) : tag_{tag}
73  {
74  }
75 
76  void
77  operator()(Env&, JTx& jt) const
78  {
80  }
81 };
82 
83 } // namespace jtx
84 } // namespace test
85 
86 class Check_test : public beast::unit_test::suite
87 {
88  // Helper function that returns the Checks on an account.
91  {
94  *env.current(),
95  account,
96  [&result](std::shared_ptr<SLE const> const& sle) {
97  if (sle->getType() == ltCHECK)
98  result.push_back(sle);
99  });
100  return result;
101  }
102 
103  // Helper function that returns the owner count on an account.
104  static std::uint32_t
105  ownerCount(test::jtx::Env const& env, test::jtx::Account const& account)
106  {
107  std::uint32_t ret{0};
108  if (auto const sleAccount = env.le(account))
109  ret = sleAccount->getFieldU32(sfOwnerCount);
110  return ret;
111  }
112 
113  // Helper function that verifies the expected DeliveredAmount is present.
114  //
115  // NOTE: the function _infers_ the transaction to operate on by calling
116  // env.tx(), which returns the result from the most recent transaction.
117  void
119  {
120  // Get the hash for the most recent transaction.
121  std::string const txHash{
122  env.tx()->getJson(JsonOptions::none)[jss::hash].asString()};
123 
124  // Verify DeliveredAmount and delivered_amount metadata are correct.
125  env.close();
126  Json::Value const meta = env.rpc("tx", txHash)[jss::result][jss::meta];
127 
128  // Expect there to be a DeliveredAmount field.
129  if (!BEAST_EXPECT(meta.isMember(sfDeliveredAmount.jsonName)))
130  return;
131 
132  // DeliveredAmount and delivered_amount should both be present and
133  // equal amount.
134  BEAST_EXPECT(
135  meta[sfDeliveredAmount.jsonName] ==
136  amount.getJson(JsonOptions::none));
137  BEAST_EXPECT(
138  meta[jss::delivered_amount] == amount.getJson(JsonOptions::none));
139  }
140 
141  void
143  {
144  testcase("Enabled");
145 
146  using namespace test::jtx;
147  Account const alice{"alice"};
148  {
149  // If the Checks amendment is not enabled, you should not be able
150  // to create, cash, or cancel checks.
151  Env env{*this, supported_amendments() - featureChecks};
152 
153  env.fund(XRP(1000), alice);
154 
155  uint256 const checkId{
156  getCheckIndex(env.master, env.seq(env.master))};
157  env(check::create(env.master, alice, XRP(100)), ter(temDISABLED));
158  env.close();
159 
160  env(check::cash(alice, checkId, XRP(100)), ter(temDISABLED));
161  env.close();
162 
163  env(check::cancel(alice, checkId), ter(temDISABLED));
164  env.close();
165  }
166  {
167  // If the Checks amendment is enabled all check-related
168  // facilities should be available.
169  Env env{*this};
170 
171  env.fund(XRP(1000), alice);
172 
173  uint256 const checkId1{
174  getCheckIndex(env.master, env.seq(env.master))};
175  env(check::create(env.master, alice, XRP(100)));
176  env.close();
177 
178  env(check::cash(alice, checkId1, XRP(100)));
179  env.close();
180 
181  uint256 const checkId2{
182  getCheckIndex(env.master, env.seq(env.master))};
183  env(check::create(env.master, alice, XRP(100)));
184  env.close();
185 
186  env(check::cancel(alice, checkId2));
187  env.close();
188  }
189  }
190 
191  void
193  {
194  // Explore many of the valid ways to create a check.
195  testcase("Create valid");
196 
197  using namespace test::jtx;
198 
199  Account const gw{"gateway"};
200  Account const alice{"alice"};
201  Account const bob{"bob"};
202  IOU const USD{gw["USD"]};
203 
204  Env env{*this};
205 
206  STAmount const startBalance{XRP(1000).value()};
207  env.fund(startBalance, gw, alice, bob);
208 
209  // Note that no trust line has been set up for alice, but alice can
210  // still write a check for USD. You don't have to have the funds
211  // necessary to cover a check in order to write a check.
212  auto writeTwoChecks = [&env, &USD, this](
213  Account const& from, Account const& to) {
214  std::uint32_t const fromOwnerCount{ownerCount(env, from)};
215  std::uint32_t const toOwnerCount{ownerCount(env, to)};
216 
217  std::size_t const fromCkCount{checksOnAccount(env, from).size()};
218  std::size_t const toCkCount{checksOnAccount(env, to).size()};
219 
220  env(check::create(from, to, XRP(2000)));
221  env.close();
222 
223  env(check::create(from, to, USD(50)));
224  env.close();
225 
226  BEAST_EXPECT(checksOnAccount(env, from).size() == fromCkCount + 2);
227  BEAST_EXPECT(checksOnAccount(env, to).size() == toCkCount + 2);
228 
229  env.require(owners(from, fromOwnerCount + 2));
230  env.require(
231  owners(to, to == from ? fromOwnerCount + 2 : toOwnerCount));
232  };
233  // from to
234  writeTwoChecks(alice, bob);
235  writeTwoChecks(gw, alice);
236  writeTwoChecks(alice, gw);
237 
238  // Now try adding the various optional fields. There's no
239  // expected interaction between these optional fields; other than
240  // the expiration, they are just plopped into the ledger. So I'm
241  // not looking at interactions.
242  using namespace std::chrono_literals;
243  std::size_t const aliceCount{checksOnAccount(env, alice).size()};
244  std::size_t const bobCount{checksOnAccount(env, bob).size()};
245  env(check::create(alice, bob, USD(50)), expiration(env.now() + 1s));
246  env.close();
247 
248  env(check::create(alice, bob, USD(50)), source_tag(2));
249  env.close();
250  env(check::create(alice, bob, USD(50)), dest_tag(3));
251  env.close();
252  env(check::create(alice, bob, USD(50)), invoice_id(uint256{4}));
253  env.close();
254  env(check::create(alice, bob, USD(50)),
255  expiration(env.now() + 1s),
256  source_tag(12),
257  dest_tag(13),
258  invoice_id(uint256{4}));
259  env.close();
260 
261  BEAST_EXPECT(checksOnAccount(env, alice).size() == aliceCount + 5);
262  BEAST_EXPECT(checksOnAccount(env, bob).size() == bobCount + 5);
263 
264  // Use a regular key and also multisign to create a check.
265  Account const alie{"alie", KeyType::ed25519};
266  env(regkey(alice, alie));
267  env.close();
268 
269  Account const bogie{"bogie", KeyType::secp256k1};
270  Account const demon{"demon", KeyType::ed25519};
271  env(signers(alice, 2, {{bogie, 1}, {demon, 1}}), sig(alie));
272  env.close();
273 
274  // alice uses her regular key to create a check.
275  env(check::create(alice, bob, USD(50)), sig(alie));
276  env.close();
277  BEAST_EXPECT(checksOnAccount(env, alice).size() == aliceCount + 6);
278  BEAST_EXPECT(checksOnAccount(env, bob).size() == bobCount + 6);
279 
280  // alice uses multisigning to create a check.
281  XRPAmount const baseFeeDrops{env.current()->fees().base};
282  env(check::create(alice, bob, USD(50)),
283  msig(bogie, demon),
284  fee(3 * baseFeeDrops));
285  env.close();
286  BEAST_EXPECT(checksOnAccount(env, alice).size() == aliceCount + 7);
287  BEAST_EXPECT(checksOnAccount(env, bob).size() == bobCount + 7);
288  }
289 
290  void
292  {
293  // Explore many of the invalid ways to create a check.
294  testcase("Create invalid");
295 
296  using namespace test::jtx;
297 
298  Account const gw1{"gateway1"};
299  Account const gwF{"gatewayFrozen"};
300  Account const alice{"alice"};
301  Account const bob{"bob"};
302  IOU const USD{gw1["USD"]};
303 
304  Env env{*this};
305 
306  STAmount const startBalance{XRP(1000).value()};
307  env.fund(startBalance, gw1, gwF, alice, bob);
308 
309  // Bad fee.
310  env(check::create(alice, bob, USD(50)),
311  fee(drops(-10)),
312  ter(temBAD_FEE));
313  env.close();
314 
315  // Bad flags.
316  env(check::create(alice, bob, USD(50)),
317  txflags(tfImmediateOrCancel),
318  ter(temINVALID_FLAG));
319  env.close();
320 
321  // Check to self.
322  env(check::create(alice, alice, XRP(10)), ter(temREDUNDANT));
323  env.close();
324 
325  // Bad amount.
326  env(check::create(alice, bob, drops(-1)), ter(temBAD_AMOUNT));
327  env.close();
328 
329  env(check::create(alice, bob, drops(0)), ter(temBAD_AMOUNT));
330  env.close();
331 
332  env(check::create(alice, bob, drops(1)));
333  env.close();
334 
335  env(check::create(alice, bob, USD(-1)), ter(temBAD_AMOUNT));
336  env.close();
337 
338  env(check::create(alice, bob, USD(0)), ter(temBAD_AMOUNT));
339  env.close();
340 
341  env(check::create(alice, bob, USD(1)));
342  env.close();
343  {
344  IOU const BAD{gw1, badCurrency()};
345  env(check::create(alice, bob, BAD(2)), ter(temBAD_CURRENCY));
346  env.close();
347  }
348 
349  // Bad expiration.
350  env(check::create(alice, bob, USD(50)),
351  expiration(NetClock::time_point{}),
352  ter(temBAD_EXPIRATION));
353  env.close();
354 
355  // Destination does not exist.
356  Account const bogie{"bogie"};
357  env(check::create(alice, bogie, USD(50)), ter(tecNO_DST));
358  env.close();
359 
360  // Require destination tag.
361  env(fset(bob, asfRequireDest));
362  env.close();
363 
364  env(check::create(alice, bob, USD(50)), ter(tecDST_TAG_NEEDED));
365  env.close();
366 
367  env(check::create(alice, bob, USD(50)), dest_tag(11));
368  env.close();
369 
370  env(fclear(bob, asfRequireDest));
371  env.close();
372  {
373  // Globally frozen asset.
374  IOU const USF{gwF["USF"]};
375  env(fset(gwF, asfGlobalFreeze));
376  env.close();
377 
378  env(check::create(alice, bob, USF(50)), ter(tecFROZEN));
379  env.close();
380 
381  env(fclear(gwF, asfGlobalFreeze));
382  env.close();
383 
384  env(check::create(alice, bob, USF(50)));
385  env.close();
386  }
387  {
388  // Frozen trust line. Check creation should be similar to payment
389  // behavior in the face of frozen trust lines.
390  env.trust(USD(1000), alice);
391  env.trust(USD(1000), bob);
392  env.close();
393  env(pay(gw1, alice, USD(25)));
394  env(pay(gw1, bob, USD(25)));
395  env.close();
396 
397  // Setting trustline freeze in one direction prevents alice from
398  // creating a check for USD. But bob and gw1 should still be able
399  // to create a check for USD to alice.
400  env(trust(gw1, alice["USD"](0), tfSetFreeze));
401  env.close();
402  env(check::create(alice, bob, USD(50)), ter(tecFROZEN));
403  env.close();
404  env(pay(alice, bob, USD(1)), ter(tecPATH_DRY));
405  env.close();
406  env(check::create(bob, alice, USD(50)));
407  env.close();
408  env(pay(bob, alice, USD(1)));
409  env.close();
410  env(check::create(gw1, alice, USD(50)));
411  env.close();
412  env(pay(gw1, alice, USD(1)));
413  env.close();
414 
415  // Clear that freeze. Now check creation works.
416  env(trust(gw1, alice["USD"](0), tfClearFreeze));
417  env.close();
418  env(check::create(alice, bob, USD(50)));
419  env.close();
420  env(check::create(bob, alice, USD(50)));
421  env.close();
422  env(check::create(gw1, alice, USD(50)));
423  env.close();
424 
425  // Freezing in the other direction does not effect alice's USD
426  // check creation, but prevents bob and gw1 from writing a check
427  // for USD to alice.
428  env(trust(alice, USD(0), tfSetFreeze));
429  env.close();
430  env(check::create(alice, bob, USD(50)));
431  env.close();
432  env(pay(alice, bob, USD(1)));
433  env.close();
434  env(check::create(bob, alice, USD(50)), ter(tecFROZEN));
435  env.close();
436  env(pay(bob, alice, USD(1)), ter(tecPATH_DRY));
437  env.close();
438  env(check::create(gw1, alice, USD(50)), ter(tecFROZEN));
439  env.close();
440  env(pay(gw1, alice, USD(1)), ter(tecPATH_DRY));
441  env.close();
442 
443  // Clear that freeze.
444  env(trust(alice, USD(0), tfClearFreeze));
445  env.close();
446  }
447 
448  // Expired expiration.
449  env(check::create(alice, bob, USD(50)),
450  expiration(env.now()),
451  ter(tecEXPIRED));
452  env.close();
453 
454  using namespace std::chrono_literals;
455  env(check::create(alice, bob, USD(50)), expiration(env.now() + 1s));
456  env.close();
457 
458  // Insufficient reserve.
459  Account const cheri{"cheri"};
460  env.fund(env.current()->fees().accountReserve(1) - drops(1), cheri);
461 
462  env(check::create(cheri, bob, USD(50)),
463  fee(drops(env.current()->fees().base)),
465  env.close();
466 
467  env(pay(bob, cheri, drops(env.current()->fees().base + 1)));
468  env.close();
469 
470  env(check::create(cheri, bob, USD(50)));
471  env.close();
472  }
473 
474  void
476  {
477  // Explore many of the valid ways to cash a check for XRP.
478  testcase("Cash XRP");
479 
480  using namespace test::jtx;
481 
482  Account const alice{"alice"};
483  Account const bob{"bob"};
484 
485  Env env{*this};
486 
487  XRPAmount const baseFeeDrops{env.current()->fees().base};
488  STAmount const startBalance{XRP(300).value()};
489  env.fund(startBalance, alice, bob);
490  {
491  // Basic XRP check.
492  uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
493  env(check::create(alice, bob, XRP(10)));
494  env.close();
495  env.require(balance(alice, startBalance - drops(baseFeeDrops)));
496  env.require(balance(bob, startBalance));
497  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
498  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
499  BEAST_EXPECT(ownerCount(env, alice) == 1);
500  BEAST_EXPECT(ownerCount(env, bob) == 0);
501 
502  env(check::cash(bob, chkId, XRP(10)));
503  env.close();
504  env.require(
505  balance(alice, startBalance - XRP(10) - drops(baseFeeDrops)));
506  env.require(
507  balance(bob, startBalance + XRP(10) - drops(baseFeeDrops)));
508  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
509  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
510  BEAST_EXPECT(ownerCount(env, alice) == 0);
511  BEAST_EXPECT(ownerCount(env, bob) == 0);
512 
513  // Make alice's and bob's balances easy to think about.
514  env(pay(env.master, alice, XRP(10) + drops(baseFeeDrops)));
515  env(pay(bob, env.master, XRP(10) - drops(baseFeeDrops * 2)));
516  env.close();
517  env.require(balance(alice, startBalance));
518  env.require(balance(bob, startBalance));
519  }
520  {
521  // Write a check that chews into alice's reserve.
522  STAmount const reserve{env.current()->fees().accountReserve(0)};
523  STAmount const checkAmount{
524  startBalance - reserve - drops(baseFeeDrops)};
525  uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
526  env(check::create(alice, bob, checkAmount));
527  env.close();
528 
529  // bob tries to cash for more than the check amount.
530  env(check::cash(bob, chkId, checkAmount + drops(1)),
531  ter(tecPATH_PARTIAL));
532  env.close();
533  env(check::cash(
534  bob, chkId, check::DeliverMin(checkAmount + drops(1))),
535  ter(tecPATH_PARTIAL));
536  env.close();
537 
538  // bob cashes exactly the check amount. This is successful
539  // because one unit of alice's reserve is released when the
540  // check is consumed.
541  env(check::cash(bob, chkId, check::DeliverMin(checkAmount)));
542  verifyDeliveredAmount(env, drops(checkAmount.mantissa()));
543  env.require(balance(alice, reserve));
544  env.require(balance(
545  bob, startBalance + checkAmount - drops(baseFeeDrops * 3)));
546  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
547  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
548  BEAST_EXPECT(ownerCount(env, alice) == 0);
549  BEAST_EXPECT(ownerCount(env, bob) == 0);
550 
551  // Make alice's and bob's balances easy to think about.
552  env(pay(env.master, alice, checkAmount + drops(baseFeeDrops)));
553  env(pay(bob, env.master, checkAmount - drops(baseFeeDrops * 4)));
554  env.close();
555  env.require(balance(alice, startBalance));
556  env.require(balance(bob, startBalance));
557  }
558  {
559  // Write a check that goes one drop past what alice can pay.
560  STAmount const reserve{env.current()->fees().accountReserve(0)};
561  STAmount const checkAmount{
562  startBalance - reserve - drops(baseFeeDrops - 1)};
563  uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
564  env(check::create(alice, bob, checkAmount));
565  env.close();
566 
567  // bob tries to cash for exactly the check amount. Fails because
568  // alice is one drop shy of funding the check.
569  env(check::cash(bob, chkId, checkAmount), ter(tecPATH_PARTIAL));
570  env.close();
571 
572  // bob decides to get what he can from the bounced check.
573  env(check::cash(bob, chkId, check::DeliverMin(drops(1))));
574  verifyDeliveredAmount(env, drops(checkAmount.mantissa() - 1));
575  env.require(balance(alice, reserve));
576  env.require(balance(
577  bob, startBalance + checkAmount - drops(baseFeeDrops * 2 + 1)));
578  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
579  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
580  BEAST_EXPECT(ownerCount(env, alice) == 0);
581  BEAST_EXPECT(ownerCount(env, bob) == 0);
582 
583  // Make alice's and bob's balances easy to think about.
584  env(pay(env.master, alice, checkAmount + drops(baseFeeDrops - 1)));
585  env(pay(
586  bob, env.master, checkAmount - drops(baseFeeDrops * 3 + 1)));
587  env.close();
588  env.require(balance(alice, startBalance));
589  env.require(balance(bob, startBalance));
590  }
591  }
592 
593  void
595  {
596  // Explore many of the valid ways to cash a check for an IOU.
597  testcase("Cash IOU");
598 
599  using namespace test::jtx;
600 
601  Account const gw{"gateway"};
602  Account const alice{"alice"};
603  Account const bob{"bob"};
604  IOU const USD{gw["USD"]};
605  {
606  // Simple IOU check cashed with Amount (with failures).
607  Env env{*this};
608 
609  env.fund(XRP(1000), gw, alice, bob);
610 
611  // alice writes the check before she gets the funds.
612  uint256 const chkId1{getCheckIndex(alice, env.seq(alice))};
613  env(check::create(alice, bob, USD(10)));
614  env.close();
615 
616  // bob attempts to cash the check. Should fail.
617  env(check::cash(bob, chkId1, USD(10)), ter(tecPATH_PARTIAL));
618  env.close();
619 
620  // alice gets almost enough funds. bob tries and fails again.
621  env(trust(alice, USD(20)));
622  env.close();
623  env(pay(gw, alice, USD(9.5)));
624  env.close();
625  env(check::cash(bob, chkId1, USD(10)), ter(tecPATH_PARTIAL));
626  env.close();
627 
628  // alice gets the last of the necessary funds. bob tries again
629  // and fails because he hasn't got a trust line for USD.
630  env(pay(gw, alice, USD(0.5)));
631  env.close();
632  env(check::cash(bob, chkId1, USD(10)), ter(tecNO_LINE));
633  env.close();
634 
635  // bob sets up the trust line, but not at a high enough limit.
636  env(trust(bob, USD(9.5)));
637  env.close();
638  env(check::cash(bob, chkId1, USD(10)), ter(tecPATH_PARTIAL));
639  env.close();
640 
641  // bob sets the trust line limit high enough but asks for more
642  // than the check's SendMax.
643  env(trust(bob, USD(10.5)));
644  env.close();
645  env(check::cash(bob, chkId1, USD(10.5)), ter(tecPATH_PARTIAL));
646  env.close();
647 
648  // bob asks for exactly the check amount and the check clears.
649  env(check::cash(bob, chkId1, USD(10)));
650  env.close();
651  env.require(balance(alice, USD(0)));
652  env.require(balance(bob, USD(10)));
653  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
654  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
655  BEAST_EXPECT(ownerCount(env, alice) == 1);
656  BEAST_EXPECT(ownerCount(env, bob) == 1);
657 
658  // bob tries to cash the same check again, which fails.
659  env(check::cash(bob, chkId1, USD(10)), ter(tecNO_ENTRY));
660  env.close();
661 
662  // bob pays alice USD(7) so he can try another case.
663  env(pay(bob, alice, USD(7)));
664  env.close();
665 
666  uint256 const chkId2{getCheckIndex(alice, env.seq(alice))};
667  env(check::create(alice, bob, USD(7)));
668  env.close();
669  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
670  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
671 
672  // bob cashes the check for less than the face amount. That works,
673  // consumes the check, and bob receives as much as he asked for.
674  env(check::cash(bob, chkId2, USD(5)));
675  env.close();
676  env.require(balance(alice, USD(2)));
677  env.require(balance(bob, USD(8)));
678  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
679  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
680  BEAST_EXPECT(ownerCount(env, alice) == 1);
681  BEAST_EXPECT(ownerCount(env, bob) == 1);
682 
683  // alice writes two checks for USD(2), although she only has USD(2).
684  uint256 const chkId3{getCheckIndex(alice, env.seq(alice))};
685  env(check::create(alice, bob, USD(2)));
686  env.close();
687  uint256 const chkId4{getCheckIndex(alice, env.seq(alice))};
688  env(check::create(alice, bob, USD(2)));
689  env.close();
690  BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
691  BEAST_EXPECT(checksOnAccount(env, bob).size() == 2);
692 
693  // bob cashes the second check for the face amount.
694  env(check::cash(bob, chkId4, USD(2)));
695  env.close();
696  env.require(balance(alice, USD(0)));
697  env.require(balance(bob, USD(10)));
698  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
699  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
700  BEAST_EXPECT(ownerCount(env, alice) == 2);
701  BEAST_EXPECT(ownerCount(env, bob) == 1);
702 
703  // bob is not allowed to cash the last check for USD(0), he must
704  // use check::cancel instead.
705  env(check::cash(bob, chkId3, USD(0)), ter(temBAD_AMOUNT));
706  env.close();
707  env.require(balance(alice, USD(0)));
708  env.require(balance(bob, USD(10)));
709  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
710  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
711  BEAST_EXPECT(ownerCount(env, alice) == 2);
712  BEAST_EXPECT(ownerCount(env, bob) == 1);
713 
714  // ... so bob cancels alice's remaining check.
715  env(check::cancel(bob, chkId3));
716  env.close();
717  env.require(balance(alice, USD(0)));
718  env.require(balance(bob, USD(10)));
719  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
720  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
721  BEAST_EXPECT(ownerCount(env, alice) == 1);
722  BEAST_EXPECT(ownerCount(env, bob) == 1);
723  }
724  {
725  // Simple IOU check cashed with DeliverMin (with failures).
726  Env env{*this};
727 
728  env.fund(XRP(1000), gw, alice, bob);
729 
730  env(trust(alice, USD(20)));
731  env(trust(bob, USD(20)));
732  env.close();
733  env(pay(gw, alice, USD(8)));
734  env.close();
735 
736  // alice creates several checks ahead of time.
737  uint256 const chkId9{getCheckIndex(alice, env.seq(alice))};
738  env(check::create(alice, bob, USD(9)));
739  env.close();
740  uint256 const chkId8{getCheckIndex(alice, env.seq(alice))};
741  env(check::create(alice, bob, USD(8)));
742  env.close();
743  uint256 const chkId7{getCheckIndex(alice, env.seq(alice))};
744  env(check::create(alice, bob, USD(7)));
745  env.close();
746  uint256 const chkId6{getCheckIndex(alice, env.seq(alice))};
747  env(check::create(alice, bob, USD(6)));
748  env.close();
749 
750  // bob attempts to cash a check for the amount on the check.
751  // Should fail, since alice doesn't have the funds.
752  env(check::cash(bob, chkId9, check::DeliverMin(USD(9))),
753  ter(tecPATH_PARTIAL));
754  env.close();
755 
756  // bob sets a DeliverMin of 7 and gets all that alice has.
757  env(check::cash(bob, chkId9, check::DeliverMin(USD(7))));
758  verifyDeliveredAmount(env, USD(8));
759  env.require(balance(alice, USD(0)));
760  env.require(balance(bob, USD(8)));
761  BEAST_EXPECT(checksOnAccount(env, alice).size() == 3);
762  BEAST_EXPECT(checksOnAccount(env, bob).size() == 3);
763  BEAST_EXPECT(ownerCount(env, alice) == 4);
764  BEAST_EXPECT(ownerCount(env, bob) == 1);
765 
766  // bob pays alice USD(7) so he can use another check.
767  env(pay(bob, alice, USD(7)));
768  env.close();
769 
770  // Using DeliverMin for the SendMax value of the check (and no
771  // transfer fees) should work just like setting Amount.
772  env(check::cash(bob, chkId7, check::DeliverMin(USD(7))));
773  verifyDeliveredAmount(env, USD(7));
774  env.require(balance(alice, USD(0)));
775  env.require(balance(bob, USD(8)));
776  BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
777  BEAST_EXPECT(checksOnAccount(env, bob).size() == 2);
778  BEAST_EXPECT(ownerCount(env, alice) == 3);
779  BEAST_EXPECT(ownerCount(env, bob) == 1);
780 
781  // bob pays alice USD(8) so he can use the last two checks.
782  env(pay(bob, alice, USD(8)));
783  env.close();
784 
785  // alice has USD(8). If bob uses the check for USD(6) and uses a
786  // DeliverMin of 4, he should get the SendMax value of the check.
787  env(check::cash(bob, chkId6, check::DeliverMin(USD(4))));
788  verifyDeliveredAmount(env, USD(6));
789  env.require(balance(alice, USD(2)));
790  env.require(balance(bob, USD(6)));
791  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
792  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
793  BEAST_EXPECT(ownerCount(env, alice) == 2);
794  BEAST_EXPECT(ownerCount(env, bob) == 1);
795 
796  // bob cashes the last remaining check setting a DeliverMin.
797  // of exactly alice's remaining USD.
798  env(check::cash(bob, chkId8, check::DeliverMin(USD(2))));
799  verifyDeliveredAmount(env, USD(2));
800  env.require(balance(alice, USD(0)));
801  env.require(balance(bob, USD(8)));
802  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
803  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
804  BEAST_EXPECT(ownerCount(env, alice) == 1);
805  BEAST_EXPECT(ownerCount(env, bob) == 1);
806  }
807  {
808  // Examine the effects of the asfRequireAuth flag.
809  Env env{*this};
810 
811  env.fund(XRP(1000), gw, alice, bob);
812  env(fset(gw, asfRequireAuth));
813  env.close();
814  env(trust(gw, alice["USD"](100)), txflags(tfSetfAuth));
815  env(trust(alice, USD(20)));
816  env.close();
817  env(pay(gw, alice, USD(8)));
818  env.close();
819 
820  // alice writes a check to bob for USD. bob can't cash it
821  // because he is not authorized to hold gw["USD"].
822  uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
823  env(check::create(alice, bob, USD(7)));
824  env.close();
825 
826  env(check::cash(bob, chkId, USD(7)), ter(tecNO_LINE));
827  env.close();
828 
829  // Now give bob a trustline for USD. bob still can't cash the
830  // check because he is not authorized.
831  env(trust(bob, USD(5)));
832  env.close();
833 
834  env(check::cash(bob, chkId, USD(7)), ter(tecNO_AUTH));
835  env.close();
836 
837  // bob gets authorization to hold gw["USD"].
838  env(trust(gw, bob["USD"](1)), txflags(tfSetfAuth));
839  env.close();
840 
841  // bob tries to cash the check again but fails because his trust
842  // limit is too low.
843  env(check::cash(bob, chkId, USD(7)), ter(tecPATH_PARTIAL));
844  env.close();
845 
846  // Since bob set his limit low, he cashes the check with a
847  // DeliverMin and hits his trust limit.
848  env(check::cash(bob, chkId, check::DeliverMin(USD(4))));
849  verifyDeliveredAmount(env, USD(5));
850  env.require(balance(alice, USD(3)));
851  env.require(balance(bob, USD(5)));
852  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
853  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
854  BEAST_EXPECT(ownerCount(env, alice) == 1);
855  BEAST_EXPECT(ownerCount(env, bob) == 1);
856  }
857 
858  // Use a regular key and also multisign to cash a check.
859  // featureMultiSignReserve changes the reserve on a SignerList, so
860  // check both before and after.
861  FeatureBitset const allSupported{supported_amendments()};
862  for (auto const features :
863  {allSupported - featureMultiSignReserve,
864  allSupported | featureMultiSignReserve})
865  {
866  Env env{*this, features};
867 
868  env.fund(XRP(1000), gw, alice, bob);
869 
870  // alice creates her checks ahead of time.
871  uint256 const chkId1{getCheckIndex(alice, env.seq(alice))};
872  env(check::create(alice, bob, USD(1)));
873  env.close();
874 
875  uint256 const chkId2{getCheckIndex(alice, env.seq(alice))};
876  env(check::create(alice, bob, USD(2)));
877  env.close();
878 
879  env(trust(alice, USD(20)));
880  env(trust(bob, USD(20)));
881  env.close();
882  env(pay(gw, alice, USD(8)));
883  env.close();
884 
885  // Give bob a regular key and signers
886  Account const bobby{"bobby", KeyType::secp256k1};
887  env(regkey(bob, bobby));
888  env.close();
889 
890  Account const bogie{"bogie", KeyType::secp256k1};
891  Account const demon{"demon", KeyType::ed25519};
892  env(signers(bob, 2, {{bogie, 1}, {demon, 1}}), sig(bobby));
893  env.close();
894 
895  // If featureMultiSignReserve is enabled then bob's signer list
896  // has an owner count of 1, otherwise it's 4.
897  int const signersCount{features[featureMultiSignReserve] ? 1 : 4};
898  BEAST_EXPECT(ownerCount(env, bob) == signersCount + 1);
899 
900  // bob uses his regular key to cash a check.
901  env(check::cash(bob, chkId1, (USD(1))), sig(bobby));
902  env.close();
903  env.require(balance(alice, USD(7)));
904  env.require(balance(bob, USD(1)));
905  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
906  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
907  BEAST_EXPECT(ownerCount(env, alice) == 2);
908  BEAST_EXPECT(ownerCount(env, bob) == signersCount + 1);
909 
910  // bob uses multisigning to cash a check.
911  XRPAmount const baseFeeDrops{env.current()->fees().base};
912  env(check::cash(bob, chkId2, (USD(2))),
913  msig(bogie, demon),
914  fee(3 * baseFeeDrops));
915  env.close();
916  env.require(balance(alice, USD(5)));
917  env.require(balance(bob, USD(3)));
918  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
919  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
920  BEAST_EXPECT(ownerCount(env, alice) == 1);
921  BEAST_EXPECT(ownerCount(env, bob) == signersCount + 1);
922  }
923  }
924 
925  void
927  {
928  // Look at behavior when the issuer charges a transfer fee.
929  testcase("Cash with transfer fee");
930 
931  using namespace test::jtx;
932 
933  Account const gw{"gateway"};
934  Account const alice{"alice"};
935  Account const bob{"bob"};
936  IOU const USD{gw["USD"]};
937 
938  Env env{*this};
939 
940  env.fund(XRP(1000), gw, alice, bob);
941 
942  env(trust(alice, USD(1000)));
943  env(trust(bob, USD(1000)));
944  env.close();
945  env(pay(gw, alice, USD(1000)));
946  env.close();
947 
948  // Set gw's transfer rate and see the consequences when cashing a check.
949  env(rate(gw, 1.25));
950  env.close();
951 
952  // alice writes a check with a SendMax of USD(125). The most bob
953  // can get is USD(100) because of the transfer rate.
954  uint256 const chkId125{getCheckIndex(alice, env.seq(alice))};
955  env(check::create(alice, bob, USD(125)));
956  env.close();
957 
958  // alice writes another check that won't get cashed until the transfer
959  // rate changes so we can see the rate applies when the check is
960  // cashed, not when it is created.
961  uint256 const chkId120{getCheckIndex(alice, env.seq(alice))};
962  env(check::create(alice, bob, USD(120)));
963  env.close();
964 
965  // bob attempts to cash the check for face value. Should fail.
966  env(check::cash(bob, chkId125, USD(125)), ter(tecPATH_PARTIAL));
967  env.close();
968  env(check::cash(bob, chkId125, check::DeliverMin(USD(101))),
969  ter(tecPATH_PARTIAL));
970  env.close();
971 
972  // bob decides that he'll accept anything USD(75) or up.
973  // He gets USD(100).
974  env(check::cash(bob, chkId125, check::DeliverMin(USD(75))));
975  verifyDeliveredAmount(env, USD(100));
976  env.require(balance(alice, USD(1000 - 125)));
977  env.require(balance(bob, USD(0 + 100)));
978  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
979  BEAST_EXPECT(checksOnAccount(env, bob).size() == 1);
980 
981  // Adjust gw's rate...
982  env(rate(gw, 1.2));
983  env.close();
984 
985  // bob cashes the second check for less than the face value. The new
986  // rate applies to the actual value transferred.
987  env(check::cash(bob, chkId120, USD(50)));
988  env.close();
989  env.require(balance(alice, USD(1000 - 125 - 60)));
990  env.require(balance(bob, USD(0 + 100 + 50)));
991  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
992  BEAST_EXPECT(checksOnAccount(env, bob).size() == 0);
993  }
994 
995  void
997  {
998  // Look at the eight possible cases for Quality In/Out.
999  testcase("Cash quality");
1000 
1001  using namespace test::jtx;
1002 
1003  Account const gw{"gateway"};
1004  Account const alice{"alice"};
1005  Account const bob{"bob"};
1006  IOU const USD{gw["USD"]};
1007 
1008  Env env{*this};
1009 
1010  env.fund(XRP(1000), gw, alice, bob);
1011 
1012  env(trust(alice, USD(1000)));
1013  env(trust(bob, USD(1000)));
1014  env.close();
1015  env(pay(gw, alice, USD(1000)));
1016  env.close();
1017 
1018  //
1019  // Quality effects on transfers between two non-issuers.
1020  //
1021 
1022  // Provide lambdas that return a qualityInPercent and qualityOutPercent.
1023  auto qIn = [](double percent) { return qualityInPercent(percent); };
1024  auto qOut = [](double percent) { return qualityOutPercent(percent); };
1025 
1026  // There are two test lambdas: one for a Payment and one for a Check.
1027  // This shows whether a Payment and a Check behave the same.
1028  auto testNonIssuerQPay = [&env, &alice, &bob, &USD](
1029  Account const& truster,
1030  IOU const& iou,
1031  auto const& inOrOut,
1032  double pct,
1033  double amount) {
1034  // Capture bob's and alice's balances so we can test at the end.
1035  STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1036  STAmount const bobStart{env.balance(bob, USD.issue()).value()};
1037 
1038  // Set the modified quality.
1039  env(trust(truster, iou(1000)), inOrOut(pct));
1040  env.close();
1041 
1042  env(pay(alice, bob, USD(amount)), sendmax(USD(10)));
1043  env.close();
1044  env.require(balance(alice, aliceStart - USD(10)));
1045  env.require(balance(bob, bobStart + USD(10)));
1046 
1047  // Return the quality to the unmodified state so it doesn't
1048  // interfere with upcoming tests.
1049  env(trust(truster, iou(1000)), inOrOut(0));
1050  env.close();
1051  };
1052 
1053  auto testNonIssuerQCheck = [&env, &alice, &bob, &USD](
1054  Account const& truster,
1055  IOU const& iou,
1056  auto const& inOrOut,
1057  double pct,
1058  double amount) {
1059  // Capture bob's and alice's balances so we can test at the end.
1060  STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1061  STAmount const bobStart{env.balance(bob, USD.issue()).value()};
1062 
1063  // Set the modified quality.
1064  env(trust(truster, iou(1000)), inOrOut(pct));
1065  env.close();
1066 
1067  uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
1068  env(check::create(alice, bob, USD(10)));
1069  env.close();
1070 
1071  env(check::cash(bob, chkId, USD(amount)));
1072  env.close();
1073  env.require(balance(alice, aliceStart - USD(10)));
1074  env.require(balance(bob, bobStart + USD(10)));
1075 
1076  // Return the quality to the unmodified state so it doesn't
1077  // interfere with upcoming tests.
1078  env(trust(truster, iou(1000)), inOrOut(0));
1079  env.close();
1080  };
1081 
1082  // pct amount
1083  testNonIssuerQPay(alice, gw["USD"], qIn, 50, 10);
1084  testNonIssuerQCheck(alice, gw["USD"], qIn, 50, 10);
1085 
1086  // This is the only case where the Quality affects the outcome.
1087  testNonIssuerQPay(bob, gw["USD"], qIn, 50, 5);
1088  testNonIssuerQCheck(bob, gw["USD"], qIn, 50, 5);
1089 
1090  testNonIssuerQPay(gw, alice["USD"], qIn, 50, 10);
1091  testNonIssuerQCheck(gw, alice["USD"], qIn, 50, 10);
1092 
1093  testNonIssuerQPay(gw, bob["USD"], qIn, 50, 10);
1094  testNonIssuerQCheck(gw, bob["USD"], qIn, 50, 10);
1095 
1096  testNonIssuerQPay(alice, gw["USD"], qOut, 200, 10);
1097  testNonIssuerQCheck(alice, gw["USD"], qOut, 200, 10);
1098 
1099  testNonIssuerQPay(bob, gw["USD"], qOut, 200, 10);
1100  testNonIssuerQCheck(bob, gw["USD"], qOut, 200, 10);
1101 
1102  testNonIssuerQPay(gw, alice["USD"], qOut, 200, 10);
1103  testNonIssuerQCheck(gw, alice["USD"], qOut, 200, 10);
1104 
1105  testNonIssuerQPay(gw, bob["USD"], qOut, 200, 10);
1106  testNonIssuerQCheck(gw, bob["USD"], qOut, 200, 10);
1107 
1108  //
1109  // Quality effects on transfers between an issuer and a non-issuer.
1110  //
1111 
1112  // There are two test lambdas for the same reason as before.
1113  auto testIssuerQPay = [&env, &gw, &alice, &USD](
1114  Account const& truster,
1115  IOU const& iou,
1116  auto const& inOrOut,
1117  double pct,
1118  double amt1,
1119  double max1,
1120  double amt2,
1121  double max2) {
1122  // Capture alice's balance so we can test at the end. It doesn't
1123  // make any sense to look at the balance of a gateway.
1124  STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1125 
1126  // Set the modified quality.
1127  env(trust(truster, iou(1000)), inOrOut(pct));
1128  env.close();
1129 
1130  // alice pays gw.
1131  env(pay(alice, gw, USD(amt1)), sendmax(USD(max1)));
1132  env.close();
1133  env.require(balance(alice, aliceStart - USD(10)));
1134 
1135  // gw pays alice.
1136  env(pay(gw, alice, USD(amt2)), sendmax(USD(max2)));
1137  env.close();
1138  env.require(balance(alice, aliceStart));
1139 
1140  // Return the quality to the unmodified state so it doesn't
1141  // interfere with upcoming tests.
1142  env(trust(truster, iou(1000)), inOrOut(0));
1143  env.close();
1144  };
1145 
1146  auto testIssuerQCheck = [&env, &gw, &alice, &USD](
1147  Account const& truster,
1148  IOU const& iou,
1149  auto const& inOrOut,
1150  double pct,
1151  double amt1,
1152  double max1,
1153  double amt2,
1154  double max2) {
1155  // Capture alice's balance so we can test at the end. It doesn't
1156  // make any sense to look at the balance of the issuer.
1157  STAmount const aliceStart{env.balance(alice, USD.issue()).value()};
1158 
1159  // Set the modified quality.
1160  env(trust(truster, iou(1000)), inOrOut(pct));
1161  env.close();
1162 
1163  // alice writes check to gw. gw cashes.
1164  uint256 const chkAliceId{getCheckIndex(alice, env.seq(alice))};
1165  env(check::create(alice, gw, USD(max1)));
1166  env.close();
1167 
1168  env(check::cash(gw, chkAliceId, USD(amt1)));
1169  env.close();
1170  env.require(balance(alice, aliceStart - USD(10)));
1171 
1172  // gw writes check to alice. alice cashes.
1173  uint256 const chkGwId{getCheckIndex(gw, env.seq(gw))};
1174  env(check::create(gw, alice, USD(max2)));
1175  env.close();
1176 
1177  env(check::cash(alice, chkGwId, USD(amt2)));
1178  env.close();
1179  env.require(balance(alice, aliceStart));
1180 
1181  // Return the quality to the unmodified state so it doesn't
1182  // interfere with upcoming tests.
1183  env(trust(truster, iou(1000)), inOrOut(0));
1184  env.close();
1185  };
1186 
1187  // The first case is the only one where the quality affects the outcome.
1188  // pct amt1 max1 amt2 max2
1189  testIssuerQPay(alice, gw["USD"], qIn, 50, 10, 10, 5, 10);
1190  testIssuerQCheck(alice, gw["USD"], qIn, 50, 10, 10, 5, 10);
1191 
1192  testIssuerQPay(gw, alice["USD"], qIn, 50, 10, 10, 10, 10);
1193  testIssuerQCheck(gw, alice["USD"], qIn, 50, 10, 10, 10, 10);
1194 
1195  testIssuerQPay(alice, gw["USD"], qOut, 200, 10, 10, 10, 10);
1196  testIssuerQCheck(alice, gw["USD"], qOut, 200, 10, 10, 10, 10);
1197 
1198  testIssuerQPay(gw, alice["USD"], qOut, 200, 10, 10, 10, 10);
1199  testIssuerQCheck(gw, alice["USD"], qOut, 200, 10, 10, 10, 10);
1200  }
1201 
1202  void
1204  {
1205  // Explore many of the ways to fail at cashing a check.
1206  testcase("Cash invalid");
1207 
1208  using namespace test::jtx;
1209 
1210  Account const gw{"gateway"};
1211  Account const alice{"alice"};
1212  Account const bob{"bob"};
1213  Account const zoe{"zoe"};
1214  IOU const USD{gw["USD"]};
1215 
1216  Env env{*this};
1217 
1218  env.fund(XRP(1000), gw, alice, bob, zoe);
1219 
1220  // Now set up alice's trustline.
1221  env(trust(alice, USD(20)));
1222  env.close();
1223  env(pay(gw, alice, USD(20)));
1224  env.close();
1225 
1226  // Before bob gets a trustline, have him try to cash a check.
1227  // Should fail.
1228  {
1229  uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
1230  env(check::create(alice, bob, USD(20)));
1231  env.close();
1232 
1233  env(check::cash(bob, chkId, USD(20)), ter(tecNO_LINE));
1234  env.close();
1235  }
1236 
1237  // Now set up bob's trustline.
1238  env(trust(bob, USD(20)));
1239  env.close();
1240 
1241  // bob tries to cash a non-existent check from alice.
1242  {
1243  uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
1244  env(check::cash(bob, chkId, USD(20)), ter(tecNO_ENTRY));
1245  env.close();
1246  }
1247 
1248  // alice creates her checks ahead of time.
1249  uint256 const chkIdU{getCheckIndex(alice, env.seq(alice))};
1250  env(check::create(alice, bob, USD(20)));
1251  env.close();
1252 
1253  uint256 const chkIdX{getCheckIndex(alice, env.seq(alice))};
1254  env(check::create(alice, bob, XRP(10)));
1255  env.close();
1256 
1257  using namespace std::chrono_literals;
1258  uint256 const chkIdExp{getCheckIndex(alice, env.seq(alice))};
1259  env(check::create(alice, bob, XRP(10)), expiration(env.now() + 1s));
1260  env.close();
1261 
1262  uint256 const chkIdFroz1{getCheckIndex(alice, env.seq(alice))};
1263  env(check::create(alice, bob, USD(1)));
1264  env.close();
1265 
1266  uint256 const chkIdFroz2{getCheckIndex(alice, env.seq(alice))};
1267  env(check::create(alice, bob, USD(2)));
1268  env.close();
1269 
1270  uint256 const chkIdFroz3{getCheckIndex(alice, env.seq(alice))};
1271  env(check::create(alice, bob, USD(3)));
1272  env.close();
1273 
1274  uint256 const chkIdFroz4{getCheckIndex(alice, env.seq(alice))};
1275  env(check::create(alice, bob, USD(4)));
1276  env.close();
1277 
1278  uint256 const chkIdNoDest1{getCheckIndex(alice, env.seq(alice))};
1279  env(check::create(alice, bob, USD(1)));
1280  env.close();
1281 
1282  uint256 const chkIdHasDest2{getCheckIndex(alice, env.seq(alice))};
1283  env(check::create(alice, bob, USD(2)), dest_tag(7));
1284  env.close();
1285 
1286  // Same set of failing cases for both IOU and XRP check cashing.
1287  auto failingCases = [&env, &gw, &alice, &bob](
1288  uint256 const& chkId, STAmount const& amount) {
1289  // Bad fee.
1290  env(check::cash(bob, chkId, amount),
1291  fee(drops(-10)),
1292  ter(temBAD_FEE));
1293  env.close();
1294 
1295  // Bad flags.
1296  env(check::cash(bob, chkId, amount),
1297  txflags(tfImmediateOrCancel),
1298  ter(temINVALID_FLAG));
1299  env.close();
1300 
1301  // Missing both Amount and DeliverMin.
1302  {
1303  Json::Value tx{check::cash(bob, chkId, amount)};
1305  env(tx, ter(temMALFORMED));
1306  env.close();
1307  }
1308  // Both Amount and DeliverMin present.
1309  {
1310  Json::Value tx{check::cash(bob, chkId, amount)};
1311  tx[sfDeliverMin.jsonName] = amount.getJson(JsonOptions::none);
1312  env(tx, ter(temMALFORMED));
1313  env.close();
1314  }
1315 
1316  // Negative or zero amount.
1317  {
1318  STAmount neg{amount};
1319  neg.negate();
1320  env(check::cash(bob, chkId, neg), ter(temBAD_AMOUNT));
1321  env.close();
1322  env(check::cash(bob, chkId, amount.zeroed()),
1323  ter(temBAD_AMOUNT));
1324  env.close();
1325  }
1326 
1327  // Bad currency.
1328  if (!amount.native())
1329  {
1330  Issue const badIssue{badCurrency(), amount.getIssuer()};
1331  STAmount badAmount{amount};
1332  badAmount.setIssue(Issue{badCurrency(), amount.getIssuer()});
1333  env(check::cash(bob, chkId, badAmount), ter(temBAD_CURRENCY));
1334  env.close();
1335  }
1336 
1337  // Not destination cashing check.
1338  env(check::cash(alice, chkId, amount), ter(tecNO_PERMISSION));
1339  env.close();
1340  env(check::cash(gw, chkId, amount), ter(tecNO_PERMISSION));
1341  env.close();
1342 
1343  // Currency mismatch.
1344  {
1345  IOU const wrongCurrency{gw["EUR"]};
1346  STAmount badAmount{amount};
1347  badAmount.setIssue(wrongCurrency.issue());
1348  env(check::cash(bob, chkId, badAmount), ter(temMALFORMED));
1349  env.close();
1350  }
1351 
1352  // Issuer mismatch.
1353  {
1354  IOU const wrongIssuer{alice["USD"]};
1355  STAmount badAmount{amount};
1356  badAmount.setIssue(wrongIssuer.issue());
1357  env(check::cash(bob, chkId, badAmount), ter(temMALFORMED));
1358  env.close();
1359  }
1360 
1361  // Amount bigger than SendMax.
1362  env(check::cash(bob, chkId, amount + amount), ter(tecPATH_PARTIAL));
1363  env.close();
1364 
1365  // DeliverMin bigger than SendMax.
1366  env(check::cash(bob, chkId, check::DeliverMin(amount + amount)),
1367  ter(tecPATH_PARTIAL));
1368  env.close();
1369  };
1370 
1371  failingCases(chkIdX, XRP(10));
1372  failingCases(chkIdU, USD(20));
1373 
1374  // Verify that those two checks really were cashable.
1375  env(check::cash(bob, chkIdU, USD(20)));
1376  env.close();
1377  env(check::cash(bob, chkIdX, check::DeliverMin(XRP(10))));
1378  verifyDeliveredAmount(env, XRP(10));
1379 
1380  // Try to cash an expired check.
1381  env(check::cash(bob, chkIdExp, XRP(10)), ter(tecEXPIRED));
1382  env.close();
1383 
1384  // Cancel the expired check. Anyone can cancel an expired check.
1385  env(check::cancel(zoe, chkIdExp));
1386  env.close();
1387 
1388  // Can we cash a check with frozen currency?
1389  {
1390  env(pay(bob, alice, USD(20)));
1391  env.close();
1392  env.require(balance(alice, USD(20)));
1393  env.require(balance(bob, USD(0)));
1394 
1395  // Global freeze
1396  env(fset(gw, asfGlobalFreeze));
1397  env.close();
1398 
1399  env(check::cash(bob, chkIdFroz1, USD(1)), ter(tecPATH_PARTIAL));
1400  env.close();
1401  env(check::cash(bob, chkIdFroz1, check::DeliverMin(USD(0.5))),
1402  ter(tecPATH_PARTIAL));
1403  env.close();
1404 
1405  env(fclear(gw, asfGlobalFreeze));
1406  env.close();
1407 
1408  // No longer frozen. Success.
1409  env(check::cash(bob, chkIdFroz1, USD(1)));
1410  env.close();
1411  env.require(balance(alice, USD(19)));
1412  env.require(balance(bob, USD(1)));
1413 
1414  // Freeze individual trustlines.
1415  env(trust(gw, alice["USD"](0), tfSetFreeze));
1416  env.close();
1417  env(check::cash(bob, chkIdFroz2, USD(2)), ter(tecPATH_PARTIAL));
1418  env.close();
1419  env(check::cash(bob, chkIdFroz2, check::DeliverMin(USD(1))),
1420  ter(tecPATH_PARTIAL));
1421  env.close();
1422 
1423  // Clear that freeze. Now check cashing works.
1424  env(trust(gw, alice["USD"](0), tfClearFreeze));
1425  env.close();
1426  env(check::cash(bob, chkIdFroz2, USD(2)));
1427  env.close();
1428  env.require(balance(alice, USD(17)));
1429  env.require(balance(bob, USD(3)));
1430 
1431  // Freeze bob's trustline. bob can't cash the check.
1432  env(trust(gw, bob["USD"](0), tfSetFreeze));
1433  env.close();
1434  env(check::cash(bob, chkIdFroz3, USD(3)), ter(tecFROZEN));
1435  env.close();
1436  env(check::cash(bob, chkIdFroz3, check::DeliverMin(USD(1))),
1437  ter(tecFROZEN));
1438  env.close();
1439 
1440  // Clear that freeze. Now check cashing works again.
1441  env(trust(gw, bob["USD"](0), tfClearFreeze));
1442  env.close();
1443  env(check::cash(bob, chkIdFroz3, check::DeliverMin(USD(1))));
1444  verifyDeliveredAmount(env, USD(3));
1445  env.require(balance(alice, USD(14)));
1446  env.require(balance(bob, USD(6)));
1447 
1448  // Set bob's freeze bit in the other direction. Check
1449  // cashing fails.
1450  env(trust(bob, USD(20), tfSetFreeze));
1451  env.close();
1452  env(check::cash(bob, chkIdFroz4, USD(4)), ter(terNO_LINE));
1453  env.close();
1454  env(check::cash(bob, chkIdFroz4, check::DeliverMin(USD(1))),
1455  ter(terNO_LINE));
1456  env.close();
1457 
1458  // Clear bob's freeze bit and the check should be cashable.
1459  env(trust(bob, USD(20), tfClearFreeze));
1460  env.close();
1461  env(check::cash(bob, chkIdFroz4, USD(4)));
1462  env.close();
1463  env.require(balance(alice, USD(10)));
1464  env.require(balance(bob, USD(10)));
1465  }
1466  {
1467  // Set the RequireDest flag on bob's account (after the check
1468  // was created) then cash a check without a destination tag.
1469  env(fset(bob, asfRequireDest));
1470  env.close();
1471  env(check::cash(bob, chkIdNoDest1, USD(1)), ter(tecDST_TAG_NEEDED));
1472  env.close();
1473  env(check::cash(bob, chkIdNoDest1, check::DeliverMin(USD(0.5))),
1474  ter(tecDST_TAG_NEEDED));
1475  env.close();
1476 
1477  // bob can cash a check with a destination tag.
1478  env(check::cash(bob, chkIdHasDest2, USD(2)));
1479  env.close();
1480  env.require(balance(alice, USD(8)));
1481  env.require(balance(bob, USD(12)));
1482 
1483  // Clear the RequireDest flag on bob's account so he can
1484  // cash the check with no DestinationTag.
1485  env(fclear(bob, asfRequireDest));
1486  env.close();
1487  env(check::cash(bob, chkIdNoDest1, USD(1)));
1488  env.close();
1489  env.require(balance(alice, USD(7)));
1490  env.require(balance(bob, USD(13)));
1491  }
1492  }
1493 
1494  void
1496  {
1497  // Explore many of the ways to cancel a check.
1498  testcase("Cancel valid");
1499 
1500  using namespace test::jtx;
1501 
1502  Account const gw{"gateway"};
1503  Account const alice{"alice"};
1504  Account const bob{"bob"};
1505  Account const zoe{"zoe"};
1506  IOU const USD{gw["USD"]};
1507 
1508  // featureMultiSignReserve changes the reserve on a SignerList, so
1509  // check both before and after.
1510  FeatureBitset const allSupported{supported_amendments()};
1511  for (auto const features :
1512  {allSupported - featureMultiSignReserve,
1513  allSupported | featureMultiSignReserve})
1514  {
1515  Env env{*this, features};
1516 
1517  env.fund(XRP(1000), gw, alice, bob, zoe);
1518 
1519  // alice creates her checks ahead of time.
1520  // Three ordinary checks with no expiration.
1521  uint256 const chkId1{getCheckIndex(alice, env.seq(alice))};
1522  env(check::create(alice, bob, USD(10)));
1523  env.close();
1524 
1525  uint256 const chkId2{getCheckIndex(alice, env.seq(alice))};
1526  env(check::create(alice, bob, XRP(10)));
1527  env.close();
1528 
1529  uint256 const chkId3{getCheckIndex(alice, env.seq(alice))};
1530  env(check::create(alice, bob, USD(10)));
1531  env.close();
1532 
1533  // Three checks that expire in 10 minutes.
1534  using namespace std::chrono_literals;
1535  uint256 const chkIdNotExp1{getCheckIndex(alice, env.seq(alice))};
1536  env(check::create(alice, bob, XRP(10)),
1537  expiration(env.now() + 600s));
1538  env.close();
1539 
1540  uint256 const chkIdNotExp2{getCheckIndex(alice, env.seq(alice))};
1541  env(check::create(alice, bob, USD(10)),
1542  expiration(env.now() + 600s));
1543  env.close();
1544 
1545  uint256 const chkIdNotExp3{getCheckIndex(alice, env.seq(alice))};
1546  env(check::create(alice, bob, XRP(10)),
1547  expiration(env.now() + 600s));
1548  env.close();
1549 
1550  // Three checks that expire in one second.
1551  uint256 const chkIdExp1{getCheckIndex(alice, env.seq(alice))};
1552  env(check::create(alice, bob, USD(10)), expiration(env.now() + 1s));
1553  env.close();
1554 
1555  uint256 const chkIdExp2{getCheckIndex(alice, env.seq(alice))};
1556  env(check::create(alice, bob, XRP(10)), expiration(env.now() + 1s));
1557  env.close();
1558 
1559  uint256 const chkIdExp3{getCheckIndex(alice, env.seq(alice))};
1560  env(check::create(alice, bob, USD(10)), expiration(env.now() + 1s));
1561  env.close();
1562 
1563  // Two checks to cancel using a regular key and using multisigning.
1564  uint256 const chkIdReg{getCheckIndex(alice, env.seq(alice))};
1565  env(check::create(alice, bob, USD(10)));
1566  env.close();
1567 
1568  uint256 const chkIdMSig{getCheckIndex(alice, env.seq(alice))};
1569  env(check::create(alice, bob, XRP(10)));
1570  env.close();
1571  BEAST_EXPECT(checksOnAccount(env, alice).size() == 11);
1572  BEAST_EXPECT(ownerCount(env, alice) == 11);
1573 
1574  // Creator, destination, and an outsider cancel the checks.
1575  env(check::cancel(alice, chkId1));
1576  env.close();
1577  BEAST_EXPECT(checksOnAccount(env, alice).size() == 10);
1578  BEAST_EXPECT(ownerCount(env, alice) == 10);
1579 
1580  env(check::cancel(bob, chkId2));
1581  env.close();
1582  BEAST_EXPECT(checksOnAccount(env, alice).size() == 9);
1583  BEAST_EXPECT(ownerCount(env, alice) == 9);
1584 
1585  env(check::cancel(zoe, chkId3), ter(tecNO_PERMISSION));
1586  env.close();
1587  BEAST_EXPECT(checksOnAccount(env, alice).size() == 9);
1588  BEAST_EXPECT(ownerCount(env, alice) == 9);
1589 
1590  // Creator, destination, and an outsider cancel unexpired checks.
1591  env(check::cancel(alice, chkIdNotExp1));
1592  env.close();
1593  BEAST_EXPECT(checksOnAccount(env, alice).size() == 8);
1594  BEAST_EXPECT(ownerCount(env, alice) == 8);
1595 
1596  env(check::cancel(bob, chkIdNotExp2));
1597  env.close();
1598  BEAST_EXPECT(checksOnAccount(env, alice).size() == 7);
1599  BEAST_EXPECT(ownerCount(env, alice) == 7);
1600 
1601  env(check::cancel(zoe, chkIdNotExp3), ter(tecNO_PERMISSION));
1602  env.close();
1603  BEAST_EXPECT(checksOnAccount(env, alice).size() == 7);
1604  BEAST_EXPECT(ownerCount(env, alice) == 7);
1605 
1606  // Creator, destination, and an outsider cancel expired checks.
1607  env(check::cancel(alice, chkIdExp1));
1608  env.close();
1609  BEAST_EXPECT(checksOnAccount(env, alice).size() == 6);
1610  BEAST_EXPECT(ownerCount(env, alice) == 6);
1611 
1612  env(check::cancel(bob, chkIdExp2));
1613  env.close();
1614  BEAST_EXPECT(checksOnAccount(env, alice).size() == 5);
1615  BEAST_EXPECT(ownerCount(env, alice) == 5);
1616 
1617  env(check::cancel(zoe, chkIdExp3));
1618  env.close();
1619  BEAST_EXPECT(checksOnAccount(env, alice).size() == 4);
1620  BEAST_EXPECT(ownerCount(env, alice) == 4);
1621 
1622  // Use a regular key and also multisign to cancel checks.
1623  Account const alie{"alie", KeyType::ed25519};
1624  env(regkey(alice, alie));
1625  env.close();
1626 
1627  Account const bogie{"bogie", KeyType::secp256k1};
1628  Account const demon{"demon", KeyType::ed25519};
1629  env(signers(alice, 2, {{bogie, 1}, {demon, 1}}), sig(alie));
1630  env.close();
1631 
1632  // If featureMultiSignReserve is enabled then alices's signer list
1633  // has an owner count of 1, otherwise it's 4.
1634  int const signersCount{features[featureMultiSignReserve] ? 1 : 4};
1635 
1636  // alice uses her regular key to cancel a check.
1637  env(check::cancel(alice, chkIdReg), sig(alie));
1638  env.close();
1639  BEAST_EXPECT(checksOnAccount(env, alice).size() == 3);
1640  BEAST_EXPECT(ownerCount(env, alice) == signersCount + 3);
1641 
1642  // alice uses multisigning to cancel a check.
1643  XRPAmount const baseFeeDrops{env.current()->fees().base};
1644  env(check::cancel(alice, chkIdMSig),
1645  msig(bogie, demon),
1646  fee(3 * baseFeeDrops));
1647  env.close();
1648  BEAST_EXPECT(checksOnAccount(env, alice).size() == 2);
1649  BEAST_EXPECT(ownerCount(env, alice) == signersCount + 2);
1650 
1651  // Creator and destination cancel the remaining unexpired checks.
1652  env(check::cancel(alice, chkId3), sig(alice));
1653  env.close();
1654  BEAST_EXPECT(checksOnAccount(env, alice).size() == 1);
1655  BEAST_EXPECT(ownerCount(env, alice) == signersCount + 1);
1656 
1657  env(check::cancel(bob, chkIdNotExp3));
1658  env.close();
1659  BEAST_EXPECT(checksOnAccount(env, alice).size() == 0);
1660  BEAST_EXPECT(ownerCount(env, alice) == signersCount + 0);
1661  }
1662  }
1663 
1664  void
1666  {
1667  // Explore many of the ways to fail at canceling a check.
1668  testcase("Cancel invalid");
1669 
1670  using namespace test::jtx;
1671 
1672  Account const alice{"alice"};
1673  Account const bob{"bob"};
1674 
1675  Env env{*this};
1676 
1677  env.fund(XRP(1000), alice, bob);
1678 
1679  // Bad fee.
1680  env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))),
1681  fee(drops(-10)),
1682  ter(temBAD_FEE));
1683  env.close();
1684 
1685  // Bad flags.
1686  env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))),
1687  txflags(tfImmediateOrCancel),
1688  ter(temINVALID_FLAG));
1689  env.close();
1690 
1691  // Non-existent check.
1692  env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))),
1693  ter(tecNO_ENTRY));
1694  env.close();
1695  }
1696 
1697  void
1699  {
1700  testcase("Fix1623 enable");
1701 
1702  using namespace test::jtx;
1703 
1704  auto testEnable = [this](
1705  FeatureBitset const& features, bool hasFields) {
1706  // Unless fix1623 is enabled a "tx" RPC command should return
1707  // neither "DeliveredAmount" nor "delivered_amount" on a CheckCash
1708  // transaction.
1709  Account const alice{"alice"};
1710  Account const bob{"bob"};
1711 
1712  Env env{*this, features};
1713 
1714  env.fund(XRP(1000), alice, bob);
1715  env.close();
1716 
1717  uint256 const chkId{getCheckIndex(alice, env.seq(alice))};
1718  env(check::create(alice, bob, XRP(200)));
1719  env.close();
1720 
1721  env(check::cash(bob, chkId, check::DeliverMin(XRP(100))));
1722 
1723  // Get the hash for the most recent transaction.
1724  std::string const txHash{
1725  env.tx()->getJson(JsonOptions::none)[jss::hash].asString()};
1726 
1727  // DeliveredAmount and delivered_amount are either present or
1728  // not present in the metadata returned by "tx" based on fix1623.
1729  env.close();
1730  Json::Value const meta =
1731  env.rpc("tx", txHash)[jss::result][jss::meta];
1732 
1733  BEAST_EXPECT(
1734  meta.isMember(sfDeliveredAmount.jsonName) == hasFields);
1735  BEAST_EXPECT(meta.isMember(jss::delivered_amount) == hasFields);
1736  };
1737 
1738  // Run both the disabled and enabled cases.
1739  testEnable(supported_amendments() - fix1623, false);
1740  testEnable(supported_amendments(), true);
1741  }
1742 
1743 public:
1744  void
1745  run() override
1746  {
1747  testEnabled();
1748  testCreateValid();
1750  testCashXRP();
1751  testCashIOU();
1752  testCashXferFee();
1753  testCashQuality();
1754  testCashInvalid();
1755  testCancelValid();
1758  }
1759 };
1760 
1761 BEAST_DEFINE_TESTSUITE(Check, tx, ripple);
1762 
1763 } // namespace ripple
ripple::badCurrency
Currency const & badCurrency()
We deliberately disallow the currency that looks like "XRP" because too many people were using it ins...
Definition: UintTypes.cpp:126
ripple::STAmount::negate
void negate()
Definition: STAmount.h:272
ripple::tecFROZEN
@ tecFROZEN
Definition: TER.h:261
ripple::Issue
A currency issued by an account.
Definition: Issue.h:34
std::string
STL class.
std::shared_ptr
STL class.
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
ripple::test::jtx::dest_tag
Set DestinationTag on a JTx.
Definition: Check_test.cpp:66
ripple::temBAD_CURRENCY
@ temBAD_CURRENCY
Definition: TER.h:85
ripple::test::jtx::Env::tx
std::shared_ptr< STTx const > tx() const
Return the tx data for the last JTx.
Definition: Env.cpp:352
ripple::terNO_LINE
@ terNO_LINE
Definition: TER.h:192
ripple::Check_test::testEnabled
void testEnabled()
Definition: Check_test.cpp:142
ripple::asfGlobalFreeze
const std::uint32_t asfGlobalFreeze
Definition: TxFlags.h:71
ripple::sfDeliveredAmount
const SF_Amount sfDeliveredAmount(access, STI_AMOUNT, 18, "DeliveredAmount")
Definition: SField.h:451
std::vector
STL class.
ripple::STAmount::getJson
Json::Value getJson(JsonOptions) const override
Definition: STAmount.cpp:594
ripple::test::jtx::dest_tag::dest_tag
dest_tag(std::uint32_t tag)
Definition: Check_test.cpp:72
ripple::tecDST_TAG_NEEDED
@ tecDST_TAG_NEEDED
Definition: TER.h:267
ripple::test::jtx::expiration::operator()
void operator()(Env &, JTx &jt) const
Definition: Check_test.cpp:41
ripple::featureMultiSignReserve
const uint256 featureMultiSignReserve
Definition: Feature.cpp:174
ripple::test::jtx::source_tag::tag_
const std::uint32_t tag_
Definition: Check_test.cpp:51
ripple::sfAmount
const SF_Amount sfAmount(access, STI_AMOUNT, 1, "Amount")
Definition: SField.h:437
ripple::tfClearFreeze
const std::uint32_t tfClearFreeze
Definition: TxFlags.h:95
ripple::sfOwnerCount
const SF_U32 sfOwnerCount(access, STI_UINT32, 13, "OwnerCount")
Definition: SField.h:364
ripple::SField::jsonName
const Json::StaticString jsonName
Definition: SField.h:133
ripple::sfDestinationTag
const SF_U32 sfDestinationTag(access, STI_UINT32, 14, "DestinationTag")
Definition: SField.h:365
ripple::forEachItem
void forEachItem(ReadView const &view, AccountID const &id, std::function< void(std::shared_ptr< SLE const > const &)> f)
Iterate all items in an account's owner directory.
Definition: View.cpp:251
ripple::Check_test::testCashXferFee
void testCashXferFee()
Definition: Check_test.cpp:926
ripple::KeyType::ed25519
@ ed25519
ripple::test::jtx::expiration
Set Expiration on a JTx.
Definition: Check_test.cpp:29
ripple::base_uint< 256 >
ripple::test::jtx::source_tag
Set SourceTag on a JTx.
Definition: Check_test.cpp:48
ripple::getCheckIndex
uint256 getCheckIndex(AccountID const &account, std::uint32_t uSequence)
Definition: Indexes.cpp:168
ripple::temINVALID_FLAG
@ temINVALID_FLAG
Definition: TER.h:106
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
ripple::Check_test::ownerCount
static std::uint32_t ownerCount(test::jtx::Env const &env, test::jtx::Account const &account)
Definition: Check_test.cpp:105
ripple::asfRequireAuth
const std::uint32_t asfRequireAuth
Definition: TxFlags.h:66
ripple::JsonOptions::none
@ none
ripple::Check_test::run
void run() override
Definition: Check_test.cpp:1745
ripple::test::jtx::JTx
Execution context for applying a JSON transaction.
Definition: JTx.h:41
ripple::test::jtx::dest_tag::operator()
void operator()(Env &, JTx &jt) const
Definition: Check_test.cpp:77
ripple::fix1623
const uint256 fix1623
Definition: Feature.cpp:170
ripple::Check_test::testCashXRP
void testCashXRP()
Definition: Check_test.cpp:475
ripple::STAmount
Definition: STAmount.h:42
std::chrono::time_point
ripple::temBAD_AMOUNT
@ temBAD_AMOUNT
Definition: TER.h:84
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:932
ripple::Check_test::testCashIOU
void testCashIOU()
Definition: Check_test.cpp:594
std::uint32_t
ripple::tfSetFreeze
const std::uint32_t tfSetFreeze
Definition: TxFlags.h:94
ripple::tfImmediateOrCancel
const std::uint32_t tfImmediateOrCancel
Definition: TxFlags.h:77
ripple::STAmount::setIssue
void setIssue(Issue const &issue)
Set the Issue for this amount and update mIsNative.
Definition: STAmount.cpp:424
ripple::tecPATH_PARTIAL
@ tecPATH_PARTIAL
Definition: TER.h:240
ripple::featureChecks
const uint256 featureChecks
Definition: Feature.cpp:167
ripple::Check_test::testCancelValid
void testCancelValid()
Definition: Check_test.cpp:1495
ripple::test::jtx::expiration::expry_
const std::uint32_t expry_
Definition: Check_test.cpp:32
ripple::sfSourceTag
const SF_U32 sfSourceTag(access, STI_UINT32, 3, "SourceTag")
Definition: SField.h:354
ripple::temREDUNDANT
@ temREDUNDANT
Definition: TER.h:107
ripple::temBAD_FEE
@ temBAD_FEE
Definition: TER.h:87
ripple::sfExpiration
const SF_U32 sfExpiration(access, STI_UINT32, 10, "Expiration")
Definition: SField.h:361
ripple::asfRequireDest
const std::uint32_t asfRequireDest
Definition: TxFlags.h:65
ripple::KeyType::secp256k1
@ secp256k1
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
Json::Value::removeMember
Value removeMember(const char *key)
Remove and return the named member.
Definition: json_value.cpp:907
ripple::tecNO_LINE
@ tecNO_LINE
Definition: TER.h:259
ripple::tecEXPIRED
@ tecEXPIRED
Definition: TER.h:272
ripple::sfDeliverMin
const SF_Amount sfDeliverMin(access, STI_AMOUNT, 10, "DeliverMin")
Definition: SField.h:446
ripple::Check_test::testCashInvalid
void testCashInvalid()
Definition: Check_test.cpp:1203
ripple::temDISABLED
@ temDISABLED
Definition: TER.h:109
ripple::Check_test
Definition: Check_test.cpp:86
ripple::test::jtx::Env::close
void close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:111
ripple::test::jtx::Env::le
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Definition: Env.cpp:189
ripple::Check_test::checksOnAccount
static std::vector< std::shared_ptr< SLE const > > checksOnAccount(test::jtx::Env &env, test::jtx::Account account)
Definition: Check_test.cpp:90
ripple::tecNO_PERMISSION
@ tecNO_PERMISSION
Definition: TER.h:263
ripple::FeatureBitset
Definition: Feature.h:154
ripple::tecPATH_DRY
@ tecPATH_DRY
Definition: TER.h:252
ripple::tecINSUFFICIENT_RESERVE
@ tecINSUFFICIENT_RESERVE
Definition: TER.h:265
std::size_t
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::Check_test::testCreateInvalid
void testCreateInvalid()
Definition: Check_test.cpp:291
ripple::test::jtx::source_tag::source_tag
source_tag(std::uint32_t tag)
Definition: Check_test.cpp:54
ripple::tecNO_ENTRY
@ tecNO_ENTRY
Definition: TER.h:264
ripple::Check_test::testFix1623Enable
void testFix1623Enable()
Definition: Check_test.cpp:1698
ripple::temMALFORMED
@ temMALFORMED
Definition: TER.h:82
ripple::Check_test::testCreateValid
void testCreateValid()
Definition: Check_test.cpp:192
ripple::test::jtx::expiration::expiration
expiration(NetClock::time_point const &expiry)
Definition: Check_test.cpp:35
ripple::tecNO_AUTH
@ tecNO_AUTH
Definition: TER.h:258
ripple::temBAD_EXPIRATION
@ temBAD_EXPIRATION
Definition: TER.h:86
ripple::tfSetfAuth
const std::uint32_t tfSetfAuth
Definition: TxFlags.h:91
ripple::test::jtx::dest_tag::tag_
const std::uint32_t tag_
Definition: Check_test.cpp:69
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:297
ripple::Check_test::verifyDeliveredAmount
void verifyDeliveredAmount(test::jtx::Env &env, STAmount const &amount)
Definition: Check_test.cpp:118
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:114
ripple::tecNO_DST
@ tecNO_DST
Definition: TER.h:248
ripple::test::jtx::Env::rpc
Json::Value rpc(std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition: Env.h:676
ripple::Check_test::testCashQuality
void testCashQuality()
Definition: Check_test.cpp:996
ripple::Check_test::testCancelInvalid
void testCancelInvalid()
Definition: Check_test.cpp:1665
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::XRPAmount
Definition: XRPAmount.h:46
ripple::test::jtx::source_tag::operator()
void operator()(Env &, JTx &jt) const
Definition: Check_test.cpp:59