Skip to content

Commit

Permalink
change return type of mulDiv into std::optional
Browse files Browse the repository at this point in the history
  • Loading branch information
Chenna Keshava B S committed Jul 19, 2022
1 parent 4e72479 commit 67d77ce
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 71 deletions.
4 changes: 2 additions & 2 deletions src/ripple/app/misc/NetworkOPs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2047,7 +2047,7 @@ NetworkOPsImp::pubServer()
f.em->openLedgerFeeLevel,
f.loadBaseServer,
f.em->referenceFeeLevel)
.second);
.value_or(std::numeric_limits<std::uint64_t>::max()));

jvObj[jss::load_factor] = trunc32(loadFactor);
jvObj[jss::load_factor_fee_escalation] =
Expand Down Expand Up @@ -2482,7 +2482,7 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters)
escalationMetrics.openLedgerFeeLevel,
loadBaseServer,
escalationMetrics.referenceFeeLevel)
.second;
.value_or(std::numeric_limits<std::uint64_t>::max());

auto const loadFactor = std::max(
safe_cast<std::uint64_t>(loadFactorServer),
Expand Down
9 changes: 4 additions & 5 deletions src/ripple/app/misc/TxQ.h
Original file line number Diff line number Diff line change
Expand Up @@ -862,18 +862,17 @@ template <class T>
XRPAmount
toDrops(FeeLevel<T> const& level, XRPAmount const& baseFee)
{
if (auto const drops = mulDiv(level, baseFee, TxQ::baseLevel); drops.first)
return drops.second;
if (auto const drops = mulDiv(level, baseFee, TxQ::baseLevel))
return *drops;

return XRPAmount(STAmount::cMaxNativeN);
}

inline FeeLevel64
toFeeLevel(XRPAmount const& drops, XRPAmount const& baseFee)
{
if (auto const feeLevel = mulDiv(drops, TxQ::baseLevel, baseFee);
feeLevel.first)
return feeLevel.second;
if (auto const feeLevel = mulDiv(drops, TxQ::baseLevel, baseFee))
return *feeLevel;

return FeeLevel64(std::numeric_limits<std::uint64_t>::max());
}
Expand Down
4 changes: 2 additions & 2 deletions src/ripple/app/misc/impl/LoadFeeTrack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ scaleFeeLoad(
baseFee *= feeFactor;

auto const result = mulDiv(fee, baseFee, den);
if (!result.first)
if (!result)
Throw<std::overflow_error>("scaleFeeLoad");
return result.second;
return *result;
}

} // namespace ripple
41 changes: 29 additions & 12 deletions src/ripple/app/misc/impl/TxQ.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@ getFeeLevelPaid(ReadView const& view, STTx const& tx)
return FeeLevel64(0);
}

if (std::pair<bool, FeeLevel64> const feeLevelPaid =
mulDiv(effectiveFeePaid, TxQ::baseLevel, baseFee);
feeLevelPaid.first)
return feeLevelPaid.second;
if (auto const feeLevelPaid =
mulDiv(effectiveFeePaid, TxQ::baseLevel, baseFee))
return *feeLevelPaid;

return FeeLevel64(std::numeric_limits<std::uint64_t>::max());
}
Expand All @@ -73,7 +72,9 @@ getLastLedgerSequence(STTx const& tx)
static FeeLevel64
increase(FeeLevel64 level, std::uint32_t increasePercent)
{
return mulDiv(level, 100 + increasePercent, 100).second;
return mulDiv(level, 100 + increasePercent, 100)
.value_or(
static_cast<FeeLevel64>(std::numeric_limits<std::uint64_t>::max()));
}

