Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stratum v2 Template Provider inside Bitcoin Core (deprecated) #68

Open
wants to merge 3 commits into
base: 2024/07/sv2-tp-common
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
379 changes: 379 additions & 0 deletions doc/stratum-v2.md

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,15 @@ target_link_libraries(bitcoin_node
$<TARGET_NAME_IF_EXISTS:libevent::extra>
$<TARGET_NAME_IF_EXISTS:libevent::pthreads>
$<TARGET_NAME_IF_EXISTS:USDT::headers>
$<TARGET_NAME_IF_EXISTS:bitcoin_sv2>
)

if(WITH_SV2)
target_compile_definitions(bitcoin_node
PUBLIC
WITH_SV2=1
)
endif()

# Bitcoin Core bitcoind.
if(BUILD_DAEMON)
Expand Down
72 changes: 72 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
#include <node/mempool_persist_args.h>
#include <node/miner.h>
#include <node/peerman_args.h>
#ifdef WITH_SV2
#include <sv2/template_provider.h>
#endif
#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/fees_args.h>
Expand Down Expand Up @@ -271,6 +274,11 @@ void Interrupt(NodeContext& node)
InterruptRPC();
InterruptREST();
InterruptTorControl();
#ifdef WITH_SV2
if (node.sv2_template_provider) {
node.sv2_template_provider->Interrupt();
}
#endif
InterruptMapPort();
if (node.connman)
node.connman->Interrupt();
Expand Down Expand Up @@ -310,6 +318,11 @@ void Shutdown(NodeContext& node)

StopTorControl();

#ifdef WITH_SV2
// Stop Template Provider
if (node.sv2_template_provider) node.sv2_template_provider->StopThreads();
#endif

if (node.background_init_thread.joinable()) node.background_init_thread.join();
// After everything has been shut down, but before things get flushed, stop the
// the scheduler. After this point, SyncWithValidationInterfaceQueue() should not be called anymore
Expand All @@ -323,6 +336,9 @@ void Shutdown(NodeContext& node)
node.banman.reset();
node.addrman.reset();
node.netgroupman.reset();
#ifdef WITH_SV2
node.sv2_template_provider.reset();
#endif

