Skip to content

Commit

Permalink
Rm some offers where the quality is reduced:
Browse files Browse the repository at this point in the history
Substantial reductions in an offer's effective quality from its
initial quality may clog offer books.
  • Loading branch information
seelabs committed Apr 21, 2021
1 parent 2913847 commit e1bf2c9
Show file tree
Hide file tree
Showing 10 changed files with 429 additions and 4 deletions.
117 changes: 117 additions & 0 deletions src/ripple/app/tx/impl/OfferStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <ripple/app/tx/impl/OfferStream.h>
#include <ripple/basics/Log.h>
#include <ripple/protocol/Feature.h>

namespace ripple {

Expand Down Expand Up @@ -132,6 +133,68 @@ accountFundsHelper(
view, id, issue.currency, issue.account, freezeHandling, j));
}

template <class TIn, class TOut>
template <class TTakerPays, class TTakerGets>
bool
TOfferStreamBase<TIn, TOut>::shouldRmSmallIncreasedQOffer() const
{
static_assert(
std::is_same_v<TTakerPays, IOUAmount> ||
std::is_same_v<TTakerPays, XRPAmount>,
"");

static_assert(
std::is_same_v<TTakerGets, IOUAmount> ||
std::is_same_v<TTakerGets, XRPAmount>,
"");

static_assert(
!std::is_same_v<TTakerPays, XRPAmount> ||
!std::is_same_v<TTakerGets, XRPAmount>,
"Cannot have XRP/XRP offers");

if (!view_.rules().enabled(fixRmSmallIncreasedQOffers))
return false;

// Consider removing the offer if `TakerPays` is XRP or `TakerPays` and
// `TakerGets` are both IOU and `TakerPays` < `TakerGets`
constexpr bool const inIsXRP = std::is_same_v<TTakerPays, XRPAmount>;
constexpr bool const outIsXRP = std::is_same_v<TTakerGets, XRPAmount>;

if (outIsXRP)
return false;

TAmounts<TTakerPays, TTakerGets> const ofrAmts{
toAmount<TTakerPays>(offer_.amount().in),
toAmount<TTakerGets>(offer_.amount().out)};

if constexpr (!inIsXRP && !outIsXRP)
{
if (ofrAmts.in >= ofrAmts.out)
return false;
}

TTakerGets const ownerFunds = toAmount<TTakerGets>(*ownerFunds_);

auto const effectiveAmounts = [&] {
if (offer_.owner() != offer_.issueOut().account &&
ownerFunds < ofrAmts.out)
{
// adjust the amounts by owner funds
return offer_.quality().ceil_out(ofrAmts, ownerFunds);
}
return ofrAmts;
}();

TTakerPays const thresh = TTakerPays::minPositiveAmount();

if (effectiveAmounts.in > thresh)
return false;

Quality const effectiveQuality{effectiveAmounts};
return effectiveQuality < offer_.quality();
}

template <class TIn, class TOut>
bool
TOfferStreamBase<TIn, TOut>::step()
Expand Down Expand Up @@ -222,6 +285,60 @@ TOfferStreamBase<TIn, TOut>::step()
<< "Removing became unfunded offer " << entry->key();
}
offer_ = TOffer<TIn, TOut>{};
// See comment at top of loop for why the offer is removed
continue;
}

bool const rmSmallIncreasedQOffer = [&] {
bool const inIsXRP = isXRP(offer_.issueIn());
bool const outIsXRP = isXRP(offer_.issueOut());
if (inIsXRP && !outIsXRP)
{
if constexpr (!(std::is_same_v<TIn, IOUAmount> ||
std::is_same_v<TOut, XRPAmount>))
return shouldRmSmallIncreasedQOffer<XRPAmount, IOUAmount>();
}
if (!inIsXRP && outIsXRP)
{
if constexpr (!(std::is_same_v<TIn, XRPAmount> ||
std::is_same_v<TOut, IOUAmount>))
return shouldRmSmallIncreasedQOffer<IOUAmount, XRPAmount>();
}
if (!inIsXRP && !outIsXRP)
{
if constexpr (!(std::is_same_v<TIn, XRPAmount> ||
std::is_same_v<TOut, XRPAmount>))
return shouldRmSmallIncreasedQOffer<IOUAmount, IOUAmount>();
}
assert(0); // xrp/xrp offer!?! should never happen
return false;
}();

if (rmSmallIncreasedQOffer)
{
auto const original_funds = accountFundsHelper(
cancelView_,
offer_.owner(),
amount.out,
offer_.issueOut(),
fhZERO_IF_FROZEN,
j_);

if (original_funds == *ownerFunds_)
{
permRmOffer(entry->key());
JLOG(j_.trace())
<< "Removing tiny offer due to reduced quality "
<< entry->key();
}
else
{
JLOG(j_.trace()) << "Removing became tiny offer due to "
"reduced quality "
<< entry->key();
}
offer_ = TOffer<TIn, TOut>{};
// See comment at top of loop for why the offer is removed
continue;
}

