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  boost::optional<AccountID> const& existingAcc,
290  boost::optional<Currency> const& existingCur,
291  boost::optional<AccountID> const& existingIss)
292  {
293  assert(!has(SB::last));
294 
295  auto const acc = [&]() -> boost::optional<AccountID> {
296  if (!has(SB::acc))
297  return boost::none;
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 = [&]() -> boost::optional<AccountID> {
305  if (!has(SB::iss))
306  return boost::none;
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 = [&]() -> boost::optional<Currency> {
316  if (!has(SB::cur))
317  return boost::none;
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  boost::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  boost::optional<AccountID> const& existingAcc,
586  boost::optional<Currency> const& existingCur,
587  boost::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  boost::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  boost::none,
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*/ boost::none,
700  /*sendMaxIssue*/ EUR.issue(),
701  path,
702  true,
703  false,
704  env.app().logs().journal("Flow"));
705  (void)ter;
706  (void)_;
707  BEAST_EXPECT(ter == tesSUCCESS);
708  }
709  {
710  STPath const path = STPath({ipe(USD), cpe(xrpCurrency())});
711  auto [ter, _] = toStrand(
712  *env.current(),
713  alice,
714  alice,
715  /*deliver*/ xrpIssue(),
716  /*limitQuality*/ boost::none,
717  /*sendMaxIssue*/ EUR.issue(),
718  path,
719  true,
720  false,
721  env.app().logs().journal("Flow"));
722  (void)ter;
723  (void)_;
724  BEAST_EXPECT(ter == tesSUCCESS);
725  }
726  return;
727  };
728 
729  {
730  Env env(*this, features);
731  env.fund(XRP(10000), alice, bob, carol, gw);
732 
733  test(env, USD, boost::none, STPath(), terNO_LINE);
734 
735  env.trust(USD(1000), alice, bob, carol);
736  test(env, USD, boost::none, STPath(), tecPATH_DRY);
737 
738  env(pay(gw, alice, USD(100)));
739  env(pay(gw, carol, USD(100)));
740 
741  // Insert implied account
742  test(
743  env,
744  USD,
745  boost::none,
746  STPath(),
747  tesSUCCESS,
748  D{alice, gw, usdC},
749  D{gw, bob, usdC});
750  env.trust(EUR(1000), alice, bob);
751 
752  // Insert implied offer
753  test(
754  env,
755  EUR,
756  USD.issue(),
757  STPath(),
758  tesSUCCESS,
759  D{alice, gw, usdC},
760  B{USD, EUR},
761  D{gw, bob, eurC});
762 
763  // Path with explicit offer
764  test(
765  env,
766  EUR,
767  USD.issue(),
768  STPath({ipe(EUR)}),
769  tesSUCCESS,
770  D{alice, gw, usdC},
771  B{USD, EUR},
772  D{gw, bob, eurC});
773 
774  // Path with offer that changes issuer only
775  env.trust(carol["USD"](1000), bob);
776  test(
777  env,
778  carol["USD"],
779  USD.issue(),
780  STPath({iape(carol)}),
781  tesSUCCESS,
782  D{alice, gw, usdC},
783  B{USD, carol["USD"]},
784  D{carol, bob, usdC});
785 
786  // Path with XRP src currency
787  test(
788  env,
789  USD,
790  xrpIssue(),
791  STPath({ipe(USD)}),
792  tesSUCCESS,
793  XRPS{alice},
794  B{XRP, USD},
795  D{gw, bob, usdC});
796 
797  // Path with XRP dst currency
798  test(
799  env,
800  xrpIssue(),
801  USD.issue(),
802  STPath({ipe(XRP)}),
803  tesSUCCESS,
804  D{alice, gw, usdC},
805  B{USD, XRP},
806  XRPS{bob});
807 
808  // Path with XRP cross currency bridged payment
809  test(
810  env,
811  EUR,
812  USD.issue(),
813  STPath({cpe(xrpCurrency())}),
814  tesSUCCESS,
815  D{alice, gw, usdC},
816  B{USD, XRP},
817  B{XRP, EUR},
818  D{gw, bob, eurC});
819 
820  // XRP -> XRP transaction can't include a path
821  test(env, XRP, boost::none, STPath({ape(carol)}), temBAD_PATH);
822 
823  {
824  // The root account can't be the src or dst
825  auto flowJournal = env.app().logs().journal("Flow");
826  {
827  // The root account can't be the dst
828  auto r = toStrand(
829  *env.current(),
830  alice,
831  xrpAccount(),
832  XRP,
833  boost::none,
834  USD.issue(),
835  STPath(),
836  true,
837  false,
838  flowJournal);
839  BEAST_EXPECT(r.first == temBAD_PATH);
840  }
841  {
842  // The root account can't be the src
843  auto r = toStrand(
844  *env.current(),
845  xrpAccount(),
846  alice,
847  XRP,
848  boost::none,
849  boost::none,
850  STPath(),
851  true,
852  false,
853  flowJournal);
854  BEAST_EXPECT(r.first == temBAD_PATH);
855  }
856  {
857  // The root account can't be the src
858  auto r = toStrand(
859  *env.current(),
860  noAccount(),
861  bob,
862  USD,
863  boost::none,
864  boost::none,
865  STPath(),
866  true,
867  false,
868  flowJournal);
869  BEAST_EXPECT(r.first == terNO_ACCOUNT);
870  }
871  }
872 
873  // Create an offer with the same in/out issue
874  test(
875  env,
876  EUR,
877  USD.issue(),
878  STPath({ipe(USD), ipe(EUR)}),
879  temBAD_PATH);
880 
881  // Path element with type zero
882  test(
883  env,
884  USD,
885  boost::none,
887  0, xrpAccount(), xrpCurrency(), xrpAccount())}),
888  temBAD_PATH);
889 
890  // The same account can't appear more than once on a path
891  // `gw` will be used from alice->carol and implied between carol
892  // and bob
893  test(
894  env,
895  USD,
896  boost::none,
897  STPath({ape(gw), ape(carol)}),
899 
900  // The same offer can't appear more than once on a path
901  test(
902  env,
903  EUR,
904  USD.issue(),
905  STPath({ipe(EUR), ipe(USD), ipe(EUR)}),
907  }
908 
909  {
910  // cannot have more than one offer with the same output issue
911 
912  using namespace jtx;
913  Env env(*this, features);
914 
915  env.fund(XRP(10000), alice, bob, carol, gw);
916  env.trust(USD(10000), alice, bob, carol);
917  env.trust(EUR(10000), alice, bob, carol);
918 
919  env(pay(gw, bob, USD(100)));
920  env(pay(gw, bob, EUR(100)));
921 
922  env(offer(bob, XRP(100), USD(100)));
923  env(offer(bob, USD(100), EUR(100)), txflags(tfPassive));
924  env(offer(bob, EUR(100), USD(100)), txflags(tfPassive));
925 
926  // payment path: XRP -> XRP/USD -> USD/EUR -> EUR/USD
927  env(pay(alice, carol, USD(100)),
928  path(~USD, ~EUR, ~USD),
929  sendmax(XRP(200)),
932  }
933 
934  {
935  Env env(*this, features);
936  env.fund(XRP(10000), alice, bob, noripple(gw));
937  env.trust(USD(1000), alice, bob);
938  env(pay(gw, alice, USD(100)));
939  test(env, USD, boost::none, STPath(), terNO_RIPPLE);
940  }
941 
942  {
943  // check global freeze
944  Env env(*this, features);
945  env.fund(XRP(10000), alice, bob, gw);
946  env.trust(USD(1000), alice, bob);
947  env(pay(gw, alice, USD(100)));
948 
949  // Account can still issue payments
950  env(fset(alice, asfGlobalFreeze));
951  test(env, USD, boost::none, STPath(), tesSUCCESS);
952  env(fclear(alice, asfGlobalFreeze));
953  test(env, USD, boost::none, STPath(), tesSUCCESS);
954 
955  // Account can not issue funds
956  env(fset(gw, asfGlobalFreeze));
957  test(env, USD, boost::none, STPath(), terNO_LINE);
958  env(fclear(gw, asfGlobalFreeze));
959  test(env, USD, boost::none, STPath(), tesSUCCESS);
960 
961  // Account can not receive funds
962  env(fset(bob, asfGlobalFreeze));
963  test(env, USD, boost::none, STPath(), terNO_LINE);
964  env(fclear(bob, asfGlobalFreeze));
965  test(env, USD, boost::none, STPath(), tesSUCCESS);
966  }
967  {
968  // Freeze between gw and alice
969  Env env(*this, features);
970  env.fund(XRP(10000), alice, bob, gw);
971  env.trust(USD(1000), alice, bob);
972  env(pay(gw, alice, USD(100)));
973  test(env, USD, boost::none, STPath(), tesSUCCESS);
974  env(trust(gw, alice["USD"](0), tfSetFreeze));
975  BEAST_EXPECT(getTrustFlag(env, gw, alice, usdC, TrustFlag::freeze));
976  test(env, USD, boost::none, STPath(), terNO_LINE);
977  }
978  {
979  // check no auth
980  // An account may require authorization to receive IOUs from an
981  // issuer
982  Env env(*this, features);
983  env.fund(XRP(10000), alice, bob, gw);
984  env(fset(gw, asfRequireAuth));
985  env.trust(USD(1000), alice, bob);
986  // Authorize alice but not bob
987  env(trust(gw, alice["USD"](1000), tfSetfAuth));
988  BEAST_EXPECT(getTrustFlag(env, gw, alice, usdC, TrustFlag::auth));
989  env(pay(gw, alice, USD(100)));
990  env.require(balance(alice, USD(100)));
991  test(env, USD, boost::none, STPath(), terNO_AUTH);
992 
993  // Check pure issue redeem still works
994  auto [ter, strand] = toStrand(
995  *env.current(),
996  alice,
997  gw,
998  USD,
999  boost::none,
1000  boost::none,
1001  STPath(),
1002  true,
1003  false,
1004  env.app().logs().journal("Flow"));
1005  BEAST_EXPECT(ter == tesSUCCESS);
1006  BEAST_EXPECT(equal(strand, D{alice, gw, usdC}));
1007  }
1008  {
1009  // Check path with sendMax and node with correct sendMax already set
1010  Env env(*this, features);
1011  env.fund(XRP(10000), alice, bob, gw);
1012  env.trust(USD(1000), alice, bob);
1013  env.trust(EUR(1000), alice, bob);
1014  env(pay(gw, alice, EUR(100)));
1015  auto const path = STPath({STPathElement(
1017  EUR.account,
1018  EUR.currency,
1019  EUR.account)});
1020  test(env, USD, EUR.issue(), path, tesSUCCESS);
1021  }
1022 
1023  {
1024  // last step xrp from offer
1025  Env env(*this, features);
1026  env.fund(XRP(10000), alice, bob, gw);
1027  env.trust(USD(1000), alice, bob);
1028  env(pay(gw, alice, USD(100)));
1029 
1030  // alice -> USD/XRP -> bob
1031  STPath path;
1032  path.emplace_back(boost::none, USD.currency, USD.account.id());
1033  path.emplace_back(boost::none, xrpCurrency(), boost::none);
1034 
1035  auto [ter, strand] = toStrand(
1036  *env.current(),
1037  alice,
1038  bob,
1039  XRP,
1040  boost::none,
1041  USD.issue(),
1042  path,
1043  false,
1044  false,
1045  env.app().logs().journal("Flow"));
1046  BEAST_EXPECT(ter == tesSUCCESS);
1047  BEAST_EXPECT(equal(
1048  strand,
1049  D{alice, gw, usdC},
1050  B{USD.issue(), xrpIssue()},
1051  XRPS{bob}));
1052  }
1053  }
1054 
1055  void
1057  {
1058  using namespace jtx;
1059  testcase("RIPD1373");
1060 
1061  auto const alice = Account("alice");
1062  auto const bob = Account("bob");
1063  auto const carol = Account("carol");
1064  auto const gw = Account("gw");
1065  auto const USD = gw["USD"];
1066  auto const EUR = gw["EUR"];
1067 
1068  {
1069  Env env(*this, features);
1070  env.fund(XRP(10000), alice, bob, gw);
1071 
1072  env.trust(USD(1000), alice, bob);
1073  env.trust(EUR(1000), alice, bob);
1074  env.trust(bob["USD"](1000), alice, gw);
1075  env.trust(bob["EUR"](1000), alice, gw);
1076 
1077  env(offer(bob, XRP(100), bob["USD"](100)), txflags(tfPassive));
1078  env(offer(gw, XRP(100), USD(100)), txflags(tfPassive));
1079 
1080  env(offer(bob, bob["USD"](100), bob["EUR"](100)),
1081  txflags(tfPassive));
1082  env(offer(gw, USD(100), EUR(100)), txflags(tfPassive));
1083 
1084  Path const p = [&] {
1085  Path result;
1086  result.push_back(allpe(gw, bob["USD"]));
1087  result.push_back(cpe(EUR.currency));
1088  return result;
1089  }();
1090 
1091  PathSet paths(p);
1092 
1093  env(pay(alice, alice, EUR(1)),
1094  json(paths.json()),
1095  sendmax(XRP(10)),
1097  ter(temBAD_PATH));
1098  }
1099 
1100  {
1101  Env env(*this, features);
1102 
1103  env.fund(XRP(10000), alice, bob, carol, gw);
1104  env.trust(USD(10000), alice, bob, carol);
1105 
1106  env(pay(gw, bob, USD(100)));
1107 
1108  env(offer(bob, XRP(100), USD(100)), txflags(tfPassive));
1109  env(offer(bob, USD(100), XRP(100)), txflags(tfPassive));
1110 
1111  // payment path: XRP -> XRP/USD -> USD/XRP
1112  env(pay(alice, carol, XRP(100)),
1113  path(~USD, ~XRP),
1116  }
1117 
1118  {
1119  Env env(*this, features);
1120 
1121  env.fund(XRP(10000), alice, bob, carol, gw);
1122  env.trust(USD(10000), alice, bob, carol);
1123 
1124  env(pay(gw, bob, USD(100)));
1125 
1126  env(offer(bob, XRP(100), USD(100)), txflags(tfPassive));
1127  env(offer(bob, USD(100), XRP(100)), txflags(tfPassive));
1128 
1129  // payment path: XRP -> XRP/USD -> USD/XRP
1130  env(pay(alice, carol, XRP(100)),
1131  path(~USD, ~XRP),
1132  sendmax(XRP(200)),
1135  }
1136  }
1137 
1138  void
1140  {
1141  testcase("test loop");
1142  using namespace jtx;
1143 
1144  auto const alice = Account("alice");
1145  auto const bob = Account("bob");
1146  auto const carol = Account("carol");
1147  auto const gw = Account("gw");
1148  auto const USD = gw["USD"];
1149  auto const EUR = gw["EUR"];
1150  auto const CNY = gw["CNY"];
1151 
1152  {
1153  Env env(*this, features);
1154 
1155  env.fund(XRP(10000), alice, bob, carol, gw);
1156  env.trust(USD(10000), alice, bob, carol);
1157 
1158  env(pay(gw, bob, USD(100)));
1159  env(pay(gw, alice, USD(100)));
1160 
1161  env(offer(bob, XRP(100), USD(100)), txflags(tfPassive));
1162  env(offer(bob, USD(100), XRP(100)), txflags(tfPassive));
1163 
1164  // payment path: USD -> USD/XRP -> XRP/USD
1165  env(pay(alice, carol, USD(100)),
1166  sendmax(USD(100)),
1167  path(~XRP, ~USD),
1170  }
1171  {
1172  Env env(*this, features);
1173 
1174  env.fund(XRP(10000), alice, bob, carol, gw);
1175  env.trust(USD(10000), alice, bob, carol);
1176  env.trust(EUR(10000), alice, bob, carol);
1177  env.trust(CNY(10000), alice, bob, carol);
1178 
1179  env(pay(gw, bob, USD(100)));
1180  env(pay(gw, bob, EUR(100)));
1181  env(pay(gw, bob, CNY(100)));
1182 
1183  env(offer(bob, XRP(100), USD(100)), txflags(tfPassive));
1184  env(offer(bob, USD(100), EUR(100)), txflags(tfPassive));
1185  env(offer(bob, EUR(100), CNY(100)), txflags(tfPassive));
1186 
1187  // payment path: XRP->XRP/USD->USD/EUR->USD/CNY
1188  env(pay(alice, carol, CNY(100)),
1189  sendmax(XRP(100)),
1190  path(~USD, ~EUR, ~USD, ~CNY),
1193  }
1194  }
1195 
1196  void
1198  {
1199  testcase("test no account");
1200  using namespace jtx;
1201 
1202  auto const alice = Account("alice");
1203  auto const bob = Account("bob");
1204  auto const gw = Account("gw");
1205  auto const USD = gw["USD"];
1206 
1207  Env env(*this, features);
1208  env.fund(XRP(10000), alice, bob, gw);
1209 
1210  STAmount sendMax{USD.issue(), 100, 1};
1211  STAmount noAccountAmount{Issue{USD.currency, noAccount()}, 100, 1};
1212  STAmount deliver;
1213  AccountID const srcAcc = alice.id();
1214  AccountID dstAcc = bob.id();
1215  STPathSet pathSet;
1217  inputs.defaultPathsAllowed = true;
1218  try
1219  {
1220  PaymentSandbox sb{env.current().get(), tapNONE};
1221  {
1223  sb,
1224  sendMax,
1225  deliver,
1226  dstAcc,
1227  noAccount(),
1228  pathSet,
1229  env.app().logs(),
1230  &inputs);
1231  BEAST_EXPECT(r.result() == temBAD_PATH);
1232  }
1233  {
1235  sb,
1236  sendMax,
1237  deliver,
1238  noAccount(),
1239  srcAcc,
1240  pathSet,
1241  env.app().logs(),
1242  &inputs);
1243  BEAST_EXPECT(r.result() == temBAD_PATH);
1244  }
1245  {
1247  sb,
1248  noAccountAmount,
1249  deliver,
1250  dstAcc,
1251  srcAcc,
1252  pathSet,
1253  env.app().logs(),
1254  &inputs);
1255  BEAST_EXPECT(r.result() == temBAD_PATH);
1256  }
1257  {
1259  sb,
1260  sendMax,
1261  noAccountAmount,
1262  dstAcc,
1263  srcAcc,
1264  pathSet,
1265  env.app().logs(),
1266  &inputs);
1267  BEAST_EXPECT(r.result() == temBAD_PATH);
1268  }
1269  }
1270  catch (...)
1271  {
1272  this->fail();
1273  }
1274  }
1275 
1276  void
1277  run() override
1278  {
1279  using namespace jtx;
1280  auto const sa = supported_amendments();
1281  testToStrand(sa - featureFlowCross);
1282  testToStrand(sa);
1283 
1284  testRIPD1373(sa - featureFlowCross);
1285  testRIPD1373(sa);
1286 
1287  testLoop(sa - featureFlowCross);
1288  testLoop(sa);
1289 
1290  testNoAccount(sa);
1291  }
1292 };
1293 
1294 BEAST_DEFINE_TESTSUITE(PayStrand, app, ripple);
1295 
1296 } // namespace test
1297 } // 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
ripple::tfNoRippleDirect
const std::uint32_t tfNoRippleDirect
Definition: TxFlags.h:84
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:95
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::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountDelete, app, ripple)
ripple::test::ElementComboIter::SB::existingCur
@ existingCur
ripple::test::ExistingElementPool::StateGuard::state_
ResetState state_
Definition: PayStrand_test.cpp:376
ripple::tfPartialPayment
const std::uint32_t tfPartialPayment
Definition: TxFlags.h:85
ripple::test::ExistingElementPool::currencyNames
std::vector< std::string > currencyNames
Definition: PayStrand_test.cpp:339
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:192
ripple::PaymentSandbox
A wrapper which makes credits unavailable to balances.
Definition: PaymentSandbox.h:112
ripple::STPathElement::typeAll
@ typeAll
Definition: STPathSet.h:43
ripple::test::jtx::Env::require
void require(Args const &... args)
Check a set of requirements.
Definition: Env.h:464
std::vector::reserve
T reserve(T... args)
ripple::lsfLowAuth
@ lsfLowAuth
Definition: LedgerFormats.h:121
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::asfGlobalFreeze
const std::uint32_t asfGlobalFreeze
Definition: TxFlags.h:71
ripple::lsfLowNoRipple
@ lsfLowNoRipple
Definition: LedgerFormats.h:123
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::tfPassive
const std::uint32_t tfPassive
Definition: TxFlags.h:76
ripple::path::RippleCalc::Input
Definition: RippleCalc.h:46
ripple::toStrand
std::pair< TER, Strand > toStrand(ReadView const &view, AccountID const &src, AccountID const &dst, Issue const &deliver, boost::optional< Quality > const &limitQuality, boost::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::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:91
ripple::test::Path
Definition: PathSet.h:50
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::test::ElementComboIter::prev_
STPathElement const * prev_
Definition: PayStrand_test.cpp:210
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:238
ripple::terNO_RIPPLE
@ terNO_RIPPLE
Definition: TER.h:197
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::ElementComboIter::emplace_into
void emplace_into(Col &col, AccFactory &&accF, IssFactory &&issF, CurrencyFactory &&currencyF, boost::optional< AccountID > const &existingAcc, boost::optional< Currency > const &existingCur, boost::optional< AccountID > const &existingIss)
Definition: PayStrand_test.cpp:284
ripple::test::PayStrand_test::testLoop
void testLoop(FeatureBitset features)
Definition: PayStrand_test.cpp:1139
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:31
ripple::temBAD_PATH
@ temBAD_PATH
Definition: TER.h:91
ripple::test::bookStepEqual
bool bookStepEqual(Step const &step, ripple::Book const &book)
Definition: BookStep.cpp:1104
ripple::test::ExistingElementPool
Definition: PayStrand_test.cpp:335
ripple::STPathElement::typeCurrency
@ typeCurrency
Definition: STPathSet.h:40
ripple::STPathSet
Definition: STPathSet.h:309
ripple::test::jtx::Env::trust
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
Definition: Env.cpp:240
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:122
std::vector::clear
T clear(T... args)
ripple::STPathElement::typeIssuer
@ typeIssuer
Definition: STPathSet.h:41
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:102
std::tie
T tie(T... args)
ripple::test::PayStrand_test::testRIPD1373
void testRIPD1373(FeatureBitset features)
Definition: PayStrand_test.cpp:1056
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::asfRequireAuth
const std::uint32_t asfRequireAuth
Definition: TxFlags.h:66
ripple::keylet::account
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition: Indexes.cpp:120
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:98
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:1197
ripple::test::iape
STPathElement iape(AccountID const &account)
Definition: PayStrand_test.cpp:159
ripple::test::PathSet
Definition: PathSet.h:123
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:191
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::STAmount
Definition: STAmount.h:42
ripple::test::ElementComboIter::SB::existingAcc
@ existingAcc
ripple::xrpAccount
AccountID const & xrpAccount()
Compute AccountID from public key.
Definition: AccountID.cpp:143
ripple::Application::logs
virtual Logs & logs()=0
ripple::test::PayStrand_test::run
void run() override
Definition: PayStrand_test.cpp:1277
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:69
std::uint32_t
ripple::test::ElementComboIter::SB::sameAccIss
@ sameAccIss
ripple::tfSetFreeze
const std::uint32_t tfSetFreeze
Definition: TxFlags.h:94
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:172
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::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:124
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, boost::optional< AccountID > const &existingAcc, boost::optional< Currency > const &existingCur, boost::optional< AccountID > const &existingIss, F &&f)
Definition: PayStrand_test.cpp:580
ripple::terNO_ACCOUNT
@ terNO_ACCOUNT
Definition: TER.h:190
ripple::test::equal
bool equal(STAmount const &sa1, STAmount const &sa2)
Definition: Path_test.cpp:125
ripple::lsfHighFreeze
@ lsfHighFreeze
Definition: LedgerFormats.h:126
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:959
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:188
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:63
ripple::Logs::journal
beast::Journal journal(std::string const &name)
Definition: Log.cpp:144
ripple::sfBalance
const SF_Amount sfBalance(access, STI_AMOUNT, 2, "Balance")
Definition: SField.h:440
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:33
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:111
std::vector::begin
T begin(T... args)
ripple::STAmount::issue
Issue const & issue() const
Definition: STAmount.h:197
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::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:209
ripple::test::jtx::Env::le
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
Definition: Env.cpp:197
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:32
ripple::test::ipe
STPathElement ipe(Issue const &iss)
Definition: PayStrand_test.cpp:148
ripple::STPathElement::typeAccount
@ typeAccount
Definition: STPathSet.h:38
ripple::test::ape
STPathElement ape(AccountID const &a)
Definition: PayStrand_test.cpp:140
ripple::FeatureBitset
Definition: Feature.h:154
ripple::tecPATH_DRY
@ tecPATH_DRY
Definition: TER.h:252
ripple::test::ExistingElementPool::setupEnv
void setupEnv(jtx::Env &env, size_t numAct, size_t numCur, boost::optional< size_t > const &offererIndex)
Definition: PayStrand_test.cpp:394
std::vector::empty
T empty(T... args)
ripple::xrpIssue
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
Definition: Issue.h:97
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:32
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:92
std::vector::end
T end(T... args)
ripple::lsfLowFreeze
@ lsfLowFreeze
Definition: LedgerFormats.h:125
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::tfSetfAuth
const std::uint32_t tfSetfAuth
Definition: TxFlags.h:91
ripple::featureFlowCross
const uint256 featureFlowCross
Definition: Feature.cpp:164
ripple::STPath
Definition: STPathSet.h:212
ripple::tesSUCCESS
@ tesSUCCESS
Definition: TER.h:213
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:297
ripple::test::ElementComboIter::SB::xrp
@ xrp
ripple::noAccount
AccountID const & noAccount()
A placeholder for empty accounts.
Definition: AccountID.cpp:150
ripple::xrpCurrency
Currency const & xrpCurrency()
XRP currency.
Definition: UintTypes.cpp:121
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:114
ripple::test::DirectStepInfo::dst
AccountID dst
Definition: PayStrand_test.cpp:38
ripple::Issue::account
AccountID account
Definition: Issue.h:38
std::initializer_list
ripple::test::ExistingElementPool::getAvailCurrency
ripple::Currency getAvailCurrency()
Definition: PayStrand_test.cpp:573