1#include <xrpl/tx/paths/OfferStream.h>
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/Number.h>
5#include <xrpl/basics/base_uint.h>
6#include <xrpl/basics/chrono.h>
7#include <xrpl/beast/utility/Journal.h>
8#include <xrpl/beast/utility/Zero.h>
9#include <xrpl/beast/utility/instrumentation.h>
10#include <xrpl/ledger/ApplyView.h>
11#include <xrpl/ledger/ReadView.h>
12#include <xrpl/ledger/helpers/MPTokenHelpers.h>
13#include <xrpl/ledger/helpers/PermissionedDEXHelpers.h>
14#include <xrpl/ledger/helpers/RippleStateHelpers.h>
15#include <xrpl/ledger/helpers/TokenHelpers.h>
16#include <xrpl/protocol/AccountID.h>
17#include <xrpl/protocol/Asset.h>
18#include <xrpl/protocol/Book.h>
19#include <xrpl/protocol/Concepts.h>
20#include <xrpl/protocol/Feature.h>
21#include <xrpl/protocol/IOUAmount.h>
22#include <xrpl/protocol/Indexes.h>
23#include <xrpl/protocol/MPTAmount.h>
24#include <xrpl/protocol/MPTIssue.h>
25#include <xrpl/protocol/Quality.h>
26#include <xrpl/protocol/SField.h>
27#include <xrpl/protocol/STLedgerEntry.h>
28#include <xrpl/protocol/XRPAmount.h>
41 auto issuerExists = [](
ReadView const& view,
Asset const& asset) ->
bool {
42 auto const& issuer = asset.getIssuer();
45 return issuerExists(view,
book.in) && issuerExists(view,
book.out);
49template <StepAmount TIn, StepAmount TOut>
66 XRPL_ASSERT(
validBook_,
"xrpl::TOfferStreamBase::TOfferStreamBase : valid book");
71template <StepAmount TIn, StepAmount TOut>
83 JLOG(
j_.error()) <<
"Missing directory " <<
tip_.dir() <<
" for offer " <<
tip_.index();
87 auto v(p->getFieldV256(sfIndexes));
92 JLOG(
j_.error()) <<
"Missing offer " <<
tip_.index() <<
" for directory " <<
tip_.dir();
97 p->setFieldV256(sfIndexes, v);
100 JLOG(
j_.trace()) <<
"Missing offer " <<
tip_.index() <<
" removed from directory "
104template <StepAmount T>
134template <StepAmount TIn, StepAmount TOut>
135template <
class TTakerPays,
class TTakerGets>
136 requires ValidTaker<TTakerPays, TTakerGets>
146 if constexpr (!kInIsIntegral && kOutIsIntegral)
161 if constexpr (!kInIsIntegral && !kOutIsIntegral)
169 auto const effectiveAmounts = [&] {
173 bool const issuerHasUnlimitedFunds =
offer_.owner() ==
offer_.assetOut().getIssuer() &&
174 offer_.assetOut().template holds<Issue>();
187 if (effectiveAmounts.in.signum() <= 0 || effectiveAmounts.out.signum() <= 0)
190 if (effectiveAmounts.in > TTakerPays::minPositiveAmount())
193 Quality const effectiveQuality{effectiveAmounts};
194 return effectiveQuality <
offer_.quality();
197template <StepAmount TIn, StepAmount TOut>
232 if (entry->isFieldPresent(sfExpiration) && tp{d{(*entry)[sfExpiration]}} <=
expire_)
234 JLOG(
j_.trace()) <<
"Removing expired offer " << entry->key();
241 auto const amount(
offer_.amount());
246 JLOG(
j_.warn()) <<
"Removing bad offer " << entry->key();
254 JLOG(
j_.trace()) <<
"Removing deep frozen unfunded offer " << entry->key();
265 if ((!
view_.rules().enabled(fixCleanup3_3_0) ||
book_.domain.has_value()) &&
266 entry->isFieldPresent(sfDomainID) &&
268 view_, entry->key(), entry->getFieldH256(sfDomainID),
j_))
270 JLOG(
j_.trace()) <<
"Removing offer no longer in domain " << entry->key();
304 JLOG(
j_.trace()) <<
"Removing unfunded offer " << entry->key();
308 JLOG(
j_.trace()) <<
"Removing became unfunded offer " << entry->key();
318 bool shouldRemoveSmallIncreasedQOffer =
false;
325 if (
view_.rules().enabled(featureMPTokensV2))
329 "OfferStream::step removed MPT offer with overflowing "
332 JLOG(
j_.warn()) <<
"Removing offer with overflowing reduced quality "
343 view_.rules().enabled(featureMPTokensV2),
344 "xrpl::TOfferStreamBase::step : overflow implies MPTokensV2");
349 if (shouldRemoveSmallIncreasedQOffer)
363 JLOG(
j_.trace()) <<
"Removing tiny offer due to reduced quality " << entry->key();
367 JLOG(
j_.trace()) <<
"Removing tiny offer that became tiny due "
368 "to reduced quality "
382template <StepAmount TIn, StepAmount TOut>
A generic endpoint for log messages.
Writeable view to a ledger, for applying a transaction.
virtual SLE::pointer peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void update(SLE::ref sle)=0
Indicate changes to a peeked SLE.
constexpr TIss const & get() const
AccountID const & getIssuer() const
Presents and consumes the offers in an order book.
boost::container::flat_set< uint256 > permToRemove_
void permRmOffer(uint256 const &offerIndex) override
std::chrono::time_point< NetClock > time_point
std::chrono::duration< rep, period > duration
Number is a floating point type that can represent a wide range of values.
Represents the logical ratio of output currency to input currency.
std::shared_ptr< STLedgerEntry > pointer
std::optional< TOut > ownerFunds_
TOfferStreamBase(ApplyView &view, ApplyView &cancelView, Book const &book, NetClock::time_point when, StepCounter &counter, beast::Journal journal)
bool shouldRmSmallIncreasedQOffer() const
NetClock::time_point const expire_
TOffer< TIn, TOut > offer_
virtual void permRmOffer(uint256 const &offerIndex)=0
bool step()
Advance to the next valid offer.
void erase(ApplyView &view)
Keylet book(Book const &b)
The beginning of an order book.
Keylet page(uint256 const &root, std::uint64_t const index=0) noexcept
A page in a directory.
Keylet account(AccountID const &id) noexcept
AccountID root.
bool offerInDomain(ReadView const &view, uint256 const &offerID, Domain const &domainID, beast::Journal j)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
static T accountFundsHelper(ReadView const &view, AccountID const &id, T const &amtDefault, Asset const &asset, FreezeHandling freezeHandling, AuthHandling authHandling, beast::Journal j)
FreezeHandling
Controls the treatment of frozen account balances.
bool isXRP(AccountID const &c)
bool isDeepFrozen(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer)
T toAmount(STAmount const &amt)=delete
AuthHandling
Controls the treatment of unauthorized MPT balances.
BaseUInt< 160, detail::AccountIDTag > AccountID
A 160-bit unsigned that uniquely identifies an account.
void erase(STObject &st, TypedField< U > const &f)
Remove a field in an STObject.
STAmount issuerFundsToSelfIssue(ReadView const &view, MPTIssue const &issue)
Determine funds available for an issuer to sell in an issuer owned offer.
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=SpendableHandling::SimpleBalance)
Represents a pair of input and output currencies.