mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
Merge bitcoin/bitcoin#30200: Introduce Mining interface
a9716c53f0
rpc: call IsInitialBlockDownload via miner interface (Sjors Provoost)dda0b0834f
rpc: minize getTipHash() calls in gbt (Sjors Provoost)7b4d3249ce
rpc: call processNewBlock via miner interface (Sjors Provoost)9e228351e7
rpc: getTransactionsUpdated via miner interface (Sjors Provoost)64ebb0f971
Always pass options to BlockAssembler constructor (Sjors Provoost)4bf2e361da
rpc: call CreateNewBlock via miner interface (Sjors Provoost)404b01c436
rpc: getblocktemplate getTipHash() via Miner interface (Sjors Provoost)d8a3496b5a
rpc: call TestBlockValidity via miner interface (Sjors Provoost)8ecb681678
Introduce Mining interface (Sjors Provoost) Pull request description: Introduce a `Mining` interface for the `getblocktemplate`, `generateblock` and other mining RPCs to use now, and for Stratum v2 to use later. Suggested here: https://github.com/bitcoin/bitcoin/pull/29346#issuecomment-2108528652 The selection of methods added to the interface is mostly based on what the Template Provider in #29432 uses. It could be expanded further so that `rpc/mining.cpp` no longer needs `EnsureMemPool` and `EnsureChainman`. This PR should be a pure refactor. ACKs for top commit: tdb3: re ACKa9716c53f0
itornaza: Code review and std-tests ACKa9716c53f0
ryanofsky: Code review ACKa9716c53f0
with one minor suggestion in case you update. Only changes since last review were other small changes to the interface. Tree-SHA512: cf97f87d6e9ed89da3835a0730da3b24a7b14c8605ea221149103a5915e79598cf082a95f2bc88e33f1c450e3d4aad88aed1163a29195acca88bcace055af724
This commit is contained in:
commit
323b0acfcb
21 changed files with 226 additions and 52 deletions
|
@ -1457,8 +1457,9 @@ independent (node, wallet, GUI), are defined in
|
||||||
there are [`interfaces::Chain`](../src/interfaces/chain.h), used by wallet to
|
there are [`interfaces::Chain`](../src/interfaces/chain.h), used by wallet to
|
||||||
access the node's latest chain state,
|
access the node's latest chain state,
|
||||||
[`interfaces::Node`](../src/interfaces/node.h), used by the GUI to control the
|
[`interfaces::Node`](../src/interfaces/node.h), used by the GUI to control the
|
||||||
node, and [`interfaces::Wallet`](../src/interfaces/wallet.h), used by the GUI
|
node, [`interfaces::Wallet`](../src/interfaces/wallet.h), used by the GUI
|
||||||
to control an individual wallet. There are also more specialized interface
|
to control an individual wallet and [`interfaces::Mining`](../src/interfaces/mining.h),
|
||||||
|
used by RPC to generate block templates. There are also more specialized interface
|
||||||
types like [`interfaces::Handler`](../src/interfaces/handler.h)
|
types like [`interfaces::Handler`](../src/interfaces/handler.h)
|
||||||
[`interfaces::ChainClient`](../src/interfaces/chain.h) passed to and from
|
[`interfaces::ChainClient`](../src/interfaces/chain.h) passed to and from
|
||||||
various interface methods.
|
various interface methods.
|
||||||
|
|
|
@ -177,6 +177,7 @@ BITCOIN_CORE_H = \
|
||||||
interfaces/handler.h \
|
interfaces/handler.h \
|
||||||
interfaces/init.h \
|
interfaces/init.h \
|
||||||
interfaces/ipc.h \
|
interfaces/ipc.h \
|
||||||
|
interfaces/mining.h \
|
||||||
interfaces/node.h \
|
interfaces/node.h \
|
||||||
interfaces/wallet.h \
|
interfaces/wallet.h \
|
||||||
kernel/blockmanager_opts.h \
|
kernel/blockmanager_opts.h \
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <init/common.h>
|
#include <init/common.h>
|
||||||
#include <interfaces/chain.h>
|
#include <interfaces/chain.h>
|
||||||
#include <interfaces/init.h>
|
#include <interfaces/init.h>
|
||||||
|
#include <interfaces/mining.h>
|
||||||
#include <interfaces/node.h>
|
#include <interfaces/node.h>
|
||||||
#include <kernel/context.h>
|
#include <kernel/context.h>
|
||||||
#include <key.h>
|
#include <key.h>
|
||||||
|
@ -1117,6 +1118,7 @@ bool AppInitLockDataDirectory()
|
||||||
bool AppInitInterfaces(NodeContext& node)
|
bool AppInitInterfaces(NodeContext& node)
|
||||||
{
|
{
|
||||||
node.chain = node.init->makeChain();
|
node.chain = node.init->makeChain();
|
||||||
|
node.mining = node.init->makeMining();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ public:
|
||||||
}
|
}
|
||||||
std::unique_ptr<interfaces::Node> makeNode() override { return interfaces::MakeNode(m_node); }
|
std::unique_ptr<interfaces::Node> makeNode() override { return interfaces::MakeNode(m_node); }
|
||||||
std::unique_ptr<interfaces::Chain> makeChain() override { return interfaces::MakeChain(m_node); }
|
std::unique_ptr<interfaces::Chain> makeChain() override { return interfaces::MakeChain(m_node); }
|
||||||
|
std::unique_ptr<interfaces::Mining> makeMining() override { return interfaces::MakeMining(m_node); }
|
||||||
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain) override
|
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain) override
|
||||||
{
|
{
|
||||||
return MakeWalletLoader(chain, *Assert(m_node.args));
|
return MakeWalletLoader(chain, *Assert(m_node.args));
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <interfaces/chain.h>
|
#include <interfaces/chain.h>
|
||||||
#include <interfaces/echo.h>
|
#include <interfaces/echo.h>
|
||||||
#include <interfaces/init.h>
|
#include <interfaces/init.h>
|
||||||
|
#include <interfaces/mining.h>
|
||||||
#include <interfaces/node.h>
|
#include <interfaces/node.h>
|
||||||
#include <interfaces/wallet.h>
|
#include <interfaces/wallet.h>
|
||||||
#include <node/context.h>
|
#include <node/context.h>
|
||||||
|
@ -25,6 +26,7 @@ public:
|
||||||
}
|
}
|
||||||
std::unique_ptr<interfaces::Node> makeNode() override { return interfaces::MakeNode(m_node); }
|
std::unique_ptr<interfaces::Node> makeNode() override { return interfaces::MakeNode(m_node); }
|
||||||
std::unique_ptr<interfaces::Chain> makeChain() override { return interfaces::MakeChain(m_node); }
|
std::unique_ptr<interfaces::Chain> makeChain() override { return interfaces::MakeChain(m_node); }
|
||||||
|
std::unique_ptr<interfaces::Mining> makeMining() override { return interfaces::MakeMining(m_node); }
|
||||||
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain) override
|
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain) override
|
||||||
{
|
{
|
||||||
return MakeWalletLoader(chain, *Assert(m_node.args));
|
return MakeWalletLoader(chain, *Assert(m_node.args));
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <interfaces/chain.h>
|
#include <interfaces/chain.h>
|
||||||
#include <interfaces/echo.h>
|
#include <interfaces/echo.h>
|
||||||
#include <interfaces/init.h>
|
#include <interfaces/init.h>
|
||||||
|
#include <interfaces/mining.h>
|
||||||
#include <interfaces/node.h>
|
#include <interfaces/node.h>
|
||||||
#include <interfaces/wallet.h>
|
#include <interfaces/wallet.h>
|
||||||
#include <node/context.h>
|
#include <node/context.h>
|
||||||
|
@ -27,6 +28,7 @@ public:
|
||||||
}
|
}
|
||||||
std::unique_ptr<interfaces::Node> makeNode() override { return interfaces::MakeNode(m_node); }
|
std::unique_ptr<interfaces::Node> makeNode() override { return interfaces::MakeNode(m_node); }
|
||||||
std::unique_ptr<interfaces::Chain> makeChain() override { return interfaces::MakeChain(m_node); }
|
std::unique_ptr<interfaces::Chain> makeChain() override { return interfaces::MakeChain(m_node); }
|
||||||
|
std::unique_ptr<interfaces::Mining> makeMining() override { return interfaces::MakeMining(m_node); }
|
||||||
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain) override
|
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain) override
|
||||||
{
|
{
|
||||||
return MakeWalletLoader(chain, *Assert(m_node.args));
|
return MakeWalletLoader(chain, *Assert(m_node.args));
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <interfaces/chain.h>
|
#include <interfaces/chain.h>
|
||||||
#include <interfaces/echo.h>
|
#include <interfaces/echo.h>
|
||||||
|
#include <interfaces/mining.h>
|
||||||
#include <interfaces/node.h>
|
#include <interfaces/node.h>
|
||||||
#include <interfaces/wallet.h>
|
#include <interfaces/wallet.h>
|
||||||
|
|
||||||
|
@ -32,6 +33,7 @@ public:
|
||||||
virtual ~Init() = default;
|
virtual ~Init() = default;
|
||||||
virtual std::unique_ptr<Node> makeNode() { return nullptr; }
|
virtual std::unique_ptr<Node> makeNode() { return nullptr; }
|
||||||
virtual std::unique_ptr<Chain> makeChain() { return nullptr; }
|
virtual std::unique_ptr<Chain> makeChain() { return nullptr; }
|
||||||
|
virtual std::unique_ptr<Mining> makeMining() { return nullptr; }
|
||||||
virtual std::unique_ptr<WalletLoader> makeWalletLoader(Chain& chain) { return nullptr; }
|
virtual std::unique_ptr<WalletLoader> makeWalletLoader(Chain& chain) { return nullptr; }
|
||||||
virtual std::unique_ptr<Echo> makeEcho() { return nullptr; }
|
virtual std::unique_ptr<Echo> makeEcho() { return nullptr; }
|
||||||
virtual Ipc* ipc() { return nullptr; }
|
virtual Ipc* ipc() { return nullptr; }
|
||||||
|
|
82
src/interfaces/mining.h
Normal file
82
src/interfaces/mining.h
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// Copyright (c) 2024 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#ifndef BITCOIN_INTERFACES_MINING_H
|
||||||
|
#define BITCOIN_INTERFACES_MINING_H
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <uint256.h>
|
||||||
|
|
||||||
|
namespace node {
|
||||||
|
struct CBlockTemplate;
|
||||||
|
struct NodeContext;
|
||||||
|
} // namespace node
|
||||||
|
|
||||||
|
class BlockValidationState;
|
||||||
|
class CBlock;
|
||||||
|
class CScript;
|
||||||
|
|
||||||
|
namespace interfaces {
|
||||||
|
|
||||||
|
//! Interface giving clients (RPC, Stratum v2 Template Provider in the future)
|
||||||
|
//! ability to create block templates.
|
||||||
|
|
||||||
|
class Mining
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Mining() {}
|
||||||
|
|
||||||
|
//! If this chain is exclusively used for testing
|
||||||
|
virtual bool isTestChain() = 0;
|
||||||
|
|
||||||
|
//! Returns whether IBD is still in progress.
|
||||||
|
virtual bool isInitialBlockDownload() = 0;
|
||||||
|
|
||||||
|
//! Returns the hash for the tip of this chain
|
||||||
|
virtual std::optional<uint256> getTipHash() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new block template
|
||||||
|
*
|
||||||
|
* @param[in] script_pub_key the coinbase output
|
||||||
|
* @param[in] use_mempool set false to omit mempool transactions
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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[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; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Return implementation of Mining interface.
|
||||||
|
std::unique_ptr<Mining> MakeMining(node::NodeContext& node);
|
||||||
|
|
||||||
|
} // namespace interfaces
|
||||||
|
|
||||||
|
#endif // BITCOIN_INTERFACES_MINING_H
|
|
@ -7,6 +7,7 @@
|
||||||
#include <addrman.h>
|
#include <addrman.h>
|
||||||
#include <banman.h>
|
#include <banman.h>
|
||||||
#include <interfaces/chain.h>
|
#include <interfaces/chain.h>
|
||||||
|
#include <interfaces/mining.h>
|
||||||
#include <kernel/context.h>
|
#include <kernel/context.h>
|
||||||
#include <key.h>
|
#include <key.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
|
|
|
@ -27,6 +27,7 @@ class PeerManager;
|
||||||
namespace interfaces {
|
namespace interfaces {
|
||||||
class Chain;
|
class Chain;
|
||||||
class ChainClient;
|
class ChainClient;
|
||||||
|
class Mining;
|
||||||
class Init;
|
class Init;
|
||||||
class WalletLoader;
|
class WalletLoader;
|
||||||
} // namespace interfaces
|
} // namespace interfaces
|
||||||
|
@ -74,6 +75,7 @@ struct NodeContext {
|
||||||
std::vector<std::unique_ptr<interfaces::ChainClient>> chain_clients;
|
std::vector<std::unique_ptr<interfaces::ChainClient>> chain_clients;
|
||||||
//! Reference to chain client that should used to load or create wallets
|
//! Reference to chain client that should used to load or create wallets
|
||||||
//! opened by the gui.
|
//! opened by the gui.
|
||||||
|
std::unique_ptr<interfaces::Mining> mining;
|
||||||
interfaces::WalletLoader* wallet_loader{nullptr};
|
interfaces::WalletLoader* wallet_loader{nullptr};
|
||||||
std::unique_ptr<CScheduler> scheduler;
|
std::unique_ptr<CScheduler> scheduler;
|
||||||
std::function<void()> rpc_interruption_point = [] {};
|
std::function<void()> rpc_interruption_point = [] {};
|
||||||
|
|
|
@ -8,12 +8,14 @@
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
#include <common/args.h>
|
#include <common/args.h>
|
||||||
|
#include <consensus/validation.h>
|
||||||
#include <deploymentstatus.h>
|
#include <deploymentstatus.h>
|
||||||
#include <external_signer.h>
|
#include <external_signer.h>
|
||||||
#include <index/blockfilterindex.h>
|
#include <index/blockfilterindex.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <interfaces/chain.h>
|
#include <interfaces/chain.h>
|
||||||
#include <interfaces/handler.h>
|
#include <interfaces/handler.h>
|
||||||
|
#include <interfaces/mining.h>
|
||||||
#include <interfaces/node.h>
|
#include <interfaces/node.h>
|
||||||
#include <interfaces/wallet.h>
|
#include <interfaces/wallet.h>
|
||||||
#include <kernel/chain.h>
|
#include <kernel/chain.h>
|
||||||
|
@ -30,6 +32,7 @@
|
||||||
#include <node/context.h>
|
#include <node/context.h>
|
||||||
#include <node/interface_ui.h>
|
#include <node/interface_ui.h>
|
||||||
#include <node/mini_miner.h>
|
#include <node/mini_miner.h>
|
||||||
|
#include <node/miner.h>
|
||||||
#include <node/transaction.h>
|
#include <node/transaction.h>
|
||||||
#include <node/types.h>
|
#include <node/types.h>
|
||||||
#include <node/warnings.h>
|
#include <node/warnings.h>
|
||||||
|
@ -69,8 +72,10 @@ using interfaces::Chain;
|
||||||
using interfaces::FoundBlock;
|
using interfaces::FoundBlock;
|
||||||
using interfaces::Handler;
|
using interfaces::Handler;
|
||||||
using interfaces::MakeSignalHandler;
|
using interfaces::MakeSignalHandler;
|
||||||
|
using interfaces::Mining;
|
||||||
using interfaces::Node;
|
using interfaces::Node;
|
||||||
using interfaces::WalletLoader;
|
using interfaces::WalletLoader;
|
||||||
|
using node::BlockAssembler;
|
||||||
using util::Join;
|
using util::Join;
|
||||||
|
|
||||||
namespace node {
|
namespace node {
|
||||||
|
@ -831,10 +836,64 @@ public:
|
||||||
ValidationSignals& validation_signals() { return *Assert(m_node.validation_signals); }
|
ValidationSignals& validation_signals() { return *Assert(m_node.validation_signals); }
|
||||||
NodeContext& m_node;
|
NodeContext& m_node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MinerImpl : public Mining
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit MinerImpl(NodeContext& node) : m_node(node) {}
|
||||||
|
|
||||||
|
bool isTestChain() override
|
||||||
|
{
|
||||||
|
return chainman().GetParams().IsTestChain();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isInitialBlockDownload() override
|
||||||
|
{
|
||||||
|
return chainman().IsInitialBlockDownload();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<uint256> getTipHash() override
|
||||||
|
{
|
||||||
|
LOCK(::cs_main);
|
||||||
|
CBlockIndex* tip{chainman().ActiveChain().Tip()};
|
||||||
|
if (!tip) return {};
|
||||||
|
return tip->GetBlockHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
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(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<CBlockTemplate> createNewBlock(const CScript& script_pub_key, bool use_mempool) override
|
||||||
|
{
|
||||||
|
BlockAssembler::Options options;
|
||||||
|
ApplyArgsManOptions(gArgs, options);
|
||||||
|
|
||||||
|
LOCK(::cs_main);
|
||||||
|
return BlockAssembler{chainman().ActiveChainstate(), use_mempool ? context()->mempool.get() : nullptr, options}.CreateNewBlock(script_pub_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeContext* context() override { return &m_node; }
|
||||||
|
ChainstateManager& chainman() { return *Assert(m_node.chainman); }
|
||||||
|
NodeContext& m_node;
|
||||||
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace node
|
} // namespace node
|
||||||
|
|
||||||
namespace interfaces {
|
namespace interfaces {
|
||||||
std::unique_ptr<Node> MakeNode(node::NodeContext& context) { return std::make_unique<node::NodeImpl>(context); }
|
std::unique_ptr<Node> MakeNode(node::NodeContext& context) { return std::make_unique<node::NodeImpl>(context); }
|
||||||
std::unique_ptr<Chain> MakeChain(node::NodeContext& context) { return std::make_unique<node::ChainImpl>(context); }
|
std::unique_ptr<Chain> MakeChain(node::NodeContext& context) { return std::make_unique<node::ChainImpl>(context); }
|
||||||
|
std::unique_ptr<Mining> MakeMining(node::NodeContext& context) { return std::make_unique<node::MinerImpl>(context); }
|
||||||
} // namespace interfaces
|
} // namespace interfaces
|
||||||
|
|
|
@ -80,15 +80,6 @@ void ApplyArgsManOptions(const ArgsManager& args, BlockAssembler::Options& optio
|
||||||
if (const auto parsed{ParseMoney(*blockmintxfee)}) options.blockMinFeeRate = CFeeRate{*parsed};
|
if (const auto parsed{ParseMoney(*blockmintxfee)}) options.blockMinFeeRate = CFeeRate{*parsed};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static BlockAssembler::Options ConfiguredOptions()
|
|
||||||
{
|
|
||||||
BlockAssembler::Options options;
|
|
||||||
ApplyArgsManOptions(gArgs, options);
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockAssembler::BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool)
|
|
||||||
: BlockAssembler(chainstate, mempool, ConfiguredOptions()) {}
|
|
||||||
|
|
||||||
void BlockAssembler::resetBlock()
|
void BlockAssembler::resetBlock()
|
||||||
{
|
{
|
||||||
|
|
|
@ -161,7 +161,6 @@ public:
|
||||||
bool test_block_validity{true};
|
bool test_block_validity{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool);
|
|
||||||
explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool, const Options& options);
|
explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool, const Options& options);
|
||||||
|
|
||||||
/** Construct a new block template with coinbase to scriptPubKeyIn */
|
/** Construct a new block template with coinbase to scriptPubKeyIn */
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
#include <deploymentinfo.h>
|
#include <deploymentinfo.h>
|
||||||
#include <deploymentstatus.h>
|
#include <deploymentstatus.h>
|
||||||
|
#include <interfaces/mining.h>
|
||||||
#include <key_io.h>
|
#include <key_io.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <node/context.h>
|
#include <node/context.h>
|
||||||
|
@ -45,6 +46,7 @@
|
||||||
|
|
||||||
using node::BlockAssembler;
|
using node::BlockAssembler;
|
||||||
using node::CBlockTemplate;
|
using node::CBlockTemplate;
|
||||||
|
using interfaces::Mining;
|
||||||
using node::NodeContext;
|
using node::NodeContext;
|
||||||
using node::RegenerateCommitments;
|
using node::RegenerateCommitments;
|
||||||
using node::UpdateTime;
|
using node::UpdateTime;
|
||||||
|
@ -127,7 +129,7 @@ static RPCHelpMan getnetworkhashps()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t& max_tries, std::shared_ptr<const CBlock>& block_out, bool process_new_block)
|
static bool GenerateBlock(ChainstateManager& chainman, Mining& miner, CBlock& block, uint64_t& max_tries, std::shared_ptr<const CBlock>& block_out, bool process_new_block)
|
||||||
{
|
{
|
||||||
block_out.reset();
|
block_out.reset();
|
||||||
block.hashMerkleRoot = BlockMerkleRoot(block);
|
block.hashMerkleRoot = BlockMerkleRoot(block);
|
||||||
|
@ -147,23 +149,23 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
|
||||||
|
|
||||||
if (!process_new_block) return true;
|
if (!process_new_block) return true;
|
||||||
|
|
||||||
if (!chainman.ProcessNewBlock(block_out, /*force_processing=*/true, /*min_pow_checked=*/true, nullptr)) {
|
if (!miner.processNewBlock(block_out, nullptr)) {
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UniValue generateBlocks(ChainstateManager& chainman, const CTxMemPool& mempool, const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
|
static UniValue generateBlocks(ChainstateManager& chainman, Mining& miner, const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
|
||||||
{
|
{
|
||||||
UniValue blockHashes(UniValue::VARR);
|
UniValue blockHashes(UniValue::VARR);
|
||||||
while (nGenerate > 0 && !chainman.m_interrupt) {
|
while (nGenerate > 0 && !chainman.m_interrupt) {
|
||||||
std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler{chainman.ActiveChainstate(), &mempool}.CreateNewBlock(coinbase_script));
|
std::unique_ptr<CBlockTemplate> pblocktemplate(miner.createNewBlock(coinbase_script));
|
||||||
if (!pblocktemplate.get())
|
if (!pblocktemplate.get())
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
|
||||||
|
|
||||||
std::shared_ptr<const CBlock> block_out;
|
std::shared_ptr<const CBlock> block_out;
|
||||||
if (!GenerateBlock(chainman, pblocktemplate->block, nMaxTries, block_out, /*process_new_block=*/true)) {
|
if (!GenerateBlock(chainman, miner, pblocktemplate->block, nMaxTries, block_out, /*process_new_block=*/true)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,10 +241,10 @@ static RPCHelpMan generatetodescriptor()
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
Mining& miner = EnsureMining(node);
|
||||||
ChainstateManager& chainman = EnsureChainman(node);
|
ChainstateManager& chainman = EnsureChainman(node);
|
||||||
|
|
||||||
return generateBlocks(chainman, mempool, coinbase_script, num_blocks, max_tries);
|
return generateBlocks(chainman, miner, coinbase_script, num_blocks, max_tries);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -285,12 +287,12 @@ static RPCHelpMan generatetoaddress()
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
Mining& miner = EnsureMining(node);
|
||||||
ChainstateManager& chainman = EnsureChainman(node);
|
ChainstateManager& chainman = EnsureChainman(node);
|
||||||
|
|
||||||
CScript coinbase_script = GetScriptForDestination(destination);
|
CScript coinbase_script = GetScriptForDestination(destination);
|
||||||
|
|
||||||
return generateBlocks(chainman, mempool, coinbase_script, num_blocks, max_tries);
|
return generateBlocks(chainman, miner, coinbase_script, num_blocks, max_tries);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -337,6 +339,7 @@ static RPCHelpMan generateblock()
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||||
|
Mining& miner = EnsureMining(node);
|
||||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
const CTxMemPool& mempool = EnsureMemPool(node);
|
||||||
|
|
||||||
std::vector<CTransactionRef> txs;
|
std::vector<CTransactionRef> txs;
|
||||||
|
@ -370,7 +373,7 @@ static RPCHelpMan generateblock()
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
std::unique_ptr<CBlockTemplate> blocktemplate(BlockAssembler{chainman.ActiveChainstate(), nullptr}.CreateNewBlock(coinbase_script));
|
std::unique_ptr<CBlockTemplate> blocktemplate{miner.createNewBlock(coinbase_script, /*use_mempool=*/false)};
|
||||||
if (!blocktemplate) {
|
if (!blocktemplate) {
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
|
||||||
}
|
}
|
||||||
|
@ -387,15 +390,15 @@ static RPCHelpMan generateblock()
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
BlockValidationState state;
|
BlockValidationState state;
|
||||||
if (!TestBlockValidity(state, chainman.GetParams(), chainman.ActiveChainstate(), block, chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock), false, false)) {
|
if (!miner.testBlockValidity(state, block, /*check_merkle_root=*/false)) {
|
||||||
throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("TestBlockValidity failed: %s", state.ToString()));
|
throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("testBlockValidity failed: %s", state.ToString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const CBlock> block_out;
|
std::shared_ptr<const CBlock> block_out;
|
||||||
uint64_t max_tries{DEFAULT_MAX_TRIES};
|
uint64_t max_tries{DEFAULT_MAX_TRIES};
|
||||||
|
|
||||||
if (!GenerateBlock(chainman, block, max_tries, block_out, process_new_block) || !block_out) {
|
if (!GenerateBlock(chainman, miner, block, max_tries, block_out, process_new_block) || !block_out) {
|
||||||
throw JSONRPCError(RPC_MISC_ERROR, "Failed to make block.");
|
throw JSONRPCError(RPC_MISC_ERROR, "Failed to make block.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,13 +665,15 @@ static RPCHelpMan getblocktemplate()
|
||||||
{
|
{
|
||||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||||
ChainstateManager& chainman = EnsureChainman(node);
|
ChainstateManager& chainman = EnsureChainman(node);
|
||||||
|
Mining& miner = EnsureMining(node);
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
std::optional<uint256> maybe_tip{miner.getTipHash()};
|
||||||
|
CHECK_NONFATAL(maybe_tip);
|
||||||
|
uint256 tip{maybe_tip.value()};
|
||||||
|
|
||||||
std::string strMode = "template";
|
std::string strMode = "template";
|
||||||
UniValue lpval = NullUniValue;
|
UniValue lpval = NullUniValue;
|
||||||
std::set<std::string> setClientRules;
|
std::set<std::string> setClientRules;
|
||||||
Chainstate& active_chainstate = chainman.ActiveChainstate();
|
|
||||||
CChain& active_chain = active_chainstate.m_chain;
|
|
||||||
if (!request.params[0].isNull())
|
if (!request.params[0].isNull())
|
||||||
{
|
{
|
||||||
const UniValue& oparam = request.params[0].get_obj();
|
const UniValue& oparam = request.params[0].get_obj();
|
||||||
|
@ -703,12 +708,12 @@ static RPCHelpMan getblocktemplate()
|
||||||
return "duplicate-inconclusive";
|
return "duplicate-inconclusive";
|
||||||
}
|
}
|
||||||
|
|
||||||
CBlockIndex* const pindexPrev = active_chain.Tip();
|
// testBlockValidity only supports blocks built on the current Tip
|
||||||
// TestBlockValidity only supports blocks built on the current Tip
|
if (block.hashPrevBlock != tip) {
|
||||||
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
|
|
||||||
return "inconclusive-not-best-prevblk";
|
return "inconclusive-not-best-prevblk";
|
||||||
|
}
|
||||||
BlockValidationState state;
|
BlockValidationState state;
|
||||||
TestBlockValidity(state, chainman.GetParams(), active_chainstate, block, pindexPrev, false, true);
|
miner.testBlockValidity(state, block);
|
||||||
return BIP22ValidationResult(state);
|
return BIP22ValidationResult(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,19 +729,18 @@ static RPCHelpMan getblocktemplate()
|
||||||
if (strMode != "template")
|
if (strMode != "template")
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
|
||||||
|
|
||||||
if (!chainman.GetParams().IsTestChain()) {
|
if (!miner.isTestChain()) {
|
||||||
const CConnman& connman = EnsureConnman(node);
|
const CConnman& connman = EnsureConnman(node);
|
||||||
if (connman.GetNodeCount(ConnectionDirection::Both) == 0) {
|
if (connman.GetNodeCount(ConnectionDirection::Both) == 0) {
|
||||||
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!");
|
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chainman.IsInitialBlockDownload()) {
|
if (miner.isInitialBlockDownload()) {
|
||||||
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, PACKAGE_NAME " is in initial sync and waiting for blocks...");
|
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, PACKAGE_NAME " is in initial sync and waiting for blocks...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int nTransactionsUpdatedLast;
|
static unsigned int nTransactionsUpdatedLast;
|
||||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
|
||||||
|
|
||||||
if (!lpval.isNull())
|
if (!lpval.isNull())
|
||||||
{
|
{
|
||||||
|
@ -756,7 +760,7 @@ static RPCHelpMan getblocktemplate()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
|
// NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
|
||||||
hashWatchedChain = active_chain.Tip()->GetBlockHash();
|
hashWatchedChain = tip;
|
||||||
nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
|
nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,7 +776,7 @@ static RPCHelpMan getblocktemplate()
|
||||||
{
|
{
|
||||||
// Timeout: Check transactions for update
|
// Timeout: Check transactions for update
|
||||||
// without holding the mempool lock to avoid deadlocks
|
// without holding the mempool lock to avoid deadlocks
|
||||||
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
|
if (miner.getTransactionsUpdated() != nTransactionsUpdatedLastLP)
|
||||||
break;
|
break;
|
||||||
checktxtime += std::chrono::seconds(10);
|
checktxtime += std::chrono::seconds(10);
|
||||||
}
|
}
|
||||||
|
@ -780,6 +784,10 @@ static RPCHelpMan getblocktemplate()
|
||||||
}
|
}
|
||||||
ENTER_CRITICAL_SECTION(cs_main);
|
ENTER_CRITICAL_SECTION(cs_main);
|
||||||
|
|
||||||
|
std::optional<uint256> maybe_tip{miner.getTipHash()};
|
||||||
|
CHECK_NONFATAL(maybe_tip);
|
||||||
|
tip = maybe_tip.value();
|
||||||
|
|
||||||
if (!IsRPCRunning())
|
if (!IsRPCRunning())
|
||||||
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
|
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
|
||||||
// TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
|
// TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
|
||||||
|
@ -801,24 +809,25 @@ static RPCHelpMan getblocktemplate()
|
||||||
static CBlockIndex* pindexPrev;
|
static CBlockIndex* pindexPrev;
|
||||||
static int64_t time_start;
|
static int64_t time_start;
|
||||||
static std::unique_ptr<CBlockTemplate> pblocktemplate;
|
static std::unique_ptr<CBlockTemplate> pblocktemplate;
|
||||||
if (pindexPrev != active_chain.Tip() ||
|
if (!pindexPrev || pindexPrev->GetBlockHash() != tip ||
|
||||||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - time_start > 5))
|
(miner.getTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - time_start > 5))
|
||||||
{
|
{
|
||||||
// Clear pindexPrev so future calls make a new block, despite any failures from here on
|
// Clear pindexPrev so future calls make a new block, despite any failures from here on
|
||||||
pindexPrev = nullptr;
|
pindexPrev = nullptr;
|
||||||
|
|
||||||
// Store the pindexBest used before CreateNewBlock, to avoid races
|
// Store the pindexBest used before createNewBlock, to avoid races
|
||||||
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
nTransactionsUpdatedLast = miner.getTransactionsUpdated();
|
||||||
CBlockIndex* pindexPrevNew = active_chain.Tip();
|
CBlockIndex* pindexPrevNew = chainman.m_blockman.LookupBlockIndex(tip);
|
||||||
time_start = GetTime();
|
time_start = GetTime();
|
||||||
|
|
||||||
// Create new block
|
// Create new block
|
||||||
CScript scriptDummy = CScript() << OP_TRUE;
|
CScript scriptDummy = CScript() << OP_TRUE;
|
||||||
pblocktemplate = BlockAssembler{active_chainstate, &mempool}.CreateNewBlock(scriptDummy);
|
pblocktemplate = miner.createNewBlock(scriptDummy);
|
||||||
if (!pblocktemplate)
|
if (!pblocktemplate) {
|
||||||
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
||||||
|
}
|
||||||
|
|
||||||
// Need to update only after we know CreateNewBlock succeeded
|
// Need to update only after we know createNewBlock succeeded
|
||||||
pindexPrev = pindexPrevNew;
|
pindexPrev = pindexPrevNew;
|
||||||
}
|
}
|
||||||
CHECK_NONFATAL(pindexPrev);
|
CHECK_NONFATAL(pindexPrev);
|
||||||
|
@ -941,7 +950,7 @@ static RPCHelpMan getblocktemplate()
|
||||||
result.pushKV("transactions", std::move(transactions));
|
result.pushKV("transactions", std::move(transactions));
|
||||||
result.pushKV("coinbaseaux", std::move(aux));
|
result.pushKV("coinbaseaux", std::move(aux));
|
||||||
result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue);
|
result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue);
|
||||||
result.pushKV("longpollid", active_chain.Tip()->GetBlockHash().GetHex() + ToString(nTransactionsUpdatedLast));
|
result.pushKV("longpollid", tip.GetHex() + ToString(nTransactionsUpdatedLast));
|
||||||
result.pushKV("target", hashTarget.GetHex());
|
result.pushKV("target", hashTarget.GetHex());
|
||||||
result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1);
|
result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1);
|
||||||
result.pushKV("mutable", std::move(aMutable));
|
result.pushKV("mutable", std::move(aMutable));
|
||||||
|
@ -1047,10 +1056,13 @@ static RPCHelpMan submitblock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||||
|
Mining& miner = EnsureMining(node);
|
||||||
|
|
||||||
bool new_block;
|
bool new_block;
|
||||||
auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
|
auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
|
||||||
CHECK_NONFATAL(chainman.m_options.signals)->RegisterSharedValidationInterface(sc);
|
CHECK_NONFATAL(chainman.m_options.signals)->RegisterSharedValidationInterface(sc);
|
||||||
bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block);
|
bool accepted = miner.processNewBlock(blockptr, /*new_block=*/&new_block);
|
||||||
CHECK_NONFATAL(chainman.m_options.signals)->UnregisterSharedValidationInterface(sc);
|
CHECK_NONFATAL(chainman.m_options.signals)->UnregisterSharedValidationInterface(sc);
|
||||||
if (!new_block && accepted) {
|
if (!new_block && accepted) {
|
||||||
return "duplicate";
|
return "duplicate";
|
||||||
|
|
|
@ -101,6 +101,14 @@ CConnman& EnsureConnman(const NodeContext& node)
|
||||||
return *node.connman;
|
return *node.connman;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interfaces::Mining& EnsureMining(const NodeContext& node)
|
||||||
|
{
|
||||||
|
if (!node.mining) {
|
||||||
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Node miner not found");
|
||||||
|
}
|
||||||
|
return *node.mining;
|
||||||
|
}
|
||||||
|
|
||||||
PeerManager& EnsurePeerman(const NodeContext& node)
|
PeerManager& EnsurePeerman(const NodeContext& node)
|
||||||
{
|
{
|
||||||
if (!node.peerman) {
|
if (!node.peerman) {
|
||||||
|
|
|
@ -18,6 +18,9 @@ class BanMan;
|
||||||
namespace node {
|
namespace node {
|
||||||
struct NodeContext;
|
struct NodeContext;
|
||||||
} // namespace node
|
} // namespace node
|
||||||
|
namespace interfaces {
|
||||||
|
class Mining;
|
||||||
|
} // namespace interfaces
|
||||||
|
|
||||||
node::NodeContext& EnsureAnyNodeContext(const std::any& context);
|
node::NodeContext& EnsureAnyNodeContext(const std::any& context);
|
||||||
CTxMemPool& EnsureMemPool(const node::NodeContext& node);
|
CTxMemPool& EnsureMemPool(const node::NodeContext& node);
|
||||||
|
@ -31,6 +34,7 @@ ChainstateManager& EnsureAnyChainman(const std::any& context);
|
||||||
CBlockPolicyEstimator& EnsureFeeEstimator(const node::NodeContext& node);
|
CBlockPolicyEstimator& EnsureFeeEstimator(const node::NodeContext& node);
|
||||||
CBlockPolicyEstimator& EnsureAnyFeeEstimator(const std::any& context);
|
CBlockPolicyEstimator& EnsureAnyFeeEstimator(const std::any& context);
|
||||||
CConnman& EnsureConnman(const node::NodeContext& node);
|
CConnman& EnsureConnman(const node::NodeContext& node);
|
||||||
|
interfaces::Mining& EnsureMining(const node::NodeContext& node);
|
||||||
PeerManager& EnsurePeerman(const node::NodeContext& node);
|
PeerManager& EnsurePeerman(const node::NodeContext& node);
|
||||||
AddrMan& EnsureAddrman(const node::NodeContext& node);
|
AddrMan& EnsureAddrman(const node::NodeContext& node);
|
||||||
AddrMan& EnsureAnyAddrman(const std::any& context);
|
AddrMan& EnsureAnyAddrman(const std::any& context);
|
||||||
|
|
|
@ -67,7 +67,8 @@ CBlock BuildChainTestingSetup::CreateBlock(const CBlockIndex* prev,
|
||||||
const std::vector<CMutableTransaction>& txns,
|
const std::vector<CMutableTransaction>& txns,
|
||||||
const CScript& scriptPubKey)
|
const CScript& scriptPubKey)
|
||||||
{
|
{
|
||||||
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get()}.CreateNewBlock(scriptPubKey);
|
BlockAssembler::Options options;
|
||||||
|
std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get(), options}.CreateNewBlock(scriptPubKey);
|
||||||
CBlock& block = pblocktemplate->block;
|
CBlock& block = pblocktemplate->block;
|
||||||
block.hashPrevBlock = prev->GetBlockHash();
|
block.hashPrevBlock = prev->GetBlockHash();
|
||||||
block.nTime = prev->nTime + 1;
|
block.nTime = prev->nTime + 1;
|
||||||
|
|
|
@ -20,7 +20,8 @@ static void mineBlock(const node::NodeContext& node, std::chrono::seconds block_
|
||||||
{
|
{
|
||||||
auto curr_time = GetTime<std::chrono::seconds>();
|
auto curr_time = GetTime<std::chrono::seconds>();
|
||||||
SetMockTime(block_time); // update time so the block is created with it
|
SetMockTime(block_time); // update time so the block is created with it
|
||||||
CBlock block = node::BlockAssembler{node.chainman->ActiveChainstate(), nullptr}.CreateNewBlock(CScript() << OP_TRUE)->block;
|
node::BlockAssembler::Options options;
|
||||||
|
CBlock block = node::BlockAssembler{node.chainman->ActiveChainstate(), nullptr, options}.CreateNewBlock(CScript() << OP_TRUE)->block;
|
||||||
while (!CheckProofOfWork(block.GetHash(), block.nBits, node.chainman->GetConsensus())) ++block.nNonce;
|
while (!CheckProofOfWork(block.GetHash(), block.nBits, node.chainman->GetConsensus())) ++block.nNonce;
|
||||||
block.fChecked = true; // little speedup
|
block.fChecked = true; // little speedup
|
||||||
SetMockTime(curr_time); // process block at current time
|
SetMockTime(curr_time); // process block at current time
|
||||||
|
|
|
@ -374,7 +374,8 @@ CBlock TestChain100Setup::CreateBlock(
|
||||||
const CScript& scriptPubKey,
|
const CScript& scriptPubKey,
|
||||||
Chainstate& chainstate)
|
Chainstate& chainstate)
|
||||||
{
|
{
|
||||||
CBlock block = BlockAssembler{chainstate, nullptr}.CreateNewBlock(scriptPubKey)->block;
|
BlockAssembler::Options options;
|
||||||
|
CBlock block = BlockAssembler{chainstate, nullptr, options}.CreateNewBlock(scriptPubKey)->block;
|
||||||
|
|
||||||
Assert(block.vtx.size() == 1);
|
Assert(block.vtx.size() == 1);
|
||||||
for (const CMutableTransaction& tx : txns) {
|
for (const CMutableTransaction& tx : txns) {
|
||||||
|
|
|
@ -65,7 +65,8 @@ std::shared_ptr<CBlock> MinerTestingSetup::Block(const uint256& prev_hash)
|
||||||
static int i = 0;
|
static int i = 0;
|
||||||
static uint64_t time = Params().GenesisBlock().nTime;
|
static uint64_t time = Params().GenesisBlock().nTime;
|
||||||
|
|
||||||
auto ptemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get()}.CreateNewBlock(CScript{} << i++ << OP_TRUE);
|
BlockAssembler::Options options;
|
||||||
|
auto ptemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get(), options}.CreateNewBlock(CScript{} << i++ << OP_TRUE);
|
||||||
auto pblock = std::make_shared<CBlock>(ptemplate->block);
|
auto pblock = std::make_shared<CBlock>(ptemplate->block);
|
||||||
pblock->hashPrevBlock = prev_hash;
|
pblock->hashPrevBlock = prev_hash;
|
||||||
pblock->nTime = ++time;
|
pblock->nTime = ++time;
|
||||||
|
@ -329,7 +330,8 @@ BOOST_AUTO_TEST_CASE(witness_commitment_index)
|
||||||
LOCK(Assert(m_node.chainman)->GetMutex());
|
LOCK(Assert(m_node.chainman)->GetMutex());
|
||||||
CScript pubKey;
|
CScript pubKey;
|
||||||
pubKey << 1 << OP_TRUE;
|
pubKey << 1 << OP_TRUE;
|
||||||
auto ptemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get()}.CreateNewBlock(pubKey);
|
BlockAssembler::Options options;
|
||||||
|
auto ptemplate = BlockAssembler{m_node.chainman->ActiveChainstate(), m_node.mempool.get(), options}.CreateNewBlock(pubKey);
|
||||||
CBlock pblock = ptemplate->block;
|
CBlock pblock = ptemplate->block;
|
||||||
|
|
||||||
CTxOut witness;
|
CTxOut witness;
|
||||||
|
|
|
@ -87,7 +87,7 @@ class RPCGenerateTest(BitcoinTestFramework):
|
||||||
txid1 = miniwallet.send_self_transfer(from_node=node)['txid']
|
txid1 = miniwallet.send_self_transfer(from_node=node)['txid']
|
||||||
utxo1 = miniwallet.get_utxo(txid=txid1)
|
utxo1 = miniwallet.get_utxo(txid=txid1)
|
||||||
rawtx2 = miniwallet.create_self_transfer(utxo_to_spend=utxo1)['hex']
|
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')
|
self.log.info('Fail to generate block with txid not in mempool')
|
||||||
missing_txid = '0000000000000000000000000000000000000000000000000000000000000000'
|
missing_txid = '0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
|
|
Loading…
Add table
Reference in a new issue