Blockchain: remove old fee calc logic
This commit is contained in:
parent
7b7958bbd9
commit
7194506792
|
@ -3691,18 +3691,16 @@ void Blockchain::check_ring_signature(const crypto::hash &tx_prefix_hash, const
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_block_weight, uint8_t version)
|
uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_block_weight)
|
||||||
{
|
{
|
||||||
const uint64_t min_block_weight = get_min_block_weight(version);
|
constexpr uint64_t min_block_weight = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5;
|
||||||
if (median_block_weight < min_block_weight)
|
if (median_block_weight < min_block_weight)
|
||||||
median_block_weight = min_block_weight;
|
median_block_weight = min_block_weight;
|
||||||
uint64_t hi, lo;
|
uint64_t hi, lo;
|
||||||
|
|
||||||
if (version >= HF_VERSION_PER_BYTE_FEE)
|
|
||||||
{
|
{
|
||||||
lo = mul128(block_reward, DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT, &hi);
|
lo = mul128(block_reward, DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT, &hi);
|
||||||
div128_64(hi, lo, median_block_weight, &hi, &lo, NULL, NULL);
|
div128_64(hi, lo, median_block_weight, &hi, &lo, NULL, NULL);
|
||||||
if (version >= HF_VERSION_2021_SCALING)
|
|
||||||
{
|
{
|
||||||
// min_fee_per_byte = round_up( 0.95 * block_reward * ref_weight / (fee_median^2) )
|
// min_fee_per_byte = round_up( 0.95 * block_reward * ref_weight / (fee_median^2) )
|
||||||
// note: since hardfork HF_VERSION_2021_SCALING, fee_median (a.k.a. median_block_weight) equals effective long term median
|
// note: since hardfork HF_VERSION_2021_SCALING, fee_median (a.k.a. median_block_weight) equals effective long term median
|
||||||
|
@ -3711,29 +3709,7 @@ uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_b
|
||||||
lo -= lo / 20;
|
lo -= lo / 20;
|
||||||
return lo == 0 ? 1 : lo;
|
return lo == 0 ? 1 : lo;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// min_fee_per_byte = 0.2 * block_reward * ref_weight / (min_penalty_free_zone * fee_median)
|
|
||||||
div128_64(hi, lo, min_block_weight, &hi, &lo, NULL, NULL);
|
|
||||||
assert(hi == 0);
|
|
||||||
lo /= 5;
|
|
||||||
return lo;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const uint64_t fee_base = version >= 5 ? DYNAMIC_FEE_PER_KB_BASE_FEE_V5 : DYNAMIC_FEE_PER_KB_BASE_FEE;
|
|
||||||
|
|
||||||
uint64_t unscaled_fee_base = (fee_base * min_block_weight / median_block_weight);
|
|
||||||
lo = mul128(unscaled_fee_base, block_reward, &hi);
|
|
||||||
div128_64(hi, lo, DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD, &hi, &lo, NULL, NULL);
|
|
||||||
assert(hi == 0);
|
|
||||||
|
|
||||||
// quantize fee up to 8 decimals
|
|
||||||
uint64_t mask = get_fee_quantization_mask();
|
|
||||||
uint64_t qlo = (lo + mask - 1) / mask * mask;
|
|
||||||
MDEBUG("lo " << print_money(lo) << ", qlo " << print_money(qlo) << ", mask " << mask);
|
|
||||||
|
|
||||||
return qlo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
@ -3744,7 +3720,6 @@ bool Blockchain::check_fee(size_t tx_weight, uint64_t fee) const
|
||||||
uint64_t median = 0;
|
uint64_t median = 0;
|
||||||
uint64_t already_generated_coins = 0;
|
uint64_t already_generated_coins = 0;
|
||||||
uint64_t base_reward = 0;
|
uint64_t base_reward = 0;
|
||||||
if (version >= HF_VERSION_DYNAMIC_FEE)
|
|
||||||
{
|
{
|
||||||
median = m_current_block_cumul_weight_limit / 2;
|
median = m_current_block_cumul_weight_limit / 2;
|
||||||
const uint64_t blockchain_height = m_db->height();
|
const uint64_t blockchain_height = m_db->height();
|
||||||
|
@ -3754,33 +3729,15 @@ bool Blockchain::check_fee(size_t tx_weight, uint64_t fee) const
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t needed_fee;
|
uint64_t needed_fee;
|
||||||
if (version >= HF_VERSION_PER_BYTE_FEE)
|
|
||||||
{
|
{
|
||||||
const bool use_long_term_median_in_fee = version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT;
|
const uint64_t fee_per_byte = get_dynamic_base_fee(base_reward,
|
||||||
uint64_t fee_per_byte = get_dynamic_base_fee(base_reward, use_long_term_median_in_fee ? std::min<uint64_t>(median, m_long_term_effective_median_block_weight) : median, version);
|
std::min<uint64_t>(median, m_long_term_effective_median_block_weight));
|
||||||
MDEBUG("Using " << print_money(fee_per_byte) << "/byte fee");
|
MDEBUG("Using " << print_money(fee_per_byte) << "/byte fee");
|
||||||
needed_fee = tx_weight * fee_per_byte;
|
needed_fee = tx_weight * fee_per_byte;
|
||||||
// quantize fee up to 8 decimals
|
// quantize fee up to 8 decimals
|
||||||
const uint64_t mask = get_fee_quantization_mask();
|
const uint64_t mask = get_fee_quantization_mask();
|
||||||
needed_fee = (needed_fee + mask - 1) / mask * mask;
|
needed_fee = (needed_fee + mask - 1) / mask * mask;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
uint64_t fee_per_kb;
|
|
||||||
if (version < HF_VERSION_DYNAMIC_FEE)
|
|
||||||
{
|
|
||||||
fee_per_kb = FEE_PER_KB;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fee_per_kb = get_dynamic_base_fee(base_reward, median, version);
|
|
||||||
}
|
|
||||||
MDEBUG("Using " << print_money(fee_per_kb) << "/kB fee");
|
|
||||||
|
|
||||||
needed_fee = tx_weight / 1024;
|
|
||||||
needed_fee += (tx_weight % 1024) ? 1 : 0;
|
|
||||||
needed_fee *= fee_per_kb;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fee < needed_fee - needed_fee / 50) // keep a little 2% buffer on acceptance - no integer overflow
|
if (fee < needed_fee - needed_fee / 50) // keep a little 2% buffer on acceptance - no integer overflow
|
||||||
{
|
{
|
||||||
|
@ -3791,7 +3748,8 @@ bool Blockchain::check_fee(size_t tx_weight, uint64_t fee) const
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
void Blockchain::get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, uint64_t base_reward, uint64_t Mnw, uint64_t Mlw, std::vector<uint64_t> &fees) const
|
void Blockchain::get_dynamic_base_fee_estimate_2021_scaling(uint64_t base_reward, uint64_t Mnw,
|
||||||
|
uint64_t Mlw, std::vector<uint64_t> &fees)
|
||||||
{
|
{
|
||||||
// variable names and calculations as per https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021-02.pdf
|
// variable names and calculations as per https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021-02.pdf
|
||||||
// from (earlier than) this fork, the base fee is per byte
|
// from (earlier than) this fork, the base fee is per byte
|
||||||
|
@ -3863,55 +3821,8 @@ void Blockchain::get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_block
|
||||||
base_reward = BLOCK_REWARD_OVERESTIMATE;
|
base_reward = BLOCK_REWARD_OVERESTIMATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_dynamic_base_fee_estimate_2021_scaling(grace_blocks, base_reward, Mnw, Mlw_penalty_free_zone_for_wallet, fees);
|
get_dynamic_base_fee_estimate_2021_scaling(base_reward, Mnw, Mlw_penalty_free_zone_for_wallet, fees);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
|
||||||
uint64_t Blockchain::get_dynamic_base_fee_estimate(uint64_t grace_blocks) const
|
|
||||||
{
|
|
||||||
const uint8_t version = get_current_hard_fork_version();
|
|
||||||
const uint64_t db_height = m_db->height();
|
|
||||||
|
|
||||||
if (version < HF_VERSION_DYNAMIC_FEE)
|
|
||||||
return FEE_PER_KB;
|
|
||||||
|
|
||||||
if (grace_blocks >= CRYPTONOTE_REWARD_BLOCKS_WINDOW)
|
|
||||||
grace_blocks = CRYPTONOTE_REWARD_BLOCKS_WINDOW - 1;
|
|
||||||
|
|
||||||
if (version >= HF_VERSION_2021_SCALING)
|
|
||||||
{
|
|
||||||
std::vector<uint64_t> fees;
|
|
||||||
get_dynamic_base_fee_estimate_2021_scaling(grace_blocks, fees);
|
|
||||||
return fees[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint64_t min_block_weight = get_min_block_weight(version);
|
|
||||||
std::vector<uint64_t> weights;
|
|
||||||
get_last_n_blocks_weights(weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW - grace_blocks);
|
|
||||||
weights.reserve(grace_blocks);
|
|
||||||
for (size_t i = 0; i < grace_blocks; ++i)
|
|
||||||
weights.push_back(min_block_weight);
|
|
||||||
|
|
||||||
uint64_t median = epee::misc_utils::median(weights);
|
|
||||||
if(median <= min_block_weight)
|
|
||||||
median = min_block_weight;
|
|
||||||
|
|
||||||
uint64_t already_generated_coins = db_height ? m_db->get_block_already_generated_coins(db_height - 1) : 0;
|
|
||||||
uint64_t base_reward;
|
|
||||||
if (!get_block_reward(m_current_block_cumul_weight_limit / 2, 1, already_generated_coins, base_reward, version))
|
|
||||||
{
|
|
||||||
MERROR("Failed to determine block reward, using placeholder " << print_money(BLOCK_REWARD_OVERESTIMATE) << " as a high bound");
|
|
||||||
base_reward = BLOCK_REWARD_OVERESTIMATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool use_long_term_median_in_fee = version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT;
|
|
||||||
const uint64_t use_median_value = use_long_term_median_in_fee ? std::min<uint64_t>(median, m_long_term_effective_median_block_weight) : median;
|
|
||||||
const uint64_t fee = get_dynamic_base_fee(base_reward, use_median_value, version);
|
|
||||||
const bool per_byte = version < HF_VERSION_PER_BYTE_FEE;
|
|
||||||
MDEBUG("Estimating " << grace_blocks << "-block fee at " << print_money(fee) << "/" << (per_byte ? "byte" : "kB"));
|
|
||||||
return fee;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// This function checks to see if a tx is unlocked. unlock_time is either
|
// This function checks to see if a tx is unlocked. unlock_time is either
|
||||||
// a block index or a unix time.
|
// a block index or a unix time.
|
||||||
|
|
|
@ -638,27 +638,24 @@ namespace cryptonote
|
||||||
*
|
*
|
||||||
* @param block_reward the current block reward
|
* @param block_reward the current block reward
|
||||||
* @param median_block_weight the median block weight in the past window
|
* @param median_block_weight the median block weight in the past window
|
||||||
* @param version hard fork version for rules and constants to use
|
|
||||||
*
|
*
|
||||||
* @return the fee
|
* @return the fee
|
||||||
*/
|
*/
|
||||||
static uint64_t get_dynamic_base_fee(uint64_t block_reward, size_t median_block_weight, uint8_t version);
|
static uint64_t get_dynamic_base_fee(uint64_t block_reward, size_t median_block_weight);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get dynamic per kB or byte fee estimate for the next few blocks
|
* @brief get four levels of dynamic per byte fee estimate for the next few blocks
|
||||||
*
|
*
|
||||||
* The dynamic fee is based on the block weight in a past window, and
|
* The dynamic fee is based on the block weight in a past window, and
|
||||||
* the current block reward. It is expressed by kB before v8, and
|
* the current block reward. It is expressed per byte, and is based on
|
||||||
* per byte from v8.
|
* https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021-02.pdf
|
||||||
* This function calculates an estimate for a dynamic fee which will be
|
|
||||||
* valid for the next grace_blocks
|
|
||||||
*
|
*
|
||||||
* @param grace_blocks number of blocks we want the fee to be valid for
|
* @param Mnw min(Msw, 50*Mlw)
|
||||||
*
|
* @param Mlw The median over the last 99990 and future 10 blocks of max(min(Mbw, 2*Ml), Zm, Ml/2)
|
||||||
* @return the fee estimate
|
* @param[out] fees fee estimate levels [Fl, Fn, Fm, Fh]
|
||||||
*/
|
*/
|
||||||
uint64_t get_dynamic_base_fee_estimate(uint64_t grace_blocks) const;
|
static void get_dynamic_base_fee_estimate_2021_scaling(uint64_t base_reward, uint64_t Mnw,
|
||||||
void get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, uint64_t base_reward, uint64_t Mnw, uint64_t Mlw, std::vector<uint64_t> &fees) const;
|
uint64_t Mlw, std::vector<uint64_t> &fees);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief get four levels of dynamic per byte fee estimate for the next few blocks
|
* @brief get four levels of dynamic per byte fee estimate for the next few blocks
|
||||||
|
@ -670,8 +667,7 @@ namespace cryptonote
|
||||||
* valid for the next grace_blocks
|
* valid for the next grace_blocks
|
||||||
*
|
*
|
||||||
* @param grace_blocks number of blocks we want the fee to be valid for
|
* @param grace_blocks number of blocks we want the fee to be valid for
|
||||||
*
|
* @param[out] fees fee estimate levels [Fl, Fn, Fm, Fh]
|
||||||
* @return the fee estimates (4 of them)
|
|
||||||
*/
|
*/
|
||||||
void get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, std::vector<uint64_t> &fees) const;
|
void get_dynamic_base_fee_estimate_2021_scaling(uint64_t grace_blocks, std::vector<uint64_t> &fees) const;
|
||||||
|
|
||||||
|
|
|
@ -3019,16 +3019,10 @@ namespace cryptonote
|
||||||
|
|
||||||
CHECK_PAYMENT(req, res, COST_PER_FEE_ESTIMATE);
|
CHECK_PAYMENT(req, res, COST_PER_FEE_ESTIMATE);
|
||||||
|
|
||||||
const uint8_t version = m_core.get_blockchain_storage().get_current_hard_fork_version();
|
|
||||||
if (version >= HF_VERSION_2021_SCALING)
|
|
||||||
{
|
{
|
||||||
m_core.get_blockchain_storage().get_dynamic_base_fee_estimate_2021_scaling(req.grace_blocks, res.fees);
|
m_core.get_blockchain_storage().get_dynamic_base_fee_estimate_2021_scaling(req.grace_blocks, res.fees);
|
||||||
res.fee = res.fees[0];
|
res.fee = res.fees[0];
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
res.fee = m_core.get_blockchain_storage().get_dynamic_base_fee_estimate(req.grace_blocks);
|
|
||||||
}
|
|
||||||
res.quantization_mask = Blockchain::get_fee_quantization_mask();
|
res.quantization_mask = Blockchain::get_fee_quantization_mask();
|
||||||
res.status = CORE_RPC_STATUS_OK;
|
res.status = CORE_RPC_STATUS_OK;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -831,14 +831,11 @@ namespace rpc
|
||||||
void DaemonHandler::handle(const GetFeeEstimate::Request& req, GetFeeEstimate::Response& res)
|
void DaemonHandler::handle(const GetFeeEstimate::Request& req, GetFeeEstimate::Response& res)
|
||||||
{
|
{
|
||||||
res.hard_fork_version = m_core.get_blockchain_storage().get_current_hard_fork_version();
|
res.hard_fork_version = m_core.get_blockchain_storage().get_current_hard_fork_version();
|
||||||
res.estimated_base_fee = m_core.get_blockchain_storage().get_dynamic_base_fee_estimate(req.num_grace_blocks);
|
|
||||||
|
|
||||||
if (res.hard_fork_version < HF_VERSION_PER_BYTE_FEE)
|
std::vector<uint64_t> fees;
|
||||||
{
|
m_core.get_blockchain_storage().get_dynamic_base_fee_estimate_2021_scaling(req.num_grace_blocks, fees);
|
||||||
res.size_scale = 1024; // per KiB fee
|
res.estimated_base_fee = fees[0];
|
||||||
res.fee_mask = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
res.size_scale = 1; // per byte fee
|
res.size_scale = 1; // per byte fee
|
||||||
res.fee_mask = Blockchain::get_fee_quantization_mask();
|
res.fee_mask = Blockchain::get_fee_quantization_mask();
|
||||||
|
|
|
@ -51,7 +51,6 @@ set(unit_tests_sources
|
||||||
epee_serialization.cpp
|
epee_serialization.cpp
|
||||||
epee_utils.cpp
|
epee_utils.cpp
|
||||||
expect.cpp
|
expect.cpp
|
||||||
fee.cpp
|
|
||||||
json_serialization.cpp
|
json_serialization.cpp
|
||||||
get_xtype_from_string.cpp
|
get_xtype_from_string.cpp
|
||||||
hashchain.cpp
|
hashchain.cpp
|
||||||
|
|
|
@ -1,136 +0,0 @@
|
||||||
// Copyright (c) 2014-2023, The Monero Project
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other
|
|
||||||
// materials provided with the distribution.
|
|
||||||
//
|
|
||||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
|
||||||
// used to endorse or promote products derived from this software without specific
|
|
||||||
// prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
||||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
||||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
|
|
||||||
#include "cryptonote_core/blockchain.h"
|
|
||||||
|
|
||||||
using namespace cryptonote;
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
static uint64_t clamp_fee(uint64_t fee)
|
|
||||||
{
|
|
||||||
static uint64_t mask = 0;
|
|
||||||
if (mask == 0)
|
|
||||||
{
|
|
||||||
mask = 1;
|
|
||||||
for (size_t n = PER_KB_FEE_QUANTIZATION_DECIMALS; n < CRYPTONOTE_DISPLAY_DECIMAL_POINT; ++n)
|
|
||||||
mask *= 10;
|
|
||||||
}
|
|
||||||
return (fee + mask - 1) / mask * mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------------------
|
|
||||||
class fee : public ::testing::Test
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
// try with blocks ~ 1GB. Passing 2 GB will break on 32 bit systems
|
|
||||||
|
|
||||||
TEST_F(fee, 10xmr)
|
|
||||||
{
|
|
||||||
// CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 and lower are clamped
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2, 3), clamp_fee(2000000000));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 2, 3), clamp_fee(2000000000));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 100, 3), clamp_fee(2000000000));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(10000000000000, 1, 3), 2000000000);
|
|
||||||
|
|
||||||
// higher is inverse proportional
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 2, 3), clamp_fee(2000000000 / 2));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 10, 3), clamp_fee(2000000000 / 10));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 1000, 3), clamp_fee(2000000000 / 1000));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 20000ull, 3), clamp_fee(2000000000 / 20000));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(fee, 1xmr)
|
|
||||||
{
|
|
||||||
// CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 and lower are clamped
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2, 3), clamp_fee(200000000));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 2, 3), clamp_fee(200000000));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 100, 3), clamp_fee(200000000));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(1000000000000, 1, 3), 200000000);
|
|
||||||
|
|
||||||
// higher is inverse proportional
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 2, 3), clamp_fee(200000000 / 2));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 10, 3), clamp_fee(200000000 / 10));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 1000, 3), clamp_fee(200000000 / 1000));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 20000ull, 3), clamp_fee(200000000 / 20000));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(fee, dot3xmr)
|
|
||||||
{
|
|
||||||
// CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 and lower are clamped
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2, 3), clamp_fee(60000000));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 2, 3), clamp_fee(60000000));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 100, 3), clamp_fee(60000000));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(300000000000, 1, 3), 60000000);
|
|
||||||
|
|
||||||
// higher is inverse proportional
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 2, 3), clamp_fee(60000000 / 2));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 10, 3), clamp_fee(60000000 / 10));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 1000, 3), clamp_fee(60000000 / 1000));
|
|
||||||
ASSERT_EQ(Blockchain::get_dynamic_base_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 20000ull, 3), clamp_fee(60000000 / 20000));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_more_or_less(double x, double y)
|
|
||||||
{
|
|
||||||
return fabs(y - x) < 0.001;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const double MAX_MULTIPLIER = 166.f;
|
|
||||||
|
|
||||||
TEST_F(fee, double_at_full)
|
|
||||||
{
|
|
||||||
static const uint64_t block_rewards[] = {
|
|
||||||
20000000000000ull, // 20 monero
|
|
||||||
13000000000000ull,
|
|
||||||
1000000000000ull,
|
|
||||||
600000000000ull, // .6 monero, minimum reward per block at 2min
|
|
||||||
300000000000ull, // .3 monero, minimum reward per block at 1min
|
|
||||||
};
|
|
||||||
static const uint64_t median_block_weights[] = {
|
|
||||||
CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2,
|
|
||||||
CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 2,
|
|
||||||
CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 10,
|
|
||||||
CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 1000,
|
|
||||||
// with clamping, the formula does not hold for such large blocks and small fees
|
|
||||||
// CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 20000ull
|
|
||||||
};
|
|
||||||
|
|
||||||
for (uint64_t block_reward: block_rewards)
|
|
||||||
{
|
|
||||||
for (uint64_t median_block_weight: median_block_weights)
|
|
||||||
{
|
|
||||||
ASSERT_TRUE(is_more_or_less(Blockchain::get_dynamic_base_fee(block_reward, median_block_weight, 3) * (median_block_weight / 1024.) * MAX_MULTIPLIER / (double)block_reward, 1.992 * 1000 / 1024));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -30,68 +30,26 @@
|
||||||
// - https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021.pdf
|
// - https://github.com/ArticMine/Monero-Documents/blob/master/MoneroScaling2021.pdf
|
||||||
// - https://github.com/monero-project/research-lab/issues/70
|
// - https://github.com/monero-project/research-lab/issues/70
|
||||||
|
|
||||||
#define IN_UNIT_TESTS
|
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "cryptonote_core/blockchain.h"
|
#include "cryptonote_core/blockchain.h"
|
||||||
#include "cryptonote_core/tx_pool.h"
|
|
||||||
#include "cryptonote_core/cryptonote_core.h"
|
|
||||||
#include "blockchain_db/testdb.h"
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
class TestDB: public cryptonote::BaseTestDB
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TestDB() { m_open = true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PREFIX_WINDOW(hf_version,window) \
|
|
||||||
struct get_test_options { \
|
|
||||||
const std::pair<uint8_t, uint64_t> hard_forks[3]; \
|
|
||||||
const cryptonote::test_options test_options = { \
|
|
||||||
hard_forks, \
|
|
||||||
window, \
|
|
||||||
}; \
|
|
||||||
get_test_options(): hard_forks{std::make_pair(1, (uint64_t)0), std::make_pair((uint8_t)hf_version, (uint64_t)1), std::make_pair((uint8_t)0, (uint64_t)0)} {} \
|
|
||||||
} opts; \
|
|
||||||
cryptonote::BlockchainAndPool bap; \
|
|
||||||
cryptonote::Blockchain *blockchain = &bap.blockchain; \
|
|
||||||
cryptonote::Blockchain *bc = blockchain; \
|
|
||||||
bool r = blockchain->init(new TestDB(), cryptonote::FAKECHAIN, true, &opts.test_options, 0, NULL); \
|
|
||||||
ASSERT_TRUE(r)
|
|
||||||
|
|
||||||
#define PREFIX(hf_version) PREFIX_WINDOW(hf_version, TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW)
|
|
||||||
|
|
||||||
TEST(fee_2021_scaling, relay_fee_cases_from_pdf)
|
TEST(fee_2021_scaling, relay_fee_cases_from_pdf)
|
||||||
{
|
{
|
||||||
PREFIX_WINDOW(HF_VERSION_2021_SCALING, CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE);
|
ASSERT_EQ(cryptonote::Blockchain::get_dynamic_base_fee(1200000000000, 300000), 38000);
|
||||||
|
ASSERT_EQ(cryptonote::Blockchain::get_dynamic_base_fee(1200000000000, 1425000), 1684 /*1680*/);
|
||||||
|
ASSERT_EQ(cryptonote::Blockchain::get_dynamic_base_fee(1200000000000, 1500000), 1520);
|
||||||
|
|
||||||
ASSERT_EQ(bc->get_dynamic_base_fee(1200000000000, 300000, HF_VERSION_2021_SCALING-1), 8000);
|
ASSERT_EQ(cryptonote::Blockchain::get_dynamic_base_fee(600000000000, 300000), 19000);
|
||||||
ASSERT_EQ(bc->get_dynamic_base_fee(1200000000000, 300000, HF_VERSION_2021_SCALING), 38000);
|
ASSERT_EQ(cryptonote::Blockchain::get_dynamic_base_fee(600000000000, 1425000), 842 /*840*/);
|
||||||
ASSERT_EQ(bc->get_dynamic_base_fee(1200000000000, 1425000, HF_VERSION_2021_SCALING-1), 1684 /*1680*/);
|
ASSERT_EQ(cryptonote::Blockchain::get_dynamic_base_fee(600000000000, 1500000), 760);
|
||||||
ASSERT_EQ(bc->get_dynamic_base_fee(1200000000000, 1425000, HF_VERSION_2021_SCALING), 1684 /*1680*/);
|
|
||||||
ASSERT_EQ(bc->get_dynamic_base_fee(1200000000000, 1500000, HF_VERSION_2021_SCALING-1), 1600);
|
|
||||||
ASSERT_EQ(bc->get_dynamic_base_fee(1200000000000, 1500000, HF_VERSION_2021_SCALING), 1520);
|
|
||||||
|
|
||||||
ASSERT_EQ(bc->get_dynamic_base_fee(600000000000, 300000, HF_VERSION_2021_SCALING-1), 4000);
|
|
||||||
ASSERT_EQ(bc->get_dynamic_base_fee(600000000000, 300000, HF_VERSION_2021_SCALING), 19000);
|
|
||||||
ASSERT_EQ(bc->get_dynamic_base_fee(600000000000, 1425000, HF_VERSION_2021_SCALING-1), 842 /*840*/);
|
|
||||||
ASSERT_EQ(bc->get_dynamic_base_fee(600000000000, 1425000, HF_VERSION_2021_SCALING), 842 /*840*/);
|
|
||||||
ASSERT_EQ(bc->get_dynamic_base_fee(600000000000, 1500000, HF_VERSION_2021_SCALING-1), 800);
|
|
||||||
ASSERT_EQ(bc->get_dynamic_base_fee(600000000000, 1500000, HF_VERSION_2021_SCALING), 760);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(fee_2021_scaling, wallet_fee_cases_from_pdf)
|
TEST(fee_2021_scaling, wallet_fee_cases_from_pdf)
|
||||||
{
|
{
|
||||||
PREFIX_WINDOW(HF_VERSION_2021_SCALING, CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE);
|
|
||||||
std::vector<uint64_t> fees;
|
std::vector<uint64_t> fees;
|
||||||
|
|
||||||
fees.clear();
|
fees.clear();
|
||||||
bc->get_dynamic_base_fee_estimate_2021_scaling(10, 600000000000, 300000, 300000, fees);
|
cryptonote::Blockchain::get_dynamic_base_fee_estimate_2021_scaling(600000000000, 300000, 300000, fees);
|
||||||
ASSERT_EQ(fees.size(), 4);
|
ASSERT_EQ(fees.size(), 4);
|
||||||
ASSERT_EQ(fees[0], 20000);
|
ASSERT_EQ(fees[0], 20000);
|
||||||
ASSERT_EQ(fees[1], 80000);
|
ASSERT_EQ(fees[1], 80000);
|
||||||
|
@ -99,7 +57,7 @@ TEST(fee_2021_scaling, wallet_fee_cases_from_pdf)
|
||||||
ASSERT_EQ(fees[3], 4000000);
|
ASSERT_EQ(fees[3], 4000000);
|
||||||
|
|
||||||
fees.clear();
|
fees.clear();
|
||||||
bc->get_dynamic_base_fee_estimate_2021_scaling(10, 600000000000, 15000000, 300000, fees);
|
cryptonote::Blockchain::get_dynamic_base_fee_estimate_2021_scaling(600000000000, 15000000, 300000, fees);
|
||||||
ASSERT_EQ(fees.size(), 4);
|
ASSERT_EQ(fees.size(), 4);
|
||||||
ASSERT_EQ(fees[0], 20000);
|
ASSERT_EQ(fees[0], 20000);
|
||||||
ASSERT_EQ(fees[1], 80000);
|
ASSERT_EQ(fees[1], 80000);
|
||||||
|
@ -107,7 +65,7 @@ TEST(fee_2021_scaling, wallet_fee_cases_from_pdf)
|
||||||
ASSERT_EQ(fees[3], 1300000);
|
ASSERT_EQ(fees[3], 1300000);
|
||||||
|
|
||||||
fees.clear();
|
fees.clear();
|
||||||
bc->get_dynamic_base_fee_estimate_2021_scaling(10, 600000000000, 1425000, 1425000, fees);
|
cryptonote::Blockchain::get_dynamic_base_fee_estimate_2021_scaling(600000000000, 1425000, 1425000, fees);
|
||||||
ASSERT_EQ(fees.size(), 4);
|
ASSERT_EQ(fees.size(), 4);
|
||||||
ASSERT_EQ(fees[0], 890);
|
ASSERT_EQ(fees[0], 890);
|
||||||
ASSERT_EQ(fees[1], 3600);
|
ASSERT_EQ(fees[1], 3600);
|
||||||
|
@ -115,7 +73,7 @@ TEST(fee_2021_scaling, wallet_fee_cases_from_pdf)
|
||||||
ASSERT_EQ(fees[3], 850000 /* 842000 */);
|
ASSERT_EQ(fees[3], 850000 /* 842000 */);
|
||||||
|
|
||||||
fees.clear();
|
fees.clear();
|
||||||
bc->get_dynamic_base_fee_estimate_2021_scaling(10, 600000000000, 1500000, 1500000, fees);
|
cryptonote::Blockchain::get_dynamic_base_fee_estimate_2021_scaling(600000000000, 1500000, 1500000, fees);
|
||||||
ASSERT_EQ(fees.size(), 4);
|
ASSERT_EQ(fees.size(), 4);
|
||||||
ASSERT_EQ(fees[0], 800);
|
ASSERT_EQ(fees[0], 800);
|
||||||
ASSERT_EQ(fees[1], 3200);
|
ASSERT_EQ(fees[1], 3200);
|
||||||
|
@ -123,7 +81,7 @@ TEST(fee_2021_scaling, wallet_fee_cases_from_pdf)
|
||||||
ASSERT_EQ(fees[3], 800000);
|
ASSERT_EQ(fees[3], 800000);
|
||||||
|
|
||||||
fees.clear();
|
fees.clear();
|
||||||
bc->get_dynamic_base_fee_estimate_2021_scaling(10, 600000000000, 75000000, 1500000, fees);
|
cryptonote::Blockchain::get_dynamic_base_fee_estimate_2021_scaling(600000000000, 75000000, 1500000, fees);
|
||||||
ASSERT_EQ(fees.size(), 4);
|
ASSERT_EQ(fees.size(), 4);
|
||||||
ASSERT_EQ(fees[0], 800);
|
ASSERT_EQ(fees[0], 800);
|
||||||
ASSERT_EQ(fees[1], 3200);
|
ASSERT_EQ(fees[1], 3200);
|
||||||
|
|
Loading…
Reference in New Issue