Convert STAmount switchovers to tls (RIPD-1068)

This commit is contained in:
Miguel Portilla
2016-01-08 15:00:55 -05:00
committed by Edward Hennis
parent 4fb6bf3e67
commit 14dde47173
17 changed files with 93 additions and 142 deletions

View File

@@ -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);
}

View File

@@ -21,6 +21,7 @@
#define RIPPLE_PROTOCOL_STAMOUNT_H_INCLUDED
#include <ripple/basics/chrono.h>
#include <ripple/basics/LocalValue.h>
#include <ripple/protocol/SField.h>
#include <ripple/protocol/Serializer.h>
#include <ripple/protocol/STBase.h>
@@ -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<bool> 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

View File

@@ -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());

View File

@@ -35,6 +35,10 @@
namespace ripple {
LocalValue<bool> 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<std::runtime_error> ("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

View File

@@ -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);