rippled
PayStrand_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  Permission to use, copy, modify, and/or distribute this software for any
6  purpose with or without fee is hereby granted, provided that the above
7  copyright notice and this permission notice appear in all copies.
8  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16 //==============================================================================
17 
18 #include <ripple/app/paths/Flow.h>
19 #include <ripple/app/paths/RippleCalc.h>
20 #include <ripple/app/paths/impl/Steps.h>
21 #include <ripple/basics/contract.h>
22 #include <ripple/basics/safe_cast.h>
23 #include <ripple/core/Config.h>
24 #include <ripple/ledger/ApplyViewImpl.h>
25 #include <ripple/ledger/PaymentSandbox.h>
26 #include <ripple/ledger/Sandbox.h>
27 #include <ripple/protocol/Feature.h>
28 #include <ripple/protocol/jss.h>
29 #include <test/jtx.h>
30 #include <test/jtx/PathSet.h>
31 
32 namespace ripple {
33 namespace test {
34 
36 {
40 };
41 
43 {
45 };
46 
47 enum class TrustFlag { freeze, auth, noripple };
48 
49 /*constexpr*/ std::uint32_t
50 trustFlag(TrustFlag f, bool useHigh)
51 {
52  switch (f)
53  {
54  case TrustFlag::freeze:
55  if (useHigh)
56  return lsfHighFreeze;
57  return lsfLowFreeze;
58  case TrustFlag::auth:
59  if (useHigh)
60  return lsfHighAuth;
61  return lsfLowAuth;
63  if (useHigh)
64  return lsfHighNoRipple;
65  return lsfLowNoRipple;
66  }
67  return 0; // Silence warning about end of non-void function
68 }
69 
70 bool
72  jtx::Env const& env,
73  jtx::Account const& src,
74  jtx::Account const& dst,
75  Currency const& cur,
76  TrustFlag flag)
77 {
78  if (auto sle = env.le(keylet::line(src, dst, cur)))
79  {
80  auto const useHigh = src.id() > dst.id();
81  return sle->isFlag(trustFlag(flag, useHigh));
82  }
83  Throw<std::runtime_error>("No line in getTrustFlag");
84  return false; // silence warning
85 }
86 
87 bool
89 {
90  if (!s1)
91  return false;
92  return test::directStepEqual(*s1, dsi.src, dsi.dst, dsi.currency);
93 }
94 
95 bool
97 {
98  if (!s1)
99  return false;
100  return test::xrpEndpointStepEqual(*s1, xrpsi.acc);
101 }
102 
103 bool
105 {
106  if (!s1)
107  return false;
108  return bookStepEqual(*s1, bsi);
109 }
110 
111 template <class Iter>
112 bool
114 {
115  // base case. all args processed and found equal.
116  return true;
117 }
118 
119 template <class Iter, class StepInfo, class... Args>
120 bool
121 strandEqualHelper(Iter i, StepInfo&& si, Args&&... args)
122 {
123  if (!equal(*i, std::forward<StepInfo>(si)))
124  return false;
125  return strandEqualHelper(++i, std::forward<Args>(args)...);
126 }
127 
128 template <class... Args>
129 bool
130 equal(Strand const& strand, Args&&... args)
131 {
132  if (strand.size() != sizeof...(Args))
133  return false;
134  if (strand.empty())
135  return true;
136  return strandEqualHelper(strand.begin(), std::forward<Args>(args)...);
137 }
138 
140 ape(AccountID const& a)
141 {
142  return STPathElement(
144 };
145 
146 // Issue path element
148 ipe(Issue const& iss)
149 {
150  return STPathElement(
152  xrpAccount(),
153  iss.currency,
154  iss.account);
155 };
156 
157 // Issuer path element
159 iape(AccountID const& account)
160 {
161  return STPathElement(
163 };
164 
165 // Currency path element
167 cpe(Currency const& c)
168 {
169  return STPathElement(
171 };
172 
173 // All path element
175 allpe(AccountID const& a, Issue const& iss)
176 {
177  return STPathElement(
180  a,
181  iss.currency,
182  iss.account);
183 };
184 
186 {
187  enum class SB /*state bit*/
188  : std::uint16_t {
189  acc,
190  iss,
191  cur,
192  rootAcc,
193  rootIss,
194  xrp,
195  sameAccIss,
196  existingAcc,
197  existingCur,
198  existingIss,
199  prevAcc,
200  prevCur,
201  prevIss,
202  boundary,
203  last
204  };
205 
207  static_assert(
208  safe_cast<size_t>(SB::last) <= sizeof(decltype(state_)) * 8,
209  "");
210  STPathElement const* prev_ = nullptr;
211  // disallow iss and cur to be specified with acc is specified (simplifies
212  // some tests)
213  bool const allowCompound_ = false;
214 
215  bool
216  has(SB s) const
217  {
218  return state_ & (1 << safe_cast<int>(s));
219  }
220 
221  bool
223  {
224  for (auto const s : sb)
225  if (has(s))
226  return true;
227  return false;
228  }
229 
230  size_t
232  {
233  size_t result = 0;
234 
235  for (auto const s : sb)
236  if (has(s))
237  result++;
238  return result;
239  }
240 
241 public:
242  explicit ElementComboIter(STPathElement const* prev = nullptr) : prev_(prev)
243  {
244  }
245 
246  bool
247  valid() const
248  {
249  return (allowCompound_ ||
250  !(has(SB::acc) && hasAny({SB::cur, SB::iss}))) &&
252  (!hasAny(
254  has(SB::acc)) &&
255  (!hasAny(
257  has(SB::iss)) &&
259  has(SB::cur)) &&
260  // These will be duplicates
264  }
265  bool
267  {
268  if (!(has(SB::last)))
269  {
270  do
271  {
272  ++state_;
273  } while (!valid());
274  }
275  return !has(SB::last);
276  }
277 
278  template <
279  class Col,
280  class AccFactory,
281  class IssFactory,
282  class CurrencyFactory>
283  void
285  Col& col,
286  AccFactory&& accF,
287  IssFactory&& issF,
288  CurrencyFactory&& currencyF,
289  std::optional<AccountID> const& existingAcc,
290  std::optional<Currency> const& existingCur,
291  std::optional<AccountID> const& existingIss)
292  {
293  assert(!has(SB::last));
294 
295  auto const acc = [&]() -> std::optional<AccountID> {
296  if (!has(SB::acc))
297  return std::nullopt;
298  if (has(SB::rootAcc))
299  return xrpAccount();
300  if (has(SB::existingAcc) && existingAcc)
301  return existingAcc;
302  return accF().id();
303  }();
304  auto const iss = [&]() -> std::optional<AccountID> {
305  if (!has(SB::iss))
306  return std::nullopt;
307  if (has(SB::rootIss))
308  return xrpAccount();
309  if (has(SB::sameAccIss))
310  return acc;
311  if (has(SB::existingIss) && existingIss)
312  return *existingIss;
313  return issF().id();
314  }();
315  auto const cur = [&]() -> std::optional<Currency> {
316  if (!has(SB::cur))
317  return std::nullopt;
318  if (has(SB::xrp))
319  return xrpCurrency();
320  if (has(SB::existingCur) && existingCur)
321  return *existingCur;
322  return currencyF();
323  }();
324  if (!has(SB::boundary))
325  col.emplace_back(acc, cur, iss);
326  else
327  col.emplace_back(
328  STPathElement::Type::typeBoundary,
329  acc.value_or(AccountID{}),
330  cur.value_or(Currency{}),
331  iss.value_or(AccountID{}));
332  }
333 };
334 
336 {
340 
342  getAccount(size_t id)
343  {
344  assert(id < accounts.size());
345  return accounts[id];
346  }
347 
349  getCurrency(size_t id)
350  {
351  assert(id < currencies.size());
352  return currencies[id];
353  }
354 
355  // ids from 0 through (nextAvail -1) have already been used in the
356  // path
357  size_t nextAvailAccount = 0;
358  size_t nextAvailCurrency = 0;
359 
361  ResetState
363  {
365  }
366 
367  void
368  resetTo(ResetState const& s)
369  {
371  }
372 
373  struct StateGuard
374  {
377 
379  : p_{p}, state_{p.getResetState()}
380  {
381  }
383  {
384  p_.resetTo(state_);
385  }
386  };
387 
388  // Create the given number of accounts, and add trust lines so every
389  // account trusts every other with every currency
390  // Create an offer from every currency/account to every other
391  // currency/account; the offer owner is either the specified
392  // account or the issuer of the "taker gets" account
393  void
395  jtx::Env& env,
396  size_t numAct,
397  size_t numCur,
398  std::optional<size_t> const& offererIndex)
399  {
400  using namespace jtx;
401 
402  assert(!offererIndex || offererIndex < numAct);
403 
404  accounts.clear();
405  accounts.reserve(numAct);
406  currencies.clear();
407  currencies.reserve(numCur);
409  currencyNames.reserve(numCur);
410 
411  constexpr size_t bufSize = 32;
412  char buf[bufSize];
413 
414  for (size_t id = 0; id < numAct; ++id)
415  {
416  snprintf(buf, bufSize, "A%zu", id);
417  accounts.emplace_back(buf);
418  }
419 
420  for (size_t id = 0; id < numCur; ++id)
421  {
422  if (id < 10)
423  snprintf(buf, bufSize, "CC%zu", id);
424  else if (id < 100)
425  snprintf(buf, bufSize, "C%zu", id);
426  else
427  snprintf(buf, bufSize, "%zu", id);
428  currencies.emplace_back(to_currency(buf));
430  }
431 
432  for (auto const& a : accounts)
433  env.fund(XRP(100000), a);
434 
435  // Every account trusts every other account with every currency
436  for (auto ai1 = accounts.begin(), aie = accounts.end(); ai1 != aie;
437  ++ai1)
438  {
439  for (auto ai2 = accounts.begin(); ai2 != aie; ++ai2)
440  {
441  if (ai1 == ai2)
442  continue;
443  for (auto const& cn : currencyNames)
444  {
445  env.trust((*ai1)[cn](1'000'000), *ai2);
446  if (ai1 > ai2)
447  {
448  // accounts with lower indexes hold balances from
449  // accounts
450  // with higher indexes
451  auto const& src = *ai1;
452  auto const& dst = *ai2;
453  env(pay(src, dst, src[cn](500000)));
454  }
455  }
456  env.close();
457  }
458  }
459 
460  std::vector<IOU> ious;
461  ious.reserve(numAct * numCur);
462  for (auto const& a : accounts)
463  for (auto const& cn : currencyNames)
464  ious.emplace_back(a[cn]);
465 
466  // create offers from every currency to every other currency
467  for (auto takerPays = ious.begin(), ie = ious.end(); takerPays != ie;
468  ++takerPays)
469  {
470  for (auto takerGets = ious.begin(); takerGets != ie; ++takerGets)
471  {
472  if (takerPays == takerGets)
473  continue;
474  auto const owner =
475  offererIndex ? accounts[*offererIndex] : takerGets->account;
476  if (owner.id() != takerGets->account.id())
477  env(pay(takerGets->account, owner, (*takerGets)(1000)));
478 
479  env(offer(owner, (*takerPays)(1000), (*takerGets)(1000)),
480  txflags(tfPassive));
481  }
482  env.close();
483  }
484 
485  // create offers to/from xrp to every other ious
486  for (auto const& iou : ious)
487  {
488  auto const owner =
489  offererIndex ? accounts[*offererIndex] : iou.account;
490  env(offer(owner, iou(1000), XRP(1000)), txflags(tfPassive));
491  env(offer(owner, XRP(1000), iou(1000)), txflags(tfPassive));
492  env.close();
493  }
494  }
495 
497  totalXRP(ReadView const& v, bool incRoot)
498  {
500  auto add = [&](auto const& a) {
501  // XRP balance
502  auto const sle = v.read(keylet::account(a));
503  if (!sle)
504  return;
505  auto const b = (*sle)[sfBalance];
506  totalXRP += b.mantissa();
507  };
508  for (auto const& a : accounts)
509  add(a);
510  if (incRoot)
511  add(xrpAccount());
512  return totalXRP;
513  }
514 
515  // Check that the balances for all accounts for all currencies & XRP are the
516  // same
517  bool
518  checkBalances(ReadView const& v1, ReadView const& v2)
519  {
521 
522  auto xrpBalance = [](ReadView const& v, ripple::Keylet const& k) {
523  auto const sle = v.read(k);
524  if (!sle)
525  return STAmount{};
526  return (*sle)[sfBalance];
527  };
528  auto lineBalance = [](ReadView const& v, ripple::Keylet const& k) {
529  auto const sle = v.read(k);
530  if (!sle)
531  return STAmount{};
532  return (*sle)[sfBalance];
533  };
534  std::uint64_t totalXRP[2]{};
535  for (auto ai1 = accounts.begin(), aie = accounts.end(); ai1 != aie;
536  ++ai1)
537  {
538  {
539  // XRP balance
540  auto const ak = keylet::account(*ai1);
541  auto const b1 = xrpBalance(v1, ak);
542  auto const b2 = xrpBalance(v2, ak);
543  totalXRP[0] += b1.mantissa();
544  totalXRP[1] += b2.mantissa();
545  if (b1 != b2)
546  diffs.emplace_back(b1, b2, xrpAccount(), *ai1);
547  }
548  for (auto ai2 = accounts.begin(); ai2 != aie; ++ai2)
549  {
550  if (ai1 >= ai2)
551  continue;
552  for (auto const& c : currencies)
553  {
554  // Line balance
555  auto const lk = keylet::line(*ai1, *ai2, c);
556  auto const b1 = lineBalance(v1, lk);
557  auto const b2 = lineBalance(v2, lk);
558  if (b1 != b2)
559  diffs.emplace_back(b1, b2, *ai1, *ai2);
560  }
561  }
562  }
563  return diffs.empty();
564  }
565 
568  {
569  return getAccount(nextAvailAccount++);
570  }
571 
574  {
575  return getCurrency(nextAvailCurrency++);
576  }
577 
578  template <class F>
579  void
581  STAmount const& sendMax,
582  STAmount const& deliver,
583  std::vector<STPathElement> const& prefix,
584  std::vector<STPathElement> const& suffix,
585  std::optional<AccountID> const& existingAcc,
586  std::optional<Currency> const& existingCur,
587  std::optional<AccountID> const& existingIss,
588  F&& f)
589  {
590  auto accF = [&] { return this->getAvailAccount(); };
591  auto issF = [&] { return this->getAvailAccount(); };
592  auto currencyF = [&] { return this->getAvailCurrency(); };
593 
594  STPathElement const* prevOuter =
595  prefix.empty() ? nullptr : &prefix.back();
596  ElementComboIter outer(prevOuter);
597 
598  std::vector<STPathElement> outerResult;
600  auto const resultSize = prefix.size() + suffix.size() + 2;
601  outerResult.reserve(resultSize);
602  result.reserve(resultSize);
603  while (outer.next())
604  {
605  StateGuard og{*this};
606  outerResult = prefix;
607  outer.emplace_into(
608  outerResult,
609  accF,
610  issF,
611  currencyF,
612  existingAcc,
613  existingCur,
614  existingIss);
615  STPathElement const* prevInner = &outerResult.back();
616  ElementComboIter inner(prevInner);
617  while (inner.next())
618  {
619  StateGuard ig{*this};
620  result = outerResult;
621  inner.emplace_into(
622  result,
623  accF,
624  issF,
625  currencyF,
626  existingAcc,
627  existingCur,
628  existingIss);
629  result.insert(result.end(), suffix.begin(), suffix.end());
630  f(sendMax, deliver, result);
631  }
632  };
633  }
634 };
635 
636 struct PayStrand_test : public beast::unit_test::suite
637 {
638  void
640  {
641  testcase("To Strand");
642 
643  using namespace jtx;
644 
645  auto const alice = Account("alice");
646  auto const bob = Account("bob");
647  auto const carol = Account("carol");
648  auto const gw = Account("gw");
649 
650  auto const USD = gw["USD"];
651  auto const EUR = gw["EUR"];
652 
653  auto const eurC = EUR.currency;
654  auto const usdC = USD.currency;
655 
656  using D = DirectStepInfo;
657  using B = ripple::Book;
658  using XRPS = XRPEndpointStepInfo;
659 
660  auto test = [&, this](
661  jtx::Env& env,
662  Issue const& deliver,
663  std::optional<Issue> const& sendMaxIssue,
664  STPath const& path,
665  TER expTer,
666  auto&&... expSteps) {
667  auto [ter, strand] = toStrand(
668  *env.current(),
669  alice,
670  bob,
671  deliver,
672  std::nullopt,
673  sendMaxIssue,
674  path,
675  true,
676  false,
677  env.app().logs().journal("Flow"));
678  BEAST_EXPECT(ter == expTer);
679  if (sizeof...(expSteps) != 0)
680  BEAST_EXPECT(equal(
681  strand, std::forward<decltype(expSteps)>(expSteps)...));
682  };
683 
684  {
685  Env env(*this, features);
686  env.fund(XRP(10000), alice, bob, gw);
687  env.trust(USD(1000), alice, bob);
688  env.trust(EUR(1000), alice, bob);
689  env(pay(gw, alice, EUR(100)));
690 
691  {
692  STPath const path =
693  STPath({ipe(bob["USD"]), cpe(EUR.currency)});
694  auto [ter, _] = toStrand(
695  *env.current(),
696  alice,
697  alice,
698  /*deliver*/ xrpIssue(),
699  /*limitQuality*/ std::nullopt,
700  /*sendMaxIssue*/ EUR.issue(),
701  path,
702  true,
703  false,
704  env.app().logs().journal("Flow"));
705  (void)_;
706  BEAST_EXPECT(ter == tesSUCCESS);
707  }
708  {
709  STPath const path = STPath({ipe(USD), cpe(xrpCurrency())});
710  auto [ter, _] = toStrand(
711  *env.current(),
712  alice,
713  alice,
714  /*deliver*/ xrpIssue(),
715  /*limitQuality*/ std::nullopt,
716  /*sendMaxIssue*/ EUR.issue(),
717  path,
718  true,
719  false,
720  env.app().logs().journal("Flow"));
721  (void)_;
722  BEAST_EXPECT(ter == tesSUCCESS);
723  }
724  }
725 
726  {
727  Env env(*this, features);
728  env.fund(XRP(10000), alice, bob, carol, gw);
729 
730  test(env, USD, std::nullopt, STPath(), terNO_LINE);
731 
732  env.trust(USD(1000), alice, bob, carol);
733  test(env, USD, std::nullopt, STPath(), tecPATH_DRY);
734 
735  env(pay(gw, alice, USD(100)));
736  env(pay(gw, carol, USD(100)));
737 
738  // Insert implied account
739  test(
740  env,
741  USD,
742  std::nullopt,
743  STPath(),
744  tesSUCCESS,
745  D{alice, gw, usdC},
746  D{gw, bob, usdC});
747  env.trust(EUR(1000), alice, bob);
748 
749  // Insert implied offer
750  test(
751  env,
752  EUR,
753  USD.issue(),
754  STPath(),
755  tesSUCCESS,
756  D{alice, gw, usdC},
757  B{USD, EUR},
758  D{gw, bob, eurC});
759 
760  // Path with explicit offer
761  test(
762  env,
763  EUR,
764  USD.issue(),
765  STPath({ipe(EUR)}),
766  tesSUCCESS,
767  D{alice, gw, usdC},
768  B{USD, EUR},
769  D{gw, bob, eurC});
770 
771  // Path with offer that changes issuer only
772  env.trust(carol["USD"](1000), bob);
773  test(
774  env,
775  carol["USD"],
776  USD.issue(),
777  STPath({iape(carol)}),
778  tesSUCCESS,
779  D{alice, gw, usdC},
780  B{USD, carol["USD"]},
781  D{carol, bob, usdC});
782 
783  // Path with XRP src currency
784  test(
785  env,
786  USD,
787  xrpIssue(),
788  STPath({ipe(USD)}),
789  tesSUCCESS,
790  XRPS{alice},
791  B{XRP, USD},
792  D{gw, bob, usdC});
793 
794  // Path with XRP dst currency.
795  test(
796  env,
797  xrpIssue(),
798  USD.issue(),
801  xrpAccount(),
802  xrpCurrency(),
803  xrpAccount()}}),
804  tesSUCCESS,
805  D{alice, gw, usdC},
806  B{USD, XRP},
807  XRPS{bob});
808 
809  // Path with XRP cross currency bridged payment
810  test(
811  env,
812  EUR,
813  USD.issue(),
814  STPath({cpe(xrpCurrency())}),
815  tesSUCCESS,
816  D{alice, gw, usdC},
817  B{USD, XRP},
818  B{XRP, EUR},
819  D{gw, bob, eurC});
820 
821  // XRP -> XRP transaction can't include a path
822  test(env, XRP, std::nullopt, STPath({ape(carol)}), temBAD_PATH);
823 
824  {
825  // The root account can't be the src or dst
826  auto flowJournal = env.app().logs().journal("Flow");
827  {
828  // The root account can't be the dst
829  auto r = toStrand(
830  *env.current(),
831  alice,
832  xrpAccount(),
833  XRP,
834  std::nullopt,
835  USD.issue(),
836  STPath(),
837  true,
838  false,
839  flowJournal);
840  BEAST_EXPECT(r.first == temBAD_PATH);
841  }
842  {
843  // The root account can't be the src
844  auto r = toStrand(
845  *env.current(),
846  xrpAccount(),
847  alice,
848  XRP,
849  std::nullopt,
850  std::nullopt,
851  STPath(),
852  true,
853  false,
854  flowJournal);
855  BEAST_EXPECT(r.first == temBAD_PATH);
856  }
857  {
858  // The root account can't be the src.
859  auto r = toStrand(
860  *env.current(),
861  noAccount(),
862  bob,
863  USD,
864  std::nullopt,
865  std::nullopt,
866  STPath(),
867  true,
868  false,
869  flowJournal);
870  BEAST_EXPECT(r.first == temBAD_PATH);
871  }
872  }
873 
874  // Create an offer with the same in/out issue
875  test(
876  env,
877  EUR,
878  USD.issue(),
879  STPath({ipe(USD), ipe(EUR)}),
880  temBAD_PATH);
881 
882  // Path element with type zero
883  test(
884  env,
885  USD,
886  std::nullopt,
888  0, xrpAccount(), xrpCurrency(), xrpAccount())}),
889  temBAD_PATH);
890 
891  // The same account can't appear more than once on a path
892  // `gw` will be used from alice->carol and implied between carol
893  // and bob
894  test(
895  env,
896  USD,
897  std::nullopt,
898  STPath({ape(gw), ape(carol)}),
900 
901  // The same offer can't appear more than once on a path
902  test(
903  env,
904  EUR,
905  USD.issue(),
906  STPath({ipe(EUR), ipe(USD), ipe(EUR)}),
908  }
909 
910  {
911  // cannot have more than one offer with the same output issue
912 
913  using namespace jtx;
914  Env env(*this, features);
915 
916  env.fund(XRP(10000), alice, bob, carol, gw);
917  env.trust(USD(10000), alice, bob, carol);
918  env.trust(EUR(10000), alice, bob, carol);
919 
920  env(pay(gw, bob, USD(100)));
921  env(pay(gw, bob, EUR(100)));
922 
923  env(offer(bob, XRP(100), USD(100)));
924  env(offer(bob, USD(100), EUR(100)), txflags(tfPassive));
925  env(offer(bob, EUR(100), USD(100)), txflags(tfPassive));
926 
927  // payment path: XRP -> XRP/USD -> USD/EUR -> EUR/USD
928  env(pay(alice, carol, USD(100)),
929  path(~USD, ~EUR, ~USD),
930  sendmax(XRP(200)),
933  }
934 
935  {
936  Env env(*this, features);
937  env.fund(XRP(10000), alice, bob, noripple(gw));
938  env.trust(USD(1000), alice, bob);
939  env(pay(gw, alice, USD(100)));
940  test(env, USD, std::nullopt, STPath(), terNO_RIPPLE);
941  }
942 
943  {
944  // check global freeze
945  Env env(*this, features);
946  env.fund(XRP(10000), alice, bob, gw);
947  env.trust(USD(1000), alice, bob);
948  env(pay(gw, alice, USD(100)));
949 
950  // Account can still issue payments
951  env(fset(alice, asfGlobalFreeze));
952  test(env, USD, std::nullopt, STPath(), tesSUCCESS);
953  env(fclear(alice, asfGlobalFreeze));
954  test(env, USD, std::nullopt, STPath(), tesSUCCESS);
955 
956  // Account can not issue funds
957  env(fset(gw, asfGlobalFreeze));
958  test(env, USD, std::nullopt, STPath(), terNO_LINE);
959  env(fclear(gw, asfGlobalFreeze));
960  test(env, USD, std::nullopt, STPath(), tesSUCCESS);
961 
962  // Account can not receive funds
963  env(fset(bob, asfGlobalFreeze));
964  test(env, USD, std::nullopt, STPath(), terNO_LINE);
965  env(fclear(bob, asfGlobalFreeze));
966  test(env, USD, std::nullopt, STPath(), tesSUCCESS);
967  }
968  {
969  // Freeze between gw and alice
970  Env env(*this, features);
971  env.fund(XRP(10000), alice, bob, gw);
972  env.trust(USD(1000), alice, bob);
973  env(pay(gw, alice, USD(100)));
974  test(env, USD, std::nullopt, STPath(), tesSUCCESS);
975  env(trust(gw, alice["USD"](0), tfSetFreeze));
976  BEAST_EXPECT(getTrustFlag(env, gw, alice, usdC, TrustFlag::freeze));
977  test(env, USD, std::nullopt, STPath(), terNO_LINE);
978  }
979  {
980  // check no auth
981  // An account may require authorization to receive IOUs from an
982  // issuer
983  Env env(*this, features);
984  env.fund(XRP(10000), alice, bob, gw);
985  env(fset(gw, asfRequireAuth));
986  env.trust(USD(1000), alice, bob);
987  // Authorize alice but not bob
988  env(trust(gw, alice["USD"](1000), tfSetfAuth));
989  BEAST_EXPECT(getTrustFlag(env, gw, alice, usdC, TrustFlag::auth));
990  env(pay(gw, alice, USD(100)));
991  env.require(balance(alice, USD(100)));
992  test(env, USD, std::nullopt, STPath(), terNO_AUTH);
993 
994  // Check pure issue redeem still works
995  auto [ter, strand] = toStrand(
996  *env.current(),
997  alice,
998  gw,
999  USD,
1000  std::nullopt,
1001  std::nullopt,
1002  STPath(),
1003  true,
1004  false,
1005  env.app().logs().journal("Flow"));
1006  BEAST_EXPECT(ter == tesSUCCESS);
1007  BEAST_EXPECT(equal(strand, D{alice, gw, usdC}));
1008  }
1009 
1010  {
1011  // last step xrp from offer
1012  Env env(*this, features);
1013  env.fund(XRP(10000), alice, bob, gw);
1014  env.trust(USD(1000), alice, bob);
1015  env(pay(gw, alice, USD(100)));
1016 
1017  // alice -> USD/XRP -> bob
1018  STPath path;
1019  path.emplace_back(std::nullopt, xrpCurrency(), std::nullopt);
1020 
1021  auto [ter, strand] = toStrand(
1022  *env.current(),
1023  alice,
1024  bob,
1025  XRP,
1026  std::nullopt,
1027  USD.issue(),
1028  path,
1029  false,
1030  false,
1031  env.app().logs().journal("Flow"));
1032  BEAST_EXPECT(ter == tesSUCCESS);
1033  BEAST_EXPECT(equal(
1034  strand,
1035  D{alice, gw, usdC},
1036  B{USD.issue(), xrpIssue()},
1037  XRPS{bob}));
1038  }
1039  }
1040 
1041  void
1043  {
1044  using namespace jtx;
1045  testcase("RIPD1373");
1046 
1047  auto const alice = Account("alice");
1048  auto const bob = Account("bob");
1049  auto const carol = Account("carol");
1050  auto const gw = Account("gw");
1051  auto const USD = gw["USD"];
1052  auto const EUR = gw["EUR"];
1053 
1054  {
1055  Env env(*this, features);
1056  env.fund(XRP(10000), alice, bob, gw);
1057 
1058  env.trust(USD(1000), alice, bob);
1059  env.trust(EUR(1000), alice, bob);
1060  env.trust(bob["USD"](1000), alice, gw);
1061  env.trust(bob["EUR"](1000), alice, gw);
1062 
1063  env(offer(bob, XRP(100), bob["USD"](100)), txflags(tfPassive));
1064  env(offer(gw, XRP(100), USD(100)), txflags(tfPassive));
1065 
1066  env(offer(bob, bob["USD"](100), bob["EUR"](100)),
1067  txflags(tfPassive));
1068  env(offer(gw, USD(100), EUR(100)), txflags(tfPassive));
1069 
1070  Path const p = [&] {
1071  Path result;
1072  result.push_back(allpe(gw, bob["USD"]));
1073  result.push_back(cpe(EUR.currency));
1074  return result;
1075  }();
1076 
1077  PathSet paths(p);
1078 
1079  env(pay(alice, alice, EUR(1)),
1080  json(paths.json()),
1081  sendmax(XRP(10)),
1083  ter(temBAD_PATH));
1084  }
1085 
1086  {
1087  Env env(*this, features);
1088 
1089  env.fund(XRP(10000), alice, bob, carol, gw);
1090  env.trust(USD(10000), alice, bob, carol);
1091 
1092  env(pay(gw, bob, USD(100)));
1093 
1094  env(offer(bob, XRP(100), USD(100)), txflags(tfPassive));
1095  env(offer(bob, USD(100), XRP(100)), txflags(tfPassive));
1096 
1097  // payment path: XRP -> XRP/USD -> USD/XRP
1098  env(pay(alice, carol, XRP(100)),
1099  path(~USD, ~XRP),
1102  }
1103 
1104  {
1105  Env env(*this, features);
1106 
1107  env.fund(XRP(10000), alice, bob, carol, gw);
1108  env.trust(USD(10000), alice, bob, carol);
1109 
1110  env(pay(gw, bob, USD(100)));
1111 
1112  env(offer(bob, XRP(100), USD(100)), txflags(tfPassive));
1113  env(offer(bob, USD(100), XRP(100)), txflags(tfPassive));
1114 
1115  // payment path: XRP -> XRP/USD -> USD/XRP
1116  env(pay(alice, carol, XRP(100)),
1117  path(~USD, ~XRP),
1118  sendmax(XRP(200)),
1121  }
1122  }
1123 
1124  void
1126  {
1127  testcase("test loop");
1128  using namespace jtx;
1129 
1130  auto const alice = Account("alice");
1131  auto const bob = Account("bob");
1132  auto const carol = Account("carol");
1133  auto const gw = Account("gw");
1134  auto const USD = gw["USD"];
1135  auto const EUR = gw["EUR"];
1136  auto const CNY = gw["CNY"];
1137 
1138  {
1139  Env env(*this, features);
1140 
1141  env.fund(XRP(10000), alice, bob, carol, gw);
1142  env.trust(USD(10000), alice, bob, carol);
1143 
1144  env(pay(gw, bob, USD(100)));
1145  env(pay(gw, alice, USD(100)));
1146 
1147  env(offer(bob, XRP(100), USD(100)), txflags(tfPassive));
1148  env(offer(bob, USD(100), XRP(100)), txflags(tfPassive));
1149 
1150  // payment path: USD -> USD/XRP -> XRP/USD
1151  env(pay(alice, carol, USD(100)),
1152  sendmax(USD(100)),
1153  path(~XRP, ~USD),
1156  }
1157  {
1158  Env env(*this, features);
1159 
1160  env.fund(XRP(10000), alice, bob, carol, gw);
1161  env.trust(USD(10000), alice, bob, carol);
1162  env.trust(EUR(10000), alice, bob, carol);
1163  env.trust(CNY(10000), alice, bob, carol);
1164 
1165  env(pay(gw, bob, USD(100)));
1166  env(pay(gw, bob, EUR(100)));
1167  env(pay(gw, bob, CNY(100)));
1168 
1169  env(offer(bob, XRP(100), USD(100)), txflags(tfPassive));
1170  env(offer(bob, USD(100), EUR(100)), txflags(tfPassive));
1171  env(offer(bob, EUR(100), CNY(100)), txflags(tfPassive));
1172 
1173  // payment path: XRP->XRP/USD->USD/EUR->USD/CNY
1174  env(pay(alice, carol, CNY(100)),
1175  sendmax(XRP(100)),
1176  path(~USD, ~EUR, ~USD, ~CNY),
1179  }
1180  }
1181 
1182  void
1184  {
1185  testcase("test no account");
1186  using namespace jtx;
1187 
1188  auto const alice = Account("alice");
1189  auto const bob = Account("bob");
1190  auto const gw = Account("gw");
1191  auto const USD = gw["USD"];
1192 
1193  Env env(*this, features);
1194  env.fund(XRP(10000), alice, bob, gw);
1195 
1196  STAmount sendMax{USD.issue(), 100, 1};
1197  STAmount noAccountAmount{Issue{USD.currency, noAccount()}, 100, 1};
1198  STAmount deliver;
1199  AccountID const srcAcc = alice.id();
1200  AccountID dstAcc = bob.id();
1201  STPathSet pathSet;
1203  inputs.defaultPathsAllowed = true;
1204  try
1205  {
1206  PaymentSandbox sb{env.current().get(), tapNONE};
1207  {
1209  sb,
1210  sendMax,
1211  deliver,
1212  dstAcc,
1213  noAccount(),
1214  pathSet,
1215  env.app().logs(),
1216  &inputs);
1217  BEAST_EXPECT(r.result() == temBAD_PATH);
1218  }
1219  {
1221  sb,
1222  sendMax,
1223  deliver,
1224  noAccount(),
1225  srcAcc,
1226  pathSet,
1227  env.app().logs(),
1228  &inputs);
1229  BEAST_EXPECT(r.result() == temBAD_PATH);
1230  }
1231  {
1233  sb,
1234  noAccountAmount,
1235  deliver,
1236  dstAcc,
1237  srcAcc,
1238  pathSet,
1239  env.app().logs(),
1240  &inputs);
1241  BEAST_EXPECT(r.result() == temBAD_PATH);
1242  }
1243  {
1245  sb,
1246  sendMax,
1247  noAccountAmount,
1248  dstAcc,
1249  srcAcc,
1250  pathSet,
1251  env.app().logs(),
1252  &inputs);
1253  BEAST_EXPECT(r.result() == temBAD_PATH);
1254  }
1255  }
1256  catch (...)
1257  {
1258  this->fail();
1259  }
1260  }
1261 
1262  void
1263  run() override
1264  {
1265  using namespace jtx;
1266  auto const sa = supported_amendments();
1267  testToStrand(sa - featureFlowCross);
1268  testToStrand(sa);
1269 
1270  testRIPD1373(sa - featureFlowCross);
1271  testRIPD1373(sa);
1272 
1273  testLoop(sa - featureFlowCross);
1274  testLoop(sa);
1275 
1276  testNoAccount(sa);
1277  }
1278 };
1279 
1280 BEAST_DEFINE_TESTSUITE(PayStrand, app, ripple);
1281 
1282 } // namespace test
1283 } // namespace ripple
ripple::test::ExistingElementPool::resetTo
void resetTo(ResetState const &s)
Definition: PayStrand_test.cpp:368
ripple::test::ElementComboIter::SB::rootIss
@ rootIss
ripple::test::jtx::json
Inject raw JSON.
Definition: jtx_json.h:31
ripple::to_currency
bool to_currency(Currency &currency, std::string const &code)
Tries to convert a string to a Currency, returns true on success.
Definition: UintTypes.cpp:80
ripple::test::TrustFlag::noripple
@ noripple
ripple::test::trustFlag
std::uint32_t trustFlag(TrustFlag f, bool useHigh)
Definition: PayStrand_test.cpp:50
ripple::test::ExistingElementPool::checkBalances
bool checkBalances(ReadView const &v1, ReadView const &v2)
Definition: PayStrand_test.cpp:518
std::make_tuple
T make_tuple(T... args)
ripple::test::jtx::XRP
const XRP_t XRP
Converts to XRP Issue or STAmount.
Definition: amount.cpp:105
ripple::test::ElementComboIter::SB::prevCur
@ prevCur
ripple::Keylet
A pair of SHAMap key and LedgerEntryType.
Definition: Keylet.h:38
ripple::temBAD_SEND_XRP_MAX
@ temBAD_SEND_XRP_MAX
Definition: TER.h:98
ripple::Issue
A currency issued by an account.
Definition: Issue.h:34
ripple::test::ExistingElementPool::StateGuard::~StateGuard
~StateGuard()
Definition: PayStrand_test.cpp:382
ripple::test::ElementComboIter::SB::existingCur
@ existingCur
ripple::test::ExistingElementPool::StateGuard::state_
ResetState state_
Definition: PayStrand_test.cpp:376
ripple::test::ExistingElementPool::currencyNames
std::vector< std::string > currencyNames
Definition: PayStrand_test.cpp:339
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:347
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::terNO_LINE
@ terNO_LINE
Definition: TER.h:200
ripple::PaymentSandbox
A wrapper which makes credits unavailable to balances.
Definition: PaymentSandbox.h:112
ripple::test::jtx::Env::require
void require(Args const &... args)
Check a set of requirements.
Definition: Env.h:466
std::vector::reserve
T reserve(T... args)
ripple::lsfLowAuth
@ lsfLowAuth
Definition: LedgerFormats.h:254
ripple::test::jtx::balance
A balance matches.
Definition: balance.h:38
ripple::test::PayStrand_test::testToStrand
void testToStrand(FeatureBitset features)
Definition: PayStrand_test.cpp:639
ripple::lsfLowNoRipple
@ lsfLowNoRipple
Definition: LedgerFormats.h:256
std::vector
STL class.
std::vector::size
T size(T... args)
ripple::test::jtx::trust
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
Definition: trust.cpp:30
ripple::path::RippleCalc::Input
Definition: RippleCalc.h:46
ripple::test::ElementComboIter::SB::boundary
@ boundary
ripple::Issue::currency
Currency currency
Definition: Issue.h:37
ripple::test::Path::push_back
Path & push_back(Issue const &iss)
Definition: PathSet.h:133
ripple::test::Path
Definition: PathSet.h:92
ripple::test::ElementComboIter::valid
bool valid() const
Definition: PayStrand_test.cpp:247
ripple::test::strandEqualHelper
bool strandEqualHelper(Iter i)
Definition: PayStrand_test.cpp:113
ripple::test::TrustFlag::auth
@ auth
std::tuple< size_t, size_t >
ripple::tfPassive
constexpr std::uint32_t tfPassive
Definition: TxFlags.h:93
ripple::test::ElementComboIter::prev_
STPathElement const * prev_
Definition: PayStrand_test.cpp:210
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:241
ripple::terNO_RIPPLE
@ terNO_RIPPLE
Definition: TER.h:205
std::vector::back
T back(T... args)
ripple::test::ElementComboIter::count
size_t count(std::initializer_list< SB > sb) const
Definition: PayStrand_test.cpp:231
ripple::test::DirectStepInfo
Definition: PayStrand_test.cpp:35
ripple::test::PayStrand_test::testLoop
void testLoop(FeatureBitset features)
Definition: PayStrand_test.cpp:1125
ripple::toStrand
std::pair< TER, Strand > toStrand(ReadView const &view, AccountID const &src, AccountID const &dst, Issue const &deliver, std::optional< Quality > const &limitQuality, std::optional< Issue > const &sendMaxIssue, STPath const &path, bool ownerPaysTransferFee, bool offerCrossing, beast::Journal j)
Create a Strand for the specified path.
Definition: PaySteps.cpp:135
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:30
ripple::temBAD_PATH
@ temBAD_PATH
Definition: TER.h:94
ripple::test::bookStepEqual
bool bookStepEqual(Step const &step, ripple::Book const &book)
Definition: BookStep.cpp:1123
ripple::test::ExistingElementPool
Definition: PayStrand_test.cpp:335
ripple::STPathElement::typeCurrency
@ typeCurrency
Definition: STPathSet.h:49
ripple::STPathSet
Definition: STPathSet.h:176
ripple::test::jtx::Env::trust
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition: Env.cpp:259
ripple::test::ExistingElementPool::getCurrency
ripple::Currency getCurrency(size_t id)
Definition: PayStrand_test.cpp:349
ripple::test::ExistingElementPool::accounts
std::vector< jtx::Account > accounts
Definition: PayStrand_test.cpp:337
ripple::test::ElementComboIter::SB::prevAcc
@ prevAcc
ripple::lsfHighAuth
@ lsfHighAuth
Definition: LedgerFormats.h:255
std::vector::clear
T clear(T... args)
ripple::STPathElement::typeIssuer
@ typeIssuer
Definition: STPathSet.h:50
ripple::test::TrustFlag::freeze
@ freeze
ripple::test::XRPEndpointStepInfo::acc
AccountID acc
Definition: PayStrand_test.cpp:44
ripple::test::jtx::Account::id
AccountID id() const
Returns the Account ID.
Definition: Account.h:106
std::tie
T tie(T... args)
ripple::test::PayStrand_test::testRIPD1373
void testRIPD1373(FeatureBitset features)
Definition: PayStrand_test.cpp:1042
ripple::test::ElementComboIter::SB::existingIss
@ existingIss
ripple::test::ElementComboIter::next
bool next()
Definition: PayStrand_test.cpp:266
ripple::base_uint< 160, detail::AccountIDTag >
ripple::test::ElementComboIter::has
bool has(SB s) const
Definition: PayStrand_test.cpp:216
ripple::test::DirectStepInfo::currency
Currency currency
Definition: PayStrand_test.cpp:39
ripple::path::RippleCalc::Input::defaultPathsAllowed
bool defaultPathsAllowed
Definition: RippleCalc.h:51
ripple::test::XRPEndpointStepInfo
Definition: PayStrand_test.cpp:42
ripple::tfPartialPayment
constexpr std::uint32_t tfPartialPayment
Definition: TxFlags.h:102
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:133
std::forward
T forward(T... args)
ripple::test::allpe
STPathElement allpe(AccountID const &a, Issue const &iss)
Definition: PayStrand_test.cpp:175
ripple::test::ElementComboIter::SB::prevIss
@ prevIss
ripple::test::ExistingElementPool::getAvailAccount
jtx::Account getAvailAccount()
Definition: PayStrand_test.cpp:567
ripple::temBAD_SEND_XRP_PATHS
@ temBAD_SEND_XRP_PATHS
Definition: TER.h:101
ripple::TERSubset< CanCvtToTER >
ripple::test::jtx::sendmax
Sets the SendMax on a JTx.
Definition: sendmax.h:31
ripple::test::PayStrand_test::testNoAccount
void testNoAccount(FeatureBitset features)
Definition: PayStrand_test.cpp:1183
ripple::test::iape
STPathElement iape(AccountID const &account)
Definition: PayStrand_test.cpp:159
ripple::test::PathSet
Definition: PathSet.h:165
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::test::ElementComboIter::SB::rootAcc
@ rootAcc
ripple::test::ElementComboIter::hasAny
bool hasAny(std::initializer_list< SB > sb) const
Definition: PayStrand_test.cpp:222
ripple::test::jtx::txflags
Set the flags on a JTx.
Definition: txflags.h:30
ripple::terNO_AUTH
@ terNO_AUTH
Definition: TER.h:199
ripple::test::jtx::paths
Set Paths, SendMax on a JTx.
Definition: paths.h:32
ripple::test::ExistingElementPool::getAccount
jtx::Account getAccount(size_t id)
Definition: PayStrand_test.cpp:342
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
Definition: Env.cpp:121
ripple::STAmount
Definition: STAmount.h:45
ripple::test::ElementComboIter::SB::existingAcc
@ existingAcc
ripple::xrpAccount
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition: AccountID.cpp:168
ripple::Application::logs
virtual Logs & logs()=0
ripple::test::PayStrand_test::run
void run() override
Definition: PayStrand_test.cpp:1263
ripple::test::ElementComboIter::ElementComboIter
ElementComboIter(STPathElement const *prev=nullptr)
Definition: PayStrand_test.cpp:242
ripple::test::jtx::path
Add a path.
Definition: paths.h:55
ripple::test::jtx::supported_amendments
FeatureBitset supported_amendments()
Definition: Env.h:70
std::uint32_t
ripple::test::ElementComboIter::emplace_into
void emplace_into(Col &col, AccFactory &&accF, IssFactory &&issF, CurrencyFactory &&currencyF, std::optional< AccountID > const &existingAcc, std::optional< Currency > const &existingCur, std::optional< AccountID > const &existingIss)
Definition: PayStrand_test.cpp:284
ripple::test::ElementComboIter::SB::sameAccIss
@ sameAccIss
ripple::keylet::line
Keylet line(AccountID const &id0, AccountID const &id1, Currency const &currency) noexcept
The index of a trust line for a given currency.
Definition: Indexes.cpp:193
ripple::test::ElementComboIter::SB
SB
Definition: PayStrand_test.cpp:187
ripple::test::ElementComboIter::SB::acc
@ acc
ripple::test::ElementComboIter
Definition: PayStrand_test.cpp:185
ripple::test::TrustFlag
TrustFlag
Definition: PayStrand_test.cpp:47
ripple::test::jtx::fclear
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
Definition: flags.h:40
ripple::test::ExistingElementPool::setupEnv
void setupEnv(jtx::Env &env, size_t numAct, size_t numCur, std::optional< size_t > const &offererIndex)
Definition: PayStrand_test.cpp:394
ripple::ReadView::read
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
ripple::test::ExistingElementPool::totalXRP
std::int64_t totalXRP(ReadView const &v, bool incRoot)
Definition: PayStrand_test.cpp:497
ripple::test::ElementComboIter::SB::last
@ last
ripple::lsfHighNoRipple
@ lsfHighNoRipple
Definition: LedgerFormats.h:257
ripple::test::PayStrand_test
Definition: PayStrand_test.cpp:636
ripple::test::ExistingElementPool::for_each_element_pair
void for_each_element_pair(STAmount const &sendMax, STAmount const &deliver, std::vector< STPathElement > const &prefix, std::vector< STPathElement > const &suffix, std::optional< AccountID > const &existingAcc, std::optional< Currency > const &existingCur, std::optional< AccountID > const &existingIss, F &&f)
Definition: PayStrand_test.cpp:580
ripple::test::equal
bool equal(STAmount const &sa1, STAmount const &sa2)
Definition: Path_test.cpp:126
ripple::lsfHighFreeze
@ lsfHighFreeze
Definition: LedgerFormats.h:259
ripple::test::cpe
STPathElement cpe(Currency const &c)
Definition: PayStrand_test.cpp:167
ripple::test::directStepEqual
bool directStepEqual(Step const &step, AccountID const &src, AccountID const &dst, Currency const &currency)
Definition: DirectStep.cpp:958
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:125
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::test::ExistingElementPool::getResetState
ResetState getResetState() const
Definition: PayStrand_test.cpp:362
ripple::test::ExistingElementPool::nextAvailCurrency
size_t nextAvailCurrency
Definition: PayStrand_test.cpp:358
ripple::test::jtx::noripple
std::array< Account, 1+sizeof...(Args)> noripple(Account const &account, Args const &... args)
Designate accounts as no-ripple in Env::fund.
Definition: Env.h:64
ripple::Logs::journal
beast::Journal journal(std::string const &name)
Definition: Log.cpp:144
ripple::tfSetFreeze
constexpr std::uint32_t tfSetFreeze
Definition: TxFlags.h:111
ripple::test::jtx::pay
Json::Value pay(Account const &account, Account const &to, AnyAmount amount)
Create a payment.
Definition: pay.cpp:29
ripple::test::ElementComboIter::state_
std::uint16_t state_
Definition: PayStrand_test.cpp:206
ripple::STPathElement
Definition: STPathSet.h:34
ripple::tfSetfAuth
constexpr std::uint32_t tfSetfAuth
Definition: TxFlags.h:108
std::vector::begin
T begin(T... args)
ripple::test::getTrustFlag
bool getTrustFlag(jtx::Env const &env, jtx::Account const &src, jtx::Account const &dst, Currency const &cur, TrustFlag flag)
Definition: PayStrand_test.cpp:71
std::vector::insert
T insert(T... args)
ripple::test::ElementComboIter::SB::cur
@ cur
ripple::asfRequireAuth
constexpr std::uint32_t asfRequireAuth
Definition: TxFlags.h:75
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:228
ripple::test::jtx::Env::le
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Definition: Env.cpp:216
ripple::test::ExistingElementPool::currencies
std::vector< ripple::Currency > currencies
Definition: PayStrand_test.cpp:338
ripple::path::RippleCalc::rippleCalculate
static Output rippleCalculate(PaymentSandbox &view, STAmount const &saMaxAmountReq, STAmount const &saDstAmountReq, AccountID const &uDstAccountID, AccountID const &uSrcAccountID, STPathSet const &spsPaths, Logs &l, Input const *const pInputs=nullptr)
Definition: RippleCalc.cpp:31
ripple::test::ipe
STPathElement ipe(Issue const &iss)
Definition: PayStrand_test.cpp:148
ripple::STPathElement::typeAccount
@ typeAccount
Definition: STPathSet.h:47
ripple::sfBalance
const SF_AMOUNT sfBalance
ripple::test::ape
STPathElement ape(AccountID const &a)
Definition: PayStrand_test.cpp:140
ripple::FeatureBitset
Definition: Feature.h:113
ripple::tecPATH_DRY
@ tecPATH_DRY
Definition: TER.h:261
std::vector::empty
T empty(T... args)
ripple::xrpIssue
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
Definition: Issue.h:95
ripple::asfGlobalFreeze
constexpr std::uint32_t asfGlobalFreeze
Definition: TxFlags.h:80
std::optional
ripple::test::ExistingElementPool::StateGuard::StateGuard
StateGuard(ExistingElementPool &p)
Definition: PayStrand_test.cpp:378
ripple::test::ElementComboIter::allowCompound_
const bool allowCompound_
Definition: PayStrand_test.cpp:213
ripple::test::ExistingElementPool::StateGuard::p_
ExistingElementPool & p_
Definition: PayStrand_test.cpp:375
ripple::test::jtx::Account
Immutable cryptographic account descriptor.
Definition: Account.h:37
ripple::Book
Specifies an order book.
Definition: Book.h:33
ripple::test::xrpEndpointStepEqual
bool xrpEndpointStepEqual(Step const &step, AccountID const &acc)
Definition: XRPEndpointStep.cpp:385
ripple::temBAD_PATH_LOOP
@ temBAD_PATH_LOOP
Definition: TER.h:95
std::vector::end
T end(T... args)
ripple::lsfLowFreeze
@ lsfLowFreeze
Definition: LedgerFormats.h:258
ripple::test::ExistingElementPool::nextAvailAccount
size_t nextAvailAccount
Definition: PayStrand_test.cpp:357
ripple::test::ExistingElementPool::StateGuard
Definition: PayStrand_test.cpp:373
ripple::test::DirectStepInfo::src
AccountID src
Definition: PayStrand_test.cpp:37
std::unique_ptr
STL class.
ripple::featureFlowCross
const uint256 featureFlowCross
ripple::STPath
Definition: STPathSet.h:118
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:222
ripple::test::ElementComboIter::SB::iss
@ iss
ripple::test::jtx::Env::current
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Definition: Env.h:300
ripple::test::ElementComboIter::SB::xrp
@ xrp
ripple::noAccount
AccountID const & noAccount()
A placeholder for empty accounts.
Definition: AccountID.cpp:175
ripple::xrpCurrency
Currency const & xrpCurrency()
XRP currency.
Definition: UintTypes.cpp:121
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:116
ripple::test::DirectStepInfo::dst
AccountID dst
Definition: PayStrand_test.cpp:38
ripple::Issue::account
AccountID account
Definition: Issue.h:38
ripple::tfNoRippleDirect
constexpr std::uint32_t tfNoRippleDirect
Definition: TxFlags.h:101
std::initializer_list
ripple::test::ExistingElementPool::getAvailCurrency
ripple::Currency getAvailCurrency()
Definition: PayStrand_test.cpp:573
ripple::test::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(DeliverMin, app, ripple)