From d4cb62e78da80d8dae1f3f44ed45fff8e10eeea4 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Mon, 13 Jul 2026 13:27:41 -0400 Subject: [PATCH] clean up OracleEntry --- include/xrpl/ledger/helpers/OracleHelpers.h | 32 ++++++++++ include/xrpl/ledger/helpers/SLEWrappers.h | 61 ++++++------------- .../tx/transactors/oracle/OracleDelete.cpp | 16 +++-- .../tx/transactors/oracle/OracleSet.cpp | 8 +-- 4 files changed, 62 insertions(+), 55 deletions(-) diff --git a/include/xrpl/ledger/helpers/OracleHelpers.h b/include/xrpl/ledger/helpers/OracleHelpers.h index da04618e46..98defa4bba 100644 --- a/include/xrpl/ledger/helpers/OracleHelpers.h +++ b/include/xrpl/ledger/helpers/OracleHelpers.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include // IWYU pragma: keep #include @@ -28,4 +29,35 @@ calculateOracleReserve(SLE::const_ref oracleSle) return calculateOracleReserve(oracleSle->getFieldArray(sfPriceDataSeries)); } +template +class OracleEntry : public SLEBase +{ +public: + // 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, + beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) + : SLEBase(keylet::oracle(account, documentID), view, j) + { + } + + [[nodiscard]] SField const& + ownerField() const override + { + return sfOwner; + } + + // An Oracle with more than five price-data pairs occupies two reserve slots. + [[nodiscard]] std::uint32_t + reserveCount() const override + { + return calculateOracleReserve(this->sle()->getFieldArray(sfPriceDataSeries)); + } +}; + } // namespace xrpl diff --git a/include/xrpl/ledger/helpers/SLEWrappers.h b/include/xrpl/ledger/helpers/SLEWrappers.h index c6c41405b1..f52d4adec4 100644 --- a/include/xrpl/ledger/helpers/SLEWrappers.h +++ b/include/xrpl/ledger/helpers/SLEWrappers.h @@ -39,7 +39,8 @@ public: { } - /** Create an NFToken offer. + /** + * Create an NFToken offer. * * An NFToken offer lives in its owner's directory (sfOwnerNode) and in the * NFToken's buy or sell offer directory (sfNFTokenOfferNode), the latter @@ -97,8 +98,10 @@ public: return tesSUCCESS; } - /** Remove an NFToken offer from the ledger (inverse of create()). Mirrors - * the former deleteTokenOffer() helper. */ + /** + * Remove an NFToken offer from the ledger (inverse of create()). Mirrors + * the former deleteTokenOffer() helper. + */ [[nodiscard]] TER destroy() requires SLEBase::kIsWritable @@ -362,7 +365,8 @@ public: { } - /** Remove an offer from the ledger. + /** + * Remove an offer from the ledger. * * An offer lives in its owner's directory (sfOwnerNode) and in one or more * order-book page directories (sfBookDirectory/sfBookNode, plus the @@ -480,7 +484,8 @@ public: { } - /** Remove a trust line from the ledger. + /** + * Remove a trust line from the ledger. * * A trust line sits in both endpoints' directories (sfLowNode/sfHighNode, * not sfOwnerNode) and, unlike single-owner entries, does not adjust @@ -645,7 +650,8 @@ public: return {{this->sle()->getAccountID(sfAccount), &sfOwnerNode, /*countsToward=*/false}}; } - /** Remove the AMM object from its pseudo-account's directory. + /** + * Remove the AMM object from its pseudo-account's directory. * * Unlike the default destroy(), this also collapses the pseudo-account's * now-empty owner directory root and reports tecINTERNAL on failure. The @@ -719,7 +725,8 @@ public: return sfAccount; } - /** Create an MPToken for its holder. + /** + * Create an MPToken for its holder. * * Like a trust line, an MPToken is free of reserve until the holder owns * two or more objects — but a reserve sponsor on the transaction must @@ -759,37 +766,6 @@ public: } }; -template -class OracleEntry : public SLEBase -{ -public: - // 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, - beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) - : SLEBase(keylet::oracle(account, documentID), view, j) - { - } - - [[nodiscard]] SField const& - ownerField() const override - { - return sfOwner; - } - - // An Oracle with more than five price-data pairs occupies two reserve slots. - [[nodiscard]] std::uint32_t - reserveCount() const override - { - return this->sle()->getFieldArray(sfPriceDataSeries).size() > 5 ? 2 : 1; - } -}; - template class CredentialEntry : public SLEBase { @@ -973,7 +949,8 @@ public: { } - /** Materialize the loan and link it into both directories it lives in: its + /** + * Materialize the loan and link it into both directories it lives in: its * LoanBroker's pseudo-account directory (sfLoanBrokerNode) and its * borrower's directory (sfOwnerNode). * @@ -996,9 +973,11 @@ public: return this->linkOwnerDirs(dirs); } - /** Unlink the loan from both directories and erase it (inverse of the + /** + * Unlink the loan from both directories and erase it (inverse of the * directory work in create()). OwnerCount decrements on the borrower and - * LoanBroker object are handled by the transactor. Mirrors LoanDelete. */ + * LoanBroker object are handled by the transactor. Mirrors LoanDelete. + */ [[nodiscard]] TER destroy() requires SLEBase::kIsWritable diff --git a/src/libxrpl/tx/transactors/oracle/OracleDelete.cpp b/src/libxrpl/tx/transactors/oracle/OracleDelete.cpp index 03c4e20ceb..51f98173d5 100644 --- a/src/libxrpl/tx/transactors/oracle/OracleDelete.cpp +++ b/src/libxrpl/tx/transactors/oracle/OracleDelete.cpp @@ -28,12 +28,10 @@ OracleDelete::preflight(PreflightContext const& ctx) TER OracleDelete::preclaim(PreclaimContext const& ctx) { - if (!ctx.view.exists(keylet::account(ctx.tx.getAccountID(sfAccount)))) - return terNO_ACCOUNT; // LCOV_EXCL_LINE + auto const sle = OracleEntry{ + ctx.tx.getAccountID(sfAccount), ctx.tx[sfOracleDocumentID], ctx.view, ctx.j}; - auto const sle = - ctx.view.read(keylet::oracle(ctx.tx.getAccountID(sfAccount), ctx.tx[sfOracleDocumentID])); - if (!sle) + if (!sle.exists()) { JLOG(ctx.j.debug()) << "Oracle Delete: Oracle does not exist."; return tecNO_ENTRY; @@ -70,11 +68,11 @@ OracleDelete::deleteOracle( TER OracleDelete::doApply() { - if (OracleEntry sle{ - keylet::oracle(accountID_, ctx_.tx[sfOracleDocumentID]), ctx_.view()}) - return deleteOracle(ctx_.view(), sle.mutableSle(), accountID_, j_); + auto const sle = OracleEntry{accountID_, ctx_.tx[sfOracleDocumentID], ctx_.view()}; + if (!sle.exists()) + return tecINTERNAL; // LCOV_EXCL_LINE - return tecINTERNAL; // LCOV_EXCL_LINE + return deleteOracle(ctx_.view(), sle.mutableSle(), accountID_, j_); } void diff --git a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp index cb137f31d0..6f3d098727 100644 --- a/src/libxrpl/tx/transactors/oracle/OracleSet.cpp +++ b/src/libxrpl/tx/transactors/oracle/OracleSet.cpp @@ -85,7 +85,7 @@ OracleSet::preclaim(PreclaimContext const& ctx) return tecINVALID_UPDATE_TIME; OracleEntry sle{ - keylet::oracle(ctx.tx.getAccountID(sfAccount), ctx.tx[sfOracleDocumentID]), ctx.view}; + ctx.tx.getAccountID(sfAccount), ctx.tx[sfOracleDocumentID], ctx.view, ctx.j}; // token pairs to add/update std::set> pairs; @@ -154,7 +154,7 @@ OracleSet::preclaim(PreclaimContext const& ctx) if (!pairsDel.empty()) return tecTOKEN_PAIR_NOT_FOUND; - auto const oldCount = calculateOracleReserve(sle.sle()); + auto const oldCount = sle.reserveCount(); auto const newCount = calculateOracleReserve(pairs); adjustReserve = newCount - oldCount; @@ -217,8 +217,6 @@ setPriceDataInnerObjTemplate(STObject& obj) TER OracleSet::doApply() { - auto const oracleID = keylet::oracle(accountID_, ctx_.tx[sfOracleDocumentID]); - auto populatePriceData = [](STObject& priceData, STObject const& entry) { setPriceDataInnerObjTemplate(priceData); priceData.setFieldCurrency(sfBaseAsset, entry.getFieldCurrency(sfBaseAsset)); @@ -228,7 +226,7 @@ OracleSet::doApply() priceData.setFieldU8(sfScale, entry.getFieldU8(sfScale)); }; - OracleEntry sle{oracleID, ctx_.view()}; + OracleEntry sle{accountID_, ctx_.tx[sfOracleDocumentID], ctx_.view()}; if (sle) { // update