1#include <xrpl/basics/Expected.h>
2#include <xrpl/basics/Log.h>
3#include <xrpl/basics/chrono.h>
4#include <xrpl/beast/utility/instrumentation.h>
5#include <xrpl/ledger/ReadView.h>
6#include <xrpl/ledger/View.h>
7#include <xrpl/ledger/helpers/AccountRootHelpers.h>
8#include <xrpl/ledger/helpers/CredentialHelpers.h>
9#include <xrpl/ledger/helpers/DirectoryHelpers.h>
10#include <xrpl/ledger/helpers/RippleStateHelpers.h>
11#include <xrpl/protocol/Feature.h>
12#include <xrpl/protocol/Indexes.h>
13#include <xrpl/protocol/LedgerFormats.h>
14#include <xrpl/protocol/MPTIssue.h>
15#include <xrpl/protocol/Protocol.h>
16#include <xrpl/protocol/Quality.h>
17#include <xrpl/protocol/TER.h>
18#include <xrpl/protocol/TxFlags.h>
19#include <xrpl/protocol/digest.h>
20#include <xrpl/protocol/st.h>
56 if (mptIssuance ==
nullptr)
59 auto const issuer = mptIssuance->getAccountID(sfIssuer);
61 if (mptIssuer ==
nullptr)
64 UNREACHABLE(
"xrpl::isVaultPseudoAccountFrozen : null MPToken issuer");
69 if (!mptIssuer->isFieldPresent(sfVaultID))
75 UNREACHABLE(
"xrpl::isVaultPseudoAccountFrozen : null vault");
80 return isAnyFrozen(view, {issuer, account}, vault->at(sfAsset), depth + 1);
108 if (hash && (*hash != validLedger.
header().
hash))
110 JLOG(s) << reason <<
" incompatible with valid ledger";
112 JLOG(s) <<
"Hash(VSeq): " <<
to_string(*hash);
122 if (hash && (*hash != testLedger.
header().
hash))
124 JLOG(s) << reason <<
" incompatible preceding ledger";
126 JLOG(s) <<
"Hash(NSeq): " <<
to_string(*hash);
136 JLOG(s) << reason <<
" incompatible ledger";
143 JLOG(s) <<
"Val: " << validLedger.
header().
seq <<
" "
162 if (testLedger.
header().
seq > validIndex)
167 if (hash && (*hash != validHash))
169 JLOG(s) << reason <<
" incompatible following ledger";
170 JLOG(s) <<
"Hash(VSeq): " <<
to_string(*hash);
175 else if ((validIndex == testLedger.
header().
seq) && (testLedger.
header().
hash != validHash))
177 JLOG(s) << reason <<
" incompatible ledger";
184 JLOG(s) <<
"Val: " << validIndex <<
" " <<
to_string(validHash);
199 if (sle->isFieldPresent(sfAmendments))
201 auto const& v = sle->getFieldV256(sfAmendments);
202 amendments.insert(v.begin(), v.end());
216 if (sle->isFieldPresent(sfMajorities))
219 using d = tp::duration;
221 auto const majorities = sle->getFieldArray(sfMajorities);
223 for (
auto const& m : majorities)
224 ret[m.getFieldH256(sfAmendment)] = tp(d(m.getFieldU32(sfCloseTime)));
235 if (seq > ledger.
seq())
237 JLOG(journal.
warn()) <<
"Can't get seq " << seq <<
" from " << ledger.
seq() <<
" future";
240 if (seq == ledger.
seq())
242 if (seq == (ledger.
seq() - 1))
245 if (
int const diff = ledger.
seq() - seq; diff <= 256)
252 hashIndex->getFieldU32(sfLastLedgerSequence) == (ledger.
seq() - 1),
253 "xrpl::hashOfSeq : matching ledger sequence");
254 STVector256 vec = hashIndex->getFieldV256(sfHashes);
255 if (vec.
size() >= diff)
256 return vec[vec.
size() - diff];
257 JLOG(journal.
warn()) <<
"Ledger " << ledger.
seq() <<
" missing hash for " << seq <<
" ("
258 << vec.
size() <<
"," << diff <<
")";
263 <<
" missing normal list";
267 if ((seq & 0xff) != 0)
269 JLOG(journal.
debug()) <<
"Can't get seq " << seq <<
" from " << ledger.
seq() <<
" past";
277 auto const lastSeq = hashIndex->getFieldU32(sfLastLedgerSequence);
278 XRPL_ASSERT(lastSeq >= seq,
"xrpl::hashOfSeq : minimum last ledger");
279 XRPL_ASSERT((lastSeq & 0xff) == 0,
"xrpl::hashOfSeq : valid last ledger");
280 auto const diff = (lastSeq - seq) >> 8;
281 STVector256 vec = hashIndex->getFieldV256(sfHashes);
282 if (vec.
size() > diff)
283 return vec[vec.
size() - diff - 1];
285 JLOG(journal.
warn()) <<
"Can't get seq " << seq <<
" from " << ledger.
seq() <<
" error";
306 object->setFieldU64(node, *page);
333 auto const& issuer = amount.getIssuer();
334 if (from == to || to == issuer ||
isXRP(issuer))
341 auto const& currency = issue.currency;
343 if (owed <= beast::zero)
345 auto const limit =
creditLimit(view, to, issuer, currency);
346 if (-owed >= limit || amount > (limit + owed))
352 amount.asset().value());
362 bool hasDestinationTag)
370 if (toSle->isFlag(lsfDepositAuth))
385 bool hasDestinationTag)
389 return canWithdraw(view, from, to, toSle, amount, hasDestinationTag);
395 auto const from = tx[sfAccount];
396 auto const to = tx[~sfDestination].value_or(from);
413 if (dstAcct == senderAcct)
415 if (
auto const ter =
addEmptyHolding(view, senderAcct, priorBalance, amount.asset(), j);
436 JLOG(j.
error()) <<
"doWithdraw: negative balance of broker cover assets.";
449 Keylet const& ownerDirKeylet,
456 unsigned int uDirEntry{0};
460 if (view.
exists(ownerDirKeylet) &&
461 dirFirst(view, ownerDirKeylet.
key, sleDirNode, uDirEntry, dirEntry))
465 if (maxNodesToDelete && ++deleted > *maxNodesToDelete)
474 JLOG(j.
fatal()) <<
"DeleteAccount: Directory node in ledger " << view.
seq()
475 <<
" has index to object that is missing: " <<
to_string(dirEntry);
481 safe_cast<LedgerEntryType>(sleItem->getFieldU16(sfLedgerEntryType))};
485 auto const [ter, skipEntry] = deleter(nodeType, dirEntry, sleItem);
505 XRPL_ASSERT(uDirEntry >= 1,
"xrpl::cleanupOnAccountDelete : minimum dir entries");
509 JLOG(j.
error()) <<
"DeleteAccount iterator re-validation failed.";
516 }
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.
Writeable view to a ledger, for applying a transaction.
std::optional< std::uint64_t > dirInsert(Keylet const &directory, uint256 const &key, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Insert an entry to a directory.
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
A currency issued by an account.
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 LedgerHeader const & header() const =0
Returns information about the ledger.
LedgerIndex seq() const
Returns the sequence number of the base ledger.
virtual std::shared_ptr< SLE const > read(Keylet const &k) const =0
Return the state item associated with a key.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
bool isFieldPresent(SField const &field) const
Keylet const & skip() noexcept
The index of the "short" skip list.
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Keylet const & amendments() noexcept
The index of the amendment table.
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Keylet mptIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Keylet account(AccountID const &id) noexcept
AccountID root.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool dirFirst(ApplyView &view, uint256 const &root, std::shared_ptr< SLE > &page, unsigned int &index, uint256 &entry)
bool isXRP(AccountID const &c)
std::uint8_t constexpr maxAssetCheckDepth
Maximum recursion depth for vault shares being put as an asset inside another vault; counted from 0.
std::map< uint256, NetClock::time_point > majorityAmendments_t
std::set< uint256 > getEnabledAmendments(ReadView const &view)
bool isVaultPseudoAccountFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptShare, int depth)
std::string to_string(base_uint< Bits, Tag > const &a)
TER verifyDepositPreauth(STTx const &tx, ApplyView &view, AccountID const &src, AccountID const &dst, std::shared_ptr< SLE const > const &sleDst, beast::Journal j)
TER doWithdraw(ApplyView &view, STTx const &tx, AccountID const &senderAcct, AccountID const &dstAcct, AccountID const &sourceAcct, XRPAmount priorBalance, STAmount const &amount, beast::Journal j)
bool hasExpired(ReadView const &view, std::optional< std::uint32_t > const &exp)
Determines whether the given expiration time has passed.
TER addEmptyHolding(ApplyView &view, AccountID const &accountID, XRPAmount priorBalance, MPTIssue const &mptIssue, beast::Journal journal)
bool isAnyFrozen(ReadView const &view, std::initializer_list< AccountID > const &accounts, MPTIssue const &mptIssue, int depth=0)
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=shSIMPLE_BALANCE)
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.
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 accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No)
Calls static accountSendIOU if saAmount represents Issue.
bool isFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptIssue, int depth=0)
std::optional< uint256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
TERSubset< CanCvtToTER > TER
static TER withdrawToDestExceedsLimit(ReadView const &view, AccountID const &from, AccountID const &to, STAmount const &amount)
majorityAmendments_t getMajorityAmendments(ReadView const &view)
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::function< void(SLE::ref)> describeOwnerDir(AccountID const &account)
Returns a function that sets the owner on a directory SLE.
TER dirLink(ApplyView &view, AccountID const &owner, std::shared_ptr< SLE > &object, SF_UINT64 const &node=sfOwnerNode)
bool isTesSuccess(TER x) noexcept
LedgerEntryType
Identifiers for on-ledger objects.
TER canWithdraw(ReadView const &view, AccountID const &from, AccountID const &to, SLE::const_ref toSle, STAmount const &amount, bool hasDestinationTag)
Checks that can withdraw funds from an object to itself or a destination.
TER checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag)
Checks the destination and tag.
bool isLPTokenFrozen(ReadView const &view, AccountID const &account, Issue const &asset, Issue const &asset2)
bool dirNext(ApplyView &view, uint256 const &root, std::shared_ptr< SLE > &page, unsigned int &index, uint256 &entry)
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.
A pair of SHAMap key and LedgerEntryType.
A field with a type known at compile time.
T time_since_epoch(T... args)