xrpld
Loading...
Searching...
No Matches
AccountRootHelpers.cpp
1#include <xrpl/ledger/helpers/AccountRootHelpers.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/base_uint.h>
5#include <xrpl/basics/contract.h>
6#include <xrpl/beast/utility/Journal.h>
7#include <xrpl/beast/utility/Zero.h>
8#include <xrpl/beast/utility/instrumentation.h>
9#include <xrpl/ledger/ApplyView.h>
10#include <xrpl/ledger/OwnerCounts.h>
11#include <xrpl/ledger/ReadView.h>
12#include <xrpl/ledger/helpers/SponsorHelpers.h>
13#include <xrpl/protocol/AccountID.h>
14#include <xrpl/protocol/Feature.h>
15#include <xrpl/protocol/Indexes.h>
16#include <xrpl/protocol/LedgerFormats.h>
17#include <xrpl/protocol/Rate.h>
18#include <xrpl/protocol/SField.h>
19#include <xrpl/protocol/STLedgerEntry.h>
20#include <xrpl/protocol/STTx.h>
21#include <xrpl/protocol/TER.h>
22#include <xrpl/protocol/XRPAmount.h>
23#include <xrpl/protocol/digest.h>
24
25#include <algorithm>
26#include <cstdint>
27#include <expected>
28#include <limits>
29#include <memory>
30#include <optional>
31#include <set>
32#include <stdexcept>
33#include <vector>
34
35namespace xrpl {
36
37bool
38isGlobalFrozen(ReadView const& view, AccountID const& issuer)
39{
40 if (isXRP(issuer))
41 return false;
42 if (auto const sle = view.read(keylet::account(issuer)))
43 return sle->isFlag(lsfGlobalFreeze);
44 return false;
45}
46
47namespace {
48
49// An owner count cannot be negative. If adjustment would cause a negative
50// owner count, clamp the owner count at 0. Similarly for overflow. This
51// adjustment allows the ownerCount to be adjusted up or down in multiple steps.
52// If id != std::nullopt, then do error reporting.
53//
54// Returns adjusted owner count.
56confineOwnerCount(
57 std::uint32_t currentOwnerCount,
58 std::int32_t ownerCountAdj,
59 std::optional<AccountID> const& id = std::nullopt,
61{
62 std::uint32_t totalOwnerCount{currentOwnerCount + ownerCountAdj};
63 if (ownerCountAdj > 0)
64 {
65 // Overflow is well defined on unsigned
66 if (totalOwnerCount < currentOwnerCount)
67 {
68 // LCOV_EXCL_START
69 if (id)
70 {
71 JLOG(j.fatal()) << "Account " << *id << " owner count exceeds max!";
72 }
74 // LCOV_EXCL_STOP
75 }
76 }
77 else
78 {
79 // Underflow is well defined on unsigned
80 if (totalOwnerCount > currentOwnerCount)
81 {
82 // LCOV_EXCL_START
83 if (id)
84 {
85 JLOG(j.fatal()) << "Account " << *id << " owner count set below 0!";
86 }
87 totalOwnerCount = 0;
88 XRPL_ASSERT(!id, "xrpl::confineOwnerCount : id is not set");
89 // LCOV_EXCL_STOP
90 }
91 }
92 return totalOwnerCount;
93}
94
95// Returns the number of account reserves funded by this account: 1 for itself (0 if sponsored by
96// another account) plus the count of accounts it sponsors.
97std::uint32_t
98accountCountImpl(SLE::const_ref sle, std::int32_t accountCountAdj, beast::Journal j)
99{
100 bool const isSponsored = sle->isFieldPresent(sfSponsor);
101 std::int64_t const sponsoringAccountCount = sle->getFieldU32(sfSponsoringAccountCount);
102 std::int64_t const currentAccountCount = (isSponsored ? 0 : 1) + sponsoringAccountCount;
103
104 std::int64_t totalAccountCount{currentAccountCount + accountCountAdj};
105 if (totalAccountCount > std::numeric_limits<std::uint32_t>::max())
106 {
107 // LCOV_EXCL_START
108 JLOG(j.fatal()) << "Reserve count exceeds max!";
109 totalAccountCount = std::numeric_limits<std::uint32_t>::max();
110 // LCOV_EXCL_STOP
111 }
112 else if (totalAccountCount < 0)
113 {
114 // LCOV_EXCL_START
115 UNREACHABLE("xrpl::accountCountImpl : Reserve count set below 0");
116 JLOG(j.fatal()) << "Reserve count set below 0";
117 totalAccountCount = 0;
118 // LCOV_EXCL_STOP
119 }
120
121 return totalAccountCount;
122}
123
124std::uint32_t
125adjustOwnerCountImpl(
126 ApplyView& view,
127 SLE::ref sle,
128 SF_UINT32 const& sfield,
129 AccountID const& accID,
130 std::int32_t ownerCountAdj,
131 beast::Journal j)
132{
133 std::uint32_t const currentOwnerCount = sle->at(sfield);
134 std::uint32_t const totalOwnerCount =
135 confineOwnerCount(currentOwnerCount, ownerCountAdj, accID, j);
136 sle->at(sfield) = totalOwnerCount;
137 view.update(sle);
138 return totalOwnerCount;
139}
140
141void
142adjustOwnerCountSigned(
143 ApplyView& view,
144 SLE::ref accountSle,
145 SLE::ref sponsorSle,
146 std::int32_t adjustment,
147 beast::Journal j)
148{
149 if (view.rules().enabled(featureSponsor))
150 {
151 XRPL_ASSERT(accountSle, "xrpl::adjustOwnerCountSigned : valid account sle");
152 if (!accountSle)
153 return; // LCOV_EXCL_LINE
154
155 auto const accountID = accountSle->getAccountID(sfAccount);
156 bool const validType = accountSle->getType() == ltACCOUNT_ROOT;
157 XRPL_ASSERT(validType, "xrpl::adjustOwnerCountSigned : valid account sle type");
158 if (!validType)
159 return; // LCOV_EXCL_LINE
160
161 XRPL_ASSERT(adjustment, "xrpl::adjustOwnerCountSigned : nonzero adjustment input");
162
163 OwnerCounts const currentOwnerCount(accountSle);
164 OwnerCounts totalOwnerCount(currentOwnerCount);
165
166 if (sponsorSle)
167 {
168 bool const validSponsorType = sponsorSle->getType() == ltACCOUNT_ROOT;
169 XRPL_ASSERT(validSponsorType, "xrpl::adjustOwnerCountSigned : valid sponsor sle type");
170 if (!validSponsorType)
171 return; // LCOV_EXCL_LINE
172 auto const sponsorID = sponsorSle->getAccountID(sfAccount);
173
174 totalOwnerCount.sponsored = adjustOwnerCountImpl(
175 view, accountSle, sfSponsoredOwnerCount, accountID, adjustment, j);
176
177 {
178 OwnerCounts const sponsorCurrent(sponsorSle);
179 OwnerCounts sponsorAdjustment(sponsorCurrent);
180 sponsorAdjustment.sponsoring = adjustOwnerCountImpl(
181 view, sponsorSle, sfSponsoringOwnerCount, sponsorID, adjustment, j);
182 view.adjustOwnerCountHook(sponsorID, sponsorCurrent, sponsorAdjustment);
183 }
184
185 auto sponsorshipSle = view.peek(keylet::sponsorship(sponsorID, accountID));
186 if (sponsorshipSle && adjustment > 0)
187 {
188 // Only decrease the pre-funded ReserveCount on Sponsorship if we assign new
189 // objects. Removing/reassigning ownership of the object doesn't increase
190 // RemainingOwnerCount back. Don't call hook because this counter is not something
191 // that requires reserve (like other sf...OwnerCounts do).
192 adjustOwnerCountImpl(
193 view, sponsorshipSle, sfRemainingOwnerCount, sponsorID, -adjustment, j);
194 }
195 }
196
197 totalOwnerCount.owner =
198 adjustOwnerCountImpl(view, accountSle, sfOwnerCount, accountID, adjustment, j);
199 view.adjustOwnerCountHook(accountID, currentOwnerCount, totalOwnerCount);
200 }
201 else
202 {
203 XRPL_ASSERT(accountSle, "xrpl::adjustOwnerCountSigned : valid account sle");
204 if (!accountSle)
205 return;
206 // the remaining are only asserts to preserve existing behavior
207 XRPL_ASSERT(sponsorSle == nullptr, "xrpl::adjustOwnerCountSigned : sponsor not enabled");
208 XRPL_ASSERT(
209 accountSle->getType() == ltACCOUNT_ROOT,
210 "xrpl::adjustOwnerCountSigned : valid account sle type");
211 XRPL_ASSERT(adjustment, "xrpl::adjustOwnerCount : nonzero adjustment input");
212 std::uint32_t const current{accountSle->getFieldU32(sfOwnerCount)};
213 AccountID const id = (*accountSle)[sfAccount];
214 std::uint32_t const adjusted = confineOwnerCount(current, adjustment, id, j);
215
216 OwnerCounts const currentOwnerCount(accountSle);
217 OwnerCounts finalOwnerCount(currentOwnerCount);
218 finalOwnerCount.owner = adjusted;
219
220 view.adjustOwnerCountHook(id, currentOwnerCount, finalOwnerCount);
221 accountSle->at(sfOwnerCount) = adjusted;
222 view.update(accountSle);
223 }
224}
225
226} // namespace
227
228std::uint32_t
230{
231 XRPL_ASSERT(sle && sle->getType() == ltACCOUNT_ROOT, "xrpl::ownerCount : sle is account root");
232
233 AccountID const id = sle->getAccountID(sfAccount);
234 std::uint32_t const currentOwnerCount = sle->at(sfOwnerCount);
235 std::uint32_t const sponsoredOwnerCount = sle->at(sfSponsoredOwnerCount);
236 std::uint32_t const sponsoringOwnerCount = sle->at(sfSponsoringOwnerCount);
237
238 XRPL_ASSERT(
239 currentOwnerCount >= sponsoredOwnerCount,
240 "xrpl::ownerCount : OwnerCount must be greater than or equal to SponsoredOwnerCount");
241
242 std::int64_t deltaCount =
243 static_cast<std::int64_t>(ownerCountAdj) - sponsoredOwnerCount + sponsoringOwnerCount;
244
246 {
247 // LCOV_EXCL_START
249 JLOG(j.fatal()) << "Account " << id << " delta count exceeds max, "
250 << "adjustment: " << ownerCountAdj
251 << ", sponsoredCount: " << sponsoredOwnerCount
252 << ", sponsoringOwnerCount: " << sponsoringOwnerCount;
253 // LCOV_EXCL_STOP
254 }
255 else if (deltaCount < std::numeric_limits<std::int32_t>::min())
256 {
257 // LCOV_EXCL_START
259 JLOG(j.fatal()) << "Account " << id << " delta count is below min, "
260 << "adjustment: " << ownerCountAdj
261 << ", sponsoredCount: " << sponsoredOwnerCount
262 << ", sponsoringCount: " << sponsoringOwnerCount;
263 // LCOV_EXCL_STOP
264 }
265
266 return confineOwnerCount(currentOwnerCount, deltaCount);
267}
268
269XRPAmount
270xrpLiquid(ReadView const& view, AccountID const& id, std::int32_t ownerCountAdj, beast::Journal j)
271{
272 auto const sle = view.read(keylet::account(id));
273 if (sle == nullptr)
274 return beast::kZero;
275
276 // Return balance minus reserve
277 std::uint32_t const currentOwnerCount =
278 confineOwnerCount(view.ownerCountHook(id, OwnerCounts(sle)).count(), ownerCountAdj);
279 std::uint32_t const currentAccountCount = accountCountImpl(sle, 0, j);
280
281 // Pseudo-accounts have no reserve requirement
282 auto const reserve = isPseudoAccount(sle)
283 ? XRPAmount{0}
284 : view.fees().accountReserve(currentOwnerCount, currentAccountCount);
285
286 auto const fullBalance = sle->getFieldAmount(sfBalance);
287
288 auto const balance = view.balanceHookIOU(id, xrpAccount(), fullBalance);
289
290 STAmount const amount = (balance < reserve) ? STAmount{0} : balance - reserve;
291
292 JLOG(j.trace()) << "accountHolds:" << " account=" << to_string(id)
293 << " amount=" << amount.getFullText()
294 << " fullBalance=" << fullBalance.getFullText()
295 << " balance=" << balance.getFullText() << " reserve=" << reserve
296 << " ownerCount=" << currentOwnerCount << " ownerCountAdj=" << ownerCountAdj;
297
298 return amount.xrp();
299}
300
301Rate
302transferRate(ReadView const& view, AccountID const& issuer)
303{
304 auto const sle = view.read(keylet::account(issuer));
305
306 if (sle && sle->isFieldPresent(sfTransferRate))
307 return Rate{sle->getFieldU32(sfTransferRate)};
308
309 return kParityRate;
310}
311
312void
314 ApplyView& view,
315 SLE::ref accountSle,
316 SLE::ref sponsorSle,
317 std::uint32_t count,
319{
320 XRPL_ASSERT(
321 count != 0 && count <= std::numeric_limits<std::int32_t>::max(),
322 "xrpl::increaseOwnerCount : count in signed delta range");
323 if (count == 0 || count > std::numeric_limits<std::int32_t>::max())
324 return; // LCOV_EXCL_LINE
325
326 adjustOwnerCountSigned(view, accountSle, sponsorSle, static_cast<std::int32_t>(count), j);
327}
328
329void
331{
332 auto const sponsorExp = getEffectiveTxReserveSponsor(ctx, accountSle);
333
334 // The sponsor's existence is validated by checkReserve/checkSponsor before
335 // any owner-count mutation, so loading it here cannot fail.
336 XRPL_ASSERT(
337 sponsorExp.has_value(), "xrpl::increaseOwnerCount : sponsor validated before mutation");
338
339 increaseOwnerCount(ctx.view, accountSle, sponsorExp ? *sponsorExp : SLE::pointer(), count, j);
340}
341
342void
344 ApplyView& view,
345 SLE::ref accountSle,
346 SLE::ref sponsorSle,
347 std::uint32_t count,
349{
350 XRPL_ASSERT(
351 count != 0 && count <= std::numeric_limits<std::int32_t>::max(),
352 "xrpl::decreaseOwnerCount : count in signed delta range");
353 if (count == 0 || count > std::numeric_limits<std::int32_t>::max())
354 return; // LCOV_EXCL_LINE
355
356 adjustOwnerCountSigned(view, accountSle, sponsorSle, -static_cast<std::int32_t>(count), j);
357}
358
359void
361 ApplyView& view,
362 SLE::ref accountSle,
363 SLE::ref objectSle,
364 std::uint32_t count,
366{
367 XRPL_ASSERT(objectSle, "xrpl::decreaseOwnerCountForObject : valid object sle");
368 if (!objectSle)
369 return; // LCOV_EXCL_LINE
370
371 bool const validObjectType = objectSle->getType() != ltACCOUNT_ROOT;
372 XRPL_ASSERT(validObjectType, "xrpl::decreaseOwnerCountForObject : valid object sle type");
373 if (!validObjectType)
374 return; // LCOV_EXCL_LINE
375
376 SLE::ref sponsorSle = getLedgerEntryReserveSponsor(view, objectSle);
377 decreaseOwnerCount(view, accountSle, sponsorSle, count, j);
378}
379
380void
382 ApplyView& view,
383 SLE::ref brokerSle,
384 std::int32_t delta,
386{
387 XRPL_ASSERT(
388 brokerSle && brokerSle->getType() == ltLOAN_BROKER,
389 "xrpl::adjustLoanBrokerOwnerCount : valid loan broker sle");
390 if (!brokerSle || brokerSle->getType() != ltLOAN_BROKER)
391 return; // LCOV_EXCL_LINE
392
393 XRPL_ASSERT(delta != 0, "xrpl::adjustLoanBrokerOwnerCount : nonzero delta input");
394 if (delta == 0)
395 return; // LCOV_EXCL_LINE
396
397 adjustOwnerCountImpl(
398 view, brokerSle, sfOwnerCount, brokerSle->getAccountID(sfAccount), delta, j);
399}
400
401XRPAmount
403{
404 XRPL_ASSERT(sle && sle->getType() == ltACCOUNT_ROOT, "xrpl::accountReserve : valid sle");
405
406 if (!view.rules().enabled(featureSponsor))
407 {
408 XRPL_ASSERT(adj.accountCountDelta == 0, "xrpl::accountReserve : no account count delta");
409 return view.fees().accountReserve(sle->getFieldU32(sfOwnerCount) + adj.ownerCountDelta, 1);
410 }
411 std::uint32_t const currentOwnerCount = ownerCount(sle, j, adj.ownerCountDelta);
412 std::uint32_t const currentAccountCount = accountCountImpl(sle, adj.accountCountDelta, j);
413
414 return view.fees().accountReserve(currentOwnerCount, currentAccountCount);
415}
416
417TER
420 SLE::const_ref accSle,
421 XRPAmount accBalance,
422 SLE::const_ref sponsorSle,
423 Adjustment adj,
425 TER insufReserveCode)
426{
427 // TODO: swap to assert after fixCleanup3_2_0 is retired
428 if (!accSle || accSle->getType() != ltACCOUNT_ROOT)
429 return tefINTERNAL; // LCOV_EXCL_LINE
430 XRPL_ASSERT(
431 !isTesSuccess(insufReserveCode), "xrpl::checkReserve : insufReserveCode is not tesSUCCESS");
432 if (ctx.view.rules().enabled(featureSponsor))
433 {
434 if (sponsorSle)
435 {
436 if (sponsorSle->getType() != ltACCOUNT_ROOT)
437 return tefINTERNAL; // LCOV_EXCL_LINE
438
439 auto const sle = ctx.view.read(
441 sponsorSle->getAccountID(sfAccount), accSle->getAccountID(sfAccount)));
442
443 // A reserve-sponsored tx must carry a sponsor signature
444 // (cosigning path) and/or have a pre-existing sponsorship SLE
445 // (prefunded path). Absence of both is an internal invariant break.
446 if (isReserveSponsored(ctx.tx) && !sle && !ctx.tx.isFieldPresent(sfSponsorSignature))
447 return tecINTERNAL; // LCOV_EXCL_LINE
448
449 if (sle)
450 {
451 auto const ownerCountAllowed = sle->getFieldU32(sfRemainingOwnerCount);
452 if (adj.ownerCountDelta > 0 &&
453 ownerCountAllowed < static_cast<std::uint32_t>(adj.ownerCountDelta))
454 return insufReserveCode;
455 }
456
457 auto const sponsorBalance = sponsorSle->getFieldAmount(sfBalance).xrp();
458 XRPAmount const sponsorReserve = accountReserve(ctx.view, sponsorSle, j, adj);
459
460 if (sponsorBalance < sponsorReserve)
461 return insufReserveCode;
462 }
463 else
464 {
465 XRPAmount const reserve = accountReserve(ctx.view, accSle, j, adj);
466 if (accBalance < reserve)
467 return insufReserveCode;
468 }
469 }
470 else
471 {
472 XRPL_ASSERT(
473 !sponsorSle,
474 "xrpl::checkReserve : featureSponsor disabled and sponsorSle not provided");
475 XRPL_ASSERT(adj.accountCountDelta == 0, "xrpl::checkReserve : accountCountDelta is 0");
476 auto const reserve = ctx.view.fees().accountReserve(
477 accSle->getFieldU32(sfOwnerCount) + adj.ownerCountDelta, 1);
478 if (accBalance < reserve)
479 return insufReserveCode;
480 }
481 return tesSUCCESS;
482}
483
484TER
487 SLE::const_ref accSle,
488 XRPAmount accBalance,
489 Adjustment adj,
491{
492 auto const sponsorExp = getEffectiveTxReserveSponsor(ctx, accSle);
493 if (!sponsorExp)
494 return sponsorExp.error(); // LCOV_EXCL_LINE
495 return checkReserve(ctx, accSle, accBalance, *sponsorExp, adj, j);
496}
497
498// ----------------------------------------------------
499
501pseudoAccountAddress(ReadView const& view, uint256 const& pseudoOwnerKey)
502{
503 // This number must not be changed without an amendment
504 static constexpr std::uint16_t kMaxAccountAttempts = 256;
505 for (std::uint16_t i = 0; i < kMaxAccountAttempts; ++i)
506 {
507 RipeshaHasher rsh;
508 auto const hash = sha512Half(i, view.header().parentHash, pseudoOwnerKey);
509 rsh(hash.data(), hash.size());
510 AccountID const ret = AccountID::fromRaw(static_cast<RipeshaHasher::result_type>(rsh));
511 if (!view.read(keylet::account(ret)))
512 return ret;
513 }
514 return beast::kZero;
515}
516
517// Pseudo-account designator fields MUST be maintained by including the
518// SField::sMD_PseudoAccount flag in the SField definition. (Don't forget to
519// "| SField::sMD_Default"!) The fields do NOT need to be amendment-gated,
520// since a non-active amendment will not set any field, by definition.
521// Specific properties of a pseudo-account are NOT checked here, that's what
522// InvariantCheck is for.
523[[nodiscard]] std::vector<SField const*> const&
525{
526 static std::vector<SField const*> const kPseudoFields = []() {
527 auto const ar = LedgerFormats::getInstance().findByType(ltACCOUNT_ROOT);
528 if (!ar)
529 {
530 // LCOV_EXCL_START
532 "xrpl::getPseudoAccountFields : unable to find account root "
533 "ledger format");
534 // LCOV_EXCL_STOP
535 }
536 auto const& soTemplate = ar->getSOTemplate();
537
538 std::vector<SField const*> pseudoFields;
539 for (auto const& field : soTemplate)
540 {
541 if (field.sField().shouldMeta(SField::kSmdPseudoAccount))
542 pseudoFields.emplace_back(&field.sField());
543 }
544 return pseudoFields;
545 }();
546 return kPseudoFields;
547}
548
549[[nodiscard]] bool
551{
552 auto const& fields = getPseudoAccountFields();
553
554 // Intentionally use defensive coding here because it's cheap and makes the
555 // semantics of true return value clean.
556 return sleAcct && sleAcct->getType() == ltACCOUNT_ROOT &&
558 fields.begin(), fields.end(), [&sleAcct, &pseudoFieldFilter](SField const* sf) -> bool {
559 return sleAcct->isFieldPresent(*sf) &&
560 (pseudoFieldFilter.empty() || pseudoFieldFilter.contains(sf));
561 }) > 0;
562}
563
564std::expected<SLE::pointer, TER>
565createPseudoAccount(ApplyView& view, uint256 const& pseudoOwnerKey, SField const& ownerField)
566{
567 [[maybe_unused]]
568 auto const& fields = getPseudoAccountFields();
569 XRPL_ASSERT(
571 fields.begin(),
572 fields.end(),
573 [&ownerField](SField const* sf) -> bool { return *sf == ownerField; }) == 1,
574 "xrpl::createPseudoAccount : valid owner field");
575
576 auto const accountId = pseudoAccountAddress(view, pseudoOwnerKey);
577 if (accountId == beast::kZero)
579
580 // Create pseudo-account.
581 auto account = std::make_shared<SLE>(keylet::account(accountId));
582 account->setAccountID(sfAccount, accountId);
583 account->setFieldAmount(sfBalance, STAmount{});
584
585 // Pseudo-accounts can't submit transactions, so set the sequence number
586 // to 0 to make them easier to spot and verify, and add an extra level
587 // of protection.
588 std::uint32_t const seqno = //
589 view.rules().enabled(featureSingleAssetVault) || //
590 view.rules().enabled(featureLendingProtocol) //
591 ? 0 //
592 : view.seq();
593 account->setFieldU32(sfSequence, seqno);
594 // Ignore reserves requirement, disable the master key, allow default
595 // rippling, and enable deposit authorization to prevent payments into
596 // pseudo-account.
597 account->setFieldU32(sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth);
598 // Link the pseudo-account with its owner object.
599 account->setFieldH256(ownerField, pseudoOwnerKey);
600
601 view.insert(account);
602
603 return account;
604}
605
606[[nodiscard]] TER
607checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag)
608{
609 if (toSle == nullptr)
610 return tecNO_DST;
611
612 // The tag is basically account-specific information we don't
613 // understand, but we can require someone to fill it in.
614 if (toSle->isFlag(lsfRequireDestTag) && !hasDestinationTag)
615 return tecDST_TAG_NEEDED; // Cannot send without a tag
616
617 return tesSUCCESS;
618}
619
620} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
Stream fatal() const
Definition Journal.h:368
static Sink & getNullSink()
Returns a Sink which does nothing.
Stream trace() const
Severity stream access functions.
Definition Journal.h:338
Writeable view to a ledger, for applying a transaction.
Definition ApplyView.h:134
virtual void insert(SLE::ref sle)=0
Insert a new state SLE.
static BaseUInt fromRaw(Container const &c)
Definition base_uint.h:302
Item const * findByType(KeyType type) const
Retrieve a format based on its type.
static LedgerFormats const & getInstance()
A view into a ledger.
Definition ReadView.h:41
virtual Rules const & rules() const =0
Returns the tx processing rules.
virtual Fees const & fees() const =0
Returns the fees for the base ledger.
virtual SLE::const_pointer read(Keylet const &k) const =0
Return the state item associated with a key.
virtual OwnerCounts ownerCountHook(AccountID const &account, OwnerCounts const &count) const
Definition ReadView.h:211
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
virtual STAmount balanceHookIOU(AccountID const &account, AccountID const &issuer, STAmount const &amount) const
Definition ReadView.h:180
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
Definition Rules.cpp:180
Identifies fields.
Definition SField.h:132
static constexpr auto kSmdPseudoAccount
Definition SField.h:141
std::string getFullText() const override
Definition STAmount.cpp:636
XRPAmount xrp() const
Definition STAmount.cpp:271
std::shared_ptr< STLedgerEntry > const & ref
std::shared_ptr< STLedgerEntry > pointer
std::shared_ptr< STLedgerEntry const > const & const_ref
std::shared_ptr< STLedgerEntry const > const_pointer
bool isFieldPresent(SField const &field) const
Definition STObject.cpp:464
T count_if(T... args)
T emplace_back(T... args)
T make_shared(T... args)
T max(T... args)
T min(T... args)
constexpr Zero kZero
Definition Zero.h:30
Keylet account(AccountID const &id) noexcept
AccountID root.
Definition Indexes.cpp:198
Keylet sponsorship(AccountID const &sponsor, AccountID const &sponsee) noexcept
A Sponsorship.
Definition Indexes.cpp:332
std::uint32_t sponsoringAccountCount(Env const &env, Account const &account)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::vector< SField const * > const & getPseudoAccountFields()
Returns the list of fields that define an ACCOUNT_ROOT as a pseudo-account if set.
void decreaseOwnerCountForObject(ApplyView &view, SLE::ref accountSle, SLE::ref objectSle, std::uint32_t count, beast::Journal j)
Decrease owner-count fields for an existing ledger object.
XRPAmount xrpLiquid(ReadView const &view, AccountID const &id, std::int32_t ownerCountAdj, beast::Journal j)
Calculate liquid XRP balance for an account.
AccountID pseudoAccountAddress(ReadView const &view, uint256 const &pseudoOwnerKey)
Generate a pseudo-account address from a pseudo owner key.
bool isXRP(AccountID const &c)
Definition AccountID.h:84
void increaseOwnerCount(ApplyView &view, SLE::ref accountSle, SLE::ref sponsorSle, std::uint32_t count, beast::Journal j)
Increase owner-count fields when the caller supplies the sponsor.
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:215
@ tefINTERNAL
Definition TER.h:165
void adjustLoanBrokerOwnerCount(ApplyView &view, SLE::ref brokerSle, std::int32_t delta, beast::Journal j)
Adjust a LoanBroker's owner count.
std::expected< SLE::pointer, TER > createPseudoAccount(ApplyView &view, uint256 const &pseudoOwnerKey, SField const &ownerField)
Create pseudo-account, storing pseudoOwnerKey into ownerField.
TypedField< STInteger< std::uint32_t > > SF_UINT32
Definition SField.h:341
bool isReserveSponsored(STTx const &tx)
Whether the transaction's reserve is sponsored (sfSponsor present + spfSponsorReserve set).
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:651
std::expected< SLE::pointer, TER > getEffectiveTxReserveSponsor(ApplyViewContext ctx, SLE::const_ref accountSle)
The transaction's reserve sponsor for the given account, if applicable.
bool isGlobalFrozen(ReadView const &view, AccountID const &issuer)
Check if the issuer has the global freeze flag set.
Rate transferRate(ReadView const &view, AccountID const &issuer)
Returns IOU issuer transfer fee as Rate.
void decreaseOwnerCount(ApplyView &view, SLE::ref accountSle, SLE::ref sponsorSle, std::uint32_t count, beast::Journal j)
Decrease owner-count fields when the caller supplies the sponsor.
Rate const kParityRate
A transfer rate signifying a 1:1 exchange.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
Definition AccountID.h:34
TER checkReserve(ApplyViewContext ctx, SLE::const_ref accSle, XRPAmount accBalance, SLE::const_ref sponsorSle, Adjustment adj, beast::Journal j, TER insufReserveCode=tecINSUFFICIENT_RESERVE)
Check if an account has sufficient reserve.
bool isTesSuccess(TER x) noexcept
Definition TER.h:676
TERSubset< CanCvtToTER > TER
Definition TER.h:647
AccountID const & xrpAccount()
Compute AccountID from public key.
@ tecINTERNAL
Definition TER.h:313
@ tecDST_TAG_NEEDED
Definition TER.h:312
@ tecDUPLICATE
Definition TER.h:318
@ tecNO_DST
Definition TER.h:293
SLE::pointer getLedgerEntryReserveSponsor(ApplyView &view, SLE::const_ref sle, SF_ACCOUNT const &field=sfSponsor)
Return a mutable SLE for the reserve sponsor recorded on a ledger entry.
bool isPseudoAccount(SLE::const_pointer sleAcct, std::set< SField const * > const &pseudoFieldFilter={})
Returns true if and only if sleAcct is a pseudo-account or specific pseudo-accounts in pseudoFieldFil...
TER checkDestinationAndTag(SLE::const_ref toSle, bool hasDestinationTag)
Checks the destination and tag.
std::uint32_t ownerCount(SLE::const_ref sle, beast::Journal j, std::int32_t ownerCountAdj=0)
Return number of the objects which reserve is covered by the account(sle) (so called "ownercount").
BaseUInt< 256 > uint256
Definition base_uint.h:580
XRPAmount accountReserve(ReadView const &view, SLE::const_ref sle, beast::Journal j, Adjustment adj={})
Returns the account reserve, in drops.
@ tesSUCCESS
Definition TER.h:245
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:52
std::int32_t accountCountDelta
std::int32_t ownerCountDelta
Bundles the mutable ledger view and the transaction being applied.
Definition ApplyView.h:444
XRPAmount accountReserve(std::uint32_t ownerCount, std::uint32_t accountCount) const
Returns the account reserve given the owner count, in drops.
Represents a transfer rate.
Definition Rate.h:21
Returns the RIPEMD-160 digest of the SHA256 hash of the message.
Definition digest.h:124
std::array< std::uint8_t, 20 > result_type
Definition digest.h:131
T unexpected(T... args)