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/RawView.h>
7#include <xrpl/protocol/AccountID.h>
8#include <xrpl/protocol/Issue.h>
9#include <xrpl/protocol/MPTIssue.h>
10#include <xrpl/protocol/SField.h>
11#include <xrpl/protocol/UintTypes.h>
12#include <xrpl/protocol/XRPAmount.h>
41 STAmount const& preCreditSenderBalance)
44 sender != receiver,
"xrpl::detail::DeferredCredits::creditIOU : sender is not receiver");
45 XRPL_ASSERT(!amount.
negative(),
"xrpl::detail::DeferredCredits::creditIOU : positive amount");
47 amount.
holds<
Issue>(),
"xrpl::detail::DeferredCredits::creditIOU : amount is for Issue");
55 if (sender < receiver)
74 if (sender < receiver)
76 v.lowAcctDebits += amount;
80 v.highAcctDebits += amount;
95 "xrpl::detail::DeferredCredits::creditMPT : amount is for MPTIssue");
96 XRPL_ASSERT(!amount.
negative(),
"xrpl::detail::DeferredCredits::creditMPT : positive amount");
98 sender != receiver,
"xrpl::detail::DeferredCredits::creditMPT : sender is not receiver");
100 auto const mptAmtVal = amount.
mpt().
value();
103 auto const& mptID = mptIssue.
getMptID();
104 bool const isSenderIssuer = sender == issuer;
113 v.
holders[receiver].origBalance = preCreditBalanceHolder;
117 v.
holders[sender].debit = mptAmtVal;
118 v.
holders[sender].origBalance = preCreditBalanceHolder;
129 v.credit += mptAmtVal;
130 if (!v.holders.contains(receiver))
132 v.holders[receiver].origBalance = preCreditBalanceHolder;
137 if (!v.holders.contains(sender))
139 v.holders[sender].debit = mptAmtVal;
140 v.holders[sender].origBalance = preCreditBalanceHolder;
144 v.holders[sender].debit += mptAmtVal;
156 auto const& mptID = issue.
getMptID();
168 i->second.selfDebit += amount;
179 auto& mapVal = r.first->second;
207 auto const& v = i->second;
211 result.
emplace(v.lowAcctDebits, v.highAcctDebits, v.lowAcctOrigBalance);
215 result.
emplace(v.highAcctDebits, v.lowAcctDebits, -v.lowAcctOrigBalance);
236 auto& toVal = r.first->second;
237 auto const& fromVal = i.second;
238 toVal.lowAcctDebits += fromVal.lowAcctDebits;
239 toVal.highAcctDebits += fromVal.highAcctDebits;
249 auto& toVal = r.first->second;
250 auto const& fromVal = i.second;
251 toVal.credit += fromVal.credit;
252 toVal.selfDebit += fromVal.selfDebit;
253 for (
auto& [k, v] : fromVal.holders)
255 if (!toVal.holders.contains(k))
257 toVal.holders[k] = v;
261 toVal.holders[k].debit += v.debit;
273 auto& toVal = r.first->second;
274 auto const& fromVal = i.second;
288 XRPL_ASSERT(amount.
holds<
Issue>(),
"balanceHookIOU: amount is for Issue");
301 auto const& currency = amount.
get<
Issue>().currency;
303 auto delta = amount.
zeroed();
304 auto lastBal = amount;
305 auto minBal = amount;
306 for (
auto curSB =
this; curSB !=
nullptr; curSB = curSB->ps_)
308 if (
auto adj = curSB->tab_.adjustmentsIOU(account, issuer, currency))
310 delta += adj->debits;
311 lastBal = adj->origBalance;
312 if (lastBal < minBal)
321 auto adjustedAmt =
std::min({amount, lastBal - delta, minBal});
324 if (
isXRP(issuer) && adjustedAmt < beast::kZero)
341 bool const accountIsHolder = account != issuer;
346 for (
auto curSB =
this; curSB !=
nullptr; curSB = curSB->ps_)
348 if (
auto adj = curSB->tab_.adjustmentsMPT(issue))
352 if (
auto const i = adj->holders.find(account); i != adj->holders.end())
354 delta += i->second.debit;
355 lastBal = i->second.origBalance;
360 delta += adj->credit;
361 lastBal = adj->origBalance;
369 auto const adjustedAmt =
std::min({amount, lastBal - delta, minBal});
379 for (
auto curSB =
this; curSB !=
nullptr; curSB = curSB->ps_)
381 if (
auto adj = curSB->tab_.adjustmentsMPT(issue))
383 selfDebited += adj->selfDebit;
384 lastBal = adj->origBalance;
388 if (lastBal > selfDebited)
389 return STAmount{issue, lastBal - selfDebited};
398 for (
auto curSB =
this; curSB !=
nullptr; curSB = curSB->ps_)
400 if (
auto adj = curSB->tab_.ownerCount(account))
413 XRPL_ASSERT(amount.
holds<
Issue>(),
"creditHookIOU: amount is for Issue");
415 tab_.creditIOU(from, to, amount, preCreditBalance);
426 XRPL_ASSERT(amount.
holds<
MPTIssue>(),
"creditHookMPT: amount is for MPTIssue");
428 tab_.creditMPT(from, to, amount, preCreditBalanceHolder, preCreditBalanceIssuer);
437 XRPL_ASSERT(amount > 0,
"PaymentSandbox::issuerSelfDebitHookMPT: amount must be > 0");
439 tab_.issuerSelfDebitMPT(issue, amount, origBalance);
448 tab_.ownerCount(account, cur, next);
454 XRPL_ASSERT(!
ps_,
"xrpl::PaymentSandbox::apply : non-null sandbox");
461 XRPL_ASSERT(
ps_ == &to,
"xrpl::PaymentSandbox::apply : matching sandbox");
469 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
void adjustOwnerCountHook(AccountID const &account, std::uint32_t cur, std::uint32_t next) override
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
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_
std::uint32_t ownerCountHook(AccountID const &account, std::uint32_t 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 apply(DeferredCredits &to)
static KeyIOU makeKeyIOU(AccountID const &a1, AccountID const &a2, Currency const ¤cy)
std::map< AccountID, std::uint32_t > ownerCounts_
void creditIOU(AccountID const &sender, AccountID const &receiver, STAmount const &amount, STAmount const &preCreditSenderBalance)
void ownerCount(AccountID const &id, std::uint32_t cur, std::uint32_t next)
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::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