Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions cspell.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ suggestWords:
words:
- abempty
- AMMID
- AMMMPT
- AMMMPToken
- AMMMPTokens
- AMMXRP
- amt
- amts
- asnode
Expand Down Expand Up @@ -96,6 +100,7 @@ words:
- distro
- doxyfile
- dxrpl
- enabled
- endmacro
- exceptioned
- Falco
Expand Down Expand Up @@ -148,6 +153,8 @@ words:
- ltype
- mcmodel
- MEMORYSTATUSEX
- MPTAMM
- MPTDEX
- Merkle
- Metafuncton
- misprediction
Expand All @@ -157,6 +164,7 @@ words:
- mptid
- mptissuance
- mptissuanceid
- mptissue
- mptoken
- mptokenid
- mptokenissuance
Expand Down
51 changes: 50 additions & 1 deletion include/xrpl/ledger/ApplyView.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,60 @@
// Called when a credit is made to an account
// This is required to support PaymentSandbox
virtual void
creditHook(
creditHookIOU(
AccountID const& from,
AccountID const& to,
STAmount const& amount,
STAmount const& preCreditBalance)
{
XRPL_ASSERT(amount.holds<Issue>(), "creditHookIOU: amount is for Issue");
}

virtual void
creditHookMPT(
AccountID const& from,
AccountID const& to,
STAmount const& amount,
std::uint64_t preCreditBalanceHolder,
std::int64_t preCreditBalanceIssuer)
{
XRPL_ASSERT(amount.holds<MPTIssue>(), "creditHookMPT: amount is for MPTIssue");
}

/** Facilitate tracking of MPT sold by an issuer owning MPT sell offer.
* Unlike IOU, MPT doesn't have bi-directional relationship with an issuer,
* where a trustline limits an amount that can be issued to a holder.
* Consequently, the credit step (last MPTEndpointStep or
* BookStep buying MPT) might temporarily overflow OutstandingAmount.
* Limiting of a step's output amount in this case is delegated to
* the next step (in rev order). The next step always redeems when a holder
* account sells MPT (first MPTEndpointStep or BookStep selling MPT).
* In this case the holder account is only limited by the step's output
* and it's available funds since it's transferring the funds from one
* account to another account and doesn't change OutstandingAmount.
* This doesn't apply to an offer owned by an issuer.
* In this case the issuer sells or self debits and is increasing
* OutstandingAmount. Ability to issue is limited by the issuer
* originally available funds less already self sold MPT amounts (MPT sell
* offer).
* Consider an example:
* - GW creates MPT(USD) with 1,000USD MaximumAmount.
* - GW pays 950USD to A1.
* - A1 creates an offer 100XRP(buy)/100USD(sell).
* - GW creates an offer 100XRP(buy)/100USD(sell).
* - A2 pays 200USD to A3 with sendMax of 200XRP.
* Since the payment engine executes payments in reverse,
* OutstandingAmount overflows in MPTEndpointStep: 950 + 200 = 1,150USD.
* BookStep first consumes A1 offer. This reduces OutstandingAmount
* by 100USD: 1,150 - 100 = 1,050USD. GW offer can only be partially
* consumed because the initial available amount is 50USD = 1,000 - 950.
* BookStep limits it's output to 150USD. This in turn limits A3's send
* amount to 150XRP: A1 buys 100XRP and sells 100USD to A3. This doesn't
* change OutstandingAmount. GW buys 50XRP and sells 50USD to A3. This
* changes OutstandingAmount to 1,000USD.
*/
virtual void
issuerSelfDebitHookMPT(MPTIssue const& issue, std::uint64_t amount, std::int64_t origBalance)

Check warning on line 269 in include/xrpl/ledger/ApplyView.h

View check run for this annotation

Codecov / codecov/patch

include/xrpl/ledger/ApplyView.h#L269

Added line #L269 was not covered by tests
{
}

Expand Down
14 changes: 7 additions & 7 deletions include/xrpl/ledger/OrderBookDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
#include <xrpl/ledger/AcceptedLedgerTx.h>
#include <xrpl/ledger/BookListeners.h>
#include <xrpl/ledger/ReadView.h>
#include <xrpl/protocol/Asset.h>
#include <xrpl/protocol/Book.h>
#include <xrpl/protocol/Issue.h>
#include <xrpl/protocol/MultiApiJson.h>
#include <xrpl/protocol/UintTypes.h>

Expand Down Expand Up @@ -53,30 +53,30 @@ class OrderBookDB
issue. This is useful for pathfinding to find all possible next hops
from a given currency.

@param issue The issue to search for
@param asset The asset to search for
@param domain Optional domain restriction for the order book
@return Vector of books that want this issue
*/
virtual std::vector<Book>
getBooksByTakerPays(Issue const& issue, std::optional<Domain> const& domain = std::nullopt) = 0;
getBooksByTakerPays(Asset const& asset, std::optional<Domain> const& domain = std::nullopt) = 0;
Comment thread
bthomee marked this conversation as resolved.

/** Get the count of order books that want a specific issue.

@param issue The issue to search for
@param asset The asset to search for
@param domain Optional domain restriction for the order book
@return Number of books that want this issue
*/
virtual int
getBookSize(Issue const& issue, std::optional<Domain> const& domain = std::nullopt) = 0;
getBookSize(Asset const& asset, std::optional<Domain> const& domain = std::nullopt) = 0;

/** Check if an order book to XRP exists for the given issue.

@param issue The issue to check
@param asset The asset to check
@param domain Optional domain restriction for the order book
@return true if a book from this issue to XRP exists
*/
virtual bool
isBookToXRP(Issue const& issue, std::optional<Domain> const& domain = std::nullopt) = 0;
isBookToXRP(Asset const& asset, std::optional<Domain> const& domain = std::nullopt) = 0;

/**
* Process a transaction for order book tracking.
Expand Down
110 changes: 89 additions & 21 deletions include/xrpl/ledger/PaymentSandbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,55 @@ namespace detail {
// into the PaymentSandbox class itself
class DeferredCredits
{
private:
using KeyIOU = std::tuple<AccountID, AccountID, Currency>;
struct ValueIOU
{
explicit ValueIOU() = default;

STAmount lowAcctCredits;
STAmount highAcctCredits;
STAmount lowAcctOrigBalance;
};

struct HolderValueMPT
{
HolderValueMPT() = default;
// Debit to issuer
std::uint64_t debit = 0;
std::uint64_t origBalance = 0;
};

struct IssuerValueMPT
{
IssuerValueMPT() = default;
std::map<AccountID, HolderValueMPT> holders;
// Credit to holder
std::uint64_t credit = 0;
// OutstandingAmount might overflow when MPTs are credited to a holder.
// Consider A1 paying 100MPT to A2 and A1 already having maximum MPTs.
// Since the payment engine executes a payment in revers, A2 is
// credited first and OutstandingAmount is going to be equal
// to MaximumAmount + 100MPT. In the next step A1 redeems 100MPT
// to the issuer and OutstandingAmount balances out.
std::int64_t origBalance = 0;
// Self debit on offer selling MPT. Since the payment engine executes
// a payment in reverse, a crediting/buying step may overflow
// OutstandingAmount. A sell MPT offer owned by a holder can redeem any
// amount up to the offer's amount and holder's available funds,
// balancing out OutstandingAmount. But if the offer's owner is issuer
// then it issues more MPT. In this case the available amount to issue
// is the initial issuer's available amount less all offer sell amounts
// by the issuer. This is self-debit, where the offer's owner,
// issuer in this case, debits to self.
std::uint64_t selfDebit = 0;
};
using AdjustmentMPT = IssuerValueMPT;

public:
struct Adjustment
struct AdjustmentIOU
{
Adjustment(STAmount const& d, STAmount const& c, STAmount const& b)
AdjustmentIOU(STAmount const& d, STAmount const& c, STAmount const& b)
: debits(d), credits(c), origBalance(b)
{
}
Expand All @@ -29,16 +74,30 @@ class DeferredCredits

// Get the adjustments for the balance between main and other.
// Returns the debits, credits and the original balance
std::optional<Adjustment>
adjustments(AccountID const& main, AccountID const& other, Currency const& currency) const;
std::optional<AdjustmentIOU>
adjustmentsIOU(AccountID const& main, AccountID const& other, Currency const& currency) const;

std::optional<AdjustmentMPT>
adjustmentsMPT(MPTID const& mptID) const;

void
credit(
creditIOU(
AccountID const& sender,
AccountID const& receiver,
STAmount const& amount,
STAmount const& preCreditSenderBalance);

void
creditMPT(
AccountID const& sender,
AccountID const& receiver,
STAmount const& amount,
std::uint64_t preCreditBalanceHolder,
std::int64_t preCreditBalanceIssuer);

void
issuerSelfDebitMPT(MPTIssue const& issue, std::uint64_t amount, std::int64_t origBalance);

void
ownerCount(AccountID const& id, std::uint32_t cur, std::uint32_t next);

Expand All @@ -52,21 +111,11 @@ class DeferredCredits
apply(DeferredCredits& to);

private:
// lowAccount, highAccount
using Key = std::tuple<AccountID, AccountID, Currency>;
struct Value
{
explicit Value() = default;

STAmount lowAcctCredits;
STAmount highAcctCredits;
STAmount lowAcctOrigBalance;
};

static Key
makeKey(AccountID const& a1, AccountID const& a2, Currency const& c);
static KeyIOU
makeKeyIOU(AccountID const& a1, AccountID const& a2, Currency const& currency);

std::map<Key, Value> credits_;
std::map<KeyIOU, ValueIOU> creditsIOU_;
std::map<MPTID, IssuerValueMPT> creditsMPT_;
std::map<AccountID, std::uint32_t> ownerCounts_;
};

Expand Down Expand Up @@ -131,16 +180,35 @@ class PaymentSandbox final : public detail::ApplyViewBase
/** @} */

STAmount
balanceHook(AccountID const& account, AccountID const& issuer, STAmount const& amount)
balanceHookIOU(AccountID const& account, AccountID const& issuer, STAmount const& amount)
const override;

STAmount
balanceHookMPT(AccountID const& account, MPTIssue const& issue, std::int64_t amount)
const override;

STAmount
balanceHookSelfIssueMPT(MPTIssue const& issue, std::int64_t amount) const override;

void
creditHook(
creditHookIOU(
AccountID const& from,
AccountID const& to,
STAmount const& amount,
STAmount const& preCreditBalance) override;

void
creditHookMPT(
AccountID const& from,
AccountID const& to,
STAmount const& amount,
std::uint64_t preCreditBalanceHolder,
std::int64_t preCreditBalanceIssuer) override;

void
issuerSelfDebitHookMPT(MPTIssue const& issue, std::uint64_t amount, std::int64_t origBalance)
override;

void
adjustOwnerCountHook(AccountID const& account, std::uint32_t cur, std::uint32_t next) override;

Expand Down
24 changes: 22 additions & 2 deletions include/xrpl/ledger/ReadView.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,35 @@

// Accounts in a payment are not allowed to use assets acquired during that
// payment. The PaymentSandbox tracks the debits, credits, and owner count
// changes that accounts make during a payment. `balanceHook` adjusts
// changes that accounts make during a payment. `balanceHookIOU` adjusts
// balances so newly acquired assets are not counted toward the balance.
// This is required to support PaymentSandbox.
virtual STAmount
balanceHook(AccountID const& account, AccountID const& issuer, STAmount const& amount) const
balanceHookIOU(AccountID const& account, AccountID const& issuer, STAmount const& amount) const
{
XRPL_ASSERT(amount.holds<Issue>(), "balanceHookIOU: amount is for Issue");

return amount;
}

// balanceHookMPT adjusts balances so newly acquired assets are not counted
// toward the balance.
virtual STAmount
balanceHookMPT(AccountID const& account, MPTIssue const& issue, std::int64_t amount) const
{
return STAmount{issue, amount};
}

// An offer owned by an issuer and selling MPT is limited by the issuer's
// funds available to issue, which are originally available funds less
// already self sold MPT amounts (MPT sell offer). This hook is used
// by issuerFundsToSelfIssue() function.
virtual STAmount
balanceHookSelfIssueMPT(MPTIssue const& issue, std::int64_t amount) const

Check warning on line 175 in include/xrpl/ledger/ReadView.h

View check run for this annotation

Codecov / codecov/patch

include/xrpl/ledger/ReadView.h#L175

Added line #L175 was not covered by tests
{
return STAmount{issue, amount};

Check warning on line 177 in include/xrpl/ledger/ReadView.h

View check run for this annotation

Codecov / codecov/patch

include/xrpl/ledger/ReadView.h#L177

Added line #L177 was not covered by tests
}

// Accounts in a payment are not allowed to use assets acquired during that
// payment. The PaymentSandbox tracks the debits, credits, and owner count
// changes that accounts make during a payment. `ownerCountHook` adjusts the
Expand Down
4 changes: 2 additions & 2 deletions include/xrpl/ledger/View.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ isVaultPseudoAccountFrozen(
isLPTokenFrozen(
ReadView const& view,
AccountID const& account,
Issue const& asset,
Issue const& asset2);
Asset const& asset,
Asset const& asset2);

// Return the list of enabled amendments
[[nodiscard]] std::set<uint256>
Expand Down
Loading
Loading