diff --git a/.github/scripts/rename/copyright.sh b/.github/scripts/rename/copyright.sh index c0f64de496..41dbdc1f94 100755 --- a/.github/scripts/rename/copyright.sh +++ b/.github/scripts/rename/copyright.sh @@ -70,9 +70,6 @@ fi if ! grep -q 'Dev Null' src/test/app/tx/apply_test.cpp; then echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/tx/apply_test.cpp)" > src/test/app/tx/apply_test.cpp fi -if ! grep -q 'Dev Null' src/test/app/NetworkOPs_test.cpp; then - echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/app/NetworkOPs_test.cpp)" > src/test/app/NetworkOPs_test.cpp -fi if ! grep -q 'Dev Null' src/test/rpc/ManifestRPC_test.cpp; then echo -e "// Copyright (c) 2020 Dev Null Productions\n\n$(cat src/test/rpc/ManifestRPC_test.cpp)" > src/test/rpc/ManifestRPC_test.cpp fi diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index 768897f665..8ce810aa2e 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -130,7 +130,7 @@ jobs: --target "${CMAKE_TARGET}" - name: Upload rippled artifact (Linux) - if: ${{ runner.os == 'Linux' }} + if: ${{ github.repository_owner == 'XRPLF' && runner.os == 'Linux' }} uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 env: BUILD_DIR: ${{ inputs.build_dir }} diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index 71be6a89d4..e5ecac614e 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -66,12 +66,10 @@ XRPL_FEATURE(AMM, Supported::yes, VoteBehavior::DefaultNo XRPL_FEATURE(Clawback, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (UniversalNumber, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(XRPFees, Supported::yes, VoteBehavior::DefaultNo) -XRPL_FEATURE(DisallowIncoming, Supported::yes, VoteBehavior::DefaultNo) XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(DeletableAccounts, Supported::yes, VoteBehavior::DefaultYes) -XRPL_FEATURE(Checks, Supported::yes, VoteBehavior::DefaultYes) XRPL_FEATURE(Flow, Supported::yes, VoteBehavior::DefaultYes) // The following amendments are obsolete, but must remain supported @@ -119,10 +117,12 @@ XRPL_RETIRE_FIX(STAmountCanonicalize) XRPL_RETIRE_FIX(TakerDryOfferRemoval) XRPL_RETIRE_FIX(TrustLinesToSelf) +XRPL_RETIRE_FEATURE(Checks) XRPL_RETIRE_FEATURE(CheckCashMakesTrustLine) XRPL_RETIRE_FEATURE(CryptoConditions) XRPL_RETIRE_FEATURE(DepositAuth) XRPL_RETIRE_FEATURE(DepositPreauth) +XRPL_RETIRE_FEATURE(DisallowIncoming) XRPL_RETIRE_FEATURE(Escrow) XRPL_RETIRE_FEATURE(EnforceInvariants) XRPL_RETIRE_FEATURE(ExpandedSignerList) diff --git a/include/xrpl/protocol/detail/transactions.macro b/include/xrpl/protocol/detail/transactions.macro index 9ba32042b4..dd1b52b355 100644 --- a/include/xrpl/protocol/detail/transactions.macro +++ b/include/xrpl/protocol/detail/transactions.macro @@ -226,7 +226,7 @@ TRANSACTION(ttPAYCHAN_CLAIM, 15, PaymentChannelClaim, #endif TRANSACTION(ttCHECK_CREATE, 16, CheckCreate, Delegation::delegatable, - featureChecks, + uint256{}, noPriv, ({ {sfDestination, soeREQUIRED}, @@ -242,7 +242,7 @@ TRANSACTION(ttCHECK_CREATE, 16, CheckCreate, #endif TRANSACTION(ttCHECK_CASH, 17, CheckCash, Delegation::delegatable, - featureChecks, + uint256{}, noPriv, ({ {sfCheckID, soeREQUIRED}, @@ -256,7 +256,7 @@ TRANSACTION(ttCHECK_CASH, 17, CheckCash, #endif TRANSACTION(ttCHECK_CANCEL, 18, CheckCancel, Delegation::delegatable, - featureChecks, + uint256{}, noPriv, ({ {sfCheckID, soeREQUIRED}, diff --git a/src/test/app/Check_test.cpp b/src/test/app/Check_test.cpp index 61e20a0098..b7d158041b 100644 --- a/src/test/app/Check_test.cpp +++ b/src/test/app/Check_test.cpp @@ -67,8 +67,6 @@ public: class Check_test : public beast::unit_test::suite { - FeatureBitset const disallowIncoming{featureDisallowIncoming}; - static uint256 getCheckIndex(AccountID const& account, std::uint32_t uSequence) { @@ -125,25 +123,6 @@ class Check_test : public beast::unit_test::suite using namespace test::jtx; Account const alice{"alice"}; - { - // If the Checks amendment is not enabled, you should not be able - // to create, cash, or cancel checks. - Env env{*this, features - featureChecks}; - - env.fund(XRP(1000), alice); - env.close(); - - uint256 const checkId{ - getCheckIndex(env.master, env.seq(env.master))}; - env(check::create(env.master, alice, XRP(100)), ter(temDISABLED)); - env.close(); - - env(check::cash(alice, checkId, XRP(100)), ter(temDISABLED)); - env.close(); - - env(check::cancel(alice, checkId), ter(temDISABLED)); - env.close(); - } { // If the Checks amendment is enabled all check-related // facilities should be available. @@ -277,24 +256,12 @@ class Check_test : public beast::unit_test::suite using namespace test::jtx; - // test flag doesn't set unless amendment enabled - { - Env env{*this, features - disallowIncoming}; - Account const alice{"alice"}; - env.fund(XRP(10000), alice); - env(fset(alice, asfDisallowIncomingCheck)); - env.close(); - auto const sle = env.le(alice); - uint32_t flags = sle->getFlags(); - BEAST_EXPECT(!(flags & lsfDisallowIncomingCheck)); - } - Account const gw{"gateway"}; Account const alice{"alice"}; Account const bob{"bob"}; IOU const USD{gw["USD"]}; - Env env{*this, features | disallowIncoming}; + Env env{*this, features}; STAmount const startBalance{XRP(1000).value()}; env.fund(startBalance, gw, alice, bob); @@ -2613,7 +2580,6 @@ public: { using namespace test::jtx; auto const sa = testable_amendments(); - testWithFeats(sa - disallowIncoming); testWithFeats(sa); testTrustLineCreation(sa); } diff --git a/src/test/app/Delegate_test.cpp b/src/test/app/Delegate_test.cpp index 9e1c777a91..e36ad9a550 100644 --- a/src/test/app/Delegate_test.cpp +++ b/src/test/app/Delegate_test.cpp @@ -1703,9 +1703,6 @@ class Delegate_test : public beast::unit_test::suite // NFTokenMint, NFTokenBurn, NFTokenCreateOffer, NFTokenCancelOffer, // NFTokenAcceptOffer are not included, they are tested separately. std::unordered_map txRequiredFeatures{ - {"CheckCreate", featureChecks}, - {"CheckCash", featureChecks}, - {"CheckCancel", featureChecks}, {"Clawback", featureClawback}, {"AMMClawback", featureAMMClawback}, {"AMMCreate", featureAMM}, diff --git a/src/test/app/NFToken_test.cpp b/src/test/app/NFToken_test.cpp index a11446df71..12ac309acb 100644 --- a/src/test/app/NFToken_test.cpp +++ b/src/test/app/NFToken_test.cpp @@ -12,8 +12,6 @@ namespace ripple { class NFTokenBaseUtil_test : public beast::unit_test::suite { - FeatureBitset const disallowIncoming{featureDisallowIncoming}; - // Helper function that returns the number of NFTs minted by an issuer. static std::uint32_t mintedCount(test::jtx::Env const& env, test::jtx::Account const& issuer) @@ -2960,19 +2958,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::suite using namespace test::jtx; - // test flag doesn't set unless amendment enabled - { - Env env{*this, features - disallowIncoming}; - Account const alice{"alice"}; - env.fund(XRP(10000), alice); - env(fset(alice, asfDisallowIncomingNFTokenOffer)); - env.close(); - auto const sle = env.le(alice); - uint32_t flags = sle->getFlags(); - BEAST_EXPECT(!(flags & lsfDisallowIncomingNFTokenOffer)); - } - - Env env{*this, features | disallowIncoming}; + Env env{*this, features}; Account const issuer{"issuer"}; Account const minter{"minter"}; @@ -7624,8 +7610,8 @@ class NFTokenDisallowIncoming_test : public NFTokenBaseUtil_test run() override { testWithFeats( - allFeatures - featureDisallowIncoming - fixNFTokenReserve - - featureNFTokenMintOffer - featureDynamicNFT); + allFeatures - fixNFTokenReserve - featureNFTokenMintOffer - + featureDynamicNFT); } }; diff --git a/src/test/app/NetworkOPs_test.cpp b/src/test/app/NetworkOPs_test.cpp index d9afe6d628..3965778221 100644 --- a/src/test/app/NetworkOPs_test.cpp +++ b/src/test/app/NetworkOPs_test.cpp @@ -1,5 +1,3 @@ -// Copyright (c) 2020 Dev Null Productions - #include #include #include diff --git a/src/test/app/PayChan_test.cpp b/src/test/app/PayChan_test.cpp index bee3167b29..59c404ae28 100644 --- a/src/test/app/PayChan_test.cpp +++ b/src/test/app/PayChan_test.cpp @@ -14,8 +14,6 @@ using namespace jtx::paychan; struct PayChan_test : public beast::unit_test::suite { - FeatureBitset const disallowIncoming{featureDisallowIncoming}; - static std::pair> channelKeyAndSle( ReadView const& view, @@ -242,20 +240,8 @@ struct PayChan_test : public beast::unit_test::suite testcase("Disallow Incoming Flag"); using namespace jtx; - // test flag doesn't set unless amendment enabled - { - Env env{*this, features - disallowIncoming}; - Account const alice{"alice"}; - env.fund(XRP(10000), alice); - env(fset(alice, asfDisallowIncomingPayChan)); - env.close(); - auto const sle = env.le(alice); - uint32_t flags = sle->getFlags(); - BEAST_EXPECT(!(flags & lsfDisallowIncomingPayChan)); - } - using namespace std::literals::chrono_literals; - Env env{*this, features | disallowIncoming}; + Env env{*this, features}; auto const alice = Account("alice"); auto const bob = Account("bob"); auto const cho = Account("cho"); @@ -2127,7 +2113,6 @@ public: { using namespace test::jtx; FeatureBitset const all{testable_amendments()}; - testWithFeats(all - disallowIncoming); testWithFeats(all); testDepositAuthCreds(); testMetaAndOwnership(all - fixIncludeKeyletFields); diff --git a/src/test/app/SetTrust_test.cpp b/src/test/app/SetTrust_test.cpp index 88e359ab23..07573cf13f 100644 --- a/src/test/app/SetTrust_test.cpp +++ b/src/test/app/SetTrust_test.cpp @@ -9,8 +9,6 @@ namespace test { class SetTrust_test : public beast::unit_test::suite { - FeatureBitset const disallowIncoming{featureDisallowIncoming}; - public: void testTrustLineDelete() @@ -478,25 +476,12 @@ public: using namespace test::jtx; - // test flag doesn't set unless amendment enabled - { - Env env{*this, features - disallowIncoming}; - Account const alice{"alice"}; - env.fund(XRP(10000), alice); - env(fset(alice, asfDisallowIncomingTrustline)); - env.close(); - auto const sle = env.le(alice); - uint32_t flags = sle->getFlags(); - BEAST_EXPECT(!(flags & lsfDisallowIncomingTrustline)); - } - // fixDisallowIncomingV1 { for (bool const withFix : {true, false}) { - auto const amend = withFix - ? features | disallowIncoming - : (features | disallowIncoming) - fixDisallowIncomingV1; + auto const amend = + withFix ? features : features - fixDisallowIncomingV1; Env env{*this, amend}; auto const dist = Account("dist"); @@ -532,7 +517,7 @@ public: } } - Env env{*this, features | disallowIncoming}; + Env env{*this, features}; auto const gw = Account{"gateway"}; auto const alice = Account{"alice"}; @@ -630,7 +615,6 @@ public: { using namespace test::jtx; auto const sa = testable_amendments(); - testWithFeats(sa - disallowIncoming); testWithFeats(sa); } }; diff --git a/src/test/rpc/AccountInfo_test.cpp b/src/test/rpc/AccountInfo_test.cpp index 86d0a4b4f6..5e2fc608b3 100644 --- a/src/test/rpc/AccountInfo_test.cpp +++ b/src/test/rpc/AccountInfo_test.cpp @@ -615,33 +615,23 @@ public: {"disallowIncomingTrustline", asfDisallowIncomingTrustline}}}; - if (features[featureDisallowIncoming]) + for (auto& asf : disallowIncomingFlags) { - for (auto& asf : disallowIncomingFlags) - { - // Clear a flag and check that account_info returns results - // as expected - env(fclear(alice, asf.second)); - env.close(); - auto const f1 = getAccountFlag(asf.first, alice); - BEAST_EXPECT(f1.has_value()); - BEAST_EXPECT(!f1.value()); + // Clear a flag and check that account_info returns results + // as expected + env(fclear(alice, asf.second)); + env.close(); + auto const f1 = getAccountFlag(asf.first, alice); + BEAST_EXPECT(f1.has_value()); + BEAST_EXPECT(!f1.value()); - // Set a flag and check that account_info returns results - // as expected - env(fset(alice, asf.second)); - env.close(); - auto const f2 = getAccountFlag(asf.first, alice); - BEAST_EXPECT(f2.has_value()); - BEAST_EXPECT(f2.value()); - } - } - else - { - for (auto& asf : disallowIncomingFlags) - { - BEAST_EXPECT(!getAccountFlag(asf.first, alice)); - } + // Set a flag and check that account_info returns results + // as expected + env(fset(alice, asf.second)); + env.close(); + auto const f2 = getAccountFlag(asf.first, alice); + BEAST_EXPECT(f2.has_value()); + BEAST_EXPECT(f2.value()); } static constexpr std::pair @@ -706,12 +696,8 @@ public: FeatureBitset const allFeatures{ ripple::test::jtx::testable_amendments()}; testAccountFlags(allFeatures); - testAccountFlags(allFeatures - featureDisallowIncoming); - testAccountFlags( - allFeatures - featureDisallowIncoming - featureClawback); - testAccountFlags( - allFeatures - featureDisallowIncoming - featureClawback - - featureTokenEscrow); + testAccountFlags(allFeatures - featureClawback); + testAccountFlags(allFeatures - featureClawback - featureTokenEscrow); } }; diff --git a/src/test/rpc/LedgerEntry_test.cpp b/src/test/rpc/LedgerEntry_test.cpp index fdd3838e89..a0fde0f457 100644 --- a/src/test/rpc/LedgerEntry_test.cpp +++ b/src/test/rpc/LedgerEntry_test.cpp @@ -1103,7 +1103,7 @@ class LedgerEntry_test : public beast::unit_test::suite checkErrorValue( jrr[jss::result], "malformedAuthorizedCredentials", - "Invalid field 'authorized_credentials', not array."); + "Invalid field 'authorized_credentials', array empty."); } { @@ -1144,7 +1144,7 @@ class LedgerEntry_test : public beast::unit_test::suite checkErrorValue( jrr[jss::result], "malformedAuthorizedCredentials", - "Invalid field 'authorized_credentials', not array."); + "Invalid field 'authorized_credentials', array too long."); } } diff --git a/src/test/rpc/RPCCall_test.cpp b/src/test/rpc/RPCCall_test.cpp index 07129e4bae..7647dc5f65 100644 --- a/src/test/rpc/RPCCall_test.cpp +++ b/src/test/rpc/RPCCall_test.cpp @@ -1584,8 +1584,6 @@ static RPCCallTestData const rpcCallTestArray[] = { "EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789", - "junk", // Note: indexing bug in parseBookOffers() requires junk - // param. "200", }, RPCCallTestData::no_exception, @@ -1597,7 +1595,6 @@ static RPCCallTestData const rpcCallTestArray[] = { "issuer" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "ledger_hash" : "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789", "limit" : 200, - "proof" : true, "taker_gets" : { "currency" : "EUR", "issuer" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA" @@ -1617,8 +1614,8 @@ static RPCCallTestData const rpcCallTestArray[] = { "EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789", - "junk", // Note: indexing bug in parseBookOffers() requires junk param. "200", + "0", "MyMarker"}, RPCCallTestData::no_exception, R"({ @@ -1630,7 +1627,6 @@ static RPCCallTestData const rpcCallTestArray[] = { "ledger_hash" : "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789", "limit" : 200, "marker" : "MyMarker", - "proof" : true, "taker_gets" : { "currency" : "EUR", "issuer" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA" @@ -1665,8 +1661,8 @@ static RPCCallTestData const rpcCallTestArray[] = { "EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789", - "junk", // Note: indexing bug in parseBookOffers() requires junk param. "200", + "0", "MyMarker", "extra"}, RPCCallTestData::no_exception, @@ -1770,12 +1766,19 @@ static RPCCallTestData const rpcCallTestArray[] = { "EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA", "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789", - "junk", // Note: indexing bug in parseBookOffers() requires junk - // param. "not_a_number", }, - RPCCallTestData::bad_cast, - R"()"}, + RPCCallTestData::no_exception, + R"({ + "method" : "book_offers", + "params" : [ + { + "error" : "invalidParams", + "error_code" : 31, + "error_message" : "Invalid field 'limit'." + } + ] + })"}, // can_delete // ------------------------------------------------------------------ diff --git a/src/xrpld/app/tx/detail/CreateCheck.cpp b/src/xrpld/app/tx/detail/CreateCheck.cpp index f5a36e6ac5..df859c4364 100644 --- a/src/xrpld/app/tx/detail/CreateCheck.cpp +++ b/src/xrpld/app/tx/detail/CreateCheck.cpp @@ -61,8 +61,7 @@ CreateCheck::preclaim(PreclaimContext const& ctx) auto const flags = sleDst->getFlags(); // Check if the destination has disallowed incoming checks - if (ctx.view.rules().enabled(featureDisallowIncoming) && - (flags & lsfDisallowIncomingCheck)) + if (flags & lsfDisallowIncomingCheck) return tecNO_PERMISSION; // Pseudo-accounts cannot cash checks. Note, this is not amendment-gated diff --git a/src/xrpld/app/tx/detail/NFTokenUtils.cpp b/src/xrpld/app/tx/detail/NFTokenUtils.cpp index 67f3a0de5f..db2b00cb2c 100644 --- a/src/xrpld/app/tx/detail/NFTokenUtils.cpp +++ b/src/xrpld/app/tx/detail/NFTokenUtils.cpp @@ -919,31 +919,21 @@ tokenOfferCreatePreclaim( return tecNO_DST; // check if the destination has disallowed incoming offers - if (view.rules().enabled(featureDisallowIncoming)) - { - // flag cannot be set unless amendment is enabled but - // out of an abundance of caution check anyway - - if (sleDst->getFlags() & lsfDisallowIncomingNFTokenOffer) - return tecNO_PERMISSION; - } + if (sleDst->getFlags() & lsfDisallowIncomingNFTokenOffer) + return tecNO_PERMISSION; } if (owner) { - // Check if the owner (buy offer) has disallowed incoming offers - if (view.rules().enabled(featureDisallowIncoming)) - { - auto const sleOwner = view.read(keylet::account(*owner)); + auto const sleOwner = view.read(keylet::account(*owner)); - // defensively check - // it should not be possible to specify owner that doesn't exist - if (!sleOwner) - return tecNO_TARGET; + // defensively check + // it should not be possible to specify owner that doesn't exist + if (!sleOwner) + return tecNO_TARGET; - if (sleOwner->getFlags() & lsfDisallowIncomingNFTokenOffer) - return tecNO_PERMISSION; - } + if (sleOwner->getFlags() & lsfDisallowIncomingNFTokenOffer) + return tecNO_PERMISSION; } if (view.rules().enabled(fixEnforceNFTokenTrustlineV2) && !amount.native()) diff --git a/src/xrpld/app/tx/detail/PayChan.cpp b/src/xrpld/app/tx/detail/PayChan.cpp index c3dc99e7fb..b52ae78523 100644 --- a/src/xrpld/app/tx/detail/PayChan.cpp +++ b/src/xrpld/app/tx/detail/PayChan.cpp @@ -202,8 +202,7 @@ PayChanCreate::preclaim(PreclaimContext const& ctx) auto const flags = sled->getFlags(); // Check if they have disallowed incoming payment channels - if (ctx.view.rules().enabled(featureDisallowIncoming) && - (flags & lsfDisallowIncomingPayChan)) + if (flags & lsfDisallowIncomingPayChan) return tecNO_PERMISSION; if ((flags & lsfRequireDestTag) && !ctx.tx[~sfDestinationTag]) diff --git a/src/xrpld/app/tx/detail/SetAccount.cpp b/src/xrpld/app/tx/detail/SetAccount.cpp index db513d9f05..e860eca22d 100644 --- a/src/xrpld/app/tx/detail/SetAccount.cpp +++ b/src/xrpld/app/tx/detail/SetAccount.cpp @@ -595,29 +595,25 @@ SetAccount::doApply() sle->isFieldPresent(sfNFTokenMinter)) sle->makeFieldAbsent(sfNFTokenMinter); - // Set or clear flags for disallowing various incoming instruments - if (ctx_.view().rules().enabled(featureDisallowIncoming)) - { - if (uSetFlag == asfDisallowIncomingNFTokenOffer) - uFlagsOut |= lsfDisallowIncomingNFTokenOffer; - else if (uClearFlag == asfDisallowIncomingNFTokenOffer) - uFlagsOut &= ~lsfDisallowIncomingNFTokenOffer; + if (uSetFlag == asfDisallowIncomingNFTokenOffer) + uFlagsOut |= lsfDisallowIncomingNFTokenOffer; + else if (uClearFlag == asfDisallowIncomingNFTokenOffer) + uFlagsOut &= ~lsfDisallowIncomingNFTokenOffer; - if (uSetFlag == asfDisallowIncomingCheck) - uFlagsOut |= lsfDisallowIncomingCheck; - else if (uClearFlag == asfDisallowIncomingCheck) - uFlagsOut &= ~lsfDisallowIncomingCheck; + if (uSetFlag == asfDisallowIncomingCheck) + uFlagsOut |= lsfDisallowIncomingCheck; + else if (uClearFlag == asfDisallowIncomingCheck) + uFlagsOut &= ~lsfDisallowIncomingCheck; - if (uSetFlag == asfDisallowIncomingPayChan) - uFlagsOut |= lsfDisallowIncomingPayChan; - else if (uClearFlag == asfDisallowIncomingPayChan) - uFlagsOut &= ~lsfDisallowIncomingPayChan; + if (uSetFlag == asfDisallowIncomingPayChan) + uFlagsOut |= lsfDisallowIncomingPayChan; + else if (uClearFlag == asfDisallowIncomingPayChan) + uFlagsOut &= ~lsfDisallowIncomingPayChan; - if (uSetFlag == asfDisallowIncomingTrustline) - uFlagsOut |= lsfDisallowIncomingTrustline; - else if (uClearFlag == asfDisallowIncomingTrustline) - uFlagsOut &= ~lsfDisallowIncomingTrustline; - } + if (uSetFlag == asfDisallowIncomingTrustline) + uFlagsOut |= lsfDisallowIncomingTrustline; + else if (uClearFlag == asfDisallowIncomingTrustline) + uFlagsOut &= ~lsfDisallowIncomingTrustline; // Set or clear flags for disallowing escrow if (ctx_.view().rules().enabled(featureTokenEscrow)) diff --git a/src/xrpld/app/tx/detail/SetTrust.cpp b/src/xrpld/app/tx/detail/SetTrust.cpp index 8d5f335f47..4e8f20f3ae 100644 --- a/src/xrpld/app/tx/detail/SetTrust.cpp +++ b/src/xrpld/app/tx/detail/SetTrust.cpp @@ -200,31 +200,27 @@ SetTrust::preclaim(PreclaimContext const& ctx) // This might be nullptr auto const sleDst = ctx.view.read(keylet::account(uDstAccountID)); - if ((ctx.view.rules().enabled(featureDisallowIncoming) || - ammEnabled(ctx.view.rules()) || + if ((ammEnabled(ctx.view.rules()) || ctx.view.rules().enabled(featureSingleAssetVault)) && sleDst == nullptr) return tecNO_DST; // If the destination has opted to disallow incoming trustlines // then honour that flag - if (ctx.view.rules().enabled(featureDisallowIncoming)) + if (sleDst->getFlags() & lsfDisallowIncomingTrustline) { - if (sleDst->getFlags() & lsfDisallowIncomingTrustline) + // The original implementation of featureDisallowIncoming was + // too restrictive. If + // o fixDisallowIncomingV1 is enabled and + // o The trust line already exists + // Then allow the TrustSet. + if (ctx.view.rules().enabled(fixDisallowIncomingV1) && + ctx.view.exists(keylet::line(id, uDstAccountID, currency))) { - // The original implementation of featureDisallowIncoming was - // too restrictive. If - // o fixDisallowIncomingV1 is enabled and - // o The trust line already exists - // Then allow the TrustSet. - if (ctx.view.rules().enabled(fixDisallowIncomingV1) && - ctx.view.exists(keylet::line(id, uDstAccountID, currency))) - { - // pass - } - else - return tecNO_PERMISSION; + // pass } + else + return tecNO_PERMISSION; } // In general, trust lines to pseudo accounts are not permitted, unless diff --git a/src/xrpld/rpc/detail/RPCCall.cpp b/src/xrpld/rpc/detail/RPCCall.cpp index 915f951749..185043302a 100644 --- a/src/xrpld/rpc/detail/RPCCall.cpp +++ b/src/xrpld/rpc/detail/RPCCall.cpp @@ -332,15 +332,31 @@ private: if (jvParams.size() >= 5) { - int iLimit = jvParams[5u].asInt(); + try + { + int iLimit = jvParams[4u].asInt(); - if (iLimit > 0) - jvRequest[jss::limit] = iLimit; + if (iLimit > 0) + jvRequest[jss::limit] = iLimit; + } + catch (std::exception const&) + { + return RPC::invalid_field_error(jss::limit); + } } - if (jvParams.size() >= 6 && jvParams[5u].asInt()) + if (jvParams.size() >= 6) { - jvRequest[jss::proof] = true; + try + { + int bProof = jvParams[5u].asInt(); + if (bProof) + jvRequest[jss::proof] = true; + } + catch (std::exception const&) + { + return RPC::invalid_field_error(jss::proof); + } } if (jvParams.size() == 7) diff --git a/src/xrpld/rpc/handlers/AccountInfo.cpp b/src/xrpld/rpc/handlers/AccountInfo.cpp index 683077be6e..e9f95d450b 100644 --- a/src/xrpld/rpc/handlers/AccountInfo.cpp +++ b/src/xrpld/rpc/handlers/AccountInfo.cpp @@ -116,11 +116,8 @@ doAccountInfo(RPC::JsonContext& context) for (auto const& lsf : lsFlags) acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second); - if (ledger->rules().enabled(featureDisallowIncoming)) - { - for (auto const& lsf : disallowIncomingFlags) - acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second); - } + for (auto const& lsf : disallowIncomingFlags) + acctFlags[lsf.first.data()] = sleAccepted->isFlag(lsf.second); if (ledger->rules().enabled(featureClawback)) acctFlags[allowTrustLineClawbackFlag.first.data()] = diff --git a/src/xrpld/rpc/handlers/LedgerEntry.cpp b/src/xrpld/rpc/handlers/LedgerEntry.cpp index b8b17e6b59..5a1dfb4ace 100644 --- a/src/xrpld/rpc/handlers/LedgerEntry.cpp +++ b/src/xrpld/rpc/handlers/LedgerEntry.cpp @@ -16,8 +16,6 @@ #include #include -#include - namespace ripple { static Expected @@ -178,18 +176,41 @@ static Expected parseAuthorizeCredentials(Json::Value const& jv) { if (!jv.isArray()) + { return LedgerEntryHelpers::invalidFieldError( "malformedAuthorizedCredentials", jss::authorized_credentials, "array"); - STArray arr(sfAuthorizeCredentials, jv.size()); + } + + std::uint32_t const n = jv.size(); + if (n > maxCredentialsArraySize) + { + return Unexpected(LedgerEntryHelpers::malformedError( + "malformedAuthorizedCredentials", + "Invalid field '" + std::string(jss::authorized_credentials) + + "', array too long.")); + } + + if (n == 0) + { + return Unexpected(LedgerEntryHelpers::malformedError( + "malformedAuthorizedCredentials", + "Invalid field '" + std::string(jss::authorized_credentials) + + "', array empty.")); + } + + STArray arr(sfAuthorizeCredentials, n); for (auto const& jo : jv) { if (!jo.isObject()) + { return LedgerEntryHelpers::invalidFieldError( "malformedAuthorizedCredentials", jss::authorized_credentials, "array"); + } + if (auto const value = LedgerEntryHelpers::hasRequired( jo, {jss::issuer, jss::credential_type}, @@ -260,13 +281,6 @@ parseDepositPreauth(Json::Value const& dp, Json::StaticString const fieldName) auto const arr = parseAuthorizeCredentials(ac); if (!arr.has_value()) return Unexpected(arr.error()); - if (arr->empty() || (arr->size() > maxCredentialsArraySize)) - { - return LedgerEntryHelpers::invalidFieldError( - "malformedAuthorizedCredentials", - jss::authorized_credentials, - "array"); - } auto const& sorted = credentials::makeSorted(arr.value()); if (sorted.empty())