Skip to content

Commit

Permalink
Add units to all fee calculations:
Browse files Browse the repository at this point in the history
* Uses the boost::units library with units for drops,
  fee units (LoadFeeTrack), and fee levels (TxQ).
* Resolves XRPLF#2451
  • Loading branch information
ximinez committed Jun 14, 2019
1 parent 2c8d1b0 commit 08aa83a
Show file tree
Hide file tree
Showing 59 changed files with 1,405 additions and 416 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2351,6 +2351,7 @@ else ()
src/test/basics/base64_test.cpp
src/test/basics/base_uint_test.cpp
src/test/basics/contract_test.cpp
src/test/basics/feeunits_test.cpp
src/test/basics/hardened_hash_test.cpp
src/test/basics/mulDiv_test.cpp
src/test/basics/qalloc_test.cpp
Expand Down
12 changes: 8 additions & 4 deletions src/ripple/app/ledger/Ledger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <ripple/app/misc/LoadFeeTrack.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/feeunits.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/core/Config.h>
Expand Down Expand Up @@ -594,16 +595,19 @@ Ledger::setup (Config const& config)
// VFALCO NOTE Why getFieldIndex and not isFieldPresent?

if (sle->getFieldIndex (sfBaseFee) != -1)
fees_.base = sle->getFieldU64 (sfBaseFee);
fees_.base = sle->getFieldU64 (sfBaseFee) * units::drops;

if (sle->getFieldIndex (sfReferenceFeeUnits) != -1)
fees_.units = sle->getFieldU32 (sfReferenceFeeUnits);
fees_.units = sle->getFieldU32 (sfReferenceFeeUnits) *
units::feeunits;

if (sle->getFieldIndex (sfReserveBase) != -1)
fees_.reserve = sle->getFieldU32 (sfReserveBase);
fees_.reserve = sle->getFieldU32 (sfReserveBase) *
units::drops;

if (sle->getFieldIndex (sfReserveIncrement) != -1)
fees_.increment = sle->getFieldU32 (sfReserveIncrement);
fees_.increment = sle->getFieldU32 (sfReserveIncrement) *
units::drops;
}
}
catch (SHAMapMissingNode &)
Expand Down
8 changes: 4 additions & 4 deletions src/ripple/app/misc/FeeVote.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@ class FeeVote
struct Setup
{
/** The cost of a reference transaction in drops. */
std::uint64_t reference_fee = 10;
Drops64 reference_fee{ 10 * units::drops };

/** The cost of a reference transaction in fee units. */
std::uint32_t const reference_fee_units = 10;
FeeUnit32 const reference_fee_units{ 10 * units::feeunits };

/** The account reserve requirement in drops. */
std::uint64_t account_reserve = 20 * SYSTEM_CURRENCY_PARTS;
Drops32 account_reserve{ 20 * SYSTEM_CURRENCY_PARTS };

/** The per-owned item reserve requirement in drops. */
std::uint64_t owner_reserve = 5 * SYSTEM_CURRENCY_PARTS;
Drops32 owner_reserve{ 5 * SYSTEM_CURRENCY_PARTS };
};

virtual ~FeeVote () = default;
Expand Down
39 changes: 24 additions & 15 deletions src/ripple/app/misc/FeeVoteImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ template <typename Integer>
class VotableInteger
{
private:
using map_type = std::map <Integer, int>;
Integer mCurrent; // The current setting
Integer mTarget; // The setting we want
map_type mVoteMap;
using Value = Drops<Integer>;
Value mCurrent; // The current setting
Value mTarget; // The setting we want
std::map <Value, int> mVoteMap;

public:
VotableInteger (Integer current, Integer target)
VotableInteger (Value current, Value target)
: mCurrent (current)
, mTarget (target)
{
Expand All @@ -48,6 +48,12 @@ class VotableInteger

void
addVote(Integer vote)
{
addVote(vote * units::drops);
}

void
addVote(Value vote)
{
++mVoteMap[vote];
}
Expand All @@ -58,15 +64,16 @@ class VotableInteger
addVote (mCurrent);
}

Integer
Value
getVotes() const;
};

