Compare commits

...

11 Commits

Author SHA1 Message Date
Mayukha Vadari
51401e1f57 Document transferRate return value 2026-10-05 15:50:45 +01:00
Mayukha Vadari
8891288bf1 refactor: Move transferRate onto AccountRootEntry
Add the const member AccountRootEntry::transferRate(). The
transferRate(view, issuer) free function stays as the shim and keeps
returning kParityRate when the account does not exist.
2026-10-05 15:50:07 +01:00
Mayukha Vadari
821567f4ad refactor: Move xrpLiquid onto AccountRootEntry
Move the xrpLiquid body to the const member
AccountRootEntry::xrpLiquid(ownerCountAdj). It returns zero when the
entry does not exist, as before. The xrpLiquid(view, id, adj, j) free
function stays as a one-line inline shim that passes the journal to the
entry constructor.
2026-10-05 15:50:03 +01:00
Mayukha Vadari
dcd32a6f6a Document isGlobalFrozen return value 2026-10-05 15:49:56 +01:00
Mayukha Vadari
14368cf1f3 refactor: Move isGlobalFrozen onto AccountRootEntry
Add the const member AccountRootEntry::isGlobalFrozen(), which reads
lsfGlobalFreeze. The isGlobalFrozen(view, issuer) free function stays
as the shim and keeps its XRP and missing-account handling.
2026-10-05 15:49:28 +01:00
Mayukha Vadari
95323edaf3 Document checkDestinationAndTag parameters and return value 2026-10-05 15:49:19 +01:00
Mayukha Vadari
8940046ca8 refactor: Move checkDestinationAndTag onto AccountRootEntry
Replace the entry-taking checkDestinationAndTag free function with the
const member AccountRootEntry::checkDestinationAndTag(hasDestinationTag).
The body is short, so it is inline in the header.
2026-10-05 15:48:35 +01:00
Mayukha Vadari
f27581a6bb Document createPseudoAccount parameters and return value 2026-10-05 15:48:28 +01:00
Mayukha Vadari
b0a1f81256 refactor: Move createPseudoAccount onto AccountRootEntry
Replace the free createPseudoAccount function with the static factory
AccountRootEntryW::createPseudoAccount. It returns the new entry
instead of a raw SLE pointer; every caller only reads sfAccount from
the result, so the call sites change only in name.

The factory builds the account with newSLE() and insert() on the
entry. pseudoAccountAddress and getPseudoAccountFields stay free.
2026-10-05 15:47:46 +01:00
Mayukha Vadari
d21cf46021 Document isPseudoAccount return value 2026-10-05 15:47:38 +01:00
Mayukha Vadari
b3e0936504 refactor: Move isPseudoAccount onto AccountRootEntry
Replace the entry-taking isPseudoAccount free function with the const
member AccountRootEntry::isPseudoAccount(). The (view, AccountID)
overload stays as a one-line shim. The invariant-only
isPseudoAccountSle(SLE) helper is unchanged; VaultInvariant.cpp changes
only because its call used the removed overload.
2026-10-05 15:46:52 +01:00
22 changed files with 233 additions and 176 deletions

View File