Expand Down
4 changes: 4 additions & 0 deletions src/ripple/app/tx/impl/OfferStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ class TOfferStreamBase
virtual void
permRmOffer(uint256 const& offerIndex) = 0;

template <class TTakerPays, class TTakerGets>
bool
shouldRmSmallIncreasedQOffer() const;

public:
TOfferStreamBase(
ApplyView& view,
Expand Down
3 changes: 3 additions & 0 deletions src/ripple/basics/IOUAmount.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ class IOUAmount : private boost::totally_ordered<IOUAmount>,
{
return mantissa_;
}

static IOUAmount
minPositiveAmount();
};

std::string
Expand Down
6 changes: 6 additions & 0 deletions src/ripple/basics/XRPAmount.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,12 @@ class XRPAmount : private boost::totally_ordered<XRPAmount>,
s >> val.drops_;
return s;
}

static XRPAmount
minPositiveAmount()
{
return XRPAmount{1};
}
};

/** Number of drops per 1 XRP */
Expand Down
8 changes: 7 additions & 1 deletion src/ripple/basics/impl/IOUAmount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ static std::int64_t const maxMantissa = 9999999999999999ull;
static int const minExponent = -96;
static int const maxExponent = 80;

IOUAmount
IOUAmount::minPositiveAmount()
{
return IOUAmount(minMantissa, minExponent);
}

void
IOUAmount::normalize()
{
Expand Down Expand Up @@ -353,7 +359,7 @@ mulRatio(
{
if (!result)
{
return IOUAmount(minMantissa, minExponent);
return IOUAmount::minPositiveAmount();
}
// This addition cannot overflow because the mantissa is already
// normalized
Expand Down
30 changes: 30 additions & 0 deletions src/ripple/protocol/AmountConversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,36 @@ toAmount<XRPAmount>(STAmount const& amt)
return XRPAmount(sMant);
}

template <class T>
T
toAmount(IOUAmount const& amt)
{
static_assert(sizeof(T) == -1, "Must use specialized function");
return T(0);
}

template <>
inline IOUAmount
toAmount<IOUAmount>(IOUAmount const& amt)
{
return amt;
}

template <class T>
T
toAmount(XRPAmount const& amt)
{
static_assert(sizeof(T) == -1, "Must use specialized function");
return T(0);
}

template <>
inline XRPAmount
toAmount<XRPAmount>(XRPAmount const& amt)
{
return amt;
}

} // namespace ripple

#endif
2 changes: 2 additions & 0 deletions src/ripple/protocol/Feature.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class FeatureCollections
"TicketBatch",
"FlowSortStrands",
"fixSTAmountCanonicalize",
"fixRmSmallIncreasedQOffers",
};

std::vector<uint256> features;
Expand Down Expand Up @@ -376,6 +377,7 @@ extern uint256 const featureNegativeUNL;
extern uint256 const featureTicketBatch;
extern uint256 const featureFlowSortStrands;
extern uint256 const fixSTAmountCanonicalize;
extern uint256 const fixRmSmallIncreasedQOffers;

} // namespace ripple

Expand Down
7 changes: 7 additions & 0 deletions src/ripple/protocol/Quality.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ class Quality
/** Create a quality from the ratio of two amounts. */
explicit Quality(Amounts const& amount);

/** Create a quality from the ratio of two amounts. */
template <class In, class Out>
Quality(TAmounts<In, Out> const& amount)
: Quality(Amounts(toSTAmount(amount.in), toSTAmount(amount.out)))
{
}

/** Create a quality from the ratio of two amounts. */
template <class In, class Out>
Quality(Out const& out, In const& in)
Expand Down
4 changes: 3 additions & 1 deletion src/ripple/protocol/impl/Feature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ detail::supportedAmendments()
"TicketBatch",
"FlowSortStrands",
"fixSTAmountCanonicalize",
"fixRmSmallIncreasedQOffers",
};
return supported;
}
Expand Down Expand Up @@ -190,7 +191,8 @@ uint256 const
featureNegativeUNL = *getRegisteredFeature("NegativeUNL"),
featureTicketBatch = *getRegisteredFeature("TicketBatch"),
featureFlowSortStrands = *getRegisteredFeature("FlowSortStrands"),
fixSTAmountCanonicalize = *getRegisteredFeature("fixSTAmountCanonicalize");
fixSTAmountCanonicalize = *getRegisteredFeature("fixSTAmountCanonicalize"),
fixRmSmallIncreasedQOffers = *getRegisteredFeature("fixRmSmallIncreasedQOffers");

// The following amendments have been active for at least two years. Their
// pre-amendment code has been removed and the identifiers are deprecated.
Expand Down
Loading

0 comments on commit e1bf2c9

Please sign in to comment.