Add checkBlock to Mining interface
Use it in miner_tests. The getblocktemplate and generateblock RPC calls don't use this, because it would make the code more verbose.
This commit is contained in:
5 files changed
+81
-1
No files matched your search
@@ -114,6 +114,21 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual std::unique_ptr<BlockTemplate> createNewBlock(const node::BlockCreateOptions& options = {}) = 0;
|
virtual std::unique_ptr<BlockTemplate> createNewBlock(const node::BlockCreateOptions& options = {}) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a given block is valid.
|
||||||
|
*
|
||||||
|
* @param[in] block the block to check
|
||||||
|
* @param[in] options verification options: the proof-of-work check can be
|
||||||
|
* skipped in order to verify a template generated by
|
||||||
|
* external software.
|
||||||
|
* @param[out] reason failure reason (BIP22)
|
||||||
|
* @param[out] debug more detailed rejection reason
|
||||||
|
* @returns whether the block is valid
|
||||||
|
*
|
||||||
|
* For signets the challenge verification is skipped when check_pow is false.
|
||||||
|
*/
|
||||||
|
virtual bool checkBlock(const CBlock& block, const node::BlockCheckOptions& options, std::string& reason, std::string& debug) = 0;
|
||||||
|
|
||||||
//! Get internal node context. Useful for RPC and testing,
|
//! Get internal node context. Useful for RPC and testing,
|
||||||
//! but not accessible across processes.
|
//! but not accessible across processes.
|
||||||
virtual node::NodeContext* context() { return nullptr; }
|
virtual node::NodeContext* context() { return nullptr; }
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ interface Mining $Proxy.wrap("interfaces::Mining") {
|
|||||||
getTip @2 (context :Proxy.Context) -> (result: Common.BlockRef, hasResult: Bool);
|
getTip @2 (context :Proxy.Context) -> (result: Common.BlockRef, hasResult: Bool);
|
||||||
waitTipChanged @3 (context :Proxy.Context, currentTip: Data, timeout: Float64) -> (result: Common.BlockRef);
|
waitTipChanged @3 (context :Proxy.Context, currentTip: Data, timeout: Float64) -> (result: Common.BlockRef);
|
||||||
createNewBlock @4 (options: BlockCreateOptions) -> (result: BlockTemplate);
|
createNewBlock @4 (options: BlockCreateOptions) -> (result: BlockTemplate);
|
||||||
|
checkBlock @5 (block: Data, options: BlockCheckOptions) -> (reason: Text, debug: Text, result: Bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") {
|
interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") {
|
||||||
@@ -44,3 +45,8 @@ struct BlockWaitOptions $Proxy.wrap("node::BlockWaitOptions") {
|
|||||||
timeout @0 : Float64 $Proxy.name("timeout");
|
timeout @0 : Float64 $Proxy.name("timeout");
|
||||||
feeThreshold @1 : Int64 $Proxy.name("fee_threshold");
|
feeThreshold @1 : Int64 $Proxy.name("fee_threshold");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct BlockCheckOptions $Proxy.wrap("node::BlockCheckOptions") {
|
||||||
|
checkMerkleRoot @0 :Bool $Proxy.name("check_merkle_root");
|
||||||
|
checkPow @1 :Bool $Proxy.name("check_pow");
|
||||||
|
}
|
||||||
@@ -984,6 +984,15 @@ public:
|
|||||||
return std::make_unique<BlockTemplateImpl>(assemble_options, BlockAssembler{chainman().ActiveChainstate(), context()->mempool.get(), assemble_options}.CreateNewBlock(), m_node);
|
return std::make_unique<BlockTemplateImpl>(assemble_options, BlockAssembler{chainman().ActiveChainstate(), context()->mempool.get(), assemble_options}.CreateNewBlock(), m_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool checkBlock(const CBlock& block, const node::BlockCheckOptions& options, std::string& reason, std::string& debug) override
|
||||||
|
{
|
||||||
|
LOCK(chainman().GetMutex());
|
||||||
|
BlockValidationState state{TestBlockValidity(chainman().ActiveChainstate(), block, /*check_pow=*/options.check_pow, /*=check_merkle_root=*/options.check_merkle_root)};
|
||||||
|
reason = state.GetRejectReason();
|
||||||
|
debug = state.GetDebugMessage();
|
||||||
|
return state.IsValid();
|
||||||
|
}
|
||||||
|
|
||||||
NodeContext* context() override { return &m_node; }
|
NodeContext* context() override { return &m_node; }
|
||||||
ChainstateManager& chainman() { return *Assert(m_node.chainman); }
|
ChainstateManager& chainman() { return *Assert(m_node.chainman); }
|
||||||
KernelNotifications& notifications() { return *Assert(m_node.notifications); }
|
KernelNotifications& notifications() { return *Assert(m_node.notifications); }
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
|
#include <uint256.h>
|
||||||
#include <util/time.h>
|
#include <util/time.h>
|
||||||
|
|
||||||
namespace node {
|
namespace node {
|
||||||
@@ -85,6 +86,17 @@ struct BlockWaitOptions {
|
|||||||
CAmount fee_threshold{MAX_MONEY};
|
CAmount fee_threshold{MAX_MONEY};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BlockCheckOptions {
|
||||||
|
/**
|
||||||
|
* Set false to omit the merkle root check
|
||||||
|
*/
|
||||||
|
bool check_merkle_root{true};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set false to omit the proof-of-work check
|
||||||
|
*/
|
||||||
|
bool check_pow{true};
|
||||||
|
};
|
||||||
} // namespace node
|
} // namespace node
|
||||||
|
|
||||||
#endif // BITCOIN_NODE_TYPES_H
|
#endif // BITCOIN_NODE_TYPES_H
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <util/translation.h>
|
#include <util/translation.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <versionbits.h>
|
#include <versionbits.h>
|
||||||
|
#include <pow.h>
|
||||||
|
|
||||||
#include <test/util/setup_common.h>
|
#include <test/util/setup_common.h>
|
||||||
|
|
||||||
@@ -666,7 +667,44 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
CScript scriptPubKey = CScript() << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"_hex << OP_CHECKSIG;
|
CScript scriptPubKey = CScript() << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"_hex << OP_CHECKSIG;
|
||||||
BlockAssembler::Options options;
|
BlockAssembler::Options options;
|
||||||
options.coinbase_output_script = scriptPubKey;
|
options.coinbase_output_script = scriptPubKey;
|
||||||
std::unique_ptr<BlockTemplate> block_template;
|
|
||||||
|
// Create and check a simple template
|
||||||
|
std::unique_ptr<BlockTemplate> block_template = mining->createNewBlock(options);
|
||||||
|
BOOST_REQUIRE(block_template);
|
||||||
|
{
|
||||||
|
CBlock block{block_template->getBlock()};
|
||||||
|
{
|
||||||
|
std::string reason;
|
||||||
|
std::string debug;
|
||||||
|
BOOST_REQUIRE(!mining->checkBlock(block, {.check_pow = false}, reason, debug));
|
||||||
|
BOOST_REQUIRE_EQUAL(reason, "bad-txnmrklroot");
|
||||||
|
BOOST_REQUIRE_EQUAL(debug, "hashMerkleRoot mismatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
block.hashMerkleRoot = BlockMerkleRoot(block);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string reason;
|
||||||
|
std::string debug;
|
||||||
|
BOOST_REQUIRE(mining->checkBlock(block, {.check_pow = false}, reason, debug));
|
||||||
|
BOOST_REQUIRE_EQUAL(reason, "");
|
||||||
|
BOOST_REQUIRE_EQUAL(debug, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// A block template does not have proof-of-work, but it might pass
|
||||||
|
// verification by coincidence. Grind the nonce if needed:
|
||||||
|
while (CheckProofOfWork(block.GetHash(), block.nBits, Assert(m_node.chainman)->GetParams().GetConsensus())) {
|
||||||
|
block.nNonce++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string reason;
|
||||||
|
std::string debug;
|
||||||
|
BOOST_REQUIRE(!mining->checkBlock(block, {.check_pow = true}, reason, debug));
|
||||||
|
BOOST_REQUIRE_EQUAL(reason, "high-hash");
|
||||||
|
BOOST_REQUIRE_EQUAL(debug, "proof of work failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We can't make transactions until we have inputs
|
// We can't make transactions until we have inputs
|
||||||
// Therefore, load 110 blocks :)
|
// Therefore, load 110 blocks :)
|
||||||
|
|||||||
Reference in new issue
Block a user