1#include <xrpl/ledger/View.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/base_uint.h>
5#include <xrpl/basics/chrono.h>
6#include <xrpl/basics/safe_cast.h>
7#include <xrpl/beast/utility/Journal.h>
8#include <xrpl/beast/utility/Zero.h>
9#include <xrpl/beast/utility/instrumentation.h>
10#include <xrpl/ledger/ApplyView.h>
11#include <xrpl/ledger/ReadView.h>
12#include <xrpl/ledger/entries/AmendmentsEntry.h>
13#include <xrpl/ledger/entries/LedgerHashesEntry.h>
14#include <xrpl/ledger/helpers/AccountRootHelpers.h>
15#include <xrpl/ledger/helpers/CredentialHelpers.h>
16#include <xrpl/ledger/helpers/DirectoryHelpers.h>
17#include <xrpl/ledger/helpers/MPTokenHelpers.h>
18#include <xrpl/ledger/helpers/RippleStateHelpers.h>
19#include <xrpl/ledger/helpers/SponsorHelpers.h>
20#include <xrpl/ledger/helpers/TokenHelpers.h>
21#include <xrpl/protocol/AccountID.h>
22#include <xrpl/protocol/Asset.h>
23#include <xrpl/protocol/Feature.h>
24#include <xrpl/protocol/Indexes.h>
25#include <xrpl/protocol/Issue.h>
26#include <xrpl/protocol/Keylet.h>
27#include <xrpl/protocol/LedgerFormats.h>
28#include <xrpl/protocol/MPTIssue.h>
29#include <xrpl/protocol/Protocol.h>
30#include <xrpl/protocol/SField.h>
31#include <xrpl/protocol/STAmount.h>
32#include <xrpl/protocol/STLedgerEntry.h>
33#include <xrpl/protocol/STTx.h>
34#include <xrpl/protocol/TER.h>
35#include <xrpl/protocol/XRPAmount.h>
61 auto const boundary = Tp{D{*exp}};
70checkVaultPseudoAccountFrozenPreconditions(ReadView
const& view,
std::uint8_t depth)
72 if (!view.rules().enabled(featureSingleAssetVault))
79 "xrpl::View::checkVaultPseudoAccountFrozenPreconditions : reached asset check depth");
88isVaultPseudoAccountFrozenForIssuance(
91 SLE const& issuanceSle,
95 issuanceSle.getType() == ltMPTOKEN_ISSUANCE,
96 "xrpl::isVaultPseudoAccountFrozenForIssuance : MPTokenIssuance SLE");
98 auto const issuer = issuanceSle.getAccountID(sfIssuer);
105 if (issuanceSle.isFieldPresent(sfReferenceHolding))
107 auto const sleHolding =
112 UNREACHABLE(
"xrpl::isVaultPseudoAccountFrozen : dangling sfReferenceHolding");
121 if (mptIssuer ==
nullptr)
124 UNREACHABLE(
"xrpl::isVaultPseudoAccountFrozen : null MPToken issuer");
129 if (!mptIssuer->isFieldPresent(sfVaultID))
133 if (vault ==
nullptr)
135 UNREACHABLE(
"xrpl::isVaultPseudoAccountFrozen : null vault");
149 SLE const& issuanceSle,
152 if (
auto const result = checkVaultPseudoAccountFrozenPreconditions(view, depth))
155 return isVaultPseudoAccountFrozenForIssuance(view, account, issuanceSle, depth);
165 if (
auto const result = checkVaultPseudoAccountFrozenPreconditions(view, depth))
169 if (issuanceSle ==
nullptr)
172 return isVaultPseudoAccountFrozenForIssuance(view, account, *issuanceSle, depth);
195 if (!sleIssuer || !sleIssuer->isFieldPresent(sfAMMID))
202 auto const transferable = [&](
Asset const& a) ->
TER {
207 if (
auto const err = transferable((*sleAmm)[sfAsset]); !
isTesSuccess(err))
209 return transferable((*sleAmm)[sfAsset2]);
226 if (hash && (*hash != validLedger.
header().
hash))
228 JLOG(s) << reason <<
" incompatible with valid ledger";
230 JLOG(s) <<
"Hash(VSeq): " <<
to_string(*hash);
240 if (hash && (*hash != testLedger.
header().
hash))
242 JLOG(s) << reason <<
" incompatible preceding ledger";
244 JLOG(s) <<
"Hash(NSeq): " <<
to_string(*hash);
254 JLOG(s) << reason <<
" incompatible ledger";
261 JLOG(s) <<
"Val: " << validLedger.
header().
seq <<
" "
280 if (testLedger.
header().
seq > validIndex)
285 if (hash && (*hash != validHash))
287 JLOG(s) << reason <<
" incompatible following ledger";
288 JLOG(s) <<
"Hash(VSeq): " <<
to_string(*hash);
293 else if ((validIndex == testLedger.
header().
seq) && (testLedger.
header().
hash != validHash))
295 JLOG(s) << reason <<
" incompatible ledger";
302 JLOG(s) <<
"Val: " << validIndex <<
" " <<
to_string(validHash);
326 if (seq > ledger.
seq())
328 JLOG(journal.
warn()) <<
"Can't get seq " << seq <<
" from " << ledger.
seq() <<
" future";
331 if (seq == ledger.
seq())
333 if (seq == (ledger.
seq() - 1))
336 if (
int const diff = ledger.
seq() - seq; diff <= 256)
343 hashIndex->
getFieldU32(sfLastLedgerSequence) == (ledger.
seq() - 1),
344 "xrpl::hashOfSeq : matching ledger sequence");
345 if (
auto const hash = hashIndex.
hashAt(diff - 1))
347 JLOG(journal.
warn()) <<
"Ledger " << ledger.
seq() <<
" missing hash for " << seq <<
" ("
353 <<
" missing normal list";
357 if ((seq & 0xff) != 0)
359 JLOG(journal.
debug()) <<
"Can't get seq " << seq <<
" from " << ledger.
seq() <<
" past";
367 auto const lastSeq = hashIndex->
getFieldU32(sfLastLedgerSequence);
368 XRPL_ASSERT(lastSeq >= seq,
"xrpl::hashOfSeq : minimum last ledger");
369 XRPL_ASSERT((lastSeq & 0xff) == 0,
"xrpl::hashOfSeq : valid last ledger");
370 if (
auto const hash = hashIndex.
hashAt((lastSeq - seq) >> 8))
373 JLOG(journal.
warn()) <<
"Can't get seq " << seq <<
" from " << ledger.
seq() <<
" error";
390 object->setFieldU64(node, *page);
418 if (from == to || to == issuer ||
isXRP(issuer))
423 auto const& currency = issue.
currency;
427 auto const limit =
creditLimit(view, to, issuer, currency);
428 if (-owed >= limit || amount > (limit + owed))
443 bool hasDestinationTag,
452 if (toSle->isFlag(lsfDepositAuth))
456 if (credentialIDs.has_value())
462 for (
auto const& h : credIDs)
488 bool hasDestinationTag,
493 return canWithdraw(view, from, to, toSle, amount, hasDestinationTag, credentialIDs);
499 auto const from = tx[sfAccount];
500 auto const to = tx[~sfDestination].value_or(from);
503 view, from, to, tx[sfAmount], tx.
isFieldPresent(sfDestinationTag), tx[~sfCredentialIDs]);
523 if (dstAcct == senderAcct)
548 JLOG(j.
error()) <<
"doWithdraw: negative balance of broker cover assets.";
559 return sponsorSle.error();
570 Keylet const& ownerDirKeylet,
577 unsigned int uDirEntry{0};
581 if (view.
exists(ownerDirKeylet) &&
582 dirFirst(view, ownerDirKeylet.
key, sleDirNode, uDirEntry, dirEntry))
586 if (maxNodesToDelete && ++deleted > *maxNodesToDelete)
595 JLOG(j.
fatal()) <<
"DeleteAccount: Directory node in ledger " << view.
seq()
596 <<
" has index to object that is missing: " <<
to_string(dirEntry);
606 auto const [ter, skipEntry] = deleter(nodeType, dirEntry, sleItem);
626 XRPL_ASSERT(uDirEntry >= 1,
"xrpl::cleanupOnAccountDelete : minimum dir entries");
630 JLOG(j.
error()) <<
"DeleteAccount iterator re-validation failed.";
637 }
while (
dirNext(view, ownerDirKeylet.
key, sleDirNode, uDirEntry, dirEntry));
Provide a light-weight way to check active() before string formatting.
A generic endpoint for log messages.
static Sink & getNullSink()
Returns a Sink which does nothing.
std::set< UInt256 > enabledAmendments() const
Returns the set of amendments this entry reports as enabled.
std::map< UInt256, NetClock::time_point > majorityAmendments() const
Returns a map of amendments that have achieved majority, to the time majority was reached.
Writeable view to a ledger, for applying a transaction.
virtual SLE::pointer peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
std::optional< std::uint64_t > dirInsert(Keylet const &directory, UInt256 const &key, std::function< void(SLE::Ref)> const &describe)
Insert an entry to a directory.
constexpr auto visit(Visitors &&... visitors) const -> decltype(auto)
A currency issued by an account.
std::optional< UInt256 > hashAt(std::size_t diff) const
Looks up a hash diff slots back from the most recent entry in the sfHashes vector (diff == 0 is the m...
constexpr MPTID const & getMptID() const
std::chrono::time_point< NetClock > time_point
std::chrono::duration< rep, period > duration
virtual Rules const & rules() const =0
Returns the tx processing rules.
NetClock::time_point parentCloseTime() const
Returns the close time of the previous ledger.
virtual bool exists(Keylet const &k) const =0
Determine if a state item exists.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
virtual LedgerHeader const & header() const =0
Returns information about the ledger.
LedgerIndex seq() const
Returns the sequence number of the base ledger.
bool enabled(UInt256 const &feature) const
Returns true if a feature is enabled.
Asset const & asset() const
AccountID const & getIssuer() const
UInt256 const & key() const
Returns the 'key' (or 'index') of this item.
std::shared_ptr< STLedgerEntry > pointer
std::shared_ptr< STLedgerEntry const > const & ConstRef
std::uint32_t getFieldU32(SField const &field) const
bool isFieldPresent(SField const &field) const
STVector256 const & getFieldV256(SField const &field) const
TER authorizedDepositPreauth(ReadView const &view, STVector256 const &ctx, AccountID const &dst)
Keylet const & skip() noexcept
The index of the "short" skip list.
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Keylet unchecked(UInt256 const &key) noexcept
Any ledger entry.
Keylet vault(AccountID const &owner, SeqProxy const &seq) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet credential(AccountID const &subject, AccountID const &issuer, Slice const &credType) noexcept
Keylet child(UInt256 const &key) noexcept
Any item that can be in an owner dir.
Keylet mptokenIssuance(MPTID const &issuanceID) noexcept
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::optional< UInt256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
bool hasExpired(ReadView const &view, std::optional< std::uint32_t > const &exp, ExpiryComparison comparison=ExpiryComparison::Inclusive)
Determines whether the given expiration time has passed.
TypedField< STInteger< std::uint64_t > > SF_UINT64
bool isXRP(AccountID const &c)
std::uint32_t LedgerIndex
A ledger index.
std::set< UInt256 > getEnabledAmendments(ReadView const &view)
TER checkDestinationAndTag(SLE::ConstRef toSle, bool hasDestinationTag)
Checks the destination and tag.
bool dirNext(ApplyView &view, UInt256 const &root, SLE::pointer &page, unsigned int &index, UInt256 &entry)
TER addEmptyHolding(ApplyViewContext ctx, AccountID const &accountID, XRPAmount priorBalance, MPTIssue const &mptIssue, beast::Journal journal)
ExpiryComparison
Whether an expiration check should be inclusive or exclusive.
Asset assetOfHolding(SLE const &sleShareIssuance, SLE const &sleHolding)
Resolve the underlying asset of a vault share.
std::expected< SLE::pointer, TER > getEffectiveTxReserveSponsor(ApplyViewContext ctx, SLE::ConstRef accountSle)
The transaction's reserve sponsor for the given account, if applicable.
TER canTransfer(ReadView const &view, MPTIssue const &mptIssue, AccountID const &from, AccountID const &to, WaiveMPTCanTransfer waive=WaiveMPTCanTransfer::No, std::uint8_t depth=0)
Check whether to may receive the given MPT from from.
STAmount creditLimit(ReadView const &view, AccountID const &account, AccountID const &issuer, Currency const ¤cy)
Calculate the maximum amount of IOUs that an account can hold.
constexpr Dest safeCast(Src s) noexcept
std::string to_string(BaseUInt< Bits, Tag > const &a)
bool isVaultPseudoAccountFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptShare, std::uint8_t depth)
bool areCompatible(ReadView const &validLedger, ReadView const &testLedger, beast::Journal::Stream &s, char const *reason)
Return false if the test ledger is provably incompatible with the valid ledger, that is,...
TER doWithdraw(ApplyViewContext ctx, AccountID const &senderAcct, AccountID const &dstAcct, AccountID const &sourceAcct, XRPAmount priorBalance, STAmount const &amount, beast::Journal j)
TER canTransferLPToken(ReadView const &view, AccountID const &from, AccountID const &to, AccountID const &lpTokenIssuer)
Check whether an AMM LPToken may be transferred between from and to.
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, SLE::Ref sponsorSle={}, WaiveTransferFee waiveFee=WaiveTransferFee::No, AllowMPTOverflow allowOverflow=AllowMPTOverflow::No)
Calls static accountSendIOU if saAmount represents Issue.
bool dirFirst(ApplyView &view, UInt256 const &root, SLE::pointer &page, unsigned int &index, UInt256 &entry)
constexpr std::uint8_t kMaxAssetCheckDepth
Maximum recursion depth for vault shares being put as an asset inside another vault; counted from 0.
TER dirLink(ApplyView &view, AccountID const &owner, SLE::pointer &object, SF_UINT64 const &node=sfOwnerNode)
static TER withdrawToDestExceedsLimit(ReadView const &view, AccountID const &from, AccountID const &to, STAmount const &amount)
TER canWithdraw(ReadView const &view, AccountID const &from, AccountID const &to, SLE::ConstRef toSle, STAmount const &amount, bool hasDestinationTag, std::optional< std::vector< UInt256 > > const &credentialIDs=std::nullopt)
Checks that can withdraw funds from an object to itself or a destination.
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
STAmount creditBalance(ReadView const &view, AccountID const &account, AccountID const &issuer, Currency const ¤cy)
Returns the amount of IOUs issued by issuer that are held by an account.
std::map< UInt256, NetClock::time_point > MajorityAmendmentsT
bool isFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptIssue, std::uint8_t depth=0)
Returns true if account cannot send or receive tokens of mptIssue because a freeze applies.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
std::function< std::pair< TER, SkipEntry >(LedgerEntryType, UInt256 const &, SLE::pointer &)> EntryDeleter
Deleter function prototype.
bool isTesSuccess(TER x) noexcept
bool isAnyFrozen(ReadView const &view, std::initializer_list< AccountID > const &accounts, MPTIssue const &mptIssue, std::uint8_t depth=0)
TERSubset< CanCvtToTER > TER
bool isLPTokenFrozen(ReadView const &view, AccountID const &account, Asset const &asset, Asset const &asset2)
LedgerEntryType
Identifiers for on-ledger objects.
LedgerHashesEntry< ReadView > LedgerHashesEntryR
TER verifyDepositPreauth(STTx const &tx, ApplyView &view, AccountID const &src, AccountID const &dst, SLE::ConstRef sleDst, beast::Journal j)
std::function< void(SLE::Ref)> describeOwnerDir(AccountID const &account)
Returns a function that sets the owner on a directory SLE.
MajorityAmendmentsT getMajorityAmendments(ReadView const &view)
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=SpendableHandling::SimpleBalance)
TER cleanupOnAccountDelete(ApplyView &view, Keylet const &ownerDirKeylet, EntryDeleter const &deleter, beast::Journal j, std::optional< std::uint16_t > maxNodesToDelete=std::nullopt)
Cleanup owner directory entries on account delete.
AmendmentsEntry< ReadView > AmendmentsEntryR
Bundles the mutable ledger view and the transaction being applied.
A pair of SHAMap key and LedgerEntryType.
T time_since_epoch(T... args)