1#include <xrpl/ledger/PaymentSandbox.h>
3#include <xrpl/basics/base_uint.h>
4#include <xrpl/beast/utility/Zero.h>
5#include <xrpl/beast/utility/instrumentation.h>
6#include <xrpl/ledger/OwnerCounts.h>
7#include <xrpl/ledger/RawView.h>
8#include <xrpl/protocol/AccountID.h>
9#include <xrpl/protocol/Issue.h>
10#include <xrpl/protocol/MPTIssue.h>
11#include <xrpl/protocol/SField.h>
12#include <xrpl/protocol/UintTypes.h>
13#include <xrpl/protocol/XRPAmount.h>
42 STAmount const& preCreditSenderBalance)
45 sender != receiver,
"xrpl::detail::DeferredCredits::creditIOU : sender is not receiver");
46 XRPL_ASSERT(!amount.
negative(),
"xrpl::detail::DeferredCredits::creditIOU : positive amount");
48 amount.
holds<
Issue>(),
"xrpl::detail::DeferredCredits::creditIOU : amount is for Issue");
56 if (sender < receiver)
75 if (sender < receiver)
77 v.lowAcctDebits += amount;
81 v.highAcctDebits += amount;
96 "xrpl::detail::DeferredCredits::creditMPT : amount is for MPTIssue");
97 XRPL_ASSERT(!amount.
negative(),
"xrpl::detail::DeferredCredits::creditMPT : positive amount");
99 sender != receiver,
"xrpl::detail::DeferredCredits::creditMPT : sender is not receiver");
101 auto const mptAmtVal = amount.
mpt().
value();
104 auto const& mptID = mptIssue.
getMptID();
105 bool const isSenderIssuer = sender == issuer;
114 v.
holders[receiver].origBalance = preCreditBalanceHolder;
118 v.
holders[sender].debit = mptAmtVal;
119 v.
holders[sender].origBalance = preCreditBalanceHolder;
130 v.credit += mptAmtVal;
131 if (!v.holders.contains(receiver))
133 v.holders[receiver].origBalance = preCreditBalanceHolder;
138 if (!v.holders.contains(sender))
140 v.holders[sender].debit = mptAmtVal;
141 v.holders[sender].origBalance = preCreditBalanceHolder;
145 v.holders[sender].debit += mptAmtVal;
157 auto const& mptID = issue.
getMptID();
169 i->second.selfDebit += amount;
180 auto& mapVal = r.first->second;
208 auto const& v = i->second;
212 result.
emplace(v.lowAcctDebits, v.highAcctDebits, v.lowAcctOrigBalance);
216 result.
emplace(v.highAcctDebits, v.lowAcctDebits, -v.lowAcctOrigBalance);
237 auto& toVal = r.first->second;
238 auto const& fromVal = i.second;
239 toVal.lowAcctDebits += fromVal.lowAcctDebits;
240 toVal.highAcctDebits += fromVal.highAcctDebits;
250 auto& toVal = r.first->second;
251 auto const& fromVal = i.second;
252 toVal.credit += fromVal.credit;
253 toVal.selfDebit += fromVal.selfDebit;
254 for (
auto& [k, v] : fromVal.holders)
256 if (!toVal.holders.contains(k))
258 toVal.holders[k] = v;
262 toVal.holders[k].debit += v.debit;
274 auto& toVal = r.first->second;
275 auto const& fromVal = i.second;
289 XRPL_ASSERT(amount.
holds<
Issue>(),
"balanceHookIOU: amount is for Issue");
302 auto const& currency = amount.
get<
Issue>().currency;
304 auto delta = amount.
zeroed();
305 auto lastBal = amount;
306 auto minBal = amount;
307 for (
auto curSB =
this; curSB !=
nullptr; curSB = curSB->ps_)
309 if (
auto adj = curSB->tab_.adjustmentsIOU(account, issuer, currency))
311 delta += adj->debits;
312 lastBal = adj->origBalance;
313 if (lastBal < minBal)
322 auto adjustedAmt =
std::min({amount, lastBal - delta, minBal});
342 bool const accountIsHolder = account != issuer;
347 for (
auto curSB =
this; curSB !=
nullptr; curSB = curSB->ps_)
349 if (
auto adj = curSB->tab_.adjustmentsMPT(issue))
353 if (
auto const i = adj->holders.find(account); i != adj->holders.end())
355 delta += i->second.debit;
356 lastBal = i->second.origBalance;
361 delta += adj->credit;
362 lastBal = adj->origBalance;
370 auto const adjustedAmt =
std::min({amount, lastBal - delta, minBal});
380 for (
auto curSB =
this; curSB !=
nullptr; curSB = curSB->ps_)
382 if (
auto adj = curSB->tab_.adjustmentsMPT(issue))
384 selfDebited += adj->selfDebit;
385 lastBal = adj->origBalance;
389 if (lastBal > selfDebited)
390 return STAmount{issue, lastBal - selfDebited};
399 for (
auto curSB =
this; curSB !=
nullptr; curSB = curSB->ps_)
401 if (
auto adj = curSB->tab_.ownerCount(account))
414 XRPL_ASSERT(amount.
holds<
Issue>(),
"creditHookIOU: amount is for Issue");
416 tab_.creditIOU(from, to, amount, preCreditBalance);
427 XRPL_ASSERT(amount.
holds<
MPTIssue>(),
"creditHookMPT: amount is for MPTIssue");
429 tab_.creditMPT(from, to, amount, preCreditBalanceHolder, preCreditBalanceIssuer);
438 XRPL_ASSERT(amount > 0,
"PaymentSandbox::issuerSelfDebitHookMPT: amount must be > 0");
440 tab_.issuerSelfDebitMPT(issue, amount, origBalance);
449 tab_.ownerCount(account, cur, next);
455 XRPL_ASSERT(!
ps_,
"xrpl::PaymentSandbox::apply : non-null sandbox");
462 XRPL_ASSERT(
ps_ == &to,
"xrpl::PaymentSandbox::apply : matching sandbox");
470 return items_.dropsDestroyed();
A currency issued by an account.
constexpr value_type value() const
Returns the underlying value.
constexpr MPTID const & getMptID() const
AccountID const & getIssuer() const
STAmount balanceHookMPT(AccountID const &account, MPTIssue const &issue, std::int64_t amount) const override
void creditHookMPT(AccountID const &from, AccountID const &to, STAmount const &amount, std::uint64_t preCreditBalanceHolder, std::int64_t preCreditBalanceIssuer) override
STAmount balanceHookIOU(AccountID const &account, AccountID const &issuer, STAmount const &amount) const override
void creditHookIOU(AccountID const &from, AccountID const &to, STAmount const &amount, STAmount const &preCreditBalance) override
void adjustOwnerCountHook(AccountID const &account, OwnerCounts const &cur, OwnerCounts const &next) override
PaymentSandbox const * ps_
void issuerSelfDebitHookMPT(MPTIssue const &issue, std::uint64_t amount, std::int64_t origBalance) override
Facilitate tracking of MPT sold by an issuer owning MPT sell offer.
void apply(RawView &to)
Apply changes to base view.
detail::DeferredCredits tab_
OwnerCounts ownerCountHook(AccountID const &account, OwnerCounts const &count) const override
STAmount balanceHookSelfIssueMPT(MPTIssue const &issue, std::int64_t amount) const override
XRPAmount xrpDestroyed() const
Interface for ledger entry changes.
constexpr bool holds() const noexcept
constexpr TIss const & get() const
bool negative() const noexcept
STAmount zeroed() const
Returns a zero value with the same issuer and currency.
AccountID const & getIssuer() const
detail::ApplyStateTable items_
std::optional< AdjustmentIOU > adjustmentsIOU(AccountID const &main, AccountID const &other, Currency const ¤cy) const
std::map< MPTID, IssuerValueMPT > creditsMPT_
void ownerCount(AccountID const &id, OwnerCounts const &cur, OwnerCounts const &next)
void apply(DeferredCredits &to)
static KeyIOU makeKeyIOU(AccountID const &a1, AccountID const &a2, Currency const ¤cy)
void creditIOU(AccountID const &sender, AccountID const &receiver, STAmount const &amount, STAmount const &preCreditSenderBalance)
std::map< KeyIOU, ValueIOU > creditsIOU_
void creditMPT(AccountID const &sender, AccountID const &receiver, STAmount const &amount, std::uint64_t preCreditBalanceHolder, std::int64_t preCreditBalanceIssuer)
std::map< AccountID, OwnerCounts > ownerCounts_
std::tuple< AccountID, AccountID, Currency > KeyIOU
std::optional< AdjustmentMPT > adjustmentsMPT(MPTID const &mptID) const
void issuerSelfDebitMPT(MPTIssue const &issue, std::uint64_t amount, std::int64_t origBalance)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
bool isXRP(AccountID const &c)
BaseUInt< 160, detail::CurrencyTag > Currency
Currency is a hash representing a specific currency.
BaseUInt< 192 > MPTID
MPTID is a 192-bit value representing MPT Issuance ID, which is a concatenation of a 32-bit sequence ...
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
std::map< AccountID, HolderValueMPT > holders
STAmount lowAcctOrigBalance