1#include <xrpl/ledger/helpers/AccountRootHelpers.h>
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>
43 return sle->isFlag(lsfGlobalFreeze);
62 std::uint32_t totalOwnerCount{currentOwnerCount + ownerCountAdj};
63 if (ownerCountAdj > 0)
66 if (totalOwnerCount < currentOwnerCount)
71 JLOG(j.fatal()) <<
"Account " << *
id <<
" owner count exceeds max!";
80 if (totalOwnerCount > currentOwnerCount)
85 JLOG(j.fatal()) <<
"Account " << *
id <<
" owner count set below 0!";
88 XRPL_ASSERT(!
id,
"xrpl::confineOwnerCount : id is not set");
92 return totalOwnerCount;
98accountCountImpl(
SLE::const_ref sle, std::int32_t accountCountAdj, beast::Journal j)
100 bool const isSponsored = sle->isFieldPresent(sfSponsor);
102 std::int64_t
const currentAccountCount = (isSponsored ? 0 : 1) + sponsoringAccountCount;
104 std::int64_t totalAccountCount{currentAccountCount + accountCountAdj};
108 JLOG(j.
fatal()) <<
"Reserve count exceeds max!";
112 else if (totalAccountCount < 0)
115 UNREACHABLE(
"xrpl::accountCountImpl : Reserve count set below 0");
116 JLOG(j.
fatal()) <<
"Reserve count set below 0";
117 totalAccountCount = 0;
121 return totalAccountCount;
130 std::int32_t ownerCountAdj,
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;
138 return totalOwnerCount;
142adjustOwnerCountSigned(
146 std::int32_t adjustment,
149 if (view.rules().enabled(featureSponsor))
151 XRPL_ASSERT(accountSle,
"xrpl::adjustOwnerCountSigned : valid account sle");
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");
161 XRPL_ASSERT(adjustment,
"xrpl::adjustOwnerCountSigned : nonzero adjustment input");
168 bool const validSponsorType = sponsorSle->getType() == ltACCOUNT_ROOT;
169 XRPL_ASSERT(validSponsorType,
"xrpl::adjustOwnerCountSigned : valid sponsor sle type");
170 if (!validSponsorType)
172 auto const sponsorID = sponsorSle->getAccountID(sfAccount);
174 totalOwnerCount.sponsored = adjustOwnerCountImpl(
175 view, accountSle, sfSponsoredOwnerCount, accountID, adjustment, j);
180 sponsorAdjustment.sponsoring = adjustOwnerCountImpl(
181 view, sponsorSle, sfSponsoringOwnerCount, sponsorID, adjustment, j);
182 view.adjustOwnerCountHook(sponsorID, sponsorCurrent, sponsorAdjustment);
186 if (sponsorshipSle && adjustment > 0)
192 adjustOwnerCountImpl(
193 view, sponsorshipSle, sfRemainingOwnerCount, sponsorID, -adjustment, j);
197 totalOwnerCount.owner =
198 adjustOwnerCountImpl(view, accountSle, sfOwnerCount, accountID, adjustment, j);
199 view.adjustOwnerCountHook(accountID, currentOwnerCount, totalOwnerCount);
203 XRPL_ASSERT(accountSle,
"xrpl::adjustOwnerCountSigned : valid account sle");
207 XRPL_ASSERT(sponsorSle ==
nullptr,
"xrpl::adjustOwnerCountSigned : sponsor not enabled");
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);
218 finalOwnerCount.owner = adjusted;
220 view.adjustOwnerCountHook(
id, currentOwnerCount, finalOwnerCount);
221 accountSle->at(sfOwnerCount) = adjusted;
222 view.update(accountSle);
231 XRPL_ASSERT(sle && sle->getType() == ltACCOUNT_ROOT,
"xrpl::ownerCount : sle is account root");
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);
239 currentOwnerCount >= sponsoredOwnerCount,
240 "xrpl::ownerCount : OwnerCount must be greater than or equal to SponsoredOwnerCount");
243 static_cast<std::int64_t>(ownerCountAdj) - sponsoredOwnerCount + sponsoringOwnerCount;
249 JLOG(j.
fatal()) <<
"Account " <<
id <<
" delta count exceeds max, "
250 <<
"adjustment: " << ownerCountAdj
251 <<
", sponsoredCount: " << sponsoredOwnerCount
252 <<
", sponsoringOwnerCount: " << sponsoringOwnerCount;
259 JLOG(j.
fatal()) <<
"Account " <<
id <<
" delta count is below min, "
260 <<
"adjustment: " << ownerCountAdj
261 <<
", sponsoredCount: " << sponsoredOwnerCount
262 <<
", sponsoringCount: " << sponsoringOwnerCount;
266 return confineOwnerCount(currentOwnerCount, deltaCount);
279 std::uint32_t const currentAccountCount = accountCountImpl(sle, 0, j);
286 auto const fullBalance = sle->getFieldAmount(sfBalance);
290 STAmount const amount = (balance < reserve) ?
STAmount{0} : balance - reserve;
292 JLOG(j.
trace()) <<
"accountHolds:" <<
" account=" <<
to_string(
id)
294 <<
" fullBalance=" << fullBalance.getFullText()
295 <<
" balance=" << balance.getFullText() <<
" reserve=" << reserve
296 <<
" ownerCount=" << currentOwnerCount <<
" ownerCountAdj=" << ownerCountAdj;
306 if (sle && sle->isFieldPresent(sfTransferRate))
307 return Rate{sle->getFieldU32(sfTransferRate)};
322 "xrpl::increaseOwnerCount : count in signed delta range");
326 adjustOwnerCountSigned(view, accountSle, sponsorSle,
static_cast<std::int32_t>(count), j);
337 sponsorExp.has_value(),
"xrpl::increaseOwnerCount : sponsor validated before mutation");
352 "xrpl::decreaseOwnerCount : count in signed delta range");
356 adjustOwnerCountSigned(view, accountSle, sponsorSle, -
static_cast<std::int32_t>(count), j);
367 XRPL_ASSERT(objectSle,
"xrpl::decreaseOwnerCountForObject : valid object sle");
371 bool const validObjectType = objectSle->getType() != ltACCOUNT_ROOT;
372 XRPL_ASSERT(validObjectType,
"xrpl::decreaseOwnerCountForObject : valid object sle type");
373 if (!validObjectType)
388 brokerSle && brokerSle->getType() == ltLOAN_BROKER,
389 "xrpl::adjustLoanBrokerOwnerCount : valid loan broker sle");
390 if (!brokerSle || brokerSle->getType() != ltLOAN_BROKER)
393 XRPL_ASSERT(delta != 0,
"xrpl::adjustLoanBrokerOwnerCount : nonzero delta input");
397 adjustOwnerCountImpl(
398 view, brokerSle, sfOwnerCount, brokerSle->getAccountID(sfAccount), delta, j);
404 XRPL_ASSERT(sle && sle->getType() == ltACCOUNT_ROOT,
"xrpl::accountReserve : valid sle");
408 XRPL_ASSERT(adj.
accountCountDelta == 0,
"xrpl::accountReserve : no account count delta");
425 TER insufReserveCode)
428 if (!accSle || accSle->getType() != ltACCOUNT_ROOT)
431 !
isTesSuccess(insufReserveCode),
"xrpl::checkReserve : insufReserveCode is not tesSUCCESS");
436 if (sponsorSle->getType() != ltACCOUNT_ROOT)
441 sponsorSle->getAccountID(sfAccount), accSle->getAccountID(sfAccount)));
451 auto const ownerCountAllowed = sle->getFieldU32(sfRemainingOwnerCount);
454 return insufReserveCode;
457 auto const sponsorBalance = sponsorSle->getFieldAmount(sfBalance).xrp();
460 if (sponsorBalance < sponsorReserve)
461 return insufReserveCode;
466 if (accBalance < reserve)
467 return insufReserveCode;
474 "xrpl::checkReserve : featureSponsor disabled and sponsorSle not provided");
475 XRPL_ASSERT(adj.
accountCountDelta == 0,
"xrpl::checkReserve : accountCountDelta is 0");
478 if (accBalance < reserve)
479 return insufReserveCode;
494 return sponsorExp.error();
495 return checkReserve(ctx, accSle, accBalance, *sponsorExp, adj, j);
509 rsh(hash.data(), hash.size());
532 "xrpl::getPseudoAccountFields : unable to find account root "
536 auto const& soTemplate = ar->getSOTemplate();
539 for (
auto const& field : soTemplate)
546 return kPseudoFields;
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));
564std::expected<SLE::pointer, TER>
573 [&ownerField](
SField const* sf) ->
bool { return *sf == ownerField; }) == 1,
574 "xrpl::createPseudoAccount : valid owner field");
582 account->setAccountID(sfAccount, accountId);
583 account->setFieldAmount(sfBalance,
STAmount{});
593 account->setFieldU32(sfSequence, seqno);
597 account->setFieldU32(sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth);
599 account->setFieldH256(ownerField, pseudoOwnerKey);
609 if (toSle ==
nullptr)
614 if (toSle->isFlag(lsfRequireDestTag) && !hasDestinationTag)
A generic endpoint for log messages.
static Sink & getNullSink()
Returns a Sink which does nothing.
Stream trace() const
Severity stream access functions.
Writeable view to a ledger, for applying a transaction.
virtual void insert(SLE::ref sle)=0
Insert a new state SLE.
static BaseUInt fromRaw(Container const &c)
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
virtual LedgerHeader const & header() const =0
Returns information about the ledger.
LedgerIndex seq() const
Returns the sequence number of the base ledger.
virtual STAmount balanceHookIOU(AccountID const &account, AccountID const &issuer, STAmount const &amount) const
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
static constexpr auto kSmdPseudoAccount
std::string getFullText() const override
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
T emplace_back(T... args)
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet sponsorship(AccountID const &sponsor, AccountID const &sponsee) noexcept
A Sponsorship.
std::uint32_t sponsoringAccountCount(Env const &env, Account const &account)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
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)
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.
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
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)
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.
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
TERSubset< CanCvtToTER > TER
AccountID const & xrpAccount()
Compute AccountID from public key.
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").
XRPAmount accountReserve(ReadView const &view, SLE::const_ref sle, beast::Journal j, Adjustment adj={})
Returns the account reserve, in drops.
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
std::int32_t accountCountDelta
std::int32_t ownerCountDelta
Bundles the mutable ledger view and the transaction being applied.
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.
Returns the RIPEMD-160 digest of the SHA256 hash of the message.
std::array< std::uint8_t, 20 > result_type