mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Minor refactor of LoadFeeTrack (RIPD-956):
* Load scaling functions are free, and take `Fees`. * Move LoadFeeTrack to app/misc. * Update naming convention.
This commit is contained in:
150
src/ripple/app/misc/LoadFeeTrack.h
Normal file
150
src/ripple/app/misc/LoadFeeTrack.h
Normal file
@@ -0,0 +1,150 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_CORE_LOADFEETRACK_H_INCLUDED
|
||||
#define RIPPLE_CORE_LOADFEETRACK_H_INCLUDED
|
||||
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <ripple/beast/utility/Journal.h>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
struct Fees;
|
||||
|
||||
/** Manages the current fee schedule.
|
||||
|
||||
The "base" fee is the cost to send a reference transaction under no load,
|
||||
expressed in millionths of one XRP.
|
||||
|
||||
The "load" fee is how much the local server currently charges to send a
|
||||
reference transaction. This fee fluctuates based on the load of the
|
||||
server.
|
||||
*/
|
||||
class LoadFeeTrack final
|
||||
{
|
||||
public:
|
||||
explicit LoadFeeTrack (beast::Journal journal = beast::Journal())
|
||||
: j_ (journal)
|
||||
, localTxnLoadFee_ (lftNormalFee)
|
||||
, remoteTxnLoadFee_ (lftNormalFee)
|
||||
, clusterTxnLoadFee_ (lftNormalFee)
|
||||
, raiseCount_ (0)
|
||||
{
|
||||
}
|
||||
|
||||
~LoadFeeTrack() = default;
|
||||
|
||||
void setRemoteFee (std::uint32_t f)
|
||||
{
|
||||
std::lock_guard <std::mutex> sl (lock_);
|
||||
remoteTxnLoadFee_ = f;
|
||||
}
|
||||
|
||||
std::uint32_t getRemoteFee () const
|
||||
{
|
||||
std::lock_guard <std::mutex> sl (lock_);
|
||||
return remoteTxnLoadFee_;
|
||||
}
|
||||
|
||||
std::uint32_t getLocalFee () const
|
||||
{
|
||||
std::lock_guard <std::mutex> sl (lock_);
|
||||
return localTxnLoadFee_;
|
||||
}
|
||||
|
||||
std::uint32_t getClusterFee () const
|
||||
{
|
||||
std::lock_guard <std::mutex> sl (lock_);
|
||||
return clusterTxnLoadFee_;
|
||||
}
|
||||
|
||||
std::uint32_t getLoadBase () const
|
||||
{
|
||||
return lftNormalFee;
|
||||
}
|
||||
|
||||
std::uint32_t getLoadFactor () const
|
||||
{
|
||||
std::lock_guard <std::mutex> sl (lock_);
|
||||
return std::max({ clusterTxnLoadFee_, localTxnLoadFee_, remoteTxnLoadFee_ });
|
||||
}
|
||||
|
||||
std::pair<std::uint32_t, std::uint32_t>
|
||||
getScalingFactors() const
|
||||
{
|
||||
std::lock_guard<std::mutex> sl(lock_);
|
||||
|
||||
return std::make_pair(
|
||||
std::max(localTxnLoadFee_, remoteTxnLoadFee_),
|
||||
std::max(remoteTxnLoadFee_, clusterTxnLoadFee_));
|
||||
}
|
||||
|
||||
|
||||
void setClusterFee (std::uint32_t fee)
|
||||
{
|
||||
std::lock_guard <std::mutex> sl (lock_);
|
||||
clusterTxnLoadFee_ = fee;
|
||||
}
|
||||
|
||||
bool raiseLocalFee ();
|
||||
bool lowerLocalFee ();
|
||||
|
||||
bool isLoadedLocal () const
|
||||
{
|
||||
std::lock_guard <std::mutex> sl (lock_);
|
||||
return (raiseCount_ != 0) || (localTxnLoadFee_ != lftNormalFee);
|
||||
}
|
||||
|
||||
bool isLoadedCluster () const
|
||||
{
|
||||
std::lock_guard <std::mutex> sl (lock_);
|
||||
return (raiseCount_ != 0) || (localTxnLoadFee_ != lftNormalFee) ||
|
||||
(clusterTxnLoadFee_ != lftNormalFee);
|
||||
}
|
||||
|
||||
private:
|
||||
static std::uint32_t constexpr lftNormalFee = 256; // 256 is the minimum/normal load factor
|
||||
static std::uint32_t constexpr lftFeeIncFraction = 4; // increase fee by 1/4
|
||||
static std::uint32_t constexpr lftFeeDecFraction = 4; // decrease fee by 1/4
|
||||
static std::uint32_t constexpr lftFeeMax = lftNormalFee * 1000000;
|
||||
|
||||
beast::Journal j_;
|
||||
std::mutex mutable lock_;
|
||||
|
||||
std::uint32_t localTxnLoadFee_; // Scale factor, lftNormalFee = normal fee
|
||||
std::uint32_t remoteTxnLoadFee_; // Scale factor, lftNormalFee = normal fee
|
||||
std::uint32_t clusterTxnLoadFee_; // Scale factor, lftNormalFee = normal fee
|
||||
std::uint32_t raiseCount_;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Scale from fee units to millionths of a ripple
|
||||
std::uint64_t scaleFeeBase(std::uint64_t fee, Fees const& fees);
|
||||
|
||||
// Scale using load as well as base rate
|
||||
std::uint64_t scaleFeeLoad(std::uint64_t fee, LoadFeeTrack const& feeTrack,
|
||||
Fees const& fees, bool bUnlimited);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <ripple/app/ledger/TransactionMaster.h>
|
||||
#include <ripple/app/main/LoadManager.h>
|
||||
#include <ripple/app/misc/HashRouter.h>
|
||||
#include <ripple/app/misc/LoadFeeTrack.h>
|
||||
#include <ripple/app/misc/Transaction.h>
|
||||
#include <ripple/app/misc/TxQ.h>
|
||||
#include <ripple/app/misc/Validations.h>
|
||||
@@ -53,7 +54,6 @@
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/core/ConfigSections.h>
|
||||
#include <ripple/core/DeadlineTimer.h>
|
||||
#include <ripple/core/LoadFeeTrack.h>
|
||||
#include <ripple/core/TimeKeeper.h>
|
||||
#include <ripple/crypto/csprng.h>
|
||||
#include <ripple/crypto/RFC1751.h>
|
||||
@@ -1581,13 +1581,14 @@ void NetworkOPsImp::pubServer ()
|
||||
if (!mSubServer.empty ())
|
||||
{
|
||||
Json::Value jvObj (Json::objectValue);
|
||||
auto const& feeTrack = app_.getFeeTrack();
|
||||
|
||||
jvObj [jss::type] = "serverStatus";
|
||||
jvObj [jss::server_status] = strOperatingMode ();
|
||||
jvObj [jss::load_base] =
|
||||
(mLastLoadBase = app_.getFeeTrack ().getLoadBase ());
|
||||
(mLastLoadBase = feeTrack.getLoadBase ());
|
||||
jvObj [jss::load_factor] =
|
||||
(mLastLoadFactor = app_.getFeeTrack ().getLoadFactor ());
|
||||
(mLastLoadFactor = feeTrack.getLoadFactor ());
|
||||
|
||||
for (auto i = mSubServer.begin (); i != mSubServer.end (); )
|
||||
{
|
||||
@@ -2358,8 +2359,9 @@ void NetworkOPsImp::pubLedger (
|
||||
|
||||
void NetworkOPsImp::reportFeeChange ()
|
||||
{
|
||||
if ((app_.getFeeTrack ().getLoadBase () == mLastLoadBase) &&
|
||||
(app_.getFeeTrack ().getLoadFactor () == mLastLoadFactor))
|
||||
auto const& feeTrack = app_.getFeeTrack();
|
||||
if ((feeTrack.getLoadBase () == mLastLoadBase) &&
|
||||
(feeTrack.getLoadFactor () == mLastLoadFactor))
|
||||
return;
|
||||
|
||||
m_job_queue.addJob (
|
||||
@@ -2724,10 +2726,11 @@ bool NetworkOPsImp::subServer (InfoSub::ref isrListener, Json::Value& jvResult,
|
||||
uRandom.size(),
|
||||
crypto_prng());
|
||||
|
||||
auto const& feeTrack = app_.getFeeTrack();
|
||||
jvResult[jss::random] = to_string (uRandom);
|
||||
jvResult[jss::server_status] = strOperatingMode ();
|
||||
jvResult[jss::load_base] = app_.getFeeTrack ().getLoadBase ();
|
||||
jvResult[jss::load_factor] = app_.getFeeTrack ().getLoadFactor ();
|
||||
jvResult[jss::load_base] = feeTrack.getLoadBase ();
|
||||
jvResult[jss::load_factor] = feeTrack.getLoadFactor ();
|
||||
jvResult [jss::hostid] = getHostId (admin);
|
||||
jvResult[jss::pubkey_node] = toBase58 (
|
||||
TokenType::TOKEN_NODE_PUBLIC,
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <ripple/ledger/OpenView.h>
|
||||
#include <ripple/ledger/ApplyView.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/core/LoadFeeTrack.h>
|
||||
#include <ripple/protocol/TER.h>
|
||||
#include <ripple/protocol/STTx.h>
|
||||
#include <boost/intrusive/set.hpp>
|
||||
|
||||
155
src/ripple/app/misc/impl/LoadFeeTrack.cpp
Normal file
155
src/ripple/app/misc/impl/LoadFeeTrack.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <BeastConfig.h>
|
||||
#include <ripple/app/misc/LoadFeeTrack.h>
|
||||
#include <ripple/basics/contract.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/basics/mulDiv.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/ledger/ReadView.h>
|
||||
#include <ripple/protocol/STAmount.h>
|
||||
#include <ripple/protocol/JsonFields.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
bool
|
||||
LoadFeeTrack::raiseLocalFee ()
|
||||
{
|
||||
std::lock_guard <std::mutex> sl (lock_);
|
||||
|
||||
if (++raiseCount_ < 2)
|
||||
return false;
|
||||
|
||||
std::uint32_t origFee = localTxnLoadFee_;
|
||||
|
||||
// make sure this fee takes effect
|
||||
if (localTxnLoadFee_ < remoteTxnLoadFee_)
|
||||
localTxnLoadFee_ = remoteTxnLoadFee_;
|
||||
|
||||
// Increase slowly
|
||||
localTxnLoadFee_ += (localTxnLoadFee_ / lftFeeIncFraction);
|
||||
|
||||
if (localTxnLoadFee_ > lftFeeMax)
|
||||
localTxnLoadFee_ = lftFeeMax;
|
||||
|
||||
if (origFee == localTxnLoadFee_)
|
||||
return false;
|
||||
|
||||
JLOG(j_.debug()) << "Local load fee raised from " <<
|
||||
origFee << " to " << localTxnLoadFee_;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
LoadFeeTrack::lowerLocalFee ()
|
||||
{
|
||||
std::lock_guard <std::mutex> sl (lock_);
|
||||
std::uint32_t origFee = localTxnLoadFee_;
|
||||
raiseCount_ = 0;
|
||||
|
||||
// Reduce slowly
|
||||
localTxnLoadFee_ -= (localTxnLoadFee_ / lftFeeDecFraction );
|
||||
|
||||
if (localTxnLoadFee_ < lftNormalFee)
|
||||
localTxnLoadFee_ = lftNormalFee;
|
||||
|
||||
if (origFee == localTxnLoadFee_)
|
||||
return false;
|
||||
|
||||
JLOG(j_.debug()) << "Local load fee lowered from " <<
|
||||
origFee << " to " << localTxnLoadFee_;
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Scale from fee units to millionths of a ripple
|
||||
std::uint64_t
|
||||
scaleFeeBase(std::uint64_t fee, Fees const& fees)
|
||||
{
|
||||
return mulDivThrow (fee, fees.base, fees.units);
|
||||
}
|
||||
|
||||
// Scale using load as well as base rate
|
||||
std::uint64_t
|
||||
scaleFeeLoad(std::uint64_t fee, LoadFeeTrack const& feeTrack,
|
||||
Fees const& fees, bool bUnlimited)
|
||||
{
|
||||
if (fee == 0)
|
||||
return fee;
|
||||
std::uint32_t feeFactor;
|
||||
std::uint32_t uRemFee;
|
||||
{
|
||||
// Collect the fee rates
|
||||
std::tie(feeFactor, uRemFee) = feeTrack.getScalingFactors();
|
||||
}
|
||||
// Let privileged users pay the normal fee until
|
||||
// the local load exceeds four times the remote.
|
||||
if (bUnlimited && (feeFactor > uRemFee) && (feeFactor < (4 * uRemFee)))
|
||||
feeFactor = uRemFee;
|
||||
|
||||
auto baseFee = fees.base;
|
||||
// Compute:
|
||||
// fee = fee * baseFee * feeFactor / (fees.units * lftNormalFee);
|
||||
// without overflow, and as accurately as possible
|
||||
|
||||
// The denominator of the fraction we're trying to compute.
|
||||
// fees.units and lftNormalFee are both 32 bit,
|
||||
// so the multiplication can't overflow.
|
||||
auto den = static_cast<std::uint64_t>(fees.units)
|
||||
* static_cast<std::uint64_t>(feeTrack.getLoadBase());
|
||||
// Reduce fee * baseFee * feeFactor / (fees.units * lftNormalFee)
|
||||
// to lowest terms.
|
||||
lowestTerms(fee, den);
|
||||
lowestTerms(baseFee, den);
|
||||
lowestTerms(feeFactor, den);
|
||||
|
||||
// fee and baseFee are 64 bit, feeFactor is 32 bit
|
||||
// Order fee and baseFee largest first
|
||||
if (fee < baseFee)
|
||||
std::swap(fee, baseFee);
|
||||
// If baseFee * feeFactor overflows, the final result will overflow
|
||||
const auto max = std::numeric_limits<std::uint64_t>::max();
|
||||
if (baseFee > max / feeFactor)
|
||||
Throw<std::overflow_error> ("scaleFeeLoad");
|
||||
baseFee *= feeFactor;
|
||||
// Reorder fee and baseFee
|
||||
if (fee < baseFee)
|
||||
std::swap(fee, baseFee);
|
||||
// If fee * baseFee / den might overflow...
|
||||
if (fee > max / baseFee)
|
||||
{
|
||||
// Do the division first, on the larger of fee and baseFee
|
||||
fee /= den;
|
||||
if (fee > max / baseFee)
|
||||
Throw<std::overflow_error> ("scaleFeeLoad");
|
||||
fee *= baseFee;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise fee * baseFee won't overflow,
|
||||
// so do it prior to the division.
|
||||
fee *= baseFee;
|
||||
fee /= den;
|
||||
}
|
||||
return fee;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <ripple/app/misc/TxQ.h>
|
||||
#include <ripple/app/ledger/OpenLedger.h>
|
||||
#include <ripple/app/main/Application.h>
|
||||
#include <ripple/app/misc/LoadFeeTrack.h>
|
||||
#include <ripple/app/tx/apply.h>
|
||||
#include <ripple/protocol/st.h>
|
||||
#include <ripple/protocol/Feature.h>
|
||||
|
||||
Reference in New Issue
Block a user