diff --git a/include/xrpl/ledger/helpers/LendingHelpers.h b/include/xrpl/ledger/helpers/LendingHelpers.h index 873abae272..04f28e7ddd 100644 --- a/include/xrpl/ledger/helpers/LendingHelpers.h +++ b/include/xrpl/ledger/helpers/LendingHelpers.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include // IWYU pragma: keep #include @@ -48,7 +49,7 @@ namespace xrpl { [[nodiscard]] TER canApplyToBrokerCover( ReadView const& view, - SLE::const_ref sleBroker, + LoanBrokerEntry const& sleBroker, Asset const& vaultAsset, STAmount const& amount, beast::Journal j, @@ -214,7 +215,7 @@ adjustImpreciseNumber( } inline int -getAssetsTotalScale(SLE::const_ref vaultSle) +getAssetsTotalScale(VaultEntry const& vaultSle) { if (!vaultSle) return Number::kMinExponent - 1; // LCOV_EXCL_LINE @@ -225,7 +226,10 @@ getAssetsTotalScale(SLE::const_ref vaultSle) // DebtTotal is a broker-level aggregate maintained at vault scale, so the // rounding must also use vault scale — never an individual loan's scale. inline Number -minimumBrokerCover(Number const& debtTotal, TenthBips32 coverRateMinimum, SLE::const_ref vaultSle) +minimumBrokerCover( + Number const& debtTotal, + TenthBips32 coverRateMinimum, + VaultEntry const& vaultSle) { XRPL_ASSERT( vaultSle && vaultSle->getType() == ltVAULT, "xrpl::minimumBrokerCover : valid Vault sle"); @@ -263,7 +267,7 @@ constructLoanState( // Constructs a valid LoanState object from a Loan object, which always has // rounded values LoanState -constructRoundedLoanState(SLE::const_ref loan); +constructRoundedLoanState(LoanEntry const& loan); Number computeManagementFee( @@ -545,8 +549,8 @@ std::expected loanMakePayment( Asset const& asset, ApplyView& view, - SLE::ref loan, - SLE::const_ref brokerSle, + LoanEntry& loan, + LoanBrokerEntry const& brokerSle, STAmount const& amount, LoanPaymentType const paymentType, beast::Journal j); diff --git a/include/xrpl/ledger/helpers/SLEBase.h b/include/xrpl/ledger/helpers/SLEBase.h index 419859e3e5..e2539e1517 100644 --- a/include/xrpl/ledger/helpers/SLEBase.h +++ b/include/xrpl/ledger/helpers/SLEBase.h @@ -177,7 +177,10 @@ public: return j_; } -protected: + // --- Constructors that adopt/resolve an SLE (public so the ReadOnlySLE / + // WritableSLE aliases and the per-type wrappers can be built directly + // from an already-fetched SLE or a keylet). --- + /** Constructor for read-only context */ explicit SLEBase( SLE::const_pointer sle, @@ -233,6 +236,7 @@ protected: { } +protected: view_ref_type view_{}; // Keylet is only meaningful for writable views, but we conditionally @@ -247,4 +251,15 @@ protected: beast::Journal j_; }; +/** Generic (any-entry-type) SLE handles. + * + * Use these when the concrete ledger entry type is not known at a given site; + * otherwise prefer the per-type wrappers in SLEWrappers.h. + * + * SLE::const_pointer / SLE::const_ref -> ReadOnlySLE + * SLE::pointer / SLE::ref -> WritableSLE + */ +using ReadOnlySLE = SLEBase; +using WritableSLE = SLEBase; + } // namespace xrpl diff --git a/include/xrpl/ledger/helpers/SLEWrappers.h b/include/xrpl/ledger/helpers/SLEWrappers.h index f824c248c9..2c4d29aa39 100644 --- a/include/xrpl/ledger/helpers/SLEWrappers.h +++ b/include/xrpl/ledger/helpers/SLEWrappers.h @@ -14,8 +14,8 @@ namespace xrpl { * than translate the entry's "keylet parts" (the arguments to its keylet:: * function) into a Keylet that the base class resolves against the view: * - * AccountRoot acct{id, view}; // peek (writable) - * AccountRoot acct{id, readView}; // read (read-only) + * AccountRootEntry acct{id, view}; // peek (writable) + * AccountRootEntry acct{id, readView}; // read (read-only) * * Domain-specific accessors will be layered onto each wrapper over time. */ @@ -23,10 +23,14 @@ namespace xrpl { // Ordered to match include/xrpl/protocol/detail/ledger_entries.macro. template -class NFTokenOffer : public SLEBase +class NFTokenOfferEntry : public SLEBase { public: - explicit NFTokenOffer( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit NFTokenOfferEntry( AccountID const& owner, std::uint32_t seq, typename SLEBase::view_ref_type view, @@ -37,10 +41,14 @@ public: }; template -class Check : public SLEBase +class CheckEntry : public SLEBase { public: - explicit Check( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit CheckEntry( AccountID const& id, std::uint32_t seq, typename SLEBase::view_ref_type view, @@ -51,10 +59,14 @@ public: }; template -class DID : public SLEBase +class DIDEntry : public SLEBase { public: - explicit DID( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit DIDEntry( AccountID const& account, typename SLEBase::view_ref_type view, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) @@ -64,10 +76,14 @@ public: }; template -class NegativeUNL : public SLEBase +class NegativeUNLEntry : public SLEBase { public: - explicit NegativeUNL( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit NegativeUNLEntry( typename SLEBase::view_ref_type view, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) : SLEBase(keylet::negativeUNL(), view, j) @@ -76,10 +92,14 @@ public: }; template -class NFTokenPage : public SLEBase +class NFTokenPageEntry : public SLEBase { public: - explicit NFTokenPage( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit NFTokenPageEntry( Keylet const& page, uint256 const& token, typename SLEBase::view_ref_type view, @@ -90,10 +110,14 @@ public: }; template -class SignerList : public SLEBase +class SignerListEntry : public SLEBase { public: - explicit SignerList( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit SignerListEntry( AccountID const& account, typename SLEBase::view_ref_type view, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) @@ -103,10 +127,14 @@ public: }; template -class Ticket : public SLEBase +class TicketEntry : public SLEBase { public: - explicit Ticket( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit TicketEntry( AccountID const& id, std::uint32_t ticketSeq, typename SLEBase::view_ref_type view, @@ -117,10 +145,14 @@ public: }; template -class AccountRoot : public SLEBase +class AccountRootEntry : public SLEBase { public: - explicit AccountRoot( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit AccountRootEntry( AccountID const& id, typename SLEBase::view_ref_type view, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) @@ -130,10 +162,14 @@ public: }; template -class DirectoryNode : public SLEBase +class DirectoryNodeEntry : public SLEBase { public: - explicit DirectoryNode( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit DirectoryNodeEntry( AccountID const& id, typename SLEBase::view_ref_type view, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) @@ -143,10 +179,14 @@ public: }; template -class Amendments : public SLEBase +class AmendmentsEntry : public SLEBase { public: - explicit Amendments( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit AmendmentsEntry( typename SLEBase::view_ref_type view, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) : SLEBase(keylet::amendments(), view, j) @@ -155,10 +195,14 @@ public: }; template -class LedgerHashes : public SLEBase +class LedgerHashesEntry : public SLEBase { public: - explicit LedgerHashes( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit LedgerHashesEntry( typename SLEBase::view_ref_type view, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) : SLEBase(keylet::skip(), view, j) @@ -167,10 +211,14 @@ public: }; template -class Bridge : public SLEBase +class BridgeEntry : public SLEBase { public: - explicit Bridge( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit BridgeEntry( STXChainBridge const& bridge, STXChainBridge::ChainType chainType, typename SLEBase::view_ref_type view, @@ -181,10 +229,14 @@ public: }; template -class Offer : public SLEBase +class OfferEntry : public SLEBase { public: - explicit Offer( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit OfferEntry( AccountID const& id, std::uint32_t seq, typename SLEBase::view_ref_type view, @@ -195,10 +247,14 @@ public: }; template -class DepositPreauth : public SLEBase +class DepositPreauthEntry : public SLEBase { public: - explicit DepositPreauth( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit DepositPreauthEntry( AccountID const& owner, AccountID const& preauthorized, typename SLEBase::view_ref_type view, @@ -209,10 +265,14 @@ public: }; template -class XChainOwnedClaimID : public SLEBase +class XChainOwnedClaimIDEntry : public SLEBase { public: - explicit XChainOwnedClaimID( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit XChainOwnedClaimIDEntry( STXChainBridge const& bridge, std::uint64_t seq, typename SLEBase::view_ref_type view, @@ -223,10 +283,14 @@ public: }; template -class RippleState : public SLEBase +class RippleStateEntry : public SLEBase { public: - explicit RippleState( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit RippleStateEntry( AccountID const& id0, AccountID const& id1, Currency const& currency, @@ -238,10 +302,14 @@ public: }; template -class FeeSettings : public SLEBase +class FeeSettingsEntry : public SLEBase { public: - explicit FeeSettings( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit FeeSettingsEntry( typename SLEBase::view_ref_type view, beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) : SLEBase(keylet::feeSettings(), view, j) @@ -250,10 +318,14 @@ public: }; template -class XChainOwnedCreateAccountClaimID : public SLEBase +class XChainOwnedCreateAccountClaimIDEntry : public SLEBase { public: - explicit XChainOwnedCreateAccountClaimID( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit XChainOwnedCreateAccountClaimIDEntry( STXChainBridge const& bridge, std::uint64_t seq, typename SLEBase::view_ref_type view, @@ -264,10 +336,14 @@ public: }; template -class Escrow : public SLEBase +class EscrowEntry : public SLEBase { public: - explicit Escrow( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit EscrowEntry( AccountID const& src, std::uint32_t seq, typename SLEBase::view_ref_type view, @@ -278,10 +354,14 @@ public: }; template -class PayChannel : public SLEBase +class PayChannelEntry : public SLEBase { public: - explicit PayChannel( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit PayChannelEntry( AccountID const& src, AccountID const& dst, std::uint32_t seq, @@ -293,10 +373,14 @@ public: }; template -class AMM : public SLEBase +class AMMEntry : public SLEBase { public: - explicit AMM( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit AMMEntry( Asset const& issue1, Asset const& issue2, typename SLEBase::view_ref_type view, @@ -307,10 +391,14 @@ public: }; template -class MPTokenIssuance : public SLEBase +class MPTokenIssuanceEntry : public SLEBase { public: - explicit MPTokenIssuance( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit MPTokenIssuanceEntry( std::uint32_t seq, AccountID const& issuer, typename SLEBase::view_ref_type view, @@ -321,10 +409,14 @@ public: }; template -class MPToken : public SLEBase +class MPTokenEntry : public SLEBase { public: - explicit MPToken( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit MPTokenEntry( MPTID const& issuanceID, AccountID const& holder, typename SLEBase::view_ref_type view, @@ -335,10 +427,14 @@ public: }; template -class Oracle : public SLEBase +class OracleEntry : public SLEBase { public: - explicit Oracle( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit OracleEntry( AccountID const& account, std::uint32_t documentID, typename SLEBase::view_ref_type view, @@ -349,10 +445,14 @@ public: }; template -class Credential : public SLEBase +class CredentialEntry : public SLEBase { public: - explicit Credential( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit CredentialEntry( AccountID const& subject, AccountID const& issuer, Slice const& credType, @@ -364,10 +464,14 @@ public: }; template -class PermissionedDomain : public SLEBase +class PermissionedDomainEntry : public SLEBase { public: - explicit PermissionedDomain( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit PermissionedDomainEntry( AccountID const& account, std::uint32_t seq, typename SLEBase::view_ref_type view, @@ -378,10 +482,14 @@ public: }; template -class Delegate : public SLEBase +class DelegateEntry : public SLEBase { public: - explicit Delegate( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit DelegateEntry( AccountID const& account, AccountID const& authorizedAccount, typename SLEBase::view_ref_type view, @@ -392,10 +500,14 @@ public: }; template -class Vault : public SLEBase +class VaultEntry : public SLEBase { public: - explicit Vault( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit VaultEntry( AccountID const& owner, std::uint32_t seq, typename SLEBase::view_ref_type view, @@ -406,10 +518,14 @@ public: }; template -class LoanBroker : public SLEBase +class LoanBrokerEntry : public SLEBase { public: - explicit LoanBroker( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit LoanBrokerEntry( AccountID const& owner, std::uint32_t seq, typename SLEBase::view_ref_type view, @@ -420,10 +536,14 @@ public: }; template -class Loan : public SLEBase +class LoanEntry : public SLEBase { public: - explicit Loan( + // Inherit base constructors: adopt an existing SLE, or resolve one from a + // Keylet against the view. + using SLEBase::SLEBase; + + explicit LoanEntry( uint256 const& loanBrokerID, std::uint32_t loanSeq, typename SLEBase::view_ref_type view, @@ -433,18 +553,4 @@ public: } }; -template -class Sponsorship : public SLEBase -{ -public: - explicit Sponsorship( - AccountID const& sponsor, - AccountID const& sponsee, - typename SLEBase::view_ref_type view, - beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) - : SLEBase(keylet::sponsorship(sponsor, sponsee), view, j) - { - } -}; - } // namespace xrpl diff --git a/include/xrpl/protocol/Indexes.h b/include/xrpl/protocol/Indexes.h index 053a66787f..0b2d49173a 100644 --- a/include/xrpl/protocol/Indexes.h +++ b/include/xrpl/protocol/Indexes.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -363,20 +362,10 @@ struct KeyletDesc }; // This list should include all of the keylet functions that take a single -// AccountID parameter. -std::array, 6> const kDirectAccountKeylets{ - {{.function = &keylet::account, .expectedLEName = jss::AccountRoot, .includeInTests = false}, - {.function = &keylet::ownerDir, .expectedLEName = jss::DirectoryNode, .includeInTests = true}, - {.function = &keylet::signerList, .expectedLEName = jss::SignerList, .includeInTests = true}, - // It's normally impossible to create an item at nftpage_min, but - // test it anyway, since the invariant checks for it. - {.function = &keylet::nftokenPageMin, - .expectedLEName = jss::NFTokenPage, - .includeInTests = true}, - {.function = &keylet::nftokenPageMax, - .expectedLEName = jss::NFTokenPage, - .includeInTests = true}, - {.function = &keylet::did, .expectedLEName = jss::DID, .includeInTests = true}}}; +// AccountID parameter. Defined in Indexes.cpp so that this header does not +// need to include jss.h (which transitively re-includes transactions.macro +// and breaks headers processed inside the TRANSACTION_INCLUDE machinery). +extern std::array, 6> const kDirectAccountKeylets; MPTID makeMptID(std::uint32_t sequence, AccountID const& account); diff --git a/include/xrpl/tx/transactors/lending/LoanManage.h b/include/xrpl/tx/transactors/lending/LoanManage.h index c8a5584131..f420b30f29 100644 --- a/include/xrpl/tx/transactors/lending/LoanManage.h +++ b/include/xrpl/tx/transactors/lending/LoanManage.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -41,9 +42,9 @@ public: static TER defaultLoan( ApplyView& view, - SLE::ref loanSle, - SLE::ref brokerSle, - SLE::ref vaultSle, + LoanEntry& loanSle, + LoanBrokerEntry& brokerSle, + VaultEntry& vaultSle, Asset const& vaultAsset, beast::Journal j); @@ -52,8 +53,8 @@ public: static TER impairLoan( ApplyView& view, - SLE::ref loanSle, - SLE::ref vaultSle, + LoanEntry& loanSle, + VaultEntry& vaultSle, Asset const& vaultAsset, beast::Journal j); @@ -62,8 +63,8 @@ public: [[nodiscard]] static TER unimpairLoan( ApplyView& view, - SLE::ref loanSle, - SLE::ref vaultSle, + LoanEntry& loanSle, + VaultEntry& vaultSle, Asset const& vaultAsset, beast::Journal j); diff --git a/src/libxrpl/ledger/helpers/LendingHelpers.cpp b/src/libxrpl/ledger/helpers/LendingHelpers.cpp index f7ec8a8bc3..13a37b09e3 100644 --- a/src/libxrpl/ledger/helpers/LendingHelpers.cpp +++ b/src/libxrpl/ledger/helpers/LendingHelpers.cpp @@ -33,7 +33,7 @@ namespace xrpl { [[nodiscard]] TER canApplyToBrokerCover( ReadView const& view, - SLE::const_ref sleBroker, + LoanBrokerEntry const& sleBroker, Asset const& vaultAsset, STAmount const& amount, beast::Journal j, @@ -1632,7 +1632,7 @@ constructLoanState( } LoanState -constructRoundedLoanState(SLE::const_ref loan) +constructRoundedLoanState(LoanEntry const& loan) { return constructLoanState( loan->at(sfTotalValueOutstanding), @@ -1784,8 +1784,8 @@ std::expected loanMakePayment( Asset const& asset, ApplyView& view, - SLE::ref loan, - SLE::const_ref brokerSle, + LoanEntry& loan, + LoanBrokerEntry const& brokerSle, STAmount const& amount, LoanPaymentType const paymentType, beast::Journal j) @@ -1836,7 +1836,7 @@ loanMakePayment( XRPL_ASSERT(*totalValueOutstandingProxy > 0, "xrpl::loanMakePayment : valid total value"); - view.update(loan); + loan.update(); // ------------------------------------------------------------- // A late payment not flagged as late overrides all other options. diff --git a/src/libxrpl/protocol/Indexes.cpp b/src/libxrpl/protocol/Indexes.cpp index 76ff868f9e..2b7c0c3a75 100644 --- a/src/libxrpl/protocol/Indexes.cpp +++ b/src/libxrpl/protocol/Indexes.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,23 @@ namespace xrpl { +// This list should include all of the keylet functions that take a single +// AccountID parameter. Declared in Indexes.h; defined here so the header need +// not include jss.h. +std::array, 6> const kDirectAccountKeylets{ + {{.function = &keylet::account, .expectedLEName = jss::AccountRoot, .includeInTests = false}, + {.function = &keylet::ownerDir, .expectedLEName = jss::DirectoryNode, .includeInTests = true}, + {.function = &keylet::signerList, .expectedLEName = jss::SignerList, .includeInTests = true}, + // It's normally impossible to create an item at nftpage_min, but + // test it anyway, since the invariant checks for it. + {.function = &keylet::nftokenPageMin, + .expectedLEName = jss::NFTokenPage, + .includeInTests = true}, + {.function = &keylet::nftokenPageMax, + .expectedLEName = jss::NFTokenPage, + .includeInTests = true}, + {.function = &keylet::did, .expectedLEName = jss::DID, .includeInTests = true}}}; + /** Type-specific prefix for calculating ledger indices. The identifier for a given object within the ledger is calculated based diff --git a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverClawback.cpp b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverClawback.cpp index 9bb84e878e..0d3e0d72d0 100644 --- a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverClawback.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverClawback.cpp @@ -161,7 +161,7 @@ determineClawAmount( SLE const& sleBroker, Asset const& vaultAsset, std::optional const& amount, - SLE::const_ref vaultSle, + VaultEntry const& vaultSle, Rules const& rules) { auto const maxClawAmount = [&]() { @@ -293,8 +293,8 @@ LoanBrokerCoverClawback::preclaim(PreclaimContext const& ctx) } } - auto const findClawAmount = - determineClawAmount(*sleBroker, vaultAsset, amount, vault, ctx.view.rules()); + auto const findClawAmount = determineClawAmount( + *sleBroker, vaultAsset, amount, VaultEntry{vault, ctx.view}, ctx.view.rules()); if (!findClawAmount) { JLOG(ctx.j.warn()) << "LoanBroker cover is already at minimum."; @@ -303,7 +303,12 @@ LoanBrokerCoverClawback::preclaim(PreclaimContext const& ctx) STAmount const& clawAmount = *findClawAmount; if (auto const ret = canApplyToBrokerCover( - ctx.view, sleBroker, vaultAsset, clawAmount, ctx.j, "LoanBrokerCoverClawback")) + ctx.view, + LoanBrokerEntry{sleBroker, ctx.view}, + vaultAsset, + clawAmount, + ctx.j, + "LoanBrokerCoverClawback")) return ret; // Explicitly check the balance of the trust line / MPT to make sure the @@ -356,8 +361,8 @@ LoanBrokerCoverClawback::doApply() auto const vaultAsset = vault->at(sfAsset); - auto const findClawAmount = - determineClawAmount(*sleBroker, vaultAsset, amount, vault, view().rules()); + auto const findClawAmount = determineClawAmount( + *sleBroker, vaultAsset, amount, VaultEntry{vault, view()}, view().rules()); if (!findClawAmount) return tecINTERNAL; // LCOV_EXCL_LINE STAmount const& clawAmount = *findClawAmount; diff --git a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverWithdraw.cpp b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverWithdraw.cpp index 008857a4ad..9d35564218 100644 --- a/src/libxrpl/tx/transactors/lending/LoanBrokerCoverWithdraw.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanBrokerCoverWithdraw.cpp @@ -96,7 +96,12 @@ LoanBrokerCoverWithdraw::preclaim(PreclaimContext const& ctx) // Helper handles both IOU and MPT correctly without explicit branching. if (auto const ret = canApplyToBrokerCover( - ctx.view, sleBroker, vaultAsset, amount, ctx.j, "LoanBrokerCoverWithdraw")) + ctx.view, + LoanBrokerEntry{sleBroker, ctx.view}, + vaultAsset, + amount, + ctx.j, + "LoanBrokerCoverWithdraw")) return ret; // The broker's pseudo-account is the source of funds. @@ -152,7 +157,9 @@ LoanBrokerCoverWithdraw::preclaim(PreclaimContext const& ctx) if (fix320Enabled) { return minimumBrokerCover( - currentDebtTotal, TenthBips32{sleBroker->at(sfCoverRateMinimum)}, vault); + currentDebtTotal, + TenthBips32{sleBroker->at(sfCoverRateMinimum)}, + VaultEntry{vault, ctx.view}); } // Always round the minimum required up. diff --git a/src/libxrpl/tx/transactors/lending/LoanBrokerDelete.cpp b/src/libxrpl/tx/transactors/lending/LoanBrokerDelete.cpp index 141cc2cf56..3b579d38ca 100644 --- a/src/libxrpl/tx/transactors/lending/LoanBrokerDelete.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanBrokerDelete.cpp @@ -78,7 +78,7 @@ LoanBrokerDelete::preclaim(PreclaimContext const& ctx) { // Any remaining debt should have been wiped out by the last Loan // Delete. This check is purely defensive. - auto const scale = getAssetsTotalScale(vault); + auto const scale = getAssetsTotalScale(VaultEntry{vault, ctx.view}); auto const rounded = roundToAsset(asset, debtTotal, scale, Number::RoundingMode::TowardsZero); diff --git a/src/libxrpl/tx/transactors/lending/LoanDelete.cpp b/src/libxrpl/tx/transactors/lending/LoanDelete.cpp index 3459119379..441db5417d 100644 --- a/src/libxrpl/tx/transactors/lending/LoanDelete.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanDelete.cpp @@ -121,7 +121,7 @@ LoanDelete::doApply() roundToAsset( vaultSle->at(sfAsset), debtTotalProxy, - getAssetsTotalScale(vaultSle), + getAssetsTotalScale(VaultEntry{vaultSle, view}), Number::RoundingMode::TowardsZero) == beast::kZero, "xrpl::LoanDelete::doApply", "last loan, remaining debt rounds to zero"); diff --git a/src/libxrpl/tx/transactors/lending/LoanManage.cpp b/src/libxrpl/tx/transactors/lending/LoanManage.cpp index 830eb30272..97f1a9faaf 100644 --- a/src/libxrpl/tx/transactors/lending/LoanManage.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanManage.cpp @@ -128,7 +128,7 @@ LoanManage::preclaim(PreclaimContext const& ctx) } static Number -owedToVault(SLE::ref loanSle) +owedToVault(LoanEntry const& loanSle) { // Spec section 3.2.3.2, defines the default amount as // @@ -147,9 +147,9 @@ owedToVault(SLE::ref loanSle) TER LoanManage::defaultLoan( ApplyView& view, - SLE::ref loanSle, - SLE::ref brokerSle, - SLE::ref vaultSle, + LoanEntry& loanSle, + LoanBrokerEntry& brokerSle, + VaultEntry& vaultSle, Asset const& vaultAsset, beast::Journal j) { @@ -251,7 +251,7 @@ LoanManage::defaultLoan( adjustImpreciseNumber( vaultLossUnrealizedProxy, -totalDefaultAmount, vaultAsset, vaultScale); } - view.update(vaultSle); + vaultSle.update(); } // Update the LoanBroker object: @@ -269,7 +269,7 @@ LoanManage::defaultLoan( // LCOV_EXCL_STOP } coverAvailableProxy -= defaultCovered; - view.update(brokerSle); + brokerSle.update(); } // Update the Loan object: @@ -282,7 +282,7 @@ LoanManage::defaultLoan( // Zero out the next due date. Since it's default, it'll be removed from // the object. loanSle->at(sfNextPaymentDueDate) = 0; - view.update(loanSle); + loanSle.update(); // Return funds from the LoanBroker pseudo-account to the // Vault pseudo-account: @@ -298,8 +298,8 @@ LoanManage::defaultLoan( TER LoanManage::impairLoan( ApplyView& view, - SLE::ref loanSle, - SLE::ref vaultSle, + LoanEntry& loanSle, + VaultEntry& vaultSle, Asset const& vaultAsset, beast::Journal j) { @@ -321,7 +321,7 @@ LoanManage::impairLoan( "corrupt the vault."; return tecLIMIT_EXCEEDED; } - view.update(vaultSle); + vaultSle.update(); // Update the Loan object loanSle->setFlag(lsfLoanImpaired); @@ -332,7 +332,7 @@ LoanManage::impairLoan( // move the next payment due date to now loanNextDueProxy = view.parentCloseTime().time_since_epoch().count(); } - view.update(loanSle); + loanSle.update(); return tesSUCCESS; } @@ -340,8 +340,8 @@ LoanManage::impairLoan( [[nodiscard]] TER LoanManage::unimpairLoan( ApplyView& view, - SLE::ref loanSle, - SLE::ref vaultSle, + LoanEntry& loanSle, + VaultEntry& vaultSle, Asset const& vaultAsset, beast::Journal j) { @@ -363,7 +363,7 @@ LoanManage::unimpairLoan( // Reverse the "paper loss" adjustImpreciseNumber(vaultLossUnrealizedProxy, -lossReversed, vaultAsset, vaultScale); - view.update(vaultSle); + vaultSle.update(); // Update the Loan object loanSle->clearFlag(lsfLoanImpaired); @@ -381,7 +381,7 @@ LoanManage::unimpairLoan( loanSle->at(sfNextPaymentDueDate) = view.parentCloseTime().time_since_epoch().count() + paymentInterval; } - view.update(loanSle); + loanSle.update(); return tesSUCCESS; } @@ -393,16 +393,16 @@ LoanManage::doApply() auto& view = ctx_.view(); auto const loanID = tx[sfLoanID]; - auto const loanSle = view.peek(keylet::loan(loanID)); + LoanEntry loanSle{keylet::loan(loanID), view}; if (!loanSle) return tefBAD_LEDGER; // LCOV_EXCL_LINE auto const brokerID = loanSle->at(sfLoanBrokerID); - auto const brokerSle = view.peek(keylet::loanBroker(brokerID)); + LoanBrokerEntry brokerSle{keylet::loanBroker(brokerID), view}; if (!brokerSle) return tefBAD_LEDGER; // LCOV_EXCL_LINE - auto const vaultSle = view.peek(keylet::vault(brokerSle->at(sfVaultID))); + VaultEntry vaultSle{keylet::vault(brokerSle->at(sfVaultID)), view}; if (!vaultSle) return tefBAD_LEDGER; // LCOV_EXCL_LINE auto const vaultAsset = vaultSle->at(sfAsset); diff --git a/src/libxrpl/tx/transactors/lending/LoanPay.cpp b/src/libxrpl/tx/transactors/lending/LoanPay.cpp index fcda2a9fff..6832b60237 100644 --- a/src/libxrpl/tx/transactors/lending/LoanPay.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanPay.cpp @@ -287,19 +287,19 @@ LoanPay::doApply() auto const amount = tx[sfAmount]; auto const loanID = tx[sfLoanID]; - auto const loanSle = view.peek(keylet::loan(loanID)); + LoanEntry loanSle{keylet::loan(loanID), view}; if (!loanSle) return tefBAD_LEDGER; // LCOV_EXCL_LINE std::int32_t const loanScale = loanSle->at(sfLoanScale); auto const brokerID = loanSle->at(sfLoanBrokerID); - auto const brokerSle = view.peek(keylet::loanBroker(brokerID)); + LoanBrokerEntry brokerSle{keylet::loanBroker(brokerID), view}; if (!brokerSle) return tefBAD_LEDGER; // LCOV_EXCL_LINE auto const brokerOwner = brokerSle->at(sfOwner); auto const brokerPseudoAccount = brokerSle->at(sfAccount); auto const vaultID = brokerSle->at(sfVaultID); - auto const vaultSle = view.peek(keylet::vault(vaultID)); + VaultEntry vaultSle{keylet::vault(vaultID), view}; if (!vaultSle) return tefBAD_LEDGER; // LCOV_EXCL_LINE auto const vaultPseudoAccount = vaultSle->at(sfAccount); @@ -392,7 +392,7 @@ LoanPay::doApply() // If the payment computation completed without error, the loanSle object // has been modified. - view.update(loanSle); + loanSle.update(); XRPL_ASSERT_PARTS( // It is possible to pay 0 principal @@ -427,7 +427,7 @@ LoanPay::doApply() //------------------------------------------------------ // LoanBroker object state changes - view.update(brokerSle); + brokerSle.update(); auto assetsAvailableProxy = vaultSle->at(sfAssetsAvailable); auto assetsTotalProxy = vaultSle->at(sfAssetsTotal); @@ -468,7 +468,7 @@ LoanPay::doApply() //------------------------------------------------------ // Vault object state changes - view.update(vaultSle); + vaultSle.update(); Number const assetsAvailableBefore = *assetsAvailableProxy; Number const assetsTotalBefore = *assetsTotalProxy; diff --git a/src/libxrpl/tx/transactors/lending/LoanSet.cpp b/src/libxrpl/tx/transactors/lending/LoanSet.cpp index 1ac387d1b1..6cc2d9683e 100644 --- a/src/libxrpl/tx/transactors/lending/LoanSet.cpp +++ b/src/libxrpl/tx/transactors/lending/LoanSet.cpp @@ -381,7 +381,7 @@ LoanSet::doApply() if (!brokerOwnerSle) return tefBAD_LEDGER; // LCOV_EXCL_LINE - auto const vaultSle = view.peek(keylet ::vault(brokerSle->at(sfVaultID))); + VaultEntry vaultSle{keylet::vault(brokerSle->at(sfVaultID)), view}; if (!vaultSle) return tefBAD_LEDGER; // LCOV_EXCL_LINE auto const vaultPseudo = vaultSle->at(sfAccount); @@ -627,7 +627,7 @@ LoanSet::doApply() *vaultAvailableProxy <= *vaultTotalProxy, "xrpl::LoanSet::doApply", "assets available must not be greater than assets outstanding"); - view.update(vaultSle); + vaultSle.update(); // Update the balances in the loan broker adjustImpreciseNumber(brokerSle->at(sfDebtTotal), newDebtDelta, vaultAsset, vaultScale); diff --git a/src/test/app/LoanBroker_test.cpp b/src/test/app/LoanBroker_test.cpp index 2a4de18a9c..ded4638e09 100644 --- a/src/test/app/LoanBroker_test.cpp +++ b/src/test/app/LoanBroker_test.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -139,9 +140,9 @@ class LoanBroker_test : public beast::unit_test::Suite VaultInfo const& vault, VaultInfo const& badVault, std::function modifyJTx, - std::function checkBroker, - std::function changeBroker, - std::function checkChangedBroker) + std::function const&)> checkBroker, + std::function const&)> changeBroker, + std::function const&)> checkChangedBroker) { { auto const& asset = vault.asset.raw(); @@ -219,7 +220,7 @@ class LoanBroker_test : public beast::unit_test::Suite BEAST_EXPECT(broker->at(sfDebtTotal) == 0); BEAST_EXPECT(broker->at(sfCoverAvailable) == 0); if (checkBroker) - checkBroker(broker); + checkBroker(LoanBrokerEntry{broker, *env.current()}); // if (auto const vaultSLE = env.le(keylet::vault(vault.vaultID))) //{ @@ -469,14 +470,14 @@ class LoanBroker_test : public beast::unit_test::Suite // Make modifications to the broker if (changeBroker) - changeBroker(broker); + changeBroker(LoanBrokerEntry{broker, *env.current()}); env.close(); // Check the results of modifications broker = env.le(keylet); if (BEAST_EXPECT(broker) && checkChangedBroker) - checkChangedBroker(broker); + checkChangedBroker(LoanBrokerEntry{broker, *env.current()}); // Verify that fields get removed when set to default values // Debt maximum: explicit 0 @@ -722,7 +723,7 @@ class LoanBroker_test : public beast::unit_test::Suite badVault, // No modifications {}, - [&](SLE::const_ref broker) { + [&](LoanBrokerEntry const& broker) { // Extra checks BEAST_EXPECT(!broker->isFieldPresent(sfManagementFeeRate)); BEAST_EXPECT(!broker->isFieldPresent(sfCoverRateMinimum)); @@ -735,7 +736,7 @@ class LoanBroker_test : public beast::unit_test::Suite BEAST_EXPECT(env.ownerCount(alice) == aliceOriginalCount + 4); }, - [&](SLE::const_ref broker) { + [&](LoanBrokerEntry const& broker) { // Modifications // Update the fields @@ -795,7 +796,7 @@ class LoanBroker_test : public beast::unit_test::Suite kData(testData), kDebtMaximum(debtMax)); }, - [&](SLE::const_ref broker) { + [&](LoanBrokerEntry const& broker) { // Check the updated fields BEAST_EXPECT(checkVL(broker->at(sfData), testData)); Number const expected = STAmount{vault.asset, Number(175, -1)}; @@ -826,7 +827,7 @@ class LoanBroker_test : public beast::unit_test::Suite kCoverRateMinimum(TenthBips32(100)), kCoverRateLiquidation(TenthBips32(200))); }, - [&](SLE::const_ref broker) { + [&](LoanBrokerEntry const& broker) { // Extra checks BEAST_EXPECT(broker->at(sfManagementFeeRate) == 123); BEAST_EXPECT(broker->at(sfCoverRateMinimum) == 100); @@ -834,14 +835,14 @@ class LoanBroker_test : public beast::unit_test::Suite BEAST_EXPECT(broker->at(sfDebtMaximum) == Number(9)); BEAST_EXPECT(checkVL(broker->at(sfData), testData)); }, - [&](SLE::const_ref broker) { + [&](LoanBrokerEntry const& broker) { // Reset Data & Debt maximum to default values env(set(alice, vault.vaultID), kLoanBrokerId(broker->key()), kData(""), kDebtMaximum(Number(0))); }, - [&](SLE::const_ref broker) { + [&](LoanBrokerEntry const& broker) { // Check the updated fields BEAST_EXPECT(!broker->isFieldPresent(sfData)); BEAST_EXPECT(!broker->isFieldPresent(sfDebtMaximum)); diff --git a/src/test/app/Loan_test.cpp b/src/test/app/Loan_test.cpp index 3e62af48ff..cdb75862a9 100644 --- a/src/test/app/Loan_test.cpp +++ b/src/test/app/Loan_test.cpp @@ -211,7 +211,7 @@ protected: using namespace jtx; auto const vaultSle = env.le(keylet::vault(vaultID)); - return getAssetsTotalScale(vaultSle); + return getAssetsTotalScale(VaultEntry{vaultSle, *env.current()}); } }; @@ -440,7 +440,8 @@ protected: env.test.BEAST_EXPECT(loan->at(sfPeriodicPayment) == periodicPayment); env.test.BEAST_EXPECT(loan->at(sfFlags) == flags); - auto const ls = constructRoundedLoanState(loan); + auto const ls = + constructRoundedLoanState(LoanEntry{loan, *env.current()}); auto const interestRate = TenthBips32{loan->at(sfInterestRate)}; auto const paymentInterval = loan->at(sfPaymentInterval); @@ -1108,7 +1109,8 @@ protected: // No reason for this not to exist return; } - auto const current = constructRoundedLoanState(loanSle); + auto const current = + constructRoundedLoanState(LoanEntry{loanSle, *env.current()}); auto const errors = nextTrueState - current; log << currencyLabel << " Loan balances: " << "\n\tAmount taken: " << paymentComponents.trackedValueDelta @@ -6033,7 +6035,8 @@ protected: auto const loanSle = env.le(loanKeylet); if (!BEAST_EXPECT(loanSle)) return; - auto const state = constructRoundedLoanState(loanSle); + auto const state = + constructRoundedLoanState(LoanEntry{loanSle, *env.current()}); log << "Loan state:" << std::endl; log << " ValueOutstanding: " << state.valueOutstanding << std::endl; @@ -8257,7 +8260,8 @@ protected: return std::nullopt; if (!BEAST_EXPECT(tinyLoanSle->at(sfLoanScale) == -12) || !BEAST_EXPECT(bigLoanSle->at(sfLoanScale) == -11) || - !BEAST_EXPECT(getAssetsTotalScale(vaultSle) == -11)) + !BEAST_EXPECT( + getAssetsTotalScale(VaultEntry{vaultSle, *env.current()}) == -11)) return std::nullopt; // Use issuer clawback to reduce cover to the minimum the @@ -8384,7 +8388,8 @@ protected: auto const coverAvail = brokerSle->at(sfCoverAvailable); auto const debtTotal = brokerSle->at(sfDebtTotal); - auto const vaultScale = getAssetsTotalScale(vaultSle); + auto const vaultScale = + getAssetsTotalScale(VaultEntry{vaultSle, *env.current()}); auto const debtScale = scale(debtTotal, asset); // Sanity: debt scale differs from vault scale for this setup. @@ -8398,7 +8403,9 @@ protected: debtScale); }(); auto const newMin = minimumBrokerCover( - debtTotal, TenthBips32{c.brokerParams.coverRateMin}, vaultSle); + debtTotal, + TenthBips32{c.brokerParams.coverRateMin}, + VaultEntry{vaultSle, *env.current()}); // The new (vaultScale) minimum must be strictly larger than // the old (debtScale) minimum — that is the gap the amendment @@ -8482,7 +8489,8 @@ protected: auto const vaultSle = env.le(keylet::vault(c.broker.vaultID)); if (!BEAST_EXPECT(vaultSle)) return; - auto const vaultScale = getAssetsTotalScale(vaultSle); + auto const vaultScale = + getAssetsTotalScale(VaultEntry{vaultSle, *env.current()}); BEAST_EXPECT(vaultScale == -11); // Now try to create a tiny additional loan. Principal is