diff options
author | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2019-02-18 15:43:08 +0000 |
---|---|---|
committer | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2019-02-18 15:43:08 +0000 |
commit | 0c0f6034c099aadbb63c42c604beb8ba853a55e4 (patch) | |
tree | c169ea0ce1c4dc8a347162a311f2ca7162600a2a | |
parent | Merge pull request #5159 (diff) | |
download | monero-0c0f6034c099aadbb63c42c604beb8ba853a55e4.tar.xz |
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
-rw-r--r-- | src/cryptonote_core/blockchain.cpp | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 343bec330..1b11f1c73 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1274,7 +1274,10 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m uint64_t already_generated_coins; 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(); if (m_btc_valid) { // The pool cookie is atomic. The lack of locking is OK, as if it changes @@ -1310,8 +1313,6 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m median_weight = m_current_block_cumul_weight_limit / 2; already_generated_coins = m_db->get_block_already_generated_coins(height - 1); - CRITICAL_REGION_END(); - size_t txs_weight; 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())) @@ -1322,7 +1323,6 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m #if defined(DEBUG_CREATE_BLOCK_TEMPLATE) size_t real_txs_weight = 0; uint64_t real_fee = 0; - CRITICAL_REGION_BEGIN(m_tx_pool.m_transactions_lock); for(crypto::hash &cur_hash: b.tx_hashes) { auto cur_res = m_tx_pool.m_transactions.find(cur_hash); @@ -1366,7 +1366,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m { LOG_ERROR("Creating block template: error: wrongly calculated fee"); } - CRITICAL_REGION_END(); + MDEBUG("Creating block template: height " << height << ", median weight " << median_weight << ", already generated coins " << already_generated_coins << |