diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 11dbb2fe..5f9d6937 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1085,7 +1085,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m size_t txs_size; uint64_t fee; - if (!m_tx_pool.fill_block_template(b, median_size, already_generated_coins, txs_size, fee)) + if (!m_tx_pool.fill_block_template(b, median_size, already_generated_coins, txs_size, fee, m_hardfork->get_current_version())) { return false; } diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index ca4b6d6f..59ac534f 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -60,6 +60,7 @@ namespace cryptonote 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 = 0.99f; // a kind of increasing backoff within min/max bounds time_t get_relay_delay(time_t now, time_t received) @@ -69,6 +70,11 @@ namespace cryptonote d = MAX_RELAY_TIME; return d; } + + uint64_t template_accept_threshold(uint64_t amount) + { + return amount * ACCEPT_THRESHOLD; + } } //--------------------------------------------------------------------------------- //--------------------------------------------------------------------------------- @@ -587,7 +593,7 @@ namespace cryptonote } //--------------------------------------------------------------------------------- //TODO: investigate whether boolean return is appropriate - bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee) + bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee, uint8_t version) { // Warning: This function takes already_generated_ // coins as an argument and appears to do nothing @@ -595,47 +601,51 @@ namespace cryptonote CRITICAL_REGION_LOCAL(m_transactions_lock); + uint64_t best_coinbase = 0; total_size = 0; fee = 0; - // Maximum block size is 130% of the median block size. This gives a - // little extra headroom for the max size transaction. - size_t max_total_size = (130 * median_size) / 100 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; + size_t max_total_size = 2 * median_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; std::unordered_set k_images; + LOG_PRINT_L2("Filling block template, median size " << median_size << ", " << m_txs_by_fee.size() << " txes in the pool"); auto sorted_it = m_txs_by_fee.begin(); while (sorted_it != m_txs_by_fee.end()) { auto tx_it = m_transactions.find(sorted_it->second); + LOG_PRINT_L2("Considering " << tx_it->first << ", size " << tx_it->second.blob_size << ", current block size " << total_size << "/" << max_total_size << ", current coinbase " << print_money(best_coinbase)); // Can not exceed maximum block size if (max_total_size < total_size + tx_it->second.blob_size) { + LOG_PRINT_L2(" would exceed maximum block size"); sorted_it++; continue; } - // If adding this tx will make the block size - // greater than CRYPTONOTE_GETBLOCKTEMPLATE_MAX - // _BLOCK_SIZE bytes, reject the tx; this will - // keep block sizes from becoming too unwieldly - // to propagate at 60s block times. - if ( (total_size + tx_it->second.blob_size) > CRYPTONOTE_GETBLOCKTEMPLATE_MAX_BLOCK_SIZE ) - { - sorted_it++; - continue; - } - - // If we've exceeded the penalty free size, + // If we're getting lower coinbase tx, // stop including more tx - if (total_size > median_size) - break; + uint64_t block_reward; + if(!get_block_reward(median_size, total_size + tx_it->second.blob_size, already_generated_coins, block_reward, version)) + { + LOG_PRINT_L2(" would exceed maximum block size"); + sorted_it++; + continue; + } + uint64_t coinbase = block_reward + fee; + if (coinbase < template_accept_threshold(best_coinbase)) + { + LOG_PRINT_L2(" would decrease coinbase to " << print_money(coinbase)); + sorted_it++; + continue; + } // Skip transactions that are not ready to be // included into the blockchain or that are // missing key images if (!is_transaction_ready_to_go(tx_it->second) || have_key_images(k_images, tx_it->second.tx)) { + LOG_PRINT_L2(" not ready to go, or key images already seen"); sorted_it++; continue; } @@ -643,10 +653,15 @@ namespace cryptonote bl.tx_hashes.push_back(tx_it->first); total_size += tx_it->second.blob_size; fee += tx_it->second.fee; + best_coinbase = coinbase; append_key_images(k_images, tx_it->second.tx); sorted_it++; + LOG_PRINT_L2(" added, new block size " << total_size << "/" << max_total_size << ", coinbase " << print_money(best_coinbase)); } + LOG_PRINT_L2("Block template filled with " << bl.tx_hashes.size() << " txes, size " + << total_size << "/" << max_total_size << ", coinbase " << print_money(best_coinbase) + << " (including " << print_money(fee) << " in fees)"); return true; } //--------------------------------------------------------------------------------- diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 794b8671..32a05b0f 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -216,10 +216,11 @@ namespace cryptonote * @param already_generated_coins the current total number of coins "minted" * @param total_size return-by-reference the total size of the new block * @param fee return-by-reference the total of fees from the included transactions + * @param version hard fork version to use for consensus rules * * @return true */ - bool fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee); + bool fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee, uint8_t version); /** * @brief get a list of all transactions in the pool diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 41b1fad2..4d415b4c 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -473,8 +473,9 @@ bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, u if (!first) std::cout << std::endl; std::cout + << "height: " << header.height << ", timestamp: " << header.timestamp << ", difficulty: " << header.difficulty + << ", size: " << header.block_size << std::endl << "major version: " << (unsigned)header.major_version << ", minor version: " << (unsigned)header.minor_version << std::endl - << "height: " << header.height << ", timestamp: " << header.timestamp << ", difficulty: " << header.difficulty << std::endl << "block id: " << header.hash << ", previous block id: " << header.prev_hash << std::endl << "difficulty: " << header.difficulty << ", nonce " << header.nonce << ", reward " << cryptonote::print_money(header.reward) << std::endl; first = false; diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index c2ff63fc..6ca01ed2 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -143,6 +143,7 @@ namespace cryptonote res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count(); res.testnet = m_testnet; res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1); + res.block_size_limit = m_core.get_blockchain_storage().get_current_cumulative_blocksize_limit(); res.status = CORE_RPC_STATUS_OK; return true; } @@ -891,6 +892,7 @@ namespace cryptonote response.hash = string_tools::pod_to_hex(hash); response.difficulty = m_core.get_blockchain_storage().block_difficulty(height); response.reward = get_block_reward(blk); + response.block_size = m_core.get_blockchain_storage().get_db().get_block_size(height); return true; } //------------------------------------------------------------------------------------------------------------------------------ @@ -1161,6 +1163,7 @@ namespace cryptonote res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count(); res.testnet = m_testnet; res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1); + res.block_size_limit = m_core.get_blockchain_storage().get_current_cumulative_blocksize_limit(); res.status = CORE_RPC_STATUS_OK; return true; } diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 6060cee3..c08e4306 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -49,7 +49,7 @@ namespace cryptonote // advance which version they will stop working with // Don't go over 32767 for any of these #define CORE_RPC_VERSION_MAJOR 1 -#define CORE_RPC_VERSION_MINOR 0 +#define CORE_RPC_VERSION_MINOR 3 #define CORE_RPC_VERSION (((CORE_RPC_VERSION_MAJOR)<<16)|(CORE_RPC_VERSION_MINOR)) struct COMMAND_RPC_GET_HEIGHT @@ -512,6 +512,7 @@ namespace cryptonote bool testnet; std::string top_block_hash; uint64_t cumulative_difficulty; + uint64_t block_size_limit; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) @@ -529,6 +530,7 @@ namespace cryptonote KV_SERIALIZE(testnet) KV_SERIALIZE(top_block_hash) KV_SERIALIZE(cumulative_difficulty) + KV_SERIALIZE(block_size_limit) END_KV_SERIALIZE_MAP() }; }; @@ -693,6 +695,7 @@ namespace cryptonote std::string hash; difficulty_type difficulty; uint64_t reward; + uint64_t block_size; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(major_version) @@ -706,6 +709,7 @@ namespace cryptonote KV_SERIALIZE(hash) KV_SERIALIZE(difficulty) KV_SERIALIZE(reward) + KV_SERIALIZE(block_size) END_KV_SERIALIZE_MAP() };