20#include <xrpld/app/tx/detail/OfferStream.h>
22#include <xrpl/basics/Log.h>
23#include <xrpl/protocol/Feature.h>
29checkIssuers(ReadView
const& view, Book
const& book)
31 auto issuerExists = [](ReadView
const& view, Issue
const& iss) ->
bool {
34 return issuerExists(view, book.in) && issuerExists(view, book.out);
38template <
class TIn,
class TOut>
48 , cancelView_(cancelView)
50 , validBook_(checkIssuers(view, book))
56 validBook_,
"ripple::TOfferStreamBase::TOfferStreamBase : valid book");
61template <
class TIn,
class TOut>
73 JLOG(j_.
error()) <<
"Missing directory " << tip_.dir() <<
" for offer "
78 auto v(p->getFieldV256(sfIndexes));
79 auto it(
std::find(v.begin(), v.end(), tip_.index()));
83 JLOG(j_.
error()) <<
"Missing offer " << tip_.index()
84 <<
" for directory " << tip_.dir();
89 p->setFieldV256(sfIndexes, v);
92 JLOG(j_.
trace()) <<
"Missing offer " << tip_.index()
93 <<
" removed from directory " << tip_.dir();
105 return accountFunds(view,
id, saDefault, freezeHandling, j);
138template <
class TIn,
class TOut>
139template <
class TTakerPays,
class TTakerGets>
144 std::is_same_v<TTakerPays, IOUAmount> ||
145 std::is_same_v<TTakerPays, XRPAmount>,
146 "STAmount is not supported");
149 std::is_same_v<TTakerGets, IOUAmount> ||
150 std::is_same_v<TTakerGets, XRPAmount>,
151 "STAmount is not supported");
154 !std::is_same_v<TTakerPays, XRPAmount> ||
155 !std::is_same_v<TTakerGets, XRPAmount>,
156 "Cannot have XRP/XRP offers");
158 if (!view_.rules().enabled(fixRmSmallIncreasedQOffers))
164 constexpr bool const inIsXRP = std::is_same_v<TTakerPays, XRPAmount>;
165 constexpr bool const outIsXRP = std::is_same_v<TTakerGets, XRPAmount>;
167 if constexpr (outIsXRP)
176 TAmounts<TTakerPays, TTakerGets>
const ofrAmts{
177 toAmount<TTakerPays>(offer_.amount().in),
178 toAmount<TTakerGets>(offer_.amount().out)};
180 if constexpr (!inIsXRP && !outIsXRP)
182 if (ofrAmts.in >= ofrAmts.out)
186 TTakerGets
const ownerFunds = toAmount<TTakerGets>(*ownerFunds_);
187 bool const fixReduced = view_.rules().enabled(fixReducedOffersV1);
189 auto const effectiveAmounts = [&] {
190 if (offer_.owner() != offer_.issueOut().account &&
191 ownerFunds < ofrAmts.out)
199 return offer_.quality().ceil_out_strict(
200 ofrAmts, ownerFunds,
false);
202 return offer_.quality().ceil_out(ofrAmts, ownerFunds);
210 (effectiveAmounts.in.signum() <= 0 ||
211 effectiveAmounts.out.signum() <= 0))
214 if (effectiveAmounts.in > TTakerPays::minPositiveAmount())
217 Quality
const effectiveQuality{effectiveAmounts};
218 return effectiveQuality < offer_.quality();
221template <
class TIn,
class TOut>
233 ownerFunds_ = std::nullopt;
242 if (!counter_.step())
256 if (entry->isFieldPresent(sfExpiration) &&
257 tp{d{(*entry)[sfExpiration]}} <= expire_)
259 JLOG(j_.
trace()) <<
"Removing expired offer " << entry->key();
260 permRmOffer(entry->key());
266 auto const amount(offer_.amount());
271 JLOG(j_.
warn()) <<
"Removing bad offer " << entry->key();
272 permRmOffer(entry->key());
280 offer_.issueIn().currency,
281 offer_.issueIn().account);
285 <<
"Removing deep frozen unfunded offer " << entry->key();
286 permRmOffer(entry->key());
301 if (*ownerFunds_ <= beast::zero)
314 if (original_funds == *ownerFunds_)
316 permRmOffer(entry->key());
317 JLOG(j_.
trace()) <<
"Removing unfunded offer " << entry->key();
322 <<
"Removing became unfunded offer " << entry->key();
329 bool const rmSmallIncreasedQOffer = [&] {
330 bool const inIsXRP =
isXRP(offer_.issueIn());
331 bool const outIsXRP =
isXRP(offer_.issueOut());
332 if (inIsXRP && !outIsXRP)
340 if constexpr (!(std::is_same_v<TIn, IOUAmount> ||
341 std::is_same_v<TOut, XRPAmount>))
342 return shouldRmSmallIncreasedQOffer<XRPAmount, IOUAmount>();
344 if (!inIsXRP && outIsXRP)
347 if constexpr (!(std::is_same_v<TIn, XRPAmount> ||
348 std::is_same_v<TOut, IOUAmount>))
349 return shouldRmSmallIncreasedQOffer<IOUAmount, XRPAmount>();
351 if (!inIsXRP && !outIsXRP)
354 if constexpr (!(std::is_same_v<TIn, XRPAmount> ||
355 std::is_same_v<TOut, XRPAmount>))
356 return shouldRmSmallIncreasedQOffer<IOUAmount, IOUAmount>();
359 "rippls::TOfferStreamBase::step::rmSmallIncreasedQOffer : XRP "
364 if (rmSmallIncreasedQOffer)
374 if (original_funds == *ownerFunds_)
376 permRmOffer(entry->key());
378 <<
"Removing tiny offer due to reduced quality "
383 JLOG(j_.
trace()) <<
"Removing tiny offer that became tiny due "
384 "to reduced quality "
399OfferStream::permRmOffer(
uint256 const& offerIndex)
401 offerDelete(cancelView_, cancelView_.peek(keylet::offer(offerIndex)), j_);
404template <
class TIn,
class TOut>
408 permToRemove_.insert(offerIndex);
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
Writeable view to a ledger, for applying a transaction.
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
Presents and consumes the offers in an order book.
Floating point representation of amounts with high dynamic range.
A currency issued by an account.
std::chrono::time_point< NetClock > time_point
std::chrono::duration< rep, period > duration
void erase(ApplyView &view)
bool step()
Advance to the next valid offer.
TOfferStreamBase(ApplyView &view, ApplyView &cancelView, Book const &book, NetClock::time_point when, StepCounter &counter, beast::Journal journal)
bool shouldRmSmallIncreasedQOffer() const
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, 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)
static STAmount accountFundsHelper(ReadView const &view, AccountID const &id, STAmount const &saDefault, Issue const &, FreezeHandling freezeHandling, beast::Journal j)
IOUAmount toAmount< IOUAmount >(STAmount const &amt)
TER offerDelete(ApplyView &view, std::shared_ptr< SLE > const &sle, beast::Journal j)
Delete an offer.
void erase(STObject &st, TypedField< U > const &f)
Remove a field in an STObject.
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j)
XRPAmount toAmount< XRPAmount >(STAmount const &amt)