From d0bcca6bf1963b4056879d6bcaaa4a2aaa752db1 Mon Sep 17 00:00:00 2001 From: tequ Date: Tue, 28 Oct 2025 17:18:38 +0900 Subject: [PATCH] Fix the behavior of co-sign + pre-fund --- include/xrpl/ledger/View.h | 17 +---- src/libxrpl/ledger/CredentialHelpers.cpp | 2 +- src/libxrpl/ledger/View.cpp | 44 ++++++++----- src/test/app/Sponsor_test.cpp | 65 +++++++++++++++++++ src/xrpld/app/tx/detail/CancelCheck.cpp | 2 +- src/xrpld/app/tx/detail/CashCheck.cpp | 2 +- src/xrpld/app/tx/detail/Change.cpp | 4 +- src/xrpld/app/tx/detail/Credentials.cpp | 2 +- src/xrpld/app/tx/detail/DID.cpp | 2 +- src/xrpld/app/tx/detail/DelegateSet.cpp | 2 +- src/xrpld/app/tx/detail/DeleteOracle.cpp | 2 +- src/xrpld/app/tx/detail/DepositPreauth.cpp | 2 +- src/xrpld/app/tx/detail/Escrow.cpp | 4 +- .../app/tx/detail/MPTokenIssuanceDestroy.cpp | 2 +- src/xrpld/app/tx/detail/NFTokenUtils.cpp | 12 ++-- src/xrpld/app/tx/detail/PayChan.cpp | 2 +- .../tx/detail/PermissionedDomainDelete.cpp | 2 +- src/xrpld/app/tx/detail/SetOracle.cpp | 2 +- src/xrpld/app/tx/detail/SetSignerList.cpp | 2 +- src/xrpld/app/tx/detail/SetTrust.cpp | 4 +- src/xrpld/app/tx/detail/SponsorshipSet.cpp | 4 +- src/xrpld/app/tx/detail/Transactor.cpp | 34 ++++++---- src/xrpld/app/tx/detail/Transactor.h | 2 +- src/xrpld/app/tx/detail/VaultDelete.cpp | 4 +- src/xrpld/app/tx/detail/XChainBridge.cpp | 2 +- 25 files changed, 143 insertions(+), 79 deletions(-) diff --git a/include/xrpl/ledger/View.h b/include/xrpl/ledger/View.h index 8fa0d6ce66..8e9b0bd2b1 100644 --- a/include/xrpl/ledger/View.h +++ b/include/xrpl/ledger/View.h @@ -520,7 +520,6 @@ adjustOwnerCount( std::shared_ptr const& accountSle, std::optional> const& sponsorSle, std::int32_t amount, - bool const isSponsorCoSigning, beast::Journal j); inline void @@ -532,8 +531,7 @@ adjustOwnerCount( std::int32_t amount, beast::Journal j) { - auto const isCoSigning = isSponsorReserveCoSigning(tx); - adjustOwnerCount(view, accountSle, sponsorSle, amount, isCoSigning, j); + adjustOwnerCount(view, accountSle, sponsorSle, amount, j); } inline void @@ -555,19 +553,6 @@ adjustOwnerCount( j); } -inline void -reduceOwnerCount( - ApplyView& view, - std::shared_ptr const& accountSle, - std::optional> const& sponsorSle, - std::int32_t amount, - beast::Journal j) -{ - XRPL_ASSERT( - amount <= 0, "ripple::reduceOwnerCount : amount must be negative"); - adjustOwnerCount(view, accountSle, sponsorSle, amount, true, j); -} - /** @{ */ /** Returns the first entry in the directory, advancing the index diff --git a/src/libxrpl/ledger/CredentialHelpers.cpp b/src/libxrpl/ledger/CredentialHelpers.cpp index 5a14bd952a..fd3092495c 100644 --- a/src/libxrpl/ledger/CredentialHelpers.cpp +++ b/src/libxrpl/ledger/CredentialHelpers.cpp @@ -99,7 +99,7 @@ deleteSLE( { auto const sponsor = getLedgerEntryReserveSponsor(view, sleCredential); - reduceOwnerCount(view, sleAccount, sponsor, -1, j); + adjustOwnerCount(view, sleAccount, sponsor, -1, j); } return tesSUCCESS; diff --git a/src/libxrpl/ledger/View.cpp b/src/libxrpl/ledger/View.cpp index 586f1d3a94..bbfef0a85c 100644 --- a/src/libxrpl/ledger/View.cpp +++ b/src/libxrpl/ledger/View.cpp @@ -1073,8 +1073,21 @@ checkInsufficientReserve( { auto const isCoSigning = isSponsorReserveCoSigning(tx); + auto const sle = view.read(keylet::sponsor( + (*sponsorSle)->getAccountID(sfAccount), + accSle->getAccountID(sfAccount))); + if (isCoSigning) { + if (sle) + { + auto const reserveCountAllowed = + sle->getFieldU32(sfReserveCount); + if (reserveCountAllowed < ownerCountDelta) + return tecINSUFFICIENT_RESERVE; + + return tesSUCCESS; + } auto const sponsorBalance = (*sponsorSle)->getFieldAmount(sfBalance); STAmount const sponsorReserve{view.fees().accountReserve( @@ -1092,17 +1105,12 @@ checkInsufficientReserve( else { // pre funded - auto const sle = view.read(keylet::sponsor( - (*sponsorSle)->getAccountID(sfAccount), - accSle->getAccountID(sfAccount))); if (!sle) return tecINTERNAL; // LCOV_EXCL_LINE auto const reserveCountAllowed = sle->getFieldU32(sfReserveCount); if (reserveCountAllowed < ownerCountDelta) - { return tecINSUFFICIENT_RESERVE; - } } } else @@ -1225,7 +1233,6 @@ adjustOwnerCount( std::shared_ptr const& accountSle, std::optional> const& sponsorSle, std::int32_t amount, - bool const isSponsorCoSigning, beast::Journal j) { if (!accountSle) @@ -1264,13 +1271,14 @@ adjustOwnerCount( view.update(accountSle); } - if (!isSponsorCoSigning && amount > 0) + auto sle = view.peek(keylet::sponsor( + (*sponsorSle)->getAccountID(sfAccount), + accountSle->getAccountID(sfAccount))); + + if (sle && amount > 0) { // pre funded // modify sponsor's ReserveCount - auto sle = view.peek(keylet::sponsor( - (*sponsorSle)->getAccountID(sfAccount), - accountSle->getAccountID(sfAccount))); XRPL_ASSERT( sle, "ripple::adjustOwnerCount : co-signing sponsor not found"); @@ -1572,7 +1580,7 @@ authorizeMPToken( return tecINTERNAL; // LCOV_EXCL_LINE auto const sponsor = getLedgerEntryReserveSponsor(view, sleMpt); - reduceOwnerCount(view, sleAcct, sponsor, -1, journal); + adjustOwnerCount(view, sleAcct, sponsor, -1, journal); view.erase(sleMpt); return tesSUCCESS; @@ -1766,7 +1774,7 @@ trustCreate( sponsorSle = view.peek(keylet::account(*sponsorAccountID)); sleRippleState->setFieldU32(sfFlags, uFlags); - adjustOwnerCount(view, sleAccount, sponsorSle, 1, isSponsorCoSigning, j); + adjustOwnerCount(view, sleAccount, sponsorSle, 1, j); addSponsorToLedgerEntry( sleRippleState, @@ -1820,7 +1828,7 @@ removeEmptyHolding( if (!sleLowAccount) return tecINTERNAL; // LCOV_EXCL_LINE - reduceOwnerCount(view, sleLowAccount, std::nullopt, -1, journal); + adjustOwnerCount(view, sleLowAccount, std::nullopt, -1, journal); // It's not really necessary to clear the reserve flag, since the line // is about to be deleted, but this will make the metadata reflect an // accurate state at the time of deletion. @@ -1835,7 +1843,7 @@ removeEmptyHolding( if (!sleHighAccount) return tecINTERNAL; // LCOV_EXCL_LINE - reduceOwnerCount(view, sleHighAccount, std::nullopt, -1, journal); + adjustOwnerCount(view, sleHighAccount, std::nullopt, -1, journal); // It's not really necessary to clear the reserve flag, since the line // is about to be deleted, but this will make the metadata reflect an // accurate state at the time of deletion. @@ -1970,7 +1978,7 @@ offerDelete(ApplyView& view, std::shared_ptr const& sle, beast::Journal j) } auto const sponsor = getLedgerEntryReserveSponsor(view, sle); - reduceOwnerCount(view, view.peek(keylet::account(owner)), sponsor, -1, j); + adjustOwnerCount(view, view.peek(keylet::account(owner)), sponsor, -1, j); view.erase(sle); @@ -2069,7 +2077,7 @@ rippleCreditIOU( view, sleRippleState, !bSenderHigh ? sfLowSponsorAccount : sfHighSponsorAccount); - reduceOwnerCount( + adjustOwnerCount( view, view.peek(keylet::account(uSenderID)), currentSponsor, @@ -2587,7 +2595,7 @@ updateTrustLine( view, state, !bSenderHigh ? sfLowSponsorAccount : sfHighSponsorAccount); - reduceOwnerCount(view, sle, currentSponsor, -1, j); + adjustOwnerCount(view, sle, currentSponsor, -1, j); // Clear reserve flag. state->setFieldU32( @@ -3196,7 +3204,7 @@ deleteAMMTrustLine( auto const sponsorSle = getLedgerEntryReserveSponsor( view, sleState, !ammLow ? sfLowSponsorAccount : sfHighSponsorAccount); - reduceOwnerCount(view, !ammLow ? sleLow : sleHigh, sponsorSle, -1, j); + adjustOwnerCount(view, !ammLow ? sleLow : sleHigh, sponsorSle, -1, j); removeSponsorFromLedgerEntry( sleState, !ammLow ? sfLowSponsorAccount : sfHighSponsorAccount); diff --git a/src/test/app/Sponsor_test.cpp b/src/test/app/Sponsor_test.cpp index 4ba271a412..d57e5fccb6 100644 --- a/src/test/app/Sponsor_test.cpp +++ b/src/test/app/Sponsor_test.cpp @@ -26,6 +26,8 @@ #include #include +#include "test/jtx/txflags.h" + namespace ripple { namespace test { @@ -426,6 +428,67 @@ public: } } + void + testPreFundAndCosign() + { + testcase("PreFund and Cosign"); + using namespace test::jtx; + Account const alice("alice"); + Account const sponsor("sponsor"); + + { + // both pre-funded and co-signed,pre-funded value is used + Env env{*this, testable_amendments()}; + env.fund(XRP(10000), alice, sponsor); + env.close(); + + env(sponsor::set(sponsor, 0, 100, XRP(100), XRP(1)), + sponsor::sponseeAcc(alice), + ter(tesSUCCESS)); + env.close(); + + env(ticket::create(alice, 1), + sponsor::as(sponsor, tfSponsorReserve | tfSponsorFee), + sig(sfSponsorSignature, sponsor), + fee(XRP(1)), + ter(tesSUCCESS)); + env.close(); + + auto const sle = env.le(keylet::sponsor(sponsor, alice)); + BEAST_EXPECT(sle); + BEAST_EXPECT(sle->at(sfReserveCount) == 99); + BEAST_EXPECT(sle->at(sfFeeAmount) == XRP(99)); + } + + { + // if pre-funded value is not enough, error + Env env{*this, testable_amendments()}; + env.fund(XRP(10000), alice, sponsor); + env.close(); + + env(sponsor::set(sponsor, 0, 10, XRP(10), XRP(100)), + sponsor::sponseeAcc(alice), + ter(tesSUCCESS)); + env.close(); + + // fee insufficient + env(ticket::create(alice, 1), + sponsor::as(sponsor, tfSponsorReserve | tfSponsorFee), + sig(sfSponsorSignature, sponsor), + fee(XRP(11)), + ter(terINSUF_FEE_B)); + env.close(); + + // reserve insufficient + env(ticket::create(alice, 11), + sponsor::as(sponsor, tfSponsorReserve | tfSponsorFee), + sig(sfSponsorSignature, sponsor), + fee(XRP(1)), + ter(tecINSUFFICIENT_RESERVE)); + env.close(); + } + } + void testTransferSponsor() { @@ -4260,6 +4323,8 @@ public: testSimpleSponsorshipSet(); + testPreFundAndCosign(); + testTransferSponsor(); testSponsorFee(); testSponsorAccount(); diff --git a/src/xrpld/app/tx/detail/CancelCheck.cpp b/src/xrpld/app/tx/detail/CancelCheck.cpp index da71577b05..b9bf0b6c8a 100644 --- a/src/xrpld/app/tx/detail/CancelCheck.cpp +++ b/src/xrpld/app/tx/detail/CancelCheck.cpp @@ -114,7 +114,7 @@ CancelCheck::doApply() // If we succeeded, update the check owner's reserve. auto const sleSrc = view().peek(keylet::account(srcId)); auto const sponsor = getLedgerEntryReserveSponsor(view(), sleCheck); - reduceOwnerCount(view(), sleSrc, sponsor, -1, viewJ); + adjustOwnerCount(view(), sleSrc, sponsor, -1, viewJ); // Remove check from ledger. view().erase(sleCheck); diff --git a/src/xrpld/app/tx/detail/CashCheck.cpp b/src/xrpld/app/tx/detail/CashCheck.cpp index ab3fae7c18..41dc133e2c 100644 --- a/src/xrpld/app/tx/detail/CashCheck.cpp +++ b/src/xrpld/app/tx/detail/CashCheck.cpp @@ -517,7 +517,7 @@ CashCheck::doApply() // If we succeeded, update the check owner's reserve. auto const sponsorSle = getLedgerEntryReserveSponsor(psb, sleCheck); - reduceOwnerCount( + adjustOwnerCount( psb, psb.peek(keylet::account(srcId)), sponsorSle, -1, viewJ); // Remove check from ledger. diff --git a/src/xrpld/app/tx/detail/Change.cpp b/src/xrpld/app/tx/detail/Change.cpp index 606f0677d9..ecc54d7759 100644 --- a/src/xrpld/app/tx/detail/Change.cpp +++ b/src/xrpld/app/tx/detail/Change.cpp @@ -215,7 +215,7 @@ Change::activateTrustLinesToSelfFix() } if (tl->getFlags() & lsfLowReserve) - reduceOwnerCount( + adjustOwnerCount( sb, sb.peek(keylet::account(lo.getIssuer())), std::nullopt, @@ -223,7 +223,7 @@ Change::activateTrustLinesToSelfFix() j_); if (tl->getFlags() & lsfHighReserve) - reduceOwnerCount( + adjustOwnerCount( sb, sb.peek(keylet::account(hi.getIssuer())), std::nullopt, diff --git a/src/xrpld/app/tx/detail/Credentials.cpp b/src/xrpld/app/tx/detail/Credentials.cpp index c1bd6cff09..85b8513952 100644 --- a/src/xrpld/app/tx/detail/Credentials.cpp +++ b/src/xrpld/app/tx/detail/Credentials.cpp @@ -366,7 +366,7 @@ CredentialAccept::doApply() sleCred->setFieldU32(sfFlags, lsfAccepted); view().update(sleCred); - reduceOwnerCount(view(), sleIssuer, currentSponsor, -1, j_); + adjustOwnerCount(view(), sleIssuer, currentSponsor, -1, j_); removeSponsorFromLedgerEntry(sleCred); adjustOwnerCount(view(), ctx_.tx, sleSubject, newSponsor, 1, j_); addSponsorToLedgerEntry(sleCred, newSponsor); diff --git a/src/xrpld/app/tx/detail/DID.cpp b/src/xrpld/app/tx/detail/DID.cpp index 4cabc8bd20..9ead403587 100644 --- a/src/xrpld/app/tx/detail/DID.cpp +++ b/src/xrpld/app/tx/detail/DID.cpp @@ -199,7 +199,7 @@ DIDDelete::deleteSLE( return tecINTERNAL; // LCOV_EXCL_LINE auto const sponsor = getLedgerEntryReserveSponsor(view, sle); - reduceOwnerCount(view, sleOwner, sponsor, -1, j); + adjustOwnerCount(view, sleOwner, sponsor, -1, j); view.update(sleOwner); // Remove object from ledger diff --git a/src/xrpld/app/tx/detail/DelegateSet.cpp b/src/xrpld/app/tx/detail/DelegateSet.cpp index 5acfc2f184..b79866238d 100644 --- a/src/xrpld/app/tx/detail/DelegateSet.cpp +++ b/src/xrpld/app/tx/detail/DelegateSet.cpp @@ -165,7 +165,7 @@ DelegateSet::deleteDelegate( return tecINTERNAL; // LCOV_EXCL_LINE auto const sponsor = getLedgerEntryReserveSponsor(view, sle); - reduceOwnerCount(view, sleOwner, sponsor, -1, j); + adjustOwnerCount(view, sleOwner, sponsor, -1, j); view.erase(sle); diff --git a/src/xrpld/app/tx/detail/DeleteOracle.cpp b/src/xrpld/app/tx/detail/DeleteOracle.cpp index 705b2ae639..e84cc2c333 100644 --- a/src/xrpld/app/tx/detail/DeleteOracle.cpp +++ b/src/xrpld/app/tx/detail/DeleteOracle.cpp @@ -83,7 +83,7 @@ DeleteOracle::deleteOracle( sle->getFieldArray(sfPriceDataSeries).size() > 5 ? -2 : -1; auto const sponsor = getLedgerEntryReserveSponsor(view, sle); - reduceOwnerCount(view, sleOwner, sponsor, count, j); + adjustOwnerCount(view, sleOwner, sponsor, count, j); view.erase(sle); diff --git a/src/xrpld/app/tx/detail/DepositPreauth.cpp b/src/xrpld/app/tx/detail/DepositPreauth.cpp index 62fa073f16..be4c9b00f3 100644 --- a/src/xrpld/app/tx/detail/DepositPreauth.cpp +++ b/src/xrpld/app/tx/detail/DepositPreauth.cpp @@ -309,7 +309,7 @@ DepositPreauth::removeFromLedger( return tefINTERNAL; // LCOV_EXCL_LINE auto const sponsor = getLedgerEntryReserveSponsor(view, slePreauth); - reduceOwnerCount(view, sleOwner, sponsor, -1, j); + adjustOwnerCount(view, sleOwner, sponsor, -1, j); // Remove DepositPreauth from ledger. view.erase(slePreauth); diff --git a/src/xrpld/app/tx/detail/Escrow.cpp b/src/xrpld/app/tx/detail/Escrow.cpp index fbeb8eca7a..18fdbc13d8 100644 --- a/src/xrpld/app/tx/detail/Escrow.cpp +++ b/src/xrpld/app/tx/detail/Escrow.cpp @@ -1237,7 +1237,7 @@ EscrowFinish::doApply() // Adjust source owner count auto const sle = ctx_.view().peek(keylet::account(account)); auto const sponsor = getLedgerEntryReserveSponsor(ctx_.view(), slep); - reduceOwnerCount(ctx_.view(), sle, sponsor, -1, ctx_.journal); + adjustOwnerCount(ctx_.view(), sle, sponsor, -1, ctx_.journal); ctx_.view().update(sle); // Remove escrow from ledger @@ -1461,7 +1461,7 @@ EscrowCancel::doApply() } auto const sponsor = getLedgerEntryReserveSponsor(ctx_.view(), slep); - reduceOwnerCount(ctx_.view(), sle, sponsor, -1, ctx_.journal); + adjustOwnerCount(ctx_.view(), sle, sponsor, -1, ctx_.journal); ctx_.view().update(sle); // Remove escrow from ledger diff --git a/src/xrpld/app/tx/detail/MPTokenIssuanceDestroy.cpp b/src/xrpld/app/tx/detail/MPTokenIssuanceDestroy.cpp index 097fbb185e..af17d6c5f5 100644 --- a/src/xrpld/app/tx/detail/MPTokenIssuanceDestroy.cpp +++ b/src/xrpld/app/tx/detail/MPTokenIssuanceDestroy.cpp @@ -75,7 +75,7 @@ MPTokenIssuanceDestroy::doApply() view().erase(mpt); auto const sponsor = getLedgerEntryReserveSponsor(view(), mpt); - reduceOwnerCount( + adjustOwnerCount( view(), view().peek(keylet::account(account_)), sponsor, -1, j_); return tesSUCCESS; diff --git a/src/xrpld/app/tx/detail/NFTokenUtils.cpp b/src/xrpld/app/tx/detail/NFTokenUtils.cpp index ee2c0e9f6b..7b54d54eea 100644 --- a/src/xrpld/app/tx/detail/NFTokenUtils.cpp +++ b/src/xrpld/app/tx/detail/NFTokenUtils.cpp @@ -495,7 +495,7 @@ removeToken( if (prev && mergePages(view, prev, curr)) { auto const sponsor = getLedgerEntryReserveSponsor(view, prev); - reduceOwnerCount( + adjustOwnerCount( view, view.peek(keylet::account(owner)), sponsor, @@ -506,7 +506,7 @@ removeToken( if (next && mergePages(view, curr, next)) { auto const sponsor = getLedgerEntryReserveSponsor(view, curr); - reduceOwnerCount( + adjustOwnerCount( view, view.peek(keylet::account(owner)), sponsor, @@ -547,7 +547,7 @@ removeToken( } auto const sponsor = getLedgerEntryReserveSponsor(view, prev); - reduceOwnerCount( + adjustOwnerCount( view, view.peek(keylet::account(owner)), sponsor, @@ -581,7 +581,7 @@ removeToken( } auto const sponsor = getLedgerEntryReserveSponsor(view, curr); - reduceOwnerCount( + adjustOwnerCount( view, view.peek(keylet::account(owner)), getLedgerEntryReserveSponsor(view, curr), @@ -604,7 +604,7 @@ removeToken( view.peek(Keylet(ltNFTOKEN_PAGE, prev->key())), view.peek(Keylet(ltNFTOKEN_PAGE, next->key())))) { - reduceOwnerCount( + adjustOwnerCount( view, view.peek(keylet::account(owner)), getLedgerEntryReserveSponsor(view, prev), @@ -763,7 +763,7 @@ deleteTokenOffer(ApplyView& view, std::shared_ptr const& offer) return false; auto const sponsor = getLedgerEntryReserveSponsor(view, offer); - reduceOwnerCount( + adjustOwnerCount( view, view.peek(keylet::account(owner)), sponsor, diff --git a/src/xrpld/app/tx/detail/PayChan.cpp b/src/xrpld/app/tx/detail/PayChan.cpp index 2bbf118e52..4b466b70d1 100644 --- a/src/xrpld/app/tx/detail/PayChan.cpp +++ b/src/xrpld/app/tx/detail/PayChan.cpp @@ -160,7 +160,7 @@ closeChannel( (*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount] - (*slep)[sfBalance]; auto const sponsor = getLedgerEntryReserveSponsor(view, slep); - reduceOwnerCount(view, sle, sponsor, -1, j); + adjustOwnerCount(view, sle, sponsor, -1, j); view.update(sle); // Remove PayChan from ledger diff --git a/src/xrpld/app/tx/detail/PermissionedDomainDelete.cpp b/src/xrpld/app/tx/detail/PermissionedDomainDelete.cpp index ee7e606862..8fc904caea 100644 --- a/src/xrpld/app/tx/detail/PermissionedDomainDelete.cpp +++ b/src/xrpld/app/tx/detail/PermissionedDomainDelete.cpp @@ -78,7 +78,7 @@ PermissionedDomainDelete::doApply() ownerSle && ownerSle->getFieldU32(sfOwnerCount) > 0, "ripple::PermissionedDomainDelete::doApply : nonzero owner count"); auto const sponsor = getLedgerEntryReserveSponsor(view(), slePd); - reduceOwnerCount(view(), ownerSle, sponsor, -1, ctx_.journal); + adjustOwnerCount(view(), ownerSle, sponsor, -1, ctx_.journal); view().erase(slePd); return tesSUCCESS; diff --git a/src/xrpld/app/tx/detail/SetOracle.cpp b/src/xrpld/app/tx/detail/SetOracle.cpp index f326489108..cd4cdb331f 100644 --- a/src/xrpld/app/tx/detail/SetOracle.cpp +++ b/src/xrpld/app/tx/detail/SetOracle.cpp @@ -200,7 +200,7 @@ adjustOwnerCount( adjustOwnerCount( ctx.view(), ctx.tx, sleAccount, sponsor, count, ctx.journal); else - reduceOwnerCount( + adjustOwnerCount( ctx.view(), sleAccount, sponsor, count, ctx.journal); return true; } diff --git a/src/xrpld/app/tx/detail/SetSignerList.cpp b/src/xrpld/app/tx/detail/SetSignerList.cpp index 2150a40a5b..47cc6f8a0f 100644 --- a/src/xrpld/app/tx/detail/SetSignerList.cpp +++ b/src/xrpld/app/tx/detail/SetSignerList.cpp @@ -233,7 +233,7 @@ removeSignersFromLedger( } auto const sponsor = getLedgerEntryReserveSponsor(view, signers); - reduceOwnerCount( + adjustOwnerCount( view, view.peek(accountKeylet), sponsor, diff --git a/src/xrpld/app/tx/detail/SetTrust.cpp b/src/xrpld/app/tx/detail/SetTrust.cpp index 3fa8637dc3..ced0db8a2b 100644 --- a/src/xrpld/app/tx/detail/SetTrust.cpp +++ b/src/xrpld/app/tx/detail/SetTrust.cpp @@ -670,7 +670,7 @@ SetTrust::doApply() if (bLowReserveClear && bLowReserved) { // Clear reserve for low account. - reduceOwnerCount( + adjustOwnerCount( view(), sleLowAccount, currentLowSponsor, -1, viewJ); uFlagsOut &= ~lsfLowReserve; @@ -705,7 +705,7 @@ SetTrust::doApply() if (bHighReserveClear && bHighReserved) { // Clear reserve for high account. - reduceOwnerCount( + adjustOwnerCount( view(), sleHighAccount, currentHighSponsor, -1, viewJ); uFlagsOut &= ~lsfHighReserve; diff --git a/src/xrpld/app/tx/detail/SponsorshipSet.cpp b/src/xrpld/app/tx/detail/SponsorshipSet.cpp index f89e289319..8c507ead81 100644 --- a/src/xrpld/app/tx/detail/SponsorshipSet.cpp +++ b/src/xrpld/app/tx/detail/SponsorshipSet.cpp @@ -217,7 +217,7 @@ SponsorshipSet::doApply() auto const sponsor = getLedgerEntryReserveSponsor(ctx_.view(), sponsorObjSle); - reduceOwnerCount(ctx_.view(), sponsorAccSle, sponsor, -1, ctx_.journal); + adjustOwnerCount(ctx_.view(), sponsorAccSle, sponsor, -1, ctx_.journal); ctx_.view().dirRemove( keylet::ownerDir(sponsorAcc), @@ -370,7 +370,7 @@ SponsorshipSet::deleteSponsorship( (*sponsorAccSle)[sfBalance] += feeAmount; auto const reserveSponsor = getLedgerEntryReserveSponsor(view, sle); - reduceOwnerCount(view, sponsorAccSle, reserveSponsor, -1, j); + adjustOwnerCount(view, sponsorAccSle, reserveSponsor, -1, j); view.update(sponsorAccSle); diff --git a/src/xrpld/app/tx/detail/Transactor.cpp b/src/xrpld/app/tx/detail/Transactor.cpp index d4c824b542..469e708170 100644 --- a/src/xrpld/app/tx/detail/Transactor.cpp +++ b/src/xrpld/app/tx/detail/Transactor.cpp @@ -444,7 +444,7 @@ Transactor::checkFee(PreclaimContext const& ctx, XRPAmount baseFee) std::optional availableBalance; - auto const result = getFeePayer(ctx.tx); + auto const result = getFeePayer(ctx.view, ctx.tx); if (result.type == FeePayerType::SponsorPreFunded) { @@ -511,7 +511,7 @@ Transactor::payFee() { auto const feePaid = ctx_.tx[sfFee].xrp(); - auto const result = getFeePayer(ctx_.tx); + auto const result = getFeePayer(view(), ctx_.tx); auto const sle = view().peek(result.keylet); @@ -711,7 +711,7 @@ Transactor::ticketDelete( // Update the Ticket owner's reserve. auto const sponsor = getLedgerEntryReserveSponsor(view, sleTicket); - reduceOwnerCount(view, sleAccount, sponsor, -1, j); + adjustOwnerCount(view, sleAccount, sponsor, -1, j); // Remove Ticket from ledger. view.erase(sleTicket); @@ -1226,7 +1226,7 @@ Transactor::reset(XRPAmount fee) if (!txnAcct) return {tefINTERNAL, beast::zero}; - auto const result = getFeePayer(ctx_.tx); + auto const result = getFeePayer(view(), ctx_.tx); auto const payerSle = view().peek(result.keylet); @@ -1269,25 +1269,31 @@ Transactor::reset(XRPAmount fee) } FeePayer -Transactor::getFeePayer(STTx const& tx) +Transactor::getFeePayer(ReadView const& view, STTx const& tx) { if (tx.isFieldPresent(sfSponsor) && tx.getFieldObject(sfSponsor).isFlag(tfSponsorFee)) { auto const sponsor = tx.getFieldObject(sfSponsor); auto const hasSignature = tx.isFieldPresent(sfSponsorSignature); + auto const keylet = keylet::sponsor( + sponsor.getAccountID(sfAccount), tx.getAccountID(sfAccount)); - if (!hasSignature) + if (hasSignature) { - // pre funded - auto const keylet = keylet::sponsor( - sponsor.getAccountID(sfAccount), tx.getAccountID(sfAccount)); - return FeePayer{ - keylet, sfFeeAmount, FeePayerType::SponsorPreFunded}; + // if pre-funded sponsorship exists, prefer it + if (view.exists(keylet)) + return FeePayer{ + keylet, sfFeeAmount, FeePayerType::SponsorPreFunded}; + + // co-signed + auto const keylet = + keylet::account(sponsor.getAccountID(sfAccount)); + return FeePayer{keylet, sfBalance, FeePayerType::SponsorCoSigned}; } - // co-signed - auto const keylet = keylet::account(sponsor.getAccountID(sfAccount)); - return FeePayer{keylet, sfBalance, FeePayerType::SponsorCoSigned}; + + // pre funded + return FeePayer{keylet, sfFeeAmount, FeePayerType::SponsorPreFunded}; } if (tx.isFieldPresent(sfDelegate)) diff --git a/src/xrpld/app/tx/detail/Transactor.h b/src/xrpld/app/tx/detail/Transactor.h index 04ef354a6e..03857cb116 100644 --- a/src/xrpld/app/tx/detail/Transactor.h +++ b/src/xrpld/app/tx/detail/Transactor.h @@ -337,7 +337,7 @@ private: reset(XRPAmount fee); static FeePayer - getFeePayer(STTx const& tx); + getFeePayer(ReadView const& view, STTx const& tx); TER consumeSeqProxy(SLE::pointer const& sleAccount); diff --git a/src/xrpld/app/tx/detail/VaultDelete.cpp b/src/xrpld/app/tx/detail/VaultDelete.cpp index fdacc185f8..656c371065 100644 --- a/src/xrpld/app/tx/detail/VaultDelete.cpp +++ b/src/xrpld/app/tx/detail/VaultDelete.cpp @@ -157,7 +157,7 @@ VaultDelete::doApply() return tefBAD_LEDGER; // LCOV_EXCL_STOP } - reduceOwnerCount(view(), pseudoAcct, std::nullopt, -1, j_); + adjustOwnerCount(view(), pseudoAcct, std::nullopt, -1, j_); view().erase(mpt); @@ -191,7 +191,7 @@ VaultDelete::doApply() // LCOV_EXCL_STOP } auto const vaultSponsor = getLedgerEntryReserveSponsor(view(), vault); - reduceOwnerCount(view(), owner, vaultSponsor, -1, j_); + adjustOwnerCount(view(), owner, vaultSponsor, -1, j_); // Destroy the vault. view().erase(vault); diff --git a/src/xrpld/app/tx/detail/XChainBridge.cpp b/src/xrpld/app/tx/detail/XChainBridge.cpp index f4106c260b..787e75c74d 100644 --- a/src/xrpld/app/tx/detail/XChainBridge.cpp +++ b/src/xrpld/app/tx/detail/XChainBridge.cpp @@ -769,7 +769,7 @@ finalizeClaimHelper( auto const sponsor = getLedgerEntryReserveSponsor(outerSb, sleClaimID); - reduceOwnerCount(outerSb, sleOwner, sponsor, -1, j); + adjustOwnerCount(outerSb, sleOwner, sponsor, -1, j); } }