aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSjors Provoost <sjors@sprovoost.nl>2024-06-10 17:58:13 +0200
committerSjors Provoost <sjors@sprovoost.nl>2024-06-18 18:47:51 +0200
commitd8a3496b5ad27bea4c79ea0344f595cc1b95f0d3 (patch)
tree0aac30137fb85c4fd26398c43f4b2da75002cdc9
parent8ecb6816781c7c7f423b501cbb2de3abd7250119 (diff)
rpc: call TestBlockValidity via miner interface
-rw-r--r--src/interfaces/mining.h15
-rw-r--r--src/node/interfaces.cpp7
-rw-r--r--src/rpc/mining.cpp14
-rwxr-xr-xtest/functional/rpc_generate.py2
4 files changed, 31 insertions, 7 deletions
diff --git a/src/interfaces/mining.h b/src/interfaces/mining.h
index afcd8d1cda..603d8475d3 100644
--- a/src/interfaces/mining.h
+++ b/src/interfaces/mining.h
@@ -9,6 +9,9 @@ namespace node {
struct NodeContext;
} // namespace node
+class BlockValidationState;
+class CBlock;
+
namespace interfaces {
//! Interface giving clients (RPC, Stratum v2 Template Provider in the future)
@@ -22,6 +25,18 @@ public:
//! If this chain is exclusively used for testing
virtual bool isTestChain() = 0;
+ /**
+ * Check a block is completely valid from start to finish.
+ * 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
+ */
+ virtual bool testBlockValidity(BlockValidationState& state, const CBlock& block, bool check_merkle_root = true) = 0;
+
//! Get internal node context. Useful for RPC and testing,
//! but not accessible across processes.
virtual node::NodeContext* context() { return nullptr; }
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index e44cb51873..a528afcff0 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -8,6 +8,7 @@
#include <chain.h>
#include <chainparams.h>
#include <common/args.h>
+#include <consensus/validation.h>
#include <deploymentstatus.h>
#include <external_signer.h>
#include <index/blockfilterindex.h>
@@ -844,6 +845,12 @@ public:
return chainman().GetParams().IsTestChain();
}
+ bool testBlockValidity(BlockValidationState& state, const CBlock& block, bool check_merkle_root) override
+ {
+ LOCK(::cs_main);
+ return TestBlockValidity(state, chainman().GetParams(), chainman().ActiveChainstate(), block, chainman().ActiveChain().Tip(), /*fCheckPOW=*/false, check_merkle_root);
+ }
+
NodeContext* context() override { return &m_node; }
ChainstateManager& chainman() { return *Assert(m_node.chainman); }
NodeContext& m_node;
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 0e9d4829d2..a9968b6e5f 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -339,6 +339,7 @@ static RPCHelpMan generateblock()
}
NodeContext& node = EnsureAnyNodeContext(request.context);
+ Mining& miner = EnsureMining(node);
const CTxMemPool& mempool = EnsureMemPool(node);
std::vector<CTransactionRef> txs;
@@ -389,8 +390,8 @@ static RPCHelpMan generateblock()
LOCK(cs_main);
BlockValidationState state;
- if (!TestBlockValidity(state, chainman.GetParams(), chainman.ActiveChainstate(), block, chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock), false, false)) {
- throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("TestBlockValidity failed: %s", state.ToString()));
+ if (!miner.testBlockValidity(state, block, /*check_merkle_root=*/false)) {
+ throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("testBlockValidity failed: %s", state.ToString()));
}
}
@@ -664,6 +665,7 @@ static RPCHelpMan getblocktemplate()
{
NodeContext& node = EnsureAnyNodeContext(request.context);
ChainstateManager& chainman = EnsureChainman(node);
+ Mining& miner = EnsureMining(node);
LOCK(cs_main);
std::string strMode = "template";
@@ -706,11 +708,12 @@ static RPCHelpMan getblocktemplate()
}
CBlockIndex* const pindexPrev = active_chain.Tip();
- // TestBlockValidity only supports blocks built on the current Tip
- if (block.hashPrevBlock != pindexPrev->GetBlockHash())
+ // testBlockValidity only supports blocks built on the current Tip
+ if (block.hashPrevBlock != pindexPrev->GetBlockHash()) {
return "inconclusive-not-best-prevblk";
+ }
BlockValidationState state;
- TestBlockValidity(state, chainman.GetParams(), active_chainstate, block, pindexPrev, false, true);
+ miner.testBlockValidity(state, block);
return BIP22ValidationResult(state);
}
@@ -726,7 +729,6 @@ static RPCHelpMan getblocktemplate()
if (strMode != "template")
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
- Mining& miner = EnsureMining(node);
if (!miner.isTestChain()) {
const CConnman& connman = EnsureConnman(node);
if (connman.GetNodeCount(ConnectionDirection::Both) == 0) {
diff --git a/test/functional/rpc_generate.py b/test/functional/rpc_generate.py
index 20f62079fd..3e250925e7 100755
--- a/test/functional/rpc_generate.py
+++ b/test/functional/rpc_generate.py
@@ -87,7 +87,7 @@ class RPCGenerateTest(BitcoinTestFramework):
txid1 = miniwallet.send_self_transfer(from_node=node)['txid']
utxo1 = miniwallet.get_utxo(txid=txid1)
rawtx2 = miniwallet.create_self_transfer(utxo_to_spend=utxo1)['hex']
- assert_raises_rpc_error(-25, 'TestBlockValidity failed: bad-txns-inputs-missingorspent', self.generateblock, node, address, [rawtx2, txid1])
+ assert_raises_rpc_error(-25, 'testBlockValidity failed: bad-txns-inputs-missingorspent', self.generateblock, node, address, [rawtx2, txid1])
self.log.info('Fail to generate block with txid not in mempool')
missing_txid = '0000000000000000000000000000000000000000000000000000000000000000'