Merge pull request #9232

7194506 Blockchain: remove old fee calc logic (jeffro256)
This commit is contained in:
luigi1111 2024-05-20 23:18:07 -05:00
commit 6462d3760d
No known key found for this signature in database
GPG Key ID: F4ACA0183641E010
7 changed files with 32 additions and 313 deletions

View File

@ -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.

View File

@ -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;

View File

@ -3021,16 +3021,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;

View File

@ -841,14 +841,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();

View File

@ -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

View File

@ -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));
}
}
}
}

View File

@ -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);