aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interfaces/mining.h8
-rw-r--r--src/node/interfaces.cpp14
-rw-r--r--src/rpc/mining.cpp12
3 files changed, 18 insertions, 16 deletions
diff --git a/src/interfaces/mining.h b/src/interfaces/mining.h
index b96881f67c..7d71a01450 100644
--- a/src/interfaces/mining.h
+++ b/src/interfaces/mining.h
@@ -5,6 +5,7 @@
#ifndef BITCOIN_INTERFACES_MINING_H
#define BITCOIN_INTERFACES_MINING_H
+#include <memory>
#include <optional>
#include <uint256.h>
@@ -44,6 +45,7 @@ public:
* @returns a block template
*/
virtual std::unique_ptr<node::CBlockTemplate> createNewBlock(const CScript& script_pub_key, bool use_mempool = true) = 0;
+
/**
* Processes new block. A valid new block is automatically relayed to peers.
*
@@ -62,12 +64,12 @@ public:
* Only works on top of our current best block.
* Does not check proof-of-work.
*
- * @param[out] state details of why a block failed to validate
* @param[in] block the block to validate
* @param[in] check_merkle_root call CheckMerkleRoot()
- * @returns false if any of the checks fail
+ * @param[out] state details of why a block failed to validate
+ * @returns false if it does not build on the current tip, or any of the checks fail
*/
- virtual bool testBlockValidity(BlockValidationState& state, const CBlock& block, bool check_merkle_root = true) = 0;
+ virtual bool testBlockValidity(const CBlock& block, bool check_merkle_root, BlockValidationState& state) = 0;
//! Get internal node context. Useful for RPC and testing,
//! but not accessible across processes.
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index e0bab6e22e..fa151407fa 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -870,10 +870,17 @@ public:
return context()->mempool->GetTransactionsUpdated();
}
- bool testBlockValidity(BlockValidationState& state, const CBlock& block, bool check_merkle_root) override
+ bool testBlockValidity(const CBlock& block, bool check_merkle_root, BlockValidationState& state) override
{
- LOCK(::cs_main);
- return TestBlockValidity(state, chainman().GetParams(), chainman().ActiveChainstate(), block, chainman().ActiveChain().Tip(), /*fCheckPOW=*/false, check_merkle_root);
+ LOCK(cs_main);
+ CBlockIndex* tip{chainman().ActiveChain().Tip()};
+ // Fail if the tip updated before the lock was taken
+ if (block.hashPrevBlock != tip->GetBlockHash()) {
+ state.Error("Block does not connect to current chain tip.");
+ return false;
+ }
+
+ return TestBlockValidity(state, chainman().GetParams(), chainman().ActiveChainstate(), block, tip, /*fCheckPOW=*/false, check_merkle_root);
}
std::unique_ptr<CBlockTemplate> createNewBlock(const CScript& script_pub_key, bool use_mempool) override
@@ -881,7 +888,6 @@ public:
BlockAssembler::Options options;
ApplyArgsManOptions(gArgs, options);
- LOCK(::cs_main);
return BlockAssembler{chainman().ActiveChainstate(), use_mempool ? context()->mempool.get() : nullptr, options}.CreateNewBlock(script_pub_key);
}
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 2b93c18965..7e420dcd9b 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -371,8 +371,6 @@ static RPCHelpMan generateblock()
ChainstateManager& chainman = EnsureChainman(node);
{
- LOCK(cs_main);
-
std::unique_ptr<CBlockTemplate> blocktemplate{miner.createNewBlock(coinbase_script, /*use_mempool=*/false)};
if (!blocktemplate) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
@@ -387,10 +385,8 @@ static RPCHelpMan generateblock()
RegenerateCommitments(block, chainman);
{
- LOCK(cs_main);
-
BlockValidationState state;
- if (!miner.testBlockValidity(state, block, /*check_merkle_root=*/false)) {
+ if (!miner.testBlockValidity(block, /*check_merkle_root=*/false, state)) {
throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("testBlockValidity failed: %s", state.ToString()));
}
}
@@ -667,9 +663,7 @@ static RPCHelpMan getblocktemplate()
ChainstateManager& chainman = EnsureChainman(node);
Mining& miner = EnsureMining(node);
LOCK(cs_main);
- std::optional<uint256> maybe_tip{miner.getTipHash()};
- CHECK_NONFATAL(maybe_tip);
- uint256 tip{maybe_tip.value()};
+ uint256 tip{CHECK_NONFATAL(miner.getTipHash()).value()};
std::string strMode = "template";
UniValue lpval = NullUniValue;
@@ -713,7 +707,7 @@ static RPCHelpMan getblocktemplate()
return "inconclusive-not-best-prevblk";
}
BlockValidationState state;
- miner.testBlockValidity(state, block);
+ miner.testBlockValidity(block, /*check_merkle_root=*/true, state);
return BIP22ValidationResult(state);
}