@@ -1,5 +1,6 @@
#pragma once
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
@@ -7,10 +8,13 @@
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/Rate.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/XRPAmount.h>
#include <cstdint>
#include <expected>
#include <optional>
namespace xrpl {
@@ -103,6 +107,87 @@ public:
[[nodiscard]] TER
checkReserve(ApplyViewContext ctx, XRPAmount accBalance, Adjustment adj) const;
/**
* Returns true if and only if this entry is a pseudo-account of any kind
* (i.e. carries at least one field flagged with SField::kSmdPseudoAccount).
*
* Returns false if the entry:
* - is NOT a pseudo-account OR
* - is NOT a ltACCOUNT_ROOT OR
* - does not exist
*
* @return true if and only if this entry is a pseudo-account of any kind.
*/
[[nodiscard]] bool
isPseudoAccount() const;
/**
* Calculate the liquid XRP balance of this account.
*
* This is the amount of XRP that the holder is able to freely spend. It
* subtracts reserve requirements. Returns zero if the entry does not exist.
*
* ownerCountAdj adjusts the owner count in case the caller calculates
* before ledger entries are added or removed. Positive to add, negative
* to subtract.
*
* @param ownerCountAdj Positive to add to count, negative to reduce count
* @return The liquid XRP amount available to the account
*/
[[nodiscard]] XRPAmount
xrpLiquid(std::int32_t ownerCountAdj = 0) const;
/**
* Returns true if this account has the global freeze flag set.
*
* @return true if this account has the global freeze flag set.
*/
[[nodiscard]] bool
isGlobalFrozen() const
{
return (*this)->isFlag(lsfGlobalFreeze);
}
/**
* Returns this account's IOU transfer fee as Rate, or kParityRate if it
* sets none. Rate specifies the fee as fractions of 1 billion. For
* example, 1% transfer rate is represented as 1,010,000,000.
*
* @return This account's IOU transfer fee, or kParityRate if it sets none.
*/
[[nodiscard]] Rate
transferRate() const
{
if ((*this)->isFieldPresent(sfTransferRate))
return Rate{(*this)->getFieldU32(sfTransferRate)};
return kParityRate;
}
/**
* Checks the destination and tag.
*
* - Checks that the entry exists.
* - If the entry requires a destination tag, checks that there is a tag.
*
* @param hasDestinationTag Whether the transaction supplies a destination tag
* @return tecNO_DST if the entry does not exist; tecDST_TAG_NEEDED if the
* entry requires a destination tag and hasDestinationTag is false;
* tesSUCCESS otherwise
*/
[[nodiscard]] TER
checkDestinationAndTag(bool hasDestinationTag) const
{
if (!this->exists())
return tecNO_DST;
// The tag is basically account-specific information we don't
// understand, but we can require someone to fill it in.
if ((*this)->isFlag(lsfRequireDestTag) && !hasDestinationTag)
return tecDST_TAG_NEEDED; // Cannot send without a tag
return tesSUCCESS;
}
/**
* Increase owner-count fields when the caller supplies the sponsor.
*
@@ -149,6 +234,25 @@ public:
decreaseOwnerCount(std::optional<AccountRootEntry<ApplyView>>& sponsorSle, std::uint32_t count)
requires Base::kIsWritable;
/**
* Create pseudo-account, storing pseudoOwnerKey into ownerField.
*
* The list of valid ownerField is maintained in AccountRootHelpers.cpp and
* the caller to this function must perform necessary amendment check(s)
* before using a field. The amendment check is **not** performed in
* createPseudoAccount.
*
* @param view The ledger view to create the pseudo-account in
* @param pseudoOwnerKey The key of the object that owns the pseudo-account,
* stored into ownerField
* @param ownerField The field linking the pseudo-account to its owner
* @return The newly created pseudo-account, or tecDUPLICATE if an account
* already exists at the derived pseudo-account address
*/
[[nodiscard]] static std::expected<AccountRootEntry<ApplyView>, TER>
createPseudoAccount(ApplyView& view, UInt256 const& pseudoOwnerKey, SField const& ownerField)
requires Base::kIsWritable;
private:
void
adjustOwnerCountSigned(

View File

@@ -9,11 +9,9 @@
#include <xrpl/protocol/Rate.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/XRPAmount.h>
#include <cstdint>
#include <expected>
#include <optional>
#include <vector>
@@ -43,8 +41,11 @@ isGlobalFrozen(ReadView const& view, AccountID const& issuer);
* @param j Journal for logging
* @return The liquid XRP amount available to the account
*/
[[nodiscard]] XRPAmount
xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j);
[[nodiscard]] inline XRPAmount
xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j)
{
return AccountRootEntryR(id, view, j).xrpLiquid(ownerCountAdj);
}
namespace detail {
@@ -253,45 +254,13 @@ pseudoAccountAddress(ReadView const& view, UInt256 const& pseudoOwnerKey);
[[nodiscard]] std::vector<SField const*> const&
getPseudoAccountFields();
/**
* Returns true if and only if sleAcct is a pseudo-account of any kind
* (i.e. carries at least one field flagged with SField::kSmdPseudoAccount).
*
* Returns false if sleAcct is:
* - NOT a pseudo-account OR
* - NOT a ltACCOUNT_ROOT OR
* - null pointer
*/
[[nodiscard]] bool
isPseudoAccount(AccountRootEntryR const& sleAcct);
/**
* Convenience overload that reads the account from the view.
*/
[[nodiscard]] inline bool
isPseudoAccount(ReadView const& view, AccountID const& accountId)
{
return isPseudoAccount(AccountRootEntryR(accountId, view));
return AccountRootEntryR(accountId, view).isPseudoAccount();
}
/**
* Create pseudo-account, storing pseudoOwnerKey into ownerField.
*
* The list of valid ownerField is maintained in AccountRootHelpers.cpp and
* the caller to this function must perform necessary amendment check(s)
* before using a field. The amendment check is **not** performed in
* createPseudoAccount.
*/
[[nodiscard]] std::expected<SLE::pointer, TER>
createPseudoAccount(ApplyView& view, UInt256 const& pseudoOwnerKey, SField const& ownerField);
/**
* Checks the destination and tag.
*
* - Checks that the SLE is not null.
* - If the SLE requires a destination tag, checks that there is a tag.
*/
[[nodiscard]] TER
checkDestinationAndTag(AccountRootEntryR const& toSle, bool hasDestinationTag);
} // namespace xrpl

