mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-10 09:06:15 +01:00
Merge bitcoin/bitcoin#31196: Prune mining interface
c991cea1a0
Remove processNewBlock() from mining interface (Sjors Provoost)9a47852d88
Remove getTransactionsUpdated() from mining interface (Sjors Provoost)bfc4e029d4
Remove testBlockValidity() from mining interface (Sjors Provoost) Pull request description: There are three methods in the mining interface that can be dropped. The Template Provider doesn't need them and other application should probably not use them either. 1. `processNewBlock()` was added in7b4d3249ce
, but became unnecessary with the introduction of interfaces::BlockTemplate::submitSolution in7b4d3249ce
. Dropping it was suggested in https://github.com/bitcoin/bitcoin/pull/30200#issuecomment-2404460342 2. `getTransactionsUpdated()`: this is used in the implementation of #31003 `waitFeesChanged`. It's not very useful generically because the mempool updates very frequently. 3. `testBlockValidity()`: it might be useful for mining application to have a way to check the validity of a block template they modified, but the Stratum v2 Template Provider doesn't do that, and this method is a bit brittle (e.g. the block needs to build on the tip). ACKs for top commit: TheCharlatan: Re-ACKc991cea1a0
ryanofsky: Code review ACKc991cea1a0
. Since last review, just rebased to avoid conflicts in surrounding code, and edited a commit message tdb3: code review ACKc991cea1a0
Tree-SHA512: 2138e54f920b26e01c068b24498c6a210c5c4358138dce0702ab58185d9ae148a18f04c97ac9f043646d40f8031618d80a718a176b1ce4779c237de6fb9c4a67
This commit is contained in:
commit
fa0c473d4c
5 changed files with 15 additions and 67 deletions
|
@ -93,31 +93,6 @@ public:
|
|||
*/
|
||||
virtual std::unique_ptr<BlockTemplate> createNewBlock(const node::BlockCreateOptions& options = {}) = 0;
|
||||
|
||||
/**
|
||||
* Processes new block. A valid new block is automatically relayed to peers.
|
||||
*
|
||||
* @param[in] block The block we want to process.
|
||||
* @param[out] new_block A boolean which is set to indicate if the block was first received via this call
|
||||
* @returns If the block was processed, independently of block validity
|
||||
*/
|
||||
virtual bool processNewBlock(const std::shared_ptr<const CBlock>& block, bool* new_block) = 0;
|
||||
|
||||
//! Return the number of transaction updates in the mempool,
|
||||
//! used to decide whether to make a new block template.
|
||||
virtual unsigned int getTransactionsUpdated() = 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[in] block the block to validate
|
||||
* @param[in] check_merkle_root call CheckMerkleRoot()
|
||||
* @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(const CBlock& block, bool check_merkle_root, BlockValidationState& state) = 0;
|
||||
|
||||
//! Get internal node context. Useful for RPC and testing,
|
||||
//! but not accessible across processes.
|
||||
virtual node::NodeContext* context() { return nullptr; }
|
||||
|
|
|
@ -18,9 +18,6 @@ interface Mining $Proxy.wrap("interfaces::Mining") {
|
|||
getTip @2 (context :Proxy.Context) -> (result: Common.BlockRef, hasResult: Bool);
|
||||
waitTipChanged @3 (context :Proxy.Context, currentTip: Data, timeout: Float64) -> (result: Common.BlockRef);
|
||||
createNewBlock @4 (options: BlockCreateOptions) -> (result: BlockTemplate);
|
||||
processNewBlock @5 (context :Proxy.Context, block: Data) -> (newBlock: Bool, result: Bool);
|
||||
getTransactionsUpdated @6 (context :Proxy.Context) -> (result: UInt32);
|
||||
testBlockValidity @7 (context :Proxy.Context, block: Data, checkMerkleRoot: Bool) -> (state: BlockValidationState, result: Bool);
|
||||
}
|
||||
|
||||
interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") {
|
||||
|
|
|
@ -979,29 +979,6 @@ public:
|
|||
return BlockRef{chainman().ActiveChain().Tip()->GetBlockHash(), chainman().ActiveChain().Tip()->nHeight};
|
||||
}
|
||||
|
||||
bool processNewBlock(const std::shared_ptr<const CBlock>& block, bool* new_block) override
|
||||
{
|
||||
return chainman().ProcessNewBlock(block, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/new_block);
|
||||
}
|
||||
|
||||
unsigned int getTransactionsUpdated() override
|
||||
{
|
||||
return context()->mempool->GetTransactionsUpdated();
|
||||
}
|
||||
|
||||
bool testBlockValidity(const CBlock& block, bool check_merkle_root, BlockValidationState& state) override
|
||||
{
|
||||
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<BlockTemplate> createNewBlock(const BlockCreateOptions& options) override
|
||||
{
|
||||
BlockAssembler::Options assemble_options{options};
|
||||
|
|
|
@ -131,7 +131,7 @@ static RPCHelpMan getnetworkhashps()
|
|||
};
|
||||
}
|
||||
|
||||
static bool GenerateBlock(ChainstateManager& chainman, Mining& miner, CBlock&& block, uint64_t& max_tries, std::shared_ptr<const CBlock>& block_out, bool process_new_block)
|
||||
static bool GenerateBlock(ChainstateManager& chainman, CBlock&& block, uint64_t& max_tries, std::shared_ptr<const CBlock>& block_out, bool process_new_block)
|
||||
{
|
||||
block_out.reset();
|
||||
block.hashMerkleRoot = BlockMerkleRoot(block);
|
||||
|
@ -151,7 +151,7 @@ static bool GenerateBlock(ChainstateManager& chainman, Mining& miner, CBlock&& b
|
|||
|
||||
if (!process_new_block) return true;
|
||||
|
||||
if (!miner.processNewBlock(block_out, nullptr)) {
|
||||
if (!chainman.ProcessNewBlock(block_out, /*force_processing=*/true, /*min_pow_checked=*/true, nullptr)) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ static UniValue generateBlocks(ChainstateManager& chainman, Mining& miner, const
|
|||
CHECK_NONFATAL(block_template);
|
||||
|
||||
std::shared_ptr<const CBlock> block_out;
|
||||
if (!GenerateBlock(chainman, miner, block_template->getBlock(), nMaxTries, block_out, /*process_new_block=*/true)) {
|
||||
if (!GenerateBlock(chainman, block_template->getBlock(), nMaxTries, block_out, /*process_new_block=*/true)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -384,16 +384,17 @@ static RPCHelpMan generateblock()
|
|||
RegenerateCommitments(block, chainman);
|
||||
|
||||
{
|
||||
LOCK(::cs_main);
|
||||
BlockValidationState state;
|
||||
if (!miner.testBlockValidity(block, /*check_merkle_root=*/false, state)) {
|
||||
throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("testBlockValidity failed: %s", state.ToString()));
|
||||
if (!TestBlockValidity(state, chainman.GetParams(), chainman.ActiveChainstate(), block, chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock), /*fCheckPOW=*/false, /*fCheckMerkleRoot=*/false)) {
|
||||
throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("TestBlockValidity failed: %s", state.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<const CBlock> block_out;
|
||||
uint64_t max_tries{DEFAULT_MAX_TRIES};
|
||||
|
||||
if (!GenerateBlock(chainman, miner, std::move(block), max_tries, block_out, process_new_block) || !block_out) {
|
||||
if (!GenerateBlock(chainman, std::move(block), max_tries, block_out, process_new_block) || !block_out) {
|
||||
throw JSONRPCError(RPC_MISC_ERROR, "Failed to make block.");
|
||||
}
|
||||
|
||||
|
@ -709,12 +710,12 @@ static RPCHelpMan getblocktemplate()
|
|||
return "duplicate-inconclusive";
|
||||
}
|
||||
|
||||
// testBlockValidity only supports blocks built on the current Tip
|
||||
// TestBlockValidity only supports blocks built on the current Tip
|
||||
if (block.hashPrevBlock != tip) {
|
||||
return "inconclusive-not-best-prevblk";
|
||||
}
|
||||
BlockValidationState state;
|
||||
miner.testBlockValidity(block, /*check_merkle_root=*/true, state);
|
||||
TestBlockValidity(state, chainman.GetParams(), chainman.ActiveChainstate(), block, chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock), /*fCheckPOW=*/false, /*fCheckMerkleRoot=*/true);
|
||||
return BIP22ValidationResult(state);
|
||||
}
|
||||
|
||||
|
@ -742,6 +743,7 @@ static RPCHelpMan getblocktemplate()
|
|||
}
|
||||
|
||||
static unsigned int nTransactionsUpdatedLast;
|
||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
||||
|
||||
if (!lpval.isNull())
|
||||
{
|
||||
|
@ -772,7 +774,7 @@ static RPCHelpMan getblocktemplate()
|
|||
tip = miner.waitTipChanged(hashWatchedChain, checktxtime).hash;
|
||||
// Timeout: Check transactions for update
|
||||
// without holding the mempool lock to avoid deadlocks
|
||||
if (miner.getTransactionsUpdated() != nTransactionsUpdatedLastLP)
|
||||
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
|
||||
break;
|
||||
checktxtime = std::chrono::seconds(10);
|
||||
}
|
||||
|
@ -803,13 +805,13 @@ static RPCHelpMan getblocktemplate()
|
|||
static int64_t time_start;
|
||||
static std::unique_ptr<BlockTemplate> block_template;
|
||||
if (!pindexPrev || pindexPrev->GetBlockHash() != tip ||
|
||||
(miner.getTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - time_start > 5))
|
||||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - time_start > 5))
|
||||
{
|
||||
// Clear pindexPrev so future calls make a new block, despite any failures from here on
|
||||
pindexPrev = nullptr;
|
||||
|
||||
// Store the pindexBest used before createNewBlock, to avoid races
|
||||
nTransactionsUpdatedLast = miner.getTransactionsUpdated();
|
||||
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
||||
CBlockIndex* pindexPrevNew = chainman.m_blockman.LookupBlockIndex(tip);
|
||||
time_start = GetTime();
|
||||
|
||||
|
@ -1032,13 +1034,10 @@ static RPCHelpMan submitblock()
|
|||
}
|
||||
}
|
||||
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
Mining& miner = EnsureMining(node);
|
||||
|
||||
bool new_block;
|
||||
auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
|
||||
CHECK_NONFATAL(chainman.m_options.signals)->RegisterSharedValidationInterface(sc);
|
||||
bool accepted = miner.processNewBlock(blockptr, /*new_block=*/&new_block);
|
||||
bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block);
|
||||
CHECK_NONFATAL(chainman.m_options.signals)->UnregisterSharedValidationInterface(sc);
|
||||
if (!new_block && accepted) {
|
||||
return "duplicate";
|
||||
|
|
|
@ -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