template <class Integer>
Integer
auto
VotableInteger <Integer>::getVotes() const
-> Value
{
Integer ourVote = mCurrent;
Value ourVote = mCurrent;
int weight = 0;
for (auto const& e : mVoteMap)
{
Expand Down Expand Up @@ -156,8 +163,10 @@ FeeVoteImpl::doVoting(
detail::VotableInteger<std::uint64_t> baseFeeVote (
lastClosedLedger->fees().base, target_.reference_fee);

detail::VotableInteger<std::uint32_t> baseReserveVote (
lastClosedLedger->fees().accountReserve(0).drops(), target_.account_reserve);
detail::VotableInteger<std::uint32_t> baseReserveVote(
lastClosedLedger->fees().accountReserve(0).
toDrops<std::uint32_t>(),
target_.account_reserve);

detail::VotableInteger<std::uint32_t> incReserveVote (
lastClosedLedger->fees().increment, target_.owner_reserve);
Expand Down Expand Up @@ -196,15 +205,15 @@ FeeVoteImpl::doVoting(
}

// choose our positions
std::uint64_t const baseFee = baseFeeVote.getVotes ();
std::uint32_t const baseReserve = baseReserveVote.getVotes ();
std::uint32_t const incReserve = incReserveVote.getVotes ();
std::uint32_t const feeUnits = target_.reference_fee_units;
Drops64 const baseFee = baseFeeVote.getVotes ();
Drops32 const baseReserve = baseReserveVote.getVotes ();
Drops32 const incReserve = incReserveVote.getVotes ();
FeeUnit32 const feeUnits = target_.reference_fee_units;
auto const seq = lastClosedLedger->info().seq + 1;

// add transactions to our position
if ((baseFee != lastClosedLedger->fees().base) ||
(baseReserve != lastClosedLedger->fees().accountReserve(0)) ||
(baseReserve != lastClosedLedger->fees().accountReserve(0)) ||
(incReserve != lastClosedLedger->fees().increment))
{
JLOG(journal_.warn()) <<
Expand Down
4 changes: 3 additions & 1 deletion src/ripple/app/misc/LoadFeeTrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#ifndef RIPPLE_CORE_LOADFEETRACK_H_INCLUDED
#define RIPPLE_CORE_LOADFEETRACK_H_INCLUDED

#include <ripple/basics/feeunits.h>
#include <ripple/json/json_value.h>
#include <ripple/beast/utility/Journal.h>
#include <algorithm>
Expand Down Expand Up @@ -140,7 +141,8 @@ class LoadFeeTrack final
//------------------------------------------------------------------------------

// Scale using load as well as base rate
std::uint64_t scaleFeeLoad(std::uint64_t fee, LoadFeeTrack const& feeTrack,
Drops64
scaleFeeLoad(FeeUnit64 fee, LoadFeeTrack const& feeTrack,
Fees const& fees, bool bUnlimited);

} // ripple
Expand Down
120 changes: 59 additions & 61 deletions src/ripple/app/misc/NetworkOPs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class NetworkOPsImp final
{
ServerFeeSummary() = default;

ServerFeeSummary(std::uint64_t fee,
ServerFeeSummary(Drops64 fee,
TxQ::Metrics&& escalationMetrics,
LoadFeeTrack const & loadFeeTrack);
bool
Expand All @@ -188,7 +188,7 @@ class NetworkOPsImp final

std::uint32_t loadFactorServer = 256;
std::uint32_t loadBaseServer = 256;
std::uint64_t baseFee = 10;
Drops64 baseFee{ 10 * units::drops };
boost::optional<TxQ::Metrics> em = boost::none;
};

Expand Down Expand Up @@ -1603,7 +1603,7 @@ void NetworkOPsImp::pubManifest (Manifest const& mo)
}

NetworkOPsImp::ServerFeeSummary::ServerFeeSummary(
std::uint64_t fee,
Drops64 fee,
TxQ::Metrics&& escalationMetrics,
LoadFeeTrack const & loadFeeTrack)
: loadFactorServer{loadFeeTrack.getLoadFactor()}
Expand Down Expand Up @@ -1634,6 +1634,15 @@ NetworkOPsImp::ServerFeeSummary::operator !=(NetworkOPsImp::ServerFeeSummary con
return false;
}

// Need to cap to uint64 to uint32 due to JSON limitations
std::uint32_t clamp(std::uint64_t v)
{
constexpr std::uint64_t max32 =
std::numeric_limits<std::uint32_t>::max();

return std::min(max32, v);
};

void NetworkOPsImp::pubServer ()
{
// VFALCO TODO Don't hold the lock across calls to send...make a copy of the
Expand All @@ -1650,21 +1659,11 @@ void NetworkOPsImp::pubServer ()
app_.getTxQ().getMetrics(*app_.openLedger().current()),
app_.getFeeTrack()};

// Need to cap to uint64 to uint32 due to JSON limitations
auto clamp = [](std::uint64_t v)
{
constexpr std::uint64_t max32 =
std::numeric_limits<std::uint32_t>::max();

return static_cast<std::uint32_t>(std::min(max32, v));
};


jvObj [jss::type] = "serverStatus";
jvObj [jss::server_status] = strOperatingMode ();
jvObj [jss::load_base] = f.loadBaseServer;
jvObj [jss::load_factor_server] = f.loadFactorServer;
jvObj [jss::base_fee] = clamp(f.baseFee);
jvObj [jss::base_fee] = toJson(f.baseFee);

if(f.em)
{
Expand All @@ -1674,10 +1673,12 @@ void NetworkOPsImp::pubServer ()
f.em->referenceFeeLevel).second);

jvObj [jss::load_factor] = clamp(loadFactor);
jvObj [jss::load_factor_fee_escalation] = clamp(f.em->openLedgerFeeLevel);
jvObj [jss::load_factor_fee_queue] = clamp(f.em->minProcessingFeeLevel);
jvObj [jss::load_factor_fee_reference]
= clamp(f.em->referenceFeeLevel);
jvObj [jss::load_factor_fee_escalation] =
toJson(f.em->openLedgerFeeLevel);
jvObj [jss::load_factor_fee_queue] =
toJson(f.em->minProcessingFeeLevel);
jvObj [jss::load_factor_fee_reference] =
toJson(f.em->referenceFeeLevel);

}
else
Expand Down Expand Up @@ -2238,12 +2239,8 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin, bool counters)

if (!human)
{
constexpr std::uint64_t max32 =
std::numeric_limits<std::uint32_t>::max();

info[jss::load_base] = loadBaseServer;
info[jss::load_factor] = static_cast<std::uint32_t>(
std::min(max32, loadFactor));
info[jss::load_factor] = clamp(loadFactor);
info[jss::load_factor_server] = loadFactorServer;

/* Json::Value doesn't support uint64, so clamp to max
Expand All @@ -2252,14 +2249,11 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin, bool counters)
that high.
*/
info[jss::load_factor_fee_escalation] =
static_cast<std::uint32_t> (std::min(
max32, loadFactorFeeEscalation));
toJson(loadFactorFeeEscalation);
info[jss::load_factor_fee_queue] =
static_cast<std::uint32_t> (std::min(
max32, escalationMetrics.minProcessingFeeLevel));
toJson(escalationMetrics.minProcessingFeeLevel);
info[jss::load_factor_fee_reference] =
static_cast<std::uint32_t> (std::min(
max32, loadBaseFeeEscalation));
toJson(loadBaseFeeEscalation);
}
else
{
Expand All @@ -2286,16 +2280,19 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin, bool counters)
}
if (loadFactorFeeEscalation !=
escalationMetrics.referenceFeeLevel &&
(admin || loadFactorFeeEscalation != loadFactor))
info[jss::load_factor_fee_escalation] =
static_cast<double> (loadFactorFeeEscalation) /
escalationMetrics.referenceFeeLevel;
(admin ||
loadFactorFeeEscalation != loadFactor * units::feelevel))
info[jss::load_factor_fee_escalation] = toJson(
static_cast<FeeLevelDouble>(loadFactorFeeEscalation) /
escalationMetrics.referenceFeeLevel
);
if (escalationMetrics.minProcessingFeeLevel !=
escalationMetrics.referenceFeeLevel)
info[jss::load_factor_fee_queue] =
static_cast<double> (
info[jss::load_factor_fee_queue] = toJson(
static_cast<FeeLevelDouble>(
escalationMetrics.minProcessingFeeLevel) /
escalationMetrics.referenceFeeLevel;
escalationMetrics.referenceFeeLevel
);
}

