Compare commits

...
Author SHA1 Message Date
Mayukha Vadari 16389dcb2e refactor: Move decreaseOwnerCount onto AccountRootEntry
Replace the entry-taking decreaseOwnerCount free function with a
writable member of AccountRootEntry, and drop the temporary friend
declaration from the previous change. The member uses the entry's view
and journal, so call sites pass their journal to the entry constructor.
The AccountID-based overload stays as a shim.
2026-10-05 15:46:48 +01:00
Mayukha Vadari 97a780b29f refactor: Move increaseOwnerCount onto AccountRootEntry
Replace both entry-taking increaseOwnerCount free functions with
writable members of AccountRootEntry. The members use the entry's view
and journal, so call sites pass their journal to the entry constructor.
The AccountID-based overload stays as a shim.

adjustOwnerCountSigned becomes a private member. decreaseOwnerCount is
a temporary friend so it can still call it until it moves too.
adjustOwnerCountImpl moves to namespace detail, because
adjustLoanBrokerOwnerCount also uses it.
2026-10-05 15:46:44 +01:00
Mayukha Vadari 654edc9a08 refactor: Move checkReserve onto AccountRootEntry
Replace both entry-taking checkReserve free functions with const members
of AccountRootEntry. The members keep the ApplyViewContext parameter,
because the check needs the transaction, and drop the journal parameter:
call sites pass their journal to the entry constructor instead.
2026-10-05 15:46:39 +01:00
Mayukha Vadari 658d04f694 Document confineOwnerCount parameters 2026-10-05 15:46:31 +01:00
Mayukha Vadari 93498952b1 refactor: Move ownerCount onto AccountRootEntry
Replace the entry-taking ownerCount(sle, j, adj) free function with the
const member AccountRootEntry::ownerCount(adj). The member uses the
entry's journal, so call sites pass their journal to the entry
constructor.

confineOwnerCount moves from the anonymous namespace to namespace
detail, because both the member and the owner-count helpers use it.
2026-10-05 15:45:43 +01:00
Mayukha Vadari 269f79e568 Include Keylet.h in the SLEBase test
(cherry picked from commit 3cca9d3266)
2026-10-05 15:45:38 +01:00
Mayukha Vadari e7a8e0336a test: Drop extern template declarations from SLEBase test
An explicit instantiation declaration stops clang from emitting the
inline constructors of the header-only entries at -O0, so the debug
builds fail to link xrpl_tests (undefined AccountRootEntry constructors).
Naming each class in a static_assert already instantiates its definition,
which is all the exhaustiveness check needs.

(cherry picked from commit 611415e1f9)
2026-10-05 15:45:38 +01:00
Mayukha Vadari 1d7e40777a refactor: Move accountReserve onto AccountRootEntry
Replace the entry-taking accountReserve(view, sle, j, adj) free function
with the const member AccountRootEntry::reserve(adj). The member uses the
entry's own view and journal, so call sites now pass their journal to the
entry constructor. The AccountID-based accountReserve overload stays as a
one-line shim.

Adjustment moves to AccountRootEntry.h, since the member takes it.
accountCountImpl moves from the anonymous namespace to namespace detail,
because both reserve() and xrpLiquid() use it.
2026-10-05 15:45:38 +01:00
Mayukha Vadari 7bb43a243b test: Declare, not define, entry instantiations in SLEBase test
The exhaustive per-entry-type check in the SLEBase gtest used explicit
instantiation definitions. Once an entry class gets out-of-line member
bodies in its own .cpp (with the explicit instantiation definition
there), the test would instantiate the class a second time, and MSVC
rejects it with C4661 because those member bodies are not visible in
the test translation unit. Explicit instantiation declarations still
instantiate the class definition, which is all the check needs.

(cherry picked from commit 8b07abc3cd)
2026-10-05 15:45:37 +01:00
Mayukha Vadari d697b7843c Document escrowDestNotAccountResult and isPseudoAccountSle parameters and return value 2026-10-05 15:45:24 +01:00
Mayukha Vadari 2de5140f20 Drop unused include from SponsorshipTransfer.cpp 2026-10-05 13:33:31 +01:00
Mayukha Vadari edf085a697 Declare canWithdraw with AccountRootEntryR in View.h 2026-10-05 13:33:31 +01:00
Mayukha Vadari c35ac1339b fix: Do not adopt the escrow SLE into an AccountRootEntry
Before fixCleanup3_2_0, EscrowCancel passes the escrow SLE to
escrowUnlockApplyHelper as sleDest. Wrapping it in AccountRootEntryR
fires the "adopted SLE matches bound entry type" assertion in Debug
builds (xrpl.app.EscrowToken "IOU Cancel DoApply").

When sleDest is not an AccountRoot, return what the old code returned
for it: the tx reserve sponsor's error if the escrow owner submitted
the tx, else tefINTERNAL from checkReserve's type check.

(cherry picked from commit 90bb3930be)
2026-10-05 13:33:31 +01:00
Mayukha Vadari dc1cfbc474 Drop unused include from AccountRootHelpers.h 2026-10-05 13:33:30 +01:00
Mayukha Vadari 3044073401 refactor: Use AccountRootEntry everywhere
Replace raw AccountRoot SLE pointers with the AccountRootEntryR and
AccountRootEntryW wrappers in src/libxrpl and src/xrpld/app.

- view.read(keylet::account(...)) becomes AccountRootEntryR and
  view.peek(keylet::account(...)) becomes AccountRootEntryW.
- AccountRoot helpers (accountReserve, checkReserve, ownerCount,
  increase/decreaseOwnerCount, isPseudoAccount,
  checkDestinationAndTag) and the sponsor helpers
  (getTxReserveSponsor, getEffectiveTxReserveSponsor,
  getLedgerEntryReserveSponsor) take or return the wrappers. A missing
  sponsor is std::nullopt instead of a null pointer.
- Generic functions that are not migrated yet (trustCreate, dirLink,
  addSponsorToLedgerEntry, ...) get rawSle() or mutableRawSle().
- Invariant checks cannot build a view-bound entry, so they use
  isPseudoAccountSle(), now declared in InvariantCheck.h.

This changes pointers only. No helper moves onto the wrapper. It is a
pure refactor with no behavior change and no amendment.
2026-10-05 13:33:30 +01:00
90 changed files with 1294 additions and 1095 deletions

No files matched your search

