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