From 621c634b7fe14fbf151cd222eeaade3505059249 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 24 Dec 2024 15:55:22 +0100 Subject: [PATCH] rpc: Extend scope of validation mutex in generateblock The mutex (required by TestBlockValidity) must be held after creating the block, until TestBlockValidity is called. Otherwise, it is possible that the chain advances in the meantime and leads to a crash in TestBlockValidity: Assertion failed: pindexPrev && pindexPrev == chainstate.m_chain.Tip() (validation.cpp: TestBlockValidity: 4338) The diff can be reviewed with the git options --ignore-all-space --function-context Github-Pull: 31563 Rebased-From: fa62c8b1f04a5386ffa171aeff713d55bd874cbe --- src/rpc/mining.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 3c41e136eca..445fd8c3447 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -370,20 +370,21 @@ static RPCHelpMan generateblock() ChainstateManager& chainman = EnsureChainman(node); { - std::unique_ptr blocktemplate{miner.createNewBlock(coinbase_script, {.use_mempool = false})}; - if (!blocktemplate) { - throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); + LOCK(chainman.GetMutex()); + { + std::unique_ptr blocktemplate{miner.createNewBlock(coinbase_script, {.use_mempool = false})}; + if (!blocktemplate) { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); + } + block = blocktemplate->block; } - block = blocktemplate->block; - } - CHECK_NONFATAL(block.vtx.size() == 1); + CHECK_NONFATAL(block.vtx.size() == 1); - // Add transactions - block.vtx.insert(block.vtx.end(), txs.begin(), txs.end()); - RegenerateCommitments(block, chainman); + // Add transactions + block.vtx.insert(block.vtx.end(), txs.begin(), txs.end()); + RegenerateCommitments(block, chainman); - { BlockValidationState state; if (!miner.testBlockValidity(block, /*check_merkle_root=*/false, state)) { throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("testBlockValidity failed: %s", state.ToString()));