aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am3
-rw-r--r--src/Makefile.bench.include1
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/attributes.h8
-rw-r--r--src/bench/block_assemble.cpp2
-rw-r--r--src/bench/checkblock.cpp3
-rw-r--r--src/bench/load_external.cpp3
-rw-r--r--src/bench/logging.cpp3
-rw-r--r--src/bench/mempool_stress.cpp5
-rw-r--r--src/bench/rpc_blockchain.cpp3
-rw-r--r--src/bench/rpc_mempool.cpp4
-rw-r--r--src/bench/streams_findbyte.cpp31
-rw-r--r--src/bench/util_time.cpp2
-rw-r--r--src/bitcoin-chainstate.cpp9
-rw-r--r--src/bitcoin-cli.cpp48
-rw-r--r--src/bitcoin-tx.cpp3
-rw-r--r--src/bitcoin-util.cpp2
-rw-r--r--src/bitcoin-wallet.cpp2
-rw-r--r--src/chainparams.cpp23
-rw-r--r--src/chainparams.h13
-rw-r--r--src/chainparamsbase.cpp23
-rw-r--r--src/chainparamsbase.h18
-rw-r--r--src/common/args.cpp56
-rw-r--r--src/common/args.h24
-rw-r--r--src/common/config.cpp5
-rw-r--r--src/common/init.cpp2
-rw-r--r--src/crypto/sha256_avx2.cpp3
-rw-r--r--src/crypto/sha256_sse41.cpp3
-rw-r--r--src/crypto/sha256_x86_shani.cpp20
-rw-r--r--src/external_signer.cpp16
-rw-r--r--src/httprpc.cpp4
-rw-r--r--src/index/base.cpp6
-rw-r--r--src/index/blockfilterindex.cpp4
-rw-r--r--src/index/coinstatsindex.cpp10
-rw-r--r--src/index/txindex.cpp4
-rw-r--r--src/init.cpp58
-rw-r--r--src/kernel/blockmanager_opts.h12
-rw-r--r--src/kernel/chainparams.cpp10
-rw-r--r--src/kernel/chainparams.h9
-rw-r--r--src/kernel/coinstats.cpp2
-rw-r--r--src/net_processing.cpp50
-rw-r--r--src/netbase.cpp14
-rw-r--r--src/node/blockmanager_args.cpp9
-rw-r--r--src/node/blockstorage.cpp103
-rw-r--r--src/node/blockstorage.h56
-rw-r--r--src/node/chainstate.cpp2
-rw-r--r--src/node/interfaces.cpp24
-rw-r--r--src/node/mempool_args.cpp2
-rw-r--r--src/node/transaction.cpp4
-rw-r--r--src/node/transaction.h4
-rw-r--r--src/qt/bitcoin.cpp2
-rw-r--r--src/qt/clientmodel.cpp10
-rw-r--r--src/qt/coincontroldialog.cpp3
-rw-r--r--src/qt/guiutil.cpp25
-rw-r--r--src/qt/intro.cpp3
-rw-r--r--src/qt/networkstyle.cpp16
-rw-r--r--src/qt/networkstyle.h4
-rw-r--r--src/qt/rpcconsole.cpp8
-rw-r--r--src/qt/test/apptests.cpp2
-rw-r--r--src/qt/test/test_main.cpp3
-rw-r--r--src/rest.cpp5
-rw-r--r--src/rpc/blockchain.cpp10
-rw-r--r--src/rpc/external_signer.cpp3
-rw-r--r--src/rpc/mempool.cpp2
-rw-r--r--src/rpc/mining.cpp10
-rw-r--r--src/rpc/net.cpp13
-rw-r--r--src/rpc/rawtransaction.cpp6
-rw-r--r--src/rpc/rawtransaction_util.cpp12
-rw-r--r--src/rpc/request.cpp6
-rw-r--r--src/rpc/txoutproof.cpp5
-rw-r--r--src/rpc/util.cpp10
-rw-r--r--src/script/descriptor.cpp83
-rw-r--r--src/streams.h20
-rw-r--r--src/test/argsman_tests.cpp45
-rw-r--r--src/test/blockfilter_index_tests.cpp23
-rw-r--r--src/test/blockmanager_tests.cpp22
-rw-r--r--src/test/checkqueue_tests.cpp5
-rw-r--r--src/test/descriptor_tests.cpp74
-rw-r--r--src/test/fuzz/addrman.cpp3
-rw-r--r--src/test/fuzz/block.cpp3
-rw-r--r--src/test/fuzz/buffered_file.cpp2
-rw-r--r--src/test/fuzz/coins_view.cpp1
-rw-r--r--src/test/fuzz/connman.cpp1
-rw-r--r--src/test/fuzz/descriptor_parse.cpp3
-rw-r--r--src/test/fuzz/headerssync.cpp3
-rw-r--r--src/test/fuzz/integer.cpp3
-rw-r--r--src/test/fuzz/key.cpp4
-rw-r--r--src/test/fuzz/key_io.cpp3
-rw-r--r--src/test/fuzz/message.cpp3
-rw-r--r--src/test/fuzz/net.cpp4
-rw-r--r--src/test/fuzz/p2p_transport_serialization.cpp3
-rw-r--r--src/test/fuzz/parse_hd_keypath.cpp2
-rw-r--r--src/test/fuzz/parse_univalue.cpp3
-rw-r--r--src/test/fuzz/pow.cpp3
-rw-r--r--src/test/fuzz/process_message.cpp3
-rw-r--r--src/test/fuzz/process_messages.cpp2
-rw-r--r--src/test/fuzz/rpc.cpp5
-rw-r--r--src/test/fuzz/script.cpp3
-rw-r--r--src/test/fuzz/script_format.cpp3
-rw-r--r--src/test/fuzz/script_sigcache.cpp1
-rw-r--r--src/test/fuzz/script_sign.cpp4
-rw-r--r--src/test/fuzz/signet.cpp3
-rw-r--r--src/test/fuzz/socks5.cpp8
-rw-r--r--src/test/fuzz/system.cpp2
-rw-r--r--src/test/fuzz/transaction.cpp3
-rw-r--r--src/test/fuzz/tx_pool.cpp4
-rw-r--r--src/test/fuzz/util.h1
-rw-r--r--src/test/fuzz/utxo_snapshot.cpp3
-rw-r--r--src/test/fuzz/utxo_total_supply.cpp166
-rw-r--r--src/test/fuzz/validation_load_mempool.cpp1
-rw-r--r--src/test/fuzz/versionbits.cpp3
-rw-r--r--src/test/interfaces_tests.cpp2
-rw-r--r--src/test/key_io_tests.cpp21
-rw-r--r--src/test/pow_tests.cpp33
-rw-r--r--src/test/rpc_tests.cpp42
-rw-r--r--src/test/settings_tests.cpp8
-rw-r--r--src/test/streams_tests.cpp2
-rw-r--r--src/test/system_tests.cpp4
-rw-r--r--src/test/txindex_tests.cpp6
-rw-r--r--src/test/txvalidationcache_tests.cpp3
-rw-r--r--src/test/util/blockfilter.cpp9
-rw-r--r--src/test/util/blockfilter.h6
-rw-r--r--src/test/util/mining.cpp48
-rw-r--r--src/test/util/mining.h12
-rw-r--r--src/test/util/setup_common.cpp30
-rw-r--r--src/test/util/setup_common.h26
-rw-r--r--src/test/validation_chainstatemanager_tests.cpp7
-rw-r--r--src/test/validation_tests.cpp9
-rw-r--r--src/test/versionbits_tests.cpp9
-rw-r--r--src/txmempool.cpp11
-rw-r--r--src/univalue/include/univalue.h4
-rw-r--r--src/univalue/lib/univalue.cpp11
-rw-r--r--src/util/bip32.cpp8
-rw-r--r--src/util/bip32.h4
-rw-r--r--src/util/chaintype.cpp39
-rw-r--r--src/util/chaintype.h22
-rw-r--r--src/util/settings.cpp8
-rw-r--r--src/util/settings.h6
-rw-r--r--src/util/time.cpp13
-rw-r--r--src/util/time.h3
-rw-r--r--src/validation.cpp53
-rw-r--r--src/wallet/coincontrol.cpp68
-rw-r--r--src/wallet/coincontrol.h124
-rw-r--r--src/wallet/external_signer_scriptpubkeyman.cpp2
-rw-r--r--src/wallet/rpc/addresses.cpp4
-rw-r--r--src/wallet/rpc/backup.cpp2
-rw-r--r--src/wallet/rpc/coins.cpp5
-rw-r--r--src/wallet/rpc/spend.cpp4
-rw-r--r--src/wallet/rpc/transactions.cpp2
-rw-r--r--src/wallet/rpc/util.cpp10
-rw-r--r--src/wallet/rpc/util.h10
-rw-r--r--src/wallet/rpc/wallet.cpp5
-rw-r--r--src/wallet/scriptpubkeyman.cpp18
-rw-r--r--src/wallet/spend.cpp21
-rw-r--r--src/wallet/test/init_test_fixture.cpp3
-rw-r--r--src/wallet/test/init_test_fixture.h3
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp5
-rw-r--r--src/wallet/test/wallet_test_fixture.h3
-rw-r--r--src/wallet/test/wallet_tests.cpp7
-rw-r--r--src/wallet/wallet.cpp20
-rw-r--r--src/wallet/wallet.h6
-rw-r--r--src/zmq/zmqabstractnotifier.h3
-rw-r--r--src/zmq/zmqnotificationinterface.cpp10
-rw-r--r--src/zmq/zmqnotificationinterface.h5
-rw-r--r--src/zmq/zmqpublishnotifier.cpp5
-rw-r--r--src/zmq/zmqpublishnotifier.h7
166 files changed, 1396 insertions, 830 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index d12edca64e..9e1fab869d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -280,6 +280,7 @@ BITCOIN_CORE_H = \
util/bip32.h \
util/bitdeque.h \
util/bytevectorhash.h \
+ util/chaintype.h \
util/check.h \
util/epochguard.h \
util/error.h \
@@ -707,6 +708,7 @@ libbitcoin_util_a_SOURCES = \
util/asmap.cpp \
util/bip32.cpp \
util/bytevectorhash.cpp \
+ util/chaintype.cpp \
util/check.cpp \
util/error.cpp \
util/exception.cpp \
@@ -956,6 +958,7 @@ libbitcoinkernel_la_SOURCES = \
txdb.cpp \
txmempool.cpp \
uint256.cpp \
+ util/chaintype.cpp \
util/check.cpp \
util/exception.cpp \
util/fs.cpp \
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index c230728a1c..c8e510b482 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -47,6 +47,7 @@ bench_bench_bitcoin_SOURCES = \
bench/rollingbloom.cpp \
bench/rpc_blockchain.cpp \
bench/rpc_mempool.cpp \
+ bench/streams_findbyte.cpp \
bench/strencodings.cpp \
bench/util_time.cpp \
bench/verify_script.cpp
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 69965ed1b8..461022bbfc 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -344,6 +344,7 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/txorphan.cpp \
test/fuzz/txrequest.cpp \
test/fuzz/utxo_snapshot.cpp \
+ test/fuzz/utxo_total_supply.cpp \
test/fuzz/validation_load_mempool.cpp \
test/fuzz/versionbits.cpp
endif # ENABLE_FUZZ_BINARY
diff --git a/src/attributes.h b/src/attributes.h
index 9957bcd84b..a4603b0270 100644
--- a/src/attributes.h
+++ b/src/attributes.h
@@ -16,4 +16,12 @@
# define LIFETIMEBOUND
#endif
+#if defined(__GNUC__)
+# define ALWAYS_INLINE inline __attribute__((always_inline))
+#elif defined(_MSC_VER)
+# define ALWAYS_INLINE __forceinline
+#else
+# error No known always_inline attribute for this platform.
+#endif
+
#endif // BITCOIN_ATTRIBUTES_H
diff --git a/src/bench/block_assemble.cpp b/src/bench/block_assemble.cpp
index 8dd4117a3e..4d032cefc5 100644
--- a/src/bench/block_assemble.cpp
+++ b/src/bench/block_assemble.cpp
@@ -27,7 +27,7 @@ static void AssembleBlock(benchmark::Bench& bench)
std::array<CTransactionRef, NUM_BLOCKS - COINBASE_MATURITY + 1> txs;
for (size_t b{0}; b < NUM_BLOCKS; ++b) {
CMutableTransaction tx;
- tx.vin.push_back(MineBlock(test_setup->m_node, P2WSH_OP_TRUE));
+ tx.vin.push_back(CTxIn{MineBlock(test_setup->m_node, P2WSH_OP_TRUE)});
tx.vin.back().scriptWitness = witness;
tx.vout.emplace_back(1337, P2WSH_OP_TRUE);
if (NUM_BLOCKS - b >= COINBASE_MATURITY)
diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp
index 260c8991ce..269ac847a5 100644
--- a/src/bench/checkblock.cpp
+++ b/src/bench/checkblock.cpp
@@ -9,6 +9,7 @@
#include <common/args.h>
#include <consensus/validation.h>
#include <streams.h>
+#include <util/chaintype.h>
#include <validation.h>
// These are the two major time-sinks which happen after we have fully received
@@ -36,7 +37,7 @@ static void DeserializeAndCheckBlockTest(benchmark::Bench& bench)
stream.write({&a, 1}); // Prevent compaction
ArgsManager bench_args;
- const auto chainParams = CreateChainParams(bench_args, CBaseChainParams::MAIN);
+ const auto chainParams = CreateChainParams(bench_args, ChainType::MAIN);
bench.unit("block").run([&] {
CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here
diff --git a/src/bench/load_external.cpp b/src/bench/load_external.cpp
index 0fd842c7c3..2ff72a3012 100644
--- a/src/bench/load_external.cpp
+++ b/src/bench/load_external.cpp
@@ -6,6 +6,7 @@
#include <bench/data.h>
#include <chainparams.h>
#include <test/util/setup_common.h>
+#include <util/chaintype.h>
#include <validation.h>
/**
@@ -22,7 +23,7 @@
*/
static void LoadExternalBlockFile(benchmark::Bench& bench)
{
- const auto testing_setup{MakeNoLogFileContext<const TestingSetup>(CBaseChainParams::MAIN)};
+ const auto testing_setup{MakeNoLogFileContext<const TestingSetup>(ChainType::MAIN)};
// Create a single block as in the blocks files (magic bytes, block size,
// block data) as a stream object.
diff --git a/src/bench/logging.cpp b/src/bench/logging.cpp
index 9aedb26236..c97c4e151b 100644
--- a/src/bench/logging.cpp
+++ b/src/bench/logging.cpp
@@ -5,6 +5,7 @@
#include <bench/bench.h>
#include <logging.h>
#include <test/util/setup_common.h>
+#include <util/chaintype.h>
// All but 2 of the benchmarks should have roughly similar performance:
//
@@ -18,7 +19,7 @@ static void Logging(benchmark::Bench& bench, const std::vector<const char*>& ext
LogInstance().DisableCategory(BCLog::LogFlags::ALL);
TestingSetup test_setup{
- CBaseChainParams::REGTEST,
+ ChainType::REGTEST,
extra_args,
};
diff --git a/src/bench/mempool_stress.cpp b/src/bench/mempool_stress.cpp
index 80c959cdfb..826da73800 100644
--- a/src/bench/mempool_stress.cpp
+++ b/src/bench/mempool_stress.cpp
@@ -7,6 +7,7 @@
#include <policy/policy.h>
#include <test/util/setup_common.h>
#include <txmempool.h>
+#include <util/chaintype.h>
#include <validation.h>
#include <vector>
@@ -88,7 +89,7 @@ static void ComplexMemPool(benchmark::Bench& bench)
childTxs = static_cast<int>(bench.complexityN());
}
std::vector<CTransactionRef> ordered_coins = CreateOrderedCoins(det_rand, childTxs, /*min_ancestors=*/1);
- const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(CBaseChainParams::MAIN);
+ const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(ChainType::MAIN);
CTxMemPool& pool = *testing_setup.get()->m_node.mempool;
LOCK2(cs_main, pool.cs);
bench.run([&]() NO_THREAD_SAFETY_ANALYSIS {
@@ -103,7 +104,7 @@ static void ComplexMemPool(benchmark::Bench& bench)
static void MempoolCheck(benchmark::Bench& bench)
{
FastRandomContext det_rand{true};
- auto testing_setup = MakeNoLogFileContext<TestChain100Setup>(CBaseChainParams::REGTEST, {"-checkmempool=1"});
+ auto testing_setup = MakeNoLogFileContext<TestChain100Setup>(ChainType::REGTEST, {"-checkmempool=1"});
CTxMemPool& pool = *testing_setup.get()->m_node.mempool;
LOCK2(cs_main, pool.cs);
testing_setup->PopulateMempool(det_rand, 400, true);
diff --git a/src/bench/rpc_blockchain.cpp b/src/bench/rpc_blockchain.cpp
index f68b6acb5b..a9b197b190 100644
--- a/src/bench/rpc_blockchain.cpp
+++ b/src/bench/rpc_blockchain.cpp
@@ -8,6 +8,7 @@
#include <rpc/blockchain.h>
#include <streams.h>
#include <test/util/setup_common.h>
+#include <util/chaintype.h>
#include <validation.h>
#include <univalue.h>
@@ -15,7 +16,7 @@
namespace {
struct TestBlockAndIndex {
- const std::unique_ptr<const TestingSetup> testing_setup{MakeNoLogFileContext<const TestingSetup>(CBaseChainParams::MAIN)};
+ const std::unique_ptr<const TestingSetup> testing_setup{MakeNoLogFileContext<const TestingSetup>(ChainType::MAIN)};
CBlock block{};
uint256 blockHash{};
CBlockIndex blockindex{};
diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp
index e3e1a07c83..7e274370e0 100644
--- a/src/bench/rpc_mempool.cpp
+++ b/src/bench/rpc_mempool.cpp
@@ -3,12 +3,12 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <bench/bench.h>
-#include <chainparamsbase.h>
#include <kernel/cs_main.h>
#include <kernel/mempool_entry.h>
#include <rpc/mempool.h>
#include <test/util/setup_common.h>
#include <txmempool.h>
+#include <util/chaintype.h>
#include <univalue.h>
@@ -21,7 +21,7 @@ static void AddTx(const CTransactionRef& tx, const CAmount& fee, CTxMemPool& poo
static void RpcMempool(benchmark::Bench& bench)
{
- const auto testing_setup = MakeNoLogFileContext<const ChainTestingSetup>(CBaseChainParams::MAIN);
+ const auto testing_setup = MakeNoLogFileContext<const ChainTestingSetup>(ChainType::MAIN);
CTxMemPool& pool = *Assert(testing_setup->m_node.mempool);
LOCK2(cs_main, pool.cs);
diff --git a/src/bench/streams_findbyte.cpp b/src/bench/streams_findbyte.cpp
new file mode 100644
index 0000000000..77f5940926
--- /dev/null
+++ b/src/bench/streams_findbyte.cpp
@@ -0,0 +1,31 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <bench/bench.h>
+
+#include <util/fs.h>
+#include <streams.h>
+
+static void FindByte(benchmark::Bench& bench)
+{
+ // Setup
+ FILE* file = fsbridge::fopen("streams_tmp", "w+b");
+ const size_t file_size = 200;
+ uint8_t data[file_size] = {0};
+ data[file_size-1] = 1;
+ fwrite(&data, sizeof(uint8_t), file_size, file);
+ rewind(file);
+ CBufferedFile bf(file, /*nBufSize=*/file_size + 1, /*nRewindIn=*/file_size, 0, 0);
+
+ bench.run([&] {
+ bf.SetPos(0);
+ bf.FindByte(std::byte(1));
+ });
+
+ // Cleanup
+ bf.fclose();
+ fs::remove("streams_tmp");
+}
+
+BENCHMARK(FindByte, benchmark::PriorityLevel::HIGH);
diff --git a/src/bench/util_time.cpp b/src/bench/util_time.cpp
index 8dbbdec28c..4cbc0dfbbd 100644
--- a/src/bench/util_time.cpp
+++ b/src/bench/util_time.cpp
@@ -32,7 +32,7 @@ static void BenchTimeMillis(benchmark::Bench& bench)
static void BenchTimeMillisSys(benchmark::Bench& bench)
{
bench.run([&] {
- (void)GetTimeMillis();
+ (void)TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now());
});
}
diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp
index 04f6aae4f7..16c3bfb708 100644
--- a/src/bitcoin-chainstate.cpp
+++ b/src/bitcoin-chainstate.cpp
@@ -25,6 +25,7 @@
#include <node/chainstate.h>
#include <scheduler.h>
#include <script/sigcache.h>
+#include <util/chaintype.h>
#include <util/thread.h>
#include <validation.h>
#include <validationinterface.h>
@@ -52,7 +53,7 @@ int main(int argc, char* argv[])
// SETUP: Misc Globals
- SelectParams(CBaseChainParams::MAIN);
+ SelectParams(ChainType::MAIN);
auto chainparams = CChainParams::Main();
kernel::Context kernel_context{};
@@ -86,7 +87,11 @@ int main(int argc, char* argv[])
.datadir = gArgs.GetDataDirNet(),
.adjusted_time_callback = NodeClock::now,
};
- ChainstateManager chainman{chainman_opts, {}};
+ const node::BlockManager::Options blockman_opts{
+ .chainparams = chainman_opts.chainparams,
+ .blocks_dir = gArgs.GetBlocksDirPath(),
+ };
+ ChainstateManager chainman{chainman_opts, blockman_opts};
node::CacheSizes cache_sizes;
cache_sizes.block_tree_db = 2 << 20;
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 63ba6a935d..48dc11b95a 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -20,6 +20,7 @@
#include <rpc/request.h>
#include <tinyformat.h>
#include <univalue.h>
+#include <util/chaintype.h>
#include <util/exception.h>
#include <util/strencodings.h>
#include <util/system.h>
@@ -73,10 +74,10 @@ static void SetupCliArgs(ArgsManager& argsman)
{
SetupHelpOptions(argsman);
- const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
- const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
- const auto signetBaseParams = CreateBaseChainParams(CBaseChainParams::SIGNET);
- const auto regtestBaseParams = CreateBaseChainParams(CBaseChainParams::REGTEST);
+ const auto defaultBaseParams = CreateBaseChainParams(ChainType::MAIN);
+ const auto testnetBaseParams = CreateBaseChainParams(ChainType::TESTNET);
+ const auto signetBaseParams = CreateBaseChainParams(ChainType::SIGNET);
+ const auto regtestBaseParams = CreateBaseChainParams(ChainType::REGTEST);
argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-conf=<file>", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@@ -174,7 +175,7 @@ static int AppInitRPC(int argc, char* argv[])
}
// Check for chain settings (BaseParams() calls are only valid after this clause)
try {
- SelectBaseParams(gArgs.GetChainName());
+ SelectBaseParams(gArgs.GetChainType());
} catch (const std::exception& e) {
tfm::format(std::cerr, "Error: %s\n", e.what());
return EXIT_FAILURE;
@@ -426,10 +427,17 @@ private:
std::vector<Peer> m_peers;
std::string ChainToString() const
{
- if (gArgs.GetChainName() == CBaseChainParams::TESTNET) return " testnet";
- if (gArgs.GetChainName() == CBaseChainParams::SIGNET) return " signet";
- if (gArgs.GetChainName() == CBaseChainParams::REGTEST) return " regtest";
- return "";
+ switch (gArgs.GetChainType()) {
+ case ChainType::TESTNET:
+ return " testnet";
+ case ChainType::SIGNET:
+ return " signet";
+ case ChainType::REGTEST:
+ return " regtest";
+ case ChainType::MAIN:
+ return "";
+ }
+ assert(false);
}
std::string PingTimeToString(double seconds) const
{
@@ -863,7 +871,7 @@ static UniValue ConnectAndCallRPC(BaseRequestHandler* rh, const std::string& str
try {
response = CallRPC(rh, strMethod, args, rpcwallet);
if (fWait) {
- const UniValue& error = find_value(response, "error");
+ const UniValue& error = response.find_value("error");
if (!error.isNull() && error["code"].getInt<int>() == RPC_IN_WARMUP) {
throw CConnectionFailed("server in warmup");
}
@@ -891,8 +899,8 @@ static void ParseResult(const UniValue& result, std::string& strPrint)
static void ParseError(const UniValue& error, std::string& strPrint, int& nRet)
{
if (error.isObject()) {
- const UniValue& err_code = find_value(error, "code");
- const UniValue& err_msg = find_value(error, "message");
+ const UniValue& err_code = error.find_value("code");
+ const UniValue& err_msg = error.find_value("message");
if (!err_code.isNull()) {
strPrint = "error code: " + err_code.getValStr() + "\n";
}
@@ -918,15 +926,15 @@ static void GetWalletBalances(UniValue& result)
{
DefaultRequestHandler rh;
const UniValue listwallets = ConnectAndCallRPC(&rh, "listwallets", /* args=*/{});
- if (!find_value(listwallets, "error").isNull()) return;
- const UniValue& wallets = find_value(listwallets, "result");
+ if (!listwallets.find_value("error").isNull()) return;
+ const UniValue& wallets = listwallets.find_value("result");
if (wallets.size() <= 1) return;
UniValue balances(UniValue::VOBJ);
for (const UniValue& wallet : wallets.getValues()) {
const std::string& wallet_name = wallet.get_str();
const UniValue getbalances = ConnectAndCallRPC(&rh, "getbalances", /* args=*/{}, wallet_name);
- const UniValue& balance = find_value(getbalances, "result")["mine"]["trusted"];
+ const UniValue& balance = getbalances.find_value("result")["mine"]["trusted"];
balances.pushKV(wallet_name, balance);
}
result.pushKV("balances", balances);
@@ -962,7 +970,7 @@ static void GetProgressBar(double progress, std::string& progress_bar)
*/
static void ParseGetInfoResult(UniValue& result)
{
- if (!find_value(result, "error").isNull()) return;
+ if (!result.find_value("error").isNull()) return;
std::string RESET, GREEN, BLUE, YELLOW, MAGENTA, CYAN;
bool should_colorize = false;
@@ -1174,9 +1182,9 @@ static int CommandLineRPC(int argc, char *argv[])
rh.reset(new NetinfoRequestHandler());
} else if (gArgs.GetBoolArg("-generate", false)) {
const UniValue getnewaddress{GetNewAddress()};
- const UniValue& error{find_value(getnewaddress, "error")};
+ const UniValue& error{getnewaddress.find_value("error")};
if (error.isNull()) {
- SetGenerateToAddressArgs(find_value(getnewaddress, "result").get_str(), args);
+ SetGenerateToAddressArgs(getnewaddress.find_value("result").get_str(), args);
rh.reset(new GenerateToAddressRequestHandler());
} else {
ParseError(error, strPrint, nRet);
@@ -1198,8 +1206,8 @@ static int CommandLineRPC(int argc, char *argv[])
const UniValue reply = ConnectAndCallRPC(rh.get(), method, args, wallet_name);
// Parse reply
- UniValue result = find_value(reply, "result");
- const UniValue& error = find_value(reply, "error");
+ UniValue result = reply.find_value("result");
+ const UniValue& error = reply.find_value("error");
if (error.isNull()) {
if (gArgs.GetBoolArg("-getinfo", false)) {
if (!gArgs.IsArgSet("-rpcwallet")) {
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index c35a111313..e291f20a11 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -6,6 +6,7 @@
#include <config/bitcoin-config.h>
#endif
+#include <chainparamsbase.h>
#include <clientversion.h>
#include <coins.h>
#include <common/args.h>
@@ -91,7 +92,7 @@ static int AppInitRawTx(int argc, char* argv[])
// Check for chain settings (Params() calls are only valid after this clause)
try {
- SelectParams(gArgs.GetChainName());
+ SelectParams(gArgs.GetChainType());
} catch (const std::exception& e) {
tfm::format(std::cerr, "Error: %s\n", e.what());
return EXIT_FAILURE;
diff --git a/src/bitcoin-util.cpp b/src/bitcoin-util.cpp
index e3f70e1b76..f62a9f7bbf 100644
--- a/src/bitcoin-util.cpp
+++ b/src/bitcoin-util.cpp
@@ -75,7 +75,7 @@ static int AppInitUtil(ArgsManager& args, int argc, char* argv[])
// Check for chain settings (Params() calls are only valid after this clause)
try {
- SelectParams(args.GetChainName());
+ SelectParams(args.GetChainType());
} catch (const std::exception& e) {
tfm::format(std::cerr, "Error: %s\n", e.what());
return EXIT_FAILURE;
diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp
index 5dbf8a8616..1863173aa8 100644
--- a/src/bitcoin-wallet.cpp
+++ b/src/bitcoin-wallet.cpp
@@ -91,7 +91,7 @@ static std::optional<int> WalletAppInit(ArgsManager& args, int argc, char* argv[
return EXIT_FAILURE;
}
// Check for chain settings (Params() calls are only valid after this clause)
- SelectParams(args.GetChainName());
+ SelectParams(args.GetChainType());
return std::nullopt;
}
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index d3d358a3f0..6f4453d1fe 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -5,6 +5,7 @@
#include <chainparams.h>
+#include <chainparamsbase.h>
#include <chainparamsseeds.h>
#include <common/args.h>
#include <consensus/merkle.h>
@@ -12,6 +13,7 @@
#include <hash.h> // for signet block challenge hash
#include <logging.h>
#include <script/interpreter.h>
+#include <util/chaintype.h>
#include <util/string.h>
#include <assert.h>
@@ -97,26 +99,29 @@ const CChainParams &Params() {
return *globalChainParams;
}
-std::unique_ptr<const CChainParams> CreateChainParams(const ArgsManager& args, const std::string& chain)
+std::unique_ptr<const CChainParams> CreateChainParams(const ArgsManager& args, const ChainType chain)
{
- if (chain == CBaseChainParams::MAIN) {
+ switch (chain) {
+ case ChainType::MAIN:
return CChainParams::Main();
- } else if (chain == CBaseChainParams::TESTNET) {
+ case ChainType::TESTNET:
return CChainParams::TestNet();
- } else if (chain == CBaseChainParams::SIGNET) {
+ case ChainType::SIGNET: {
auto opts = CChainParams::SigNetOptions{};
ReadSigNetArgs(args, opts);
return CChainParams::SigNet(opts);
- } else if (chain == CBaseChainParams::REGTEST) {
+ }
+ case ChainType::REGTEST: {
auto opts = CChainParams::RegTestOptions{};
ReadRegTestArgs(args, opts);
return CChainParams::RegTest(opts);
}
- throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
+ }
+ assert(false);
}
-void SelectParams(const std::string& network)
+void SelectParams(const ChainType chain)
{
- SelectBaseParams(network);
- globalChainParams = CreateChainParams(gArgs, network);
+ SelectBaseParams(chain);
+ globalChainParams = CreateChainParams(gArgs, chain);
}
diff --git a/src/chainparams.h b/src/chainparams.h
index cb34d068e1..1e8366dcf5 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -8,11 +8,11 @@
#include <kernel/chainparams.h>
-#include <chainparamsbase.h>
#include <consensus/params.h>
#include <netaddress.h>
#include <primitives/block.h>
#include <protocol.h>
+#include <util/chaintype.h>
#include <util/hash_type.h>
#include <cstdint>
@@ -21,12 +21,12 @@
#include <unordered_map>
#include <vector>
+class ArgsManager;
+
/**
* Creates and returns a std::unique_ptr<CChainParams> of the chosen chain.
- * @returns a CChainParams* of the chosen chain.
- * @throws a std::runtime_error if the chain is not supported.
*/
-std::unique_ptr<const CChainParams> CreateChainParams(const ArgsManager& args, const std::string& chain);
+std::unique_ptr<const CChainParams> CreateChainParams(const ArgsManager& args, const ChainType chain);
/**
* Return the currently selected parameters. This won't change after app
@@ -35,9 +35,8 @@ std::unique_ptr<const CChainParams> CreateChainParams(const ArgsManager& args, c
const CChainParams &Params();
/**
- * Sets the params returned by Params() to those for the given chain name.
- * @throws std::runtime_error when the chain is not supported.
+ * Sets the params returned by Params() to those for the given chain type.
*/
-void SelectParams(const std::string& chain);
+void SelectParams(const ChainType chain);
#endif // BITCOIN_CHAINPARAMS_H
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index eb7b31923d..8cbf9e85e0 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -7,14 +7,10 @@
#include <common/args.h>
#include <tinyformat.h>
+#include <util/chaintype.h>
#include <assert.h>
-const std::string CBaseChainParams::MAIN = "main";
-const std::string CBaseChainParams::TESTNET = "test";
-const std::string CBaseChainParams::SIGNET = "signet";
-const std::string CBaseChainParams::REGTEST = "regtest";
-
void SetupChainParamsBaseOptions(ArgsManager& argsman)
{
argsman.AddArg("-chain=<chain>", "Use the chain <chain> (default: main). Allowed values: main, test, signet, regtest", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
@@ -40,22 +36,23 @@ const CBaseChainParams& BaseParams()
* Port numbers for incoming Tor connections (8334, 18334, 38334, 18445) have
* been chosen arbitrarily to keep ranges of used ports tight.
*/
-std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain)
+std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const ChainType chain)
{
- if (chain == CBaseChainParams::MAIN) {
+ switch (chain) {
+ case ChainType::MAIN:
return std::make_unique<CBaseChainParams>("", 8332, 8334);
- } else if (chain == CBaseChainParams::TESTNET) {
+ case ChainType::TESTNET:
return std::make_unique<CBaseChainParams>("testnet3", 18332, 18334);
- } else if (chain == CBaseChainParams::SIGNET) {
+ case ChainType::SIGNET:
return std::make_unique<CBaseChainParams>("signet", 38332, 38334);
- } else if (chain == CBaseChainParams::REGTEST) {
+ case ChainType::REGTEST:
return std::make_unique<CBaseChainParams>("regtest", 18443, 18445);
}
- throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
+ assert(false);
}
-void SelectBaseParams(const std::string& chain)
+void SelectBaseParams(const ChainType chain)
{
globalChainBaseParams = CreateBaseChainParams(chain);
- gArgs.SelectConfigNetwork(chain);
+ gArgs.SelectConfigNetwork(ChainTypeToString(chain));
}
diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h
index d593cff722..ea933d1ca8 100644
--- a/src/chainparamsbase.h
+++ b/src/chainparamsbase.h
@@ -5,6 +5,8 @@
#ifndef BITCOIN_CHAINPARAMSBASE_H
#define BITCOIN_CHAINPARAMSBASE_H
+#include <util/chaintype.h>
+
#include <memory>
#include <string>
@@ -17,14 +19,6 @@ class ArgsManager;
class CBaseChainParams
{
public:
- ///@{
- /** Chain name strings */
- static const std::string MAIN;
- static const std::string TESTNET;
- static const std::string SIGNET;
- static const std::string REGTEST;
- ///@}
-
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; }
@@ -41,10 +35,8 @@ private:
/**
* Creates and returns a std::unique_ptr<CBaseChainParams> of the chosen chain.
- * @returns a CBaseChainParams* of the chosen chain.
- * @throws a std::runtime_error if the chain is not supported.
*/
-std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain);
+std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const ChainType chain);
/**
*Set the arguments for chainparams
@@ -57,7 +49,7 @@ void SetupChainParamsBaseOptions(ArgsManager& argsman);
*/
const CBaseChainParams& BaseParams();
-/** Sets the params returned by Params() to those for the given network. */
-void SelectBaseParams(const std::string& chain);
+/** Sets the params returned by Params() to those for the given chain. */
+void SelectBaseParams(const ChainType chain);
#endif // BITCOIN_CHAINPARAMSBASE_H
diff --git a/src/common/args.cpp b/src/common/args.cpp
index d29b8648bf..93f2005931 100644
--- a/src/common/args.cpp
+++ b/src/common/args.cpp
@@ -10,6 +10,7 @@
#include <sync.h>
#include <tinyformat.h>
#include <univalue.h>
+#include <util/chaintype.h>
#include <util/check.h>
#include <util/fs.h>
#include <util/fs_helpers.h>
@@ -33,6 +34,7 @@
#include <stdexcept>
#include <string>
#include <utility>
+#include <variant>
const char * const BITCOIN_CONF_FILENAME = "bitcoin.conf";
const char * const BITCOIN_SETTINGS_FILENAME = "settings.json";
@@ -141,7 +143,7 @@ std::set<std::string> ArgsManager::GetUnsuitableSectionOnlyArgs() const
if (m_network.empty()) return std::set<std::string> {};
// if it's okay to use the default section for this network, don't worry
- if (m_network == CBaseChainParams::MAIN) return std::set<std::string> {};
+ if (m_network == ChainTypeToString(ChainType::MAIN)) return std::set<std::string> {};
for (const auto& arg : m_network_only_args) {
if (OnlyHasDefaultSectionSetting(m_settings, m_network, SettingName(arg))) {
@@ -155,10 +157,10 @@ std::list<SectionInfo> ArgsManager::GetUnrecognizedSections() const
{
// Section names to be recognized in the config file.
static const std::set<std::string> available_sections{
- CBaseChainParams::REGTEST,
- CBaseChainParams::SIGNET,
- CBaseChainParams::TESTNET,
- CBaseChainParams::MAIN
+ ChainTypeToString(ChainType::REGTEST),
+ ChainTypeToString(ChainType::SIGNET),
+ ChainTypeToString(ChainType::TESTNET),
+ ChainTypeToString(ChainType::MAIN),
};
LOCK(cs_args);
@@ -443,7 +445,7 @@ util::SettingsValue ArgsManager::GetPersistentSetting(const std::string& name) c
{
LOCK(cs_args);
return util::GetSetting(m_settings, m_network, name, !UseDefaultSection("-" + name),
- /*ignore_nonpersistent=*/true, /*get_chain_name=*/false);
+ /*ignore_nonpersistent=*/true, /*get_chain_type=*/false);
}
bool ArgsManager::IsArgNegated(const std::string& strArg) const
@@ -717,39 +719,53 @@ fs::path ArgsManager::GetConfigFilePath() const
return GetConfigFile(*this, GetPathArg("-conf", BITCOIN_CONF_FILENAME));
}
-std::string ArgsManager::GetChainName() const
+ChainType ArgsManager::GetChainType() const
+{
+ std::variant<ChainType, std::string> arg = GetChainArg();
+ if (auto* parsed = std::get_if<ChainType>(&arg)) return *parsed;
+ throw std::runtime_error(strprintf("Unknown chain %s.", std::get<std::string>(arg)));
+}
+
+std::string ArgsManager::GetChainTypeString() const
+{
+ auto arg = GetChainArg();
+ if (auto* parsed = std::get_if<ChainType>(&arg)) return ChainTypeToString(*parsed);
+ return std::get<std::string>(arg);
+}
+
+std::variant<ChainType, std::string> ArgsManager::GetChainArg() const
{
auto get_net = [&](const std::string& arg) {
LOCK(cs_args);
util::SettingsValue value = util::GetSetting(m_settings, /* section= */ "", SettingName(arg),
/* ignore_default_section_config= */ false,
/*ignore_nonpersistent=*/false,
- /* get_chain_name= */ true);
+ /* get_chain_type= */ true);
return value.isNull() ? false : value.isBool() ? value.get_bool() : InterpretBool(value.get_str());
};
const bool fRegTest = get_net("-regtest");
const bool fSigNet = get_net("-signet");
const bool fTestNet = get_net("-testnet");
- const bool is_chain_arg_set = IsArgSet("-chain");
+ const auto chain_arg = GetArg("-chain");
- if ((int)is_chain_arg_set + (int)fRegTest + (int)fSigNet + (int)fTestNet > 1) {
+ if ((int)chain_arg.has_value() + (int)fRegTest + (int)fSigNet + (int)fTestNet > 1) {
throw std::runtime_error("Invalid combination of -regtest, -signet, -testnet and -chain. Can use at most one.");
}
- if (fRegTest)
- return CBaseChainParams::REGTEST;
- if (fSigNet) {
- return CBaseChainParams::SIGNET;
+ if (chain_arg) {
+ if (auto parsed = ChainTypeFromString(*chain_arg)) return *parsed;
+ // Not a known string, so return original string
+ return *chain_arg;
}
- if (fTestNet)
- return CBaseChainParams::TESTNET;
-
- return GetArg("-chain", CBaseChainParams::MAIN);
+ if (fRegTest) return ChainType::REGTEST;
+ if (fSigNet) return ChainType::SIGNET;
+ if (fTestNet) return ChainType::TESTNET;
+ return ChainType::MAIN;
}
bool ArgsManager::UseDefaultSection(const std::string& arg) const
{
- return m_network == CBaseChainParams::MAIN || m_network_only_args.count(arg) == 0;
+ return m_network == ChainTypeToString(ChainType::MAIN) || m_network_only_args.count(arg) == 0;
}
util::SettingsValue ArgsManager::GetSetting(const std::string& arg) const
@@ -757,7 +773,7 @@ util::SettingsValue ArgsManager::GetSetting(const std::string& arg) const
LOCK(cs_args);
return util::GetSetting(
m_settings, m_network, SettingName(arg), !UseDefaultSection(arg),
- /*ignore_nonpersistent=*/false, /*get_chain_name=*/false);
+ /*ignore_nonpersistent=*/false, /*get_chain_type=*/false);
}
std::vector<util::SettingsValue> ArgsManager::GetSettingsList(const std::string& arg) const
diff --git a/src/common/args.h b/src/common/args.h
index 430c392e2b..537a64fcfd 100644
--- a/src/common/args.h
+++ b/src/common/args.h
@@ -7,6 +7,7 @@
#include <compat/compat.h>
#include <sync.h>
+#include <util/chaintype.h>
#include <util/fs.h>
#include <util/settings.h>
@@ -17,6 +18,7 @@
#include <set>
#include <stdint.h>
#include <string>
+#include <variant>
#include <vector>
class ArgsManager;
@@ -323,10 +325,18 @@ protected:
void ForceSetArg(const std::string& strArg, const std::string& strValue);
/**
- * Returns the appropriate chain name from the program arguments.
- * @return CBaseChainParams::MAIN by default; raises runtime error if an invalid combination is given.
+ * Returns the appropriate chain type from the program arguments.
+ * @return ChainType::MAIN by default; raises runtime error if an invalid
+ * combination, or unknown chain is given.
*/
- std::string GetChainName() const;
+ ChainType GetChainType() const;
+
+ /**
+ * Returns the appropriate chain type string from the program arguments.
+ * @return ChainType::MAIN string by default; raises runtime error if an
+ * invalid combination is given.
+ */
+ std::string GetChainTypeString() const;
/**
* Add argument
@@ -411,6 +421,14 @@ private:
*/
const fs::path& GetDataDir(bool net_specific) const;
+ /**
+ * Return -regtest/-signet/-testnet/-chain= setting as a ChainType enum if a
+ * recognized chain type was set, or as a string if an unrecognized chain
+ * name was set. Raise an exception if an invalid combination of flags was
+ * provided.
+ */
+ std::variant<ChainType, std::string> GetChainArg() const;
+
// Helper function for LogArgs().
void logArgsPrefix(
const std::string& prefix,
diff --git a/src/common/config.cpp b/src/common/config.cpp
index 747503ad2a..5efb5efb67 100644
--- a/src/common/config.cpp
+++ b/src/common/config.cpp
@@ -8,6 +8,7 @@
#include <sync.h>
#include <tinyformat.h>
#include <univalue.h>
+#include <util/chaintype.h>
#include <util/fs.h>
#include <util/settings.h>
#include <util/string.h>
@@ -152,7 +153,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
}
}
if (use_conf_file) {
- std::string chain_id = GetChainName();
+ std::string chain_id = GetChainTypeString();
std::vector<std::string> conf_file_names;
auto add_includes = [&](const std::string& network, size_t skip = 0) {
@@ -191,7 +192,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
conf_file_names.clear();
add_includes(chain_id, /* skip= */ chain_includes);
add_includes({}, /* skip= */ default_includes);
- std::string chain_id_final = GetChainName();
+ std::string chain_id_final = GetChainTypeString();
if (chain_id_final != chain_id) {
// Also warn about recursive includeconf for the chain that was specified in one of the includeconfs
add_includes(chain_id_final);
diff --git a/src/common/init.cpp b/src/common/init.cpp
index 6ffa44847a..8933d59c27 100644
--- a/src/common/init.cpp
+++ b/src/common/init.cpp
@@ -26,7 +26,7 @@ std::optional<ConfigError> InitConfig(ArgsManager& args, SettingsAbortFn setting
}
// Check for chain settings (Params() calls are only valid after this clause)
- SelectParams(args.GetChainName());
+ SelectParams(args.GetChainType());
// Create datadir if it does not exist.
const auto base_path{args.GetDataDirBase()};
diff --git a/src/crypto/sha256_avx2.cpp b/src/crypto/sha256_avx2.cpp
index 624bdb42e4..df8cb7a6c9 100644
--- a/src/crypto/sha256_avx2.cpp
+++ b/src/crypto/sha256_avx2.cpp
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <immintrin.h>
+#include <attributes.h>
#include <crypto/common.h>
namespace sha256d64_avx2 {
@@ -36,7 +37,7 @@ __m256i inline sigma0(__m256i x) { return Xor(Or(ShR(x, 7), ShL(x, 25)), Or(ShR(
__m256i inline sigma1(__m256i x) { return Xor(Or(ShR(x, 17), ShL(x, 15)), Or(ShR(x, 19), ShL(x, 13)), ShR(x, 10)); }
/** One round of SHA-256. */
-void inline __attribute__((always_inline)) Round(__m256i a, __m256i b, __m256i c, __m256i& d, __m256i e, __m256i f, __m256i g, __m256i& h, __m256i k)
+void ALWAYS_INLINE Round(__m256i a, __m256i b, __m256i c, __m256i& d, __m256i e, __m256i f, __m256i g, __m256i& h, __m256i k)
{
__m256i t1 = Add(h, Sigma1(e), Ch(e, f, g), k);
__m256i t2 = Add(Sigma0(a), Maj(a, b, c));
diff --git a/src/crypto/sha256_sse41.cpp b/src/crypto/sha256_sse41.cpp
index 4eaf7d7b18..d041fdfefc 100644
--- a/src/crypto/sha256_sse41.cpp
+++ b/src/crypto/sha256_sse41.cpp
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <immintrin.h>
+#include <attributes.h>
#include <crypto/common.h>
namespace sha256d64_sse41 {
@@ -36,7 +37,7 @@ __m128i inline sigma0(__m128i x) { return Xor(Or(ShR(x, 7), ShL(x, 25)), Or(ShR(
__m128i inline sigma1(__m128i x) { return Xor(Or(ShR(x, 17), ShL(x, 15)), Or(ShR(x, 19), ShL(x, 13)), ShR(x, 10)); }
/** One round of SHA-256. */
-void inline __attribute__((always_inline)) Round(__m128i a, __m128i b, __m128i c, __m128i& d, __m128i e, __m128i f, __m128i g, __m128i& h, __m128i k)
+void ALWAYS_INLINE Round(__m128i a, __m128i b, __m128i c, __m128i& d, __m128i e, __m128i f, __m128i g, __m128i& h, __m128i k)
{
__m128i t1 = Add(h, Sigma1(e), Ch(e, f, g), k);
__m128i t2 = Add(Sigma0(a), Maj(a, b, c));
diff --git a/src/crypto/sha256_x86_shani.cpp b/src/crypto/sha256_x86_shani.cpp
index e3143a55c2..79871bfcc1 100644
--- a/src/crypto/sha256_x86_shani.cpp
+++ b/src/crypto/sha256_x86_shani.cpp
@@ -11,43 +11,45 @@
#include <stdint.h>
#include <immintrin.h>
+#include <attributes.h>
+
namespace {
alignas(__m128i) const uint8_t MASK[16] = {0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04, 0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c};
alignas(__m128i) const uint8_t INIT0[16] = {0x8c, 0x68, 0x05, 0x9b, 0x7f, 0x52, 0x0e, 0x51, 0x85, 0xae, 0x67, 0xbb, 0x67, 0xe6, 0x09, 0x6a};
alignas(__m128i) const uint8_t INIT1[16] = {0x19, 0xcd, 0xe0, 0x5b, 0xab, 0xd9, 0x83, 0x1f, 0x3a, 0xf5, 0x4f, 0xa5, 0x72, 0xf3, 0x6e, 0x3c};
-void inline __attribute__((always_inline)) QuadRound(__m128i& state0, __m128i& state1, uint64_t k1, uint64_t k0)
+void ALWAYS_INLINE QuadRound(__m128i& state0, __m128i& state1, uint64_t k1, uint64_t k0)
{
const __m128i msg = _mm_set_epi64x(k1, k0);
state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
state0 = _mm_sha256rnds2_epu32(state0, state1, _mm_shuffle_epi32(msg, 0x0e));
}
-void inline __attribute__((always_inline)) QuadRound(__m128i& state0, __m128i& state1, __m128i m, uint64_t k1, uint64_t k0)
+void ALWAYS_INLINE QuadRound(__m128i& state0, __m128i& state1, __m128i m, uint64_t k1, uint64_t k0)
{
const __m128i msg = _mm_add_epi32(m, _mm_set_epi64x(k1, k0));
state1 = _mm_sha256rnds2_epu32(state1, state0, msg);
state0 = _mm_sha256rnds2_epu32(state0, state1, _mm_shuffle_epi32(msg, 0x0e));
}
-void inline __attribute__((always_inline)) ShiftMessageA(__m128i& m0, __m128i m1)
+void ALWAYS_INLINE ShiftMessageA(__m128i& m0, __m128i m1)
{
m0 = _mm_sha256msg1_epu32(m0, m1);
}
-void inline __attribute__((always_inline)) ShiftMessageC(__m128i& m0, __m128i m1, __m128i& m2)
+void ALWAYS_INLINE ShiftMessageC(__m128i& m0, __m128i m1, __m128i& m2)
{
m2 = _mm_sha256msg2_epu32(_mm_add_epi32(m2, _mm_alignr_epi8(m1, m0, 4)), m1);
}
-void inline __attribute__((always_inline)) ShiftMessageB(__m128i& m0, __m128i m1, __m128i& m2)
+void ALWAYS_INLINE ShiftMessageB(__m128i& m0, __m128i m1, __m128i& m2)
{
ShiftMessageC(m0, m1, m2);
ShiftMessageA(m0, m1);
}
-void inline __attribute__((always_inline)) Shuffle(__m128i& s0, __m128i& s1)
+void ALWAYS_INLINE Shuffle(__m128i& s0, __m128i& s1)
{
const __m128i t1 = _mm_shuffle_epi32(s0, 0xB1);
const __m128i t2 = _mm_shuffle_epi32(s1, 0x1B);
@@ -55,7 +57,7 @@ void inline __attribute__((always_inline)) Shuffle(__m128i& s0, __m128i& s1)
s1 = _mm_blend_epi16(t2, t1, 0xF0);
}
-void inline __attribute__((always_inline)) Unshuffle(__m128i& s0, __m128i& s1)
+void ALWAYS_INLINE Unshuffle(__m128i& s0, __m128i& s1)
{
const __m128i t1 = _mm_shuffle_epi32(s0, 0x1B);
const __m128i t2 = _mm_shuffle_epi32(s1, 0xB1);
@@ -63,12 +65,12 @@ void inline __attribute__((always_inline)) Unshuffle(__m128i& s0, __m128i& s1)
s1 = _mm_alignr_epi8(t2, t1, 0x08);
}
-__m128i inline __attribute__((always_inline)) Load(const unsigned char* in)
+__m128i ALWAYS_INLINE Load(const unsigned char* in)
{
return _mm_shuffle_epi8(_mm_loadu_si128((const __m128i*)in), _mm_load_si128((const __m128i*)MASK));
}
-void inline __attribute__((always_inline)) Save(unsigned char* out, __m128i s)
+void ALWAYS_INLINE Save(unsigned char* out, __m128i s)
{
_mm_storeu_si128((__m128i*)out, _mm_shuffle_epi8(s, _mm_load_si128((const __m128i*)MASK)));
}
diff --git a/src/external_signer.cpp b/src/external_signer.cpp
index 5524b943f4..6b1e1f0241 100644
--- a/src/external_signer.cpp
+++ b/src/external_signer.cpp
@@ -30,7 +30,7 @@ bool ExternalSigner::Enumerate(const std::string& command, std::vector<ExternalS
}
for (const UniValue& signer : result.getValues()) {
// Check for error
- const UniValue& error = find_value(signer, "error");
+ const UniValue& error = signer.find_value("error");
if (!error.isNull()) {
if (!error.isStr()) {
throw std::runtime_error(strprintf("'%s' error", command));
@@ -38,11 +38,11 @@ bool ExternalSigner::Enumerate(const std::string& command, std::vector<ExternalS
throw std::runtime_error(strprintf("'%s' error: %s", command, error.getValStr()));
}
// Check if fingerprint is present
- const UniValue& fingerprint = find_value(signer, "fingerprint");
+ const UniValue& fingerprint = signer.find_value("fingerprint");
if (fingerprint.isNull()) {
throw std::runtime_error(strprintf("'%s' received invalid response, missing signer fingerprint", command));
}
- const std::string fingerprintStr = fingerprint.get_str();
+ const std::string& fingerprintStr{fingerprint.get_str()};
// Skip duplicate signer
bool duplicate = false;
for (const ExternalSigner& signer : signers) {
@@ -50,7 +50,7 @@ bool ExternalSigner::Enumerate(const std::string& command, std::vector<ExternalS
}
if (duplicate) break;
std::string name;
- const UniValue& model_field = find_value(signer, "model");
+ const UniValue& model_field = signer.find_value("model");
if (model_field.isStr() && model_field.getValStr() != "") {
name += model_field.getValStr();
}
@@ -97,19 +97,19 @@ bool ExternalSigner::SignTransaction(PartiallySignedTransaction& psbtx, std::str
const UniValue signer_result = RunCommandParseJSON(command, stdinStr);
- if (find_value(signer_result, "error").isStr()) {
- error = find_value(signer_result, "error").get_str();
+ if (signer_result.find_value("error").isStr()) {
+ error = signer_result.find_value("error").get_str();
return false;
}
- if (!find_value(signer_result, "psbt").isStr()) {
+ if (!signer_result.find_value("psbt").isStr()) {
error = "Unexpected result from signer";
return false;
}
PartiallySignedTransaction signer_psbtx;
std::string signer_psbt_error;
- if (!DecodeBase64PSBT(signer_psbtx, find_value(signer_result, "psbt").get_str(), signer_psbt_error)) {
+ if (!DecodeBase64PSBT(signer_psbtx, signer_result.find_value("psbt").get_str(), signer_psbt_error)) {
error = strprintf("TX decode failed %s", signer_psbt_error);
return false;
}
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index bf3fa6298d..661406e122 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -76,7 +76,7 @@ static void JSONErrorReply(HTTPRequest* req, const UniValue& objError, const Uni
{
// Send error reply from json-rpc error object
int nStatus = HTTP_INTERNAL_SERVER_ERROR;
- int code = find_value(objError, "code").getInt<int>();
+ int code = objError.find_value("code").getInt<int>();
if (code == RPC_INVALID_REQUEST)
nStatus = HTTP_BAD_REQUEST;
@@ -213,7 +213,7 @@ static bool HTTPReq_JSONRPC(const std::any& context, HTTPRequest* req)
} else {
const UniValue& request = valRequest[reqIdx].get_obj();
// Parse method
- std::string strMethod = find_value(request, "method").get_str();
+ std::string strMethod = request.find_value("method").get_str();
if (!g_rpc_whitelist[jreq.authUser].count(strMethod)) {
LogPrintf("RPC User %s not allowed to call method %s\n", jreq.authUser, strMethod);
req->WriteReply(HTTP_FORBIDDEN);
diff --git a/src/index/base.cpp b/src/index/base.cpp
index 237c8e8be0..3e05c9b965 100644
--- a/src/index/base.cpp
+++ b/src/index/base.cpp
@@ -23,8 +23,6 @@
#include <string>
#include <utility>
-using node::ReadBlockFromDisk;
-
constexpr uint8_t DB_BEST_BLOCK{'B'};
constexpr auto SYNC_LOG_INTERVAL{30s};
@@ -159,8 +157,6 @@ void BaseIndex::ThreadSync()
SetSyscallSandboxPolicy(SyscallSandboxPolicy::TX_INDEX);
const CBlockIndex* pindex = m_best_block_index.load();
if (!m_synced) {
- auto& consensus_params = Params().GetConsensus();
-
std::chrono::steady_clock::time_point last_log_time{0s};
std::chrono::steady_clock::time_point last_locator_write_time{0s};
while (true) {
@@ -207,7 +203,7 @@ void BaseIndex::ThreadSync()
CBlock block;
interfaces::BlockInfo block_info = kernel::MakeBlockInfo(pindex);
- if (!ReadBlockFromDisk(block, pindex, consensus_params)) {
+ if (!m_chainstate->m_blockman.ReadBlockFromDisk(block, *pindex)) {
FatalError("%s: Failed to read block %s from disk",
__func__, pindex->GetBlockHash().ToString());
return;
diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp
index e6300ce3dd..a860b3a94d 100644
--- a/src/index/blockfilterindex.cpp
+++ b/src/index/blockfilterindex.cpp
@@ -12,8 +12,6 @@
#include <util/fs_helpers.h>
#include <validation.h>
-using node::UndoReadFromDisk;
-
/* The index database stores three items for each block: the disk location of the encoded filter,
* its dSHA256 hash, and the header. Those belonging to blocks on the active chain are indexed by
* height, and those belonging to blocks that have been reorganized out of the active chain are
@@ -223,7 +221,7 @@ bool BlockFilterIndex::CustomAppend(const interfaces::BlockInfo& block)
// pindex variable gives indexing code access to node internals. It
// will be removed in upcoming commit
const CBlockIndex* pindex = WITH_LOCK(cs_main, return m_chainstate->m_blockman.LookupBlockIndex(block.hash));
- if (!UndoReadFromDisk(block_undo, pindex)) {
+ if (!m_chainstate->m_blockman.UndoReadFromDisk(block_undo, *pindex)) {
return false;
}
diff --git a/src/index/coinstatsindex.cpp b/src/index/coinstatsindex.cpp
index 5bc6ad3d31..d80885f842 100644
--- a/src/index/coinstatsindex.cpp
+++ b/src/index/coinstatsindex.cpp
@@ -19,9 +19,6 @@ using kernel::CCoinsStats;
using kernel::GetBogoSize;
using kernel::TxOutSer;
-using node::ReadBlockFromDisk;
-using node::UndoReadFromDisk;
-
static constexpr uint8_t DB_BLOCK_HASH{'s'};
static constexpr uint8_t DB_BLOCK_HEIGHT{'t'};
static constexpr uint8_t DB_MUHASH{'M'};
@@ -125,7 +122,7 @@ bool CoinStatsIndex::CustomAppend(const interfaces::BlockInfo& block)
// pindex variable gives indexing code access to node internals. It
// will be removed in upcoming commit
const CBlockIndex* pindex = WITH_LOCK(cs_main, return m_chainstate->m_blockman.LookupBlockIndex(block.hash));
- if (!UndoReadFromDisk(block_undo, pindex)) {
+ if (!m_chainstate->m_blockman.UndoReadFromDisk(block_undo, *pindex)) {
return false;
}
@@ -282,12 +279,11 @@ bool CoinStatsIndex::CustomRewind(const interfaces::BlockKey& current_tip, const
LOCK(cs_main);
const CBlockIndex* iter_tip{m_chainstate->m_blockman.LookupBlockIndex(current_tip.hash)};
const CBlockIndex* new_tip_index{m_chainstate->m_blockman.LookupBlockIndex(new_tip.hash)};
- const auto& consensus_params{Params().GetConsensus()};
do {
CBlock block;
- if (!ReadBlockFromDisk(block, iter_tip, consensus_params)) {
+ if (!m_chainstate->m_blockman.ReadBlockFromDisk(block, *iter_tip)) {
return error("%s: Failed to read block %s from disk",
__func__, iter_tip->GetBlockHash().ToString());
}
@@ -409,7 +405,7 @@ bool CoinStatsIndex::ReverseBlock(const CBlock& block, const CBlockIndex* pindex
// Ignore genesis block
if (pindex->nHeight > 0) {
- if (!UndoReadFromDisk(block_undo, pindex)) {
+ if (!m_chainstate->m_blockman.UndoReadFromDisk(block_undo, *pindex)) {
return false;
}
diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp
index 49bddf2d4d..2e07a35d0d 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -10,8 +10,6 @@
#include <node/blockstorage.h>
#include <validation.h>
-using node::OpenBlockFile;
-
constexpr uint8_t DB_TXINDEX{'t'};
std::unique_ptr<TxIndex> g_txindex;
@@ -80,7 +78,7 @@ bool TxIndex::FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRe
return false;
}
- CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
+ CAutoFile file(m_chainstate->m_blockman.OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
if (file.IsNull()) {
return error("%s: OpenBlockFile failed", __func__);
}
diff --git a/src/init.cpp b/src/init.cpp
index 525648b812..52c5780ed4 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -18,6 +18,7 @@
#include <blockfilter.h>
#include <chain.h>
#include <chainparams.h>
+#include <chainparamsbase.h>
#include <common/args.h>
#include <consensus/amount.h>
#include <deploymentstatus.h>
@@ -69,6 +70,7 @@
#include <txdb.h>
#include <txmempool.h>
#include <util/asmap.h>
+#include <util/chaintype.h>
#include <util/check.h>
#include <util/fs.h>
#include <util/fs_helpers.h>
@@ -110,22 +112,23 @@
#include <zmq/zmqrpc.h>
#endif
+using kernel::DEFAULT_STOPAFTERBLOCKIMPORT;
using kernel::DumpMempool;
using kernel::ValidationCacheSizes;
using node::ApplyArgsManOptions;
+using node::BlockManager;
using node::CacheSizes;
using node::CalculateCacheSizes;
using node::DEFAULT_PERSIST_MEMPOOL;
using node::DEFAULT_PRINTPRIORITY;
-using node::DEFAULT_STOPAFTERBLOCKIMPORT;
+using node::fReindex;
using node::LoadChainstate;
using node::MempoolPath;
-using node::ShouldPersistMempool;
using node::NodeContext;
+using node::ShouldPersistMempool;
using node::ThreadImport;
using node::VerifyLoadedChainstate;
-using node::fReindex;
static constexpr bool DEFAULT_PROXYRANDOMIZE{true};
static constexpr bool DEFAULT_REST_ENABLE{false};
@@ -326,9 +329,8 @@ void Shutdown(NodeContext& node)
#if ENABLE_ZMQ
if (g_zmq_notification_interface) {
- UnregisterValidationInterface(g_zmq_notification_interface);
- delete g_zmq_notification_interface;
- g_zmq_notification_interface = nullptr;
+ UnregisterValidationInterface(g_zmq_notification_interface.get());
+ g_zmq_notification_interface.reset();
}
#endif
@@ -408,14 +410,14 @@ void SetupServerArgs(ArgsManager& argsman)
init::AddLoggingArgs(argsman);
- const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
- const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
- const auto signetBaseParams = CreateBaseChainParams(CBaseChainParams::SIGNET);
- const auto regtestBaseParams = CreateBaseChainParams(CBaseChainParams::REGTEST);
- const auto defaultChainParams = CreateChainParams(argsman, CBaseChainParams::MAIN);
- const auto testnetChainParams = CreateChainParams(argsman, CBaseChainParams::TESTNET);
- const auto signetChainParams = CreateChainParams(argsman, CBaseChainParams::SIGNET);
- const auto regtestChainParams = CreateChainParams(argsman, CBaseChainParams::REGTEST);
+ const auto defaultBaseParams = CreateBaseChainParams(ChainType::MAIN);
+ const auto testnetBaseParams = CreateBaseChainParams(ChainType::TESTNET);
+ const auto signetBaseParams = CreateBaseChainParams(ChainType::SIGNET);
+ const auto regtestBaseParams = CreateBaseChainParams(ChainType::REGTEST);
+ const auto defaultChainParams = CreateChainParams(argsman, ChainType::MAIN);
+ const auto testnetChainParams = CreateChainParams(argsman, ChainType::TESTNET);
+ const auto signetChainParams = CreateChainParams(argsman, ChainType::SIGNET);
+ const auto regtestChainParams = CreateChainParams(argsman, ChainType::REGTEST);
// Hidden Options
std::vector<std::string> hidden_args = {
@@ -844,14 +846,14 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
// Error if network-specific options (-addnode, -connect, etc) are
// specified in default section of config file, but not overridden
- // on the command line or in this network's section of the config file.
- std::string network = args.GetChainName();
- if (network == CBaseChainParams::SIGNET) {
+ // on the command line or in this chain's section of the config file.
+ ChainType chain = args.GetChainType();
+ if (chain == ChainType::SIGNET) {
LogPrintf("Signet derived magic (message start): %s\n", HexStr(chainparams.MessageStart()));
}
bilingual_str errors;
for (const auto& arg : args.GetUnsuitableSectionOnlyArgs()) {
- errors += strprintf(_("Config setting for %s only applied on %s network when in [%s] section.") + Untranslated("\n"), arg, network, network);
+ errors += strprintf(_("Config setting for %s only applied on %s network when in [%s] section.") + Untranslated("\n"), arg, ChainTypeToString(chain), ChainTypeToString(chain));
}
if (!errors.empty()) {
@@ -1036,7 +1038,10 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
if (const auto error{ApplyArgsManOptions(args, chainman_opts_dummy)}) {
return InitError(*error);
}
- node::BlockManager::Options blockman_opts_dummy{};
+ BlockManager::Options blockman_opts_dummy{
+ .chainparams = chainman_opts_dummy.chainparams,
+ .blocks_dir = args.GetBlocksDirPath(),
+ };
if (const auto error{ApplyArgsManOptions(args, blockman_opts_dummy)}) {
return InitError(*error);
}
@@ -1421,10 +1426,14 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
#if ENABLE_ZMQ
- g_zmq_notification_interface = CZMQNotificationInterface::Create();
+ g_zmq_notification_interface = CZMQNotificationInterface::Create(
+ [&chainman = node.chainman](CBlock& block, const CBlockIndex& index) {
+ assert(chainman);
+ return chainman->m_blockman.ReadBlockFromDisk(block, index);
+ });
if (g_zmq_notification_interface) {
- RegisterValidationInterface(g_zmq_notification_interface);
+ RegisterValidationInterface(g_zmq_notification_interface.get());
}
#endif
@@ -1439,7 +1448,10 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
};
Assert(!ApplyArgsManOptions(args, chainman_opts)); // no error can happen, already checked in AppInitParameterInteraction
- node::BlockManager::Options blockman_opts{};
+ BlockManager::Options blockman_opts{
+ .chainparams = chainman_opts.chainparams,
+ .blocks_dir = args.GetBlocksDirPath(),
+ };
Assert(!ApplyArgsManOptions(args, blockman_opts)); // no error can happen, already checked in AppInitParameterInteraction
// cache size calculations
@@ -1668,7 +1680,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
chainman.m_load_block = std::thread(&util::TraceThread, "loadblk", [=, &chainman, &args] {
- ThreadImport(chainman, vImportFiles, args, ShouldPersistMempool(args) ? MempoolPath(args) : fs::path{});
+ ThreadImport(chainman, vImportFiles, ShouldPersistMempool(args) ? MempoolPath(args) : fs::path{});
});
// Wait for genesis block to be processed
diff --git a/src/kernel/blockmanager_opts.h b/src/kernel/blockmanager_opts.h
index 9dc93b6dd2..8f26422f72 100644
--- a/src/kernel/blockmanager_opts.h
+++ b/src/kernel/blockmanager_opts.h
@@ -5,14 +5,26 @@
#ifndef BITCOIN_KERNEL_BLOCKMANAGER_OPTS_H
#define BITCOIN_KERNEL_BLOCKMANAGER_OPTS_H
+#include <util/fs.h>
+
+#include <cstdint>
+
+class CChainParams;
+
namespace kernel {
+static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false};
+
/**
* An options struct for `BlockManager`, more ergonomically referred to as
* `BlockManager::Options` due to the using-declaration in `BlockManager`.
*/
struct BlockManagerOpts {
+ const CChainParams& chainparams;
uint64_t prune_target{0};
+ bool fast_prune{false};
+ bool stop_after_block_import{DEFAULT_STOPAFTERBLOCKIMPORT};
+ const fs::path blocks_dir;
};
} // namespace kernel
diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp
index 2827737ee1..d9ed1547b3 100644
--- a/src/kernel/chainparams.cpp
+++ b/src/kernel/chainparams.cpp
@@ -10,13 +10,13 @@
#include <consensus/merkle.h>
#include <consensus/params.h>
#include <hash.h>
-#include <chainparamsbase.h>
#include <logging.h>
#include <primitives/block.h>
#include <primitives/transaction.h>
#include <script/interpreter.h>
#include <script/script.h>
#include <uint256.h>
+#include <util/chaintype.h>
#include <util/strencodings.h>
#include <algorithm>
@@ -70,7 +70,7 @@ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits
class CMainParams : public CChainParams {
public:
CMainParams() {
- strNetworkID = CBaseChainParams::MAIN;
+ m_chain_type = ChainType::MAIN;
consensus.signet_blocks = false;
consensus.signet_challenge.clear();
consensus.nSubsidyHalvingInterval = 210000;
@@ -192,7 +192,7 @@ public:
class CTestNetParams : public CChainParams {
public:
CTestNetParams() {
- strNetworkID = CBaseChainParams::TESTNET;
+ m_chain_type = ChainType::TESTNET;
consensus.signet_blocks = false;
consensus.signet_challenge.clear();
consensus.nSubsidyHalvingInterval = 210000;
@@ -328,7 +328,7 @@ public:
vSeeds = *options.seeds;
}
- strNetworkID = CBaseChainParams::SIGNET;
+ m_chain_type = ChainType::SIGNET;
consensus.signet_blocks = true;
consensus.signet_challenge.assign(bin.begin(), bin.end());
consensus.nSubsidyHalvingInterval = 210000;
@@ -397,7 +397,7 @@ class CRegTestParams : public CChainParams
public:
explicit CRegTestParams(const RegTestOptions& opts)
{
- strNetworkID = CBaseChainParams::REGTEST;
+ m_chain_type = ChainType::REGTEST;
consensus.signet_blocks = false;
consensus.signet_challenge.clear();
consensus.nSubsidyHalvingInterval = 150;
diff --git a/src/kernel/chainparams.h b/src/kernel/chainparams.h
index 32fe618dbd..ad0b49a885 100644
--- a/src/kernel/chainparams.h
+++ b/src/kernel/chainparams.h
@@ -11,6 +11,7 @@
#include <primitives/block.h>
#include <protocol.h>
#include <uint256.h>
+#include <util/chaintype.h>
#include <util/hash_type.h>
#include <cstdint>
@@ -114,8 +115,10 @@ public:
uint64_t AssumedChainStateSize() const { return m_assumed_chain_state_size; }
/** Whether it is possible to mine blocks on demand (no retargeting) */
bool MineBlocksOnDemand() const { return consensus.fPowNoRetargeting; }
- /** Return the network string */
- std::string NetworkIDString() const { return strNetworkID; }
+ /** Return the chain type string */
+ std::string GetChainTypeString() const { return ChainTypeToString(m_chain_type); }
+ /** Return the chain type */
+ ChainType GetChainType() const { return m_chain_type; }
/** Return the list of hostnames to look up for DNS seeds */
const std::vector<std::string>& DNSSeeds() const { return vSeeds; }
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
@@ -172,7 +175,7 @@ protected:
std::vector<std::string> vSeeds;
std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES];
std::string bech32_hrp;
- std::string strNetworkID;
+ ChainType m_chain_type;
CBlock genesis;
std::vector<uint8_t> vFixedSeeds;
bool fDefaultConsistencyChecks;
diff --git a/src/kernel/coinstats.cpp b/src/kernel/coinstats.cpp
index 4b75c387a6..527433f45e 100644
--- a/src/kernel/coinstats.cpp
+++ b/src/kernel/coinstats.cpp
@@ -123,7 +123,7 @@ static bool ComputeUTXOStats(CCoinsView* view, CCoinsStats& stats, T hash_obj, c
uint256 prevkey;
std::map<uint32_t, Coin> outputs;
while (pcursor->Valid()) {
- interruption_point();
+ if (interruption_point) interruption_point();
COutPoint key;
Coin coin;
if (pcursor->GetKey(key) && pcursor->GetValue(coin)) {
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index c50aa2e4f9..0e3f7435c8 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -51,9 +51,6 @@
#include <optional>
#include <typeinfo>
-using node::ReadBlockFromDisk;
-using node::ReadRawBlockFromDisk;
-
/** How long to cache transactions in mapRelay for normal relay */
static constexpr auto RELAY_TX_CACHE_TIME = 15min;
/** How long a transaction has to be in the mempool before it can unconditionally be relayed (even when not in mapRelay). */
@@ -292,7 +289,8 @@ struct Peer {
* this does not have to be sorted. */
std::set<uint256> m_tx_inventory_to_send GUARDED_BY(m_tx_inventory_mutex);
/** Whether the peer has requested us to send our complete mempool. Only
- * permitted if the peer has NetPermissionFlags::Mempool. See BIP35. */
+ * permitted if the peer has NetPermissionFlags::Mempool or we advertise
+ * NODE_BLOOM. See BIP35. */
bool m_send_mempool GUARDED_BY(m_tx_inventory_mutex){false};
/** The last time a BIP35 `mempool` request was serviced. */
std::atomic<std::chrono::seconds> m_last_mempool_req{0s};
@@ -882,8 +880,11 @@ private:
/** Remove this block from our tracked requested blocks. Called if:
* - the block has been received from a peer
* - the request for the block has timed out
+ * If "from_peer" is specified, then only remove the block if it is in
+ * flight from that peer (to avoid one peer's network traffic from
+ * affecting another's state).
*/
- void RemoveBlockRequest(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ void RemoveBlockRequest(const uint256& hash, std::optional<NodeId> from_peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/* Mark a block as in flight
* Returns false, still setting pit, if the block was already in flight from the same peer
@@ -1119,7 +1120,7 @@ bool PeerManagerImpl::IsBlockRequested(const uint256& hash)
return mapBlocksInFlight.find(hash) != mapBlocksInFlight.end();
}
-void PeerManagerImpl::RemoveBlockRequest(const uint256& hash)
+void PeerManagerImpl::RemoveBlockRequest(const uint256& hash, std::optional<NodeId> from_peer)
{
auto it = mapBlocksInFlight.find(hash);
if (it == mapBlocksInFlight.end()) {
@@ -1128,6 +1129,12 @@ void PeerManagerImpl::RemoveBlockRequest(const uint256& hash)
}
auto [node_id, list_it] = it->second;
+
+ if (from_peer && node_id != *from_peer) {
+ // Block was requested by another peer
+ return;
+ }
+
CNodeState *state = State(node_id);
assert(state != nullptr);
@@ -1163,7 +1170,7 @@ bool PeerManagerImpl::BlockRequested(NodeId nodeid, const CBlockIndex& block, st
}
// Make sure it's not listed somewhere already.
- RemoveBlockRequest(hash);
+ RemoveBlockRequest(hash, std::nullopt);
std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
{&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
@@ -2179,7 +2186,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
// Fast-path: in this case it is possible to serve the block directly from disk,
// as the network format matches the format on disk
std::vector<uint8_t> block_data;
- if (!ReadRawBlockFromDisk(block_data, pindex->GetBlockPos(), m_chainparams.MessageStart())) {
+ if (!m_chainman.m_blockman.ReadRawBlockFromDisk(block_data, pindex->GetBlockPos(), m_chainparams.MessageStart())) {
assert(!"cannot load block from disk");
}
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, Span{block_data}));
@@ -2187,7 +2194,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
} else {
// Send block from disk
std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
- if (!ReadBlockFromDisk(*pblockRead, pindex, m_chainparams.GetConsensus())) {
+ if (!m_chainman.m_blockman.ReadBlockFromDisk(*pblockRead, *pindex)) {
assert(!"cannot load block from disk");
}
pblock = pblockRead;
@@ -3154,6 +3161,11 @@ void PeerManagerImpl::ProcessBlock(CNode& node, const std::shared_ptr<const CBlo
m_chainman.ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
if (new_block) {
node.m_last_block_time = GetTime<std::chrono::seconds>();
+ // In case this block came from a different peer than we requested
+ // from, we can erase the block request now anyway (as we just stored
+ // this block to disk).
+ LOCK(cs_main);
+ RemoveBlockRequest(block->GetHash(), std::nullopt);
} else {
LOCK(cs_main);
mapBlockSource.erase(block->GetHash());
@@ -3874,7 +3886,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
if (pindex->nHeight >= m_chainman.ActiveChain().Height() - MAX_BLOCKTXN_DEPTH) {
CBlock block;
- bool ret = ReadBlockFromDisk(block, pindex, m_chainparams.GetConsensus());
+ const bool ret{m_chainman.m_blockman.ReadBlockFromDisk(block, *pindex)};
assert(ret);
SendBlockTransactions(pfrom, *peer, block, req);
@@ -4304,7 +4316,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
PartiallyDownloadedBlock& partialBlock = *(*queuedBlockIt)->partialBlock;
ReadStatus status = partialBlock.InitData(cmpctblock, vExtraTxnForCompact);
if (status == READ_STATUS_INVALID) {
- RemoveBlockRequest(pindex->GetBlockHash()); // Reset in-flight state in case Misbehaving does not result in a disconnect
+ RemoveBlockRequest(pindex->GetBlockHash(), pfrom.GetId()); // Reset in-flight state in case Misbehaving does not result in a disconnect
Misbehaving(*peer, 100, "invalid compact block");
return;
} else if (status == READ_STATUS_FAILED) {
@@ -4399,7 +4411,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// process from some other peer. We do this after calling
// ProcessNewBlock so that a malleated cmpctblock announcement
// can't be used to interfere with block relay.
- RemoveBlockRequest(pblock->GetHash());
+ RemoveBlockRequest(pblock->GetHash(), std::nullopt);
}
}
return;
@@ -4431,7 +4443,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
PartiallyDownloadedBlock& partialBlock = *it->second.second->partialBlock;
ReadStatus status = partialBlock.FillBlock(*pblock, resp.txn);
if (status == READ_STATUS_INVALID) {
- RemoveBlockRequest(resp.blockhash); // Reset in-flight state in case Misbehaving does not result in a disconnect
+ RemoveBlockRequest(resp.blockhash, pfrom.GetId()); // Reset in-flight state in case Misbehaving does not result in a disconnect
Misbehaving(*peer, 100, "invalid compact block/non-matching block transactions");
return;
} else if (status == READ_STATUS_FAILED) {
@@ -4457,7 +4469,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// though the block was successfully read, and rely on the
// handling in ProcessNewBlock to ensure the block index is
// updated, etc.
- RemoveBlockRequest(resp.blockhash); // it is now an empty pointer
+ RemoveBlockRequest(resp.blockhash, pfrom.GetId()); // it is now an empty pointer
fBlockRead = true;
// mapBlockSource is used for potentially punishing peers and
// updating which peers send us compact blocks, so the race
@@ -4546,7 +4558,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
// Always process the block if we requested it, since we may
// need it even when it's not a candidate for a new best tip.
forceProcessing = IsBlockRequested(hash);
- RemoveBlockRequest(hash);
+ RemoveBlockRequest(hash, pfrom.GetId());
// mapBlockSource is only used for punishing peers and setting
// which peers send us compact blocks, so the race between here and
// cs_main in ProcessNewBlock is fine.
@@ -4600,6 +4612,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
if (msg_type == NetMsgType::MEMPOOL) {
+ // Only process received mempool messages if we advertise NODE_BLOOM
+ // or if the peer has mempool permissions.
if (!(peer->m_our_services & NODE_BLOOM) && !pfrom.HasPermission(NetPermissionFlags::Mempool))
{
if (!pfrom.HasPermission(NetPermissionFlags::NoBan))
@@ -5529,7 +5543,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
m_connman.PushMessage(pto, std::move(cached_cmpctblock_msg.value()));
} else {
CBlock block;
- bool ret = ReadBlockFromDisk(block, pBestIndex, consensusParams);
+ const bool ret{m_chainman.m_blockman.ReadBlockFromDisk(block, *pBestIndex)};
assert(ret);
CBlockHeaderAndShortTxIDs cmpctblock{block};
m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::CMPCTBLOCK, cmpctblock));
@@ -5663,7 +5677,9 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
// especially since we have many peers and some will draw much shorter delays.
unsigned int nRelayedTransactions = 0;
LOCK(tx_relay->m_bloom_filter_mutex);
- while (!vInvTx.empty() && nRelayedTransactions < INVENTORY_BROADCAST_MAX) {
+ size_t broadcast_max{INVENTORY_BROADCAST_MAX + (tx_relay->m_tx_inventory_to_send.size()/1000)*5};
+ broadcast_max = std::min<size_t>(1000, broadcast_max);
+ while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
// Fetch the top element from the heap
std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
std::set<uint256>::iterator it = vInvTx.back();
diff --git a/src/netbase.cpp b/src/netbase.cpp
index f39a3635f4..4f78d2e31a 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -36,8 +36,8 @@ static Proxy nameProxy GUARDED_BY(g_proxyinfo_mutex);
int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
bool fNameLookup = DEFAULT_NAME_LOOKUP;
-// Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
-int g_socks5_recv_timeout = 20 * 1000;
+// Need ample time for negotiation for very slow proxies such as Tor
+std::chrono::milliseconds g_socks5_recv_timeout = 20s;
static std::atomic<bool> interruptSocks5Recv(false);
std::vector<CNetAddr> WrappedGetAddrInfo(const std::string& name, bool allow_lookup)
@@ -296,7 +296,7 @@ enum class IntrRecvError {
*
* @param data The buffer where the read bytes should be stored.
* @param len The number of bytes to read into the specified buffer.
- * @param timeout The total timeout in milliseconds for this read.
+ * @param timeout The total timeout for this read.
* @param sock The socket (has to be in non-blocking mode) from which to read bytes.
*
* @returns An IntrRecvError indicating the resulting status of this read.
@@ -306,10 +306,10 @@ enum class IntrRecvError {
* @see This function can be interrupted by calling InterruptSocks5(bool).
* Sockets can be made non-blocking with Sock::SetNonBlocking().
*/
-static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const Sock& sock)
+static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, std::chrono::milliseconds timeout, const Sock& sock)
{
- int64_t curTime = GetTimeMillis();
- int64_t endTime = curTime + timeout;
+ auto curTime{Now<SteadyMilliseconds>()};
+ const auto endTime{curTime + timeout};
while (len > 0 && curTime < endTime) {
ssize_t ret = sock.Recv(data, len, 0); // Optimistically try the recv first
if (ret > 0) {
@@ -333,7 +333,7 @@ static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, c
}
if (interruptSocks5Recv)
return IntrRecvError::Interrupted;
- curTime = GetTimeMillis();
+ curTime = Now<SteadyMilliseconds>();
}
return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
}
diff --git a/src/node/blockmanager_args.cpp b/src/node/blockmanager_args.cpp
index 06a1934947..23b0bd37ab 100644
--- a/src/node/blockmanager_args.cpp
+++ b/src/node/blockmanager_args.cpp
@@ -5,8 +5,14 @@
#include <node/blockmanager_args.h>
#include <common/args.h>
+#include <node/blockstorage.h>
+#include <tinyformat.h>
+#include <util/translation.h>
#include <validation.h>
+#include <cstdint>
+#include <optional>
+
namespace node {
std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& args, BlockManager::Options& opts)
{
@@ -25,6 +31,9 @@ std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& args, BlockM
}
opts.prune_target = nPruneTarget;
+ if (auto value{args.GetBoolArg("-fastprune")}) opts.fast_prune = *value;
+ if (auto value{args.GetBoolArg("-stopafterblockimport")}) opts.stop_after_block_import = *value;
+
return std::nullopt;
}
} // namespace node
diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp
index 38859f1b0d..65dac459c5 100644
--- a/src/node/blockstorage.cpp
+++ b/src/node/blockstorage.cpp
@@ -6,7 +6,6 @@
#include <chain.h>
#include <clientversion.h>
-#include <common/args.h>
#include <consensus/validation.h>
#include <flatfile.h>
#include <hash.h>
@@ -53,10 +52,6 @@ bool CBlockIndexHeightOnlyComparator::operator()(const CBlockIndex* pa, const CB
return pa->nHeight < pb->nHeight;
}
-static FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly = false);
-static FlatFileSeq BlockFileSeq();
-static FlatFileSeq UndoFileSeq();
-
std::vector<CBlockIndex*> BlockManager::GetAllBlockIndices()
{
AssertLockHeld(cs_main);
@@ -253,9 +248,9 @@ CBlockIndex* BlockManager::InsertBlockIndex(const uint256& hash)
return pindex;
}
-bool BlockManager::LoadBlockIndex(const Consensus::Params& consensus_params)
+bool BlockManager::LoadBlockIndex()
{
- if (!m_block_tree_db->LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); })) {
+ if (!m_block_tree_db->LoadBlockIndexGuts(GetConsensus(), [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); })) {
return false;
}
@@ -318,9 +313,9 @@ bool BlockManager::WriteBlockIndexDB()
return true;
}
-bool BlockManager::LoadBlockIndexDB(const Consensus::Params& consensus_params)
+bool BlockManager::LoadBlockIndexDB()
{
- if (!LoadBlockIndex(consensus_params)) {
+ if (!LoadBlockIndex()) {
return false;
}
@@ -423,7 +418,7 @@ const CBlockIndex* BlockManager::GetFirstStoredBlock(const CBlockIndex& start_bl
// rev files since they'll be rewritten by the reindex anyway. This ensures that m_blockfile_info
// is in sync with what's actually on disk by the time we start downloading, so that pruning
// works correctly.
-void CleanupBlockRevFiles()
+void BlockManager::CleanupBlockRevFiles() const
{
std::map<std::string, fs::path> mapBlockFiles;
@@ -431,8 +426,7 @@ void CleanupBlockRevFiles()
// Remove the rev files immediately and insert the blk file paths into an
// ordered map keyed by block file index.
LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n");
- const fs::path& blocksdir = gArgs.GetBlocksDirPath();
- for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); it++) {
+ for (fs::directory_iterator it(m_opts.blocks_dir); it != fs::directory_iterator(); it++) {
const std::string path = fs::PathToString(it->path().filename());
if (fs::is_regular_file(*it) &&
path.length() == 12 &&
@@ -467,7 +461,7 @@ CBlockFileInfo* BlockManager::GetBlockFileInfo(size_t n)
return &m_blockfile_info.at(n);
}
-static bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart)
+bool BlockManager::UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart) const
{
// Open history file to append
AutoFile fileout{OpenUndoFile(pos)};
@@ -496,9 +490,9 @@ static bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const
return true;
}
-bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex)
+bool BlockManager::UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex& index) const
{
- const FlatFilePos pos{WITH_LOCK(::cs_main, return pindex->GetUndoPos())};
+ const FlatFilePos pos{WITH_LOCK(::cs_main, return index.GetUndoPos())};
if (pos.IsNull()) {
return error("%s: no undo data available", __func__);
@@ -514,7 +508,7 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex)
uint256 hashChecksum;
HashVerifier verifier{filein}; // Use HashVerifier as reserializing may lose data, c.f. commit d342424301013ec47dc146a4beb49d5c9319d80a
try {
- verifier << pindex->pprev->GetBlockHash();
+ verifier << index.pprev->GetBlockHash();
verifier >> blockundo;
filein >> hashChecksum;
} catch (const std::exception& e) {
@@ -570,7 +564,7 @@ uint64_t BlockManager::CalculateCurrentUsage()
return retval;
}
-void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune)
+void BlockManager::UnlinkPrunedFiles(const std::set<int>& setFilesToPrune) const
{
std::error_code ec;
for (std::set<int>::iterator it = setFilesToPrune.begin(); it != setFilesToPrune.end(); ++it) {
@@ -583,28 +577,28 @@ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune)
}
}
-static FlatFileSeq BlockFileSeq()
+FlatFileSeq BlockManager::BlockFileSeq() const
{
- return FlatFileSeq(gArgs.GetBlocksDirPath(), "blk", gArgs.GetBoolArg("-fastprune", false) ? 0x4000 /* 16kb */ : BLOCKFILE_CHUNK_SIZE);
+ return FlatFileSeq(m_opts.blocks_dir, "blk", m_opts.fast_prune ? 0x4000 /* 16kb */ : BLOCKFILE_CHUNK_SIZE);
}
-static FlatFileSeq UndoFileSeq()
+FlatFileSeq BlockManager::UndoFileSeq() const
{
- return FlatFileSeq(gArgs.GetBlocksDirPath(), "rev", UNDOFILE_CHUNK_SIZE);
+ return FlatFileSeq(m_opts.blocks_dir, "rev", UNDOFILE_CHUNK_SIZE);
}
-FILE* OpenBlockFile(const FlatFilePos& pos, bool fReadOnly)
+FILE* BlockManager::OpenBlockFile(const FlatFilePos& pos, bool fReadOnly) const
{
return BlockFileSeq().Open(pos, fReadOnly);
}
/** Open an undo file (rev?????.dat) */
-static FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly)
+FILE* BlockManager::OpenUndoFile(const FlatFilePos& pos, bool fReadOnly) const
{
return UndoFileSeq().Open(pos, fReadOnly);
}
-fs::path GetBlockPosFilename(const FlatFilePos& pos)
+fs::path BlockManager::GetBlockPosFilename(const FlatFilePos& pos) const
{
return BlockFileSeq().FileName(pos);
}
@@ -620,7 +614,18 @@ bool BlockManager::FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigne
bool finalize_undo = false;
if (!fKnown) {
- while (m_blockfile_info[nFile].nSize + nAddSize >= (gArgs.GetBoolArg("-fastprune", false) ? 0x10000 /* 64kb */ : MAX_BLOCKFILE_SIZE)) {
+ unsigned int max_blockfile_size{MAX_BLOCKFILE_SIZE};
+ // Use smaller blockfiles in test-only -fastprune mode - but avoid
+ // the possibility of having a block not fit into the block file.
+ if (m_opts.fast_prune) {
+ max_blockfile_size = 0x10000; // 64kiB
+ if (nAddSize >= max_blockfile_size) {
+ // dynamically adjust the blockfile size to be larger than the added size
+ max_blockfile_size = nAddSize + 1;
+ }
+ }
+ assert(nAddSize < max_blockfile_size);
+ while (m_blockfile_info[nFile].nSize + nAddSize >= max_blockfile_size) {
// when the undo file is keeping up with the block file, we want to flush it explicitly
// when it is lagging behind (more blocks arrive than are being connected), we let the
// undo block write case handle it
@@ -686,7 +691,7 @@ bool BlockManager::FindUndoPos(BlockValidationState& state, int nFile, FlatFileP
return true;
}
-static bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessageHeader::MessageStartChars& messageStart)
+bool BlockManager::WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessageHeader::MessageStartChars& messageStart) const
{
// Open history file to append
CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
@@ -709,16 +714,16 @@ static bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessa
return true;
}
-bool BlockManager::WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams)
+bool BlockManager::WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex& block)
{
AssertLockHeld(::cs_main);
// Write undo information to disk
- if (pindex->GetUndoPos().IsNull()) {
+ if (block.GetUndoPos().IsNull()) {
FlatFilePos _pos;
- if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, CLIENT_VERSION) + 40)) {
+ if (!FindUndoPos(state, block.nFile, _pos, ::GetSerializeSize(blockundo, CLIENT_VERSION) + 40)) {
return error("ConnectBlock(): FindUndoPos failed");
}
- if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) {
+ if (!UndoWriteToDisk(blockundo, _pos, block.pprev->GetBlockHash(), GetParams().MessageStart())) {
return AbortNode(state, "Failed to write undo data");
}
// rev files are written in block height order, whereas blk files are written as blocks come in (often out of order)
@@ -726,20 +731,20 @@ bool BlockManager::WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValid
// in the block file info as below; note that this does not catch the case where the undo writes are keeping up
// with the block writes (usually when a synced up node is getting newly mined blocks) -- this case is caught in
// the FindBlockPos function
- if (_pos.nFile < m_last_blockfile && static_cast<uint32_t>(pindex->nHeight) == m_blockfile_info[_pos.nFile].nHeightLast) {
+ if (_pos.nFile < m_last_blockfile && static_cast<uint32_t>(block.nHeight) == m_blockfile_info[_pos.nFile].nHeightLast) {
FlushUndoFile(_pos.nFile, true);
}
// update nUndoPos in block index
- pindex->nUndoPos = _pos.nPos;
- pindex->nStatus |= BLOCK_HAVE_UNDO;
- m_dirty_blockindex.insert(pindex);
+ block.nUndoPos = _pos.nPos;
+ block.nStatus |= BLOCK_HAVE_UNDO;
+ m_dirty_blockindex.insert(&block);
}
return true;
}
-bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams)
+bool BlockManager::ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos) const
{
block.SetNull();
@@ -757,33 +762,33 @@ bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::P
}
// Check the header
- if (!CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) {
+ if (!CheckProofOfWork(block.GetHash(), block.nBits, GetConsensus())) {
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
}
// Signet only: check block solution
- if (consensusParams.signet_blocks && !CheckSignetBlockSolution(block, consensusParams)) {
+ if (GetConsensus().signet_blocks && !CheckSignetBlockSolution(block, GetConsensus())) {
return error("ReadBlockFromDisk: Errors in block solution at %s", pos.ToString());
}
return true;
}
-bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
+bool BlockManager::ReadBlockFromDisk(CBlock& block, const CBlockIndex& index) const
{
- const FlatFilePos block_pos{WITH_LOCK(cs_main, return pindex->GetBlockPos())};
+ const FlatFilePos block_pos{WITH_LOCK(cs_main, return index.GetBlockPos())};
- if (!ReadBlockFromDisk(block, block_pos, consensusParams)) {
+ if (!ReadBlockFromDisk(block, block_pos)) {
return false;
}
- if (block.GetHash() != pindex->GetBlockHash()) {
+ if (block.GetHash() != index.GetBlockHash()) {
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
- pindex->ToString(), block_pos.ToString());
+ index.ToString(), block_pos.ToString());
}
return true;
}
-bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start)
+bool BlockManager::ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start) const
{
FlatFilePos hpos = pos;
hpos.nPos -= 8; // Seek back 8 bytes for meta header
@@ -818,7 +823,7 @@ bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, c
return true;
}
-FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp)
+FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const FlatFilePos* dbp)
{
unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION);
FlatFilePos blockPos;
@@ -836,7 +841,7 @@ FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, CCha
return FlatFilePos();
}
if (!position_known) {
- if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) {
+ if (!WriteBlockToDisk(block, blockPos, GetParams().MessageStart())) {
AbortNode("Failed to write block");
return FlatFilePos();
}
@@ -861,7 +866,7 @@ public:
}
};
-void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const ArgsManager& args, const fs::path& mempool_path)
+void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const fs::path& mempool_path)
{
SetSyscallSandboxPolicy(SyscallSandboxPolicy::INITIALIZATION_LOAD_BLOCKS);
ScheduleBatchPriority();
@@ -877,10 +882,10 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
std::multimap<uint256, FlatFilePos> blocks_with_unknown_parent;
while (true) {
FlatFilePos pos(nFile, 0);
- if (!fs::exists(GetBlockPosFilename(pos))) {
+ if (!fs::exists(chainman.m_blockman.GetBlockPosFilename(pos))) {
break; // No block files left to reindex
}
- FILE* file = OpenBlockFile(pos, true);
+ FILE* file = chainman.m_blockman.OpenBlockFile(pos, true);
if (!file) {
break; // This error is logged in OpenBlockFile
}
@@ -928,7 +933,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
}
}
- if (args.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) {
+ if (chainman.m_blockman.StopAfterBlockImport()) {
LogPrintf("Stopping after block import\n");
StartShutdown();
return;
diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h
index 3eb27cc72d..bce071c7df 100644
--- a/src/node/blockstorage.h
+++ b/src/node/blockstorage.h
@@ -8,6 +8,7 @@
#include <attributes.h>
#include <chain.h>
#include <kernel/blockmanager_opts.h>
+#include <kernel/chainparams.h>
#include <kernel/cs_main.h>
#include <protocol.h>
#include <sync.h>
@@ -19,7 +20,6 @@
#include <unordered_map>
#include <vector>
-class ArgsManager;
class BlockValidationState;
class CBlock;
class CBlockFileInfo;
@@ -35,7 +35,6 @@ struct Params;
}
namespace node {
-static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false};
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
@@ -81,18 +80,28 @@ class BlockManager
friend ChainstateManager;
private:
+ const CChainParams& GetParams() const { return m_opts.chainparams; }
+ const Consensus::Params& GetConsensus() const { return m_opts.chainparams.GetConsensus(); }
/**
* Load the blocktree off disk and into memory. Populate certain metadata
* per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral
* collections like m_dirty_blockindex.
*/
- bool LoadBlockIndex(const Consensus::Params& consensus_params)
+ bool LoadBlockIndex()
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void FlushBlockFile(bool fFinalize = false, bool finalize_undo = false);
void FlushUndoFile(int block_file, bool finalize = false);
bool FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigned int nHeight, CChain& active_chain, uint64_t nTime, bool fKnown);
bool FindUndoPos(BlockValidationState& state, int nFile, FlatFilePos& pos, unsigned int nAddSize);
+ FlatFileSeq BlockFileSeq() const;
+ FlatFileSeq UndoFileSeq() const;
+
+ FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly = false) const;
+
+ bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessageHeader::MessageStartChars& messageStart) const;
+ bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart) const;
+
/* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */
void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight, int chain_tip_height);
@@ -162,7 +171,7 @@ public:
std::unique_ptr<CBlockTreeDB> m_block_tree_db GUARDED_BY(::cs_main);
bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
- bool LoadBlockIndexDB(const Consensus::Params& consensus_params) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+ bool LoadBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/**
* Remove any pruned block & undo files that are still on disk.
@@ -184,11 +193,11 @@ public:
/** Get block file info entry for one block file */
CBlockFileInfo* GetBlockFileInfo(size_t n);
- bool WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams)
+ bool WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex& block)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/** Store block on disk. If dbp is not nullptr, then it provides the known position of the block within a block file on disk. */
- FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp);
+ FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const FlatFilePos* dbp);
/** Whether running in -prune mode. */
[[nodiscard]] bool IsPruneMode() const { return m_prune_mode; }
@@ -199,6 +208,8 @@ public:
[[nodiscard]] bool LoadingBlocks() const { return m_importing || fReindex; }
+ [[nodiscard]] bool StopAfterBlockImport() const { return m_opts.stop_after_block_import; }
+
/** Calculate the amount of disk space the block & undo files currently use */
uint64_t CalculateCurrentUsage();
@@ -216,28 +227,29 @@ public:
//! Create or update a prune lock identified by its name
void UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
-};
-void CleanupBlockRevFiles();
+ /** Open a block file (blk?????.dat) */
+ FILE* OpenBlockFile(const FlatFilePos& pos, bool fReadOnly = false) const;
-/** Open a block file (blk?????.dat) */
-FILE* OpenBlockFile(const FlatFilePos& pos, bool fReadOnly = false);
-/** Translation to a filesystem path */
-fs::path GetBlockPosFilename(const FlatFilePos& pos);
+ /** Translation to a filesystem path */
+ fs::path GetBlockPosFilename(const FlatFilePos& pos) const;
-/**
- * Actually unlink the specified files
- */
-void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune);
+ /**
+ * Actually unlink the specified files
+ */
+ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune) const;
-/** Functions for disk access for blocks */
-bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams);
-bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams);
-bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start);
+ /** Functions for disk access for blocks */
+ bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos) const;
+ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex& index) const;
+ bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start) const;
-bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex);
+ bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex& index) const;
+
+ void CleanupBlockRevFiles() const;
+};
-void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const ArgsManager& args, const fs::path& mempool_path);
+void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const fs::path& mempool_path);
} // namespace node
#endif // BITCOIN_NODE_BLOCKSTORAGE_H
diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp
index f60ff83a0d..40b609d069 100644
--- a/src/node/chainstate.cpp
+++ b/src/node/chainstate.cpp
@@ -51,7 +51,7 @@ static ChainstateLoadResult CompleteChainstateInitialization(
pblocktree->WriteReindexing(true);
//If we're reindexing in prune mode, wipe away unusable block files and all undo data files
if (options.prune) {
- CleanupBlockRevFiles();
+ chainman.m_blockman.CleanupBlockRevFiles();
}
}
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index 5fcace833f..6e39ccf34e 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -239,7 +239,7 @@ public:
std::vector<ExternalSigner> signers = {};
const std::string command = args().GetArg("-signer", "");
if (command == "") return {};
- ExternalSigner::Enumerate(command, signers, Params().NetworkIDString());
+ ExternalSigner::Enumerate(command, signers, Params().GetChainTypeString());
std::vector<std::unique_ptr<interfaces::ExternalSigner>> result;
result.reserve(signers.size());
for (auto& signer : signers) {
@@ -394,7 +394,7 @@ public:
NodeContext* m_context{nullptr};
};
-bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock, const CChain& active)
+bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock, const CChain& active, const BlockManager& blockman)
{
if (!index) return false;
if (block.m_hash) *block.m_hash = index->GetBlockHash();
@@ -404,10 +404,10 @@ bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<Rec
if (block.m_mtp_time) *block.m_mtp_time = index->GetMedianTimePast();
if (block.m_in_active_chain) *block.m_in_active_chain = active[index->nHeight] == index;
if (block.m_locator) { *block.m_locator = GetLocator(index); }
- if (block.m_next_block) FillBlock(active[index->nHeight] == index ? active[index->nHeight + 1] : nullptr, *block.m_next_block, lock, active);
+ if (block.m_next_block) FillBlock(active[index->nHeight] == index ? active[index->nHeight + 1] : nullptr, *block.m_next_block, lock, active, blockman);
if (block.m_data) {
REVERSE_LOCK(lock);
- if (!ReadBlockFromDisk(*block.m_data, index, Params().GetConsensus())) block.m_data->SetNull();
+ if (!blockman.ReadBlockFromDisk(*block.m_data, *index)) block.m_data->SetNull();
}
block.found = true;
return true;
@@ -557,13 +557,13 @@ public:
bool findBlock(const uint256& hash, const FoundBlock& block) override
{
WAIT_LOCK(cs_main, lock);
- return FillBlock(chainman().m_blockman.LookupBlockIndex(hash), block, lock, chainman().ActiveChain());
+ return FillBlock(chainman().m_blockman.LookupBlockIndex(hash), block, lock, chainman().ActiveChain(), chainman().m_blockman);
}
bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
{
WAIT_LOCK(cs_main, lock);
const CChain& active = chainman().ActiveChain();
- return FillBlock(active.FindEarliestAtLeast(min_time, min_height), block, lock, active);
+ return FillBlock(active.FindEarliestAtLeast(min_time, min_height), block, lock, active, chainman().m_blockman);
}
bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override
{
@@ -571,10 +571,10 @@ public:
const CChain& active = chainman().ActiveChain();
if (const CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash)) {
if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
- return FillBlock(ancestor, ancestor_out, lock, active);
+ return FillBlock(ancestor, ancestor_out, lock, active, chainman().m_blockman);
}
}
- return FillBlock(nullptr, ancestor_out, lock, active);
+ return FillBlock(nullptr, ancestor_out, lock, active, chainman().m_blockman);
}
bool findAncestorByHash(const uint256& block_hash, const uint256& ancestor_hash, const FoundBlock& ancestor_out) override
{
@@ -582,7 +582,7 @@ public:
const CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash);
const CBlockIndex* ancestor = chainman().m_blockman.LookupBlockIndex(ancestor_hash);
if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
- return FillBlock(ancestor, ancestor_out, lock, chainman().ActiveChain());
+ return FillBlock(ancestor, ancestor_out, lock, chainman().ActiveChain(), chainman().m_blockman);
}
bool findCommonAncestor(const uint256& block_hash1, const uint256& block_hash2, const FoundBlock& ancestor_out, const FoundBlock& block1_out, const FoundBlock& block2_out) override
{
@@ -594,9 +594,9 @@ public:
// Using & instead of && below to avoid short circuiting and leaving
// output uninitialized. Cast bool to int to avoid -Wbitwise-instead-of-logical
// compiler warnings.
- return int{FillBlock(ancestor, ancestor_out, lock, active)} &
- int{FillBlock(block1, block1_out, lock, active)} &
- int{FillBlock(block2, block2_out, lock, active)};
+ return int{FillBlock(ancestor, ancestor_out, lock, active, chainman().m_blockman)} &
+ int{FillBlock(block1, block1_out, lock, active, chainman().m_blockman)} &
+ int{FillBlock(block2, block2_out, lock, active, chainman().m_blockman)};
}
void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(m_node, coins); }
double guessVerificationProgress(const uint256& block_hash) override
diff --git a/src/node/mempool_args.cpp b/src/node/mempool_args.cpp
index f193469506..294111a58a 100644
--- a/src/node/mempool_args.cpp
+++ b/src/node/mempool_args.cpp
@@ -89,7 +89,7 @@ std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& argsman, con
mempool_opts.require_standard = !argsman.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
if (!chainparams.IsTestChain() && !mempool_opts.require_standard) {
- return strprintf(Untranslated("acceptnonstdtxn is not currently supported for %s chain"), chainparams.NetworkIDString());
+ return strprintf(Untranslated("acceptnonstdtxn is not currently supported for %s chain"), chainparams.GetChainTypeString());
}
mempool_opts.full_rbf = argsman.GetBoolArg("-mempoolfullrbf", mempool_opts.full_rbf);
diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp
index c7c8493f0c..026c8084dd 100644
--- a/src/node/transaction.cpp
+++ b/src/node/transaction.cpp
@@ -122,7 +122,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
return TransactionError::OK;
}
-CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock)
+CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, uint256& hashBlock, const BlockManager& blockman)
{
if (mempool && !block_index) {
CTransactionRef ptx = mempool->get(hash);
@@ -143,7 +143,7 @@ CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMe
}
if (block_index) {
CBlock block;
- if (ReadBlockFromDisk(block, block_index, consensusParams)) {
+ if (blockman.ReadBlockFromDisk(block, *block_index)) {
for (const auto& tx : block.vtx) {
if (tx->GetHash() == hash) {
hashBlock = block_index->GetBlockHash();
diff --git a/src/node/transaction.h b/src/node/transaction.h
index 45f174f13c..168273594c 100644
--- a/src/node/transaction.h
+++ b/src/node/transaction.h
@@ -16,6 +16,7 @@ struct Params;
}
namespace node {
+class BlockManager;
struct NodeContext;
/** Maximum fee rate for sendrawtransaction and testmempoolaccept RPC calls.
@@ -53,11 +54,10 @@ static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE{COIN / 10};
* @param[in] block_index The block to read from disk, or nullptr
* @param[in] mempool If provided, check mempool for tx
* @param[in] hash The txid
- * @param[in] consensusParams The params
* @param[out] hashBlock The block hash, if the tx was found via -txindex or block_index
* @returns The tx if found, otherwise nullptr
*/
-CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock);
+CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, uint256& hashBlock, const BlockManager& blockman);
} // namespace node
#endif // BITCOIN_NODE_TRANSACTION_H
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 2f00009596..d602d2c1ac 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -601,7 +601,7 @@ int GuiMain(int argc, char* argv[])
PaymentServer::ipcParseCommandLine(argc, argv);
#endif
- QScopedPointer<const NetworkStyle> networkStyle(NetworkStyle::instantiate(Params().NetworkIDString()));
+ QScopedPointer<const NetworkStyle> networkStyle(NetworkStyle::instantiate(Params().GetChainType()));
assert(!networkStyle.isNull());
// Allow for separate UI settings for testnets
QApplication::setApplicationName(networkStyle->getAppName());
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 837e5f4fed..b22f1bc35c 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -28,8 +28,8 @@
#include <QThread>
#include <QTimer>
-static int64_t nLastHeaderTipUpdateNotification = 0;
-static int64_t nLastBlockTipUpdateNotification = 0;
+static SteadyClock::time_point g_last_header_tip_update_notification{};
+static SteadyClock::time_point g_last_block_tip_update_notification{};
ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QObject *parent) :
QObject(parent),
@@ -222,9 +222,9 @@ void ClientModel::TipChanged(SynchronizationState sync_state, interfaces::BlockT
// Throttle GUI notifications about (a) blocks during initial sync, and (b) both blocks and headers during reindex.
const bool throttle = (sync_state != SynchronizationState::POST_INIT && synctype == SyncType::BLOCK_SYNC) || sync_state == SynchronizationState::INIT_REINDEX;
- const int64_t now = throttle ? GetTimeMillis() : 0;
- int64_t& nLastUpdateNotification = synctype != SyncType::BLOCK_SYNC ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
- if (throttle && now < nLastUpdateNotification + count_milliseconds(MODEL_UPDATE_DELAY)) {
+ const auto now{throttle ? SteadyClock::now() : SteadyClock::time_point{}};
+ auto& nLastUpdateNotification = synctype != SyncType::BLOCK_SYNC ? g_last_header_tip_update_notification : g_last_block_tip_update_notification;
+ if (throttle && now < nLastUpdateNotification + MODEL_UPDATE_DELAY) {
return;
}
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index e1b1ae12e9..50d3c2e559 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -412,8 +412,7 @@ void CoinControlDialog::updateLabels(CCoinControl& m_coin_control, WalletModel *
unsigned int nQuantity = 0;
bool fWitness = false;
- std::vector<COutPoint> vCoinControl;
- m_coin_control.ListSelected(vCoinControl);
+ auto vCoinControl{m_coin_control.ListSelected()};
size_t i = 0;
for (const auto& out : model->wallet().getCoins(vCoinControl)) {
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index dc7daed4bc..8d8328aad8 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -21,6 +21,7 @@
#include <protocol.h>
#include <script/script.h>
#include <script/standard.h>
+#include <util/chaintype.h>
#include <util/exception.h>
#include <util/fs.h>
#include <util/fs_helpers.h>
@@ -503,12 +504,12 @@ bool LabelOutOfFocusEventFilter::eventFilter(QObject* watched, QEvent* event)
#ifdef WIN32
fs::path static StartupShortcutPath()
{
- std::string chain = gArgs.GetChainName();
- if (chain == CBaseChainParams::MAIN)
+ ChainType chain = gArgs.GetChainType();
+ if (chain == ChainType::MAIN)
return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin.lnk";
- if (chain == CBaseChainParams::TESTNET) // Remove this special case when CBaseChainParams::TESTNET = "testnet4"
+ if (chain == ChainType::TESTNET) // Remove this special case when testnet CBaseChainParams::DataDir() is incremented to "testnet4"
return GetSpecialFolderPath(CSIDL_STARTUP) / "Bitcoin (testnet).lnk";
- return GetSpecialFolderPath(CSIDL_STARTUP) / fs::u8path(strprintf("Bitcoin (%s).lnk", chain));
+ return GetSpecialFolderPath(CSIDL_STARTUP) / fs::u8path(strprintf("Bitcoin (%s).lnk", ChainTypeToString(chain)));
}
bool GetStartOnSystemStartup()
@@ -541,7 +542,7 @@ bool SetStartOnSystemStartup(bool fAutoStart)
// Start client minimized
QString strArgs = "-min";
// Set -testnet /-regtest options
- strArgs += QString::fromStdString(strprintf(" -chain=%s", gArgs.GetChainName()));
+ strArgs += QString::fromStdString(strprintf(" -chain=%s", gArgs.GetChainTypeString()));
// Set the path to the shortcut target
psl->SetPath(pszExePath);
@@ -586,10 +587,10 @@ fs::path static GetAutostartDir()
fs::path static GetAutostartFilePath()
{
- std::string chain = gArgs.GetChainName();
- if (chain == CBaseChainParams::MAIN)
+ ChainType chain = gArgs.GetChainType();
+ if (chain == ChainType::MAIN)
return GetAutostartDir() / "bitcoin.desktop";
- return GetAutostartDir() / fs::u8path(strprintf("bitcoin-%s.desktop", chain));
+ return GetAutostartDir() / fs::u8path(strprintf("bitcoin-%s.desktop", ChainTypeToString(chain)));
}
bool GetStartOnSystemStartup()
@@ -629,15 +630,15 @@ bool SetStartOnSystemStartup(bool fAutoStart)
std::ofstream optionFile{GetAutostartFilePath(), std::ios_base::out | std::ios_base::trunc};
if (!optionFile.good())
return false;
- std::string chain = gArgs.GetChainName();
+ ChainType chain = gArgs.GetChainType();
// Write a bitcoin.desktop file to the autostart directory:
optionFile << "[Desktop Entry]\n";
optionFile << "Type=Application\n";
- if (chain == CBaseChainParams::MAIN)
+ if (chain == ChainType::MAIN)
optionFile << "Name=Bitcoin\n";
else
- optionFile << strprintf("Name=Bitcoin (%s)\n", chain);
- optionFile << "Exec=" << pszExePath << strprintf(" -min -chain=%s\n", chain);
+ optionFile << strprintf("Name=Bitcoin (%s)\n", ChainTypeToString(chain));
+ optionFile << "Exec=" << pszExePath << strprintf(" -min -chain=%s\n", ChainTypeToString(chain));
optionFile << "Terminal=false\n";
optionFile << "Hidden=false\n";
optionFile.close();
diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp
index a54ba19354..f86b167076 100644
--- a/src/qt/intro.cpp
+++ b/src/qt/intro.cpp
@@ -9,6 +9,7 @@
#include <chainparams.h>
#include <qt/intro.h>
#include <qt/forms/ui_intro.h>
+#include <util/chaintype.h>
#include <util/fs.h>
#include <qt/guiconstants.h>
@@ -219,7 +220,7 @@ bool Intro::showIfNeeded(bool& did_show_intro, int64_t& prune_MiB)
{
/* Use selectParams here to guarantee Params() can be used by node interface */
try {
- SelectParams(gArgs.GetChainName());
+ SelectParams(gArgs.GetChainType());
} catch (const std::exception&) {
return false;
}
diff --git a/src/qt/networkstyle.cpp b/src/qt/networkstyle.cpp
index b789e6a958..b6314f5533 100644
--- a/src/qt/networkstyle.cpp
+++ b/src/qt/networkstyle.cpp
@@ -6,21 +6,21 @@
#include <qt/guiconstants.h>
-#include <chainparamsbase.h>
#include <tinyformat.h>
+#include <util/chaintype.h>
#include <QApplication>
static const struct {
- const char *networkId;
+ const ChainType networkId;
const char *appName;
const int iconColorHueShift;
const int iconColorSaturationReduction;
} network_styles[] = {
- {"main", QAPP_APP_NAME_DEFAULT, 0, 0},
- {"test", QAPP_APP_NAME_TESTNET, 70, 30},
- {"signet", QAPP_APP_NAME_SIGNET, 35, 15},
- {"regtest", QAPP_APP_NAME_REGTEST, 160, 30},
+ {ChainType::MAIN, QAPP_APP_NAME_DEFAULT, 0, 0},
+ {ChainType::TESTNET, QAPP_APP_NAME_TESTNET, 70, 30},
+ {ChainType::SIGNET, QAPP_APP_NAME_SIGNET, 35, 15},
+ {ChainType::REGTEST, QAPP_APP_NAME_REGTEST, 160, 30},
};
// titleAddText needs to be const char* for tr()
@@ -77,9 +77,9 @@ NetworkStyle::NetworkStyle(const QString &_appName, const int iconColorHueShift,
trayAndWindowIcon = QIcon(pixmap.scaled(QSize(256,256)));
}
-const NetworkStyle* NetworkStyle::instantiate(const std::string& networkId)
+const NetworkStyle* NetworkStyle::instantiate(const ChainType networkId)
{
- std::string titleAddText = networkId == CBaseChainParams::MAIN ? "" : strprintf("[%s]", networkId);
+ std::string titleAddText = networkId == ChainType::MAIN ? "" : strprintf("[%s]", ChainTypeToString(networkId));
for (const auto& network_style : network_styles) {
if (networkId == network_style.networkId) {
return new NetworkStyle(
diff --git a/src/qt/networkstyle.h b/src/qt/networkstyle.h
index a73e3e2625..dd2aee3eb3 100644
--- a/src/qt/networkstyle.h
+++ b/src/qt/networkstyle.h
@@ -5,6 +5,8 @@
#ifndef BITCOIN_QT_NETWORKSTYLE_H
#define BITCOIN_QT_NETWORKSTYLE_H
+#include <util/chaintype.h>
+
#include <QIcon>
#include <QPixmap>
#include <QString>
@@ -14,7 +16,7 @@ class NetworkStyle
{
public:
/** Get style associated with provided network id, or 0 if not known */
- static const NetworkStyle* instantiate(const std::string& networkId);
+ static const NetworkStyle* instantiate(const ChainType networkId);
const QString &getAppName() const { return appName; }
const QIcon &getAppIcon() const { return appIcon; }
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 76500a4a36..bac64e3d5f 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -249,7 +249,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
subelement = lastResult[parsed.value()];
}
else if (lastResult.isObject())
- subelement = find_value(lastResult, curarg);
+ subelement = lastResult.find_value(curarg);
else
throw std::runtime_error("Invalid result query"); //no array or object: abort
lastResult = subelement;
@@ -448,8 +448,8 @@ void RPCExecutor::request(const QString &command, const WalletModel* wallet_mode
{
try // Nice formatting for standard-format error
{
- int code = find_value(objError, "code").getInt<int>();
- std::string message = find_value(objError, "message").get_str();
+ int code = objError.find_value("code").getInt<int>();
+ std::string message = objError.find_value("message").get_str();
Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
}
catch (const std::runtime_error&) // raised when converting to invalid type, i.e. missing code or message
@@ -744,7 +744,7 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_
ui->dataDir->setText(model->dataDir());
ui->blocksDir->setText(model->blocksDir());
ui->startupTime->setText(model->formatClientStartupTime());
- ui->networkName->setText(QString::fromStdString(Params().NetworkIDString()));
+ ui->networkName->setText(QString::fromStdString(Params().GetChainTypeString()));
//Setup autocomplete and attach it
QStringList wordList;
diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp
index 000bbe65be..e918e84184 100644
--- a/src/qt/test/apptests.cpp
+++ b/src/qt/test/apptests.cpp
@@ -73,7 +73,7 @@ void AppTests::appTests()
qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo");
m_app.parameterSetup();
QVERIFY(m_app.createOptionsModel(/*resetSettings=*/true));
- QScopedPointer<const NetworkStyle> style(NetworkStyle::instantiate(Params().NetworkIDString()));
+ QScopedPointer<const NetworkStyle> style(NetworkStyle::instantiate(Params().GetChainType()));
m_app.setupPlatformStyle();
m_app.createWindow(style.data());
connect(&m_app, &BitcoinApplication::windowShown, this, &AppTests::guiTests);
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index 2d069f76a0..eaadbd7f7a 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -14,6 +14,7 @@
#include <qt/test/rpcnestedtests.h>
#include <qt/test/uritests.h>
#include <test/util/setup_common.h>
+#include <util/chaintype.h>
#ifdef ENABLE_WALLET
#include <qt/test/addressbooktests.h>
@@ -57,7 +58,7 @@ int main(int argc, char* argv[])
//
// All tests must use their own testing setup (if needed).
fs::create_directories([] {
- BasicTestingSetup dummy{CBaseChainParams::REGTEST};
+ BasicTestingSetup dummy{ChainType::REGTEST};
return gArgs.GetDataDirNet() / "blocks";
}());
diff --git a/src/rest.cpp b/src/rest.cpp
index e46406f1ad..dae064f89d 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -36,7 +36,6 @@
using node::GetTransaction;
using node::NodeContext;
-using node::ReadBlockFromDisk;
static const size_t MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once
static constexpr unsigned int MAX_REST_HEADERS_RESULTS = 2000;
@@ -311,7 +310,7 @@ static bool rest_block(const std::any& context,
}
- if (!ReadBlockFromDisk(block, pblockindex, chainman.GetParams().GetConsensus())) {
+ if (!chainman.m_blockman.ReadBlockFromDisk(block, *pblockindex)) {
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
}
@@ -716,7 +715,7 @@ static bool rest_tx(const std::any& context, HTTPRequest* req, const std::string
const NodeContext* const node = GetNodeContext(context, req);
if (!node) return false;
uint256 hashBlock = uint256();
- const CTransactionRef tx = GetTransaction(/*block_index=*/nullptr, node->mempool.get(), hash, Params().GetConsensus(), hashBlock);
+ const CTransactionRef tx = GetTransaction(/*block_index=*/nullptr, node->mempool.get(), hash, hashBlock, node->chainman->m_blockman);
if (!tx) {
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
}
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 11484a9d8d..72866532d2 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -58,9 +58,7 @@ using kernel::CoinStatsHashType;
using node::BlockManager;
using node::NodeContext;
-using node::ReadBlockFromDisk;
using node::SnapshotMetadata;
-using node::UndoReadFromDisk;
struct CUpdatedBlock
{
@@ -183,7 +181,7 @@ UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIn
case TxVerbosity::SHOW_DETAILS_AND_PREVOUT:
CBlockUndo blockUndo;
const bool is_not_pruned{WITH_LOCK(::cs_main, return !blockman.IsBlockPruned(blockindex))};
- const bool have_undo{is_not_pruned && UndoReadFromDisk(blockUndo, blockindex)};
+ const bool have_undo{is_not_pruned && blockman.UndoReadFromDisk(blockUndo, *blockindex)};
for (size_t i = 0; i < block.vtx.size(); ++i) {
const CTransactionRef& tx = block.vtx.at(i);
@@ -587,7 +585,7 @@ static CBlock GetBlockChecked(BlockManager& blockman, const CBlockIndex* pblocki
}
}
- if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) {
+ if (!blockman.ReadBlockFromDisk(block, *pblockindex)) {
// Block not found on disk. This could be because we have the block
// header in our index but not yet have the block or did not accept the
// block. Or if the block was pruned right after we released the lock above.
@@ -611,7 +609,7 @@ static CBlockUndo GetUndoChecked(BlockManager& blockman, const CBlockIndex* pblo
}
}
- if (!UndoReadFromDisk(blockUndo, pblockindex)) {
+ if (!blockman.UndoReadFromDisk(blockUndo, *pblockindex)) {
throw JSONRPCError(RPC_MISC_ERROR, "Can't read undo data from disk");
}
@@ -1256,7 +1254,7 @@ RPCHelpMan getblockchaininfo()
const CBlockIndex& tip{*CHECK_NONFATAL(active_chainstate.m_chain.Tip())};
const int height{tip.nHeight};
UniValue obj(UniValue::VOBJ);
- obj.pushKV("chain", chainman.GetParams().NetworkIDString());
+ obj.pushKV("chain", chainman.GetParams().GetChainTypeString());
obj.pushKV("blocks", height);
obj.pushKV("headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1);
obj.pushKV("bestblockhash", tip.GetBlockHash().GetHex());
diff --git a/src/rpc/external_signer.cpp b/src/rpc/external_signer.cpp
index 1e139c9990..ac135ba216 100644
--- a/src/rpc/external_signer.cpp
+++ b/src/rpc/external_signer.cpp
@@ -2,7 +2,6 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <chainparamsbase.h>
#include <common/args.h>
#include <external_signer.h>
#include <rpc/protocol.h>
@@ -43,7 +42,7 @@ static RPCHelpMan enumeratesigners()
{
const std::string command = gArgs.GetArg("-signer", "");
if (command == "") throw JSONRPCError(RPC_MISC_ERROR, "Error: restart bitcoind with -signer=<cmd>");
- const std::string chain = gArgs.GetChainName();
+ const std::string chain = gArgs.GetChainTypeString();
UniValue signers_res = UniValue::VARR;
try {
std::vector<ExternalSigner> signers;
diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp
index 927b4ce1fc..89c403b6f5 100644
--- a/src/rpc/mempool.cpp
+++ b/src/rpc/mempool.cpp
@@ -638,7 +638,7 @@ static RPCHelpMan gettxspendingprevout()
}, /*fAllowNull=*/false, /*fStrict=*/true);
const uint256 txid(ParseHashO(o, "txid"));
- const int nOutput{find_value(o, "vout").getInt<int>()};
+ const int nOutput{o.find_value("vout").getInt<int>()};
if (nOutput < 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
}
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index d55e20ba5e..68017e5af2 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -435,7 +435,7 @@ static RPCHelpMan getmininginfo()
obj.pushKV("difficulty", (double)GetDifficulty(active_chain.Tip()));
obj.pushKV("networkhashps", getnetworkhashps().HandleRequest(request));
obj.pushKV("pooledtx", (uint64_t)mempool.size());
- obj.pushKV("chain", chainman.GetParams().NetworkIDString());
+ obj.pushKV("chain", chainman.GetParams().GetChainTypeString());
obj.pushKV("warnings", GetWarnings(false).original);
return obj;
},
@@ -612,7 +612,7 @@ static RPCHelpMan getblocktemplate()
if (!request.params[0].isNull())
{
const UniValue& oparam = request.params[0].get_obj();
- const UniValue& modeval = find_value(oparam, "mode");
+ const UniValue& modeval = oparam.find_value("mode");
if (modeval.isStr())
strMode = modeval.get_str();
else if (modeval.isNull())
@@ -621,11 +621,11 @@ static RPCHelpMan getblocktemplate()
}
else
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
- lpval = find_value(oparam, "longpollid");
+ lpval = oparam.find_value("longpollid");
if (strMode == "proposal")
{
- const UniValue& dataval = find_value(oparam, "data");
+ const UniValue& dataval = oparam.find_value("data");
if (!dataval.isStr())
throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
@@ -652,7 +652,7 @@ static RPCHelpMan getblocktemplate()
return BIP22ValidationResult(state);
}
- const UniValue& aClientRules = find_value(oparam, "rules");
+ const UniValue& aClientRules = oparam.find_value("rules");
if (aClientRules.isArray()) {
for (unsigned int i = 0; i < aClientRules.size(); ++i) {
const UniValue& v = aClientRules[i];
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 7ffa777ef4..f247e6ee91 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -21,6 +21,7 @@
#include <rpc/util.h>
#include <sync.h>
#include <timedata.h>
+#include <util/chaintype.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/time.h>
@@ -354,7 +355,7 @@ static RPCHelpMan addconnection()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- if (Params().NetworkIDString() != CBaseChainParams::REGTEST) {
+ if (Params().GetChainType() != ChainType::REGTEST) {
throw std::runtime_error("addconnection is for regression testing (-regtest mode) only.");
}
@@ -512,15 +513,15 @@ static RPCHelpMan getaddednodeinfo()
static RPCHelpMan getnettotals()
{
return RPCHelpMan{"getnettotals",
- "\nReturns information about network traffic, including bytes in, bytes out,\n"
- "and current time.\n",
- {},
+ "Returns information about network traffic, including bytes in, bytes out,\n"
+ "and current system time.",
+ {},
RPCResult{
RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::NUM, "totalbytesrecv", "Total bytes received"},
{RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"},
- {RPCResult::Type::NUM_TIME, "timemillis", "Current " + UNIX_EPOCH_TIME + " in milliseconds"},
+ {RPCResult::Type::NUM_TIME, "timemillis", "Current system " + UNIX_EPOCH_TIME + " in milliseconds"},
{RPCResult::Type::OBJ, "uploadtarget", "",
{
{RPCResult::Type::NUM, "timeframe", "Length of the measuring timeframe in seconds"},
@@ -544,7 +545,7 @@ static RPCHelpMan getnettotals()
UniValue obj(UniValue::VOBJ);
obj.pushKV("totalbytesrecv", connman.GetTotalBytesRecv());
obj.pushKV("totalbytessent", connman.GetTotalBytesSent());
- obj.pushKV("timemillis", GetTimeMillis());
+ obj.pushKV("timemillis", TicksSinceEpoch<std::chrono::milliseconds>(SystemClock::now()));
UniValue outboundLimit(UniValue::VOBJ);
outboundLimit.pushKV("timeframe", count_seconds(connman.GetMaxOutboundTimeframe()));
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 4a918cbd42..464be66046 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -51,8 +51,6 @@ using node::FindCoins;
using node::GetTransaction;
using node::NodeContext;
using node::PSBTAnalysis;
-using node::ReadBlockFromDisk;
-using node::UndoReadFromDisk;
static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry,
Chainstate& active_chainstate, const CTxUndo* txundo = nullptr,
@@ -362,7 +360,7 @@ static RPCHelpMan getrawtransaction()
}
uint256 hash_block;
- const CTransactionRef tx = GetTransaction(blockindex, node.mempool.get(), hash, chainman.GetConsensus(), hash_block);
+ const CTransactionRef tx = GetTransaction(blockindex, node.mempool.get(), hash, hash_block, chainman.m_blockman);
if (!tx) {
std::string errmsg;
if (blockindex) {
@@ -406,7 +404,7 @@ static RPCHelpMan getrawtransaction()
if (tx->IsCoinBase() ||
!blockindex || is_block_pruned ||
- !(UndoReadFromDisk(blockUndo, blockindex) && ReadBlockFromDisk(block, blockindex, Params().GetConsensus()))) {
+ !(chainman.m_blockman.UndoReadFromDisk(blockUndo, *blockindex) && chainman.m_blockman.ReadBlockFromDisk(block, *blockindex))) {
TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate());
return result;
}
diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp
index 3ba930f84f..3a6fa39e4d 100644
--- a/src/rpc/rawtransaction_util.cpp
+++ b/src/rpc/rawtransaction_util.cpp
@@ -36,7 +36,7 @@ void AddInputs(CMutableTransaction& rawTx, const UniValue& inputs_in, std::optio
uint256 txid = ParseHashO(o, "txid");
- const UniValue& vout_v = find_value(o, "vout");
+ const UniValue& vout_v = o.find_value("vout");
if (!vout_v.isNum())
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
int nOutput = vout_v.getInt<int>();
@@ -54,7 +54,7 @@ void AddInputs(CMutableTransaction& rawTx, const UniValue& inputs_in, std::optio
}
// set the sequence number if passed in the parameters object
- const UniValue& sequenceObj = find_value(o, "sequence");
+ const UniValue& sequenceObj = o.find_value("sequence");
if (sequenceObj.isNum()) {
int64_t seqNr64 = sequenceObj.getInt<int64_t>();
if (seqNr64 < 0 || seqNr64 > CTxIn::SEQUENCE_FINAL) {
@@ -187,7 +187,7 @@ void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keyst
uint256 txid = ParseHashO(prevOut, "txid");
- int nOut = find_value(prevOut, "vout").getInt<int>();
+ int nOut = prevOut.find_value("vout").getInt<int>();
if (nOut < 0) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout cannot be negative");
}
@@ -208,7 +208,7 @@ void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keyst
newcoin.out.scriptPubKey = scriptPubKey;
newcoin.out.nValue = MAX_MONEY;
if (prevOut.exists("amount")) {
- newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
+ newcoin.out.nValue = AmountFromValue(prevOut.find_value("amount"));
}
newcoin.nHeight = 1;
coins[out] = std::move(newcoin);
@@ -223,8 +223,8 @@ void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keyst
{"redeemScript", UniValueType(UniValue::VSTR)},
{"witnessScript", UniValueType(UniValue::VSTR)},
}, true);
- UniValue rs = find_value(prevOut, "redeemScript");
- UniValue ws = find_value(prevOut, "witnessScript");
+ const UniValue& rs{prevOut.find_value("redeemScript")};
+ const UniValue& ws{prevOut.find_value("witnessScript")};
if (rs.isNull() && ws.isNull()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Missing redeemScript/witnessScript");
}
diff --git a/src/rpc/request.cpp b/src/rpc/request.cpp
index ad91ed0f23..cf1b6cd92b 100644
--- a/src/rpc/request.cpp
+++ b/src/rpc/request.cpp
@@ -165,10 +165,10 @@ void JSONRPCRequest::parse(const UniValue& valRequest)
const UniValue& request = valRequest.get_obj();
// Parse id now so errors from here on will have the id
- id = find_value(request, "id");
+ id = request.find_value("id");
// Parse method
- UniValue valMethod = find_value(request, "method");
+ const UniValue& valMethod{request.find_value("method")};
if (valMethod.isNull())
throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
if (!valMethod.isStr())
@@ -181,7 +181,7 @@ void JSONRPCRequest::parse(const UniValue& valRequest)
LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n", SanitizeString(strMethod), this->authUser);
// Parse params
- UniValue valParams = find_value(request, "params");
+ const UniValue& valParams{request.find_value("params")};
if (valParams.isArray() || valParams.isObject())
params = valParams;
else if (valParams.isNull())
diff --git a/src/rpc/txoutproof.cpp b/src/rpc/txoutproof.cpp
index 24b5d04115..d74959cecc 100644
--- a/src/rpc/txoutproof.cpp
+++ b/src/rpc/txoutproof.cpp
@@ -18,7 +18,6 @@
#include <validation.h>
using node::GetTransaction;
-using node::ReadBlockFromDisk;
static RPCHelpMan gettxoutproof()
{
@@ -85,7 +84,7 @@ static RPCHelpMan gettxoutproof()
}
if (pblockindex == nullptr) {
- const CTransactionRef tx = GetTransaction(/*block_index=*/nullptr, /*mempool=*/nullptr, *setTxids.begin(), chainman.GetConsensus(), hashBlock);
+ const CTransactionRef tx = GetTransaction(/*block_index=*/nullptr, /*mempool=*/nullptr, *setTxids.begin(), hashBlock, chainman.m_blockman);
if (!tx || hashBlock.IsNull()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
}
@@ -98,7 +97,7 @@ static RPCHelpMan gettxoutproof()
}
CBlock block;
- if (!ReadBlockFromDisk(block, pblockindex, chainman.GetConsensus())) {
+ if (!chainman.m_blockman.ReadBlockFromDisk(block, *pblockindex)) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
}
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index 1f3f37d0a0..81489d7cec 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -37,7 +37,7 @@ void RPCTypeCheckObj(const UniValue& o,
bool fStrict)
{
for (const auto& t : typesExpected) {
- const UniValue& v = find_value(o, t.first);
+ const UniValue& v = o.find_value(t.first);
if (!fAllowNull && v.isNull())
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first));
@@ -81,7 +81,7 @@ uint256 ParseHashV(const UniValue& v, std::string strName)
}
uint256 ParseHashO(const UniValue& o, std::string strKey)
{
- return ParseHashV(find_value(o, strKey), strKey);
+ return ParseHashV(o.find_value(strKey), strKey);
}
std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName)
{
@@ -94,7 +94,7 @@ std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName)
}
std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey)
{
- return ParseHexV(find_value(o, strKey), strKey);
+ return ParseHexV(o.find_value(strKey), strKey);
}
namespace {
@@ -1133,10 +1133,10 @@ std::vector<CScript> EvalDescriptorStringOrObject(const UniValue& scanobject, Fl
if (scanobject.isStr()) {
desc_str = scanobject.get_str();
} else if (scanobject.isObject()) {
- UniValue desc_uni = find_value(scanobject, "desc");
+ const UniValue& desc_uni{scanobject.find_value("desc")};
if (desc_uni.isNull()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Descriptor needs to be provided in scan object");
desc_str = desc_uni.get_str();
- UniValue range_uni = find_value(scanobject, "range");
+ const UniValue& range_uni{scanobject.find_value("range")};
if (!range_uni.isNull()) {
range = ParseDescriptorRange(range_uni);
}
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index 0951504ee0..b8ade1684a 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -197,7 +197,9 @@ public:
/** Get the descriptor string form including private data (if available in arg). */
virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0;
- /** Get the descriptor string form with the xpub at the last hardened derivation */
+ /** Get the descriptor string form with the xpub at the last hardened derivation,
+ * and always use h for hardened derivation.
+ */
virtual bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache = nullptr) const = 0;
/** Derive a private key, if private data is available in arg. */
@@ -208,14 +210,15 @@ class OriginPubkeyProvider final : public PubkeyProvider
{
KeyOriginInfo m_origin;
std::unique_ptr<PubkeyProvider> m_provider;
+ bool m_apostrophe;
- std::string OriginString() const
+ std::string OriginString(bool normalized=false) const
{
- return HexStr(m_origin.fingerprint) + FormatHDKeypath(m_origin.path);
+ return HexStr(m_origin.fingerprint) + FormatHDKeypath(m_origin.path, /*apostrophe=*/!normalized && m_apostrophe);
}
public:
- OriginPubkeyProvider(uint32_t exp_index, KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider) : PubkeyProvider(exp_index), m_origin(std::move(info)), m_provider(std::move(provider)) {}
+ OriginPubkeyProvider(uint32_t exp_index, KeyOriginInfo info, std::unique_ptr<PubkeyProvider> provider, bool apostrophe) : PubkeyProvider(exp_index), m_origin(std::move(info)), m_provider(std::move(provider)), m_apostrophe(apostrophe) {}
bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key, KeyOriginInfo& info, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const override
{
if (!m_provider->GetPubKey(pos, arg, key, info, read_cache, write_cache)) return false;
@@ -242,9 +245,9 @@ public:
// and append that to our own origin string.
if (sub[0] == '[') {
sub = sub.substr(9);
- ret = "[" + OriginString() + std::move(sub);
+ ret = "[" + OriginString(/*normalized=*/true) + std::move(sub);
} else {
- ret = "[" + OriginString() + "]" + std::move(sub);
+ ret = "[" + OriginString(/*normalized=*/true) + "]" + std::move(sub);
}
return true;
}
@@ -312,6 +315,8 @@ class BIP32PubkeyProvider final : public PubkeyProvider
CExtPubKey m_root_extkey;
KeyPath m_path;
DeriveType m_derive;
+ // Whether ' or h is used in harded derivation
+ bool m_apostrophe;
bool GetExtKey(const SigningProvider& arg, CExtKey& ret) const
{
@@ -348,7 +353,7 @@ class BIP32PubkeyProvider final : public PubkeyProvider
}
public:
- BIP32PubkeyProvider(uint32_t exp_index, const CExtPubKey& extkey, KeyPath path, DeriveType derive) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(std::move(path)), m_derive(derive) {}
+ BIP32PubkeyProvider(uint32_t exp_index, const CExtPubKey& extkey, KeyPath path, DeriveType derive, bool apostrophe) : PubkeyProvider(exp_index), m_root_extkey(extkey), m_path(std::move(path)), m_derive(derive), m_apostrophe(apostrophe) {}
bool IsRange() const override { return m_derive != DeriveType::NO; }
size_t GetSize() const override { return 33; }
bool GetPubKey(int pos, const SigningProvider& arg, CPubKey& key_out, KeyOriginInfo& final_info_out, const DescriptorCache* read_cache = nullptr, DescriptorCache* write_cache = nullptr) const override
@@ -416,31 +421,36 @@ public:
return true;
}
- std::string ToString() const override
+ std::string ToString(bool normalized) const
{
- std::string ret = EncodeExtPubKey(m_root_extkey) + FormatHDKeypath(m_path);
+ const bool use_apostrophe = !normalized && m_apostrophe;
+ std::string ret = EncodeExtPubKey(m_root_extkey) + FormatHDKeypath(m_path, /*apostrophe=*/use_apostrophe);
if (IsRange()) {
ret += "/*";
- if (m_derive == DeriveType::HARDENED) ret += '\'';
+ if (m_derive == DeriveType::HARDENED) ret += use_apostrophe ? '\'' : 'h';
}
return ret;
}
+ std::string ToString() const override
+ {
+ return ToString(/*normalized=*/false);
+ }
bool ToPrivateString(const SigningProvider& arg, std::string& out) const override
{
CExtKey key;
if (!GetExtKey(arg, key)) return false;
- out = EncodeExtKey(key) + FormatHDKeypath(m_path);
+ out = EncodeExtKey(key) + FormatHDKeypath(m_path, /*apostrophe=*/m_apostrophe);
if (IsRange()) {
out += "/*";
- if (m_derive == DeriveType::HARDENED) out += '\'';
+ if (m_derive == DeriveType::HARDENED) out += m_apostrophe ? '\'' : 'h';
}
return true;
}
bool ToNormalizedString(const SigningProvider& arg, std::string& out, const DescriptorCache* cache) const override
{
- // For hardened derivation type, just return the typical string, nothing to normalize
if (m_derive == DeriveType::HARDENED) {
- out = ToString();
+ out = ToString(/*normalized=*/true);
+
return true;
}
// Step backwards to find the last hardened step in the path
@@ -1049,15 +1059,27 @@ enum class ParseScriptContext {
P2TR, //!< Inside tr() (either internal key, or BIP342 script leaf)
};
-/** Parse a key path, being passed a split list of elements (the first element is ignored). */
-[[nodiscard]] bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out, std::string& error)
+/**
+ * Parse a key path, being passed a split list of elements (the first element is ignored).
+ *
+ * @param[in] split BIP32 path string, using either ' or h for hardened derivation
+ * @param[out] out the key path
+ * @param[out] apostrophe only updated if hardened derivation is found
+ * @param[out] error parsing error message
+ * @returns false if parsing failed
+ **/
+[[nodiscard]] bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out, bool& apostrophe, std::string& error)
{
for (size_t i = 1; i < split.size(); ++i) {
Span<const char> elem = split[i];
bool hardened = false;
- if (elem.size() > 0 && (elem[elem.size() - 1] == '\'' || elem[elem.size() - 1] == 'h')) {
- elem = elem.first(elem.size() - 1);
- hardened = true;
+ if (elem.size() > 0) {
+ const char last = elem[elem.size() - 1];
+ if (last == '\'' || last == 'h') {
+ elem = elem.first(elem.size() - 1);
+ hardened = true;
+ apostrophe = last == '\'';
+ }
}
uint32_t p;
if (!ParseUInt32(std::string(elem.begin(), elem.end()), &p)) {
@@ -1073,7 +1095,7 @@ enum class ParseScriptContext {
}
/** Parse a public key that excludes origin information. */
-std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index, const Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error)
+std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index, const Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, bool& apostrophe, std::string& error)
{
using namespace spanparsing;
@@ -1130,15 +1152,16 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index, const S
split.pop_back();
type = DeriveType::UNHARDENED;
} else if (split.back() == Span{"*'"}.first(2) || split.back() == Span{"*h"}.first(2)) {
+ apostrophe = split.back() == Span{"*'"}.first(2);
split.pop_back();
type = DeriveType::HARDENED;
}
- if (!ParseKeyPath(split, path, error)) return nullptr;
+ if (!ParseKeyPath(split, path, apostrophe, error)) return nullptr;
if (extkey.key.IsValid()) {
extpubkey = extkey.Neuter();
out.keys.emplace(extpubkey.pubkey.GetID(), extkey.key);
}
- return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type);
+ return std::make_unique<BIP32PubkeyProvider>(key_exp_index, extpubkey, std::move(path), type, apostrophe);
}
/** Parse a public key including origin information (if enabled). */
@@ -1151,7 +1174,11 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index, const Span<c
error = "Multiple ']' characters found for a single pubkey";
return nullptr;
}
- if (origin_split.size() == 1) return ParsePubkeyInner(key_exp_index, origin_split[0], ctx, out, error);
+ // This is set if either the origin or path suffix contains a hardened derivation.
+ bool apostrophe = false;
+ if (origin_split.size() == 1) {
+ return ParsePubkeyInner(key_exp_index, origin_split[0], ctx, out, apostrophe, error);
+ }
if (origin_split[0].empty() || origin_split[0][0] != '[') {
error = strprintf("Key origin start '[ character expected but not found, got '%c' instead",
origin_split[0].empty() ? /** empty, implies split char */ ']' : origin_split[0][0]);
@@ -1172,10 +1199,10 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(uint32_t key_exp_index, const Span<c
static_assert(sizeof(info.fingerprint) == 4, "Fingerprint must be 4 bytes");
assert(fpr_bytes.size() == 4);
std::copy(fpr_bytes.begin(), fpr_bytes.end(), info.fingerprint);
- if (!ParseKeyPath(slash_split, info.path, error)) return nullptr;
- auto provider = ParsePubkeyInner(key_exp_index, origin_split[1], ctx, out, error);
+ if (!ParseKeyPath(slash_split, info.path, apostrophe, error)) return nullptr;
+ auto provider = ParsePubkeyInner(key_exp_index, origin_split[1], ctx, out, apostrophe, error);
if (!provider) return nullptr;
- return std::make_unique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider));
+ return std::make_unique<OriginPubkeyProvider>(key_exp_index, std::move(info), std::move(provider), apostrophe);
}
std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptContext, const SigningProvider& provider)
@@ -1183,7 +1210,7 @@ std::unique_ptr<PubkeyProvider> InferPubkey(const CPubKey& pubkey, ParseScriptCo
std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, false);
KeyOriginInfo info;
if (provider.GetKeyOrigin(pubkey.GetID(), info)) {
- return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
+ return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider), /*apostrophe=*/false);
}
return key_provider;
}
@@ -1196,7 +1223,7 @@ std::unique_ptr<PubkeyProvider> InferXOnlyPubkey(const XOnlyPubKey& xkey, ParseS
std::unique_ptr<PubkeyProvider> key_provider = std::make_unique<ConstPubkeyProvider>(0, pubkey, true);
KeyOriginInfo info;
if (provider.GetKeyOriginByXOnly(xkey, info)) {
- return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider));
+ return std::make_unique<OriginPubkeyProvider>(0, std::move(info), std::move(key_provider), /*apostrophe=*/false);
}
return key_provider;
}
diff --git a/src/streams.h b/src/streams.h
index 8788343809..e346aa0a3f 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -756,15 +756,25 @@ public:
}
//! search for a given byte in the stream, and remain positioned on it
- void FindByte(uint8_t ch)
+ void FindByte(std::byte byte)
{
+ // For best performance, avoid mod operation within the loop.
+ size_t buf_offset{size_t(m_read_pos % uint64_t(vchBuf.size()))};
while (true) {
- if (m_read_pos == nSrcPos)
+ if (m_read_pos == nSrcPos) {
+ // No more bytes available; read from the file into the buffer,
+ // setting nSrcPos to one beyond the end of the new data.
+ // Throws exception if end-of-file reached.
Fill();
- if (vchBuf[m_read_pos % vchBuf.size()] == std::byte{ch}) {
- break;
}
- m_read_pos++;
+ const size_t len{std::min<size_t>(vchBuf.size() - buf_offset, nSrcPos - m_read_pos)};
+ const auto it_start{vchBuf.begin() + buf_offset};
+ const auto it_find{std::find(it_start, it_start + len, byte)};
+ const size_t inc{size_t(std::distance(it_start, it_find))};
+ m_read_pos += inc;
+ if (inc < len) break;
+ buf_offset += inc;
+ if (buf_offset >= vchBuf.size()) buf_offset = 0;
}
}
};
diff --git a/src/test/argsman_tests.cpp b/src/test/argsman_tests.cpp
index 6a0925f0bb..48bffc4ac9 100644
--- a/src/test/argsman_tests.cpp
+++ b/src/test/argsman_tests.cpp
@@ -8,6 +8,7 @@
#include <test/util/setup_common.h>
#include <test/util/str.h>
#include <univalue.h>
+#include <util/chaintype.h>
#include <util/fs.h>
#include <util/strencodings.h>
@@ -254,7 +255,7 @@ BOOST_AUTO_TEST_CASE(util_ParseInvalidParameters)
BOOST_CHECK(!test.ParseParameters(2, (char**)argv, error));
BOOST_CHECK_EQUAL(error, "Invalid parameter -unregistered");
- // Make sure registered parameters prefixed with a chain name trigger errors.
+ // Make sure registered parameters prefixed with a chain type trigger errors.
// (Previously, they were accepted and ignored.)
argv[1] = "-test.registered";
BOOST_CHECK(!test.ParseParameters(2, (char**)argv, error));
@@ -580,7 +581,7 @@ BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
test_args.SetNetworkOnlyArg("-ccc");
test_args.SetNetworkOnlyArg("-h");
- test_args.SelectConfigNetwork(CBaseChainParams::MAIN);
+ test_args.SelectConfigNetwork(ChainTypeToString(ChainType::MAIN));
BOOST_CHECK(test_args.GetArg("-d", "xxx") == "e");
BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
@@ -637,7 +638,7 @@ BOOST_AUTO_TEST_CASE(util_GetArg)
BOOST_CHECK_EQUAL(testArgs.GetArg("pritest4", "default"), "b");
}
-BOOST_AUTO_TEST_CASE(util_GetChainName)
+BOOST_AUTO_TEST_CASE(util_GetChainTypeString)
{
TestArgsManager test_args;
const auto testnet = std::make_pair("-testnet", ArgsManager::ALLOW_ANY);
@@ -655,39 +656,39 @@ BOOST_AUTO_TEST_CASE(util_GetChainName)
std::string error;
BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error));
- BOOST_CHECK_EQUAL(test_args.GetChainName(), "main");
+ BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "main");
BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error));
- BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+ BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test");
BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error));
- BOOST_CHECK_EQUAL(test_args.GetChainName(), "regtest");
+ BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "regtest");
BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_test_no_reg, error));
- BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+ BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test");
BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error));
- BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
+ BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error));
test_args.ReadConfigString(testnetconf);
- BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+ BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test");
BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error));
test_args.ReadConfigString(testnetconf);
- BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+ BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test");
BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error));
test_args.ReadConfigString(testnetconf);
- BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
+ BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_test_no_reg, error));
test_args.ReadConfigString(testnetconf);
- BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+ BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test");
BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error));
test_args.ReadConfigString(testnetconf);
- BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
+ BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
// check setting the network to test (and thus making
// [test] regtest=1 potentially relevant) doesn't break things
@@ -695,23 +696,23 @@ BOOST_AUTO_TEST_CASE(util_GetChainName)
BOOST_CHECK(test_args.ParseParameters(0, (char**)argv_testnet, error));
test_args.ReadConfigString(testnetconf);
- BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+ BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test");
BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_testnet, error));
test_args.ReadConfigString(testnetconf);
- BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+ BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test");
BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_regtest, error));
test_args.ReadConfigString(testnetconf);
- BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
+ BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
BOOST_CHECK(test_args.ParseParameters(2, (char**)argv_test_no_reg, error));
test_args.ReadConfigString(testnetconf);
- BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+ BOOST_CHECK_EQUAL(test_args.GetChainTypeString(), "test");
BOOST_CHECK(test_args.ParseParameters(3, (char**)argv_both, error));
test_args.ReadConfigString(testnetconf);
- BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
+ BOOST_CHECK_THROW(test_args.GetChainTypeString(), std::runtime_error);
}
// Test different ways settings can be merged, and verify results. This test can
@@ -755,8 +756,8 @@ struct ArgsMergeTestingSetup : public BasicTestingSetup {
ForEachNoDup(conf_actions, SET, SECTION_NEGATE, [&] {
for (bool soft_set : {false, true}) {
for (bool force_set : {false, true}) {
- for (const std::string& section : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::SIGNET}) {
- for (const std::string& network : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::SIGNET}) {
+ for (const std::string& section : {ChainTypeToString(ChainType::MAIN), ChainTypeToString(ChainType::TESTNET), ChainTypeToString(ChainType::SIGNET)}) {
+ for (const std::string& network : {ChainTypeToString(ChainType::MAIN), ChainTypeToString(ChainType::TESTNET), ChainTypeToString(ChainType::SIGNET)}) {
for (bool net_specific : {false, true}) {
fn(arg_actions, conf_actions, soft_set, force_set, section, network, net_specific);
}
@@ -913,7 +914,7 @@ BOOST_FIXTURE_TEST_CASE(util_ArgsMerge, ArgsMergeTestingSetup)
BOOST_CHECK_EQUAL(out_sha_hex, "d1e436c1cd510d0ec44d5205d4b4e3bee6387d316e0075c58206cb16603f3d82");
}
-// Similar test as above, but for ArgsManager::GetChainName function.
+// Similar test as above, but for ArgsManager::GetChainTypeString function.
struct ChainMergeTestingSetup : public BasicTestingSetup {
static constexpr int MAX_ACTIONS = 2;
@@ -982,7 +983,7 @@ BOOST_FIXTURE_TEST_CASE(util_ChainMerge, ChainMergeTestingSetup)
desc += " || ";
try {
- desc += parser.GetChainName();
+ desc += parser.GetChainTypeString();
} catch (const std::runtime_error& e) {
desc += "error: ";
desc += e.what();
diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp
index a572bb02b9..1ff5d6cf59 100644
--- a/src/test/blockfilter_index_tests.cpp
+++ b/src/test/blockfilter_index_tests.cpp
@@ -19,6 +19,7 @@
#include <boost/test/unit_test.hpp>
using node::BlockAssembler;
+using node::BlockManager;
using node::CBlockTemplate;
BOOST_AUTO_TEST_SUITE(blockfilter_index_tests)
@@ -29,10 +30,10 @@ struct BuildChainTestingSetup : public TestChain100Setup {
};
static bool CheckFilterLookups(BlockFilterIndex& filter_index, const CBlockIndex* block_index,
- uint256& last_header)
+ uint256& last_header, const BlockManager& blockman)
{
BlockFilter expected_filter;
- if (!ComputeFilter(filter_index.GetFilterType(), block_index, expected_filter)) {
+ if (!ComputeFilter(filter_index.GetFilterType(), *block_index, expected_filter, blockman)) {
BOOST_ERROR("ComputeFilter failed on block " << block_index->nHeight);
return false;
}
@@ -141,10 +142,10 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
BOOST_REQUIRE(filter_index.Start());
// Allow filter index to catch up with the block index.
- constexpr int64_t timeout_ms = 10 * 1000;
- int64_t time_start = GetTimeMillis();
+ constexpr auto timeout{10s};
+ const auto time_start{SteadyClock::now()};
while (!filter_index.BlockUntilSyncedToCurrentChain()) {
- BOOST_REQUIRE(time_start + timeout_ms > GetTimeMillis());
+ BOOST_REQUIRE(time_start + timeout > SteadyClock::now());
UninterruptibleSleep(std::chrono::milliseconds{100});
}
@@ -155,7 +156,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
for (block_index = m_node.chainman->ActiveChain().Genesis();
block_index != nullptr;
block_index = m_node.chainman->ActiveChain().Next(block_index)) {
- CheckFilterLookups(filter_index, block_index, last_header);
+ CheckFilterLookups(filter_index, block_index, last_header, m_node.chainman->m_blockman);
}
}
@@ -189,7 +190,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
}
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
- CheckFilterLookups(filter_index, block_index, chainA_last_header);
+ CheckFilterLookups(filter_index, block_index, chainA_last_header, m_node.chainman->m_blockman);
}
// Reorg to chain B.
@@ -207,7 +208,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
}
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
- CheckFilterLookups(filter_index, block_index, chainB_last_header);
+ CheckFilterLookups(filter_index, block_index, chainB_last_header, m_node.chainman->m_blockman);
}
// Check that filters for stale blocks on A can be retrieved.
@@ -221,7 +222,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
}
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
- CheckFilterLookups(filter_index, block_index, chainA_last_header);
+ CheckFilterLookups(filter_index, block_index, chainA_last_header, m_node.chainman->m_blockman);
}
// Reorg back to chain A.
@@ -241,14 +242,14 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup)
block_index = m_node.chainman->m_blockman.LookupBlockIndex(chainA[i]->GetHash());
}
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
- CheckFilterLookups(filter_index, block_index, chainA_last_header);
+ CheckFilterLookups(filter_index, block_index, chainA_last_header, m_node.chainman->m_blockman);
{
LOCK(cs_main);
block_index = m_node.chainman->m_blockman.LookupBlockIndex(chainB[i]->GetHash());
}
BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain());
- CheckFilterLookups(filter_index, block_index, chainB_last_header);
+ CheckFilterLookups(filter_index, block_index, chainB_last_header, m_node.chainman->m_blockman);
}
// Test lookups for a range of filters/hashes.
diff --git a/src/test/blockmanager_tests.cpp b/src/test/blockmanager_tests.cpp
index 2118f476cd..f094766886 100644
--- a/src/test/blockmanager_tests.cpp
+++ b/src/test/blockmanager_tests.cpp
@@ -5,6 +5,7 @@
#include <chainparams.h>
#include <node/blockstorage.h>
#include <node/context.h>
+#include <util/chaintype.h>
#include <validation.h>
#include <boost/test/unit_test.hpp>
@@ -13,31 +14,34 @@
using node::BlockManager;
using node::BLOCK_SERIALIZATION_HEADER_SIZE;
using node::MAX_BLOCKFILE_SIZE;
-using node::OpenBlockFile;
// use BasicTestingSetup here for the data directory configuration, setup, and cleanup
BOOST_FIXTURE_TEST_SUITE(blockmanager_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(blockmanager_find_block_pos)
{
- const auto params {CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN)};
- BlockManager blockman{{}};
+ const auto params {CreateChainParams(ArgsManager{}, ChainType::MAIN)};
+ const BlockManager::Options blockman_opts{
+ .chainparams = *params,
+ .blocks_dir = m_args.GetBlocksDirPath(),
+ };
+ BlockManager blockman{blockman_opts};
CChain chain {};
// simulate adding a genesis block normally
- BOOST_CHECK_EQUAL(blockman.SaveBlockToDisk(params->GenesisBlock(), 0, chain, *params, nullptr).nPos, BLOCK_SERIALIZATION_HEADER_SIZE);
+ BOOST_CHECK_EQUAL(blockman.SaveBlockToDisk(params->GenesisBlock(), 0, chain, nullptr).nPos, BLOCK_SERIALIZATION_HEADER_SIZE);
// simulate what happens during reindex
// simulate a well-formed genesis block being found at offset 8 in the blk00000.dat file
// the block is found at offset 8 because there is an 8 byte serialization header
// consisting of 4 magic bytes + 4 length bytes before each block in a well-formed blk file.
FlatFilePos pos{0, BLOCK_SERIALIZATION_HEADER_SIZE};
- BOOST_CHECK_EQUAL(blockman.SaveBlockToDisk(params->GenesisBlock(), 0, chain, *params, &pos).nPos, BLOCK_SERIALIZATION_HEADER_SIZE);
+ BOOST_CHECK_EQUAL(blockman.SaveBlockToDisk(params->GenesisBlock(), 0, chain, &pos).nPos, BLOCK_SERIALIZATION_HEADER_SIZE);
// now simulate what happens after reindex for the first new block processed
// the actual block contents don't matter, just that it's a block.
// verify that the write position is at offset 0x12d.
// this is a check to make sure that https://github.com/bitcoin/bitcoin/issues/21379 does not recur
// 8 bytes (for serialization header) + 285 (for serialized genesis block) = 293
// add another 8 bytes for the second block's serialization header and we get 293 + 8 = 301
- FlatFilePos actual{blockman.SaveBlockToDisk(params->GenesisBlock(), 1, chain, *params, nullptr)};
+ FlatFilePos actual{blockman.SaveBlockToDisk(params->GenesisBlock(), 1, chain, nullptr)};
BOOST_CHECK_EQUAL(actual.nPos, BLOCK_SERIALIZATION_HEADER_SIZE + ::GetSerializeSize(params->GenesisBlock(), CLIENT_VERSION) + BLOCK_SERIALIZATION_HEADER_SIZE);
}
@@ -63,13 +67,13 @@ BOOST_FIXTURE_TEST_CASE(blockmanager_scan_unlink_already_pruned_files, TestChain
// Check that the file is not unlinked after ScanAndUnlinkAlreadyPrunedFiles
// if m_have_pruned is not yet set
WITH_LOCK(chainman->GetMutex(), blockman.ScanAndUnlinkAlreadyPrunedFiles());
- BOOST_CHECK(!AutoFile(OpenBlockFile(pos, true)).IsNull());
+ BOOST_CHECK(!AutoFile(blockman.OpenBlockFile(pos, true)).IsNull());
// Check that the file is unlinked after ScanAndUnlinkAlreadyPrunedFiles
// once m_have_pruned is set
blockman.m_have_pruned = true;
WITH_LOCK(chainman->GetMutex(), blockman.ScanAndUnlinkAlreadyPrunedFiles());
- BOOST_CHECK(AutoFile(OpenBlockFile(pos, true)).IsNull());
+ BOOST_CHECK(AutoFile(blockman.OpenBlockFile(pos, true)).IsNull());
// Check that calling with already pruned files doesn't cause an error
WITH_LOCK(chainman->GetMutex(), blockman.ScanAndUnlinkAlreadyPrunedFiles());
@@ -79,7 +83,7 @@ BOOST_FIXTURE_TEST_CASE(blockmanager_scan_unlink_already_pruned_files, TestChain
BOOST_CHECK_NE(old_tip, new_tip);
const int new_file_number{WITH_LOCK(chainman->GetMutex(), return new_tip->GetBlockPos().nFile)};
const FlatFilePos new_pos(new_file_number, 0);
- BOOST_CHECK(!AutoFile(OpenBlockFile(new_pos, true)).IsNull());
+ BOOST_CHECK(!AutoFile(blockman.OpenBlockFile(new_pos, true)).IsNull());
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp
index 9011e703e8..cb3831071a 100644
--- a/src/test/checkqueue_tests.cpp
+++ b/src/test/checkqueue_tests.cpp
@@ -7,6 +7,7 @@
#include <sync.h>
#include <test/util/random.h>
#include <test/util/setup_common.h>
+#include <util/chaintype.h>
#include <util/time.h>
#include <boost/test/unit_test.hpp>
@@ -27,9 +28,9 @@
struct NoLockLoggingTestingSetup : public TestingSetup {
NoLockLoggingTestingSetup()
#ifdef DEBUG_LOCKCONTENTION
- : TestingSetup{CBaseChainParams::MAIN, /*extra_args=*/{"-debugexclude=lock"}} {}
+ : TestingSetup{ChainType::MAIN, /*extra_args=*/{"-debugexclude=lock"}} {}
#else
- : TestingSetup{CBaseChainParams::MAIN} {}
+ : TestingSetup{ChainType::MAIN} {}
#endif
};
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
index c4b2b4c63b..7a7790e2ae 100644
--- a/src/test/descriptor_tests.cpp
+++ b/src/test/descriptor_tests.cpp
@@ -127,7 +127,7 @@ std::set<std::pair<CPubKey, KeyOriginInfo>> GetKeyOriginData(const FlatSigningPr
return ret;
}
-void DoCheck(const std::string& prv, const std::string& pub, const std::string& norm_pub, int flags,
+void DoCheck(std::string prv, std::string pub, const std::string& norm_pub, int flags,
const std::vector<std::vector<std::string>>& scripts, const std::optional<OutputType>& type,
const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY, bool replace_apostrophe_with_h_in_prv=false,
bool replace_apostrophe_with_h_in_pub=false, uint32_t spender_nlocktime=0, uint32_t spender_nsequence=CTxIn::SEQUENCE_FINAL,
@@ -141,16 +141,14 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
std::unique_ptr<Descriptor> parse_pub;
// Check that parsing succeeds.
if (replace_apostrophe_with_h_in_prv) {
- parse_priv = Parse(UseHInsteadOfApostrophe(prv), keys_priv, error);
- } else {
- parse_priv = Parse(prv, keys_priv, error);
+ prv = UseHInsteadOfApostrophe(prv);
}
+ parse_priv = Parse(prv, keys_priv, error);
BOOST_CHECK_MESSAGE(parse_priv, error);
if (replace_apostrophe_with_h_in_pub) {
- parse_pub = Parse(UseHInsteadOfApostrophe(pub), keys_pub, error);
- } else {
- parse_pub = Parse(pub, keys_pub, error);
+ pub = UseHInsteadOfApostrophe(pub);
}
+ parse_pub = Parse(pub, keys_pub, error);
BOOST_CHECK_MESSAGE(parse_pub, error);
// Check that the correct OutputType is inferred
@@ -171,19 +169,19 @@ void DoCheck(const std::string& prv, const std::string& pub, const std::string&
if (!(flags & MISSING_PRIVKEYS)) {
std::string prv1;
BOOST_CHECK(parse_priv->ToPrivateString(keys_priv, prv1));
- BOOST_CHECK(EqualDescriptor(prv, prv1));
+ BOOST_CHECK_MESSAGE(EqualDescriptor(prv, prv1), "Private ser: " + prv1 + " Private desc: " + prv);
BOOST_CHECK(!parse_priv->ToPrivateString(keys_pub, prv1));
BOOST_CHECK(parse_pub->ToPrivateString(keys_priv, prv1));
- BOOST_CHECK(EqualDescriptor(prv, prv1));
+ BOOST_CHECK_MESSAGE(EqualDescriptor(prv, prv1), "Private ser: " + prv1 + " Private desc: " + prv);
BOOST_CHECK(!parse_pub->ToPrivateString(keys_pub, prv1));
}
// Check that private can produce the normalized descriptors
std::string norm1;
BOOST_CHECK(parse_priv->ToNormalizedString(keys_priv, norm1));
- BOOST_CHECK(EqualDescriptor(norm1, norm_pub));
+ BOOST_CHECK_MESSAGE(EqualDescriptor(norm1, norm_pub), "priv->ToNormalizedString(): " + norm1 + " Norm. desc: " + norm_pub);
BOOST_CHECK(parse_pub->ToNormalizedString(keys_priv, norm1));
- BOOST_CHECK(EqualDescriptor(norm1, norm_pub));
+ BOOST_CHECK_MESSAGE(EqualDescriptor(norm1, norm_pub), "pub->ToNormalizedString(): " + norm1 + " Norm. desc: " + norm_pub);
// Check whether IsRange on both returns the expected result
BOOST_CHECK_EQUAL(parse_pub->IsRange(), (flags & RANGE) != 0);
@@ -357,32 +355,13 @@ void Check(const std::string& prv, const std::string& pub, const std::string& no
const std::set<std::vector<uint32_t>>& paths = ONLY_EMPTY, uint32_t spender_nlocktime=0,
uint32_t spender_nsequence=CTxIn::SEQUENCE_FINAL, std::map<std::vector<uint8_t>, std::vector<uint8_t>> preimages={})
{
- bool found_apostrophes_in_prv = false;
- bool found_apostrophes_in_pub = false;
-
// Do not replace apostrophes with 'h' in prv and pub
DoCheck(prv, pub, norm_pub, flags, scripts, type, paths, /*replace_apostrophe_with_h_in_prv=*/false,
/*replace_apostrophe_with_h_in_pub=*/false, /*spender_nlocktime=*/spender_nlocktime,
/*spender_nsequence=*/spender_nsequence, /*preimages=*/preimages);
- // Replace apostrophes with 'h' in prv but not in pub, if apostrophes are found in prv
- if (prv.find('\'') != std::string::npos) {
- found_apostrophes_in_prv = true;
- DoCheck(prv, pub, norm_pub, flags, scripts, type, paths, /*replace_apostrophe_with_h_in_prv=*/true,
- /*replace_apostrophe_with_h_in_pub=*/false, /*spender_nlocktime=*/spender_nlocktime,
- /*spender_nsequence=*/spender_nsequence, /*preimages=*/preimages);
- }
-
- // Replace apostrophes with 'h' in pub but not in prv, if apostrophes are found in pub
- if (pub.find('\'') != std::string::npos) {
- found_apostrophes_in_pub = true;
- DoCheck(prv, pub, norm_pub, flags, scripts, type, paths, /*replace_apostrophe_with_h_in_prv=*/false,
- /*replace_apostrophe_with_h_in_pub=*/true, /*spender_nlocktime=*/spender_nlocktime,
- /*spender_nsequence=*/spender_nsequence, /*preimages=*/preimages);
- }
-
// Replace apostrophes with 'h' both in prv and in pub, if apostrophes are found in both
- if (found_apostrophes_in_prv && found_apostrophes_in_pub) {
+ if (prv.find('\'') != std::string::npos && pub.find('\'') != std::string::npos) {
DoCheck(prv, pub, norm_pub, flags, scripts, type, paths, /*replace_apostrophe_with_h_in_prv=*/true,
/*replace_apostrophe_with_h_in_pub=*/true, /*spender_nlocktime=*/spender_nlocktime,
/*spender_nsequence=*/spender_nsequence, /*preimages=*/preimages);
@@ -398,12 +377,12 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
// Basic single-key compressed
Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, std::nullopt);
Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}}, std::nullopt);
- Check("pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}}, OutputType::LEGACY, {{1,0x80000002UL,3,0x80000004UL}});
+ Check("pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pkh([deadbeef/1/2h/3/4h]03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}}, OutputType::LEGACY, {{1,0x80000002UL,3,0x80000004UL}});
Check("wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}}, OutputType::BECH32);
Check("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}}, OutputType::P2SH_SEGWIT);
Check("tr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE | XONLY_KEYS, {{"512077aab6e066f8a7419c5ab714c12c67d25007ed55a43cadcacb4d7a970a093f11"}}, OutputType::BECH32M);
CheckUnparsable("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY2))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5))", "wpkh(): Pubkey '03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5' is invalid"); // Invalid pubkey
- CheckUnparsable("pkh(deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh(deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pkh(): Key origin start '[ character expected but not found, got 'd' instead"); // Missing start bracket in key origin
+ CheckUnparsable("pkh(deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh(deadbeef/1/2h/3/4h]03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pkh(): Key origin start '[ character expected but not found, got 'd' instead"); // Missing start bracket in key origin
CheckUnparsable("pkh([deadbeef]/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh([deadbeef]/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "pkh(): Multiple ']' characters found for a single pubkey"); // Multiple end brackets in key origin
// Basic single-key uncompressed
@@ -426,10 +405,10 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
// Versions with BIP32 derivations
Check("combo([01234567]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "combo([01234567]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}}, std::nullopt);
Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}}, std::nullopt, {{0}});
- Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", "pkh([bd16bee5/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{0xFFFFFFFFUL,0}});
+ Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", "pkh([bd16bee5/2147483647h]xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{0xFFFFFFFFUL,0}});
- Check("wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}}, OutputType::BECH32, {{0x8000000DUL, 1, 2, 0}, {0x8000000DUL, 1, 2, 1}, {0x8000000DUL, 1, 2, 2}});
- Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED | DERIVE_HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}}, OutputType::P2SH_SEGWIT, {{10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
+ Check("wpkh([ffffffff/13']xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", "wpkh([ffffffff/13h]xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}}, OutputType::BECH32, {{0x8000000DUL, 1, 2, 0}, {0x8000000DUL, 1, 2, 1}, {0x8000000DUL, 1, 2, 2}});
+ Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*h))", RANGE | HARDENED | DERIVE_HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}}, OutputType::P2SH_SEGWIT, {{10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}}, std::nullopt, {{0}, {1}});
Check("tr(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/0/*,pk(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/1/*))", "tr(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*,pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*))", "tr(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*,pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*))", XONLY_KEYS | RANGE, {{"512078bc707124daa551b65af74de2ec128b7525e10f374dc67b64e00ce0ab8b3e12"}, {"512001f0a02a17808c20134b78faab80ef93ffba82261ccef0a2314f5d62b6438f11"}, {"512021024954fcec88237a9386fce80ef2ced5f1e91b422b26c59ccfc174c8d1ad25"}}, OutputType::BECH32M, {{0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 1}, {1, 2}});
// Mixed xpubs and const pubkeys
@@ -440,23 +419,23 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
CheckUnparsable("combo([012345678]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo([012345678]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", "combo(): Fingerprint is not 4 bytes (9 characters instead of 8 characters)"); // Too long key fingerprint
CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648)", "pkh(): Key path value 2147483648 is out of range"); // BIP 32 path element overflow
CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/1aa)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1aa)", "pkh(): Key path value '1aa' is not a valid uint32"); // Path is not valid uint
- Check("pkh([01234567/10/20]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh([01234567/10/20]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", "pkh([01234567/10/20/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{10, 20, 0xFFFFFFFFUL, 0}});
+ Check("pkh([01234567/10/20]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh([01234567/10/20]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", "pkh([01234567/10/20/2147483647h]xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}}, OutputType::LEGACY, {{10, 20, 0xFFFFFFFFUL, 0}});
// Multisig constructions
Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt);
Check("sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt);
Check("sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}, std::nullopt);
- Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", "sh(multi(2,[00000000/111h/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
Check("sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", RANGE, {{"5221025d5fc65ebb8d44a5274b53bac21ff8307fec2334a32df05553459f8b1f7fe1b62102fbd47cc8034098f0e6a94c6aeee8528abf0a2153a5d8e46d325b7284c046784652ae"}, {"52210264fd4d1f5dea8ded94c61e9641309349b62f27fbffe807291f664e286bfbe6472103f4ece6dfccfa37b211eb3d0af4d0c61dba9ef698622dc17eecdf764beeb005a652ae"}, {"5221022ccabda84c30bad578b13c89eb3b9544ce149787e5b538175b1d1ba259cbb83321024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c52ae"}}, std::nullopt, {{0}, {1}, {2}, {0, 0, 0}, {0, 0, 1}, {0, 0, 2}});
- Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "wsh(multi(2,[bd16bee5/2147483647']xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE | DERIVE_HARDENED, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, OutputType::BECH32, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
+ Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "wsh(multi(2,[bd16bee5/2147483647h]xpub69H7F5dQzmVd3vPuLKtcXJziMEQByuDidnX3YdwgtNsecY5HRGtAAQC5mXTt4dsv9RzyjgDjAQs9VGVV6ydYCHnprc9vvaA5YtqWyL6hyds/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*h))", HARDENED | RANGE | DERIVE_HARDENED, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, OutputType::BECH32, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}});
Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", "sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}}, OutputType::P2SH_SEGWIT);
Check("tr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,pk(KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy))", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pk(669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))", "tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pk(669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))", SIGNABLE | XONLY_KEYS, {{"512017cf18db381d836d8923b1bdb246cfcd818da1a9f0e6e7907f187f0b2f937754"}}, OutputType::BECH32M);
CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))", "P2SH script is too large, 547 bytes is larger than 520 bytes"); // P2SH does not fit 16 compressed pubkeys in a redeemscript
- CheckUnparsable("wsh(multi(2,[aaaaaaaa][aaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa][aaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Multi: Multiple ']' characters found for a single pubkey"); // Double key origin descriptor
- CheckUnparsable("wsh(multi(2,[aaaagaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaagaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Multi: Fingerprint 'aaagaaaa' is not hex"); // Non hex fingerprint
- CheckUnparsable("wsh(multi(2,[aaaaaaaa],xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa],xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Multi: No key provided"); // No public key with origin
- CheckUnparsable("wsh(multi(2,[aaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Multi: Fingerprint is not 4 bytes (7 characters instead of 8 characters)"); // Too short fingerprint
- CheckUnparsable("wsh(multi(2,[aaaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", "Multi: Fingerprint is not 4 bytes (9 characters instead of 8 characters)"); // Too long fingerprint
+ CheckUnparsable("wsh(multi(2,[aaaaaaaa][aaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa][aaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647h/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*h))", "Multi: Multiple ']' characters found for a single pubkey"); // Double key origin descriptor
+ CheckUnparsable("wsh(multi(2,[aaaagaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaagaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647h/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*h))", "Multi: Fingerprint 'aaagaaaa' is not hex"); // Non hex fingerprint
+ CheckUnparsable("wsh(multi(2,[aaaaaaaa],xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaa],xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*h))", "Multi: No key provided"); // No public key with origin
+ CheckUnparsable("wsh(multi(2,[aaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647h/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*h))", "Multi: Fingerprint is not 4 bytes (7 characters instead of 8 characters)"); // Too short fingerprint
+ CheckUnparsable("wsh(multi(2,[aaaaaaaaa]xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,[aaaaaaaaa]xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647h/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*h))", "Multi: Fingerprint is not 4 bytes (9 characters instead of 8 characters)"); // Too long fingerprint
CheckUnparsable("multi(a,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(a,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "Multi threshold 'a' is not valid"); // Invalid threshold
CheckUnparsable("multi(0,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(0,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "Multisig threshold cannot be 0, must be at least 1"); // Threshold of 0
CheckUnparsable("multi(3,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(3,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "Multisig threshold cannot be larger than the number of keys; threshold is 3 but only 2 keys specified"); // Threshold larger than number of keys
@@ -474,8 +453,8 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
CheckUnparsable("wsh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "wsh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", "Can only have wsh() at top level or inside sh()"); // Cannot embed P2WSH inside P2WSH
// Checksums
- Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
- Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfy", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5t", "sh(multi(2,[00000000/111h/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#hgmsckna", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
+ Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", "sh(multi(2,[00000000/111h/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, OutputType::LEGACY, {{0x8000006FUL,222},{0}});
CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#", "Expected 8 character checksum, not 0 characters"); // Empty checksum
CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxfyq", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5tq", "Expected 8 character checksum, not 9 characters"); // Too long checksum
CheckUnparsable("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))#ggrsrxf", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))#tjg09x5", "Expected 8 character checksum, not 7 characters"); // Too short checksum
@@ -491,13 +470,12 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
Check(
"rawtr(xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/86'/1'/0'/1/*)#a5gn3t7k",
"rawtr(xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/86'/1'/0'/1/*)#4ur3xhft",
- "rawtr([5a61ff8e/86'/1'/0']xpub6DtZpc9PRL2B6pwoNGysmHAaBofDmWv5S6KQEKKGPKhf5fV62ywDtSziSApYVK3JnYY5KUSgiCwiXW5wtd8z7LNBxT9Mu5sEro8itdGfTeA/1/*)#llheyd9x",
+ "rawtr([5a61ff8e/86h/1h/0h]xpub6DtZpc9PRL2B6pwoNGysmHAaBofDmWv5S6KQEKKGPKhf5fV62ywDtSziSApYVK3JnYY5KUSgiCwiXW5wtd8z7LNBxT9Mu5sEro8itdGfTeA/1/*)#vwgx7hj9",
RANGE | HARDENED | XONLY_KEYS,
{{"51205172af752f057d543ce8e4a6f8dcf15548ec6be44041bfa93b72e191cfc8c1ee"}, {"51201b66f20b86f700c945ecb9ad9b0ad1662b73084e2bfea48bee02126350b8a5b1"}, {"512063e70f66d815218abcc2306aa930aaca07c5cde73b75127eb27b5e8c16b58a25"}},
OutputType::BECH32M,
{{0x80000056, 0x80000001, 0x80000000, 1, 0}, {0x80000056, 0x80000001, 0x80000000, 1, 1}, {0x80000056, 0x80000001, 0x80000000, 1, 2}});
-
Check(
"rawtr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)",
"rawtr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)",
diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp
index 5ad7a25c53..7218bb82d1 100644
--- a/src/test/fuzz/addrman.cpp
+++ b/src/test/fuzz/addrman.cpp
@@ -16,6 +16,7 @@
#include <test/util/setup_common.h>
#include <time.h>
#include <util/asmap.h>
+#include <util/chaintype.h>
#include <cassert>
#include <cstdint>
@@ -34,7 +35,7 @@ int32_t GetCheckRatio()
void initialize_addrman()
{
- static const auto testing_setup = MakeNoLogFileContext<>(CBaseChainParams::REGTEST);
+ static const auto testing_setup = MakeNoLogFileContext<>(ChainType::REGTEST);
g_setup = testing_setup.get();
}
diff --git a/src/test/fuzz/block.cpp b/src/test/fuzz/block.cpp
index c3e17724eb..e90dcc189a 100644
--- a/src/test/fuzz/block.cpp
+++ b/src/test/fuzz/block.cpp
@@ -11,6 +11,7 @@
#include <pubkey.h>
#include <streams.h>
#include <test/fuzz/fuzz.h>
+#include <util/chaintype.h>
#include <validation.h>
#include <version.h>
@@ -19,7 +20,7 @@
void initialize_block()
{
- SelectParams(CBaseChainParams::REGTEST);
+ SelectParams(ChainType::REGTEST);
}
FUZZ_TARGET_INIT(block, initialize_block)
diff --git a/src/test/fuzz/buffered_file.cpp b/src/test/fuzz/buffered_file.cpp
index 67cac8fa4e..2f7ce60c7f 100644
--- a/src/test/fuzz/buffered_file.cpp
+++ b/src/test/fuzz/buffered_file.cpp
@@ -53,7 +53,7 @@ FUZZ_TARGET(buffered_file)
return;
}
try {
- opt_buffered_file->FindByte(fuzzed_data_provider.ConsumeIntegral<uint8_t>());
+ opt_buffered_file->FindByte(std::byte(fuzzed_data_provider.ConsumeIntegral<uint8_t>()));
} catch (const std::ios_base::failure&) {
}
},
diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp
index 5843b80c0a..fc7e000dc7 100644
--- a/src/test/fuzz/coins_view.cpp
+++ b/src/test/fuzz/coins_view.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
-#include <chainparamsbase.h>
#include <coins.h>
#include <consensus/amount.h>
#include <consensus/tx_check.h>
diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp
index 0f3c850e66..f81658b832 100644
--- a/src/test/fuzz/connman.cpp
+++ b/src/test/fuzz/connman.cpp
@@ -4,7 +4,6 @@
#include <addrman.h>
#include <chainparams.h>
-#include <chainparamsbase.h>
#include <common/args.h>
#include <net.h>
#include <netaddress.h>
diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp
index 1f5601ca9f..12c22ef2ed 100644
--- a/src/test/fuzz/descriptor_parse.cpp
+++ b/src/test/fuzz/descriptor_parse.cpp
@@ -6,11 +6,12 @@
#include <pubkey.h>
#include <script/descriptor.h>
#include <test/fuzz/fuzz.h>
+#include <util/chaintype.h>
void initialize_descriptor_parse()
{
ECC_Start();
- SelectParams(CBaseChainParams::MAIN);
+ SelectParams(ChainType::MAIN);
}
FUZZ_TARGET_INIT(descriptor_parse, initialize_descriptor_parse)
diff --git a/src/test/fuzz/headerssync.cpp b/src/test/fuzz/headerssync.cpp
index 521afadb51..c1a187038b 100644
--- a/src/test/fuzz/headerssync.cpp
+++ b/src/test/fuzz/headerssync.cpp
@@ -6,6 +6,7 @@
#include <test/fuzz/util.h>
#include <test/util/setup_common.h>
#include <uint256.h>
+#include <util/chaintype.h>
#include <util/time.h>
#include <validation.h>
@@ -15,7 +16,7 @@
static void initialize_headers_sync_state_fuzz()
{
static const auto testing_setup = MakeNoLogFileContext<>(
- /*chain_name=*/CBaseChainParams::MAIN);
+ /*chain_type=*/ChainType::MAIN);
}
void MakeHeadersContinuous(
diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp
index ead877fe05..392f3591f1 100644
--- a/src/test/fuzz/integer.cpp
+++ b/src/test/fuzz/integer.cpp
@@ -26,6 +26,7 @@
#include <test/fuzz/util.h>
#include <uint256.h>
#include <univalue.h>
+#include <util/chaintype.h>
#include <util/check.h>
#include <util/moneystr.h>
#include <util/overflow.h>
@@ -42,7 +43,7 @@
void initialize_integer()
{
- SelectParams(CBaseChainParams::REGTEST);
+ SelectParams(ChainType::REGTEST);
}
FUZZ_TARGET_INIT(integer, initialize_integer)
diff --git a/src/test/fuzz/key.cpp b/src/test/fuzz/key.cpp
index ea6883c08d..3eab2e20c0 100644
--- a/src/test/fuzz/key.cpp
+++ b/src/test/fuzz/key.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
-#include <chainparamsbase.h>
#include <key.h>
#include <key_io.h>
#include <outputtype.h>
@@ -17,6 +16,7 @@
#include <script/standard.h>
#include <streams.h>
#include <test/fuzz/fuzz.h>
+#include <util/chaintype.h>
#include <util/strencodings.h>
#include <cassert>
@@ -28,7 +28,7 @@
void initialize_key()
{
ECC_Start();
- SelectParams(CBaseChainParams::REGTEST);
+ SelectParams(ChainType::REGTEST);
}
FUZZ_TARGET_INIT(key, initialize_key)
diff --git a/src/test/fuzz/key_io.cpp b/src/test/fuzz/key_io.cpp
index 29c6996365..a1c587a75b 100644
--- a/src/test/fuzz/key_io.cpp
+++ b/src/test/fuzz/key_io.cpp
@@ -5,6 +5,7 @@
#include <chainparams.h>
#include <key_io.h>
#include <test/fuzz/fuzz.h>
+#include <util/chaintype.h>
#include <cassert>
#include <cstdint>
@@ -14,7 +15,7 @@
void initialize_key_io()
{
ECC_Start();
- SelectParams(CBaseChainParams::MAIN);
+ SelectParams(ChainType::MAIN);
}
FUZZ_TARGET_INIT(key_io, initialize_key_io)
diff --git a/src/test/fuzz/message.cpp b/src/test/fuzz/message.cpp
index 63e24aacdd..8b7e3f11cc 100644
--- a/src/test/fuzz/message.cpp
+++ b/src/test/fuzz/message.cpp
@@ -7,6 +7,7 @@
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
+#include <util/chaintype.h>
#include <util/message.h>
#include <util/strencodings.h>
@@ -19,7 +20,7 @@
void initialize_message()
{
ECC_Start();
- SelectParams(CBaseChainParams::REGTEST);
+ SelectParams(ChainType::REGTEST);
}
FUZZ_TARGET_INIT(message, initialize_message)
diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp
index 13b4638688..e090f13061 100644
--- a/src/test/fuzz/net.cpp
+++ b/src/test/fuzz/net.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
-#include <chainparamsbase.h>
#include <net.h>
#include <net_permissions.h>
#include <netaddress.h>
@@ -16,6 +15,7 @@
#include <test/util/net.h>
#include <test/util/setup_common.h>
#include <util/asmap.h>
+#include <util/chaintype.h>
#include <cstdint>
#include <optional>
@@ -24,7 +24,7 @@
void initialize_net()
{
- static const auto testing_setup = MakeNoLogFileContext<>(CBaseChainParams::MAIN);
+ static const auto testing_setup = MakeNoLogFileContext<>(ChainType::MAIN);
}
FUZZ_TARGET_INIT(net, initialize_net)
diff --git a/src/test/fuzz/p2p_transport_serialization.cpp b/src/test/fuzz/p2p_transport_serialization.cpp
index 96254aa222..ec3cdbff5a 100644
--- a/src/test/fuzz/p2p_transport_serialization.cpp
+++ b/src/test/fuzz/p2p_transport_serialization.cpp
@@ -9,6 +9,7 @@
#include <protocol.h>
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
+#include <util/chaintype.h>
#include <cassert>
#include <cstdint>
@@ -18,7 +19,7 @@
void initialize_p2p_transport_serialization()
{
- SelectParams(CBaseChainParams::REGTEST);
+ SelectParams(ChainType::REGTEST);
}
FUZZ_TARGET_INIT(p2p_transport_serialization, initialize_p2p_transport_serialization)
diff --git a/src/test/fuzz/parse_hd_keypath.cpp b/src/test/fuzz/parse_hd_keypath.cpp
index 411b70230a..9a2d9a73da 100644
--- a/src/test/fuzz/parse_hd_keypath.cpp
+++ b/src/test/fuzz/parse_hd_keypath.cpp
@@ -18,6 +18,6 @@ FUZZ_TARGET(parse_hd_keypath)
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::vector<uint32_t> random_keypath = ConsumeRandomLengthIntegralVector<uint32_t>(fuzzed_data_provider);
- (void)FormatHDKeypath(random_keypath);
+ (void)FormatHDKeypath(random_keypath, /*apostrophe=*/true); // WriteHDKeypath calls this with false
(void)WriteHDKeypath(random_keypath);
}
diff --git a/src/test/fuzz/parse_univalue.cpp b/src/test/fuzz/parse_univalue.cpp
index 16486f6b96..be15a38e92 100644
--- a/src/test/fuzz/parse_univalue.cpp
+++ b/src/test/fuzz/parse_univalue.cpp
@@ -7,13 +7,14 @@
#include <rpc/client.h>
#include <rpc/util.h>
#include <test/fuzz/fuzz.h>
+#include <util/chaintype.h>
#include <limits>
#include <string>
void initialize_parse_univalue()
{
- SelectParams(CBaseChainParams::REGTEST);
+ SelectParams(ChainType::REGTEST);
}
FUZZ_TARGET_INIT(parse_univalue, initialize_parse_univalue)
diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp
index e5a3a6e68a..6d584c9f10 100644
--- a/src/test/fuzz/pow.cpp
+++ b/src/test/fuzz/pow.cpp
@@ -9,6 +9,7 @@
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
+#include <util/chaintype.h>
#include <util/check.h>
#include <util/overflow.h>
@@ -19,7 +20,7 @@
void initialize_pow()
{
- SelectParams(CBaseChainParams::MAIN);
+ SelectParams(ChainType::MAIN);
}
FUZZ_TARGET_INIT(pow, initialize_pow)
diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp
index 0a7924f226..70dd1e17c5 100644
--- a/src/test/fuzz/process_message.cpp
+++ b/src/test/fuzz/process_message.cpp
@@ -19,6 +19,7 @@
#include <test/util/net.h>
#include <test/util/setup_common.h>
#include <test/util/validation.h>
+#include <util/chaintype.h>
#include <validationinterface.h>
#include <version.h>
@@ -57,7 +58,7 @@ void initialize_process_message()
Assert(GetNumMsgTypes() == getAllNetMessageTypes().size()); // If this fails, add or remove the message type below
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(
- /*chain_name=*/CBaseChainParams::REGTEST,
+ /*chain_type=*/ChainType::REGTEST,
/*extra_args=*/{"-txreconciliation"});
g_setup = testing_setup.get();
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp
index 96339743ba..68d4e02a26 100644
--- a/src/test/fuzz/process_messages.cpp
+++ b/src/test/fuzz/process_messages.cpp
@@ -24,7 +24,7 @@ const TestingSetup* g_setup;
void initialize_process_messages()
{
static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>(
- /*chain_name=*/CBaseChainParams::REGTEST,
+ /*chain_type=*/ChainType::REGTEST,
/*extra_args=*/{"-txreconciliation"});
g_setup = testing_setup.get();
for (int i = 0; i < 2 * COINBASE_MATURITY; i++) {
diff --git a/src/test/fuzz/rpc.cpp b/src/test/fuzz/rpc.cpp
index 1c6140c66a..33ffcc4cdd 100644
--- a/src/test/fuzz/rpc.cpp
+++ b/src/test/fuzz/rpc.cpp
@@ -23,6 +23,7 @@
#include <test/util/setup_common.h>
#include <tinyformat.h>
#include <univalue.h>
+#include <util/chaintype.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/time.h>
@@ -37,7 +38,7 @@
namespace {
struct RPCFuzzTestingSetup : public TestingSetup {
- RPCFuzzTestingSetup(const std::string& chain_name, const std::vector<const char*>& extra_args) : TestingSetup{chain_name, extra_args}
+ RPCFuzzTestingSetup(const ChainType chain_type, const std::vector<const char*>& extra_args) : TestingSetup{chain_type, extra_args}
{
}
@@ -363,7 +364,7 @@ FUZZ_TARGET_INIT(rpc, initialize_rpc)
try {
rpc_testing_setup->CallRPC(rpc_command, arguments);
} catch (const UniValue& json_rpc_error) {
- const std::string error_msg{find_value(json_rpc_error, "message").get_str()};
+ const std::string error_msg{json_rpc_error.find_value("message").get_str()};
// Once c++20 is allowed, starts_with can be used.
// if (error_msg.starts_with("Internal bug detected")) {
if (0 == error_msg.rfind("Internal bug detected", 0)) {
diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp
index 1037dd934a..8a88c1107a 100644
--- a/src/test/fuzz/script.cpp
+++ b/src/test/fuzz/script.cpp
@@ -22,6 +22,7 @@
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <univalue.h>
+#include <util/chaintype.h>
#include <algorithm>
#include <cassert>
@@ -32,7 +33,7 @@
void initialize_script()
{
- SelectParams(CBaseChainParams::REGTEST);
+ SelectParams(ChainType::REGTEST);
}
FUZZ_TARGET_INIT(script, initialize_script)
diff --git a/src/test/fuzz/script_format.cpp b/src/test/fuzz/script_format.cpp
index 9186746bcf..5aa0ea58ff 100644
--- a/src/test/fuzz/script_format.cpp
+++ b/src/test/fuzz/script_format.cpp
@@ -11,10 +11,11 @@
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <univalue.h>
+#include <util/chaintype.h>
void initialize_script_format()
{
- SelectParams(CBaseChainParams::REGTEST);
+ SelectParams(ChainType::REGTEST);
}
FUZZ_TARGET_INIT(script_format, initialize_script_format)
diff --git a/src/test/fuzz/script_sigcache.cpp b/src/test/fuzz/script_sigcache.cpp
index de895cc69c..f332987987 100644
--- a/src/test/fuzz/script_sigcache.cpp
+++ b/src/test/fuzz/script_sigcache.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
-#include <chainparamsbase.h>
#include <key.h>
#include <pubkey.h>
#include <script/sigcache.h>
diff --git a/src/test/fuzz/script_sign.cpp b/src/test/fuzz/script_sign.cpp
index c78c22e6cc..8b62daf162 100644
--- a/src/test/fuzz/script_sign.cpp
+++ b/src/test/fuzz/script_sign.cpp
@@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
-#include <chainparamsbase.h>
#include <key.h>
#include <psbt.h>
#include <pubkey.h>
@@ -14,6 +13,7 @@
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
+#include <util/chaintype.h>
#include <util/translation.h>
#include <cassert>
@@ -27,7 +27,7 @@
void initialize_script_sign()
{
ECC_Start();
- SelectParams(CBaseChainParams::REGTEST);
+ SelectParams(ChainType::REGTEST);
}
FUZZ_TARGET_INIT(script_sign, initialize_script_sign)
diff --git a/src/test/fuzz/signet.cpp b/src/test/fuzz/signet.cpp
index 303dcf13e3..e9af93c639 100644
--- a/src/test/fuzz/signet.cpp
+++ b/src/test/fuzz/signet.cpp
@@ -11,6 +11,7 @@
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <test/util/setup_common.h>
+#include <util/chaintype.h>
#include <cstdint>
#include <optional>
@@ -18,7 +19,7 @@
void initialize_signet()
{
- static const auto testing_setup = MakeNoLogFileContext<>(CBaseChainParams::SIGNET);
+ static const auto testing_setup = MakeNoLogFileContext<>(ChainType::SIGNET);
}
FUZZ_TARGET_INIT(signet, initialize_signet)
diff --git a/src/test/fuzz/socks5.cpp b/src/test/fuzz/socks5.cpp
index 97f643db49..73235b7ced 100644
--- a/src/test/fuzz/socks5.cpp
+++ b/src/test/fuzz/socks5.cpp
@@ -14,12 +14,12 @@
#include <string>
#include <vector>
+extern std::chrono::milliseconds g_socks5_recv_timeout;
+
namespace {
-int default_socks5_recv_timeout;
+decltype(g_socks5_recv_timeout) default_socks5_recv_timeout;
};
-extern int g_socks5_recv_timeout;
-
void initialize_socks5()
{
static const auto testing_setup = MakeNoLogFileContext<const BasicTestingSetup>();
@@ -35,7 +35,7 @@ FUZZ_TARGET_INIT(socks5, initialize_socks5)
InterruptSocks5(fuzzed_data_provider.ConsumeBool());
// Set FUZZED_SOCKET_FAKE_LATENCY=1 to exercise recv timeout code paths. This
// will slow down fuzzing.
- g_socks5_recv_timeout = (fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) ? 1 : default_socks5_recv_timeout;
+ g_socks5_recv_timeout = (fuzzed_data_provider.ConsumeBool() && std::getenv("FUZZED_SOCKET_FAKE_LATENCY") != nullptr) ? 1ms : default_socks5_recv_timeout;
FuzzedSock fuzzed_sock = ConsumeSock(fuzzed_data_provider);
// This Socks5(...) fuzzing harness would have caught CVE-2017-18350 within
// a few seconds of fuzzing.
diff --git a/src/test/fuzz/system.cpp b/src/test/fuzz/system.cpp
index 935f0c21e1..04cbbe52cb 100644
--- a/src/test/fuzz/system.cpp
+++ b/src/test/fuzz/system.cpp
@@ -108,7 +108,7 @@ FUZZ_TARGET_INIT(system, initialize_system)
(void)args_manager.GetArgs(s1);
(void)args_manager.GetBoolArg(s1, b);
try {
- (void)args_manager.GetChainName();
+ (void)args_manager.GetChainTypeString();
} catch (const std::runtime_error&) {
}
(void)args_manager.GetHelpMessage();
diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp
index bacb178b44..7035c53d13 100644
--- a/src/test/fuzz/transaction.cpp
+++ b/src/test/fuzz/transaction.cpp
@@ -15,6 +15,7 @@
#include <streams.h>
#include <test/fuzz/fuzz.h>
#include <univalue.h>
+#include <util/chaintype.h>
#include <util/rbf.h>
#include <validation.h>
#include <version.h>
@@ -23,7 +24,7 @@
void initialize_transaction()
{
- SelectParams(CBaseChainParams::REGTEST);
+ SelectParams(ChainType::REGTEST);
}
FUZZ_TARGET_INIT(transaction, initialize_transaction)
diff --git a/src/test/fuzz/tx_pool.cpp b/src/test/fuzz/tx_pool.cpp
index a055705575..b758c715ef 100644
--- a/src/test/fuzz/tx_pool.cpp
+++ b/src/test/fuzz/tx_pool.cpp
@@ -42,12 +42,12 @@ void initialize_tx_pool()
g_setup = testing_setup.get();
for (int i = 0; i < 2 * COINBASE_MATURITY; ++i) {
- CTxIn in = MineBlock(g_setup->m_node, P2WSH_OP_TRUE);
+ COutPoint prevout{MineBlock(g_setup->m_node, P2WSH_OP_TRUE)};
// Remember the txids to avoid expensive disk access later on
auto& outpoints = i < COINBASE_MATURITY ?
g_outpoints_coinbase_init_mature :
g_outpoints_coinbase_init_immature;
- outpoints.push_back(in.prevout);
+ outpoints.push_back(prevout);
}
SyncWithValidationInterfaceQueue();
}
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h
index c14f633029..5f2aff08da 100644
--- a/src/test/fuzz/util.h
+++ b/src/test/fuzz/util.h
@@ -6,7 +6,6 @@
#define BITCOIN_TEST_FUZZ_UTIL_H
#include <arith_uint256.h>
-#include <chainparamsbase.h>
#include <coins.h>
#include <compat/compat.h>
#include <consensus/amount.h>
diff --git a/src/test/fuzz/utxo_snapshot.cpp b/src/test/fuzz/utxo_snapshot.cpp
index be34906025..b4ef0c7a3e 100644
--- a/src/test/fuzz/utxo_snapshot.cpp
+++ b/src/test/fuzz/utxo_snapshot.cpp
@@ -10,6 +10,7 @@
#include <test/fuzz/util.h>
#include <test/util/mining.h>
#include <test/util/setup_common.h>
+#include <util/chaintype.h>
#include <util/fs.h>
#include <validation.h>
#include <validationinterface.h>
@@ -22,7 +23,7 @@ const std::vector<std::shared_ptr<CBlock>>* g_chain;
void initialize_chain()
{
- const auto params{CreateChainParams(ArgsManager{}, CBaseChainParams::REGTEST)};
+ const auto params{CreateChainParams(ArgsManager{}, ChainType::REGTEST)};
static const auto chain{CreateBlockChain(2 * COINBASE_MATURITY, *params)};
g_chain = &chain;
}
diff --git a/src/test/fuzz/utxo_total_supply.cpp b/src/test/fuzz/utxo_total_supply.cpp
new file mode 100644
index 0000000000..19f41880f4
--- /dev/null
+++ b/src/test/fuzz/utxo_total_supply.cpp
@@ -0,0 +1,166 @@
+// Copyright (c) 2020 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chainparams.h>
+#include <consensus/consensus.h>
+#include <consensus/merkle.h>
+#include <kernel/coinstats.h>
+#include <node/miner.h>
+#include <script/interpreter.h>
+#include <streams.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <test/util/mining.h>
+#include <test/util/setup_common.h>
+#include <util/chaintype.h>
+#include <validation.h>
+#include <version.h>
+
+FUZZ_TARGET(utxo_total_supply)
+{
+ /** The testing setup that creates a chainman only (no chainstate) */
+ ChainTestingSetup test_setup{
+ ChainType::REGTEST,
+ {
+ "-testactivationheight=bip34@2",
+ },
+ };
+ // Create chainstate
+ test_setup.LoadVerifyActivateChainstate();
+ auto& node{test_setup.m_node};
+ auto& chainman{*Assert(test_setup.m_node.chainman)};
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+
+ const auto ActiveHeight = [&]() {
+ LOCK(chainman.GetMutex());
+ return chainman.ActiveHeight();
+ };
+ const auto PrepareNextBlock = [&]() {
+ // Use OP_FALSE to avoid BIP30 check from hitting early
+ auto block = PrepareBlock(node, CScript{} << OP_FALSE);
+ // Replace OP_FALSE with OP_TRUE
+ {
+ CMutableTransaction tx{*block->vtx.back()};
+ tx.vout.at(0).scriptPubKey = CScript{} << OP_TRUE;
+ block->vtx.back() = MakeTransactionRef(tx);
+ }
+ return block;
+ };
+
+ /** The block template this fuzzer is working on */
+ auto current_block = PrepareNextBlock();
+ /** Append-only set of tx outpoints, entries are not removed when spent */
+ std::vector<std::pair<COutPoint, CTxOut>> txos;
+ /** The utxo stats at the chain tip */
+ kernel::CCoinsStats utxo_stats;
+ /** The total amount of coins in the utxo set */
+ CAmount circulation{0};
+
+
+ // Store the tx out in the txo map
+ const auto StoreLastTxo = [&]() {
+ // get last tx
+ const CTransaction& tx = *current_block->vtx.back();
+ // get last out
+ const uint32_t i = tx.vout.size() - 1;
+ // store it
+ txos.emplace_back(COutPoint{tx.GetHash(), i}, tx.vout.at(i));
+ if (current_block->vtx.size() == 1 && tx.vout.at(i).scriptPubKey[0] == OP_RETURN) {
+ // also store coinbase
+ const uint32_t i = tx.vout.size() - 2;
+ txos.emplace_back(COutPoint{tx.GetHash(), i}, tx.vout.at(i));
+ }
+ };
+ const auto AppendRandomTxo = [&](CMutableTransaction& tx) {
+ const auto& txo = txos.at(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, txos.size() - 1));
+ tx.vin.emplace_back(txo.first);
+ tx.vout.emplace_back(txo.second.nValue, txo.second.scriptPubKey); // "Forward" coin with no fee
+ };
+ const auto UpdateUtxoStats = [&]() {
+ LOCK(chainman.GetMutex());
+ chainman.ActiveChainstate().ForceFlushStateToDisk();
+ utxo_stats = std::move(
+ *Assert(kernel::ComputeUTXOStats(kernel::CoinStatsHashType::NONE, &chainman.ActiveChainstate().CoinsDB(), chainman.m_blockman, {})));
+ // Check that miner can't print more money than they are allowed to
+ assert(circulation == utxo_stats.total_amount);
+ };
+
+
+ // Update internal state to chain tip
+ StoreLastTxo();
+ UpdateUtxoStats();
+ assert(ActiveHeight() == 0);
+ // Get at which height we duplicate the coinbase
+ // Assuming that the fuzzer will mine relatively short chains (less than 200 blocks), we want the duplicate coinbase to be not too high.
+ // Up to 2000 seems reasonable.
+ int64_t duplicate_coinbase_height = fuzzed_data_provider.ConsumeIntegralInRange(0, 20 * COINBASE_MATURITY);
+ // Always pad with OP_0 at the end to avoid bad-cb-length error
+ const CScript duplicate_coinbase_script = CScript() << duplicate_coinbase_height << OP_0;
+ // Mine the first block with this duplicate
+ current_block = PrepareNextBlock();
+ StoreLastTxo();
+
+ {
+ // Create duplicate (CScript should match exact format as in CreateNewBlock)
+ CMutableTransaction tx{*current_block->vtx.front()};
+ tx.vin.at(0).scriptSig = duplicate_coinbase_script;
+
+ // Mine block and create next block template
+ current_block->vtx.front() = MakeTransactionRef(tx);
+ }
+ current_block->hashMerkleRoot = BlockMerkleRoot(*current_block);
+ assert(!MineBlock(node, current_block).IsNull());
+ circulation += GetBlockSubsidy(ActiveHeight(), Params().GetConsensus());
+
+ assert(ActiveHeight() == 1);
+ UpdateUtxoStats();
+ current_block = PrepareNextBlock();
+ StoreLastTxo();
+
+ LIMITED_WHILE(fuzzed_data_provider.remaining_bytes(), 100'000)
+ {
+ CallOneOf(
+ fuzzed_data_provider,
+ [&] {
+ // Append an input-output pair to the last tx in the current block
+ CMutableTransaction tx{*current_block->vtx.back()};
+ AppendRandomTxo(tx);
+ current_block->vtx.back() = MakeTransactionRef(tx);
+ StoreLastTxo();
+ },
+ [&] {
+ // Append a tx to the list of txs in the current block
+ CMutableTransaction tx{};
+ AppendRandomTxo(tx);
+ current_block->vtx.push_back(MakeTransactionRef(tx));
+ StoreLastTxo();
+ },
+ [&] {
+ // Append the current block to the active chain
+ node::RegenerateCommitments(*current_block, chainman);
+ const bool was_valid = !MineBlock(node, current_block).IsNull();
+
+ const auto prev_utxo_stats = utxo_stats;
+ if (was_valid) {
+ circulation += GetBlockSubsidy(ActiveHeight(), Params().GetConsensus());
+
+ if (duplicate_coinbase_height == ActiveHeight()) {
+ // we mined the duplicate coinbase
+ assert(current_block->vtx.at(0)->vin.at(0).scriptSig == duplicate_coinbase_script);
+ }
+ }
+
+ UpdateUtxoStats();
+
+ if (!was_valid) {
+ // utxo stats must not change
+ assert(prev_utxo_stats.hashSerialized == utxo_stats.hashSerialized);
+ }
+
+ current_block = PrepareNextBlock();
+ StoreLastTxo();
+ });
+ }
+}
diff --git a/src/test/fuzz/validation_load_mempool.cpp b/src/test/fuzz/validation_load_mempool.cpp
index 817593cf6e..4e2ca6d903 100644
--- a/src/test/fuzz/validation_load_mempool.cpp
+++ b/src/test/fuzz/validation_load_mempool.cpp
@@ -4,7 +4,6 @@
#include <kernel/mempool_persist.h>
-#include <chainparamsbase.h>
#include <node/mempool_args.h>
#include <node/mempool_persist_args.h>
#include <test/fuzz/FuzzedDataProvider.h>
diff --git a/src/test/fuzz/versionbits.cpp b/src/test/fuzz/versionbits.cpp
index e6a19d6e91..b3df4dadd2 100644
--- a/src/test/fuzz/versionbits.cpp
+++ b/src/test/fuzz/versionbits.cpp
@@ -7,6 +7,7 @@
#include <common/args.h>
#include <consensus/params.h>
#include <primitives/block.h>
+#include <util/chaintype.h>
#include <versionbits.h>
#include <test/fuzz/FuzzedDataProvider.h>
@@ -104,7 +105,7 @@ std::unique_ptr<const CChainParams> g_params;
void initialize()
{
// this is actually comparatively slow, so only do it once
- g_params = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN);
+ g_params = CreateChainParams(ArgsManager{}, ChainType::MAIN);
assert(g_params != nullptr);
}
diff --git a/src/test/interfaces_tests.cpp b/src/test/interfaces_tests.cpp
index d37fe35a11..68377e197f 100644
--- a/src/test/interfaces_tests.cpp
+++ b/src/test/interfaces_tests.cpp
@@ -98,7 +98,7 @@ BOOST_AUTO_TEST_CASE(findAncestorByHash)
BOOST_AUTO_TEST_CASE(findCommonAncestor)
{
auto& chain = m_node.chain;
- const CChain& active = WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return Assert(m_node.chainman)->ActiveChain());
+ const CChain& active{*WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return &Assert(m_node.chainman)->ActiveChain())};
auto* orig_tip = active.Tip();
for (int i = 0; i < 10; ++i) {
BlockValidationState state;
diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp
index a400afee71..92bdbae3c4 100644
--- a/src/test/key_io_tests.cpp
+++ b/src/test/key_io_tests.cpp
@@ -10,6 +10,7 @@
#include <script/script.h>
#include <test/util/json.h>
#include <test/util/setup_common.h>
+#include <util/chaintype.h>
#include <util/strencodings.h>
#include <boost/test/unit_test.hpp>
@@ -24,7 +25,7 @@ BOOST_AUTO_TEST_CASE(key_io_valid_parse)
UniValue tests = read_json(std::string(json_tests::key_io_valid, json_tests::key_io_valid + sizeof(json_tests::key_io_valid)));
CKey privkey;
CTxDestination destination;
- SelectParams(CBaseChainParams::MAIN);
+ SelectParams(ChainType::MAIN);
for (unsigned int idx = 0; idx < tests.size(); idx++) {
const UniValue& test = tests[idx];
@@ -36,11 +37,11 @@ BOOST_AUTO_TEST_CASE(key_io_valid_parse)
std::string exp_base58string = test[0].get_str();
const std::vector<std::byte> exp_payload{ParseHex<std::byte>(test[1].get_str())};
const UniValue &metadata = test[2].get_obj();
- bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
- SelectParams(find_value(metadata, "chain").get_str());
- bool try_case_flip = find_value(metadata, "tryCaseFlip").isNull() ? false : find_value(metadata, "tryCaseFlip").get_bool();
+ bool isPrivkey = metadata.find_value("isPrivkey").get_bool();
+ SelectParams(ChainTypeFromString(metadata.find_value("chain").get_str()).value());
+ bool try_case_flip = metadata.find_value("tryCaseFlip").isNull() ? false : metadata.find_value("tryCaseFlip").get_bool();
if (isPrivkey) {
- bool isCompressed = find_value(metadata, "isCompressed").get_bool();
+ bool isCompressed = metadata.find_value("isCompressed").get_bool();
// Must be valid private key
privkey = DecodeSecret(exp_base58string);
BOOST_CHECK_MESSAGE(privkey.IsValid(), "!IsValid:" + strTest);
@@ -95,10 +96,10 @@ BOOST_AUTO_TEST_CASE(key_io_valid_gen)
std::string exp_base58string = test[0].get_str();
std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
const UniValue &metadata = test[2].get_obj();
- bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
- SelectParams(find_value(metadata, "chain").get_str());
+ bool isPrivkey = metadata.find_value("isPrivkey").get_bool();
+ SelectParams(ChainTypeFromString(metadata.find_value("chain").get_str()).value());
if (isPrivkey) {
- bool isCompressed = find_value(metadata, "isCompressed").get_bool();
+ bool isCompressed = metadata.find_value("isCompressed").get_bool();
CKey key;
key.Set(exp_payload.begin(), exp_payload.end(), isCompressed);
assert(key.IsValid());
@@ -113,7 +114,7 @@ BOOST_AUTO_TEST_CASE(key_io_valid_gen)
}
}
- SelectParams(CBaseChainParams::MAIN);
+ SelectParams(ChainType::MAIN);
}
@@ -135,7 +136,7 @@ BOOST_AUTO_TEST_CASE(key_io_invalid)
std::string exp_base58string = test[0].get_str();
// must be invalid as public and as private key
- for (const auto& chain : { CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::SIGNET, CBaseChainParams::REGTEST }) {
+ for (const auto& chain : {ChainType::MAIN, ChainType::TESTNET, ChainType::SIGNET, ChainType::REGTEST}) {
SelectParams(chain);
destination = DecodeDestination(exp_base58string);
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey in mainnet:" + strTest);
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
index addc925bab..5bd14f22c6 100644
--- a/src/test/pow_tests.cpp
+++ b/src/test/pow_tests.cpp
@@ -7,6 +7,7 @@
#include <pow.h>
#include <test/util/random.h>
#include <test/util/setup_common.h>
+#include <util/chaintype.h>
#include <boost/test/unit_test.hpp>
@@ -15,7 +16,7 @@ BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup)
/* Test calculation of next difficulty target with no constraints applying */
BOOST_AUTO_TEST_CASE(get_next_work)
{
- const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
+ const auto chainParams = CreateChainParams(*m_node.args, ChainType::MAIN);
int64_t nLastRetargetTime = 1261130161; // Block #30240
CBlockIndex pindexLast;
pindexLast.nHeight = 32255;
@@ -34,7 +35,7 @@ BOOST_AUTO_TEST_CASE(get_next_work)
/* Test the constraint on the upper bound for next work */
BOOST_AUTO_TEST_CASE(get_next_work_pow_limit)
{
- const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
+ const auto chainParams = CreateChainParams(*m_node.args, ChainType::MAIN);
int64_t nLastRetargetTime = 1231006505; // Block #0
CBlockIndex pindexLast;
pindexLast.nHeight = 2015;
@@ -48,7 +49,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_pow_limit)
/* Test the constraint on the lower bound for actual time taken */
BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual)
{
- const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
+ const auto chainParams = CreateChainParams(*m_node.args, ChainType::MAIN);
int64_t nLastRetargetTime = 1279008237; // Block #66528
CBlockIndex pindexLast;
pindexLast.nHeight = 68543;
@@ -65,7 +66,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual)
/* Test the constraint on the upper bound for actual time taken */
BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
{
- const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
+ const auto chainParams = CreateChainParams(*m_node.args, ChainType::MAIN);
int64_t nLastRetargetTime = 1263163443; // NOTE: Not an actual block time
CBlockIndex pindexLast;
pindexLast.nHeight = 46367;
@@ -81,7 +82,7 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_negative_target)
{
- const auto consensus = CreateChainParams(*m_node.args, CBaseChainParams::MAIN)->GetConsensus();
+ const auto consensus = CreateChainParams(*m_node.args, ChainType::MAIN)->GetConsensus();
uint256 hash;
unsigned int nBits;
nBits = UintToArith256(consensus.powLimit).GetCompact(true);
@@ -91,7 +92,7 @@ BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_negative_target)
BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_overflow_target)
{
- const auto consensus = CreateChainParams(*m_node.args, CBaseChainParams::MAIN)->GetConsensus();
+ const auto consensus = CreateChainParams(*m_node.args, ChainType::MAIN)->GetConsensus();
uint256 hash;
unsigned int nBits{~0x00800000U};
hash.SetHex("0x1");
@@ -100,7 +101,7 @@ BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_overflow_target)
BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_too_easy_target)
{
- const auto consensus = CreateChainParams(*m_node.args, CBaseChainParams::MAIN)->GetConsensus();
+ const auto consensus = CreateChainParams(*m_node.args, ChainType::MAIN)->GetConsensus();
uint256 hash;
unsigned int nBits;
arith_uint256 nBits_arith = UintToArith256(consensus.powLimit);
@@ -112,7 +113,7 @@ BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_too_easy_target)
BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_biger_hash_than_target)
{
- const auto consensus = CreateChainParams(*m_node.args, CBaseChainParams::MAIN)->GetConsensus();
+ const auto consensus = CreateChainParams(*m_node.args, ChainType::MAIN)->GetConsensus();
uint256 hash;
unsigned int nBits;
arith_uint256 hash_arith = UintToArith256(consensus.powLimit);
@@ -124,7 +125,7 @@ BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_biger_hash_than_target)
BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_zero_target)
{
- const auto consensus = CreateChainParams(*m_node.args, CBaseChainParams::MAIN)->GetConsensus();
+ const auto consensus = CreateChainParams(*m_node.args, ChainType::MAIN)->GetConsensus();
uint256 hash;
unsigned int nBits;
arith_uint256 hash_arith{0};
@@ -135,7 +136,7 @@ BOOST_AUTO_TEST_CASE(CheckProofOfWork_test_zero_target)
BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
{
- const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
+ const auto chainParams = CreateChainParams(*m_node.args, ChainType::MAIN);
std::vector<CBlockIndex> blocks(10000);
for (int i = 0; i < 10000; i++) {
blocks[i].pprev = i ? &blocks[i - 1] : nullptr;
@@ -155,9 +156,9 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
}
}
-void sanity_check_chainparams(const ArgsManager& args, std::string chainName)
+void sanity_check_chainparams(const ArgsManager& args, ChainType chain_type)
{
- const auto chainParams = CreateChainParams(args, chainName);
+ const auto chainParams = CreateChainParams(args, chain_type);
const auto consensus = chainParams->GetConsensus();
// hash genesis is correct
@@ -184,22 +185,22 @@ void sanity_check_chainparams(const ArgsManager& args, std::string chainName)
BOOST_AUTO_TEST_CASE(ChainParams_MAIN_sanity)
{
- sanity_check_chainparams(*m_node.args, CBaseChainParams::MAIN);
+ sanity_check_chainparams(*m_node.args, ChainType::MAIN);
}
BOOST_AUTO_TEST_CASE(ChainParams_REGTEST_sanity)
{
- sanity_check_chainparams(*m_node.args, CBaseChainParams::REGTEST);
+ sanity_check_chainparams(*m_node.args, ChainType::REGTEST);
}
BOOST_AUTO_TEST_CASE(ChainParams_TESTNET_sanity)
{
- sanity_check_chainparams(*m_node.args, CBaseChainParams::TESTNET);
+ sanity_check_chainparams(*m_node.args, ChainType::TESTNET);
}
BOOST_AUTO_TEST_CASE(ChainParams_SIGNET_sanity)
{
- sanity_check_chainparams(*m_node.args, CBaseChainParams::SIGNET);
+ sanity_check_chainparams(*m_node.args, ChainType::SIGNET);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 791c9ddf31..da0029c737 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -75,7 +75,7 @@ UniValue RPCTestingSetup::CallRPC(std::string args)
return result;
}
catch (const UniValue& objError) {
- throw std::runtime_error(find_value(objError, "message").get_str());
+ throw std::runtime_error(objError.find_value("message").get_str());
}
}
@@ -130,9 +130,9 @@ BOOST_AUTO_TEST_CASE(rpc_rawparams)
BOOST_CHECK_THROW(CallRPC("decoderawtransaction DEADBEEF"), std::runtime_error);
std::string rawtx = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx));
- BOOST_CHECK_EQUAL(find_value(r.get_obj(), "size").getInt<int>(), 193);
- BOOST_CHECK_EQUAL(find_value(r.get_obj(), "version").getInt<int>(), 1);
- BOOST_CHECK_EQUAL(find_value(r.get_obj(), "locktime").getInt<int>(), 0);
+ BOOST_CHECK_EQUAL(r.get_obj().find_value("size").getInt<int>(), 193);
+ BOOST_CHECK_EQUAL(r.get_obj().find_value("version").getInt<int>(), 1);
+ BOOST_CHECK_EQUAL(r.get_obj().find_value("locktime").getInt<int>(), 0);
BOOST_CHECK_THROW(CallRPC(std::string("decoderawtransaction ")+rawtx+" extra"), std::runtime_error);
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false"));
BOOST_CHECK_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false extra"), std::runtime_error);
@@ -149,20 +149,20 @@ BOOST_AUTO_TEST_CASE(rpc_togglenetwork)
UniValue r;
r = CallRPC("getnetworkinfo");
- bool netState = find_value(r.get_obj(), "networkactive").get_bool();
+ bool netState = r.get_obj().find_value("networkactive").get_bool();
BOOST_CHECK_EQUAL(netState, true);
BOOST_CHECK_NO_THROW(CallRPC("setnetworkactive false"));
r = CallRPC("getnetworkinfo");
- int numConnection = find_value(r.get_obj(), "connections").getInt<int>();
+ int numConnection = r.get_obj().find_value("connections").getInt<int>();
BOOST_CHECK_EQUAL(numConnection, 0);
- netState = find_value(r.get_obj(), "networkactive").get_bool();
+ netState = r.get_obj().find_value("networkactive").get_bool();
BOOST_CHECK_EQUAL(netState, false);
BOOST_CHECK_NO_THROW(CallRPC("setnetworkactive true"));
r = CallRPC("getnetworkinfo");
- netState = find_value(r.get_obj(), "networkactive").get_bool();
+ netState = r.get_obj().find_value("networkactive").get_bool();
BOOST_CHECK_EQUAL(netState, true);
}
@@ -180,9 +180,9 @@ BOOST_AUTO_TEST_CASE(rpc_rawsign)
std::string privkey1 = "\"KzsXybp9jX64P5ekX1KUxRQ79Jht9uzW7LorgwE65i5rWACL6LQe\"";
std::string privkey2 = "\"Kyhdf5LuKTRx4ge69ybABsiUAWjVRK4XGxAKk2FQLp2HjGMy87Z4\"";
r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" [] "+prevout);
- BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == false);
+ BOOST_CHECK(r.get_obj().find_value("complete").get_bool() == false);
r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" ["+privkey1+","+privkey2+"] "+prevout);
- BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true);
+ BOOST_CHECK(r.get_obj().find_value("complete").get_bool() == true);
}
BOOST_AUTO_TEST_CASE(rpc_createraw_op_return)
@@ -325,7 +325,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
UniValue ar = r.get_array();
UniValue o1 = ar[0].get_obj();
- UniValue adr = find_value(o1, "address");
+ UniValue adr = o1.find_value("address");
BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/32");
BOOST_CHECK_NO_THROW(CallRPC(std::string("setban 127.0.0.0 remove")));
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
@@ -336,8 +336,8 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
o1 = ar[0].get_obj();
- adr = find_value(o1, "address");
- int64_t banned_until{find_value(o1, "banned_until").getInt<int64_t>()};
+ adr = o1.find_value("address");
+ int64_t banned_until{o1.find_value("banned_until").getInt<int64_t>()};
BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
BOOST_CHECK_EQUAL(banned_until, 9907731200); // absolute time check
@@ -351,11 +351,11 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
o1 = ar[0].get_obj();
- adr = find_value(o1, "address");
- banned_until = find_value(o1, "banned_until").getInt<int64_t>();
- const int64_t ban_created{find_value(o1, "ban_created").getInt<int64_t>()};
- const int64_t ban_duration{find_value(o1, "ban_duration").getInt<int64_t>()};
- const int64_t time_remaining{find_value(o1, "time_remaining").getInt<int64_t>()};
+ adr = o1.find_value("address");
+ banned_until = o1.find_value("banned_until").getInt<int64_t>();
+ const int64_t ban_created{o1.find_value("ban_created").getInt<int64_t>()};
+ const int64_t ban_duration{o1.find_value("ban_duration").getInt<int64_t>()};
+ const int64_t time_remaining{o1.find_value("time_remaining").getInt<int64_t>()};
BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
BOOST_CHECK_EQUAL(banned_until, time_remaining_expected + now.count());
BOOST_CHECK_EQUAL(ban_duration, banned_until - ban_created);
@@ -385,7 +385,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
o1 = ar[0].get_obj();
- adr = find_value(o1, "address");
+ adr = o1.find_value("address");
BOOST_CHECK_EQUAL(adr.get_str(), "fe80::202:b3ff:fe1e:8329/128");
BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
@@ -393,7 +393,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
o1 = ar[0].get_obj();
- adr = find_value(o1, "address");
+ adr = o1.find_value("address");
BOOST_CHECK_EQUAL(adr.get_str(), "2001:db8::/30");
BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
@@ -401,7 +401,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
ar = r.get_array();
o1 = ar[0].get_obj();
- adr = find_value(o1, "address");
+ adr = o1.find_value("address");
BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128");
}
diff --git a/src/test/settings_tests.cpp b/src/test/settings_tests.cpp
index 604eb48df6..fff84d24f0 100644
--- a/src/test/settings_tests.cpp
+++ b/src/test/settings_tests.cpp
@@ -6,12 +6,12 @@
#include <test/util/setup_common.h>
#include <test/util/str.h>
-#include <util/fs.h>
-
#include <boost/test/unit_test.hpp>
#include <common/args.h>
#include <univalue.h>
+#include <util/chaintype.h>
+#include <util/fs.h>
#include <util/strencodings.h>
#include <util/string.h>
@@ -190,7 +190,7 @@ BOOST_FIXTURE_TEST_CASE(Merge, MergeTestingSetup)
if (!out_file) throw std::system_error(errno, std::generic_category(), "fopen failed");
}
- const std::string& network = CBaseChainParams::MAIN;
+ const std::string& network = ChainTypeToString(ChainType::MAIN);
ForEachMergeSetup([&](const ActionList& arg_actions, const ActionList& conf_actions, bool force_set,
bool ignore_default_section_config) {
std::string desc;
@@ -225,7 +225,7 @@ BOOST_FIXTURE_TEST_CASE(Merge, MergeTestingSetup)
}
desc += " || ";
- desc += GetSetting(settings, network, name, ignore_default_section_config, /*ignore_nonpersistent=*/false, /*get_chain_name=*/false).write();
+ desc += GetSetting(settings, network, name, ignore_default_section_config, /*ignore_nonpersistent=*/false, /*get_chain_type=*/false).write();
desc += " |";
for (const auto& s : GetSettingsList(settings, network, name, ignore_default_section_config)) {
desc += " ";
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
index a0392570f1..55e4f200b1 100644
--- a/src/test/streams_tests.cpp
+++ b/src/test/streams_tests.cpp
@@ -463,7 +463,7 @@ BOOST_AUTO_TEST_CASE(streams_buffered_file_rand)
size_t find = currentPos + InsecureRandRange(8);
if (find >= fileSize)
find = fileSize - 1;
- bf.FindByte(uint8_t(find));
+ bf.FindByte(std::byte(find));
// The value at each offset is the offset.
BOOST_CHECK_EQUAL(bf.GetPos(), find);
currentPos = find;
diff --git a/src/test/system_tests.cpp b/src/test/system_tests.cpp
index c0a2566959..7ce350b84b 100644
--- a/src/test/system_tests.cpp
+++ b/src/test/system_tests.cpp
@@ -52,7 +52,7 @@ BOOST_AUTO_TEST_CASE(run_command)
const UniValue result = RunCommandParseJSON("echo \"{\"success\": true}\"");
#endif
BOOST_CHECK(result.isObject());
- const UniValue& success = find_value(result, "success");
+ const UniValue& success = result.find_value("success");
BOOST_CHECK(!success.isNull());
BOOST_CHECK_EQUAL(success.get_bool(), true);
}
@@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(run_command)
{
const UniValue result = RunCommandParseJSON("cat", "{\"success\": true}");
BOOST_CHECK(result.isObject());
- const UniValue& success = find_value(result, "success");
+ const UniValue& success = result.find_value("success");
BOOST_CHECK(!success.isNull());
BOOST_CHECK_EQUAL(success.get_bool(), true);
}
diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp
index b9bfa65c0a..b666517ae2 100644
--- a/src/test/txindex_tests.cpp
+++ b/src/test/txindex_tests.cpp
@@ -32,10 +32,10 @@ BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
BOOST_REQUIRE(txindex.Start());
// Allow tx index to catch up with the block index.
- constexpr int64_t timeout_ms = 10 * 1000;
- int64_t time_start = GetTimeMillis();
+ constexpr auto timeout{10s};
+ const auto time_start{SteadyClock::now()};
while (!txindex.BlockUntilSyncedToCurrentChain()) {
- BOOST_REQUIRE(time_start + timeout_ms > GetTimeMillis());
+ BOOST_REQUIRE(time_start + timeout > SteadyClock::now());
UninterruptibleSleep(std::chrono::milliseconds{100});
}
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index 8cdea3890e..8f8628169f 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -9,13 +9,14 @@
#include <script/standard.h>
#include <test/util/setup_common.h>
#include <txmempool.h>
+#include <util/chaintype.h>
#include <validation.h>
#include <boost/test/unit_test.hpp>
struct Dersig100Setup : public TestChain100Setup {
Dersig100Setup()
- : TestChain100Setup{CBaseChainParams::REGTEST, {"-testactivationheight=dersig@102"}} {}
+ : TestChain100Setup{ChainType::REGTEST, {"-testactivationheight=dersig@102"}} {}
};
bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
diff --git a/src/test/util/blockfilter.cpp b/src/test/util/blockfilter.cpp
index ec703c6a7b..a806844e34 100644
--- a/src/test/util/blockfilter.cpp
+++ b/src/test/util/blockfilter.cpp
@@ -8,20 +8,19 @@
#include <node/blockstorage.h>
#include <validation.h>
-using node::ReadBlockFromDisk;
-using node::UndoReadFromDisk;
+using node::BlockManager;
-bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index, BlockFilter& filter)
+bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex& block_index, BlockFilter& filter, const BlockManager& blockman)
{
LOCK(::cs_main);
CBlock block;
- if (!ReadBlockFromDisk(block, block_index->GetBlockPos(), Params().GetConsensus())) {
+ if (!blockman.ReadBlockFromDisk(block, block_index.GetBlockPos())) {
return false;
}
CBlockUndo block_undo;
- if (block_index->nHeight > 0 && !UndoReadFromDisk(block_undo, block_index)) {
+ if (block_index.nHeight > 0 && !blockman.UndoReadFromDisk(block_undo, block_index)) {
return false;
}
diff --git a/src/test/util/blockfilter.h b/src/test/util/blockfilter.h
index 79d11dcad8..789ce5d3aa 100644
--- a/src/test/util/blockfilter.h
+++ b/src/test/util/blockfilter.h
@@ -6,8 +6,12 @@
#define BITCOIN_TEST_UTIL_BLOCKFILTER_H
#include <blockfilter.h>
+
class CBlockIndex;
+namespace node {
+class BlockManager;
+}
-bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index, BlockFilter& filter);
+bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex& block_index, BlockFilter& filter, const node::BlockManager& blockman);
#endif // BITCOIN_TEST_UTIL_BLOCKFILTER_H
diff --git a/src/test/util/mining.cpp b/src/test/util/mining.cpp
index 0df1db84c4..51f4b89512 100644
--- a/src/test/util/mining.cpp
+++ b/src/test/util/mining.cpp
@@ -6,19 +6,22 @@
#include <chainparams.h>
#include <consensus/merkle.h>
+#include <consensus/validation.h>
#include <key_io.h>
#include <node/context.h>
#include <pow.h>
+#include <primitives/transaction.h>
#include <script/standard.h>
#include <test/util/script.h>
#include <util/check.h>
#include <validation.h>
+#include <validationinterface.h>
#include <versionbits.h>
using node::BlockAssembler;
using node::NodeContext;
-CTxIn generatetoaddress(const NodeContext& node, const std::string& address)
+COutPoint generatetoaddress(const NodeContext& node, const std::string& address)
{
const auto dest = DecodeDestination(address);
assert(IsValidDestination(dest));
@@ -58,19 +61,52 @@ std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const
return ret;
}
-CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
+COutPoint MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey)
{
auto block = PrepareBlock(node, coinbase_scriptPubKey);
+ auto valid = MineBlock(node, block);
+ assert(!valid.IsNull());
+ return valid;
+}
+
+struct BlockValidationStateCatcher : public CValidationInterface {
+ const uint256 m_hash;
+ std::optional<BlockValidationState> m_state;
+ BlockValidationStateCatcher(const uint256& hash)
+ : m_hash{hash},
+ m_state{} {}
+
+protected:
+ void BlockChecked(const CBlock& block, const BlockValidationState& state) override
+ {
+ if (block.GetHash() != m_hash) return;
+ m_state = state;
+ }
+};
+
+COutPoint MineBlock(const NodeContext& node, std::shared_ptr<CBlock>& block)
+{
while (!CheckProofOfWork(block->GetHash(), block->nBits, Params().GetConsensus())) {
++block->nNonce;
assert(block->nNonce);
}
- bool processed{Assert(node.chainman)->ProcessNewBlock(block, true, true, nullptr)};
- assert(processed);
-
- return CTxIn{block->vtx[0]->GetHash(), 0};
+ auto& chainman{*Assert(node.chainman)};
+ const auto old_height = WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight());
+ bool new_block;
+ BlockValidationStateCatcher bvsc{block->GetHash()};
+ RegisterValidationInterface(&bvsc);
+ const bool processed{chainman.ProcessNewBlock(block, true, true, &new_block)};
+ const bool duplicate{!new_block && processed};
+ assert(!duplicate);
+ UnregisterValidationInterface(&bvsc);
+ SyncWithValidationInterfaceQueue();
+ const bool was_valid{bvsc.m_state && bvsc.m_state->IsValid()};
+ assert(old_height + was_valid == WITH_LOCK(chainman.GetMutex(), return chainman.ActiveHeight()));
+
+ if (was_valid) return {block->vtx[0]->GetHash(), 0};
+ return {};
}
std::shared_ptr<CBlock> PrepareBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey,
diff --git a/src/test/util/mining.h b/src/test/util/mining.h
index 70b1f7b3fb..3f071257f1 100644
--- a/src/test/util/mining.h
+++ b/src/test/util/mining.h
@@ -13,8 +13,8 @@
class CBlock;
class CChainParams;
+class COutPoint;
class CScript;
-class CTxIn;
namespace node {
struct NodeContext;
} // namespace node
@@ -23,7 +23,13 @@ struct NodeContext;
std::vector<std::shared_ptr<CBlock>> CreateBlockChain(size_t total_height, const CChainParams& params);
/** Returns the generated coin */
-CTxIn MineBlock(const node::NodeContext&, const CScript& coinbase_scriptPubKey);
+COutPoint MineBlock(const node::NodeContext&, const CScript& coinbase_scriptPubKey);
+
+/**
+ * Returns the generated coin (or Null if the block was invalid).
+ * It is recommended to call RegenerateCommitments before mining the block to avoid merkle tree mismatches.
+ **/
+COutPoint MineBlock(const node::NodeContext&, std::shared_ptr<CBlock>& block);
/** Prepare a block to be mined */
std::shared_ptr<CBlock> PrepareBlock(const node::NodeContext&, const CScript& coinbase_scriptPubKey);
@@ -31,6 +37,6 @@ std::shared_ptr<CBlock> PrepareBlock(const node::NodeContext& node, const CScrip
const node::BlockAssembler::Options& assembler_options);
/** RPC-like helper function, returns the generated coin */
-CTxIn generatetoaddress(const node::NodeContext&, const std::string& address);
+COutPoint generatetoaddress(const node::NodeContext&, const std::string& address);
#endif // BITCOIN_TEST_UTIL_MINING_H
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index ddc1e7ab37..62d60d6774 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -42,6 +42,7 @@
#include <timedata.h>
#include <txdb.h>
#include <txmempool.h>
+#include <util/chaintype.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/system.h>
@@ -61,6 +62,7 @@
using kernel::ValidationCacheSizes;
using node::ApplyArgsManOptions;
using node::BlockAssembler;
+using node::BlockManager;
using node::CalculateCacheSizes;
using node::LoadChainstate;
using node::RegenerateCommitments;
@@ -98,7 +100,7 @@ std::ostream& operator<<(std::ostream& os, const uint256& num)
return os;
}
-BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
+BasicTestingSetup::BasicTestingSetup(const ChainType chainType, const std::vector<const char*>& extra_args)
: m_path_root{fs::temp_directory_path() / "test_common_" PACKAGE_NAME / g_insecure_rand_ctx_temp_path.rand256().ToString()},
m_args{}
{
@@ -132,7 +134,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName, const std::ve
throw std::runtime_error{error};
}
}
- SelectParams(chainName);
+ SelectParams(chainType);
SeedInsecureRand();
if (G_TEST_LOG_FUN) LogInstance().PushBackCallback(G_TEST_LOG_FUN);
InitLogging(*m_node.args);
@@ -163,8 +165,8 @@ BasicTestingSetup::~BasicTestingSetup()
gArgs.ClearArgs();
}
-ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
- : BasicTestingSetup(chainName, extra_args)
+ChainTestingSetup::ChainTestingSetup(const ChainType chainType, const std::vector<const char*>& extra_args)
+ : BasicTestingSetup(chainType, extra_args)
{
const CChainParams& chainparams = Params();
@@ -185,7 +187,11 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve
.adjusted_time_callback = GetAdjustedTime,
.check_block_index = true,
};
- m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts, node::BlockManager::Options{});
+ const BlockManager::Options blockman_opts{
+ .chainparams = chainman_opts.chainparams,
+ .blocks_dir = m_args.GetBlocksDirPath(),
+ };
+ m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts, blockman_opts);
m_node.chainman->m_blockman.m_block_tree_db = std::make_unique<CBlockTreeDB>(DBParams{
.path = m_args.GetDataDirNet() / "blocks" / "index",
.cache_bytes = static_cast<size_t>(m_cache_sizes.block_tree_db),
@@ -211,7 +217,7 @@ ChainTestingSetup::~ChainTestingSetup()
m_node.chainman.reset();
}
-void TestingSetup::LoadVerifyActivateChainstate()
+void ChainTestingSetup::LoadVerifyActivateChainstate()
{
auto& chainman{*Assert(m_node.chainman)};
node::ChainstateLoadOptions options;
@@ -237,14 +243,14 @@ void TestingSetup::LoadVerifyActivateChainstate()
}
TestingSetup::TestingSetup(
- const std::string& chainName,
+ const ChainType chainType,
const std::vector<const char*>& extra_args,
const bool coins_db_in_memory,
const bool block_tree_db_in_memory)
- : ChainTestingSetup(chainName, extra_args),
- m_coins_db_in_memory(coins_db_in_memory),
- m_block_tree_db_in_memory(block_tree_db_in_memory)
+ : ChainTestingSetup(chainType, extra_args)
{
+ m_coins_db_in_memory = coins_db_in_memory;
+ m_block_tree_db_in_memory = block_tree_db_in_memory;
// Ideally we'd move all the RPC tests to the functional testing framework
// instead of unit tests, but for now we need these here.
RegisterAllCoreRPCCommands(tableRPC);
@@ -268,11 +274,11 @@ TestingSetup::TestingSetup(
}
TestChain100Setup::TestChain100Setup(
- const std::string& chain_name,
+ const ChainType chain_type,
const std::vector<const char*>& extra_args,
const bool coins_db_in_memory,
const bool block_tree_db_in_memory)
- : TestingSetup{CBaseChainParams::REGTEST, extra_args, coins_db_in_memory, block_tree_db_in_memory}
+ : TestingSetup{ChainType::REGTEST, extra_args, coins_db_in_memory, block_tree_db_in_memory}
{
SetMockTime(1598887952);
constexpr std::array<unsigned char, 32> vchKey = {
diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h
index 750f010fb0..bd5a81be45 100644
--- a/src/test/util/setup_common.h
+++ b/src/test/util/setup_common.h
@@ -5,7 +5,6 @@
#ifndef BITCOIN_TEST_UTIL_SETUP_COMMON_H
#define BITCOIN_TEST_UTIL_SETUP_COMMON_H
-#include <chainparamsbase.h>
#include <common/args.h>
#include <key.h>
#include <node/caches.h>
@@ -14,6 +13,7 @@
#include <pubkey.h>
#include <random.h>
#include <stdexcept>
+#include <util/chaintype.h>
#include <util/check.h>
#include <util/fs.h>
#include <util/string.h>
@@ -80,7 +80,7 @@ static constexpr CAmount CENT{1000000};
struct BasicTestingSetup {
node::NodeContext m_node; // keep as first member to be destructed last
- explicit BasicTestingSetup(const std::string& chainName = CBaseChainParams::MAIN, const std::vector<const char*>& extra_args = {});
+ explicit BasicTestingSetup(const ChainType chainType = ChainType::MAIN, const std::vector<const char*>& extra_args = {});
~BasicTestingSetup();
const fs::path m_path_root;
@@ -93,21 +93,21 @@ struct BasicTestingSetup {
*/
struct ChainTestingSetup : public BasicTestingSetup {
node::CacheSizes m_cache_sizes{};
+ bool m_coins_db_in_memory{true};
+ bool m_block_tree_db_in_memory{true};
- explicit ChainTestingSetup(const std::string& chainName = CBaseChainParams::MAIN, const std::vector<const char*>& extra_args = {});
+ explicit ChainTestingSetup(const ChainType chainType = ChainType::MAIN, const std::vector<const char*>& extra_args = {});
~ChainTestingSetup();
+
+ // Supplies a chainstate, if one is needed
+ void LoadVerifyActivateChainstate();
};
/** Testing setup that configures a complete environment.
*/
struct TestingSetup : public ChainTestingSetup {
- bool m_coins_db_in_memory{true};
- bool m_block_tree_db_in_memory{true};
-
- void LoadVerifyActivateChainstate();
-
explicit TestingSetup(
- const std::string& chainName = CBaseChainParams::MAIN,
+ const ChainType chainType = ChainType::MAIN,
const std::vector<const char*>& extra_args = {},
const bool coins_db_in_memory = true,
const bool block_tree_db_in_memory = true);
@@ -116,7 +116,7 @@ struct TestingSetup : public ChainTestingSetup {
/** Identical to TestingSetup, but chain set to regtest */
struct RegTestingSetup : public TestingSetup {
RegTestingSetup()
- : TestingSetup{CBaseChainParams::REGTEST} {}
+ : TestingSetup{ChainType::REGTEST} {}
};
class CBlock;
@@ -128,7 +128,7 @@ class CScript;
*/
struct TestChain100Setup : public TestingSetup {
TestChain100Setup(
- const std::string& chain_name = CBaseChainParams::REGTEST,
+ const ChainType chain_type = ChainType::REGTEST,
const std::vector<const char*>& extra_args = {},
const bool coins_db_in_memory = true,
const bool block_tree_db_in_memory = true);
@@ -206,7 +206,7 @@ struct TestChain100Setup : public TestingSetup {
* be used in "hot loops", for example fuzzing or benchmarking.
*/
template <class T = const BasicTestingSetup>
-std::unique_ptr<T> MakeNoLogFileContext(const std::string& chain_name = CBaseChainParams::REGTEST, const std::vector<const char*>& extra_args = {})
+std::unique_ptr<T> MakeNoLogFileContext(const ChainType chain_type = ChainType::REGTEST, const std::vector<const char*>& extra_args = {})
{
const std::vector<const char*> arguments = Cat(
{
@@ -215,7 +215,7 @@ std::unique_ptr<T> MakeNoLogFileContext(const std::string& chain_name = CBaseCha
},
extra_args);
- return std::make_unique<T>(chain_name, arguments);
+ return std::make_unique<T>(chain_type, arguments);
}
CBlock getBlock13b8a();
diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp
index edc7e4b70a..05e2787075 100644
--- a/src/test/validation_chainstatemanager_tests.cpp
+++ b/src/test/validation_chainstatemanager_tests.cpp
@@ -22,6 +22,7 @@
#include <boost/test/unit_test.hpp>
+using node::BlockManager;
using node::SnapshotMetadata;
BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, ChainTestingSetup)
@@ -381,10 +382,14 @@ struct SnapshotTestSetup : TestChain100Setup {
.datadir = m_args.GetDataDirNet(),
.adjusted_time_callback = GetAdjustedTime,
};
+ const BlockManager::Options blockman_opts{
+ .chainparams = chainman_opts.chainparams,
+ .blocks_dir = m_args.GetBlocksDirPath(),
+ };
// For robustness, ensure the old manager is destroyed before creating a
// new one.
m_node.chainman.reset();
- m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts, node::BlockManager::Options{});
+ m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts, blockman_opts);
}
return *Assert(m_node.chainman);
}
diff --git a/src/test/validation_tests.cpp b/src/test/validation_tests.cpp
index 0b4c491615..d00f2ff4d1 100644
--- a/src/test/validation_tests.cpp
+++ b/src/test/validation_tests.cpp
@@ -7,6 +7,7 @@
#include <net.h>
#include <signet.h>
#include <uint256.h>
+#include <util/chaintype.h>
#include <validation.h>
#include <test/util/setup_common.h>
@@ -41,7 +42,7 @@ static void TestBlockSubsidyHalvings(int nSubsidyHalvingInterval)
BOOST_AUTO_TEST_CASE(block_subsidy_test)
{
- const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
+ const auto chainParams = CreateChainParams(*m_node.args, ChainType::MAIN);
TestBlockSubsidyHalvings(chainParams->GetConsensus()); // As in main
TestBlockSubsidyHalvings(150); // As in regtest
TestBlockSubsidyHalvings(1000); // Just another interval
@@ -49,7 +50,7 @@ BOOST_AUTO_TEST_CASE(block_subsidy_test)
BOOST_AUTO_TEST_CASE(subsidy_limit_test)
{
- const auto chainParams = CreateChainParams(*m_node.args, CBaseChainParams::MAIN);
+ const auto chainParams = CreateChainParams(*m_node.args, ChainType::MAIN);
CAmount nSum = 0;
for (int nHeight = 0; nHeight < 14000000; nHeight += 1000) {
CAmount nSubsidy = GetBlockSubsidy(nHeight, chainParams->GetConsensus());
@@ -64,7 +65,7 @@ BOOST_AUTO_TEST_CASE(signet_parse_tests)
{
ArgsManager signet_argsman;
signet_argsman.ForceSetArg("-signetchallenge", "51"); // set challenge to OP_TRUE
- const auto signet_params = CreateChainParams(signet_argsman, CBaseChainParams::SIGNET);
+ const auto signet_params = CreateChainParams(signet_argsman, ChainType::SIGNET);
CBlock block;
BOOST_CHECK(signet_params->GetConsensus().signet_challenge == std::vector<uint8_t>{OP_TRUE});
CScript challenge{OP_TRUE};
@@ -124,7 +125,7 @@ BOOST_AUTO_TEST_CASE(signet_parse_tests)
//! Test retrieval of valid assumeutxo values.
BOOST_AUTO_TEST_CASE(test_assumeutxo)
{
- const auto params = CreateChainParams(*m_node.args, CBaseChainParams::REGTEST);
+ const auto params = CreateChainParams(*m_node.args, ChainType::REGTEST);
// These heights don't have assumeutxo configurations associated, per the contents
// of kernel/chainparams.cpp.
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
index 80c00036e7..9e69992752 100644
--- a/src/test/versionbits_tests.cpp
+++ b/src/test/versionbits_tests.cpp
@@ -7,6 +7,7 @@
#include <consensus/params.h>
#include <test/util/random.h>
#include <test/util/setup_common.h>
+#include <util/chaintype.h>
#include <versionbits.h>
#include <boost/test/unit_test.hpp>
@@ -418,8 +419,8 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
// check that any deployment on any chain can conceivably reach both
// ACTIVE and FAILED states in roughly the way we expect
- for (const auto& chain_name : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::SIGNET, CBaseChainParams::REGTEST}) {
- const auto chainParams = CreateChainParams(*m_node.args, chain_name);
+ for (const auto& chain_type: {ChainType::MAIN, ChainType::TESTNET, ChainType::SIGNET, ChainType::REGTEST}) {
+ const auto chainParams = CreateChainParams(*m_node.args, chain_type);
uint32_t chain_all_vbits{0};
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) {
const auto dep = static_cast<Consensus::DeploymentPos>(i);
@@ -440,7 +441,7 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
// deployment that's not always/never active
ArgsManager args;
args.ForceSetArg("-vbparams", "testdummy:1199145601:1230767999"); // January 1, 2008 - December 31, 2008
- const auto chainParams = CreateChainParams(args, CBaseChainParams::REGTEST);
+ const auto chainParams = CreateChainParams(args, ChainType::REGTEST);
check_computeblockversion(vbcache, chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
}
@@ -450,7 +451,7 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
// live deployment
ArgsManager args;
args.ForceSetArg("-vbparams", "testdummy:1199145601:1230767999:403200"); // January 1, 2008 - December 31, 2008, min act height 403200
- const auto chainParams = CreateChainParams(args, CBaseChainParams::REGTEST);
+ const auto chainParams = CreateChainParams(args, ChainType::REGTEST);
check_computeblockversion(vbcache, chainParams->GetConsensus(), Consensus::DEPLOYMENT_TESTDUMMY);
}
}
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index da875c271e..05f28520be 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -755,11 +755,16 @@ void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendhei
bool CTxMemPool::CompareDepthAndScore(const uint256& hasha, const uint256& hashb, bool wtxid)
{
+ /* Return `true` if hasha should be considered sooner than hashb. Namely when:
+ * a is not in the mempool, but b is
+ * both are in the mempool and a has fewer ancestors than b
+ * both are in the mempool and a has a higher score than b
+ */
LOCK(cs);
- indexed_transaction_set::const_iterator i = wtxid ? get_iter_from_wtxid(hasha) : mapTx.find(hasha);
- if (i == mapTx.end()) return false;
indexed_transaction_set::const_iterator j = wtxid ? get_iter_from_wtxid(hashb) : mapTx.find(hashb);
- if (j == mapTx.end()) return true;
+ if (j == mapTx.end()) return false;
+ indexed_transaction_set::const_iterator i = wtxid ? get_iter_from_wtxid(hasha) : mapTx.find(hasha);
+ if (i == mapTx.end()) return true;
uint64_t counta = i->GetCountWithAncestors();
uint64_t countb = j->GetCountWithAncestors();
if (counta == countb) {
diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h
index d501c3fb69..004135ef97 100644
--- a/src/univalue/include/univalue.h
+++ b/src/univalue/include/univalue.h
@@ -123,7 +123,7 @@ public:
const UniValue& get_array() const;
enum VType type() const { return getType(); }
- friend const UniValue& find_value( const UniValue& obj, const std::string& name);
+ const UniValue& find_value(std::string_view key) const;
};
template <class It>
@@ -201,6 +201,4 @@ static inline bool json_isspace(int ch)
extern const UniValue NullUniValue;
-const UniValue& find_value( const UniValue& obj, const std::string& name);
-
#endif // BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_H
diff --git a/src/univalue/lib/univalue.cpp b/src/univalue/lib/univalue.cpp
index 5aa39edb75..c3d19caae0 100644
--- a/src/univalue/lib/univalue.cpp
+++ b/src/univalue/lib/univalue.cpp
@@ -230,12 +230,13 @@ const char *uvTypeName(UniValue::VType t)
return nullptr;
}
-const UniValue& find_value(const UniValue& obj, const std::string& name)
+const UniValue& UniValue::find_value(std::string_view key) const
{
- for (unsigned int i = 0; i < obj.keys.size(); i++)
- if (obj.keys[i] == name)
- return obj.values.at(i);
-
+ for (unsigned int i = 0; i < keys.size(); ++i) {
+ if (keys[i] == key) {
+ return values.at(i);
+ }
+ }
return NullUniValue;
}
diff --git a/src/util/bip32.cpp b/src/util/bip32.cpp
index c0ad9257ce..4ab14bd704 100644
--- a/src/util/bip32.cpp
+++ b/src/util/bip32.cpp
@@ -51,17 +51,17 @@ bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypa
return true;
}
-std::string FormatHDKeypath(const std::vector<uint32_t>& path)
+std::string FormatHDKeypath(const std::vector<uint32_t>& path, bool apostrophe)
{
std::string ret;
for (auto i : path) {
ret += strprintf("/%i", (i << 1) >> 1);
- if (i >> 31) ret += '\'';
+ if (i >> 31) ret += apostrophe ? '\'' : 'h';
}
return ret;
}
-std::string WriteHDKeypath(const std::vector<uint32_t>& keypath)
+std::string WriteHDKeypath(const std::vector<uint32_t>& keypath, bool apostrophe)
{
- return "m" + FormatHDKeypath(keypath);
+ return "m" + FormatHDKeypath(keypath, apostrophe);
}
diff --git a/src/util/bip32.h b/src/util/bip32.h
index b720cb5638..ea5f192c07 100644
--- a/src/util/bip32.h
+++ b/src/util/bip32.h
@@ -13,7 +13,7 @@
[[nodiscard]] bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath);
/** Write HD keypaths as strings */
-std::string WriteHDKeypath(const std::vector<uint32_t>& keypath);
-std::string FormatHDKeypath(const std::vector<uint32_t>& path);
+std::string WriteHDKeypath(const std::vector<uint32_t>& keypath, bool apostrophe = false);
+std::string FormatHDKeypath(const std::vector<uint32_t>& path, bool apostrophe = false);
#endif // BITCOIN_UTIL_BIP32_H
diff --git a/src/util/chaintype.cpp b/src/util/chaintype.cpp
new file mode 100644
index 0000000000..8a199e352a
--- /dev/null
+++ b/src/util/chaintype.cpp
@@ -0,0 +1,39 @@
+// Copyright (c) 2023 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util/chaintype.h>
+
+#include <cassert>
+#include <optional>
+#include <string>
+
+std::string ChainTypeToString(ChainType chain)
+{
+ switch (chain) {
+ case ChainType::MAIN:
+ return "main";
+ case ChainType::TESTNET:
+ return "test";
+ case ChainType::SIGNET:
+ return "signet";
+ case ChainType::REGTEST:
+ return "regtest";
+ }
+ assert(false);
+}
+
+std::optional<ChainType> ChainTypeFromString(std::string_view chain)
+{
+ if (chain == "main") {
+ return ChainType::MAIN;
+ } else if (chain == "test") {
+ return ChainType::TESTNET;
+ } else if (chain == "signet") {
+ return ChainType::SIGNET;
+ } else if (chain == "regtest") {
+ return ChainType::REGTEST;
+ } else {
+ return std::nullopt;
+ }
+}
diff --git a/src/util/chaintype.h b/src/util/chaintype.h
new file mode 100644
index 0000000000..c73985df57
--- /dev/null
+++ b/src/util/chaintype.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2023 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_UTIL_CHAINTYPE_H
+#define BITCOIN_UTIL_CHAINTYPE_H
+
+#include <optional>
+#include <string>
+
+enum class ChainType {
+ MAIN,
+ TESTNET,
+ SIGNET,
+ REGTEST,
+};
+
+std::string ChainTypeToString(ChainType chain);
+
+std::optional<ChainType> ChainTypeFromString(std::string_view chain);
+
+#endif // BITCOIN_UTIL_CHAINTYPE_H
diff --git a/src/util/settings.cpp b/src/util/settings.cpp
index bb257c0584..db3d60046e 100644
--- a/src/util/settings.cpp
+++ b/src/util/settings.cpp
@@ -130,7 +130,7 @@ SettingsValue GetSetting(const Settings& settings,
const std::string& name,
bool ignore_default_section_config,
bool ignore_nonpersistent,
- bool get_chain_name)
+ bool get_chain_type)
{
SettingsValue result;
bool done = false; // Done merging any more settings sources.
@@ -145,17 +145,17 @@ SettingsValue GetSetting(const Settings& settings,
// assigned value instead of last. In general, later settings take
// precedence over early settings, but for backwards compatibility in
// the config file the precedence is reversed for all settings except
- // chain name settings.
+ // chain type settings.
const bool reverse_precedence =
(source == Source::CONFIG_FILE_NETWORK_SECTION || source == Source::CONFIG_FILE_DEFAULT_SECTION) &&
- !get_chain_name;
+ !get_chain_type;
// Weird behavior preserved for backwards compatibility: Negated
// -regtest and -testnet arguments which you would expect to override
// values set in the configuration file are currently accepted but
// silently ignored. It would be better to apply these just like other
// negated values, or at least warn they are ignored.
- const bool skip_negated_command_line = get_chain_name;
+ const bool skip_negated_command_line = get_chain_type;
if (done) return;
diff --git a/src/util/settings.h b/src/util/settings.h
index 27e87a4751..bb1fe585e1 100644
--- a/src/util/settings.h
+++ b/src/util/settings.h
@@ -60,14 +60,14 @@ bool WriteSettings(const fs::path& path,
//! command line). Only return settings in the
//! read-only config and read-write settings
//! files.
-//! @param get_chain_name - enable special backwards compatible behavior
-//! for GetChainName
+//! @param get_chain_type - enable special backwards compatible behavior
+//! for GetChainType
SettingsValue GetSetting(const Settings& settings,
const std::string& section,
const std::string& name,
bool ignore_default_section_config,
bool ignore_nonpersistent,
- bool get_chain_name);
+ bool get_chain_type);
//! Get combined setting value similar to GetSetting(), except if setting was
//! specified multiple times, return a list of all the values specified.
diff --git a/src/util/time.cpp b/src/util/time.cpp
index fb9bc34931..5ca9d21f8d 100644
--- a/src/util/time.cpp
+++ b/src/util/time.cpp
@@ -78,14 +78,6 @@ NodeClock::time_point NodeClock::now() noexcept
return time_point{ret};
};
-template <typename T>
-static T GetSystemTime()
-{
- const auto now = std::chrono::duration_cast<T>(std::chrono::system_clock::now().time_since_epoch());
- assert(now.count() > 0);
- return now;
-}
-
void SetMockTime(int64_t nMockTimeIn)
{
Assert(nMockTimeIn >= 0);
@@ -102,11 +94,6 @@ std::chrono::seconds GetMockTime()
return std::chrono::seconds(nMockTime.load(std::memory_order_relaxed));
}
-int64_t GetTimeMillis()
-{
- return int64_t{GetSystemTime<std::chrono::milliseconds>().count()};
-}
-
int64_t GetTime() { return GetTime<std::chrono::seconds>().count(); }
std::string FormatISO8601DateTime(int64_t nTime) {
diff --git a/src/util/time.h b/src/util/time.h
index 8c6baeb12a..b6aab615ba 100644
--- a/src/util/time.h
+++ b/src/util/time.h
@@ -71,9 +71,6 @@ using MillisecondsDouble = std::chrono::duration<double, std::chrono::millisecon
*/
int64_t GetTime();
-/** Returns the system time (not mockable) */
-int64_t GetTimeMillis();
-
/**
* DEPRECATED
* Use SetMockTime with chrono type
diff --git a/src/validation.cpp b/src/validation.cpp
index b2f4283e16..e536dfb4eb 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -79,10 +79,7 @@ using node::BlockMap;
using node::CBlockIndexHeightOnlyComparator;
using node::CBlockIndexWorkComparator;
using node::fReindex;
-using node::ReadBlockFromDisk;
using node::SnapshotMetadata;
-using node::UndoReadFromDisk;
-using node::UnlinkPrunedFiles;
/** Maximum kilobytes for transactions to store for processing during reorg */
static const unsigned int MAX_DISCONNECTED_TX_POOL_SIZE = 20000;
@@ -1914,7 +1911,7 @@ DisconnectResult Chainstate::DisconnectBlock(const CBlock& block, const CBlockIn
bool fClean = true;
CBlockUndo blockUndo;
- if (!UndoReadFromDisk(blockUndo, pindex)) {
+ if (!m_blockman.UndoReadFromDisk(blockUndo, *pindex)) {
error("DisconnectBlock(): failure reading undo data");
return DISCONNECT_FAILED;
}
@@ -2374,7 +2371,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
if (fJustCheck)
return true;
- if (!m_blockman.WriteUndoDataForBlock(blockundo, state, pindex, params)) {
+ if (!m_blockman.WriteUndoDataForBlock(blockundo, state, *pindex)) {
return false;
}
@@ -2545,7 +2542,7 @@ bool Chainstate::FlushStateToDisk(
if (fFlushForPrune) {
LOG_TIME_MILLIS_WITH_CATEGORY("unlink pruned files", BCLog::BENCH);
- UnlinkPrunedFiles(setFilesToPrune);
+ m_blockman.UnlinkPrunedFiles(setFilesToPrune);
}
m_last_write = nNow;
}
@@ -2709,7 +2706,7 @@ bool Chainstate::DisconnectTip(BlockValidationState& state, DisconnectedBlockTra
// Read block from disk.
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
CBlock& block = *pblock;
- if (!ReadBlockFromDisk(block, pindexDelete, m_chainman.GetConsensus())) {
+ if (!m_blockman.ReadBlockFromDisk(block, *pindexDelete)) {
return error("DisconnectTip(): Failed to read block");
}
// Apply the block atomically to the chain state.
@@ -2826,7 +2823,7 @@ bool Chainstate::ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew,
std::shared_ptr<const CBlock> pthisBlock;
if (!pblock) {
std::shared_ptr<CBlock> pblockNew = std::make_shared<CBlock>();
- if (!ReadBlockFromDisk(*pblockNew, pindexNew, m_chainman.GetConsensus())) {
+ if (!m_blockman.ReadBlockFromDisk(*pblockNew, *pindexNew)) {
return AbortNode(state, "Failed to read block");
}
pthisBlock = pblockNew;
@@ -4000,7 +3997,7 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
// Write block to history file
if (fNewBlock) *fNewBlock = true;
try {
- FlatFilePos blockPos{m_blockman.SaveBlockToDisk(block, pindex->nHeight, m_chain, params, dbp)};
+ FlatFilePos blockPos{m_blockman.SaveBlockToDisk(block, pindex->nHeight, m_chain, dbp)};
if (blockPos.IsNull()) {
state.Error(strprintf("%s: Failed to find position to write new block to disk", __func__));
return false;
@@ -4208,7 +4205,7 @@ VerifyDBResult CVerifyDB::VerifyDB(
}
CBlock block;
// check level 0: read from disk
- if (!ReadBlockFromDisk(block, pindex, consensus_params)) {
+ if (!chainstate.m_blockman.ReadBlockFromDisk(block, *pindex)) {
LogPrintf("Verification error: ReadBlockFromDisk failed at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
return VerifyDBResult::CORRUPTED_BLOCK_DB;
}
@@ -4222,7 +4219,7 @@ VerifyDBResult CVerifyDB::VerifyDB(
if (nCheckLevel >= 2 && pindex) {
CBlockUndo undo;
if (!pindex->GetUndoPos().IsNull()) {
- if (!UndoReadFromDisk(undo, pindex)) {
+ if (!chainstate.m_blockman.UndoReadFromDisk(undo, *pindex)) {
LogPrintf("Verification error: found bad undo data at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
return VerifyDBResult::CORRUPTED_BLOCK_DB;
}
@@ -4274,7 +4271,7 @@ VerifyDBResult CVerifyDB::VerifyDB(
uiInterface.ShowProgress(_("Verifying blocks…").translated, percentageDone, false);
pindex = chainstate.m_chain.Next(pindex);
CBlock block;
- if (!ReadBlockFromDisk(block, pindex, consensus_params)) {
+ if (!chainstate.m_blockman.ReadBlockFromDisk(block, *pindex)) {
LogPrintf("Verification error: ReadBlockFromDisk failed at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
return VerifyDBResult::CORRUPTED_BLOCK_DB;
}
@@ -4303,7 +4300,7 @@ bool Chainstate::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& in
AssertLockHeld(cs_main);
// TODO: merge with ConnectBlock
CBlock block;
- if (!ReadBlockFromDisk(block, pindex, m_chainman.GetConsensus())) {
+ if (!m_blockman.ReadBlockFromDisk(block, *pindex)) {
return error("ReplayBlock(): ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
}
@@ -4355,7 +4352,7 @@ bool Chainstate::ReplayBlocks()
while (pindexOld != pindexFork) {
if (pindexOld->nHeight > 0) { // Never disconnect the genesis block.
CBlock block;
- if (!ReadBlockFromDisk(block, pindexOld, m_chainman.GetConsensus())) {
+ if (!m_blockman.ReadBlockFromDisk(block, *pindexOld)) {
return error("RollbackBlock(): ReadBlockFromDisk() failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString());
}
LogPrintf("Rolling back %s (%i)\n", pindexOld->GetBlockHash().ToString(), pindexOld->nHeight);
@@ -4418,7 +4415,7 @@ bool ChainstateManager::LoadBlockIndex()
// Load block index from databases
bool needs_init = fReindex;
if (!fReindex) {
- bool ret = m_blockman.LoadBlockIndexDB(GetConsensus());
+ bool ret{m_blockman.LoadBlockIndexDB()};
if (!ret) return false;
m_blockman.ScanAndUnlinkAlreadyPrunedFiles();
@@ -4522,7 +4519,7 @@ bool Chainstate::LoadGenesisBlock()
try {
const CBlock& block = params.GenesisBlock();
- FlatFilePos blockPos{m_blockman.SaveBlockToDisk(block, 0, m_chain, params, nullptr)};
+ FlatFilePos blockPos{m_blockman.SaveBlockToDisk(block, 0, m_chain, nullptr)};
if (blockPos.IsNull()) {
return error("%s: writing genesis block to disk failed", __func__);
}
@@ -4565,7 +4562,7 @@ void Chainstate::LoadExternalBlockFile(
try {
// locate a header
unsigned char buf[CMessageHeader::MESSAGE_START_SIZE];
- blkdat.FindByte(params.MessageStart()[0]);
+ blkdat.FindByte(std::byte(params.MessageStart()[0]));
nRewind = blkdat.GetPos() + 1;
blkdat >> buf;
if (memcmp(buf, params.MessageStart(), CMessageHeader::MESSAGE_START_SIZE)) {
@@ -4593,6 +4590,9 @@ void Chainstate::LoadExternalBlockFile(
// next block, but it's still possible to rewind to the start of the current block (without a disk read).
nRewind = nBlockPos + nSize;
blkdat.SkipTo(nRewind);
+
+ std::shared_ptr<CBlock> pblock{}; // needs to remain available after the cs_main lock is released to avoid duplicate reads from disk
+
{
LOCK(cs_main);
// detect out of order blocks, and store them for later
@@ -4610,7 +4610,7 @@ void Chainstate::LoadExternalBlockFile(
if (!pindex || (pindex->nStatus & BLOCK_HAVE_DATA) == 0) {
// This block can be processed immediately; rewind to its start, read and deserialize it.
blkdat.SetPos(nBlockPos);
- std::shared_ptr<CBlock> pblock{std::make_shared<CBlock>()};
+ pblock = std::make_shared<CBlock>();
blkdat >> *pblock;
nRewind = blkdat.GetPos();
@@ -4634,6 +4634,21 @@ void Chainstate::LoadExternalBlockFile(
}
}
+ if (m_blockman.IsPruneMode() && !fReindex && pblock) {
+ // must update the tip for pruning to work while importing with -loadblock.
+ // this is a tradeoff to conserve disk space at the expense of time
+ // spent updating the tip to be able to prune.
+ // otherwise, ActivateBestChain won't be called by the import process
+ // until after all of the block files are loaded. ActivateBestChain can be
+ // called by concurrent network message processing. but, that is not
+ // reliable for the purpose of pruning while importing.
+ BlockValidationState state;
+ if (!ActivateBestChain(state, pblock)) {
+ LogPrint(BCLog::REINDEX, "failed to activate chain (%s)\n", state.ToString());
+ break;
+ }
+ }
+
NotifyHeaderTip(*this);
if (!blocks_with_unknown_parent) continue;
@@ -4648,7 +4663,7 @@ void Chainstate::LoadExternalBlockFile(
while (range.first != range.second) {
std::multimap<uint256, FlatFilePos>::iterator it = range.first;
std::shared_ptr<CBlock> pblockrecursive = std::make_shared<CBlock>();
- if (ReadBlockFromDisk(*pblockrecursive, it->second, params.GetConsensus())) {
+ if (m_blockman.ReadBlockFromDisk(*pblockrecursive, it->second)) {
LogPrint(BCLog::REINDEX, "%s: Processing out of order child %s of %s\n", __func__, pblockrecursive->GetHash().ToString(),
head.ToString());
LOCK(cs_main);
diff --git a/src/wallet/coincontrol.cpp b/src/wallet/coincontrol.cpp
index ad2fab4b7d..2087119db9 100644
--- a/src/wallet/coincontrol.cpp
+++ b/src/wallet/coincontrol.cpp
@@ -11,4 +11,72 @@ CCoinControl::CCoinControl()
{
m_avoid_partial_spends = gArgs.GetBoolArg("-avoidpartialspends", DEFAULT_AVOIDPARTIALSPENDS);
}
+
+bool CCoinControl::HasSelected() const
+{
+ return !m_selected_inputs.empty();
+}
+
+bool CCoinControl::IsSelected(const COutPoint& output) const
+{
+ return m_selected_inputs.count(output) > 0;
+}
+
+bool CCoinControl::IsExternalSelected(const COutPoint& output) const
+{
+ return m_external_txouts.count(output) > 0;
+}
+
+std::optional<CTxOut> CCoinControl::GetExternalOutput(const COutPoint& outpoint) const
+{
+ const auto ext_it = m_external_txouts.find(outpoint);
+ if (ext_it == m_external_txouts.end()) {
+ return std::nullopt;
+ }
+
+ return std::make_optional(ext_it->second);
+}
+
+void CCoinControl::Select(const COutPoint& output)
+{
+ m_selected_inputs.insert(output);
+}
+
+void CCoinControl::SelectExternal(const COutPoint& outpoint, const CTxOut& txout)
+{
+ m_selected_inputs.insert(outpoint);
+ m_external_txouts.emplace(outpoint, txout);
+}
+
+void CCoinControl::UnSelect(const COutPoint& output)
+{
+ m_selected_inputs.erase(output);
+}
+
+void CCoinControl::UnSelectAll()
+{
+ m_selected_inputs.clear();
+}
+
+std::vector<COutPoint> CCoinControl::ListSelected() const
+{
+ return {m_selected_inputs.begin(), m_selected_inputs.end()};
+}
+
+void CCoinControl::SetInputWeight(const COutPoint& outpoint, int64_t weight)
+{
+ m_input_weights[outpoint] = weight;
+}
+
+bool CCoinControl::HasInputWeight(const COutPoint& outpoint) const
+{
+ return m_input_weights.count(outpoint) > 0;
+}
+
+int64_t CCoinControl::GetInputWeight(const COutPoint& outpoint) const
+{
+ auto it = m_input_weights.find(outpoint);
+ assert(it != m_input_weights.end());
+ return it->second;
+}
} // namespace wallet
diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h
index cb6f0a1635..7ff8fee5bc 100644
--- a/src/wallet/coincontrol.h
+++ b/src/wallet/coincontrol.h
@@ -13,9 +13,9 @@
#include <script/signingprovider.h>
#include <script/standard.h>
-#include <optional>
#include <algorithm>
#include <map>
+#include <optional>
#include <set>
namespace wallet {
@@ -63,76 +63,62 @@ public:
CCoinControl();
- bool HasSelected() const
- {
- return (setSelected.size() > 0);
- }
-
- bool IsSelected(const COutPoint& output) const
- {
- return (setSelected.count(output) > 0);
- }
-
- bool IsExternalSelected(const COutPoint& output) const
- {
- return (m_external_txouts.count(output) > 0);
- }
-
- bool GetExternalOutput(const COutPoint& outpoint, CTxOut& txout) const
- {
- const auto ext_it = m_external_txouts.find(outpoint);
- if (ext_it == m_external_txouts.end()) {
- return false;
- }
- txout = ext_it->second;
- return true;
- }
-
- void Select(const COutPoint& output)
- {
- setSelected.insert(output);
- }
-
- void SelectExternal(const COutPoint& outpoint, const CTxOut& txout)
- {
- setSelected.insert(outpoint);
- m_external_txouts.emplace(outpoint, txout);
- }
-
- void UnSelect(const COutPoint& output)
- {
- setSelected.erase(output);
- }
-
- void UnSelectAll()
- {
- setSelected.clear();
- }
-
- void ListSelected(std::vector<COutPoint>& vOutpoints) const
- {
- vOutpoints.assign(setSelected.begin(), setSelected.end());
- }
-
- void SetInputWeight(const COutPoint& outpoint, int64_t weight)
- {
- m_input_weights[outpoint] = weight;
- }
-
- bool HasInputWeight(const COutPoint& outpoint) const
- {
- return m_input_weights.count(outpoint) > 0;
- }
-
- int64_t GetInputWeight(const COutPoint& outpoint) const
- {
- auto it = m_input_weights.find(outpoint);
- assert(it != m_input_weights.end());
- return it->second;
- }
+ /**
+ * Returns true if there are pre-selected inputs.
+ */
+ bool HasSelected() const;
+ /**
+ * Returns true if the given output is pre-selected.
+ */
+ bool IsSelected(const COutPoint& output) const;
+ /**
+ * Returns true if the given output is selected as an external input.
+ */
+ bool IsExternalSelected(const COutPoint& output) const;
+ /**
+ * Returns the external output for the given outpoint if it exists.
+ */
+ std::optional<CTxOut> GetExternalOutput(const COutPoint& outpoint) const;
+ /**
+ * Lock-in the given output for spending.
+ * The output will be included in the transaction even if it's not the most optimal choice.
+ */
+ void Select(const COutPoint& output);
+ /**
+ * Lock-in the given output as an external input for spending because it is not in the wallet.
+ * The output will be included in the transaction even if it's not the most optimal choice.
+ */
+ void SelectExternal(const COutPoint& outpoint, const CTxOut& txout);
+ /**
+ * Unselects the given output.
+ */
+ void UnSelect(const COutPoint& output);
+ /**
+ * Unselects all outputs.
+ */
+ void UnSelectAll();
+ /**
+ * List the selected inputs.
+ */
+ std::vector<COutPoint> ListSelected() const;
+ /**
+ * Set an input's weight.
+ */
+ void SetInputWeight(const COutPoint& outpoint, int64_t weight);
+ /**
+ * Returns true if the input weight is set.
+ */
+ bool HasInputWeight(const COutPoint& outpoint) const;
+ /**
+ * Returns the input weight.
+ */
+ int64_t GetInputWeight(const COutPoint& outpoint) const;
private:
- std::set<COutPoint> setSelected;
+ //! Selected inputs (inputs that will be used, regardless of whether they're optimal or not)
+ std::set<COutPoint> m_selected_inputs;
+ //! Map of external inputs to include in the transaction
+ //! These are not in the wallet, so we need to track them separately
std::map<COutPoint, CTxOut> m_external_txouts;
//! Map of COutPoints to the maximum weight for that input
std::map<COutPoint, int64_t> m_input_weights;
diff --git a/src/wallet/external_signer_scriptpubkeyman.cpp b/src/wallet/external_signer_scriptpubkeyman.cpp
index 079e3baa4e..e2852c5d52 100644
--- a/src/wallet/external_signer_scriptpubkeyman.cpp
+++ b/src/wallet/external_signer_scriptpubkeyman.cpp
@@ -45,7 +45,7 @@ ExternalSigner ExternalSignerScriptPubKeyMan::GetExternalSigner() {
const std::string command = gArgs.GetArg("-signer", "");
if (command == "") throw std::runtime_error(std::string(__func__) + ": restart bitcoind with -signer=<cmd>");
std::vector<ExternalSigner> signers;
- ExternalSigner::Enumerate(command, signers, Params().NetworkIDString());
+ ExternalSigner::Enumerate(command, signers, Params().GetChainTypeString());
if (signers.empty()) throw std::runtime_error(std::string(__func__) + ": No external signers found");
// TODO: add fingerprint argument instead of failing in case of multiple signers.
if (signers.size() > 1) throw std::runtime_error(std::string(__func__) + ": More than one external signer found. Please connect only one at a time.");
diff --git a/src/wallet/rpc/addresses.cpp b/src/wallet/rpc/addresses.cpp
index a5be0739a9..0bd6a9670c 100644
--- a/src/wallet/rpc/addresses.cpp
+++ b/src/wallet/rpc/addresses.cpp
@@ -608,7 +608,9 @@ RPCHelpMan getaddressinfo()
if (const std::unique_ptr<CKeyMetadata> meta = spk_man->GetMetadata(dest)) {
ret.pushKV("timestamp", meta->nCreateTime);
if (meta->has_key_origin) {
- ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path));
+ // In legacy wallets hdkeypath has always used an apostrophe for
+ // hardened derivation. Perhaps some external tool depends on that.
+ ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path, /*apostrophe=*/!desc_spk_man));
ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint));
}
diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp
index 553bbfb62f..43da15b36e 100644
--- a/src/wallet/rpc/backup.cpp
+++ b/src/wallet/rpc/backup.cpp
@@ -805,7 +805,7 @@ RPCHelpMan dumpwallet()
} else {
file << "change=1";
}
- file << strprintf(" # addr=%s%s\n", strAddr, (metadata.has_key_origin ? " hdkeypath="+WriteHDKeypath(metadata.key_origin.path) : ""));
+ file << strprintf(" # addr=%s%s\n", strAddr, (metadata.has_key_origin ? " hdkeypath="+WriteHDKeypath(metadata.key_origin.path, /*apostrophe=*/true) : ""));
}
}
file << "\n";
diff --git a/src/wallet/rpc/coins.cpp b/src/wallet/rpc/coins.cpp
index 4c386789f1..5bdd3c9e72 100644
--- a/src/wallet/rpc/coins.cpp
+++ b/src/wallet/rpc/coins.cpp
@@ -320,7 +320,7 @@ RPCHelpMan lockunspent()
});
const uint256 txid(ParseHashO(o, "txid"));
- const int nOutput = find_value(o, "vout").getInt<int>();
+ const int nOutput = o.find_value("vout").getInt<int>();
if (nOutput < 0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
}
@@ -448,6 +448,7 @@ RPCHelpMan getbalances()
{RPCResult::Type::STR_AMOUNT, "untrusted_pending", "untrusted pending balance (outputs created by others that are in the mempool)"},
{RPCResult::Type::STR_AMOUNT, "immature", "balance from immature coinbase outputs"},
}},
+ RESULT_LAST_PROCESSED_BLOCK,
}
},
RPCExamples{
@@ -488,6 +489,8 @@ RPCHelpMan getbalances()
balances_watchonly.pushKV("immature", ValueFromAmount(bal.m_watchonly_immature));
balances.pushKV("watchonly", balances_watchonly);
}
+
+ AppendLastProcessedBlock(balances, wallet);
return balances;
},
};
diff --git a/src/wallet/rpc/spend.cpp b/src/wallet/rpc/spend.cpp
index 88ee6e96b0..a5b1f594bf 100644
--- a/src/wallet/rpc/spend.cpp
+++ b/src/wallet/rpc/spend.cpp
@@ -673,7 +673,7 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
for (const UniValue& input : options["input_weights"].get_array().getValues()) {
uint256 txid = ParseHashO(input, "txid");
- const UniValue& vout_v = find_value(input, "vout");
+ const UniValue& vout_v = input.find_value("vout");
if (!vout_v.isNum()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
}
@@ -682,7 +682,7 @@ void FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& fee_out,
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
}
- const UniValue& weight_v = find_value(input, "weight");
+ const UniValue& weight_v = input.find_value("weight");
if (!weight_v.isNum()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing weight key");
}
diff --git a/src/wallet/rpc/transactions.cpp b/src/wallet/rpc/transactions.cpp
index eb4f4c87ae..c34391e6e8 100644
--- a/src/wallet/rpc/transactions.cpp
+++ b/src/wallet/rpc/transactions.cpp
@@ -731,6 +731,7 @@ RPCHelpMan gettransaction()
{
{RPCResult::Type::ELISION, "", "Equivalent to the RPC decoderawtransaction method, or the RPC getrawtransaction method when `verbose` is passed."},
}},
+ RESULT_LAST_PROCESSED_BLOCK,
})
},
RPCExamples{
@@ -791,6 +792,7 @@ RPCHelpMan gettransaction()
entry.pushKV("decoded", decoded);
}
+ AppendLastProcessedBlock(entry, *pwallet);
return entry;
},
};
diff --git a/src/wallet/rpc/util.cpp b/src/wallet/rpc/util.cpp
index 4d82e0a41f..4ff44b84b0 100644
--- a/src/wallet/rpc/util.cpp
+++ b/src/wallet/rpc/util.cpp
@@ -177,4 +177,14 @@ void HandleWalletError(const std::shared_ptr<CWallet> wallet, DatabaseStatus& st
throw JSONRPCError(code, error.original);
}
}
+
+void AppendLastProcessedBlock(UniValue& entry, const CWallet& wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
+{
+ AssertLockHeld(wallet.cs_wallet);
+ UniValue lastprocessedblock{UniValue::VOBJ};
+ lastprocessedblock.pushKV("hash", wallet.GetLastBlockHash().GetHex());
+ lastprocessedblock.pushKV("height", wallet.GetLastBlockHeight());
+ entry.pushKV("lastprocessedblock", lastprocessedblock);
+}
+
} // namespace wallet
diff --git a/src/wallet/rpc/util.h b/src/wallet/rpc/util.h
index d5d6ac0dfa..2fdba04352 100644
--- a/src/wallet/rpc/util.h
+++ b/src/wallet/rpc/util.h
@@ -5,7 +5,9 @@
#ifndef BITCOIN_WALLET_RPC_UTIL_H
#define BITCOIN_WALLET_RPC_UTIL_H
+#include <rpc/util.h>
#include <script/script.h>
+#include <wallet/wallet.h>
#include <any>
#include <memory>
@@ -17,13 +19,17 @@ class UniValue;
struct bilingual_str;
namespace wallet {
-class CWallet;
class LegacyScriptPubKeyMan;
enum class DatabaseStatus;
struct WalletContext;
extern const std::string HELP_REQUIRING_PASSPHRASE;
+static const RPCResult RESULT_LAST_PROCESSED_BLOCK { RPCResult::Type::OBJ, "lastprocessedblock", "hash and height of the block this information was generated on",{
+ {RPCResult::Type::STR_HEX, "hash", "hash of the block this information was generated on"},
+ {RPCResult::Type::NUM, "height", "height of the block this information was generated on"}}
+};
+
/**
* Figures out what wallet, if any, to use for a JSONRPCRequest.
*
@@ -45,8 +51,8 @@ std::string LabelFromValue(const UniValue& value);
void PushParentDescriptors(const CWallet& wallet, const CScript& script_pubkey, UniValue& entry);
void HandleWalletError(const std::shared_ptr<CWallet> wallet, DatabaseStatus& status, bilingual_str& error);
-
int64_t ParseISO8601DateTime(const std::string& str);
+void AppendLastProcessedBlock(UniValue& entry, const CWallet& wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
} // namespace wallet
#endif // BITCOIN_WALLET_RPC_UTIL_H
diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp
index 7e57740706..a22862bfa9 100644
--- a/src/wallet/rpc/wallet.cpp
+++ b/src/wallet/rpc/wallet.cpp
@@ -68,6 +68,7 @@ static RPCHelpMan getwalletinfo()
}, /*skip_type_check=*/true},
{RPCResult::Type::BOOL, "descriptors", "whether this wallet uses descriptors for scriptPubKey management"},
{RPCResult::Type::BOOL, "external_signer", "whether this wallet is configured to use an external signer such as a hardware wallet"},
+ RESULT_LAST_PROCESSED_BLOCK,
}},
},
RPCExamples{
@@ -121,7 +122,7 @@ static RPCHelpMan getwalletinfo()
obj.pushKV("avoid_reuse", pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE));
if (pwallet->IsScanning()) {
UniValue scanning(UniValue::VOBJ);
- scanning.pushKV("duration", pwallet->ScanningDuration() / 1000);
+ scanning.pushKV("duration", Ticks<std::chrono::seconds>(pwallet->ScanningDuration()));
scanning.pushKV("progress", pwallet->ScanningProgress());
obj.pushKV("scanning", scanning);
} else {
@@ -129,6 +130,8 @@ static RPCHelpMan getwalletinfo()
}
obj.pushKV("descriptors", pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
obj.pushKV("external_signer", pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
+
+ AppendLastProcessedBlock(obj, *pwallet);
return obj;
},
};
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index 62bd0c06cd..953fdb63b6 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -1555,7 +1555,7 @@ bool LegacyScriptPubKeyMan::AddKeyOriginWithDB(WalletBatch& batch, const CPubKey
std::copy(info.fingerprint, info.fingerprint + 4, mapKeyMetadata[pubkey.GetID()].key_origin.fingerprint);
mapKeyMetadata[pubkey.GetID()].key_origin.path = info.path;
mapKeyMetadata[pubkey.GetID()].has_key_origin = true;
- mapKeyMetadata[pubkey.GetID()].hdKeypath = WriteHDKeypath(info.path);
+ mapKeyMetadata[pubkey.GetID()].hdKeypath = WriteHDKeypath(info.path, /*apostrophe=*/true);
return batch.WriteKeyMetadata(mapKeyMetadata[pubkey.GetID()], pubkey, true);
}
@@ -1821,7 +1821,7 @@ std::optional<MigrationData> LegacyScriptPubKeyMan::MigrateToDescriptor()
// Make the combo descriptor
std::string xpub = EncodeExtPubKey(master_key.Neuter());
- std::string desc_str = "combo(" + xpub + "/0'/" + ToString(i) + "'/*')";
+ std::string desc_str = "combo(" + xpub + "/0h/" + ToString(i) + "h/*h)";
FlatSigningProvider keys;
std::string error;
std::unique_ptr<Descriptor> desc = Parse(desc_str, keys, error, false);
@@ -2264,20 +2264,20 @@ bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(const CExtKey& master_
std::string desc_suffix = "/*)";
switch (addr_type) {
case OutputType::LEGACY: {
- desc_prefix = "pkh(" + xpub + "/44'";
+ desc_prefix = "pkh(" + xpub + "/44h";
break;
}
case OutputType::P2SH_SEGWIT: {
- desc_prefix = "sh(wpkh(" + xpub + "/49'";
+ desc_prefix = "sh(wpkh(" + xpub + "/49h";
desc_suffix += ")";
break;
}
case OutputType::BECH32: {
- desc_prefix = "wpkh(" + xpub + "/84'";
+ desc_prefix = "wpkh(" + xpub + "/84h";
break;
}
case OutputType::BECH32M: {
- desc_prefix = "tr(" + xpub + "/86'";
+ desc_prefix = "tr(" + xpub + "/86h";
break;
}
case OutputType::UNKNOWN: {
@@ -2290,13 +2290,13 @@ bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(const CExtKey& master_
// Mainnet derives at 0', testnet and regtest derive at 1'
if (Params().IsTestChain()) {
- desc_prefix += "/1'";
+ desc_prefix += "/1h";
} else {
- desc_prefix += "/0'";
+ desc_prefix += "/0h";
}
std::string internal_path = internal ? "/1" : "/0";
- std::string desc_str = desc_prefix + "/0'" + internal_path + desc_suffix;
+ std::string desc_str = desc_prefix + "/0h" + internal_path + desc_suffix;
// Make the descriptor
FlatSigningProvider keys;
diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp
index 748f40dce8..b14a30921b 100644
--- a/src/wallet/spend.cpp
+++ b/src/wallet/spend.cpp
@@ -52,9 +52,7 @@ int CalculateMaximumSignedInputSize(const CTxOut& txout, const CWallet* wallet,
TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, const CCoinControl* coin_control)
{
CMutableTransaction txNew(tx);
- if (!wallet->DummySignTx(txNew, txouts, coin_control)) {
- return TxSize{-1, -1};
- }
+ if (!wallet->DummySignTx(txNew, txouts, coin_control)) return TxSize{-1, -1};
CTransaction ctx(txNew);
int64_t vsize = GetVirtualTransactionSize(ctx);
int64_t weight = GetTransactionWeight(ctx);
@@ -72,11 +70,9 @@ TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *walle
assert(input.prevout.n < mi->second.tx->vout.size());
txouts.emplace_back(mi->second.tx->vout.at(input.prevout.n));
} else if (coin_control) {
- CTxOut txout;
- if (!coin_control->GetExternalOutput(input.prevout, txout)) {
- return TxSize{-1, -1};
- }
- txouts.emplace_back(txout);
+ const auto& txout{coin_control->GetExternalOutput(input.prevout)};
+ if (!txout) return TxSize{-1, -1};
+ txouts.emplace_back(*txout);
} else {
return TxSize{-1, -1};
}
@@ -163,10 +159,8 @@ util::Result<PreSelectedInputs> FetchSelectedInputs(const CWallet& wallet, const
const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
{
PreSelectedInputs result;
- std::vector<COutPoint> vPresetInputs;
- coin_control.ListSelected(vPresetInputs);
const bool can_grind_r = wallet.CanGrindR();
- for (const COutPoint& outpoint : vPresetInputs) {
+ for (const COutPoint& outpoint : coin_control.ListSelected()) {
int input_bytes = -1;
CTxOut txout;
if (auto ptr_wtx = wallet.GetWalletTx(outpoint.hash)) {
@@ -178,9 +172,12 @@ util::Result<PreSelectedInputs> FetchSelectedInputs(const CWallet& wallet, const
input_bytes = CalculateMaximumSignedInputSize(txout, &wallet, &coin_control);
} else {
// The input is external. We did not find the tx in mapWallet.
- if (!coin_control.GetExternalOutput(outpoint, txout)) {
+ const auto out{coin_control.GetExternalOutput(outpoint)};
+ if (!out) {
return util::Error{strprintf(_("Not found pre-selected input %s"), outpoint.ToString())};
}
+
+ txout = *out;
}
if (input_bytes == -1) {
diff --git a/src/wallet/test/init_test_fixture.cpp b/src/wallet/test/init_test_fixture.cpp
index 0adc63876c..5bdf36ec19 100644
--- a/src/wallet/test/init_test_fixture.cpp
+++ b/src/wallet/test/init_test_fixture.cpp
@@ -4,6 +4,7 @@
#include <common/args.h>
#include <univalue.h>
+#include <util/chaintype.h>
#include <util/check.h>
#include <util/fs.h>
@@ -13,7 +14,7 @@
#include <wallet/test/init_test_fixture.h>
namespace wallet {
-InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
+InitWalletDirTestingSetup::InitWalletDirTestingSetup(const ChainType chainType) : BasicTestingSetup(chainType)
{
m_wallet_loader = MakeWalletLoader(*m_node.chain, m_args);
diff --git a/src/wallet/test/init_test_fixture.h b/src/wallet/test/init_test_fixture.h
index df5819fd1d..ac7bb8997c 100644
--- a/src/wallet/test/init_test_fixture.h
+++ b/src/wallet/test/init_test_fixture.h
@@ -9,11 +9,12 @@
#include <interfaces/wallet.h>
#include <node/context.h>
#include <test/util/setup_common.h>
+#include <util/chaintype.h>
namespace wallet {
struct InitWalletDirTestingSetup: public BasicTestingSetup {
- explicit InitWalletDirTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
+ explicit InitWalletDirTestingSetup(const ChainType chain_type = ChainType::MAIN);
~InitWalletDirTestingSetup();
void SetWalletDir(const fs::path& walletdir_path);
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
index a72446d599..57c538e4ef 100644
--- a/src/wallet/test/wallet_test_fixture.cpp
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -6,10 +6,11 @@
#include <wallet/test/wallet_test_fixture.h>
#include <scheduler.h>
+#include <util/chaintype.h>
namespace wallet {
-WalletTestingSetup::WalletTestingSetup(const std::string& chainName)
- : TestingSetup(chainName),
+WalletTestingSetup::WalletTestingSetup(const ChainType chainType)
+ : TestingSetup(chainType),
m_wallet_loader{interfaces::MakeWalletLoader(*m_node.chain, *Assert(m_node.args))},
m_wallet(m_node.chain.get(), "", CreateMockableWalletDatabase())
{
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
index f1ef15a282..4aae02e075 100644
--- a/src/wallet/test/wallet_test_fixture.h
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -10,6 +10,7 @@
#include <interfaces/chain.h>
#include <interfaces/wallet.h>
#include <node/context.h>
+#include <util/chaintype.h>
#include <util/check.h>
#include <wallet/wallet.h>
@@ -19,7 +20,7 @@ namespace wallet {
/** Testing setup and teardown for wallet.
*/
struct WalletTestingSetup : public TestingSetup {
- explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
+ explicit WalletTestingSetup(const ChainType chainType = ChainType::MAIN);
~WalletTestingSetup();
std::unique_ptr<interfaces::WalletLoader> m_wallet_loader;
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 241ac8f065..805ddf3a57 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -29,7 +29,6 @@
#include <univalue.h>
using node::MAX_BLOCKFILE_SIZE;
-using node::UnlinkPrunedFiles;
namespace wallet {
RPCHelpMan importmulti();
@@ -159,7 +158,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
file_number = oldTip->GetBlockPos().nFile;
Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(file_number);
}
- UnlinkPrunedFiles({file_number});
+ m_node.chainman->m_blockman.UnlinkPrunedFiles({file_number});
// Verify ScanForWalletTransactions only picks transactions in the new block
// file.
@@ -188,7 +187,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
file_number = newTip->GetBlockPos().nFile;
Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(file_number);
}
- UnlinkPrunedFiles({file_number});
+ m_node.chainman->m_blockman.UnlinkPrunedFiles({file_number});
// Verify ScanForWalletTransactions scans no blocks.
{
@@ -226,7 +225,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
file_number = oldTip->GetBlockPos().nFile;
Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(file_number);
}
- UnlinkPrunedFiles({file_number});
+ m_node.chainman->m_blockman.UnlinkPrunedFiles({file_number});
// Verify importmulti RPC returns failure for a key whose creation time is
// before the missing block, and success for a key whose creation time is
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index caf95a3f03..b3eed8abc7 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -559,13 +559,14 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
return false;
if (Unlock(_vMasterKey))
{
- int64_t nStartTime = GetTimeMillis();
+ constexpr MillisecondsDouble target{100};
+ auto start{SteadyClock::now()};
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
- pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime))));
+ pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start));
- nStartTime = GetTimeMillis();
+ start = SteadyClock::now();
crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
- pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
+ pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
if (pMasterKey.second.nDeriveIterations < 25000)
pMasterKey.second.nDeriveIterations = 25000;
@@ -762,13 +763,14 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
GetStrongRandBytes(kMasterKey.vchSalt);
CCrypter crypter;
- int64_t nStartTime = GetTimeMillis();
+ constexpr MillisecondsDouble target{100};
+ auto start{SteadyClock::now()};
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
- kMasterKey.nDeriveIterations = static_cast<unsigned int>(2500000 / ((double)(GetTimeMillis() - nStartTime)));
+ kMasterKey.nDeriveIterations = static_cast<unsigned int>(25000 * target / (SteadyClock::now() - start));
- nStartTime = GetTimeMillis();
+ start = SteadyClock::now();
crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
- kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
+ kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + static_cast<unsigned int>(kMasterKey.nDeriveIterations * target / (SteadyClock::now() - start))) / 2;
if (kMasterKey.nDeriveIterations < 25000)
kMasterKey.nDeriveIterations = 25000;
@@ -3587,7 +3589,7 @@ void CWallet::SetupDescriptorScriptPubKeyMans()
if (!signer_res.isObject()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
for (bool internal : {false, true}) {
- const UniValue& descriptor_vals = find_value(signer_res, internal ? "internal" : "receive");
+ const UniValue& descriptor_vals = signer_res.find_value(internal ? "internal" : "receive");
if (!descriptor_vals.isArray()) throw std::runtime_error(std::string(__func__) + ": Unexpected result");
for (const UniValue& desc_val : descriptor_vals.get_array().getValues()) {
const std::string& desc_str = desc_val.getValStr();
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 5252b46cdc..79f4c43456 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -284,7 +284,7 @@ private:
std::atomic<bool> fScanningWallet{false}; // controlled by WalletRescanReserver
std::atomic<bool> m_attaching_chain{false};
std::atomic<bool> m_scanning_with_passphrase{false};
- std::atomic<int64_t> m_scanning_start{0};
+ std::atomic<SteadyClock::time_point> m_scanning_start{SteadyClock::time_point{}};
std::atomic<double> m_scanning_progress{0};
friend class WalletRescanReserver;
@@ -505,7 +505,7 @@ public:
bool IsAbortingRescan() const { return fAbortRescan; }
bool IsScanning() const { return fScanningWallet; }
bool IsScanningWithPassphrase() const { return m_scanning_with_passphrase; }
- int64_t ScanningDuration() const { return fScanningWallet ? GetTimeMillis() - m_scanning_start : 0; }
+ SteadyClock::duration ScanningDuration() const { return fScanningWallet ? SteadyClock::now() - m_scanning_start.load() : SteadyClock::duration{}; }
double ScanningProgress() const { return fScanningWallet ? (double) m_scanning_progress : 0; }
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
@@ -1014,7 +1014,7 @@ public:
return false;
}
m_wallet.m_scanning_with_passphrase.exchange(with_passphrase);
- m_wallet.m_scanning_start = GetTimeMillis();
+ m_wallet.m_scanning_start = SteadyClock::now();
m_wallet.m_scanning_progress = 0;
m_could_reserve = true;
return true;
diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h
index cf0ee48f47..17fa7bbaa9 100644
--- a/src/zmq/zmqabstractnotifier.h
+++ b/src/zmq/zmqabstractnotifier.h
@@ -6,6 +6,7 @@
#define BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H
#include <cstdint>
+#include <functional>
#include <memory>
#include <string>
@@ -13,7 +14,7 @@ class CBlockIndex;
class CTransaction;
class CZMQAbstractNotifier;
-using CZMQNotifierFactory = std::unique_ptr<CZMQAbstractNotifier> (*)();
+using CZMQNotifierFactory = std::function<std::unique_ptr<CZMQAbstractNotifier>()>;
class CZMQAbstractNotifier
{
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index 9920d80a69..6755368249 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -39,12 +39,14 @@ std::list<const CZMQAbstractNotifier*> CZMQNotificationInterface::GetActiveNotif
return result;
}
-CZMQNotificationInterface* CZMQNotificationInterface::Create()
+std::unique_ptr<CZMQNotificationInterface> CZMQNotificationInterface::Create(std::function<bool(CBlock&, const CBlockIndex&)> get_block_by_index)
{
std::map<std::string, CZMQNotifierFactory> factories;
factories["pubhashblock"] = CZMQAbstractNotifier::Create<CZMQPublishHashBlockNotifier>;
factories["pubhashtx"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionNotifier>;
- factories["pubrawblock"] = CZMQAbstractNotifier::Create<CZMQPublishRawBlockNotifier>;
+ factories["pubrawblock"] = [&get_block_by_index]() -> std::unique_ptr<CZMQAbstractNotifier> {
+ return std::make_unique<CZMQPublishRawBlockNotifier>(get_block_by_index);
+ };
factories["pubrawtx"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionNotifier>;
factories["pubsequence"] = CZMQAbstractNotifier::Create<CZMQPublishSequenceNotifier>;
@@ -68,7 +70,7 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create()
notificationInterface->notifiers = std::move(notifiers);
if (notificationInterface->Initialize()) {
- return notificationInterface.release();
+ return notificationInterface;
}
}
@@ -198,4 +200,4 @@ void CZMQNotificationInterface::BlockDisconnected(const std::shared_ptr<const CB
});
}
-CZMQNotificationInterface* g_zmq_notification_interface = nullptr;
+std::unique_ptr<CZMQNotificationInterface> g_zmq_notification_interface;
diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h
index a43f9bfef3..ce67633b30 100644
--- a/src/zmq/zmqnotificationinterface.h
+++ b/src/zmq/zmqnotificationinterface.h
@@ -9,6 +9,7 @@
#include <validationinterface.h>
#include <cstdint>
+#include <functional>
#include <list>
#include <memory>
@@ -23,7 +24,7 @@ public:
std::list<const CZMQAbstractNotifier*> GetActiveNotifiers() const;
- static CZMQNotificationInterface* Create();
+ static std::unique_ptr<CZMQNotificationInterface> Create(std::function<bool(CBlock&, const CBlockIndex&)> get_block_by_index);
protected:
bool Initialize();
@@ -43,6 +44,6 @@ private:
std::list<std::unique_ptr<CZMQAbstractNotifier>> notifiers;
};
-extern CZMQNotificationInterface* g_zmq_notification_interface;
+extern std::unique_ptr<CZMQNotificationInterface> g_zmq_notification_interface;
#endif // BITCOIN_ZMQ_ZMQNOTIFICATIONINTERFACE_H
diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp
index 55f3d4e934..21aa44c309 100644
--- a/src/zmq/zmqpublishnotifier.cpp
+++ b/src/zmq/zmqpublishnotifier.cpp
@@ -39,8 +39,6 @@ namespace Consensus {
struct Params;
}
-using node::ReadBlockFromDisk;
-
static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers;
static const char *MSG_HASHBLOCK = "hashblock";
@@ -247,10 +245,9 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
LogPrint(BCLog::ZMQ, "Publish rawblock %s to %s\n", pindex->GetBlockHash().GetHex(), this->address);
- const Consensus::Params& consensusParams = Params().GetConsensus();
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
CBlock block;
- if (!ReadBlockFromDisk(block, pindex, consensusParams)) {
+ if (!m_get_block_by_index(block, *pindex)) {
zmqError("Can't read block from disk");
return false;
}
diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h
index 18336a5eb0..a5cd433761 100644
--- a/src/zmq/zmqpublishnotifier.h
+++ b/src/zmq/zmqpublishnotifier.h
@@ -9,7 +9,9 @@
#include <cstddef>
#include <cstdint>
+#include <functional>
+class CBlock;
class CBlockIndex;
class CTransaction;
@@ -46,7 +48,12 @@ public:
class CZMQPublishRawBlockNotifier : public CZMQAbstractPublishNotifier
{
+private:
+ const std::function<bool(CBlock&, const CBlockIndex&)> m_get_block_by_index;
+
public:
+ CZMQPublishRawBlockNotifier(std::function<bool(CBlock&, const CBlockIndex&)> get_block_by_index)
+ : m_get_block_by_index{std::move(get_block_by_index)} {}
bool NotifyBlock(const CBlockIndex *pindex) override;
};