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/helpers/AccountRootHelpers.h>
13#include <xrpl/ledger/helpers/CredentialHelpers.h>
14#include <xrpl/ledger/helpers/DirectoryHelpers.h>
15#include <xrpl/ledger/helpers/MPTokenHelpers.h>
16#include <xrpl/ledger/helpers/RippleStateHelpers.h>
17#include <xrpl/ledger/helpers/TokenHelpers.h>
18#include <xrpl/protocol/AccountID.h>
19#include <xrpl/protocol/Asset.h>
20#include <xrpl/protocol/Feature.h>
21#include <xrpl/protocol/Indexes.h>
22#include <xrpl/protocol/Issue.h>
23#include <xrpl/protocol/Keylet.h>
24#include <xrpl/protocol/LedgerFormats.h>
25#include <xrpl/protocol/MPTIssue.h>
26#include <xrpl/protocol/Protocol.h>
27#include <xrpl/protocol/SField.h>
28#include <xrpl/protocol/STAmount.h>
29#include <xrpl/protocol/STLedgerEntry.h>
30#include <xrpl/protocol/STTx.h>
31#include <xrpl/protocol/TER.h>
32#include <xrpl/protocol/XRPAmount.h>
68 UNREACHABLE(
"xrpl::View::isVaultPseudoAccountFrozen : reached asset check depth");
74 if (mptIssuance ==
nullptr)
77 auto const issuer = mptIssuance->getAccountID(sfIssuer);
84 if (mptIssuance->isFieldPresent(sfReferenceHolding))
86 auto const sleHolding =
91 UNREACHABLE(
"xrpl::isVaultPseudoAccountFrozen : dangling sfReferenceHolding");
96 view, {issuer, account},
assetOfHolding(*mptIssuance, *sleHolding), depth + 1);
100 if (mptIssuer ==
nullptr)
103 UNREACHABLE(
"xrpl::isVaultPseudoAccountFrozen : null MPToken issuer");
108 if (!mptIssuer->isFieldPresent(sfVaultID))
112 if (vault ==
nullptr)
114 UNREACHABLE(
"xrpl::isVaultPseudoAccountFrozen : null vault");
119 return isAnyFrozen(view, {issuer, account}, vault->at(sfAsset), depth + 1);
146 if (hash && (*hash != validLedger.
header().
hash))
148 JLOG(s) << reason <<
" incompatible with valid ledger";
150 JLOG(s) <<
"Hash(VSeq): " <<
to_string(*hash);
160 if (hash && (*hash != testLedger.
header().
hash))
162 JLOG(s) << reason <<
" incompatible preceding ledger";
164 JLOG(s) <<
"Hash(NSeq): " <<
to_string(*hash);
174 JLOG(s) << reason <<
" incompatible ledger";
181 JLOG(s) <<
"Val: " << validLedger.
header().
seq <<
" "
200 if (testLedger.
header().
seq > validIndex)
205 if (hash && (*hash != validHash))
207 JLOG(s) << reason <<
" incompatible following ledger";
208 JLOG(s) <<
"Hash(VSeq): " <<
to_string(*hash);
213 else if ((validIndex == testLedger.
header().
seq) && (testLedger.
header().
hash != validHash))
215 JLOG(s) << reason <<
" incompatible ledger";
222 JLOG(s) <<
"Val: " << validIndex <<
" " <<
to_string(validHash);
237 if (sle->isFieldPresent(sfAmendments))
239 auto const& v = sle->getFieldV256(sfAmendments);
240 amendments.insert(v.begin(), v.end());
254 if (sle->isFieldPresent(sfMajorities))
257 using d = tp::duration;
259 auto const majorities = sle->getFieldArray(sfMajorities);
261 for (
auto const& m : majorities)
262 ret[m.getFieldH256(sfAmendment)] = tp(d(m.getFieldU32(sfCloseTime)));
273 if (seq > ledger.
seq())
275 JLOG(journal.
warn()) <<
"Can't get seq " << seq <<
" from " << ledger.
seq() <<
" future";
278 if (seq == ledger.
seq())
280 if (seq == (ledger.
seq() - 1))
283 if (
int const diff = ledger.
seq() - seq; diff <= 256)
290 hashIndex->getFieldU32(sfLastLedgerSequence) == (ledger.
seq() - 1),
291 "xrpl::hashOfSeq : matching ledger sequence");
292 STVector256 vec = hashIndex->getFieldV256(sfHashes);
293 if (vec.
size() >= diff)
294 return vec[vec.
size() - diff];
295 JLOG(journal.
warn()) <<
"Ledger " << ledger.
seq() <<
" missing hash for " << seq <<
" ("
296 << vec.
size() <<
"," << diff <<
")";
301 <<
" missing normal list";
305 if ((seq & 0xff) != 0)
307 JLOG(journal.
debug()) <<
"Can't get seq " << seq <<
" from " << ledger.
seq() <<
" past";
315 auto const lastSeq = hashIndex->getFieldU32(sfLastLedgerSequence);
316 XRPL_ASSERT(lastSeq >= seq,
"xrpl::hashOfSeq : minimum last ledger");
317 XRPL_ASSERT((lastSeq & 0xff) == 0,
"xrpl::hashOfSeq : valid last ledger");
318 auto const diff = (lastSeq - seq) >> 8;
319 STVector256 vec = hashIndex->getFieldV256(sfHashes);
320 if (vec.
size() > diff)
321 return vec[vec.
size() - diff - 1];
323 JLOG(journal.
warn()) <<
"Can't get seq " << seq <<
" from " << ledger.
seq() <<
" error";
340 object->setFieldU64(node, *page);
368 if (from == to || to == issuer ||
isXRP(issuer))
373 auto const& currency = issue.
currency;
375 if (owed <= beast::kZero)
377 auto const limit =
creditLimit(view, to, issuer, currency);
378 if (-owed >= limit || amount > (limit + owed))
393 bool hasDestinationTag)
401 if (toSle->isFlag(lsfDepositAuth))
416 bool hasDestinationTag)
420 return canWithdraw(view, from, to, toSle, amount, hasDestinationTag);
426 auto const from = tx[sfAccount];
427 auto const to = tx[~sfDestination].value_or(from);
444 if (dstAcct == senderAcct)
467 JLOG(j.
error()) <<
"doWithdraw: negative balance of broker cover assets.";
480 Keylet const& ownerDirKeylet,
487 unsigned int uDirEntry{0};
488 uint256 dirEntry{beast::kZero};
491 if (view.
exists(ownerDirKeylet) &&
492 dirFirst(view, ownerDirKeylet.
key, sleDirNode, uDirEntry, dirEntry))
496 if (maxNodesToDelete && ++deleted > *maxNodesToDelete)
505 JLOG(j.
fatal()) <<
"DeleteAccount: Directory node in ledger " << view.
seq()
506 <<
" has index to object that is missing: " <<
to_string(dirEntry);
516 auto const [ter, skipEntry] = deleter(nodeType, dirEntry, sleItem);
536 XRPL_ASSERT(uDirEntry >= 1,
"xrpl::cleanupOnAccountDelete : minimum dir entries");
540 JLOG(j.
error()) <<
"DeleteAccount iterator re-validation failed.";
547 }
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.
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.
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 & const_ref
bool isFieldPresent(SField const &field) const
Keylet const & skip() noexcept
The index of the "short" skip list.
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Keylet mptokenIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
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 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.
TypedField< STInteger< std::uint64_t > > SF_UINT64
bool isXRP(AccountID const &c)
std::set< uint256 > getEnabledAmendments(ReadView const &view)
std::uint32_t LedgerIndex
A ledger index.
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)
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safeCast(Src s) noexcept
bool dirNext(ApplyView &view, uint256 const &root, SLE::pointer &page, unsigned int &index, uint256 &entry)
Asset assetOfHolding(SLE const &sleShareIssuance, SLE const &sleHolding)
Resolve the underlying asset of a vault share.
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.
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,...
std::optional< uint256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
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)
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.
bool isFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptIssue, std::uint8_t depth=0)
std::map< uint256, NetClock::time_point > majorityAmendments_t
TER accountSend(ApplyView &view, AccountID const &from, AccountID const &to, STAmount const &saAmount, beast::Journal j, WaiveTransferFee waiveFee=WaiveTransferFee::No, AllowMPTOverflow allowOverflow=AllowMPTOverflow::No)
Calls static accountSendIOU if saAmount represents Issue.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
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)
std::function< std::pair< TER, SkipEntry >(LedgerEntryType, uint256 const &, SLE::pointer &)> EntryDeleter
Deleter function prototype.
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 dirFirst(ApplyView &view, uint256 const &root, SLE::pointer &page, unsigned int &index, uint256 &entry)
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.
TER verifyDepositPreauth(STTx const &tx, ApplyView &view, AccountID const &src, AccountID const &dst, SLE::const_ref sleDst, beast::Journal j)
A pair of SHAMap key and LedgerEntryType.
T time_since_epoch(T... args)