diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index f54fb9e974..ac393eae98 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -32,6 +32,7 @@ // If you add an amendment here, then do not forget to increment `numFeatures` // in include/xrpl/protocol/Feature.h. +XRPL_FIX (PayChanCancelAfter, Supported::yes, VoteBehavior::DefaultNo) // Check flags in Credential transactions XRPL_FIX (InvalidTxFlags, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (FrozenLPTokenTransfer, Supported::yes, VoteBehavior::DefaultNo) diff --git a/src/test/app/PayChan_test.cpp b/src/test/app/PayChan_test.cpp index 4fd5f0bb26..f2fcf344da 100644 --- a/src/test/app/PayChan_test.cpp +++ b/src/test/app/PayChan_test.cpp @@ -402,6 +402,52 @@ struct PayChan_test : public beast::unit_test::suite BEAST_EXPECT(!channelExists(*env.current(), chan)); BEAST_EXPECT(env.balance(alice) == preAlice + channelFunds); } + // fixPayChanCancelAfter + // CancelAfter should be greater than close time + { + for (bool const withFixPayChan : {true, false}) + { + auto const amend = withFixPayChan + ? features + : features - fixPayChanCancelAfter; + Env env{*this, amend}; + env.fund(XRP(10000), alice, bob); + env.close(); + + auto const pk = alice.pk(); + auto const settleDelay = 100s; + auto const channelFunds = XRP(1000); + NetClock::time_point const cancelAfter = + env.current()->info().parentCloseTime - 1s; + auto const txResult = + withFixPayChan ? ter(tecEXPIRED) : ter(tesSUCCESS); + env(create( + alice, bob, channelFunds, settleDelay, pk, cancelAfter), + txResult); + } + } + // fixPayChanCancelAfter + // CancelAfter can be equal to the close time + { + for (bool const withFixPayChan : {true, false}) + { + auto const amend = withFixPayChan + ? features + : features - fixPayChanCancelAfter; + Env env{*this, amend}; + env.fund(XRP(10000), alice, bob); + env.close(); + + auto const pk = alice.pk(); + auto const settleDelay = 100s; + auto const channelFunds = XRP(1000); + NetClock::time_point const cancelAfter = + env.current()->info().parentCloseTime; + env(create( + alice, bob, channelFunds, settleDelay, pk, cancelAfter), + ter(tesSUCCESS)); + } + } } void diff --git a/src/xrpld/app/tx/detail/Escrow.cpp b/src/xrpld/app/tx/detail/Escrow.cpp index 5cf5e8740b..bc9ad0a11f 100644 --- a/src/xrpld/app/tx/detail/Escrow.cpp +++ b/src/xrpld/app/tx/detail/Escrow.cpp @@ -76,18 +76,6 @@ namespace ripple { //------------------------------------------------------------------------------ -/** Has the specified time passed? - - @param now the current time - @param mark the cutoff point - @return true if \a now refers to a time strictly after \a mark, else false. -*/ -static inline bool -after(NetClock::time_point now, std::uint32_t mark) -{ - return now.time_since_epoch().count() > mark; -} - TxConsequences EscrowCreate::makeTxConsequences(PreflightContext const& ctx) { diff --git a/src/xrpld/app/tx/detail/PayChan.cpp b/src/xrpld/app/tx/detail/PayChan.cpp index fa5d44fb00..25cdd0e69a 100644 --- a/src/xrpld/app/tx/detail/PayChan.cpp +++ b/src/xrpld/app/tx/detail/PayChan.cpp @@ -252,6 +252,13 @@ PayChanCreate::doApply() if (!sle) return tefINTERNAL; + if (ctx_.view().rules().enabled(fixPayChanCancelAfter)) + { + auto const closeTime = ctx_.view().info().parentCloseTime; + if (ctx_.tx[~sfCancelAfter] && after(closeTime, ctx_.tx[sfCancelAfter])) + return tecEXPIRED; + } + auto const dst = ctx_.tx[sfDestination]; // Create PayChan in ledger. diff --git a/src/xrpld/ledger/View.h b/src/xrpld/ledger/View.h index 85aa02f1b4..bb04fa8b87 100644 --- a/src/xrpld/ledger/View.h +++ b/src/xrpld/ledger/View.h @@ -592,6 +592,15 @@ deleteAMMTrustLine( std::optional const& ammAccountID, beast::Journal j); +/** Has the specified time passed? + + @param now the current time + @param mark the cutoff point + @return true if \a now refers to a time strictly after \a mark, else false. +*/ +bool +after(NetClock::time_point now, std::uint32_t mark); + } // namespace ripple #endif diff --git a/src/xrpld/ledger/detail/View.cpp b/src/xrpld/ledger/detail/View.cpp index 1860f61445..2a5224ebf1 100644 --- a/src/xrpld/ledger/detail/View.cpp +++ b/src/xrpld/ledger/detail/View.cpp @@ -2123,4 +2123,10 @@ rippleCredit( saAmount.asset().value()); } +bool +after(NetClock::time_point now, std::uint32_t mark) +{ + return now.time_since_epoch().count() > mark; +} + } // namespace ripple