mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-06 02:07:07 +00:00
198 lines
6.1 KiB
C++
198 lines
6.1 KiB
C++
#pragma once
|
|
|
|
#include <xrpl/basics/Expected.h>
|
|
#include <xrpl/beast/utility/Journal.h>
|
|
#include <xrpl/beast/utility/instrumentation.h>
|
|
#include <xrpl/ledger/ApplyView.h>
|
|
#include <xrpl/ledger/ReadView.h>
|
|
#include <xrpl/ledger/helpers/SLEBase.h>
|
|
#include <xrpl/protocol/Indexes.h>
|
|
#include <xrpl/protocol/Rate.h>
|
|
#include <xrpl/protocol/STLedgerEntry.h>
|
|
#include <xrpl/protocol/TER.h>
|
|
|
|
#include <memory>
|
|
#include <set>
|
|
#include <vector>
|
|
|
|
namespace xrpl {
|
|
|
|
/**
|
|
* View-parameterized wrapper for AccountRoot ledger entries.
|
|
*
|
|
* AccountRoot<ReadView> — read-only access to account data
|
|
* AccountRoot<ApplyView> — read-write access, with insert/update/erase
|
|
* and domain-specific write methods
|
|
*/
|
|
template <typename ViewT>
|
|
class AccountRoot : public SLEBase<ViewT>
|
|
{
|
|
static constexpr bool kIS_WRITABLE = SLEBase<ViewT>::kIS_WRITABLE;
|
|
|
|
AccountID const id_;
|
|
|
|
public:
|
|
/** Constructor for read-only context */
|
|
AccountRoot(
|
|
AccountID const& id,
|
|
ReadView const& view,
|
|
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
|
|
requires(!kIS_WRITABLE)
|
|
: SLEBase<ViewT>(view.read(keylet::account(id)), view, j), id_(id)
|
|
{
|
|
}
|
|
|
|
/** Constructor for writable context */
|
|
AccountRoot(
|
|
AccountID const& id,
|
|
ApplyView& view,
|
|
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
|
|
requires kIS_WRITABLE
|
|
: SLEBase<ViewT>(keylet::account(id), view, j), id_(id)
|
|
{
|
|
}
|
|
|
|
/** Converting constructor: writable → read-only. */
|
|
template <WritableView OtherViewT>
|
|
AccountRoot(AccountRoot<OtherViewT> const& other)
|
|
requires(!kIS_WRITABLE)
|
|
: SLEBase<ViewT>(other), id_(other.id())
|
|
{
|
|
}
|
|
|
|
/** Create an AccountRoot backed by a brand-new SLE.
|
|
*/
|
|
[[nodiscard]] static AccountRoot
|
|
makeNew(
|
|
AccountID const& id,
|
|
ApplyView& view,
|
|
beast::Journal j = beast::Journal{beast::Journal::getNullSink()})
|
|
requires kIS_WRITABLE
|
|
{
|
|
return AccountRoot(id, view, j, std::make_shared<SLE>(keylet::account(id)));
|
|
}
|
|
|
|
[[nodiscard]] AccountID const&
|
|
id() const
|
|
{
|
|
return id_;
|
|
}
|
|
|
|
// --- Read-only domain methods (available on both specializations) ---
|
|
|
|
/** Check if the issuer has the global freeze flag set.
|
|
@return true if the account has global freeze set
|
|
*/
|
|
[[nodiscard]] bool
|
|
isGlobalFrozen() const;
|
|
|
|
/** Returns IOU issuer transfer fee as Rate. Rate specifies
|
|
* the fee as fractions of 1 billion. For example, 1% transfer rate
|
|
* is represented as 1,010,000,000.
|
|
*/
|
|
[[nodiscard]] Rate
|
|
transferRate() const;
|
|
|
|
// Calculate liquid XRP balance for an account.
|
|
// This function may be used to calculate the amount of XRP that
|
|
// the holder is able to freely spend. It subtracts reserve requirements.
|
|
//
|
|
// 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.
|
|
[[nodiscard]] XRPAmount
|
|
xrpLiquid(std::int32_t ownerCountAdj) const;
|
|
|
|
/** 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(bool hasDestinationTag) const;
|
|
|
|
/** Returns true if and only if sleAcct is a pseudo-account or specific
|
|
pseudo-accounts in pseudoFieldFilter.
|
|
|
|
Returns false if sleAcct is:
|
|
- NOT a pseudo-account OR
|
|
- NOT a ltACCOUNT_ROOT OR
|
|
- null pointer
|
|
*/
|
|
[[nodiscard]] bool
|
|
isPseudoAccount(std::set<SField const*> const& pseudoFieldFilter = {}) const;
|
|
|
|
[[nodiscard]] bool
|
|
operator==(AccountRoot const& other) const
|
|
{
|
|
return id_ == other.id_;
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
operator==(AccountID const& other) const
|
|
{
|
|
return id_ == other;
|
|
}
|
|
|
|
// --- Write-only domain methods (compile-time gated) ---
|
|
|
|
/** Adjust the owner count up or down. */
|
|
void
|
|
adjustOwnerCount(std::int32_t amount)
|
|
requires kIS_WRITABLE;
|
|
|
|
private:
|
|
// Private constructor only used by `makeNew`
|
|
AccountRoot(AccountID const& id, ApplyView& view, beast::Journal j, std::shared_ptr<SLE> sle)
|
|
requires kIS_WRITABLE
|
|
: SLEBase<ViewT>(std::move(sle), view, j), id_(id)
|
|
{
|
|
this->insert();
|
|
}
|
|
};
|
|
|
|
// CTAD deduction guide — bare AccountRoot(id, view) always deduces read-only.
|
|
// For writable access, use WAccountRoot(id, applyView) explicitly.
|
|
AccountRoot(AccountID const&, ReadView const&) -> AccountRoot<ReadView>;
|
|
AccountRoot(AccountID const&, ReadView const&, beast::Journal) -> AccountRoot<ReadView>;
|
|
|
|
// Backward-compatible aliases
|
|
using RAccountRoot = AccountRoot<ReadView>;
|
|
using WAccountRoot = AccountRoot<ApplyView>;
|
|
|
|
// Explicit instantiation declarations (definitions in .cpp)
|
|
extern template class AccountRoot<ReadView>;
|
|
extern template class AccountRoot<ApplyView>;
|
|
|
|
/** Generate a pseudo-account address from a pseudo owner key.
|
|
@param pseudoOwnerKey The key to generate the address from
|
|
@return The generated account ID
|
|
*/
|
|
[[nodiscard]] AccountID
|
|
pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey);
|
|
|
|
/** Returns the list of fields that define an ACCOUNT_ROOT as a pseudo-account
|
|
if set.
|
|
|
|
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.
|
|
*/
|
|
[[nodiscard]] std::vector<SField const*> const&
|
|
getPseudoAccountFields();
|
|
|
|
/**
|
|
* 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]] Expected<std::shared_ptr<SLE>, TER>
|
|
createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const& ownerField);
|
|
|
|
} // namespace xrpl
|