diff --git a/src/ripple/app/paths/cursor/DeliverNodeForward.cpp b/src/ripple/app/paths/cursor/DeliverNodeForward.cpp index b27274333..4e9a629dc 100644 --- a/src/ripple/app/paths/cursor/DeliverNodeForward.cpp +++ b/src/ripple/app/paths/cursor/DeliverNodeForward.cpp @@ -43,9 +43,6 @@ TER PathCursor::deliverNodeForward ( // Zeroed in reverse pass. node().directory.restart(multiQuality_); - STAmountCalcSwitchovers amountCalcSwitchovers ( - rippleCalc_.view.info ().parentCloseTime); - saInAct.clear (saInReq); saInFees.clear (saInReq); @@ -110,11 +107,11 @@ TER PathCursor::deliverNodeForward ( saOutPassFunded, node().saOfrRate, node().saTakerPays.issue (), - true, amountCalcSwitchovers); + true); // Offer maximum in with fees. auto saInTotal = mulRound (saInFunded, saInFeeRate, - saInFunded.issue (), true, amountCalcSwitchovers); + saInFunded.issue (), true); auto saInRemaining = saInReq - saInAct - saInFees; if (saInRemaining < zero) @@ -126,13 +123,11 @@ TER PathCursor::deliverNodeForward ( // In without fees. auto saInPassAct = std::min ( node().saTakerPays, divRound ( - saInSum, saInFeeRate, saInSum.issue (), true, - amountCalcSwitchovers)); + saInSum, saInFeeRate, saInSum.issue (), true)); // Out limited by in remaining. auto outPass = divRound ( - saInPassAct, node().saOfrRate, node().saTakerGets.issue (), true, - amountCalcSwitchovers); + saInPassAct, node().saOfrRate, node().saTakerGets.issue (), true); STAmount saOutPassMax = std::min (saOutPassFunded, outPass); STAmount saInPassFeesMax = saInSum - saInPassAct; @@ -248,12 +243,10 @@ TER PathCursor::deliverNodeForward ( assert (saOutPassAct < saOutPassMax); auto inPassAct = mulRound ( - saOutPassAct, node().saOfrRate, saInReq.issue (), true, - amountCalcSwitchovers); + saOutPassAct, node().saOfrRate, saInReq.issue (), true); saInPassAct = std::min (node().saTakerPays, inPassAct); auto inPassFees = mulRound ( - saInPassAct, saInFeeRate, saInPassAct.issue (), true, - amountCalcSwitchovers); + saInPassAct, saInFeeRate, saInPassAct.issue (), true); saInPassFees = std::min (saInPassFeesMax, inPassFees); } diff --git a/src/ripple/app/paths/cursor/DeliverNodeReverse.cpp b/src/ripple/app/paths/cursor/DeliverNodeReverse.cpp index 12c2e9859..d20ceba49 100644 --- a/src/ripple/app/paths/cursor/DeliverNodeReverse.cpp +++ b/src/ripple/app/paths/cursor/DeliverNodeReverse.cpp @@ -45,9 +45,6 @@ TER PathCursor::deliverNodeReverseImpl ( { TER resultCode = tesSUCCESS; - STAmountCalcSwitchovers amountCalcSwitchovers ( - rippleCalc_.view.info ().parentCloseTime); - // Accumulation of what the previous node must deliver. // Possible optimization: Note this gets zeroed on each increment, ideally // only on first increment, then it could be a limit on the forward pass. @@ -160,8 +157,7 @@ TER PathCursor::deliverNodeReverseImpl ( // // Round down: prefer liquidity rather than microscopic fees. STAmount saOutPlusFees = mulRound ( - saOutPassAct, saOutFeeRate, saOutPassAct.issue (), false, - amountCalcSwitchovers); + saOutPassAct, saOutFeeRate, saOutPassAct.issue (), false); // Offer out with fees. @@ -184,7 +180,7 @@ TER PathCursor::deliverNodeReverseImpl ( // Round up: prefer liquidity rather than microscopic fees. But, // limit by requested. auto fee = divRound (saOutPlusFees, saOutFeeRate, - saOutPlusFees.issue (), true, amountCalcSwitchovers); + saOutPlusFees.issue (), true); saOutPassAct = std::min (saOutPassReq, fee); JLOG (j_.trace) @@ -196,9 +192,8 @@ TER PathCursor::deliverNodeReverseImpl ( // Compute portion of input needed to cover actual output. auto outputFee = mulRound ( - saOutPassAct, node().saOfrRate, node().saTakerPays.issue (), true, - amountCalcSwitchovers); - if (!amountCalcSwitchovers.enableUnderflowFix () && !outputFee) + saOutPassAct, node().saOfrRate, node().saTakerPays.issue (), true); + if (*stAmountCalcSwitchover == false && ! outputFee) { JLOG (j_.fatal) << "underflow computing outputFee " @@ -269,13 +264,11 @@ TER PathCursor::deliverNodeReverseImpl ( if (saInPassAct < saInPassReq) { // Adjust output to conform to limited input. - auto outputRequirements = divRound ( - saInPassAct, node ().saOfrRate, node ().saTakerGets.issue (), true, - amountCalcSwitchovers); + auto outputRequirements = divRound (saInPassAct, node ().saOfrRate, + node ().saTakerGets.issue (), true); saOutPassAct = std::min (saOutPassReq, outputRequirements); - auto outputFees = mulRound ( - saOutPassAct, saOutFeeRate, saOutPassAct.issue (), true, - amountCalcSwitchovers); + auto outputFees = mulRound (saOutPassAct, saOutFeeRate, + saOutPassAct.issue (), true); saOutPlusFees = std::min (node().saOfferFunds, outputFees); JLOG (j_.trace) diff --git a/src/ripple/app/paths/cursor/ForwardLiquidityForAccount.cpp b/src/ripple/app/paths/cursor/ForwardLiquidityForAccount.cpp index d61b9a64e..137a0701f 100644 --- a/src/ripple/app/paths/cursor/ForwardLiquidityForAccount.cpp +++ b/src/ripple/app/paths/cursor/ForwardLiquidityForAccount.cpp @@ -150,9 +150,6 @@ TER PathCursor::forwardLiquidityForAccount () const << " previousNode.saFwdRedeem:" << previousNode().saFwdRedeem << " previousNode.saFwdIssue:" << previousNode().saFwdIssue; - STAmountCalcSwitchovers amountCalcSwitchovers ( - rippleCalc_.view.info ().parentCloseTime); - // Last node. Accept all funds. Calculate amount actually to credit. auto& saCurReceive = pathState_.outPass(); @@ -162,7 +159,7 @@ TER PathCursor::forwardLiquidityForAccount () const previousNode().saFwdIssue, amountFromRate (uQualityIn), previousNode().saFwdIssue.issue (), - true, amountCalcSwitchovers); // Amount to credit. + true); // Amount to credit. // Amount to credit. Credit for less than received as a surcharge. pathState_.setOutPass (previousNode().saFwdRedeem + saIssueCrd); diff --git a/src/ripple/app/paths/cursor/RippleLiquidity.cpp b/src/ripple/app/paths/cursor/RippleLiquidity.cpp index aaad07597..06c436a03 100644 --- a/src/ripple/app/paths/cursor/RippleLiquidity.cpp +++ b/src/ripple/app/paths/cursor/RippleLiquidity.cpp @@ -135,21 +135,16 @@ void rippleLiquidity ( // If the next rate is at least as good as the current rate, process. if (!uRateMax || uRate <= uRateMax) { - STAmountCalcSwitchovers amountCalcSwitchovers ( - rippleCalc.view.info ().parentCloseTime); - auto currency = saCur.getCurrency (); auto uCurIssuerID = saCur.getIssuer (); // current actual = current request * (quality out / quality in). auto numerator = mulRound ( - saCur, uQualityOut, {currency, uCurIssuerID}, true, - amountCalcSwitchovers); + saCur, uQualityOut, {currency, uCurIssuerID}, true); // True means "round up" to get best flow. STAmount saCurIn = divRound ( - numerator, uQualityIn, {currency, uCurIssuerID}, true, - amountCalcSwitchovers); + numerator, uQualityIn, {currency, uCurIssuerID}, true); JLOG (rippleCalc.j_.trace) << "rippleLiquidity:" @@ -177,14 +172,11 @@ void rippleLiquidity ( // going the other way Issue issue{currency, uCurIssuerID}; - auto numerator = mulRound ( - saPrv, uQualityIn, issue, true, - amountCalcSwitchovers); + auto numerator = mulRound (saPrv, uQualityIn, issue, true); // A part of current. All of previous. (Cur is the driver // variable.) STAmount saCurOut = divRound ( - numerator, uQualityOut, issue, true, - amountCalcSwitchovers); + numerator, uQualityOut, issue, true); JLOG (rippleCalc.j_.trace) << "rippleLiquidity:4: saCurReq=" << saCurReq; diff --git a/src/ripple/app/tests/Offer.test.cpp b/src/ripple/app/tests/Offer.test.cpp index 5199c2c0e..925127df5 100644 --- a/src/ripple/app/tests/Offer.test.cpp +++ b/src/ripple/app/tests/Offer.test.cpp @@ -147,18 +147,16 @@ public: for (int i=0;i<101;++i) env (offer (carol, USD (1), EUR (2))); - auto const switchoverTime = STAmountCalcSwitchovers::enableUnderflowFixCloseTime (); - for (auto timeDelta : { - env.closed()->info().closeTimeResolution, env.closed()->info().closeTimeResolution} ) { - auto const closeTime = switchoverTime + timeDelta; - STAmountCalcSwitchovers switchover (closeTime); + auto const closeTime = STAmountSO::soTime + timeDelta; env.close (closeTime); + *stAmountCalcSwitchover = closeTime <= STAmountSO::soTime; // Will fail without the underflow fix - auto expectedResult = switchover.enableUnderflowFix () ? - tesSUCCESS : tecPATH_PARTIAL; + auto expectedResult = *stAmountCalcSwitchover ? + tesSUCCESS : tecPATH_PARTIAL; env (pay ("alice", "bob", EUR (epsilon)), path (~EUR), sendmax (USD (100)), ter (expectedResult)); } diff --git a/src/ripple/app/tests/Taker.test.cpp b/src/ripple/app/tests/Taker.test.cpp index bd888e3eb..7437ffd3c 100644 --- a/src/ripple/app/tests/Taker.test.cpp +++ b/src/ripple/app/tests/Taker.test.cpp @@ -85,7 +85,7 @@ class Taker_test : public beast::unit_test::suite { /* check if composed quality should be rejected */ Quality const quality (composed_quality ( - quality1, quality2, STAmountCalcSwitchovers{false})); + quality1, quality2)); if (reject (quality)) return std::make_pair( diff --git a/src/ripple/app/tx/impl/CreateOffer.cpp b/src/ripple/app/tx/impl/CreateOffer.cpp index b5bdbe84a..c8f4a6c82 100644 --- a/src/ripple/app/tx/impl/CreateOffer.cpp +++ b/src/ripple/app/tx/impl/CreateOffer.cpp @@ -274,8 +274,7 @@ CreateOffer::dry_offer (ApplyView& view, Offer const& offer) std::pair CreateOffer::select_path ( bool have_direct, OfferStream const& direct, - bool have_bridge, OfferStream const& leg1, OfferStream const& leg2, - STAmountCalcSwitchovers const& amountCalcSwitchovers) + bool have_bridge, OfferStream const& leg1, OfferStream const& leg2) { // If we don't have any viable path, why are we here?! assert (have_direct || have_bridge); @@ -285,7 +284,7 @@ CreateOffer::select_path ( return std::make_pair (true, direct.tip ().quality ()); Quality const bridged_quality (composed_quality ( - leg1.tip ().quality (), leg2.tip ().quality (), amountCalcSwitchovers)); + leg1.tip ().quality (), leg2.tip ().quality ())); if (have_direct) { @@ -352,9 +351,6 @@ CreateOffer::bridged_cross ( auto viewJ = ctx_.app.journal ("View"); - STAmountCalcSwitchovers amountCalcSwitchovers ( - view.info ().parentCloseTime); - // Modifying the order or logic of the operations in the loop will cause // a protocol breaking change. while (have_direct || have_bridge) @@ -368,8 +364,7 @@ CreateOffer::bridged_cross ( std::tie (use_direct, quality) = select_path ( have_direct, offers_direct, - have_bridge, offers_leg1, offers_leg2, - amountCalcSwitchovers); + have_bridge, offers_leg1, offers_leg2); // We are always looking at the best quality; we are done with @@ -473,7 +468,7 @@ CreateOffer::bridged_cross ( Throw ("bridged crossing: nothing was fully consumed."); } - return std::make_pair(cross_result, taker.remaining_offer (amountCalcSwitchovers)); + return std::make_pair(cross_result, taker.remaining_offer ()); } std::pair @@ -554,8 +549,7 @@ CreateOffer::direct_cross ( Throw ("direct crossing: nothing was fully consumed."); } - STAmountCalcSwitchovers amountCalcSwitchovers (view.info ().parentCloseTime); - return std::make_pair(cross_result, taker.remaining_offer (amountCalcSwitchovers)); + return std::make_pair(cross_result, taker.remaining_offer ()); } // Step through the stream for as long as possible, skipping any offers @@ -598,7 +592,6 @@ CreateOffer::cross ( Taker taker (cross_type_, view, account_, taker_amount, ctx_.tx.getFlags(), beast::Journal (takerSink)); - STAmountCalcSwitchovers amountCalcSwitchovers (view.info ().parentCloseTime); try { if (cross_type_ == CrossType::IouToIou) @@ -609,7 +602,7 @@ CreateOffer::cross ( catch (std::exception const& e) { j_.error << "Exception during offer crossing: " << e.what (); - return std::make_pair (tecINTERNAL, taker.remaining_offer (amountCalcSwitchovers)); + return std::make_pair (tecINTERNAL, taker.remaining_offer ()); } } diff --git a/src/ripple/app/tx/impl/CreateOffer.h b/src/ripple/app/tx/impl/CreateOffer.h index dc205a38d..cadf660fe 100644 --- a/src/ripple/app/tx/impl/CreateOffer.h +++ b/src/ripple/app/tx/impl/CreateOffer.h @@ -78,8 +78,7 @@ private: std::pair select_path ( bool have_direct, OfferStream const& direct, - bool have_bridge, OfferStream const& leg1, OfferStream const& leg2, - STAmountCalcSwitchovers const& amountCalcSwitchovers); + bool have_bridge, OfferStream const& leg1, OfferStream const& leg2); std::pair bridged_cross ( diff --git a/src/ripple/app/tx/impl/Taker.cpp b/src/ripple/app/tx/impl/Taker.cpp index c6113b4bf..6a6fa38b7 100644 --- a/src/ripple/app/tx/impl/Taker.cpp +++ b/src/ripple/app/tx/impl/Taker.cpp @@ -140,7 +140,7 @@ BasicTaker::done () const } Amounts -BasicTaker::remaining_offer (STAmountCalcSwitchovers const& amountCalcSwitchovers) const +BasicTaker::remaining_offer () const { // If the taker is done, then there's no offer to place. if (done ()) @@ -156,15 +156,14 @@ BasicTaker::remaining_offer (STAmountCalcSwitchovers const& amountCalcSwitchover // We scale the output based on the remaining input: return Amounts (remaining_.in, divRound ( - remaining_.in, quality_.rate (), issue_out_, true, - amountCalcSwitchovers)); + remaining_.in, quality_.rate (), issue_out_, true)); } assert (remaining_.out > zero); // We scale the input based on the remaining output: return Amounts (mulRound ( - remaining_.out, quality_.rate (), issue_in_, true, amountCalcSwitchovers), + remaining_.out, quality_.rate (), issue_in_, true), remaining_.out); } diff --git a/src/ripple/app/tx/impl/Taker.h b/src/ripple/app/tx/impl/Taker.h index b5033a35a..e6db44997 100644 --- a/src/ripple/app/tx/impl/Taker.h +++ b/src/ripple/app/tx/impl/Taker.h @@ -167,7 +167,7 @@ public: It is always at the original offer quality (quality_) */ Amounts - remaining_offer (STAmountCalcSwitchovers const& amountCalcSwitchovers) const; + remaining_offer () const; /** Returns the amount that the offer was originally placed at. */ Amounts const& diff --git a/src/ripple/app/tx/impl/apply.cpp b/src/ripple/app/tx/impl/apply.cpp index 4aa967196..00608ed9c 100644 --- a/src/ripple/app/tx/impl/apply.cpp +++ b/src/ripple/app/tx/impl/apply.cpp @@ -108,8 +108,8 @@ apply (Application& app, OpenView& view, STTx const& tx, ApplyFlags flags, beast::Journal j) { - auto pfresult = preflight(app, view.rules(), - tx, flags, j); + STAmountSO saved(view.info().parentCloseTime); + auto pfresult = preflight(app, view.rules(), tx, flags, j); auto pcresult = preclaim(pfresult, app, view); return doApply(pcresult, app, view); } diff --git a/src/ripple/basics/LocalValue.h b/src/ripple/basics/LocalValue.h index 28e8a6b3a..9f7355db4 100644 --- a/src/ripple/basics/LocalValue.h +++ b/src/ripple/basics/LocalValue.h @@ -44,7 +44,7 @@ struct LocalValues T t_; Value() = default; - Value(T const& t) : t_(t) {} + explicit Value(T const& t) : t_(t) {} void* get() override { @@ -52,6 +52,7 @@ struct LocalValues } }; + // Keys are the address of a LocalValue. std::unordered_map> values; static diff --git a/src/ripple/protocol/Quality.h b/src/ripple/protocol/Quality.h index 9f6c40285..60b564a0d 100644 --- a/src/ripple/protocol/Quality.h +++ b/src/ripple/protocol/Quality.h @@ -131,16 +131,14 @@ public: to prevent money creation. */ Amounts - ceil_in (Amounts const& amount, STAmount const& limit, - STAmountCalcSwitchovers const& switchovers) const; + ceil_in (Amounts const& amount, STAmount const& limit) const; /** Returns the scaled amount with out capped. Math is avoided if the result is exact. The input is clamped to prevent money creation. */ Amounts - ceil_out (Amounts const& amount, STAmount const& limit, - STAmountCalcSwitchovers const& switchovers) const; + ceil_out (Amounts const& amount, STAmount const& limit) const; /** Returns `true` if lhs is lower quality than `rhs`. Lower quality means the taker receives a worse deal. @@ -181,8 +179,7 @@ public: @param rhs The second leg of the path: intermediate to output. */ Quality -composed_quality (Quality const& lhs, Quality const& rhs, - STAmountCalcSwitchovers const& switchovers); +composed_quality (Quality const& lhs, Quality const& rhs); } diff --git a/src/ripple/protocol/STAmount.h b/src/ripple/protocol/STAmount.h index 7328a7e26..9c4d01340 100644 --- a/src/ripple/protocol/STAmount.h +++ b/src/ripple/protocol/STAmount.h @@ -21,6 +21,7 @@ #define RIPPLE_PROTOCOL_STAMOUNT_H_INCLUDED #include +#include #include #include #include @@ -378,32 +379,14 @@ divide (STAmount const& v1, STAmount const& v2, Issue const& issue); STAmount multiply (STAmount const& v1, STAmount const& v2, Issue const& issue); -/** Control when bugfixes that require switchover dates are enabled */ -class STAmountCalcSwitchovers -{ - bool enableUnderflowFix_ {false}; - public: - STAmountCalcSwitchovers () = delete; - explicit - STAmountCalcSwitchovers (NetClock::time_point parentCloseTime); - explicit - STAmountCalcSwitchovers (bool enableAll) - : enableUnderflowFix_ (enableAll) {} - bool enableUnderflowFix () const; - // for tests - static NetClock::time_point enableUnderflowFixCloseTime (); -}; - // multiply, or divide rounding result in specified direction STAmount mulRound (STAmount const& v1, STAmount const& v2, - Issue const& issue, bool roundUp, - STAmountCalcSwitchovers const& switchovers); + Issue const& issue, bool roundUp); STAmount divRound (STAmount const& v1, STAmount const& v2, - Issue const& issue, bool roundUp, - STAmountCalcSwitchovers const& switchovers); + Issue const& issue, bool roundUp); // Someone is offering X for Y, what is the rate? // Rate: smaller is better, the taker wants the most out: in/out @@ -418,6 +401,30 @@ inline bool isXRP(STAmount const& amount) return isXRP (amount.issue().currency); } +extern LocalValue stAmountCalcSwitchover; + +/** RAII class to set and restore the STAmount calc switchover.*/ +class STAmountSO +{ +public: + explicit STAmountSO(NetClock::time_point const closeTime) + : saved_(*stAmountCalcSwitchover) + { + *stAmountCalcSwitchover = closeTime <= soTime; + } + + ~STAmountSO() + { + *stAmountCalcSwitchover = saved_; + } + + // Mon Dec 28, 2015 10:00:00am PST + static NetClock::time_point const soTime; + +private: + bool saved_; +}; + } // ripple #endif diff --git a/src/ripple/protocol/impl/Quality.cpp b/src/ripple/protocol/impl/Quality.cpp index 4fd7ffc8e..fefcb7802 100644 --- a/src/ripple/protocol/impl/Quality.cpp +++ b/src/ripple/protocol/impl/Quality.cpp @@ -67,13 +67,12 @@ Quality::operator-- (int) } Amounts -Quality::ceil_in (Amounts const& amount, STAmount const& limit, - STAmountCalcSwitchovers const& switchovers) const +Quality::ceil_in (Amounts const& amount, STAmount const& limit) const { if (amount.in > limit) { Amounts result (limit, divRound ( - limit, rate(), amount.out.issue (), true, switchovers)); + limit, rate(), amount.out.issue (), true)); // Clamp out if (result.out > amount.out) result.out = amount.out; @@ -85,13 +84,12 @@ Quality::ceil_in (Amounts const& amount, STAmount const& limit, } Amounts -Quality::ceil_out (Amounts const& amount, STAmount const& limit, - STAmountCalcSwitchovers const& switchovers) const +Quality::ceil_out (Amounts const& amount, STAmount const& limit) const { if (amount.out > limit) { Amounts result (mulRound ( - limit, rate(), amount.in.issue (), true, switchovers), limit); + limit, rate(), amount.in.issue (), true), limit); // Clamp in if (result.in > amount.in) result.in = amount.in; @@ -103,8 +101,7 @@ Quality::ceil_out (Amounts const& amount, STAmount const& limit, } Quality -composed_quality (Quality const& lhs, Quality const& rhs, - STAmountCalcSwitchovers const& switchovers) +composed_quality (Quality const& lhs, Quality const& rhs) { STAmount const lhs_rate (lhs.rate ()); assert (lhs_rate != zero); @@ -113,7 +110,7 @@ composed_quality (Quality const& lhs, Quality const& rhs, assert (rhs_rate != zero); STAmount const rate (mulRound ( - lhs_rate, rhs_rate, lhs_rate.issue (), true, switchovers)); + lhs_rate, rhs_rate, lhs_rate.issue (), true)); std::uint64_t const stored_exponent (rate.exponent () + 100); std::uint64_t const stored_mantissa (rate.mantissa()); diff --git a/src/ripple/protocol/impl/STAmount.cpp b/src/ripple/protocol/impl/STAmount.cpp index 9ea925374..bf63181f4 100644 --- a/src/ripple/protocol/impl/STAmount.cpp +++ b/src/ripple/protocol/impl/STAmount.cpp @@ -35,6 +35,10 @@ namespace ripple { +LocalValue stAmountCalcSwitchover(true); +using namespace std::chrono_literals; +const NetClock::time_point STAmountSO::soTime{504640800s}; + static const std::uint64_t tenTo14 = 100000000000000ull; static const std::uint64_t tenTo14m1 = tenTo14 - 1; static const std::uint64_t tenTo17 = tenTo14 * 1000; @@ -1139,9 +1143,8 @@ canonicalizeRound (bool native, std::uint64_t& value, int& offset, bool roundUp) } STAmount -mulRound (STAmount const& v1, STAmount const& v2, - Issue const& issue, bool roundUp, - STAmountCalcSwitchovers const& switchovers) +mulRound (STAmount const& v1, STAmount const& v2, Issue const& issue, + bool roundUp) { if (v1 == zero || v2 == zero) return {issue}; @@ -1205,20 +1208,20 @@ mulRound (STAmount const& v1, STAmount const& v2, canonicalizeRound ( isXRP (issue), amount, offset, resultNegative != roundUp); STAmount result (issue, amount, offset, resultNegative); - if (switchovers.enableUnderflowFix () && roundUp && !resultNegative && !result) + // Control when bugfixes that require switchover dates are enabled + if (roundUp && !resultNegative && !result && *stAmountCalcSwitchover) { // return the smallest value above zero amount = STAmount::cMinValue; offset = STAmount::cMinOffset; - return STAmount (issue, amount, offset, resultNegative); + return STAmount(issue, amount, offset, resultNegative); } return result; } STAmount divRound (STAmount const& num, STAmount const& den, - Issue const& issue, bool roundUp, - STAmountCalcSwitchovers const& switchovers) + Issue const& issue, bool roundUp) { if (den == zero) Throw ("division by zero"); @@ -1265,7 +1268,8 @@ divRound (STAmount const& num, STAmount const& den, canonicalizeRound ( isXRP (issue), amount, offset, resultNegative != roundUp); STAmount result (issue, amount, offset, resultNegative); - if (switchovers.enableUnderflowFix () && roundUp && !resultNegative && !result) + // Control when bugfixes that require switchover dates are enabled + if (roundUp && !resultNegative && !result && *stAmountCalcSwitchover) { // return the smallest value above zero amount = STAmount::cMinValue; @@ -1275,23 +1279,4 @@ divRound (STAmount const& num, STAmount const& den, return result; } -NetClock::time_point -STAmountCalcSwitchovers::enableUnderflowFixCloseTime () -{ - using namespace std::chrono_literals; - // Mon Dec 28, 2015 10:00:00am PST - return NetClock::time_point{504640800s}; -} - -STAmountCalcSwitchovers::STAmountCalcSwitchovers (NetClock::time_point parentCloseTime) -{ - enableUnderflowFix_ = parentCloseTime > enableUnderflowFixCloseTime(); -} - - -bool STAmountCalcSwitchovers::enableUnderflowFix () const -{ - return enableUnderflowFix_; -} - } // ripple diff --git a/src/ripple/protocol/tests/Quality.test.cpp b/src/ripple/protocol/tests/Quality.test.cpp index 2ee21cb02..90adc3b85 100644 --- a/src/ripple/protocol/tests/Quality.test.cpp +++ b/src/ripple/protocol/tests/Quality.test.cpp @@ -71,7 +71,7 @@ public: { auto expect_result (amounts (in_expected, out_expected)); auto actual_result (q.ceil_in ( - amounts (in, out), amount (limit), STAmountCalcSwitchovers{false})); + amounts (in, out), amount (limit))); expect (actual_result == expect_result); } @@ -83,7 +83,7 @@ public: { auto const expect_result (amounts (in_expected, out_expected)); auto const actual_result (q.ceil_out ( - amounts (in, out), amount (limit), STAmountCalcSwitchovers{false})); + amounts (in, out), amount (limit))); expect (actual_result == expect_result); } @@ -233,7 +233,7 @@ public: STAmount const limit ( raw (4131113916555555, -16)); // .4131113916555555 Amounts const result ( - q.ceil_out (value, limit, STAmountCalcSwitchovers{false})); + q.ceil_out (value, limit)); expect (result.in != zero); } } @@ -277,12 +277,12 @@ public: Quality const q31 (Amounts (amount3, amount1)); expect ( - composed_quality (q12, q21, STAmountCalcSwitchovers{false}) == q11); + composed_quality (q12, q21) == q11); Quality const q13_31 ( - composed_quality (q13, q31, STAmountCalcSwitchovers{false})); + composed_quality (q13, q31)); Quality const q31_13 ( - composed_quality (q31, q13, STAmountCalcSwitchovers{false})); + composed_quality (q31, q13)); expect (q13_31 == q31_13); expect (q13_31 == q11);