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