View File

@@ -10,7 +10,6 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
@@ -472,7 +471,7 @@ canWithdraw(
bool hasDestinationTag,
std::optional<std::vector<UInt256>> const& credentialIDs)
{
if (auto const ret = checkDestinationAndTag(toSle, hasDestinationTag))
if (auto const ret = toSle.checkDestinationAndTag(hasDestinationTag))
return ret;
if (from == to)

View File

@@ -1,6 +1,8 @@
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/basics/Log.h>
#include <xrpl/basics/base_uint.h>
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/OwnerCounts.h>
@@ -16,7 +18,9 @@
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/XRPAmount.h>
#include <algorithm>
#include <cstdint>
#include <expected>
#include <limits>
#include <optional>
#include <utility>
@@ -173,6 +177,54 @@ AccountRootEntry<ViewT>::checkReserve(ApplyViewContext ctx, XRPAmount accBalance
return checkReserve(ctx, accBalance, sponsorSle, adj);
}
template <typename ViewT>
XRPAmount
AccountRootEntry<ViewT>::xrpLiquid(std::int32_t ownerCountAdj) const
{
if (!this->exists())
return beast::kZero;
auto const& view = this->readView();
auto const j = this->journal();
AccountID const id = (*this)->getAccountID(sfAccount);
// Return balance minus reserve
std::uint32_t const currentOwnerCount = detail::confineOwnerCount(
view.ownerCountHook(id, OwnerCounts(this->rawSle())).count(), ownerCountAdj);
std::uint32_t const currentAccountCount = detail::accountCountImpl(*this, 0, j);
// Pseudo-accounts have no reserve requirement
auto const reserve = isPseudoAccount()
? XRPAmount{0}
: view.fees().accountReserve(currentOwnerCount, currentAccountCount);
auto const fullBalance = (*this)->getFieldAmount(sfBalance);
auto const balance = view.balanceHookIOU(id, xrpAccount(), fullBalance);
STAmount const amount = (balance < reserve) ? STAmount{0} : balance - reserve;
JLOG(j.trace()) << "accountHolds:" << " account=" << to_string(id)
<< " amount=" << amount.getFullText()
<< " fullBalance=" << fullBalance.getFullText()
<< " balance=" << balance.getFullText() << " reserve=" << reserve
<< " ownerCount=" << currentOwnerCount << " ownerCountAdj=" << ownerCountAdj;
return amount.xrp();
}
template <typename ViewT>
bool
AccountRootEntry<ViewT>::isPseudoAccount() const
{
// Intentionally use defensive coding here because it's cheap and makes the
// semantics of true return value clean.
return this->exists() && (*this)->getType() == ltACCOUNT_ROOT &&
std::ranges::any_of(getPseudoAccountFields(), [this](SField const* sf) {
return (*this)->isFieldPresent(*sf);
});
}
template <typename ViewT>
void
AccountRootEntry<ViewT>::adjustOwnerCountSigned(
@@ -316,6 +368,54 @@ AccountRootEntry<ViewT>::decreaseOwnerCount(
adjustOwnerCountSigned(sponsorSle, -static_cast<std::int32_t>(count));
}
template <typename ViewT>
std::expected<AccountRootEntry<ApplyView>, TER>
AccountRootEntry<ViewT>::createPseudoAccount(
ApplyView& view,
UInt256 const& pseudoOwnerKey,
SField const& ownerField)
requires Base::kIsWritable
{
[[maybe_unused]]
auto const& fields = getPseudoAccountFields();
XRPL_ASSERT(
std::count_if(
fields.begin(),
fields.end(),
[&ownerField](SField const* sf) -> bool { return *sf == ownerField; }) == 1,
"xrpl::createPseudoAccount : valid owner field");
auto const accountId = pseudoAccountAddress(view, pseudoOwnerKey);
if (accountId == beast::kZero)
return std::unexpected(tecDUPLICATE);
// Create pseudo-account.
AccountRootEntry<ApplyView> account(accountId, view);
account.newSLE();
account->setAccountID(sfAccount, accountId);
account->setFieldAmount(sfBalance, STAmount{});
// Pseudo-accounts can't submit transactions, so set the sequence number
// to 0 to make them easier to spot and verify, and add an extra level
// of protection.
std::uint32_t const seqno = //
view.rules().enabled(featureSingleAssetVault) || //
view.rules().enabled(featureLendingProtocol) //
? 0 //
: view.seq();
account->setFieldU32(sfSequence, seqno);
// Ignore reserves requirement, disable the master key, allow default
// rippling, and enable deposit authorization to prevent payments into
// pseudo-account.
account->setFieldU32(sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth);
// Link the pseudo-account with its owner object.
account->setFieldH256(ownerField, pseudoOwnerKey);
account.insert();
return account;
}
template class AccountRootEntry<ReadView>;
template class AccountRootEntry<ApplyView>;

View File

@@ -7,24 +7,17 @@
#include <xrpl/beast/utility/Zero.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/entries/AccountRootEntry.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/Rate.h>
#include <xrpl/protocol/SField.h>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/TER.h>
#include <xrpl/protocol/XRPAmount.h>
#include <xrpl/protocol/digest.h>
#include <algorithm>
#include <cstdint>
#include <expected>
#include <limits>
#include <memory>
#include <optional>
@@ -39,7 +32,7 @@ isGlobalFrozen(ReadView const& view, AccountID const& issuer)
if (isXRP(issuer))
return false;
if (auto const sle = AccountRootEntryR(issuer, view))
return sle->isFlag(lsfGlobalFreeze);
return sle.isGlobalFrozen();
return false;
}
@@ -131,45 +124,13 @@ adjustOwnerCountImpl(
} // namespace detail
XRPAmount
xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j)
{
auto const sle = AccountRootEntryR(id, view);
if (!sle.exists())
return beast::kZero;
// Return balance minus reserve
std::uint32_t const currentOwnerCount = detail::confineOwnerCount(
view.ownerCountHook(id, OwnerCounts(sle.rawSle())).count(), ownerCountAdj);
std::uint32_t const currentAccountCount = detail::accountCountImpl(sle, 0, j);
// Pseudo-accounts have no reserve requirement
auto const reserve = isPseudoAccount(sle)
? XRPAmount{0}
: view.fees().accountReserve(currentOwnerCount, currentAccountCount);
auto const fullBalance = sle->getFieldAmount(sfBalance);
auto const balance = view.balanceHookIOU(id, xrpAccount(), fullBalance);
STAmount const amount = (balance < reserve) ? STAmount{0} : balance - reserve;
JLOG(j.trace()) << "accountHolds:" << " account=" << to_string(id)
<< " amount=" << amount.getFullText()
<< " fullBalance=" << fullBalance.getFullText()
<< " balance=" << balance.getFullText() << " reserve=" << reserve
<< " ownerCount=" << currentOwnerCount << " ownerCountAdj=" << ownerCountAdj;
return amount.xrp();
}
Rate
transferRate(ReadView const& view, AccountID const& issuer)
{
auto const sle = AccountRootEntryR(issuer, view);
if (sle && sle->isFieldPresent(sfTransferRate))
return Rate{sle->getFieldU32(sfTransferRate)};
if (sle)
return sle.transferRate();
return kParityRate;
}
@@ -267,71 +228,4 @@ getPseudoAccountFields()
return kPseudoFields;
}
[[nodiscard]] bool
isPseudoAccount(AccountRootEntryR const& sleAcct)
{
// Intentionally use defensive coding here because it's cheap and makes the
// semantics of true return value clean.
return sleAcct && sleAcct->getType() == ltACCOUNT_ROOT &&
std::ranges::any_of(getPseudoAccountFields(), [&sleAcct](SField const* sf) {
return sleAcct->isFieldPresent(*sf);
});
}
std::expected<SLE::pointer, TER>
createPseudoAccount(ApplyView& view, UInt256 const& pseudoOwnerKey, SField const& ownerField)
{
[[maybe_unused]]
auto const& fields = getPseudoAccountFields();
XRPL_ASSERT(
std::count_if(
fields.begin(),
fields.end(),
[&ownerField](SField const* sf) -> bool { return *sf == ownerField; }) == 1,
"xrpl::createPseudoAccount : valid owner field");
auto const accountId = pseudoAccountAddress(view, pseudoOwnerKey);
if (accountId == beast::kZero)
return std::unexpected(tecDUPLICATE);
// Create pseudo-account.
auto account = std::make_shared<SLE>(keylet::account(accountId));
account->setAccountID(sfAccount, accountId);
account->setFieldAmount(sfBalance, STAmount{});
// Pseudo-accounts can't submit transactions, so set the sequence number
// to 0 to make them easier to spot and verify, and add an extra level
// of protection.
std::uint32_t const seqno = //
view.rules().enabled(featureSingleAssetVault) || //
view.rules().enabled(featureLendingProtocol) //
? 0 //
: view.seq();
account->setFieldU32(sfSequence, seqno);
// Ignore reserves requirement, disable the master key, allow default
// rippling, and enable deposit authorization to prevent payments into
// pseudo-account.
account->setFieldU32(sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth);
// Link the pseudo-account with its owner object.
account->setFieldH256(ownerField, pseudoOwnerKey);
view.insert(account);
return account;
}
[[nodiscard]] TER
checkDestinationAndTag(AccountRootEntryR const& toSle, bool hasDestinationTag)
{
if (!toSle.exists())
return tecNO_DST;
// The tag is basically account-specific information we don't
// understand, but we can require someone to fill it in.
if (toSle->isFlag(lsfRequireDestTag) && !hasDestinationTag)
return tecDST_TAG_NEEDED; // Cannot send without a tag
return tesSUCCESS;
}
} // namespace xrpl

