Add units to all fee calculations:

* Uses existing XRPAmount with units for drops, and a new TaggedFee for
  fee units (LoadFeeTrack), and fee levels (TxQ).
* Resolves #2451
This commit is contained in:
Edward Hennis
2019-02-14 18:59:07 -05:00
parent 1901b981f3
commit e3b5b808c5
87 changed files with 2195 additions and 681 deletions

View File

@@ -176,7 +176,7 @@ class NetworkOPsImp final
{
ServerFeeSummary() = default;
ServerFeeSummary(std::uint64_t fee,
ServerFeeSummary(XRPAmount fee,
TxQ::Metrics&& escalationMetrics,
LoadFeeTrack const & loadFeeTrack);
bool
@@ -190,7 +190,7 @@ class NetworkOPsImp final
std::uint32_t loadFactorServer = 256;
std::uint32_t loadBaseServer = 256;
std::uint64_t baseFee = 10;
XRPAmount baseFee{ 10 };
boost::optional<TxQ::Metrics> em = boost::none;
};
@@ -1651,7 +1651,7 @@ void NetworkOPsImp::pubManifest (Manifest const& mo)
}
NetworkOPsImp::ServerFeeSummary::ServerFeeSummary(
std::uint64_t fee,
XRPAmount fee,
TxQ::Metrics&& escalationMetrics,
LoadFeeTrack const & loadFeeTrack)
: loadFactorServer{loadFeeTrack.getLoadFactor()}
@@ -1682,6 +1682,15 @@ NetworkOPsImp::ServerFeeSummary::operator !=(NetworkOPsImp::ServerFeeSummary con
return false;
}
// Need to cap to uint64 to uint32 due to JSON limitations
static std::uint32_t trunc32(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
@@ -1698,21 +1707,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] = f.baseFee.jsonClipped();
if(f.em)
{
@@ -1721,11 +1720,13 @@ void NetworkOPsImp::pubServer ()
mulDiv(f.em->openLedgerFeeLevel, f.loadBaseServer,
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] = trunc32(loadFactor);
jvObj [jss::load_factor_fee_escalation] =
f.em->openLedgerFeeLevel.jsonClipped();
jvObj [jss::load_factor_fee_queue] =
f.em->minProcessingFeeLevel.jsonClipped();
jvObj [jss::load_factor_fee_reference] =
f.em->referenceFeeLevel.jsonClipped();
}
else
@@ -2313,22 +2314,20 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin, bool counters)
auto const loadFactorServer = app_.getFeeTrack().getLoadFactor();
auto const loadBaseServer = app_.getFeeTrack().getLoadBase();
auto const loadFactorFeeEscalation =
escalationMetrics.openLedgerFeeLevel;
auto const loadBaseFeeEscalation =
escalationMetrics.referenceFeeLevel;
/* Scale the escalated fee level to unitless "load factor".
In practice, this just strips the units, but it will continue
to work correctly if either base value ever changes. */
auto const loadFactorFeeEscalation = mulDiv(
escalationMetrics.openLedgerFeeLevel, loadBaseServer,
escalationMetrics.referenceFeeLevel).second;
auto const loadFactor = std::max(safe_cast<std::uint64_t>(loadFactorServer),
mulDiv(loadFactorFeeEscalation, loadBaseServer, loadBaseFeeEscalation).second);
loadFactorFeeEscalation);
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] = trunc32(loadFactor);
info[jss::load_factor_server] = loadFactorServer;
/* Json::Value doesn't support uint64, so clamp to max
@@ -2337,14 +2336,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));
escalationMetrics.openLedgerFeeLevel.jsonClipped();
info[jss::load_factor_fee_queue] =
static_cast<std::uint32_t> (std::min(
max32, escalationMetrics.minProcessingFeeLevel));
escalationMetrics.minProcessingFeeLevel.jsonClipped();
info[jss::load_factor_fee_reference] =
static_cast<std::uint32_t> (std::min(
max32, loadBaseFeeEscalation));
escalationMetrics.referenceFeeLevel.jsonClipped();
}
else
{
@@ -2369,18 +2365,18 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin, bool counters)
info[jss::load_factor_cluster] =
static_cast<double> (fee) / loadBaseServer;
}
if (loadFactorFeeEscalation !=
if (escalationMetrics.openLedgerFeeLevel !=
escalationMetrics.referenceFeeLevel &&
(admin || loadFactorFeeEscalation != loadFactor))
(admin ||
loadFactorFeeEscalation != loadFactor))
info[jss::load_factor_fee_escalation] =
static_cast<double> (loadFactorFeeEscalation) /
escalationMetrics.referenceFeeLevel;
escalationMetrics.openLedgerFeeLevel.decimalFromReference(
escalationMetrics.referenceFeeLevel);
if (escalationMetrics.minProcessingFeeLevel !=
escalationMetrics.referenceFeeLevel)
info[jss::load_factor_fee_queue] =
static_cast<double> (
escalationMetrics.minProcessingFeeLevel) /
escalationMetrics.referenceFeeLevel;
escalationMetrics.minProcessingFeeLevel.decimalFromReference(
escalationMetrics.referenceFeeLevel);
}
bool valid = false;
@@ -2393,33 +2389,28 @@ 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;
XRPAmount 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::reserve_base] = Json::Value::UInt (lpClosed->fees().accountReserve(0).drops());
l[jss::base_fee] = baseFee.jsonClipped();
l[jss::reserve_base] = lpClosed->fees().accountReserve(0).jsonClipped();
l[jss::reserve_inc] =
Json::Value::UInt (lpClosed->fees().increment);
l[jss::close_time] =
Json::Value::UInt (lpClosed->info().closeTime.time_since_epoch().count());
lpClosed->fees().increment.jsonClipped();
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] =
baseFee.decimalXRP();
l[jss::reserve_base_xrp] =
lpClosed->fees().accountReserve(0).decimalXRP();
l[jss::reserve_inc_xrp] =
lpClosed->fees().increment.decimalXRP();
auto const nowOffset = app_.timeKeeper().nowOffset();
if (std::abs (nowOffset.count()) >= 60)
@@ -2537,11 +2528,11 @@ void NetworkOPsImp::pubLedger (
jvObj[jss::ledger_time]
= 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);
jvObj[jss::fee_ref] = lpAccepted->fees().units.jsonClipped();
jvObj[jss::fee_base] = lpAccepted->fees().base.jsonClipped();
jvObj[jss::reserve_base] =
lpAccepted->fees().accountReserve(0).jsonClipped();
jvObj[jss::reserve_inc] = lpAccepted->fees().increment.jsonClipped();
jvObj[jss::txn_count] = Json::UInt (alpAccepted->getTxnCount ());
@@ -2914,13 +2905,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] = lpClosed->fees().units.jsonClipped();
jvResult[jss::fee_base] = lpClosed->fees().base.jsonClipped();
jvResult[jss::reserve_base] =
lpClosed->fees().accountReserve(0).jsonClipped();
jvResult[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped();
}
if ((mMode >= OperatingMode::SYNCING) && !isNeedNetworkLedger ())