1#include <xrpl/basics/Log.h>
2#include <xrpl/ledger/View.h>
3#include <xrpl/ledger/helpers/OfferHelpers.h>
4#include <xrpl/ledger/helpers/RippleStateHelpers.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/LedgerFormats.h>
7#include <xrpl/tx/paths/OfferStream.h>
8#include <xrpl/tx/transactors/dex/PermissionedDEXHelpers.h>
14checkIssuers(ReadView
const& view, Book
const& book)
16 auto issuerExists = [](ReadView
const& view, Issue
const& iss) ->
bool {
19 return issuerExists(view, book.in) && issuerExists(view, book.out);
23template <
class TIn,
class TOut>
33 , cancelView_(cancelView)
35 , validBook_(checkIssuers(view, book))
40 XRPL_ASSERT(
validBook_,
"xrpl::TOfferStreamBase::TOfferStreamBase : valid book");
45template <
class TIn,
class TOut>
57 JLOG(j_.
error()) <<
"Missing directory " << tip_.dir() <<
" for offer " << tip_.index();
61 auto v(p->getFieldV256(sfIndexes));
62 auto it(
std::find(v.begin(), v.end(), tip_.index()));
66 JLOG(j_.
error()) <<
"Missing offer " << tip_.index() <<
" for directory " << tip_.dir();
71 p->setFieldV256(sfIndexes, v);
74 JLOG(j_.
trace()) <<
"Missing offer " << tip_.index() <<
" removed from directory "
87 return accountFunds(view,
id, saDefault, freezeHandling, j);
122template <
class TIn,
class TOut>
123template <
class TTakerPays,
class TTakerGets>
129 "STAmount is not supported");
133 "STAmount is not supported");
137 "Cannot have XRP/XRP offers");
145 if constexpr (outIsXRP)
154 TAmounts<TTakerPays, TTakerGets>
const ofrAmts{
155 toAmount<TTakerPays>(offer_.amount().in), toAmount<TTakerGets>(offer_.amount().out)};
157 if constexpr (!inIsXRP && !outIsXRP)
159 if (ofrAmts.in >= ofrAmts.out)
163 TTakerGets
const ownerFunds = toAmount<TTakerGets>(*ownerFunds_);
165 auto const effectiveAmounts = [&] {
166 if (offer_.owner() != offer_.issueOut().account && ownerFunds < ofrAmts.out)
172 return offer_.quality().ceil_out_strict(ofrAmts, ownerFunds,
false);
178 if (effectiveAmounts.in.signum() <= 0 || effectiveAmounts.out.signum() <= 0)
181 if (effectiveAmounts.in > TTakerPays::minPositiveAmount())
184 Quality
const effectiveQuality{effectiveAmounts};
185 return effectiveQuality < offer_.quality();
188template <
class TIn,
class TOut>
209 if (!counter_.step())
223 if (entry->isFieldPresent(sfExpiration) && tp{d{(*entry)[sfExpiration]}} <= expire_)
225 JLOG(j_.
trace()) <<
"Removing expired offer " << entry->key();
226 permRmOffer(entry->key());
232 auto const amount(offer_.amount());
237 JLOG(j_.
warn()) <<
"Removing bad offer " << entry->key();
238 permRmOffer(entry->key());
244 view_, offer_.owner(), offer_.issueIn().currency, offer_.issueIn().account);
247 JLOG(j_.
trace()) <<
"Removing deep frozen unfunded offer " << entry->key();
248 permRmOffer(entry->key());
253 if (entry->isFieldPresent(sfDomainID) &&
255 view_, entry->key(), entry->getFieldH256(sfDomainID), j_))
257 JLOG(j_.
trace()) <<
"Removing offer no longer in domain " << entry->key();
258 permRmOffer(entry->key());
265 view_, offer_.owner(), amount.out, offer_.issueOut(),
fhZERO_IF_FROZEN, j_);
268 if (*ownerFunds_ <= beast::zero)
274 cancelView_, offer_.owner(), amount.out, offer_.issueOut(),
fhZERO_IF_FROZEN, j_);
276 if (original_funds == *ownerFunds_)
278 permRmOffer(entry->key());
279 JLOG(j_.
trace()) <<
"Removing unfunded offer " << entry->key();
283 JLOG(j_.
trace()) <<
"Removing became unfunded offer " << entry->key();
290 bool const rmSmallIncreasedQOffer = [&] {
291 bool const inIsXRP =
isXRP(offer_.issueIn());
292 bool const outIsXRP =
isXRP(offer_.issueOut());
293 if (inIsXRP && !outIsXRP)
302 return shouldRmSmallIncreasedQOffer<XRPAmount, IOUAmount>();
304 if (!inIsXRP && outIsXRP)
308 return shouldRmSmallIncreasedQOffer<IOUAmount, XRPAmount>();
310 if (!inIsXRP && !outIsXRP)
314 return shouldRmSmallIncreasedQOffer<IOUAmount, IOUAmount>();
318 "xrpl::TOfferStreamBase::step::rmSmallIncreasedQOffer : XRP "
324 if (rmSmallIncreasedQOffer)
327 cancelView_, offer_.owner(), amount.out, offer_.issueOut(),
fhZERO_IF_FROZEN, j_);
329 if (original_funds == *ownerFunds_)
331 permRmOffer(entry->key());
332 JLOG(j_.
trace()) <<
"Removing tiny offer due to reduced quality " << entry->key();
336 JLOG(j_.
trace()) <<
"Removing tiny offer that became tiny due "
337 "to reduced quality "
352OfferStream::permRmOffer(
uint256 const& offerIndex)
354 offerDelete(cancelView_, cancelView_.peek(keylet::offer(offerIndex)), j_);
357template <
class TIn,
class TOut>
361 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
TOfferStreamBase(ApplyView &view, ApplyView &cancelView, Book const &book, NetClock::time_point when, StepCounter &counter, beast::Journal journal)
bool shouldRmSmallIncreasedQOffer() const
bool step()
Advance to the next valid offer.
void erase(ApplyView &view)
Keylet account(AccountID const &id) noexcept
AccountID root.
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
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.
FreezeHandling
Controls the treatment of frozen account balances.
bool isXRP(AccountID const &c)
STAmount accountHolds(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer, FreezeHandling zeroIfFrozen, beast::Journal j, SpendableHandling includeFullBalance=shSIMPLE_BALANCE)
bool isDeepFrozen(ReadView const &view, AccountID const &account, Currency const ¤cy, AccountID const &issuer)
STAmount accountFunds(ReadView const &view, AccountID const &id, STAmount const &saDefault, FreezeHandling freezeHandling, beast::Journal j)
XRPAmount toAmount< XRPAmount >(STAmount const &amt)
static STAmount accountFundsHelper(ReadView const &view, AccountID const &id, STAmount const &saDefault, Issue const &, FreezeHandling freezeHandling, beast::Journal j)
TER offerDelete(ApplyView &view, std::shared_ptr< SLE > const &sle, beast::Journal j)
Delete an offer.
IOUAmount toAmount< IOUAmount >(STAmount const &amt)
void erase(STObject &st, TypedField< U > const &f)
Remove a field in an STObject.