2#include <test/jtx/PathSet.h>
4#include <xrpld/core/Config.h>
6#include <xrpl/basics/contract.h>
7#include <xrpl/basics/safe_cast.h>
8#include <xrpl/ledger/PaymentSandbox.h>
9#include <xrpl/protocol/Feature.h>
10#include <xrpl/protocol/jss.h>
11#include <xrpl/tx/paths/RippleCalc.h>
12#include <xrpl/tx/paths/detail/Steps.h>
13#include <xrpl/tx/transactors/dex/AMMContext.h>
49 return lsfHighNoRipple;
50 return lsfLowNoRipple;
65 auto const useHigh = src.
id() > dst.
id();
66 return sle->isFlag(
trustFlag(flag, useHigh));
68 Throw<std::runtime_error>(
"No line in getTrustFlag");
104template <
class Iter,
class StepInfo,
class... Args>
113template <
class... Args>
115equal(Strand
const& strand, Args&&... args)
117 if (strand.size() !=
sizeof...(Args))
170 static_assert(safe_cast<size_t>(
SB::last) <=
sizeof(
decltype(
state_)) * 8,
"");
179 return (
state_ & (1 << safe_cast<int>(s))) != 0;
185 for (
auto const s : sb)
198 for (
auto const s : sb)
239 template <
class Col,
class AccFactory,
class IssFactory,
class CurrencyFactory>
245 CurrencyFactory&& currencyF,
358 assert(!offererIndex || offererIndex < numAct);
367 constexpr size_t bufSize = 32;
370 for (
size_t id = 0;
id < numAct; ++id)
372 snprintf(buf, bufSize,
"A%zu",
id);
376 for (
size_t id = 0;
id < numCur; ++id)
380 snprintf(buf, bufSize,
"CC%zu",
id);
384 snprintf(buf, bufSize,
"C%zu",
id);
388 snprintf(buf, bufSize,
"%zu",
id);
400 for (
auto ai2 =
accounts.begin(); ai2 != aie; ++ai2)
406 env.
trust((*ai1)[cn](1'000'000), *ai2);
412 auto const& src = *ai1;
413 auto const& dst = *ai2;
414 env(
pay(src, dst, src[cn](500000)));
430 for (
auto takerPays = ious.
begin(), ie = ious.
end(); takerPays != ie; ++takerPays)
432 for (
auto takerGets = ious.
begin(); takerGets != ie; ++takerGets)
434 if (takerPays == takerGets)
436 auto const owner = offererIndex ?
accounts[*offererIndex] : takerGets->account;
437 if (owner.id() != takerGets->account.id())
438 env(
pay(takerGets->account, owner, (*takerGets)(1000)));
440 env(
offer(owner, (*takerPays)(1000), (*takerGets)(1000)),
txflags(tfPassive));
446 for (
auto const& iou : ious)
448 auto const owner = offererIndex ?
accounts[*offererIndex] : iou.account;
459 auto add = [&](
auto const& a) {
464 auto const b = (*sle)[sfBalance];
482 auto const sle = v.
read(k);
485 return (*sle)[sfBalance];
488 auto const sle = v.
read(k);
491 return (*sle)[sfBalance];
499 auto const b1 = xrpBalance(v1, ak);
500 auto const b2 = xrpBalance(v2, ak);
506 for (
auto ai2 =
accounts.begin(); ai2 != aie; ++ai2)
514 auto const b1 = lineBalance(v1, lk);
515 auto const b2 = lineBalance(v2, lk);
521 return diffs.
empty();
557 auto const resultSize = prefix.
size() + suffix.
size() + 2;
558 outerResult.
reserve(resultSize);
563 outerResult = prefix;
565 outerResult, accF, issF, currencyF, existingAcc, existingCur, existingIss);
571 result = outerResult;
573 result, accF, issF, currencyF, existingAcc, existingCur, existingIss);
575 f(sendMax, deliver, result);
590 auto const alice =
Account(
"alice");
591 auto const bob =
Account(
"bob");
592 auto const carol =
Account(
"carol");
595 auto const USD = gw[
"USD"];
596 auto const EUR = gw[
"EUR"];
598 auto const eurC = EUR.currency;
599 auto const usdC = USD.currency;
607 auto test = [&,
this](
609 Issue const& deliver,
613 auto&&... expSteps) {
627 BEAST_EXPECT(
ter == expTer);
628 if (
sizeof...(expSteps) != 0)
633 Env env(*
this, features);
634 env.
fund(
XRP(10000), alice, bob, gw);
635 env.
trust(USD(1000), alice, bob);
636 env.
trust(EUR(1000), alice, bob);
637 env(
pay(gw, alice, EUR(100)));
678 Env env(*
this, features);
679 env.
fund(
XRP(10000), alice, bob, carol, gw);
683 env.
trust(USD(1000), alice, bob, carol);
686 env(
pay(gw, alice, USD(100)));
687 env(
pay(gw, carol, USD(100)));
691 env, USD,
std::nullopt,
STPath(),
tesSUCCESS, D{alice, gw, usdC}, D{gw, bob, usdC});
692 env.
trust(EUR(1000), alice, bob);
717 env.
trust(carol[
"USD"](1000), bob);
726 D{carol, bob, usdC});
846 Env env(*
this, features);
848 env.
fund(
XRP(10000), alice, bob, carol, gw);
849 env.
trust(USD(10000), alice, bob, carol);
850 env.
trust(EUR(10000), alice, bob, carol);
852 env(
pay(gw, bob, USD(100)));
853 env(
pay(gw, bob, EUR(100)));
855 env(
offer(bob,
XRP(100), USD(100)));
856 env(
offer(bob, USD(100), EUR(100)),
txflags(tfPassive));
857 env(
offer(bob, EUR(100), USD(100)),
txflags(tfPassive));
860 env(
pay(alice, carol, USD(100)),
861 path(~USD, ~EUR, ~USD),
868 Env env(*
this, features);
870 env.
trust(USD(1000), alice, bob);
871 env(
pay(gw, alice, USD(100)));
877 Env env(*
this, features);
878 env.
fund(
XRP(10000), alice, bob, gw);
879 env.
trust(USD(1000), alice, bob);
880 env(
pay(gw, alice, USD(100)));
883 env(
fset(alice, asfGlobalFreeze));
885 env(
fclear(alice, asfGlobalFreeze));
889 env(
fset(gw, asfGlobalFreeze));
891 env(
fclear(gw, asfGlobalFreeze));
895 env(
fset(bob, asfGlobalFreeze));
897 env(
fclear(bob, asfGlobalFreeze));
902 Env env(*
this, features);
903 env.
fund(
XRP(10000), alice, bob, gw);
904 env.
trust(USD(1000), alice, bob);
905 env(
pay(gw, alice, USD(100)));
907 env(
trust(gw, alice[
"USD"](0), tfSetFreeze));
915 Env env(*
this, features);
916 env.
fund(
XRP(10000), alice, bob, gw);
917 env(
fset(gw, asfRequireAuth));
918 env.
trust(USD(1000), alice, bob);
920 env(
trust(gw, alice[
"USD"](1000), tfSetfAuth));
922 env(
pay(gw, alice, USD(100)));
941 BEAST_EXPECT(
equal(strand, D{alice, gw, usdC}));
946 Env env(*
this, features);
947 env.
fund(
XRP(10000), alice, bob, gw);
948 env.
trust(USD(1000), alice, bob);
949 env(
pay(gw, alice, USD(100)));
980 auto const alice =
Account(
"alice");
981 auto const bob =
Account(
"bob");
982 auto const carol =
Account(
"carol");
984 auto const USD = gw[
"USD"];
985 auto const EUR = gw[
"EUR"];
988 Env env(*
this, features);
989 env.
fund(
XRP(10000), alice, bob, gw);
991 env.
trust(USD(1000), alice, bob);
992 env.
trust(EUR(1000), alice, bob);
993 env.
trust(bob[
"USD"](1000), alice, gw);
994 env.
trust(bob[
"EUR"](1000), alice, gw);
999 env(
offer(bob, bob[
"USD"](100), bob[
"EUR"](100)),
txflags(tfPassive));
1000 env(
offer(gw, USD(100), EUR(100)),
txflags(tfPassive));
1002 Path const p = [&] {
1011 env(
pay(alice, alice, EUR(1)),
1014 txflags(tfNoRippleDirect | tfPartialPayment),
1019 Env env(*
this, features);
1021 env.
fund(
XRP(10000), alice, bob, carol, gw);
1022 env.
trust(USD(10000), alice, bob, carol);
1024 env(
pay(gw, bob, USD(100)));
1030 env(
pay(alice, carol,
XRP(100)),
1037 Env env(*
this, features);
1039 env.
fund(
XRP(10000), alice, bob, carol, gw);
1040 env.
trust(USD(10000), alice, bob, carol);
1042 env(
pay(gw, bob, USD(100)));
1048 env(
pay(alice, carol,
XRP(100)),
1060 using namespace jtx;
1062 auto const alice =
Account(
"alice");
1063 auto const bob =
Account(
"bob");
1064 auto const carol =
Account(
"carol");
1065 auto const gw =
Account(
"gw");
1066 auto const USD = gw[
"USD"];
1067 auto const EUR = gw[
"EUR"];
1068 auto const CNY = gw[
"CNY"];
1071 Env env(*
this, features);
1073 env.
fund(
XRP(10000), alice, bob, carol, gw);
1074 env.
trust(USD(10000), alice, bob, carol);
1076 env(
pay(gw, bob, USD(100)));
1077 env(
pay(gw, alice, USD(100)));
1083 env(
pay(alice, carol, USD(100)),
1090 Env env(*
this, features);
1092 env.
fund(
XRP(10000), alice, bob, carol, gw);
1093 env.
trust(USD(10000), alice, bob, carol);
1094 env.
trust(EUR(10000), alice, bob, carol);
1095 env.
trust(CNY(10000), alice, bob, carol);
1097 env(
pay(gw, bob, USD(100)));
1098 env(
pay(gw, bob, EUR(100)));
1099 env(
pay(gw, bob, CNY(100)));
1102 env(
offer(bob, USD(100), EUR(100)),
txflags(tfPassive));
1103 env(
offer(bob, EUR(100), CNY(100)),
txflags(tfPassive));
1106 env(
pay(alice, carol, CNY(100)),
1108 path(~USD, ~EUR, ~USD, ~CNY),
1118 using namespace jtx;
1120 auto const alice =
Account(
"alice");
1121 auto const bob =
Account(
"bob");
1122 auto const gw =
Account(
"gw");
1123 auto const USD = gw[
"USD"];
1125 Env env(*
this, features);
1126 env.
fund(
XRP(10000), alice, bob, gw);
1201 using namespace jtx;
1209 testLoop(sa - featurePermissionedDEX);
1216BEAST_DEFINE_TESTSUITE(PayStrand, app,
xrpl);
testcase_t testcase
Memberspace for declaring test cases.
void fail(String const &reason, char const *file, int line)
Record a failure.
Maintains AMM info per overall payment engine execution and individual iteration.
A currency issued by an account.
A wrapper which makes credits unavailable to balances.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
Issue const & issue() const
virtual beast::Journal getJournal(std::string const &name)=0
static Output rippleCalculate(PaymentSandbox &view, STAmount const &saMaxAmountReq, STAmount const &saDstAmountReq, AccountID const &uDstAccountID, AccountID const &uSrcAccountID, STPathSet const &spsPaths, std::optional< uint256 > const &domainID, ServiceRegistry ®istry, Input const *const pInputs=nullptr)
ElementComboIter(STPathElement const *prev=nullptr)
bool const allowCompound_
void emplace_into(Col &col, AccFactory &&accF, IssFactory &&issF, CurrencyFactory &¤cyF, std::optional< AccountID > const &existingAcc, std::optional< Currency > const &existingCur, std::optional< AccountID > const &existingIss)
bool hasAny(std::initializer_list< SB > sb) const
STPathElement const * prev_
size_t count(std::initializer_list< SB > sb) const
Path & push_back(Issue const &iss)
Immutable cryptographic account descriptor.
AccountID id() const
Returns the Account ID.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
std::shared_ptr< SLE const > le(Account const &account) const
Return an account root.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
void trust(STAmount const &amount, Account const &account)
Establish trust lines.
void require(Args const &... args)
Check a set of requirements.
std::shared_ptr< OpenView const > current() const
Returns the current ledger.
Set Paths, SendMax on a JTx.
Sets the SendMax on a JTx.
Set the expected result code for a JTx The test will fail if the code doesn't match.
T emplace_back(T... args)
Keylet line(AccountID const &id0, AccountID const &id1, Currency const ¤cy) noexcept
The index of a trust line for a given currency.
Keylet account(AccountID const &id) noexcept
AccountID root.
Json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
XRP_t const XRP
Converts to XRP Issue or STAmount.
STPathElement allPathElements(AccountID const &a, Issue const &iss)
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
Json::Value fclear(Account const &account, std::uint32_t off)
Remove account flag.
STPathElement cpe(Currency const &c)
FeatureBitset testable_amendments()
Json::Value fset(Account const &account, std::uint32_t on, std::uint32_t off=0)
Add and/or remove flag.
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
STPathElement ape(AccountID const &a)
bool bookStepEqual(Step const &step, xrpl::Book const &book)
STPathElement ipe(Issue const &iss)
bool getTrustFlag(jtx::Env const &env, jtx::Account const &src, jtx::Account const &dst, Currency const &cur, TrustFlag flag)
std::uint32_t trustFlag(TrustFlag f, bool useHigh)
bool strandEqualHelper(Iter i)
bool xrpEndpointStepEqual(Step const &step, AccountID const &acc)
bool directStepEqual(Step const &step, AccountID const &src, AccountID const &dst, Currency const ¤cy)
bool equal(std::unique_ptr< Step > const &s1, DirectStepInfo const &dsi)
STPathElement iape(AccountID const &account)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Issue const & xrpIssue()
Returns an asset specifier that represents XRP.
std::pair< TER, Strand > toStrand(ReadView const &sb, AccountID const &src, AccountID const &dst, Issue const &deliver, std::optional< Quality > const &limitQuality, std::optional< Issue > const &sendMaxIssue, STPath const &path, bool ownerPaysTransferFee, OfferCrossing offerCrossing, AMMContext &ammContext, std::optional< uint256 > const &domainID, beast::Journal j)
Create a Strand for the specified path.
Currency const & xrpCurrency()
XRP currency.
AccountID const & noAccount()
A placeholder for empty accounts.
bool isTesSuccess(TER x) noexcept
AccountID const & xrpAccount()
Compute AccountID from public key.
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
A pair of SHAMap key and LedgerEntryType.
StateGuard(ExistingElementPool &p)
std::vector< jtx::Account > accounts
std::int64_t totalXRP(ReadView const &v, bool incRoot)
bool checkBalances(ReadView const &v1, ReadView const &v2)
ResetState getResetState() const
std::vector< xrpl::Currency > currencies
void resetTo(ResetState const &s)
jtx::Account getAccount(size_t id)
jtx::Account getAvailAccount()
void setupEnv(jtx::Env &env, size_t numAct, size_t numCur, std::optional< size_t > const &offererIndex)
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)
std::vector< std::string > currencyNames
xrpl::Currency getCurrency(size_t id)
xrpl::Currency getAvailCurrency()
void testRIPD1373(FeatureBitset features)
void testLoop(FeatureBitset features)
void run() override
Runs the suite.
void testToStrand(FeatureBitset features)
void testNoAccount(FeatureBitset features)