if (node.mempool && node.mempool->GetLoadTried() && ShouldPersistMempool(*node.args)) {
DumpMempool(*node.mempool, MempoolPath(*node.args));
Expand Down Expand Up @@ -652,6 +668,11 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
argsman.AddArg("-blockreservedweight=<n>", strprintf("Reserve space for the fixed-size block header plus the largest coinbase transaction the mining software may add to the block. (default: %d).", DEFAULT_BLOCK_RESERVED_WEIGHT), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
argsman.AddArg("-blockmintxfee=<amt>", strprintf("Set lowest fee rate (in %s/kvB) for transactions to be included in block creation. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_BLOCK_MIN_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
argsman.AddArg("-blockversion=<n>", "Override block version to test forking scenarios", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::BLOCK_CREATION);
#ifdef WITH_SV2
argsman.AddArg("-sv2", "Bitcoind will act as a Stratum v2 Template Provider, see doc/stratum-v2.md (default: false)", ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
argsman.AddArg("-sv2interval", strprintf("Template Provider block template update interval (default: %d seconds)", Sv2TemplateProviderOptions().fee_check_interval.count()), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
argsman.AddArg("-sv2feedelta", strprintf("Minimum fee delta for Template Provider to send update upstream (default: %d sat)", uint64_t(Sv2TemplateProviderOptions().fee_delta)), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
#endif

argsman.AddArg("-rest", strprintf("Accept public REST requests (default: %u)", DEFAULT_REST_ENABLE), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
argsman.AddArg("-rpcallowip=<ip>", "Allow JSON-RPC connections from specified source. Valid values for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0), a network/CIDR (e.g. 1.2.3.4/24), all ipv4 (0.0.0.0/0), or all ipv6 (::/0). This option can be specified multiple times", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
Expand All @@ -673,6 +694,11 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
argsman.AddArg("-ipcbind=<address>", "Bind to Unix socket address and listen for incoming connections. Valid address values are \"unix\" to listen on the default path, <datadir>/node.sock, or \"unix:/custom/path\" to specify a custom path. Can be specified multiple times to listen on multiple paths. Default behavior is not to listen on any path. If relative paths are specified, they are interpreted relative to the network data directory. If paths include any parent directory components and the parent directories do not exist, they will be created.", ArgsManager::ALLOW_ANY, OptionsCategory::IPC);
}

#ifdef WITH_SV2
argsman.AddArg("-sv2bind=<addr>[:<port>]", strprintf("Bind to given address and always listen on it (default: 127.0.0.1). Use [host]:port notation for IPv6."), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
argsman.AddArg("-sv2port=<port>", strprintf("Listen for Stratum v2 connections on <port> (default: %u, testnet: %u, signet: %u, regtest: %u)", defaultBaseParams->Sv2Port(), testnetBaseParams->Sv2Port(), signetBaseParams->Sv2Port(), regtestBaseParams->Sv2Port()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
#endif

#if HAVE_DECL_FORK
argsman.AddArg("-daemon", strprintf("Run in the background as a daemon and accept commands (default: %d)", DEFAULT_DAEMON), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-daemonwait", strprintf("Wait for initialization to be finished before exiting. This implies -daemon (default: %d)", DEFAULT_DAEMONWAIT), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
Expand Down Expand Up @@ -1172,6 +1198,9 @@ bool CheckHostPortOptions(const ArgsManager& args) {
{"-onion", true},
{"-proxy", true},
{"-rpcbind", false},
#ifdef WITH_SV2
{"-sv2bind", false},
#endif
{"-torcontrol", false},
{"-whitebind", false},
{"-zmqpubhashblock", true},
Expand Down Expand Up @@ -2036,6 +2065,49 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
return false;
}

#ifdef WITH_SV2
if (args.GetBoolArg("-sv2", false)) {
assert(!node.sv2_template_provider);
assert(node.mining);

Sv2TemplateProviderOptions options{};

node.sv2_template_provider = std::make_unique<Sv2TemplateProvider>(*node.mining);

const std::string sv2_port_arg = args.GetArg("-sv2port", "");

if (sv2_port_arg.empty()) {
options.port = BaseParams().Sv2Port();
} else {
if (!ParseUInt16(sv2_port_arg, &options.port) || options.port == 0) {
return InitError(InvalidPortErrMsg("sv2port", sv2_port_arg));
}
}

if (gArgs.IsArgSet("-sv2bind")) { // Specific bind address
std::optional<std::string> sv2_bind{gArgs.GetArg("-sv2bind")};
if (sv2_bind) {
if (!SplitHostPort(sv2_bind.value(), options.port, options.host)) {
throw std::runtime_error(strprintf("Invalid port %d", options.port));
}
}
}

options.fee_delta = gArgs.GetIntArg("-sv2feedelta", Sv2TemplateProviderOptions().fee_delta);

if (gArgs.IsArgSet("-sv2interval")) {
if (args.GetIntArg("-sv2interval", 0) < 1) {
return InitError(Untranslated("-sv2interval must be at least one second"));
}
options.fee_check_interval = std::chrono::seconds(gArgs.GetIntArg("-sv2interval", 0));
}

if (!node.sv2_template_provider->Start(options)) {
return InitError(_("Unable to start Stratum v2 Template Provider"));
}
}
#endif

// ********************************************************* Step 13: finished

// At this point, the RPC is "started", but still in warmup, which means it
Expand Down
3 changes: 3 additions & 0 deletions src/node/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#include <node/warnings.h>
#include <policy/fees.h>
#include <scheduler.h>
#ifdef WITH_SV2
#include <sv2/template_provider.h>
#endif
#include <txmempool.h>
#include <validation.h>
#include <validationinterface.h>
Expand Down
8 changes: 8 additions & 0 deletions src/node/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ class ChainstateManager;
class ECC_Context;
class NetGroupManager;
class PeerManager;
#ifdef WITH_SV2
class Sv2TemplateProvider;
#endif
namespace interfaces {
class Chain;
class ChainClient;
Expand All @@ -40,6 +42,11 @@ namespace util {
class SignalInterrupt;
}

#ifndef WITH_SV2
// Dummy
class Sv2TemplateProvider {};
#endif

namespace node {
class KernelNotifications;
class Warnings;
Expand Down Expand Up @@ -72,6 +79,7 @@ struct NodeContext {
std::unique_ptr<PeerManager> peerman;
std::unique_ptr<ChainstateManager> chainman;
std::unique_ptr<BanMan> banman;
std::unique_ptr<Sv2TemplateProvider> sv2_template_provider;
ArgsManager* args{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
std::vector<BaseIndex*> indexes; // raw pointers because memory is not managed by this struct
std::unique_ptr<interfaces::Chain> chain;
Expand Down
Loading
Loading