Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions include/xrpl/ledger/helpers/AccountRootHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <cstdint>
#include <expected>
#include <optional>
#include <set>
#include <vector>

namespace xrpl {
Expand Down Expand Up @@ -353,33 +352,30 @@ pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey);
*
* The list is constructed during initialization and is const after that.
* Pseudo-account designator fields MUST be maintained by including the
* SField::sMD_PseudoAccount flag in the SField definition.
* SField::kSmdPseudoAccount flag in the SField definition.
*/
[[nodiscard]] std::vector<SField const*> const&
getPseudoAccountFields();

/**
* Returns true if and only if sleAcct is a pseudo-account or specific
* pseudo-accounts in pseudoFieldFilter.
* 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(SLE::const_pointer sleAcct, std::set<SField const*> const& pseudoFieldFilter = {});
isPseudoAccount(SLE::const_pointer sleAcct);

/**
* Convenience overload that reads the account from the view.
*/
[[nodiscard]] inline bool
isPseudoAccount(
ReadView const& view,
AccountID const& accountId,
std::set<SField const*> const& pseudoFieldFilter = {})
isPseudoAccount(ReadView const& view, AccountID const& accountId)
{
return isPseudoAccount(view.read(keylet::account(accountId)), pseudoFieldFilter);
return isPseudoAccount(view.read(keylet::account(accountId)));
}

/**
Expand Down
15 changes: 5 additions & 10 deletions src/libxrpl/ledger/helpers/AccountRootHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#include <limits>
#include <memory>
#include <optional>
#include <set>
#include <stdexcept>
#include <vector>

Expand Down Expand Up @@ -515,7 +514,7 @@ pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey)
}

// Pseudo-account designator fields MUST be maintained by including the
// SField::sMD_PseudoAccount flag in the SField definition. (Don't forget to
// SField::kSmdPseudoAccount flag in the SField definition. (Don't forget to
// "| SField::sMD_Default"!) The fields do NOT need to be amendment-gated,
Comment thread
Copilot marked this conversation as resolved.
Outdated
// since a non-active amendment will not set any field, by definition.
// Specific properties of a pseudo-account are NOT checked here, that's what
Expand Down Expand Up @@ -547,18 +546,14 @@ getPseudoAccountFields()
}

[[nodiscard]] bool
isPseudoAccount(SLE::const_pointer sleAcct, std::set<SField const*> const& pseudoFieldFilter)
isPseudoAccount(SLE::const_pointer sleAcct)
{
auto const& fields = getPseudoAccountFields();

// 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::count_if(
fields.begin(), fields.end(), [&sleAcct, &pseudoFieldFilter](SField const* sf) -> bool {
return sleAcct->isFieldPresent(*sf) &&
(pseudoFieldFilter.empty() || pseudoFieldFilter.contains(sf));
Comment thread
mvadari marked this conversation as resolved.
}) > 0;
std::ranges::any_of(getPseudoAccountFields(), [&sleAcct](SField const* sf) {
return sleAcct->isFieldPresent(*sf);
});
}

std::expected<SLE::pointer, TER>
Expand Down
3 changes: 1 addition & 2 deletions src/libxrpl/ledger/helpers/MPTokenHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,7 @@ requireAuth(
// They are implicitly authorized for any MPT they hold, including vault shares whose
// underlying asset would otherwise require auth.
auto const isPseudoAccountExempt = [&] {
return (featureSAVEnabled || featureMPTV2Enabled) &&
isPseudoAccount(view, account, {&sfVaultID, &sfLoanBrokerID, &sfAMMID});
return (featureSAVEnabled || featureMPTV2Enabled) && isPseudoAccount(view, account);
};

auto const mptID = keylet::mptokenIssuance(mptIssue.getMptID());
Expand Down
2 changes: 1 addition & 1 deletion src/libxrpl/tx/invariants/MPTInvariant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ ValidMPTTransfer::isAuthorized(
// auth. Exempt them here rather than relying on requireAuth: the recursive
// share -> underlying descent in requireAuth fails for a pseudo-account
// that holds the share but not the underlying.
if (isPseudoAccount(view, holder, {&sfVaultID, &sfLoanBrokerID, &sfAMMID}))
if (isPseudoAccount(view, holder))
return true;

auto const key = keylet::mptoken(mptid, holder);
Expand Down
2 changes: 1 addition & 1 deletion src/libxrpl/tx/transactors/token/MPTokenAuthorize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ MPTokenAuthorize::preclaim(PreclaimContext const& ctx)
// always authorized. No need to amendment gate since Vault and LoanBroker
// can only be created if the Vault amendment is enabled; AMM with MPToken asset
// can only be created if MPTokensV2 is enabled.
if (isPseudoAccount(ctx.view, *holderID, {&sfVaultID, &sfLoanBrokerID, &sfAMMID}))
if (isPseudoAccount(ctx.view, *holderID))
Comment thread
ximinez marked this conversation as resolved.
return tecNO_PERMISSION;

return tesSUCCESS;
Expand Down
Loading