2#include <test/jtx/Account.h>
3#include <test/jtx/Env.h>
4#include <test/jtx/amount.h>
5#include <test/jtx/balance.h>
6#include <test/jtx/offer.h>
7#include <test/jtx/paths.h>
8#include <test/jtx/pay.h>
9#include <test/jtx/rate.h>
10#include <test/jtx/sendmax.h>
11#include <test/jtx/trust.h>
12#include <test/jtx/txflags.h>
14#include <xrpl/beast/unit_test/suite.h>
15#include <xrpl/beast/utility/Journal.h>
16#include <xrpl/beast/xor_shift_engine.h>
17#include <xrpl/json/json_value.h>
18#include <xrpl/ledger/ApplyView.h>
19#include <xrpl/ledger/PaymentSandbox.h>
20#include <xrpl/protocol/AccountID.h>
21#include <xrpl/protocol/Asset.h>
22#include <xrpl/protocol/IOUAmount.h>
23#include <xrpl/protocol/Issue.h>
24#include <xrpl/protocol/Quality.h>
25#include <xrpl/protocol/SField.h>
26#include <xrpl/protocol/STAmount.h>
27#include <xrpl/protocol/STPathSet.h>
28#include <xrpl/protocol/TER.h>
29#include <xrpl/protocol/TxFlags.h>
30#include <xrpl/protocol/UintTypes.h>
31#include <xrpl/protocol/jss.h>
32#include <xrpl/tx/paths/detail/Steps.h>
33#include <xrpl/tx/paths/detail/StrandFlow.h>
34#include <xrpl/tx/transactors/dex/AMMContext.h>
73 for (auto const& path : jv[jss::Paths])
76 for (auto const& pe : path)
78 if (pe.isMember(jss::account))
80 assert(!pe.isMember(jss::currency) && !pe.isMember(jss::issuer));
83 *parseBase58<AccountID>(pe[jss::account].asString()),
87 else if (pe.isMember(jss::currency) && pe.isMember(jss::issuer))
89 auto const currency = toCurrency(pe[jss::currency].asString());
90 std::optional<AccountID> issuer;
94 issuer = *parseBase58<AccountID>(pe[jss::issuer].asString());
99 assert(isXRP(*parseBase58<AccountID>(pe[jss::issuer].asString())));
101 p.emplaceBack(std::nullopt, currency, issuer);
108 paths.emplaceBack(std::move(p));
149 auto const value =
static_cast<std::uint32_t>((percent / 100) * QUALITY_ONE);
150 jv[field.jsonName] = value;
162 IOU const iou{peer, currency};
191 IOU const iou{acc, currency};
235 sstr <<
rate <<
" (" << q <<
")";
239 template <
class Stream>
243 stream <<
"Strand:\n";
244 for (
auto const& step : strand)
245 stream <<
"\n" << *step;
281 BEAST_EXPECT(isTesSuccess(sr.first));
283 if (!isTesSuccess(sr.first))
290 auto compareClose = [](Quality
const& q1, Quality
const& q2) {
293 static constexpr double kTolerance = 0.0000001;
294 return relativeDistance(q1, q2) <= kTolerance;
297 for (
auto const& strand : sr.second)
299 Quality
const theoreticalQ =
300 *qualityUpperBound(sb, strand);
302 flow<IOUAmount, IOUAmount>(sb, strand, IOUAmount(10, 0), IOUAmount(5, 0), dummyJ);
303 BEAST_EXPECT(f.success);
304 Quality
const actualQ(f.out, f.in);
305 if (actualQ != theoreticalQ && !compareClose(actualQ, theoreticalQ))
307 BEAST_EXPECT(actualQ == theoreticalQ);
308 log <<
"\nActual != Theoretical\n";
309 log <<
"\nTQ: " << prettyQuality(theoreticalQ) <<
"\n";
310 log <<
"AQ: " << prettyQuality(actualQ) <<
"\n";
311 logStrand(log, strand);
313 if (expectedQ && expectedQ != theoreticalQ && !compareClose(*expectedQ, theoreticalQ))
315 BEAST_EXPECT(expectedQ == theoreticalQ);
316 log <<
"\nExpected != Theoretical\n";
317 log <<
"\nTQ: " << prettyQuality(theoreticalQ) <<
"\n";
318 log <<
"EQ: " << prettyQuality(*expectedQ) <<
"\n";
319 logStrand(log, strand);
356 int const numTestIterations = reqNumIterations.
value_or(250);
367 for (
int i = 0; i < numTestIterations; ++i)
372 auto const alice =
Account(
"alice" + iterAsStr);
373 auto const bob =
Account(
"bob" + iterAsStr);
374 auto const carol =
Account(
"carol" + iterAsStr);
375 auto const dan =
Account(
"dan" + iterAsStr);
377 static_assert(kNumAccounts == 4,
"Path is only correct for four accounts");
378 Path const accountsPath(accounts[1], accounts[2]);
379 env.
fund(
XRP(10000), alice, bob, carol, dan);
392 if (j == kNumAccounts)
395 rndAccParams.
setupTrustLines(env, accounts[ii], accounts[j], currency);
400 IOU const iou{accounts.
back(), currency};
402 pay(accounts.
front(), accounts.
back(), iou(kPaymentAmount)),
423 int const numTestIterations = reqNumIterations.
value_or(100);
437 for (
int i = 0; i < numTestIterations; ++i)
440 auto const alice =
Account(
"alice" + iterAsStr);
441 auto const bob =
Account(
"bob" + iterAsStr);
442 auto const carol =
Account(
"carol" + iterAsStr);
443 auto const dan =
Account(
"dan" + iterAsStr);
444 auto const oscar =
Account(
"oscar" + iterAsStr);
445 auto const usdb = bob[
"USD"];
446 auto const eurc = carol[
"EUR"];
453 Path const bookPath(~eurc);
455 env.
fund(
XRP(10000), alice, bob, carol, dan, oscar);
458 for (
auto const& acc : accounts)
461 for (
auto const& currency : {usdCurrency, eurCurrency})
474 env(
offer(oscar, usdb(50), eurc(50)));
478 IOU const srcIOU{bob, usdCurrency};
479 IOU const dstIOU{carol, eurCurrency};
481 pay(alice, dan, dstIOU(kPaymentAmount)),
482 Sendmax(srcIOU(100 * kPaymentAmount)),
493 testcase(
"Relative quality distance");
504 BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(100)) == 0);
505 BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(100, 1)) == 9);
506 BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(110)) == .1);
507 BEAST_EXPECT(relativeDistance(toQuality(100, 90), toQuality(110, 90)) == .1);
508 BEAST_EXPECT(relativeDistance(toQuality(100, 90), toQuality(110, 91)) == 10);
509 BEAST_EXPECT(relativeDistance(toQuality(100, 0), toQuality(100, 90)) == 1e90);
514 BEAST_EXPECT(relativeDistance(toQuality(102, 0), toQuality(101, 90)) >= 1e89);
528 auto const r = stoi(s, &pos);
A generic endpoint for log messages.
static Sink & getNullSink()
Returns a Sink which does nothing.
TestcaseT testcase
Memberspace for declaring test cases.
std::string const & arg() const
Return the argument associated with the runner.
bool isMember(char const *key) const
Return true if the object has a member named key.
Maintains AMM info per overall payment engine execution and individual iteration.
A wrapper which makes credits unavailable to balances.
Represents the logical ratio of output currency to input currency.
STAmount rate() const
Returns the quality as STAmount.
Asset const & asset() const
beast::xor_shift_engine engine_
std::uint32_t const initialBalance_
void setupTrustLine(jtx::Env &env, jtx::Account const &acc, jtx::Account const &peer, Currency const ¤cy)
static constexpr double kProbRedeem
std::uniform_real_distribution qualityPercentDist_
void setupTrustLines(jtx::Env &env, jtx::Account const &acc1, jtx::Account const &acc2, Currency const ¤cy)
RandomAccountParams(std::uint32_t trustAmount=100, std::uint32_t initialBalance=50)
std::uint32_t const trustAmount_
std::uniform_real_distribution transferRateDist_
void setInitialBalance(jtx::Env &env, jtx::Account const &acc, jtx::Account const &peer, Currency const ¤cy) const
void maybeInsertQuality(json::Value &jv, QualityDirection qDir)
void maybeSetInitialBalance(jtx::Env &env, jtx::Account const &acc, jtx::Account const &peer, Currency const ¤cy)
void maybeSetTransferRate(jtx::Env &env, jtx::Account const &acc)
static constexpr double kProbChangeDefault
std::uniform_real_distribution zeroOneDist_
static std::string prettyQuality(Quality const &q)
void run() override
Runs the suite.
void testDirectStep(std::optional< int > const &reqNumIterations)
void testCase(RippleCalcTestParams const &rcp, std::shared_ptr< ReadView const > closed, std::optional< Quality > const &expectedQ={})
void testBookStep(std::optional< int > const &reqNumIterations)
void testRelativeQDistance()
static void logStrand(Stream &stream, Strand const &strand)
Immutable cryptographic account descriptor.
A transaction testing environment.
bool close(NetClock::time_point closeTime, std::optional< std::chrono::milliseconds > consensusDelay=std::nullopt)
Close and advance the ledger.
json::Value json(JsonValue &&jv, FN const &... fN)
Create JSON from parameters.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Converts to IOU Issue or STAmount.
Sets the SendMax on a JTx.
detail::XorShiftEngine<> xor_shift_engine
XOR-shift Generator.
json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
XrpT const XRP
Converts to XRP Issue or STAmount.
FeatureBitset testableAmendments()
json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
json::Value trust(Account const &account, STAmount const &amount, std::uint32_t flags)
Modify a trust line.
json::Value rate(Account const &account, double multiplier)
Set a transfer rate.
BEAST_DEFINE_TESTSUITE_PRIO(AccountDelete, app, xrpl, 2)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
BaseUInt< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
bool toCurrency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
STAmount amountFromJson(SField const &name, json::Value const &v)
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Issue const & noIssue()
Returns an asset specifier that represents no account and currency.
RippleCalcTestParams(json::Value const &jv)
std::optional< STAmount > sendMax