diff --git a/.github/workflows/check-pr-title.yml b/.github/workflows/check-pr-title.yml index 6d7bdefa08..5631950df6 100644 --- a/.github/workflows/check-pr-title.yml +++ b/.github/workflows/check-pr-title.yml @@ -11,4 +11,4 @@ on: jobs: check_title: if: ${{ github.event.pull_request.draft != true }} - uses: XRPLF/actions/.github/workflows/check-pr-title.yml@a5d8dd35be543365e90a11358447130c8763871d + uses: XRPLF/actions/.github/workflows/check-pr-title.yml@291206777251b4d493641b5afbdf7c23009d2988 diff --git a/.github/workflows/reusable-clang-tidy.yml b/.github/workflows/reusable-clang-tidy.yml index e979e7179a..e01a50cf6d 100644 --- a/.github/workflows/reusable-clang-tidy.yml +++ b/.github/workflows/reusable-clang-tidy.yml @@ -176,7 +176,7 @@ jobs: - name: Create issue if: ${{ steps.run_clang_tidy.outcome != 'success' && inputs.create_issue_on_failure }} - uses: XRPLF/actions/create-issue@fbcc16eb7f20dc3199eaf1aed0d3523a5ba9008c + uses: XRPLF/actions/create-issue@36d450d12d301e8410c1b7936e5de70c291cbe36 with: title: "Clang-tidy check failed" body_file: ${{ env.ISSUE_FILE }} diff --git a/cfg/xrpld-example.cfg b/cfg/xrpld-example.cfg index 45269903b2..5de61bb6d1 100644 --- a/cfg/xrpld-example.cfg +++ b/cfg/xrpld-example.cfg @@ -527,6 +527,17 @@ # # The current default (which is subject to change) is 300 seconds. # +# verify_endpoints = <0 | 1> +# +# If set to 0, the server will skip validation of endpoint +# addresses received in TMEndpoints peer protocol messages, +# allowing addresses that are not publicly routable or have a +# port of 0. The default is 1 (verification enabled). +# +# WARNING: Disabling this option is a security risk and should +# only be used for local testing and debugging. Do not disable +# on mainnet. +# # # [transaction_queue] EXPERIMENTAL # diff --git a/cspell.config.yaml b/cspell.config.yaml index 34482d9d8f..bc56ef5d79 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -326,3 +326,4 @@ words: - xrplf - xxhash - xxhasher + - CGNAT diff --git a/include/xrpl/tx/paths/detail/StepChecks.h b/include/xrpl/tx/paths/detail/StepChecks.h index dc923e422f..47e15b34c3 100644 --- a/include/xrpl/tx/paths/detail/StepChecks.h +++ b/include/xrpl/tx/paths/detail/StepChecks.h @@ -78,8 +78,8 @@ checkNoRipple( if (!sleIn || !sleOut) return terNO_LINE; - if ((((*sleIn)[sfFlags] & ((cur > prev) ? lsfHighNoRipple : lsfLowNoRipple)) != 0u) && - (((*sleOut)[sfFlags] & ((cur > next) ? lsfHighNoRipple : lsfLowNoRipple)) != 0u)) + if (sleIn->isFlag((cur > prev) ? lsfHighNoRipple : lsfLowNoRipple) && + sleOut->isFlag((cur > next) ? lsfHighNoRipple : lsfLowNoRipple)) { JLOG(j.info()) << "Path violates noRipple constraint between " << prev << ", " << cur << " and " << next; diff --git a/src/libxrpl/beast/net/IPAddressV4.cpp b/src/libxrpl/beast/net/IPAddressV4.cpp index 48554d0ec3..e087da92eb 100644 --- a/src/libxrpl/beast/net/IPAddressV4.cpp +++ b/src/libxrpl/beast/net/IPAddressV4.cpp @@ -14,7 +14,45 @@ isPrivate(AddressV4 const& addr) bool isPublic(AddressV4 const& addr) { - return !isPrivate(addr) && !addr.is_multicast(); + if (isPrivate(addr)) + return false; + if (addr.is_multicast()) + return false; + + auto const ip = addr.to_uint(); + + // 0.0.0.0/8 "This network" + if ((ip & 0xff000000) == 0x00000000) + return false; + // 100.64.0.0/10 Shared Address Space (CGNAT) - RFC 6598 + if ((ip & 0xffc00000) == 0x64400000) + return false; + // 169.254.0.0/16 Link-local + if ((ip & 0xffff0000) == 0xa9fe0000) + return false; + // 192.0.0.0/24 IETF Protocol Assignments - RFC 6890 + if ((ip & 0xffffff00) == 0xc0000000) + return false; + // 192.0.2.0/24 TEST-NET-1 (documentation) - RFC 5737 + if ((ip & 0xffffff00) == 0xc0000200) + return false; + // 192.88.99.0/24 6to4 Relay Anycast (deprecated) - RFC 7526 + if ((ip & 0xffffff00) == 0xc0586300) + return false; + // 198.18.0.0/15 Benchmarking - RFC 2544 + if ((ip & 0xfffe0000) == 0xc6120000) + return false; + // 198.51.100.0/24 TEST-NET-2 (documentation) - RFC 5737 + if ((ip & 0xffffff00) == 0xc6336400) + return false; + // 203.0.113.0/24 TEST-NET-3 (documentation) - RFC 5737 + if ((ip & 0xffffff00) == 0xcb007100) + return false; + // 240.0.0.0/4 Reserved for future use - RFC 1112 + if ((ip & 0xf0000000) == 0xf0000000) + return false; + + return true; } char diff --git a/src/libxrpl/beast/net/IPAddressV6.cpp b/src/libxrpl/beast/net/IPAddressV6.cpp index fad11dddc0..c75ccaf1cc 100644 --- a/src/libxrpl/beast/net/IPAddressV6.cpp +++ b/src/libxrpl/beast/net/IPAddressV6.cpp @@ -9,17 +9,53 @@ namespace beast::IP { bool isPrivate(AddressV6 const& addr) { - return ( - ((addr.to_bytes()[0] & 0xfd) != 0) || // TODO fc00::/8 too ? - (addr.is_v4_mapped() && - isPrivate(boost::asio::ip::make_address_v4(boost::asio::ip::v4_mapped, addr)))); + // fc00::/7 - Unique Local Address (ULA), covers fc00:: and fd00:: + if ((addr.to_bytes()[0] & 0xfe) == 0xfc) + return true; + if (addr.is_v4_mapped()) + return isPrivate(boost::asio::ip::make_address_v4(boost::asio::ip::v4_mapped, addr)); + return false; } bool isPublic(AddressV6 const& addr) { - // TODO is this correct? - return !isPrivate(addr) && !addr.is_multicast(); + if (addr.is_loopback()) + return false; + if (addr.is_v4_mapped()) + return isPublic(boost::asio::ip::make_address_v4(boost::asio::ip::v4_mapped, addr)); + if (isPrivate(addr)) + return false; + if (addr.is_multicast()) + return false; + if (addr.is_unspecified()) + return false; + + auto const b = addr.to_bytes(); + + // fe80::/10 - Link-local + if (b[0] == 0xfe && (b[1] & 0xc0) == 0x80) + return false; + // 100::/64 - Discard prefix (RFC 6666) + if (b[0] == 0x01 && b[1] == 0x00 && b[2] == 0 && b[3] == 0 && b[4] == 0 && b[5] == 0 && + b[6] == 0 && b[7] == 0) + return false; + // 2001:db8::/32 - Documentation (RFC 3849) + if (b[0] == 0x20 && b[1] == 0x01 && b[2] == 0x0d && b[3] == 0xb8) + return false; + // 2001::/32 - IETF Protocol Assignments / Teredo (RFC 4380) + if (b[0] == 0x20 && b[1] == 0x01 && b[2] == 0x00 && b[3] == 0x00) + return false; + // 2001:20::/28 - ORCHIDv2 (RFC 7343) + // 28-bit prefix: 0x2001002 => b[0]=0x20, b[1]=0x01, b[2]=0x00, + // top nibble of b[3]=0x2 + if (b[0] == 0x20 && b[1] == 0x01 && b[2] == 0x00 && (b[3] & 0xf0) == 0x20) + return false; + // 2002::/16 - 6to4 (RFC 3056, deprecated by RFC 7526) + if (b[0] == 0x20 && b[1] == 0x02) + return false; + + return true; } } // namespace beast::IP diff --git a/src/libxrpl/ledger/helpers/CredentialHelpers.cpp b/src/libxrpl/ledger/helpers/CredentialHelpers.cpp index b0e004d9d7..03d24ff6f7 100644 --- a/src/libxrpl/ledger/helpers/CredentialHelpers.cpp +++ b/src/libxrpl/ledger/helpers/CredentialHelpers.cpp @@ -105,7 +105,7 @@ deleteSLE(ApplyView& view, std::shared_ptr const& sleCredential, beast::Jou auto const issuer = sleCredential->getAccountID(sfIssuer); auto const subject = sleCredential->getAccountID(sfSubject); - bool const accepted = (sleCredential->getFlags() & lsfAccepted) != 0u; + bool const accepted = sleCredential->isFlag(lsfAccepted); auto err = delSLE(issuer, sfIssuerNode, !accepted || (subject == issuer)); if (!isTesSuccess(err)) @@ -174,7 +174,7 @@ valid(STTx const& tx, ReadView const& view, AccountID const& src, beast::Journal return tecBAD_CREDENTIALS; } - if ((sleCred->getFlags() & lsfAccepted) == 0u) + if (!sleCred->isFlag(lsfAccepted)) { JLOG(j.trace()) << "Credential isn't accepted. Cred: " << h; return tecBAD_CREDENTIALS; @@ -215,7 +215,7 @@ validDomain(ReadView const& view, uint256 domainID, AccountID const& subject) foundExpired = true; continue; } - if ((sleCredential->getFlags() & lsfAccepted) != 0u) + if (sleCredential->isFlag(lsfAccepted)) { return tesSUCCESS; } @@ -339,7 +339,7 @@ verifyValidDomain(ApplyView& view, AccountID const& account, uint256 domainID, b if (!sleCredential) continue; // expired, i.e. deleted in credentials::removeExpired - if ((sleCredential->getFlags() & lsfAccepted) != 0u) + if (sleCredential->isFlag(lsfAccepted)) return tesSUCCESS; } diff --git a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp index 1c93336c1b..fd98cfefea 100644 --- a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp +++ b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp @@ -357,7 +357,7 @@ requireAuth( if (maybeDomainID) { XRPL_ASSERT( - sleIssuance->getFieldU32(sfFlags) & lsfMPTRequireAuth, + sleIssuance->isFlag(lsfMPTRequireAuth), "xrpl::requireAuth : issuance requires authorization"); // ter = tefINTERNAL | tecOBJECT_NOT_FOUND | tecNO_AUTH | tecEXPIRED auto const ter = credentials::validDomain(view, *maybeDomainID, account); diff --git a/src/libxrpl/ledger/helpers/NFTokenHelpers.cpp b/src/libxrpl/ledger/helpers/NFTokenHelpers.cpp index 2796cff274..0a433aebed 100644 --- a/src/libxrpl/ledger/helpers/NFTokenHelpers.cpp +++ b/src/libxrpl/ledger/helpers/NFTokenHelpers.cpp @@ -625,8 +625,8 @@ deleteTokenOffer(ApplyView& view, std::shared_ptr const& offer) auto const nftokenID = (*offer)[sfNFTokenID]; if (!view.dirRemove( - (((*offer)[sfFlags] & lsfSellNFToken) != 0u) ? keylet::nftSells(nftokenID) - : keylet::nftBuys(nftokenID), + offer->isFlag(lsfSellNFToken) ? keylet::nftSells(nftokenID) + : keylet::nftBuys(nftokenID), (*offer)[sfNFTokenOfferNode], offer->key(), false)) diff --git a/src/libxrpl/ledger/helpers/RippleStateHelpers.cpp b/src/libxrpl/ledger/helpers/RippleStateHelpers.cpp index 07eea81eb3..b726779423 100644 --- a/src/libxrpl/ledger/helpers/RippleStateHelpers.cpp +++ b/src/libxrpl/ledger/helpers/RippleStateHelpers.cpp @@ -341,22 +341,25 @@ updateTrustLine( { if (!state) return false; - std::uint32_t const flags(state->getFieldU32(sfFlags)); WAccountRoot wrappedAcct(sender, view, j); if (!wrappedAcct) return false; + auto const senderReserveFlag = bSenderHigh ? lsfHighReserve : lsfLowReserve; + auto const senderNoRippleFlag = bSenderHigh ? lsfHighNoRipple : lsfLowNoRipple; + auto const senderFreezeFlag = bSenderHigh ? lsfHighFreeze : lsfLowFreeze; + auto const receiverReserveFlag = bSenderHigh ? lsfLowReserve : lsfHighReserve; + // YYY Could skip this if rippling in reverse. if (before > beast::kZERO // Sender balance was positive. && after <= beast::kZERO // Sender is zero or negative. - && ((flags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve)) != 0u) + && state->isFlag(senderReserveFlag) // Sender reserve is set. - && static_cast(flags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) != - wrappedAcct->isFlag(lsfDefaultRipple) && - ((flags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze)) == 0u) && + && state->isFlag(senderNoRippleFlag) != wrappedAcct->isFlag(lsfDefaultRipple) && + !state->isFlag(senderFreezeFlag) && !state->getFieldAmount(!bSenderHigh ? sfLowLimit : sfHighLimit) // Sender trust limit is 0. && (state->getFieldU32(!bSenderHigh ? sfLowQualityIn : sfHighQualityIn) == 0u) @@ -369,11 +372,10 @@ updateTrustLine( wrappedAcct.adjustOwnerCount(-1); // Clear reserve flag. - state->setFieldU32(sfFlags, flags & (!bSenderHigh ? ~lsfLowReserve : ~lsfHighReserve)); + state->clearFlag(senderReserveFlag); // Balance is zero, receiver reserve is clear. - if (!after // Balance is zero. - && ((flags & (bSenderHigh ? lsfLowReserve : lsfHighReserve)) == 0u)) + if (!after && !state->isFlag(receiverReserveFlag)) return true; } return false; @@ -453,7 +455,7 @@ issueIOU( if (!receiverAccount) return tefINTERNAL; // LCOV_EXCL_LINE - bool const noRipple = (receiverAccount->getFlags() & lsfDefaultRipple) == 0; + bool const noRipple = !receiverAccount->isFlag(lsfDefaultRipple); return trustCreate( view, @@ -569,8 +571,7 @@ requireAuth(ReadView const& view, Issue const& issue, AccountID const& account, { if (trustLine) { - return (((*trustLine)[sfFlags] & - ((account > issue.account) ? lsfLowAuth : lsfHighAuth)) != 0u) + return trustLine->isFlag((account > issue.account) ? lsfLowAuth : lsfHighAuth) ? tesSUCCESS : TER{tecNO_AUTH}; } @@ -776,7 +777,7 @@ deleteAMMTrustLine( } auto const uFlags = !ammLow ? lsfLowReserve : lsfHighReserve; - if ((sleState->getFlags() & uFlags) == 0u) + if (!sleState->isFlag(uFlags)) return tecINTERNAL; // LCOV_EXCL_LINE WAccountRoot wrappedHolder = !ammLow ? wrappedLow : wrappedHigh; diff --git a/src/libxrpl/ledger/helpers/TokenHelpers.cpp b/src/libxrpl/ledger/helpers/TokenHelpers.cpp index 6a04687898..0678ae9c41 100644 --- a/src/libxrpl/ledger/helpers/TokenHelpers.cpp +++ b/src/libxrpl/ledger/helpers/TokenHelpers.cpp @@ -571,26 +571,30 @@ directSendNoFeeIOU( << " amount=" << saAmount.getFullText() << " after=" << saBalance.getFullText(); - std::uint32_t const uFlags(sleRippleState->getFieldU32(sfFlags)); bool bDelete = false; + auto const senderReserveFlag = bSenderHigh ? lsfHighReserve : lsfLowReserve; + auto const senderNoRippleFlag = bSenderHigh ? lsfHighNoRipple : lsfLowNoRipple; + auto const senderFreezeFlag = bSenderHigh ? lsfHighFreeze : lsfLowFreeze; + auto const receiverReserveFlag = bSenderHigh ? lsfLowReserve : lsfHighReserve; + // FIXME This NEEDS to be cleaned up and simplified. It's impossible // for anyone to understand. if (saBefore > beast::kZERO // Sender balance was positive. && saBalance <= beast::kZERO // Sender is zero or negative. - && ((uFlags & (!bSenderHigh ? lsfLowReserve : lsfHighReserve)) != 0u) + && sleRippleState->isFlag(senderReserveFlag) // Sender reserve is set. - && static_cast(uFlags & (!bSenderHigh ? lsfLowNoRipple : lsfHighNoRipple)) != + && sleRippleState->isFlag(senderNoRippleFlag) != AccountRoot(uSenderID, view, j)->isFlag(lsfDefaultRipple) && - ((uFlags & (!bSenderHigh ? lsfLowFreeze : lsfHighFreeze)) == 0u) && + !sleRippleState->isFlag(senderFreezeFlag) && !sleRippleState->getFieldAmount(!bSenderHigh ? sfLowLimit : sfHighLimit) // Sender trust limit is 0. - && (sleRippleState->getFieldU32(!bSenderHigh ? sfLowQualityIn : sfHighQualityIn) == 0u) + && (sleRippleState->getFieldU32(bSenderHigh ? sfHighQualityIn : sfLowQualityIn) == 0u) // Sender quality in is 0. && - (sleRippleState->getFieldU32(!bSenderHigh ? sfLowQualityOut : sfHighQualityOut) == 0u)) + (sleRippleState->getFieldU32(bSenderHigh ? sfHighQualityOut : sfLowQualityOut) == 0u)) // Sender quality out is 0. { // Clear the reserve of the sender, possibly delete the line! @@ -598,12 +602,11 @@ directSendNoFeeIOU( wrappedSender.adjustOwnerCount(-1); // Clear reserve flag. - sleRippleState->setFieldU32( - sfFlags, uFlags & (!bSenderHigh ? ~lsfLowReserve : ~lsfHighReserve)); + sleRippleState->clearFlag(senderReserveFlag); // Balance is zero, receiver reserve is clear. bDelete = !saBalance // Balance is zero. - && ((uFlags & (bSenderHigh ? lsfLowReserve : lsfHighReserve)) == 0u); + && !sleRippleState->isFlag(receiverReserveFlag); // Receiver reserve is clear. } @@ -620,7 +623,7 @@ directSendNoFeeIOU( view, sleRippleState, bSenderHigh ? uReceiverID : uSenderID, - !bSenderHigh ? uReceiverID : uSenderID, + bSenderHigh ? uSenderID : uReceiverID, j); } diff --git a/src/libxrpl/tx/invariants/AMMInvariant.cpp b/src/libxrpl/tx/invariants/AMMInvariant.cpp index 6469799eb6..18c37b9eaf 100644 --- a/src/libxrpl/tx/invariants/AMMInvariant.cpp +++ b/src/libxrpl/tx/invariants/AMMInvariant.cpp @@ -44,7 +44,7 @@ ValidAMM::visitEntry( } // AMM pool changed else if ( - (type == ltRIPPLE_STATE && ((after->getFlags() & lsfAMMNode) != 0u)) || + (type == ltRIPPLE_STATE && after->isFlag(lsfAMMNode)) || (type == ltACCOUNT_ROOT && after->isFieldPresent(sfAMMID))) { ammPoolChanged_ = true; diff --git a/src/libxrpl/tx/invariants/InvariantCheck.cpp b/src/libxrpl/tx/invariants/InvariantCheck.cpp index fc03bab585..c490af3c09 100644 --- a/src/libxrpl/tx/invariants/InvariantCheck.cpp +++ b/src/libxrpl/tx/invariants/InvariantCheck.cpp @@ -675,12 +675,11 @@ NoDeepFreezeTrustLinesWithoutFreeze::visitEntry( { bool const overwriteFixEnabled = isFeatureEnabled(fixCleanup3_1_3, true); - std::uint32_t const uFlags = after->getFieldU32(sfFlags); - bool const lowFreeze = (uFlags & lsfLowFreeze) != 0u; - bool const lowDeepFreeze = (uFlags & lsfLowDeepFreeze) != 0u; + bool const lowFreeze = after->isFlag(lsfLowFreeze); + bool const lowDeepFreeze = after->isFlag(lsfLowDeepFreeze); - bool const highFreeze = (uFlags & lsfHighFreeze) != 0u; - bool const highDeepFreeze = (uFlags & lsfHighDeepFreeze) != 0u; + bool const highFreeze = after->isFlag(lsfHighFreeze); + bool const highDeepFreeze = after->isFlag(lsfHighDeepFreeze); bool const bad = (lowDeepFreeze && !lowFreeze) || (highDeepFreeze && !highFreeze); if (overwriteFixEnabled) diff --git a/src/libxrpl/tx/paths/BookStep.cpp b/src/libxrpl/tx/paths/BookStep.cpp index 4126931ada..7548d6f5d6 100644 --- a/src/libxrpl/tx/paths/BookStep.cpp +++ b/src/libxrpl/tx/paths/BookStep.cpp @@ -1357,8 +1357,7 @@ BookStep::check(StrandContext const& ctx) const auto sle = view.read(keylet::line(*prev, cur, issue.currency)); if (!sle) return terNO_LINE; - if (((*sle)[sfFlags] & ((cur > *prev) ? lsfHighNoRipple : lsfLowNoRipple)) != - 0u) + if (sle->isFlag((cur > *prev) ? lsfHighNoRipple : lsfLowNoRipple)) return terNO_RIPPLE; return std::nullopt; }, diff --git a/src/libxrpl/tx/paths/DirectStep.cpp b/src/libxrpl/tx/paths/DirectStep.cpp index 3a01adffff..f22179a9b5 100644 --- a/src/libxrpl/tx/paths/DirectStep.cpp +++ b/src/libxrpl/tx/paths/DirectStep.cpp @@ -429,8 +429,8 @@ DirectIPaymentStep::check(StrandContext const& ctx, std::shared_ptr c auto const authField = (src_ > dst_) ? lsfHighAuth : lsfLowAuth; - if ((((*sleSrc)[sfFlags] & lsfRequireAuth) != 0u) && - (((*sleLine)[sfFlags] & authField) == 0u) && (*sleLine)[sfBalance] == beast::kZERO) + if (sleSrc->isFlag(lsfRequireAuth) && !sleLine->isFlag(authField) && + (*sleLine)[sfBalance] == beast::kZERO) { JLOG(j_.debug()) << "DirectStepI: can't receive IOUs from issuer without auth." << " src: " << src_; @@ -441,9 +441,7 @@ DirectIPaymentStep::check(StrandContext const& ctx, std::shared_ptr c { if (ctx.prevStep->bookStepBook()) { - auto const noRippleSrcToDst = - ((*sleLine)[sfFlags] & ((src_ > dst_) ? lsfHighNoRipple : lsfLowNoRipple)); - if (noRippleSrcToDst != 0u) + if (sleLine->isFlag((src_ > dst_) ? lsfHighNoRipple : lsfLowNoRipple)) return terNO_RIPPLE; } } diff --git a/src/libxrpl/tx/transactors/account/AccountSet.cpp b/src/libxrpl/tx/transactors/account/AccountSet.cpp index 5e93ea2b4b..4322cbbe56 100644 --- a/src/libxrpl/tx/transactors/account/AccountSet.cpp +++ b/src/libxrpl/tx/transactors/account/AccountSet.cpp @@ -70,8 +70,6 @@ AccountSet::preflight(PreflightContext const& ctx) auto& tx = ctx.tx; auto& j = ctx.j; - std::uint32_t const uTxFlags = tx.getFlags(); - std::uint32_t const uSetFlag = tx.getFieldU32(sfSetFlag); std::uint32_t const uClearFlag = tx.getFieldU32(sfClearFlag); @@ -84,9 +82,8 @@ AccountSet::preflight(PreflightContext const& ctx) // // RequireAuth // - bool const bSetRequireAuth = ((uTxFlags & tfRequireAuth) != 0u) || (uSetFlag == asfRequireAuth); - bool const bClearRequireAuth = - ((uTxFlags & tfOptionalAuth) != 0u) || (uClearFlag == asfRequireAuth); + bool const bSetRequireAuth = tx.isFlag(tfRequireAuth) || (uSetFlag == asfRequireAuth); + bool const bClearRequireAuth = tx.isFlag(tfOptionalAuth) || (uClearFlag == asfRequireAuth); if (bSetRequireAuth && bClearRequireAuth) { @@ -97,10 +94,8 @@ AccountSet::preflight(PreflightContext const& ctx) // // RequireDestTag // - bool const bSetRequireDest = - ((uTxFlags & tfRequireDestTag) != 0u) || (uSetFlag == asfRequireDest); - bool const bClearRequireDest = - ((uTxFlags & tfOptionalDestTag) != 0u) || (uClearFlag == asfRequireDest); + bool const bSetRequireDest = tx.isFlag(tfRequireDestTag) || (uSetFlag == asfRequireDest); + bool const bClearRequireDest = tx.isFlag(tfOptionalDestTag) || (uClearFlag == asfRequireDest); if (bSetRequireDest && bClearRequireDest) { @@ -111,9 +106,8 @@ AccountSet::preflight(PreflightContext const& ctx) // // DisallowXRP // - bool const bSetDisallowXRP = ((uTxFlags & tfDisallowXRP) != 0u) || (uSetFlag == asfDisallowXRP); - bool const bClearDisallowXRP = - ((uTxFlags & tfAllowXRP) != 0u) || (uClearFlag == asfDisallowXRP); + bool const bSetDisallowXRP = tx.isFlag(tfDisallowXRP) || (uSetFlag == asfDisallowXRP); + bool const bClearDisallowXRP = tx.isFlag(tfAllowXRP) || (uClearFlag == asfDisallowXRP); if (bSetDisallowXRP && bClearDisallowXRP) { @@ -196,12 +190,11 @@ AccountSet::checkPermission(ReadView const& view, STTx const& tx) auto const uSetFlag = tx.getFieldU32(sfSetFlag); auto const uClearFlag = tx.getFieldU32(sfClearFlag); - auto const uTxFlags = tx.getFlags(); // We don't support any flag based granular permission under // AccountSet transaction. If any delegated account is trying to // update the flag on behalf of another account, it is not // authorized. - if (uSetFlag != 0 || uClearFlag != 0 || ((uTxFlags & tfUniversalMask) != 0u)) + if (uSetFlag != 0 || uClearFlag != 0 || ((tx.getFlags() & tfUniversalMask) != 0u)) return terNO_DELEGATE_PERMISSION; if (tx.isFieldPresent(sfEmailHash) && !granularPermissions.contains(AccountEmailHashSet)) @@ -230,8 +223,6 @@ AccountSet::preclaim(PreclaimContext const& ctx) { auto const id = ctx.tx[sfAccount]; - std::uint32_t const uTxFlags = ctx.tx.getFlags(); - AccountRoot const acctRoot(id, ctx.view); if (!acctRoot) return terNO_ACCOUNT; @@ -241,7 +232,7 @@ AccountSet::preclaim(PreclaimContext const& ctx) std::uint32_t const uSetFlag = ctx.tx.getFieldU32(sfSetFlag); // legacy AccountSet flags - bool const bSetRequireAuth = ((uTxFlags & tfRequireAuth) != 0u) || (uSetFlag == asfRequireAuth); + bool const bSetRequireAuth = ctx.tx.isFlag(tfRequireAuth) || (uSetFlag == asfRequireAuth); // // RequireAuth @@ -303,16 +294,12 @@ AccountSet::doApply() std::uint32_t const uClearFlag{tx.getFieldU32(sfClearFlag)}; // legacy AccountSet flags - std::uint32_t const uTxFlags{tx.getFlags()}; - bool const bSetRequireDest{ - ((uTxFlags & tfRequireDestTag) != 0u) || (uSetFlag == asfRequireDest)}; - bool const bClearRequireDest{ - ((uTxFlags & tfOptionalDestTag) != 0u) || (uClearFlag == asfRequireDest)}; - bool const bSetRequireAuth{((uTxFlags & tfRequireAuth) != 0u) || (uSetFlag == asfRequireAuth)}; - bool const bClearRequireAuth{ - ((uTxFlags & tfOptionalAuth) != 0u) || (uClearFlag == asfRequireAuth)}; - bool const bSetDisallowXRP{((uTxFlags & tfDisallowXRP) != 0u) || (uSetFlag == asfDisallowXRP)}; - bool const bClearDisallowXRP{((uTxFlags & tfAllowXRP) != 0u) || (uClearFlag == asfDisallowXRP)}; + bool const bSetRequireDest{tx.isFlag(tfRequireDestTag) || (uSetFlag == asfRequireDest)}; + bool const bClearRequireDest{tx.isFlag(tfOptionalDestTag) || (uClearFlag == asfRequireDest)}; + bool const bSetRequireAuth{tx.isFlag(tfRequireAuth) || (uSetFlag == asfRequireAuth)}; + bool const bClearRequireAuth{tx.isFlag(tfOptionalAuth) || (uClearFlag == asfRequireAuth)}; + bool const bSetDisallowXRP{tx.isFlag(tfDisallowXRP) || (uSetFlag == asfDisallowXRP)}; + bool const bClearDisallowXRP{tx.isFlag(tfAllowXRP) || (uClearFlag == asfDisallowXRP)}; bool const sigWithMaster{[&tx, &acct = accountID_]() { auto const spk = tx.getSigningPubKey(); diff --git a/src/libxrpl/tx/transactors/account/SignerListSet.cpp b/src/libxrpl/tx/transactors/account/SignerListSet.cpp index 4757451aa1..c5ff1c7bb4 100644 --- a/src/libxrpl/tx/transactors/account/SignerListSet.cpp +++ b/src/libxrpl/tx/transactors/account/SignerListSet.cpp @@ -197,7 +197,7 @@ removeSignersFromLedger( // If the lsfOneOwnerCount bit is Operation::Set then remove just one owner count. // Otherwise use the pre-MultiSignReserve amendment calculation. int removeFromOwnerCount = -1; - if ((signers->getFlags() & lsfOneOwnerCount) == 0) + if (!signers->isFlag(lsfOneOwnerCount)) { STArray const& actualList = signers->getFieldArray(sfSignerEntries); removeFromOwnerCount = diff --git a/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp b/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp index dcbdd22739..8cd012dd71 100644 --- a/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp +++ b/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp @@ -1501,7 +1501,7 @@ BridgeModify::preflight(PreflightContext const& ctx) auto const reward = ctx.tx[~sfSignatureReward]; auto const minAccountCreate = ctx.tx[~sfMinAccountCreateAmount]; auto const bridgeSpec = ctx.tx[sfXChainBridge]; - bool const clearAccountCreate = (ctx.tx.getFlags() & tfClearAccountCreateAmount) != 0u; + bool const clearAccountCreate = ctx.tx.isFlag(tfClearAccountCreateAmount); if (!reward && !minAccountCreate && !clearAccountCreate) { @@ -1559,7 +1559,7 @@ BridgeModify::doApply() auto const bridgeSpec = ctx_.tx[sfXChainBridge]; auto const reward = ctx_.tx[~sfSignatureReward]; auto const minAccountCreate = ctx_.tx[~sfMinAccountCreateAmount]; - bool const clearAccountCreate = (ctx_.tx.getFlags() & tfClearAccountCreateAmount) != 0u; + bool const clearAccountCreate = ctx_.tx.isFlag(tfClearAccountCreateAmount); if (!AccountRoot(account, ctx_.view(), j_)) return tecINTERNAL; // LCOV_EXCL_LINE diff --git a/src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp b/src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp index 6648b910df..e3f241c54f 100644 --- a/src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp +++ b/src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp @@ -73,7 +73,7 @@ CredentialAccept::preclaim(PreclaimContext const& ctx) return tecNO_ENTRY; } - if ((sleCred->getFieldU32(sfFlags) & lsfAccepted) != 0u) + if (sleCred->isFlag(lsfAccepted)) { JLOG(ctx.j.warn()) << "Credential already accepted: " << to_string(subject) << ", " << to_string(issuer) << ", " << credType; diff --git a/src/libxrpl/tx/transactors/dex/AMMClawback.cpp b/src/libxrpl/tx/transactors/dex/AMMClawback.cpp index e8f9f49b92..36d4ff039a 100644 --- a/src/libxrpl/tx/transactors/dex/AMMClawback.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMClawback.cpp @@ -72,9 +72,7 @@ AMMClawback::preflight(PreflightContext const& ctx) if (isXRP(asset)) return temMALFORMED; - auto const flags = ctx.tx.getFlags(); - - if (((flags & tfClawTwoAssets) != 0u) && asset.getIssuer() != asset2.getIssuer()) + if (ctx.tx.isFlag(tfClawTwoAssets) && asset.getIssuer() != asset2.getIssuer()) { JLOG(ctx.j.trace()) << "AMMClawback: tfClawTwoAssets can only be enabled when two " "assets in the AMM pool are both issued by the issuer"; @@ -284,8 +282,7 @@ AMMClawback::applyGuts(Sandbox& sb) if (!amount2Withdraw) return tecINTERNAL; // LCOV_EXCL_LINE - auto const flags = ctx_.tx.getFlags(); - if ((flags & tfClawTwoAssets) != 0u) + if (ctx_.tx.isFlag(tfClawTwoAssets)) return sendAmount(*amount2Withdraw); return tesSUCCESS; diff --git a/src/libxrpl/tx/transactors/dex/AMMDeposit.cpp b/src/libxrpl/tx/transactors/dex/AMMDeposit.cpp index 024b242540..9d90b82528 100644 --- a/src/libxrpl/tx/transactors/dex/AMMDeposit.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMDeposit.cpp @@ -75,35 +75,35 @@ AMMDeposit::preflight(PreflightContext const& ctx) JLOG(ctx.j.debug()) << "AMM Deposit: invalid flags."; return temMALFORMED; } - if ((flags & tfLPToken) != 0u) + if (ctx.tx.isFlag(tfLPToken)) { // if included then both amount and amount2 are deposit min if (!lpTokens || ePrice || (amount && !amount2) || (!amount && amount2) || tradingFee) return temMALFORMED; } - else if ((flags & tfSingleAsset) != 0u) + else if (ctx.tx.isFlag(tfSingleAsset)) { // if included then lpTokens is deposit min if (!amount || amount2 || ePrice || tradingFee) return temMALFORMED; } - else if ((flags & tfTwoAsset) != 0u) + else if (ctx.tx.isFlag(tfTwoAsset)) { // if included then lpTokens is deposit min if (!amount || !amount2 || ePrice || tradingFee) return temMALFORMED; } - else if ((flags & tfOneAssetLPToken) != 0u) + else if (ctx.tx.isFlag(tfOneAssetLPToken)) { if (!amount || !lpTokens || amount2 || ePrice || tradingFee) return temMALFORMED; } - else if ((flags & tfLimitLPToken) != 0u) + else if (ctx.tx.isFlag(tfLimitLPToken)) { if (!amount || !ePrice || lpTokens || amount2 || tradingFee) return temMALFORMED; } - else if ((flags & tfTwoAssetIfEmpty) != 0u) + else if (ctx.tx.isFlag(tfTwoAssetIfEmpty)) { if (!amount || !amount2 || ePrice || lpTokens) return temMALFORMED; @@ -198,7 +198,7 @@ AMMDeposit::preclaim(PreclaimContext const& ctx) if (!expected) return expected.error(); // LCOV_EXCL_LINE auto const [amountBalance, amount2Balance, lptAMMBalance] = *expected; - if ((ctx.tx.getFlags() & tfTwoAssetIfEmpty) != 0u) + if (ctx.tx.isFlag(tfTwoAssetIfEmpty)) { if (lptAMMBalance != beast::kZERO) return tecAMM_NOT_EMPTY; @@ -332,7 +332,7 @@ AMMDeposit::preclaim(PreclaimContext const& ctx) }; // amount and amount2 are deposit min in case of tfLPToken - if ((ctx.tx.getFlags() & tfLPToken) == 0u) + if (!ctx.tx.isFlag(tfLPToken)) { if (auto const ter = checkAmount(amount, true)) return ter; diff --git a/src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp b/src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp index 6531dee511..e50e1efb7f 100644 --- a/src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp @@ -83,37 +83,37 @@ AMMWithdraw::preflight(PreflightContext const& ctx) JLOG(ctx.j.debug()) << "AMM Withdraw: invalid flags."; return temMALFORMED; } - if ((flags & tfLPToken) != 0u) + if (ctx.tx.isFlag(tfLPToken)) { if (!lpTokens || amount || amount2 || ePrice) return temMALFORMED; } - else if ((flags & tfWithdrawAll) != 0u) + else if (ctx.tx.isFlag(tfWithdrawAll)) { if (lpTokens || amount || amount2 || ePrice) return temMALFORMED; } - else if ((flags & tfOneAssetWithdrawAll) != 0u) + else if (ctx.tx.isFlag(tfOneAssetWithdrawAll)) { if (!amount || lpTokens || amount2 || ePrice) return temMALFORMED; } - else if ((flags & tfSingleAsset) != 0u) + else if (ctx.tx.isFlag(tfSingleAsset)) { if (!amount || lpTokens || amount2 || ePrice) return temMALFORMED; } - else if ((flags & tfTwoAsset) != 0u) + else if (ctx.tx.isFlag(tfTwoAsset)) { if (!amount || !amount2 || lpTokens || ePrice) return temMALFORMED; } - else if ((flags & tfOneAssetLPToken) != 0u) + else if (ctx.tx.isFlag(tfOneAssetLPToken)) { if (!amount || !lpTokens || amount2 || ePrice) return temMALFORMED; } - else if ((flags & tfLimitLPToken) != 0u) + else if (ctx.tx.isFlag(tfLimitLPToken)) { if (!amount || !ePrice || lpTokens || amount2) return temMALFORMED; diff --git a/src/libxrpl/tx/transactors/dex/OfferCreate.cpp b/src/libxrpl/tx/transactors/dex/OfferCreate.cpp index a65ecdfa0f..d80d290bda 100644 --- a/src/libxrpl/tx/transactors/dex/OfferCreate.cpp +++ b/src/libxrpl/tx/transactors/dex/OfferCreate.cpp @@ -91,13 +91,11 @@ OfferCreate::preflight(PreflightContext const& ctx) auto& tx = ctx.tx; auto& j = ctx.j; - std::uint32_t const uTxFlags = tx.getFlags(); - if (tx.isFlag(tfHybrid) && !tx.isFieldPresent(sfDomainID)) return temINVALID_FLAG; - bool const bImmediateOrCancel((uTxFlags & tfImmediateOrCancel) != 0u); - bool const bFillOrKill((uTxFlags & tfFillOrKill) != 0u); + bool const bImmediateOrCancel(tx.isFlag(tfImmediateOrCancel)); + bool const bFillOrKill(tx.isFlag(tfFillOrKill)); if (bImmediateOrCancel && bFillOrKill) { @@ -289,8 +287,7 @@ OfferCreate::checkAcceptAsset( // access. bool const canonicalGt(id > issuer); - bool const isAuthorized( - ((*trustLine)[sfFlags] & (canonicalGt ? lsfLowAuth : lsfHighAuth)) != 0u); + bool const isAuthorized(trustLine->isFlag(canonicalGt ? lsfLowAuth : lsfHighAuth)); if (!isAuthorized) { @@ -380,8 +377,7 @@ OfferCreate::flowCross( // If we're creating a passive offer adjust the threshold so we only // cross offers that have a better quality than this one. - std::uint32_t const txFlags = ctx_.tx.getFlags(); - if ((txFlags & tfPassive) != 0u) + if (ctx_.tx.isFlag(tfPassive)) ++threshold; // Don't send more than our balance. @@ -403,7 +399,7 @@ OfferCreate::flowCross( STAmount deliver = takerAmount.out; auto const& deliverAsset = deliver.asset(); OfferCrossing offerCrossing = OfferCrossing::Yes; - if ((txFlags & tfSell) != 0u) + if (ctx_.tx.isFlag(tfSell)) { offerCrossing = OfferCrossing::Sell; // We are selling, so we will accept *more* than the offer @@ -437,9 +433,9 @@ OfferCreate::flowCross( accountID_, accountID_, paths, - true, // default path - (txFlags & tfFillOrKill) == 0u, // partial payment - true, // owner pays transfer fee + true, // default path + !ctx_.tx.isFlag(tfFillOrKill), // partial payment + true, // owner pays transfer fee offerCrossing, threshold, sendMax, @@ -478,7 +474,7 @@ OfferCreate::flowCross( { STAmount const rate{Quality{takerAmount.out, takerAmount.in}.rate()}; - if ((txFlags & tfSell) != 0u) + if (ctx_.tx.isFlag(tfSell)) { // If selling then scale the new out amount based on how // much we sold during crossing. This preserves the offer @@ -597,13 +593,11 @@ OfferCreate::applyGuts(Sandbox& sb, Sandbox& sbCancel) { using beast::kZERO; - std::uint32_t const uTxFlags = ctx_.tx.getFlags(); - - bool const bPassive((uTxFlags & tfPassive) != 0u); - bool const bImmediateOrCancel((uTxFlags & tfImmediateOrCancel) != 0u); - bool const bFillOrKill((uTxFlags & tfFillOrKill) != 0u); - bool const bSell((uTxFlags & tfSell) != 0u); - bool const bHybrid((uTxFlags & tfHybrid) != 0u); + bool const bPassive(ctx_.tx.isFlag(tfPassive)); + bool const bImmediateOrCancel(ctx_.tx.isFlag(tfImmediateOrCancel)); + bool const bFillOrKill(ctx_.tx.isFlag(tfFillOrKill)); + bool const bSell(ctx_.tx.isFlag(tfSell)); + bool const bHybrid(ctx_.tx.isFlag(tfHybrid)); auto saTakerPays = ctx_.tx[sfTakerPays]; auto saTakerGets = ctx_.tx[sfTakerGets]; diff --git a/src/libxrpl/tx/transactors/nft/NFTokenAcceptOffer.cpp b/src/libxrpl/tx/transactors/nft/NFTokenAcceptOffer.cpp index fadb20a567..8e5cc4618b 100644 --- a/src/libxrpl/tx/transactors/nft/NFTokenAcceptOffer.cpp +++ b/src/libxrpl/tx/transactors/nft/NFTokenAcceptOffer.cpp @@ -160,7 +160,7 @@ NFTokenAcceptOffer::preclaim(PreclaimContext const& ctx) if (bo) { - if (((*bo)[sfFlags] & lsfSellNFToken) == lsfSellNFToken) + if (bo->isFlag(lsfSellNFToken)) return tecNFTOKEN_OFFER_TYPE_MISMATCH; // An account can't accept an offer it placed: @@ -219,7 +219,7 @@ NFTokenAcceptOffer::preclaim(PreclaimContext const& ctx) if (so) { - if (((*so)[sfFlags] & lsfSellNFToken) != lsfSellNFToken) + if (!so->isFlag(lsfSellNFToken)) return tecNFTOKEN_OFFER_TYPE_MISMATCH; // An account can't accept an offer it placed: diff --git a/src/libxrpl/tx/transactors/nft/NFTokenCreateOffer.cpp b/src/libxrpl/tx/transactors/nft/NFTokenCreateOffer.cpp index 727290a80c..9c7fe7d5ef 100644 --- a/src/libxrpl/tx/transactors/nft/NFTokenCreateOffer.cpp +++ b/src/libxrpl/tx/transactors/nft/NFTokenCreateOffer.cpp @@ -55,9 +55,8 @@ NFTokenCreateOffer::preclaim(PreclaimContext const& ctx) uint256 const nftokenID = ctx.tx[sfNFTokenID]; std::uint32_t const txFlags = ctx.tx.getFlags(); - if (!nft::findToken( - ctx.view, ctx.tx[((txFlags & tfSellNFToken) != 0u) ? sfAccount : sfOwner], nftokenID)) + ctx.view, ctx.tx[ctx.tx.isFlag(tfSellNFToken) ? sfAccount : sfOwner], nftokenID)) return tecNO_ENTRY; // Use implementation shared with NFTokenMint diff --git a/src/libxrpl/tx/transactors/payment/Payment.cpp b/src/libxrpl/tx/transactors/payment/Payment.cpp index 652b976336..47d6a1fa75 100644 --- a/src/libxrpl/tx/transactors/payment/Payment.cpp +++ b/src/libxrpl/tx/transactors/payment/Payment.cpp @@ -122,14 +122,12 @@ Payment::preflight(PreflightContext const& ctx) if (!ctx.rules.enabled(featureMPTokensV1) && isDstMPT) return temDISABLED; - std::uint32_t const txFlags = tx.getFlags(); - if (!mpTokensV2 && isDstMPT && ctx.tx.isFieldPresent(sfPaths)) return temMALFORMED; - bool const partialPaymentAllowed = (txFlags & tfPartialPayment) != 0u; - bool const limitQuality = (txFlags & tfLimitQuality) != 0u; - bool const defaultPathsAllowed = (txFlags & tfNoRippleDirect) == 0u; + bool const partialPaymentAllowed = tx.isFlag(tfPartialPayment); + bool const limitQuality = tx.isFlag(tfLimitQuality); + bool const defaultPathsAllowed = !tx.isFlag(tfNoRippleDirect); bool const hasPaths = tx.isFieldPresent(sfPaths); bool const hasMax = tx.isFieldPresent(sfSendMax); @@ -311,8 +309,7 @@ TER Payment::preclaim(PreclaimContext const& ctx) { // Ripple if source or destination is non-native or if there are paths. - std::uint32_t const txFlags = ctx.tx.getFlags(); - bool const partialPaymentAllowed = (txFlags & tfPartialPayment) != 0u; + bool const partialPaymentAllowed = ctx.tx.isFlag(tfPartialPayment); auto const hasPaths = ctx.tx.isFieldPresent(sfPaths); auto const sendMax = ctx.tx[~sfSendMax]; @@ -405,10 +402,9 @@ Payment::doApply() auto const deliverMin = ctx_.tx[~sfDeliverMin]; // Ripple if source or destination is non-native or if there are paths. - std::uint32_t const txFlags = ctx_.tx.getFlags(); - bool const partialPaymentAllowed = (txFlags & tfPartialPayment) != 0u; - bool const limitQuality = (txFlags & tfLimitQuality) != 0u; - bool const defaultPathsAllowed = (txFlags & tfNoRippleDirect) == 0u; + bool const partialPaymentAllowed = ctx_.tx.isFlag(tfPartialPayment); + bool const limitQuality = ctx_.tx.isFlag(tfLimitQuality); + bool const defaultPathsAllowed = !ctx_.tx.isFlag(tfNoRippleDirect); auto const hasPaths = ctx_.tx.isFieldPresent(sfPaths); auto const sendMax = ctx_.tx[~sfSendMax]; diff --git a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelClaim.cpp b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelClaim.cpp index d112815998..32069da8bf 100644 --- a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelClaim.cpp +++ b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelClaim.cpp @@ -55,9 +55,7 @@ PaymentChannelClaim::preflight(PreflightContext const& ctx) return temBAD_AMOUNT; { - auto const flags = ctx.tx.getFlags(); - - if (((flags & tfClose) != 0u) && ((flags & tfRenew) != 0u)) + if (ctx.tx.isFlag(tfClose) && ctx.tx.isFlag(tfRenew)) return temMALFORMED; } @@ -173,7 +171,7 @@ PaymentChannelClaim::doApply() ctx_.view().update(slep); } - if ((ctx_.tx.getFlags() & tfRenew) != 0u) + if (ctx_.tx.isFlag(tfRenew)) { if (src != txAccount) return tecNO_PERMISSION; @@ -181,7 +179,7 @@ PaymentChannelClaim::doApply() ctx_.view().update(slep); } - if ((ctx_.tx.getFlags() & tfClose) != 0u) + if (ctx_.tx.isFlag(tfClose)) { // Channel will close immediately if dry or the receiver closes if (dst == txAccount || (*slep)[sfBalance] == (*slep)[sfAmount]) diff --git a/src/libxrpl/tx/transactors/system/Batch.cpp b/src/libxrpl/tx/transactors/system/Batch.cpp index a7c9ef52a0..a278b838b9 100644 --- a/src/libxrpl/tx/transactors/system/Batch.cpp +++ b/src/libxrpl/tx/transactors/system/Batch.cpp @@ -287,7 +287,7 @@ Batch::preflight(PreflightContext const& ctx) return temINVALID_INNER_BATCH; } - if ((stx.getFlags() & tfInnerBatchTxn) == 0u) + if (!stx.isFlag(tfInnerBatchTxn)) { JLOG(ctx.j.debug()) << "BatchTrace[" << parentBatchId << "]: " << "inner txn must have the tfInnerBatchTxn flag. " diff --git a/src/libxrpl/tx/transactors/system/Change.cpp b/src/libxrpl/tx/transactors/system/Change.cpp index 4701e805fd..b251ca3899 100644 --- a/src/libxrpl/tx/transactors/system/Change.cpp +++ b/src/libxrpl/tx/transactors/system/Change.cpp @@ -177,10 +177,8 @@ Change::applyAmendment() if (std::ranges::find(amendments, amendment) != amendments.end()) return tefALREADY; - auto flags = ctx_.tx.getFlags(); - - bool const gotMajority = (flags & tfGotMajority) != 0; - bool const lostMajority = (flags & tfLostMajority) != 0; + bool const gotMajority = ctx_.tx.isFlag(tfGotMajority); + bool const lostMajority = ctx_.tx.isFlag(tfLostMajority); if (gotMajority && lostMajority) return temINVALID_FLAG; diff --git a/src/libxrpl/tx/transactors/token/Clawback.cpp b/src/libxrpl/tx/transactors/token/Clawback.cpp index b099bdadc1..34513304f9 100644 --- a/src/libxrpl/tx/transactors/token/Clawback.cpp +++ b/src/libxrpl/tx/transactors/token/Clawback.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -105,12 +104,9 @@ preclaimHelper( AccountID const& holder, STAmount const& clawAmount) { - std::uint32_t const issuerFlagsIn = sleIssuer.getFieldU32(sfFlags); - // If AllowTrustLineClawback is not set or NoFreeze is set, return no // permission - if (((issuerFlagsIn & lsfAllowTrustLineClawback) == 0u) || - ((issuerFlagsIn & lsfNoFreeze) != 0u)) + if (!sleIssuer.isFlag(lsfAllowTrustLineClawback) || sleIssuer.isFlag(lsfNoFreeze)) return tecNO_PERMISSION; auto const sleRippleState = @@ -163,7 +159,7 @@ preclaimHelper( if (!sleIssuance) return tecOBJECT_NOT_FOUND; - if (((*sleIssuance)[sfFlags] & lsfMPTCanClawback) == 0u) + if (!sleIssuance->isFlag(lsfMPTCanClawback)) return tecNO_PERMISSION; if (sleIssuance->getAccountID(sfIssuer) != issuer) diff --git a/src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp b/src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp index 0869dbfda2..c889c8470f 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp @@ -58,7 +58,7 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx) // before fetching the MPTIssuance object. // if holder wants to delete/unauthorize a mpt - if ((ctx.tx.getFlags() & tfMPTUnauthorize) != 0u) + if (ctx.tx.isFlag(tfMPTUnauthorize)) { if (!sleMpt) return tecOBJECT_NOT_FOUND; @@ -112,8 +112,6 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx) if (!sleMptIssuance) return tecOBJECT_NOT_FOUND; - std::uint32_t const mptIssuanceFlags = sleMptIssuance->getFieldU32(sfFlags); - // If tx is submitted by issuer, they would either try to do the following // for allowlisting: // 1. authorize an account @@ -126,7 +124,7 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx) // If tx is submitted by issuer, it only applies for MPT with // lsfMPTRequireAuth set - if ((mptIssuanceFlags & lsfMPTRequireAuth) == 0u) + if (!sleMptIssuance->isFlag(lsfMPTRequireAuth)) return tecNO_AUTH; // The holder must create the MPT before the issuer can authorize it. diff --git a/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp b/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp index 31bc1aaf77..6bbbc6429c 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp @@ -72,7 +72,7 @@ MPTokenIssuanceCreate::preflight(PreflightContext const& ctx) return temMALFORMED; // Domain present implies that MPTokenIssuance is not public - if ((ctx.tx.getFlags() & tfMPTRequireAuth) == 0) + if (!ctx.tx.isFlag(tfMPTRequireAuth)) return temMALFORMED; } diff --git a/src/libxrpl/tx/transactors/token/MPTokenIssuanceSet.cpp b/src/libxrpl/tx/transactors/token/MPTokenIssuanceSet.cpp index 05089621c6..438d7614c5 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenIssuanceSet.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenIssuanceSet.cpp @@ -86,10 +86,8 @@ MPTokenIssuanceSet::preflight(PreflightContext const& ctx) if (ctx.tx.isFieldPresent(sfDomainID) && ctx.tx.isFieldPresent(sfHolder)) return temMALFORMED; - auto const txFlags = ctx.tx.getFlags(); - // fails if both flags are set - if (((txFlags & tfMPTLock) != 0u) && ((txFlags & tfMPTUnlock) != 0u)) + if (ctx.tx.isFlag(tfMPTLock) && ctx.tx.isFlag(tfMPTUnlock)) return temINVALID_FLAG; auto const accountID = ctx.tx[sfAccount]; @@ -100,7 +98,7 @@ MPTokenIssuanceSet::preflight(PreflightContext const& ctx) if (ctx.rules.enabled(featureSingleAssetVault) || ctx.rules.enabled(featureDynamicMPT)) { // Is this transaction actually changing anything ? - if (txFlags == 0 && !ctx.tx.isFieldPresent(sfDomainID) && !isMutate) + if (ctx.tx.getFlags() == 0 && !ctx.tx.isFieldPresent(sfDomainID) && !isMutate) return temMALFORMED; } @@ -111,7 +109,7 @@ MPTokenIssuanceSet::preflight(PreflightContext const& ctx) return temMALFORMED; // Can not set flags when mutating MPTokenIssuance - if (isMutate && ((txFlags & tfUniversalMask) != 0u)) + if (isMutate && ((ctx.tx.getFlags() & tfUniversalMask) != 0u)) return temMALFORMED; if (transferFee && *transferFee > kMAX_TRANSFER_FEE) @@ -157,20 +155,18 @@ MPTokenIssuanceSet::checkPermission(ReadView const& view, STTx const& tx) if (isTesSuccess(checkTxPermission(sle, tx))) return tesSUCCESS; - auto const txFlags = tx.getFlags(); - // this is added in case more flags will be added for MPTokenIssuanceSet // in the future. Currently unreachable. - if ((txFlags & tfMPTokenIssuanceSetMask) != 0u) + if ((tx.getFlags() & tfMPTokenIssuanceSetMask) != 0u) return terNO_DELEGATE_PERMISSION; // LCOV_EXCL_LINE std::unordered_set granularPermissions; loadGranularPermission(sle, ttMPTOKEN_ISSUANCE_SET, granularPermissions); - if (((txFlags & tfMPTLock) != 0u) && !granularPermissions.contains(MPTokenIssuanceLock)) + if (tx.isFlag(tfMPTLock) && !granularPermissions.contains(MPTokenIssuanceLock)) return terNO_DELEGATE_PERMISSION; - if (((txFlags & tfMPTUnlock) != 0u) && !granularPermissions.contains(MPTokenIssuanceUnlock)) + if (tx.isFlag(tfMPTUnlock) && !granularPermissions.contains(MPTokenIssuanceUnlock)) return terNO_DELEGATE_PERMISSION; return tesSUCCESS; @@ -273,7 +269,6 @@ TER MPTokenIssuanceSet::doApply() { auto const mptIssuanceID = ctx_.tx[sfMPTokenIssuanceID]; - auto const txFlags = ctx_.tx.getFlags(); auto const holderID = ctx_.tx[~sfHolder]; auto const domainID = ctx_.tx[~sfDomainID]; std::shared_ptr sle; @@ -293,11 +288,11 @@ MPTokenIssuanceSet::doApply() std::uint32_t const flagsIn = sle->getFieldU32(sfFlags); std::uint32_t flagsOut = flagsIn; - if ((txFlags & tfMPTLock) != 0u) + if (ctx_.tx.isFlag(tfMPTLock)) { flagsOut |= lsfMPTLocked; } - else if ((txFlags & tfMPTUnlock) != 0u) + else if (ctx_.tx.isFlag(tfMPTUnlock)) { flagsOut &= ~lsfMPTLocked; } diff --git a/src/libxrpl/tx/transactors/token/TrustSet.cpp b/src/libxrpl/tx/transactors/token/TrustSet.cpp index 705e3b55a1..5065ed5bb1 100644 --- a/src/libxrpl/tx/transactors/token/TrustSet.cpp +++ b/src/libxrpl/tx/transactors/token/TrustSet.cpp @@ -78,13 +78,11 @@ TrustSet::preflight(PreflightContext const& ctx) auto& tx = ctx.tx; auto& j = ctx.j; - std::uint32_t const uTxFlags = tx.getFlags(); - if (!ctx.rules.enabled(featureDeepFreeze)) { // Even though the deep freeze flags are included in the // `tfTrustSetMask`, they are not valid if the amendment is not enabled. - if ((uTxFlags & (tfSetDeepFreeze | tfClearDeepFreeze)) != 0u) + if ((tx.getFlags() & (tfSetDeepFreeze | tfClearDeepFreeze)) != 0u) { return temINVALID_FLAG; } @@ -142,12 +140,10 @@ TrustSet::checkPermission(ReadView const& view, STTx const& tx) if (isTesSuccess(checkTxPermission(sle, tx))) return tesSUCCESS; - std::uint32_t const txFlags = tx.getFlags(); - // Currently we only support TrustlineAuthorize, TrustlineFreeze and // TrustlineUnfreeze granular permission. Setting other flags returns // error. - if ((txFlags & tfTrustSetPermissionMask) != 0u) + if ((tx.getFlags() & tfTrustSetPermissionMask) != 0u) return terNO_DELEGATE_PERMISSION; if (tx.isFieldPresent(sfQualityIn) || tx.isFieldPresent(sfQualityOut)) @@ -166,11 +162,11 @@ TrustSet::checkPermission(ReadView const& view, STTx const& tx) std::unordered_set granularPermissions; loadGranularPermission(sle, ttTRUST_SET, granularPermissions); - if (((txFlags & tfSetfAuth) != 0u) && !granularPermissions.contains(TrustlineAuthorize)) + if (tx.isFlag(tfSetfAuth) && !granularPermissions.contains(TrustlineAuthorize)) return terNO_DELEGATE_PERMISSION; - if (((txFlags & tfSetFreeze) != 0u) && !granularPermissions.contains(TrustlineFreeze)) + if (tx.isFlag(tfSetFreeze) && !granularPermissions.contains(TrustlineFreeze)) return terNO_DELEGATE_PERMISSION; - if (((txFlags & tfClearFreeze) != 0u) && !granularPermissions.contains(TrustlineUnfreeze)) + if (tx.isFlag(tfClearFreeze) && !granularPermissions.contains(TrustlineUnfreeze)) return terNO_DELEGATE_PERMISSION; // updating LimitAmount is not allowed only with granular permissions, @@ -198,7 +194,6 @@ TrustSet::preclaim(PreclaimContext const& ctx) return terNO_ACCOUNT; std::uint32_t const uTxFlags = ctx.tx.getFlags(); - bool const bSetAuth = (uTxFlags & tfSetfAuth) != 0u; if (bSetAuth && ((acct->getFieldU32(sfFlags) & lsfRequireAuth) == 0u)) @@ -297,8 +292,8 @@ TrustSet::preclaim(PreclaimContext const& ctx) return tecNO_PERMISSION; } - bool const bClearFreeze = (uTxFlags & tfClearFreeze) != 0u; - bool const bClearDeepFreeze = (uTxFlags & tfClearDeepFreeze) != 0u; + bool const bClearFreeze = ctx.tx.isFlag(tfClearFreeze); + bool const bClearDeepFreeze = ctx.tx.isFlag(tfClearDeepFreeze); if ((bSetFreeze || bSetDeepFreeze) && (bClearFreeze || bClearDeepFreeze)) { // Freezing and unfreezing in the same transaction should be @@ -377,15 +372,13 @@ TrustSet::doApply() if (bQualityOut && QUALITY_ONE == uQualityOut) uQualityOut = 0; - std::uint32_t const uTxFlags = ctx_.tx.getFlags(); - - bool const bSetAuth = (uTxFlags & tfSetfAuth) != 0u; - bool const bSetNoRipple = (uTxFlags & tfSetNoRipple) != 0u; - bool const bClearNoRipple = (uTxFlags & tfClearNoRipple) != 0u; - bool const bSetFreeze = (uTxFlags & tfSetFreeze) != 0u; - bool const bClearFreeze = (uTxFlags & tfClearFreeze) != 0u; - bool const bSetDeepFreeze = (uTxFlags & tfSetDeepFreeze) != 0u; - bool const bClearDeepFreeze = (uTxFlags & tfClearDeepFreeze) != 0u; + bool const bSetAuth = ctx_.tx.isFlag(tfSetfAuth); + bool const bSetNoRipple = ctx_.tx.isFlag(tfSetNoRipple); + bool const bClearNoRipple = ctx_.tx.isFlag(tfClearNoRipple); + bool const bSetFreeze = ctx_.tx.isFlag(tfSetFreeze); + bool const bClearFreeze = ctx_.tx.isFlag(tfClearFreeze); + bool const bSetDeepFreeze = ctx_.tx.isFlag(tfSetDeepFreeze); + bool const bClearDeepFreeze = ctx_.tx.isFlag(tfClearDeepFreeze); auto viewJ = ctx_.registry.get().getJournal("View"); @@ -552,8 +545,8 @@ TrustSet::doApply() bool const bDefault = bLowReserveClear && bHighReserveClear; - bool const bLowReserved = (uFlagsIn & lsfLowReserve) != 0u; - bool const bHighReserved = (uFlagsIn & lsfHighReserve) != 0u; + bool const bLowReserved = sleRippleState->isFlag(lsfLowReserve); + bool const bHighReserved = sleRippleState->isFlag(lsfHighReserve); bool bReserveIncrease = false; diff --git a/src/libxrpl/tx/transactors/vault/VaultClawback.cpp b/src/libxrpl/tx/transactors/vault/VaultClawback.cpp index 15e2b229d5..3ef6e7b14e 100644 --- a/src/libxrpl/tx/transactors/vault/VaultClawback.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultClawback.cpp @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -186,8 +185,7 @@ VaultClawback::preclaim(PreclaimContext const& ctx) if (mptIssue == nullptr) return tecOBJECT_NOT_FOUND; - std::uint32_t const issueFlags = mptIssue->getFieldU32(sfFlags); - if ((issueFlags & lsfMPTCanClawback) == 0u) + if (!mptIssue->isFlag(lsfMPTCanClawback)) { JLOG(ctx.j.debug()) << "VaultClawback: cannot clawback " "MPT vault asset."; @@ -206,9 +204,7 @@ VaultClawback::preclaim(PreclaimContext const& ctx) // LCOV_EXCL_STOP } - std::uint32_t const issuerFlags = issuerSle->getFieldU32(sfFlags); - if (((issuerFlags & lsfAllowTrustLineClawback) == 0u) || - ((issuerFlags & lsfNoFreeze) != 0u)) + if (!issuerSle->isFlag(lsfAllowTrustLineClawback) || issuerSle->isFlag(lsfNoFreeze)) { JLOG(ctx.j.debug()) << "VaultClawback: cannot clawback " "IOU vault asset."; diff --git a/src/libxrpl/tx/transactors/vault/VaultCreate.cpp b/src/libxrpl/tx/transactors/vault/VaultCreate.cpp index 38564b5563..3090850e2f 100644 --- a/src/libxrpl/tx/transactors/vault/VaultCreate.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultCreate.cpp @@ -68,7 +68,7 @@ VaultCreate::preflight(PreflightContext const& ctx) { return temMALFORMED; } - if ((ctx.tx.getFlags() & tfVaultPrivate) == 0) + if (!ctx.tx.isFlag(tfVaultPrivate)) { return temMALFORMED; // DomainID only allowed on private vaults } @@ -174,11 +174,10 @@ VaultCreate::doApply() ? 0 : ctx_.tx[~sfScale].value_or(kVAULT_DEFAULT_IOU_SCALE); - auto txFlags = tx.getFlags(); std::uint32_t mptFlags = 0; - if ((txFlags & tfVaultShareNonTransferable) == 0) + if (!tx.isFlag(tfVaultShareNonTransferable)) mptFlags |= (lsfMPTCanEscrow | lsfMPTCanTrade | lsfMPTCanTransfer); - if ((txFlags & tfVaultPrivate) != 0u) + if (tx.isFlag(tfVaultPrivate)) mptFlags |= lsfMPTRequireAuth; // Note, here we are **not** creating an MPToken for the assets held in @@ -204,7 +203,7 @@ VaultCreate::doApply() auto const& mptIssuanceID = *maybeShare; vault->setFieldIssue(sfAsset, STIssue{sfAsset, asset}); - vault->at(sfFlags) = txFlags & tfVaultPrivate; + vault->at(sfFlags) = tx.getFlags() & tfVaultPrivate; vault->at(sfSequence) = sequence; vault->at(sfOwner) = accountID_; vault->at(sfAccount) = pseudoId; @@ -237,7 +236,7 @@ VaultCreate::doApply() return err; // If the vault is private, set the authorized flag for the vault owner - if ((txFlags & tfVaultPrivate) != 0u) + if (tx.isFlag(tfVaultPrivate)) { if (auto const err = authorizeMPToken( view(), preFeeBalance_, mptIssuanceID, pseudoId, ctx_.journal, {}, accountID_); diff --git a/src/libxrpl/tx/transactors/vault/VaultSet.cpp b/src/libxrpl/tx/transactors/vault/VaultSet.cpp index 78627f22b7..684413399d 100644 --- a/src/libxrpl/tx/transactors/vault/VaultSet.cpp +++ b/src/libxrpl/tx/transactors/vault/VaultSet.cpp @@ -103,7 +103,7 @@ VaultSet::preclaim(PreclaimContext const& ctx) } // Sanity check only, this should be enforced by VaultCreate - if ((sleIssuance->getFlags() & lsfMPTRequireAuth) == 0) + if (!sleIssuance->isFlag(lsfMPTRequireAuth)) { // LCOV_EXCL_START JLOG(ctx.j.error()) << "VaultSet: issuance of vault shares is not private."; diff --git a/src/test/app/Credentials_test.cpp b/src/test/app/Credentials_test.cpp index c321c3bdca..0ab7fc341b 100644 --- a/src/test/app/Credentials_test.cpp +++ b/src/test/app/Credentials_test.cpp @@ -143,7 +143,7 @@ struct Credentials_test : public beast::unit_test::Suite BEAST_EXPECT(sleCred->getAccountID(sfSubject) == issuer.id()); BEAST_EXPECT(sleCred->getAccountID(sfIssuer) == issuer.id()); - BEAST_EXPECT((sleCred->getFieldU32(sfFlags) & lsfAccepted)); + BEAST_EXPECT(sleCred->isFlag(lsfAccepted)); BEAST_EXPECT( sleCred->getFieldU64(sfIssuerNode) == sleCred->getFieldU64(sfSubjectNode)); BEAST_EXPECT(ownerCount(env, issuer) == 1); @@ -1075,7 +1075,7 @@ struct Credentials_test : public beast::unit_test::Suite // Verify credential exists and is accepted { auto const sleCred = env.current()->read(credKeylet); - BEAST_EXPECT(sleCred && sleCred->getFlags() & lsfAccepted); + BEAST_EXPECT(sleCred && sleCred->isFlag(lsfAccepted)); } // Create DepositPreauth @@ -1129,11 +1129,11 @@ struct Credentials_test : public beast::unit_test::Suite RAccountRoot const dst(becky.id(), av, j); auto const dpTer = xrpl::verifyDepositPreauth(*stx, av, subject, dst, j); auto sleCredAfter = av.read(credKeylet); - BEAST_EXPECT(sleCredAfter && (sleCredAfter->getFlags() & lsfAccepted)); + BEAST_EXPECT(sleCredAfter && sleCredAfter->isFlag(lsfAccepted)); auto const domTer = xrpl::verifyValidDomain(av, subject.id(), domain, j); sleCredAfter = av.read(credKeylet); - BEAST_EXPECT(sleCredAfter && (sleCredAfter->getFlags() & lsfAccepted)); + BEAST_EXPECT(sleCredAfter && sleCredAfter->isFlag(lsfAccepted)); if (fixEnabled) { diff --git a/src/test/app/DepositAuth_test.cpp b/src/test/app/DepositAuth_test.cpp index 5452f02175..7b371b3c06 100644 --- a/src/test/app/DepositAuth_test.cpp +++ b/src/test/app/DepositAuth_test.cpp @@ -58,7 +58,7 @@ reserve(jtx::Env& env, std::uint32_t count) static bool hasDepositAuth(jtx::Env const& env, jtx::Account const& acct) { - return ((*env.le(acct))[sfFlags] & lsfDepositAuth) == lsfDepositAuth; + return env.le(acct)->isFlag(lsfDepositAuth); } struct DepositAuth_test : public beast::unit_test::Suite diff --git a/src/test/app/SetRegularKey_test.cpp b/src/test/app/SetRegularKey_test.cpp index 00b1fe3f84..b9cba43011 100644 --- a/src/test/app/SetRegularKey_test.cpp +++ b/src/test/app/SetRegularKey_test.cpp @@ -84,15 +84,12 @@ public: env.fund(XRP(10000), alice, bob); auto ar = env.le(alice); - BEAST_EXPECT( - ar->isFieldPresent(sfFlags) && ((ar->getFieldU32(sfFlags) & lsfPasswordSpent) == 0)); + BEAST_EXPECT(ar->isFieldPresent(sfFlags) && !ar->isFlag(lsfPasswordSpent)); env(regkey(alice, bob), Sig(alice), Fee(0)); ar = env.le(alice); - BEAST_EXPECT( - ar->isFieldPresent(sfFlags) && - ((ar->getFieldU32(sfFlags) & lsfPasswordSpent) == lsfPasswordSpent)); + BEAST_EXPECT(ar->isFieldPresent(sfFlags) && ar->isFlag(lsfPasswordSpent)); // The second SetRegularKey transaction with Fee=0 should fail. env(regkey(alice, bob), Sig(alice), Fee(0), Ter(telINSUF_FEE_P)); @@ -100,8 +97,7 @@ public: env.trust(bob["USD"](1), alice); env(pay(bob, alice, bob["USD"](1))); ar = env.le(alice); - BEAST_EXPECT( - ar->isFieldPresent(sfFlags) && ((ar->getFieldU32(sfFlags) & lsfPasswordSpent) == 0)); + BEAST_EXPECT(ar->isFieldPresent(sfFlags) && !ar->isFlag(lsfPasswordSpent)); } void diff --git a/src/test/jtx/impl/flags.cpp b/src/test/jtx/impl/flags.cpp index 7733335668..ad49f559f3 100644 --- a/src/test/jtx/impl/flags.cpp +++ b/src/test/jtx/impl/flags.cpp @@ -34,7 +34,7 @@ Flags::operator()(Env& env) const } else if (sle->isFieldPresent(sfFlags)) { - env.test.expect((sle->getFieldU32(sfFlags) & mask_) == mask_); + env.test.expect(sle->isFlag(mask_)); } else { diff --git a/src/test/peerfinder/PeerFinder_test.cpp b/src/test/peerfinder/PeerFinder_test.cpp index 17ce6835ef..2e4ab001b4 100644 --- a/src/test/peerfinder/PeerFinder_test.cpp +++ b/src/test/peerfinder/PeerFinder_test.cpp @@ -424,7 +424,7 @@ public: (c.PEERS_MAX == max && c.PEERS_IN_MAX == 0 && c.PEERS_OUT_MAX == 0) || (c.PEERS_IN_MAX == *maxIn && c.PEERS_OUT_MAX == *maxOut)); - Config const config = Config::makeConfig(c, port, false, 0); + Config const config = Config::makeConfig(c, port, false, 0, true); Counts counts; counts.onConfig(config); diff --git a/src/xrpld/app/main/Application.cpp b/src/xrpld/app/main/Application.cpp index f7679d14d8..20a81f6768 100644 --- a/src/xrpld/app/main/Application.cpp +++ b/src/xrpld/app/main/Application.cpp @@ -1357,7 +1357,7 @@ ApplicationImp::setup(boost::program_options::variables_map const& cmdline) // if (!config_.standalone()) overlay_ = makeOverlay( *this, - setupOverlay(*config_), + setupOverlay(*config_, journal_), *serverHandler_, *resourceManager_, *resolver_, diff --git a/src/xrpld/overlay/Overlay.h b/src/xrpld/overlay/Overlay.h index 80430293d8..ef97ea7f24 100644 --- a/src/xrpld/overlay/Overlay.h +++ b/src/xrpld/overlay/Overlay.h @@ -47,6 +47,7 @@ public: std::uint32_t crawlOptions = 0; std::optional networkID; bool vlEnabled = true; + bool verifyEndpoints = true; }; using PeerSequence = std::vector>; diff --git a/src/xrpld/overlay/detail/OverlayImpl.cpp b/src/xrpld/overlay/detail/OverlayImpl.cpp index bfed850e5c..770df6e43a 100644 --- a/src/xrpld/overlay/detail/OverlayImpl.cpp +++ b/src/xrpld/overlay/detail/OverlayImpl.cpp @@ -508,7 +508,8 @@ OverlayImpl::start() app_.config(), serverHandler_.setup().overlay.port(), app_.getValidationPublicKey().has_value(), - setup_.ipLimit); + setup_.ipLimit, + setup_.verifyEndpoints); peerFinder_->setConfig(config); peerFinder_->start(); @@ -1510,7 +1511,7 @@ OverlayImpl::deleteIdlePeers() //------------------------------------------------------------------------------ Overlay::Setup -setupOverlay(BasicConfig const& config) +setupOverlay(BasicConfig const& config, beast::Journal j) { Overlay::Setup setup; @@ -1528,9 +1529,17 @@ setupOverlay(BasicConfig const& config) { boost::system::error_code ec; setup.publicIp = boost::asio::ip::make_address(ip, ec); - if (ec || beast::IP::isPrivate(setup.publicIp)) + if (ec || !beast::IP::isPublic(setup.publicIp)) Throw("Configured public IP is invalid"); } + + set(setup.verifyEndpoints, true, "verify_endpoints", section); + if (!setup.verifyEndpoints) + { + JLOG(j.warn()) << "Endpoint verification is disabled. This is a " + "security risk and should only be used for " + "testing."; + } } { diff --git a/src/xrpld/overlay/make_Overlay.h b/src/xrpld/overlay/make_Overlay.h index 94d1110f4b..acd477deec 100644 --- a/src/xrpld/overlay/make_Overlay.h +++ b/src/xrpld/overlay/make_Overlay.h @@ -10,7 +10,7 @@ namespace xrpl { Overlay::Setup -setupOverlay(BasicConfig const& config); +setupOverlay(BasicConfig const& config, beast::Journal j); /** Creates the implementation of Overlay. */ std::unique_ptr diff --git a/src/xrpld/peerfinder/PeerfinderManager.h b/src/xrpld/peerfinder/PeerfinderManager.h index 5b235a4db1..083abf92c6 100644 --- a/src/xrpld/peerfinder/PeerfinderManager.h +++ b/src/xrpld/peerfinder/PeerfinderManager.h @@ -59,6 +59,9 @@ struct Config /** Limit how many incoming connections we allow per IP */ int ipLimit{0}; + /** `true` if we want to verify endpoints in TMEndpoints messages */ + bool verifyEndpoints = true; + //-------------------------------------------------------------------------- /** Create a configuration with default values. */ @@ -81,6 +84,8 @@ struct Config * @param port server's listening port * @param validationPublicKey true if validation public key is not empty * @param ipLimit limit of incoming connections per IP + * @param verifyEndpoints `true` if we want to verify endpoints in + * TMEndpoints messages * @return PeerFinder::Config */ static Config @@ -88,10 +93,11 @@ struct Config xrpl::Config const& config, std::uint16_t port, bool validationPublicKey, - int ipLimit); + int ipLimit, + bool verifyEndpoints); friend bool - operator==(Config const& lhs, Config const& rhs); + operator==(Config const& lhs, Config const& rhs) = default; }; //------------------------------------------------------------------------------ diff --git a/src/xrpld/peerfinder/detail/Logic.h b/src/xrpld/peerfinder/detail/Logic.h index fce5bb4afa..4d0cc9cf29 100644 --- a/src/xrpld/peerfinder/detail/Logic.h +++ b/src/xrpld/peerfinder/detail/Logic.h @@ -696,7 +696,7 @@ public: } // Discard invalid addresses - if (!isValidAddress(ep.address)) + if (config_.verifyEndpoints && !isValidAddress(ep.address)) { JLOG(journal.debug()) << beast::Leftw(18) << "Endpoints drop " << ep.address << " as invalid"; @@ -1088,6 +1088,8 @@ public: { if (isUnspecified(address)) return false; + if (isLoopback(address)) + return false; if (!isPublic(address)) return false; if (address.port() == 0) diff --git a/src/xrpld/peerfinder/detail/PeerfinderConfig.cpp b/src/xrpld/peerfinder/detail/PeerfinderConfig.cpp index 83b78883db..a8323f6239 100644 --- a/src/xrpld/peerfinder/detail/PeerfinderConfig.cpp +++ b/src/xrpld/peerfinder/detail/PeerfinderConfig.cpp @@ -15,16 +15,6 @@ Config::Config() : outPeers(calcOutPeers()) { } -bool -operator==(Config const& lhs, Config const& rhs) -{ - return lhs.autoConnect == rhs.autoConnect && lhs.peerPrivate == rhs.peerPrivate && - lhs.wantIncoming == rhs.wantIncoming && lhs.inPeers == rhs.inPeers && - lhs.maxPeers == rhs.maxPeers && lhs.outPeers == rhs.outPeers && - lhs.features == rhs.features && lhs.ipLimit == rhs.ipLimit && - lhs.listeningPort == rhs.listeningPort; -} - std::size_t Config::calcOutPeers() const { @@ -61,6 +51,7 @@ Config::onWrite(beast::PropertyStream::Map& map) const map["port"] = listeningPort; map["features"] = features; map["ip_limit"] = ipLimit; + map["verify_endpoints"] = verifyEndpoints; } Config @@ -68,7 +59,8 @@ Config::makeConfig( xrpl::Config const& cfg, std::uint16_t port, bool validationPublicKey, - int ipLimit) + int ipLimit, + bool verifyEndpoints) { PeerFinder::Config config; @@ -121,6 +113,7 @@ Config::makeConfig( config.listeningPort = port; config.features = ""; config.ipLimit = ipLimit; + config.verifyEndpoints = verifyEndpoints; // Enforce business rules config.applyTuning(); diff --git a/src/xrpld/rpc/detail/Pathfinder.cpp b/src/xrpld/rpc/detail/Pathfinder.cpp index 133eada2c9..258be24095 100644 --- a/src/xrpld/rpc/detail/Pathfinder.cpp +++ b/src/xrpld/rpc/detail/Pathfinder.cpp @@ -938,7 +938,7 @@ Pathfinder::isNoRipple( auto const flag((toAccount > fromAccount) ? lsfHighNoRipple : lsfLowNoRipple); - return sleRipple && ((sleRipple->getFieldU32(sfFlags) & flag) != 0u); + return sleRipple && sleRipple->isFlag(flag); } // Does this path end on an account-to-account link whose last account has diff --git a/src/xrpld/rpc/handlers/account/AccountLines.cpp b/src/xrpld/rpc/handlers/account/AccountLines.cpp index 967f5151b7..d8f067a3be 100644 --- a/src/xrpld/rpc/handlers/account/AccountLines.cpp +++ b/src/xrpld/rpc/handlers/account/AccountLines.cpp @@ -219,11 +219,11 @@ doAccountLines(RPC::JsonContext& context) { if (sleCur->getFieldAmount(sfLowLimit).getIssuer() == visitData.accountID) { - ignore = !(sleCur->getFieldU32(sfFlags) & lsfLowReserve); + ignore = !sleCur->isFlag(lsfLowReserve); } else { - ignore = !(sleCur->getFieldU32(sfFlags) & lsfHighReserve); + ignore = !sleCur->isFlag(lsfHighReserve); } } diff --git a/src/xrpld/rpc/handlers/account/NoRippleCheck.cpp b/src/xrpld/rpc/handlers/account/NoRippleCheck.cpp index bc7e5b13d4..cb7953a805 100644 --- a/src/xrpld/rpc/handlers/account/NoRippleCheck.cpp +++ b/src/xrpld/rpc/handlers/account/NoRippleCheck.cpp @@ -143,8 +143,7 @@ doNoRippleCheck(RPC::JsonContext& context) { bool const bLow = accountID == ownedItem->getFieldAmount(sfLowLimit).getIssuer(); - bool const bNoRipple = - ownedItem->getFieldU32(sfFlags) & (bLow ? lsfLowNoRipple : lsfHighNoRipple); + bool const bNoRipple = ownedItem->isFlag(bLow ? lsfLowNoRipple : lsfHighNoRipple); std::string problem; bool needFix = false; diff --git a/src/xrpld/rpc/handlers/orderbook/DepositAuthorized.cpp b/src/xrpld/rpc/handlers/orderbook/DepositAuthorized.cpp index 79509e0f1a..3c798f8ed3 100644 --- a/src/xrpld/rpc/handlers/orderbook/DepositAuthorized.cpp +++ b/src/xrpld/rpc/handlers/orderbook/DepositAuthorized.cpp @@ -136,7 +136,7 @@ doDepositAuthorized(RPC::JsonContext& context) return result; } - if ((sleCred->getFlags() & lsfAccepted) == 0u) + if (!sleCred->isFlag(lsfAccepted)) { RPC::injectError(RpcBadCredentials, "credentials aren't accepted", result); return result;