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>
42 return sle->isFlag(lsfGlobalFreeze);
61 std::uint32_t totalOwnerCount{currentOwnerCount + ownerCountAdj};
62 if (ownerCountAdj > 0)
65 if (totalOwnerCount < currentOwnerCount)
70 JLOG(j.fatal()) <<
"Account " << *
id <<
" owner count exceeds max!";
79 if (totalOwnerCount > currentOwnerCount)
84 JLOG(j.fatal()) <<
"Account " << *
id <<
" owner count set below 0!";
87 XRPL_ASSERT(!
id,
"xrpl::confineOwnerCount : id is not set");
91 return totalOwnerCount;
97accountCountImpl(
SLE::ConstRef sle, std::int32_t accountCountAdj, beast::Journal j)
99 bool const isSponsored = sle->isFieldPresent(sfSponsor);
101 std::int64_t
const currentAccountCount = (isSponsored ? 0 : 1) + sponsoringAccountCount;
103 std::int64_t totalAccountCount{currentAccountCount + accountCountAdj};
107 JLOG(j.
fatal()) <<
"Reserve count exceeds max!";
111 else if (totalAccountCount < 0)
114 UNREACHABLE(
"xrpl::accountCountImpl : Reserve count set below 0");
115 JLOG(j.
fatal()) <<
"Reserve count set below 0";
116 totalAccountCount = 0;
120 return totalAccountCount;
129 std::int32_t ownerCountAdj,
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;
137 return totalOwnerCount;
141adjustOwnerCountSigned(
145 std::int32_t adjustment,
148 if (view.rules().enabled(featureSponsor))
150 XRPL_ASSERT(accountSle,
"xrpl::adjustOwnerCountSigned : valid account sle");
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");
160 XRPL_ASSERT(adjustment,
"xrpl::adjustOwnerCountSigned : nonzero adjustment input");
167 bool const validSponsorType = sponsorSle->getType() == ltACCOUNT_ROOT;
168 XRPL_ASSERT(validSponsorType,
"xrpl::adjustOwnerCountSigned : valid sponsor sle type");
169 if (!validSponsorType)
171 auto const sponsorID = sponsorSle->getAccountID(sfAccount);
173 totalOwnerCount.sponsored = adjustOwnerCountImpl(
174 view, accountSle, sfSponsoredOwnerCount, accountID, adjustment, j);
179 sponsorAdjustment.sponsoring = adjustOwnerCountImpl(
180 view, sponsorSle, sfSponsoringOwnerCount, sponsorID, adjustment, j);
181 view.adjustOwnerCountHook(sponsorID, sponsorCurrent, sponsorAdjustment);
185 if (sponsorshipSle && adjustment > 0)
191 adjustOwnerCountImpl(
192 view, sponsorshipSle, sfRemainingOwnerCount, sponsorID, -adjustment, j);
196 totalOwnerCount.owner =
197 adjustOwnerCountImpl(view, accountSle, sfOwnerCount, accountID, adjustment, j);
198 view.adjustOwnerCountHook(accountID, currentOwnerCount, totalOwnerCount);
202 XRPL_ASSERT(accountSle,
"xrpl::adjustOwnerCountSigned : valid account sle");
206 XRPL_ASSERT(sponsorSle ==
nullptr,
"xrpl::adjustOwnerCountSigned : sponsor not enabled");
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);
217 finalOwnerCount.owner = adjusted;
219 view.adjustOwnerCountHook(
id, currentOwnerCount, finalOwnerCount);
220 accountSle->at(sfOwnerCount) = adjusted;
221 view.update(accountSle);
230 XRPL_ASSERT(sle && sle->getType() == ltACCOUNT_ROOT,
"xrpl::ownerCount : sle is account root");
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);
238 currentOwnerCount >= sponsoredOwnerCount,
239 "xrpl::ownerCount : OwnerCount must be greater than or equal to SponsoredOwnerCount");
242 static_cast<std::int64_t>(ownerCountAdj) - sponsoredOwnerCount + sponsoringOwnerCount;
248 JLOG(j.
fatal()) <<
"Account " <<
id <<
" delta count exceeds max, "
249 <<
"adjustment: " << ownerCountAdj
250 <<
", sponsoredCount: " << sponsoredOwnerCount
251 <<
", sponsoringOwnerCount: " << sponsoringOwnerCount;
258 JLOG(j.
fatal()) <<
"Account " <<
id <<
" delta count is below min, "
259 <<
"adjustment: " << ownerCountAdj
260 <<
", sponsoredCount: " << sponsoredOwnerCount
261 <<
", sponsoringCount: " << sponsoringOwnerCount;
265 return confineOwnerCount(currentOwnerCount, deltaCount);
278 std::uint32_t const currentAccountCount = accountCountImpl(sle, 0, j);
285 auto const fullBalance = sle->getFieldAmount(sfBalance);
289 STAmount const amount = (balance < reserve) ?
STAmount{0} : balance - reserve;
291 JLOG(j.
trace()) <<
"accountHolds:" <<
" account=" <<
to_string(
id)
293 <<
" fullBalance=" << fullBalance.getFullText()
294 <<
" balance=" << balance.getFullText() <<
" reserve=" << reserve
295 <<
" ownerCount=" << currentOwnerCount <<
" ownerCountAdj=" << ownerCountAdj;
305 if (sle && sle->isFieldPresent(sfTransferRate))
306 return Rate{sle->getFieldU32(sfTransferRate)};
321 "xrpl::increaseOwnerCount : count in signed delta range");
325 adjustOwnerCountSigned(view, accountSle, sponsorSle,
static_cast<std::int32_t>(count), j);
336 sponsorExp.has_value(),
"xrpl::increaseOwnerCount : sponsor validated before mutation");
351 "xrpl::decreaseOwnerCount : count in signed delta range");
355 adjustOwnerCountSigned(view, accountSle, sponsorSle, -
static_cast<std::int32_t>(count), j);
366 XRPL_ASSERT(objectSle,
"xrpl::decreaseOwnerCountForObject : valid object sle");
370 bool const validObjectType = objectSle->getType() != ltACCOUNT_ROOT;
371 XRPL_ASSERT(validObjectType,
"xrpl::decreaseOwnerCountForObject : valid object sle type");
372 if (!validObjectType)
387 brokerSle && brokerSle->getType() == ltLOAN_BROKER,
388 "xrpl::adjustLoanBrokerOwnerCount : valid loan broker sle");
389 if (!brokerSle || brokerSle->getType() != ltLOAN_BROKER)
392 XRPL_ASSERT(delta != 0,
"xrpl::adjustLoanBrokerOwnerCount : nonzero delta input");
396 adjustOwnerCountImpl(
397 view, brokerSle, sfOwnerCount, brokerSle->getAccountID(sfAccount), delta, j);
403 XRPL_ASSERT(sle && sle->getType() == ltACCOUNT_ROOT,
"xrpl::accountReserve : valid sle");
407 XRPL_ASSERT(adj.
accountCountDelta == 0,
"xrpl::accountReserve : no account count delta");
424 TER insufReserveCode)
427 if (!accSle || accSle->getType() != ltACCOUNT_ROOT)
430 !
isTesSuccess(insufReserveCode),
"xrpl::checkReserve : insufReserveCode is not tesSUCCESS");
435 if (sponsorSle->getType() != ltACCOUNT_ROOT)
440 sponsorSle->getAccountID(sfAccount), accSle->getAccountID(sfAccount)));
450 auto const ownerCountAllowed = sle->getFieldU32(sfRemainingOwnerCount);
453 return insufReserveCode;
456 auto const sponsorBalance = sponsorSle->getFieldAmount(sfBalance).xrp();
459 if (sponsorBalance < sponsorReserve)
460 return insufReserveCode;
465 if (accBalance < reserve)
466 return insufReserveCode;
473 "xrpl::checkReserve : featureSponsor disabled and sponsorSle not provided");
474 XRPL_ASSERT(adj.
accountCountDelta == 0,
"xrpl::checkReserve : accountCountDelta is 0");
477 if (accBalance < reserve)
478 return insufReserveCode;
493 return sponsorExp.error();
494 return checkReserve(ctx, accSle, accBalance, *sponsorExp, adj, j);
508 rsh(hash.data(), hash.size());
531 "xrpl::getPseudoAccountFields : unable to find account root "
535 auto const& soTemplate = ar->getSOTemplate();
538 for (
auto const& field : soTemplate)
545 return kPseudoFields;
553 return sleAcct && sleAcct->getType() == ltACCOUNT_ROOT &&
555 return sleAcct->isFieldPresent(*sf);
559std::expected<SLE::pointer, TER>
568 [&ownerField](
SField const* sf) ->
bool { return *sf == ownerField; }) == 1,
569 "xrpl::createPseudoAccount : valid owner field");
577 account->setAccountID(sfAccount, accountId);
578 account->setFieldAmount(sfBalance,
STAmount{});
588 account->setFieldU32(sfSequence, seqno);
592 account->setFieldU32(sfFlags, lsfDisableMaster | lsfDefaultRipple | lsfDepositAuth);
594 account->setFieldH256(ownerField, pseudoOwnerKey);
604 if (toSle ==
nullptr)
609 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 > 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
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.
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)
TER checkDestinationAndTag(SLE::ConstRef toSle, bool hasDestinationTag)
Checks the destination and tag.
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
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)
bool isGlobalFrozen(ReadView const &view, AccountID const &issuer)
Check if the issuer has the global freeze flag set.
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.
bool isTesSuccess(TER x) noexcept
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
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.
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Sha512HalfHasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
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