diff --git a/CMakeLists.txt b/CMakeLists.txt index ff0e4fdb7392b..3611c9e280c40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,6 +298,15 @@ if(WIN32) try_append_linker_flag("-Wl,--major-subsystem-version,6" TARGET core_interface) try_append_linker_flag("-Wl,--minor-subsystem-version,2" TARGET core_interface) endif() + + # Workaround producing large object files, which cannot be handled by the assembler. + # More likely to happen with no, or lower levels of optimisation. + # See discussion in https://github.com/bitcoin/bitcoin/issues/28109. + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + try_append_cxx_flags("/bigobj" TARGET core_interface_debug SKIP_LINK) + else() + try_append_cxx_flags("-Wa,-mbig-obj" TARGET core_interface_debug SKIP_LINK) + endif() endif() # Use 64-bit off_t on 32-bit Linux. diff --git a/ci/test/00_setup_env_i686_centos.sh b/ci/test/00_setup_env_i686_centos.sh old mode 100755 new mode 100644 index 85750b1ecb8c2..a149e7e44de2a --- a/ci/test/00_setup_env_i686_centos.sh +++ b/ci/test/00_setup_env_i686_centos.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Copyright (c) 2020-2022 The Bitcoin Core developers +# Copyright (c) 2020-present The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,9 +9,9 @@ export LC_ALL=C.UTF-8 export HOST=i686-pc-linux-gnu export CONTAINER_NAME=ci_i686_centos export CI_IMAGE_NAME_TAG="quay.io/centos/amd64:stream9" -export CI_BASE_PACKAGES="gcc-c++ glibc-devel.x86_64 libstdc++-devel.x86_64 glibc-devel.i686 libstdc++-devel.i686 ccache make git python3 python3-pip which patch lbzip2 xz procps-ng dash rsync coreutils bison e2fsprogs cmake" +export STREAM_GCC_V="12" +export CI_BASE_PACKAGES="gcc-toolset-${STREAM_GCC_V}-gcc-c++ glibc-devel.x86_64 gcc-toolset-${STREAM_GCC_V}-libstdc++-devel.x86_64 glibc-devel.i686 gcc-toolset-${STREAM_GCC_V}-libstdc++-devel.i686 ccache make git python3 python3-pip which patch lbzip2 xz procps-ng dash rsync coreutils bison e2fsprogs cmake" export PIP_PACKAGES="pyzmq" export GOAL="install" -export NO_WERROR=1 # Suppress error: #warning _FORTIFY_SOURCE > 2 is treated like 2 on this platform [-Werror=cpp] export GROESTLCOIN_CONFIG="-DWITH_ZMQ=ON -DBUILD_GUI=ON -DREDUCE_EXPORTS=ON" export CONFIG_SHELL="/bin/dash" diff --git a/ci/test/03_test_script.sh b/ci/test/03_test_script.sh old mode 100755 new mode 100644 index e0e97e3b47269..2e9da29292f0f --- a/ci/test/03_test_script.sh +++ b/ci/test/03_test_script.sh @@ -76,8 +76,9 @@ fi if [ -z "$NO_DEPENDS" ]; then if [[ $CI_IMAGE_NAME_TAG == *centos* ]]; then - # Use bash for GRS - SHELL_OPTS="CONFIG_SHELL=/bin/bash" + SHELL_OPTS="CONFIG_SHELL=/bin/dash" + # shellcheck disable=SC1090 + source "/opt/rh/gcc-toolset-${STREAM_GCC_V}/enable" else SHELL_OPTS="CONFIG_SHELL=" fi diff --git a/depends/.gitignore b/depends/.gitignore index be6280f5990ad..c53f7f610e626 100644 --- a/depends/.gitignore +++ b/depends/.gitignore @@ -3,6 +3,7 @@ work/ built/ sources/ x86_64* +amd64* i686* mips* arm* diff --git a/depends/hosts/netbsd.mk b/depends/hosts/netbsd.mk index 838b58e7ba4c5..d2b79f9d5bf3a 100644 --- a/depends/hosts/netbsd.mk +++ b/depends/hosts/netbsd.mk @@ -7,8 +7,6 @@ netbsd_NM = $(host_toolchain)gcc-nm netbsd_RANLIB = $(host_toolchain)gcc-ranlib endif -netbsd_CXXFLAGS=$(netbsd_CFLAGS) - netbsd_release_CFLAGS=-O2 netbsd_release_CXXFLAGS=$(netbsd_release_CFLAGS) diff --git a/depends/packages/native_capnp.mk b/depends/packages/native_capnp.mk index 484e78d5d906b..d6e6b4cadbd62 100644 --- a/depends/packages/native_capnp.mk +++ b/depends/packages/native_capnp.mk @@ -1,9 +1,9 @@ package=native_capnp -$(package)_version=1.0.1 +$(package)_version=1.0.2 $(package)_download_path=https://capnproto.org/ $(package)_download_file=capnproto-c++-$($(package)_version).tar.gz $(package)_file_name=capnproto-cxx-$($(package)_version).tar.gz -$(package)_sha256_hash=0f7f4b8a76a2cdb284fddef20de8306450df6dd031a47a15ac95bc43c3358e09 +$(package)_sha256_hash=9057dbc0223366b74bbeca33a05de164a229b0377927f1b7ef3828cdd8cb1d7e define $(package)_set_vars $(package)_config_opts := -DBUILD_TESTING=OFF diff --git a/doc/release-notes-31223.md b/doc/release-notes-31223.md new file mode 100644 index 0000000000000..44f0552fd9335 --- /dev/null +++ b/doc/release-notes-31223.md @@ -0,0 +1,15 @@ +P2P and network changes +----------------------- +When the `-port` configuration option is used, the default onion listening port will now +be derived to be that port + 1 instead of being set to a fixed value (8334 on mainnet). +This re-allows setups with multiple local nodes using different `-port` and not using `-bind`, +which would lead to a startup failure in v28.0 due to a port collision. + +Note that a `HiddenServicePort` manually configured in `torrc` may need adjustment if used in +connection with the `-port` option. +For example, if you are using `-port=5555` with a non-standard value and not using `-bind=...=onion`, +previously Bitcoin Core would listen for incoming Tor connections on `127.0.0.1:8334`. +Now it would listen on `127.0.0.1:5556` (`-port` plus one). If you configured the hidden service manually +in torrc now you have to change it from `HiddenServicePort 8333 127.0.0.1:8334` to `HiddenServicePort 8333 +127.0.0.1:5556`, or configure bitcoind with `-bind=127.0.0.1:8334=onion` to get the previous behavior. +(#31223) diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp index 4005701caea6b..00102aefe2c8f 100644 --- a/src/bench/block_assemble.cpp +++ b/src/bench/block_assemble.cpp @@ -20,19 +20,23 @@ #include #include +using node::BlockAssembler; + static void AssembleBlock(benchmark::Bench& bench) { const auto test_setup = MakeNoLogFileContext(); CScriptWitness witness; witness.stack.push_back(WITNESS_STACK_ELEM_OP_TRUE); + BlockAssembler::Options options; + options.coinbase_output_script = P2WSH_OP_TRUE; // Collect some loose transactions that spend the coinbases of our mined blocks constexpr size_t NUM_BLOCKS{200}; std::array txs; for (size_t b{0}; b < NUM_BLOCKS; ++b) { CMutableTransaction tx; - tx.vin.emplace_back(MineBlock(test_setup->m_node, P2WSH_OP_TRUE)); + tx.vin.emplace_back(MineBlock(test_setup->m_node, options)); tx.vin.back().scriptWitness = witness; tx.vout.emplace_back(1337, P2WSH_OP_TRUE); if (NUM_BLOCKS - b >= COINBASE_MATURITY) @@ -48,7 +52,7 @@ static void AssembleBlock(benchmark::Bench& bench) } bench.run([&] { - PrepareBlock(test_setup->m_node, P2WSH_OP_TRUE); + PrepareBlock(test_setup->m_node, options); }); } static void BlockAssemblerAddPackageTxns(benchmark::Bench& bench) @@ -56,11 +60,12 @@ static void BlockAssemblerAddPackageTxns(benchmark::Bench& bench) FastRandomContext det_rand{true}; auto testing_setup{MakeNoLogFileContext()}; testing_setup->PopulateMempool(det_rand, /*num_transactions=*/1000, /*submit=*/true); - node::BlockAssembler::Options assembler_options; + BlockAssembler::Options assembler_options; assembler_options.test_block_validity = false; + assembler_options.coinbase_output_script = P2WSH_OP_TRUE; bench.run([&] { - PrepareBlock(testing_setup->m_node, P2WSH_OP_TRUE, assembler_options); + PrepareBlock(testing_setup->m_node, assembler_options); }); } diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index b07f12e508690..feb8360d3e138 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -42,15 +42,15 @@ std::unique_ptr CreateBaseChainParams(const ChainType chain) { switch (chain) { case ChainType::MAIN: - return std::make_unique("", 1441, 1444); + return std::make_unique("", 1441); case ChainType::TESTNET: - return std::make_unique("testnet3", 17766, 17764); + return std::make_unique("testnet3", 17766); case ChainType::TESTNET4: - return std::make_unique("testnet4", 41441, 41444); + return std::make_unique("testnet4", 41441); case ChainType::SIGNET: - return std::make_unique("signet", 31441, 31444); + return std::make_unique("signet", 31441); case ChainType::REGTEST: - return std::make_unique("regtest", 18443, 18445); + return std::make_unique("regtest", 18443); } assert(false); } diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index 0477efcf05a5b..506c63bb6c669 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -22,15 +22,13 @@ class CBaseChainParams public: const std::string& DataDir() const { return strDataDir; } uint16_t RPCPort() const { return m_rpc_port; } - uint16_t OnionServiceTargetPort() const { return m_onion_service_target_port; } CBaseChainParams() = delete; - CBaseChainParams(const std::string& data_dir, uint16_t rpc_port, uint16_t onion_service_target_port) - : m_rpc_port(rpc_port), m_onion_service_target_port(onion_service_target_port), strDataDir(data_dir) {} + CBaseChainParams(const std::string& data_dir, uint16_t rpc_port) + : m_rpc_port(rpc_port), strDataDir(data_dir) {} private: const uint16_t m_rpc_port; - const uint16_t m_onion_service_target_port; std::string strDataDir; }; diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp index dc32f0ab80b1c..7dd24e1868f25 100644 --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -4,6 +4,7 @@ #include #include +#include /* WARNING! If you're reading this because you're learning about crypto and/or designing a new system that will use merkle trees, keep in mind @@ -84,8 +85,10 @@ uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated) } /* This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */ -static void MerkleComputation(const std::vector& leaves, uint256* proot, bool* pmutated, uint32_t branchpos, std::vector* pbranch) { - if (pbranch) pbranch->clear(); +static void MerkleComputation(const std::vector& leaves, uint256* proot, bool* pmutated, uint32_t leaf_pos, std::vector* path) +{ + if (path) path->clear(); + Assume(leaves.size() <= UINT32_MAX); if (leaves.size() == 0) { if (pmutated) *pmutated = false; if (proot) *proot = uint256(); @@ -105,18 +108,18 @@ static void MerkleComputation(const std::vector& leaves, uint256* proot // First process all leaves into 'inner' values. while (count < leaves.size()) { uint256 h = leaves[count]; - bool matchh = count == branchpos; + bool matchh = count == leaf_pos; count++; int level; // For each of the lower bits in count that are 0, do 1 step. Each // corresponds to an inner value that existed before processing the // current leaf, and each needs a hash to combine it. for (level = 0; !(count & ((uint32_t{1}) << level)); level++) { - if (pbranch) { + if (path) { if (matchh) { - pbranch->push_back(inner[level]); + path->push_back(inner[level]); } else if (matchlevel == level) { - pbranch->push_back(h); + path->push_back(h); matchh = true; } } @@ -144,8 +147,8 @@ static void MerkleComputation(const std::vector& leaves, uint256* proot // If we reach this point, h is an inner value that is not the top. // We combine it with itself (Bitcoin's special rule for odd levels in // the tree) to produce a higher level one. - if (pbranch && matchh) { - pbranch->push_back(h); + if (path && matchh) { + path->push_back(h); } h = Hash(h, h); // Increment count to the value it would have if two entries at this @@ -154,11 +157,11 @@ static void MerkleComputation(const std::vector& leaves, uint256* proot level++; // And propagate the result upwards accordingly. while (!(count & ((uint32_t{1}) << level))) { - if (pbranch) { + if (path) { if (matchh) { - pbranch->push_back(inner[level]); + path->push_back(inner[level]); } else if (matchlevel == level) { - pbranch->push_back(h); + path->push_back(h); matchh = true; } } @@ -171,18 +174,18 @@ static void MerkleComputation(const std::vector& leaves, uint256* proot if (proot) *proot = h; } -static std::vector ComputeMerkleBranch(const std::vector& leaves, uint32_t position) { +static std::vector ComputeMerklePath(const std::vector& leaves, uint32_t position) { std::vector ret; MerkleComputation(leaves, nullptr, nullptr, position, &ret); return ret; } -std::vector BlockMerkleBranch(const CBlock& block, uint32_t position) +std::vector TransactionMerklePath(const CBlock& block, uint32_t position) { std::vector leaves; leaves.resize(block.vtx.size()); for (size_t s = 0; s < block.vtx.size(); s++) { leaves[s] = block.vtx[s]->GetHash(); } - return ComputeMerkleBranch(leaves, position); + return ComputeMerklePath(leaves, position); } diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h index 363f68039c3b7..c722cbe446f5b 100644 --- a/src/consensus/merkle.h +++ b/src/consensus/merkle.h @@ -28,10 +28,10 @@ uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated = nullptr); * Compute merkle path to the specified transaction * * @param[in] block the block - * @param[in] position transaction for which to calculate the merkle path, defaults to coinbase + * @param[in] position transaction for which to calculate the merkle path (0 is the coinbase) * * @return merkle path ordered from the deepest */ -std::vector BlockMerkleBranch(const CBlock& block, uint32_t position = 0); +std::vector TransactionMerklePath(const CBlock& block, uint32_t position); #endif // BITCOIN_CONSENSUS_MERKLE_H diff --git a/src/init.cpp b/src/init.cpp index db473ee5fae11..54524460500f9 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -523,7 +523,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc) argsman.AddArg("-addnode=", strprintf("Add a node to connect to and attempt to keep the connection open (see the addnode RPC help for more info). This option can be specified multiple times to add multiple nodes; connections are limited to %u at a time and are counted separately from the -maxconnections limit.", MAX_ADDNODE_CONNECTIONS), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); argsman.AddArg("-asmap=", strprintf("Specify asn mapping used for bucketing of the peers (default: %s). Relative paths will be prefixed by the net-specific datadir location.", DEFAULT_ASMAP_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-bantime=", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-bind=[:][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet3: 127.0.0.1:%u=onion, testnet4: 127.0.0.1:%u=onion, signet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultBaseParams->OnionServiceTargetPort(), testnetBaseParams->OnionServiceTargetPort(), testnet4BaseParams->OnionServiceTargetPort(), signetBaseParams->OnionServiceTargetPort(), regtestBaseParams->OnionServiceTargetPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); + argsman.AddArg("-bind=[:][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet3: 127.0.0.1:%u=onion, testnet4: 127.0.0.1:%u=onion, signet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultChainParams->GetDefaultPort() + 1, testnetChainParams->GetDefaultPort() + 1, testnet4ChainParams->GetDefaultPort() + 1, signetChainParams->GetDefaultPort() + 1, regtestChainParams->GetDefaultPort() + 1), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); argsman.AddArg("-cjdnsreachable", "If set, then this host is configured for CJDNS (connecting to fc00::/8 addresses would lead us to the CJDNS network, see doc/cjdns.md) (default: 0)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-connect=", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); @@ -550,7 +550,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc) argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-txreconciliation", strprintf("Enable transaction reconciliations per BIP 330 (default: %d)", DEFAULT_TXRECONCILIATION_ENABLE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION); - argsman.AddArg("-port=", strprintf("Listen for connections on (default: %u, testnet3: %u, testnet4: %u, signet: %u, regtest: %u). Not relevant for I2P (see doc/i2p.md).", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), testnet4ChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); + argsman.AddArg("-port=", strprintf("Listen for connections on (default: %u, testnet3: %u, testnet4: %u, signet: %u, regtest: %u). Not relevant for I2P (see doc/i2p.md). If set to a value x, the default onion listening port will be set to x+1.", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), testnet4ChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); #ifdef HAVE_SOCKADDR_UN argsman.AddArg("-proxy=", "Connect through SOCKS5 proxy, set -noproxy to disable (default: disabled). May be a local file path prefixed with 'unix:' if the proxy supports it.", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_ELISION, OptionsCategory::CONNECTION); #else @@ -1770,7 +1770,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) node.background_init_thread = std::thread(&util::TraceThread, "initload", [=, &chainman, &args, &node] { ScheduleBatchPriority(); - // Import blocks + // Import blocks and ActivateBestChain() ImportBlocks(chainman, vImportFiles); if (args.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) { LogPrintf("Stopping after block import\n"); @@ -1793,8 +1793,18 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } }); - // Wait for genesis block to be processed - if (WITH_LOCK(chainman.GetMutex(), return chainman.ActiveTip() == nullptr)) { + /* + * Wait for genesis block to be processed. Typically kernel_notifications.m_tip_block + * has already been set by a call to LoadChainTip() in CompleteChainstateInitialization(). + * But this is skipped if the chainstate doesn't exist yet or is being wiped: + * + * 1. first startup with an empty datadir + * 2. reindex + * 3. reindex-chainstate + * + * In these case it's connected by a call to ActivateBestChain() in the initload thread. + */ + { WAIT_LOCK(kernel_notifications.m_tip_block_mutex, lock); kernel_notifications.m_tip_block_cv.wait(lock, [&]() EXCLUSIVE_LOCKS_REQUIRED(kernel_notifications.m_tip_block_mutex) { return !kernel_notifications.m_tip_block.IsNull() || ShutdownRequested(node); @@ -1817,7 +1827,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) if (tip_info) { tip_info->block_height = chain_active_height; tip_info->block_time = best_block_time; - tip_info->verification_progress = GuessVerificationProgress(chainman.GetParams().TxData(), &tip); + tip_info->verification_progress = chainman.GuessVerificationProgress(&tip); } if (tip_info && chainman.m_best_header) { tip_info->header_height = chainman.m_best_header->nHeight; @@ -1848,6 +1858,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) const uint16_t default_bind_port = static_cast(args.GetIntArg("-port", Params().GetDefaultPort())); + const uint16_t default_bind_port_onion = default_bind_port + 1; + const auto BadPortWarning = [](const char* prefix, uint16_t port) { return strprintf(_("%s request to listen on port %u. This port is considered \"bad\" and " "thus it is unlikely that any peer will connect to it. See " @@ -1872,7 +1884,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) const std::string network_type = bind_arg.substr(index + 1); if (network_type == "onion") { const std::string truncated_bind_arg = bind_arg.substr(0, index); - bind_addr = Lookup(truncated_bind_arg, BaseParams().OnionServiceTargetPort(), false); + bind_addr = Lookup(truncated_bind_arg, default_bind_port_onion, false); if (bind_addr.has_value()) { connOptions.onion_binds.push_back(bind_addr.value()); continue; @@ -1908,7 +1920,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } else if (!connOptions.vBinds.empty()) { onion_service_target = connOptions.vBinds.front(); } else { - onion_service_target = DefaultOnionServiceTarget(); + onion_service_target = DefaultOnionServiceTarget(default_bind_port_onion); connOptions.onion_binds.push_back(onion_service_target); } diff --git a/src/interfaces/mining.h b/src/interfaces/mining.h index c77f3c30a2638..bc5955ded6628 100644 --- a/src/interfaces/mining.h +++ b/src/interfaces/mining.h @@ -55,7 +55,7 @@ class BlockTemplate * * @returns if the block was processed, independent of block validity */ - virtual bool submitSolution(uint32_t version, uint32_t timestamp, uint32_t nonce, CMutableTransaction coinbase) = 0; + virtual bool submitSolution(uint32_t version, uint32_t timestamp, uint32_t nonce, CTransactionRef coinbase) = 0; }; //! Interface giving clients (RPC, Stratum v2 Template Provider in the future) @@ -75,8 +75,8 @@ class Mining virtual std::optional getTip() = 0; /** - * Waits for the connected tip to change. If the tip was not connected on - * startup, this will wait. + * Waits for the connected tip to change. During node initialization, this will + * wait until the tip is connected. * * @param[in] current_tip block hash of the current chain tip. Function waits * for the chain tip to differ from this. @@ -88,36 +88,10 @@ class Mining /** * Construct a new block template * - * @param[in] script_pub_key the coinbase output * @param[in] options options for creating the block * @returns a block template */ - virtual std::unique_ptr createNewBlock(const CScript& script_pub_key, 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& 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; + virtual std::unique_ptr createNewBlock(const node::BlockCreateOptions& options = {}) = 0; //! Get internal node context. Useful for RPC and testing, //! but not accessible across processes. diff --git a/src/ipc/capnp/mining.capnp b/src/ipc/capnp/mining.capnp index f8faaa0c4246d..50b07bda708b7 100644 --- a/src/ipc/capnp/mining.capnp +++ b/src/ipc/capnp/mining.capnp @@ -17,10 +17,7 @@ interface Mining $Proxy.wrap("interfaces::Mining") { isInitialBlockDownload @1 (context :Proxy.Context) -> (result: Bool); getTip @2 (context :Proxy.Context) -> (result: Common.BlockRef, hasResult: Bool); waitTipChanged @3 (context :Proxy.Context, currentTip: Data, timeout: Float64) -> (result: Common.BlockRef); - createNewBlock @4 (scriptPubKey: Data, 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); + createNewBlock @4 (options: BlockCreateOptions) -> (result: BlockTemplate); } interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") { diff --git a/src/ipc/process.cpp b/src/ipc/process.cpp index 432c365d8f294..bdc541b6544bc 100644 --- a/src/ipc/process.cpp +++ b/src/ipc/process.cpp @@ -72,7 +72,7 @@ static bool ParseAddress(std::string& address, struct sockaddr_un& addr, std::string& error) { - if (address.compare(0, 4, "unix") == 0 && (address.size() == 4 || address[4] == ':')) { + if (address == "unix" || address.starts_with("unix:")) { fs::path path; if (address.size() <= 5) { path = data_dir / fs::PathFromString(strprintf("%s.sock", RemovePrefixView(dest_exe_name, "bitcoin-"))); diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 03bc5f4600720..ac6db0558df8f 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -430,6 +430,7 @@ class BlockManager void CleanupBlockRevFiles() const; }; +// Calls ActivateBestChain() even if no blocks are imported. void ImportBlocks(ChainstateManager& chainman, std::span import_paths); } // namespace node diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index e4ae9400e37aa..b7dbd8c6ab184 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -324,7 +324,7 @@ class NodeImpl : public Node } double getVerificationProgress() override { - return GuessVerificationProgress(chainman().GetParams().TxData(), WITH_LOCK(::cs_main, return chainman().ActiveChain().Tip())); + return chainman().GuessVerificationProgress(WITH_LOCK(chainman().GetMutex(), return chainman().ActiveChain().Tip())); } bool isInitialBlockDownload() override { @@ -406,9 +406,9 @@ class NodeImpl : public Node } std::unique_ptr handleNotifyBlockTip(NotifyBlockTipFn fn) override { - return MakeSignalHandler(::uiInterface.NotifyBlockTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) { + return MakeSignalHandler(::uiInterface.NotifyBlockTip_connect([fn, this](SynchronizationState sync_state, const CBlockIndex* block) { fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()}, - GuessVerificationProgress(Params().TxData(), block)); + chainman().GuessVerificationProgress(block)); })); } std::unique_ptr handleNotifyHeaderTip(NotifyHeaderTipFn fn) override @@ -639,8 +639,8 @@ class ChainImpl : public Chain void findCoins(std::map& coins) override { return FindCoins(m_node, coins); } double guessVerificationProgress(const uint256& block_hash) override { - LOCK(::cs_main); - return GuessVerificationProgress(chainman().GetParams().TxData(), chainman().m_blockman.LookupBlockIndex(block_hash)); + LOCK(chainman().GetMutex()); + return chainman().GuessVerificationProgress(chainman().m_blockman.LookupBlockIndex(block_hash)); } bool hasBlocks(const uint256& block_hash, int min_height, std::optional max_height) override { @@ -913,19 +913,17 @@ class BlockTemplateImpl : public BlockTemplate std::vector getCoinbaseMerklePath() override { - return BlockMerkleBranch(m_block_template->block); + return TransactionMerklePath(m_block_template->block, 0); } - bool submitSolution(uint32_t version, uint32_t timestamp, uint32_t nonce, CMutableTransaction coinbase) override + bool submitSolution(uint32_t version, uint32_t timestamp, uint32_t nonce, CTransactionRef coinbase) override { CBlock block{m_block_template->block}; - auto cb = MakeTransactionRef(std::move(coinbase)); - if (block.vtx.size() == 0) { - block.vtx.push_back(cb); + block.vtx.push_back(coinbase); } else { - block.vtx[0] = cb; + block.vtx[0] = coinbase; } block.nVersion = version; @@ -981,34 +979,11 @@ class MinerImpl : public Mining return BlockRef{chainman().ActiveChain().Tip()->GetBlockHash(), chainman().ActiveChain().Tip()->nHeight}; } - bool processNewBlock(const std::shared_ptr& 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 createNewBlock(const CScript& script_pub_key, const BlockCreateOptions& options) override + std::unique_ptr createNewBlock(const BlockCreateOptions& options) override { BlockAssembler::Options assemble_options{options}; ApplyArgsManOptions(*Assert(m_node.args), assemble_options); - return std::make_unique(BlockAssembler{chainman().ActiveChainstate(), context()->mempool.get(), assemble_options}.CreateNewBlock(script_pub_key), m_node); + return std::make_unique(BlockAssembler{chainman().ActiveChainstate(), context()->mempool.get(), assemble_options}.CreateNewBlock(), m_node); } NodeContext* context() override { return &m_node; } diff --git a/src/node/kernel_notifications.h b/src/node/kernel_notifications.h index 296b9c426dcef..35070b5285d5f 100644 --- a/src/node/kernel_notifications.h +++ b/src/node/kernel_notifications.h @@ -56,9 +56,9 @@ class KernelNotifications : public kernel::Notifications Mutex m_tip_block_mutex; std::condition_variable m_tip_block_cv GUARDED_BY(m_tip_block_mutex); - //! The block for which the last blockTip notification was received for. - //! The initial ZERO means that no block has been connected yet, which may - //! be true even long after startup, until shutdown. + //! The block for which the last blockTip notification was received. + //! It's first set when the tip is connected during node initialization. + //! Might be unset during an early shutdown. uint256 m_tip_block GUARDED_BY(m_tip_block_mutex){uint256::ZERO}; private: diff --git a/src/node/miner.cpp b/src/node/miner.cpp index 6afabd5a48839..0629a38bf1aa5 100644 --- a/src/node/miner.cpp +++ b/src/node/miner.cpp @@ -107,7 +107,7 @@ void BlockAssembler::resetBlock() nFees = 0; } -std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) +std::unique_ptr BlockAssembler::CreateNewBlock() { const auto time_start{SteadyClock::now()}; @@ -152,7 +152,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc coinbaseTx.vin.resize(1); coinbaseTx.vin[0].prevout.SetNull(); coinbaseTx.vout.resize(1); - coinbaseTx.vout[0].scriptPubKey = scriptPubKeyIn; + coinbaseTx.vout[0].scriptPubKey = m_options.coinbase_output_script; coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus()); coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0; pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx)); diff --git a/src/node/miner.h b/src/node/miner.h index 25ce110b34886..f6461a8d55378 100644 --- a/src/node/miner.h +++ b/src/node/miner.h @@ -169,8 +169,8 @@ class BlockAssembler explicit BlockAssembler(Chainstate& chainstate, const CTxMemPool* mempool, const Options& options); - /** Construct a new block template with coinbase to scriptPubKeyIn */ - std::unique_ptr CreateNewBlock(const CScript& scriptPubKeyIn); + /** Construct a new block template */ + std::unique_ptr CreateNewBlock(); inline static std::optional m_last_block_num_txs{}; inline static std::optional m_last_block_weight{}; diff --git a/src/node/types.h b/src/node/types.h index 1302f1b127fa6..4b0de084ab3d0 100644 --- a/src/node/types.h +++ b/src/node/types.h @@ -3,8 +3,8 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. //! @file node/types.h is a home for public enum and struct type definitions -//! that are used by internally by node code, but also used externally by wallet -//! or GUI code. +//! that are used internally by node code, but also used externally by wallet, +//! mining or GUI code. //! //! This file is intended to define only simple types that do not have external //! dependencies. More complicated types should be defined in dedicated header @@ -14,6 +14,7 @@ #define BITCOIN_NODE_TYPES_H #include +#include