Skip to content

Commit

Permalink
Add intervening v5 fork for increased min block size
Browse files Browse the repository at this point in the history
Minimum mixin 4 and enforced ringct is moved from v5 to v6.
v5 is now used for an increased minimum block size (from 60000
to 300000) to cater for larger typical/minimum transaction size.

The fee algorithm is also changed to decrease the base per kB
fee, and add a cheap tier for those transactions which we do
not care if they get delayed (or even included in a block).
  • Loading branch information
moneromooo-monero committed Mar 15, 2017
1 parent 1dfed89 commit 3396a9f
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 76 deletions.
11 changes: 10 additions & 1 deletion src/cryptonote_basic/cryptonote_basic_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ namespace cryptonote {
/* Cryptonote helper functions */
/************************************************************************/
//-----------------------------------------------------------------------------------------------
size_t get_min_block_size(uint8_t version)
{
if (version < 2)
return CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1;
if (version < 5)
return CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2;
return CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5;
}
//-----------------------------------------------------------------------------------------------
size_t get_max_block_size()
{
return CRYPTONOTE_MAX_BLOCK_SIZE;
Expand All @@ -89,7 +98,7 @@ namespace cryptonote {
base_reward = FINAL_SUBSIDY_PER_MINUTE*target_minutes;
}

uint64_t full_reward_zone = version < 2 ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2;
uint64_t full_reward_zone = get_min_block_size(version);

//make it soft
if (median_size < full_reward_zone) {
Expand Down
1 change: 1 addition & 0 deletions src/cryptonote_basic/cryptonote_basic_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ namespace cryptonote {
/************************************************************************/
/* Cryptonote helper functions */
/************************************************************************/
size_t get_min_block_size(uint8_t version);
size_t get_max_block_size();
size_t get_max_tx_size();
bool get_block_reward(size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint8_t version);
Expand Down
5 changes: 5 additions & 0 deletions src/cryptonote_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW 100
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 60000 //size of block (bytes) after which reward for block calculated using block size
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 20000 //size of block (bytes) after which reward for block calculated using block size - before first fork
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 300000 //size of block (bytes) after which reward for block calculated using block size - second change, from v5
#define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE 600
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT 12
// COIN - number of smallest units in one coin
Expand All @@ -66,6 +67,7 @@
#define FEE_PER_KB ((uint64_t)2000000000) // 2 * pow(10, 9)
#define DYNAMIC_FEE_PER_KB_BASE_FEE ((uint64_t)2000000000) // 2 * pow(10,9)
#define DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD ((uint64_t)10000000000000) // 10 * pow(10,12)
#define DYNAMIC_FEE_PER_KB_BASE_FEE_V5 ((uint64_t)2000000000 * (uint64_t)CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5)

#define ORPHANED_BLOCKS_MAX_COUNT 100

Expand Down Expand Up @@ -128,6 +130,9 @@
#define THREAD_STACK_SIZE 5 * 1024 * 1024

#define HF_VERSION_DYNAMIC_FEE 4
#define HF_VERSION_MIN_MIXIN_4 6
#define HF_VERSION_ENFORCE_RCT 6

#define PER_KB_FEE_QUANTIZATION_DECIMALS 8

// New constants are intended to go here
Expand Down
33 changes: 19 additions & 14 deletions src/cryptonote_core/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ static const struct {
// version 4 starts from block 1220516, which is on or around the 5th of January, 2017. Fork time finalised on 2016-09-18.
{ 4, 1220516, 0, 1483574400 },

// version 5 starts from block 1406997, which is on or around the 20th of September, 2017. Fork time finalised on 2016-09-18.
{ 5, 1406997, 0, 1505865600 },
// version 5 starts from block 1288616, which is on or around the 15th of april, 2017. Fork time finalised on 2016-03-14.
{ 5, 1288616, 0, 1489520158 },
};
static const uint64_t mainnet_hard_fork_version_1_till = 1009826;

Expand Down Expand Up @@ -2426,7 +2426,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
{
size_t n_unmixable = 0, n_mixable = 0;
size_t mixin = std::numeric_limits<size_t>::max();
const size_t min_mixin = hf_version >= 5 ? 4 : 2;
const size_t min_mixin = hf_version >= HF_VERSION_MIN_MIXIN_4 ? 4 : 2;
for (const auto& txin : tx.vin)
{
// non txin_to_key inputs will be rejected below
Expand Down Expand Up @@ -2479,7 +2479,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
tvc.m_verifivation_failed = true;
return false;
}
const size_t min_tx_version = (n_unmixable > 0 ? 1 : (hf_version >= 5) ? 2 : 1);
const size_t min_tx_version = (n_unmixable > 0 ? 1 : (hf_version >= HF_VERSION_ENFORCE_RCT) ? 2 : 1);
if (tx.version < min_tx_version)
{
MERROR_VER("transaction version " << (unsigned)tx.version << " is lower than min accepted version " << min_tx_version);
Expand Down Expand Up @@ -2809,15 +2809,19 @@ static uint64_t get_fee_quantization_mask()
}

//------------------------------------------------------------------
uint64_t Blockchain::get_dynamic_per_kb_fee(uint64_t block_reward, size_t median_block_size)
uint64_t Blockchain::get_dynamic_per_kb_fee(uint64_t block_reward, size_t median_block_size, uint8_t version)
{
if (median_block_size < CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2)
median_block_size = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2;
const uint64_t min_block_size = get_min_block_size(version);
const uint64_t fee_per_kb_base = version >= 5 ? DYNAMIC_FEE_PER_KB_BASE_FEE_V5 : DYNAMIC_FEE_PER_KB_BASE_FEE;

uint64_t unscaled_fee_per_kb = (DYNAMIC_FEE_PER_KB_BASE_FEE * CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / median_block_size);
if (median_block_size < min_block_size)
median_block_size = min_block_size;

uint64_t unscaled_fee_per_kb = (fee_per_kb_base * min_block_size / median_block_size);
uint64_t hi, lo = mul128(unscaled_fee_per_kb, block_reward, &hi);
static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD % 1000000 == 0, "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD must be divisible by 1000000");
static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000 <= std::numeric_limits<uint32_t>::max(), "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD is too large");

// divide in two steps, since the divisor must be 32 bits, but DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD isn't
div128_32(hi, lo, DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000, &hi, &lo);
div128_32(hi, lo, 1000000, &hi, &lo);
Expand Down Expand Up @@ -2848,7 +2852,7 @@ bool Blockchain::check_fee(size_t blob_size, uint64_t fee) const
uint64_t base_reward;
if (!get_block_reward(median, 1, already_generated_coins, base_reward, version))
return false;
fee_per_kb = get_dynamic_per_kb_fee(base_reward, median);
fee_per_kb = get_dynamic_per_kb_fee(base_reward, median, version);
}
MDEBUG("Using " << print_money(fee) << "/kB fee");

Expand All @@ -2875,14 +2879,15 @@ uint64_t Blockchain::get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks) cons
if (grace_blocks >= CRYPTONOTE_REWARD_BLOCKS_WINDOW)
grace_blocks = CRYPTONOTE_REWARD_BLOCKS_WINDOW - 1;

const uint64_t min_block_size = get_min_block_size(version);
std::vector<size_t> sz;
get_last_n_blocks_sizes(sz, CRYPTONOTE_REWARD_BLOCKS_WINDOW - grace_blocks);
for (size_t i = 0; i < grace_blocks; ++i)
sz.push_back(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2);
sz.push_back(min_block_size);

uint64_t median = epee::misc_utils::median(sz);
if(median <= CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2)
median = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2;
if(median <= min_block_size)
median = min_block_size;

uint64_t already_generated_coins = m_db->height() ? m_db->get_block_already_generated_coins(m_db->height() - 1) : 0;
uint64_t base_reward;
Expand All @@ -2892,7 +2897,7 @@ uint64_t Blockchain::get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks) cons
base_reward = BLOCK_REWARD_OVERESTIMATE;
}

