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>
32 #include <test/jtx/PathSet.h>
48 :
srcAccount{*parseBase58<AccountID>(jv[jss::Account].asString())}
49 ,
dstAccount{*parseBase58<AccountID>(jv[jss::Destination].asString())}
52 if (jv.isMember(jss::SendMax))
55 if (jv.isMember(jss::Paths))
59 for (
auto const& path : jv[jss::Paths])
62 for (
auto const& pe : path)
64 if (pe.isMember(jss::account))
67 !pe.isMember(jss::currency) &&
68 !pe.isMember(jss::issuer));
70 *parseBase58<AccountID>(
71 pe[jss::account].asString()),
76 pe.isMember(jss::currency) && pe.isMember(jss::issuer))
82 issuer = *parseBase58<AccountID>(
83 pe[jss::issuer].asString());
85 assert(
isXRP(*parseBase58<AccountID>(
86 pe[jss::issuer].asString())));
87 p.emplace_back(std::nullopt, currency, issuer);
138 jv[field.jsonName] = value;
150 IOU const iou{peer, currency};
183 IOU const iou{acc, currency};
227 sstr <<
rate <<
" (" << q <<
")";
231 template <
class Stream>
235 stream <<
"Strand:\n";
236 for (
auto const& step : strand)
237 stream <<
"\n" << *step;
279 auto compareClose = [](Quality
const& q1, Quality
const& q2) {
282 constexpr
double tolerance = 0.0000001;
283 return relativeDistance(q1, q2) <= tolerance;
286 for (
auto const& strand : sr.second)
288 Quality
const theoreticalQ = *qualityUpperBound(sb, strand);
289 auto const f = flow<IOUAmount, IOUAmount>(
290 sb, strand, IOUAmount(10, 0), IOUAmount(5, 0), dummyJ);
291 BEAST_EXPECT(f.success);
292 Quality
const actualQ(f.out, f.in);
293 if (actualQ != theoreticalQ && !compareClose(actualQ, theoreticalQ))
295 BEAST_EXPECT(actualQ == theoreticalQ);
296 log <<
"\nAcutal != Theoretical\n";
297 log <<
"\nTQ: " << prettyQuality(theoreticalQ) <<
"\n";
298 log <<
"AQ: " << prettyQuality(actualQ) <<
"\n";
299 logStrand(log, strand);
301 if (expectedQ && expectedQ != theoreticalQ &&
302 !compareClose(*expectedQ, theoreticalQ))
304 BEAST_EXPECT(expectedQ == theoreticalQ);
305 log <<
"\nExpected != Theoretical\n";
306 log <<
"\nTQ: " << prettyQuality(theoreticalQ) <<
"\n";
307 log <<
"EQ: " << prettyQuality(*expectedQ) <<
"\n";
308 logStrand(log, strand);
317 testcase(
"Direct Step");
349 int const numTestIterations = reqNumIterations.
value_or(250);
360 for (
int i = 0; i < numTestIterations; ++i)
365 auto const alice =
Account(
"alice" + iterAsStr);
366 auto const bob =
Account(
"bob" + iterAsStr);
367 auto const carol =
Account(
"carol" + iterAsStr);
368 auto const dan =
Account(
"dan" + iterAsStr);
371 numAccounts == 4,
"Path is only correct for four accounts");
372 path const accountsPath(accounts[1], accounts[2]);
373 env.
fund(
XRP(10000), alice, bob, carol, dan);
386 if (j == numAccounts)
390 env, accounts[ii], accounts[j], currency);
392 env, accounts[ii], accounts[j], currency);
396 IOU const iou{accounts.back(), currency};
398 pay(accounts.front(), accounts.back(), iou(paymentAmount)),
402 testCase(rcp, env.
closed());
409 testcase(
"Book Step");
421 int const numTestIterations = reqNumIterations.
value_or(100);
435 for (
int i = 0; i < numTestIterations; ++i)
438 auto const alice =
Account(
"alice" + iterAsStr);
439 auto const bob =
Account(
"bob" + iterAsStr);
440 auto const carol =
Account(
"carol" + iterAsStr);
441 auto const dan =
Account(
"dan" + iterAsStr);
442 auto const oscar =
Account(
"oscar" + iterAsStr);
443 auto const USDB = bob[
"USD"];
444 auto const EURC = carol[
"EUR"];
447 {alice, bob, carol, dan, oscar}};
452 path const bookPath(~EURC);
454 env.
fund(
XRP(10000), alice, bob, carol, dan, oscar);
457 for (
auto const& acc : accounts)
460 for (
auto const& currency : {usdCurrency, eurCurrency})
463 env, alice, bob, currency);
465 env, carol, dan, currency);
467 env, oscar, bob, currency);
469 env, oscar, carol, currency);
477 env(offer(oscar, USDB(50), EURC(50)));
481 IOU const srcIOU{bob, usdCurrency};
482 IOU const dstIOU{carol, eurCurrency};
484 pay(alice, dan, dstIOU(paymentAmount)),
485 sendmax(srcIOU(100 * paymentAmount)),
489 testCase(rcp, env.
closed());
496 testcase(
"Relative quality distance");
499 int exponent = 0) -> Quality {
505 return Quality{
one, v};
508 BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(100)) == 0);
509 BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(100, 1)) == 9);
510 BEAST_EXPECT(relativeDistance(toQuality(100), toQuality(110)) == .1);
512 relativeDistance(toQuality(100, 90), toQuality(110, 90)) == .1);
514 relativeDistance(toQuality(100, 90), toQuality(110, 91)) == 10);
516 relativeDistance(toQuality(100, 0), toQuality(100, 90)) == 1e90);
522 relativeDistance(toQuality(102, 0), toQuality(101, 90)) >= 1e89);
536 auto const r = stoi(s, &pos);
546 testRelativeQDistance();
547 testDirectStep(numIterations);
548 testBookStep(numIterations);