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