blockchain: fix block template creation race
If two create_block_template are called at nearly the same time, and a block is added at nearly the same time, this could happen: - the blockchain top block is B0 - thread 1 enters create_block_template, takes blockchain lock - thread 1 creates a fresh block referencing prev block B0 - thread 1 releases blockchain lock - thread 0 adds a new block - thread 0 enters create_block_template - thread 0 updates block template - thread 1 takes txpool lock and continues creating block template - thread 1 overwrites block template with previous data
This commit is contained in:
parent
362ecad06c
commit
0622741c03
|
@ -1264,7 +1264,10 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
||||||
uint64_t already_generated_coins;
|
uint64_t already_generated_coins;
|
||||||
uint64_t pool_cookie;
|
uint64_t pool_cookie;
|
||||||
|
|
||||||
CRITICAL_REGION_BEGIN(m_blockchain_lock);
|
m_tx_pool.lock();
|
||||||
|
const auto txpool_unlocker = epee::misc_utils::create_scope_leave_handler([&]() { m_tx_pool.unlock(); });
|
||||||
|
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||||
|
|
||||||
height = m_db->height();
|
height = m_db->height();
|
||||||
if (m_btc_valid) {
|
if (m_btc_valid) {
|
||||||
// The pool cookie is atomic. The lack of locking is OK, as if it changes
|
// The pool cookie is atomic. The lack of locking is OK, as if it changes
|
||||||
|
@ -1300,8 +1303,6 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
||||||
median_weight = m_current_block_cumul_weight_limit / 2;
|
median_weight = m_current_block_cumul_weight_limit / 2;
|
||||||
already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
|
already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
|
||||||
|
|
||||||
CRITICAL_REGION_END();
|
|
||||||
|
|
||||||
size_t txs_weight;
|
size_t txs_weight;
|
||||||
uint64_t fee;
|
uint64_t fee;
|
||||||
if (!m_tx_pool.fill_block_template(b, median_weight, already_generated_coins, txs_weight, fee, expected_reward, m_hardfork->get_current_version()))
|
if (!m_tx_pool.fill_block_template(b, median_weight, already_generated_coins, txs_weight, fee, expected_reward, m_hardfork->get_current_version()))
|
||||||
|
@ -1312,7 +1313,6 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
||||||
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
|
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
|
||||||
size_t real_txs_weight = 0;
|
size_t real_txs_weight = 0;
|
||||||
uint64_t real_fee = 0;
|
uint64_t real_fee = 0;
|
||||||
CRITICAL_REGION_BEGIN(m_tx_pool.m_transactions_lock);
|
|
||||||
for(crypto::hash &cur_hash: b.tx_hashes)
|
for(crypto::hash &cur_hash: b.tx_hashes)
|
||||||
{
|
{
|
||||||
auto cur_res = m_tx_pool.m_transactions.find(cur_hash);
|
auto cur_res = m_tx_pool.m_transactions.find(cur_hash);
|
||||||
|
@ -1356,7 +1356,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
||||||
{
|
{
|
||||||
LOG_ERROR("Creating block template: error: wrongly calculated fee");
|
LOG_ERROR("Creating block template: error: wrongly calculated fee");
|
||||||
}
|
}
|
||||||
CRITICAL_REGION_END();
|
|
||||||
MDEBUG("Creating block template: height " << height <<
|
MDEBUG("Creating block template: height " << height <<
|
||||||
", median weight " << median_weight <<
|
", median weight " << median_weight <<
|
||||||
", already generated coins " << already_generated_coins <<
|
", already generated coins " << already_generated_coins <<
|
||||||
|
|
Loading…
Reference in New Issue