2#include <test/jtx/PathSet.h>
4#include <xrpld/app/paths/AMMContext.h>
5#include <xrpld/app/paths/Flow.h>
6#include <xrpld/app/paths/detail/Steps.h>
7#include <xrpld/app/paths/detail/StrandFlow.h>
9#include <xrpl/basics/contract.h>
10#include <xrpl/basics/random.h>
11#include <xrpl/ledger/PaymentSandbox.h>
12#include <xrpl/protocol/Feature.h>
13#include <xrpl/protocol/jss.h>
40 for (
auto const&
path : jv[jss::Paths])
43 for (
auto const& pe :
path)
45 if (pe.isMember(jss::account))
47 assert(!pe.isMember(jss::currency) && !pe.isMember(jss::issuer));
51 else if (pe.isMember(jss::currency) && pe.isMember(jss::issuer))
53 auto const currency =
to_currency(pe[jss::currency].asString());
56 issuer = *parseBase58<AccountID>(pe[jss::issuer].asString());
58 assert(
isXRP(*parseBase58<AccountID>(pe[jss::issuer].asString())));
66 paths.emplace_back(std::move(p));
107 auto const value =
static_cast<std::uint32_t>((percent / 100) * QUALITY_ONE);
108 jv[field.jsonName] = value;
116 IOU const iou{peer, currency};
141 IOU const iou{acc, currency};
175 sstr <<
rate <<
" (" << q <<
")";
179 template <
class Stream>
183 stream <<
"Strand:\n";
184 for (
auto const& step : strand)
185 stream <<
"\n" << *step;
230 auto compareClose = [](Quality
const& q1, Quality
const& q2) {
233 constexpr double tolerance = 0.0000001;
234 return relativeDistance(q1, q2) <= tolerance;
237 for (
auto const& strand : sr.second)
239 Quality
const theoreticalQ = *qualityUpperBound(sb, strand);
240 auto const f = flow<IOUAmount, IOUAmount>(sb, strand, IOUAmount(10, 0), IOUAmount(5, 0), dummyJ);
241 BEAST_EXPECT(f.success);
242 Quality
const actualQ(f.out, f.in);
243 if (actualQ != theoreticalQ && !compareClose(actualQ, theoreticalQ))
245 BEAST_EXPECT(actualQ == theoreticalQ);
246 log <<
"\nActual != Theoretical\n";
251 if (expectedQ && expectedQ != theoreticalQ && !compareClose(*expectedQ, theoreticalQ))
253 BEAST_EXPECT(expectedQ == theoreticalQ);
254 log <<
"\nExpected != Theoretical\n";
298 int const numTestIterations = reqNumIterations.
value_or(250);
309 for (
int i = 0; i < numTestIterations; ++i)
314 auto const alice =
Account(
"alice" + iterAsStr);
315 auto const bob =
Account(
"bob" + iterAsStr);
316 auto const carol =
Account(
"carol" + iterAsStr);
317 auto const dan =
Account(
"dan" + iterAsStr);
319 static_assert(numAccounts == 4,
"Path is only correct for four accounts");
320 path const accountsPath(accounts[1], accounts[2]);
321 env.
fund(
XRP(10000), alice, bob, carol, dan);
334 if (j == numAccounts)
337 rndAccParams.
setupTrustLines(env, accounts[ii], accounts[j], currency);
342 IOU const iou{accounts.back(), currency};
365 int const numTestIterations = reqNumIterations.
value_or(100);
379 for (
int i = 0; i < numTestIterations; ++i)
382 auto const alice =
Account(
"alice" + iterAsStr);
383 auto const bob =
Account(
"bob" + iterAsStr);
384 auto const carol =
Account(
"carol" + iterAsStr);
385 auto const dan =
Account(
"dan" + iterAsStr);
386 auto const oscar =
Account(
"oscar" + iterAsStr);
387 auto const USDB = bob[
"USD"];
388 auto const EURC = carol[
"EUR"];
395 path const bookPath(~EURC);
397 env.
fund(
XRP(10000), alice, bob, carol, dan, oscar);
400 for (
auto const& acc : accounts)
403 for (
auto const& currency : {usdCurrency, eurCurrency})
416 env(
offer(oscar, USDB(50), EURC(50)));
420 IOU const srcIOU{bob, usdCurrency};
421 IOU const dstIOU{carol, eurCurrency};
423 pay(alice, dan, dstIOU(paymentAmount)),
424 sendmax(srcIOU(100 * paymentAmount)),
435 testcase(
"Relative quality distance");
437 auto toQuality = [](
std::uint64_t mantissa,
int exponent = 0) -> Quality {
443 return Quality{one, v};
446 BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(100)) == 0);
447 BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(100, 1)) == 9);
448 BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(110)) == .1);
449 BEAST_EXPECT(relativeDistance(toQuality(100, 90), toQuality(110, 90)) == .1);
450 BEAST_EXPECT(relativeDistance(toQuality(100, 90), toQuality(110, 91)) == 10);
451 BEAST_EXPECT(relativeDistance(toQuality(100, 0), toQuality(100, 90)) == 1e90);
456 BEAST_EXPECT(relativeDistance(toQuality(102, 0), toQuality(101, 90)) >= 1e89);
470 auto const r = stoi(s, &pos);
486BEAST_DEFINE_TESTSUITE_PRIO(TheoreticalQuality, app,
xrpl, 3);
bool isMember(char const *key) const
Return true if the object has a member named key.
A generic endpoint for log messages.
static Sink & getNullSink()
Returns a Sink which does nothing.
log_os< char > log
Logging output stream.
testcase_t testcase
Memberspace for declaring test cases.
std::string const & arg() const
Return the argument associated with the runner.
Maintains AMM info per overall payment engine execution and individual iteration.
A wrapper which makes credits unavailable to balances.
Issue const & issue() const
void emplace_back(Args &&... args)
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 probRedeem_
std::uniform_real_distribution qualityPercentDist_
void setupTrustLines(jtx::Env &env, jtx::Account const &acc1, jtx::Account const &acc2, Currency const ¤cy)
void setInitialBalance(jtx::Env &env, jtx::Account const &acc, jtx::Account const &peer, 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 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 probChangeDefault_
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.
std::shared_ptr< ReadView const > closed()
Returns the last closed ledger.
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Json::Value json(JsonValue &&jv, FN const &... fN)
Create JSON from parameters.
Converts to IOU Issue or STAmount.
Set Paths, SendMax on a JTx.
Sets the SendMax on a JTx.
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.
XRP_t const XRP
Converts to XRP Issue or STAmount.
Json::Value pay(AccountID const &account, AccountID const &to, AnyAmount amount)
Create a payment.
FeatureBitset testable_amendments()
Json::Value offer(Account const &account, STAmount const &takerPays, STAmount const &takerGets, std::uint32_t flags)
Create an offer.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool isXRP(AccountID const &c)
std::optional< AccountID > parseBase58(std::string const &s)
Parse AccountID from checked, base58 string.
std::pair< TER, std::vector< Strand > > toStrands(ReadView const &view, AccountID const &src, AccountID const &dst, Issue const &deliver, std::optional< Quality > const &limitQuality, std::optional< Issue > const &sendMax, STPathSet const &paths, bool addDefaultPath, bool ownerPaysTransferFee, OfferCrossing offerCrossing, AMMContext &ammContext, std::optional< uint256 > const &domainID, beast::Journal j)
Create a Strand for each specified path (including the default path, if indicated)
STAmount amountFromJson(SField const &name, Json::Value const &v)
constexpr std::uint32_t tfNoRippleDirect
Issue const & noIssue()
Returns an asset specifier that represents no account and currency.
constexpr std::uint32_t tfPartialPayment
bool to_currency(Currency &, std::string const &)
Tries to convert a string to a Currency, returns true on success.
std::optional< STAmount > sendMax
RippleCalcTestParams(Json::Value const &jv)