Simplify fee handling during transaction submission:

Avoid custom overflow code; simply use 128-bit math to
maintain precision and return a saturated 64-bit value
as the final result.

Disallow use of negative values in the `fee_mult_max`
and `fee_div_max` fields. This change could potentially
cause submissions with negative values that would have
previously succeeded to now fail.
This commit is contained in:
Nik Bougalis
2017-01-18 03:33:46 -08:00
parent c7de7950c4
commit 8345475bc3
8 changed files with 135 additions and 106 deletions

View File

@@ -20,46 +20,29 @@
#include <BeastConfig.h>
#include <ripple/basics/mulDiv.h>
#include <ripple/basics/contract.h>
#include <boost/multiprecision/cpp_int.hpp>
#include <limits>
#include <stdexcept>
#include <utility>
namespace ripple
{
// compute (value)*(mul)/(div) - avoid overflow but keep precision
std::pair<bool, std::uint64_t>
mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
{
if ((value == 0 || mul == 0) && div != 0)
return{ true, 0 };
lowestTerms(value, div);
lowestTerms(mul, div);
using namespace boost::multiprecision;
if (value < mul)
std::swap(value, mul);
constexpr std::uint64_t max =
std::numeric_limits<std::uint64_t>::max();
const auto limit = max / mul;
if (value > limit)
{
value /= div;
if (value > limit)
return{ false, max };
return{ true, value * mul };
}
return{ true, value * mul / div };
uint128_t result;
result = multiply(result, value, mul);
result /= div;
auto const limit = std::numeric_limits<std::uint64_t>::max();
if (result > limit)
return { false, limit };
return { true, static_cast<std::uint64_t>(result) };
}
// compute (value)*(mul)/(div) - avoid overflow but keep precision
std::uint64_t
mulDivThrow(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
{
auto const result = mulDiv(value, mul, div);
if(!result.first)
Throw<std::overflow_error>("mulDiv");
return result.second;
}
} // ripple