//////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -112,16 +113,21 @@ TxQ::FeeMetrics::update(
// upperLimit must be >= minimumTxnCount_ or std::clamp can give
// unexpected results
auto const upperLimit = std::max<std::uint64_t>(
mulDiv(txnsExpected_, cutPct, 100).second, minimumTxnCount_);
mulDiv(txnsExpected_, cutPct, 100)
.value_or(std::numeric_limits<std::uint64_t>::max()),
minimumTxnCount_);
txnsExpected_ = std::clamp<std::uint64_t>(
mulDiv(size, cutPct, 100).second, minimumTxnCount_, upperLimit);
mulDiv(size, cutPct, 100)
.value_or(std::numeric_limits<std::uint64_t>::max()),
minimumTxnCount_,
upperLimit);
recentTxnCounts_.clear();
}
else if (size > txnsExpected_ || size > targetTxnCount_)
{
recentTxnCounts_.push_back(
mulDiv(size, 100 + setup.normalConsensusIncreasePercent, 100)
.second);
.value_or(std::numeric_limits<std::uint64_t>::max()));
auto const iter =
std::max_element(recentTxnCounts_.begin(), recentTxnCounts_.end());
BOOST_ASSERT(iter != recentTxnCounts_.end());
Expand Down Expand Up @@ -179,7 +185,9 @@ TxQ::FeeMetrics::scaleFeeLevel(Snapshot const& snapshot, OpenView const& view)
{
// Compute escalated fee level
// Don't care about the overflow flag
return mulDiv(multiplier, current * current, target * target).second;
return mulDiv(multiplier, current * current, target * target)
.value_or(static_cast<FeeLevel64>(
std::numeric_limits<std::uint64_t>::max()));
}

return baseLevel;
Expand Down Expand Up @@ -262,7 +270,7 @@ TxQ::FeeMetrics::escalatedSeriesFeeLevel(
auto const totalFeeLevel = mulDiv(
multiplier, sumNlast.second - sumNcurrent.second, target * target);

return totalFeeLevel;
return {totalFeeLevel.has_value(), *totalFeeLevel};
}

LedgerHash TxQ::MaybeTx::parentHashComp{};
Expand Down Expand Up @@ -1767,8 +1775,17 @@ TxQ::getTxRequiredFeeAndSeq(

std::uint32_t const accountSeq = sle ? (*sle)[sfSequence] : 0;
std::uint32_t const availableSeq = nextQueuableSeqImpl(sle, lock).value();

return {mulDiv(fee, baseFee, baseLevel).second, accountSeq, availableSeq};
// @Ed Hennis, @nik bougalis:
// How do I set the correct return type for the value_or statement?
// How can I typecast the value_or into XRPAmount type?
// I tried the below static_cast but it did not compile.
// Below a few layers of abstraction, XRPAmount is compatible ith uint64
return {
*mulDiv(fee, baseFee, baseLevel),
// .value_or(static_cast<XRPAmount>(
// std::numeric_limits<std::uint64_t>::max())),
accountSeq,
availableSeq};
}

std::vector<TxQ::TxDetails>
Expand Down
10 changes: 5 additions & 5 deletions src/ripple/app/tx/impl/DeleteAccount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ DeleteAccount::calculateBaseFee(ReadView const& view, STTx const& tx)
// The fee required for AccountDelete is one owner reserve. But the
// owner reserve is stored in drops. We need to convert it to fee units.
Fees const& fees{view.fees()};
std::pair<bool, FeeUnit64> const mulDivResult{
const auto mulDivResult{
mulDiv(fees.increment, safe_cast<FeeUnit64>(fees.units), fees.base)};
if (mulDivResult.first)
return mulDivResult.second;
if (mulDivResult)
return *mulDivResult;

// If mulDiv returns false then overflow happened. Punt by using the
// standard calculation.
// If mulDiv does not contain a value, then overflow happened. Punt by
// using the standard calculation.
return Transactor::calculateBaseFee(view, tx);
}

Expand Down
32 changes: 18 additions & 14 deletions src/ripple/basics/FeeUnits.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ template <
class Source2,
class Dest,
class = enable_muldiv_t<Source1, Source2, Dest>>
std::pair<bool, Dest>
std::optional<Dest>
mulDivU(Source1 value, Dest mul, Source2 div)
{
// Fees can never be negative in any context.
Expand All @@ -420,20 +420,20 @@ mulDivU(Source1 value, Dest mul, Source2 div)
assert(value.value() >= 0);
assert(mul.value() >= 0);
assert(div.value() >= 0);
return {false, Dest{0}};
return std::nullopt;
}

