-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Amendment fixReducedOffersV2 fixes issue #4937 #5032
Changes from 1 commit
9ddf547
186eda8
af7849c
aecda42
52a04e6
e5dbc1d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
#include <ripple/ledger/ApplyView.h> | ||
#include <ripple/ledger/View.h> | ||
#include <ripple/protocol/Quality.h> | ||
#include <ripple/protocol/Rules.h> | ||
#include <ripple/protocol/TER.h> | ||
|
||
namespace ripple { | ||
|
@@ -103,15 +104,19 @@ class AMMOffer | |
limitOut( | ||
TAmounts<TIn, TOut> const& offrAmt, | ||
TOut const& limit, | ||
bool fixReducedOffers, | ||
Rules const& rules, | ||
bool roundUp) const; | ||
|
||
/** Limit in of the provided offer. If one-path then swapIn | ||
* using current balances. If multi-path then ceil_in using | ||
* current quality. | ||
*/ | ||
TAmounts<TIn, TOut> | ||
limitIn(TAmounts<TIn, TOut> const& offrAmt, TIn const& limit) const; | ||
limitIn( | ||
TAmounts<TIn, TOut> const& offrAmt, | ||
TIn const& limit, | ||
Rules const& rules, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See comment above about passing rules as a param. |
||
bool roundUp) const; | ||
|
||
QualityFunction | ||
getQualityFunc() const; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -661,14 +661,18 @@ limitStepIn( | |
TOut& ownerGives, | ||
std::uint32_t transferRateIn, | ||
std::uint32_t transferRateOut, | ||
TIn const& limit) | ||
TIn const& limit, | ||
Rules const& rules) | ||
{ | ||
if (limit < stpAmt.in) | ||
{ | ||
stpAmt.in = limit; | ||
auto const inLmt = | ||
mulRatio(stpAmt.in, QUALITY_ONE, transferRateIn, /*roundUp*/ false); | ||
ofrAmt = offer.limitIn(ofrAmt, inLmt); | ||
// It turns out we can prevent order book blocking by (strictly) | ||
// rounding down the ceil_in() result. This adjustment changes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be beneficial to add a comment here and in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. Maybe something like...
|
||
// transaction outcomes, so it must be made under an amendment. | ||
ofrAmt = offer.limitIn(ofrAmt, inLmt, rules, /* roundUp */ false); | ||
stpAmt.out = ofrAmt.out; | ||
ownerGives = mulRatio( | ||
ofrAmt.out, transferRateOut, QUALITY_ONE, /*roundUp*/ false); | ||
|
@@ -696,7 +700,7 @@ limitStepOut( | |
ofrAmt = offer.limitOut( | ||
ofrAmt, | ||
stpAmt.out, | ||
rules.enabled(fixReducedOffersV1), | ||
rules, | ||
/*roundUp*/ true); | ||
stpAmt.in = | ||
mulRatio(ofrAmt.in, transferRateIn, QUALITY_ONE, /*roundUp*/ true); | ||
|
@@ -736,7 +740,6 @@ BookStep<TIn, TOut, TDerived>::forEachOffer( | |
sb, afView, book_, sb.parentCloseTime(), counter, j_); | ||
|
||
bool const flowCross = afView.rules().enabled(featureFlowCross); | ||
bool const fixReduced = afView.rules().enabled(fixReducedOffersV1); | ||
bool offerAttempted = false; | ||
std::optional<Quality> ofrQ; | ||
auto execOffer = [&](auto& offer) { | ||
|
@@ -818,7 +821,7 @@ BookStep<TIn, TOut, TDerived>::forEachOffer( | |
// rounding down the ceil_out() result. This adjustment changes | ||
// transaction outcomes, so it must be made under an amendment. | ||
ofrAmt = offer.limitOut( | ||
ofrAmt, stpAmt.out, fixReduced, /*roundUp*/ false); | ||
ofrAmt, stpAmt.out, afView.rules(), /*roundUp*/ false); | ||
|
||
stpAmt.in = | ||
mulRatio(ofrAmt.in, ofrInRate, QUALITY_ONE, /*roundUp*/ true); | ||
|
@@ -1177,7 +1180,8 @@ BookStep<TIn, TOut, TDerived>::fwdImp( | |
ownerGivesAdj, | ||
transferRateIn, | ||
transferRateOut, | ||
remainingIn); | ||
remainingIn, | ||
afView.rules()); | ||
savedIns.insert(remainingIn); | ||
lastOut = savedOuts.insert(stpAdjAmt.out); | ||
result.out = sum(savedOuts); | ||
|
@@ -1228,7 +1232,7 @@ BookStep<TIn, TOut, TDerived>::fwdImp( | |
} | ||
else | ||
{ | ||
// This is (likely) a problem case, and wil be caught | ||
// This is (likely) a problem case, and will be caught | ||
// with later checks | ||
savedOuts.insert(lastOutAmt); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -200,6 +200,29 @@ | |
toAmount<In>(stRes.in), toAmount<Out>(stRes.out)); | ||
} | ||
|
||
Amounts | ||
ceil_in_strict(Amounts const& amount, STAmount const& limit, bool roundUp) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could use a comment for how "strict" differs from the non-strict function. |
||
const; | ||
|
||
template <class In, class Out> | ||
TAmounts<In, Out> | ||
ceil_in_strict( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We usually don't define functions inline in the class. I know this is a member template and that gets a little tedious outside of the class. I'd prefer it was defined out of the class, but it's a minor nit. |
||
TAmounts<In, Out> const& amount, | ||
In const& limit, | ||
bool roundUp) const | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like a copy of If On the same topic, if the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure about |
||
if (amount.in <= limit) | ||
return amount; | ||
|
||
// Use the existing STAmount implementation for now, but consider | ||
// replacing with code specific to IOUAMount and XRPAmount | ||
Amounts stAmt(toSTAmount(amount.in), toSTAmount(amount.out)); | ||
STAmount stLim(toSTAmount(limit)); | ||
auto const stRes = ceil_in_strict(stAmt, stLim, roundUp); | ||
return TAmounts<In, Out>( | ||
toAmount<In>(stRes.in), toAmount<Out>(stRes.out)); | ||
} | ||
|
||
/** Returns the scaled amount with out capped. | ||
Math is avoided if the result is exact. The input is clamped | ||
to prevent money creation. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,13 +64,20 @@ Quality::operator--(int) | |
return prev; | ||
} | ||
|
||
Amounts | ||
Quality::ceil_in(Amounts const& amount, STAmount const& limit) const | ||
template <STAmount ( | ||
*DivRoundFunc)(STAmount const&, STAmount const&, Issue const&, bool)> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I usually like passing the callback as a parameter rather than as a template. But I'm also fine with this as-is. |
||
static Amounts | ||
ceil_in_impl( | ||
Amounts const& amount, | ||
STAmount const& limit, | ||
bool roundUp, | ||
Quality const& quality) | ||
{ | ||
if (amount.in > limit) | ||
{ | ||
Amounts result( | ||
limit, divRound(limit, rate(), amount.out.issue(), true)); | ||
limit, | ||
DivRoundFunc(limit, quality.rate(), amount.out.issue(), roundUp)); | ||
// Clamp out | ||
if (result.out > amount.out) | ||
result.out = amount.out; | ||
|
@@ -81,6 +88,21 @@ Quality::ceil_in(Amounts const& amount, STAmount const& limit) const | |
return amount; | ||
} | ||
|
||
Amounts | ||
Quality::ceil_in(Amounts const& amount, STAmount const& limit) const | ||
{ | ||
return ceil_in_impl<divRound>(amount, limit, /* roundUp */ true, *this); | ||
} | ||
|
||
Amounts | ||
Quality::ceil_in_strict( | ||
Amounts const& amount, | ||
STAmount const& limit, | ||
bool roundUp) const | ||
{ | ||
return ceil_in_impl<divRoundStrict>(amount, limit, roundUp, *this); | ||
} | ||
|
||
template <STAmount ( | ||
*MulRoundFunc)(STAmount const&, STAmount const&, Issue const&, bool)> | ||
static Amounts | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using the globally available rules rather than passing this as a parameter. (also fine as-is, but I think I'd like to get away from passing rules around as much as we do and just using the new global).