Skip to content

Commit

Permalink
Merge #30200: Introduce Mining interface
Browse files Browse the repository at this point in the history
a9716c5 rpc: call IsInitialBlockDownload via miner interface (Sjors Provoost)
dda0b08 rpc: minize getTipHash() calls in gbt (Sjors Provoost)
7b4d324 rpc: call processNewBlock via miner interface (Sjors Provoost)
9e22835 rpc: getTransactionsUpdated via miner interface (Sjors Provoost)
64ebb0f Always pass options to BlockAssembler constructor (Sjors Provoost)
4bf2e36 rpc: call CreateNewBlock via miner interface (Sjors Provoost)
404b01c rpc: getblocktemplate getTipHash() via Miner interface (Sjors Provoost)
d8a3496 rpc: call TestBlockValidity via miner interface (Sjors Provoost)
8ecb681 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: #29346 (comment)

  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 ACK a9716c5
  itornaza:
    Code review and std-tests ACK a9716c5
  ryanofsky:
    Code review ACK a9716c5 with one minor suggestion in case you update. Only changes since last review were other small changes to the interface.

Tree-SHA512: cf97f87d6e9ed89da3835a0730da3b24a7b14c8605ea221149103a5915e79598cf082a95f2bc88e33f1c450e3d4aad88aed1163a29195acca88bcace055af724
  • Loading branch information
ryanofsky committed Jun 24, 2024
2 parents a57da5e + a9716c5 commit 323b0ac
Show file tree
Hide file tree
Showing 21 changed files with 226 additions and 52 deletions.
5 changes: 3 additions & 2 deletions doc/developer-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -1457,8 +1457,9 @@ independent (node, wallet, GUI), are defined in
there are [`interfaces::Chain`](../src/interfaces/chain.h), used by wallet to
access the node's latest chain state,
[`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
to control an individual wallet. There are also more specialized interface
node, [`interfaces::Wallet`](../src/interfaces/wallet.h), used by the GUI
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)
[`interfaces::ChainClient`](../src/interfaces/chain.h) passed to and from
various interface methods.
Expand Down
1 change: 1 addition & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ BITCOIN_CORE_H = \
interfaces/handler.h \
interfaces/init.h \
interfaces/ipc.h \
interfaces/mining.h \
interfaces/node.h \
interfaces/wallet.h \
kernel/blockmanager_opts.h \
Expand Down
2 changes: 2 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <init/common.h>
#include <interfaces/chain.h>
#include <interfaces/init.h>
#include <interfaces/mining.h>
#include <interfaces/node.h>
#include <kernel/context.h>
#include <key.h>
Expand Down Expand Up @@ -1117,6 +1118,7 @@ bool AppInitLockDataDirectory()
bool AppInitInterfaces(NodeContext& node)
{
node.chain = node.init->makeChain();
node.mining = node.init->makeMining();
return true;
}

Expand Down
1 change: 1 addition & 0 deletions src/init/bitcoin-node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class BitcoinNodeInit : public interfaces::Init
}
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::Mining> makeMining() override { return interfaces::MakeMining(m_node); }
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain) override
{
return MakeWalletLoader(chain, *Assert(m_node.args));
Expand Down
2 changes: 2 additions & 0 deletions src/init/bitcoin-qt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <interfaces/chain.h>
#include <interfaces/echo.h>
#include <interfaces/init.h>
#include <interfaces/mining.h>
#include <interfaces/node.h>
#include <interfaces/wallet.h>
#include <node/context.h>
Expand All @@ -25,6 +26,7 @@ class BitcoinQtInit : public interfaces::Init
}
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::Mining> makeMining() override { return interfaces::MakeMining(m_node); }
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain) override
{
return MakeWalletLoader(chain, *Assert(m_node.args));
Expand Down
2 changes: 2 additions & 0 deletions src/init/bitcoind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <interfaces/chain.h>
#include <interfaces/echo.h>
#include <interfaces/init.h>
#include <interfaces/mining.h>
#include <interfaces/node.h>
#include <interfaces/wallet.h>
#include <node/context.h>
Expand All @@ -27,6 +28,7 @@ class BitcoindInit : public interfaces::Init
}
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::Mining> makeMining() override { return interfaces::MakeMining(m_node); }
std::unique_ptr<interfaces::WalletLoader> makeWalletLoader(interfaces::Chain& chain) override
{
return MakeWalletLoader(chain, *Assert(m_node.args));
Expand Down
2 changes: 2 additions & 0 deletions src/interfaces/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <interfaces/chain.h>
#include <interfaces/echo.h>
#include <interfaces/mining.h>
#include <interfaces/node.h>
#include <interfaces/wallet.h>

Expand All @@ -32,6 +33,7 @@ class Init
virtual ~Init() = default;
virtual std::unique_ptr<Node> makeNode() { 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<Echo> makeEcho() { return nullptr; }
virtual Ipc* ipc() { return nullptr; }
Expand Down
82 changes: 82 additions & 0 deletions src/interfaces/mining.h
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions src/node/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <addrman.h>
#include <banman.h>
#include <interfaces/chain.h>
#include <interfaces/mining.h>
#include <kernel/context.h>
#include <key.h>
#include <net.h>
Expand Down
2 changes: 2 additions & 0 deletions src/node/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class PeerManager;
namespace interfaces {
class Chain;
class ChainClient;
class Mining;
class Init;
class WalletLoader;
} // namespace interfaces
Expand Down Expand Up @@ -74,6 +75,7 @@ struct NodeContext {
std::vector<std::unique_ptr<interfaces::ChainClient>> chain_clients;
//! Reference to chain client that should used to load or create wallets
//! opened by the gui.
std::unique_ptr<interfaces::Mining> mining;
interfaces::WalletLoader* wallet_loader{nullptr};
std::unique_ptr<CScheduler> scheduler;
std::function<void()> rpc_interruption_point = [] {};
Expand Down
59 changes: 59 additions & 0 deletions src/node/interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
#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>
#include <init.h>
#include <interfaces/chain.h>
#include <interfaces/handler.h>
#include <interfaces/mining.h>
#include <interfaces/node.h>
#include <interfaces/wallet.h>
#include <kernel/chain.h>
Expand All @@ -30,6 +32,7 @@
#include <node/context.h>
#include <node/interface_ui.h>
#include <node/mini_miner.h>
#include <node/miner.h>
#include <node/transaction.h>
#include <node/types.h>
#include <node/warnings.h>
Expand Down Expand Up @@ -69,8 +72,10 @@ using interfaces::Chain;
using interfaces::FoundBlock;
using interfaces::Handler;
using interfaces::MakeSignalHandler;
using interfaces::Mining;
using interfaces::Node;
using interfaces::WalletLoader;
using node::BlockAssembler;
using util::Join;

namespace node {
Expand Down Expand Up @@ -831,10 +836,64 @@ class ChainImpl : public Chain
ValidationSignals& validation_signals() { return *Assert(m_node.validation_signals); }
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 node

namespace interfaces {
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<Mining> MakeMining(node::NodeContext& context) { return std::make_unique<node::MinerImpl>(context); }
} // namespace interfaces
9 changes: 0 additions & 9 deletions src/node/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,6 @@ void ApplyArgsManOptions(const ArgsManager& args, BlockAssembler::Options& optio
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()
{
Expand Down
1 change: 0 additions & 1 deletion src/node/miner.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ class BlockAssembler
bool test_block_validity{true};
};

explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool);
explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool, const Options& options);

/** Construct a new block template with coinbase to scriptPubKeyIn */
Expand Down
Loading

0 comments on commit 323b0ac

Please sign in to comment.