diff --git a/src/ripple/app/paths/impl/BookStep.cpp b/src/ripple/app/paths/impl/BookStep.cpp index ea241c2b863..634496b84d0 100644 --- a/src/ripple/app/paths/impl/BookStep.cpp +++ b/src/ripple/app/paths/impl/BookStep.cpp @@ -684,6 +684,26 @@ BookStep::check(StrandContext const& ctx) const return temBAD_PATH_LOOP; } + if (amendmentRIPD1443(ctx.view.info().parentCloseTime)) + { + if (ctx.prevStep) + { + if (auto const prev = ctx.prevStep->directStepSrcAcct()) + { + auto const& view = ctx.view; + auto const& cur = book_.in.account; + + auto sle = + view.read(keylet::line(*prev, cur, book_.in.currency)); + if (!sle) + return terNO_LINE; + if ((*sle)[sfFlags] & + ((cur > *prev) ? lsfHighNoRipple : lsfLowNoRipple)) + return terNO_RIPPLE; + } + } + } + return tesSUCCESS; } diff --git a/src/ripple/ledger/View.h b/src/ripple/ledger/View.h index 246e3b4a5ee..95d77dacd54 100644 --- a/src/ripple/ledger/View.h +++ b/src/ripple/ledger/View.h @@ -344,6 +344,8 @@ bool amendmentRIPD1274 (NetClock::time_point const closeTime); NetClock::time_point const& amendmentRIPD1298SoTime (); bool amendmentRIPD1298 (NetClock::time_point const closeTime); +NetClock::time_point const& amendmentRIPD1443SoTime (); +bool amendmentRIPD1443 (NetClock::time_point const closeTime); } // ripple diff --git a/src/ripple/ledger/impl/View.cpp b/src/ripple/ledger/impl/View.cpp index d6670b4094d..89aadb0890f 100644 --- a/src/ripple/ledger/impl/View.cpp +++ b/src/ripple/ledger/impl/View.cpp @@ -72,6 +72,20 @@ bool amendmentRIPD1298 (NetClock::time_point const closeTime) return closeTime > amendmentRIPD1298SoTime(); } +NetClock::time_point const& amendmentRIPD1443SoTime () +{ + using namespace std::chrono_literals; + // Sat Mar 11, 2017 05:00:00pm PST + static NetClock::time_point const soTime{542595600s}; + + return soTime; +} + +bool amendmentRIPD1443 (NetClock::time_point const closeTime) +{ + return closeTime > amendmentRIPD1443SoTime(); +} + // VFALCO NOTE A copy of the other one for now /** Maximum number of entries in a directory page A change would be protocol-breaking. diff --git a/src/test/app/Flow_test.cpp b/src/test/app/Flow_test.cpp index 3b573524ac2..d4679d6b956 100644 --- a/src/test/app/Flow_test.cpp +++ b/src/test/app/Flow_test.cpp @@ -1379,6 +1379,59 @@ struct Flow_test : public beast::unit_test::suite } } + void + testRIPD1443(bool withFix) + { + testcase("ripd1443"); + + using namespace jtx; + Env env(*this, features(featureFlow)); + auto const timeDelta = env.closed ()->info ().closeTimeResolution; + auto const d = withFix ? timeDelta*100 : -timeDelta*100; + auto closeTime = amendmentRIPD1443SoTime() + d; + env.close(closeTime); + + auto const alice = Account("alice"); + auto const bob = Account("bob"); + auto const carol = Account("carol"); + auto const gw = Account("gw"); + + env.fund(XRP(100000000), alice, noripple(bob), carol, gw); + env.trust(gw["USD"](10000), alice, carol); + env(trust(bob, gw["USD"](10000), tfSetNoRipple)); + env.trust(gw["USD"](10000), bob); + env.close(); + + // set no ripple between bob and the gateway + + env(pay(gw, alice, gw["USD"](1000))); + env.close(); + + env(offer(alice, bob["USD"](1000), XRP(1))); + env.close(); + + env(pay(alice, alice, XRP(1)), path(gw, bob, ~XRP), + sendmax(gw["USD"](1000)), txflags(tfNoRippleDirect), + ter(withFix ? tecPATH_DRY : tesSUCCESS)); + env.close(); + + if (withFix) + { + env.trust(bob["USD"](10000), alice); + env(pay(bob, alice, bob["USD"](1000))); + } + + env(offer(alice, XRP(1000), bob["USD"](1000))); + env.close(); + + env(pay (carol, carol, gw["USD"](1000)), path(~bob["USD"], gw), + sendmax(XRP(100000)), txflags(tfNoRippleDirect), + ter(withFix ? tecPATH_DRY : tesSUCCESS)); + env.close(); + + pass(); + } + void run() override { testDirectStep (); @@ -1394,6 +1447,8 @@ struct Flow_test : public beast::unit_test::suite testSelfFundedXRPEndpoint(true); testUnfundedOffer(true); testUnfundedOffer(false); + testRIPD1443(true); + testRIPD1443(false); } };