bool valid = false;
Expand All @@ -2308,33 +2305,33 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin, bool counters)

if (lpClosed)
{
std::uint64_t baseFee = lpClosed->fees().base;
std::uint64_t baseRef = lpClosed->fees().units;
Drops64 const baseFee = lpClosed->fees().base;
Json::Value l (Json::objectValue);
l[jss::seq] = Json::UInt (lpClosed->info().seq);
l[jss::hash] = to_string (lpClosed->info().hash);

if (!human)
{
l[jss::base_fee] = Json::Value::UInt (baseFee);
l[jss::base_fee] = toJson(baseFee);
l[jss::reserve_base] = Json::Value::UInt (lpClosed->fees().accountReserve(0).drops());
l[jss::reserve_inc] =
Json::Value::UInt (lpClosed->fees().increment);
toJson (lpClosed->fees().increment);
l[jss::close_time] =
Json::Value::UInt (lpClosed->info().closeTime.time_since_epoch().count());
}
else
{
l[jss::base_fee_xrp] = static_cast<double> (baseFee) /
SYSTEM_CURRENCY_PARTS;
l[jss::reserve_base_xrp] =
static_cast<double> (Json::UInt (
lpClosed->fees().accountReserve(0).drops() * baseFee / baseRef))
/ SYSTEM_CURRENCY_PARTS;
l[jss::reserve_inc_xrp] =
static_cast<double> (Json::UInt (
lpClosed->fees().increment * baseFee / baseRef))
/ SYSTEM_CURRENCY_PARTS;
l[jss::base_fee_xrp] = toJson(
static_cast<DropsDouble>(baseFee) /
SYSTEM_CURRENCY_PARTS);
l[jss::reserve_base_xrp] = toJson(
static_cast<DropsDouble>(
lpClosed->fees().accountReserve(0).toDrops())
/ SYSTEM_CURRENCY_PARTS);
l[jss::reserve_inc_xrp] = toJson(
static_cast<DropsDouble>(
lpClosed->fees().increment)
/ SYSTEM_CURRENCY_PARTS);

auto const nowOffset = app_.timeKeeper().nowOffset();
if (std::abs (nowOffset.count()) >= 60)
Expand Down Expand Up @@ -2453,10 +2450,11 @@ void NetworkOPsImp::pubLedger (
= Json::Value::UInt (lpAccepted->info().closeTime.time_since_epoch().count());

jvObj[jss::fee_ref]
= Json::UInt (lpAccepted->fees().units);
jvObj[jss::fee_base] = Json::UInt (lpAccepted->fees().base);
jvObj[jss::reserve_base] = Json::UInt (lpAccepted->fees().accountReserve(0).drops());
jvObj[jss::reserve_inc] = Json::UInt (lpAccepted->fees().increment);
= toJson(lpAccepted->fees().units);
jvObj[jss::fee_base] = toJson(lpAccepted->fees().base);
jvObj[jss::reserve_base] = toJson(
lpAccepted->fees().accountReserve(0).toDrops());
jvObj[jss::reserve_inc] = toJson(lpAccepted->fees().increment);

jvObj[jss::txn_count] = Json::UInt (alpAccepted->getTxnCount ());

Expand Down Expand Up @@ -2821,13 +2819,13 @@ bool NetworkOPsImp::subLedger (InfoSub::ref isrListener, Json::Value& jvResult)
{
jvResult[jss::ledger_index] = lpClosed->info().seq;
jvResult[jss::ledger_hash] = to_string (lpClosed->info().hash);
jvResult[jss::ledger_time]
= Json::Value::UInt(lpClosed->info().closeTime.time_since_epoch().count());
jvResult[jss::fee_ref]
= Json::UInt (lpClosed->fees().units);
jvResult[jss::fee_base] = Json::UInt (lpClosed->fees().base);
jvResult[jss::reserve_base] = Json::UInt (lpClosed->fees().accountReserve(0).drops());
jvResult[jss::reserve_inc] = Json::UInt (lpClosed->fees().increment);
jvResult[jss::ledger_time] = Json::Value::UInt(
lpClosed->info().closeTime.time_since_epoch().count());
jvResult[jss::fee_ref] = toJson (lpClosed->fees().units);
jvResult[jss::fee_base] = toJson (lpClosed->fees().base);
jvResult[jss::reserve_base] = toJson(
lpClosed->fees().accountReserve(0).toDrops());
jvResult[jss::reserve_inc] = toJson (lpClosed->fees().increment);
}

if ((mMode >= omSYNCING) && !isNeedNetworkLedger ())
Expand Down
Loading

0 comments on commit 08aa83a

Please sign in to comment.