xrpld
Loading...
Searching...
No Matches
View.cpp
1#include <xrpl/ledger/View.h>
2
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>
36
37#include <cstdint>
38#include <optional>
39#include <set>
40#include <vector>
41
42namespace xrpl {
43
44//------------------------------------------------------------------------------
45//
46// Observers
47//
48//------------------------------------------------------------------------------
49
50bool
52 ReadView const& view,
54 ExpiryComparison comparison)
55{
56 using D = NetClock::duration;
57 using Tp = NetClock::time_point;
58
59 if (!exp)
60 return false;
61 auto const boundary = Tp{D{*exp}};
62 return comparison == ExpiryComparison::Inclusive //
63 ? view.parentCloseTime() >= boundary
64 : view.parentCloseTime() > boundary;
65}
66
67namespace {
68
70checkVaultPseudoAccountFrozenPreconditions(ReadView const& view, std::uint8_t depth)
71{
72 if (!view.rules().enabled(featureSingleAssetVault))
73 return false;
74
75 if (depth >= kMaxAssetCheckDepth)
76 {
77 // LCOV_EXCL_START
78 UNREACHABLE(
79 "xrpl::View::checkVaultPseudoAccountFrozenPreconditions : reached asset check depth");
80 return true;
81 // LCOV_EXCL_STOP
82 }
83
84 return std::nullopt;
85}
86
87bool
88isVaultPseudoAccountFrozenForIssuance(
89 ReadView const& view,
90 AccountID const& account,
91 SLE const& issuanceSle,
92 std::uint8_t depth)
93{
94 XRPL_ASSERT(
95 issuanceSle.getType() == ltMPTOKEN_ISSUANCE,
96 "xrpl::isVaultPseudoAccountFrozenForIssuance : MPTokenIssuance SLE");
97
98 auto const issuer = issuanceSle.getAccountID(sfIssuer);
99
100 // Post-fixCleanup3_2_0: vault shares carry sfReferenceHolding pointing
101 // to the vault pseudo's MPToken or RippleState for the underlying.
102 // Read it to derive the underlying asset and recurse, skipping the
103 // issuer-account-then-vault chain. Pre-amendment shares (no field)
104 // fall back to the chain lookup below.
105 if (issuanceSle.isFieldPresent(sfReferenceHolding))
106 {
107 auto const sleHolding =
108 view.read(keylet::unchecked(issuanceSle.getFieldH256(sfReferenceHolding)));
109 if (!sleHolding)
110 {
111 // LCOV_EXCL_START
112 UNREACHABLE("xrpl::isVaultPseudoAccountFrozen : dangling sfReferenceHolding");
113 return false;
114 // LCOV_EXCL_STOP
115 }
116 return isAnyFrozen(
117 view, {issuer, account}, assetOfHolding(issuanceSle, *sleHolding), depth + 1);
118 }
119
120 auto const mptIssuer = view.read(keylet::account(issuer));
121 if (mptIssuer == nullptr)
122 {
123 // LCOV_EXCL_START
124 UNREACHABLE("xrpl::isVaultPseudoAccountFrozen : null MPToken issuer");
125 return false;
126 // LCOV_EXCL_STOP
127 }
128
129 if (!mptIssuer->isFieldPresent(sfVaultID))
130 return false; // not a Vault pseudo-account, common case
131
132 auto const vault = view.read(keylet::vault(mptIssuer->getFieldH256(sfVaultID)));
133 if (vault == nullptr)
134 { // LCOV_EXCL_START
135 UNREACHABLE("xrpl::isVaultPseudoAccountFrozen : null vault");
136 return false;
137 // LCOV_EXCL_STOP
138 }
139
140 return isAnyFrozen(view, {issuer, account}, vault->at(sfAsset), depth + 1);
141}
142
143} // namespace
144
145bool
147 ReadView const& view,
148 AccountID const& account,
149 SLE const& issuanceSle,
150 std::uint8_t depth)
151{
152 if (auto const result = checkVaultPseudoAccountFrozenPreconditions(view, depth))
153 return *result;
154
155 return isVaultPseudoAccountFrozenForIssuance(view, account, issuanceSle, depth);
156}
157
158bool
160 ReadView const& view,
161 AccountID const& account,
162 MPTIssue const& mptShare,
163 std::uint8_t depth)
164{
165 if (auto const result = checkVaultPseudoAccountFrozenPreconditions(view, depth))
166 return *result;
167
168 auto const issuanceSle = view.read(keylet::mptokenIssuance(mptShare.getMptID()));
169 if (issuanceSle == nullptr)
170 return false; // zero MPToken won't block deletion of MPTokenIssuance
171
172 return isVaultPseudoAccountFrozenForIssuance(view, account, *issuanceSle, depth);
173}
174
175bool
177 ReadView const& view,
178 AccountID const& account,
179 Asset const& asset,
180 Asset const& asset2)
181{
182 return isFrozen(view, account, asset) || isFrozen(view, account, asset2);
183}
184
185TER
187 ReadView const& view,
188 AccountID const& from,
189 AccountID const& to,
190 AccountID const& lpTokenIssuer)
191{
192 // Only AMM-issued LPTokens are subject to this check. The LPToken's issuer
193 // is the AMM account; if it is not an AMM, this is not an LPToken.
194 auto const sleIssuer = view.read(keylet::account(lpTokenIssuer));
195 if (!sleIssuer || !sleIssuer->isFieldPresent(sfAMMID))
196 return tesSUCCESS;
197
198 auto const sleAmm = view.read(keylet::amm((*sleIssuer)[sfAMMID]));
199 if (!sleAmm)
200 return tecINTERNAL; // LCOV_EXCL_LINE
201
202 auto const transferable = [&](Asset const& a) -> TER {
203 if (!a.holds<MPTIssue>())
204 return tesSUCCESS;
205 return canTransfer(view, a.get<MPTIssue>(), from, to);
206 };
207 if (auto const err = transferable((*sleAmm)[sfAsset]); !isTesSuccess(err))
208 return err;
209 return transferable((*sleAmm)[sfAsset2]);
210}
211
212bool
214 ReadView const& validLedger,
215 ReadView const& testLedger,
217 char const* reason)
218{
219 bool ret = true;
220
221 if (validLedger.header().seq < testLedger.header().seq)
222 {
223 // valid -> ... -> test
224 auto hash = hashOfSeq(
225 testLedger, validLedger.header().seq, beast::Journal{beast::Journal::getNullSink()});
226 if (hash && (*hash != validLedger.header().hash))
227 {
228 JLOG(s) << reason << " incompatible with valid ledger";
229
230 JLOG(s) << "Hash(VSeq): " << to_string(*hash);
231
232 ret = false;
233 }
234 }
235 else if (validLedger.header().seq > testLedger.header().seq)
236 {
237 // test -> ... -> valid
238 auto hash = hashOfSeq(
239 validLedger, testLedger.header().seq, beast::Journal{beast::Journal::getNullSink()});
240 if (hash && (*hash != testLedger.header().hash))
241 {
242 JLOG(s) << reason << " incompatible preceding ledger";
243
244 JLOG(s) << "Hash(NSeq): " << to_string(*hash);
245
246 ret = false;
247 }
248 }
249 else if (
250 (validLedger.header().seq == testLedger.header().seq) &&
251 (validLedger.header().hash != testLedger.header().hash))
252 {
253 // Same sequence number, different hash
254 JLOG(s) << reason << " incompatible ledger";
255
256 ret = false;
257 }
258
259 if (!ret)
260 {
261 JLOG(s) << "Val: " << validLedger.header().seq << " "
262 << to_string(validLedger.header().hash);
263
264 JLOG(s) << "New: " << testLedger.header().seq << " " << to_string(testLedger.header().hash);
265 }
266
267 return ret;
268}
269
270bool
272 UInt256 const& validHash,
273 LedgerIndex validIndex,
274 ReadView const& testLedger,
276 char const* reason)
277{
278 bool ret = true;
279
280 if (testLedger.header().seq > validIndex)
281 {
282 // Ledger we are testing follows last valid ledger
283 auto hash =
284 hashOfSeq(testLedger, validIndex, beast::Journal{beast::Journal::getNullSink()});
285 if (hash && (*hash != validHash))
286 {
287 JLOG(s) << reason << " incompatible following ledger";
288 JLOG(s) << "Hash(VSeq): " << to_string(*hash);
289
290 ret = false;
291 }
292 }
293 else if ((validIndex == testLedger.header().seq) && (testLedger.header().hash != validHash))
294 {
295 JLOG(s) << reason << " incompatible ledger";
296
297 ret = false;
298 }
299
300 if (!ret)
301 {
302 JLOG(s) << "Val: " << validIndex << " " << to_string(validHash);
303
304 JLOG(s) << "New: " << testLedger.header().seq << " " << to_string(testLedger.header().hash);
305 }
306
307 return ret;
308}
309
312{
313 return AmendmentsEntryR(view).enabledAmendments();
314}
315
318{
320}
321
323hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal)
324{
325 // Easy cases...
326 if (seq > ledger.seq())
327 {
328 JLOG(journal.warn()) << "Can't get seq " << seq << " from " << ledger.seq() << " future";
329 return std::nullopt;
330 }
331 if (seq == ledger.seq())
332 return ledger.header().hash;
333 if (seq == (ledger.seq() - 1))
334 return ledger.header().parentHash;
335
336 if (int const diff = ledger.seq() - seq; diff <= 256)
337 {
338 // Within 256...
339 LedgerHashesEntryR const hashIndex(ledger, journal);
340 if (hashIndex)
341 {
342 XRPL_ASSERT(
343 hashIndex->getFieldU32(sfLastLedgerSequence) == (ledger.seq() - 1),
344 "xrpl::hashOfSeq : matching ledger sequence");
345 if (auto const hash = hashIndex.hashAt(diff - 1))
346 return hash;
347 JLOG(journal.warn()) << "Ledger " << ledger.seq() << " missing hash for " << seq << " ("
348 << hashIndex->getFieldV256(sfHashes).size() << "," << diff << ")";
349 }
350 else
351 {
352 JLOG(journal.warn()) << "Ledger " << ledger.seq() << ":" << ledger.header().hash
353 << " missing normal list";
354 }
355 }
356
357 if ((seq & 0xff) != 0)
358 {
359 JLOG(journal.debug()) << "Can't get seq " << seq << " from " << ledger.seq() << " past";
360 return std::nullopt;
361 }
362
363 // in skiplist
364 LedgerHashesEntryR const hashIndex(keylet::skip(seq), ledger, journal);
365 if (hashIndex)
366 {
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))
371 return hash;
372 }
373 JLOG(journal.warn()) << "Can't get seq " << seq << " from " << ledger.seq() << " error";
374 return std::nullopt;
375}
376
377//------------------------------------------------------------------------------
378//
379// Modifiers
380//
381//------------------------------------------------------------------------------
382
383TER
384dirLink(ApplyView& view, AccountID const& owner, SLE::pointer& object, SF_UINT64 const& node)
385{
386 auto const page =
387 view.dirInsert(keylet::ownerDir(owner), object->key(), describeOwnerDir(owner));
388 if (!page)
389 return tecDIR_FULL; // LCOV_EXCL_LINE
390 object->setFieldU64(node, *page);
391 return tesSUCCESS;
392}
393
394/*
395 * Checks if a withdrawal amount into the destination account exceeds
396 * any applicable receiving limit.
397 * Called by VaultWithdraw and LoanBrokerCoverWithdraw.
398 *
399 * IOU : Performs the trustline check against the destination account's
400 * credit limit to ensure the account's trust maximum is not exceeded.
401 *
402 * MPT: The limit check is effectively skipped (returns true). This is
403 * because MPT MaximumAmount relates to token supply, and withdrawal does not
404 * involve minting new tokens that could exceed the global cap.
405 * On withdrawal, tokens are simply transferred from the vault's pseudo-account
406 * to the destination account. Since no new MPT tokens are minted during this
407 * transfer, the withdrawal cannot violate the MPT MaximumAmount/supply cap
408 * even if `from` is the issuer.
409 */
410static TER
412 ReadView const& view,
413 AccountID const& from,
414 AccountID const& to,
415 STAmount const& amount)
416{
417 auto const& issuer = amount.getIssuer();
418 if (from == to || to == issuer || isXRP(issuer))
419 return tesSUCCESS;
420
421 return amount.asset().visit(
422 [&](Issue const& issue) -> TER {
423 auto const& currency = issue.currency;
424 auto const owed = creditBalance(view, to, issuer, currency);
425 if (owed <= beast::kZero)
426 {
427 auto const limit = creditLimit(view, to, issuer, currency);
428 if (-owed >= limit || amount > (limit + owed))
429 return tecNO_LINE;
430 }
431 return tesSUCCESS;
432 },
433 [](MPTIssue const&) -> TER { return tesSUCCESS; });
434}
435
436[[nodiscard]] TER
438 ReadView const& view,
439 AccountID const& from,
440 AccountID const& to,
441 SLE::ConstRef toSle,
442 STAmount const& amount,
443 bool hasDestinationTag,
444 std::optional<std::vector<UInt256>> const& credentialIDs)
445{
446 if (auto const ret = checkDestinationAndTag(toSle, hasDestinationTag))
447 return ret;
448
449 if (from == to)
450 return tesSUCCESS;
451
452 if (toSle->isFlag(lsfDepositAuth))
453 {
454 if (!view.exists(keylet::depositPreauth(to, from)))
455 {
456 if (credentialIDs.has_value())
457 {
458 STVector256 const credIDs{*credentialIDs};
459
460 // Callers must have validated these in preclaim, so a missing
461 // credential here is an invariant violation.
462 for (auto const& h : credIDs)
463 {
464 if (!view.exists(keylet::credential(h)))
465 return tecINTERNAL; // LCOV_EXCL_LINE
466 }
467
468 if (auto const ret = credentials::authorizedDepositPreauth(view, credIDs, to);
469 !isTesSuccess(ret))
470 return ret;
471 }
472 else
473 {
474 return tecNO_PERMISSION;
475 }
476 }
477 }
478
479 return withdrawToDestExceedsLimit(view, from, to, amount);
480}
481
482[[nodiscard]] TER
484 ReadView const& view,
485 AccountID const& from,
486 AccountID const& to,
487 STAmount const& amount,
488 bool hasDestinationTag,
489 std::optional<std::vector<UInt256>> const& credentialIDs)
490{
491 auto const toSle = view.read(keylet::account(to));
492
493 return canWithdraw(view, from, to, toSle, amount, hasDestinationTag, credentialIDs);
494}
495
496[[nodiscard]] TER
497canWithdraw(ReadView const& view, STTx const& tx)
498{
499 auto const from = tx[sfAccount];
500 auto const to = tx[~sfDestination].value_or(from);
501
502 return canWithdraw(
503 view, from, to, tx[sfAmount], tx.isFieldPresent(sfDestinationTag), tx[~sfCredentialIDs]);
504}
505
506TER
509 AccountID const& senderAcct,
510 AccountID const& dstAcct,
511 AccountID const& sourceAcct,
512 XRPAmount priorBalance,
513 STAmount const& amount,
515{
516 auto const dstSle = ctx.view.read(keylet::account(dstAcct));
517
518 // Create a trust line or MPToken for a self-destination only when there
519 // is a payout to credit. Post-fixCleanup3_4_0, a zero-value withdraw
520 // (e.g. share redemption from a fully impaired vault) must not insert
521 // an empty holding: that records a one-sided zero delta and can also
522 // create+delete MPTokens in the same transaction.
523 if (dstAcct == senderAcct)
524 {
525 if (amount > beast::kZero || !ctx.view.rules().enabled(fixCleanup3_4_0))
526 {
527 if (auto const ter = addEmptyHolding(ctx, senderAcct, priorBalance, amount.asset(), j);
528 !isTesSuccess(ter) && ter != tecDUPLICATE)
529 return ter;
530 }
531 }
532 else
533 {
534 if (auto err = verifyDepositPreauth(ctx.tx, ctx.view, senderAcct, dstAcct, dstSle, j))
535 return err;
536 }
537
538 // Sanity check
539 if (accountHolds(
540 ctx.view,
541 sourceAcct,
542 amount.asset(),
545 j) < amount)
546 {
547 // LCOV_EXCL_START
548 JLOG(j.error()) << "doWithdraw: negative balance of broker cover assets.";
549 return tefINTERNAL;
550 // LCOV_EXCL_STOP
551 }
552
553 // A reserve sponsor only covers tx.Account's own objects, so resolve the
554 // sponsor against the destination. accountSend can auto-create a holding
555 // for dstAcct; keying on the destination ensures a third-party destination's
556 // holding is never stamped with the tx's reserve sponsor.
557 auto const sponsorSle = getEffectiveTxReserveSponsor(ctx, dstSle);
558 if (!sponsorSle)
559 return sponsorSle.error(); // LCOV_EXCL_LINE
560
561 // Move the funds directly from the broker's pseudo-account to the
562 // dstAcct
563 return accountSend(
564 ctx.view, sourceAcct, dstAcct, amount, j, *sponsorSle, WaiveTransferFee::Yes);
565}
566
567TER
569 ApplyView& view,
570 Keylet const& ownerDirKeylet,
571 EntryDeleter const& deleter,
573 std::optional<uint16_t> maxNodesToDelete)
574{
575 // Delete all the entries in the account directory.
576 SLE::pointer sleDirNode{};
577 unsigned int uDirEntry{0};
578 UInt256 dirEntry{beast::kZero};
579 std::uint32_t deleted = 0;
580
581 if (view.exists(ownerDirKeylet) &&
582 dirFirst(view, ownerDirKeylet.key, sleDirNode, uDirEntry, dirEntry))
583 {
584 do
585 {
586 if (maxNodesToDelete && ++deleted > *maxNodesToDelete)
587 return tecINCOMPLETE;
588
589 // Choose the right way to delete each directory node.
590 auto sleItem = view.peek(keylet::child(dirEntry));
591 if (!sleItem)
592 {
593 // Directory node has an invalid index. Bail out.
594 // LCOV_EXCL_START
595 JLOG(j.fatal()) << "DeleteAccount: Directory node in ledger " << view.seq()
596 << " has index to object that is missing: " << to_string(dirEntry);
597 return tefBAD_LEDGER;
598 // LCOV_EXCL_STOP
599 }
600
601 LedgerEntryType const nodeType{
602 safeCast<LedgerEntryType>(sleItem->getFieldU16(sfLedgerEntryType))};
603
604 // Deleter handles the details of specific account-owned object
605 // deletion
606 auto const [ter, skipEntry] = deleter(nodeType, dirEntry, sleItem);
607 if (!isTesSuccess(ter))
608 return ter;
609
610 // dirFirst() and dirNext() are like iterators with exposed
611 // internal state. We'll take advantage of that exposed state
612 // to solve a common C++ problem: iterator invalidation while
613 // deleting elements from a container.
614 //
615 // We have just deleted one directory entry, which means our
616 // "iterator state" is invalid.
617 //
618 // 1. During the process of getting an entry from the
619 // directory uDirEntry was incremented from 'it' to 'it'+1.
620 //
621 // 2. We then deleted the entry at index 'it', which means the
622 // entry that was at 'it'+1 has now moved to 'it'.
623 //
624 // 3. So we verify that uDirEntry is indeed 'it'+1. Then we jam it
625 // back to 'it' to "un-invalidate" the iterator.
626 XRPL_ASSERT(uDirEntry >= 1, "xrpl::cleanupOnAccountDelete : minimum dir entries");
627 if (uDirEntry == 0)
628 {
629 // LCOV_EXCL_START
630 JLOG(j.error()) << "DeleteAccount iterator re-validation failed.";
631 return tefBAD_LEDGER;
632 // LCOV_EXCL_STOP
633 }
634 if (skipEntry == SkipEntry::No)
635 uDirEntry--;
636
637 } while (dirNext(view, ownerDirKeylet.key, sleDirNode, uDirEntry, dirEntry));
638 }
639
640 return tesSUCCESS;
641}
642
643bool
645{
646 return now.time_since_epoch().count() > mark;
647}
648
649} // namespace xrpl
Provide a light-weight way to check active() before string formatting.
Definition Journal.h:199
A generic endpoint for log messages.
Definition Journal.h:44
Stream fatal() const
Definition Journal.h:368
Stream error() const
Definition Journal.h:362
Stream debug() const
Definition Journal.h:344
static Sink & getNullSink()
Returns a Sink which does nothing.
Stream warn() const
Definition Journal.h:356
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.
Definition ApplyView.h:141
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.
Definition ApplyView.h:373
constexpr auto visit(Visitors &&... visitors) const -> decltype(auto)
Definition Asset.h:117
A currency issued by an account.
Definition Issue.h:18
Currency currency
Definition Issue.h:20
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
Definition MPTIssue.h:43
std::chrono::time_point< NetClock > time_point
Definition chrono.h:48
std::chrono::duration< rep, period > duration
Definition chrono.h:47
A view into a ledger.
Definition ReadView.h:41
virtual Rules const & rules() const =0
Returns the tx processing rules.
NetClock::time_point parentCloseTime() const
Returns the close time of the previous ledger.
Definition ReadView.h:106
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.
Definition ReadView.h:115
bool enabled(UInt256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:182
Asset const & asset() const
Definition STAmount.h:496
AccountID const & getIssuer() const
Definition STAmount.h:516
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
Definition STObject.cpp:601
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:464
STVector256 const & getFieldV256(SField const &field) const
Definition STObject.cpp:671
std::size_t size() const
constexpr Zero kZero
Definition Zero.h:30
TER authorizedDepositPreauth(ReadView const &view, STVector256 const &ctx, AccountID const &dst)
Keylet const & skip() noexcept
The index of the "short" skip list.
Definition Indexes.cpp:232
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Definition Indexes.cpp:374
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:403
Keylet amm(Asset const &issue1, Asset const &issue2) noexcept
AMM entry.
Definition Indexes.cpp:471
Keylet unchecked(UInt256 const &key) noexcept
Any ledger entry.
Definition Indexes.cpp:397
Keylet vault(AccountID const &owner, SeqProxy const &seq) noexcept
Definition Indexes.cpp:591
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:220
Keylet credential(AccountID const &subject, AccountID const &issuer, Slice const &credType) noexcept
Definition Indexes.cpp:585
Keylet child(UInt256 const &key) noexcept
Any item that can be in an owner dir.
Definition Indexes.cpp:226
Keylet mptokenIssuance(MPTID const &issuanceID) noexcept
Definition Indexes.cpp:567
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::optional< UInt256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
Definition View.cpp:323
bool hasExpired(ReadView const &view, std::optional< std::uint32_t > const &exp, ExpiryComparison comparison=ExpiryComparison::Inclusive)
Determines whether the given expiration time has passed.
Definition View.cpp:51
TypedField< STInteger< std::uint64_t > > SF_UINT64
Definition SField.h:345
bool isXRP(AccountID const &c)
Definition AccountID.h:84
std::uint32_t LedgerIndex
A ledger index.
Definition Protocol.h:382
std::set< UInt256 > getEnabledAmendments(ReadView const &view)
Definition View.cpp:311
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)
@ tefBAD_LEDGER
Definition TER.h:165
@ tefINTERNAL
Definition TER.h:168
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.
Definition View.h:42
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 &currency)
Calculate the maximum amount of IOUs that an account can hold.
constexpr Dest safeCast(Src s) noexcept
Definition safe_cast.h:21
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:657
bool isVaultPseudoAccountFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptShare, std::uint8_t depth)
Definition View.cpp:159
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,...
Definition View.cpp:213
STLedgerEntry SLE
TER doWithdraw(ApplyViewContext ctx, AccountID const &senderAcct, AccountID const &dstAcct, AccountID const &sourceAcct, XRPAmount priorBalance, STAmount const &amount, beast::Journal j)
Definition View.cpp:507
BaseUInt< 256 > UInt256
Definition base_uint.h:580
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.
Definition View.cpp:186
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.
Definition Protocol.h:377
TER dirLink(ApplyView &view, AccountID const &owner, SLE::pointer &object, SF_UINT64 const &node=sfOwnerNode)
Definition View.cpp:384
static TER withdrawToDestExceedsLimit(ReadView const &view, AccountID const &from, AccountID const &to, STAmount const &amount)
Definition View.cpp:411
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.
Definition View.cpp:437
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:644
STAmount creditBalance(ReadView const &view, AccountID const &account, AccountID const &issuer, Currency const &currency)
Returns the amount of IOUs issued by issuer that are held by an account.
std::map< UInt256, NetClock::time_point > MajorityAmendmentsT
Definition View.h:121
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.
Definition AccountID.h:34
std::function< std::pair< TER, SkipEntry >(LedgerEntryType, UInt256 const &, SLE::pointer &)> EntryDeleter
Deleter function prototype.
Definition View.h:283
bool isTesSuccess(TER x) noexcept
Definition TER.h:683
bool isAnyFrozen(ReadView const &view, std::initializer_list< AccountID > const &accounts, MPTIssue const &mptIssue, std::uint8_t depth=0)
TERSubset< CanCvtToTER > TER
Definition TER.h:654
bool isLPTokenFrozen(ReadView const &view, AccountID const &account, Asset const &asset, Asset const &asset2)
Definition View.cpp:176
LedgerEntryType
Identifiers for on-ledger objects.
@ tecDIR_FULL
Definition TER.h:295
@ tecINCOMPLETE
Definition TER.h:343
@ tecINTERNAL
Definition TER.h:318
@ tecNO_LINE
Definition TER.h:309
@ tecNO_PERMISSION
Definition TER.h:313
@ tecDUPLICATE
Definition TER.h:323
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)
Definition View.cpp:317
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=SpendableHandling::SimpleBalance)
@ tesSUCCESS
Definition TER.h:250
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.
Definition ApplyView.h:451
A pair of SHAMap key and LedgerEntryType.
Definition Keylet.h:20
UInt256 key
Definition Keylet.h:21
T time_since_epoch(T... args)