+2 -1
View File
@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Asset.h> #include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/Keylet.h> #include <xrpl/protocol/Keylet.h>
@@ -211,7 +212,7 @@ canWithdraw(
ReadView const& view, ReadView const& view,
AccountID const& from, AccountID const& from,
AccountID const& to, AccountID const& to,
SLE::ConstRef toSle, AccountRootEntryR const& toSle,
STAmount const& amount, STAmount const& amount,
bool hasDestinationTag, bool hasDestinationTag,
std::optional<std::vector<UInt256>> const& credentialIDs = std::nullopt); std::optional<std::vector<UInt256>> const& credentialIDs = std::nullopt);
@@ -7,9 +7,20 @@
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h> #include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/XRPAmount.h>
#include <cstdint>
#include <optional>
namespace xrpl { namespace xrpl {
struct Adjustment
{
std::int32_t ownerCountDelta = 0;
std::int32_t accountCountDelta = 0;
};
template <typename ViewT> template <typename ViewT>
class AccountRootEntry : public SLEBase<ViewT, ltACCOUNT_ROOT> class AccountRootEntry : public SLEBase<ViewT, ltACCOUNT_ROOT>
{ {
@@ -27,6 +38,123 @@ public:
: Base(keylet::account(id), view, j) : Base(keylet::account(id), view, j)
{ {
} }
/**
* Returns the account reserve, in drops.
*
* Actual owner count can be adjusted by delta in ownerCountAdj
* Actual reserve count can be adjusted by delta in accountCountAdj
* The reserve is calculated as:
* (ownerCount + "sponsoring object count" - "sponsored object count" + additionalOwnerCount) *
* increment + (1 if not sponsored account + sponsoringAccountCount) * "reserve base"
*
* @param adj Adjustment to the owner/account count (default: 0/0). Positive to add, negative
* to subtract.
* @return The account reserve amount in drops
*/
[[nodiscard]] XRPAmount
reserve(Adjustment adj = {}) const;
/**
* Return number of the objects which reserve is covered by the account (so called "owner
* count"). Actual owner count can be adjusted by delta in ownerCountAdj.
*
* @param ownerCountAdj Adjustment to the owner count (default: 0)
* @return The adjusted owner count
*/
[[nodiscard]] std::uint32_t
ownerCount(std::int32_t ownerCountAdj = 0) const;
/**
* Check if this account has sufficient reserve.
*
* @param ctx The apply-view context (view + tx)
* @param accBalance The account's balance
* @param sponsorSle The sponsor's ledger entry (if applicable)
* @param adj Adjustment to the owner/account count (default: 0/0). Positive to add, negative
* to subtract.
* @param insufReserveCode The transaction result code to return if the reserve is
* insufficient (default: tecINSUFFICIENT_RESERVE).
* @return Transaction result code
*/
[[nodiscard]] TER
checkReserve(
ApplyViewContext ctx,
XRPAmount accBalance,
std::optional<AccountRootEntry<ReadView>> const& sponsorSle,
Adjustment adj,
TER insufReserveCode = tecINSUFFICIENT_RESERVE) const;
/**
* Check if this account has sufficient reserve, deriving the sponsor internally.
*
* Equivalent to the overload above, but resolves the sponsor via
* getEffectiveTxReserveSponsor(ctx, *this) instead of taking it explicitly. Use this
* in the common case where the sponsor is simply the transaction's reserve
* sponsor for this account. Callers that must force the account's-own-reserve branch
* (passing a null sponsor) or supply a different sponsor should use the
* explicit overload above.
*
* @param ctx The apply-view context (view + tx)
* @param accBalance The account's balance
* @param adj Reserve adjustments (owner/account count deltas)
* @return Transaction result code
*/
[[nodiscard]] TER
checkReserve(ApplyViewContext ctx, XRPAmount accBalance, Adjustment adj) const;
/**
* Increase owner-count fields when the caller supplies the sponsor.
*
* This helper does not create a ledger object. It updates reserve accounting
* after the caller has created/updated an object.
* If sponsorSle is provided, this also adjusts the account's sponsored count
* and the sponsor's sponsoring count.
*
* @param sponsorSle The sponsor's ledger entry (if applicable)
* @param count Amount to add to the owner count
*/
void
increaseOwnerCount(std::optional<AccountRootEntry<ApplyView>>& sponsorSle, std::uint32_t count)
requires Base::kIsWritable;
/**
* Increase owner-count fields, deriving the tx reserve sponsor internally.
*
* Equivalent to the overload above, but resolves the sponsor via
* getEffectiveTxReserveSponsor(ctx, *this) instead of taking it explicitly. Use
* this when the sponsor is the transaction's reserve sponsor for this account
* (the common create path). Deletion paths, which derive the sponsor from an
* object's sfSponsor field, should keep using the explicit overload.
*
* @param ctx The apply-view context (view + tx)
* @param count Amount to add to the owner count
*/
void
increaseOwnerCount(ApplyViewContext ctx, std::uint32_t count)
requires Base::kIsWritable;
/**
* Decrease owner-count fields when the caller supplies the sponsor.
*
* This helper does not delete a ledger object. It updates reserve accounting
* after the caller has removed an owner-counted reserve, or for special
* owner-count changes whose sponsor cannot be derived from an object's
* sfSponsor field.
*
* @param sponsorSle The sponsor's ledger entry (if applicable)
* @param count Amount to remove from the owner count
*/
void
decreaseOwnerCount(std::optional<AccountRootEntry<ApplyView>>& sponsorSle, std::uint32_t count)
requires Base::kIsWritable;
private:
void
adjustOwnerCountSigned(
std::optional<AccountRootEntry<ApplyView>>& sponsorSle,
std::int32_t adjustment)
requires Base::kIsWritable;
}; };
using AccountRootEntryR = AccountRootEntry<ReadView>; using AccountRootEntryR = AccountRootEntry<ReadView>;
+60 -164
View File
@@ -4,8 +4,8 @@
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Rate.h> #include <xrpl/protocol/Rate.h>
#include <xrpl/protocol/SField.h> #include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h> #include <xrpl/protocol/STLedgerEntry.h>
@@ -46,30 +46,55 @@ isGlobalFrozen(ReadView const& view, AccountID const& issuer);
[[nodiscard]] XRPAmount [[nodiscard]] XRPAmount
xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j); xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j);
struct Adjustment namespace detail {
{
std::int32_t ownerCountDelta = 0;
std::int32_t accountCountDelta = 0;
};
/** /**
* Returns the account reserve, in drops. * An owner count cannot be negative. If adjustment would cause a negative
* owner count, clamp the owner count at 0. Similarly for overflow. This
* adjustment allows the ownerCount to be adjusted up or down in multiple steps.
* If id != std::nullopt, then do error reporting.
* *
* Actual owner count can be adjusted by delta in ownerCountAdj * Shared by AccountRootEntry::ownerCount() and the owner-count helpers.
* Actual reserve count can be adjusted by delta in accountCountAdj
* The reserve is calculated as:
* (ownerCount + "sponsoring object count" - "sponsored object count" + additionalOwnerCount) *
* increment + (1 if not sponsored account + sponsoringAccountCount) * "reserve base"
* *
* @param view The ledger view to read from * @param currentOwnerCount The owner count before adjustment
* @param sle The ledger entry for the account * @param ownerCountAdj Positive to add to count, negative to reduce count
* @param id The account ID to use for error reporting, or std::nullopt to
* skip error reporting
* @param j Journal for logging * @param j Journal for logging
* @param adj Adjustment to the owner/account count (default: 0/0). Positive to add, negative to * @return The adjusted owner count
* subtract.
* @return The account reserve amount in drops
*/ */
[[nodiscard]] XRPAmount std::uint32_t
accountReserve(ReadView const& view, SLE::ConstRef sle, beast::Journal j, Adjustment adj = {}); confineOwnerCount(
std::uint32_t currentOwnerCount,
std::int32_t ownerCountAdj,
std::optional<AccountID> const& id = std::nullopt,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()});
/**
* Clamps and writes an owner-count field of sle, then updates sle in view.
*
* Shared by AccountRootEntry and adjustLoanBrokerOwnerCount().
*
* @return The adjusted owner count
*/
std::uint32_t
adjustOwnerCountImpl(
ApplyView& view,
SLE::Ref sle,
SF_UINT32 const& sfield,
AccountID const& accID,
std::int32_t ownerCountAdj,
beast::Journal j);
/**
* Returns the number of account reserves funded by this account: 1 for itself
* (0 if sponsored by another account) plus the count of accounts it sponsors.
* Shared by AccountRootEntry::reserve() and xrpLiquid().
*/
std::uint32_t
accountCountImpl(AccountRootEntryR const& sle, std::int32_t accountCountAdj, beast::Journal j);
} // namespace detail
/** /**
* Convenience overload that accepts AccountID instead of SLE. * Convenience overload that accepts AccountID instead of SLE.
@@ -84,114 +109,9 @@ accountReserve(ReadView const& view, SLE::ConstRef sle, beast::Journal j, Adjust
[[nodiscard]] inline XRPAmount [[nodiscard]] inline XRPAmount
accountReserve(ReadView const& view, AccountID const& id, beast::Journal j, Adjustment adj = {}) accountReserve(ReadView const& view, AccountID const& id, beast::Journal j, Adjustment adj = {})
{ {
return accountReserve(view, view.read(keylet::account(id)), j, adj); return AccountRootEntryR(id, view, j).reserve(adj);
} }
/**
* Check if an account has sufficient reserve.
*
* @param view The ledger view to read from
* @param tx The transaction being processed
* @param accSle The account's ledger entry
* @param accBalance The account's balance
* @param sponsorSle The sponsor's ledger entry (if applicable)
* @param adj Adjustment to the owner/account count (default: 0/0). Positive to add, negative to
* subtract.
* @param j Journal for logging (default: null sink)
* @param insufReserveCode The transaction result code to return if the reserve is insufficient
* (default: tecINSUFFICIENT_RESERVE).
* @return Transaction result code
*/
[[nodiscard]] TER
checkReserve(
ApplyViewContext ctx,
SLE::ConstRef accSle,
XRPAmount accBalance,
SLE::ConstRef sponsorSle,
Adjustment adj,
beast::Journal j,
TER insufReserveCode = tecINSUFFICIENT_RESERVE);
/**
* Check if an account has sufficient reserve, deriving the sponsor internally.
*
* Equivalent to the overload above, but resolves the sponsor via
* getEffectiveTxReserveSponsor(ctx, accSle) instead of taking it explicitly. Use this
* in the common case where the sponsor is simply the transaction's reserve
* sponsor for accSle. Callers that must force the account's-own-reserve branch
* (passing a null sponsor) or supply a different sponsor should use the
* explicit overload above.
*
* @param ctx The apply-view context (view + tx)
* @param accSle The account's ledger entry
* @param accBalance The account's balance
* @param adj Reserve adjustments (owner/account count deltas)
* @param j Journal for logging (default: null sink)
* @return Transaction result code
*/
[[nodiscard]] TER
checkReserve(
ApplyViewContext ctx,
SLE::ConstRef accSle,
XRPAmount accBalance,
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
* count"). Actual owner count can be adjusted by delta in ownerCountAdj.
*
* @param sle The account's ledger entry
* @param j Journal for logging
* @param ownerCountAdj Adjustment to the owner count (default: 0)
* @return The adjusted owner count
*/
std::uint32_t
ownerCount(SLE::ConstRef sle, beast::Journal j, std::int32_t ownerCountAdj = 0);
/**
* Increase owner-count fields when the caller supplies the sponsor.
*
* This helper does not create a ledger object. It updates reserve accounting
* after the caller has created/updated an object.
* If sponsorSle is provided, this also adjusts the account's sponsored count
* and the sponsor's sponsoring count.
*
* @param view The apply view for making changes
* @param accountSle The account's ledger entry
* @param sponsorSle The sponsor's ledger entry (if applicable)
* @param count Amount to add to the owner count
* @param j Journal for logging
*/
void
increaseOwnerCount(
ApplyView& view,
SLE::Ref accountSle,
SLE::Ref sponsorSle,
std::uint32_t count,
beast::Journal j);
/**
* Increase owner-count fields, deriving the tx reserve sponsor internally.
*
* Equivalent to the overload above, but resolves the sponsor via
* getEffectiveTxReserveSponsor(ctx, accountSle) instead of taking it explicitly. Use
* this when the sponsor is the transaction's reserve sponsor for accountSle
* (the common create path). Deletion paths, which derive the sponsor from an
* object's sfSponsor field, should keep using the explicit overload.
*
* @param ctx The apply-view context (view + tx)
* @param accountSle The account's ledger entry
* @param count Amount to add to the owner count
* @param j Journal for logging
*/
void
increaseOwnerCount(
ApplyViewContext ctx,
SLE::Ref accountSle,
std::uint32_t count,
beast::Journal j);
/** /**
* Convenience overload that accepts AccountID instead of SLE references. * Convenience overload that accepts AccountID instead of SLE references.
* *
@@ -209,36 +129,13 @@ increaseOwnerCount(
std::uint32_t count, std::uint32_t count,
beast::Journal j) beast::Journal j)
{ {
increaseOwnerCount( AccountRootEntryW accountSle(account, view, j);
view, std::optional<AccountRootEntryW> sponsorSle;
view.peek(keylet::account(account)), if (sponsor)
sponsor ? view.peek(keylet::account(*sponsor)) : SLE::pointer(), sponsorSle.emplace(*sponsor, view);
count, accountSle.increaseOwnerCount(sponsorSle, count);
j);
} }
/**
* Decrease owner-count fields when the caller supplies the sponsor.
*
* This helper does not delete a ledger object. It updates reserve accounting
* after the caller has removed an owner-counted reserve, or for special
* owner-count changes whose sponsor cannot be derived from an object's
* sfSponsor field.
*
* @param view The apply view for making changes
* @param accountSle The account's ledger entry
* @param sponsorSle The sponsor's ledger entry (if applicable)
* @param count Amount to remove from the owner count
* @param j Journal for logging
*/
void
decreaseOwnerCount(
ApplyView& view,
SLE::Ref accountSle,
SLE::Ref sponsorSle,
std::uint32_t count,
beast::Journal j);
/** /**
* Convenience overload that accepts AccountID instead of SLE references. * Convenience overload that accepts AccountID instead of SLE references.
* *
@@ -256,12 +153,11 @@ decreaseOwnerCount(
std::uint32_t count, std::uint32_t count,
beast::Journal j) beast::Journal j)
{ {
decreaseOwnerCount( AccountRootEntryW accountSle(account, view, j);
view, std::optional<AccountRootEntryW> sponsorSle;
view.peek(keylet::account(account)), if (sponsor)
sponsor ? view.peek(keylet::account(*sponsor)) : SLE::pointer(), sponsorSle.emplace(*sponsor, view);
count, accountSle.decreaseOwnerCount(sponsorSle, count);
j);
} }
/** /**
@@ -281,7 +177,7 @@ decreaseOwnerCount(
void void
decreaseOwnerCountForObject( decreaseOwnerCountForObject(
ApplyView& view, ApplyView& view,
SLE::Ref accountSle, AccountRootEntryW& accountSle,
SLE::Ref objectSle, SLE::Ref objectSle,
std::uint32_t count, std::uint32_t count,
beast::Journal j); beast::Journal j);
@@ -303,7 +199,7 @@ decreaseOwnerCountForObject(
std::uint32_t count, std::uint32_t count,
beast::Journal j) beast::Journal j)
{ {
SLE::Ref accountSle = view.peek(keylet::account(account)); AccountRootEntryW accountSle(account, view);
decreaseOwnerCountForObject(view, accountSle, objectSle, count, j); decreaseOwnerCountForObject(view, accountSle, objectSle, count, j);
} }
@@ -367,7 +263,7 @@ getPseudoAccountFields();
* - null pointer * - null pointer
*/ */
[[nodiscard]] bool [[nodiscard]] bool
isPseudoAccount(SLE::const_pointer sleAcct); isPseudoAccount(AccountRootEntryR const& sleAcct);
/** /**
* Convenience overload that reads the account from the view. * Convenience overload that reads the account from the view.
@@ -375,7 +271,7 @@ isPseudoAccount(SLE::const_pointer sleAcct);
[[nodiscard]] inline bool [[nodiscard]] inline bool
isPseudoAccount(ReadView const& view, AccountID const& accountId) isPseudoAccount(ReadView const& view, AccountID const& accountId)
{ {
return isPseudoAccount(view.read(keylet::account(accountId))); return isPseudoAccount(AccountRootEntryR(accountId, view));
} }
/** /**
@@ -396,6 +292,6 @@ createPseudoAccount(ApplyView& view, UInt256 const& pseudoOwnerKey, SField const
* - If the SLE requires a destination tag, checks that there is a tag. * - If the SLE requires a destination tag, checks that there is a tag.
*/ */
[[nodiscard]] TER [[nodiscard]] TER
checkDestinationAndTag(SLE::ConstRef toSle, bool hasDestinationTag); checkDestinationAndTag(AccountRootEntryR const& toSle, bool hasDestinationTag);
} // namespace xrpl } // namespace xrpl
+62 -31
View File
@@ -4,7 +4,7 @@
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h> #include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -27,6 +27,32 @@
namespace xrpl { namespace xrpl {
namespace detail {
/**
* Before fixCleanup3_2_0, EscrowCancel passes the escrow SLE as sleDest.
* Return what the old reserve check returned for it, without adopting a
* non-AccountRoot SLE into an AccountRootEntry: the tx reserve sponsor's
* error if the escrow owner submitted the tx, else tefINTERNAL.
*
* @param ctx the apply view context for the escrow transaction.
* @param sleDest the non-AccountRoot SLE that was passed as the destination.
* @return the tx reserve sponsor's error code if the escrow owner submitted
* the tx, else tefINTERNAL.
*/
inline TER
escrowDestNotAccountResult(ApplyViewContext ctx, SLE::ConstRef sleDest)
{
if (sleDest->getAccountID(sfAccount) == ctx.tx[sfAccount])
{
if (auto const sponsor = getTxReserveSponsor(ctx); !sponsor)
return sponsor.error(); // LCOV_EXCL_LINE
}
return tefINTERNAL;
}
} // namespace detail
template <ValidIssueType T> template <ValidIssueType T>
TER TER
escrowUnlockApplyHelper( escrowUnlockApplyHelper(
@@ -70,18 +96,17 @@ escrowUnlockApplyHelper<Issue>(
if (!ctx.view.exists(trustLineKey) && createAsset) if (!ctx.view.exists(trustLineKey) && createAsset)
{ {
// Can the account cover the trust line's reserve? // Can the account cover the trust line's reserve?
auto const sponsorSle = getEffectiveTxReserveSponsor(ctx, sleDest); if (sleDest->getType() != ltACCOUNT_ROOT)
return detail::escrowDestNotAccountResult(ctx, sleDest);
auto const destSle = AccountRootEntryR(sleDest, ctx.view, journal);
auto sponsorSle = getEffectiveTxReserveSponsor(ctx, destSle);
if (!sponsorSle) if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE return sponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ret = checkReserve( auto& sponsor = *sponsorSle;
ctx,
sleDest, if (auto const ret = destSle.checkReserve(
xrpBalance, ctx, xrpBalance, sponsor, {.ownerCountDelta = 1}, tecNO_LINE_INSUF_RESERVE);
*sponsorSle,
{.ownerCountDelta = 1},
journal,
tecNO_LINE_INSUF_RESERVE);
!isTesSuccess(ret)) !isTesSuccess(ret))
{ {
JLOG(journal.trace()) << "Trust line does not exist. " JLOG(journal.trace()) << "Trust line does not exist. "
@@ -94,22 +119,22 @@ escrowUnlockApplyHelper<Issue>(
initialBalance.get<Issue>().account = noAccount(); initialBalance.get<Issue>().account = noAccount();
if (TER const ter = trustCreate( if (TER const ter = trustCreate(
ctx.view, // payment sandbox ctx.view, // payment sandbox
recvLow, // is dest low? recvLow, // is dest low?
issuer, // source issuer, // source
receiver, // destination receiver, // destination
trustLineKey.key, // ledger index trustLineKey.key, // ledger index
sleDest, // Account to add to sleDest, // Account to add to
false, // authorize account false, // authorize account
!sleDest->isFlag(lsfDefaultRipple), // !sleDest->isFlag(lsfDefaultRipple), //
false, // freeze trust line false, // freeze trust line
false, // deep freeze trust line false, // deep freeze trust line
initialBalance, // zero initial balance initialBalance, // zero initial balance
Issue(currency, receiver), // limit of zero Issue(currency, receiver), // limit of zero
0, // quality in 0, // quality in
0, // quality out 0, // quality out
*sponsorSle, // sponsor sponsor ? sponsor->mutableRawSle() : SLE::pointer(), // sponsor
journal); // journal journal); // journal
!isTesSuccess(ter)) !isTesSuccess(ter))
{ {
return ter; // LCOV_EXCL_LINE return ter; // LCOV_EXCL_LINE
@@ -204,23 +229,29 @@ escrowUnlockApplyHelper<MPTIssue>(
auto const mptKeylet = keylet::mptoken(issuanceKey.key, receiver); auto const mptKeylet = keylet::mptoken(issuanceKey.key, receiver);
if (!ctx.view.exists(mptKeylet) && createAsset && !receiverIssuer) if (!ctx.view.exists(mptKeylet) && createAsset && !receiverIssuer)
{ {
auto const sponsorSle = getEffectiveTxReserveSponsor(ctx, sleDest); if (sleDest->getType() != ltACCOUNT_ROOT)
return detail::escrowDestNotAccountResult(ctx, sleDest);
auto const destSle = AccountRootEntryR(sleDest, ctx.view, journal);
auto sponsorSle = getEffectiveTxReserveSponsor(ctx, destSle);
if (!sponsorSle) if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE return sponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ret = checkReserve( auto& sponsor = *sponsorSle;
ctx, sleDest, xrpBalance, *sponsorSle, {.ownerCountDelta = 1}, journal);
if (auto const ret = destSle.checkReserve(ctx, xrpBalance, sponsor, {.ownerCountDelta = 1});
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
if (auto const ter = createMPToken(ctx.view, mptID, receiver, *sponsorSle, 0); if (auto const ter = createMPToken(
ctx.view, mptID, receiver, sponsor ? sponsor->mutableRawSle() : SLE::pointer(), 0);
!isTesSuccess(ter)) !isTesSuccess(ter))
{ {
return ter; // LCOV_EXCL_LINE return ter; // LCOV_EXCL_LINE
} }
// update owner count. // update owner count.
increaseOwnerCount(ctx.view, sleDest, *sponsorSle, 1, journal); AccountRootEntryW receiverSle(receiver, ctx.view, journal);
receiverSle.increaseOwnerCount(sponsor, 1);
} }
if (!ctx.view.exists(mptKeylet) && !receiverIssuer) if (!ctx.view.exists(mptKeylet) && !receiverIssuer)
+12 -11
View File
@@ -2,6 +2,7 @@
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/SField.h> #include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h> #include <xrpl/protocol/STLedgerEntry.h>
@@ -54,11 +55,11 @@ getTxReserveSponsorID(STTx const& tx);
* Return a mutable SLE for the transaction's reserve sponsor account. * Return a mutable SLE for the transaction's reserve sponsor account.
* *
* @param ctx The apply-view context (view + tx) * @param ctx The apply-view context (view + tx)
* @return The sponsor account SLE, a null pointer if the tx is not * @return The sponsor account entry, nullopt if the tx is not
* reserve-sponsored, or tecINTERNAL if the sponsor account cannot * reserve-sponsored, or tecINTERNAL if the sponsor account cannot
* be loaded (an already-checked invariant). * be loaded (an already-checked invariant).
*/ */
std::expected<SLE::pointer, TER> std::expected<std::optional<AccountRootEntryW>, TER>
getTxReserveSponsor(ApplyViewContext ctx); getTxReserveSponsor(ApplyViewContext ctx);
/** /**
@@ -66,29 +67,29 @@ getTxReserveSponsor(ApplyViewContext ctx);
* *
* @param view The ledger read view * @param view The ledger read view
* @param tx The transaction to inspect * @param tx The transaction to inspect
* @return The sponsor account SLE, a null pointer if the tx is not * @return The sponsor account entry, nullopt if the tx is not
* reserve-sponsored, or tecINTERNAL if the sponsor account cannot * reserve-sponsored, or tecINTERNAL if the sponsor account cannot
* be loaded (an already-checked invariant). * be loaded (an already-checked invariant).
*/ */
std::expected<SLE::const_pointer, TER> std::expected<std::optional<AccountRootEntryR>, TER>
getTxReserveSponsor(ReadView const& view, STTx const& tx); getTxReserveSponsor(ReadView const& view, STTx const& tx);
/** /**
* The transaction's reserve sponsor for the given account, if applicable. * The transaction's reserve sponsor for the given account, if applicable.
* *
* A reserve sponsor only covers the transaction submitter's own objects, so * A reserve sponsor only covers the transaction submitter's own objects, so
* this returns the tx reserve sponsor SLE only when accountSle is the tx's own * this returns the tx reserve sponsor entry only when accountSle is the tx's
* (non-pseudo) account; otherwise it returns a null sponsor pointer. This is * own (non-pseudo) account; otherwise it returns nullopt. This is
* the single source of truth for the "sponsor applies to tx.Account only" rule * the single source of truth for the "sponsor applies to tx.Account only" rule
* that the sponsor-deriving helper overloads in AccountRootHelpers rely on. * that the sponsor-deriving helper overloads in AccountRootHelpers rely on.
* *
* @param ctx The apply-view context (view + tx) * @param ctx The apply-view context (view + tx)
* @param accountSle The account whose sponsor is being resolved * @param accountSle The account whose sponsor is being resolved
* @return The sponsor SLE (nullptr if unsponsored), or tecINTERNAL if the * @return The sponsor entry (nullopt if unsponsored), or tecINTERNAL if the
* sponsor account cannot be loaded (an already-checked invariant) * sponsor account cannot be loaded (an already-checked invariant)
*/ */
[[nodiscard]] std::expected<SLE::pointer, TER> [[nodiscard]] std::expected<std::optional<AccountRootEntryW>, TER>
getEffectiveTxReserveSponsor(ApplyViewContext ctx, SLE::ConstRef accountSle); getEffectiveTxReserveSponsor(ApplyViewContext ctx, AccountRootEntryR const& accountSle);
/** /**
* Return the AccountID stored in the given sponsor field of a ledger entry, or nullopt if absent. * Return the AccountID stored in the given sponsor field of a ledger entry, or nullopt if absent.
@@ -105,9 +106,9 @@ getLedgerEntryReserveSponsorID(SLE::ConstRef sle, SF_ACCOUNT const& field = sfSp
* @param view The mutable apply view * @param view The mutable apply view
* @param sle The ledger entry whose sponsor field is inspected * @param sle The ledger entry whose sponsor field is inspected
* @param field The field that holds the sponsor AccountID (defaults to sfSponsor) * @param field The field that holds the sponsor AccountID (defaults to sfSponsor)
* @return The sponsor account SLE, or a null pointer if the entry is unsponsored. * @return The sponsor account entry, or nullopt if the entry is unsponsored.
*/ */
SLE::pointer std::optional<AccountRootEntryW>
getLedgerEntryReserveSponsor( getLedgerEntryReserveSponsor(
ApplyView& view, ApplyView& view,
SLE::ConstRef sle, SLE::ConstRef sle,
@@ -27,6 +27,18 @@
namespace xrpl { namespace xrpl {
/**
* Returns true if sleAcct is an AccountRoot carrying a pseudo-account field.
*
* isPseudoAccount() takes a view-bound AccountRootEntry, which is not
* available while visiting entries, so invariant checks use this instead.
*
* @param sleAcct the SLE to check.
* @return true if sleAcct is an AccountRoot carrying a pseudo-account field.
*/
[[nodiscard]] bool
isPseudoAccountSle(SLE::ConstRef sleAcct);
#if GENERATING_DOCS #if GENERATING_DOCS
/** /**
* @brief Prototype for invariant check implementations. * @brief Prototype for invariant check implementations.
+3 -2
View File
@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
@@ -25,7 +26,7 @@ checkFreeze(
XRPL_ASSERT(src != dst, "xrpl::checkFreeze : unequal input accounts"); XRPL_ASSERT(src != dst, "xrpl::checkFreeze : unequal input accounts");
// check freeze // check freeze
if (auto sle = view.read(keylet::account(dst))) if (auto sle = AccountRootEntryR(dst, view))
{ {
if (sle->isFlag(lsfGlobalFreeze)) if (sle->isFlag(lsfGlobalFreeze))
{ {
@@ -49,7 +50,7 @@ checkFreeze(
if (view.rules().enabled(fixFrozenLPTokenTransfer)) if (view.rules().enabled(fixFrozenLPTokenTransfer))
{ {
if (auto const sleDst = view.read(keylet::account(dst)); if (auto const sleDst = AccountRootEntryR(dst, view);
sleDst && sleDst->isFieldPresent(sfAMMID)) sleDst && sleDst->isFieldPresent(sfAMMID))
{ {
auto const sleAmm = view.read(keylet::amm((*sleDst)[sfAMMID])); auto const sleAmm = view.read(keylet::amm((*sleDst)[sfAMMID]));
@@ -2,6 +2,7 @@
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Keylet.h> #include <xrpl/protocol/Keylet.h>
#include <xrpl/protocol/STLedgerEntry.h> #include <xrpl/protocol/STLedgerEntry.h>
@@ -12,6 +13,7 @@
#include <xrpl/tx/Transactor.h> #include <xrpl/tx/Transactor.h>
#include <cstdint> #include <cstdint>
#include <optional>
namespace xrpl { namespace xrpl {
@@ -56,8 +58,8 @@ private:
Keylet const& sponsorshipKeylet, Keylet const& sponsorshipKeylet,
AccountID const& sponsorID, AccountID const& sponsorID,
AccountID const& sponseeID, AccountID const& sponseeID,
SLE::Ref sponsorAccSle, AccountRootEntryW& sponsorAccSle,
SLE::Ref reserveSponsorAccSle); std::optional<AccountRootEntryW>& reserveSponsorAccSle);
}; };
} // namespace xrpl } // namespace xrpl
+18 -9
View File
@@ -9,6 +9,7 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
@@ -115,8 +116,8 @@ isVaultPseudoAccountFrozenForIssuance(
view, {issuer, account}, assetOfHolding(issuanceSle, *sleHolding), depth + 1); view, {issuer, account}, assetOfHolding(issuanceSle, *sleHolding), depth + 1);
} }
auto const mptIssuer = view.read(keylet::account(issuer)); auto const mptIssuer = AccountRootEntryR(issuer, view);
if (mptIssuer == nullptr) if (!mptIssuer.exists())
{ {
// LCOV_EXCL_START // LCOV_EXCL_START
UNREACHABLE("xrpl::isVaultPseudoAccountFrozen : null MPToken issuer"); UNREACHABLE("xrpl::isVaultPseudoAccountFrozen : null MPToken issuer");
@@ -189,7 +190,7 @@ canTransferLPToken(
{ {
// Only AMM-issued LPTokens are subject to this check. The LPToken's issuer // Only AMM-issued LPTokens are subject to this check. The LPToken's issuer
// is the AMM account; if it is not an AMM, this is not an LPToken. // is the AMM account; if it is not an AMM, this is not an LPToken.
auto const sleIssuer = view.read(keylet::account(lpTokenIssuer)); auto const sleIssuer = AccountRootEntryR(lpTokenIssuer, view);
if (!sleIssuer || !sleIssuer->isFieldPresent(sfAMMID)) if (!sleIssuer || !sleIssuer->isFieldPresent(sfAMMID))
return tesSUCCESS; return tesSUCCESS;
@@ -466,7 +467,7 @@ canWithdraw(
ReadView const& view, ReadView const& view,
AccountID const& from, AccountID const& from,
AccountID const& to, AccountID const& to,
SLE::ConstRef toSle, AccountRootEntryR const& toSle,
STAmount const& amount, STAmount const& amount,
bool hasDestinationTag, bool hasDestinationTag,
std::optional<std::vector<UInt256>> const& credentialIDs) std::optional<std::vector<UInt256>> const& credentialIDs)
@@ -516,7 +517,7 @@ canWithdraw(
bool hasDestinationTag, bool hasDestinationTag,
std::optional<std::vector<UInt256>> const& credentialIDs) std::optional<std::vector<UInt256>> const& credentialIDs)
{ {
auto const toSle = view.read(keylet::account(to)); auto const toSle = AccountRootEntryR(to, view);
return canWithdraw(view, from, to, toSle, amount, hasDestinationTag, credentialIDs); return canWithdraw(view, from, to, toSle, amount, hasDestinationTag, credentialIDs);
} }
@@ -541,7 +542,7 @@ doWithdraw(
STAmount const& amount, STAmount const& amount,
beast::Journal j) beast::Journal j)
{ {
auto const dstSle = ctx.view.read(keylet::account(dstAcct)); auto dstSle = AccountRootEntryW(dstAcct, ctx.view);
// Create a trust line or MPToken for a self-destination only when there // Create a trust line or MPToken for a self-destination only when there
// is a payout to credit. Post-fixCleanup3_4_0, a zero-value withdraw // is a payout to credit. Post-fixCleanup3_4_0, a zero-value withdraw
@@ -559,7 +560,8 @@ doWithdraw(
} }
else else
{ {
if (auto err = verifyDepositPreauth(ctx.tx, ctx.view, senderAcct, dstAcct, dstSle, j)) if (auto err =
verifyDepositPreauth(ctx.tx, ctx.view, senderAcct, dstAcct, dstSle.rawSle(), j))
return err; return err;
} }
@@ -582,14 +584,21 @@ doWithdraw(
// sponsor against the destination. accountSend can auto-create a holding // sponsor against the destination. accountSend can auto-create a holding
// for dstAcct; keying on the destination ensures a third-party destination's // for dstAcct; keying on the destination ensures a third-party destination's
// holding is never stamped with the tx's reserve sponsor. // holding is never stamped with the tx's reserve sponsor.
auto const sponsorSle = getEffectiveTxReserveSponsor(ctx, dstSle); auto sponsorSle = getEffectiveTxReserveSponsor(ctx, dstSle);
if (!sponsorSle) if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE return sponsorSle.error(); // LCOV_EXCL_LINE
// Move the funds directly from the broker's pseudo-account to the // Move the funds directly from the broker's pseudo-account to the
// dstAcct // dstAcct
auto& sponsor = *sponsorSle;
return accountSend( return accountSend(
ctx.view, sourceAcct, dstAcct, amount, j, *sponsorSle, WaiveTransferFee::Yes); ctx.view,
sourceAcct,
dstAcct,
amount,
j,
sponsor ? sponsor->mutableRawSle() : SLE::pointer{},
WaiveTransferFee::Yes);
} }
TER TER
@@ -0,0 +1,322 @@
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/OwnerCounts.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/XRPAmount.h>
#include <cstdint>
#include <limits>
#include <optional>
#include <utility>
namespace xrpl {
template <typename ViewT>
XRPAmount
AccountRootEntry<ViewT>::reserve(Adjustment adj) const
{
auto const& view = this->readView();
auto const j = this->journal();
XRPL_ASSERT(
this->exists() && (*this)->getType() == ltACCOUNT_ROOT, "xrpl::accountReserve : valid sle");
if (!view.rules().enabled(featureSponsor))
{
XRPL_ASSERT(adj.accountCountDelta == 0, "xrpl::accountReserve : no account count delta");
return view.fees().accountReserve(
(*this)->getFieldU32(sfOwnerCount) + adj.ownerCountDelta, 1);
}
std::uint32_t const currentOwnerCount = ownerCount(adj.ownerCountDelta);
std::uint32_t const currentAccountCount =
detail::accountCountImpl(*this, adj.accountCountDelta, j);
return view.fees().accountReserve(currentOwnerCount, currentAccountCount);
}
template <typename ViewT>
std::uint32_t
AccountRootEntry<ViewT>::ownerCount(std::int32_t ownerCountAdj) const
{
auto const j = this->journal();
XRPL_ASSERT(
this->exists() && (*this)->getType() == ltACCOUNT_ROOT,
"xrpl::ownerCount : sle is account root");
AccountID const id = (*this)->getAccountID(sfAccount);
std::uint32_t const currentOwnerCount = (*this)->at(sfOwnerCount);
std::uint32_t const sponsoredOwnerCount = (*this)->at(sfSponsoredOwnerCount);
std::uint32_t const sponsoringOwnerCount = (*this)->at(sfSponsoringOwnerCount);
XRPL_ASSERT(
currentOwnerCount >= sponsoredOwnerCount,
"xrpl::ownerCount : OwnerCount must be greater than or equal to SponsoredOwnerCount");
std::int64_t deltaCount =
static_cast<std::int64_t>(ownerCountAdj) - sponsoredOwnerCount + sponsoringOwnerCount;
if (deltaCount > std::numeric_limits<std::int32_t>::max())
{
// LCOV_EXCL_START
deltaCount = std::numeric_limits<std::int32_t>::max();
JLOG(j.fatal()) << "Account " << id << " delta count exceeds max, "
<< "adjustment: " << ownerCountAdj
<< ", sponsoredCount: " << sponsoredOwnerCount
<< ", sponsoringOwnerCount: " << sponsoringOwnerCount;
// LCOV_EXCL_STOP
}
else if (deltaCount < std::numeric_limits<std::int32_t>::min())
{
// LCOV_EXCL_START
deltaCount = std::numeric_limits<std::int32_t>::min();
JLOG(j.fatal()) << "Account " << id << " delta count is below min, "
<< "adjustment: " << ownerCountAdj
<< ", sponsoredCount: " << sponsoredOwnerCount
<< ", sponsoringCount: " << sponsoringOwnerCount;
// LCOV_EXCL_STOP
}
return detail::confineOwnerCount(currentOwnerCount, deltaCount);
}
template <typename ViewT>
TER
AccountRootEntry<ViewT>::checkReserve(
ApplyViewContext ctx,
XRPAmount accBalance,
std::optional<AccountRootEntry<ReadView>> const& sponsorSle,
Adjustment adj,
TER insufReserveCode) const
{
// TODO: swap to assert after fixCleanup3_2_0 is retired
if (!this->exists() || (*this)->getType() != ltACCOUNT_ROOT)
return tefINTERNAL; // LCOV_EXCL_LINE
XRPL_ASSERT(
!isTesSuccess(insufReserveCode), "xrpl::checkReserve : insufReserveCode is not tesSUCCESS");
if (ctx.view.rules().enabled(featureSponsor))
{
if (sponsorSle)
{
if ((*sponsorSle)->getType() != ltACCOUNT_ROOT)
return tefINTERNAL; // LCOV_EXCL_LINE
auto const sle = ctx.view.read(
keylet::sponsorship(
(*sponsorSle)->getAccountID(sfAccount), (*this)->getAccountID(sfAccount)));
// A reserve-sponsored tx must carry a sponsor signature
// (cosigning path) and/or have a pre-existing sponsorship SLE
// (prefunded path). Absence of both is an internal invariant break.
if (isReserveSponsored(ctx.tx) && !sle && !ctx.tx.isFieldPresent(sfSponsorSignature))
return tecINTERNAL; // LCOV_EXCL_LINE
if (sle)
{
auto const ownerCountAllowed = sle->getFieldU32(sfRemainingOwnerCount);
if (adj.ownerCountDelta > 0 &&
ownerCountAllowed < static_cast<std::uint32_t>(adj.ownerCountDelta))
return insufReserveCode;
}
auto const sponsorBalance = (*sponsorSle)->getFieldAmount(sfBalance).xrp();
XRPAmount const sponsorReserve = sponsorSle->reserve(adj);
if (sponsorBalance < sponsorReserve)
return insufReserveCode;
}
else
{
XRPAmount const reserve = this->reserve(adj);
if (accBalance < reserve)
return insufReserveCode;
}
}
else
{
XRPL_ASSERT(
!sponsorSle,
"xrpl::checkReserve : featureSponsor disabled and sponsorSle not provided");
XRPL_ASSERT(adj.accountCountDelta == 0, "xrpl::checkReserve : accountCountDelta is 0");
auto const reserve = ctx.view.fees().accountReserve(
(*this)->getFieldU32(sfOwnerCount) + adj.ownerCountDelta, 1);
if (accBalance < reserve)
return insufReserveCode;
}
return tesSUCCESS;
}
template <typename ViewT>
TER
AccountRootEntry<ViewT>::checkReserve(ApplyViewContext ctx, XRPAmount accBalance, Adjustment adj)
const
{
auto const sponsorExp = getEffectiveTxReserveSponsor(ctx, *this);
if (!sponsorExp)
return sponsorExp.error(); // LCOV_EXCL_LINE
std::optional<AccountRootEntry<ReadView>> sponsorSle;
if (*sponsorExp)
sponsorSle.emplace(**sponsorExp);
return checkReserve(ctx, accBalance, sponsorSle, adj);
}
template <typename ViewT>
void
AccountRootEntry<ViewT>::adjustOwnerCountSigned(
std::optional<AccountRootEntry<ApplyView>>& sponsorSle,
std::int32_t adjustment)
requires Base::kIsWritable
{
auto& view = this->applyView();
auto const j = this->journal();
if (view.rules().enabled(featureSponsor))
{
XRPL_ASSERT(this->exists(), "xrpl::adjustOwnerCountSigned : valid account sle");
if (!this->exists())
return; // LCOV_EXCL_LINE
auto const accountID = (*this)->getAccountID(sfAccount);
bool const validType = (*this)->getType() == ltACCOUNT_ROOT;
XRPL_ASSERT(validType, "xrpl::adjustOwnerCountSigned : valid account sle type");
if (!validType)
return; // LCOV_EXCL_LINE
XRPL_ASSERT(adjustment, "xrpl::adjustOwnerCountSigned : nonzero adjustment input");
OwnerCounts const currentOwnerCount(this->rawSle());
OwnerCounts totalOwnerCount(currentOwnerCount);
if (sponsorSle)
{
bool const validSponsorType = (*sponsorSle)->getType() == ltACCOUNT_ROOT;
XRPL_ASSERT(validSponsorType, "xrpl::adjustOwnerCountSigned : valid sponsor sle type");
if (!validSponsorType)
return; // LCOV_EXCL_LINE
auto const sponsorID = (*sponsorSle)->getAccountID(sfAccount);
totalOwnerCount.sponsored = detail::adjustOwnerCountImpl(
view, this->mutableRawSle(), sfSponsoredOwnerCount, accountID, adjustment, j);
{
OwnerCounts const sponsorCurrent(sponsorSle->rawSle());
OwnerCounts sponsorAdjustment(sponsorCurrent);
sponsorAdjustment.sponsoring = detail::adjustOwnerCountImpl(
view,
sponsorSle->mutableRawSle(),
sfSponsoringOwnerCount,
sponsorID,
adjustment,
j);
view.adjustOwnerCountHook(sponsorID, sponsorCurrent, sponsorAdjustment);
}
auto sponsorshipSle = view.peek(keylet::sponsorship(sponsorID, accountID));
if (sponsorshipSle && adjustment > 0)
{
// Only decrease the pre-funded ReserveCount on Sponsorship if we assign new
// objects. Removing/reassigning ownership of the object doesn't increase
// RemainingOwnerCount back. Don't call hook because this counter is not something
// that requires reserve (like other sf...OwnerCounts do).
detail::adjustOwnerCountImpl(
view, sponsorshipSle, sfRemainingOwnerCount, sponsorID, -adjustment, j);
}
}
totalOwnerCount.owner = detail::adjustOwnerCountImpl(
view, this->mutableRawSle(), sfOwnerCount, accountID, adjustment, j);
view.adjustOwnerCountHook(accountID, currentOwnerCount, totalOwnerCount);
}
else
{
XRPL_ASSERT(this->exists(), "xrpl::adjustOwnerCountSigned : valid account sle");
if (!this->exists())
return;
// the remaining are only asserts to preserve existing behavior
XRPL_ASSERT(!sponsorSle, "xrpl::adjustOwnerCountSigned : sponsor not enabled");
XRPL_ASSERT(
(*this)->getType() == ltACCOUNT_ROOT,
"xrpl::adjustOwnerCountSigned : valid account sle type");
XRPL_ASSERT(adjustment, "xrpl::adjustOwnerCount : nonzero adjustment input");
std::uint32_t const current{(*this)->getFieldU32(sfOwnerCount)};
AccountID const id = (**this)[sfAccount];
std::uint32_t const adjusted = detail::confineOwnerCount(current, adjustment, id, j);
OwnerCounts const currentOwnerCount(this->rawSle());
OwnerCounts finalOwnerCount(currentOwnerCount);
finalOwnerCount.owner = adjusted;
view.adjustOwnerCountHook(id, currentOwnerCount, finalOwnerCount);
(*this)->at(sfOwnerCount) = adjusted;
this->update();
}
}
template <typename ViewT>
void
AccountRootEntry<ViewT>::increaseOwnerCount(
std::optional<AccountRootEntry<ApplyView>>& sponsorSle,
std::uint32_t count)
requires Base::kIsWritable
{
XRPL_ASSERT(
count != 0 && count <= std::numeric_limits<std::int32_t>::max(),
"xrpl::increaseOwnerCount : count in signed delta range");
if (count == 0 || count > std::numeric_limits<std::int32_t>::max())
return; // LCOV_EXCL_LINE
adjustOwnerCountSigned(sponsorSle, static_cast<std::int32_t>(count));
}
template <typename ViewT>
void
AccountRootEntry<ViewT>::increaseOwnerCount(ApplyViewContext ctx, std::uint32_t count)
requires Base::kIsWritable
{
auto sponsorExp = getEffectiveTxReserveSponsor(ctx, *this);
// The sponsor's existence is validated by checkReserve/checkSponsor before
// any owner-count mutation, so loading it here cannot fail.
XRPL_ASSERT(
sponsorExp.has_value(), "xrpl::increaseOwnerCount : sponsor validated before mutation");
std::optional<AccountRootEntry<ApplyView>> sponsorSle;
if (sponsorExp && *sponsorExp)
sponsorSle.emplace(std::move(**sponsorExp));
increaseOwnerCount(sponsorSle, count);
}
template <typename ViewT>
void
AccountRootEntry<ViewT>::decreaseOwnerCount(
std::optional<AccountRootEntry<ApplyView>>& sponsorSle,
std::uint32_t count)
requires Base::kIsWritable
{
XRPL_ASSERT(
count != 0 && count <= std::numeric_limits<std::int32_t>::max(),
"xrpl::decreaseOwnerCount : count in signed delta range");
if (count == 0 || count > std::numeric_limits<std::int32_t>::max())
return; // LCOV_EXCL_LINE
adjustOwnerCountSigned(sponsorSle, -static_cast<std::int32_t>(count));
}
template class AccountRootEntry<ReadView>;
template class AccountRootEntry<ApplyView>;
} // namespace xrpl
+4 -3
View File
@@ -11,6 +11,7 @@
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/Sandbox.h> #include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h> #include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -641,7 +642,7 @@ ammAccountHolds(ReadView const& view, AccountID const& ammAccountID, Asset const
[&](Issue const& issue) { [&](Issue const& issue) {
if (isXRP(issue)) if (isXRP(issue))
{ {
if (auto const sle = view.read(keylet::account(ammAccountID))) if (auto const sle = AccountRootEntryR(ammAccountID, view))
return (*sle)[sfBalance]; return (*sle)[sfBalance];
} }
else if ( else if (
@@ -757,7 +758,7 @@ deleteAMMAccount(Sandbox& sb, Asset const& asset, Asset const& asset2, beast::Jo
} }
auto const ammAccountID = (*ammSle)[sfAccount]; auto const ammAccountID = (*ammSle)[sfAccount];
auto sleAMMRoot = sb.peek(keylet::account(ammAccountID)); auto sleAMMRoot = AccountRootEntryW(ammAccountID, sb);
if (!sleAMMRoot) if (!sleAMMRoot)
{ {
// LCOV_EXCL_START // LCOV_EXCL_START
@@ -795,7 +796,7 @@ deleteAMMAccount(Sandbox& sb, Asset const& asset, Asset const& asset2, beast::Jo
} }
sb.erase(ammSle); sb.erase(ammSle);
sb.erase(sleAMMRoot); sleAMMRoot.erase();
return tesSUCCESS; return tesSUCCESS;
} }
+22 -300
View File
@@ -9,6 +9,7 @@
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/OwnerCounts.h> #include <xrpl/ledger/OwnerCounts.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -17,7 +18,6 @@
#include <xrpl/protocol/Rate.h> #include <xrpl/protocol/Rate.h>
#include <xrpl/protocol/SField.h> #include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h> #include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/STTx.h>
#include <xrpl/protocol/TER.h> #include <xrpl/protocol/TER.h>
#include <xrpl/protocol/XRPAmount.h> #include <xrpl/protocol/XRPAmount.h>
#include <xrpl/protocol/digest.h> #include <xrpl/protocol/digest.h>
@@ -38,25 +38,19 @@ isGlobalFrozen(ReadView const& view, AccountID const& issuer)
{ {
if (isXRP(issuer)) if (isXRP(issuer))
return false; return false;
if (auto const sle = view.read(keylet::account(issuer))) if (auto const sle = AccountRootEntryR(issuer, view))
return sle->isFlag(lsfGlobalFreeze); return sle->isFlag(lsfGlobalFreeze);
return false; return false;
} }
namespace { namespace detail {
// An owner count cannot be negative. If adjustment would cause a negative
// owner count, clamp the owner count at 0. Similarly for overflow. This
// adjustment allows the ownerCount to be adjusted up or down in multiple steps.
// If id != std::nullopt, then do error reporting.
//
// Returns adjusted owner count.
std::uint32_t std::uint32_t
confineOwnerCount( confineOwnerCount(
std::uint32_t currentOwnerCount, std::uint32_t currentOwnerCount,
std::int32_t ownerCountAdj, std::int32_t ownerCountAdj,
std::optional<AccountID> const& id = std::nullopt, std::optional<AccountID> const& id,
beast::Journal j = beast::Journal{beast::Journal::getNullSink()}) beast::Journal j)
{ {
std::uint32_t totalOwnerCount{currentOwnerCount + ownerCountAdj}; std::uint32_t totalOwnerCount{currentOwnerCount + ownerCountAdj};
if (ownerCountAdj > 0) if (ownerCountAdj > 0)
@@ -91,10 +85,8 @@ confineOwnerCount(
return totalOwnerCount; return totalOwnerCount;
} }
// Returns the number of account reserves funded by this account: 1 for itself (0 if sponsored by
// another account) plus the count of accounts it sponsors.
std::uint32_t std::uint32_t
accountCountImpl(SLE::ConstRef sle, std::int32_t accountCountAdj, beast::Journal j) accountCountImpl(AccountRootEntryR const& sle, std::int32_t accountCountAdj, beast::Journal j)
{ {
bool const isSponsored = sle->isFieldPresent(sfSponsor); bool const isSponsored = sle->isFieldPresent(sfSponsor);
std::int64_t const sponsoringAccountCount = sle->getFieldU32(sfSponsoringAccountCount); std::int64_t const sponsoringAccountCount = sle->getFieldU32(sfSponsoringAccountCount);
@@ -131,151 +123,25 @@ adjustOwnerCountImpl(
{ {
std::uint32_t const currentOwnerCount = sle->at(sfield); std::uint32_t const currentOwnerCount = sle->at(sfield);
std::uint32_t const totalOwnerCount = std::uint32_t const totalOwnerCount =
confineOwnerCount(currentOwnerCount, ownerCountAdj, accID, j); detail::confineOwnerCount(currentOwnerCount, ownerCountAdj, accID, j);
sle->at(sfield) = totalOwnerCount; sle->at(sfield) = totalOwnerCount;
view.update(sle); view.update(sle);
return totalOwnerCount; return totalOwnerCount;
} }
void } // namespace detail
adjustOwnerCountSigned(
ApplyView& view,
SLE::Ref accountSle,
SLE::Ref sponsorSle,
std::int32_t adjustment,
beast::Journal j)
{
if (view.rules().enabled(featureSponsor))
{
XRPL_ASSERT(accountSle, "xrpl::adjustOwnerCountSigned : valid account sle");
if (!accountSle)
return; // LCOV_EXCL_LINE
auto const accountID = accountSle->getAccountID(sfAccount);
bool const validType = accountSle->getType() == ltACCOUNT_ROOT;
XRPL_ASSERT(validType, "xrpl::adjustOwnerCountSigned : valid account sle type");
if (!validType)
return; // LCOV_EXCL_LINE
XRPL_ASSERT(adjustment, "xrpl::adjustOwnerCountSigned : nonzero adjustment input");
OwnerCounts const currentOwnerCount(accountSle);
OwnerCounts totalOwnerCount(currentOwnerCount);
if (sponsorSle)
{
bool const validSponsorType = sponsorSle->getType() == ltACCOUNT_ROOT;
XRPL_ASSERT(validSponsorType, "xrpl::adjustOwnerCountSigned : valid sponsor sle type");
if (!validSponsorType)
return; // LCOV_EXCL_LINE
auto const sponsorID = sponsorSle->getAccountID(sfAccount);
totalOwnerCount.sponsored = adjustOwnerCountImpl(
view, accountSle, sfSponsoredOwnerCount, accountID, adjustment, j);
{
OwnerCounts const sponsorCurrent(sponsorSle);
OwnerCounts sponsorAdjustment(sponsorCurrent);
sponsorAdjustment.sponsoring = adjustOwnerCountImpl(
view, sponsorSle, sfSponsoringOwnerCount, sponsorID, adjustment, j);
view.adjustOwnerCountHook(sponsorID, sponsorCurrent, sponsorAdjustment);
}
auto sponsorshipSle = view.peek(keylet::sponsorship(sponsorID, accountID));
if (sponsorshipSle && adjustment > 0)
{
// Only decrease the pre-funded ReserveCount on Sponsorship if we assign new
// objects. Removing/reassigning ownership of the object doesn't increase
// RemainingOwnerCount back. Don't call hook because this counter is not something
// that requires reserve (like other sf...OwnerCounts do).
adjustOwnerCountImpl(
view, sponsorshipSle, sfRemainingOwnerCount, sponsorID, -adjustment, j);
}
}
totalOwnerCount.owner =
adjustOwnerCountImpl(view, accountSle, sfOwnerCount, accountID, adjustment, j);
view.adjustOwnerCountHook(accountID, currentOwnerCount, totalOwnerCount);
}
else
{
XRPL_ASSERT(accountSle, "xrpl::adjustOwnerCountSigned : valid account sle");
if (!accountSle)
return;
// the remaining are only asserts to preserve existing behavior
XRPL_ASSERT(sponsorSle == nullptr, "xrpl::adjustOwnerCountSigned : sponsor not enabled");
XRPL_ASSERT(
accountSle->getType() == ltACCOUNT_ROOT,
"xrpl::adjustOwnerCountSigned : valid account sle type");
XRPL_ASSERT(adjustment, "xrpl::adjustOwnerCount : nonzero adjustment input");
std::uint32_t const current{accountSle->getFieldU32(sfOwnerCount)};
AccountID const id = (*accountSle)[sfAccount];
std::uint32_t const adjusted = confineOwnerCount(current, adjustment, id, j);
OwnerCounts const currentOwnerCount(accountSle);
OwnerCounts finalOwnerCount(currentOwnerCount);
finalOwnerCount.owner = adjusted;
view.adjustOwnerCountHook(id, currentOwnerCount, finalOwnerCount);
accountSle->at(sfOwnerCount) = adjusted;
view.update(accountSle);
}
}
} // namespace
std::uint32_t
ownerCount(SLE::ConstRef sle, beast::Journal j, std::int32_t ownerCountAdj)
{
XRPL_ASSERT(sle && sle->getType() == ltACCOUNT_ROOT, "xrpl::ownerCount : sle is account root");
AccountID const id = sle->getAccountID(sfAccount);
std::uint32_t const currentOwnerCount = sle->at(sfOwnerCount);
std::uint32_t const sponsoredOwnerCount = sle->at(sfSponsoredOwnerCount);
std::uint32_t const sponsoringOwnerCount = sle->at(sfSponsoringOwnerCount);
XRPL_ASSERT(
currentOwnerCount >= sponsoredOwnerCount,
"xrpl::ownerCount : OwnerCount must be greater than or equal to SponsoredOwnerCount");
std::int64_t deltaCount =
static_cast<std::int64_t>(ownerCountAdj) - sponsoredOwnerCount + sponsoringOwnerCount;
if (deltaCount > std::numeric_limits<std::int32_t>::max())
{
// LCOV_EXCL_START
deltaCount = std::numeric_limits<std::int32_t>::max();
JLOG(j.fatal()) << "Account " << id << " delta count exceeds max, "
<< "adjustment: " << ownerCountAdj
<< ", sponsoredCount: " << sponsoredOwnerCount
<< ", sponsoringOwnerCount: " << sponsoringOwnerCount;
// LCOV_EXCL_STOP
}
else if (deltaCount < std::numeric_limits<std::int32_t>::min())
{
// LCOV_EXCL_START
deltaCount = std::numeric_limits<std::int32_t>::min();
JLOG(j.fatal()) << "Account " << id << " delta count is below min, "
<< "adjustment: " << ownerCountAdj
<< ", sponsoredCount: " << sponsoredOwnerCount
<< ", sponsoringCount: " << sponsoringOwnerCount;
// LCOV_EXCL_STOP
}
return confineOwnerCount(currentOwnerCount, deltaCount);
}
XRPAmount XRPAmount
xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j) xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j)
{ {
auto const sle = view.read(keylet::account(id)); auto const sle = AccountRootEntryR(id, view);
if (sle == nullptr) if (!sle.exists())
return beast::kZero; return beast::kZero;
// Return balance minus reserve // Return balance minus reserve
std::uint32_t const currentOwnerCount = std::uint32_t const currentOwnerCount = detail::confineOwnerCount(
confineOwnerCount(view.ownerCountHook(id, OwnerCounts(sle)).count(), ownerCountAdj); view.ownerCountHook(id, OwnerCounts(sle.rawSle())).count(), ownerCountAdj);
std::uint32_t const currentAccountCount = accountCountImpl(sle, 0, j); std::uint32_t const currentAccountCount = detail::accountCountImpl(sle, 0, j);
// Pseudo-accounts have no reserve requirement // Pseudo-accounts have no reserve requirement
auto const reserve = isPseudoAccount(sle) auto const reserve = isPseudoAccount(sle)
@@ -300,7 +166,7 @@ xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj,
Rate Rate
transferRate(ReadView const& view, AccountID const& issuer) transferRate(ReadView const& view, AccountID const& issuer)
{ {
auto const sle = view.read(keylet::account(issuer)); auto const sle = AccountRootEntryR(issuer, view);
if (sle && sle->isFieldPresent(sfTransferRate)) if (sle && sle->isFieldPresent(sfTransferRate))
return Rate{sle->getFieldU32(sfTransferRate)}; return Rate{sle->getFieldU32(sfTransferRate)};
@@ -308,57 +174,10 @@ transferRate(ReadView const& view, AccountID const& issuer)
return kParityRate; return kParityRate;
} }
void
increaseOwnerCount(
ApplyView& view,
SLE::Ref accountSle,
SLE::Ref sponsorSle,
std::uint32_t count,
beast::Journal j)
{
XRPL_ASSERT(
count != 0 && count <= std::numeric_limits<std::int32_t>::max(),
"xrpl::increaseOwnerCount : count in signed delta range");
if (count == 0 || count > std::numeric_limits<std::int32_t>::max())
return; // LCOV_EXCL_LINE
adjustOwnerCountSigned(view, accountSle, sponsorSle, static_cast<std::int32_t>(count), j);
}
void
increaseOwnerCount(ApplyViewContext ctx, SLE::Ref accountSle, std::uint32_t count, beast::Journal j)
{
auto const sponsorExp = getEffectiveTxReserveSponsor(ctx, accountSle);
// The sponsor's existence is validated by checkReserve/checkSponsor before
// any owner-count mutation, so loading it here cannot fail.
XRPL_ASSERT(
sponsorExp.has_value(), "xrpl::increaseOwnerCount : sponsor validated before mutation");
increaseOwnerCount(ctx.view, accountSle, sponsorExp ? *sponsorExp : SLE::pointer(), count, j);
}
void
decreaseOwnerCount(
ApplyView& view,
SLE::Ref accountSle,
SLE::Ref sponsorSle,
std::uint32_t count,
beast::Journal j)
{
XRPL_ASSERT(
count != 0 && count <= std::numeric_limits<std::int32_t>::max(),
"xrpl::decreaseOwnerCount : count in signed delta range");
if (count == 0 || count > std::numeric_limits<std::int32_t>::max())
return; // LCOV_EXCL_LINE
adjustOwnerCountSigned(view, accountSle, sponsorSle, -static_cast<std::int32_t>(count), j);
}
void void
decreaseOwnerCountForObject( decreaseOwnerCountForObject(
ApplyView& view, ApplyView& view,
SLE::Ref accountSle, AccountRootEntryW& accountSle,
SLE::Ref objectSle, SLE::Ref objectSle,
std::uint32_t count, std::uint32_t count,
beast::Journal j) beast::Journal j)
@@ -372,8 +191,8 @@ decreaseOwnerCountForObject(
if (!validObjectType) if (!validObjectType)
return; // LCOV_EXCL_LINE return; // LCOV_EXCL_LINE
SLE::Ref sponsorSle = getLedgerEntryReserveSponsor(view, objectSle); auto sponsorSle = getLedgerEntryReserveSponsor(view, objectSle);
decreaseOwnerCount(view, accountSle, sponsorSle, count, j); accountSle.decreaseOwnerCount(sponsorSle, count);
} }
void void
@@ -393,107 +212,10 @@ adjustLoanBrokerOwnerCount(
if (delta == 0) if (delta == 0)
return; // LCOV_EXCL_LINE return; // LCOV_EXCL_LINE
adjustOwnerCountImpl( detail::adjustOwnerCountImpl(
view, brokerSle, sfOwnerCount, brokerSle->getAccountID(sfAccount), delta, j); view, brokerSle, sfOwnerCount, brokerSle->getAccountID(sfAccount), delta, j);
} }
XRPAmount
accountReserve(ReadView const& view, SLE::ConstRef sle, beast::Journal j, Adjustment adj)
{
XRPL_ASSERT(sle && sle->getType() == ltACCOUNT_ROOT, "xrpl::accountReserve : valid sle");
if (!view.rules().enabled(featureSponsor))
{
XRPL_ASSERT(adj.accountCountDelta == 0, "xrpl::accountReserve : no account count delta");
return view.fees().accountReserve(sle->getFieldU32(sfOwnerCount) + adj.ownerCountDelta, 1);
}
std::uint32_t const currentOwnerCount = ownerCount(sle, j, adj.ownerCountDelta);
std::uint32_t const currentAccountCount = accountCountImpl(sle, adj.accountCountDelta, j);
return view.fees().accountReserve(currentOwnerCount, currentAccountCount);
}
TER
checkReserve(
ApplyViewContext ctx,
SLE::ConstRef accSle,
XRPAmount accBalance,
SLE::ConstRef sponsorSle,
Adjustment adj,
beast::Journal j,
TER insufReserveCode)
{
// TODO: swap to assert after fixCleanup3_2_0 is retired
if (!accSle || accSle->getType() != ltACCOUNT_ROOT)
return tefINTERNAL; // LCOV_EXCL_LINE
XRPL_ASSERT(
!isTesSuccess(insufReserveCode), "xrpl::checkReserve : insufReserveCode is not tesSUCCESS");
if (ctx.view.rules().enabled(featureSponsor))
{
if (sponsorSle)
{
if (sponsorSle->getType() != ltACCOUNT_ROOT)
return tefINTERNAL; // LCOV_EXCL_LINE
auto const sle = ctx.view.read(
keylet::sponsorship(
sponsorSle->getAccountID(sfAccount), accSle->getAccountID(sfAccount)));
// A reserve-sponsored tx must carry a sponsor signature
// (cosigning path) and/or have a pre-existing sponsorship SLE
// (prefunded path). Absence of both is an internal invariant break.
if (isReserveSponsored(ctx.tx) && !sle && !ctx.tx.isFieldPresent(sfSponsorSignature))
return tecINTERNAL; // LCOV_EXCL_LINE
if (sle)
{
auto const ownerCountAllowed = sle->getFieldU32(sfRemainingOwnerCount);
if (adj.ownerCountDelta > 0 &&
ownerCountAllowed < static_cast<std::uint32_t>(adj.ownerCountDelta))
return insufReserveCode;
}
auto const sponsorBalance = sponsorSle->getFieldAmount(sfBalance).xrp();
XRPAmount const sponsorReserve = accountReserve(ctx.view, sponsorSle, j, adj);
if (sponsorBalance < sponsorReserve)
return insufReserveCode;
}
else
{
XRPAmount const reserve = accountReserve(ctx.view, accSle, j, adj);
if (accBalance < reserve)
return insufReserveCode;
}
}
else
{
XRPL_ASSERT(
!sponsorSle,
"xrpl::checkReserve : featureSponsor disabled and sponsorSle not provided");
XRPL_ASSERT(adj.accountCountDelta == 0, "xrpl::checkReserve : accountCountDelta is 0");
auto const reserve = ctx.view.fees().accountReserve(
accSle->getFieldU32(sfOwnerCount) + adj.ownerCountDelta, 1);
if (accBalance < reserve)
return insufReserveCode;
}
return tesSUCCESS;
}
TER
checkReserve(
ApplyViewContext ctx,
SLE::ConstRef accSle,
XRPAmount accBalance,
Adjustment adj,
beast::Journal j)
{
auto const sponsorExp = getEffectiveTxReserveSponsor(ctx, accSle);
if (!sponsorExp)
return sponsorExp.error(); // LCOV_EXCL_LINE
return checkReserve(ctx, accSle, accBalance, *sponsorExp, adj, j);
}
// ---------------------------------------------------- // ----------------------------------------------------
AccountID AccountID
@@ -507,7 +229,7 @@ pseudoAccountAddress(ReadView const& view, UInt256 const& pseudoOwnerKey)
auto const hash = sha512Half(i, view.header().parentHash, pseudoOwnerKey); auto const hash = sha512Half(i, view.header().parentHash, pseudoOwnerKey);
rsh(hash.data(), hash.size()); rsh(hash.data(), hash.size());
AccountID const ret = AccountID::fromRaw(static_cast<RipeshaHasher::result_type>(rsh)); AccountID const ret = AccountID::fromRaw(static_cast<RipeshaHasher::result_type>(rsh));
if (!view.read(keylet::account(ret))) if (!AccountRootEntryR(ret, view).exists())
return ret; return ret;
} }
return beast::kZero; return beast::kZero;
@@ -546,7 +268,7 @@ getPseudoAccountFields()
} }
[[nodiscard]] bool [[nodiscard]] bool
isPseudoAccount(SLE::const_pointer sleAcct) isPseudoAccount(AccountRootEntryR const& sleAcct)
{ {
// Intentionally use defensive coding here because it's cheap and makes the // Intentionally use defensive coding here because it's cheap and makes the
// semantics of true return value clean. // semantics of true return value clean.
@@ -599,9 +321,9 @@ createPseudoAccount(ApplyView& view, UInt256 const& pseudoOwnerKey, SField const
} }
[[nodiscard]] TER [[nodiscard]] TER
checkDestinationAndTag(SLE::ConstRef toSle, bool hasDestinationTag) checkDestinationAndTag(AccountRootEntryR const& toSle, bool hasDestinationTag)
{ {
if (toSle == nullptr) if (!toSle.exists())
return tecNO_DST; return tecNO_DST;
// The tag is basically account-specific information we don't // The tag is basically account-specific information we don't
@@ -7,6 +7,7 @@
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -81,7 +82,7 @@ deleteSLE(ApplyView& view, SLE::Ref sleCredential, beast::Journal j)
auto delSLE = [&view, &sleCredential, j]( auto delSLE = [&view, &sleCredential, j](
AccountID const& account, SField const& node, bool isOwner) -> TER { AccountID const& account, SField const& node, bool isOwner) -> TER {
auto const sleAccount = view.peek(keylet::account(account)); auto sleAccount = AccountRootEntryW(account, view);
if (!sleAccount) if (!sleAccount)
{ {
// LCOV_EXCL_START // LCOV_EXCL_START
+15 -11
View File
@@ -7,6 +7,7 @@
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
@@ -206,7 +207,7 @@ authorizeMPToken(
std::uint32_t flags, std::uint32_t flags,
std::optional<AccountID> holderID) std::optional<AccountID> holderID)
{ {
auto const sleAcct = ctx.view.peek(keylet::account(account)); auto sleAcct = AccountRootEntryW(account, ctx.view, journal);
if (!sleAcct) if (!sleAcct)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
@@ -242,10 +243,10 @@ authorizeMPToken(
// - create the MPToken object for the holder // - create the MPToken object for the holder
// A reserve sponsor only covers tx.Account's own objects. // A reserve sponsor only covers tx.Account's own objects.
auto const sponsorExp = getEffectiveTxReserveSponsor(ctx, sleAcct); auto sponsorExp = getEffectiveTxReserveSponsor(ctx, sleAcct);
if (!sponsorExp) if (!sponsorExp)
return sponsorExp.error(); // LCOV_EXCL_LINE return sponsorExp.error(); // LCOV_EXCL_LINE
auto const sponsorSle = *sponsorExp; auto& sponsorSle = *sponsorExp;
// The reserve that is required to create the MPToken. Note // The reserve that is required to create the MPToken. Note
// that although the reserve increases with every item // that although the reserve increases with every item
@@ -255,10 +256,10 @@ authorizeMPToken(
// The "free-tier" shortcut (ownerCount < 2) does not apply once a sponsor is on // The "free-tier" shortcut (ownerCount < 2) does not apply once a sponsor is on
// the tx — the sponsor must always cover the reserve (via balance or prefunded // the tx — the sponsor must always cover the reserve (via balance or prefunded
// budget), so this check always runs for sponsored transactions. // budget), so this check always runs for sponsored transactions.
if (sponsorSle || ownerCount(sleAcct, journal) >= 2) if (sponsorSle || sleAcct.ownerCount() >= 2)
{ {
if (auto const ret = checkReserve( if (auto const ret =
ctx, sleAcct, priorBalance, sponsorSle, {.ownerCountDelta = 1}, journal); sleAcct.checkReserve(ctx, priorBalance, sponsorSle, {.ownerCountDelta = 1});
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
} }
@@ -285,8 +286,8 @@ authorizeMPToken(
ctx.view.insert(mptoken); ctx.view.insert(mptoken);
// Update owner count. // Update owner count.
increaseOwnerCount(ctx.view, sleAcct, sponsorSle, 1, journal); sleAcct.increaseOwnerCount(sponsorSle, 1);
addSponsorToLedgerEntry(mptoken, sponsorSle); addSponsorToLedgerEntry(mptoken, sponsorSle ? sponsorSle->rawSle() : SLE::const_pointer{});
return tesSUCCESS; return tesSUCCESS;
} }
@@ -415,7 +416,7 @@ requireAuth(
} }
// requireAuth is recursive if the issuer is a vault pseudo-account // requireAuth is recursive if the issuer is a vault pseudo-account
auto const sleIssuer = view.read(keylet::account(mptIssuer)); auto const sleIssuer = AccountRootEntryR(mptIssuer, view);
if (!sleIssuer) if (!sleIssuer)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -1020,13 +1021,16 @@ checkCreateMPT(
{ {
return err; return err;
} }
auto const sleAcct = view.peek(keylet::account(holder)); auto sleAcct = AccountRootEntryW(holder, view, j);
if (!sleAcct) if (!sleAcct)
{ {
return tecINTERNAL; return tecINTERNAL;
} }
increaseOwnerCount(view, sleAcct, sponsorSle, 1, j); std::optional<AccountRootEntryW> sponsorAccSle;
if (sponsorSle)
sponsorAccSle.emplace(sponsorSle->getAccountID(sfAccount), view);
sleAcct.increaseOwnerCount(sponsorAccSle, 1);
} }
return tesSUCCESS; return tesSUCCESS;
} }
@@ -7,6 +7,7 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h> #include <xrpl/ledger/helpers/RippleStateHelpers.h>
@@ -855,7 +856,7 @@ tokenOfferCreatePreclaim(
if (nftIssuer != acctID && ((nftFlags & nft::kFlagTransferable) == 0)) if (nftIssuer != acctID && ((nftFlags & nft::kFlagTransferable) == 0))
{ {
auto const root = view.read(keylet::account(nftIssuer)); auto const root = AccountRootEntryR(nftIssuer, view);
XRPL_ASSERT(root, "xrpl::nft::tokenOfferCreatePreclaim : non-null account"); XRPL_ASSERT(root, "xrpl::nft::tokenOfferCreatePreclaim : non-null account");
if (auto minter = (*root)[~sfNFTokenMinter]; minter != acctID) if (auto minter = (*root)[~sfNFTokenMinter]; minter != acctID)
@@ -886,7 +887,7 @@ tokenOfferCreatePreclaim(
{ {
// If a destination is specified, the destination must already be in // If a destination is specified, the destination must already be in
// the ledger. // the ledger.
auto const sleDst = view.read(keylet::account(*dest)); auto const sleDst = AccountRootEntryR(*dest, view);
if (!sleDst) if (!sleDst)
return tecNO_DST; return tecNO_DST;
@@ -898,7 +899,7 @@ tokenOfferCreatePreclaim(
if (owner) if (owner)
{ {
auto const sleOwner = view.read(keylet::account(*owner)); auto const sleOwner = AccountRootEntryR(*owner, view);
// defensively check // defensively check
// it should not be possible to specify owner that doesn't exist // it should not be possible to specify owner that doesn't exist
@@ -937,9 +938,8 @@ tokenOfferCreateApply(
beast::Journal j, beast::Journal j,
std::uint32_t txFlags) std::uint32_t txFlags)
{ {
Keylet const acctKeylet = keylet::account(acctID); if (auto const acct = AccountRootEntryW(acctID, view, j);
if (auto const acct = view.read(acctKeylet); priorBalance < acct.reserve({.ownerCountDelta = 1}))
priorBalance < accountReserve(view, acct, j, {.ownerCountDelta = 1}))
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
auto const offerID = keylet::nftokenOffer(acctID, seqProxy); auto const offerID = keylet::nftokenOffer(acctID, seqProxy);
@@ -1008,7 +1008,7 @@ checkTrustlineAuthorized(
if (view.rules().enabled(fixEnforceNFTokenTrustlineV2)) if (view.rules().enabled(fixEnforceNFTokenTrustlineV2))
{ {
auto const issuerAccount = view.read(keylet::account(issue.account)); auto const issuerAccount = AccountRootEntryR(issue.account, view);
if (!issuerAccount) if (!issuerAccount)
{ {
JLOG(j.debug()) << "xrpl::nft::checkTrustlineAuthorized: can't " JLOG(j.debug()) << "xrpl::nft::checkTrustlineAuthorized: can't "
@@ -1060,7 +1060,7 @@ checkTrustlineDeepFrozen(
if (view.rules().enabled(featureDeepFreeze)) if (view.rules().enabled(featureDeepFreeze))
{ {
auto const issuerAccount = view.read(keylet::account(issue.account)); auto const issuerAccount = AccountRootEntryR(issue.account, view);
if (!issuerAccount) if (!issuerAccount)
{ {
JLOG(j.debug()) << "xrpl::nft::checkTrustlineDeepFrozen: can't " JLOG(j.debug()) << "xrpl::nft::checkTrustlineDeepFrozen: can't "
@@ -6,6 +6,7 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -51,7 +52,7 @@ closeChannel(SLE::Ref slep, ApplyView& view, UInt256 const& key, beast::Journal
} }
// Transfer amount back to owner, decrement owner count // Transfer amount back to owner, decrement owner count
auto const sle = view.peek(keylet::account(src)); auto sle = AccountRootEntryW(src, view);
if (!sle) if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -59,7 +60,7 @@ closeChannel(SLE::Ref slep, ApplyView& view, UInt256 const& key, beast::Journal
(*slep)[sfAmount] >= (*slep)[sfBalance], "xrpl::closeChannel : minimum channel amount"); (*slep)[sfAmount] >= (*slep)[sfBalance], "xrpl::closeChannel : minimum channel amount");
(*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount] - (*slep)[sfBalance]; (*sle)[sfBalance] = (*sle)[sfBalance] + (*slep)[sfAmount] - (*slep)[sfBalance];
decreaseOwnerCountForObject(view, sle, slep, 1, j); decreaseOwnerCountForObject(view, sle, slep, 1, j);
view.update(sle); sle.update();
// Remove PayChan from ledger // Remove PayChan from ledger
view.erase(slep); view.erase(slep);
@@ -7,6 +7,7 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -133,14 +134,14 @@ isFrozen(
{ {
if (isXRP(currency)) if (isXRP(currency))
return false; return false;
auto sle = view.read(keylet::account(issuer)); auto const sleIssuer = AccountRootEntryR(issuer, view);
if (sle && sle->isFlag(lsfGlobalFreeze)) if (sleIssuer && sleIssuer->isFlag(lsfGlobalFreeze))
return true; return true;
if (issuer != account) if (issuer != account)
{ {
// Check if the issuer froze the line // Check if the issuer froze the line
sle = view.read(keylet::trustLine(account, issuer, currency)); auto const sleLine = view.read(keylet::trustLine(account, issuer, currency));
if (sle && sle->isFlag((issuer > account) ? lsfHighFreeze : lsfLowFreeze)) if (sleLine && sleLine->isFlag((issuer > account) ? lsfHighFreeze : lsfLowFreeze))
return true; return true;
} }
return false; return false;
@@ -238,7 +239,7 @@ trustCreate(
XRPL_ASSERT( XRPL_ASSERT(
sleAccount->getAccountID(sfAccount) == (bSetHigh ? uHighAccountID : uLowAccountID), sleAccount->getAccountID(sfAccount) == (bSetHigh ? uHighAccountID : uLowAccountID),
"xrpl::trustCreate : matching account ID"); "xrpl::trustCreate : matching account ID");
auto const slePeer = view.peek(keylet::account(bSetHigh ? uLowAccountID : uHighAccountID)); auto const slePeer = AccountRootEntryW(bSetHigh ? uLowAccountID : uHighAccountID, view);
if (!slePeer) if (!slePeer)
return tecNO_TARGET; return tecNO_TARGET;
@@ -283,7 +284,11 @@ trustCreate(
} }
sleRippleState->setFieldU32(sfFlags, uFlags); sleRippleState->setFieldU32(sfFlags, uFlags);
increaseOwnerCount(view, sleAccount, sponsorSle, 1, j); AccountRootEntryW accountSle(bSetHigh ? uHighAccountID : uLowAccountID, view, j);
std::optional<AccountRootEntryW> sponsorAccSle;
if (sponsorSle)
sponsorAccSle.emplace(sponsorSle->getAccountID(sfAccount), view);
accountSle.increaseOwnerCount(sponsorAccSle, 1);
addSponsorToLedgerEntry(sleRippleState, sponsorSle, bSetHigh ? sfHighSponsor : sfLowSponsor); addSponsorToLedgerEntry(sleRippleState, sponsorSle, bSetHigh ? sfHighSponsor : sfLowSponsor);
@@ -349,7 +354,7 @@ updateTrustLine(
if (!state) if (!state)
return false; return false;
auto sle = view.peek(keylet::account(sender)); auto sle = AccountRootEntryW(sender, view, j);
if (!sle) if (!sle)
return false; return false;
@@ -376,9 +381,9 @@ updateTrustLine(
{ {
// VFALCO Where is the line being deleted? // VFALCO Where is the line being deleted?
// Clear the reserve of the sender, possibly delete the line! // Clear the reserve of the sender, possibly delete the line!
auto const currentSponsor = auto currentSponsor =
getLedgerEntryReserveSponsor(view, state, bSenderHigh ? sfHighSponsor : sfLowSponsor); getLedgerEntryReserveSponsor(view, state, bSenderHigh ? sfHighSponsor : sfLowSponsor);
decreaseOwnerCount(view, sle, currentSponsor, 1, j); sle.decreaseOwnerCount(currentSponsor, 1);
// Clear reserve flag. // Clear reserve flag.
state->clearFlag(senderReserveFlag); state->clearFlag(senderReserveFlag);
@@ -464,7 +469,7 @@ issueIOU(
finalBalance.get<Issue>().account = noAccount(); finalBalance.get<Issue>().account = noAccount();
auto const receiverAccount = view.peek(keylet::account(account)); auto receiverAccount = AccountRootEntryW(account, view);
if (!receiverAccount) if (!receiverAccount)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -476,7 +481,7 @@ issueIOU(
issue.account, issue.account,
account, account,
index.key, index.key,
receiverAccount, receiverAccount.mutableRawSle(),
false, false,
noRipple, noRipple,
false, false,
@@ -579,7 +584,7 @@ requireAuth(ReadView const& view, Issue const& issue, AccountID const& account,
// If this is a weak or legacy check, or if the account has a line, fail if // If this is a weak or legacy check, or if the account has a line, fail if
// auth is required and not set on the line // auth is required and not set on the line
if (auto const issuerAccount = view.read(keylet::account(issue.account)); if (auto const issuerAccount = AccountRootEntryR(issue.account, view);
issuerAccount && issuerAccount->isFlag(lsfRequireAuth)) issuerAccount && issuerAccount->isFlag(lsfRequireAuth))
{ {
if (trustLine) if (trustLine)
@@ -609,8 +614,8 @@ canTransfer(ReadView const& view, Issue const& issue, AccountID const& from, Acc
auto const& issuerId = issue.getIssuer(); auto const& issuerId = issue.getIssuer();
if (issuerId == from || issuerId == to) if (issuerId == from || issuerId == to)
return tesSUCCESS; return tesSUCCESS;
auto const sleIssuer = view.read(keylet::account(issuerId)); auto const sleIssuer = AccountRootEntryR(issuerId, view);
if (sleIssuer == nullptr) if (!sleIssuer.exists())
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
auto const isRippleDisabled = [&](AccountID account) -> bool { auto const isRippleDisabled = [&](AccountID account) -> bool {
@@ -665,8 +670,8 @@ addEmptyHolding(
if (isGlobalFrozen(ctx.view, issuerId)) if (isGlobalFrozen(ctx.view, issuerId))
return tecFROZEN; // LCOV_EXCL_LINE return tecFROZEN; // LCOV_EXCL_LINE
auto const sleSrc = ctx.view.peek(keylet::account(srcId)); auto const sleSrc = AccountRootEntryW(srcId, ctx.view);
auto const sleDst = ctx.view.peek(keylet::account(dstId)); auto sleDst = AccountRootEntryW(dstId, ctx.view, journal);
if (!sleDst || !sleSrc) if (!sleDst || !sleSrc)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
// Create path: DefaultRipple is still required. terNO_RIPPLE is // Create path: DefaultRipple is still required. terNO_RIPPLE is
@@ -681,20 +686,14 @@ addEmptyHolding(
return tecDUPLICATE; return tecDUPLICATE;
// A reserve sponsor only covers tx.Account's own objects. // A reserve sponsor only covers tx.Account's own objects.
auto const sponsorExp = getEffectiveTxReserveSponsor(ctx, sleDst); auto sponsorExp = getEffectiveTxReserveSponsor(ctx, sleDst);
if (!sponsorExp) if (!sponsorExp)
return sponsorExp.error(); // LCOV_EXCL_LINE return sponsorExp.error(); // LCOV_EXCL_LINE
auto const sponsorSle = *sponsorExp; auto& sponsorSle = *sponsorExp;
// Can the account cover the trust line reserve ? // Can the account cover the trust line reserve ?
if (auto const ret = checkReserve( if (auto const ret = sleDst.checkReserve(
ctx, ctx, priorBalance, sponsorSle, {.ownerCountDelta = 1}, tecNO_LINE_INSUF_RESERVE);
sleDst,
priorBalance,
sponsorSle,
{.ownerCountDelta = 1},
journal,
tecNO_LINE_INSUF_RESERVE);
!isTesSuccess(ret)) !isTesSuccess(ret))
{ {
return ret; return ret;
@@ -706,7 +705,7 @@ addEmptyHolding(
srcId, srcId,
dstId, dstId,
index.key, index.key,
sleDst, sleDst.mutableRawSle(),
/*bAuth=*/false, /*bAuth=*/false,
/*bNoRipple=*/true, /*bNoRipple=*/true,
/*bFreeze=*/false, /*bFreeze=*/false,
@@ -715,7 +714,7 @@ addEmptyHolding(
/*saLimit=*/STAmount{Issue{currency, dstId}}, /*saLimit=*/STAmount{Issue{currency, dstId}},
/*uQualityIn=*/0, /*uQualityIn=*/0,
/*uQualityOut=*/0, /*uQualityOut=*/0,
sponsorSle, sponsorSle ? sponsorSle->mutableRawSle() : SLE::pointer{},
journal); journal);
} }
@@ -728,7 +727,7 @@ removeEmptyHolding(
{ {
if (issue.native()) if (issue.native())
{ {
auto const sle = ctx.view.read(keylet::account(accountID)); auto const sle = AccountRootEntryW(accountID, ctx.view);
if (!sle) if (!sle)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
@@ -753,13 +752,14 @@ removeEmptyHolding(
if (line->isFlag(lsfLowReserve)) if (line->isFlag(lsfLowReserve))
{ {
// Clear reserve for low account. // Clear reserve for low account.
auto sleLowAccount = ctx.view.peek(keylet::account(line->at(sfLowLimit)->getIssuer())); auto sleLowAccount =
AccountRootEntryW(line->at(sfLowLimit)->getIssuer(), ctx.view, journal);
if (!sleLowAccount) if (!sleLowAccount)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
auto const currentLowSponsor = getLedgerEntryReserveSponsor(ctx.view, line, sfLowSponsor); auto currentLowSponsor = getLedgerEntryReserveSponsor(ctx.view, line, sfLowSponsor);
decreaseOwnerCount(ctx.view, sleLowAccount, currentLowSponsor, 1, journal); sleLowAccount.decreaseOwnerCount(currentLowSponsor, 1);
// It's not really necessary to clear the reserve flag, since the line // It's not really necessary to clear the reserve flag, since the line
// is about to be deleted, but this will make the metadata reflect an // is about to be deleted, but this will make the metadata reflect an
// accurate state at the time of deletion. // accurate state at the time of deletion.
@@ -770,13 +770,14 @@ removeEmptyHolding(
if (line->isFlag(lsfHighReserve)) if (line->isFlag(lsfHighReserve))
{ {
// Clear reserve for high account. // Clear reserve for high account.
auto sleHighAccount = ctx.view.peek(keylet::account(line->at(sfHighLimit)->getIssuer())); auto sleHighAccount =
AccountRootEntryW(line->at(sfHighLimit)->getIssuer(), ctx.view, journal);
if (!sleHighAccount) if (!sleHighAccount)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
auto const currentHighSponsor = getLedgerEntryReserveSponsor(ctx.view, line, sfHighSponsor); auto currentHighSponsor = getLedgerEntryReserveSponsor(ctx.view, line, sfHighSponsor);
decreaseOwnerCount(ctx.view, sleHighAccount, currentHighSponsor, 1, journal); sleHighAccount.decreaseOwnerCount(currentHighSponsor, 1);
// It's not really necessary to clear the reserve flag, since the line // It's not really necessary to clear the reserve flag, since the line
// is about to be deleted, but this will make the metadata reflect an // is about to be deleted, but this will make the metadata reflect an
// accurate state at the time of deletion. // accurate state at the time of deletion.
@@ -805,8 +806,8 @@ deleteAMMTrustLine(
auto const& [low, high] = std::minmax( auto const& [low, high] = std::minmax(
sleState->getFieldAmount(sfLowLimit).getIssuer(), sleState->getFieldAmount(sfLowLimit).getIssuer(),
sleState->getFieldAmount(sfHighLimit).getIssuer()); sleState->getFieldAmount(sfHighLimit).getIssuer());
auto sleLow = view.peek(keylet::account(low)); auto sleLow = AccountRootEntryW(low, view, j);
auto sleHigh = view.peek(keylet::account(high)); auto sleHigh = AccountRootEntryW(high, view, j);
if (!sleLow || !sleHigh) if (!sleLow || !sleHigh)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
@@ -825,7 +826,7 @@ deleteAMMTrustLine(
if (ammAccountID && (low != *ammAccountID && high != *ammAccountID)) if (ammAccountID && (low != *ammAccountID && high != *ammAccountID))
return terNO_AMM; return terNO_AMM;
auto const sponsorSle = auto sponsorSle =
getLedgerEntryReserveSponsor(view, sleState, !ammLow ? sfLowSponsor : sfHighSponsor); getLedgerEntryReserveSponsor(view, sleState, !ammLow ? sfLowSponsor : sfHighSponsor);
if (auto const ter = trustDelete(view, sleState, low, high, j); !isTesSuccess(ter)) if (auto const ter = trustDelete(view, sleState, low, high, j); !isTesSuccess(ter))
@@ -838,7 +839,7 @@ deleteAMMTrustLine(
if (!sleState->isFlag(uFlags)) if (!sleState->isFlag(uFlags))
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
decreaseOwnerCount(view, !ammLow ? sleLow : sleHigh, sponsorSle, 1, j); (!ammLow ? sleLow : sleHigh).decreaseOwnerCount(sponsorSle, 1);
return tesSUCCESS; return tesSUCCESS;
} }
+19 -18
View File
@@ -3,6 +3,7 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/OracleHelpers.h> #include <xrpl/ledger/helpers/OracleHelpers.h>
#include <xrpl/ledger/helpers/ProposalHelpers.h> #include <xrpl/ledger/helpers/ProposalHelpers.h>
@@ -76,7 +77,7 @@ getTxReserveSponsorID(STTx const& tx)
return {}; return {};
} }
std::expected<SLE::pointer, TER> std::expected<std::optional<AccountRootEntryW>, TER>
getTxReserveSponsor(ApplyViewContext ctx) getTxReserveSponsor(ApplyViewContext ctx)
{ {
auto const sponsorID = getTxReserveSponsorID(ctx.tx); auto const sponsorID = getTxReserveSponsorID(ctx.tx);
@@ -85,17 +86,17 @@ getTxReserveSponsor(ApplyViewContext ctx)
XRPL_ASSERT( XRPL_ASSERT(
ctx.view.rules().enabled(featureSponsor), ctx.view.rules().enabled(featureSponsor),
"xrpl::getTxReserveSponsor : sponsor exists + Sponsor enabled"); "xrpl::getTxReserveSponsor : sponsor exists + Sponsor enabled");
auto sle = ctx.view.peek(keylet::account(*sponsorID)); auto sle = AccountRootEntryW(*sponsorID, ctx.view);
// already checked in Transactor::checkSponsor // already checked in Transactor::checkSponsor
if (!sle) if (!sle.exists())
return std::unexpected(tecINTERNAL); // LCOV_EXCL_LINE return std::unexpected(tecINTERNAL); // LCOV_EXCL_LINE
return sle; return sle;
} }
return SLE::pointer(); return std::nullopt;
} }
std::expected<SLE::const_pointer, TER> std::expected<std::optional<AccountRootEntryR>, TER>
getTxReserveSponsor(ReadView const& view, STTx const& tx) getTxReserveSponsor(ReadView const& view, STTx const& tx)
{ {
auto const sponsorID = getTxReserveSponsorID(tx); auto const sponsorID = getTxReserveSponsorID(tx);
@@ -104,18 +105,18 @@ getTxReserveSponsor(ReadView const& view, STTx const& tx)
XRPL_ASSERT( XRPL_ASSERT(
view.rules().enabled(featureSponsor), view.rules().enabled(featureSponsor),
"xrpl::getTxReserveSponsor : sponsor exists + Sponsor enabled"); "xrpl::getTxReserveSponsor : sponsor exists + Sponsor enabled");
auto sle = view.read(keylet::account(*sponsorID)); auto sle = AccountRootEntryR(*sponsorID, view);
// already checked in Transactor::checkSponsor // already checked in Transactor::checkSponsor
if (!sle) if (!sle.exists())
return std::unexpected(tecINTERNAL); // LCOV_EXCL_LINE return std::unexpected(tecINTERNAL); // LCOV_EXCL_LINE
return sle; return sle;
} }
return SLE::pointer(); return std::nullopt;
} }
std::expected<SLE::pointer, TER> std::expected<std::optional<AccountRootEntryW>, TER>
getEffectiveTxReserveSponsor(ApplyViewContext ctx, SLE::ConstRef accountSle) getEffectiveTxReserveSponsor(ApplyViewContext ctx, AccountRootEntryR const& accountSle)
{ {
// A reserve sponsor only covers tx.Account's own objects. // A reserve sponsor only covers tx.Account's own objects.
if (ctx.view.rules().enabled(fixCleanup3_2_0)) if (ctx.view.rules().enabled(fixCleanup3_2_0))
@@ -133,7 +134,7 @@ getEffectiveTxReserveSponsor(ApplyViewContext ctx, SLE::ConstRef accountSle)
} }
if (isPseudoAccount(accountSle) || accountSle->getAccountID(sfAccount) != ctx.tx[sfAccount]) if (isPseudoAccount(accountSle) || accountSle->getAccountID(sfAccount) != ctx.tx[sfAccount])
return SLE::pointer(); return std::nullopt;
return getTxReserveSponsor(ctx); return getTxReserveSponsor(ctx);
} }
@@ -151,7 +152,7 @@ getLedgerEntryReserveSponsorID(SLE::ConstRef sle, SF_ACCOUNT const& field)
return {}; return {};
} }
SLE::pointer std::optional<AccountRootEntryW>
getLedgerEntryReserveSponsor(ApplyView& view, SLE::ConstRef sle, SF_ACCOUNT const& field) getLedgerEntryReserveSponsor(ApplyView& view, SLE::ConstRef sle, SF_ACCOUNT const& field)
{ {
auto const sponsorID = getLedgerEntryReserveSponsorID(sle, field); auto const sponsorID = getLedgerEntryReserveSponsorID(sle, field);
@@ -160,9 +161,9 @@ getLedgerEntryReserveSponsor(ApplyView& view, SLE::ConstRef sle, SF_ACCOUNT cons
XRPL_ASSERT( XRPL_ASSERT(
view.rules().enabled(featureSponsor), view.rules().enabled(featureSponsor),
"xrpl::getLedgerEntryReserveSponsor : sponsor exists + Sponsor enabled"); "xrpl::getLedgerEntryReserveSponsor : sponsor exists + Sponsor enabled");
return view.peek(keylet::account(*sponsorID)); return AccountRootEntryW(*sponsorID, view);
} }
return {}; return std::nullopt;
} }
void void
@@ -185,16 +186,16 @@ addSponsorToLedgerEntry(SLE::Ref sle, SLE::ConstRef sponsorSle, SF_ACCOUNT const
void void
addSponsorToLedgerEntry(ApplyViewContext ctx, SLE::Ref sle, SF_ACCOUNT const& field) addSponsorToLedgerEntry(ApplyViewContext ctx, SLE::Ref sle, SF_ACCOUNT const& field)
{ {
// getTxReserveSponsor yields a null pointer when the tx is not // getTxReserveSponsor yields nullopt when the tx is not reserve-sponsored,
// reserve-sponsored, so addSponsorToLedgerEntry becomes a no-op then. The // so addSponsorToLedgerEntry becomes a no-op then. The error case
// error case (tecINTERNAL) is an already-checked invariant; skip stamping. // (tecINTERNAL) is an already-checked invariant; skip stamping.
auto const sponsorSle = getTxReserveSponsor(ctx); auto const sponsorSle = getTxReserveSponsor(ctx);
if (sponsorSle && *sponsorSle) if (sponsorSle && *sponsorSle)
{ {
XRPL_ASSERT( XRPL_ASSERT(
ctx.view.rules().enabled(featureSponsor), ctx.view.rules().enabled(featureSponsor),
"xrpl::addSponsorToLedgerEntry : sponsor exists + Sponsor enabled"); "xrpl::addSponsorToLedgerEntry : sponsor exists + Sponsor enabled");
addSponsorToLedgerEntry(sle, *sponsorSle, field); addSponsorToLedgerEntry(sle, (**sponsorSle).rawSle(), field);
} }
} }
+24 -18
View File
@@ -7,6 +7,7 @@
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h> #include <xrpl/ledger/helpers/RippleStateHelpers.h>
@@ -293,7 +294,7 @@ getLineIfUsable(
// we need to check if the associated assets have been frozen // we need to check if the associated assets have been frozen
if (view.rules().enabled(fixFrozenLPTokenTransfer)) if (view.rules().enabled(fixFrozenLPTokenTransfer))
{ {
auto const sleIssuer = view.read(keylet::account(issuer)); auto const sleIssuer = AccountRootEntryR(issuer, view);
if (!sleIssuer) if (!sleIssuer)
{ {
return nullptr; // LCOV_EXCL_LINE return nullptr; // LCOV_EXCL_LINE
@@ -562,7 +563,7 @@ canAddHolding(ReadView const& view, Issue const& issue)
return tesSUCCESS; // No special checks for XRP return tesSUCCESS; // No special checks for XRP
} }
auto const issuer = view.read(keylet::account(issue.getIssuer())); auto const issuer = AccountRootEntryR(issue.getIssuer(), view);
if (!issuer) if (!issuer)
{ {
return terNO_ACCOUNT; return terNO_ACCOUNT;
@@ -738,6 +739,8 @@ directSendNoFeeIOU(
auto const senderFreezeFlag = bSenderHigh ? lsfHighFreeze : lsfLowFreeze; auto const senderFreezeFlag = bSenderHigh ? lsfHighFreeze : lsfLowFreeze;
auto const receiverReserveFlag = bSenderHigh ? lsfLowReserve : lsfHighReserve; auto const receiverReserveFlag = bSenderHigh ? lsfLowReserve : lsfHighReserve;
AccountRootEntryW senderSle(uSenderID, view, j);
// FIXME This NEEDS to be cleaned up and simplified. It's impossible // FIXME This NEEDS to be cleaned up and simplified. It's impossible
// for anyone to understand. // for anyone to understand.
if (saBefore > beast::kZero if (saBefore > beast::kZero
@@ -746,8 +749,7 @@ directSendNoFeeIOU(
// Sender is zero or negative. // Sender is zero or negative.
&& sleRippleState->isFlag(senderReserveFlag) && sleRippleState->isFlag(senderReserveFlag)
// Sender reserve is set. // Sender reserve is set.
&& sleRippleState->isFlag(senderNoRippleFlag) != && sleRippleState->isFlag(senderNoRippleFlag) != senderSle->isFlag(lsfDefaultRipple) &&
view.read(keylet::account(uSenderID))->isFlag(lsfDefaultRipple) &&
!sleRippleState->isFlag(senderFreezeFlag) && !sleRippleState->isFlag(senderFreezeFlag) &&
!sleRippleState->getFieldAmount(bSenderHigh ? sfHighLimit : sfLowLimit) !sleRippleState->getFieldAmount(bSenderHigh ? sfHighLimit : sfLowLimit)
// Sender trust limit is 0. // Sender trust limit is 0.
@@ -758,9 +760,9 @@ directSendNoFeeIOU(
// Sender quality out is 0. // Sender quality out is 0.
{ {
// Clear the reserve of the sender, possibly delete the line! // Clear the reserve of the sender, possibly delete the line!
auto const currentSponsor = getLedgerEntryReserveSponsor( auto currentSponsor = getLedgerEntryReserveSponsor(
view, sleRippleState, !bSenderHigh ? sfLowSponsor : sfHighSponsor); view, sleRippleState, !bSenderHigh ? sfLowSponsor : sfHighSponsor);
decreaseOwnerCount(view, view.peek(keylet::account(uSenderID)), currentSponsor, 1, j); senderSle.decreaseOwnerCount(currentSponsor, 1);
removeSponsorFromLedgerEntry( removeSponsorFromLedgerEntry(
sleRippleState, !bSenderHigh ? sfLowSponsor : sfHighSponsor); sleRippleState, !bSenderHigh ? sfLowSponsor : sfHighSponsor);
@@ -805,7 +807,7 @@ directSendNoFeeIOU(
<< to_string(uSenderID) << " -> " << to_string(uReceiverID) << " : " << to_string(uSenderID) << " -> " << to_string(uReceiverID) << " : "
<< saAmount.getFullText(); << saAmount.getFullText();
auto const sleAccount = view.peek(keylet::account(uReceiverID)); auto sleAccount = AccountRootEntryW(uReceiverID, view);
if (!sleAccount) if (!sleAccount)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -817,7 +819,7 @@ directSendNoFeeIOU(
uSenderID, uSenderID,
uReceiverID, uReceiverID,
index.key, index.key,
sleAccount, sleAccount.mutableRawSle(),
false, false,
noRipple, noRipple,
false, false,
@@ -1010,10 +1012,12 @@ accountSendIOU(
*/ */
TER terResult(tesSUCCESS); TER terResult(tesSUCCESS);
SLE::pointer const sender = SLE::pointer const sender = uSenderID != beast::kZero
uSenderID != beast::kZero ? view.peek(keylet::account(uSenderID)) : SLE::pointer(); ? AccountRootEntryW(uSenderID, view).mutableRawSle()
SLE::pointer const receiver = : SLE::pointer();
uReceiverID != beast::kZero ? view.peek(keylet::account(uReceiverID)) : SLE::pointer(); SLE::pointer const receiver = uReceiverID != beast::kZero
? AccountRootEntryW(uReceiverID, view).mutableRawSle()
: SLE::pointer();
if (auto stream = j.trace()) if (auto stream = j.trace())
{ {
@@ -1106,8 +1110,9 @@ accountSendMultiIOU(
* ensure that transfers are balanced. * ensure that transfers are balanced.
*/ */
SLE::pointer const sender = SLE::pointer const sender = senderID != beast::kZero
senderID != beast::kZero ? view.peek(keylet::account(senderID)) : SLE::pointer(); ? AccountRootEntryW(senderID, view).mutableRawSle()
: SLE::pointer();
if (auto stream = j.trace()) if (auto stream = j.trace())
{ {
@@ -1138,8 +1143,9 @@ accountSendMultiIOU(
if (!amount || (senderID == receiverID)) if (!amount || (senderID == receiverID))
continue; continue;
SLE::pointer const receiver = SLE::pointer const receiver = receiverID != beast::kZero
receiverID != beast::kZero ? view.peek(keylet::account(receiverID)) : SLE::pointer(); ? AccountRootEntryW(receiverID, view).mutableRawSle()
: SLE::pointer();
if (auto stream = j.trace()) if (auto stream = j.trace())
{ {
@@ -1591,8 +1597,8 @@ transferXRP(
XRPL_ASSERT(from != to, "xrpl::transferXRP : sender is not receiver"); XRPL_ASSERT(from != to, "xrpl::transferXRP : sender is not receiver");
XRPL_ASSERT(amount.native(), "xrpl::transferXRP : amount is XRP"); XRPL_ASSERT(amount.native(), "xrpl::transferXRP : amount is XRP");
SLE::pointer const sender = view.peek(keylet::account(from)); SLE::pointer const sender = AccountRootEntryW(from, view).mutableRawSle();
SLE::pointer const receiver = view.peek(keylet::account(to)); SLE::pointer const receiver = AccountRootEntryW(to, view).mutableRawSle();
if (!sender || !receiver) if (!sender || !receiver)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
+19 -18
View File
@@ -11,6 +11,7 @@
#include <xrpl/json/to_string.h> // IWYU pragma: keep #include <xrpl/json/to_string.h> // IWYU pragma: keep
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DelegateHelpers.h> #include <xrpl/ledger/helpers/DelegateHelpers.h>
@@ -586,7 +587,7 @@ Transactor::checkFee(PreclaimContext const& ctx, XRPAmount baseFee)
if (feePayer.type == FeePayerType::SponsorCoSigned) if (feePayer.type == FeePayerType::SponsorCoSigned)
{ {
auto const sponsorReserve = accountReserve(ctx.view, payerSle, ctx.j); auto const sponsorReserve = accountReserve(ctx.view, feePayer.id, ctx.j);
maxSpendable = payerSle->getFieldAmount(sfBalance).xrp() - sponsorReserve; maxSpendable = payerSle->getFieldAmount(sfBalance).xrp() - sponsorReserve;
} }
else else
@@ -652,7 +653,7 @@ Transactor::payFee()
XRPAmount spendable = balance; XRPAmount spendable = balance;
if (feePayer.type == FeePayerType::SponsorCoSigned) if (feePayer.type == FeePayerType::SponsorCoSigned)
{ {
auto const sponsorReserve = accountReserve(view(), sle, j_); auto const sponsorReserve = accountReserve(view(), feePayer.id, j_);
// max(balance - reserve, 0) with overflow handling // max(balance - reserve, 0) with overflow handling
spendable = balance > sponsorReserve ? balance - sponsorReserve : beast::kZero; spendable = balance > sponsorReserve ? balance - sponsorReserve : beast::kZero;
} }
@@ -700,7 +701,7 @@ Transactor::checkSeqProxy(ReadView const& view, STTx const& tx, beast::Journal j
{ {
auto const id = tx.getAccountID(sfAccount); auto const id = tx.getAccountID(sfAccount);
auto const sle = view.read(keylet::account(id)); auto const sle = AccountRootEntryR(id, view);
if (!sle) if (!sle)
{ {
@@ -765,7 +766,7 @@ Transactor::checkPriorTxAndLastLedger(PreclaimContext const& ctx)
{ {
auto const id = ctx.tx.getAccountID(sfAccount); auto const id = ctx.tx.getAccountID(sfAccount);
auto const sle = ctx.view.read(keylet::account(id)); auto const sle = AccountRootEntryR(id, ctx.view);
if (!sle) if (!sle)
{ {
@@ -835,7 +836,7 @@ Transactor::ticketDelete(
// Update the account root's TicketCount. If the ticket count drops to // Update the account root's TicketCount. If the ticket count drops to
// zero remove the (optional) field. // zero remove the (optional) field.
auto sleAccount = view.peek(keylet::account(account)); auto sleAccount = AccountRootEntryW(account, view);
if (!sleAccount) if (!sleAccount)
{ {
// LCOV_EXCL_START // LCOV_EXCL_START
@@ -885,19 +886,19 @@ Transactor::apply()
// If the transactor requires a valid account and the transaction doesn't // If the transactor requires a valid account and the transaction doesn't
// list one, preflight will have already a flagged a failure. // list one, preflight will have already a flagged a failure.
auto const sle = view().peek(keylet::account(accountID_)); auto sle = AccountRootEntryW(accountID_, view());
// sle must exist except for transactions // sle must exist except for transactions
// that allow zero account. // that allow zero account.
XRPL_ASSERT( XRPL_ASSERT(
sle != nullptr || accountID_ == beast::kZero, sle.exists() || accountID_ == beast::kZero,
"xrpl::Transactor::apply : non-null SLE or zero account"); "xrpl::Transactor::apply : non-null SLE or zero account");
if (sle) if (sle)
{ {
preFeeBalance_ = STAmount{(*sle)[sfBalance]}.xrp(); preFeeBalance_ = STAmount{(*sle)[sfBalance]}.xrp();
TER result = consumeSeqProxy(sle); TER result = consumeSeqProxy(sle.mutableRawSle());
if (!isTesSuccess(result)) if (!isTesSuccess(result))
return result; return result;
@@ -908,7 +909,7 @@ Transactor::apply()
if (sle->isFieldPresent(sfAccountTxnID)) if (sle->isFieldPresent(sfAccountTxnID))
sle->setFieldH256(sfAccountTxnID, ctx_.tx.getTransactionID()); sle->setFieldH256(sfAccountTxnID, ctx_.tx.getTransactionID());
view().update(sle); sle.update();
} }
return doApply(); return doApply();
@@ -925,7 +926,7 @@ Transactor::checkSign(
bool permitUncreatedAccount) bool permitUncreatedAccount)
{ {
{ {
auto const sle = view.read(keylet::account(idAccount)); auto const sle = AccountRootEntryR(idAccount, view);
if ((view.rules().enabled(featureLendingProtocol) || if ((view.rules().enabled(featureLendingProtocol) ||
view.rules().enabled(featureBatchV1_1) || view.rules().enabled(fixCleanup3_3_0)) && view.rules().enabled(featureBatchV1_1) || view.rules().enabled(fixCleanup3_3_0)) &&
@@ -991,7 +992,7 @@ Transactor::checkSign(
// Look up the account. // Look up the account.
auto const idSigner = calcAccountID(PublicKey(makeSlice(pkSigner))); auto const idSigner = calcAccountID(PublicKey(makeSlice(pkSigner)));
auto const sleAccount = view.read(keylet::account(idAccount)); auto const sleAccount = AccountRootEntryR(idAccount, view);
if (!sleAccount) if (!sleAccount)
{ {
// An account that does not exist yet can only be authorized by its own // An account that does not exist yet can only be authorized by its own
@@ -1004,7 +1005,7 @@ Transactor::checkSign(
return tesSUCCESS; return tesSUCCESS;
} }
return checkSingleSign(view, idSigner, idAccount, sleAccount, j); return checkSingleSign(view, idSigner, idAccount, sleAccount.rawSle(), j);
} }
NotTEC NotTEC
@@ -1153,7 +1154,7 @@ Transactor::checkMultiSign(
// In any of these cases we need to know whether the account is in // In any of these cases we need to know whether the account is in
// the ledger. Determine that now. // the ledger. Determine that now.
auto const sleTxSignerRoot = view.read(keylet::account(txSignerAcctID)); auto const sleTxSignerRoot = AccountRootEntryR(txSignerAcctID, view);
if (signingAcctIDFromPubKey == txSignerAcctID) if (signingAcctIDFromPubKey == txSignerAcctID)
{ {
@@ -1296,7 +1297,7 @@ Transactor::reset(XRPAmount fee)
{ {
ctx_.discard(); ctx_.discard();
auto const txnAcct = view().peek(keylet::account(ctx_.tx.getAccountID(sfAccount))); auto txnAcct = AccountRootEntryW(ctx_.tx.getAccountID(sfAccount), view());
// The account should never be missing from the ledger. But if it // The account should never be missing from the ledger. But if it
// is missing then we can't very well charge it a fee, can we? // is missing then we can't very well charge it a fee, can we?
@@ -1331,7 +1332,7 @@ Transactor::reset(XRPAmount fee)
XRPAmount spendable = balance; XRPAmount spendable = balance;
if (feePayer.type == FeePayerType::SponsorCoSigned) if (feePayer.type == FeePayerType::SponsorCoSigned)
{ {
auto const sponsorReserve = accountReserve(view(), payerSle, j_); auto const sponsorReserve = accountReserve(view(), feePayer.id, j_);
// max(balance - reserve, 0) with overflow handling // max(balance - reserve, 0) with overflow handling
spendable = balance > sponsorReserve ? balance - sponsorReserve : beast::kZero; spendable = balance > sponsorReserve ? balance - sponsorReserve : beast::kZero;
} }
@@ -1364,13 +1365,13 @@ Transactor::reset(XRPAmount fee)
payerSle->setFieldAmount(feePayer.balanceField, feeAmountAfter); payerSle->setFieldAmount(feePayer.balanceField, feeAmountAfter);
} }
TER const ter{consumeSeqProxy(txnAcct)}; TER const ter{consumeSeqProxy(txnAcct.mutableRawSle())};
XRPL_ASSERT(isTesSuccess(ter), "xrpl::Transactor::reset : result is tesSUCCESS"); XRPL_ASSERT(isTesSuccess(ter), "xrpl::Transactor::reset : result is tesSUCCESS");
if (isTesSuccess(ter)) if (isTesSuccess(ter))
{ {
view().update(txnAcct); txnAcct.update();
if (payerSle != txnAcct) if (payerSle != txnAcct.mutableRawSle())
view().update(payerSle); view().update(payerSle);
} }
+13 -4
View File
@@ -735,6 +735,15 @@ NoDeepFreezeTrustLinesWithoutFreeze::finalize(
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool
isPseudoAccountSle(SLE::ConstRef sleAcct)
{
auto const& fields = getPseudoAccountFields();
return sleAcct && sleAcct->getType() == ltACCOUNT_ROOT &&
std::ranges::any_of(
fields, [&sleAcct](SField const* sf) { return sleAcct->isFieldPresent(*sf); });
}
void void
ValidNewAccountRoot::visitEntry(bool, SLE::ConstRef before, SLE::ConstRef after) ValidNewAccountRoot::visitEntry(bool, SLE::ConstRef before, SLE::ConstRef after)
{ {
@@ -742,7 +751,7 @@ ValidNewAccountRoot::visitEntry(bool, SLE::ConstRef before, SLE::ConstRef after)
{ {
accountsCreated_++; accountsCreated_++;
accountSeq_ = (*after)[sfSequence]; accountSeq_ = (*after)[sfSequence];
pseudoAccount_ = isPseudoAccount(after); pseudoAccount_ = isPseudoAccountSle(after);
flags_ = after->getFlags(); flags_ = after->getFlags();
} }
} }
@@ -1020,9 +1029,9 @@ ValidPseudoAccounts::visitEntry(bool isDelete, SLE::ConstRef before, SLE::ConstR
if (after && after->getType() == ltACCOUNT_ROOT) if (after && after->getType() == ltACCOUNT_ROOT)
{ {
bool const isPseudo = [&]() { bool const isPseudo = [&]() {
// isPseudoAccount checks that any of the pseudo-account fields are // isPseudoAccountSle checks that any of the pseudo-account fields
// set. // are set.
if (isPseudoAccount(after)) if (isPseudoAccountSle(after))
return true; return true;
// Not all pseudo-accounts have a zero sequence, but all accounts // Not all pseudo-accounts have a zero sequence, but all accounts
// with a zero sequence had better be pseudo-accounts. // with a zero sequence had better be pseudo-accounts.
+2 -1
View File
@@ -23,6 +23,7 @@
#include <xrpl/protocol/TxFormats.h> #include <xrpl/protocol/TxFormats.h>
#include <xrpl/protocol/UintTypes.h> #include <xrpl/protocol/UintTypes.h>
#include <xrpl/protocol/XRPAmount.h> #include <xrpl/protocol/XRPAmount.h>
#include <xrpl/tx/invariants/InvariantCheck.h>
#include <xrpl/tx/invariants/InvariantCheckPrivilege.h> #include <xrpl/tx/invariants/InvariantCheckPrivilege.h>
#include <algorithm> #include <algorithm>
@@ -893,7 +894,7 @@ ValidMPTTransfer::visitEntry(
// no trace of its pseudo-account status in the post-transaction view // no trace of its pseudo-account status in the post-transaction view
// isAuthorized() sees at finalize() time. // isAuthorized() sees at finalize() time.
if (before && before->getType() == ltACCOUNT_ROOT) if (before && before->getType() == ltACCOUNT_ROOT)
pseudoAccountsBefore_[before->at(sfAccount)] = isPseudoAccount(before); pseudoAccountsBefore_[before->at(sfAccount)] = isPseudoAccountSle(before);
} }
bool bool
+1 -1
View File
@@ -740,7 +740,7 @@ ValidVault::finalize(
return false; return false;
} }
if (!isPseudoAccount(sleSharesIssuer)) if (!isPseudoAccount(AccountRootEntryR(sleSharesIssuer, view)))
{ {
JLOG(j.fatal()) // JLOG(j.fatal()) //
<< "Invariant failed: shares issuer must be a " << "Invariant failed: shares issuer must be a "
+3 -2
View File
@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/PaymentSandbox.h> #include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h> #include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -836,7 +837,7 @@ DirectStepI<TDerived>::check(StrandContext const& ctx) const
return temBAD_PATH; return temBAD_PATH;
} }
auto const sleSrc = ctx.view.read(keylet::account(src_)); auto const sleSrc = AccountRootEntryR(src_, ctx.view);
if (!sleSrc) if (!sleSrc)
{ {
JLOG(j_.warn()) << "DirectStepI: can't receive IOUs from non-existent issuer: " << src_; JLOG(j_.warn()) << "DirectStepI: can't receive IOUs from non-existent issuer: " << src_;
@@ -902,7 +903,7 @@ DirectStepI<TDerived>::check(StrandContext const& ctx) const
} }
} }
return static_cast<TDerived const*>(this)->check(ctx, sleSrc); return static_cast<TDerived const*>(this)->check(ctx, sleSrc.rawSle());
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
+3 -2
View File
@@ -6,6 +6,7 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/PaymentSandbox.h> #include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
@@ -865,7 +866,7 @@ MPTEndpointStep<TDerived>::check(StrandContext const& ctx) const
return temBAD_PATH; return temBAD_PATH;
} }
auto const sleSrc = ctx.view.read(keylet::account(src_)); auto const sleSrc = AccountRootEntryR(src_, ctx.view);
if (!sleSrc) if (!sleSrc)
{ {
JLOG(j_.warn()) << "MPTEndpointStep: can't receive MPT from non-existent issuer: " << src_; JLOG(j_.warn()) << "MPTEndpointStep: can't receive MPT from non-existent issuer: " << src_;
@@ -928,7 +929,7 @@ MPTEndpointStep<TDerived>::check(StrandContext const& ctx) const
return temBAD_PATH; return temBAD_PATH;
} }
return static_cast<TDerived const*>(this)->check(ctx, sleSrc); return static_cast<TDerived const*>(this)->check(ctx, sleSrc.rawSle());
} }
template <class TDerived> template <class TDerived>
+2 -1
View File
@@ -4,6 +4,7 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/PaymentSandbox.h> #include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
@@ -342,7 +343,7 @@ XRPEndpointStep<TDerived>::check(StrandContext const& ctx) const
return temBAD_PATH; return temBAD_PATH;
} }
auto sleAcc = ctx.view.read(keylet::account(acc_)); auto sleAcc = AccountRootEntryR(acc_, ctx.view);
if (!sleAcc) if (!sleAcc)
{ {
JLOG(j_.warn()) << "XRPEndpointStep: can't send or receive XRP from " JLOG(j_.warn()) << "XRPEndpointStep: can't send or receive XRP from "
@@ -9,6 +9,7 @@
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h> #include <xrpl/ledger/helpers/NFTokenHelpers.h>
@@ -224,7 +225,7 @@ AccountDelete::preclaim(PreclaimContext const& ctx)
AccountID const account{ctx.tx[sfAccount]}; AccountID const account{ctx.tx[sfAccount]};
AccountID const dst{ctx.tx[sfDestination]}; AccountID const dst{ctx.tx[sfDestination]};
auto sleDst = ctx.view.read(keylet::account(dst)); auto sleDst = AccountRootEntryR(dst, ctx.view);
if (!sleDst) if (!sleDst)
return tecNO_DST; return tecNO_DST;
@@ -250,7 +251,7 @@ AccountDelete::preclaim(PreclaimContext const& ctx)
} }
} }
auto sleAccount = ctx.view.read(keylet::account(account)); auto sleAccount = AccountRootEntryR(account, ctx.view);
XRPL_ASSERT(sleAccount, "xrpl::AccountDelete::preclaim : non-null account"); XRPL_ASSERT(sleAccount, "xrpl::AccountDelete::preclaim : non-null account");
if (!sleAccount) if (!sleAccount)
return terNO_ACCOUNT; return terNO_ACCOUNT;
@@ -353,11 +354,11 @@ AccountDelete::preclaim(PreclaimContext const& ctx)
TER TER
AccountDelete::doApply() AccountDelete::doApply()
{ {
auto src = view().peek(keylet::account(accountID_)); auto src = AccountRootEntryW(accountID_, view());
XRPL_ASSERT(src, "xrpl::AccountDelete::doApply : non-null source account"); XRPL_ASSERT(src, "xrpl::AccountDelete::doApply : non-null source account");
auto const dstID = ctx_.tx[sfDestination]; auto const dstID = ctx_.tx[sfDestination];
auto dst = view().peek(keylet::account(dstID)); auto dst = AccountRootEntryW(dstID, view());
XRPL_ASSERT(dst, "xrpl::AccountDelete::doApply : non-null destination account"); XRPL_ASSERT(dst, "xrpl::AccountDelete::doApply : non-null destination account");
if (!src || !dst) if (!src || !dst)
@@ -365,8 +366,8 @@ AccountDelete::doApply()
if (ctx_.tx.isFieldPresent(sfCredentialIDs)) if (ctx_.tx.isFieldPresent(sfCredentialIDs))
{ {
if (auto err = if (auto err = verifyDepositPreauth(
verifyDepositPreauth(ctx_.tx, ctx_.view(), accountID_, dstID, dst, ctx_.journal); ctx_.tx, ctx_.view(), accountID_, dstID, dst.rawSle(), ctx_.journal);
!isTesSuccess(err)) !isTesSuccess(err))
return err; return err;
} }
@@ -407,7 +408,7 @@ AccountDelete::doApply()
if (src->isFieldPresent(sfSponsor)) if (src->isFieldPresent(sfSponsor))
{ {
auto const sponsorID = src->getAccountID(sfSponsor); auto const sponsorID = src->getAccountID(sfSponsor);
auto sponsorSle = view().peek(keylet::account(sponsorID)); auto sponsorSle = AccountRootEntryW(sponsorID, view());
if (!sponsorSle) if (!sponsorSle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -425,7 +426,7 @@ AccountDelete::doApply()
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
} }
sponsorSle->at(sfSponsoringAccountCount) = sponsoringAccountCount - 1; sponsorSle->at(sfSponsoringAccountCount) = sponsoringAccountCount - 1;
view().update(sponsorSle); sponsorSle.update();
// Following line might look redundant, but without it, sfSponsor // Following line might look redundant, but without it, sfSponsor
// would end up remaining in after-ltAccountRoot during the // would end up remaining in after-ltAccountRoot during the
@@ -448,8 +449,8 @@ AccountDelete::doApply()
if (remainingBalance > XRPAmount(0) && dst->isFlag(lsfPasswordSpent)) if (remainingBalance > XRPAmount(0) && dst->isFlag(lsfPasswordSpent))
dst->clearFlag(lsfPasswordSpent); dst->clearFlag(lsfPasswordSpent);
view().update(dst); dst.update();
view().erase(src); src.erase();
return tesSUCCESS; return tesSUCCESS;
} }
@@ -6,6 +6,7 @@
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
@@ -170,7 +171,7 @@ AccountSet::preclaim(PreclaimContext const& ctx)
{ {
auto const id = ctx.tx[sfAccount]; auto const id = ctx.tx[sfAccount];
auto const sle = ctx.view.read(keylet::account(id)); auto const sle = AccountRootEntryR(id, ctx.view);
if (!sle) if (!sle)
return terNO_ACCOUNT; return terNO_ACCOUNT;
@@ -224,7 +225,7 @@ AccountSet::preclaim(PreclaimContext const& ctx)
TER TER
AccountSet::doApply() AccountSet::doApply()
{ {
auto const sle = view().peek(keylet::account(accountID_)); auto sle = AccountRootEntryW(accountID_, view());
if (!sle) if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -582,7 +583,7 @@ AccountSet::doApply()
if (uFlagsIn != uFlagsOut) if (uFlagsIn != uFlagsOut)
sle->setFieldU32(sfFlags, uFlagsOut); sle->setFieldU32(sfFlags, uFlagsOut);
ctx_.view().update(sle); sle.update();
return tesSUCCESS; return tesSUCCESS;
} }
@@ -3,6 +3,7 @@
#include <xrpl/basics/Slice.h> #include <xrpl/basics/Slice.h>
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h> #include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/PublicKey.h> #include <xrpl/protocol/PublicKey.h>
@@ -25,7 +26,7 @@ SetRegularKey::calculateBaseFee(ReadView const& view, STTx const& tx)
{ {
if (calcAccountID(PublicKey(makeSlice(spk))) == id) if (calcAccountID(PublicKey(makeSlice(spk))) == id)
{ {
auto const sle = view.read(keylet::account(id)); auto const sle = AccountRootEntryR(id, view);
if (sle && !sle->isFlag(lsfPasswordSpent)) if (sle && !sle->isFlag(lsfPasswordSpent))
{ {
@@ -53,7 +54,7 @@ SetRegularKey::preflight(PreflightContext const& ctx)
TER TER
SetRegularKey::doApply() SetRegularKey::doApply()
{ {
auto const sle = view().peek(keylet::account(accountID_)); auto sle = AccountRootEntryW(accountID_, view());
if (!sle) if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -73,7 +74,7 @@ SetRegularKey::doApply()
sle->makeFieldAbsent(sfRegularKey); sle->makeFieldAbsent(sfRegularKey);
} }
ctx_.view().update(sle); sle.update();
return tesSUCCESS; return tesSUCCESS;
} }
@@ -6,6 +6,7 @@
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -213,8 +214,9 @@ removeSignersFromLedger(
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
} }
AccountRootEntryW accountSle(accountKeylet, view);
decreaseOwnerCountForObject( decreaseOwnerCountForObject(
view, view.peek(accountKeylet), signers, removeFromOwnerCount, registry.getJournal("View")); view, accountSle, signers, removeFromOwnerCount, registry.getJournal("View"));
view.erase(signers); view.erase(signers);
@@ -309,7 +311,7 @@ SignerListSet::replaceSignerList()
ctx_.registry, view(), accountKeylet, ownerDirKeylet, signerListKeylet, j_)) ctx_.registry, view(), accountKeylet, ownerDirKeylet, signerListKeylet, j_))
return ter; return ter;
auto const sle = view().peek(accountKeylet); auto sle = AccountRootEntryW(accountKeylet, view(), ctx_.journal);
if (!sle) if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -319,12 +321,8 @@ SignerListSet::replaceSignerList()
// We check the reserve against the starting balance because we want to // We check the reserve against the starting balance because we want to
// allow dipping into the reserve to pay fees. This behavior is consistent // allow dipping into the reserve to pay fees. This behavior is consistent
// with TicketCreate. // with TicketCreate.
if (auto const ret = checkReserve( if (auto const ret = sle.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(), preFeeBalance_, {.ownerCountDelta = kAddedOwnerCount});
sle,
preFeeBalance_,
{.ownerCountDelta = kAddedOwnerCount},
ctx_.journal);
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
@@ -333,7 +331,6 @@ SignerListSet::replaceSignerList()
view().insert(signerList); view().insert(signerList);
writeSignersToSLE(signerList, flags); writeSignersToSLE(signerList, flags);
auto viewJ = ctx_.registry.get().getJournal("View");
// Add the signer list to the account's directory. // Add the signer list to the account's directory.
auto const page = auto const page =
ctx_.view().dirInsert(ownerDirKeylet, signerListKeylet, describeOwnerDir(accountID_)); ctx_.view().dirInsert(ownerDirKeylet, signerListKeylet, describeOwnerDir(accountID_));
@@ -348,7 +345,7 @@ SignerListSet::replaceSignerList()
// If we succeeded, the new entry counts against the // If we succeeded, the new entry counts against the
// creator's reserve. // creator's reserve.
increaseOwnerCount(ctx_.getApplyViewContext(), sle, kAddedOwnerCount, viewJ); sle.increaseOwnerCount(ctx_.getApplyViewContext(), kAddedOwnerCount);
addSponsorToLedgerEntry(ctx_.getApplyViewContext(), signerList); addSponsorToLedgerEntry(ctx_.getApplyViewContext(), signerList);
return tesSUCCESS; return tesSUCCESS;
} }
@@ -359,7 +356,7 @@ SignerListSet::destroySignerList()
auto const accountKeylet = keylet::account(accountID_); auto const accountKeylet = keylet::account(accountID_);
// Destroying the signer list is only allowed if either the master key // Destroying the signer list is only allowed if either the master key
// is enabled or there is a regular key. // is enabled or there is a regular key.
SLE::pointer const ledgerEntry = view().peek(accountKeylet); auto const ledgerEntry = AccountRootEntryW(accountKeylet, view());
if (!ledgerEntry) if (!ledgerEntry)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -10,6 +10,7 @@
#include <xrpl/ledger/PaymentSandbox.h> #include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/RawView.h> #include <xrpl/ledger/RawView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
@@ -125,8 +126,7 @@ checkAttestationPublicKey(
AccountID const accountFromPK = calcAccountID(pk); AccountID const accountFromPK = calcAccountID(pk);
if (auto const sleAttestationSigningAccount = if (auto const sleAttestationSigningAccount = AccountRootEntryR(attestationSignerAccount, view))
view.read(keylet::account(attestationSignerAccount)))
{ {
if (accountFromPK == attestationSignerAccount) if (accountFromPK == attestationSignerAccount)
{ {
@@ -404,7 +404,7 @@ transferHelper(
return tesSUCCESS; return tesSUCCESS;
auto const dstK = keylet::account(dst); auto const dstK = keylet::account(dst);
if (auto sleDst = psb.read(dstK)) if (auto sleDst = AccountRootEntryR(dstK, psb))
{ {
// Check dst tag and deposit auth // Check dst tag and deposit auth
@@ -430,13 +430,13 @@ transferHelper(
if (amt.native()) if (amt.native())
{ {
auto const sleSrc = psb.peek(keylet::account(src)); auto sleSrc = AccountRootEntryW(src, psb, j);
XRPL_ASSERT(sleSrc, "xrpl::transferHelper : non-null source account"); XRPL_ASSERT(sleSrc, "xrpl::transferHelper : non-null source account");
if (!sleSrc) if (!sleSrc)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
{ {
auto const reserve = accountReserve(psb, sleSrc, j); auto const reserve = sleSrc.reserve();
auto const availableBalance = [&]() -> STAmount { auto const availableBalance = [&]() -> STAmount {
STAmount curBal = (*sleSrc)[sfBalance]; STAmount curBal = (*sleSrc)[sfBalance];
@@ -455,7 +455,7 @@ transferHelper(
} }
} }
auto sleDst = psb.peek(dstK); auto sleDst = AccountRootEntryW(dstK, psb);
if (!sleDst) if (!sleDst)
{ {
if (canCreate == CanCreateDstPolicy::No) if (canCreate == CanCreateDstPolicy::No)
@@ -470,17 +470,17 @@ transferHelper(
} }
// Create the account. // Create the account.
sleDst = std::make_shared<SLE>(dstK); sleDst.newSLE();
sleDst->setAccountID(sfAccount, dst); sleDst->setAccountID(sfAccount, dst);
sleDst->setFieldU32(sfSequence, psb.seq()); sleDst->setFieldU32(sfSequence, psb.seq());
psb.insert(sleDst); sleDst.insert();
} }
(*sleSrc)[sfBalance] = (*sleSrc)[sfBalance] - amt; (*sleSrc)[sfBalance] = (*sleSrc)[sfBalance] - amt;
(*sleDst)[sfBalance] = (*sleDst)[sfBalance] + amt; (*sleDst)[sfBalance] = (*sleDst)[sfBalance] + amt;
psb.update(sleSrc); sleSrc.update();
psb.update(sleDst); sleDst.update();
return tesSUCCESS; return tesSUCCESS;
} }
@@ -724,7 +724,7 @@ finalizeClaimHelper(
auto const cidOwner = (*sleClaimID)[sfAccount]; auto const cidOwner = (*sleClaimID)[sfAccount];
{ {
// Remove the claim id // Remove the claim id
auto const sleOwner = outerSb.peek(keylet::account(cidOwner)); auto sleOwner = AccountRootEntryW(cidOwner, outerSb);
auto const page = (*sleClaimID)[sfOwnerNode]; auto const page = (*sleClaimID)[sfOwnerNode];
if (!outerSb.dirRemove(keylet::ownerDir(cidOwner), page, sleClaimID->key(), true)) if (!outerSb.dirRemove(keylet::ownerDir(cidOwner), page, sleClaimID->key(), true))
{ {
@@ -759,7 +759,7 @@ getSignersListAndQuorum(ReadView const& view, SLE const& sleBridge, beast::Journ
std::uint32_t q = std::numeric_limits<std::uint32_t>::max(); std::uint32_t q = std::numeric_limits<std::uint32_t>::max();
AccountID const thisDoor = sleBridge[sfAccount]; AccountID const thisDoor = sleBridge[sfAccount];
auto const sleDoor = [&] { return view.read(keylet::account(thisDoor)); }(); auto const sleDoor = [&] { return AccountRootEntryR(thisDoor, view); }();
if (!sleDoor) if (!sleDoor)
{ {
@@ -1036,7 +1036,7 @@ applyCreateAccountAttestations(
// Check reserve // Check reserve
auto const balance = (*sleDoor)[sfBalance]; auto const balance = (*sleDoor)[sfBalance];
auto const reserve = accountReserve(psb, sleDoor, j, {.ownerCountDelta = 1}); auto const reserve = AccountRootEntryR(sleDoor, psb, j).reserve({.ownerCountDelta = 1});
if (balance < reserve) if (balance < reserve)
return std::unexpected(tecINSUFFICIENT_RESERVE); return std::unexpected(tecINSUFFICIENT_RESERVE);
@@ -1145,7 +1145,9 @@ applyCreateAccountAttestations(
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
// Reserve was already checked // Reserve was already checked
increaseOwnerCount(psb, sleDoor, {}, 1, j); AccountRootEntryW doorSle(doorK, psb, j);
std::optional<AccountRootEntryW> noSponsor;
doorSle.increaseOwnerCount(noSponsor, 1);
psb.insert(createdSleClaimID); psb.insert(createdSleClaimID);
psb.update(sleDoor); psb.update(sleDoor);
} }
@@ -1429,7 +1431,7 @@ XChainCreateBridge::preclaim(PreclaimContext const& ctx)
if (!isXRP(bridgeSpec.issue(chainType))) if (!isXRP(bridgeSpec.issue(chainType)))
{ {
auto const sleIssuer = ctx.view.read(keylet::account(bridgeSpec.issue(chainType).account)); auto const sleIssuer = AccountRootEntryR(bridgeSpec.issue(chainType).account, ctx.view);
if (!sleIssuer) if (!sleIssuer)
return tecNO_ISSUER; return tecNO_ISSUER;
@@ -1442,12 +1444,12 @@ XChainCreateBridge::preclaim(PreclaimContext const& ctx)
{ {
// Check reserve // Check reserve
auto const sleAcc = ctx.view.read(keylet::account(account)); auto const sleAcc = AccountRootEntryR(account, ctx.view, ctx.j);
if (!sleAcc) if (!sleAcc)
return terNO_ACCOUNT; return terNO_ACCOUNT;
auto const balance = (*sleAcc)[sfBalance]; auto const balance = (*sleAcc)[sfBalance];
auto const reserve = accountReserve(ctx.view, sleAcc, ctx.j, {.ownerCountDelta = 1}); auto const reserve = sleAcc.reserve({.ownerCountDelta = 1});
if (balance < reserve) if (balance < reserve)
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
@@ -1464,7 +1466,7 @@ XChainCreateBridge::doApply()
auto const reward = ctx_.tx[sfSignatureReward]; auto const reward = ctx_.tx[sfSignatureReward];
auto const minAccountCreate = ctx_.tx[~sfMinAccountCreateAmount]; auto const minAccountCreate = ctx_.tx[~sfMinAccountCreateAmount];
auto const sleAcct = ctx_.view().peek(keylet::account(account)); auto sleAcct = AccountRootEntryW(account, ctx_.view(), ctx_.journal);
if (!sleAcct) if (!sleAcct)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
@@ -1492,10 +1494,11 @@ XChainCreateBridge::doApply()
(*sleBridge)[sfOwnerNode] = *page; (*sleBridge)[sfOwnerNode] = *page;
} }
increaseOwnerCount(ctx_.view(), sleAcct, {}, 1, ctx_.journal); std::optional<AccountRootEntryW> noSponsor;
sleAcct.increaseOwnerCount(noSponsor, 1);
ctx_.view().insert(sleBridge); ctx_.view().insert(sleBridge);
ctx_.view().update(sleAcct); sleAcct.update();
return tesSUCCESS; return tesSUCCESS;
} }
@@ -1575,7 +1578,7 @@ BridgeModify::doApply()
auto const minAccountCreate = ctx_.tx[~sfMinAccountCreateAmount]; auto const minAccountCreate = ctx_.tx[~sfMinAccountCreateAmount];
bool const clearAccountCreate = ctx_.tx.isFlag(tfClearAccountCreateAmount); bool const clearAccountCreate = ctx_.tx.isFlag(tfClearAccountCreateAmount);
auto const sleAcct = ctx_.view().peek(keylet::account(account)); auto const sleAcct = AccountRootEntryW(account, ctx_.view());
if (!sleAcct) if (!sleAcct)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
@@ -1633,7 +1636,7 @@ XChainClaim::preclaim(PreclaimContext const& ctx)
return tecNO_ENTRY; return tecNO_ENTRY;
} }
if (!ctx.view.read(keylet::account(ctx.tx[sfDestination]))) if (!AccountRootEntryR(ctx.tx[sfDestination], ctx.view))
{ {
return tecNO_DST; return tecNO_DST;
} }
@@ -1738,7 +1741,7 @@ XChainClaim::doApply()
// `finalizeClaimHelper`. Since `finalizeClaimHelper` can create child // `finalizeClaimHelper`. Since `finalizeClaimHelper` can create child
// views, it's important that the sle's lifetime doesn't overlap. // views, it's important that the sle's lifetime doesn't overlap.
auto const sleAcct = psb.peek(keylet::account(account)); auto const sleAcct = AccountRootEntryW(account, psb);
auto const sleBridge = peekBridge(psb, bridgeSpec); auto const sleBridge = peekBridge(psb, bridgeSpec);
auto const sleClaimID = psb.peek(claimIDKeylet); auto const sleClaimID = psb.peek(claimIDKeylet);
@@ -1919,7 +1922,7 @@ XChainCommit::doApply()
auto const amount = ctx_.tx[sfAmount]; auto const amount = ctx_.tx[sfAmount];
auto const bridgeSpec = ctx_.tx[sfXChainBridge]; auto const bridgeSpec = ctx_.tx[sfXChainBridge];
auto const sleAccount = psb.read(keylet::account(account)); auto const sleAccount = AccountRootEntryR(account, psb);
if (!sleAccount) if (!sleAccount)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
@@ -1990,12 +1993,12 @@ XChainCreateClaimID::preclaim(PreclaimContext const& ctx)
{ {
// Check reserve // Check reserve
auto const sleAcc = ctx.view.read(keylet::account(account)); auto const sleAcc = AccountRootEntryR(account, ctx.view, ctx.j);
if (!sleAcc) if (!sleAcc)
return terNO_ACCOUNT; return terNO_ACCOUNT;
auto const balance = (*sleAcc)[sfBalance]; auto const balance = (*sleAcc)[sfBalance];
auto const reserve = accountReserve(ctx.view, sleAcc, ctx.j, {.ownerCountDelta = 1}); auto const reserve = sleAcc.reserve({.ownerCountDelta = 1});
if (balance < reserve) if (balance < reserve)
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
} }
@@ -2011,7 +2014,7 @@ XChainCreateClaimID::doApply()
auto const reward = ctx_.tx[sfSignatureReward]; auto const reward = ctx_.tx[sfSignatureReward];
auto const otherChainSrc = ctx_.tx[sfOtherChainSource]; auto const otherChainSrc = ctx_.tx[sfOtherChainSource];
auto const sleAcct = ctx_.view().peek(keylet::account(account)); auto sleAcct = AccountRootEntryW(account, ctx_.view(), ctx_.journal);
if (!sleAcct) if (!sleAcct)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
@@ -2053,11 +2056,12 @@ XChainCreateClaimID::doApply()
(*sleClaimID)[sfOwnerNode] = *page; (*sleClaimID)[sfOwnerNode] = *page;
} }
increaseOwnerCount(ctx_.view(), sleAcct, {}, 1, ctx_.journal); std::optional<AccountRootEntryW> noSponsor;
sleAcct.increaseOwnerCount(noSponsor, 1);
ctx_.view().insert(sleClaimID); ctx_.view().insert(sleClaimID);
ctx_.view().update(sleBridge); ctx_.view().update(sleBridge);
ctx_.view().update(sleAcct); sleAcct.update();
return tesSUCCESS; return tesSUCCESS;
} }
@@ -2195,7 +2199,7 @@ XChainCreateAccountCommit::doApply()
STAmount const reward = ctx_.tx[sfSignatureReward]; STAmount const reward = ctx_.tx[sfSignatureReward];
STXChainBridge const bridge = ctx_.tx[sfXChainBridge]; STXChainBridge const bridge = ctx_.tx[sfXChainBridge];
auto const sle = psb.peek(keylet::account(account)); auto const sle = AccountRootEntryW(account, psb);
if (!sle) if (!sle)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
+22 -18
View File
@@ -7,6 +7,7 @@
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/PaymentSandbox.h> #include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h> #include <xrpl/ledger/helpers/RippleStateHelpers.h>
@@ -112,8 +113,8 @@ CheckCash::preclaim(PreclaimContext const& ctx)
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
} }
{ {
auto const sleSrc = ctx.view.read(keylet::account(srcId)); auto const sleSrc = AccountRootEntryR(srcId, ctx.view);
auto const sleDst = ctx.view.read(keylet::account(dstId)); auto const sleDst = AccountRootEntryR(dstId, ctx.view);
if (!sleSrc || !sleDst) if (!sleSrc || !sleDst)
{ {
// If the check exists this should never occur. // If the check exists this should never occur.
@@ -201,7 +202,7 @@ CheckCash::preclaim(PreclaimContext const& ctx)
auto const sleTrustLine = auto const sleTrustLine =
ctx.view.read(keylet::trustLine(dstId, issuerId, currency)); ctx.view.read(keylet::trustLine(dstId, issuerId, currency));
auto const sleIssuer = ctx.view.read(keylet::account(issuerId)); auto const sleIssuer = AccountRootEntryR(issuerId, ctx.view);
if (!sleIssuer) if (!sleIssuer)
{ {
JLOG(ctx.j.warn()) << "Can't receive IOUs from " JLOG(ctx.j.warn()) << "Can't receive IOUs from "
@@ -253,7 +254,7 @@ CheckCash::preclaim(PreclaimContext const& ctx)
return tesSUCCESS; return tesSUCCESS;
}, },
[&](MPTIssue const& issue) -> TER { [&](MPTIssue const& issue) -> TER {
auto const sleIssuer = ctx.view.read(keylet::account(issuerId)); auto const sleIssuer = AccountRootEntryR(issuerId, ctx.view);
if (!sleIssuer) if (!sleIssuer)
{ {
JLOG(ctx.j.warn()) << "Can't receive MPTs from " JLOG(ctx.j.warn()) << "Can't receive MPTs from "
@@ -406,23 +407,18 @@ CheckCash::doApply()
optDeliverMin ? maxDeliverMin() : ctx_.tx.getFieldAmount(sfAmount)}; optDeliverMin ? maxDeliverMin() : ctx_.tx.getFieldAmount(sfAmount)};
auto applyViewContext = ApplyViewContext({.view = psb, .tx = ctx_.tx}); auto applyViewContext = ApplyViewContext({.view = psb, .tx = ctx_.tx});
auto const sponsorSle = getTxReserveSponsor(applyViewContext); auto sponsorSle = getTxReserveSponsor(applyViewContext);
if (!sponsorSle) if (!sponsorSle)
return sponsorSle.error(); // LCOV_EXCL_LINE return sponsorSle.error(); // LCOV_EXCL_LINE
// Check reserve. Return destination account SLE if enough reserve, // Check reserve. Return destination account SLE if enough reserve,
// otherwise return nullptr. // otherwise return nullptr.
auto checkDstReserve = [&]() -> SLE::pointer { auto checkDstReserve = [&]() -> SLE::pointer {
auto sleDst = psb.peek(keylet::account(accountID_)); auto sleDst = AccountRootEntryW(accountID_, psb, j_);
// Can the account cover the trust line's or MPT reserve? // Can the account cover the trust line's or MPT reserve?
if (auto const ret = checkReserve( if (auto const ret = sleDst.checkReserve(
applyViewContext, applyViewContext, preFeeBalance_, *sponsorSle, {.ownerCountDelta = 1});
sleDst,
preFeeBalance_,
*sponsorSle,
{.ownerCountDelta = 1},
j_);
!isTesSuccess(ret)) !isTesSuccess(ret))
{ {
JLOG(j_.trace()) << "Trust line does not exist. " JLOG(j_.trace()) << "Trust line does not exist. "
@@ -430,7 +426,7 @@ CheckCash::doApply()
return nullptr; return nullptr;
} }
return sleDst; return sleDst.mutableRawSle();
}; };
std::optional<Keylet> trustLineKey; std::optional<Keylet> trustLineKey;
@@ -486,8 +482,10 @@ CheckCash::doApply()
Issue(currency, accountID_), // limit of zero Issue(currency, accountID_), // limit of zero
0, // quality in 0, // quality in
0, // quality out 0, // quality out
*sponsorSle, // sponsor sponsorSle->has_value() // sponsor
viewJ); // journal ? (*sponsorSle)->mutableRawSle()
: SLE::pointer{},
viewJ); // journal
!isTesSuccess(ter)) !isTesSuccess(ter))
{ {
return ter; return ter;
@@ -533,8 +531,14 @@ CheckCash::doApply()
if (sleDst == nullptr) if (sleDst == nullptr)
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
if (auto const err = if (auto const err = checkCreateMPT(
checkCreateMPT(psb, mptID, accountID_, *sponsorSle, 0, j_); psb,
mptID,
accountID_,
sponsorSle->has_value() ? (*sponsorSle)->mutableRawSle()
: SLE::pointer{},
0,
j_);
!isTesSuccess(err)) !isTesSuccess(err))
{ {
return err; return err;
@@ -4,6 +4,7 @@
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
@@ -79,7 +80,7 @@ CheckCreate::preclaim(PreclaimContext const& ctx)
{ {
AccountID const dstId{ctx.tx[sfDestination]}; AccountID const dstId{ctx.tx[sfDestination]};
AccountID const srcId{ctx.tx[sfAccount]}; AccountID const srcId{ctx.tx[sfAccount]};
auto const sleDst = ctx.view.read(keylet::account(dstId)); auto const sleDst = AccountRootEntryR(dstId, ctx.view);
if (!sleDst) if (!sleDst)
{ {
JLOG(ctx.j.warn()) << "Destination account does not exist."; JLOG(ctx.j.warn()) << "Destination account does not exist.";
@@ -187,15 +188,15 @@ CheckCreate::preclaim(PreclaimContext const& ctx)
TER TER
CheckCreate::doApply() CheckCreate::doApply()
{ {
auto const sle = view().peek(keylet::account(accountID_)); auto sle = AccountRootEntryW(accountID_, view(), ctx_.journal);
if (!sle) if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
// A check counts against the reserve of the issuing account, but we // A check counts against the reserve of the issuing account, but we
// check the starting balance because we want to allow dipping into the // check the starting balance because we want to allow dipping into the
// reserve to pay fees. // reserve to pay fees.
if (auto const ret = checkReserve( if (auto const ret =
ctx_.getApplyViewContext(), sle, preFeeBalance_, {.ownerCountDelta = 1}, ctx_.journal); sle.checkReserve(ctx_.getApplyViewContext(), preFeeBalance_, {.ownerCountDelta = 1});
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
// Note that we use the value from the sequence or ticket as the // Note that we use the value from the sequence or ticket as the
@@ -220,7 +221,6 @@ CheckCreate::doApply()
view().insert(sleCheck); view().insert(sleCheck);
auto viewJ = ctx_.registry.get().getJournal("View");
// If it's not a self-send (and it shouldn't be), add Check to the // If it's not a self-send (and it shouldn't be), add Check to the
// destination's owner directory. // destination's owner directory.
if (dstAccountId != accountID_) if (dstAccountId != accountID_)
@@ -251,7 +251,7 @@ CheckCreate::doApply()
} }
// If we succeeded, the new entry counts against the creator's reserve. // If we succeeded, the new entry counts against the creator's reserve.
increaseOwnerCount(ctx_.getApplyViewContext(), sle, 1, viewJ); sle.increaseOwnerCount(ctx_.getApplyViewContext(), 1);
addSponsorToLedgerEntry(ctx_.getApplyViewContext(), sleCheck); addSponsorToLedgerEntry(ctx_.getApplyViewContext(), sleCheck);
return tesSUCCESS; return tesSUCCESS;
} }
@@ -2,6 +2,7 @@
#include <xrpl/basics/Log.h> #include <xrpl/basics/Log.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -87,8 +88,8 @@ CredentialAccept::doApply()
AccountID const issuer{ctx_.tx[sfIssuer]}; AccountID const issuer{ctx_.tx[sfIssuer]};
// Both exist as credential object exist itself (checked in preclaim) // Both exist as credential object exist itself (checked in preclaim)
auto const sleSubject = view().peek(keylet::account(accountID_)); auto sleSubject = AccountRootEntryW(accountID_, view(), j_);
auto const sleIssuer = view().peek(keylet::account(issuer)); auto sleIssuer = AccountRootEntryW(issuer, view());
if (!sleSubject || !sleIssuer) if (!sleSubject || !sleIssuer)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -97,13 +98,8 @@ CredentialAccept::doApply()
if (!txSponsorSle) if (!txSponsorSle)
return txSponsorSle.error(); // LCOV_EXCL_LINE return txSponsorSle.error(); // LCOV_EXCL_LINE
if (auto const ret = checkReserve( if (auto const ret = sleSubject.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(), preFeeBalance_, *txSponsorSle, {.ownerCountDelta = 1});
sleSubject,
preFeeBalance_,
*txSponsorSle,
{.ownerCountDelta = 1},
j_);
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
@@ -130,7 +126,7 @@ CredentialAccept::doApply()
removeSponsorFromLedgerEntry(sleCred); removeSponsorFromLedgerEntry(sleCred);
addSponsorToLedgerEntry(ctx_.getApplyViewContext(), sleCred); addSponsorToLedgerEntry(ctx_.getApplyViewContext(), sleCred);
increaseOwnerCount(ctx_.getApplyViewContext(), sleSubject, 1, j_); sleSubject.increaseOwnerCount(ctx_.getApplyViewContext(), 1);
view().update(sleCred); view().update(sleCred);
return tesSUCCESS; return tesSUCCESS;
@@ -4,6 +4,7 @@
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> // IWYU pragma: keep #include <xrpl/ledger/helpers/CredentialHelpers.h> // IWYU pragma: keep
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
@@ -84,7 +85,7 @@ CredentialCreate::preclaim(PreclaimContext const& ctx)
auto const credType(ctx.tx[sfCredentialType]); auto const credType(ctx.tx[sfCredentialType]);
auto const subject = ctx.tx[sfSubject]; auto const subject = ctx.tx[sfSubject];
auto const subjectSle = ctx.view.read(keylet::account(subject)); auto const subjectSle = AccountRootEntryR(subject, ctx.view);
if (!subjectSle) if (!subjectSle)
{ {
@@ -134,12 +135,12 @@ CredentialCreate::doApply()
sleCred->setFieldU32(sfExpiration, *optExp); sleCred->setFieldU32(sfExpiration, *optExp);
} }
auto const sleIssuer = view().peek(keylet::account(accountID_)); auto sleIssuer = AccountRootEntryW(accountID_, view(), j_);
if (!sleIssuer) if (!sleIssuer)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
if (auto const ret = checkReserve( if (auto const ret = sleIssuer.checkReserve(
ctx_.getApplyViewContext(), sleIssuer, preFeeBalance_, {.ownerCountDelta = 1}, j_); ctx_.getApplyViewContext(), preFeeBalance_, {.ownerCountDelta = 1});
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
@@ -159,7 +160,7 @@ CredentialCreate::doApply()
return tecDIR_FULL; return tecDIR_FULL;
sleCred->setFieldU64(sfIssuerNode, *page); sleCred->setFieldU64(sfIssuerNode, *page);
increaseOwnerCount(ctx_.getApplyViewContext(), sleIssuer, 1, j_); sleIssuer.increaseOwnerCount(ctx_.getApplyViewContext(), 1);
addSponsorToLedgerEntry(ctx_.getApplyViewContext(), sleCred); addSponsorToLedgerEntry(ctx_.getApplyViewContext(), sleCred);
} }
@@ -3,6 +3,7 @@
#include <xrpl/basics/Log.h> #include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -52,7 +53,7 @@ DelegateSet::preclaim(PreclaimContext const& ctx)
if (!ctx.view.exists(keylet::account(ctx.tx[sfAccount]))) if (!ctx.view.exists(keylet::account(ctx.tx[sfAccount])))
return terNO_ACCOUNT; // LCOV_EXCL_LINE return terNO_ACCOUNT; // LCOV_EXCL_LINE
auto const sleAuthorize = ctx.view.read(keylet::account(ctx.tx[sfAuthorize])); auto const sleAuthorize = AccountRootEntryR(ctx.tx[sfAuthorize], ctx.view);
if (!sleAuthorize) if (!sleAuthorize)
return tecNO_TARGET; return tecNO_TARGET;
@@ -72,7 +73,7 @@ DelegateSet::preclaim(PreclaimContext const& ctx)
TER TER
DelegateSet::doApply() DelegateSet::doApply()
{ {
auto const sleOwner = ctx_.view().peek(keylet::account(accountID_)); auto sleOwner = AccountRootEntryW(accountID_, ctx_.view(), ctx_.journal);
if (!sleOwner) if (!sleOwner)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -98,12 +99,8 @@ DelegateSet::doApply()
if (permissions.empty()) if (permissions.empty())
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
if (auto const ret = checkReserve( if (auto const ret = sleOwner.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(), preFeeBalance_, {.ownerCountDelta = 1});
sleOwner,
preFeeBalance_,
{.ownerCountDelta = 1},
ctx_.journal);
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
@@ -133,7 +130,7 @@ DelegateSet::doApply()
(*sle)[sfDestinationNode] = *destPage; (*sle)[sfDestinationNode] = *destPage;
ctx_.view().insert(sle); ctx_.view().insert(sle);
increaseOwnerCount(ctx_.getApplyViewContext(), sleOwner, 1, ctx_.journal); sleOwner.increaseOwnerCount(ctx_.getApplyViewContext(), 1);
addSponsorToLedgerEntry(ctx_.getApplyViewContext(), sle); addSponsorToLedgerEntry(ctx_.getApplyViewContext(), sle);
return tesSUCCESS; return tesSUCCESS;
@@ -170,7 +167,7 @@ DelegateSet::deleteDelegate(ApplyView& view, SLE::Ref sle, beast::Journal j)
} }
// Only the delegating account's owner count was incremented on creation // Only the delegating account's owner count was incremented on creation
auto const sleOwner = view.peek(keylet::account(delegator)); auto sleOwner = AccountRootEntryW(delegator, view);
if (!sleOwner) if (!sleOwner)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
+3 -2
View File
@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/Sandbox.h> #include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h> #include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h> #include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -119,7 +120,7 @@ AMMBid::preclaim(PreclaimContext const& ctx)
{ {
for (auto const& account : ctx.tx.getFieldArray(sfAuthAccounts)) for (auto const& account : ctx.tx.getFieldArray(sfAuthAccounts))
{ {
if (!ctx.view.read(keylet::account(account[sfAccount]))) if (!AccountRootEntryR(account[sfAccount], ctx.view))
{ {
JLOG(ctx.j.debug()) << "AMM Bid: Invalid Account."; JLOG(ctx.j.debug()) << "AMM Bid: Invalid Account.";
return terNO_ACCOUNT; return terNO_ACCOUNT;
@@ -208,7 +209,7 @@ applyBid(ApplyContext& ctx, Sandbox& sb, AccountID const& account, beast::Journa
auto validOwner = [&](AccountID const& account) { auto validOwner = [&](AccountID const& account) {
// Valid range is 0-19 but the tailing slot pays MinSlotPrice // Valid range is 0-19 but the tailing slot pays MinSlotPrice
// and doesn't refund so the check is < instead of <= to optimize. // and doesn't refund so the check is < instead of <= to optimize.
return timeSlot && *timeSlot < kTailingSlot && sb.read(keylet::account(account)); return timeSlot && *timeSlot < kTailingSlot && AccountRootEntryR(account, sb);
}; };
auto updateSlot = [&](std::uint32_t fee, Number const& minPrice, Number const& burn) -> TER { auto updateSlot = [&](std::uint32_t fee, Number const& minPrice, Number const& burn) -> TER {
@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/Sandbox.h> #include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h> #include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
@@ -102,11 +103,11 @@ AMMClawback::preclaim(PreclaimContext const& ctx)
{ {
auto const asset = ctx.tx[sfAsset]; auto const asset = ctx.tx[sfAsset];
auto const asset2 = ctx.tx[sfAsset2]; auto const asset2 = ctx.tx[sfAsset2];
auto const sleIssuer = ctx.view.read(keylet::account(ctx.tx[sfAccount])); auto const sleIssuer = AccountRootEntryR(ctx.tx[sfAccount], ctx.view);
if (!sleIssuer) if (!sleIssuer)
return terNO_ACCOUNT; // LCOV_EXCL_LINE return terNO_ACCOUNT; // LCOV_EXCL_LINE
if (!ctx.view.read(keylet::account(ctx.tx[sfHolder]))) if (!AccountRootEntryR(ctx.tx[sfHolder], ctx.view))
return terNO_ACCOUNT; return terNO_ACCOUNT;
auto const ammSle = ctx.view.read(keylet::amm(asset, asset2)); auto const ammSle = ctx.view.read(keylet::amm(asset, asset2));
@@ -178,7 +179,7 @@ AMMClawback::applyGuts(Sandbox& sb)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
auto const ammAccount = (*ammSle)[sfAccount]; auto const ammAccount = (*ammSle)[sfAccount];
auto const accountSle = sb.read(keylet::account(ammAccount)); auto const accountSle = AccountRootEntryR(ammAccount, sb);
if (!accountSle) if (!accountSle)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
+4 -3
View File
@@ -5,6 +5,7 @@
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/Sandbox.h> #include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h> #include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
@@ -133,7 +134,7 @@ AMMCreate::preclaim(PreclaimContext const& ctx)
if (asset.holds<MPTIssue>() || isXRP(asset)) if (asset.holds<MPTIssue>() || isXRP(asset))
return false; return false;
if (auto const issuerAccount = view.read(keylet::account(asset.getIssuer()))) if (auto const issuerAccount = AccountRootEntryR(asset.getIssuer(), view))
return !issuerAccount->isFlag(lsfDefaultRipple); return !issuerAccount->isFlag(lsfDefaultRipple);
return false; return false;
@@ -173,7 +174,7 @@ AMMCreate::preclaim(PreclaimContext const& ctx)
} }
auto isLPToken = [&](STAmount const& amount) -> bool { auto isLPToken = [&](STAmount const& amount) -> bool {
if (auto const sle = ctx.view.read(keylet::account(amount.asset().getIssuer()))) if (auto const sle = AccountRootEntryR(amount.asset().getIssuer(), ctx.view))
return sle->isFieldPresent(sfAMMID); return sle->isFieldPresent(sfAMMID);
return false; return false;
}; };
@@ -237,7 +238,7 @@ AMMCreate::preclaim(PreclaimContext const& ctx)
[&](Issue const& issue) -> TER { [&](Issue const& issue) -> TER {
if (isXRP(issue)) if (isXRP(issue))
return tesSUCCESS; return tesSUCCESS;
auto const sle = ctx.view.read(keylet::account(issue.account)); auto const sle = AccountRootEntryR(issue.account, ctx.view);
if (!sle) if (!sle)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
if (sle->isFlag(lsfAllowTrustLineClawback)) if (sle->isFlag(lsfAllowTrustLineClawback))
@@ -6,8 +6,8 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/Sandbox.h> #include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AMMHelpers.h> #include <xrpl/ledger/helpers/AMMHelpers.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h> #include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -344,7 +344,7 @@ AMMWithdraw::applyGuts(Sandbox& sb)
if (!ammSle) if (!ammSle)
return {tecINTERNAL, false}; // LCOV_EXCL_LINE return {tecINTERNAL, false}; // LCOV_EXCL_LINE
auto const ammAccountID = (*ammSle)[sfAccount]; auto const ammAccountID = (*ammSle)[sfAccount];
auto const accountSle = sb.read(keylet::account(ammAccountID)); auto const accountSle = AccountRootEntryR(ammAccountID, sb);
if (!accountSle) if (!accountSle)
return {tecINTERNAL, false}; // LCOV_EXCL_LINE return {tecINTERNAL, false}; // LCOV_EXCL_LINE
auto const lpTokens = ammLPHolds(ctx_.view(), *ammSle, ctx_.tx[sfAccount], ctx_.journal); auto const lpTokens = ammLPHolds(ctx_.view(), *ammSle, ctx_.tx[sfAccount], ctx_.journal);
@@ -691,16 +691,15 @@ AMMWithdraw::withdraw(
reserveHandling == ReserveHandling::IgnoreReserve) reserveHandling == ReserveHandling::IgnoreReserve)
return tesSUCCESS; return tesSUCCESS;
auto sleAccount = view.peek(keylet::account(account)); auto sleAccount = AccountRootEntryW(account, view, journal);
if (!sleAccount) if (!sleAccount)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
auto const balance = (*sleAccount)[sfBalance]->xrp(); auto const balance = (*sleAccount)[sfBalance]->xrp();
// See also TrustSet::doApply() and MPTokenAuthorize::authorize() // See also TrustSet::doApply() and MPTokenAuthorize::authorize()
XRPAmount const reserve( XRPAmount const reserve(
(ownerCount(sleAccount, journal) < 2) (sleAccount.ownerCount() < 2) ? XRPAmount(beast::kZero)
? XRPAmount(beast::kZero) : sleAccount.reserve({.ownerCountDelta = 1}));
: accountReserve(view, sleAccount, journal, {.ownerCountDelta = 1}));
auto const balanceAdj = std::max(priorBalance, balance); auto const balanceAdj = std::max(priorBalance, balance);
if (balanceAdj < reserve) if (balanceAdj < reserve)
@@ -1,6 +1,8 @@
#include <xrpl/tx/transactors/dex/OfferCancel.h> #include <xrpl/tx/transactors/dex/OfferCancel.h>
#include <xrpl/basics/Log.h> #include <xrpl/basics/Log.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/OfferHelpers.h> #include <xrpl/ledger/helpers/OfferHelpers.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/SField.h> #include <xrpl/protocol/SField.h>
@@ -33,7 +35,7 @@ OfferCancel::preclaim(PreclaimContext const& ctx)
auto const id = ctx.tx[sfAccount]; auto const id = ctx.tx[sfAccount];
auto const offerSequence = ctx.tx[sfOfferSequence]; auto const offerSequence = ctx.tx[sfOfferSequence];
auto const sle = ctx.view.read(keylet::account(id)); auto const sle = AccountRootEntryR(id, ctx.view);
if (!sle) if (!sle)
return terNO_ACCOUNT; return terNO_ACCOUNT;
@@ -54,7 +56,7 @@ OfferCancel::doApply()
{ {
auto const offerSequence = ctx_.tx[sfOfferSequence]; auto const offerSequence = ctx_.tx[sfOfferSequence];
auto const sle = view().read(keylet::account(accountID_)); auto const sle = AccountRootEntryW(accountID_, view());
if (!sle) if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -9,7 +9,7 @@
#include <xrpl/ledger/PaymentSandbox.h> #include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/Sandbox.h> #include <xrpl/ledger/Sandbox.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
@@ -181,7 +181,7 @@ OfferCreate::preclaim(PreclaimContext const& ctx)
auto const cancelSequence = ctx.tx[~sfOfferSequence]; auto const cancelSequence = ctx.tx[~sfOfferSequence];
auto const sleCreator = ctx.view.read(keylet::account(id)); auto const sleCreator = AccountRootEntryR(id, ctx.view);
if (!sleCreator) if (!sleCreator)
return terNO_ACCOUNT; return terNO_ACCOUNT;
@@ -288,7 +288,7 @@ OfferCreate::checkAcceptAsset(
// Only valid for custom currencies // Only valid for custom currencies
XRPL_ASSERT(!isXRP(asset), "xrpl::OfferCreate::checkAcceptAsset : input is not XRP"); XRPL_ASSERT(!isXRP(asset), "xrpl::OfferCreate::checkAcceptAsset : input is not XRP");
auto const issuerAccount = view.read(keylet::account(asset.getIssuer())); auto const issuerAccount = AccountRootEntryR(asset.getIssuer(), view);
if (!issuerAccount) if (!issuerAccount)
{ {
@@ -707,14 +707,14 @@ OfferCreate::applyGuts(Sandbox& sb, Sandbox& sbCancel)
// Not XRP or MPT // Not XRP or MPT
if (!saTakerPays.integral()) if (!saTakerPays.integral())
{ {
auto const sle = sb.read(keylet::account(uPaysIssuerID)); auto const sle = AccountRootEntryR(uPaysIssuerID, sb);
if (sle && sle->isFieldPresent(sfTickSize)) if (sle && sle->isFieldPresent(sfTickSize))
uTickSize = std::min(uTickSize, (*sle)[sfTickSize]); uTickSize = std::min(uTickSize, (*sle)[sfTickSize]);
} }
// Not XRP or MPT // Not XRP or MPT
if (!saTakerGets.integral()) if (!saTakerGets.integral())
{ {
auto const sle = sb.read(keylet::account(uGetsIssuerID)); auto const sle = AccountRootEntryR(uGetsIssuerID, sb);
if (sle && sle->isFieldPresent(sfTickSize)) if (sle && sle->isFieldPresent(sfTickSize))
uTickSize = std::min(uTickSize, (*sle)[sfTickSize]); uTickSize = std::min(uTickSize, (*sle)[sfTickSize]);
} }
@@ -884,12 +884,12 @@ OfferCreate::applyGuts(Sandbox& sb, Sandbox& sbCancel)
return {tesSUCCESS, true}; return {tesSUCCESS, true};
} }
auto const sleCreator = sb.peek(keylet::account(accountID_)); auto sleCreator = AccountRootEntryW(accountID_, sb, viewJ);
if (!sleCreator) if (!sleCreator)
return {tefINTERNAL, false}; return {tefINTERNAL, false};
{ {
XRPAmount const reserve = accountReserve(sb, sleCreator, viewJ, {.ownerCountDelta = 1}); XRPAmount const reserve = sleCreator.reserve({.ownerCountDelta = 1});
if (preFeeBalance_ < reserve) if (preFeeBalance_ < reserve)
{ {
// If we are here, the signing account had an insufficient reserve // If we are here, the signing account had an insufficient reserve
@@ -923,7 +923,8 @@ OfferCreate::applyGuts(Sandbox& sb, Sandbox& sbCancel)
} }
// Update owner count. // Update owner count.
increaseOwnerCount(sb, sleCreator, {}, 1, viewJ); std::optional<AccountRootEntryW> noSponsor;
sleCreator.increaseOwnerCount(noSponsor, 1);
JLOG(j_.trace()) << "adding to book: " << to_string(saTakerPays.asset()) << " : " JLOG(j_.trace()) << "adding to book: " << to_string(saTakerPays.asset()) << " : "
<< to_string(saTakerGets.asset()) << to_string(saTakerGets.asset())
+2 -1
View File
@@ -4,6 +4,7 @@
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
@@ -46,7 +47,7 @@ DIDDelete::deleteSLE(ApplyView& view, SLE::pointer sle, AccountID const owner, b
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
} }
auto const sleOwner = view.peek(keylet::account(owner)); auto sleOwner = AccountRootEntryW(owner, view);
if (!sleOwner) if (!sleOwner)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
+7 -6
View File
@@ -3,7 +3,7 @@
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -20,6 +20,7 @@
#include <cstddef> #include <cstddef>
#include <memory> #include <memory>
#include <optional>
namespace xrpl { namespace xrpl {
@@ -65,15 +66,14 @@ DIDSet::preflight(PreflightContext const& ctx)
static TER static TER
addSLE(ApplyContext& ctx, SLE::Ref sle, AccountID const& owner) addSLE(ApplyContext& ctx, SLE::Ref sle, AccountID const& owner)
{ {
auto const sleAccount = ctx.view().peek(keylet::account(owner)); auto sleAccount = AccountRootEntryW(owner, ctx.view(), ctx.journal);
if (!sleAccount) if (!sleAccount)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
// Check reserve availability for new object creation // Check reserve availability for new object creation
{ {
auto const balance = STAmount((*sleAccount)[sfBalance]).xrp(); auto const balance = STAmount((*sleAccount)[sfBalance]).xrp();
auto const reserve = auto const reserve = sleAccount.reserve({.ownerCountDelta = 1});
accountReserve(ctx.view(), sleAccount, ctx.journal, {.ownerCountDelta = 1});
if (balance < reserve) if (balance < reserve)
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
@@ -90,8 +90,9 @@ addSLE(ApplyContext& ctx, SLE::Ref sle, AccountID const& owner)
return tecDIR_FULL; // LCOV_EXCL_LINE return tecDIR_FULL; // LCOV_EXCL_LINE
(*sle)[sfOwnerNode] = *page; (*sle)[sfOwnerNode] = *page;
} }
increaseOwnerCount(ctx.view(), sleAccount, {}, 1, ctx.journal); std::optional<AccountRootEntryW> noSponsor;
ctx.view().update(sleAccount); sleAccount.increaseOwnerCount(noSponsor, 1);
sleAccount.update();
return tesSUCCESS; return tesSUCCESS;
} }
@@ -3,6 +3,7 @@
#include <xrpl/basics/Log.h> #include <xrpl/basics/Log.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/EscrowHelpers.h> #include <xrpl/ledger/helpers/EscrowHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
@@ -166,7 +167,7 @@ EscrowCancel::doApply()
} }
} }
auto const sle = ctx_.view().peek(keylet::account(account)); auto sle = AccountRootEntryW(account, ctx_.view());
STAmount const amount = slep->getFieldAmount(sfAmount); STAmount const amount = slep->getFieldAmount(sfAmount);
// The return can re-create a holding the owner deleted while the escrow // The return can re-create a holding the owner deleted while the escrow
@@ -192,7 +193,7 @@ EscrowCancel::doApply()
return escrowUnlockApplyHelper<T>( return escrowUnlockApplyHelper<T>(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
kParityRate, kParityRate,
ctx_.view().rules().enabled(fixCleanup3_2_0) ? sle : slep, ctx_.view().rules().enabled(fixCleanup3_2_0) ? sle.mutableRawSle() : slep,
preFeeBalance_, preFeeBalance_,
amount, amount,
issuer, issuer,
@@ -7,6 +7,7 @@
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
@@ -207,7 +208,7 @@ escrowCreatePreclaimHelper<Issue>(
return tecNO_PERMISSION; return tecNO_PERMISSION;
// If the lsfAllowTrustLineLocking is not enabled, return tecNO_PERMISSION // If the lsfAllowTrustLineLocking is not enabled, return tecNO_PERMISSION
auto const sleIssuer = ctx.view.read(keylet::account(issuer)); auto const sleIssuer = AccountRootEntryR(issuer, ctx.view);
if (!sleIssuer) if (!sleIssuer)
return tecNO_ISSUER; return tecNO_ISSUER;
if (!sleIssuer->isFlag(lsfAllowTrustLineLocking)) if (!sleIssuer->isFlag(lsfAllowTrustLineLocking))
@@ -347,7 +348,7 @@ EscrowCreate::preclaim(PreclaimContext const& ctx)
AccountID const account{ctx.tx[sfAccount]}; AccountID const account{ctx.tx[sfAccount]};
AccountID const dest{ctx.tx[sfDestination]}; AccountID const dest{ctx.tx[sfDestination]};
auto const sled = ctx.view.read(keylet::account(dest)); auto const sled = AccountRootEntryR(dest, ctx.view);
if (!sled) if (!sled)
return tecNO_DST; return tecNO_DST;
@@ -433,7 +434,7 @@ EscrowCreate::doApply()
if (ctx_.tx[~sfFinishAfter] && after(closeTime, ctx_.tx[sfFinishAfter])) if (ctx_.tx[~sfFinishAfter] && after(closeTime, ctx_.tx[sfFinishAfter]))
return tecNO_PERMISSION; return tecNO_PERMISSION;
auto const sle = ctx_.view().peek(keylet::account(accountID_)); auto sle = AccountRootEntryW(accountID_, ctx_.view(), j_);
if (!sle) if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -447,7 +448,7 @@ EscrowCreate::doApply()
// unsponsored this hits the source branch and validates the // unsponsored this hits the source branch and validates the
// source's pre-lock balance against base + (currentOC+1)*increment. // source's pre-lock balance against base + (currentOC+1)*increment.
if (auto const ret = if (auto const ret =
checkReserve(ctx_.getApplyViewContext(), sle, balance, {.ownerCountDelta = 1}, j_); sle.checkReserve(ctx_.getApplyViewContext(), balance, {.ownerCountDelta = 1});
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
@@ -464,15 +465,15 @@ EscrowCreate::doApply()
// - sponsored: 0 — sponsor covers the new owner increment, so the // - sponsored: 0 — sponsor covers the new owner increment, so the
// source only owes reserve for its current owners. // source only owes reserve for its current owners.
// - unsponsored: 1 — source owes reserve including the new increment. // - unsponsored: 1 — source owes reserve including the new increment.
auto const sourceReserve = accountReserve( auto const sourceReserve =
ctx_.view(), sle, j_, {.ownerCountDelta = getTxReserveSponsorID(ctx_.tx) ? 0 : 1}); sle.reserve({.ownerCountDelta = getTxReserveSponsorID(ctx_.tx) ? 0 : 1});
if (balance - STAmount(amount).xrp() < sourceReserve) if (balance - STAmount(amount).xrp() < sourceReserve)
return tecUNFUNDED; return tecUNFUNDED;
} }
// Check destination account // Check destination account
{ {
auto const sled = ctx_.view().read(keylet::account(ctx_.tx[sfDestination])); auto const sled = AccountRootEntryW(ctx_.tx[sfDestination], ctx_.view());
if (!sled) if (!sled)
return tecNO_DST; // LCOV_EXCL_LINE return tecNO_DST; // LCOV_EXCL_LINE
if (sled->isFlag(lsfRequireDestTag) && !ctx_.tx[~sfDestinationTag]) if (sled->isFlag(lsfRequireDestTag) && !ctx_.tx[~sfDestinationTag])
@@ -558,9 +559,9 @@ EscrowCreate::doApply()
} }
// increment owner count // increment owner count
increaseOwnerCount(ctx_.getApplyViewContext(), sle, 1, ctx_.journal); sle.increaseOwnerCount(ctx_.getApplyViewContext(), 1);
addSponsorToLedgerEntry(ctx_.getApplyViewContext(), slep); addSponsorToLedgerEntry(ctx_.getApplyViewContext(), slep);
ctx_.view().update(sle); sle.update();
return tesSUCCESS; return tesSUCCESS;
} }
@@ -9,6 +9,7 @@
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/EscrowHelpers.h> #include <xrpl/ledger/helpers/EscrowHelpers.h>
@@ -314,12 +315,12 @@ EscrowFinish::doApply()
// NOTE: Escrow payments cannot be used to fund accounts. // NOTE: Escrow payments cannot be used to fund accounts.
AccountID const destID = (*slep)[sfDestination]; AccountID const destID = (*slep)[sfDestination];
auto const sled = ctx_.view().peek(keylet::account(destID)); auto sled = AccountRootEntryW(destID, ctx_.view());
if (!sled) if (!sled)
return tecNO_DST; return tecNO_DST;
if (auto err = if (auto err = verifyDepositPreauth(
verifyDepositPreauth(ctx_.tx, ctx_.view(), accountID_, destID, sled, ctx_.journal); ctx_.tx, ctx_.view(), accountID_, destID, sled.rawSle(), ctx_.journal);
!isTesSuccess(err)) !isTesSuccess(err))
return err; return err;
@@ -378,7 +379,7 @@ EscrowFinish::doApply()
return escrowUnlockApplyHelper<T>( return escrowUnlockApplyHelper<T>(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
lockedRate, lockedRate,
sled, sled.mutableRawSle(),
preFeeBalance_, preFeeBalance_,
amount, amount,
issuer, issuer,
@@ -404,7 +405,7 @@ EscrowFinish::doApply()
} }
} }
ctx_.view().update(sled); sled.update();
if (!recycleReserve) if (!recycleReserve)
decreaseOwnerCountForObject(ctx_.view(), account, slep, 1, ctx_.journal); decreaseOwnerCountForObject(ctx_.view(), account, slep, 1, ctx_.journal);
@@ -6,6 +6,7 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/LendingHelpers.h> #include <xrpl/ledger/helpers/LendingHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
@@ -108,7 +109,7 @@ determineBrokerID(ReadView const& view, STTx const& tx)
// Thus, Amount.issuer _should_ be the loan broker's // Thus, Amount.issuer _should_ be the loan broker's
// pseudo-account, but we don't know yet whether it is. // pseudo-account, but we don't know yet whether it is.
auto const maybePseudo = dstAmount->getIssuer(); auto const maybePseudo = dstAmount->getIssuer();
auto const sle = view.read(keylet::account(maybePseudo)); auto const sle = AccountRootEntryR(maybePseudo, view);
// If the account was not found, the transaction can't go further. // If the account was not found, the transaction can't go further.
if (!sle) if (!sle)
@@ -319,7 +320,7 @@ LoanBrokerCoverClawback::preclaim(PreclaimContext const& ctx)
return tecINTERNAL; // tecINSUFFICIENT_FUNDS; LCOV_EXCL_LINE return tecINTERNAL; // tecINSUFFICIENT_FUNDS; LCOV_EXCL_LINE
// Check if the vault asset issuer has the correct flags // Check if the vault asset issuer has the correct flags
auto const sleIssuer = ctx.view.read(keylet::account(vaultAsset.getIssuer())); auto const sleIssuer = AccountRootEntryR(vaultAsset.getIssuer(), ctx.view);
if (!sleIssuer) if (!sleIssuer)
{ {
// LCOV_EXCL_START // LCOV_EXCL_START
@@ -3,6 +3,7 @@
#include <xrpl/basics/Log.h> #include <xrpl/basics/Log.h>
#include <xrpl/basics/Number.h> #include <xrpl/basics/Number.h>
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/LendingHelpers.h> #include <xrpl/ledger/helpers/LendingHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -161,7 +162,7 @@ LoanBrokerDelete::doApply()
if (auto ter = removeEmptyHolding(ctx_.getApplyViewContext(), brokerPseudoID, vaultAsset, j_)) if (auto ter = removeEmptyHolding(ctx_.getApplyViewContext(), brokerPseudoID, vaultAsset, j_))
return ter; return ter;
auto brokerPseudoSLE = view().peek(keylet::account(brokerPseudoID)); auto brokerPseudoSLE = AccountRootEntryW(brokerPseudoID, view());
if (!brokerPseudoSLE) if (!brokerPseudoSLE)
return tefBAD_LEDGER; // LCOV_EXCL_LINE return tefBAD_LEDGER; // LCOV_EXCL_LINE
@@ -183,10 +184,10 @@ LoanBrokerDelete::doApply()
return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE
} }
view().erase(brokerPseudoSLE); brokerPseudoSLE.erase();
{ {
auto owner = view().peek(keylet::account(accountID_)); auto owner = AccountRootEntryW(accountID_, view());
if (!owner) if (!owner)
return tefBAD_LEDGER; // LCOV_EXCL_LINE return tefBAD_LEDGER; // LCOV_EXCL_LINE
@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/LendingHelpers.h> #include <xrpl/ledger/helpers/LendingHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -23,6 +24,7 @@
#include <xrpl/tx/Transactor.h> #include <xrpl/tx/Transactor.h>
#include <memory> #include <memory>
#include <optional>
#include <vector> #include <vector>
namespace xrpl { namespace xrpl {
@@ -236,7 +238,7 @@ LoanBrokerSet::doApply()
auto const vaultAsset = sleVault->at(sfAsset); auto const vaultAsset = sleVault->at(sfAsset);
auto const sequence = tx.getSeqProxy(); auto const sequence = tx.getSeqProxy();
auto owner = view.peek(keylet::account(accountID_)); auto owner = AccountRootEntryW(accountID_, view, j_);
if (!owner) if (!owner)
{ {
// This should be impossible // This should be impossible
@@ -254,8 +256,9 @@ LoanBrokerSet::doApply()
// Increases the owner count by two: one for the LoanBroker object, and // Increases the owner count by two: one for the LoanBroker object, and
// one for the pseudo-account. // one for the pseudo-account.
increaseOwnerCount(view, owner, {}, 2, j_); std::optional<AccountRootEntryW> noSponsor;
if (preFeeBalance_ < accountReserve(view, owner, j_)) owner.increaseOwnerCount(noSponsor, 2);
if (preFeeBalance_ < owner.reserve())
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
auto maybePseudo = createPseudoAccount(view, broker->key(), sfLoanBrokerID); auto maybePseudo = createPseudoAccount(view, broker->key(), sfLoanBrokerID);
@@ -4,6 +4,7 @@
#include <xrpl/basics/Number.h> // IWYU pragma: keep #include <xrpl/basics/Number.h> // IWYU pragma: keep
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/LendingHelpers.h> #include <xrpl/ledger/helpers/LendingHelpers.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
@@ -80,7 +81,7 @@ LoanDelete::doApply()
if (!loanSle) if (!loanSle)
return tefBAD_LEDGER; // LCOV_EXCL_LINE return tefBAD_LEDGER; // LCOV_EXCL_LINE
auto const borrower = loanSle->at(sfBorrower); auto const borrower = loanSle->at(sfBorrower);
auto const borrowerSle = view.peek(keylet::account(borrower)); auto borrowerSle = AccountRootEntryW(borrower, view);
if (!borrowerSle) if (!borrowerSle)
return tefBAD_LEDGER; // LCOV_EXCL_LINE return tefBAD_LEDGER; // LCOV_EXCL_LINE
@@ -7,6 +7,7 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/json/to_string.h> #include <xrpl/json/to_string.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/LendingHelpers.h> #include <xrpl/ledger/helpers/LendingHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
@@ -56,7 +57,7 @@ conservationBalance(ReadView const& view, AccountID const& id, Asset const& asse
{ {
if (isXRP(asset)) if (isXRP(asset))
{ {
auto const sle = view.read(keylet::account(id)); auto const sle = AccountRootEntryR(id, view);
if (!sle) if (!sle)
return STAmount{asset}; // LCOV_EXCL_LINE return STAmount{asset}; // LCOV_EXCL_LINE
return view.balanceHookIOU(id, xrpAccount(), sle->getFieldAmount(sfBalance)); return view.balanceHookIOU(id, xrpAccount(), sle->getFieldAmount(sfBalance));
@@ -391,7 +392,7 @@ LoanPay::doApply()
}(); }();
auto const brokerPayee = sendBrokerFeeToOwner ? brokerOwner : brokerPseudoAccount; auto const brokerPayee = sendBrokerFeeToOwner ? brokerOwner : brokerPseudoAccount;
auto const brokerPayeeSle = view.peek(keylet::account(brokerPayee)); auto const brokerPayeeSle = AccountRootEntryW(brokerPayee, view);
if (!sendBrokerFeeToOwner) if (!sendBrokerFeeToOwner)
{ {
// If we can't send the fee to the owner, and the pseudo-account is // If we can't send the fee to the owner, and the pseudo-account is
@@ -7,6 +7,7 @@
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/LendingHelpers.h> #include <xrpl/ledger/helpers/LendingHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -305,7 +306,7 @@ LoanSet::preclaim(PreclaimContext const& ctx)
auto const brokerPseudo = brokerSle->at(sfAccount); auto const brokerPseudo = brokerSle->at(sfAccount);
auto const borrower = counterparty == brokerOwner ? account : counterparty; auto const borrower = counterparty == brokerOwner ? account : counterparty;
if (auto const borrowerSle = ctx.view.read(keylet::account(borrower)); !borrowerSle) if (auto const borrowerSle = AccountRootEntryR(borrower, ctx.view); !borrowerSle)
{ {
// It may not be possible to hit this case, because it'll fail the // It may not be possible to hit this case, because it'll fail the
// signature check with terNO_ACCOUNT. // signature check with terNO_ACCOUNT.
@@ -443,7 +444,7 @@ LoanSet::doApply()
if (!brokerSle) if (!brokerSle)
return tefBAD_LEDGER; // LCOV_EXCL_LINE return tefBAD_LEDGER; // LCOV_EXCL_LINE
auto const brokerOwner = brokerSle->at(sfOwner); auto const brokerOwner = brokerSle->at(sfOwner);
auto const brokerOwnerSle = view.peek(keylet::account(brokerOwner)); auto const brokerOwnerSle = AccountRootEntryW(brokerOwner, view);
if (!brokerOwnerSle) if (!brokerOwnerSle)
return tefBAD_LEDGER; // LCOV_EXCL_LINE return tefBAD_LEDGER; // LCOV_EXCL_LINE
@@ -455,14 +456,14 @@ LoanSet::doApply()
auto const counterparty = tx[~sfCounterparty].value_or(brokerOwner); auto const counterparty = tx[~sfCounterparty].value_or(brokerOwner);
auto const borrower = counterparty == brokerOwner ? accountID_ : counterparty; auto const borrower = counterparty == brokerOwner ? accountID_ : counterparty;
auto const borrowerSle = view.peek(keylet::account(borrower)); auto borrowerSle = AccountRootEntryW(borrower, view, j_);
if (!borrowerSle) if (!borrowerSle)
{ {
return tefBAD_LEDGER; // LCOV_EXCL_LINE return tefBAD_LEDGER; // LCOV_EXCL_LINE
} }
auto const brokerPseudo = brokerSle->at(sfAccount); auto const brokerPseudo = brokerSle->at(sfAccount);
auto const brokerPseudoSle = view.peek(keylet::account(brokerPseudo)); auto const brokerPseudoSle = AccountRootEntryW(brokerPseudo, view);
if (!brokerPseudoSle) if (!brokerPseudoSle)
{ {
return tefBAD_LEDGER; // LCOV_EXCL_LINE return tefBAD_LEDGER; // LCOV_EXCL_LINE
@@ -581,12 +582,13 @@ LoanSet::doApply()
} }
} }
increaseOwnerCount(view, borrowerSle, {}, 1, j_); std::optional<AccountRootEntryW> noSponsor;
borrowerSle.increaseOwnerCount(noSponsor, 1);
{ {
auto const balance = auto const balance =
accountID_ == borrower ? preFeeBalance_ : borrowerSle->at(sfBalance).value().xrp(); accountID_ == borrower ? preFeeBalance_ : borrowerSle->at(sfBalance).value().xrp();
if (balance < accountReserve(view, borrowerSle, j_)) if (balance < borrowerSle.reserve())
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
} }
@@ -5,7 +5,7 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h> #include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/Asset.h> #include <xrpl/protocol/Asset.h>
@@ -376,7 +376,7 @@ NFTokenAcceptOffer::transferNFToken(
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
auto const sleBuyer = view().read(keylet::account(buyer)); auto const sleBuyer = AccountRootEntryW(buyer, view(), j_);
if (!sleBuyer) if (!sleBuyer)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
@@ -397,7 +397,7 @@ NFTokenAcceptOffer::transferNFToken(
auto const buyerOwnerCountAfter = sleBuyer->getFieldU32(sfOwnerCount); auto const buyerOwnerCountAfter = sleBuyer->getFieldU32(sfOwnerCount);
if (buyerOwnerCountAfter > buyerOwnerCountBefore) if (buyerOwnerCountAfter > buyerOwnerCountBefore)
{ {
if (buyerBalance < accountReserve(view(), sleBuyer, j_)) if (buyerBalance < sleBuyer.reserve())
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
} }
@@ -1,6 +1,8 @@
#include <xrpl/tx/transactors/nft/NFTokenBurn.h> #include <xrpl/tx/transactors/nft/NFTokenBurn.h>
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h> #include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Protocol.h> #include <xrpl/protocol/Protocol.h>
@@ -43,7 +45,7 @@ NFTokenBurn::preclaim(PreclaimContext const& ctx)
if (auto const issuer = nft::getIssuer(ctx.tx[sfNFTokenID]); issuer != account) if (auto const issuer = nft::getIssuer(ctx.tx[sfNFTokenID]); issuer != account)
{ {
if (auto const sle = ctx.view.read(keylet::account(issuer)); sle) if (auto const sle = AccountRootEntryR(issuer, ctx.view); sle)
{ {
if (auto const minter = (*sle)[~sfNFTokenMinter]; minter != account) if (auto const minter = (*sle)[~sfNFTokenMinter]; minter != account)
return tecNO_PERMISSION; return tecNO_PERMISSION;
@@ -68,10 +70,10 @@ NFTokenBurn::doApply()
if (!isTesSuccess(ret)) if (!isTesSuccess(ret))
return ret; return ret;
if (auto issuer = view().peek(keylet::account(nft::getIssuer(ctx_.tx[sfNFTokenID])))) if (auto issuer = AccountRootEntryW(nft::getIssuer(ctx_.tx[sfNFTokenID]), view()))
{ {
(*issuer)[~sfBurnedNFTokens] = (*issuer)[~sfBurnedNFTokens].valueOr(0) + 1; (*issuer)[~sfBurnedNFTokens] = (*issuer)[~sfBurnedNFTokens].valueOr(0) + 1;
view().update(issuer); issuer.update();
} }
// Delete up to 500 offers in total. // Delete up to 500 offers in total.
@@ -2,12 +2,12 @@
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h> #include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/InnerObjectFormats.h> #include <xrpl/protocol/InnerObjectFormats.h>
#include <xrpl/protocol/Protocol.h> #include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/SField.h> #include <xrpl/protocol/SField.h>
@@ -186,7 +186,7 @@ NFTokenMint::preclaim(PreclaimContext const& ctx)
// transaction. Check that and verify that this is allowed: // transaction. Check that and verify that this is allowed:
if (auto issuer = ctx.tx[~sfIssuer]) if (auto issuer = ctx.tx[~sfIssuer])
{ {
auto const sle = ctx.view.read(keylet::account(*issuer)); auto const sle = AccountRootEntryR(*issuer, ctx.view);
if (!sle) if (!sle)
return tecNO_ISSUER; return tecNO_ISSUER;
@@ -225,8 +225,8 @@ NFTokenMint::doApply()
auto const issuer = ctx_.tx[~sfIssuer].value_or(accountID_); auto const issuer = ctx_.tx[~sfIssuer].value_or(accountID_);
auto const tokenSeq = [this, &issuer]() -> std::expected<std::uint32_t, TER> { auto const tokenSeq = [this, &issuer]() -> std::expected<std::uint32_t, TER> {
auto const root = view().peek(keylet::account(issuer)); auto root = AccountRootEntryW(issuer, view());
if (root == nullptr) if (!root)
{ {
// Should not happen. Checked in preclaim. // Should not happen. Checked in preclaim.
return std::unexpected(tecNO_ISSUER); return std::unexpected(tecNO_ISSUER);
@@ -271,7 +271,7 @@ NFTokenMint::doApply()
if (tokenSeq + 1u == 0u || tokenSeq < offset) if (tokenSeq + 1u == 0u || tokenSeq < offset)
return std::unexpected(tecMAX_SEQUENCE_REACHED); return std::unexpected(tecMAX_SEQUENCE_REACHED);
ctx_.view().update(root); root.update();
return tokenSeq; return tokenSeq;
}(); }();
@@ -279,7 +279,7 @@ NFTokenMint::doApply()
return (tokenSeq.error()); return (tokenSeq.error());
std::uint32_t const ownerCountBefore = std::uint32_t const ownerCountBefore =
view().read(keylet::account(accountID_))->getFieldU32(sfOwnerCount); AccountRootEntryW(accountID_, view())->getFieldU32(sfOwnerCount);
// Assemble the new NFToken. // Assemble the new NFToken.
SOTemplate const* nfTokenTemplate = SOTemplate const* nfTokenTemplate =
@@ -332,14 +332,14 @@ NFTokenMint::doApply()
// allows NFTs to be added to the page (and burn fees) without // allows NFTs to be added to the page (and burn fees) without
// requiring the reserve to be met each time. The reserve is // requiring the reserve to be met each time. The reserve is
// only managed when a new NFT page or sell offer is added. // only managed when a new NFT page or sell offer is added.
auto const sleAccount = view().read(keylet::account(accountID_)); auto const sleAccount = AccountRootEntryW(accountID_, view(), j_);
if (!sleAccount) if (!sleAccount)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
if (auto const ownerCountAfter = sleAccount->getFieldU32(sfOwnerCount); if (auto const ownerCountAfter = sleAccount->getFieldU32(sfOwnerCount);
ownerCountAfter > ownerCountBefore) ownerCountAfter > ownerCountBefore)
{ {
if (preFeeBalance_ < accountReserve(view(), sleAccount, j_)) if (preFeeBalance_ < sleAccount.reserve())
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
} }
return tesSUCCESS; return tesSUCCESS;
@@ -2,9 +2,10 @@
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h> #include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Protocol.h> #include <xrpl/protocol/Protocol.h>
#include <xrpl/protocol/SField.h> #include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h> #include <xrpl/protocol/STLedgerEntry.h>
@@ -47,7 +48,7 @@ NFTokenModify::preclaim(PreclaimContext const& ctx)
// Verify permissions for the issuer // Verify permissions for the issuer
if (AccountID const issuer = nft::getIssuer(ctx.tx[sfNFTokenID]); issuer != account) if (AccountID const issuer = nft::getIssuer(ctx.tx[sfNFTokenID]); issuer != account)
{ {
auto const sle = ctx.view.read(keylet::account(issuer)); auto const sle = AccountRootEntryR(issuer, ctx.view);
if (!sle) if (!sle)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
if (auto const minter = (*sle)[~sfNFTokenMinter]; minter != account) if (auto const minter = (*sle)[~sfNFTokenMinter]; minter != account)
@@ -3,6 +3,7 @@
#include <xrpl/basics/Log.h> #include <xrpl/basics/Log.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/OracleHelpers.h> #include <xrpl/ledger/helpers/OracleHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
@@ -67,7 +68,7 @@ OracleDelete::deleteOracle(
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
} }
auto const sleOwner = view.peek(keylet::account(account)); auto sleOwner = AccountRootEntryW(account, view);
if (!sleOwner) if (!sleOwner)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
+17 -19
View File
@@ -3,7 +3,7 @@
#include <xrpl/basics/chrono.h> #include <xrpl/basics/chrono.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/OracleHelpers.h> #include <xrpl/ledger/helpers/OracleHelpers.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -27,6 +27,7 @@
#include <cstdlib> #include <cstdlib>
#include <map> #include <map>
#include <memory> #include <memory>
#include <optional>
#include <set> #include <set>
#include <utility> #include <utility>
@@ -64,7 +65,7 @@ OracleSet::preflight(PreflightContext const& ctx)
TER TER
OracleSet::preclaim(PreclaimContext const& ctx) OracleSet::preclaim(PreclaimContext const& ctx)
{ {
auto const sleSetter = ctx.view.read(keylet::account(ctx.tx.getAccountID(sfAccount))); auto const sleSetter = AccountRootEntryR(ctx.tx.getAccountID(sfAccount), ctx.view, ctx.j);
if (!sleSetter) if (!sleSetter)
return terNO_ACCOUNT; // LCOV_EXCL_LINE return terNO_ACCOUNT; // LCOV_EXCL_LINE
@@ -172,8 +173,7 @@ OracleSet::preclaim(PreclaimContext const& ctx)
if (pairs.size() > kMaxOracleDataSeries) if (pairs.size() > kMaxOracleDataSeries)
return tecARRAY_TOO_LARGE; return tecARRAY_TOO_LARGE;
auto const reserve = auto const reserve = sleSetter.reserve({.ownerCountDelta = adjustReserve});
accountReserve(ctx.view, sleSetter, ctx.j, {.ownerCountDelta = adjustReserve});
auto const& balance = sleSetter->getFieldAmount(sfBalance); auto const& balance = sleSetter->getFieldAmount(sfBalance);
if (balance < reserve) if (balance < reserve)
@@ -187,22 +187,20 @@ adjustOracleOwnerCount(ApplyContext& ctx, int count)
{ {
XRPL_ASSERT(std::abs(count) <= 2, "xrpl::adjustOracleOwnerCount abs(counter) <= 2"); XRPL_ASSERT(std::abs(count) <= 2, "xrpl::adjustOracleOwnerCount abs(counter) <= 2");
if (auto const sleAccount = ctx.view().peek(keylet::account(ctx.tx[sfAccount]))) auto sleAccount = AccountRootEntryW(ctx.tx[sfAccount], ctx.view(), ctx.journal);
{ if (!sleAccount)
if (count > 0) return false; // LCOV_EXCL_LINE
{
increaseOwnerCount(
ctx.view(), sleAccount, {}, static_cast<std::uint32_t>(count), ctx.journal);
}
else if (count < 0)
{
decreaseOwnerCount(
ctx.view(), sleAccount, {}, static_cast<std::uint32_t>(-count), ctx.journal);
}
return true;
}
return false; // LCOV_EXCL_LINE std::optional<AccountRootEntryW> noSponsor;
if (count > 0)
{
sleAccount.increaseOwnerCount(noSponsor, static_cast<std::uint32_t>(count));
}
else if (count < 0)
{
sleAccount.decreaseOwnerCount(noSponsor, static_cast<std::uint32_t>(-count));
}
return true;
} }
static void static void
@@ -4,6 +4,7 @@
#include <xrpl/basics/Slice.h> #include <xrpl/basics/Slice.h>
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
@@ -103,7 +104,7 @@ DepositPreauth::preclaim(PreclaimContext const& ctx)
{ {
// Verify that the Authorize account is present in the ledger. // Verify that the Authorize account is present in the ledger.
AccountID const auth{ctx.tx[sfAuthorize]}; AccountID const auth{ctx.tx[sfAuthorize]};
auto const sleAuth = ctx.view.read(keylet::account(auth)); auto const sleAuth = AccountRootEntryR(auth, ctx.view);
if (!sleAuth) if (!sleAuth)
return tecNO_TARGET; return tecNO_TARGET;
@@ -161,15 +162,15 @@ DepositPreauth::doApply()
auto applyViewContext = ctx_.getApplyViewContext(); auto applyViewContext = ctx_.getApplyViewContext();
if (ctx_.tx.isFieldPresent(sfAuthorize)) if (ctx_.tx.isFieldPresent(sfAuthorize))
{ {
auto const sleOwner = view().peek(keylet::account(accountID_)); auto sleOwner = AccountRootEntryW(accountID_, view(), j_);
if (!sleOwner) if (!sleOwner)
return {tefINTERNAL}; return {tefINTERNAL};
// A preauth counts against the reserve of the issuing account, but we // A preauth counts against the reserve of the issuing account, but we
// check the starting balance because we want to allow dipping into the // check the starting balance because we want to allow dipping into the
// reserve to pay fees. // reserve to pay fees.
if (auto const ret = checkReserve( if (auto const ret =
applyViewContext, sleOwner, preFeeBalance_, {.ownerCountDelta = 1}, j_); sleOwner.checkReserve(applyViewContext, preFeeBalance_, {.ownerCountDelta = 1});
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
@@ -195,7 +196,7 @@ DepositPreauth::doApply()
slePreauth->setFieldU64(sfOwnerNode, *page); slePreauth->setFieldU64(sfOwnerNode, *page);
// If we succeeded, the new entry counts against the creator's reserve. // If we succeeded, the new entry counts against the creator's reserve.
increaseOwnerCount(applyViewContext, sleOwner, 1, j_); sleOwner.increaseOwnerCount(applyViewContext, 1);
addSponsorToLedgerEntry(applyViewContext, slePreauth); addSponsorToLedgerEntry(applyViewContext, slePreauth);
} }
else if (ctx_.tx.isFieldPresent(sfUnauthorize)) else if (ctx_.tx.isFieldPresent(sfUnauthorize))
@@ -206,15 +207,15 @@ DepositPreauth::doApply()
} }
else if (ctx_.tx.isFieldPresent(sfAuthorizeCredentials)) else if (ctx_.tx.isFieldPresent(sfAuthorizeCredentials))
{ {
auto const sleOwner = view().peek(keylet::account(accountID_)); auto sleOwner = AccountRootEntryW(accountID_, view(), j_);
if (!sleOwner) if (!sleOwner)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
// A preauth counts against the reserve of the issuing account, but we // A preauth counts against the reserve of the issuing account, but we
// check the starting balance because we want to allow dipping into the // check the starting balance because we want to allow dipping into the
// reserve to pay fees. // reserve to pay fees.
if (auto const ret = checkReserve( if (auto const ret =
applyViewContext, sleOwner, preFeeBalance_, {.ownerCountDelta = 1}, j_); sleOwner.checkReserve(applyViewContext, preFeeBalance_, {.ownerCountDelta = 1});
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
@@ -254,7 +255,7 @@ DepositPreauth::doApply()
slePreauth->setFieldU64(sfOwnerNode, *page); slePreauth->setFieldU64(sfOwnerNode, *page);
// If we succeeded, the new entry counts against the creator's reserve. // If we succeeded, the new entry counts against the creator's reserve.
increaseOwnerCount(applyViewContext, sleOwner, 1, j_); sleOwner.increaseOwnerCount(applyViewContext, 1);
addSponsorToLedgerEntry(applyViewContext, slePreauth); addSponsorToLedgerEntry(applyViewContext, slePreauth);
} }
else if (ctx_.tx.isFieldPresent(sfUnauthorizeCredentials)) else if (ctx_.tx.isFieldPresent(sfUnauthorizeCredentials))
@@ -289,7 +290,7 @@ DepositPreauth::removeFromLedger(ApplyView& view, UInt256 const& preauthIndex, b
} }
// If we succeeded, update the DepositPreauth owner's reserve. // If we succeeded, update the DepositPreauth owner's reserve.
auto const sleOwner = view.peek(keylet::account(account)); auto sleOwner = AccountRootEntryW(account, view);
if (!sleOwner) if (!sleOwner)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
+29 -13
View File
@@ -6,6 +6,7 @@
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/PaymentSandbox.h> #include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
@@ -386,7 +387,7 @@ Payment::preclaim(PreclaimContext const& ctx)
STAmount const dstAmount(ctx.tx[sfAmount]); STAmount const dstAmount(ctx.tx[sfAmount]);
auto const k = keylet::account(dstAccountID); auto const k = keylet::account(dstAccountID);
auto const sleDst = ctx.view.read(k); auto const sleDst = AccountRootEntryR(k, ctx.view);
if (!sleDst) if (!sleDst)
{ {
@@ -564,19 +565,19 @@ Payment::doApply()
// Open a ledger for editing. // Open a ledger for editing.
auto const k = keylet::account(dstAccountID); auto const k = keylet::account(dstAccountID);
SLE::pointer sleDst = view().peek(k); AccountRootEntryW sleDst(k, view());
if (!sleDst) if (!sleDst)
{ {
// Create the account. // Create the account.
sleDst = std::make_shared<SLE>(k); sleDst.newSLE();
sleDst->setAccountID(sfAccount, dstAccountID); sleDst->setAccountID(sfAccount, dstAccountID);
sleDst->setFieldU32(sfSequence, view().seq()); sleDst->setFieldU32(sfSequence, view().seq());
sleDst->setFieldAmount(sfBalance, XRPAmount(beast::kZero)); sleDst->setFieldAmount(sfBalance, XRPAmount(beast::kZero));
if (ctx_.tx.isFlag(tfSponsorCreatedAccount)) if (ctx_.tx.isFlag(tfSponsorCreatedAccount))
{ {
auto const sponsor = view().peek(keylet::account(accountID_)); auto sponsor = AccountRootEntryW(accountID_, view());
if (!sponsor) if (!sponsor)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
auto const currentSponsoringAccountCount = auto const currentSponsoringAccountCount =
@@ -591,18 +592,18 @@ Payment::doApply()
} }
sponsor->setFieldU32(sfSponsoringAccountCount, currentSponsoringAccountCount + 1); sponsor->setFieldU32(sfSponsoringAccountCount, currentSponsoringAccountCount + 1);
addSponsorToLedgerEntry(sleDst, sponsor); addSponsorToLedgerEntry(sleDst.mutableRawSle(), sponsor.rawSle());
view().update(sponsor); sponsor.update();
} }
view().insert(sleDst); sleDst.insert();
} }
else else
{ {
// Tell the engine that we are intending to change the destination // Tell the engine that we are intending to change the destination
// account. The source account gets always charged a fee so it's always // account. The source account gets always charged a fee so it's always
// marked as modified. // marked as modified.
view().update(sleDst); sleDst.update();
} }
bool const mpTokensV2 = view().rules().enabled(featureMPTokensV2); bool const mpTokensV2 = view().rules().enabled(featureMPTokensV2);
@@ -621,7 +622,12 @@ Payment::doApply()
// 2. If Account is deposit preauthorized by destination. // 2. If Account is deposit preauthorized by destination.
if (auto err = verifyDepositPreauth( if (auto err = verifyDepositPreauth(
ctx_.tx, ctx_.view(), accountID_, dstAccountID, sleDst, ctx_.journal); ctx_.tx,
ctx_.view(),
accountID_,
dstAccountID,
sleDst.mutableRawSle(),
ctx_.journal);
!isTesSuccess(err)) !isTesSuccess(err))
return err; return err;
@@ -691,7 +697,12 @@ Payment::doApply()
return ter; return ter;
if (auto err = verifyDepositPreauth( if (auto err = verifyDepositPreauth(
ctx_.tx, ctx_.view(), accountID_, dstAccountID, sleDst, ctx_.journal); ctx_.tx,
ctx_.view(),
accountID_,
dstAccountID,
sleDst.mutableRawSle(),
ctx_.journal);
!isTesSuccess(err)) !isTesSuccess(err))
return err; return err;
@@ -757,13 +768,13 @@ Payment::doApply()
// Direct XRP payment. // Direct XRP payment.
auto const sleSrc = view().peek(keylet::account(accountID_)); auto sleSrc = AccountRootEntryW(accountID_, view(), j_);
if (!sleSrc) if (!sleSrc)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
// the number of reserves in this ledger for this account that require a // the number of reserves in this ledger for this account that require a
// reserve. // reserve.
auto const reserve = accountReserve(view(), sleSrc, j_); auto const reserve = sleSrc.reserve();
// In a delegated / fee sponsored payment, the fee payer is not the source account (accountID_). // In a delegated / fee sponsored payment, the fee payer is not the source account (accountID_).
bool const accountIsPayer = ctx_.tx.getFeePayerID() == accountID_; bool const accountIsPayer = ctx_.tx.getFeePayerID() == accountID_;
@@ -820,7 +831,12 @@ Payment::doApply()
if (dstAmount > dstReserve || sleDst->getFieldAmount(sfBalance) > dstReserve) if (dstAmount > dstReserve || sleDst->getFieldAmount(sfBalance) > dstReserve)
{ {
if (auto err = verifyDepositPreauth( if (auto err = verifyDepositPreauth(
ctx_.tx, ctx_.view(), accountID_, dstAccountID, sleDst, ctx_.journal); ctx_.tx,
ctx_.view(),
accountID_,
dstAccountID,
sleDst.mutableRawSle(),
ctx_.journal);
!isTesSuccess(err)) !isTesSuccess(err))
return err; return err;
} }
@@ -3,11 +3,11 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/PaymentChannelHelpers.h> #include <xrpl/ledger/helpers/PaymentChannelHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Keylet.h> #include <xrpl/protocol/Keylet.h>
#include <xrpl/protocol/LedgerFormats.h> #include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/PayChan.h> #include <xrpl/protocol/PayChan.h>
@@ -159,12 +159,12 @@ PaymentChannelClaim::doApply()
return tecUNFUNDED_PAYMENT; return tecUNFUNDED_PAYMENT;
} }
auto const sled = ctx_.view().peek(keylet::account(dst)); auto sled = AccountRootEntryW(dst, ctx_.view());
if (!sled) if (!sled)
return tecNO_DST; return tecNO_DST;
if (auto err = if (auto err = verifyDepositPreauth(
verifyDepositPreauth(ctx_.tx, ctx_.view(), txAccount, dst, sled, ctx_.journal); ctx_.tx, ctx_.view(), txAccount, dst, sled.rawSle(), ctx_.journal);
!isTesSuccess(err)) !isTesSuccess(err))
return err; return err;
@@ -173,7 +173,7 @@ PaymentChannelClaim::doApply()
XRPL_ASSERT( XRPL_ASSERT(
reqDelta >= beast::kZero, "xrpl::PaymentChannelClaim::doApply : minimum balance delta"); reqDelta >= beast::kZero, "xrpl::PaymentChannelClaim::doApply : minimum balance delta");
(*sled)[sfBalance] = (*sled)[sfBalance] + reqDelta; (*sled)[sfBalance] = (*sled)[sfBalance] + reqDelta;
ctx_.view().update(sled); sled.update();
ctx_.view().update(slep); ctx_.view().update(slep);
} }
@@ -5,6 +5,7 @@
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -73,7 +74,7 @@ TER
PaymentChannelCreate::preclaim(PreclaimContext const& ctx) PaymentChannelCreate::preclaim(PreclaimContext const& ctx)
{ {
auto const account = ctx.tx[sfAccount]; auto const account = ctx.tx[sfAccount];
auto const sle = ctx.view.read(keylet::account(account)); auto const sle = AccountRootEntryR(account, ctx.view);
if (!sle) if (!sle)
return terNO_ACCOUNT; return terNO_ACCOUNT;
@@ -94,7 +95,7 @@ PaymentChannelCreate::preclaim(PreclaimContext const& ctx)
{ {
// Check destination account // Check destination account
auto const sled = ctx.view.read(keylet::account(dst)); auto const sled = AccountRootEntryR(dst, ctx.view);
if (!sled) if (!sled)
return tecNO_DST; return tecNO_DST;
@@ -122,7 +123,7 @@ TER
PaymentChannelCreate::doApply() PaymentChannelCreate::doApply()
{ {
auto const account = ctx_.tx[sfAccount]; auto const account = ctx_.tx[sfAccount];
auto const sle = ctx_.view().peek(keylet::account(account)); auto sle = AccountRootEntryW(account, ctx_.view(), j_);
if (!sle) if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -140,8 +141,8 @@ PaymentChannelCreate::doApply()
// validates the sponsor's reserve + remaining credit. When // validates the sponsor's reserve + remaining credit. When
// unsponsored this hits the source branch and validates the // unsponsored this hits the source branch and validates the
// source's pre-lock balance against base + (currentOC+1)*increment. // source's pre-lock balance against base + (currentOC+1)*increment.
if (auto const ret = checkReserve( if (auto const ret = sle.checkReserve(
ctx_.getApplyViewContext(), sle, preFeeBalance_, {.ownerCountDelta = 1}, j_); ctx_.getApplyViewContext(), preFeeBalance_, {.ownerCountDelta = 1});
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
@@ -157,8 +158,8 @@ PaymentChannelCreate::doApply()
// - sponsored: 0 — sponsor covers the new owner increment, so // - sponsored: 0 — sponsor covers the new owner increment, so
// the source only owes reserve for its current owners. // the source only owes reserve for its current owners.
// - unsponsored: 1 — source owes reserve including the new increment. // - unsponsored: 1 — source owes reserve including the new increment.
auto const sourceReserve = accountReserve( auto const sourceReserve =
ctx_.view(), sle, j_, {.ownerCountDelta = getTxReserveSponsorID(ctx_.tx) ? 0 : 1}); sle.reserve({.ownerCountDelta = getTxReserveSponsorID(ctx_.tx) ? 0 : 1});
if (preFeeBalance_ - ctx_.tx[sfAmount].xrp() < sourceReserve) if (preFeeBalance_ - ctx_.tx[sfAmount].xrp() < sourceReserve)
return tecUNFUNDED; return tecUNFUNDED;
} }
@@ -210,9 +211,9 @@ PaymentChannelCreate::doApply()
// Deduct owner's balance, increment owner count // Deduct owner's balance, increment owner count
(*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount]; (*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount];
increaseOwnerCount(ctx_.getApplyViewContext(), sle, 1, ctx_.journal); sle.increaseOwnerCount(ctx_.getApplyViewContext(), 1);
addSponsorToLedgerEntry(ctx_.getApplyViewContext(), slep); addSponsorToLedgerEntry(ctx_.getApplyViewContext(), slep);
ctx_.view().update(sle); sle.update();
return tesSUCCESS; return tesSUCCESS;
} }
@@ -4,11 +4,10 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/PaymentChannelHelpers.h> #include <xrpl/ledger/helpers/PaymentChannelHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Keylet.h> #include <xrpl/protocol/Keylet.h>
#include <xrpl/protocol/LedgerFormats.h> #include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/SField.h> #include <xrpl/protocol/SField.h>
@@ -82,14 +81,14 @@ PaymentChannelFund::doApply()
ctx_.view().update(slep); ctx_.view().update(slep);
} }
auto const sle = ctx_.view().peek(keylet::account(txAccount)); auto sle = AccountRootEntryW(txAccount, ctx_.view(), j_);
if (!sle) if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
{ {
// Check reserve and funds availability // Check reserve and funds availability
STAmount const balance = (*sle)[sfBalance]; STAmount const balance = (*sle)[sfBalance];
if (auto const ret = checkReserve(ctx_.getApplyViewContext(), sle, balance.xrp(), {}, j_); if (auto const ret = sle.checkReserve(ctx_.getApplyViewContext(), balance.xrp(), {});
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
@@ -99,12 +98,12 @@ PaymentChannelFund::doApply()
// when a sponsor is present and would ignore the source's post-lock // when a sponsor is present and would ignore the source's post-lock
// balance entirely. Funding an existing channel adds no owned object, // balance entirely. Funding an existing channel adds no owned object,
// so there is no owner-count delta. // so there is no owner-count delta.
if (balance < accountReserve(ctx_.view(), sle, j_) + ctx_.tx[sfAmount]) if (balance < sle.reserve() + ctx_.tx[sfAmount])
return tecUNFUNDED; return tecUNFUNDED;
} }
// do not allow adding funds if dst does not exist // do not allow adding funds if dst does not exist
if (AccountID const dst = (*slep)[sfDestination]; !ctx_.view().read(keylet::account(dst))) if (AccountID const dst = (*slep)[sfDestination]; !AccountRootEntryW(dst, ctx_.view()))
{ {
return tecNO_DST; return tecNO_DST;
} }
@@ -113,7 +112,7 @@ PaymentChannelFund::doApply()
ctx_.view().update(slep); ctx_.view().update(slep);
(*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount]; (*sle)[sfBalance] = (*sle)[sfBalance] - ctx_.tx[sfAmount];
ctx_.view().update(sle); sle.update();
return tesSUCCESS; return tesSUCCESS;
} }
@@ -3,6 +3,7 @@
#include <xrpl/basics/Log.h> #include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/SField.h> #include <xrpl/protocol/SField.h>
@@ -63,7 +64,7 @@ PermissionedDomainDelete::doApply()
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
} }
auto const ownerSle = view().peek(keylet::account(accountID_)); auto ownerSle = AccountRootEntryW(accountID_, view());
XRPL_ASSERT( XRPL_ASSERT(
ownerSle && ownerSle->getFieldU32(sfOwnerCount) > 0, ownerSle && ownerSle->getFieldU32(sfOwnerCount) > 0,
"xrpl::PermissionedDomainDelete::doApply : nonzero owner count"); "xrpl::PermissionedDomainDelete::doApply : nonzero owner count");
@@ -2,7 +2,7 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -19,6 +19,7 @@
#include <xrpl/tx/Transactor.h> #include <xrpl/tx/Transactor.h>
#include <memory> #include <memory>
#include <optional>
#include <utility> #include <utility>
namespace xrpl { namespace xrpl {
@@ -80,7 +81,7 @@ PermissionedDomainSet::preclaim(PreclaimContext const& ctx)
TER TER
PermissionedDomainSet::doApply() PermissionedDomainSet::doApply()
{ {
auto const ownerSle = view().peek(keylet::account(accountID_)); auto ownerSle = AccountRootEntryW(accountID_, view(), ctx_.journal);
if (!ownerSle) if (!ownerSle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -109,8 +110,7 @@ PermissionedDomainSet::doApply()
// Create new permissioned domain. // Create new permissioned domain.
// Check reserve availability for new object creation // Check reserve availability for new object creation
auto const balance = STAmount((*ownerSle)[sfBalance]).xrp(); auto const balance = STAmount((*ownerSle)[sfBalance]).xrp();
auto const reserve = auto const reserve = ownerSle.reserve({.ownerCountDelta = 1});
accountReserve(ctx_.view(), ownerSle, ctx_.journal, {.ownerCountDelta = 1});
if (balance < reserve) if (balance < reserve)
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
@@ -130,7 +130,8 @@ PermissionedDomainSet::doApply()
slePd->setFieldU64(sfOwnerNode, *page); slePd->setFieldU64(sfOwnerNode, *page);
// If we succeeded, the new entry counts against the creator's reserve. // If we succeeded, the new entry counts against the creator's reserve.
increaseOwnerCount(view(), ownerSle, {}, 1, ctx_.journal); std::optional<AccountRootEntryW> noSponsor;
ownerSle.increaseOwnerCount(noSponsor, 1);
view().insert(slePd); view().insert(slePd);
} }
@@ -4,6 +4,7 @@
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/ProposalHelpers.h> #include <xrpl/ledger/helpers/ProposalHelpers.h>
@@ -159,7 +160,7 @@ TransactionProposalCreate::preclaim(PreclaimContext const& ctx)
} }
AccountID const target = proposedTx.getAccountID(sfAccount); AccountID const target = proposedTx.getAccountID(sfAccount);
auto const sleTarget = ctx.view.read(keylet::account(target)); auto const sleTarget = AccountRootEntryR(target, ctx.view);
if (!sleTarget) if (!sleTarget)
{ {
JLOG(ctx.j.debug()) << "TransactionProposalCreate: target account " JLOG(ctx.j.debug()) << "TransactionProposalCreate: target account "
@@ -297,7 +298,7 @@ TransactionProposalCreate::preclaim(PreclaimContext const& ctx)
TER TER
TransactionProposalCreate::doApply() TransactionProposalCreate::doApply()
{ {
auto const sle = view().peek(keylet::account(accountID_)); auto sle = AccountRootEntryW(accountID_, view(), ctx_.journal);
if (!sle) if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -307,12 +308,10 @@ TransactionProposalCreate::doApply()
// The proposal holds a full transaction plus its collected signatures, so // The proposal holds a full transaction plus its collected signatures, so
// it reserves more than a typical ledger entry (5 increments; 10 for a // it reserves more than a typical ledger entry (5 increments; 10 for a
// proposed Batch). // proposed Batch).
if (auto const ret = checkReserve( if (auto const ret = sle.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
sle,
preFeeBalance_, preFeeBalance_,
{.ownerCountDelta = static_cast<int>(ownerCount)}, {.ownerCountDelta = static_cast<int>(ownerCount)});
ctx_.journal);
!isTesSuccess(ret)) !isTesSuccess(ret))
return ret; return ret;
@@ -327,7 +326,6 @@ TransactionProposalCreate::doApply()
view().insert(sleProposal); view().insert(sleProposal);
auto viewJ = ctx_.registry.get().getJournal("View");
{ {
auto const page = view().dirInsert( auto const page = view().dirInsert(
keylet::ownerDir(accountID_), proposalKeylet, describeOwnerDir(accountID_)); keylet::ownerDir(accountID_), proposalKeylet, describeOwnerDir(accountID_));
@@ -336,7 +334,7 @@ TransactionProposalCreate::doApply()
sleProposal->setFieldU64(sfOwnerNode, *page); sleProposal->setFieldU64(sfOwnerNode, *page);
} }
increaseOwnerCount(ctx_.getApplyViewContext(), sle, ownerCount, viewJ); sle.increaseOwnerCount(ctx_.getApplyViewContext(), ownerCount);
addSponsorToLedgerEntry(ctx_.getApplyViewContext(), sleProposal); addSponsorToLedgerEntry(ctx_.getApplyViewContext(), sleProposal);
return tesSUCCESS; return tesSUCCESS;
} }
@@ -7,6 +7,7 @@
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -164,11 +165,11 @@ SponsorshipSet::preclaim(PreclaimContext const& ctx)
if (sponseeID == sponsorID) if (sponseeID == sponsorID)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
auto const sponsorAccSle = ctx.view.read(keylet::account(sponsorID)); auto const sponsorAccSle = AccountRootEntryR(sponsorID, ctx.view);
if (!sponsorAccSle) if (!sponsorAccSle)
return tecNO_DST; return tecNO_DST;
auto const sponseeSle = ctx.view.read(keylet::account(sponseeID)); auto const sponseeSle = AccountRootEntryR(sponseeID, ctx.view);
if (!sponseeSle) if (!sponseeSle)
return tecNO_DST; return tecNO_DST;
@@ -212,7 +213,7 @@ deleteSponsorship(ApplyView& view, SLE::Ref sle, beast::Journal j)
// The sponsor owns the Sponsorship object, so deletion releases the // The sponsor owns the Sponsorship object, so deletion releases the
// sponsor's owner reserve. // sponsor's owner reserve.
auto sponsorAccSle = view.peek(keylet::account(sponsorID)); auto sponsorAccSle = AccountRootEntryW(sponsorID, view);
if (!sponsorAccSle) if (!sponsorAccSle)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
@@ -237,7 +238,7 @@ deleteSponsorship(ApplyView& view, SLE::Ref sle, beast::Journal j)
if (sle->isFieldPresent(sfFeeAmount)) if (sle->isFieldPresent(sfFeeAmount))
{ {
(*sponsorAccSle)[sfBalance] += sle->getFieldAmount(sfFeeAmount); (*sponsorAccSle)[sfBalance] += sle->getFieldAmount(sfFeeAmount);
view.update(sponsorAccSle); sponsorAccSle.update();
} }
view.erase(sle); view.erase(sle);
@@ -250,8 +251,8 @@ SponsorshipSet::createSponsorship(
Keylet const& sponsorshipKeylet, Keylet const& sponsorshipKeylet,
AccountID const& sponsorID, AccountID const& sponsorID,
AccountID const& sponseeID, AccountID const& sponseeID,
SLE::Ref sponsorAccSle, AccountRootEntryW& sponsorAccSle,
SLE::Ref reserveSponsorAccSle) std::optional<AccountRootEntryW>& reserveSponsorAccSle)
{ {
auto const feeAmountDelta = ctx_.tx[~sfFeeAmountDelta]; auto const feeAmountDelta = ctx_.tx[~sfFeeAmountDelta];
auto const maxFee = ctx_.tx[~sfMaxFee]; auto const maxFee = ctx_.tx[~sfMaxFee];
@@ -276,13 +277,11 @@ SponsorshipSet::createSponsorship(
if (hasPositiveFeeAmount) if (hasPositiveFeeAmount)
sponsorBalanceAfterFee -= *feeAmountDelta; sponsorBalanceAfterFee -= *feeAmountDelta;
if (auto const ret = checkReserve( if (auto const ret = sponsorAccSle.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
sponsorAccSle,
sponsorBalanceAfterFee.xrp(), sponsorBalanceAfterFee.xrp(),
reserveSponsorAccSle, reserveSponsorAccSle,
{.ownerCountDelta = 1}, {.ownerCountDelta = 1},
ctx_.journal,
tecUNFUNDED); tecUNFUNDED);
!isTesSuccess(ret)) !isTesSuccess(ret))
{ {
@@ -323,8 +322,9 @@ SponsorshipSet::createSponsorship(
(*newSle)[sfSponseeNode] = *sponseePage; (*newSle)[sfSponseeNode] = *sponseePage;
// NOLINTNEXTLINE(readability-suspicious-call-argument) // NOLINTNEXTLINE(readability-suspicious-call-argument)
increaseOwnerCount(view(), sponsorAccSle, reserveSponsorAccSle, 1, ctx_.journal); sponsorAccSle.increaseOwnerCount(reserveSponsorAccSle, 1);
addSponsorToLedgerEntry(newSle, reserveSponsorAccSle); if (reserveSponsorAccSle.has_value())
addSponsorToLedgerEntry(newSle, reserveSponsorAccSle->rawSle());
ctx_.view().insert(newSle); ctx_.view().insert(newSle);
return tesSUCCESS; return tesSUCCESS;
@@ -339,7 +339,7 @@ SponsorshipSet::doApply()
if (sponseeID == sponsorID) if (sponseeID == sponsorID)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
auto const sponsorAccSle = ctx_.view().peek(keylet::account(sponsorID)); auto sponsorAccSle = AccountRootEntryW(sponsorID, ctx_.view(), ctx_.journal);
if (!sponsorAccSle) if (!sponsorAccSle)
return tecINTERNAL; // LCOV_EXCL_LINE return tecINTERNAL; // LCOV_EXCL_LINE
@@ -388,13 +388,11 @@ SponsorshipSet::doApply()
// object. // object.
(*sponsorAccSle)[sfBalance] -= actualDelta; (*sponsorAccSle)[sfBalance] -= actualDelta;
if (auto const ret = checkReserve( if (auto const ret = sponsorAccSle.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
sponsorAccSle,
(*sponsorAccSle)[sfBalance]->xrp(), (*sponsorAccSle)[sfBalance]->xrp(),
*reserveSponsorAccSle, *reserveSponsorAccSle,
{}, {},
ctx_.journal,
tecUNFUNDED); tecUNFUNDED);
!isTesSuccess(ret)) !isTesSuccess(ret))
{ {
@@ -413,7 +411,7 @@ SponsorshipSet::doApply()
{ {
(*sponsorshipSle)[sfFeeAmount] = newFee; (*sponsorshipSle)[sfFeeAmount] = newFee;
} }
ctx_.view().update(sponsorAccSle); sponsorAccSle.update();
} }
if (maxFee) if (maxFee)
@@ -7,7 +7,7 @@
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
@@ -20,17 +20,13 @@
#include <bit> #include <bit>
#include <cstdint> #include <cstdint>
#include <limits> #include <limits>
#include <memory> #include <optional>
namespace xrpl { namespace xrpl {
// Increment an uint32 sponsor count field and update the SLE. // Increment an uint32 sponsor count field and update the SLE.
static TER static TER
incrementSponsorCount( incrementSponsorCount(AccountRootEntryW& sle, SF_UINT32 const& field, std::uint32_t const delta)
ApplyView& view,
SLE::Ref sle,
SF_UINT32 const& field,
std::uint32_t const delta)
{ {
auto const currentValue = sle->getFieldU32(field); auto const currentValue = sle->getFieldU32(field);
if (std::numeric_limits<std::uint32_t>::max() - currentValue < delta) if (std::numeric_limits<std::uint32_t>::max() - currentValue < delta)
@@ -42,17 +38,13 @@ incrementSponsorCount(
} }
sle->at(field) = currentValue + delta; sle->at(field) = currentValue + delta;
view.update(sle); sle.update();
return tesSUCCESS; return tesSUCCESS;
} }
// Decrement an uint32 sponsor count field and update the SLE. // Decrement an uint32 sponsor count field and update the SLE.
static TER static TER
decrementSponsorCount( decrementSponsorCount(AccountRootEntryW& sle, SF_UINT32 const& field, std::uint32_t const delta)
ApplyView& view,
SLE::Ref sle,
SF_UINT32 const& field,
std::uint32_t const delta)
{ {
auto const currentValue = sle->getFieldU32(field); auto const currentValue = sle->getFieldU32(field);
if (currentValue < delta) if (currentValue < delta)
@@ -64,7 +56,7 @@ decrementSponsorCount(
} }
sle->at(field) = currentValue - delta; sle->at(field) = currentValue - delta;
view.update(sle); sle.update();
return tesSUCCESS; return tesSUCCESS;
} }
@@ -232,7 +224,7 @@ SponsorshipTransfer::preclaim(PreclaimContext const& ctx)
auto const account = ctx.tx[sfAccount]; auto const account = ctx.tx[sfAccount];
auto const sponseeID = ctx.tx[~sfSponsee].value_or(account); auto const sponseeID = ctx.tx[~sfSponsee].value_or(account);
auto const sponseeSle = ctx.view.read(keylet::account(sponseeID)); auto const sponseeSle = AccountRootEntryR(sponseeID, ctx.view);
if (!sponseeSle) if (!sponseeSle)
{ {
// If it is ending sponsorship, sfSponsee is user input, return terNO_ACCOUNT if it does not // If it is ending sponsorship, sfSponsee is user input, return terNO_ACCOUNT if it does not
@@ -248,7 +240,7 @@ SponsorshipTransfer::preclaim(PreclaimContext const& ctx)
// Default setup with an account sponsorship transfer. If it is an object transfer, they will be // Default setup with an account sponsorship transfer. If it is an object transfer, they will be
// overridden to the object SLE and its type-specific sponsor field: // overridden to the object SLE and its type-specific sponsor field:
// sfHighSponsor/sfLowSponsor for a RippleState, sfSponsor for other object types. // sfHighSponsor/sfLowSponsor for a RippleState, sfSponsor for other object types.
SLE::const_pointer targetSle = sponseeSle; SLE::const_pointer targetSle = sponseeSle.rawSle();
auto const* sponsorField = &sfSponsor; auto const* sponsorField = &sfSponsor;
if (objectID.has_value()) if (objectID.has_value())
@@ -313,7 +305,7 @@ SponsorshipTransfer::doApply()
auto const objectID = ctx_.tx[~sfObjectID]; auto const objectID = ctx_.tx[~sfObjectID];
auto const sponseeID = ctx_.tx[~sfSponsee].value_or(accountID_); auto const sponseeID = ctx_.tx[~sfSponsee].value_or(accountID_);
auto const sponseeSle = view().peek(keylet::account(sponseeID)); auto sponseeSle = AccountRootEntryW(sponseeID, view(), ctx_.journal);
if (!sponseeSle) if (!sponseeSle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -337,7 +329,7 @@ SponsorshipTransfer::doApply()
if (!isLedgerEntryOwner(view(), *objectSle, sponseeID)) if (!isLedgerEntryOwner(view(), *objectSle, sponseeID))
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
auto const ownerSle = view().peek(keylet::account(sponseeID)); auto ownerSle = AccountRootEntryW(sponseeID, view());
if (!ownerSle) if (!ownerSle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -355,27 +347,25 @@ SponsorshipTransfer::doApply()
if (!newSponsor) if (!newSponsor)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
auto const newSponsorID = *newSponsor; auto const newSponsorID = *newSponsor;
auto const newSponsorSle = view().peek(keylet::account(newSponsorID)); auto newSponsorSle = AccountRootEntryW(newSponsorID, view());
if (!newSponsorSle) if (!newSponsorSle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
// Check if new sponsor has sufficient balance // Check if new sponsor has sufficient balance
// NOLINTNEXTLINE(readability-suspicious-call-argument) // NOLINTNEXTLINE(readability-suspicious-call-argument)
if (auto const ter = checkReserve( if (auto const ter = sponseeSle.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
sponseeSle,
sponseeSle->getFieldAmount(sfBalance).xrp(), sponseeSle->getFieldAmount(sfBalance).xrp(),
newSponsorSle, std::optional<AccountRootEntryR>{newSponsorSle},
{.ownerCountDelta = ownerCountDelta}, {.ownerCountDelta = ownerCountDelta});
ctx_.journal);
!isTesSuccess(ter)) !isTesSuccess(ter))
return ter; return ter;
if (isCreate) if (isCreate)
{ {
// Update owner's sponsored count // Update owner's sponsored count
if (auto const ter = incrementSponsorCount( if (auto const ter =
view(), ownerSle, sfSponsoredOwnerCount, ownerCountDelta); incrementSponsorCount(ownerSle, sfSponsoredOwnerCount, ownerCountDelta);
!isTesSuccess(ter)) !isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE return ter; // LCOV_EXCL_LINE
} }
@@ -384,20 +374,20 @@ SponsorshipTransfer::doApply()
auto const oldSponsorID = objectSle->getAccountID(sponsorField); auto const oldSponsorID = objectSle->getAccountID(sponsorField);
if (!oldSponsorID) if (!oldSponsorID)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
auto const oldSponsorSle = view().peek(keylet::account(oldSponsorID)); auto oldSponsorSle = AccountRootEntryW(oldSponsorID, view());
if (!oldSponsorSle) if (!oldSponsorSle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
// Decrement old sponsor's sponsoring count // Decrement old sponsor's sponsoring count
if (auto const ter = decrementSponsorCount( if (auto const ter = decrementSponsorCount(
view(), oldSponsorSle, sfSponsoringOwnerCount, ownerCountDelta); oldSponsorSle, sfSponsoringOwnerCount, ownerCountDelta);
!isTesSuccess(ter)) !isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE return ter; // LCOV_EXCL_LINE
} }
// Increment new sponsor's sponsoring count // Increment new sponsor's sponsoring count
if (auto const ter = incrementSponsorCount( if (auto const ter =
view(), newSponsorSle, sfSponsoringOwnerCount, ownerCountDelta); incrementSponsorCount(newSponsorSle, sfSponsoringOwnerCount, ownerCountDelta);
!isTesSuccess(ter)) !isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE return ter; // LCOV_EXCL_LINE
@@ -421,7 +411,7 @@ SponsorshipTransfer::doApply()
auto const oldSponsorID = objectSle->getAccountID(sponsorField); auto const oldSponsorID = objectSle->getAccountID(sponsorField);
if (!oldSponsorID) if (!oldSponsorID)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
auto const oldSponsorSle = view().peek(keylet::account(oldSponsorID)); auto oldSponsorSle = AccountRootEntryW(oldSponsorID, view());
if (!oldSponsorSle) if (!oldSponsorSle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -433,26 +423,24 @@ SponsorshipTransfer::doApply()
// steps in (Reassign), or the object/account is deleted. // steps in (Reassign), or the object/account is deleted.
if (view().rules().enabled(fixCleanup3_4_0)) if (view().rules().enabled(fixCleanup3_4_0))
{ {
if (auto const ter = checkReserve( if (auto const ter = sponseeSle.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
sponseeSle, balanceBeforeFee(sponseeSle.rawSle()),
balanceBeforeFee(sponseeSle), std::nullopt,
SLE::pointer(), {.ownerCountDelta = ownerCountDelta});
{.ownerCountDelta = ownerCountDelta},
ctx_.journal);
!isTesSuccess(ter)) !isTesSuccess(ter))
return ter; return ter;
} }
// Decrement sponsored count // Decrement sponsored count
if (auto const ter = decrementSponsorCount( if (auto const ter =
view(), sponseeSle, sfSponsoredOwnerCount, ownerCountDelta); decrementSponsorCount(sponseeSle, sfSponsoredOwnerCount, ownerCountDelta);
!isTesSuccess(ter)) !isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE return ter; // LCOV_EXCL_LINE
// Decrement old sponsoring count // Decrement old sponsoring count
if (auto const ter = decrementSponsorCount( if (auto const ter =
view(), oldSponsorSle, sfSponsoringOwnerCount, ownerCountDelta); decrementSponsorCount(oldSponsorSle, sfSponsoringOwnerCount, ownerCountDelta);
!isTesSuccess(ter)) !isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE return ter; // LCOV_EXCL_LINE
@@ -475,17 +463,15 @@ SponsorshipTransfer::doApply()
if (!newSponsor) if (!newSponsor)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
auto const newSponsorID = *newSponsor; auto const newSponsorID = *newSponsor;
auto const newSponsorSle = view().peek(keylet::account(newSponsorID)); auto newSponsorSle = AccountRootEntryW(newSponsorID, view());
if (!newSponsorSle) if (!newSponsorSle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
if (auto const ter = checkReserve( if (auto const ter = sponseeSle.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
sponseeSle,
sponseeSle->getFieldAmount(sfBalance).xrp(), sponseeSle->getFieldAmount(sfBalance).xrp(),
newSponsorSle, std::optional<AccountRootEntryR>{newSponsorSle},
{.accountCountDelta = 1}, {.accountCountDelta = 1});
ctx_.journal);
!isTesSuccess(ter)) !isTesSuccess(ter))
return ter; return ter;
@@ -494,26 +480,25 @@ SponsorshipTransfer::doApply()
auto const oldSponsorID = sponseeSle->getAccountID(sfSponsor); auto const oldSponsorID = sponseeSle->getAccountID(sfSponsor);
if (!oldSponsorID) if (!oldSponsorID)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
auto const oldSponsorSle = view().peek(keylet::account(oldSponsorID)); auto oldSponsorSle = AccountRootEntryW(oldSponsorID, view());
if (!oldSponsorSle) if (!oldSponsorSle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
// Decrement old sponsoring count // Decrement old sponsoring count
if (auto const ter = if (auto const ter =
decrementSponsorCount(view(), oldSponsorSle, sfSponsoringAccountCount, 1); decrementSponsorCount(oldSponsorSle, sfSponsoringAccountCount, 1);
!isTesSuccess(ter)) !isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE return ter; // LCOV_EXCL_LINE
} }
// Increment new sponsoring count // Increment new sponsoring count
if (auto const ter = if (auto const ter = incrementSponsorCount(newSponsorSle, sfSponsoringAccountCount, 1);
incrementSponsorCount(view(), newSponsorSle, sfSponsoringAccountCount, 1);
!isTesSuccess(ter)) !isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE return ter; // LCOV_EXCL_LINE
// Account is now sponsored by new sponsor // Account is now sponsored by new sponsor
sponseeSle->setAccountID(sfSponsor, newSponsorID); sponseeSle->setAccountID(sfSponsor, newSponsorID);
view().update(sponseeSle); sponseeSle.update();
} }
else if (ctx_.tx.isFlag(tfSponsorshipEnd)) else if (ctx_.tx.isFlag(tfSponsorshipEnd))
{ {
@@ -521,28 +506,25 @@ SponsorshipTransfer::doApply()
auto const oldSponsorID = sponseeSle->getAccountID(sfSponsor); auto const oldSponsorID = sponseeSle->getAccountID(sfSponsor);
if (!oldSponsorID) if (!oldSponsorID)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
auto const oldSponsorSle = view().peek(keylet::account(oldSponsorID)); auto oldSponsorSle = AccountRootEntryW(oldSponsorID, view());
if (!oldSponsorSle) if (!oldSponsorSle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
// The sponsee must be able to hold its own account reserve after // The sponsee must be able to hold its own account reserve after
// the sponsorship is removed. // the sponsorship is removed.
if (auto const ter = checkReserve( if (auto const ter = sponseeSle.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
sponseeSle, balanceBeforeFee(sponseeSle.rawSle()),
balanceBeforeFee(sponseeSle), std::optional<AccountRootEntryR>{},
SLE::pointer(), {.accountCountDelta = 1});
{.accountCountDelta = 1},
ctx_.journal);
!isTesSuccess(ter)) !isTesSuccess(ter))
return ter; return ter;
sponseeSle->makeFieldAbsent(sfSponsor); sponseeSle->makeFieldAbsent(sfSponsor);
view().update(sponseeSle); sponseeSle.update();
// Decrement account sponsoring count // Decrement account sponsoring count
if (auto const ter = if (auto const ter = decrementSponsorCount(oldSponsorSle, sfSponsoringAccountCount, 1);
decrementSponsorCount(view(), oldSponsorSle, sfSponsoringAccountCount, 1);
!isTesSuccess(ter)) !isTesSuccess(ter))
return ter; // LCOV_EXCL_LINE return ter; // LCOV_EXCL_LINE
} }
@@ -2,6 +2,7 @@
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h> #include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -96,7 +97,7 @@ LedgerStateFix::preclaim(PreclaimContext const& ctx)
if (static_cast<FixType>(ctx.tx[sfLedgerFixType]) == FixType::NfTokenPageLink) if (static_cast<FixType>(ctx.tx[sfLedgerFixType]) == FixType::NfTokenPageLink)
{ {
AccountID const owner{ctx.tx[sfOwner]}; AccountID const owner{ctx.tx[sfOwner]};
if (!ctx.view.read(keylet::account(owner))) if (!AccountRootEntryR(owner, ctx.view))
return tecOBJECT_NOT_FOUND; return tecOBJECT_NOT_FOUND;
return tesSUCCESS; return tesSUCCESS;
@@ -4,7 +4,8 @@
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Keylet.h> #include <xrpl/protocol/Keylet.h>
@@ -18,6 +19,7 @@
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <optional>
namespace xrpl { namespace xrpl {
@@ -42,7 +44,7 @@ TER
TicketCreate::preclaim(PreclaimContext const& ctx) TicketCreate::preclaim(PreclaimContext const& ctx)
{ {
auto const id = ctx.tx[sfAccount]; auto const id = ctx.tx[sfAccount];
auto const sleAccountRoot = ctx.view.read(keylet::account(id)); auto const sleAccountRoot = AccountRootEntryR(id, ctx.view);
if (!sleAccountRoot) if (!sleAccountRoot)
return terNO_ACCOUNT; return terNO_ACCOUNT;
@@ -67,7 +69,7 @@ TicketCreate::preclaim(PreclaimContext const& ctx)
TER TER
TicketCreate::doApply() TicketCreate::doApply()
{ {
SLE::pointer const sleAccountRoot = view().peek(keylet::account(accountID_)); auto sleAccountRoot = AccountRootEntryW(accountID_, view(), j_);
if (!sleAccountRoot) if (!sleAccountRoot)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -75,15 +77,10 @@ TicketCreate::doApply()
// check the starting balance because we want to allow dipping into the // check the starting balance because we want to allow dipping into the
// reserve to pay fees. // reserve to pay fees.
std::uint32_t const ticketCount = ctx_.tx[sfTicketCount]; std::uint32_t const ticketCount = ctx_.tx[sfTicketCount];
if (preFeeBalance_ < accountReserve( if (preFeeBalance_ <
view(), sleAccountRoot.reserve({.ownerCountDelta = static_cast<std::int32_t>(ticketCount)}))
sleAccountRoot,
j_,
{.ownerCountDelta = static_cast<std::int32_t>(ticketCount)}))
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
beast::Journal const viewJ{ctx_.registry.get().getJournal("View")};
// The starting ticket sequence is the same as the current account // The starting ticket sequence is the same as the current account
// root sequence. Before we got here to doApply(), the transaction // root sequence. Before we got here to doApply(), the transaction
// machinery already incremented the account root sequence if that // machinery already incremented the account root sequence if that
@@ -125,7 +122,8 @@ TicketCreate::doApply()
sleAccountRoot->setFieldU32(sfTicketCount, oldTicketCount + ticketCount); sleAccountRoot->setFieldU32(sfTicketCount, oldTicketCount + ticketCount);
// Every added Ticket counts against the creator's reserve. // Every added Ticket counts against the creator's reserve.
increaseOwnerCount(view(), sleAccountRoot, {}, ticketCount, viewJ); std::optional<AccountRootEntryW> noSponsor;
sleAccountRoot.increaseOwnerCount(noSponsor, ticketCount);
// TicketCreate is the only transaction that can cause an account root's // TicketCreate is the only transaction that can cause an account root's
// Sequence field to increase by more than one. October 2018. // Sequence field to increase by more than one. October 2018.
@@ -2,6 +2,7 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
@@ -186,8 +187,8 @@ Clawback::preclaim(PreclaimContext const& ctx)
auto const clawAmount = ctx.tx[sfAmount]; auto const clawAmount = ctx.tx[sfAmount];
AccountID const holder = clawAmount.holds<Issue>() ? clawAmount.getIssuer() : ctx.tx[sfHolder]; AccountID const holder = clawAmount.holds<Issue>() ? clawAmount.getIssuer() : ctx.tx[sfHolder];
auto const sleIssuer = ctx.view.read(keylet::account(issuer)); auto const sleIssuer = AccountRootEntryR(issuer, ctx.view);
auto const sleHolder = ctx.view.read(keylet::account(holder)); auto const sleHolder = AccountRootEntryR(holder, ctx.view);
if (!sleIssuer || !sleHolder) if (!sleIssuer || !sleHolder)
return terNO_ACCOUNT; return terNO_ACCOUNT;
@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/ConfidentialTransfer.h> #include <xrpl/protocol/ConfidentialTransfer.h>
@@ -167,7 +168,7 @@ ConfidentialMPTSend::preclaim(PreclaimContext const& ctx)
// Check if destination account exists // Check if destination account exists
auto const destination = ctx.tx[sfDestination]; auto const destination = ctx.tx[sfDestination];
auto const sleDst = ctx.view.read(keylet::account(destination)); auto const sleDst = AccountRootEntryR(destination, ctx.view);
if (!sleDst) if (!sleDst)
return tecNO_TARGET; return tecNO_TARGET;
@@ -292,7 +293,7 @@ ConfidentialMPTSend::preclaim(PreclaimContext const& ctx)
// Check deposit preauth before the expensive ZK proof verification. // Check deposit preauth before the expensive ZK proof verification.
// Uses read-only view. // Uses read-only view.
auto const preauthErr = auto const preauthErr =
checkDepositPreauth(ctx.tx, ctx.view, account, destination, sleDst, ctx.j); checkDepositPreauth(ctx.tx, ctx.view, account, destination, sleDst.rawSle(), ctx.j);
if (!isTesSuccess(preauthErr)) if (!isTesSuccess(preauthErr))
return preauthErr; return preauthErr;
@@ -309,7 +310,7 @@ ConfidentialMPTSend::doApply()
auto sleDestinationMPToken = view().peek(keylet::mptoken(mptIssuanceID, destination)); auto sleDestinationMPToken = view().peek(keylet::mptoken(mptIssuanceID, destination));
auto const sleIssuance = view().read(keylet::mptokenIssuance(mptIssuanceID)); auto const sleIssuance = view().read(keylet::mptokenIssuance(mptIssuanceID));
auto const sleDestAcct = view().read(keylet::account(destination)); auto const sleDestAcct = AccountRootEntryW(destination, view());
if (!sleSenderMPToken || !sleDestinationMPToken || !sleIssuance || !sleDestAcct) if (!sleSenderMPToken || !sleDestinationMPToken || !sleIssuance || !sleDestAcct)
{ {
@@ -1,6 +1,7 @@
#include <xrpl/tx/transactors/token/MPTokenAuthorize.h> #include <xrpl/tx/transactors/token/MPTokenAuthorize.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -120,7 +121,7 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx)
return tesSUCCESS; return tesSUCCESS;
} }
auto const sleHolder = ctx.view.read(keylet::account(*holderID)); auto const sleHolder = AccountRootEntryR(*holderID, ctx.view);
if (!sleHolder) if (!sleHolder)
return tecNO_DST; return tecNO_DST;
@@ -5,7 +5,7 @@
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -125,20 +125,20 @@ MPTokenIssuanceCreate::create(
beast::Journal journal, beast::Journal journal,
MPTCreateArgs const& args) MPTCreateArgs const& args)
{ {
auto const acct = ctx.view.peek(keylet::account(args.account)); auto acct = AccountRootEntryW(args.account, ctx.view, journal);
if (!acct) if (!acct)
return std::unexpected(tecINTERNAL); // LCOV_EXCL_LINE return std::unexpected(tecINTERNAL); // LCOV_EXCL_LINE
// A reserve sponsor only covers tx.Account's own objects. // A reserve sponsor only covers tx.Account's own objects.
auto const sponsorExp = getEffectiveTxReserveSponsor(ctx, acct); auto sponsorExp = getEffectiveTxReserveSponsor(ctx, acct);
if (!sponsorExp) if (!sponsorExp)
return std::unexpected(sponsorExp.error()); // LCOV_EXCL_LINE return std::unexpected(sponsorExp.error()); // LCOV_EXCL_LINE
auto const sponsorSle = *sponsorExp; auto& sponsorSle = *sponsorExp;
if (args.priorBalance) if (args.priorBalance)
{ {
if (auto const ret = checkReserve( if (auto const ret =
ctx, acct, *(args.priorBalance), sponsorSle, {.ownerCountDelta = 1}, journal); acct.checkReserve(ctx, *(args.priorBalance), sponsorSle, {.ownerCountDelta = 1});
!isTesSuccess(ret)) !isTesSuccess(ret))
return std::unexpected(ret); return std::unexpected(ret);
} }
@@ -195,13 +195,14 @@ MPTokenIssuanceCreate::create(
(*mptIssuance)[sfReferenceHolding] = *args.referenceHolding; (*mptIssuance)[sfReferenceHolding] = *args.referenceHolding;
} }
addSponsorToLedgerEntry(mptIssuance, sponsorSle); if (sponsorSle)
addSponsorToLedgerEntry(mptIssuance, sponsorSle->rawSle());
ctx.view.insert(mptIssuance); ctx.view.insert(mptIssuance);
} }
// Update owner count. // Update owner count.
increaseOwnerCount(ctx.view, acct, sponsorSle, 1, journal); acct.increaseOwnerCount(sponsorSle, 1);
return mptId; return mptId;
} }
+36 -40
View File
@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h> #include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -26,6 +27,7 @@
#include <xrpl/tx/Transactor.h> #include <xrpl/tx/Transactor.h>
#include <cstdint> #include <cstdint>
#include <optional>
#include <unordered_set> #include <unordered_set>
namespace { namespace {
@@ -157,7 +159,7 @@ TrustSet::preclaim(PreclaimContext const& ctx)
{ {
auto const id = ctx.tx[sfAccount]; auto const id = ctx.tx[sfAccount];
auto const sle = ctx.view.read(keylet::account(id)); auto const sle = AccountRootEntryR(id, ctx.view);
if (!sle) if (!sle)
return terNO_ACCOUNT; return terNO_ACCOUNT;
@@ -178,9 +180,9 @@ TrustSet::preclaim(PreclaimContext const& ctx)
return temDST_IS_SRC; return temDST_IS_SRC;
// This might be nullptr // This might be nullptr
auto const sleDst = ctx.view.read(keylet::account(uDstAccountID)); auto const sleDst = AccountRootEntryR(uDstAccountID, ctx.view);
if ((ammEnabled(ctx.view.rules()) || ctx.view.rules().enabled(featureSingleAssetVault)) && if ((ammEnabled(ctx.view.rules()) || ctx.view.rules().enabled(featureSingleAssetVault)) &&
sleDst == nullptr) !sleDst)
return tecNO_DST; return tecNO_DST;
// If the destination has opted to disallow incoming trustlines // If the destination has opted to disallow incoming trustlines
@@ -294,7 +296,7 @@ TrustSet::doApply()
// true, if current is high account. // true, if current is high account.
bool const bHigh = accountID_ > uDstAccountID; bool const bHigh = accountID_ > uDstAccountID;
auto const sle = view().peek(keylet::account(accountID_)); auto sle = AccountRootEntryW(accountID_, view(), j_);
if (!sle) if (!sle)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
@@ -316,23 +318,24 @@ TrustSet::doApply()
// well. A person with no intention of using the gateway // well. A person with no intention of using the gateway
// could use the extra XRP for their own purposes. // could use the extra XRP for their own purposes.
auto const sponsorExp = getTxReserveSponsor(ctx_.getApplyViewContext()); auto sponsorExp = getTxReserveSponsor(ctx_.getApplyViewContext());
if (!sponsorExp) if (!sponsorExp)
return sponsorExp.error(); // LCOV_EXCL_LINE return sponsorExp.error(); // LCOV_EXCL_LINE
auto const sponsorSle = *sponsorExp; auto& sponsorSle = *sponsorExp;
auto getSponsor = [&sponsorSle, this](AccountID const& account) { std::optional<AccountRootEntryW> noSponsor;
return (sponsorSle && account == accountID_) ? sponsorSle : SLE::pointer(); auto getSponsor = [&sponsorSle, &noSponsor, this](
AccountID const& account) -> std::optional<AccountRootEntryW>& {
return (sponsorSle && account == accountID_) ? sponsorSle : noSponsor;
}; };
// The "free-tier" shortcut (ownerCount < 2) only applies when there is no sponsor. // The "free-tier" shortcut (ownerCount < 2) only applies when there is no sponsor.
// With any sponsor on the tx, the sponsor must cover the reserve (via balance or // With any sponsor on the tx, the sponsor must cover the reserve (via balance or
// prefunded budget), so the reserve check always runs. // prefunded budget), so the reserve check always runs.
bool const freeTrustLine = !sponsorSle && (ownerCount(sle, j_) < 2); bool const freeTrustLine = !sponsorSle && (sle.ownerCount() < 2);
std::uint32_t const uOwnerCount = ownerCount(sle, j_); std::uint32_t const uOwnerCount = sle.ownerCount();
XRPAmount const reserveCreate( XRPAmount const reserveCreate(
(uOwnerCount < 2) ? XRPAmount(beast::kZero) (uOwnerCount < 2) ? XRPAmount(beast::kZero) : sle.reserve({.ownerCountDelta = 1}));
: accountReserve(view(), sle, j_, {.ownerCountDelta = 1}));
std::uint32_t const uQualityIn(bQualityIn ? ctx_.tx.getFieldU32(sfQualityIn) : 0); std::uint32_t const uQualityIn(bQualityIn ? ctx_.tx.getFieldU32(sfQualityIn) : 0);
std::uint32_t uQualityOut(bQualityOut ? ctx_.tx.getFieldU32(sfQualityOut) : 0); std::uint32_t uQualityOut(bQualityOut ? ctx_.tx.getFieldU32(sfQualityOut) : 0);
@@ -350,7 +353,7 @@ TrustSet::doApply()
auto viewJ = ctx_.registry.get().getJournal("View"); auto viewJ = ctx_.registry.get().getJournal("View");
SLE::pointer const sleDst = view().peek(keylet::account(uDstAccountID)); auto sleDst = AccountRootEntryW(uDstAccountID, view(), j_);
if (!sleDst) if (!sleDst)
{ {
@@ -376,8 +379,8 @@ TrustSet::doApply()
std::uint32_t uHighQualityOut = 0; std::uint32_t uHighQualityOut = 0;
auto const& uLowAccountID = !bHigh ? accountID_ : uDstAccountID; auto const& uLowAccountID = !bHigh ? accountID_ : uDstAccountID;
auto const& uHighAccountID = bHigh ? accountID_ : uDstAccountID; auto const& uHighAccountID = bHigh ? accountID_ : uDstAccountID;
SLE::Ref sleLowAccount = !bHigh ? sle : sleDst; AccountRootEntryW& sleLowAccount = !bHigh ? sle : sleDst;
SLE::Ref sleHighAccount = bHigh ? sle : sleDst; AccountRootEntryW& sleHighAccount = bHigh ? sle : sleDst;
// //
// Balances // Balances
@@ -518,10 +521,9 @@ TrustSet::doApply()
bool bReserveIncrease = false; bool bReserveIncrease = false;
auto const currentHighSponsor = auto currentHighSponsor =
getLedgerEntryReserveSponsor(view(), sleRippleState, sfHighSponsor); getLedgerEntryReserveSponsor(view(), sleRippleState, sfHighSponsor);
auto const currentLowSponsor = auto currentLowSponsor = getLedgerEntryReserveSponsor(view(), sleRippleState, sfLowSponsor);
getLedgerEntryReserveSponsor(view(), sleRippleState, sfLowSponsor);
if (bSetAuth) if (bSetAuth)
{ {
@@ -530,17 +532,15 @@ TrustSet::doApply()
if (bLowReserveSet && !bLowReserved) if (bLowReserveSet && !bLowReserved)
{ {
SLE::pointer const lowSponsor = getSponsor(uLowAccountID); auto& lowSponsor = getSponsor(uLowAccountID);
if (view().rules().enabled(featureSponsor)) if (view().rules().enabled(featureSponsor))
{ {
if (auto const ret = checkReserve( if (auto const ret = sleLowAccount.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
sleLowAccount,
preFeeBalance_, preFeeBalance_,
lowSponsor, lowSponsor,
{.ownerCountDelta = 1}, {.ownerCountDelta = 1},
j_,
tecINSUF_RESERVE_LINE); tecINSUF_RESERVE_LINE);
lowSponsor && !isTesSuccess(ret)) lowSponsor && !isTesSuccess(ret))
{ {
@@ -549,10 +549,11 @@ TrustSet::doApply()
} }
// Set reserve for low account. // Set reserve for low account.
increaseOwnerCount(view(), sleLowAccount, lowSponsor, 1, viewJ); sleLowAccount.increaseOwnerCount(lowSponsor, 1);
uFlagsOut |= lsfLowReserve; uFlagsOut |= lsfLowReserve;
addSponsorToLedgerEntry(sleRippleState, lowSponsor, sfLowSponsor); if (lowSponsor)
addSponsorToLedgerEntry(sleRippleState, lowSponsor->rawSle(), sfLowSponsor);
if (!bHigh) if (!bHigh)
bReserveIncrease = true; bReserveIncrease = true;
@@ -561,7 +562,7 @@ TrustSet::doApply()
if (bLowReserveClear && bLowReserved) if (bLowReserveClear && bLowReserved)
{ {
// Clear reserve for low account. // Clear reserve for low account.
decreaseOwnerCount(view(), sleLowAccount, currentLowSponsor, 1, viewJ); sleLowAccount.decreaseOwnerCount(currentLowSponsor, 1);
uFlagsOut &= ~lsfLowReserve; uFlagsOut &= ~lsfLowReserve;
removeSponsorFromLedgerEntry(sleRippleState, sfLowSponsor); removeSponsorFromLedgerEntry(sleRippleState, sfLowSponsor);
@@ -569,20 +570,18 @@ TrustSet::doApply()
if (bHighReserveSet && !bHighReserved) if (bHighReserveSet && !bHighReserved)
{ {
SLE::pointer const highSponsor = getSponsor(uHighAccountID); auto& highSponsor = getSponsor(uHighAccountID);
// should be checked PreFunded Sponsor before increaseOwnerCount() // should be checked PreFunded Sponsor before increaseOwnerCount()
// For PreFunded sponsors, we need to check if there are sufficient reserves before // For PreFunded sponsors, we need to check if there are sufficient reserves before
// calling increaseOwnerCount(). // calling increaseOwnerCount().
if (view().rules().enabled(featureSponsor)) if (view().rules().enabled(featureSponsor))
{ {
if (auto const ret = checkReserve( if (auto const ret = sleHighAccount.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
sleHighAccount,
preFeeBalance_, preFeeBalance_,
highSponsor, highSponsor,
{.ownerCountDelta = 1}, {.ownerCountDelta = 1},
j_,
tecINSUF_RESERVE_LINE); tecINSUF_RESERVE_LINE);
highSponsor && !isTesSuccess(ret)) highSponsor && !isTesSuccess(ret))
{ {
@@ -591,10 +590,11 @@ TrustSet::doApply()
} }
// Set reserve for high account. // Set reserve for high account.
increaseOwnerCount(view(), sleHighAccount, highSponsor, 1, viewJ); sleHighAccount.increaseOwnerCount(highSponsor, 1);
uFlagsOut |= lsfHighReserve; uFlagsOut |= lsfHighReserve;
addSponsorToLedgerEntry(sleRippleState, highSponsor, sfHighSponsor); if (highSponsor)
addSponsorToLedgerEntry(sleRippleState, highSponsor->rawSle(), sfHighSponsor);
if (bHigh) if (bHigh)
bReserveIncrease = true; bReserveIncrease = true;
@@ -603,7 +603,7 @@ TrustSet::doApply()
if (bHighReserveClear && bHighReserved) if (bHighReserveClear && bHighReserved)
{ {
// Clear reserve for high account. // Clear reserve for high account.
decreaseOwnerCount(view(), sleHighAccount, currentHighSponsor, 1, viewJ); sleHighAccount.decreaseOwnerCount(currentHighSponsor, 1);
uFlagsOut &= ~lsfHighReserve; uFlagsOut &= ~lsfHighReserve;
removeSponsorFromLedgerEntry(sleRippleState, sfHighSponsor); removeSponsorFromLedgerEntry(sleRippleState, sfHighSponsor);
@@ -623,13 +623,11 @@ TrustSet::doApply()
} }
// Reserve is not scaled by load // Reserve is not scaled by load
else if ( else if (
auto const ret = checkReserve( auto const ret = sle.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
sle,
preFeeBalance_, preFeeBalance_,
sponsorSle, sponsorSle,
{}, {},
j_,
tecINSUF_RESERVE_LINE); tecINSUF_RESERVE_LINE);
!freeTrustLine && bReserveIncrease && !isTesSuccess(ret)) !freeTrustLine && bReserveIncrease && !isTesSuccess(ret))
{ {
@@ -697,13 +695,11 @@ TrustSet::doApply()
terResult = tecNO_LINE_INSUF_RESERVE; terResult = tecNO_LINE_INSUF_RESERVE;
} }
else if ( else if (
auto const ret = checkReserve( auto const ret = sle.checkReserve(
ctx_.getApplyViewContext(), ctx_.getApplyViewContext(),
sle,
preFeeBalance_, preFeeBalance_,
sponsorSle, sponsorSle,
{.ownerCountDelta = 1}, {.ownerCountDelta = 1},
j_,
tecNO_LINE_INSUF_RESERVE); tecNO_LINE_INSUF_RESERVE);
view().rules().enabled(featureSponsor) && !freeTrustLine && view().rules().enabled(featureSponsor) && !freeTrustLine &&
!isTesSuccess(ret)) // Reserve is not scaled by load. !isTesSuccess(ret)) // Reserve is not scaled by load.
@@ -731,7 +727,7 @@ TrustSet::doApply()
accountID_, accountID_,
uDstAccountID, uDstAccountID,
k.key, k.key,
sle, sle.mutableRawSle(),
bSetAuth, bSetAuth,
bSetNoRipple && !bClearNoRipple, bSetNoRipple && !bClearNoRipple,
bSetFreeze && !bClearFreeze, bSetFreeze && !bClearFreeze,
@@ -740,7 +736,7 @@ TrustSet::doApply()
saLimitAllow, // Limit for who is being charged. saLimitAllow, // Limit for who is being charged.
uQualityIn, uQualityIn,
uQualityOut, uQualityOut,
sponsorSle, sponsorSle ? sponsorSle->mutableRawSle() : SLE::pointer{},
viewJ); viewJ);
} }
@@ -6,6 +6,7 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/ledger/helpers/VaultHelpers.h> #include <xrpl/ledger/helpers/VaultHelpers.h>
@@ -206,7 +207,7 @@ VaultClawback::preclaim(PreclaimContext const& ctx)
return tesSUCCESS; return tesSUCCESS;
}, },
[&](Issue const&) -> TER { [&](Issue const&) -> TER {
auto const issuerSle = ctx.view.read(keylet::account(account)); auto const issuerSle = AccountRootEntryR(account, ctx.view);
if (!issuerSle) if (!issuerSle)
{ {
// LCOV_EXCL_START // LCOV_EXCL_START
@@ -5,6 +5,7 @@
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/View.h> #include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -181,8 +182,8 @@ VaultCreate::doApply()
auto const& tx = ctx_.tx; auto const& tx = ctx_.tx;
auto applyViewContext = ctx_.getApplyViewContext(); auto applyViewContext = ctx_.getApplyViewContext();
auto const sequence = tx.getSeqProxy(); auto const sequence = tx.getSeqProxy();
auto const owner = view().peek(keylet::account(accountID_)); auto owner = AccountRootEntryW(accountID_, view(), j_);
if (owner == nullptr) if (!owner)
return tefINTERNAL; // LCOV_EXCL_LINE return tefINTERNAL; // LCOV_EXCL_LINE
auto vault = std::make_shared<SLE>(keylet::vault(accountID_, sequence)); auto vault = std::make_shared<SLE>(keylet::vault(accountID_, sequence));
@@ -190,8 +191,9 @@ VaultCreate::doApply()
if (auto ter = dirLink(view(), accountID_, vault)) if (auto ter = dirLink(view(), accountID_, vault))
return ter; return ter;
// We will create Vault and PseudoAccount, hence increase OwnerCount by 2 // We will create Vault and PseudoAccount, hence increase OwnerCount by 2
increaseOwnerCount(view(), owner, {}, 2, j_); std::optional<AccountRootEntryW> noSponsor;
if (preFeeBalance_ < accountReserve(view(), owner, j_)) owner.increaseOwnerCount(noSponsor, 2);
if (preFeeBalance_ < owner.reserve())
return tecINSUFFICIENT_RESERVE; return tecINSUFFICIENT_RESERVE;
auto maybePseudo = createPseudoAccount(view(), vault->key(), sfVaultID); auto maybePseudo = createPseudoAccount(view(), vault->key(), sfVaultID);
@@ -3,6 +3,7 @@
#include <xrpl/basics/Log.h> #include <xrpl/basics/Log.h>
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Zero.h> #include <xrpl/beast/utility/Zero.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h> #include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -109,7 +110,7 @@ VaultDelete::doApply()
return ter; return ter;
auto const& pseudoID = vault->at(sfAccount); auto const& pseudoID = vault->at(sfAccount);
auto const pseudoAcct = view().peek(keylet::account(pseudoID)); auto pseudoAcct = AccountRootEntryW(pseudoID, view());
if (!pseudoAcct) if (!pseudoAcct)
{ {
// LCOV_EXCL_START // LCOV_EXCL_START
@@ -164,7 +165,7 @@ VaultDelete::doApply()
return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE return tecHAS_OBLIGATIONS; // LCOV_EXCL_LINE
// Destroy the pseudo-account. // Destroy the pseudo-account.
auto vaultPseudoSLE = view().peek(keylet::account(pseudoID)); auto vaultPseudoSLE = AccountRootEntryW(pseudoID, view());
if (!vaultPseudoSLE || vaultPseudoSLE->at(~sfVaultID) != vault->key()) if (!vaultPseudoSLE || vaultPseudoSLE->at(~sfVaultID) != vault->key())
return tefBAD_LEDGER; // LCOV_EXCL_LINE return tefBAD_LEDGER; // LCOV_EXCL_LINE
@@ -192,7 +193,7 @@ VaultDelete::doApply()
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
} }
view().erase(vaultPseudoSLE); vaultPseudoSLE.erase();
// Remove the vault from its owner's directory. // Remove the vault from its owner's directory.
auto const ownerID = vault->at(sfOwner); auto const ownerID = vault->at(sfOwner);
@@ -204,7 +205,7 @@ VaultDelete::doApply()
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
} }
auto const owner = view().peek(keylet::account(ownerID)); auto owner = AccountRootEntryW(ownerID, view());
if (!owner) if (!owner)
{ {
// LCOV_EXCL_START // LCOV_EXCL_START
+2 -1
View File
@@ -24,6 +24,7 @@
#include <xrpl/core/ServiceRegistry.h> #include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/OpenView.h> #include <xrpl/ledger/OpenView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/protocol/AmountConversions.h> #include <xrpl/protocol/AmountConversions.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -446,7 +447,7 @@ public:
// here and the end of the test all the effort will be lost. // here and the end of the test all the effort will be lost.
env.app().getOpenLedger().modify([&gw, transferRate](OpenView& view, beast::Journal j) { env.app().getOpenLedger().modify([&gw, transferRate](OpenView& view, beast::Journal j) {
// Get the account root we want to hijack. // Get the account root we want to hijack.
auto const sle = view.read(keylet::account(gw.id())); auto const sle = AccountRootEntryR(gw.id(), view);
if (!sle) if (!sle)
return false; // This would be really surprising! return false; // This would be really surprising!
+3 -2
View File
@@ -21,6 +21,7 @@
#include <xrpl/json/to_string.h> #include <xrpl/json/to_string.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ApplyViewImpl.h> #include <xrpl/ledger/ApplyViewImpl.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> #include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -1128,10 +1129,10 @@ struct Credentials_test : public beast::unit_test::Suite
ApplyViewImpl av(&*open, TapNone); ApplyViewImpl av(&*open, TapNone);
// Erase the issuer's account to simulate ledger corruption // Erase the issuer's account to simulate ledger corruption
auto sleIssuer = av.peek(keylet::account(issuer.id())); auto sleIssuer = AccountRootEntryW(issuer.id(), av);
if (!BEAST_EXPECT(sleIssuer)) if (!BEAST_EXPECT(sleIssuer))
return; return;
av.erase(sleIssuer); sleIssuer.erase();
BEAST_EXPECT(!av.exists(keylet::account(issuer.id()))); BEAST_EXPECT(!av.exists(keylet::account(issuer.id())));
// Credential still exists before removeExpired // Credential still exists before removeExpired
+2 -1
View File
@@ -29,6 +29,7 @@
#include <xrpl/json/json_value.h> #include <xrpl/json/json_value.h>
#include <xrpl/json/to_string.h> #include <xrpl/json/to_string.h>
#include <xrpl/ledger/OpenView.h> #include <xrpl/ledger/OpenView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/protocol/ApiVersion.h> #include <xrpl/protocol/ApiVersion.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
@@ -450,7 +451,7 @@ class NFTokenBaseUtil_test : public beast::unit_test::Suite
// here and the end of the test all the effort will be lost. // here and the end of the test all the effort will be lost.
env.app().getOpenLedger().modify([&alice](OpenView& view, beast::Journal j) { env.app().getOpenLedger().modify([&alice](OpenView& view, beast::Journal j) {
// Get the account root we want to hijack. // Get the account root we want to hijack.
auto const sle = view.read(keylet::account(alice.id())); auto const sle = AccountRootEntryR(alice.id(), view);
if (!sle) if (!sle)
return false; // This would be really surprising! return false; // This would be really surprising!
+2 -1
View File
@@ -30,6 +30,7 @@
#include <xrpl/json/to_string.h> #include <xrpl/json/to_string.h>
#include <xrpl/ledger/Dir.h> #include <xrpl/ledger/Dir.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/protocol/ApiVersion.h> #include <xrpl/protocol/ApiVersion.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
@@ -69,7 +70,7 @@ struct PayChan_test : public beast::unit_test::Suite
static std::pair<UInt256, SLE::const_pointer> static std::pair<UInt256, SLE::const_pointer>
channelKeyAndSle(ReadView const& view, jtx::Account const& account, jtx::Account const& dst) channelKeyAndSle(ReadView const& view, jtx::Account const& account, jtx::Account const& dst)
{ {
auto const sle = view.read(keylet::account(account)); auto const sle = AccountRootEntryR(account, view);
if (!sle) if (!sle)
return {}; return {};
auto const k = auto const k =
+2 -1
View File
@@ -41,6 +41,7 @@
#include <xrpl/json/json_value.h> #include <xrpl/json/json_value.h>
#include <xrpl/ledger/ApplyView.h> #include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/OpenView.h> #include <xrpl/ledger/OpenView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Asset.h> #include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
@@ -4294,7 +4295,7 @@ public:
// restore the owner's OwnerCount to the legacy weight. // restore the owner's OwnerCount to the legacy weight.
env.app().getOpenLedger().modify([&](OpenView& view, beast::Journal) -> bool { env.app().getOpenLedger().modify([&](OpenView& view, beast::Journal) -> bool {
auto signerList = std::make_shared<SLE>(*view.read(signerListKeylet)); auto signerList = std::make_shared<SLE>(*view.read(signerListKeylet));
auto account = std::make_shared<SLE>(*view.read(keylet::account(alice.id()))); auto account = std::make_shared<SLE>(*AccountRootEntryR(alice.id(), view));
signerList->clearFlag(lsfOneOwnerCount); signerList->clearFlag(lsfOneOwnerCount);
account->setFieldU32(sfOwnerCount, legacyWeight); account->setFieldU32(sfOwnerCount, legacyWeight);
view.rawReplace(signerList); view.rawReplace(signerList);
@@ -176,7 +176,7 @@ class InvariantsMisc_test : public InvariantsBase
// check. // check.
sleA1->at(sfBalance) = beast::kZero; sleA1->at(sfBalance) = beast::kZero;
BEAST_EXPECT(sleA1->at(sfOwnerCount) == 0); BEAST_EXPECT(sleA1->at(sfOwnerCount) == 0);
increaseOwnerCount(ac.view(), sleA1, {}, 1, ac.journal); increaseOwnerCount(ac.view(), a1, {}, 1, ac.journal);
ac.view().erase(sleA1); ac.view().erase(sleA1);
+7 -6
View File
@@ -20,6 +20,7 @@
#include <xrpl/ledger/OwnerCounts.h> #include <xrpl/ledger/OwnerCounts.h>
#include <xrpl/ledger/PaymentSandbox.h> #include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h> #include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
@@ -417,10 +418,10 @@ class PaymentSandbox_test : public beast::unit_test::Suite
// Test basic owner count hook without sponsor // Test basic owner count hook without sponsor
{ {
auto const aliceSle = sb.peek(keylet::account(alice)); auto const aliceSle = AccountRootEntryW(alice, sb);
BEAST_EXPECT(aliceSle); BEAST_EXPECT(aliceSle);
OwnerCounts const initial(aliceSle); OwnerCounts const initial(aliceSle.rawSle());
OwnerCounts updated = initial; OwnerCounts updated = initial;
updated.owner = initial.owner + 2; updated.owner = initial.owner + 2;
@@ -436,10 +437,10 @@ class PaymentSandbox_test : public beast::unit_test::Suite
// Test owner count hook with sponsor-related counts // Test owner count hook with sponsor-related counts
{ {
auto const sponsorSle = sb.peek(keylet::account(sponsor)); auto const sponsorSle = AccountRootEntryW(sponsor, sb);
BEAST_EXPECT(sponsorSle); BEAST_EXPECT(sponsorSle);
OwnerCounts const sponsorInitial(sponsorSle); OwnerCounts const sponsorInitial(sponsorSle.rawSle());
OwnerCounts sponsorUpdated = sponsorInitial; OwnerCounts sponsorUpdated = sponsorInitial;
sponsorUpdated.owner = sponsorInitial.owner + 1; sponsorUpdated.owner = sponsorInitial.owner + 1;
sponsorUpdated.sponsoring = sponsorInitial.sponsoring + 1; sponsorUpdated.sponsoring = sponsorInitial.sponsoring + 1;
@@ -469,8 +470,8 @@ class PaymentSandbox_test : public beast::unit_test::Suite
// Test that max logic works correctly // Test that max logic works correctly
{ {
auto const aliceSle = sb.peek(keylet::account(alice)); auto const aliceSle = AccountRootEntryW(alice, sb);
OwnerCounts const current(aliceSle); OwnerCounts const current(aliceSle.rawSle());
OwnerCounts lower = current; OwnerCounts lower = current;
lower.owner = (current.owner > 0) ? current.owner - 1 : 0; lower.owner = (current.owner > 0) ? current.owner - 1 : 0;
+14 -3
View File
@@ -38,6 +38,7 @@
#include <xrpl/ledger/entries/XChainOwnedClaimIDEntry.h> // IWYU pragma: keep #include <xrpl/ledger/entries/XChainOwnedClaimIDEntry.h> // IWYU pragma: keep
#include <xrpl/ledger/entries/XChainOwnedCreateAccountClaimIDEntry.h> // IWYU pragma: keep #include <xrpl/ledger/entries/XChainOwnedCreateAccountClaimIDEntry.h> // IWYU pragma: keep
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Keylet.h>
#include <xrpl/protocol/LedgerFormats.h> #include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/SField.h> #include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h> #include <xrpl/protocol/STLedgerEntry.h>
@@ -76,12 +77,22 @@ template class SLEBase<ApplyView>;
#pragma push_macro("LEDGER_ENTRY") #pragma push_macro("LEDGER_ENTRY")
#undef LEDGER_ENTRY #undef LEDGER_ENTRY
// No explicit instantiation here, neither a definition nor a declaration.
// A definition would instantiate an entry a second time once its member
// bodies live in its own .cpp (MSVC rejects that with C4661 under /WX), and a
// declaration (`extern template`) stops clang from emitting the inline
// constructors of the header-only entries at -O0, which leaves them undefined
// at link time in the debug builds. Naming the class in a static_assert is
// enough to instantiate its definition, which is all this exhaustiveness
// check needs; the per-type suites exercise the members.
#define LEDGER_ENTRY(tag, value, name, ...) \ #define LEDGER_ENTRY(tag, value, name, ...) \
template class name##Entry<ReadView>; \
template class name##Entry<ApplyView>; \
static_assert( \ static_assert( \
name##Entry<ReadView>::kEntryType == tag && name##Entry<ApplyView>::kEntryType == tag, \ name##Entry<ReadView>::kEntryType == tag && name##Entry<ApplyView>::kEntryType == tag, \
#name "Entry must be bound to " #tag); #name "Entry must be bound to " #tag); \
static_assert( \
std::is_constructible_v<name##Entry<ReadView>, Keylet const&, ReadView const&> && \
std::is_constructible_v<name##Entry<ApplyView>, Keylet const&, ApplyView&>, \
#name "Entry must be constructible from a Keylet and a view");
#include <xrpl/protocol/detail/ledger_entries.macro> #include <xrpl/protocol/detail/ledger_entries.macro>
+2 -1
View File
@@ -3,6 +3,7 @@
#include <xrpl/basics/base_uint.h> #include <xrpl/basics/base_uint.h>
#include <xrpl/ledger/CanonicalTXSet.h> #include <xrpl/ledger/CanonicalTXSet.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/Protocol.h> #include <xrpl/protocol/Protocol.h>
@@ -143,7 +144,7 @@ public:
return true; return true;
AccountID const acctID = txn.getAccount(); AccountID const acctID = txn.getAccount();
auto const sleAcct = view.read(keylet::account(acctID)); auto const sleAcct = AccountRootEntryR(acctID, view);
if (!sleAcct) if (!sleAcct)
return false; return false;
+2 -1
View File
@@ -73,6 +73,7 @@
#include <xrpl/ledger/OpenView.h> #include <xrpl/ledger/OpenView.h>
#include <xrpl/ledger/OrderBookDB.h> #include <xrpl/ledger/OrderBookDB.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h> #include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h> #include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h> #include <xrpl/ledger/helpers/TokenHelpers.h>
@@ -4510,7 +4511,7 @@ NetworkOPsImp::subAccountHistoryStart(
} }
if (accountId == kGenesisAccountId) if (accountId == kGenesisAccountId)
{ {
if (auto const sleAcct = ledger->read(accountKeylet); sleAcct) if (auto const sleAcct = AccountRootEntryR(accountKeylet, *ledger); sleAcct)
{ {
if (sleAcct->getFieldU32(sfSequence) == 1) if (sleAcct->getFieldU32(sfSequence) == 1)
{ {
+13 -10
View File
@@ -15,6 +15,7 @@
#include <xrpl/ledger/ApplyViewImpl.h> #include <xrpl/ledger/ApplyViewImpl.h>
#include <xrpl/ledger/OpenView.h> #include <xrpl/ledger/OpenView.h>
#include <xrpl/ledger/ReadView.h> #include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h> #include <xrpl/ledger/helpers/SponsorHelpers.h>
#include <xrpl/protocol/AccountID.h> #include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Indexes.h> #include <xrpl/protocol/Indexes.h>
@@ -790,7 +791,7 @@ TxQ::apply(
// If the account is not currently in the ledger, don't queue its tx. // If the account is not currently in the ledger, don't queue its tx.
auto const account = (*tx)[sfAccount]; auto const account = (*tx)[sfAccount];
Keylet const accountKey{keylet::account(account)}; Keylet const accountKey{keylet::account(account)};
auto const sleAccount = view.read(accountKey); auto const sleAccount = AccountRootEntryR(accountKey, view);
if (!sleAccount) if (!sleAccount)
return {terNO_ACCOUNT, false}; return {terNO_ACCOUNT, false};
@@ -1007,8 +1008,8 @@ TxQ::apply(
{ {
// If the transaction is queueable, create the multiTxn // If the transaction is queueable, create the multiTxn
// object to hold the info we need to adjust for prior txns. // object to hold the info we need to adjust for prior txns.
TER const ter{ TER const ter{canBeHeld(
canBeHeld(*tx, flags, view, sleAccount, accountIter, replacedTxIter, lock)}; *tx, flags, view, sleAccount.rawSle(), accountIter, replacedTxIter, lock)};
if (!isTesSuccess(ter)) if (!isTesSuccess(ter))
return {ter, false}; return {ter, false};
@@ -1063,7 +1064,8 @@ TxQ::apply(
// front of this one in the queue. Make sure the current // front of this one in the queue. Make sure the current
// transaction fits in proper sequence order with the // transaction fits in proper sequence order with the
// previous transaction or is a ticket. // previous transaction or is a ticket.
if (txSeqProx.isSeq() && nextQueuableSeqImpl(sleAccount, lock) != txSeqProx) if (txSeqProx.isSeq() &&
nextQueuableSeqImpl(sleAccount.rawSle(), lock) != txSeqProx)
return {telCAN_NOT_QUEUE, false}; return {telCAN_NOT_QUEUE, false};
} }
@@ -1153,7 +1155,7 @@ TxQ::apply(
// Create the test view from the current view. // Create the test view from the current view.
multiTxn.emplace(view, flags); multiTxn.emplace(view, flags);
auto const sleBump = multiTxn->applyView.peek(accountKey); auto sleBump = AccountRootEntryW(accountKey, multiTxn->applyView);
if (!sleBump) if (!sleBump)
return {tefINTERNAL, false}; return {tefINTERNAL, false};
@@ -1174,7 +1176,7 @@ TxQ::apply(
// to the most successful case. // to the most successful case.
sleBump->at(sfSequence) = txSeqProx.isSeq() sleBump->at(sfSequence) = txSeqProx.isSeq()
? txSeqProx.value() ? txSeqProx.value()
: nextQueuableSeqImpl(sleAccount, lock).value(); : nextQueuableSeqImpl(sleAccount.rawSle(), lock).value();
} }
} }
@@ -1249,7 +1251,8 @@ TxQ::apply(
// If `multiTxn` has a value, then `canBeHeld` has already been verified // If `multiTxn` has a value, then `canBeHeld` has already been verified
if (!multiTxn) if (!multiTxn)
{ {
TER const ter{canBeHeld(*tx, flags, view, sleAccount, accountIter, replacedTxIter, lock)}; TER const ter{
canBeHeld(*tx, flags, view, sleAccount.rawSle(), accountIter, replacedTxIter, lock)};
if (!isTesSuccess(ter)) if (!isTesSuccess(ter))
{ {
// Bail, transaction cannot be held // Bail, transaction cannot be held
@@ -1692,7 +1695,7 @@ TxQ::tryDirectApply(
beast::Journal j) beast::Journal j)
{ {
auto const account = (*tx)[sfAccount]; auto const account = (*tx)[sfAccount];
auto const sleAccount = view.read(keylet::account(account)); auto const sleAccount = AccountRootEntryR(account, view);
// Don't attempt to direct apply if the account is not in the ledger. // Don't attempt to direct apply if the account is not in the ledger.
if (!sleAccount) if (!sleAccount)
@@ -1820,10 +1823,10 @@ TxQ::getTxRequiredFeeAndSeq(OpenView const& view, std::shared_ptr<STTx const> co
auto const baseFee = *maybeBaseFee; auto const baseFee = *maybeBaseFee;
auto const fee = FeeMetrics::scaleFeeLevel(snapshot, view); auto const fee = FeeMetrics::scaleFeeLevel(snapshot, view);
auto const sle = view.read(keylet::account(account)); auto const sle = AccountRootEntryR(account, view);
std::uint32_t const accountSeq = sle ? (*sle)[sfSequence] : 0; std::uint32_t const accountSeq = sle ? (*sle)[sfSequence] : 0;
std::uint32_t const availableSeq = nextQueuableSeqImpl(sle, lock).value(); std::uint32_t const availableSeq = nextQueuableSeqImpl(sle.rawSle(), lock).value();
return FeeAndSeq{ return FeeAndSeq{
.fee = mulDiv(fee, baseFee, kBaseLevel) .fee = mulDiv(fee, baseFee, kBaseLevel)
.value_or(XRPAmount(std::numeric_limits<std::int64_t>::max())), .value_or(XRPAmount(std::numeric_limits<std::int64_t>::max())),