diff --git a/src/ripple/ledger/impl/ApplyStateTable.cpp b/src/ripple/ledger/impl/ApplyStateTable.cpp index aa04f2962..2f2c568bf 100644 --- a/src/ripple/ledger/impl/ApplyStateTable.cpp +++ b/src/ripple/ledger/impl/ApplyStateTable.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -614,25 +615,14 @@ ApplyStateTable::threadOwners (ReadView const& base, SLE const> const& sle, Mods& mods, beast::Journal j) { - switch(sle->getType()) + LedgerEntryType const ledgerType {sle->getType()}; + switch(ledgerType) { case ltACCOUNT_ROOT: { // Nothing to do break; } - case ltESCROW: - { - threadTx (base, meta, (*sle)[sfAccount], mods, j); - threadTx (base, meta, (*sle)[sfDestination], mods, j); - break; - } - case ltPAYCHAN: - { - threadTx (base, meta, (*sle)[sfAccount], mods, j); - threadTx (base, meta, (*sle)[sfDestination], mods, j); - break; - } case ltRIPPLE_STATE: { threadTx (base, meta, (*sle)[sfLowLimit].getIssuer(), mods, j); @@ -642,9 +632,16 @@ ApplyStateTable::threadOwners (ReadView const& base, default: { // If sfAccount is present, thread to that account - if ((*sle)[~sfAccount]) - threadTx (base, meta, (*sle)[sfAccount], mods, j); - break; + if (auto const optSleAcct {(*sle)[~sfAccount]}) + threadTx (base, meta, *optSleAcct, mods, j); + + // Don't thread a check's sfDestination unless the amendment is enabled + if (ledgerType == ltCHECK && !base.rules().enabled(fixCheckThreading)) + break; + + // If sfDestination is present, thread to that account + if (auto const optSleDest {(*sle)[~sfDestination]}) + threadTx (base, meta, *optSleDest, mods, j); } } } diff --git a/src/ripple/protocol/Feature.h b/src/ripple/protocol/Feature.h index 5993379b2..6109cd897 100644 --- a/src/ripple/protocol/Feature.h +++ b/src/ripple/protocol/Feature.h @@ -84,7 +84,8 @@ class FeatureCollections "fix1578", "MultiSignReserve", "fixTakerDryOfferRemoval", - "fixMasterKeyAsRegularKey" + "fixMasterKeyAsRegularKey", + "fixCheckThreading", }; std::vector features; @@ -371,6 +372,7 @@ extern uint256 const fix1578; extern uint256 const featureMultiSignReserve; extern uint256 const fixTakerDryOfferRemoval; extern uint256 const fixMasterKeyAsRegularKey; +extern uint256 const fixCheckThreading; } // ripple diff --git a/src/ripple/protocol/impl/Feature.cpp b/src/ripple/protocol/impl/Feature.cpp index 1645a01c4..b6a499090 100644 --- a/src/ripple/protocol/impl/Feature.cpp +++ b/src/ripple/protocol/impl/Feature.cpp @@ -118,6 +118,7 @@ detail::supportedAmendments () "MultiSignReserve", "fixTakerDryOfferRemoval", "fixMasterKeyAsRegularKey", + "fixCheckThreading", }; return supported; } @@ -175,5 +176,6 @@ uint256 const fix1578 = *getRegisteredFeature("fix1578"); uint256 const featureMultiSignReserve = *getRegisteredFeature("MultiSignReserve"); uint256 const fixTakerDryOfferRemoval = *getRegisteredFeature("fixTakerDryOfferRemoval"); uint256 const fixMasterKeyAsRegularKey = *getRegisteredFeature("fixMasterKeyAsRegularKey"); +uint256 const fixCheckThreading = *getRegisteredFeature("fixCheckThreading"); } // ripple diff --git a/src/test/rpc/AccountTx_test.cpp b/src/test/rpc/AccountTx_test.cpp index 2eaf09b38..493d29eb4 100644 --- a/src/test/rpc/AccountTx_test.cpp +++ b/src/test/rpc/AccountTx_test.cpp @@ -225,9 +225,9 @@ class AccountTx_test : public beast::unit_test::suite }; NetClock::time_point const nextTime {env.now() + 2s}; - + Json::Value escrowWithFinish {escrow (alice, alice, XRP (500))}; - escrowWithFinish[sfFinishAfter.jsonName] = + escrowWithFinish[sfFinishAfter.jsonName] = nextTime.time_since_epoch().count(); std::uint32_t const escrowFinishSeq {env.seq(alice)}; @@ -279,10 +279,10 @@ class AccountTx_test : public beast::unit_test::suite payChanCreate[sfPublicKey.jsonName] = strHex (alice.pk().slice()); env (payChanCreate, sig (alie)); env.close(); - + std::string const payChanIndex { strHex (keylet::payChan (alice, gw, payChanSeq).key)}; - + { Json::Value payChanFund; payChanFund[jss::TransactionType] = jss::PaymentChannelFund; @@ -356,7 +356,7 @@ class AccountTx_test : public beast::unit_test::suite { BEAST_EXPECT(txNode[jss::validated].asBool() == true); BEAST_EXPECT( - txNode[jss::tx][sfTransactionType.jsonName].asString() == + txNode[jss::tx][sfTransactionType.jsonName].asString() == sane.txType); // Make sure all of the expected node types are present. @@ -415,13 +415,13 @@ class AccountTx_test : public beast::unit_test::suite { // txType, created, deleted, modified { 0, jss::DepositPreauth, {jss::DepositPreauth}, {}, {jss::AccountRoot, jss::DirectoryNode}}, - { 1, jss::CheckCancel, {}, {jss::Check}, {jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}}, - { 2, jss::CheckCash, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}}, - { 3, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}}, - { 4, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}}, - { 5, jss::PaymentChannelClaim, {}, {jss::PayChannel}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode}}, + { 1, jss::CheckCancel, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}}, + { 2, jss::CheckCash, {}, {jss::Check}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}}, + { 3, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}}, + { 4, jss::CheckCreate, {jss::Check}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode, jss::DirectoryNode}}, + { 5, jss::PaymentChannelClaim, {}, {jss::PayChannel}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode}}, { 6, jss::PaymentChannelFund, {}, {}, {jss::AccountRoot, jss::PayChannel }}, - { 7, jss::PaymentChannelCreate, {jss::PayChannel}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode}}, + { 7, jss::PaymentChannelCreate, {jss::PayChannel}, {}, {jss::AccountRoot, jss::AccountRoot, jss::DirectoryNode}}, { 8, jss::EscrowCancel, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}}, { 9, jss::EscrowFinish, {}, {jss::Escrow}, {jss::AccountRoot, jss::DirectoryNode}}, { 10, jss::EscrowCreate, {jss::Escrow}, {}, {jss::AccountRoot, jss::DirectoryNode}},