diff --git a/include/xrpl/ledger/helpers/AccountRootHelpers.h b/include/xrpl/ledger/helpers/AccountRootHelpers.h index 403626d06f..0e8ee78cff 100644 --- a/include/xrpl/ledger/helpers/AccountRootHelpers.h +++ b/include/xrpl/ledger/helpers/AccountRootHelpers.h @@ -39,6 +39,12 @@ isGlobalFrozen(ReadView const& view, AccountID const& issuer); [[nodiscard]] XRPAmount xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j); +struct Adjustment +{ + std::int32_t ownerCountDelta = 0; + std::int32_t accountCountDelta = 0; +}; + /** Returns the account reserve, in drops. * * Actual owner count can be adjusted by delta in ownerCountAdj @@ -55,12 +61,7 @@ xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, * @return The account reserve amount in drops */ [[nodiscard]] XRPAmount -accountReserve( - ReadView const& view, - SLE::const_ref sle, - beast::Journal j, - std::int32_t ownerCountAdj = 0, - std::int32_t accountCountAdj = 0); +accountReserve(ReadView const& view, SLE::const_ref sle, beast::Journal j, Adjustment adj = {}); /** Convenience overload that accepts AccountID instead of SLE. * @@ -72,28 +73,19 @@ accountReserve( * @return The account reserve amount in drops */ [[nodiscard]] inline XRPAmount -accountReserve( - ReadView const& view, - AccountID const& id, - beast::Journal j, - std::int32_t ownerCountAdj = 0, - std::int32_t accountCountAdj = 0) +accountReserve(ReadView const& view, AccountID const& id, beast::Journal j, Adjustment adj = {}) { - return accountReserve(view, view.read(keylet::account(id)), j, ownerCountAdj, accountCountAdj); + return accountReserve(view, view.read(keylet::account(id)), j, adj); } /** @brief Return the hypothetical reserve required by an account with the provided counters. * * @param view The ledger view to read from - * @param ownerCount Number of objects for which the account will be responsible. - * @param accountCount Number of accounts for which the account will be responsible. - * Defaults to 1, as normally every account is responsible for its own reserve. - * Can be 0 if the account is sponsored. - * Can be greater than 1 if the account is sponsoring other accounts. + * @param adj Adjustment to the default account reserve. * @return The hypothetical reserve amount */ XRPAmount -baseAccountReserve(ReadView const& view, std::int32_t ownerCount, std::int32_t accountCount = 1); +baseAccountReserve(ReadView const& view, Adjustment adj); /** Check if an account has insufficient reserve. * @@ -114,8 +106,7 @@ checkInsufficientReserve( SLE::const_ref accSle, STAmount const& accBalance, SLE::const_ref sponsorSle, - std::int32_t ownerCountAdj, - std::int32_t accountCountAdj = 0, + Adjustment adj, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}); /** Return number of the objects which reserve is covered by the account(sle) (so called "owner @@ -143,7 +134,7 @@ adjustOwnerCount( ApplyView& view, SLE::ref accountSle, SLE::ref sponsorSle, - std::int32_t accountCountAdj, + std::int32_t ownerCountAdj, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}); /** Convenience overload that accepts AccountID instead of SLE references. @@ -159,14 +150,14 @@ adjustOwnerCount( ApplyView& view, AccountID const& account, std::optional const& sponsor, - std::int32_t accountCountAdj, + std::int32_t ownerCountAdj, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) { adjustOwnerCount( view, view.peek(keylet::account(account)), sponsor ? view.peek(keylet::account(*sponsor)) : SLE::pointer(), - accountCountAdj, + ownerCountAdj, j); } @@ -184,7 +175,7 @@ adjustOwnerCountObj( ApplyView& view, SLE::ref accountSle, SLE::ref objectSle, - std::int32_t accountCountAdj, + std::int32_t ownerCountAdj, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}); /** Convenience overload that accepts AccountID instead of account SLE reference. @@ -200,11 +191,11 @@ adjustOwnerCountObj( ApplyView& view, AccountID const& account, SLE::ref objectSle, - std::int32_t accountCountAdj, + std::int32_t ownerCountAdj, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) { SLE::ref accountSle = view.peek(keylet::account(account)); - adjustOwnerCountObj(view, accountSle, objectSle, accountCountAdj, j); + adjustOwnerCountObj(view, accountSle, objectSle, ownerCountAdj, j); } /** Returns IOU issuer transfer fee as Rate. Rate specifies diff --git a/include/xrpl/ledger/helpers/EscrowHelpers.h b/include/xrpl/ledger/helpers/EscrowHelpers.h index bd27f17223..45f48975d7 100644 --- a/include/xrpl/ledger/helpers/EscrowHelpers.h +++ b/include/xrpl/ledger/helpers/EscrowHelpers.h @@ -63,8 +63,8 @@ escrowUnlockApplyHelper( if (!sponsorSle) return sponsorSle.error(); // LCOV_EXCL_LINE - if (auto const ret = - checkInsufficientReserve(view, tx, sleDest, xrpBalance, *sponsorSle, 1, 0, journal); + if (auto const ret = checkInsufficientReserve( + view, tx, sleDest, xrpBalance, *sponsorSle, {.ownerCountDelta = 1}, journal); !isTesSuccess(ret)) { JLOG(journal.trace()) << "Trust line does not exist. " @@ -193,8 +193,8 @@ escrowUnlockApplyHelper( if (!sponsorSle) return sponsorSle.error(); // LCOV_EXCL_LINE - if (auto const ret = - checkInsufficientReserve(view, tx, sleDest, xrpBalance, *sponsorSle, 1, 0, journal); + if (auto const ret = checkInsufficientReserve( + view, tx, sleDest, xrpBalance, *sponsorSle, {.ownerCountDelta = 1}, journal); !isTesSuccess(ret)) return ret; diff --git a/src/libxrpl/ledger/helpers/AccountRootHelpers.cpp b/src/libxrpl/ledger/helpers/AccountRootHelpers.cpp index 3264fa1a45..310ed4ad93 100644 --- a/src/libxrpl/ledger/helpers/AccountRootHelpers.cpp +++ b/src/libxrpl/ledger/helpers/AccountRootHelpers.cpp @@ -165,7 +165,10 @@ xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, // Pseudo-accounts have no reserve requirement auto const reserve = isPseudoAccount(sle) ? XRPAmount{0} - : baseAccountReserve(view, currentOwnerCount, currentAccountCount); + : baseAccountReserve( + view, + {.ownerCountDelta = static_cast(currentOwnerCount), + .accountCountDelta = static_cast(currentAccountCount) - 1}); auto const fullBalance = sle->getFieldAmount(sfBalance); @@ -275,29 +278,27 @@ adjustOwnerCountObj( } XRPAmount -accountReserve( - ReadView const& view, - SLE::const_ref sle, - beast::Journal j, - std::int32_t ownerCountAdj, - std::int32_t accountCountAdj) +accountReserve(ReadView const& view, SLE::const_ref sle, beast::Journal j, Adjustment adj) { if (!sle) Throw("xrpl::accountReserve : valid sle"); if (sle->getType() != ltACCOUNT_ROOT) Throw("xrpl::accountReserve : valid sle type"); - std::uint32_t const currentOwnerCount = ownerCount(sle, j, ownerCountAdj); - std::uint32_t const currentAccountCount = accountCountImpl(sle, accountCountAdj, j); + std::uint32_t const currentOwnerCount = ownerCount(sle, j, adj.ownerCountDelta); + std::uint32_t const currentAccountCount = accountCountImpl(sle, adj.accountCountDelta, j); - return baseAccountReserve(view, currentOwnerCount, currentAccountCount); + return baseAccountReserve( + view, + {.ownerCountDelta = static_cast(currentOwnerCount), + .accountCountDelta = static_cast(currentAccountCount) - 1}); } XRPAmount -baseAccountReserve(ReadView const& view, std::int32_t ownerCount, std::int32_t accountCount) +baseAccountReserve(ReadView const& view, Adjustment adj) { auto const& fees = view.fees(); - return (fees.reserve * accountCount) + (fees.increment * ownerCount); + return (fees.reserve * (1 + adj.accountCountDelta)) + (fees.increment * adj.ownerCountDelta); } TER @@ -307,8 +308,7 @@ checkInsufficientReserve( SLE::const_ref accSle, STAmount const& accBalance, SLE::const_ref sponsorSle, - std::int32_t ownerCountAdj, - std::int32_t accountCountAdj, + Adjustment adj, beast::Journal j) { if (sponsorSle) @@ -326,20 +326,20 @@ checkInsufficientReserve( if (sle) { auto const ownerCountAllowed = sle->getFieldU32(sfRemainingOwnerCount); - if (ownerCountAllowed < ownerCountAdj) + if (adj.ownerCountDelta > 0 && + ownerCountAllowed < static_cast(adj.ownerCountDelta)) return tecINSUFFICIENT_RESERVE; } auto const sponsorBalance = sponsorSle->getFieldAmount(sfBalance); - STAmount const sponsorReserve = - accountReserve(view, sponsorSle, j, ownerCountAdj, accountCountAdj); + STAmount const sponsorReserve = accountReserve(view, sponsorSle, j, adj); if (sponsorBalance < sponsorReserve) return tecINSUFFICIENT_RESERVE; } else { - STAmount const reserve = accountReserve(view, accSle, j, ownerCountAdj, accountCountAdj); + STAmount const reserve = accountReserve(view, accSle, j, adj); if (accBalance < reserve) return tecINSUFFICIENT_RESERVE; } diff --git a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp index c98f2c7cd5..d9bc4ee36c 100644 --- a/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp +++ b/src/libxrpl/ledger/helpers/MPTokenHelpers.cpp @@ -214,7 +214,7 @@ authorizeMPToken( if (sponsorSle || ownerCount(sleAcct, journal) >= 2) { if (auto const ret = checkInsufficientReserve( - view, tx, sleAcct, priorBalance, sponsorSle, 1, 0, journal); + view, tx, sleAcct, priorBalance, sponsorSle, {.ownerCountDelta = 1}, journal); !isTesSuccess(ret)) return ret; } diff --git a/src/libxrpl/ledger/helpers/NFTokenHelpers.cpp b/src/libxrpl/ledger/helpers/NFTokenHelpers.cpp index 93dbae0467..fba0d112d5 100644 --- a/src/libxrpl/ledger/helpers/NFTokenHelpers.cpp +++ b/src/libxrpl/ledger/helpers/NFTokenHelpers.cpp @@ -913,7 +913,8 @@ tokenOfferCreateApply( std::uint32_t txFlags) { Keylet const acctKeylet = keylet::account(acctID); - if (auto const acct = view.read(acctKeylet); priorBalance < accountReserve(view, acct, j, 1)) + if (auto const acct = view.read(acctKeylet); + priorBalance < accountReserve(view, acct, j, {.ownerCountDelta = 1})) return tecINSUFFICIENT_RESERVE; auto const offerID = keylet::nftoffer(acctID, seqProxy.value()); diff --git a/src/libxrpl/ledger/helpers/RippleStateHelpers.cpp b/src/libxrpl/ledger/helpers/RippleStateHelpers.cpp index 8f5b3f0563..78c4ce1520 100644 --- a/src/libxrpl/ledger/helpers/RippleStateHelpers.cpp +++ b/src/libxrpl/ledger/helpers/RippleStateHelpers.cpp @@ -676,8 +676,8 @@ addEmptyHolding( } // Can the account cover the trust line reserve ? - if (auto const ret = - checkInsufficientReserve(view, tx, sleDst, priorBalance, sponsorSle, 1, 0, journal); + if (auto const ret = checkInsufficientReserve( + view, tx, sleDst, priorBalance, sponsorSle, {.ownerCountDelta = 1}, journal); !isTesSuccess(ret)) return tecNO_LINE_INSUF_RESERVE; diff --git a/src/libxrpl/tx/transactors/Sponsor/SponsorshipSet.cpp b/src/libxrpl/tx/transactors/Sponsor/SponsorshipSet.cpp index f434b33548..5b08d4cce4 100644 --- a/src/libxrpl/tx/transactors/Sponsor/SponsorshipSet.cpp +++ b/src/libxrpl/tx/transactors/Sponsor/SponsorshipSet.cpp @@ -230,8 +230,7 @@ SponsorshipSet::doApply() sponsorAccSle, STAmount{(*sponsorAccSle)[sfBalance]}.xrp(), *reserveSponsorAccSle, - 1, - 0, + {.ownerCountDelta = 1}, ctx_.journal); !isTesSuccess(ret)) return tecUNFUNDED; @@ -299,8 +298,7 @@ SponsorshipSet::doApply() sponsorAccSle, STAmount{(*sponsorAccSle)[sfBalance]}.xrp(), *reserveSponsorAccSle, - 0, - 0, + {}, ctx_.journal); !isTesSuccess(ret)) return tecUNFUNDED; diff --git a/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp b/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp index deea6edc84..11d23c0f2d 100644 --- a/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp +++ b/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp @@ -219,8 +219,7 @@ SponsorshipTransfer::preclaim(PreclaimContext const& ctx) sponseeSle, sponseeSle->getFieldAmount(sfBalance), newSponsorSle, - ownerCountDelta, - 0, + {.ownerCountDelta = ownerCountDelta}, ctx.j); !isTesSuccess(ter)) return ter; @@ -271,8 +270,7 @@ SponsorshipTransfer::preclaim(PreclaimContext const& ctx) sponseeSle, sponseeSle->getFieldAmount(sfBalance), newSponsorSle, - 0, - 1, + {.accountCountDelta = 1}, ctx.j); !isTesSuccess(ter)) return ter; diff --git a/src/libxrpl/tx/transactors/account/SignerListSet.cpp b/src/libxrpl/tx/transactors/account/SignerListSet.cpp index d92194900c..26ca1d242e 100644 --- a/src/libxrpl/tx/transactors/account/SignerListSet.cpp +++ b/src/libxrpl/tx/transactors/account/SignerListSet.cpp @@ -331,8 +331,7 @@ SignerListSet::replaceSignerList() sle, preFeeBalance_, *sponsorSle, - kAddedOwnerCount, - 0, + {.ownerCountDelta = kAddedOwnerCount}, ctx_.journal); !isTesSuccess(ret)) return ret; diff --git a/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp b/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp index 2a02dc232e..e0506a8613 100644 --- a/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp +++ b/src/libxrpl/tx/transactors/bridge/XChainBridge.cpp @@ -1028,7 +1028,7 @@ applyCreateAccountAttestations( // Check reserve auto const balance = (*sleDoor)[sfBalance]; - auto const reserve = accountReserve(view, sleDoor, j, 1); + auto const reserve = accountReserve(view, sleDoor, j, {.ownerCountDelta = 1}); if (balance < reserve) return std::unexpected(tecINSUFFICIENT_RESERVE); @@ -1435,7 +1435,7 @@ XChainCreateBridge::preclaim(PreclaimContext const& ctx) return terNO_ACCOUNT; auto const balance = (*sleAcc)[sfBalance]; - auto const reserve = accountReserve(ctx.view, sleAcc, ctx.j, 1); + auto const reserve = accountReserve(ctx.view, sleAcc, ctx.j, {.ownerCountDelta = 1}); if (balance < reserve) return tecINSUFFICIENT_RESERVE; @@ -1983,7 +1983,7 @@ XChainCreateClaimID::preclaim(PreclaimContext const& ctx) return terNO_ACCOUNT; auto const balance = (*sleAcc)[sfBalance]; - auto const reserve = accountReserve(ctx.view, sleAcc, ctx.j, 1); + auto const reserve = accountReserve(ctx.view, sleAcc, ctx.j, {.ownerCountDelta = 1}); if (balance < reserve) return tecINSUFFICIENT_RESERVE; } diff --git a/src/libxrpl/tx/transactors/check/CheckCash.cpp b/src/libxrpl/tx/transactors/check/CheckCash.cpp index ab46f186f1..38ea87a3cd 100644 --- a/src/libxrpl/tx/transactors/check/CheckCash.cpp +++ b/src/libxrpl/tx/transactors/check/CheckCash.cpp @@ -399,7 +399,13 @@ CheckCash::doApply() // Can the account cover the trust line's or MPT reserve? if (auto const ret = checkInsufficientReserve( - psb, ctx_.tx, sleDst, preFeeBalance_, *sponsorSle, 1, 0, j_); + psb, + ctx_.tx, + sleDst, + preFeeBalance_, + *sponsorSle, + {.ownerCountDelta = 1}, + j_); !isTesSuccess(ret)) { JLOG(j_.trace()) << "Trust line does not exist. " diff --git a/src/libxrpl/tx/transactors/check/CheckCreate.cpp b/src/libxrpl/tx/transactors/check/CheckCreate.cpp index e9f3e175c6..aa4a34db1c 100644 --- a/src/libxrpl/tx/transactors/check/CheckCreate.cpp +++ b/src/libxrpl/tx/transactors/check/CheckCreate.cpp @@ -199,7 +199,13 @@ CheckCreate::doApply() if (!sponsorSle) return sponsorSle.error(); // LCOV_EXCL_LINE if (auto const ret = checkInsufficientReserve( - view(), ctx_.tx, sle, preFeeBalance_, *sponsorSle, 1, 0, ctx_.journal); + view(), + ctx_.tx, + sle, + preFeeBalance_, + *sponsorSle, + {.ownerCountDelta = 1}, + ctx_.journal); !isTesSuccess(ret)) return ret; // Note that we use the value from the sequence or ticket as the diff --git a/src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp b/src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp index 8cc9beba69..cc81c8921b 100644 --- a/src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp +++ b/src/libxrpl/tx/transactors/credentials/CredentialAccept.cpp @@ -94,7 +94,7 @@ CredentialAccept::doApply() return tefINTERNAL; // LCOV_EXCL_LINE { - STAmount const reserve{accountReserve(view(), sleSubject, j_, 1)}; + STAmount const reserve{accountReserve(view(), sleSubject, j_, {.ownerCountDelta = 1})}; if (preFeeBalance_ < reserve) return tecINSUFFICIENT_RESERVE; } diff --git a/src/libxrpl/tx/transactors/credentials/CredentialCreate.cpp b/src/libxrpl/tx/transactors/credentials/CredentialCreate.cpp index 074a9fd9bf..982253ec8f 100644 --- a/src/libxrpl/tx/transactors/credentials/CredentialCreate.cpp +++ b/src/libxrpl/tx/transactors/credentials/CredentialCreate.cpp @@ -131,7 +131,7 @@ CredentialCreate::doApply() return tefINTERNAL; // LCOV_EXCL_LINE { - STAmount const reserve{accountReserve(view(), sleIssuer, j_, 1)}; + STAmount const reserve{accountReserve(view(), sleIssuer, j_, {.ownerCountDelta = 1})}; if (preFeeBalance_ < reserve) return tecINSUFFICIENT_RESERVE; } diff --git a/src/libxrpl/tx/transactors/delegate/DelegateSet.cpp b/src/libxrpl/tx/transactors/delegate/DelegateSet.cpp index ff58e9a2c8..06b92e1912 100644 --- a/src/libxrpl/tx/transactors/delegate/DelegateSet.cpp +++ b/src/libxrpl/tx/transactors/delegate/DelegateSet.cpp @@ -99,7 +99,13 @@ DelegateSet::doApply() if (!sponsorSle) return sponsorSle.error(); // LCOV_EXCL_LINE if (auto const ret = checkInsufficientReserve( - view(), ctx_.tx, sleOwner, preFeeBalance_, *sponsorSle, 1, 0, ctx_.journal); + view(), + ctx_.tx, + sleOwner, + preFeeBalance_, + *sponsorSle, + {.ownerCountDelta = 1}, + ctx_.journal); !isTesSuccess(ret)) return ret; diff --git a/src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp b/src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp index 0fdfae1a9a..66b6b6b891 100644 --- a/src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp +++ b/src/libxrpl/tx/transactors/dex/AMMWithdraw.cpp @@ -634,8 +634,9 @@ AMMWithdraw::withdraw( std::uint32_t const currentOwnerCount = ownerCount(sleAccount, journal); // See also TrustSet::doApply() and MPTokenAuthorize::authorize() XRPAmount const reserve( - (currentOwnerCount < 2) ? XRPAmount(beast::kZero) - : accountReserve(view, sleAccount, journal, 1)); + (currentOwnerCount < 2) + ? XRPAmount(beast::kZero) + : accountReserve(view, sleAccount, journal, {.ownerCountDelta = 1})); auto const balanceAdj = isIssue ? std::max(priorBalance, balance) : priorBalance; if (balanceAdj < reserve) diff --git a/src/libxrpl/tx/transactors/dex/OfferCreate.cpp b/src/libxrpl/tx/transactors/dex/OfferCreate.cpp index d2eb101861..1c66a5ae26 100644 --- a/src/libxrpl/tx/transactors/dex/OfferCreate.cpp +++ b/src/libxrpl/tx/transactors/dex/OfferCreate.cpp @@ -832,7 +832,7 @@ OfferCreate::applyGuts(Sandbox& sb, Sandbox& sbCancel) return {tefINTERNAL, false}; { - XRPAmount const reserve = accountReserve(sb, sleCreator, viewJ, 1); + XRPAmount const reserve = accountReserve(sb, sleCreator, viewJ, {.ownerCountDelta = 1}); if (preFeeBalance_ < reserve) { // If we are here, the signing account had an insufficient reserve diff --git a/src/libxrpl/tx/transactors/did/DIDSet.cpp b/src/libxrpl/tx/transactors/did/DIDSet.cpp index 1157167082..71f15643d4 100644 --- a/src/libxrpl/tx/transactors/did/DIDSet.cpp +++ b/src/libxrpl/tx/transactors/did/DIDSet.cpp @@ -72,7 +72,8 @@ addSLE(ApplyContext& ctx, SLE::ref sle, AccountID const& owner) // Check reserve availability for new object creation { auto const balance = STAmount((*sleAccount)[sfBalance]).xrp(); - auto const reserve = accountReserve(ctx.view(), sleAccount, ctx.journal, 1); + auto const reserve = + accountReserve(ctx.view(), sleAccount, ctx.journal, {.ownerCountDelta = 1}); if (balance < reserve) return tecINSUFFICIENT_RESERVE; diff --git a/src/libxrpl/tx/transactors/escrow/EscrowCreate.cpp b/src/libxrpl/tx/transactors/escrow/EscrowCreate.cpp index bdb4bcddae..9e2d825390 100644 --- a/src/libxrpl/tx/transactors/escrow/EscrowCreate.cpp +++ b/src/libxrpl/tx/transactors/escrow/EscrowCreate.cpp @@ -439,8 +439,8 @@ EscrowCreate::doApply() auto const sponsorSle = getTxReserveSponsor(view(), ctx_.tx); if (!sponsorSle) return sponsorSle.error(); // LCOV_EXCL_LINE - if (auto const ret = - checkInsufficientReserve(ctx_.view(), ctx_.tx, sle, balance, *sponsorSle, 1, 0, j_); + if (auto const ret = checkInsufficientReserve( + ctx_.view(), ctx_.tx, sle, balance, *sponsorSle, {.ownerCountDelta = 1}, j_); !isTesSuccess(ret)) return ret; @@ -448,7 +448,13 @@ EscrowCreate::doApply() if (isXRP(amount)) { if (auto const ret = checkInsufficientReserve( - ctx_.view(), ctx_.tx, sle, balance - STAmount(amount).xrp(), {}, 1, 0, j_); + ctx_.view(), + ctx_.tx, + sle, + balance - STAmount(amount).xrp(), + {}, + {.ownerCountDelta = 1}, + j_); !isTesSuccess(ret)) return tecUNFUNDED; } diff --git a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp index dd5bcbb117..0ac7d1b9df 100644 --- a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp +++ b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp @@ -169,7 +169,8 @@ OracleSet::preclaim(PreclaimContext const& ctx) if (pairs.size() > kMaxOracleDataSeries) return tecARRAY_TOO_LARGE; - auto const reserve = accountReserve(ctx.view, sleSetter, ctx.j, adjustReserve); + auto const reserve = + accountReserve(ctx.view, sleSetter, ctx.j, {.ownerCountDelta = adjustReserve}); auto const& balance = sleSetter->getFieldAmount(sfBalance); if (balance < reserve) diff --git a/src/libxrpl/tx/transactors/payment/DepositPreauth.cpp b/src/libxrpl/tx/transactors/payment/DepositPreauth.cpp index 61f3366174..6b6b2d15e7 100644 --- a/src/libxrpl/tx/transactors/payment/DepositPreauth.cpp +++ b/src/libxrpl/tx/transactors/payment/DepositPreauth.cpp @@ -165,7 +165,7 @@ DepositPreauth::doApply() if (!sponsorSle) return sponsorSle.error(); // LCOV_EXCL_LINE if (auto const ret = checkInsufficientReserve( - view(), ctx_.tx, sleOwner, preFeeBalance_, *sponsorSle, 1, 0, j_); + view(), ctx_.tx, sleOwner, preFeeBalance_, *sponsorSle, {.ownerCountDelta = 1}, j_); !isTesSuccess(ret)) return ret; @@ -213,7 +213,7 @@ DepositPreauth::doApply() if (!sponsorSle) return sponsorSle.error(); // LCOV_EXCL_LINE if (auto const ret = checkInsufficientReserve( - view(), ctx_.tx, sleOwner, preFeeBalance_, *sponsorSle, 1, 0, j_); + view(), ctx_.tx, sleOwner, preFeeBalance_, *sponsorSle, {.ownerCountDelta = 1}, j_); !isTesSuccess(ret)) return ret; diff --git a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp index a6c1d176bb..d9f501b88a 100644 --- a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp +++ b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelCreate.cpp @@ -140,7 +140,13 @@ PaymentChannelCreate::doApply() if (!sponsorSle) return sponsorSle.error(); if (auto const ret = checkInsufficientReserve( - ctx_.view(), ctx_.tx, sle, STAmount{preFeeBalance_}, *sponsorSle, 1, 0, j_); + ctx_.view(), + ctx_.tx, + sle, + STAmount{preFeeBalance_}, + *sponsorSle, + {.ownerCountDelta = 1}, + j_); !isTesSuccess(ret)) return ret; if (auto const ret = checkInsufficientReserve( @@ -149,8 +155,7 @@ PaymentChannelCreate::doApply() sle, STAmount{preFeeBalance_ - ctx_.tx[sfAmount].xrp()}, {}, - 1, - 0, + {.ownerCountDelta = 1}, j_); !isTesSuccess(ret)) return tecUNFUNDED; diff --git a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelFund.cpp b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelFund.cpp index db14a9b06c..d0681718ce 100644 --- a/src/libxrpl/tx/transactors/payment_channel/PaymentChannelFund.cpp +++ b/src/libxrpl/tx/transactors/payment_channel/PaymentChannelFund.cpp @@ -94,12 +94,12 @@ PaymentChannelFund::doApply() if (!sponsorSle) return sponsorSle.error(); // LCOV_EXCL_LINE if (auto const ret = - checkInsufficientReserve(ctx_.view(), ctx_.tx, sle, balance, *sponsorSle, 0, 0, j_); + checkInsufficientReserve(ctx_.view(), ctx_.tx, sle, balance, *sponsorSle, {}, j_); !isTesSuccess(ret)) return ret; if (auto const ret = checkInsufficientReserve( - ctx_.view(), ctx_.tx, sle, balance - ctx_.tx[sfAmount], {}, 0, 0, j_); + ctx_.view(), ctx_.tx, sle, balance - ctx_.tx[sfAmount], {}, {}, j_); !isTesSuccess(ret)) return tecUNFUNDED; } diff --git a/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp b/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp index 658c59f984..bf4ee56bab 100644 --- a/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp +++ b/src/libxrpl/tx/transactors/permissioned_domain/PermissionedDomainSet.cpp @@ -106,7 +106,8 @@ PermissionedDomainSet::doApply() // Create new permissioned domain. // Check reserve availability for new object creation auto const balance = STAmount((*ownerSle)[sfBalance]).xrp(); - auto const reserve = accountReserve(ctx_.view(), ownerSle, ctx_.journal, 1); + auto const reserve = + accountReserve(ctx_.view(), ownerSle, ctx_.journal, {.ownerCountDelta = 1}); if (balance < reserve) return tecINSUFFICIENT_RESERVE; diff --git a/src/libxrpl/tx/transactors/system/TicketCreate.cpp b/src/libxrpl/tx/transactors/system/TicketCreate.cpp index e8483998d9..f6e9167dee 100644 --- a/src/libxrpl/tx/transactors/system/TicketCreate.cpp +++ b/src/libxrpl/tx/transactors/system/TicketCreate.cpp @@ -75,7 +75,11 @@ TicketCreate::doApply() // check the starting balance because we want to allow dipping into the // reserve to pay fees. std::uint32_t const ticketCount = ctx_.tx[sfTicketCount]; - if (preFeeBalance_ < accountReserve(view(), sleAccountRoot, j_, ticketCount)) + if (preFeeBalance_ < accountReserve( + view(), + sleAccountRoot, + j_, + {.ownerCountDelta = static_cast(ticketCount)})) return tecINSUFFICIENT_RESERVE; beast::Journal const viewJ{ctx_.registry.get().getJournal("View")}; diff --git a/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp b/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp index 6f041980f1..ca208a59c3 100644 --- a/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp +++ b/src/libxrpl/tx/transactors/token/MPTokenIssuanceCreate.cpp @@ -125,7 +125,7 @@ MPTokenIssuanceCreate::create( if (args.priorBalance) { if (auto const ret = checkInsufficientReserve( - view, tx, acct, *(args.priorBalance), sponsorSle, 1, 0, journal); + view, tx, acct, *(args.priorBalance), sponsorSle, {.ownerCountDelta = 1}, journal); !isTesSuccess(ret)) return std::unexpected(ret); // tecINSUFFICIENT_RESERVE } diff --git a/src/libxrpl/tx/transactors/token/TrustSet.cpp b/src/libxrpl/tx/transactors/token/TrustSet.cpp index 6961b40bd1..1c0a1455cc 100644 --- a/src/libxrpl/tx/transactors/token/TrustSet.cpp +++ b/src/libxrpl/tx/transactors/token/TrustSet.cpp @@ -539,7 +539,13 @@ TrustSet::doApply() // For PreFunded sponsors, we need to check if there are sufficient reserves before // calling adjustOwnerCount(). if (auto const ret = checkInsufficientReserve( - view(), ctx_.tx, sleLowAccount, preFeeBalance_, *sponsorSle, 1, 0, j_); + view(), + ctx_.tx, + sleLowAccount, + preFeeBalance_, + *sponsorSle, + {.ownerCountDelta = 1}, + j_); *sponsorSle && !isTesSuccess(ret)) return tecINSUF_RESERVE_LINE; @@ -568,7 +574,13 @@ TrustSet::doApply() // For PreFunded sponsors, we need to check if there are sufficient reserves before // calling adjustOwnerCount(). if (auto const ret = checkInsufficientReserve( - view(), ctx_.tx, sleHighAccount, preFeeBalance_, *sponsorSle, 1, 0, j_); + view(), + ctx_.tx, + sleHighAccount, + preFeeBalance_, + *sponsorSle, + {.ownerCountDelta = 1}, + j_); *sponsorSle && !isTesSuccess(ret)) return tecINSUF_RESERVE_LINE; @@ -602,8 +614,8 @@ TrustSet::doApply() } // Reserve is not scaled by load. else if ( - auto const ret = checkInsufficientReserve( - view(), ctx_.tx, sle, preFeeBalance_, *sponsorSle, 0, 0, j_); + auto const ret = + checkInsufficientReserve(view(), ctx_.tx, sle, preFeeBalance_, *sponsorSle, {}, j_); !freeTrustLine && bReserveIncrease && !isTesSuccess(ret)) { JLOG(j_.trace()) << "Delay transaction: Insufficent reserve to " @@ -634,7 +646,7 @@ TrustSet::doApply() } else if ( auto const ret = checkInsufficientReserve( - ctx_.view(), ctx_.tx, sle, preFeeBalance_, *sponsorSle, 1, 0, j_); + ctx_.view(), ctx_.tx, sle, preFeeBalance_, *sponsorSle, {.ownerCountDelta = 1}, j_); !freeTrustLine && !isTesSuccess(ret)) // Reserve is not scaled by load. { JLOG(j_.trace()) << "Delay transaction: Line does not exist. " diff --git a/src/test/app/AMMExtendedMPT_test.cpp b/src/test/app/AMMExtendedMPT_test.cpp index a409cbee88..6fbf134f86 100644 --- a/src/test/app/AMMExtendedMPT_test.cpp +++ b/src/test/app/AMMExtendedMPT_test.cpp @@ -463,8 +463,9 @@ private: // Provide micro amounts to compensate for fees to make results round // nice. - auto const startingXrp = - XRP(100) + baseAccountReserve(*env.current(), 2) + env.current()->fees().base * 3; + auto const startingXrp = XRP(100) + + baseAccountReserve(*env.current(), {.ownerCountDelta = 2}) + + env.current()->fees().base * 3; env.fund(startingXrp, gw_, alice_); env.fund(XRP(2'000), bob_); diff --git a/src/test/app/AMMExtended_test.cpp b/src/test/app/AMMExtended_test.cpp index c7fe147511..1875d42f03 100644 --- a/src/test/app/AMMExtended_test.cpp +++ b/src/test/app/AMMExtended_test.cpp @@ -546,8 +546,9 @@ private: // fees: // 1 for each trust limit == 3 (alice_ < mtgox/amazon/bitstamp) + // 1 for payment == 4 - auto const startingXrp = - XRP(100) + baseAccountReserve(*env.current(), 3) + env.current()->fees().base * 4; + auto const startingXrp = XRP(100) + + baseAccountReserve(*env.current(), {.ownerCountDelta = 3}) + + env.current()->fees().base * 4; env.fund(startingXrp, gw1, gw2, gw3, localAlice); env.fund(XRP(2'000), localBob); diff --git a/src/test/app/CheckMPT_test.cpp b/src/test/app/CheckMPT_test.cpp index b7cded444e..65d58e51cb 100644 --- a/src/test/app/CheckMPT_test.cpp +++ b/src/test/app/CheckMPT_test.cpp @@ -410,7 +410,7 @@ class CheckMPT_test : public beast::unit_test::Suite // Insufficient reserve. Account const cheri{"cheri"}; - env.fund(baseAccountReserve(*env.current(), 1) - drops(1), cheri); + env.fund(baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) - drops(1), cheri); env(check::create(cheri, bob, usd(50)), Fee(drops(env.current()->fees().base)), diff --git a/src/test/app/Check_test.cpp b/src/test/app/Check_test.cpp index f97ca9435c..cc9ba67afd 100644 --- a/src/test/app/Check_test.cpp +++ b/src/test/app/Check_test.cpp @@ -471,7 +471,7 @@ class Check_test : public beast::unit_test::Suite // Insufficient reserve. Account const cheri{"cheri"}; - env.fund(baseAccountReserve(*env.current(), 1) - drops(1), cheri); + env.fund(baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) - drops(1), cheri); env.close(); env(check::create(cheri, bob, usd(50)), diff --git a/src/test/app/Credentials_test.cpp b/src/test/app/Credentials_test.cpp index 9e7575cd50..6772514389 100644 --- a/src/test/app/Credentials_test.cpp +++ b/src/test/app/Credentials_test.cpp @@ -639,8 +639,8 @@ struct Credentials_test : public beast::unit_test::Suite { Env env{*this, features}; - env.fund(drops(baseAccountReserve(*env.current(), 1)), issuer); - env.fund(drops(baseAccountReserve(*env.current(), 0)), subject); + env.fund(drops(baseAccountReserve(*env.current(), {.ownerCountDelta = 1})), issuer); + env.fund(drops(baseAccountReserve(*env.current(), {.ownerCountDelta = 0})), subject); env.close(); { diff --git a/src/test/app/Delegate_test.cpp b/src/test/app/Delegate_test.cpp index 0779d410e2..2aaaeb4ef2 100644 --- a/src/test/app/Delegate_test.cpp +++ b/src/test/app/Delegate_test.cpp @@ -262,7 +262,7 @@ class Delegate_test : public beast::unit_test::Suite Account const bob{"bob"}; auto const txFee = env.current()->fees().base; - env.fund(baseAccountReserve(*env.current(), 0) + txFee, alice); + env.fund(baseAccountReserve(*env.current(), {.ownerCountDelta = 0}) + txFee, alice); env.fund(XRP(100000), bob); env.close(); @@ -279,7 +279,8 @@ class Delegate_test : public beast::unit_test::Suite auto const txFee = env.current()->fees().base; - env.fund(baseAccountReserve(*env.current(), 1) + (txFee * 4), alice); + env.fund( + baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) + (txFee * 4), alice); env.fund(XRP(100000), bob, carol); env.close(); @@ -305,8 +306,8 @@ class Delegate_test : public beast::unit_test::Suite Account const alice{"alice"}; Account const bob{"bob"}; - env.fund(drops(baseAccountReserve(*env.current(), 1)), alice); - env.fund(drops(baseAccountReserve(*env.current(), 2)), bob); + env.fund(drops(baseAccountReserve(*env.current(), {.ownerCountDelta = 1})), alice); + env.fund(drops(baseAccountReserve(*env.current(), {.ownerCountDelta = 2})), bob); env.close(); // alice gives bob permission @@ -409,7 +410,7 @@ class Delegate_test : public beast::unit_test::Suite Account const carol{"carol"}; auto const baseFee = env.current()->fees().base; - auto const reserve = baseAccountReserve(*env.current(), 1); + auto const reserve = baseAccountReserve(*env.current(), {.ownerCountDelta = 1}); auto const paymentAmount = XRP(1); auto const highFee = reserve + baseFee; BEAST_EXPECT(highFee > reserve); @@ -475,9 +476,11 @@ class Delegate_test : public beast::unit_test::Suite Account const carol{"carol"}; auto const baseFee = env.current()->fees().base; - auto const baseReserve = baseAccountReserve(*env.current(), 0); + auto const baseReserve = baseAccountReserve(*env.current(), {.ownerCountDelta = 0}); - env.fund(baseAccountReserve(*env.current(), 1) + baseFee + XRP(1), alice); + env.fund( + baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) + baseFee + XRP(1), + alice); env.fund(baseReserve, bob); env.fund(XRP(1000), carol); env.close(); @@ -510,7 +513,7 @@ class Delegate_test : public beast::unit_test::Suite Account const carol{"carol"}; auto const baseFee = env.current()->fees().base; - auto const reserve = baseAccountReserve(*env.current(), 1); + auto const reserve = baseAccountReserve(*env.current(), {.ownerCountDelta = 1}); // Alice is funded with (reserve + baseFee): after DelegateSet she has // exactly 'reserve', which is insufficient to send XRP(10) while keeping diff --git a/src/test/app/DepositAuth_test.cpp b/src/test/app/DepositAuth_test.cpp index c615bded16..65affea416 100644 --- a/src/test/app/DepositAuth_test.cpp +++ b/src/test/app/DepositAuth_test.cpp @@ -52,7 +52,8 @@ namespace xrpl::test { static XRPAmount reserve(jtx::Env& env, std::uint32_t count) { - return baseAccountReserve(*env.current(), count); + return baseAccountReserve( + *env.current(), {.ownerCountDelta = static_cast(count)}); } // Helper function that returns true if acct has the lsfDepositAuth flag set. @@ -1026,7 +1027,7 @@ struct DepositPreauth_test : public beast::unit_test::Suite { // not enough reserve Account const john{"john"}; - env.fund(baseAccountReserve(*env.current(), 0), john); + env.fund(baseAccountReserve(*env.current(), {.ownerCountDelta = 0}), john); env.close(); auto jv = deposit::authCredentials(john, {{.issuer = issuer, .credType = credType}}); diff --git a/src/test/app/FlowMPT_test.cpp b/src/test/app/FlowMPT_test.cpp index 01dea70939..f5c2ad424c 100644 --- a/src/test/app/FlowMPT_test.cpp +++ b/src/test/app/FlowMPT_test.cpp @@ -726,7 +726,8 @@ struct FlowMPT_test : public beast::unit_test::Suite static XRPAmount reserve(jtx::Env& env, std::uint32_t count) { - return baseAccountReserve(*env.current(), count); + return baseAccountReserve( + *env.current(), {.ownerCountDelta = static_cast(count)}); } // Helper function that returns the Offers on an account. diff --git a/src/test/app/Flow_test.cpp b/src/test/app/Flow_test.cpp index 83b050e07c..d94bece477 100644 --- a/src/test/app/Flow_test.cpp +++ b/src/test/app/Flow_test.cpp @@ -707,7 +707,8 @@ struct Flow_test : public beast::unit_test::Suite static XRPAmount reserve(jtx::Env& env, std::uint32_t count) { - return baseAccountReserve(*env.current(), count); + return baseAccountReserve( + *env.current(), {.ownerCountDelta = static_cast(count)}); } // Helper function that returns the Offers on an account. diff --git a/src/test/app/Loan_test.cpp b/src/test/app/Loan_test.cpp index 423fe7b6cc..f9eb0cdeb0 100644 --- a/src/test/app/Loan_test.cpp +++ b/src/test/app/Loan_test.cpp @@ -690,11 +690,16 @@ protected: case AssetType::MPT: { // Enough to cover initial fees if (!env.le(keylet::account(issuer))) - env.fund(baseAccountReserve(*env.current(), 10) * 10, issuer); + env.fund( + baseAccountReserve(*env.current(), {.ownerCountDelta = 10}) * 10, issuer); if (!env.le(keylet::account(lender))) - env.fund(baseAccountReserve(*env.current(), 10) * 10, noripple(lender)); + env.fund( + baseAccountReserve(*env.current(), {.ownerCountDelta = 10}) * 10, + noripple(lender)); if (!env.le(keylet::account(borrower))) - env.fund(baseAccountReserve(*env.current(), 10) * 10, noripple(borrower)); + env.fund( + baseAccountReserve(*env.current(), {.ownerCountDelta = 10}) * 10, + noripple(borrower)); MPTTester mptt{env, issuer, kMptInitNoFund}; mptt.create({.flags = tfMPTCanClawback | tfMPTCanTransfer | tfMPTCanLock}); @@ -779,11 +784,14 @@ protected: using namespace jtx; // Enough to cover initial fees - env.fund(baseAccountReserve(*env.current(), 10) * 10, issuer); + env.fund(baseAccountReserve(*env.current(), {.ownerCountDelta = 10}) * 10, issuer); if (lender != issuer) - env.fund(baseAccountReserve(*env.current(), 10) * 10, noripple(lender)); + env.fund( + baseAccountReserve(*env.current(), {.ownerCountDelta = 10}) * 10, noripple(lender)); if (borrower != issuer && borrower != lender) - env.fund(baseAccountReserve(*env.current(), 10) * 10, noripple(borrower)); + env.fund( + baseAccountReserve(*env.current(), {.ownerCountDelta = 10}) * 10, + noripple(borrower)); describeLoan(env, brokerParams, loanParams, assetType, issuer, lender, borrower); @@ -3089,7 +3097,8 @@ protected: auto const [acctReserve, incReserve] = [this]() -> std::pair { Env const env{*this, testableAmendments()}; return { - baseAccountReserve(*env.current(), 0).drops() / kDropsPerXrp.drops(), + baseAccountReserve(*env.current(), {.ownerCountDelta = 0}).drops() / + kDropsPerXrp.drops(), env.current()->fees().increment.drops() / kDropsPerXrp.drops()}; }(); diff --git a/src/test/app/OfferMPT_test.cpp b/src/test/app/OfferMPT_test.cpp index d7597dcd54..dd32178bdd 100644 --- a/src/test/app/OfferMPT_test.cpp +++ b/src/test/app/OfferMPT_test.cpp @@ -58,7 +58,8 @@ class OfferMPT_test : public beast::unit_test::Suite static XRPAmount reserve(jtx::Env& env, std::uint32_t count) { - return baseAccountReserve(*env.current(), count); + return baseAccountReserve( + *env.current(), {.ownerCountDelta = static_cast(count)}); } static std::uint32_t @@ -1793,7 +1794,8 @@ public: // 1 for each trust limit == 3 (alice < mtgox/amazon/bitstamp) + // 1 for payment == 4 auto const base = env.current()->fees().base; - auto const startingXrp = XRP(100) + baseAccountReserve(*env.current(), 3) + base * 4; + auto const startingXrp = + XRP(100) + baseAccountReserve(*env.current(), {.ownerCountDelta = 3}) + base * 4; env.fund(startingXrp, gw1, gw2, gw3, alice, bob); env.close(); @@ -1813,7 +1815,9 @@ public: env(offer(alice, usD1(200), XRP(200))); BEAST_EXPECT(env.balance(alice, usD1) == usD1(100)); - BEAST_EXPECT(env.balance(alice) == STAmount(baseAccountReserve(*env.current(), 3))); + BEAST_EXPECT( + env.balance(alice) == + STAmount(baseAccountReserve(*env.current(), {.ownerCountDelta = 3}))); BEAST_EXPECT(env.balance(bob, usD1) == usD1(400)); }; @@ -1863,8 +1867,9 @@ public: auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; - auto const startingXrp = - XRP(100) + baseAccountReserve(*env.current(), 1) + env.current()->fees().base * 2; + auto const startingXrp = XRP(100) + + baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) + + env.current()->fees().base * 2; env.fund(startingXrp, gw, alice, bob); @@ -1883,7 +1888,7 @@ public: jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - STAmount(baseAccountReserve(*env.current(), 1)).getText()); + STAmount(baseAccountReserve(*env.current(), {.ownerCountDelta = 1})).getText()); jrr = ledgerEntryMPT(env, bob, usd); BEAST_EXPECT(jrr[jss::node][sfMPTAmount.fieldName] == "400"); @@ -1902,8 +1907,9 @@ public: auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; - auto const startingXrp = - XRP(100) + baseAccountReserve(*env.current(), 1) + env.current()->fees().base * 2; + auto const startingXrp = XRP(100) + + baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) + + env.current()->fees().base * 2; env.fund(startingXrp, gw, alice, bob); @@ -1924,7 +1930,7 @@ public: jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - STAmount(baseAccountReserve(*env.current(), 1)).getText()); + STAmount(baseAccountReserve(*env.current(), {.ownerCountDelta = 1})).getText()); jrr = ledgerEntryMPT(env, bob, usd); BEAST_EXPECT(jrr[jss::node][sfMPTAmount.fieldName] == "300"); @@ -1944,7 +1950,8 @@ public: Env env{*this, features}; auto const base = env.current()->fees().base; - auto const startingXrp = XRP(100.1) + baseAccountReserve(*env.current(), 1) + base * 2; + auto const startingXrp = + XRP(100.1) + baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) + base * 2; env.fund(startingXrp, gw, alice, bob); env.close(); diff --git a/src/test/app/Offer_test.cpp b/src/test/app/Offer_test.cpp index 7d6acb29e3..6753db709c 100644 --- a/src/test/app/Offer_test.cpp +++ b/src/test/app/Offer_test.cpp @@ -61,7 +61,8 @@ class OfferBaseUtil_test : public beast::unit_test::Suite static XRPAmount reserve(jtx::Env& env, std::uint32_t count) { - return baseAccountReserve(*env.current(), count); + return baseAccountReserve( + *env.current(), {.ownerCountDelta = static_cast(count)}); } static std::uint32_t @@ -1962,8 +1963,9 @@ public: // fees: // 1 for each trust limit == 3 (alice < mtgox/amazon/bitstamp) + // 1 for payment == 4 - auto const startingXrp = - XRP(100) + baseAccountReserve(*env.current(), 3) + env.current()->fees().base * 4; + auto const startingXrp = XRP(100) + + baseAccountReserve(*env.current(), {.ownerCountDelta = 3}) + + env.current()->fees().base * 4; env.fund(startingXrp, gw1, gw2, gw3, alice, bob); env.close(); @@ -1986,7 +1988,7 @@ public: jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - STAmount(baseAccountReserve(*env.current(), 3)).getText()); + STAmount(baseAccountReserve(*env.current(), {.ownerCountDelta = 3})).getText()); jrr = ledgerEntryState(env, bob, gw1, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-400"); @@ -2045,8 +2047,9 @@ public: auto const bob = Account{"bob"}; auto const usd = gw["USD"]; - auto const startingXrp = - XRP(100) + baseAccountReserve(*env.current(), 1) + env.current()->fees().base * 2; + auto const startingXrp = XRP(100) + + baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) + + env.current()->fees().base * 2; env.fund(startingXrp, gw, alice, bob); env.close(); @@ -2067,7 +2070,7 @@ public: jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - STAmount(baseAccountReserve(*env.current(), 1)).getText()); + STAmount(baseAccountReserve(*env.current(), {.ownerCountDelta = 1})).getText()); jrr = ledgerEntryState(env, bob, gw, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-400"); @@ -2087,8 +2090,9 @@ public: auto const bob = Account{"bob"}; auto const usd = gw["USD"]; - auto const startingXrp = - XRP(100) + baseAccountReserve(*env.current(), 1) + env.current()->fees().base * 2; + auto const startingXrp = XRP(100) + + baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) + + env.current()->fees().base * 2; env.fund(startingXrp, gw, alice, bob); env.close(); @@ -2111,7 +2115,7 @@ public: jrr = ledgerEntryRoot(env, alice); BEAST_EXPECT( jrr[jss::node][sfBalance.fieldName] == - STAmount(baseAccountReserve(*env.current(), 1)).getText()); + STAmount(baseAccountReserve(*env.current(), {.ownerCountDelta = 1})).getText()); jrr = ledgerEntryState(env, bob, gw, "USD"); BEAST_EXPECT(jrr[jss::node][sfBalance.fieldName][jss::value] == "-300"); @@ -2132,8 +2136,9 @@ public: auto const xts = gw["XTS"]; auto const xxx = gw["XXX"]; - auto const startingXrp = - XRP(100.1) + baseAccountReserve(*env.current(), 1) + env.current()->fees().base * 2; + auto const startingXrp = XRP(100.1) + + baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) + + env.current()->fees().base * 2; env.fund(startingXrp, gw, alice, bob); env.close(); diff --git a/src/test/app/Oracle_test.cpp b/src/test/app/Oracle_test.cpp index 97c3d29ac6..95df66f5d3 100644 --- a/src/test/app/Oracle_test.cpp +++ b/src/test/app/Oracle_test.cpp @@ -61,7 +61,7 @@ private: // Insufficient reserve { Env env(*this); - env.fund(baseAccountReserve(*env.current(), 0), owner); + env.fund(baseAccountReserve(*env.current(), {.ownerCountDelta = 0}), owner); Oracle const oracle( env, {.owner = owner, @@ -71,7 +71,10 @@ private: // Insufficient reserve if the data series extends to greater than 5 { Env env(*this); - env.fund(baseAccountReserve(*env.current(), 1) + env.current()->fees().base * 2, owner); + env.fund( + baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) + + env.current()->fees().base * 2, + owner); Oracle oracle( env, {.owner = owner, .fee = static_cast(env.current()->fees().base.drops())}); BEAST_EXPECT(oracle.exists()); @@ -639,7 +642,10 @@ private: { Env env(*this); auto const baseFee = static_cast(env.current()->fees().base.drops()); - env.fund(baseAccountReserve(*env.current(), 1) + env.current()->fees().base * 2, owner); + env.fund( + baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) + + env.current()->fees().base * 2, + owner); Oracle oracle(env, {.owner = owner, .fee = baseFee}); oracle.set(UpdateArg{.series = {{"XRP", "USD", 742, 2}}, .fee = baseFee}); } diff --git a/src/test/app/Sponsor_test.cpp b/src/test/app/Sponsor_test.cpp index a615426463..163519989f 100644 --- a/src/test/app/Sponsor_test.cpp +++ b/src/test/app/Sponsor_test.cpp @@ -69,7 +69,8 @@ accountReserve(jtx::Env& env, std::uint32_t count = 1) static STAmount reserve(jtx::Env& env, std::uint32_t count) { - return baseAccountReserve(*env.current(), count); + return baseAccountReserve( + *env.current(), {.ownerCountDelta = static_cast(count)}); } static void @@ -1964,7 +1965,7 @@ public: // Account is not sponsored by normal Sponsor specification { - env(pay(alice, bob, drops(baseAccountReserve(*env.current(), 0))), + env(pay(alice, bob, drops(baseAccountReserve(*env.current(), {.ownerCountDelta = 0}))), sponsor::As(sponsor, spfSponsorReserve), Sig(sfSponsorSignature, sponsor)); env.close(); diff --git a/src/test/app/Ticket_test.cpp b/src/test/app/Ticket_test.cpp index c236971a9a..10d159a895 100644 --- a/src/test/app/Ticket_test.cpp +++ b/src/test/app/Ticket_test.cpp @@ -504,7 +504,7 @@ class Ticket_test : public beast::unit_test::Suite Account const alice{"alice"}; // Fund alice not quite enough to make the reserve for a Ticket. - env.fund(baseAccountReserve(*env.current(), 1) - drops(1), alice); + env.fund(baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) - drops(1), alice); env.close(); env(ticket::create(alice, 1), Ter(tecINSUFFICIENT_RESERVE)); @@ -512,7 +512,10 @@ class Ticket_test : public beast::unit_test::Suite env.require(Owners(alice, 0), tickets(alice, 0)); // Give alice enough to exactly meet the reserve for one Ticket. - env(pay(env.master, alice, baseAccountReserve(*env.current(), 1) - env.balance(alice))); + env( + pay(env.master, + alice, + baseAccountReserve(*env.current(), {.ownerCountDelta = 1}) - env.balance(alice))); env.close(); env(ticket::create(alice, 1)); @@ -525,7 +528,8 @@ class Ticket_test : public beast::unit_test::Suite env( pay(env.master, alice, - baseAccountReserve(*env.current(), 250) - drops(1) - env.balance(alice))); + baseAccountReserve(*env.current(), {.ownerCountDelta = 250}) - drops(1) - + env.balance(alice))); env.close(); // alice doesn't quite have the reserve for a total of 250 @@ -536,7 +540,10 @@ class Ticket_test : public beast::unit_test::Suite // Give alice enough so she can make the reserve for all 250 // Tickets. - env(pay(env.master, alice, baseAccountReserve(*env.current(), 250) - env.balance(alice))); + env( + pay(env.master, + alice, + baseAccountReserve(*env.current(), {.ownerCountDelta = 250}) - env.balance(alice))); env.close(); std::uint32_t const ticketSeq{env.seq(alice) + 1}; diff --git a/src/test/app/TrustSet_test.cpp b/src/test/app/TrustSet_test.cpp index e4bf6cb078..bbecedd4fd 100644 --- a/src/test/app/TrustSet_test.cpp +++ b/src/test/app/TrustSet_test.cpp @@ -192,7 +192,7 @@ public: auto const txFee = env.current()->fees().base; auto const baseReserve = env.current()->fees().reserve; - auto const threelineReserve = baseAccountReserve(*env.current(), 3); + auto const threelineReserve = baseAccountReserve(*env.current(), {.ownerCountDelta = 3}); env.fund(XRP(10000), gwA, gwB, assistor); diff --git a/src/test/app/Vault_test.cpp b/src/test/app/Vault_test.cpp index 3c58fa8142..0c0c15a60b 100644 --- a/src/test/app/Vault_test.cpp +++ b/src/test/app/Vault_test.cpp @@ -1877,7 +1877,8 @@ class Vault_test : public beast::unit_test::Suite auto const [acctReserve, incReserve] = [this]() -> std::pair { Env const env{*this, testableAmendments()}; return { - baseAccountReserve(*env.current(), 0).drops() / kDropsPerXrp.drops(), + baseAccountReserve(*env.current(), {.ownerCountDelta = 0}).drops() / + kDropsPerXrp.drops(), env.current()->fees().increment.drops() / kDropsPerXrp.drops()}; }(); @@ -2950,7 +2951,8 @@ class Vault_test : public beast::unit_test::Suite auto const [acctReserve, incReserve] = [this]() -> std::pair { Env const env{*this, testableAmendments()}; return { - baseAccountReserve(*env.current(), 0).drops() / kDropsPerXrp.drops(), + baseAccountReserve(*env.current(), {.ownerCountDelta = 0}).drops() / + kDropsPerXrp.drops(), env.current()->fees().increment.drops() / kDropsPerXrp.drops()}; }(); diff --git a/src/test/app/XChain_test.cpp b/src/test/app/XChain_test.cpp index 75e0f0e3ef..74bce77f04 100644 --- a/src/test/app/XChain_test.cpp +++ b/src/test/app/XChain_test.cpp @@ -142,7 +142,8 @@ struct SEnv XRPAmount reserve(std::uint32_t count) { - return baseAccountReserve(*env.current(), count); + return baseAccountReserve( + *env.current(), {.ownerCountDelta = static_cast(count)}); } XRPAmount @@ -372,7 +373,8 @@ struct XChain_test : public beast::unit_test::Suite, public jtx::XChainBridgeObj XRPAmount reserve(std::uint32_t count) { - return baseAccountReserve(*XEnv(*this).env.current(), count); + return baseAccountReserve( + *XEnv(*this).env.current(), {.ownerCountDelta = static_cast(count)}); } XRPAmount diff --git a/src/test/jtx/impl/AMMTest.cpp b/src/test/jtx/impl/AMMTest.cpp index 6b9a075735..8381089762 100644 --- a/src/test/jtx/impl/AMMTest.cpp +++ b/src/test/jtx/impl/AMMTest.cpp @@ -198,7 +198,8 @@ AMMTestBase::testAMM(std::function const& cb, TestAM XRPAmount AMMTest::reserve(jtx::Env& env, std::uint32_t count) { - return baseAccountReserve(*env.current(), count); + return baseAccountReserve( + *env.current(), {.ownerCountDelta = static_cast(count)}); } XRPAmount diff --git a/src/test/ledger/PaymentSandbox_test.cpp b/src/test/ledger/PaymentSandbox_test.cpp index a89d07849b..d742c9a406 100644 --- a/src/test/ledger/PaymentSandbox_test.cpp +++ b/src/test/ledger/PaymentSandbox_test.cpp @@ -331,7 +331,8 @@ class PaymentSandbox_test : public beast::unit_test::Suite }; auto reserve = [](jtx::Env& env, std::uint32_t count) -> XRPAmount { - return baseAccountReserve(*env.current(), count); + return baseAccountReserve( + *env.current(), {.ownerCountDelta = static_cast(count)}); }; Env env(*this, features); diff --git a/src/test/rpc/AccountTx_test.cpp b/src/test/rpc/AccountTx_test.cpp index 9310bf384a..35776bd85a 100644 --- a/src/test/rpc/AccountTx_test.cpp +++ b/src/test/rpc/AccountTx_test.cpp @@ -776,7 +776,9 @@ class AccountTx_test : public beast::unit_test::Suite // All it takes is a large enough XRP payment to resurrect // becky's account. Try too small a payment. - env(pay(alice, becky, drops(baseAccountReserve(*env.current(), 0)) - drops(1)), + env(pay(alice, + becky, + drops(baseAccountReserve(*env.current(), {.ownerCountDelta = 0})) - drops(1)), Ter(tecNO_DST_INSUF_XRP)); env.close();