From a383d9bf58917e1472dc4b0cdbdd763494a3b004 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Thu, 2 Jul 2026 13:42:58 -0400 Subject: [PATCH] fix stuff --- .../xrpl/ledger/helpers/AccountRootHelpers.h | 54 +++++++- .../ledger/helpers/AccountRootHelpers.cpp | 123 ++++++++++-------- .../ledger/helpers/CredentialHelpers.cpp | 2 +- src/libxrpl/ledger/helpers/MPTokenHelpers.cpp | 2 +- src/libxrpl/ledger/helpers/OfferHelpers.cpp | 2 +- .../tx/transactors/check/CheckCancel.cpp | 2 +- .../tx/transactors/escrow/EscrowFinish.cpp | 2 +- .../token/MPTokenIssuanceDestroy.cpp | 2 +- 8 files changed, 125 insertions(+), 64 deletions(-) diff --git a/include/xrpl/ledger/helpers/AccountRootHelpers.h b/include/xrpl/ledger/helpers/AccountRootHelpers.h index 240d152ada..2058123277 100644 --- a/include/xrpl/ledger/helpers/AccountRootHelpers.h +++ b/include/xrpl/ledger/helpers/AccountRootHelpers.h @@ -134,16 +134,36 @@ void increaseOwnerCount( ApplyView& view, ReserveContext const& reserveCtx, - std::int32_t ownerCountAdj, - beast::Journal j = beast::Journal{beast::Journal::getNullSink()}); + std::uint32_t count, + beast::Journal j); -/** Adjust the owner counters of the account up or down. If object has sponsor adjust its counters - * too. Used primarily just before deleting the object. +/** Decrease owner-count fields when the caller supplies the sponsor. + * + * This helper does not delete a ledger object. It updates reserve accounting + * after the caller has removed an owner-counted reserve, or for special + * owner-count changes whose sponsor cannot be derived from an object's + * sfSponsor field. * * @param view The apply view for making changes * @param accountSle The account's ledger entry + * @param sponsorSle The sponsor's ledger entry (if applicable) + * @param count Amount to remove from the owner count + * @param j Journal for logging + */ +void +decreaseOwnerCount( + ApplyView& view, + ReserveContext const& reserveCtx, + std::uint32_t count, + beast::Journal j); + +/** Decrease the owner counters of the account. If the object has a sponsor, + * adjust its counters too. Used primarily just before deleting the object. + * + * @param view The apply view for making changes + * @param ownerSle The account's ledger entry * @param objectSle The object's ledger entry - * @param ownerCountAdj Adjustment amount for the account count + * @param count Positive amount to remove from the owner count * @param j Journal for logging (default: null sink) */ void @@ -151,8 +171,28 @@ decreaseOwnerCountForObject( ApplyView& view, SLE::pointer ownerSle, SLE::ref objectSle, - std::int32_t ownerCountAdj, - beast::Journal j = beast::Journal{beast::Journal::getNullSink()}); + std::uint32_t count, + beast::Journal j); + +/** Convenience overload that accepts AccountID instead of account SLE reference. + * + * @param view The apply view for making changes + * @param account The account ID + * @param objectSle The object's ledger entry + * @param count Amount to remove from the owner count + * @param j Journal for logging + */ +inline void +decreaseOwnerCountForObject( + ApplyView& view, + AccountID const& account, + SLE::ref objectSle, + std::uint32_t count, + beast::Journal j) +{ + SLE::ref accountSle = view.peek(keylet::account(account)); + decreaseOwnerCountForObject(view, accountSle, objectSle, count, j); +} /** Returns IOU issuer transfer fee as Rate. Rate specifies * the fee as fractions of 1 billion. For example, 1% transfer rate diff --git a/src/libxrpl/ledger/helpers/AccountRootHelpers.cpp b/src/libxrpl/ledger/helpers/AccountRootHelpers.cpp index bef0fea902..a3fdc3edc0 100644 --- a/src/libxrpl/ledger/helpers/AccountRootHelpers.cpp +++ b/src/libxrpl/ledger/helpers/AccountRootHelpers.cpp @@ -194,7 +194,7 @@ transferRate(ReadView const& view, AccountID const& issuer) } static void -adjustOwnerCountValue( +adjustOwnerCountImpl( ApplyView& view, SLE::ref sle, SF_UINT32 const& sfield, @@ -212,63 +212,85 @@ adjustOwnerCountValue( view.update(sle); } +static void +adjustOwnerCountSigned( + ApplyView& view, + SLE::ref accountSle, + SLE::ref sponsorSle, + std::int32_t adjustment, + beast::Journal j) +{ + XRPL_ASSERT(accountSle, "xrpl::adjustOwnerCountSigned : valid account sle"); + if (!accountSle) + return; // LCOV_EXCL_LINE + + auto const sleType = accountSle->getType(); + bool const validType = sponsorSle ? sleType == ltACCOUNT_ROOT + : sleType == ltLOAN_BROKER || sleType == ltACCOUNT_ROOT; + XRPL_ASSERT(validType, "xrpl::adjustOwnerCountSigned : valid account sle type"); + if (!validType) + return; // LCOV_EXCL_LINE + + XRPL_ASSERT(adjustment, "xrpl::adjustOwnerCountSigned : nonzero adjustment input"); + + auto const accountID = accountSle->getAccountID(sfAccount); + if (sponsorSle) + { + bool const validSponsorType = sponsorSle->getType() == ltACCOUNT_ROOT; + XRPL_ASSERT(validSponsorType, "xrpl::adjustOwnerCountSigned : valid sponsor sle type"); + if (!validSponsorType) + return; // LCOV_EXCL_LINE + auto const sponsorID = sponsorSle->getAccountID(sfAccount); + + adjustOwnerCountImpl(view, accountSle, sfSponsoredOwnerCount, accountID, adjustment, j); + adjustOwnerCountImpl(view, sponsorSle, sfSponsoringOwnerCount, sponsorID, adjustment, j); + + auto sponsorshipSle = view.peek(keylet::sponsorship(sponsorID, accountID)); + if (sponsorshipSle && adjustment > 0) + { + // Only decrease the pre-funded ReserveCount on Sponsorship if we assign new objects. + // Removing/reassigning ownership of the object doesn't increase RemainingOwnerCount + // back. Don't call hook because this counter is not something that requires reserve + // (like other sf...OwnerCounts do). + adjustOwnerCountImpl( + view, sponsorshipSle, sfRemainingOwnerCount, sponsorID, -adjustment, j, false); + } + } + adjustOwnerCountImpl(view, accountSle, sfOwnerCount, accountID, adjustment, j); +} + void increaseOwnerCount( ApplyView& view, ReserveContext const& reserveCtx, - std::int32_t ownerCountAdj, + std::uint32_t count, beast::Journal j) { - auto& accountSle = reserveCtx.accountSle; - if (!accountSle) + XRPL_ASSERT( + count != 0 && count <= std::numeric_limits::max(), + "xrpl::increaseOwnerCount : count in signed delta range"); + if (count == 0 || count > std::numeric_limits::max()) return; // LCOV_EXCL_LINE - auto const sleType = reserveCtx.accountSle->getType(); - bool const validType = reserveCtx.sponsorSle - ? sleType == ltACCOUNT_ROOT - : sleType == ltLOAN_BROKER || sleType == ltACCOUNT_ROOT; - if (!validType) + adjustOwnerCountSigned( + view, reserveCtx.accountSle, reserveCtx.sponsorSle, static_cast(count), j); +} + +void +decreaseOwnerCount( + ApplyView& view, + ReserveContext const& reserveCtx, + std::uint32_t count, + beast::Journal j) +{ + XRPL_ASSERT( + count != 0 && count <= std::numeric_limits::max(), + "xrpl::decreaseOwnerCount : count in signed delta range"); + if (count == 0 || count > std::numeric_limits::max()) return; // LCOV_EXCL_LINE - XRPL_ASSERT(ownerCountAdj, "xrpl::adjustOwnerCountSigned : nonzero adjustment input"); - - if (reserveCtx.isSponsored()) - { - if (reserveCtx.sponsorSle->getType() != ltACCOUNT_ROOT) - Throw("xrpl::adjustOwnerCount : valid sponsor sle type"); - - adjustOwnerCountValue( - view, - reserveCtx.accountSle, - sfSponsoredOwnerCount, - reserveCtx.accountID(), - ownerCountAdj, - j); - adjustOwnerCountValue( - view, - reserveCtx.sponsorSle, - sfSponsoringOwnerCount, - reserveCtx.sponsorID().value(), - ownerCountAdj, - j); - - if (reserveCtx.sponsorshipSle && ownerCountAdj > 0) - { - // update the pre-funded RemainingOwnerCount on Sponsorship ledger object - // Remaining owner count moves opposite to ownerCountAdj: - // +ownerCountAdj => consume reserve (-), - adjustOwnerCountValue( - view, - reserveCtx.sponsorshipSle, - sfRemainingOwnerCount, - reserveCtx.sponsorID().value(), - -ownerCountAdj, - j, - false); - } - } - adjustOwnerCountValue( - view, reserveCtx.accountSle, sfOwnerCount, reserveCtx.accountID(), ownerCountAdj, j); + adjustOwnerCountSigned( + view, reserveCtx.accountSle, reserveCtx.sponsorSle, -static_cast(count), j); } void @@ -276,7 +298,7 @@ decreaseOwnerCountForObject( ApplyView& view, SLE::pointer ownerSle, SLE::ref objectSle, - std::int32_t ownerCountAdj, + std::int32_t count, beast::Journal j) { XRPL_ASSERT(objectSle, "xrpl::decreaseOwnerCountForObject : valid object sle"); @@ -288,8 +310,7 @@ decreaseOwnerCountForObject( if (!validObjectType) return; // LCOV_EXCL_LINE - increaseOwnerCount( - view, ReserveContext::makeFromObject(view, objectSle, ownerSle), ownerCountAdj, j); + increaseOwnerCount(view, ReserveContext::makeFromObject(view, objectSle, ownerSle), -count, j); } XRPAmount accountReserve(ReadView const& view, SLE::const_ref sle, beast::Journal j, Adjustment adj) diff --git a/src/libxrpl/ledger/helpers/CredentialHelpers.cpp b/src/libxrpl/ledger/helpers/CredentialHelpers.cpp index b301e29a49..5d377b2354 100644 --- a/src/libxrpl/ledger/helpers/CredentialHelpers.cpp +++ b/src/libxrpl/ledger/helpers/CredentialHelpers.cpp @@ -98,7 +98,7 @@ deleteSLE(ApplyView& view, SLE::ref sleCredential, beast::Journal j) if (isOwner) decreaseOwnerCountForObject( - view, view.peek(keylet::account(account)), sleCredential, -1, j); + view, view.peek(keylet::account(account)), sleCredential, 1, j); return tesSUCCESS; }; diff --git a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp index 4cc8c53004..a668ee4461 100644 --- a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp +++ b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp @@ -185,7 +185,7 @@ authorizeMPToken( keylet::ownerDir(account), (*sleMpt)[sfOwnerNode], sleMpt->key(), false)) return tecINTERNAL; // LCOV_EXCL_LINE - decreaseOwnerCountForObject(ctx.view, reserveCtx.accountSle, sleMpt, -1, journal); + decreaseOwnerCountForObject(ctx.view, reserveCtx.accountSle, sleMpt, 1, journal); ctx.view.erase(sleMpt); return tesSUCCESS; diff --git a/src/libxrpl/ledger/helpers/OfferHelpers.cpp b/src/libxrpl/ledger/helpers/OfferHelpers.cpp index 83335c0141..0b5626a97f 100644 --- a/src/libxrpl/ledger/helpers/OfferHelpers.cpp +++ b/src/libxrpl/ledger/helpers/OfferHelpers.cpp @@ -56,7 +56,7 @@ offerDelete(ApplyView& view, SLE::ref sle, beast::Journal j) } auto const ownerSle = view.peek(keylet::account(owner)); - decreaseOwnerCountForObject(view, ownerSle, sle, -1, j); + decreaseOwnerCountForObject(view, ownerSle, sle, 1, j); view.erase(sle); diff --git a/src/libxrpl/tx/transactors/check/CheckCancel.cpp b/src/libxrpl/tx/transactors/check/CheckCancel.cpp index f179258cda..e5908c6d2f 100644 --- a/src/libxrpl/tx/transactors/check/CheckCancel.cpp +++ b/src/libxrpl/tx/transactors/check/CheckCancel.cpp @@ -91,7 +91,7 @@ CheckCancel::doApply() } // If we succeeded, update the check owner's reserve. - decreaseOwnerCountForObject(view(), view().peek(keylet::account(srcId)), sleCheck, -1, viewJ); + decreaseOwnerCountForObject(view(), view().peek(keylet::account(srcId)), sleCheck, 1, viewJ); // Remove check from ledger. view().erase(sleCheck); diff --git a/src/libxrpl/tx/transactors/escrow/EscrowFinish.cpp b/src/libxrpl/tx/transactors/escrow/EscrowFinish.cpp index df68171499..e76cbd60ef 100644 --- a/src/libxrpl/tx/transactors/escrow/EscrowFinish.cpp +++ b/src/libxrpl/tx/transactors/escrow/EscrowFinish.cpp @@ -392,7 +392,7 @@ EscrowFinish::doApply() // Adjust source owner count decreaseOwnerCountForObject( - ctx_.view(), ctx_.view().peek(keylet::account(account)), slep, -1, ctx_.journal); + ctx_.view(), ctx_.view().peek(keylet::account(account)), slep, 1, ctx_.journal); // Remove escrow from ledger ctx_.view().erase(slep); diff --git a/src/libxrpl/tx/transactors/token/MPTokenIssuanceDestroy.cpp b/src/libxrpl/tx/transactors/token/MPTokenIssuanceDestroy.cpp index 31f1e3149c..c99e783cb5 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenIssuanceDestroy.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenIssuanceDestroy.cpp @@ -49,7 +49,7 @@ MPTokenIssuanceDestroy::doApply() if (!view().dirRemove(keylet::ownerDir(accountID_), (*mpt)[sfOwnerNode], mpt->key(), false)) return tefBAD_LEDGER; // LCOV_EXCL_LINE - decreaseOwnerCountForObject(view(), view().peek(keylet::account(accountID_)), mpt, -1, j_); + decreaseOwnerCountForObject(view(), view().peek(keylet::account(accountID_)), mpt, 1, j_); view().erase(mpt); return tesSUCCESS;