mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-24 10:17:45 -03:00
rpc: call TestBlockValidity via miner interface
This commit is contained in:
parent
8ecb681678
commit
d8a3496b5a
4 changed files with 31 additions and 7 deletions
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Add table
Reference in a new issue