20 #include <ripple/app/paths/Flow.h>
21 #include <ripple/app/paths/impl/Steps.h>
22 #include <ripple/app/paths/impl/StrandFlow.h>
23 #include <ripple/basics/contract.h>
24 #include <ripple/basics/random.h>
25 #include <ripple/core/Config.h>
26 #include <ripple/ledger/ApplyViewImpl.h>
27 #include <ripple/ledger/PaymentSandbox.h>
28 #include <ripple/ledger/Sandbox.h>
29 #include <ripple/protocol/Feature.h>
30 #include <ripple/protocol/jss.h>
31 #include "ripple/app/paths/AMMContext.h"
33 #include <test/jtx/PathSet.h>
49 :
srcAccount{*parseBase58<AccountID>(jv[jss::Account].asString())}
50 ,
dstAccount{*parseBase58<AccountID>(jv[jss::Destination].asString())}
53 if (jv.isMember(jss::SendMax))
56 if (jv.isMember(jss::Paths))
60 for (
auto const& path : jv[jss::Paths])
63 for (
auto const& pe : path)
65 if (pe.isMember(jss::account))
68 !pe.isMember(jss::currency) &&
69 !pe.isMember(jss::issuer));
71 *parseBase58<AccountID>(
72 pe[jss::account].asString()),
77 pe.isMember(jss::currency) && pe.isMember(jss::issuer))
83 issuer = *parseBase58<AccountID>(
84 pe[jss::issuer].asString());
86 assert(
isXRP(*parseBase58<AccountID>(
87 pe[jss::issuer].asString())));
88 p.emplace_back(std::nullopt, currency, issuer);
139 jv[field.jsonName] = value;
151 IOU const iou{peer, currency};
184 IOU const iou{acc, currency};
228 sstr <<
rate <<
" (" << q <<
")";
232 template <
class Stream>
236 stream <<
"Strand:\n";
237 for (
auto const& step : strand)
238 stream <<
"\n" << *step;
282 auto compareClose = [](Quality
const& q1, Quality
const& q2) {
285 constexpr
double tolerance = 0.0000001;
286 return relativeDistance(q1, q2) <= tolerance;
289 for (
auto const& strand : sr.second)
291 Quality
const theoreticalQ = *qualityUpperBound(sb, strand);
292 auto const f = flow<IOUAmount, IOUAmount>(
293 sb, strand, IOUAmount(10, 0), IOUAmount(5, 0), dummyJ);
294 BEAST_EXPECT(f.success);
295 Quality
const actualQ(f.out, f.in);
296 if (actualQ != theoreticalQ && !compareClose(actualQ, theoreticalQ))
298 BEAST_EXPECT(actualQ == theoreticalQ);
299 log <<
"\nAcutal != Theoretical\n";
300 log <<
"\nTQ: " << prettyQuality(theoreticalQ) <<
"\n";
301 log <<
"AQ: " << prettyQuality(actualQ) <<
"\n";
302 logStrand(log, strand);
304 if (expectedQ && expectedQ != theoreticalQ &&
305 !compareClose(*expectedQ, theoreticalQ))
307 BEAST_EXPECT(expectedQ == theoreticalQ);
308 log <<
"\nExpected != Theoretical\n";
309 log <<
"\nTQ: " << prettyQuality(theoreticalQ) <<
"\n";
310 log <<
"EQ: " << prettyQuality(*expectedQ) <<
"\n";
311 logStrand(log, strand);
320 testcase(
"Direct Step");
352 int const numTestIterations = reqNumIterations.
value_or(250);
363 for (
int i = 0; i < numTestIterations; ++i)
368 auto const alice =
Account(
"alice" + iterAsStr);
369 auto const bob =
Account(
"bob" + iterAsStr);
370 auto const carol =
Account(
"carol" + iterAsStr);
371 auto const dan =
Account(
"dan" + iterAsStr);
374 numAccounts == 4,
"Path is only correct for four accounts");
375 path const accountsPath(accounts[1], accounts[2]);
376 env.
fund(
XRP(10000), alice, bob, carol, dan);
389 if (j == numAccounts)
393 env, accounts[ii], accounts[j], currency);
395 env, accounts[ii], accounts[j], currency);
399 IOU const iou{accounts.back(), currency};
401 pay(accounts.front(), accounts.back(), iou(paymentAmount)),
405 testCase(rcp, env.
closed());
412 testcase(
"Book Step");
424 int const numTestIterations = reqNumIterations.
value_or(100);
438 for (
int i = 0; i < numTestIterations; ++i)
441 auto const alice =
Account(
"alice" + iterAsStr);
442 auto const bob =
Account(
"bob" + iterAsStr);
443 auto const carol =
Account(
"carol" + iterAsStr);
444 auto const dan =
Account(
"dan" + iterAsStr);
445 auto const oscar =
Account(
"oscar" + iterAsStr);
446 auto const USDB = bob[
"USD"];
447 auto const EURC = carol[
"EUR"];
450 {alice, bob, carol, dan, oscar}};
455 path const bookPath(~EURC);
457 env.
fund(
XRP(10000), alice, bob, carol, dan, oscar);
460 for (
auto const& acc : accounts)
463 for (
auto const& currency : {usdCurrency, eurCurrency})
466 env, alice, bob, currency);
468 env, carol, dan, currency);
470 env, oscar, bob, currency);
472 env, oscar, carol, currency);
480 env(offer(oscar, USDB(50), EURC(50)));
484 IOU const srcIOU{bob, usdCurrency};
485 IOU const dstIOU{carol, eurCurrency};
487 pay(alice, dan, dstIOU(paymentAmount)),
488 sendmax(srcIOU(100 * paymentAmount)),
492 testCase(rcp, env.
closed());
499 testcase(
"Relative quality distance");
502 int exponent = 0) -> Quality {
508 return Quality{
one, v};
511 BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(100)) == 0);
512 BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(100, 1)) == 9);
513 BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(110)) == .1);
515 relativeDistance(toQuality(100, 90), toQuality(110, 90)) == .1);
517 relativeDistance(toQuality(100, 90), toQuality(110, 91)) == 10);
519 relativeDistance(toQuality(100, 0), toQuality(100, 90)) == 1e90);
525 relativeDistance(toQuality(102, 0), toQuality(101, 90)) >= 1e89);
539 auto const r = stoi(s, &pos);
549 testRelativeQDistance();
550 testDirectStep(numIterations);
551 testBookStep(numIterations);