View File

@@ -4,7 +4,6 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/OracleHelpers.h>
#include <xrpl/ledger/helpers/ProposalHelpers.h>
#include <xrpl/protocol/AccountID.h>
@@ -133,7 +132,7 @@ getEffectiveTxReserveSponsor(ApplyViewContext ctx, AccountRootEntryR const& acco
"xrpl::getEffectiveTxReserveSponsor : accountSle exists and is account type");
}
if (isPseudoAccount(accountSle) || accountSle->getAccountID(sfAccount) != ctx.tx[sfAccount])
if (accountSle.isPseudoAccount() || accountSle->getAccountID(sfAccount) != ctx.tx[sfAccount])
return std::nullopt;
return getTxReserveSponsor(ctx);
}

View File

@@ -930,7 +930,7 @@ Transactor::checkSign(
if ((view.rules().enabled(featureLendingProtocol) ||
view.rules().enabled(featureBatchV1_1) || view.rules().enabled(fixCleanup3_3_0)) &&
isPseudoAccount(sle))
sle.isPseudoAccount())
{
// Pseudo-accounts can't sign transactions. This check is gated on a
// few different amendments so that it takes effect as soon as any of

View File

@@ -6,7 +6,7 @@
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/beast/utility/instrumentation.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/VaultHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
@@ -740,7 +740,7 @@ ValidVault::finalize(
return false;
}
if (!isPseudoAccount(AccountRootEntryR(sleSharesIssuer, view)))
if (!AccountRootEntryR(sleSharesIssuer, view).isPseudoAccount())
{
JLOG(j.fatal()) //
<< "Invariant failed: shares issuer must be a "

View File

@@ -5,7 +5,6 @@
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -95,7 +94,7 @@ CheckCreate::preclaim(PreclaimContext const& ctx)
// because all writes to pseudo-account discriminator fields **are**
// amendment gated, hence the behaviour of this check will always match the
// currently active amendments.
if (isPseudoAccount(sleDst))
if (sleDst.isPseudoAccount())
return tecNO_PERMISSION;
if (sleDst->isFlag(lsfRequireDestTag) && !ctx.tx.isFieldPresent(sfDestinationTag))

View File

@@ -5,7 +5,6 @@
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h> // IWYU pragma: keep
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -99,7 +98,7 @@ CredentialCreate::preclaim(PreclaimContext const& ctx)
return tecDUPLICATE;
}
if (ctx.view.rules().enabled(fixCleanup3_3_0) && isPseudoAccount(subjectSle))
if (ctx.view.rules().enabled(fixCleanup3_3_0) && subjectSle.isPseudoAccount())
{
JLOG(ctx.j.trace()) << "Subject is a pseudo-account.";
return tecPSEUDO_ACCOUNT;

View File

@@ -57,7 +57,7 @@ DelegateSet::preclaim(PreclaimContext const& ctx)
if (!sleAuthorize)
return tecNO_TARGET;
if (isPseudoAccount(sleAuthorize))
if (sleAuthorize.isPseudoAccount())
return tecPSEUDO_ACCOUNT;
// Deleting the delegate object is invalid if it doesn’t exist.

View File

@@ -264,7 +264,7 @@ applyCreate(ApplyContext& ctx, Sandbox& sb, AccountID const& account, beast::Jou
auto const ammKeylet = keylet::amm(amount.asset(), amount2.asset());
// Mitigate same account exists possibility
auto const maybeAccount = createPseudoAccount(sb, ammKeylet.key, sfAMMID);
auto const maybeAccount = AccountRootEntryW::createPseudoAccount(sb, ammKeylet.key, sfAMMID);
// AMM account already exists (should not happen)
if (!maybeAccount)
{

View File

@@ -8,7 +8,6 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
@@ -356,7 +355,7 @@ EscrowCreate::preclaim(PreclaimContext const& ctx)
// because all writes to pseudo-account discriminator fields **are**
// amendment gated, hence the behaviour of this check will always match the
// currently active amendments.
if (isPseudoAccount(sled))
if (sled.isPseudoAccount())
return tecNO_PERMISSION;
if (!isXRP(amount))

View File

@@ -6,7 +6,6 @@
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/LendingHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/ledger/helpers/VaultHelpers.h>
@@ -261,7 +260,8 @@ LoanBrokerSet::doApply()
if (preFeeBalance_ < owner.reserve())
return tecINSUFFICIENT_RESERVE;
auto maybePseudo = createPseudoAccount(view, broker->key(), sfLoanBrokerID);
auto maybePseudo =
AccountRootEntryW::createPseudoAccount(view, broker->key(), sfLoanBrokerID);
if (!maybePseudo)
return maybePseudo.error(); // LCOV_EXCL_LINE
auto& pseudo = *maybePseudo;

View File

@@ -108,7 +108,7 @@ DepositPreauth::preclaim(PreclaimContext const& ctx)
if (!sleAuth)
return tecNO_TARGET;
if (ctx.view.rules().enabled(fixCleanup3_3_0) && isPseudoAccount(sleAuth))
if (ctx.view.rules().enabled(fixCleanup3_3_0) && sleAuth.isPseudoAccount())
{
JLOG(ctx.j.debug()) << "Authorized account is a pseudo-account.";
return tecPSEUDO_ACCOUNT;

View File

@@ -7,7 +7,6 @@
#include <xrpl/ledger/PaymentSandbox.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/CredentialHelpers.h>
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
#include <xrpl/ledger/helpers/PermissionedDEXHelpers.h>
@@ -801,7 +800,7 @@ Payment::doApply()
// transaction types. Note, this is not amendment-gated because all writes
// to pseudo-account discriminator fields **are** amendment gated, hence the
// behaviour of this check will always match the active amendments.
if (isPseudoAccount(sleDst))
if (sleDst.isPseudoAccount())
return tecNO_PERMISSION;
// The source account does have enough money. Make sure the

View File

@@ -6,7 +6,6 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h>
#include <xrpl/protocol/Feature.h>
@@ -112,7 +111,7 @@ PaymentChannelCreate::preclaim(PreclaimContext const& ctx)
// writes to pseudo-account discriminator fields **are** amendment
// gated, hence the behaviour of this check will always match the
// currently active amendments.
if (isPseudoAccount(sled))
if (sled.isPseudoAccount())
return tecNO_PERMISSION;
}

View File

@@ -5,7 +5,6 @@
#include <xrpl/ledger/ApplyView.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/DirectoryHelpers.h>
#include <xrpl/ledger/helpers/ProposalHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h>
@@ -169,7 +168,7 @@ TransactionProposalCreate::preclaim(PreclaimContext const& ctx)
}
// A pseudo-account cannot authorize a transaction through a SignerList.
if (isPseudoAccount(sleTarget))
if (sleTarget.isPseudoAccount())
return tecNO_PERMISSION;
// Only the target account itself, an account on its SignerList, or (if

View File

@@ -174,7 +174,7 @@ SponsorshipSet::preclaim(PreclaimContext const& ctx)
return tecNO_DST;
// Pseudo-accounts cannot participate in sponsorship.
if (isPseudoAccount(sponsorAccSle) || isPseudoAccount(sponseeSle))
if (sponsorAccSle.isPseudoAccount() || sponseeSle.isPseudoAccount())
return tecPSEUDO_ACCOUNT;
auto const sponsorshipSle = ctx.view.read(keylet::sponsorship(sponsorID, sponseeID));

View File

@@ -3,7 +3,6 @@
#include <xrpl/beast/utility/Zero.h>
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/TokenHelpers.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/Concepts.h>
@@ -194,7 +193,7 @@ Clawback::preclaim(PreclaimContext const& ctx)
// Note the order of checks - when SAV is active, this check here will make
// the one which follows `sleHolder->isFieldPresent(sfAMMID)` redundant.
if (ctx.view.rules().enabled(featureSingleAssetVault) && isPseudoAccount(sleHolder))
if (ctx.view.rules().enabled(featureSingleAssetVault) && sleHolder.isPseudoAccount())
{
return tecPSEUDO_ACCOUNT;
}

View File

@@ -6,7 +6,6 @@
#include <xrpl/core/ServiceRegistry.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/ledger/entries/AccountRootEntry.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
#include <xrpl/ledger/helpers/SponsorHelpers.h>
#include <xrpl/protocol/AMMCore.h>
@@ -197,7 +196,7 @@ TrustSet::preclaim(PreclaimContext const& ctx)
// enabled in the code section below, for specific cases. This block is not
// amendment-gated because sleDst will not have a pseudo-account designator
// field populated, unless the appropriate amendment was already enabled.
if (sleDst && isPseudoAccount(sleDst))
if (sleDst && sleDst.isPseudoAccount())
{
// If destination is AMM and the trustline doesn't exist then only allow
// TrustSet if the asset is AMM LP token and AMM is not in empty state.

View File

@@ -196,7 +196,7 @@ VaultCreate::doApply()
if (preFeeBalance_ < owner.reserve())
return tecINSUFFICIENT_RESERVE;
auto maybePseudo = createPseudoAccount(view(), vault->key(), sfVaultID);
auto maybePseudo = AccountRootEntryW::createPseudoAccount(view(), vault->key(), sfVaultID);
if (!maybePseudo)
return maybePseudo.error(); // LCOV_EXCL_LINE
auto const& pseudo = *maybePseudo;