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/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>
33
34#include <cstdint>
35#include <optional>
36#include <set>
37
38namespace xrpl {
39
40//------------------------------------------------------------------------------
41//
42// Observers
43//
44//------------------------------------------------------------------------------
45
46bool
48{
49 using d = NetClock::duration;
50 using tp = NetClock::time_point;
51
52 return exp && (view.parentCloseTime() >= tp{d{*exp}});
53}
54
55bool
57 ReadView const& view,
58 AccountID const& account,
59 MPTIssue const& mptShare,
60 std::uint8_t depth)
61{
62 if (!view.rules().enabled(featureSingleAssetVault))
63 return false;
64
65 if (depth >= kMaxAssetCheckDepth)
66 {
67 // LCOV_EXCL_START
68 UNREACHABLE("xrpl::View::isVaultPseudoAccountFrozen : reached asset check depth");
69 return true;
70 // LCOV_EXCL_STOP
71 }
72
73 auto const mptIssuance = view.read(keylet::mptokenIssuance(mptShare.getMptID()));
74 if (mptIssuance == nullptr)
75 return false; // zero MPToken won't block deletion of MPTokenIssuance
76
77 auto const issuer = mptIssuance->getAccountID(sfIssuer);
78
79 // Post-fixCleanup3_2_0: vault shares carry sfReferenceHolding pointing
80 // to the vault pseudo's MPToken or RippleState for the underlying.
81 // Read it to derive the underlying asset and recurse, skipping the
82 // issuer-account-then-vault chain. Pre-amendment shares (no field)
83 // fall back to the chain lookup below.
84 if (mptIssuance->isFieldPresent(sfReferenceHolding))
85 {
86 auto const sleHolding =
87 view.read(keylet::unchecked(mptIssuance->getFieldH256(sfReferenceHolding)));
88 if (!sleHolding)
89 {
90 // LCOV_EXCL_START
91 UNREACHABLE("xrpl::isVaultPseudoAccountFrozen : dangling sfReferenceHolding");
92 return false;
93 // LCOV_EXCL_STOP
94 }
95 return isAnyFrozen(
96 view, {issuer, account}, assetOfHolding(*mptIssuance, *sleHolding), depth + 1);
97 }
98
99 auto const mptIssuer = view.read(keylet::account(issuer));
100 if (mptIssuer == nullptr)
101 {
102 // LCOV_EXCL_START
103 UNREACHABLE("xrpl::isVaultPseudoAccountFrozen : null MPToken issuer");
104 return false;
105 // LCOV_EXCL_STOP
106 }
107
108 if (!mptIssuer->isFieldPresent(sfVaultID))
109 return false; // not a Vault pseudo-account, common case
110
111 auto const vault = view.read(keylet::vault(mptIssuer->getFieldH256(sfVaultID)));
112 if (vault == nullptr)
113 { // LCOV_EXCL_START
114 UNREACHABLE("xrpl::isVaultPseudoAccountFrozen : null vault");
115 return false;
116 // LCOV_EXCL_STOP
117 }
118
119 return isAnyFrozen(view, {issuer, account}, vault->at(sfAsset), depth + 1);
120}
121
122bool
124 ReadView const& view,
125 AccountID const& account,
126 Asset const& asset,
127 Asset const& asset2)
128{
129 return isFrozen(view, account, asset) || isFrozen(view, account, asset2);
130}
131
132bool
134 ReadView const& validLedger,
135 ReadView const& testLedger,
137 char const* reason)
138{
139 bool ret = true;
140
141 if (validLedger.header().seq < testLedger.header().seq)
142 {
143 // valid -> ... -> test
144 auto hash = hashOfSeq(
145 testLedger, validLedger.header().seq, beast::Journal{beast::Journal::getNullSink()});
146 if (hash && (*hash != validLedger.header().hash))
147 {
148 JLOG(s) << reason << " incompatible with valid ledger";
149
150 JLOG(s) << "Hash(VSeq): " << to_string(*hash);
151
152 ret = false;
153 }
154 }
155 else if (validLedger.header().seq > testLedger.header().seq)
156 {
157 // test -> ... -> valid
158 auto hash = hashOfSeq(
159 validLedger, testLedger.header().seq, beast::Journal{beast::Journal::getNullSink()});
160 if (hash && (*hash != testLedger.header().hash))
161 {
162 JLOG(s) << reason << " incompatible preceding ledger";
163
164 JLOG(s) << "Hash(NSeq): " << to_string(*hash);
165
166 ret = false;
167 }
168 }
169 else if (
170 (validLedger.header().seq == testLedger.header().seq) &&
171 (validLedger.header().hash != testLedger.header().hash))
172 {
173 // Same sequence number, different hash
174 JLOG(s) << reason << " incompatible ledger";
175
176 ret = false;
177 }
178
179 if (!ret)
180 {
181 JLOG(s) << "Val: " << validLedger.header().seq << " "
182 << to_string(validLedger.header().hash);
183
184 JLOG(s) << "New: " << testLedger.header().seq << " " << to_string(testLedger.header().hash);
185 }
186
187 return ret;
188}
189
190bool
192 uint256 const& validHash,
193 LedgerIndex validIndex,
194 ReadView const& testLedger,
196 char const* reason)
197{
198 bool ret = true;
199
200 if (testLedger.header().seq > validIndex)
201 {
202 // Ledger we are testing follows last valid ledger
203 auto hash =
204 hashOfSeq(testLedger, validIndex, beast::Journal{beast::Journal::getNullSink()});
205 if (hash && (*hash != validHash))
206 {
207 JLOG(s) << reason << " incompatible following ledger";
208 JLOG(s) << "Hash(VSeq): " << to_string(*hash);
209
210 ret = false;
211 }
212 }
213 else if ((validIndex == testLedger.header().seq) && (testLedger.header().hash != validHash))
214 {
215 JLOG(s) << reason << " incompatible ledger";
216
217 ret = false;
218 }
219
220 if (!ret)
221 {
222 JLOG(s) << "Val: " << validIndex << " " << to_string(validHash);
223
224 JLOG(s) << "New: " << testLedger.header().seq << " " << to_string(testLedger.header().hash);
225 }
226
227 return ret;
228}
229
232{
233 std::set<uint256> amendments;
234
235 if (auto const sle = view.read(keylet::amendments()))
236 {
237 if (sle->isFieldPresent(sfAmendments))
238 {
239 auto const& v = sle->getFieldV256(sfAmendments);
240 amendments.insert(v.begin(), v.end());
241 }
242 }
243
244 return amendments;
245}
246
249{
251
252 if (auto const sle = view.read(keylet::amendments()))
253 {
254 if (sle->isFieldPresent(sfMajorities))
255 {
256 using tp = NetClock::time_point;
257 using d = tp::duration;
258
259 auto const majorities = sle->getFieldArray(sfMajorities);
260
261 for (auto const& m : majorities)
262 ret[m.getFieldH256(sfAmendment)] = tp(d(m.getFieldU32(sfCloseTime)));
263 }
264 }
265
266 return ret;
267}
268
270hashOfSeq(ReadView const& ledger, LedgerIndex seq, beast::Journal journal)
271{
272 // Easy cases...
273 if (seq > ledger.seq())
274 {
275 JLOG(journal.warn()) << "Can't get seq " << seq << " from " << ledger.seq() << " future";
276 return std::nullopt;
277 }
278 if (seq == ledger.seq())
279 return ledger.header().hash;
280 if (seq == (ledger.seq() - 1))
281 return ledger.header().parentHash;
282
283 if (int const diff = ledger.seq() - seq; diff <= 256)
284 {
285 // Within 256...
286 auto const hashIndex = ledger.read(keylet::skip());
287 if (hashIndex)
288 {
289 XRPL_ASSERT(
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 << ")";
297 }
298 else
299 {
300 JLOG(journal.warn()) << "Ledger " << ledger.seq() << ":" << ledger.header().hash
301 << " missing normal list";
302 }
303 }
304
305 if ((seq & 0xff) != 0)
306 {
307 JLOG(journal.debug()) << "Can't get seq " << seq << " from " << ledger.seq() << " past";
308 return std::nullopt;
309 }
310
311 // in skiplist
312 auto const hashIndex = ledger.read(keylet::skip(seq));
313 if (hashIndex)
314 {
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];
322 }
323 JLOG(journal.warn()) << "Can't get seq " << seq << " from " << ledger.seq() << " error";
324 return std::nullopt;
325}
326
327//------------------------------------------------------------------------------
328//
329// Modifiers
330//
331//------------------------------------------------------------------------------
332
333TER
334dirLink(ApplyView& view, AccountID const& owner, SLE::pointer& object, SF_UINT64 const& node)
335{
336 auto const page =
337 view.dirInsert(keylet::ownerDir(owner), object->key(), describeOwnerDir(owner));
338 if (!page)
339 return tecDIR_FULL; // LCOV_EXCL_LINE
340 object->setFieldU64(node, *page);
341 return tesSUCCESS;
342}
343
344/*
345 * Checks if a withdrawal amount into the destination account exceeds
346 * any applicable receiving limit.
347 * Called by VaultWithdraw and LoanBrokerCoverWithdraw.
348 *
349 * IOU : Performs the trustline check against the destination account's
350 * credit limit to ensure the account's trust maximum is not exceeded.
351 *
352 * MPT: The limit check is effectively skipped (returns true). This is
353 * because MPT MaximumAmount relates to token supply, and withdrawal does not
354 * involve minting new tokens that could exceed the global cap.
355 * On withdrawal, tokens are simply transferred from the vault's pseudo-account
356 * to the destination account. Since no new MPT tokens are minted during this
357 * transfer, the withdrawal cannot violate the MPT MaximumAmount/supply cap
358 * even if `from` is the issuer.
359 */
360static TER
362 ReadView const& view,
363 AccountID const& from,
364 AccountID const& to,
365 STAmount const& amount)
366{
367 auto const& issuer = amount.getIssuer();
368 if (from == to || to == issuer || isXRP(issuer))
369 return tesSUCCESS;
370
371 return amount.asset().visit(
372 [&](Issue const& issue) -> TER {
373 auto const& currency = issue.currency;
374 auto const owed = creditBalance(view, to, issuer, currency);
375 if (owed <= beast::kZero)
376 {
377 auto const limit = creditLimit(view, to, issuer, currency);
378 if (-owed >= limit || amount > (limit + owed))
379 return tecNO_LINE;
380 }
381 return tesSUCCESS;
382 },
383 [](MPTIssue const&) -> TER { return tesSUCCESS; });
384}
385
386[[nodiscard]] TER
388 ReadView const& view,
389 AccountID const& from,
390 AccountID const& to,
391 SLE::const_ref toSle,
392 STAmount const& amount,
393 bool hasDestinationTag)
394{
395 if (auto const ret = checkDestinationAndTag(toSle, hasDestinationTag))
396 return ret;
397
398 if (from == to)
399 return tesSUCCESS;
400
401 if (toSle->isFlag(lsfDepositAuth))
402 {
403 if (!view.exists(keylet::depositPreauth(to, from)))
404 return tecNO_PERMISSION;
405 }
406
407 return withdrawToDestExceedsLimit(view, from, to, amount);
408}
409
410[[nodiscard]] TER
412 ReadView const& view,
413 AccountID const& from,
414 AccountID const& to,
415 STAmount const& amount,
416 bool hasDestinationTag)
417{
418 auto const toSle = view.read(keylet::account(to));
419
420 return canWithdraw(view, from, to, toSle, amount, hasDestinationTag);
421}
422
423[[nodiscard]] TER
424canWithdraw(ReadView const& view, STTx const& tx)
425{
426 auto const from = tx[sfAccount];
427 auto const to = tx[~sfDestination].value_or(from);
428
429 return canWithdraw(view, from, to, tx[sfAmount], tx.isFieldPresent(sfDestinationTag));
430}
431
432TER
434 ApplyView& view,
435 STTx const& tx,
436 AccountID const& senderAcct,
437 AccountID const& dstAcct,
438 AccountID const& sourceAcct,
439 XRPAmount priorBalance,
440 STAmount const& amount,
442{
443 // Create trust line or MPToken for the receiving account
444 if (dstAcct == senderAcct)
445 {
446 if (auto const ter = addEmptyHolding(view, senderAcct, priorBalance, amount.asset(), j);
447 !isTesSuccess(ter) && ter != tecDUPLICATE)
448 return ter;
449 }
450 else
451 {
452 auto dstSle = view.read(keylet::account(dstAcct));
453 if (auto err = verifyDepositPreauth(tx, view, senderAcct, dstAcct, dstSle, j))
454 return err;
455 }
456
457 // Sanity check
458 if (accountHolds(
459 view,
460 sourceAcct,
461 amount.asset(),
464 j) < amount)
465 {
466 // LCOV_EXCL_START
467 JLOG(j.error()) << "doWithdraw: negative balance of broker cover assets.";
468 return tefINTERNAL;
469 // LCOV_EXCL_STOP
470 }
471
472 // Move the funds directly from the broker's pseudo-account to the
473 // dstAcct
474 return accountSend(view, sourceAcct, dstAcct, amount, j, WaiveTransferFee::Yes);
475}
476
477TER
479 ApplyView& view,
480 Keylet const& ownerDirKeylet,
481 EntryDeleter const& deleter,
483 std::optional<uint16_t> maxNodesToDelete)
484{
485 // Delete all the entries in the account directory.
486 SLE::pointer sleDirNode{};
487 unsigned int uDirEntry{0};
488 uint256 dirEntry{beast::kZero};
489 std::uint32_t deleted = 0;
490
491 if (view.exists(ownerDirKeylet) &&
492 dirFirst(view, ownerDirKeylet.key, sleDirNode, uDirEntry, dirEntry))
493 {
494 do
495 {
496 if (maxNodesToDelete && ++deleted > *maxNodesToDelete)
497 return tecINCOMPLETE;
498
499 // Choose the right way to delete each directory node.
500 auto sleItem = view.peek(keylet::child(dirEntry));
501 if (!sleItem)
502 {
503 // Directory node has an invalid index. Bail out.
504 // LCOV_EXCL_START
505 JLOG(j.fatal()) << "DeleteAccount: Directory node in ledger " << view.seq()
506 << " has index to object that is missing: " << to_string(dirEntry);
507 return tefBAD_LEDGER;
508 // LCOV_EXCL_STOP
509 }
510
511 LedgerEntryType const nodeType{
512 safeCast<LedgerEntryType>(sleItem->getFieldU16(sfLedgerEntryType))};
513
514 // Deleter handles the details of specific account-owned object
515 // deletion
516 auto const [ter, skipEntry] = deleter(nodeType, dirEntry, sleItem);
517 if (!isTesSuccess(ter))
518 return ter;
519
520 // dirFirst() and dirNext() are like iterators with exposed
521 // internal state. We'll take advantage of that exposed state
522 // to solve a common C++ problem: iterator invalidation while
523 // deleting elements from a container.
524 //
525 // We have just deleted one directory entry, which means our
526 // "iterator state" is invalid.
527 //
528 // 1. During the process of getting an entry from the
529 // directory uDirEntry was incremented from 'it' to 'it'+1.
530 //
531 // 2. We then deleted the entry at index 'it', which means the
532 // entry that was at 'it'+1 has now moved to 'it'.
533 //
534 // 3. So we verify that uDirEntry is indeed 'it'+1. Then we jam it
535 // back to 'it' to "un-invalidate" the iterator.
536 XRPL_ASSERT(uDirEntry >= 1, "xrpl::cleanupOnAccountDelete : minimum dir entries");
537 if (uDirEntry == 0)
538 {
539 // LCOV_EXCL_START
540 JLOG(j.error()) << "DeleteAccount iterator re-validation failed.";
541 return tefBAD_LEDGER;
542 // LCOV_EXCL_STOP
543 }
544 if (skipEntry == SkipEntry::No)
545 uDirEntry--;
546
547 } while (dirNext(view, ownerDirKeylet.key, sleDirNode, uDirEntry, dirEntry));
548 }
549
550 return tesSUCCESS;
551}
552
553bool
555{
556 return now.time_since_epoch().count() > mark;
557}
558
559} // namespace xrpl
Provide a light-weight way to check active() before string formatting.
Definition Journal.h:176
A generic endpoint for log messages.
Definition Journal.h:38
Stream fatal() const
Definition Journal.h:321
Stream error() const
Definition Journal.h:315
Stream debug() const
Definition Journal.h:297
static Sink & getNullSink()
Returns a Sink which does nothing.
Stream warn() const
Definition Journal.h:309
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:118
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:340
constexpr auto visit(Visitors &&... visitors) const -> decltype(auto)
Definition Asset.h:107
A currency issued by an account.
Definition Issue.h:13
Currency currency
Definition Issue.h:15
constexpr MPTID const & getMptID() const
Definition MPTIssue.h:33
std::chrono::time_point< NetClock > time_point
Definition chrono.h:46
std::chrono::duration< rep, period > duration
Definition chrono.h:45
A view into a ledger.
Definition ReadView.h:31
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:90
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:97
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:171
Asset const & asset() const
Definition STAmount.h:478
AccountID const & getIssuer() const
Definition STAmount.h:498
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
Definition STObject.cpp:454
std::size_t size() const
Keylet const & skip() noexcept
The index of the "short" skip list.
Definition Indexes.cpp:198
Keylet unchecked(uint256 const &key) noexcept
Any ledger entry.
Definition Indexes.cpp:351
Keylet mptokenIssuance(std::uint32_t seq, AccountID const &issuer) noexcept
Definition Indexes.cpp:521
Keylet depositPreauth(AccountID const &owner, AccountID const &preauthorized) noexcept
A DepositPreauth.
Definition Indexes.cpp:328
Keylet const & amendments() noexcept
The index of the amendment table.
Definition Indexes.cpp:214
Keylet ownerDir(AccountID const &id) noexcept
The root page of an account's directory.
Definition Indexes.cpp:357
Keylet child(uint256 const &key) noexcept
Any item that can be in an owner dir.
Definition Indexes.cpp:192
Keylet vault(AccountID const &owner, std::uint32_t seq) noexcept
Definition Indexes.cpp:551
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:186
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
TypedField< STInteger< std::uint64_t > > SF_UINT64
Definition SField.h:336
bool isXRP(AccountID const &c)
Definition AccountID.h:70
std::set< uint256 > getEnabledAmendments(ReadView const &view)
Definition View.cpp:231
std::uint32_t LedgerIndex
A ledger index.
Definition Protocol.h:259
TER doWithdraw(ApplyView &view, STTx const &tx, AccountID const &senderAcct, AccountID const &dstAcct, AccountID const &sourceAcct, XRPAmount priorBalance, STAmount const &amount, beast::Journal j)
Definition View.cpp:433
bool hasExpired(ReadView const &view, std::optional< std::uint32_t > const &exp)
Determines whether the given expiration time has passed.
Definition View.cpp:47
TER addEmptyHolding(ApplyView &view, AccountID const &accountID, XRPAmount priorBalance, MPTIssue const &mptIssue, beast::Journal journal)
@ tefBAD_LEDGER
Definition TER.h:160
@ tefINTERNAL
Definition TER.h:163
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safeCast(Src s) noexcept
Definition safe_cast.h:21
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 &currency)
Calculate the maximum amount of IOUs that an account can hold.
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
bool isVaultPseudoAccountFrozen(ReadView const &view, AccountID const &account, MPTIssue const &mptShare, std::uint8_t depth)
Definition View.cpp:56
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:133
std::optional< uint256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
Definition View.cpp:270
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:256
TER dirLink(ApplyView &view, AccountID const &owner, SLE::pointer &object, SF_UINT64 const &node=sfOwnerNode)
Definition View.cpp:334
static TER withdrawToDestExceedsLimit(ReadView const &view, AccountID const &from, AccountID const &to, STAmount const &amount)
Definition View.cpp:361
majorityAmendments_t getMajorityAmendments(ReadView const &view)
Definition View.cpp:248
bool after(NetClock::time_point now, std::uint32_t mark)
Has the specified time passed?
Definition View.cpp:554
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::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
Definition View.h:73
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.
Definition AccountID.h:28
bool isTesSuccess(TER x) noexcept
Definition TER.h:663
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:634
bool isLPTokenFrozen(ReadView const &view, AccountID const &account, Asset const &asset, Asset const &asset2)
Definition View.cpp:123
std::function< std::pair< TER, SkipEntry >(LedgerEntryType, uint256 const &, SLE::pointer &)> EntryDeleter
Deleter function prototype.
Definition View.h:217
LedgerEntryType
Identifiers for on-ledger objects.
@ tecDIR_FULL
Definition TER.h:285
@ tecINCOMPLETE
Definition TER.h:333
@ tecNO_LINE
Definition TER.h:299
@ tecNO_PERMISSION
Definition TER.h:303
@ tecDUPLICATE
Definition TER.h:313
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.
Definition View.cpp:387
TER checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag)
Checks the destination and tag.
BaseUInt< 256 > uint256
Definition base_uint.h:562
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 &currency, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=SpendableHandling::SimpleBalance)
@ tesSUCCESS
Definition TER.h:240
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.
Definition Keylet.h:19
uint256 key
Definition Keylet.h:20
T time_since_epoch(T... args)