rippled
Escrow_test.cpp
1  //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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 <test/jtx.h>
21 #include <ripple/app/tx/applySteps.h>
22 #include <ripple/ledger/Directory.h>
23 #include <ripple/protocol/Feature.h>
24 #include <ripple/protocol/Indexes.h>
25 #include <ripple/protocol/jss.h>
26 #include <ripple/protocol/TxFlags.h>
27 #include <algorithm>
28 #include <iterator>
29 
30 namespace ripple {
31 namespace test {
32 
33 struct Escrow_test : public beast::unit_test::suite
34 {
35  // A PreimageSha256 fulfillments and its associated condition.
37  {{
38  0xA0, 0x02, 0x80, 0x00
39  }};
40 
42  {{
43  0xA0, 0x25, 0x80, 0x20, 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14,
44  0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24, 0x27, 0xAE, 0x41, 0xE4,
45  0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55,
46  0x81, 0x01, 0x00
47  }};
48 
49  // Another PreimageSha256 fulfillments and its associated condition.
51  {{
52  0xA0, 0x05, 0x80, 0x03, 0x61, 0x61, 0x61
53  }};
54 
56  {{
57  0xA0, 0x25, 0x80, 0x20, 0x98, 0x34, 0x87, 0x6D, 0xCF, 0xB0, 0x5C, 0xB1,
58  0x67, 0xA5, 0xC2, 0x49, 0x53, 0xEB, 0xA5, 0x8C, 0x4A, 0xC8, 0x9B, 0x1A,
59  0xDF, 0x57, 0xF2, 0x8F, 0x2F, 0x9D, 0x09, 0xAF, 0x10, 0x7E, 0xE8, 0xF0,
60  0x81, 0x01, 0x03
61  }};
62 
63  // Another PreimageSha256 fulfillment and its associated condition.
65  {{
66  0xA0, 0x06, 0x80, 0x04, 0x6E, 0x69, 0x6B, 0x62
67  }};
68 
70  {{
71  0xA0, 0x25, 0x80, 0x20, 0x6E, 0x4C, 0x71, 0x45, 0x30, 0xC0, 0xA4, 0x26,
72  0x8B, 0x3F, 0xA6, 0x3B, 0x1B, 0x60, 0x6F, 0x2D, 0x26, 0x4A, 0x2D, 0x85,
73  0x7B, 0xE8, 0xA0, 0x9C, 0x1D, 0xFD, 0x57, 0x0D, 0x15, 0x85, 0x8B, 0xD4,
74  0x81, 0x01, 0x04
75  }};
76 
78  struct finish_time
79  {
80  private:
82 
83  public:
84  explicit
86  : value_ (value)
87  {
88  }
89 
90  void
92  {
94  }
95  };
96 
98  struct cancel_time
99  {
100  private:
102 
103  public:
104  explicit
106  : value_ (value)
107  {
108  }
109 
110  void
112  {
114  }
115  };
116 
117  struct condition
118  {
119  private:
121 
122  public:
123  explicit
125  : value_ (strHex(cond))
126  {
127  }
128 
129  template <size_t N>
131  : condition(makeSlice(c))
132  {
133  }
134 
135  void
137  {
139  }
140  };
141 
142  struct fulfillment
143  {
144  private:
146 
147  public:
148  explicit
150  : value_ (strHex(condition))
151  {
152  }
153 
154  template <size_t N>
156  : fulfillment(makeSlice(f))
157  {
158  }
159 
160  void
162  {
164  }
165  };
166 
167  static
170  jtx::Account const& account, jtx::Account const& to, STAmount const& amount)
171  {
172  using namespace jtx;
173  Json::Value jv;
174  jv[jss::TransactionType] = jss::EscrowCreate;
175  jv[jss::Flags] = tfUniversal;
176  jv[jss::Account] = account.human();
177  jv[jss::Destination] = to.human();
178  jv[jss::Amount] = amount.getJson(JsonOptions::none);
179  return jv;
180  }
181 
182  static
184  finish (jtx::Account const& account,
185  jtx::Account const& from, std::uint32_t seq)
186  {
187  Json::Value jv;
188  jv[jss::TransactionType] = jss::EscrowFinish;
189  jv[jss::Flags] = tfUniversal;
190  jv[jss::Account] = account.human();
191  jv[sfOwner.jsonName] = from.human();
193  return jv;
194  }
195 
196  static
198  cancel (jtx::Account const& account,
199  jtx::Account const& from, std::uint32_t seq)
200  {
201  Json::Value jv;
202  jv[jss::TransactionType] = jss::EscrowCancel;
203  jv[jss::Flags] = tfUniversal;
204  jv[jss::Account] = account.human();
205  jv[sfOwner.jsonName] = from.human();
207  return jv;
208  }
209 
210  void
212  {
213  testcase ("Enablement");
214 
215  using namespace jtx;
216  using namespace std::chrono;
217 
218  Env env(*this);
219  env.fund(XRP(5000), "alice", "bob");
220  env(escrow("alice", "bob", XRP(1000)), finish_time(env.now() + 1s));
221  env.close();
222 
223  auto const seq1 = env.seq("alice");
224 
225  env(escrow("alice", "bob", XRP(1000)), condition (cb1),
226  finish_time(env.now() + 1s), fee(1500));
227  env.close();
228  env(finish("bob", "alice", seq1),
229  condition(cb1), fulfillment(fb1), fee(1500));
230 
231  auto const seq2 = env.seq("alice");
232 
233  env(escrow("alice", "bob", XRP(1000)), condition(cb2),
234  finish_time(env.now() + 1s), cancel_time(env.now() + 2s), fee(1500));
235  env.close();
236  env(cancel("bob", "alice", seq2), fee(1500));
237  }
238 
239  void
241  {
242  using namespace jtx;
243  using namespace std::chrono;
244 
245  {
246  testcase("Timing: Finish Only");
247  Env env(*this);
248  env.fund(XRP(5000), "alice", "bob");
249  env.close();
250 
251  // We create an escrow that can be finished in the future
252  auto const ts = env.now() + 97s;
253 
254  auto const seq = env.seq("alice");
255  env(escrow("alice", "bob", XRP(1000)), finish_time(ts));
256 
257  // Advance the ledger, verifying that the finish won't complete
258  // prematurely.
259  for ( ; env.now() < ts; env.close())
260  env(finish("bob", "alice", seq), fee(1500), ter(tecNO_PERMISSION));
261 
262  env(finish("bob", "alice", seq), fee(1500));
263  }
264 
265  {
266  testcase("Timing: Cancel Only");
267  Env env(*this);
268  env.fund(XRP(5000), "alice", "bob");
269  env.close();
270 
271  // We create an escrow that can be cancelled in the future
272  auto const ts = env.now() + 117s;
273 
274  auto const seq = env.seq("alice");
275  env(escrow("alice", "bob", XRP(1000)), condition(cb1), cancel_time(ts));
276 
277  // Advance the ledger, verifying that the cancel won't complete
278  // prematurely.
279  for ( ; env.now() < ts; env.close())
280  env(cancel("bob", "alice", seq), fee(1500), ter(tecNO_PERMISSION));
281 
282  // Verify that a finish won't work anymore.
283  env(finish("bob", "alice", seq), condition(cb1),
285 
286  // Verify that the cancel will succeed
287  env(cancel("bob", "alice", seq), fee(1500));
288  }
289 
290  {
291  testcase("Timing: Finish and Cancel -> Finish");
292  Env env(*this);
293  env.fund(XRP(5000), "alice", "bob");
294  env.close();
295 
296  // We create an escrow that can be cancelled in the future
297  auto const fts = env.now() + 117s;
298  auto const cts = env.now() + 192s;
299 
300  auto const seq = env.seq("alice");
301  env(escrow("alice", "bob", XRP(1000)), finish_time(fts), cancel_time(cts));
302 
303  // Advance the ledger, verifying that the finish and cancel won't
304  // complete prematurely.
305  for ( ; env.now() < fts; env.close())
306  {
307  env(finish("bob", "alice", seq), fee(1500), ter(tecNO_PERMISSION));
308  env(cancel("bob", "alice", seq), fee(1500), ter(tecNO_PERMISSION));
309  }
310 
311  // Verify that a cancel still won't work
312  env(cancel("bob", "alice", seq), fee(1500), ter(tecNO_PERMISSION));
313 
314  // And verify that a finish will
315  env(finish("bob", "alice", seq), fee(1500));
316  }
317 
318  {
319  testcase("Timing: Finish and Cancel -> Cancel");
320  Env env(*this);
321  env.fund(XRP(5000), "alice", "bob");
322  env.close();
323 
324  // We create an escrow that can be cancelled in the future
325  auto const fts = env.now() + 109s;
326  auto const cts = env.now() + 184s;
327 
328  auto const seq = env.seq("alice");
329  env(escrow("alice", "bob", XRP(1000)), finish_time(fts), cancel_time(cts));
330 
331  // Advance the ledger, verifying that the finish and cancel won't
332  // complete prematurely.
333  for ( ; env.now() < fts; env.close())
334  {
335  env(finish("bob", "alice", seq), fee(1500), ter(tecNO_PERMISSION));
336  env(cancel("bob", "alice", seq), fee(1500), ter(tecNO_PERMISSION));
337  }
338 
339  // Continue advancing, verifying that the cancel won't complete
340  // prematurely. At this point a finish would succeed.
341  for ( ; env.now() < cts; env.close())
342  env(cancel("bob", "alice", seq), fee(1500), ter(tecNO_PERMISSION));
343 
344  // Verify that finish will no longer work, since we are past the
345  // cancel activation time.
346  env(finish("bob", "alice", seq), fee(1500), ter(tecNO_PERMISSION));
347 
348  // And verify that a cancel will succeed.
349  env(cancel("bob", "alice", seq), fee(1500));
350  }
351  }
352 
353  void
355  {
356  testcase ("Tags");
357 
358  using namespace jtx;
359  using namespace std::chrono;
360 
361  Env env(*this);
362 
363  auto const alice = Account("alice");
364  auto const bob = Account("bob");
365 
366  env.fund(XRP(5000), alice, bob);
367 
368  // Check to make sure that we correctly detect if tags are really
369  // required:
370  env(fset(bob, asfRequireDest));
371  env(escrow(alice, bob, XRP(1000)), finish_time(env.now() + 1s), ter(tecDST_TAG_NEEDED));
372 
373  // set source and dest tags
374  auto const seq = env.seq(alice);
375 
376  env(escrow(alice, bob, XRP(1000)), finish_time(env.now() + 1s), stag(1), dtag(2));
377 
378  auto const sle = env.le(keylet::escrow(alice.id(), seq));
379  BEAST_EXPECT(sle);
380  BEAST_EXPECT((*sle)[sfSourceTag] == 1);
381  BEAST_EXPECT((*sle)[sfDestinationTag] == 2);
382  }
383 
384  void
386  {
387  testcase ("Disallow XRP");
388 
389  using namespace jtx;
390  using namespace std::chrono;
391 
392  {
393  // Respect the "asfDisallowXRP" account flag:
395 
396  env.fund(XRP(5000), "bob", "george");
397  env(fset("george", asfDisallowXRP));
398  env(escrow("bob", "george", XRP(10)), finish_time(env.now() + 1s),
399  ter (tecNO_TARGET));
400  }
401  {
402  // Ignore the "asfDisallowXRP" account flag, which we should
403  // have been doing before.
404  Env env(*this);
405 
406  env.fund(XRP(5000), "bob", "george");
407  env(fset("george", asfDisallowXRP));
408  env(escrow("bob", "george", XRP(10)), finish_time(env.now() + 1s));
409  }
410  }
411 
412  void
414  {
415  using namespace jtx;
416  using namespace std::chrono;
417 
418  {
419  testcase ("Implied Finish Time (without fix1571)");
420 
421  Env env(*this, supported_amendments() - fix1571);
422  env.fund(XRP(5000), "alice", "bob", "carol");
423  env.close();
424 
425  // Creating an escrow without a finish time and finishing it
426  // is allowed without fix1571:
427  auto const seq1 = env.seq("alice");
428  env(escrow("alice", "bob", XRP(100)), cancel_time(env.now() + 1s), fee(1500));
429  env.close();
430  env(finish("carol", "alice", seq1), fee(1500));
431  BEAST_EXPECT (env.balance ("bob") == XRP(5100));
432 
433  env.close();
434 
435  // Creating an escrow without a finish time and a condition is
436  // also allowed without fix1571:
437  auto const seq2 = env.seq("alice");
438  env(escrow("alice", "bob", XRP(100)), cancel_time(env.now() + 1s),
439  condition(cb1), fee(1500));
440  env.close();
441  env(finish("carol", "alice", seq2), condition(cb1),
442  fulfillment(fb1), fee(1500));
443  BEAST_EXPECT (env.balance ("bob") == XRP(5200));
444  }
445 
446  {
447  testcase ("Implied Finish Time (with fix1571)");
448 
449  Env env(*this);
450  env.fund(XRP(5000), "alice", "bob", "carol");
451  env.close();
452 
453  // Creating an escrow with only a cancel time is not allowed:
454  env (escrow("alice", "bob", XRP(100)), cancel_time(env.now() + 90s),
455  fee(1500), ter(temMALFORMED));
456 
457  // Creating an escrow with only a cancel time and a condition is allowed:
458  auto const seq = env.seq("alice");
459  env (escrow("alice", "bob", XRP(100)), cancel_time(env.now() + 90s),
460  condition(cb1), fee(1500));
461  env.close();
462  env (finish("carol", "alice", seq), condition(cb1),
463  fulfillment(fb1), fee(1500));
464  BEAST_EXPECT (env.balance ("bob") == XRP(5100));
465  }
466  }
467 
468  void
470  {
471  testcase ("Failure Cases");
472 
473  using namespace jtx;
474  using namespace std::chrono;
475 
476  Env env(*this);
477  env.fund(XRP(5000), "alice", "bob");
478  env.close();
479 
480  // Finish time is in the past
481  env(escrow("alice", "bob", XRP(1000)),
482  finish_time(env.now() - 5s), ter(tecNO_PERMISSION));
483 
484  // Cancel time is in the past
485  env(escrow("alice", "bob", XRP(1000)), condition(cb1),
486  cancel_time(env.now() - 5s), ter(tecNO_PERMISSION));
487 
488  // no destination account
489  env(escrow("alice", "carol", XRP(1000)),
490  finish_time(env.now() + 1s), ter(tecNO_DST));
491 
492  env.fund(XRP(5000), "carol");
493 
494  // Using non-XRP:
495  env (escrow("alice", "carol", Account("alice")["USD"](500)),
496  finish_time(env.now() + 1s), ter(temBAD_AMOUNT));
497 
498  // Sending zero or no XRP:
499  env (escrow("alice", "carol", XRP(0)),
500  finish_time(env.now() + 1s), ter(temBAD_AMOUNT));
501  env (escrow("alice", "carol", XRP(-1000)),
502  finish_time(env.now() + 1s), ter(temBAD_AMOUNT));
503 
504  // Fail if neither CancelAfter nor FinishAfter are specified:
505  env (escrow("alice", "carol", XRP(1)), ter(temBAD_EXPIRATION));
506 
507  // Fail if neither a FinishTime nor a condition are attached:
508  env (escrow("alice", "carol", XRP(1)),
509  cancel_time(env.now() + 1s), ter(temMALFORMED));
510 
511  // Fail if FinishAfter has already passed:
512  env (escrow("alice", "carol", XRP(1)),
513  finish_time(env.now() - 1s), ter(tecNO_PERMISSION));
514 
515  // If both CancelAfter and FinishAfter are set, then CancelAfter must
516  // be strictly later than FinishAfter.
517  env(escrow("alice", "carol", XRP(1)), condition(cb1),
518  finish_time(env.now() + 10s), cancel_time(env.now() + 10s), ter(temBAD_EXPIRATION));
519 
520  env(escrow("alice", "carol", XRP(1)), condition(cb1),
521  finish_time(env.now() + 10s), cancel_time(env.now() + 5s), ter(temBAD_EXPIRATION));
522 
523  // Carol now requires the use of a destination tag
524  env(fset("carol", asfRequireDest));
525 
526  // missing destination tag
527  env(escrow("alice", "carol", XRP(1)),
529 
530  // Success!
531  env(escrow("alice", "carol", XRP(1)),
532  condition(cb1), cancel_time(env.now() + 1s), dtag(1));
533 
534  { // Fail if the sender wants to send more than he has:
535  auto const accountReserve = drops(env.current()->fees().reserve);
536  auto const accountIncrement = drops(env.current()->fees().increment);
537 
538  env.fund (accountReserve + accountIncrement + XRP(50), "daniel");
539  env(escrow("daniel", "bob", XRP(51)),
540  finish_time(env.now() + 1s), ter(tecUNFUNDED));
541 
542  env.fund (accountReserve + accountIncrement + XRP(50), "evan");
543  env(escrow("evan", "bob", XRP(50)),
544  finish_time(env.now() + 1s), ter(tecUNFUNDED));
545 
546  env.fund (accountReserve, "frank");
547  env(escrow("frank", "bob", XRP(1)),
549  }
550 
551  { // Specify incorrect sequence number
552  env.fund (XRP(5000), "hannah");
553  auto const seq = env.seq("hannah");
554  env(escrow("hannah", "hannah", XRP(10)),
555  finish_time(env.now() + 1s), fee(1500));
556  env.close();
557  env(finish ("hannah", "hannah", seq + 7), fee(1500), ter(tecNO_TARGET));
558  }
559 
560  { // Try to specify a condition for a non-conditional payment
561  env.fund (XRP(5000), "ivan");
562  auto const seq = env.seq("ivan");
563 
564  env(escrow("ivan", "ivan", XRP(10)), finish_time(env.now() + 1s));
565  env.close();
566  env(finish("ivan", "ivan", seq), condition(cb1), fulfillment(fb1),
568  }
569  }
570 
571  void
573  {
574  testcase ("Lockup");
575 
576  using namespace jtx;
577  using namespace std::chrono;
578 
579  {
580  // Unconditional
581  Env env(*this);
582  env.fund(XRP(5000), "alice", "bob");
583  auto const seq = env.seq("alice");
584  env(escrow("alice", "alice", XRP(1000)), finish_time(env.now() + 5s));
585  env.require(balance("alice", XRP(4000) - drops(10)));
586 
587  // Not enough time has elapsed for a finish and canceling isn't
588  // possible.
589  env(cancel("bob", "alice", seq), ter(tecNO_PERMISSION));
590  env(finish("bob", "alice", seq), ter(tecNO_PERMISSION));
591  env.close();
592 
593  // Cancel continues to not be possible
594  env(cancel("bob", "alice", seq), ter(tecNO_PERMISSION));
595 
596  // Finish should succeed. Verify funds.
597  env(finish("bob", "alice", seq));
598  env.require(balance("alice", XRP(5000) - drops(10)));
599  }
600  {
601  // Unconditionally pay from Alice to Bob. Zelda (neither source nor
602  // destination) signs all cancels and finishes. This shows that
603  // Escrow will make a payment to Bob with no intervention from Bob.
604  Env env(*this);
605  env.fund(XRP(5000), "alice", "bob", "zelda");
606  auto const seq = env.seq("alice");
607  env(escrow("alice", "bob", XRP(1000)), finish_time(env.now() + 5s));
608  env.require(balance("alice", XRP(4000) - drops(10)));
609 
610  // Not enough time has elapsed for a finish and canceling isn't
611  // possible.
612  env(cancel("zelda", "alice", seq), ter(tecNO_PERMISSION));
613  env(finish("zelda", "alice", seq), ter(tecNO_PERMISSION));
614  env.close();
615 
616  // Cancel continues to not be possible
617  env(cancel("zelda", "alice", seq), ter(tecNO_PERMISSION));
618 
619  // Finish should succeed. Verify funds.
620  env(finish("zelda", "alice", seq));
621  env.close();
622 
623  env.require(balance("alice", XRP(4000) - drops(10)));
624  env.require(balance("bob", XRP(6000)));
625  env.require(balance("zelda", XRP(5000) - drops(40)));
626  }
627  {
628  // Bob sets DepositAuth so only Bob can finish the escrow.
629  Env env(*this);
630 
631  env.fund(XRP(5000), "alice", "bob", "zelda");
632  env(fset ("bob", asfDepositAuth));
633  env.close();
634 
635  auto const seq = env.seq("alice");
636  env(escrow("alice", "bob", XRP(1000)), finish_time(env.now() + 5s));
637  env.require(balance("alice", XRP(4000) - drops(10)));
638 
639  // Not enough time has elapsed for a finish and canceling isn't
640  // possible.
641  env(cancel("zelda", "alice", seq), ter(tecNO_PERMISSION));
642  env(cancel("alice", "alice", seq), ter(tecNO_PERMISSION));
643  env(cancel("bob", "alice", seq), ter(tecNO_PERMISSION));
644  env(finish("zelda", "alice", seq), ter(tecNO_PERMISSION));
645  env(finish("alice", "alice", seq), ter(tecNO_PERMISSION));
646  env(finish("bob", "alice", seq), ter(tecNO_PERMISSION));
647  env.close();
648 
649  // Cancel continues to not be possible. Finish will only succeed for
650  // Bob, because of DepositAuth.
651  env(cancel("zelda", "alice", seq), ter(tecNO_PERMISSION));
652  env(cancel("alice", "alice", seq), ter(tecNO_PERMISSION));
653  env(cancel("bob", "alice", seq), ter(tecNO_PERMISSION));
654  env(finish("zelda", "alice", seq), ter(tecNO_PERMISSION));
655  env(finish("alice", "alice", seq), ter(tecNO_PERMISSION));
656  env(finish("bob", "alice", seq));
657  env.close();
658 
659  auto const baseFee = env.current()->fees().base;
660  env.require(balance("alice", XRP(4000) - (baseFee * 5)));
661  env.require(balance("bob", XRP(6000) - (baseFee * 5)));
662  env.require(balance("zelda", XRP(5000) - (baseFee * 4)));
663  }
664  {
665  // Bob sets DepositAuth but preauthorizes Zelda, so Zelda can
666  // finish the escrow.
667  Env env(*this);
668 
669  env.fund(XRP(5000), "alice", "bob", "zelda");
670  env(fset ("bob", asfDepositAuth));
671  env.close();
672  env(deposit::auth ("bob", "zelda"));
673  env.close();
674 
675  auto const seq = env.seq("alice");
676  env(escrow("alice", "bob", XRP(1000)), finish_time(env.now() + 5s));
677  env.require(balance("alice", XRP(4000) - drops(10)));
678  env.close();
679 
680  // DepositPreauth allows Finish to succeed for either Zelda or
681  // Bob. But Finish won't succeed for Alice since she is not
682  // preauthorized.
683  env(finish("alice", "alice", seq), ter(tecNO_PERMISSION));
684  env(finish("zelda", "alice", seq));
685  env.close();
686 
687  auto const baseFee = env.current()->fees().base;
688  env.require(balance("alice", XRP(4000) - (baseFee * 2)));
689  env.require(balance("bob", XRP(6000) - (baseFee * 2)));
690  env.require(balance("zelda", XRP(5000) - (baseFee * 1)));
691  }
692  {
693  // Conditional
694  Env env(*this);
695  env.fund(XRP(5000), "alice", "bob");
696  auto const seq = env.seq("alice");
697  env(escrow("alice", "alice", XRP(1000)), condition(cb2), finish_time(env.now() + 5s));
698  env.require(balance("alice", XRP(4000) - drops(10)));
699 
700  // Not enough time has elapsed for a finish and canceling isn't
701  // possible.
702  env(cancel("alice", "alice", seq), ter(tecNO_PERMISSION));
703  env(cancel("bob", "alice", seq), ter(tecNO_PERMISSION));
704  env(finish("alice", "alice", seq), ter(tecNO_PERMISSION));
705  env(finish("alice", "alice", seq),
707  env(finish("bob", "alice", seq), ter(tecNO_PERMISSION));
708  env(finish("bob", "alice", seq),
710  env.close();
711 
712  // Cancel continues to not be possible. Finish is possible but
713  // requires the fulfillment associated with the escrow.
714  env(cancel("alice", "alice", seq), ter(tecNO_PERMISSION));
715  env(cancel("bob", "alice", seq), ter(tecNO_PERMISSION));
716  env(finish("bob", "alice", seq), ter(tecCRYPTOCONDITION_ERROR));
717  env(finish("alice", "alice", seq), ter(tecCRYPTOCONDITION_ERROR));
718  env.close();
719 
720  env(finish("bob", "alice", seq),
721  condition(cb2), fulfillment(fb2), fee(1500));
722  }
723  {
724  // Self-escrowed conditional with DepositAuth.
725  Env env(*this);
726 
727  env.fund(XRP(5000), "alice", "bob");
728  auto const seq = env.seq("alice");
729  env(escrow("alice", "alice", XRP(1000)), condition(cb3), finish_time(env.now() + 5s));
730  env.require(balance("alice", XRP(4000) - drops(10)));
731  env.close();
732 
733  // Finish is now possible but requires the cryptocondition.
734  env(finish("bob", "alice", seq), ter(tecCRYPTOCONDITION_ERROR));
735  env(finish("alice", "alice", seq), ter(tecCRYPTOCONDITION_ERROR));
736 
737  // Enable deposit authorization. After this only Alice can finish
738  // the escrow.
739  env(fset ("alice", asfDepositAuth));
740  env.close();
741 
742  env(finish("alice", "alice", seq), condition(cb2),
744  env(finish("bob", "alice", seq), condition(cb3),
746  env(finish("alice", "alice", seq), condition(cb3),
747  fulfillment(fb3), fee(1500));
748  }
749  {
750  // Self-escrowed conditional with DepositAuth and DepositPreauth.
751  Env env(*this);
752 
753  env.fund(XRP(5000), "alice", "bob", "zelda");
754  auto const seq = env.seq("alice");
755  env(escrow("alice", "alice", XRP(1000)), condition(cb3), finish_time(env.now() + 5s));
756  env.require(balance("alice", XRP(4000) - drops(10)));
757  env.close();
758 
759  // Alice preauthorizes Zelda for deposit, even though Alice has not
760  // set the lsfDepositAuth flag (yet).
761  env(deposit::auth("alice", "zelda"));
762  env.close();
763 
764  // Finish is now possible but requires the cryptocondition.
765  env(finish("alice", "alice", seq), ter(tecCRYPTOCONDITION_ERROR));
766  env(finish("bob", "alice", seq), ter(tecCRYPTOCONDITION_ERROR));
767  env(finish("zelda", "alice", seq), ter(tecCRYPTOCONDITION_ERROR));
768 
769  // Alice enables deposit authorization. After this only Alice or
770  // Zelda (because Zelda is preauthorized) can finish the escrow.
771  env(fset ("alice", asfDepositAuth));
772  env.close();
773 
774  env(finish("alice", "alice", seq), condition(cb2),
776  env(finish("bob", "alice", seq), condition(cb3),
778  env(finish("zelda", "alice", seq), condition(cb3),
779  fulfillment(fb3), fee(1500));
780  }
781  }
782 
783  void
785  {
786  testcase ("Escrow with CryptoConditions");
787 
788  using namespace jtx;
789  using namespace std::chrono;
790 
791  { // Test cryptoconditions
792  Env env(*this);
793  env.fund(XRP(5000), "alice", "bob", "carol");
794  auto const seq = env.seq("alice");
795  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 0);
796  env(escrow("alice", "carol", XRP(1000)), condition(cb1),
797  cancel_time(env.now() + 1s));
798  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
799  env.require(balance("alice", XRP(4000) - drops(10)));
800  env.require(balance("carol", XRP(5000)));
801  env(cancel("bob", "alice", seq), ter(tecNO_PERMISSION));
802  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
803 
804  // Attempt to finish without a fulfillment
805  env(finish("bob", "alice", seq), ter(tecCRYPTOCONDITION_ERROR));
806  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
807 
808  // Attempt to finish with a condition instead of a fulfillment
809  env(finish("bob", "alice", seq), condition(cb1),
811  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
812  env(finish("bob", "alice", seq), condition(cb1),
814  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
815  env(finish("bob", "alice", seq), condition(cb1),
817  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
818 
819  // Attempt to finish with an incorrect condition and various
820  // combinations of correct and incorrect fulfillments.
821  env(finish("bob", "alice", seq), condition(cb2),
823  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
824  env(finish("bob", "alice", seq), condition(cb2),
826  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
827  env(finish("bob", "alice", seq), condition(cb2),
829  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
830 
831  // Attempt to finish with the correct condition & fulfillment
832  env(finish("bob", "alice", seq), condition(cb1),
833  fulfillment(fb1), fee(1500));
834 
835  // SLE removed on finish
836  BEAST_EXPECT(! env.le(keylet::escrow(Account("alice").id(), seq)));
837  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 0);
838  env.require(balance("carol", XRP(6000)));
839  env(cancel("bob", "alice", seq), ter(tecNO_TARGET));
840  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 0);
841  env(cancel("bob", "carol", 1), ter(tecNO_TARGET));
842  }
843  { // Test cancel when condition is present
844  Env env(*this);
845  env.fund(XRP(5000), "alice", "bob", "carol");
846  auto const seq = env.seq("alice");
847  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 0);
848  env(escrow("alice", "carol", XRP(1000)), condition(cb2),
849  cancel_time(env.now() + 1s));
850  env.close();
851  env.require(balance("alice", XRP(4000) - drops(10)));
852  // balance restored on cancel
853  env(cancel("bob", "alice", seq));
854  env.require(balance("alice", XRP(5000) - drops(10)));
855  // SLE removed on cancel
856  BEAST_EXPECT(! env.le(keylet::escrow(Account("alice").id(), seq)));
857  }
858  {
859  Env env(*this);
860  env.fund(XRP(5000), "alice", "bob", "carol");
861  env.close();
862  auto const seq = env.seq("alice");
863  env(escrow("alice", "carol", XRP(1000)), condition(cb3),
864  cancel_time(env.now() + 1s));
865  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
866  // cancel fails before expiration
867  env(cancel("bob", "alice", seq), ter(tecNO_PERMISSION));
868  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
869  env.close();
870  // finish fails after expiration
871  env(finish("bob", "alice", seq), condition(cb3),
873  BEAST_EXPECT((*env.le("alice"))[sfOwnerCount] == 1);
874  env.require(balance("carol", XRP(5000)));
875  }
876  { // Test long & short conditions during creation
877  Env env(*this);
878  env.fund(XRP(5000), "alice", "bob", "carol");
879 
881  v.resize(cb1.size() + 2, 0x78);
882  std::memcpy (v.data() + 1, cb1.data(), cb1.size());
883 
884  auto const p = v.data();
885  auto const s = v.size();
886 
887  auto const ts = env.now() + 1s;
888 
889  // All these are expected to fail, because the
890  // condition we pass in is malformed in some way
891  env(escrow("alice", "carol", XRP(1000)), condition(Slice{p, s}),
893  env(escrow("alice", "carol", XRP(1000)), condition(Slice{p, s - 1}),
895  env(escrow("alice", "carol", XRP(1000)), condition(Slice{p, s - 2}),
897  env(escrow("alice", "carol", XRP(1000)), condition(Slice{p + 1, s - 1}),
899  env(escrow("alice", "carol", XRP(1000)), condition(Slice{p + 1, s - 3}),
901  env(escrow("alice", "carol", XRP(1000)), condition(Slice{p + 2, s - 2}),
903  env(escrow("alice", "carol", XRP(1000)), condition(Slice{p + 2, s - 3}),
905 
906  auto const seq = env.seq("alice");
907  env(escrow("alice", "carol", XRP(1000)), condition(Slice{p + 1, s - 2}),
908  cancel_time(ts), fee(100));
909  env(finish("bob", "alice", seq),
910  condition(cb1), fulfillment(fb1), fee(1500));
911  env.require(balance("alice", XRP(4000) - drops(100)));
912  env.require(balance("bob", XRP(5000) - drops(1500)));
913  env.require(balance("carol", XRP(6000)));
914  }
915  { // Test long and short conditions & fulfillments during finish
916  Env env(*this);
917  env.fund(XRP(5000), "alice", "bob", "carol");
918 
920  cv.resize(cb2.size() + 2, 0x78);
921  std::memcpy (cv.data() + 1, cb2.data(), cb2.size());
922 
923  auto const cp = cv.data();
924  auto const cs = cv.size();
925 
927  fv.resize(fb2.size() + 2, 0x13);
928  std::memcpy(fv.data() + 1, fb2.data(), fb2.size());
929 
930  auto const fp = fv.data();
931  auto const fs = fv.size();
932 
933  auto const ts = env.now() + 1s;
934 
935  // All these are expected to fail, because the
936  // condition we pass in is malformed in some way
937  env(escrow("alice", "carol", XRP(1000)), condition(Slice{cp, cs}),
939  env(escrow("alice", "carol", XRP(1000)), condition(Slice{cp, cs - 1}),
941  env(escrow("alice", "carol", XRP(1000)), condition(Slice{cp, cs - 2}),
943  env(escrow("alice", "carol", XRP(1000)), condition(Slice{cp + 1, cs - 1}),
945  env(escrow("alice", "carol", XRP(1000)), condition(Slice{cp + 1, cs - 3}),
947  env(escrow("alice", "carol", XRP(1000)), condition(Slice{cp + 2, cs - 2}),
949  env(escrow("alice", "carol", XRP(1000)), condition(Slice{cp + 2, cs - 3}),
951 
952  auto const seq = env.seq("alice");
953  env(escrow("alice", "carol", XRP(1000)), condition(Slice{cp + 1, cs - 2}),
954  cancel_time(ts), fee(100));
955 
956  // Now, try to fulfill using the same sequence of
957  // malformed conditions.
958  env(finish("bob", "alice", seq), condition(Slice{cp, cs}), fulfillment(Slice{fp, fs}),
960  env(finish("bob", "alice", seq), condition(Slice{cp, cs - 1}), fulfillment(Slice{fp, fs}),
962  env(finish("bob", "alice", seq), condition(Slice{cp, cs - 2}), fulfillment(Slice{fp, fs}),
964  env(finish("bob", "alice", seq), condition(Slice{cp + 1, cs - 1}), fulfillment(Slice{fp, fs}),
966  env(finish("bob", "alice", seq), condition(Slice{cp + 1, cs - 3}), fulfillment(Slice{fp, fs}),
968  env(finish("bob", "alice", seq), condition(Slice{cp + 2, cs - 2}), fulfillment(Slice{fp, fs}),
970  env(finish("bob", "alice", seq), condition(Slice{cp + 2, cs - 3}), fulfillment(Slice{fp, fs}),
972 
973  // Now, using the correct condition, try malformed fulfillments:
974  env(finish("bob", "alice", seq), condition(Slice{cp + 1, cs - 2}),
975  fulfillment(Slice{fp, fs}), fee(1500), ter(tecCRYPTOCONDITION_ERROR));
976  env(finish("bob", "alice", seq), condition(Slice{cp + 1, cs - 2}),
977  fulfillment(Slice{fp, fs - 1}), fee(1500), ter(tecCRYPTOCONDITION_ERROR));
978  env(finish("bob", "alice", seq), condition(Slice{cp + 1, cs - 2}),
979  fulfillment(Slice{fp, fs - 2}), fee(1500), ter(tecCRYPTOCONDITION_ERROR));
980  env(finish("bob", "alice", seq), condition(Slice{cp + 1, cs - 2}),
981  fulfillment(Slice{fp + 1, fs - 1}), fee(1500), ter(tecCRYPTOCONDITION_ERROR));
982  env(finish("bob", "alice", seq), condition(Slice{cp + 1, cs - 2}),
983  fulfillment(Slice{fp + 1, fs - 3}), fee(1500), ter(tecCRYPTOCONDITION_ERROR));
984  env(finish("bob", "alice", seq), condition(Slice{cp + 1, cs - 2}),
985  fulfillment(Slice{fp + 1, fs - 3}), fee(1500), ter(tecCRYPTOCONDITION_ERROR));
986  env(finish("bob", "alice", seq), condition(Slice{cp + 1, cs - 2}),
987  fulfillment(Slice{fp + 2, fs - 2}), fee(1500), ter(tecCRYPTOCONDITION_ERROR));
988  env(finish("bob", "alice", seq), condition(Slice{cp + 1, cs - 2}),
989  fulfillment(Slice{fp + 2, fs - 3}), fee(1500), ter(tecCRYPTOCONDITION_ERROR));
990 
991  // Now try for the right one
992  env(finish("bob", "alice", seq), condition(cb2),
993  fulfillment(fb2), fee(1500));
994  env.require(balance("alice", XRP(4000) - drops(100)));
995  env.require(balance("carol", XRP(6000)));
996  }
997  { // Test empty condition during creation and
998  // empty condition & fulfillment during finish
999  Env env(*this);
1000  env.fund(XRP(5000), "alice", "bob", "carol");
1001 
1002  env(escrow("alice", "carol", XRP(1000)), condition(Slice{}),
1003  cancel_time(env.now() + 1s), ter(temMALFORMED));
1004 
1005  auto const seq = env.seq("alice");
1006  env(escrow("alice", "carol", XRP(1000)),
1007  condition(cb3), cancel_time(env.now() + 1s));
1008 
1009  env(finish("bob", "alice", seq), condition(Slice{}),
1011  env(finish("bob", "alice", seq), condition(cb3),
1013  env(finish("bob", "alice", seq), condition(Slice{}),
1015 
1016  // Assemble finish that is missing the Condition or the Fulfillment
1017  // since either both must be present, or neither can:
1018  env (finish("bob", "alice", seq), condition(cb3), ter(temMALFORMED));
1019  env (finish("bob", "alice", seq), fulfillment(fb3), ter(temMALFORMED));
1020 
1021  // Now finish it.
1022  env(finish("bob", "alice", seq), condition(cb3),
1023  fulfillment(fb3), fee(1500));
1024  env.require(balance ("carol", XRP(6000)));
1025  env.require(balance ("alice", XRP(4000) - drops(10)));
1026  }
1027  { // Test a condition other than PreimageSha256, which
1028  // would require a separate amendment
1029  Env env(*this);
1030  env.fund(XRP(5000), "alice", "bob");
1031 
1033  {{
1034  0xA2, 0x2B, 0x80, 0x20, 0x42, 0x4A, 0x70, 0x49, 0x49, 0x52,
1035  0x92, 0x67, 0xB6, 0x21, 0xB3, 0xD7, 0x91, 0x19, 0xD7, 0x29,
1036  0xB2, 0x38, 0x2C, 0xED, 0x8B, 0x29, 0x6C, 0x3C, 0x02, 0x8F,
1037  0xA9, 0x7D, 0x35, 0x0F, 0x6D, 0x07, 0x81, 0x03, 0x06, 0x34,
1038  0xD2, 0x82, 0x02, 0x03, 0xC8
1039  }};
1040 
1041  // FIXME: this transaction should, eventually, return temDISABLED
1042  // instead of temMALFORMED.
1043  env(escrow("alice", "bob", XRP(1000)), condition(cb),
1044  cancel_time(env.now() + 1s), ter(temMALFORMED));
1045  }
1046  }
1047 
1048  void
1050  {
1051  using namespace jtx;
1052  using namespace std::chrono;
1053 
1054  auto const alice = Account("alice");
1055  auto const bruce = Account("bruce");
1056  auto const carol = Account("carol");
1057 
1058  {
1059  testcase ("Metadata to self");
1060 
1061  Env env(*this);
1062  env.fund(XRP(5000), alice, bruce, carol);
1063  auto const aseq = env.seq(alice);
1064  auto const bseq = env.seq(bruce);
1065 
1066  env(escrow(alice, alice, XRP(1000)),
1067  finish_time(env.now() + 1s), cancel_time(env.now() + 500s));
1068  BEAST_EXPECT((*env.meta())[sfTransactionResult] ==
1069  static_cast<std::uint8_t>(tesSUCCESS));
1070  env.close(5s);
1071  auto const aa = env.le(keylet::escrow(alice.id(), aseq));
1072  BEAST_EXPECT(aa);
1073 
1074  {
1075  ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id()));
1076  BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1);
1077  BEAST_EXPECT(std::find(aod.begin(), aod.end(), aa) != aod.end());
1078  }
1079 
1080  env(escrow(bruce, bruce, XRP(1000)),
1081  finish_time(env.now() + 1s), cancel_time(env.now() + 2s));
1082  BEAST_EXPECT((*env.meta())[sfTransactionResult] ==
1083  static_cast<std::uint8_t>(tesSUCCESS));
1084  env.close(5s);
1085  auto const bb = env.le(keylet::escrow(bruce.id(), bseq));
1086  BEAST_EXPECT(bb);
1087 
1088  {
1089  ripple::Dir bod(*env.current(), keylet::ownerDir(bruce.id()));
1090  BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1);
1091  BEAST_EXPECT(std::find(bod.begin(), bod.end(), bb) != bod.end());
1092  }
1093 
1094  env.close(5s);
1095  env(finish(alice, alice, aseq));
1096  {
1097  BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq)));
1098  BEAST_EXPECT((*env.meta())[sfTransactionResult] ==
1099  static_cast<std::uint8_t>(tesSUCCESS));
1100 
1101  ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id()));
1102  BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 0);
1103  BEAST_EXPECT(std::find(aod.begin(), aod.end(), aa) == aod.end());
1104 
1105  ripple::Dir bod(*env.current(), keylet::ownerDir(bruce.id()));
1106  BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1);
1107  BEAST_EXPECT(std::find(bod.begin(), bod.end(), bb) != bod.end());
1108  }
1109 
1110  env.close(5s);
1111  env(cancel(bruce, bruce, bseq));
1112  {
1113  BEAST_EXPECT(!env.le(keylet::escrow(bruce.id(), bseq)));
1114  BEAST_EXPECT((*env.meta())[sfTransactionResult] ==
1115  static_cast<std::uint8_t>(tesSUCCESS));
1116 
1117  ripple::Dir bod(*env.current(), keylet::ownerDir(bruce.id()));
1118  BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 0);
1119  BEAST_EXPECT(std::find(bod.begin(), bod.end(), bb) == bod.end());
1120  }
1121  }
1122  {
1123  testcase ("Metadata to other");
1124 
1125  Env env(*this);
1126  env.fund(XRP(5000), alice, bruce, carol);
1127  auto const aseq = env.seq(alice);
1128  auto const bseq = env.seq(bruce);
1129 
1130  env(escrow(alice, bruce, XRP(1000)), finish_time(env.now() + 1s));
1131  BEAST_EXPECT((*env.meta())[sfTransactionResult] ==
1132  static_cast<std::uint8_t>(tesSUCCESS));
1133  env.close(5s);
1134  env(escrow(bruce, carol, XRP(1000)),
1135  finish_time(env.now() + 1s), cancel_time(env.now() + 2s));
1136  BEAST_EXPECT((*env.meta())[sfTransactionResult] ==
1137  static_cast<std::uint8_t>(tesSUCCESS));
1138  env.close(5s);
1139 
1140  auto const ab = env.le(keylet::escrow(alice.id(), aseq));
1141  BEAST_EXPECT(ab);
1142 
1143  auto const bc = env.le(keylet::escrow(bruce.id(), bseq));
1144  BEAST_EXPECT(bc);
1145 
1146  {
1147  ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id()));
1148  BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 1);
1149  BEAST_EXPECT(std::find(aod.begin(), aod.end(), ab) != aod.end());
1150 
1151  ripple::Dir bod(*env.current(), keylet::ownerDir(bruce.id()));
1152  BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 2);
1153  BEAST_EXPECT(std::find(bod.begin(), bod.end(), ab) != bod.end());
1154  BEAST_EXPECT(std::find(bod.begin(), bod.end(), bc) != bod.end());
1155 
1156  ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id()));
1157  BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1);
1158  BEAST_EXPECT(std::find(cod.begin(), cod.end(), bc) != cod.end());
1159  }
1160 
1161  env.close(5s);
1162  env(finish(alice, alice, aseq));
1163  {
1164  BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq)));
1165  BEAST_EXPECT(env.le(keylet::escrow(bruce.id(), bseq)));
1166 
1167  ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id()));
1168  BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 0);
1169  BEAST_EXPECT(std::find(aod.begin(), aod.end(), ab) == aod.end());
1170 
1171  ripple::Dir bod(*env.current(), keylet::ownerDir(bruce.id()));
1172  BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 1);
1173  BEAST_EXPECT(std::find(bod.begin(), bod.end(), ab) == bod.end());
1174  BEAST_EXPECT(std::find(bod.begin(), bod.end(), bc) != bod.end());
1175 
1176  ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id()));
1177  BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 1);
1178  }
1179 
1180  env.close(5s);
1181  env(cancel(bruce, bruce, bseq));
1182  {
1183  BEAST_EXPECT(!env.le(keylet::escrow(alice.id(), aseq)));
1184  BEAST_EXPECT(!env.le(keylet::escrow(bruce.id(), bseq)));
1185 
1186  ripple::Dir aod(*env.current(), keylet::ownerDir(alice.id()));
1187  BEAST_EXPECT(std::distance(aod.begin(), aod.end()) == 0);
1188  BEAST_EXPECT(std::find(aod.begin(), aod.end(), ab) == aod.end());
1189 
1190  ripple::Dir bod(*env.current(), keylet::ownerDir(bruce.id()));
1191  BEAST_EXPECT(std::distance(bod.begin(), bod.end()) == 0);
1192  BEAST_EXPECT(std::find(bod.begin(), bod.end(), ab) == bod.end());
1193  BEAST_EXPECT(std::find(bod.begin(), bod.end(), bc) == bod.end());
1194 
1195  ripple::Dir cod(*env.current(), keylet::ownerDir(carol.id()));
1196  BEAST_EXPECT(std::distance(cod.begin(), cod.end()) == 0);
1197  }
1198  }
1199  }
1200 
1202  {
1203  testcase ("Consequences");
1204 
1205  using namespace jtx;
1206  using namespace std::chrono;
1207  Env env(*this);
1208 
1209  env.memoize("alice");
1210  env.memoize("bob");
1211  env.memoize("carol");
1212 
1213  {
1214  auto const jtx = env.jt(escrow("alice", "carol", XRP(1000)),
1215  finish_time(env.now() + 1s), seq(1), fee(10));
1216  auto const pf = preflight(env.app(), env.current()->rules(),
1217  *jtx.stx, tapNONE, env.journal);
1218  BEAST_EXPECT(pf.ter == tesSUCCESS);
1219  auto const conseq = calculateConsequences(pf);
1220  BEAST_EXPECT(conseq.category == TxConsequences::normal);
1221  BEAST_EXPECT(conseq.fee == drops(10));
1222  BEAST_EXPECT(conseq.potentialSpend == XRP(1000));
1223  }
1224 
1225  {
1226  auto const jtx = env.jt(cancel("bob", "alice", 3), seq(1), fee(10));
1227  auto const pf = preflight(env.app(), env.current()->rules(),
1228  *jtx.stx, tapNONE, env.journal);
1229  BEAST_EXPECT(pf.ter == tesSUCCESS);
1230  auto const conseq = calculateConsequences(pf);
1231  BEAST_EXPECT(conseq.category == TxConsequences::normal);
1232  BEAST_EXPECT(conseq.fee == drops(10));
1233  BEAST_EXPECT(conseq.potentialSpend == XRP(0));
1234  }
1235 
1236  {
1237  auto const jtx = env.jt(finish("bob", "alice", 3), seq(1), fee(10));
1238  auto const pf = preflight(env.app(), env.current()->rules(),
1239  *jtx.stx, tapNONE, env.journal);
1240  BEAST_EXPECT(pf.ter == tesSUCCESS);
1241  auto const conseq = calculateConsequences(pf);
1242  BEAST_EXPECT(conseq.category == TxConsequences::normal);
1243  BEAST_EXPECT(conseq.fee == drops(10));
1244  BEAST_EXPECT(conseq.potentialSpend == XRP(0));
1245  }
1246  }
1247 
1248  void run() override
1249  {
1250  testEnablement();
1251  testTiming();
1252  testTags();
1253  testDisallowXRP();
1254  test1571();
1255  testFails();
1256  testLockup();
1259  testConsequences();
1260  }
1261 };
1262 
1263 BEAST_DEFINE_TESTSUITE(Escrow,app,ripple);
1264 
1265 } // test
1266 } // ripple
std::vector::resize
T resize(T... args)
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:109
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:199
ripple::tecNO_TARGET
@ tecNO_TARGET
Definition: TER.h:269
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
ripple::Dir::begin
const_iterator begin() const
Definition: Directory.cpp:37
std::string
STL class.
ripple::test::Escrow_test::testDisallowXRP
void testDisallowXRP()
Definition: Escrow_test.cpp:385
ripple::test::Escrow_test::escrow
static Json::Value escrow(jtx::Account const &account, jtx::Account const &to, STAmount const &amount)
Definition: Escrow_test.cpp:169
ripple::test::jtx::drops
PrettyAmount drops(Integer i)
Returns an XRP PrettyAmount, which is trivially convertible to STAmount.
Definition: amount.h:261
ripple::test::Escrow_test::cb3
const std::array< std::uint8_t, 39 > cb3
Definition: Escrow_test.cpp:69
ripple::test::jtx::ter
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition: ter.h:33
ripple::test::jtx::Env::require
void require(Args const &... args)
Check a set of requirements.
Definition: Env.h:461
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:43
ripple::test::jtx::balance
A balance matches.
Definition: balance.h:38
std::vector
STL class.
std::find
T find(T... args)
std::array::size
T size(T... args)
ripple::STAmount::getJson
Json::Value getJson(JsonOptions) const override
Definition: STAmount.cpp:582
ripple::test::jtx::Env::jt
JTx jt(JsonValue &&jv, FN const &... fN)
Create a JTx from parameters.
Definition: Env.h:431
ripple::featureDepositAuth
const uint256 featureDepositAuth
Definition: Feature.cpp:164
ripple::test::Escrow_test::fb3
const std::array< std::uint8_t, 8 > fb3
Definition: Escrow_test.cpp:64
ripple::tecDST_TAG_NEEDED
@ tecDST_TAG_NEEDED
Definition: TER.h:274
iterator
ripple::TxConsequences::normal
@ normal
Moves currency around, creates offers, etc.
Definition: applySteps.h:134
ripple::test::Escrow_test::testFails
void testFails()
Definition: Escrow_test.cpp:469
ripple::test::Escrow_test::finish
static Json::Value finish(jtx::Account const &account, jtx::Account const &from, std::uint32_t seq)
Definition: Escrow_test.cpp:184
ripple::test::jtx::Account::human
std::string const & human() const
Returns the human readable public key.
Definition: Account.h:104
ripple::test::jtx::Env::journal
const beast::Journal journal
Definition: Env.h:143
ripple::test::Escrow_test::condition::condition
condition(Slice cond)
Definition: Escrow_test.cpp:124
std::distance
T distance(T... args)
ripple::asfDepositAuth
const std::uint32_t asfDepositAuth
Definition: TxFlags.h:73
ripple::asfDisallowXRP
const std::uint32_t asfDisallowXRP
Definition: TxFlags.h:67
ripple::test::jtx::Env::balance
PrettyAmount balance(Account const &account) const
Returns the XRP balance on an account.
Definition: Env.cpp:162
ripple::test::Escrow_test::fulfillment::value_
std::string value_
Definition: Escrow_test.cpp:145
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:237
ripple::preflight
PreflightResult preflight(Application &app, Rules const &rules, STTx const &tx, ApplyFlags flags, beast::Journal j)
Gate a transaction based on static information.
Definition: applySteps.cpp:266
ripple::test::Escrow_test::testMetaAndOwnership
void testMetaAndOwnership()
Definition: Escrow_test.cpp:1049
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:33
ripple::sfOwnerCount
const SF_U32 sfOwnerCount(access, STI_UINT32, 13, "OwnerCount")
Definition: SField.h:349
ripple::SField::jsonName
const Json::StaticString jsonName
Definition: SField.h:140
ripple::sfFinishAfter
const SF_U32 sfFinishAfter(access, STI_UINT32, 37, "FinishAfter")
Definition: SField.h:374
algorithm
ripple::test::Escrow_test::cancel
static Json::Value cancel(jtx::Account const &account, jtx::Account const &from, std::uint32_t seq)
Definition: Escrow_test.cpp:198
ripple::test::Escrow_test::cancel_time::value_
NetClock::time_point value_
Definition: Escrow_test.cpp:101
ripple::sfDestinationTag
const SF_U32 sfDestinationTag(access, STI_UINT32, 14, "DestinationTag")
Definition: SField.h:350
ripple::test::jtx::stag
Set the source tag on a JTx.
Definition: tag.h:48
ripple::test::Escrow_test::testTags
void testTags()
Definition: Escrow_test.cpp:354
ripple::test::Escrow_test::cb2
const std::array< std::uint8_t, 39 > cb2
Definition: Escrow_test.cpp:55
ripple::test::Escrow_test::finish_time
Set the "FinishAfter" time tag on a JTx.
Definition: Escrow_test.cpp:78
ripple::sfFulfillment
const SF_Blob sfFulfillment(access, STI_VL, 16, "Fulfillment")
Definition: SField.h:455
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
ripple::test::jtx::Env::meta
std::shared_ptr< STObject const > meta()
Return metadata for the last JTx.
Definition: Env.cpp:362
ripple::sfOwner
const SF_Account sfOwner(access, STI_ACCOUNT, 2, "Owner")
Definition: SField.h:461
ripple::test::Escrow_test::fulfillment::operator()
void operator()(jtx::Env &, jtx::JTx &jt) const
Definition: Escrow_test.cpp:161
ripple::test::Escrow_test::condition::condition
condition(std::array< std::uint8_t, N > c)
Definition: Escrow_test.cpp:130
ripple::JsonOptions::none
@ none
ripple::test::Escrow_test::cancel_time
Set the "CancelAfter" time tag on a JTx.
Definition: Escrow_test.cpp:98
ripple::test::jtx::JTx
Execution context for applying a JSON transaction.
Definition: JTx.h:41
ripple::test::jtx::JTx::jv
Json::Value jv
Definition: JTx.h:43
ripple::test::Escrow_test::testTiming
void testTiming()
Definition: Escrow_test.cpp:240
ripple::test::jtx::fset
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Definition: flags.cpp:28
ripple::keylet::ownerDir
Keylet ownerDir(AccountID const &id)
The root page of an account's directory.
Definition: Indexes.cpp:318
ripple::tecUNFUNDED
@ tecUNFUNDED
Definition: TER.h:260
ripple::keylet::escrow
Keylet escrow(AccountID const &source, std::uint32_t seq)
An escrow entry.
Definition: Indexes.cpp:339
ripple::test::Escrow_test::fulfillment::fulfillment
fulfillment(Slice condition)
Definition: Escrow_test.cpp:149
ripple::test::Escrow_test::finish_time::finish_time
finish_time(NetClock::time_point const &value)
Definition: Escrow_test.cpp:85
std::array< std::uint8_t, 4 >
ripple::STAmount
Definition: STAmount.h:42
ripple::test::Escrow_test::run
void run() override
Definition: Escrow_test.cpp:1248
std::chrono::time_point
ripple::temBAD_AMOUNT
@ temBAD_AMOUNT
Definition: TER.h:87
ripple::test::Escrow_test::cb1
const std::array< std::uint8_t, 39 > cb1
Definition: Escrow_test.cpp:41
ripple::test::jtx::supported_amendments
FeatureBitset supported_amendments()
Definition: Env.h:71
std::uint32_t
ripple::test::Escrow_test::finish_time::operator()
void operator()(jtx::Env &, jtx::JTx &jt) const
Definition: Escrow_test.cpp:91
ripple::test::jtx::Env::seq
std::uint32_t seq(Account const &account) const
Returns the next sequence number on account.
Definition: Env.cpp:192
ripple::sfSourceTag
const SF_U32 sfSourceTag(access, STI_UINT32, 3, "SourceTag")
Definition: SField.h:339
ripple::tfUniversal
const std::uint32_t tfUniversal
Definition: TxFlags.h:49
ripple::asfRequireDest
const std::uint32_t asfRequireDest
Definition: TxFlags.h:65
ripple::test::jtx::fee
Set the fee on a JTx.
Definition: fee.h:34
ripple::test::jtx::seq
Set the sequence number on a JTx.
Definition: seq.h:32
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::Escrow_test::condition::value_
std::string value_
Definition: Escrow_test.cpp:120
ripple::calculateConsequences
TxConsequences calculateConsequences(PreflightResult const &preflightResult)
Determine the XRP balance consequences if a transaction consumes the maximum XRP allowed.
Definition: applySteps.cpp:325
ripple::test::jtx::Env::now
NetClock::time_point now()
Returns the current Ripple Network Time.
Definition: Env.h:260
ripple::sfOfferSequence
const SF_U32 sfOfferSequence(access, STI_UINT32, 25, "OfferSequence")
Definition: SField.h:362
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:114
ripple::test::Escrow_test::condition::operator()
void operator()(jtx::Env &, jtx::JTx &jt) const
Definition: Escrow_test.cpp:136
ripple::test::Escrow_test::test1571
void test1571()
Definition: Escrow_test.cpp:413
ripple::test::Escrow_test::condition
Definition: Escrow_test.cpp:117
ripple::test::Escrow_test::fulfillment::fulfillment
fulfillment(std::array< std::uint8_t, N > f)
Definition: Escrow_test.cpp:155
ripple::test::Escrow_test::fb1
const std::array< std::uint8_t, 4 > fb1
Definition: Escrow_test.cpp:36
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:214
ripple::test::jtx::Env::le
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Definition: Env.cpp:202
ripple::test::Escrow_test::fb2
const std::array< std::uint8_t, 7 > fb2
Definition: Escrow_test.cpp:50
ripple::tecNO_PERMISSION
@ tecNO_PERMISSION
Definition: TER.h:270
ripple::sfCondition
const SF_Blob sfCondition(access, STI_VL, 17, "Condition")
Definition: SField.h:456
ripple::Dir
Definition: Directory.h:28
ripple::sfTransactionResult
const SF_U8 sfTransactionResult(access, STI_UINT8, 3, "TransactionResult")
Definition: SField.h:326
ripple::test::Escrow_test::testConsequences
void testConsequences()
Definition: Escrow_test.cpp:1201
ripple::test::Escrow_test::testLockup
void testLockup()
Definition: Escrow_test.cpp:572
ripple::tecINSUFFICIENT_RESERVE
@ tecINSUFFICIENT_RESERVE
Definition: TER.h:272
std::memcpy
T memcpy(T... args)
ripple::test::Escrow_test
Definition: Escrow_test.cpp:33
ripple::test::jtx::dtag
Set the destination tag on a JTx.
Definition: tag.h:31
ripple::test::Escrow_test::testEscrowConditions
void testEscrowConditions()
Definition: Escrow_test.cpp:784
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::test::Escrow_test::testEnablement
void testEnablement()
Definition: Escrow_test.cpp:211
ripple::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:70
ripple::test::Escrow_test::cancel_time::cancel_time
cancel_time(NetClock::time_point const &value)
Definition: Escrow_test.cpp:105
ripple::temMALFORMED
@ temMALFORMED
Definition: TER.h:85
ripple::Dir::end
const_iterator end() const
Definition: Directory.cpp:56
ripple::fix1571
const uint256 fix1571
Definition: Feature.cpp:166
ripple::test::Escrow_test::fulfillment
Definition: Escrow_test.cpp:142
ripple::temBAD_EXPIRATION
@ temBAD_EXPIRATION
Definition: TER.h:89
ripple::test::Escrow_test::cancel_time::operator()
void operator()(jtx::Env &, jtx::JTx &jt) const
Definition: Escrow_test.cpp:111
ripple::test::jtx::Env::memoize
void memoize(Account const &account)
Associate AccountID with account.
Definition: Env.cpp:135
ripple::test::Escrow_test::finish_time::value_
NetClock::time_point value_
Definition: Escrow_test.cpp:81
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:219
std::vector::data
T data(T... args)
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:296
ripple::sfCancelAfter
const SF_U32 sfCancelAfter(access, STI_UINT32, 36, "CancelAfter")
Definition: SField.h:373
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:117
ripple::tecNO_DST
@ tecNO_DST
Definition: TER.h:255
Json::Value
Represents a JSON value.
Definition: json_value.h:141
ripple::tecCRYPTOCONDITION_ERROR
@ tecCRYPTOCONDITION_ERROR
Definition: TER.h:277
std::chrono