using desttype = typename Dest::value_type;
constexpr auto max = std::numeric_limits<desttype>::max();

// Shortcuts, since these happen a lot in the real world
if (value == div)
return {true, mul};
return mul;
if (mul.value() == div.value())
{
if (value.value() > max)
return {false, Dest{max}};
return {true, Dest{static_cast<desttype>(value.value())}};
return std::nullopt;
return Dest{static_cast<desttype>(value.value())};
}

using namespace boost::multiprecision;
Expand All @@ -447,9 +447,9 @@ mulDivU(Source1 value, Dest mul, Source2 div)
auto quotient = product / div.value();

if (quotient > max)
return {false, Dest{max}};
return std::nullopt;

return {true, Dest{static_cast<desttype>(quotient)}};
return Dest{static_cast<desttype>(quotient)};
}

} // namespace feeunit
Expand All @@ -469,7 +469,7 @@ template <
class Source2,
class Dest,
class = feeunit::enable_muldiv_t<Source1, Source2, Dest>>
std::pair<bool, Dest>
std::optional<Dest>
mulDiv(Source1 value, Dest mul, Source2 div)
{
return feeunit::mulDivU(value, mul, div);
Expand All @@ -480,15 +480,15 @@ template <
class Source2,
class Dest,
class = feeunit::enable_muldiv_commute_t<Source1, Source2, Dest>>
std::pair<bool, Dest>
std::optional<Dest>
mulDiv(Dest value, Source1 mul, Source2 div)
{
// Multiplication is commutative
return feeunit::mulDivU(mul, value, div);
}

template <class Dest, class = feeunit::enable_muldiv_dest_t<Dest>>
std::pair<bool, Dest>
std::optional<Dest>
mulDiv(std::uint64_t value, Dest mul, std::uint64_t div)
{
// Give the scalars a non-tag so the
Expand All @@ -497,7 +497,7 @@ mulDiv(std::uint64_t value, Dest mul, std::uint64_t div)
}

template <class Dest, class = feeunit::enable_muldiv_dest_t<Dest>>
std::pair<bool, Dest>
std::optional<Dest>
mulDiv(Dest value, std::uint64_t mul, std::uint64_t div)
{
// Multiplication is commutative
Expand All @@ -508,20 +508,24 @@ template <
class Source1,
class Source2,
class = feeunit::enable_muldiv_sources_t<Source1, Source2>>
std::pair<bool, std::uint64_t>
std::optional<std::uint64_t>
mulDiv(Source1 value, std::uint64_t mul, Source2 div)
{
// Give the scalars a dimensionless unit so the
// unit-handling version gets called.
auto unitresult = feeunit::mulDivU(value, feeunit::scalar(mul), div);
return {unitresult.first, unitresult.second.value()};

if (!unitresult)
return std::nullopt;

return unitresult->value();
}

template <
class Source1,
class Source2,
class = feeunit::enable_muldiv_sources_t<Source1, Source2>>
std::pair<bool, std::uint64_t>
std::optional<std::uint64_t>
mulDiv(std::uint64_t value, Source1 mul, Source2 div)
{
// Multiplication is commutative
Expand Down
6 changes: 3 additions & 3 deletions src/ripple/basics/impl/mulDiv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

namespace ripple {

std::pair<bool, std::uint64_t>
std::optional<std::uint64_t>
mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
{
using namespace boost::multiprecision;
Expand All @@ -38,9 +38,9 @@ mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div)
auto constexpr limit = std::numeric_limits<std::uint64_t>::max();

if (result > limit)
return {false, limit};
return std::nullopt;

return {true, static_cast<std::uint64_t>(result)};
return static_cast<std::uint64_t>(result);
}

} // namespace ripple
2 changes: 1 addition & 1 deletion src/ripple/basics/mulDiv.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ namespace ripple {
`first` is `false`, max value of `uint64_t`
if `true`.
*/
std::pair<bool, std::uint64_t>
std::optional<std::uint64_t>
mulDiv(std::uint64_t value, std::uint64_t mul, std::uint64_t div);

} // namespace ripple
Expand Down
4 changes: 2 additions & 2 deletions src/ripple/ledger/ReadView.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ struct Fees
XRPAmount
toDrops(FeeUnit64 const& fee) const
{
if (auto const resultPair = mulDiv(base, fee, units); resultPair.first)
return resultPair.second;
if (auto const resultPair = mulDiv(base, fee, units))
return *resultPair;

return XRPAmount(STAmount::cMaxNativeN);
}
Expand Down
8 changes: 4 additions & 4 deletions src/ripple/rpc/impl/TransactionSign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -740,12 +740,12 @@ checkFee(
// Scale fee units to drops:
auto const drops =
mulDiv(feeDefault, ledger->fees().base, ledger->fees().units);
if (!drops.first)
if (!drops)
Throw<std::overflow_error>("mulDiv");
auto const result = mulDiv(drops.second, mult, div);
if (!result.first)
auto const result = mulDiv(*drops, mult, div);
if (!result)
Throw<std::overflow_error>("mulDiv");
return result.second;
return *result;
}();

if (fee > limit)
Expand Down
37 changes: 25 additions & 12 deletions src/test/basics/FeeUnits_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,17 @@ class feeunits_test : public beast::unit_test::suite
FeeUnit32 f{10};
FeeUnit32 baseFee{100};

auto drops = mulDiv(baseFee, x, f).second;
auto drops = mulDiv(baseFee, x, f);

BEAST_EXPECT(drops);
BEAST_EXPECT(drops.value() == 1000);
BEAST_EXPECT(
(std::is_same_v<decltype(drops)::unit_type, feeunit::dropTag>));
BEAST_EXPECT((std::is_same_v<decltype(drops), XRPAmount>));
BEAST_EXPECT((std::is_same_v<
std::remove_reference_t<decltype(*drops)>::unit_type,
feeunit::dropTag>));

BEAST_EXPECT((std::is_same_v<
std::remove_reference_t<decltype(*drops)>,
XRPAmount>));
}
{
XRPAmount x{100};
Expand All @@ -68,12 +73,16 @@ class feeunits_test : public beast::unit_test::suite
FeeUnit64 f{10};
FeeUnit64 baseFee{100};

auto drops = mulDiv(baseFee, x, f).second;
auto drops = mulDiv(baseFee, x, f);

BEAST_EXPECT(drops);
BEAST_EXPECT(drops.value() == 1000);
BEAST_EXPECT(
(std::is_same_v<decltype(drops)::unit_type, feeunit::dropTag>));
BEAST_EXPECT((std::is_same_v<decltype(drops), XRPAmount>));
BEAST_EXPECT((std::is_same_v<
std::remove_reference_t<decltype(*drops)>::unit_type,
feeunit::dropTag>));
BEAST_EXPECT((std::is_same_v<
std::remove_reference_t<decltype(*drops)>,
XRPAmount>));
}
{
FeeLevel64 x{1024};
Expand All @@ -89,12 +98,16 @@ class feeunits_test : public beast::unit_test::suite
XRPAmount basefee{10};
FeeLevel64 referencefee{256};

auto drops = mulDiv(x, basefee, referencefee).second;
auto drops = mulDiv(x, basefee, referencefee);

BEAST_EXPECT(drops);
BEAST_EXPECT(drops.value() == 40);
BEAST_EXPECT(
(std::is_same_v<decltype(drops)::unit_type, feeunit::dropTag>));
BEAST_EXPECT((std::is_same_v<decltype(drops), XRPAmount>));
BEAST_EXPECT((std::is_same_v<
std::remove_reference_t<decltype(*drops)>::unit_type,
feeunit::dropTag>));
BEAST_EXPECT((std::is_same_v<
std::remove_reference_t<decltype(*drops)>,
XRPAmount>));
}
}

Expand Down
Loading

0 comments on commit 67d77ce

Please sign in to comment.