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