uint64_t fee = get_dynamic_per_kb_fee(base_reward, median);
uint64_t fee = get_dynamic_per_kb_fee(base_reward, median, version);
MDEBUG("Estimating " << grace_blocks << "-block fee at " << print_money(fee) << "/kB");
return fee;
}
Expand Down Expand Up @@ -3411,7 +3416,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash&
//------------------------------------------------------------------
bool Blockchain::update_next_cumulative_size_limit()
{
uint64_t full_reward_zone = get_current_hard_fork_version() < 2 ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2;
uint64_t full_reward_zone = get_min_block_size(get_current_hard_fork_version());

LOG_PRINT_L3("Blockchain::" << __func__);
std::vector<size_t> sz;
Expand Down
3 changes: 2 additions & 1 deletion src/cryptonote_core/blockchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,10 +520,11 @@ namespace cryptonote
*
* @param block_reward the current block reward
* @param median_block_size the median blob's size in the past window
* @param version hard fork version for rules and constants to use
*
* @return the per kB fee
*/
static uint64_t get_dynamic_per_kb_fee(uint64_t block_reward, size_t median_block_size);
static uint64_t get_dynamic_per_kb_fee(uint64_t block_reward, size_t median_block_size, uint8_t version);

/**
* @brief get dynamic per kB fee estimate for the next few blocks
Expand Down
21 changes: 7 additions & 14 deletions src/cryptonote_core/tx_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ namespace cryptonote
// codebase. As it stands, it is at best nontrivial to test
// whether or not changing these parameters (or adding new)
// will work correctly.
size_t const TRANSACTION_SIZE_LIMIT_V1 = (((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE);
size_t const TRANSACTION_SIZE_LIMIT_V2 = (((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE);
time_t const MIN_RELAY_TIME = (60 * 5); // only start re-relaying transactions after that many seconds
time_t const MAX_RELAY_TIME = (60 * 60 * 4); // at most that many seconds between resends
float const ACCEPT_THRESHOLD = 1.0f;
Expand All @@ -78,6 +76,11 @@ namespace cryptonote
{
return amount * ACCEPT_THRESHOLD;
}

uint64_t get_transaction_size_limit(uint8_t version)
{
return get_min_block_size(version) * 125 / 100 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
}
}
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
Expand Down Expand Up @@ -149,7 +152,7 @@ namespace cryptonote
return false;
}

size_t tx_size_limit = (version < 2 ? TRANSACTION_SIZE_LIMIT_V1 : TRANSACTION_SIZE_LIMIT_V2);
size_t tx_size_limit = get_transaction_size_limit(version);
if (!kept_by_block && blob_size >= tx_size_limit)
{
LOG_PRINT_L1("transaction is too big: " << blob_size << " bytes, maximum size: " << tx_size_limit);
Expand Down Expand Up @@ -641,15 +644,6 @@ namespace cryptonote
continue;
}

#if 1
// If we've exceeded the penalty free size,
// stop including more tx
if (total_size > median_size)
{
LOG_PRINT_L2(" would exceed median block size");
break;
}
#else
// If we're getting lower coinbase tx,
// stop including more tx
uint64_t block_reward;
Expand All @@ -666,7 +660,6 @@ namespace cryptonote
sorted_it++;
continue;
}
#endif

// Skip transactions that are not ready to be
// included into the blockchain or that are
Expand Down Expand Up @@ -705,7 +698,7 @@ namespace cryptonote
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
size_t n_removed = 0;
size_t tx_size_limit = (version < 2 ? TRANSACTION_SIZE_LIMIT_V1 : TRANSACTION_SIZE_LIMIT_V2);
size_t tx_size_limit = get_transaction_size_limit(version);
for (auto it = m_transactions.begin(); it != m_transactions.end(); ) {
if (it->second.blob_size >= tx_size_limit) {
LOG_PRINT_L1("Transaction " << get_transaction_hash(it->second.tx) << " is too big (" << it->second.blob_size << " bytes), removing it from pool");
Expand Down
12 changes: 6 additions & 6 deletions src/simplewallet/simplewallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ bool simple_wallet::set_default_priority(const std::vector<std::string> &args/*
{
if (strchr(args[1].c_str(), '-'))
{
fail_msg_writer() << tr("priority must be 0, 1, 2, or 3 ");
fail_msg_writer() << tr("priority must be 0, 1, 2, 3, or 4 ");
return true;
}
if (args[1] == "0")
Expand All @@ -501,9 +501,9 @@ bool simple_wallet::set_default_priority(const std::vector<std::string> &args/*
else
{
priority = boost::lexical_cast<int>(args[1]);
if (priority != 1 && priority != 2 && priority != 3)
if (priority < 1 || priority > 4)
{
fail_msg_writer() << tr("priority must be 0, 1, 2, or 3");
fail_msg_writer() << tr("priority must be 0, 1, 2, 3,or 4");
return true;
}
}
Expand All @@ -518,7 +518,7 @@ bool simple_wallet::set_default_priority(const std::vector<std::string> &args/*
}
catch(const boost::bad_lexical_cast &)
{
fail_msg_writer() << tr("priority must be 0, 1, 2 or 3");
fail_msg_writer() << tr("priority must be 0, 1, 2 3,or 4");
return true;
}
catch(...)
Expand Down Expand Up @@ -659,7 +659,7 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("viewkey", boost::bind(&simple_wallet::viewkey, this, _1), tr("Display private view key"));
m_cmd_binder.set_handler("spendkey", boost::bind(&simple_wallet::spendkey, this, _1), tr("Display private spend key"));
m_cmd_binder.set_handler("seed", boost::bind(&simple_wallet::seed, this, _1), tr("Display Electrum-style mnemonic seed"));
m_cmd_binder.set_handler("set", boost::bind(&simple_wallet::set_variable, this, _1), tr("Available options: seed language - set wallet seed language; always-confirm-transfers <1|0> - whether to confirm unsplit txes; print-ring-members <1|0> - whether to print detailed information about ring members during confirmation; store-tx-info <1|0> - whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference; default-mixin <n> - set default mixin (default is 4); auto-refresh <1|0> - whether to automatically sync new blocks from the daemon; refresh-type <full|optimize-coinbase|no-coinbase|default> - set wallet refresh behaviour; priority [1|2|3] - normal/elevated/priority fee; confirm-missing-payment-id <1|0>; ask-password <1|0>; unit <monero|millinero|micronero|nanonero|piconero> - set default monero (sub-)unit"));
m_cmd_binder.set_handler("set", boost::bind(&simple_wallet::set_variable, this, _1), tr("Available options: seed language - set wallet seed language; always-confirm-transfers <1|0> - whether to confirm unsplit txes; print-ring-members <1|0> - whether to print detailed information about ring members during confirmation; store-tx-info <1|0> - whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference; default-mixin <n> - set default mixin (default is 4); auto-refresh <1|0> - whether to automatically sync new blocks from the daemon; refresh-type <full|optimize-coinbase|no-coinbase|default> - set wallet refresh behaviour; priority [0|1|2|3|4] - default/unimportant/normal/elevated/priority fee; confirm-missing-payment-id <1|0>; ask-password <1|0>; unit <monero|millinero|micronero|nanonero|piconero> - set default monero (sub-)unit"));
m_cmd_binder.set_handler("rescan_spent", boost::bind(&simple_wallet::rescan_spent, this, _1), tr("Rescan blockchain for spent outputs"));
m_cmd_binder.set_handler("get_tx_key", boost::bind(&simple_wallet::get_tx_key, this, _1), tr("Get transaction key (r) for a given <txid>"));
m_cmd_binder.set_handler("check_tx_key", boost::bind(&simple_wallet::check_tx_key, this, _1), tr("Check amount going to <address> in <txid>"));
Expand Down Expand Up @@ -795,7 +795,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
{
if (args.size() <= 1)
{
fail_msg_writer() << tr("set priority: needs an argument: 0, 1, 2, or 3");
fail_msg_writer() << tr("set priority: needs an argument: 0, 1, 2, 3, or 4");
return true;
}
else
Expand Down
Loading

0 comments on commit 3396a9f

Please sign in to comment.