clean up OracleEntry

This commit is contained in:
Mayukha Vadari
2026-07-13 13:27:41 -04:00
parent cb2ab92927
commit d4cb62e78d
4 changed files with 62 additions and 55 deletions

View File

@@ -1,5 +1,6 @@
#pragma once
#include <xrpl/ledger/helpers/SLEBase.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STArray.h> // IWYU pragma: keep
#include <xrpl/protocol/STLedgerEntry.h>
@@ -28,4 +29,35 @@ calculateOracleReserve(SLE::const_ref oracleSle)
return calculateOracleReserve(oracleSle->getFieldArray(sfPriceDataSeries));
}
template <typename ViewT>
class OracleEntry : public SLEBase<ViewT>
{
public:
// Inherit base constructors: adopt an existing SLE, or resolve one from a
// Keylet against the view.
using SLEBase<ViewT>::SLEBase;
explicit OracleEntry(
AccountID const& account,
std::uint32_t documentID,
typename SLEBase<ViewT>::view_ref_type view,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
: SLEBase<ViewT>(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

View File

@@ -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<ViewT>::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 <typename ViewT>
class OracleEntry : public SLEBase<ViewT>
{
public:
// Inherit base constructors: adopt an existing SLE, or resolve one from a
// Keylet against the view.
using SLEBase<ViewT>::SLEBase;
explicit OracleEntry(
AccountID const& account,
std::uint32_t documentID,
typename SLEBase<ViewT>::view_ref_type view,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
: SLEBase<ViewT>(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 <typename ViewT>
class CredentialEntry : public SLEBase<ViewT>
{
@@ -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<ViewT>::kIsWritable

View File

@@ -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<ReadView>{
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<ApplyView> sle{
keylet::oracle(accountID_, ctx_.tx[sfOracleDocumentID]), ctx_.view()})
return deleteOracle(ctx_.view(), sle.mutableSle(), accountID_, j_);
auto const sle = OracleEntry<ApplyView>{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

View File

@@ -85,7 +85,7 @@ OracleSet::preclaim(PreclaimContext const& ctx)
return tecINVALID_UPDATE_TIME;
OracleEntry<ReadView> 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<std::pair<Currency, Currency>> 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<ApplyView> sle{oracleID, ctx_.view()};
OracleEntry<ApplyView> sle{accountID_, ctx_.tx[sfOracleDocumentID], ctx_.view()};
if (sle)
{
// update