From a518fff0f2e479064dd4cff6c29fb54c72c1407b Mon Sep 17 00:00:00 2001 From: Andrew Toth Date: Mon, 3 Oct 2022 23:28:56 -0400 Subject: [PATCH 01/72] rest: add verbose and mempool_sequence query params for mempool/contents --- src/rest.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/rest.cpp b/src/rest.cpp index 7f00db2222c22..c3c79433690f4 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -608,7 +608,20 @@ static bool rest_mempool(const std::any& context, HTTPRequest* req, const std::s case RESTResponseFormat::JSON: { std::string str_json; if (param == "contents") { - str_json = MempoolToJSON(*mempool, true).write() + "\n"; + const std::string raw_verbose{req->GetQueryParameter("verbose").value_or("true")}; + if (raw_verbose != "true" && raw_verbose != "false") { + return RESTERR(req, HTTP_BAD_REQUEST, "The \"verbose\" query parameter must be either \"true\" or \"false\"."); + } + const std::string raw_mempool_sequence{req->GetQueryParameter("mempool_sequence").value_or("false")}; + if (raw_mempool_sequence != "true" && raw_mempool_sequence != "false") { + return RESTERR(req, HTTP_BAD_REQUEST, "The \"mempool_sequence\" query parameter must be either \"true\" or \"false\"."); + } + const bool verbose{raw_verbose == "true"}; + const bool mempool_sequence{raw_mempool_sequence == "true"}; + if (verbose && mempool_sequence) { + return RESTERR(req, HTTP_BAD_REQUEST, "Verbose results cannot contain mempool sequence values. (hint: set \"verbose=false\")"); + } + str_json = MempoolToJSON(*mempool, verbose, mempool_sequence).write() + "\n"; } else { str_json = MempoolInfoToJSON(*mempool).write() + "\n"; } From 52a31dccc92366efb36db3b94920bdf8b05b264c Mon Sep 17 00:00:00 2001 From: Andrew Toth Date: Mon, 3 Oct 2022 23:29:21 -0400 Subject: [PATCH 02/72] tests: mempool/contents verbose and mempool_sequence query params tests --- test/functional/interface_rest.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py index 610a28c56b9f8..ebefb8bd6a28e 100755 --- a/test/functional/interface_rest.py +++ b/test/functional/interface_rest.py @@ -348,6 +348,34 @@ def run_test(self): assert_equal(json_obj[tx]['spentby'], txs[i + 1:i + 2]) assert_equal(json_obj[tx]['depends'], txs[i - 1:i]) + # Check the mempool response for explicit parameters + json_obj = self.test_rest_request("/mempool/contents", query_params={"verbose": "true", "mempool_sequence": "false"}) + assert_equal(json_obj, raw_mempool_verbose) + + # Check the mempool response for not verbose + json_obj = self.test_rest_request("/mempool/contents", query_params={"verbose": "false"}) + raw_mempool = self.nodes[0].getrawmempool(verbose=False) + + assert_equal(json_obj, raw_mempool) + + # Check the mempool response for sequence + json_obj = self.test_rest_request("/mempool/contents", query_params={"verbose": "false", "mempool_sequence": "true"}) + raw_mempool = self.nodes[0].getrawmempool(verbose=False, mempool_sequence=True) + + assert_equal(json_obj, raw_mempool) + + # Check for error response if verbose=true and mempool_sequence=true + resp = self.test_rest_request("/mempool/contents", ret_type=RetType.OBJ, status=400, query_params={"verbose": "true", "mempool_sequence": "true"}) + assert_equal(resp.read().decode('utf-8').strip(), 'Verbose results cannot contain mempool sequence values. (hint: set "verbose=false")') + + # Check for error response if verbose is not "true" or "false" + resp = self.test_rest_request("/mempool/contents", ret_type=RetType.OBJ, status=400, query_params={"verbose": "TRUE"}) + assert_equal(resp.read().decode('utf-8').strip(), 'The "verbose" query parameter must be either "true" or "false".') + + # Check for error response if mempool_sequence is not "true" or "false" + resp = self.test_rest_request("/mempool/contents", ret_type=RetType.OBJ, status=400, query_params={"verbose": "false", "mempool_sequence": "TRUE"}) + assert_equal(resp.read().decode('utf-8').strip(), 'The "mempool_sequence" query parameter must be either "true" or "false".') + # Now mine the transactions newblockhash = self.generate(self.nodes[1], 1) From 1ff5d61dfdaf8987e5619162662e4c760af76a43 Mon Sep 17 00:00:00 2001 From: Andrew Toth Date: Tue, 4 Oct 2022 09:19:05 -0400 Subject: [PATCH 03/72] doc: add mempool/contents rest verbose and mempool_sequence args --- doc/REST-interface.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/REST-interface.md b/doc/REST-interface.md index 265b74ee9aff7..9173f08efb937 100644 --- a/doc/REST-interface.md +++ b/doc/REST-interface.md @@ -123,11 +123,15 @@ Returns various information about the transaction mempool. Only supports JSON as output format. Refer to the `getmempoolinfo` RPC help for details. -`GET /rest/mempool/contents.json` +`GET /rest/mempool/contents.json?verbose=&mempool_sequence=` Returns the transactions in the mempool. Only supports JSON as output format. -Refer to the `getrawmempool` RPC help for details. +Refer to the `getrawmempool` RPC help for details. Defaults to setting +`verbose=true` and `mempool_sequence=false`. + +*Query parameters for `verbose` and `mempool_sequence` available in 25.0 and up.* + Risks ------------- From e43a547a3674a31504a60ede9b4912e014a54139 Mon Sep 17 00:00:00 2001 From: furszy Date: Thu, 21 Jul 2022 11:10:47 -0300 Subject: [PATCH 04/72] refactor: wallet, do not translate init arguments names --- src/wallet/spend.cpp | 2 +- src/wallet/wallet.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index 6833f9a095503..36c1a65ea2128 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -849,7 +849,7 @@ static util::Result CreateTransactionInternal( } if (feeCalc.reason == FeeReason::FALLBACK && !wallet.m_allow_fallback_fee) { // eventually allow a fallback fee - return util::Error{_("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.")}; + return util::Error{strprintf(_("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable %s."), "-fallbackfee")}; } // Calculate the cost of change diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5889de2e36b60..6ed237329438c 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2935,7 +2935,7 @@ std::shared_ptr CWallet::Create(WalletContext& context, const std::stri if (args.IsArgSet("-fallbackfee")) { std::optional fallback_fee = ParseMoney(args.GetArg("-fallbackfee", "")); if (!fallback_fee) { - error = strprintf(_("Invalid amount for -fallbackfee=: '%s'"), args.GetArg("-fallbackfee", "")); + error = strprintf(_("Invalid amount for %s=: '%s'"), "-fallbackfee", args.GetArg("-fallbackfee", "")); return nullptr; } else if (fallback_fee.value() > HIGH_TX_FEE_PER_KB) { warnings.push_back(AmountHighWarn("-fallbackfee") + Untranslated(" ") + @@ -2950,7 +2950,7 @@ std::shared_ptr CWallet::Create(WalletContext& context, const std::stri if (args.IsArgSet("-discardfee")) { std::optional discard_fee = ParseMoney(args.GetArg("-discardfee", "")); if (!discard_fee) { - error = strprintf(_("Invalid amount for -discardfee=: '%s'"), args.GetArg("-discardfee", "")); + error = strprintf(_("Invalid amount for %s=: '%s'"), "-discardfee", args.GetArg("-discardfee", "")); return nullptr; } else if (discard_fee.value() > HIGH_TX_FEE_PER_KB) { warnings.push_back(AmountHighWarn("-discardfee") + Untranslated(" ") + @@ -2972,8 +2972,8 @@ std::shared_ptr CWallet::Create(WalletContext& context, const std::stri walletInstance->m_pay_tx_fee = CFeeRate{pay_tx_fee.value(), 1000}; if (chain && walletInstance->m_pay_tx_fee < chain->relayMinFee()) { - error = strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), - args.GetArg("-paytxfee", ""), chain->relayMinFee().ToString()); + error = strprintf(_("Invalid amount for %s=: '%s' (must be at least %s)"), + "-paytxfee", args.GetArg("-paytxfee", ""), chain->relayMinFee().ToString()); return nullptr; } } @@ -2984,12 +2984,12 @@ std::shared_ptr CWallet::Create(WalletContext& context, const std::stri error = AmountErrMsg("maxtxfee", args.GetArg("-maxtxfee", "")); return nullptr; } else if (max_fee.value() > HIGH_MAX_TX_FEE) { - warnings.push_back(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.")); + warnings.push_back(strprintf(_("%s is set very high! Fees this large could be paid on a single transaction."), "-maxtxfee")); } if (chain && CFeeRate{max_fee.value(), 1000} < chain->relayMinFee()) { - error = strprintf(_("Invalid amount for -maxtxfee=: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"), - args.GetArg("-maxtxfee", ""), chain->relayMinFee().ToString()); + error = strprintf(_("Invalid amount for %s=: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"), + "-maxtxfee", args.GetArg("-maxtxfee", ""), chain->relayMinFee().ToString()); return nullptr; } From 127c637cf0a80e0ea68a7c5aaa088e5ccc9d3d13 Mon Sep 17 00:00:00 2001 From: fanquake Date: Thu, 18 Aug 2022 18:04:48 +0100 Subject: [PATCH 05/72] guix: pass --enable-initfini-array to release GCC This returns us to pre-Guix behaviour, where the compilers we were using to build releases, were configured with this option. --- contrib/guix/manifest.scm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm index e266e7d0ee636..dc42563cddcdc 100644 --- a/contrib/guix/manifest.scm +++ b/contrib/guix/manifest.scm @@ -139,9 +139,11 @@ chain for " target " development.")) ;; https://gcc.gnu.org/install/configure.html (define (hardened-gcc gcc) (package-with-extra-configure-variable ( - package-with-extra-configure-variable gcc - "--enable-default-ssp" "yes") - "--enable-default-pie" "yes")) + package-with-extra-configure-variable ( + package-with-extra-configure-variable gcc + "--enable-initfini-array" "yes") + "--enable-default-ssp" "yes") + "--enable-default-pie" "yes")) (define* (make-bitcoin-cross-toolchain target #:key From e194e3e93dd0665181bafeb162bf4c9f3621d6f1 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Sat, 4 Mar 2023 12:35:19 +0100 Subject: [PATCH 06/72] test: PSBT: eliminate magic numbers for global unsigned tx key (0) --- test/functional/test_framework/psbt.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/functional/test_framework/psbt.py b/test/functional/test_framework/psbt.py index 3a5b4ec74dbe5..1eff4a250ee63 100644 --- a/test/functional/test_framework/psbt.py +++ b/test/functional/test_framework/psbt.py @@ -105,8 +105,8 @@ def __init__(self, *, g=None, i=None, o=None): def deserialize(self, f): assert f.read(5) == b"psbt\xff" self.g = from_binary(PSBTMap, f) - assert 0 in self.g.map - self.tx = from_binary(CTransaction, self.g.map[0]) + assert PSBT_GLOBAL_UNSIGNED_TX in self.g.map + self.tx = from_binary(CTransaction, self.g.map[PSBT_GLOBAL_UNSIGNED_TX]) self.i = [from_binary(PSBTMap, f) for _ in self.tx.vin] self.o = [from_binary(PSBTMap, f) for _ in self.tx.vout] return self @@ -115,8 +115,8 @@ def serialize(self): assert isinstance(self.g, PSBTMap) assert isinstance(self.i, list) and all(isinstance(x, PSBTMap) for x in self.i) assert isinstance(self.o, list) and all(isinstance(x, PSBTMap) for x in self.o) - assert 0 in self.g.map - tx = from_binary(CTransaction, self.g.map[0]) + assert PSBT_GLOBAL_UNSIGNED_TX in self.g.map + tx = from_binary(CTransaction, self.g.map[PSBT_GLOBAL_UNSIGNED_TX]) assert len(tx.vin) == len(self.i) assert len(tx.vout) == len(self.o) @@ -130,7 +130,7 @@ def make_blank(self): for m in self.i + self.o: m.map.clear() - self.g = PSBTMap(map={0: self.g.map[0]}) + self.g = PSBTMap(map={PSBT_GLOBAL_UNSIGNED_TX: self.g.map[PSBT_GLOBAL_UNSIGNED_TX]}) def to_base64(self): return base64.b64encode(self.serialize()).decode("utf8") From dd78e3fa439d57e148a2a5e312021da962c4a394 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Sun, 5 Mar 2023 01:45:23 +0100 Subject: [PATCH 07/72] test: speedup rpc_psbt.py by whitelisting peers (immediate tx relay) master branch: 0m36.86s real 0m03.26s user 0m01.69s system 0m35.71s real 0m03.78s user 0m01.64s system 0m45.76s real 0m03.12s user 0m01.27s system PR branch: 0m13.04s real 0m02.66s user 0m00.93s system 0m14.08s real 0m02.81s user 0m00.82s system 0m14.05s real 0m02.50s user 0m00.93s system --- test/functional/rpc_psbt.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index 58a80e37a200c..dff2c80d928d9 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -59,6 +59,9 @@ def set_test_params(self): ["-walletrbf=0", "-changetype=legacy"], [] ] + # whitelist peers to speed up tx relay / mempool sync + for args in self.extra_args: + args.append("-whitelist=noban@127.0.0.1") self.supports_cli = False def skip_test_if_missing_module(self): From 3dd2f6461b4bb28b2b212c691a3df28ac793ad91 Mon Sep 17 00:00:00 2001 From: Sebastian Falbesoner Date: Sun, 5 Mar 2023 02:43:39 +0100 Subject: [PATCH 08/72] test: psbt: check non-witness UTXO removal for segwit v1 input --- test/functional/rpc_psbt.py | 39 ++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index dff2c80d928d9..76886cc0ea581 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -4,7 +4,6 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the Partially Signed Transaction RPCs. """ - from decimal import Decimal from itertools import product @@ -27,6 +26,7 @@ PSBT_IN_SHA256, PSBT_IN_HASH160, PSBT_IN_HASH256, + PSBT_IN_NON_WITNESS_UTXO, PSBT_IN_WITNESS_UTXO, PSBT_OUT_TAP_TREE, ) @@ -67,8 +67,8 @@ def set_test_params(self): def skip_test_if_missing_module(self): self.skip_if_no_wallet() - # TODO: Re-enable this test with segwit v1 def test_utxo_conversion(self): + self.log.info("Check that non-witness UTXOs are removed for segwit v1+ inputs") mining_node = self.nodes[2] offline_node = self.nodes[0] online_node = self.nodes[1] @@ -80,34 +80,41 @@ def test_utxo_conversion(self): # Create watchonly on online_node online_node.createwallet(wallet_name='wonline', disable_private_keys=True) wonline = online_node.get_wallet_rpc('wonline') - w2 = online_node.get_wallet_rpc('') + w2 = online_node.get_wallet_rpc(self.default_wallet_name) # Mine a transaction that credits the offline address - offline_addr = offline_node.getnewaddress(address_type="p2sh-segwit") - online_addr = w2.getnewaddress(address_type="p2sh-segwit") + offline_addr = offline_node.getnewaddress(address_type="bech32m") + online_addr = w2.getnewaddress(address_type="bech32m") wonline.importaddress(offline_addr, "", False) - mining_node.sendtoaddress(address=offline_addr, amount=1.0) - self.generate(mining_node, nblocks=1) + mining_wallet = mining_node.get_wallet_rpc(self.default_wallet_name) + mining_wallet.sendtoaddress(address=offline_addr, amount=1.0) + self.generate(mining_node, nblocks=1, sync_fun=lambda: self.sync_all([online_node, mining_node])) - # Construct an unsigned PSBT on the online node (who doesn't know the output is Segwit, so will include a non-witness UTXO) + # Construct an unsigned PSBT on the online node utxos = wonline.listunspent(addresses=[offline_addr]) raw = wonline.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.9999}]) psbt = wonline.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"] - assert "non_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0] + assert not "not_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0] + + # add non-witness UTXO manually + psbt_new = PSBT.from_base64(psbt) + prev_tx = wonline.gettransaction(utxos[0]["txid"])["hex"] + psbt_new.i[0].map[PSBT_IN_NON_WITNESS_UTXO] = bytes.fromhex(prev_tx) + assert "non_witness_utxo" in mining_node.decodepsbt(psbt_new.to_base64())["inputs"][0] - # Have the offline node sign the PSBT (which will update the UTXO to segwit) - signed_psbt = offline_node.walletprocesspsbt(psbt)["psbt"] - assert "witness_utxo" in mining_node.decodepsbt(signed_psbt)["inputs"][0] + # Have the offline node sign the PSBT (which will remove the non-witness UTXO) + signed_psbt = offline_node.walletprocesspsbt(psbt_new.to_base64())["psbt"] + assert not "non_witness_utxo" in mining_node.decodepsbt(signed_psbt)["inputs"][0] # Make sure we can mine the resulting transaction txid = mining_node.sendrawtransaction(mining_node.finalizepsbt(signed_psbt)["hex"]) - self.generate(mining_node, 1) + self.generate(mining_node, nblocks=1, sync_fun=lambda: self.sync_all([online_node, mining_node])) assert_equal(online_node.gettxout(txid,0)["confirmations"], 1) wonline.unloadwallet() # Reconnect - self.connect_nodes(0, 1) + self.connect_nodes(1, 0) self.connect_nodes(0, 2) def test_input_confs_control(self): @@ -574,8 +581,8 @@ def run_test(self): for i, signer in enumerate(signers): self.nodes[2].unloadwallet("wallet{}".format(i)) - # TODO: Re-enable this for segwit v1 - # self.test_utxo_conversion() + if self.options.descriptors: + self.test_utxo_conversion() self.test_input_confs_control() From 4684aa8733e831d7858d43bec4271d5d026ba183 Mon Sep 17 00:00:00 2001 From: Larry Ruane Date: Mon, 30 Jan 2023 07:21:36 -0800 Subject: [PATCH 09/72] bench: allow logging benchmarks to be order-independent The global logging object instance is not re-created for each run, so when multiple logging benchmarks are run, each one after the first one still has the logging categories enabled from the previous ones. This commit disables all categories at the start of each benchmark. --- src/bench/logging.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bench/logging.cpp b/src/bench/logging.cpp index c38552f0b8cd5..edb81ed20b308 100644 --- a/src/bench/logging.cpp +++ b/src/bench/logging.cpp @@ -9,6 +9,9 @@ static void Logging(benchmark::Bench& bench, const std::vector& extra_args, const std::function& log) { + // Reset any enabled logging categories from a previous benchmark run. + LogInstance().DisableCategory(BCLog::LogFlags::ALL); + TestingSetup test_setup{ CBaseChainParams::REGTEST, extra_args, From 4b3fdbf6fe20dc70c8dbdaacce161bc4e76b9c84 Mon Sep 17 00:00:00 2001 From: Jon Atack Date: Mon, 11 Jul 2022 11:15:26 +0200 Subject: [PATCH 10/72] bench: update logging benchmark naming for clarity to better track which benchmark corresponds to which log macro. --- src/bench/logging.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/bench/logging.cpp b/src/bench/logging.cpp index edb81ed20b308..59b89b1a797f0 100644 --- a/src/bench/logging.cpp +++ b/src/bench/logging.cpp @@ -20,23 +20,23 @@ static void Logging(benchmark::Bench& bench, const std::vector& ext bench.run([&] { log(); }); } -static void LoggingYoThreadNames(benchmark::Bench& bench) +static void LogPrintfWithThreadNames(benchmark::Bench& bench) { Logging(bench, {"-logthreadnames=1"}, [] { LogPrintf("%s\n", "test"); }); } -static void LoggingNoThreadNames(benchmark::Bench& bench) +static void LogPrintfWithoutThreadNames(benchmark::Bench& bench) { Logging(bench, {"-logthreadnames=0"}, [] { LogPrintf("%s\n", "test"); }); } -static void LoggingYoCategory(benchmark::Bench& bench) +static void LogPrintWithCategory(benchmark::Bench& bench) { Logging(bench, {"-logthreadnames=0", "-debug=net"}, [] { LogPrint(BCLog::NET, "%s\n", "test"); }); } -static void LoggingNoCategory(benchmark::Bench& bench) +static void LogPrintWithoutCategory(benchmark::Bench& bench) { Logging(bench, {"-logthreadnames=0", "-debug=0"}, [] { LogPrint(BCLog::NET, "%s\n", "test"); }); } -static void LoggingNoFile(benchmark::Bench& bench) +static void LogWithoutWriteToFile(benchmark::Bench& bench) { Logging(bench, {"-nodebuglogfile", "-debug=1"}, [] { LogPrintf("%s\n", "test"); @@ -44,8 +44,8 @@ static void LoggingNoFile(benchmark::Bench& bench) }); } -BENCHMARK(LoggingYoThreadNames, benchmark::PriorityLevel::HIGH); -BENCHMARK(LoggingNoThreadNames, benchmark::PriorityLevel::HIGH); -BENCHMARK(LoggingYoCategory, benchmark::PriorityLevel::HIGH); -BENCHMARK(LoggingNoCategory, benchmark::PriorityLevel::HIGH); -BENCHMARK(LoggingNoFile, benchmark::PriorityLevel::HIGH); +BENCHMARK(LogPrintfWithThreadNames, benchmark::PriorityLevel::HIGH); +BENCHMARK(LogPrintfWithoutThreadNames, benchmark::PriorityLevel::HIGH); +BENCHMARK(LogPrintWithCategory, benchmark::PriorityLevel::HIGH); +BENCHMARK(LogPrintWithoutCategory, benchmark::PriorityLevel::HIGH); +BENCHMARK(LogWithoutWriteToFile, benchmark::PriorityLevel::HIGH); From 102b2033493f0d61e9763d094cb8a0017f7e3a10 Mon Sep 17 00:00:00 2001 From: Jon Atack Date: Mon, 11 Jul 2022 11:23:45 +0200 Subject: [PATCH 11/72] bench: order the logging benchmark code by output --- src/bench/logging.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/bench/logging.cpp b/src/bench/logging.cpp index 59b89b1a797f0..a7162d09acbf0 100644 --- a/src/bench/logging.cpp +++ b/src/bench/logging.cpp @@ -20,22 +20,26 @@ static void Logging(benchmark::Bench& bench, const std::vector& ext bench.run([&] { log(); }); } -static void LogPrintfWithThreadNames(benchmark::Bench& bench) -{ - Logging(bench, {"-logthreadnames=1"}, [] { LogPrintf("%s\n", "test"); }); -} -static void LogPrintfWithoutThreadNames(benchmark::Bench& bench) -{ - Logging(bench, {"-logthreadnames=0"}, [] { LogPrintf("%s\n", "test"); }); -} static void LogPrintWithCategory(benchmark::Bench& bench) { Logging(bench, {"-logthreadnames=0", "-debug=net"}, [] { LogPrint(BCLog::NET, "%s\n", "test"); }); } + static void LogPrintWithoutCategory(benchmark::Bench& bench) { Logging(bench, {"-logthreadnames=0", "-debug=0"}, [] { LogPrint(BCLog::NET, "%s\n", "test"); }); } + +static void LogPrintfWithThreadNames(benchmark::Bench& bench) +{ + Logging(bench, {"-logthreadnames=1"}, [] { LogPrintf("%s\n", "test"); }); +} + +static void LogPrintfWithoutThreadNames(benchmark::Bench& bench) +{ + Logging(bench, {"-logthreadnames=0"}, [] { LogPrintf("%s\n", "test"); }); +} + static void LogWithoutWriteToFile(benchmark::Bench& bench) { Logging(bench, {"-nodebuglogfile", "-debug=1"}, [] { @@ -44,8 +48,8 @@ static void LogWithoutWriteToFile(benchmark::Bench& bench) }); } -BENCHMARK(LogPrintfWithThreadNames, benchmark::PriorityLevel::HIGH); -BENCHMARK(LogPrintfWithoutThreadNames, benchmark::PriorityLevel::HIGH); BENCHMARK(LogPrintWithCategory, benchmark::PriorityLevel::HIGH); BENCHMARK(LogPrintWithoutCategory, benchmark::PriorityLevel::HIGH); +BENCHMARK(LogPrintfWithThreadNames, benchmark::PriorityLevel::HIGH); +BENCHMARK(LogPrintfWithoutThreadNames, benchmark::PriorityLevel::HIGH); BENCHMARK(LogWithoutWriteToFile, benchmark::PriorityLevel::HIGH); From d8deba8c36a42481b1c1e73009d7c9cc2cb25f70 Mon Sep 17 00:00:00 2001 From: Jon Atack Date: Mon, 11 Jul 2022 10:58:29 +0200 Subject: [PATCH 12/72] bench: add LogPrintfCategory and LogPrintLevel benchmarks for these new macros that our logging is planned to migrate to. At some point it may be feasible to drop some of the previous logging benchmarks. --- src/bench/logging.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/bench/logging.cpp b/src/bench/logging.cpp index a7162d09acbf0..f6e5bc54e87f8 100644 --- a/src/bench/logging.cpp +++ b/src/bench/logging.cpp @@ -20,6 +20,18 @@ static void Logging(benchmark::Bench& bench, const std::vector& ext bench.run([&] { log(); }); } +static void LogPrintLevelWithThreadNames(benchmark::Bench& bench) +{ + Logging(bench, {"-logthreadnames=1", "-debug=net"}, [] { + LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", "test"); }); +} + +static void LogPrintLevelWithoutThreadNames(benchmark::Bench& bench) +{ + Logging(bench, {"-logthreadnames=0", "-debug=net"}, [] { + LogPrintLevel(BCLog::NET, BCLog::Level::Error, "%s\n", "test"); }); +} + static void LogPrintWithCategory(benchmark::Bench& bench) { Logging(bench, {"-logthreadnames=0", "-debug=net"}, [] { LogPrint(BCLog::NET, "%s\n", "test"); }); @@ -30,6 +42,20 @@ static void LogPrintWithoutCategory(benchmark::Bench& bench) Logging(bench, {"-logthreadnames=0", "-debug=0"}, [] { LogPrint(BCLog::NET, "%s\n", "test"); }); } +static void LogPrintfCategoryWithThreadNames(benchmark::Bench& bench) +{ + Logging(bench, {"-logthreadnames=1", "-debug=net"}, [] { + LogPrintfCategory(BCLog::NET, "%s\n", "test"); + }); +} + +static void LogPrintfCategoryWithoutThreadNames(benchmark::Bench& bench) +{ + Logging(bench, {"-logthreadnames=0", "-debug=net"}, [] { + LogPrintfCategory(BCLog::NET, "%s\n", "test"); + }); +} + static void LogPrintfWithThreadNames(benchmark::Bench& bench) { Logging(bench, {"-logthreadnames=1"}, [] { LogPrintf("%s\n", "test"); }); @@ -48,8 +74,12 @@ static void LogWithoutWriteToFile(benchmark::Bench& bench) }); } +BENCHMARK(LogPrintLevelWithThreadNames, benchmark::PriorityLevel::HIGH); +BENCHMARK(LogPrintLevelWithoutThreadNames, benchmark::PriorityLevel::HIGH); BENCHMARK(LogPrintWithCategory, benchmark::PriorityLevel::HIGH); BENCHMARK(LogPrintWithoutCategory, benchmark::PriorityLevel::HIGH); +BENCHMARK(LogPrintfCategoryWithThreadNames, benchmark::PriorityLevel::HIGH); +BENCHMARK(LogPrintfCategoryWithoutThreadNames, benchmark::PriorityLevel::HIGH); BENCHMARK(LogPrintfWithThreadNames, benchmark::PriorityLevel::HIGH); BENCHMARK(LogPrintfWithoutThreadNames, benchmark::PriorityLevel::HIGH); BENCHMARK(LogWithoutWriteToFile, benchmark::PriorityLevel::HIGH); From 20d89d6802b67e2b8c864bedf23673d008e3faab Mon Sep 17 00:00:00 2001 From: jonatack Date: Mon, 23 Jan 2023 07:49:46 -0800 Subject: [PATCH 13/72] bench: document expected results in logging benchmarks and clarify the intention behind the -nodebuglogfile bench. Co-authored-by: "kouloumos " Co-authored-by: "Larry Ruane " --- src/bench/logging.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/bench/logging.cpp b/src/bench/logging.cpp index f6e5bc54e87f8..9aedb26236df9 100644 --- a/src/bench/logging.cpp +++ b/src/bench/logging.cpp @@ -6,6 +6,11 @@ #include #include +// All but 2 of the benchmarks should have roughly similar performance: +// +// LogPrintWithoutCategory should be ~3 orders of magnitude faster, as nothing is logged. +// +// LogWithoutWriteToFile should be ~2 orders of magnitude faster, as it avoids disk writes. static void Logging(benchmark::Bench& bench, const std::vector& extra_args, const std::function& log) { @@ -68,6 +73,7 @@ static void LogPrintfWithoutThreadNames(benchmark::Bench& bench) static void LogWithoutWriteToFile(benchmark::Bench& bench) { + // Disable writing the log to a file, as used for unit tests and fuzzing in `MakeNoLogFileContext`. Logging(bench, {"-nodebuglogfile", "-debug=1"}, [] { LogPrintf("%s\n", "test"); LogPrint(BCLog::NET, "%s\n", "test"); From 8c47d599b87d6b2d43e7d37ce0aaf4f541535bb9 Mon Sep 17 00:00:00 2001 From: jonatack Date: Mon, 23 Jan 2023 10:34:00 -0800 Subject: [PATCH 14/72] doc: improve -debuglogfile help to be a bit clearer --- src/init/common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init/common.cpp b/src/init/common.cpp index e1a37d7db93e9..fa065d221f64f 100644 --- a/src/init/common.cpp +++ b/src/init/common.cpp @@ -23,7 +23,7 @@ namespace init { void AddLoggingArgs(ArgsManager& argsman) { - argsman.AddArg("-debuglogfile=", strprintf("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (-nodebuglogfile to disable; default: %s)", DEFAULT_DEBUGLOGFILE), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + argsman.AddArg("-debuglogfile=", strprintf("Specify location of debug log file (default: %s). Relative paths will be prefixed by a net-specific datadir location. Pass -nodebuglogfile to disable writing the log to a file.", DEFAULT_DEBUGLOGFILE), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); argsman.AddArg("-debug=", "Output debug and trace logging (default: -nodebug, supplying is optional). " "If is not supplied or if = 1, output all debug and trace logging. can be: " + LogInstance().LogCategoriesString() + ". This option can be specified multiple times to output multiple categories.", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); From 805f399b174ef129ffabc07a87024be1ea1bfc35 Mon Sep 17 00:00:00 2001 From: furszy Date: Mon, 13 Feb 2023 19:56:26 -0300 Subject: [PATCH 15/72] wallet: do not make two COutputs, use shared_ptr --- src/wallet/spend.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index a8ecce119aff5..0b58f99ce9d10 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -445,10 +445,10 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, // OUTPUT_GROUP_MAX_ENTRIES COutputs, a new OutputGroup is added to the end of the vector. typedef std::map, std::vector> ScriptPubKeyToOutgroup; const auto& group_outputs = []( - const COutput& output, OutputType type, size_t ancestors, size_t descendants, + const std::shared_ptr& output, OutputType type, size_t ancestors, size_t descendants, ScriptPubKeyToOutgroup& groups_map, const CoinSelectionParams& coin_sel_params, bool positive_only) { - std::vector& groups = groups_map[std::make_pair(output.txout.scriptPubKey,type)]; + std::vector& groups = groups_map[std::make_pair(output->txout.scriptPubKey,type)]; if (groups.size() == 0) { // No OutputGroups for this scriptPubKey yet, add one @@ -468,8 +468,8 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, } // Filter for positive only before adding the output to group - if (!positive_only || output.GetEffectiveValue() > 0) { - group->Insert(std::make_shared(output), ancestors, descendants); + if (!positive_only || output->GetEffectiveValue() > 0) { + group->Insert(output, ancestors, descendants); } }; @@ -483,8 +483,9 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, size_t ancestors, descendants; wallet.chain().getTransactionAncestry(output.outpoint.hash, ancestors, descendants); - group_outputs(output, type, ancestors, descendants, spk_to_groups_map, coin_sel_params, /*positive_only=*/ false); - group_outputs(output, type, ancestors, descendants, spk_to_positive_groups_map, + const auto& shared_output = std::make_shared(output); + group_outputs(shared_output, type, ancestors, descendants, spk_to_groups_map, coin_sel_params, /*positive_only=*/ false); + group_outputs(shared_output, type, ancestors, descendants, spk_to_positive_groups_map, coin_sel_params, /*positive_only=*/ true); } } From 99034b2b72728def57204abe518e0360d9675437 Mon Sep 17 00:00:00 2001 From: furszy Date: Mon, 13 Feb 2023 20:03:28 -0300 Subject: [PATCH 16/72] wallet: APS, don't create empty groups By moving the "positive-only" flag out of the lambda function. --- src/wallet/spend.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index 0b58f99ce9d10..238422dc89147 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -444,10 +444,9 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, // to the last OutputGroup in the vector for the scriptPubKey. When the last OutputGroup has // OUTPUT_GROUP_MAX_ENTRIES COutputs, a new OutputGroup is added to the end of the vector. typedef std::map, std::vector> ScriptPubKeyToOutgroup; - const auto& group_outputs = []( + const auto& insert_output = [&]( const std::shared_ptr& output, OutputType type, size_t ancestors, size_t descendants, - ScriptPubKeyToOutgroup& groups_map, const CoinSelectionParams& coin_sel_params, - bool positive_only) { + ScriptPubKeyToOutgroup& groups_map) { std::vector& groups = groups_map[std::make_pair(output->txout.scriptPubKey,type)]; if (groups.size() == 0) { @@ -467,10 +466,7 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, group = &groups.back(); } - // Filter for positive only before adding the output to group - if (!positive_only || output->GetEffectiveValue() > 0) { - group->Insert(output, ancestors, descendants); - } + group->Insert(output, ancestors, descendants); }; ScriptPubKeyToOutgroup spk_to_groups_map; @@ -484,9 +480,13 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, wallet.chain().getTransactionAncestry(output.outpoint.hash, ancestors, descendants); const auto& shared_output = std::make_shared(output); - group_outputs(shared_output, type, ancestors, descendants, spk_to_groups_map, coin_sel_params, /*positive_only=*/ false); - group_outputs(shared_output, type, ancestors, descendants, spk_to_positive_groups_map, - coin_sel_params, /*positive_only=*/ true); + // Filter for positive only before adding the output + if (output.GetEffectiveValue() > 0) { + insert_output(shared_output, type, ancestors, descendants, spk_to_positive_groups_map); + } + + // 'All' groups + insert_output(shared_output, type, ancestors, descendants, spk_to_groups_map); } } From a9aa04183c4502c23ec924e9c8944b7c90f9f5c2 Mon Sep 17 00:00:00 2001 From: furszy Date: Mon, 13 Feb 2023 20:08:38 -0300 Subject: [PATCH 17/72] wallet: OutputGroup, remove unused effective_feerate member --- src/wallet/coinselection.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h index 3abd22c2071a9..cd03b7d224709 100644 --- a/src/wallet/coinselection.h +++ b/src/wallet/coinselection.h @@ -222,8 +222,6 @@ struct OutputGroup CAmount effective_value{0}; /** The fee to spend these UTXOs at the effective feerate. */ CAmount fee{0}; - /** The target feerate of the transaction we're trying to build. */ - CFeeRate m_effective_feerate{0}; /** The fee to spend these UTXOs at the long term feerate. */ CAmount long_term_fee{0}; /** The feerate for spending a created change output eventually (i.e. not urgently, and thus at @@ -238,7 +236,6 @@ struct OutputGroup OutputGroup() {} OutputGroup(const CoinSelectionParams& params) : - m_effective_feerate(params.m_effective_feerate), m_long_term_feerate(params.m_long_term_feerate), m_subtract_fee_outputs(params.m_subtract_fee_outputs) {} From 8471967d7be0804665fdf94a9a841b1c56598b3c Mon Sep 17 00:00:00 2001 From: furszy Date: Sat, 4 Mar 2023 11:23:11 -0300 Subject: [PATCH 18/72] wallet: GroupOutput, remove unneeded "spendable" check `AvailableCoins` already filters non-spendable coins. --- src/wallet/spend.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index 238422dc89147..359fc78df176a 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -415,9 +415,6 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, // Allowing partial spends means no grouping. Each COutput gets its own OutputGroup for (const auto& [type, outputs] : coins.coins) { for (const COutput& output : outputs) { - // Skip outputs we cannot spend - if (!output.spendable) continue; - // Get mempool info size_t ancestors, descendants; wallet.chain().getTransactionAncestry(output.outpoint.hash, ancestors, descendants); @@ -473,9 +470,6 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, ScriptPubKeyToOutgroup spk_to_positive_groups_map; for (const auto& [type, outs] : coins.coins) { for (const COutput& output : outs) { - // Skip outputs we cannot spend - if (!output.spendable) continue; - size_t ancestors, descendants; wallet.chain().getTransactionAncestry(output.outpoint.hash, ancestors, descendants); From 8a5583131ce78cd748e2279eb9331321e4ef2aa3 Mon Sep 17 00:00:00 2001 From: furszy Date: Fri, 19 Aug 2022 22:31:49 -0300 Subject: [PATCH 19/72] wallet: remove unused methods CWallet::DummySignTx, OutputGroupTypeMap::find --- src/wallet/coinselection.cpp | 7 ------- src/wallet/coinselection.h | 2 -- src/wallet/wallet.h | 6 ------ 3 files changed, 15 deletions(-) diff --git a/src/wallet/coinselection.cpp b/src/wallet/coinselection.cpp index 3fd0280b8b549..9cf61dbe514f6 100644 --- a/src/wallet/coinselection.cpp +++ b/src/wallet/coinselection.cpp @@ -387,13 +387,6 @@ void OutputGroupTypeMap::Push(const OutputGroup& group, OutputType type, bool in } } -std::optional OutputGroupTypeMap::Find(OutputType type) -{ - auto it_by_type = groups_by_type.find(type); - if (it_by_type == groups_by_type.end()) return std::nullopt; - return it_by_type->second; -} - CAmount GetSelectionWaste(const std::set>& inputs, CAmount change_cost, CAmount target, bool use_effective_value) { // This function should not be called with empty inputs as that would mean the selection failed diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h index cd03b7d224709..dbe01a08fe8bd 100644 --- a/src/wallet/coinselection.h +++ b/src/wallet/coinselection.h @@ -263,8 +263,6 @@ struct OutputGroupTypeMap // Based on the insert flag; appends group to the 'mixed_group' and, if value > 0, to the 'positive_group'. // This affects both; the groups filtered by type and the overall groups container. void Push(const OutputGroup& group, OutputType type, bool insert_positive, bool insert_mixed); - // Retrieves 'Groups' filtered by type - std::optional Find(OutputType type); // Different output types count size_t TypesCount() { return groups_by_type.size(); } }; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 16eee1e050a3f..e8c18dbb6758b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -592,12 +592,6 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati bool SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string, bool relay) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - bool DummySignTx(CMutableTransaction &txNew, const std::set &txouts, const CCoinControl* coin_control = nullptr) const - { - std::vector v_txouts(txouts.size()); - std::copy(txouts.begin(), txouts.end(), v_txouts.begin()); - return DummySignTx(txNew, v_txouts, coin_control); - } bool DummySignTx(CMutableTransaction &txNew, const std::vector &txouts, const CCoinControl* coin_control = nullptr) const; bool ImportScripts(const std::set scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); From 475c20aa568d597c7850c784058596ae26f37496 Mon Sep 17 00:00:00 2001 From: furszy Date: Wed, 8 Mar 2023 19:03:40 -0300 Subject: [PATCH 20/72] wallet: remove coin control arg from AutomaticCoinSelection we only need the "include unsafe" flag, not all what coin control stores. --- src/wallet/coinselection.h | 5 +++++ src/wallet/spend.cpp | 17 ++++++++--------- src/wallet/spend.h | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/wallet/coinselection.h b/src/wallet/coinselection.h index dbe01a08fe8bd..5a7b748be1599 100644 --- a/src/wallet/coinselection.h +++ b/src/wallet/coinselection.h @@ -153,6 +153,11 @@ struct CoinSelectionParams { * associated with the same address. This helps reduce privacy leaks resulting from address * reuse. Dust outputs are not eligible to be added to output groups and thus not considered. */ bool m_avoid_partial_spends = false; + /** + * When true, allow unsafe coins to be selected during Coin Selection. This may spend unconfirmed outputs: + * 1) Received from other wallets, 2) replacing other txs, 3) that have been replaced. + */ + bool m_include_unsafe_inputs = false; CoinSelectionParams(FastRandomContext& rng_fast, size_t change_output_size, size_t change_spend_size, CAmount min_change_target, CFeeRate effective_feerate, diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index 359fc78df176a..5771d33b7a88f 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -617,7 +617,7 @@ util::Result SelectCoins(const CWallet& wallet, CoinsResult& av } // Start wallet Coin Selection procedure - auto op_selection_result = AutomaticCoinSelection(wallet, available_coins, selection_target, coin_control, coin_selection_params); + auto op_selection_result = AutomaticCoinSelection(wallet, available_coins, selection_target, coin_selection_params); if (!op_selection_result) return op_selection_result; // If needed, add preset inputs to the automatic coin selection result @@ -632,7 +632,7 @@ util::Result SelectCoins(const CWallet& wallet, CoinsResult& av return op_selection_result; } -util::Result AutomaticCoinSelection(const CWallet& wallet, CoinsResult& available_coins, const CAmount& value_to_select, const CCoinControl& coin_control, const CoinSelectionParams& coin_selection_params) +util::Result AutomaticCoinSelection(const CWallet& wallet, CoinsResult& available_coins, const CAmount& value_to_select, const CoinSelectionParams& coin_selection_params) { unsigned int limit_ancestor_count = 0; unsigned int limit_descendant_count = 0; @@ -641,12 +641,10 @@ util::Result AutomaticCoinSelection(const CWallet& wallet, Coin const size_t max_descendants = (size_t)std::max(1, limit_descendant_count); const bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS); - // form groups from remaining coins; note that preset coins will not - // automatically have their associated (same address) coins included - if (coin_control.m_avoid_partial_spends && available_coins.Size() > OUTPUT_GROUP_MAX_ENTRIES) { - // Cases where we have 101+ outputs all pointing to the same destination may result in - // privacy leaks as they will potentially be deterministically sorted. We solve that by - // explicitly shuffling the outputs before processing + // Cases where we have 101+ outputs all pointing to the same destination may result in + // privacy leaks as they will potentially be deterministically sorted. We solve that by + // explicitly shuffling the outputs before processing + if (coin_selection_params.m_avoid_partial_spends && available_coins.Size() > OUTPUT_GROUP_MAX_ENTRIES) { available_coins.Shuffle(coin_selection_params.rng_fast); } @@ -673,7 +671,7 @@ util::Result AutomaticCoinSelection(const CWallet& wallet, Coin ordered_filters.push_back({CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, /*include_partial=*/true)}); // Try with unsafe inputs if they are allowed. This may spend unconfirmed outputs // received from other wallets. - if (coin_control.m_include_unsafe_inputs) { + if (coin_selection_params.m_include_unsafe_inputs) { ordered_filters.push_back({CoinEligibilityFilter(/*conf_mine=*/0, /*conf_theirs*/0, max_ancestors-1, max_descendants-1, /*include_partial=*/true)}); } // Try with unlimited ancestors/descendants. The transaction will still need to meet @@ -804,6 +802,7 @@ static util::Result CreateTransactionInternal( CoinSelectionParams coin_selection_params{rng_fast}; // Parameters for coin selection, init with dummy coin_selection_params.m_avoid_partial_spends = coin_control.m_avoid_partial_spends; + coin_selection_params.m_include_unsafe_inputs = coin_control.m_include_unsafe_inputs; // Set the long term feerate estimate to the wallet's consolidate feerate coin_selection_params.m_long_term_feerate = wallet.m_consolidate_feerate; diff --git a/src/wallet/spend.h b/src/wallet/spend.h index b8bc82db7aa4f..78c2c5f22b9fa 100644 --- a/src/wallet/spend.h +++ b/src/wallet/spend.h @@ -191,7 +191,7 @@ util::Result FetchSelectedInputs(const CWallet& wallet, const * or (2) an specific error message if there was something particularly wrong (e.g. a selection * result that surpassed the tx max weight size). */ -util::Result AutomaticCoinSelection(const CWallet& wallet, CoinsResult& available_coins, const CAmount& nTargetValue, const CCoinControl& coin_control, +util::Result AutomaticCoinSelection(const CWallet& wallet, CoinsResult& available_coins, const CAmount& nTargetValue, const CoinSelectionParams& coin_selection_params) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); /** From faf3f12424fa8558e65fa3f1dd3aa1d0eea8604e Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Thu, 9 Mar 2023 14:53:36 +0100 Subject: [PATCH 21/72] refactor: Replace GetTimeMicros by SystemClock --- src/logging.cpp | 7 ++++--- src/util/time.cpp | 5 ----- src/util/time.h | 10 +++++----- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/logging.cpp b/src/logging.cpp index 298ec9c01391a..a9b2a2b33a505 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -349,11 +349,12 @@ std::string BCLog::Logger::LogTimestampStr(const std::string& str) return str; if (m_started_new_line) { - int64_t nTimeMicros = GetTimeMicros(); - strStamped = FormatISO8601DateTime(nTimeMicros/1000000); + const auto now{SystemClock::now()}; + const auto now_seconds{std::chrono::time_point_cast(now)}; + strStamped = FormatISO8601DateTime(TicksSinceEpoch(now_seconds)); if (m_log_time_micros) { strStamped.pop_back(); - strStamped += strprintf(".%06dZ", nTimeMicros%1000000); + strStamped += strprintf(".%06dZ", Ticks(now - now_seconds)); } std::chrono::seconds mocktime = GetMockTime(); if (mocktime > 0s) { diff --git a/src/util/time.cpp b/src/util/time.cpp index 58200c83fcbd1..fb9bc349314bd 100644 --- a/src/util/time.cpp +++ b/src/util/time.cpp @@ -107,11 +107,6 @@ int64_t GetTimeMillis() return int64_t{GetSystemTime().count()}; } -int64_t GetTimeMicros() -{ - return int64_t{GetSystemTime().count()}; -} - int64_t GetTime() { return GetTime().count(); } std::string FormatISO8601DateTime(int64_t nTime) { diff --git a/src/util/time.h b/src/util/time.h index fcf85c1e03957..8c6baeb12a762 100644 --- a/src/util/time.h +++ b/src/util/time.h @@ -29,6 +29,8 @@ using SteadySeconds = std::chrono::time_point; using SteadyMicroseconds = std::chrono::time_point; +using SystemClock = std::chrono::system_clock; + void UninterruptibleSleep(const std::chrono::microseconds& n); /** @@ -63,16 +65,14 @@ using MillisecondsDouble = std::chrono::duration() if a cast is needed. * ClockType is - * - std::chrono::steady_clock for steady time - * - std::chrono::system_clock for system time - * - NodeClock for mockable system time + * - SteadyClock/std::chrono::steady_clock for steady time + * - SystemClock/std::chrono::system_clock for system time + * - NodeClock for mockable system time */ int64_t GetTime(); /** Returns the system time (not mockable) */ int64_t GetTimeMillis(); -/** Returns the system time (not mockable) */ -int64_t GetTimeMicros(); /** * DEPRECATED From fab9a08e145dc5a1d9576bf062473f1095b56a16 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Fri, 10 Mar 2023 10:45:28 +0100 Subject: [PATCH 22/72] refactor: Replace block_hash with block_out --- src/rpc/mining.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 8753f845a5f2a..0df43d1b4196f 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -115,9 +115,9 @@ static RPCHelpMan getnetworkhashps() }; } -static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t& max_tries, uint256& block_hash) +static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t& max_tries, std::shared_ptr& block_out) { - block_hash.SetNull(); + block_out.reset(); block.hashMerkleRoot = BlockMerkleRoot(block); while (max_tries > 0 && block.nNonce < std::numeric_limits::max() && !CheckProofOfWork(block.GetHash(), block.nBits, chainman.GetConsensus()) && !ShutdownRequested()) { @@ -131,12 +131,11 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t& return true; } - std::shared_ptr shared_pblock = std::make_shared(block); - if (!chainman.ProcessNewBlock(shared_pblock, /*force_processing=*/true, /*min_pow_checked=*/true, nullptr)) { + block_out = std::make_shared(block); + if (!chainman.ProcessNewBlock(block_out, /*force_processing=*/true, /*min_pow_checked=*/true, nullptr)) { throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); } - block_hash = block.GetHash(); return true; } @@ -147,16 +146,15 @@ static UniValue generateBlocks(ChainstateManager& chainman, const CTxMemPool& me std::unique_ptr pblocktemplate(BlockAssembler{chainman.ActiveChainstate(), &mempool}.CreateNewBlock(coinbase_script)); if (!pblocktemplate.get()) throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); - CBlock *pblock = &pblocktemplate->block; - uint256 block_hash; - if (!GenerateBlock(chainman, *pblock, nMaxTries, block_hash)) { + std::shared_ptr block_out; + if (!GenerateBlock(chainman, pblocktemplate->block, nMaxTries, block_out)) { break; } - if (!block_hash.IsNull()) { + if (block_out) { --nGenerate; - blockHashes.push_back(block_hash.GetHex()); + blockHashes.push_back(block_out->GetHash().GetHex()); } } return blockHashes; @@ -376,15 +374,15 @@ static RPCHelpMan generateblock() } } - uint256 block_hash; + std::shared_ptr block_out; uint64_t max_tries{DEFAULT_MAX_TRIES}; - if (!GenerateBlock(chainman, block, max_tries, block_hash) || block_hash.IsNull()) { + if (!GenerateBlock(chainman, block, max_tries, block_out) || !block_out) { throw JSONRPCError(RPC_MISC_ERROR, "Failed to make block."); } UniValue obj(UniValue::VOBJ); - obj.pushKV("hash", block_hash.GetHex()); + obj.pushKV("hash", block_out->GetHash().GetHex()); return obj; }, }; From fa18504d5767a40dc9827fb081633219bf251001 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Fri, 10 Mar 2023 10:40:26 +0100 Subject: [PATCH 23/72] rpc: Add submit option to generateblock --- src/rpc/client.cpp | 1 + src/rpc/mining.cpp | 17 ++++++++++++++--- test/functional/rpc_generate.py | 7 ++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 9449b9d197ef7..4459dd71aa602 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -37,6 +37,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "generatetodescriptor", 0, "num_blocks" }, { "generatetodescriptor", 2, "maxtries" }, { "generateblock", 1, "transactions" }, + { "generateblock", 2, "submit" }, { "getnetworkhashps", 0, "nblocks" }, { "getnetworkhashps", 1, "height" }, { "sendtoaddress", 1, "amount" }, diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 0df43d1b4196f..d55e20ba5e3a3 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -115,7 +115,7 @@ static RPCHelpMan getnetworkhashps() }; } -static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t& max_tries, std::shared_ptr& block_out) +static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t& max_tries, std::shared_ptr& block_out, bool process_new_block) { block_out.reset(); block.hashMerkleRoot = BlockMerkleRoot(block); @@ -132,6 +132,9 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t& } block_out = std::make_shared(block); + + if (!process_new_block) return true; + if (!chainman.ProcessNewBlock(block_out, /*force_processing=*/true, /*min_pow_checked=*/true, nullptr)) { throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); } @@ -148,7 +151,7 @@ static UniValue generateBlocks(ChainstateManager& chainman, const CTxMemPool& me throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); std::shared_ptr block_out; - if (!GenerateBlock(chainman, pblocktemplate->block, nMaxTries, block_out)) { + if (!GenerateBlock(chainman, pblocktemplate->block, nMaxTries, block_out, /*process_new_block=*/true)) { break; } @@ -293,11 +296,13 @@ static RPCHelpMan generateblock() {"rawtx/txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""}, }, }, + {"submit", RPCArg::Type::BOOL, RPCArg::Default{true}, "Whether to submit the block before the RPC call returns or to return it as hex."}, }, RPCResult{ RPCResult::Type::OBJ, "", "", { {RPCResult::Type::STR_HEX, "hash", "hash of generated block"}, + {RPCResult::Type::STR_HEX, "hex", /*optional=*/true, "hex of generated block, only present when submit=false"}, } }, RPCExamples{ @@ -346,6 +351,7 @@ static RPCHelpMan generateblock() } } + const bool process_new_block{request.params[2].isNull() ? true : request.params[2].get_bool()}; CBlock block; ChainstateManager& chainman = EnsureChainman(node); @@ -377,12 +383,17 @@ static RPCHelpMan generateblock() std::shared_ptr block_out; uint64_t max_tries{DEFAULT_MAX_TRIES}; - if (!GenerateBlock(chainman, block, max_tries, block_out) || !block_out) { + if (!GenerateBlock(chainman, block, max_tries, block_out, process_new_block) || !block_out) { throw JSONRPCError(RPC_MISC_ERROR, "Failed to make block."); } UniValue obj(UniValue::VOBJ); obj.pushKV("hash", block_out->GetHash().GetHex()); + if (!process_new_block) { + CDataStream block_ser{SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags()}; + block_ser << *block_out; + obj.pushKV("hex", HexStr(block_ser)); + } return obj; }, }; diff --git a/test/functional/rpc_generate.py b/test/functional/rpc_generate.py index 8948ccb48d923..20f62079fd683 100755 --- a/test/functional/rpc_generate.py +++ b/test/functional/rpc_generate.py @@ -29,8 +29,13 @@ def test_generateblock(self): node = self.nodes[0] miniwallet = MiniWallet(node) - self.log.info('Generate an empty block to address') + self.log.info('Mine an empty block to address and return the hex') address = miniwallet.get_address() + generated_block = self.generateblock(node, output=address, transactions=[], submit=False) + node.submitblock(hexdata=generated_block['hex']) + assert_equal(generated_block['hash'], node.getbestblockhash()) + + self.log.info('Generate an empty block to address') hash = self.generateblock(node, output=address, transactions=[])['hash'] block = node.getblock(blockhash=hash, verbose=2) assert_equal(len(block['tx']), 1) From acf0119d24c9f8fae825093249a46cd38e4a3a91 Mon Sep 17 00:00:00 2001 From: furszy Date: Tue, 7 Mar 2023 18:47:28 -0300 Subject: [PATCH 24/72] wallet: return error msg for too-long-mempool-chain failure We currently return "Insufficient funds" which doesn't really describe what went wrong; the tx creation failed because of a long-mempool-chain, not because of a lack of funds. Also, return early from Coin Selection if the sum of the discarded coins decreases the available balance below the target amount. --- src/wallet/spend.cpp | 46 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index a8ecce119aff5..60af9f9c66943 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -407,7 +407,8 @@ std::map> ListCoins(const CWallet& wallet) FilteredOutputGroups GroupOutputs(const CWallet& wallet, const CoinsResult& coins, const CoinSelectionParams& coin_sel_params, - const std::vector& filters) + const std::vector& filters, + std::vector& ret_discarded_groups) { FilteredOutputGroups filtered_groups; @@ -427,11 +428,14 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, group.Insert(std::make_shared(output), ancestors, descendants); // Each filter maps to a different set of groups + bool accepted = false; for (const auto& sel_filter : filters) { const auto& filter = sel_filter.filter; if (!group.EligibleForSpending(filter)) continue; filtered_groups[filter].Push(group, type, /*insert_positive=*/true, /*insert_mixed=*/true); + accepted = true; } + if (!accepted) ret_discarded_groups.emplace_back(group); } } return filtered_groups; @@ -497,6 +501,7 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, const OutputGroup& group = *group_it; // Each filter maps to a different set of groups + bool accepted = false; for (const auto& sel_filter : filters) { const auto& filter = sel_filter.filter; if (!group.EligibleForSpending(filter)) continue; @@ -509,7 +514,9 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, OutputType type = script.second; // Either insert the group into the positive-only groups or the mixed ones. filtered_groups[filter].Push(group, type, positive_only, /*insert_mixed=*/!positive_only); + accepted = true; } + if (!accepted) ret_discarded_groups.emplace_back(group); } } }; @@ -520,6 +527,15 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet, return filtered_groups; } +FilteredOutputGroups GroupOutputs(const CWallet& wallet, + const CoinsResult& coins, + const CoinSelectionParams& params, + const std::vector& filters) +{ + std::vector unused; + return GroupOutputs(wallet, coins, params, filters, unused); +} + // Returns true if the result contains an error and the message is not empty static bool HasErrorMsg(const util::Result& res) { return !util::ErrorString(res).empty(); } @@ -692,7 +708,24 @@ util::Result AutomaticCoinSelection(const CWallet& wallet, Coin } // Group outputs and map them by coin eligibility filter - FilteredOutputGroups filtered_groups = GroupOutputs(wallet, available_coins, coin_selection_params, ordered_filters); + std::vector discarded_groups; + FilteredOutputGroups filtered_groups = GroupOutputs(wallet, available_coins, coin_selection_params, ordered_filters, discarded_groups); + + // Check if we still have enough balance after applying filters (some coins might be discarded) + CAmount total_discarded = 0; + CAmount total_unconf_long_chain = 0; + for (const auto& group : discarded_groups) { + total_discarded += group.GetSelectionAmount(); + if (group.m_ancestors >= max_ancestors || group.m_descendants >= max_descendants) total_unconf_long_chain += group.GetSelectionAmount(); + } + + if (CAmount total_amount = available_coins.GetTotalAmount() - total_discarded < value_to_select) { + // Special case, too-long-mempool cluster. + if (total_amount + total_unconf_long_chain > value_to_select) { + return util::Result({_("Unconfirmed UTXOs are available, but spending them creates a chain of transactions that will be rejected by the mempool")}); + } + return util::Result(util::Error()); // General "Insufficient Funds" + } // Walk-through the filters until the solution gets found. // If no solution is found, return the first detailed error (if any). @@ -711,8 +744,13 @@ util::Result AutomaticCoinSelection(const CWallet& wallet, Coin if (HasErrorMsg(res)) res_detailed_errors.emplace_back(res); } } - // Coin Selection failed. - return res_detailed_errors.empty() ? util::Result(util::Error()) : res_detailed_errors.front(); + + // Return right away if we have a detailed error + if (!res_detailed_errors.empty()) return res_detailed_errors.front(); + + + // General "Insufficient Funds" + return util::Result(util::Error()); }(); return res; From f3221d373a8623fe4808e00c7a92fbb6e0d6419b Mon Sep 17 00:00:00 2001 From: furszy Date: Tue, 7 Mar 2023 18:48:21 -0300 Subject: [PATCH 25/72] test: add wallet too-long-mempool-chain error coverage --- test/functional/wallet_create_tx.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/functional/wallet_create_tx.py b/test/functional/wallet_create_tx.py index 2d9bb38fcc2e5..11c82e15b7e4d 100755 --- a/test/functional/wallet_create_tx.py +++ b/test/functional/wallet_create_tx.py @@ -32,6 +32,7 @@ def run_test(self): self.test_anti_fee_sniping() self.test_tx_size_too_large() + self.test_create_too_long_mempool_chain() def test_anti_fee_sniping(self): self.log.info('Check that we have some (old) blocks and that anti-fee-sniping is disabled') @@ -80,6 +81,30 @@ def test_tx_size_too_large(self): ) self.nodes[0].settxfee(0) + def test_create_too_long_mempool_chain(self): + self.log.info('Check too-long mempool chain error') + df_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name) + + self.nodes[0].createwallet("too_long") + test_wallet = self.nodes[0].get_wallet_rpc("too_long") + + tx_data = df_wallet.send(outputs=[{test_wallet.getnewaddress(): 25}], options={"change_position": 0}) + txid = tx_data['txid'] + vout = 1 + + options = {"change_position": 0, "add_inputs": False} + for i in range(1, 25): + options['inputs'] = [{'txid': txid, 'vout': vout}] + tx_data = test_wallet.send(outputs=[{test_wallet.getnewaddress(): 25 - i}], options=options) + txid = tx_data['txid'] + + # Sending one more chained transaction will fail + options = {"minconf": 0, "include_unsafe": True, 'add_inputs': True} + assert_raises_rpc_error(-4, "Unconfirmed UTXOs are available, but spending them creates a chain of transactions that will be rejected by the mempool", + test_wallet.send, outputs=[{test_wallet.getnewaddress(): 0.3}], options=options) + + test_wallet.unloadwallet() + if __name__ == '__main__': CreateTxWalletTest().main() From c84c5f6e89094749f90d7b0994278e50689e04dc Mon Sep 17 00:00:00 2001 From: brunoerg Date: Mon, 16 Jan 2023 11:25:13 -0300 Subject: [PATCH 26/72] p2p: set `-dnsseed` and `-listen` false if `maxconnections=0` If `maxconnections=0`, it means our possible connections are going to be manual (e.g via `addnode`). For this reason, we can skip DNS seeds and set `listen` false. --- src/init.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 983e6b8607300..c55618d1fb60f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -473,11 +473,11 @@ void SetupServerArgs(ArgsManager& argsman) argsman.AddArg("-connect=", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-dnsseed", strprintf("Query for peer addresses via DNS lookup, if low on addresses (default: %u unless -connect used)", DEFAULT_DNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); + argsman.AddArg("-dnsseed", strprintf("Query for peer addresses via DNS lookup, if low on addresses (default: %u unless -connect used or -maxconnections=0)", DEFAULT_DNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-externalip=", "Specify your own public address", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-fixedseeds", strprintf("Allow fixed seeds if DNS seeds don't provide peers (default: %u)", DEFAULT_FIXEDSEEDS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - argsman.AddArg("-listen", strprintf("Accept connections from outside (default: %u if no -proxy or -connect)", DEFAULT_LISTEN), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); + argsman.AddArg("-listen", strprintf("Accept connections from outside (default: %u if no -proxy, -connect or -maxconnections=0)", DEFAULT_LISTEN), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-listenonion", strprintf("Automatically create Tor onion service (default: %d)", DEFAULT_LISTEN_ONION), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-maxconnections=", strprintf("Maintain at most connections to peers (default: %u). This limit does not apply to connections manually added via -addnode or the addnode RPC, which have a separate limit of %u.", DEFAULT_MAX_PEER_CONNECTIONS, MAX_ADDNODE_CONNECTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-maxreceivebuffer=", strprintf("Maximum per-connection receive buffer, *1000 bytes (default: %u)", DEFAULT_MAXRECEIVEBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); @@ -684,12 +684,12 @@ void InitParameterInteraction(ArgsManager& args) LogPrintf("%s: parameter interaction: -whitebind set -> setting -listen=1\n", __func__); } - if (args.IsArgSet("-connect")) { + if (args.IsArgSet("-connect") || args.GetIntArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS) <= 0) { // when only connecting to trusted nodes, do not seed via DNS, or listen by default if (args.SoftSetBoolArg("-dnsseed", false)) - LogPrintf("%s: parameter interaction: -connect set -> setting -dnsseed=0\n", __func__); + LogPrintf("%s: parameter interaction: -connect or -maxconnections=0 set -> setting -dnsseed=0\n", __func__); if (args.SoftSetBoolArg("-listen", false)) - LogPrintf("%s: parameter interaction: -connect set -> setting -listen=0\n", __func__); + LogPrintf("%s: parameter interaction: -connect or -maxconnections=0 set -> setting -listen=0\n", __func__); } std::string proxy_arg = args.GetArg("-proxy", ""); From fabb95e7bf02f3d8e663a02dd845d42e09d330ec Mon Sep 17 00:00:00 2001 From: brunoerg Date: Thu, 26 Jan 2023 15:00:43 -0300 Subject: [PATCH 27/72] doc: add release note for 26899 --- doc/release-notes-26899.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 doc/release-notes-26899.md diff --git a/doc/release-notes-26899.md b/doc/release-notes-26899.md new file mode 100644 index 0000000000000..ceb9ec2f7a110 --- /dev/null +++ b/doc/release-notes-26899.md @@ -0,0 +1,5 @@ +Updated settings +---------------- + +- Setting `-maxconnections=0` will now disable `-dnsseed` + and `-listen` (users may still set them to override). \ No newline at end of file From 285edfadcacde4921c0afa2092c613daf21a55aa Mon Sep 17 00:00:00 2001 From: fanquake Date: Wed, 3 Aug 2022 10:54:15 +0100 Subject: [PATCH 28/72] guix: use osslsigncode 2.5 Co-authored-by: Andrew Chow --- contrib/guix/libexec/codesign.sh | 1 + contrib/guix/manifest.scm | 21 ++++++++------------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/contrib/guix/libexec/codesign.sh b/contrib/guix/libexec/codesign.sh index f6322d761ced5..6ffa0f07b2e90 100755 --- a/contrib/guix/libexec/codesign.sh +++ b/contrib/guix/libexec/codesign.sh @@ -77,6 +77,7 @@ mkdir -p "$DISTSRC" osslsigncode attach-signature \ -in "$infile" \ -out "${OUTDIR}/${infile_base/-unsigned}" \ + -CAfile "$GUIX_ENVIRONMENT/etc/ssl/certs/ca-certificates.crt" \ -sigin codesignatures/win/"$infile_base".pem done ;; diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm index e266e7d0ee636..249f1ed553882 100644 --- a/contrib/guix/manifest.scm +++ b/contrib/guix/manifest.scm @@ -28,6 +28,7 @@ (gnu packages shells) (gnu packages tls) (gnu packages version-control) + (guix build-system cmake) (guix build-system gnu) (guix build-system python) (guix build-system trivial) @@ -238,27 +239,20 @@ parse, modify and abstract ELF, PE and MachO formats.") (define osslsigncode (package (name "osslsigncode") - (version "2.0") + (version "2.5") (source (origin (method url-fetch) (uri (string-append "https://github.com/mtrojnar/" name "/archive/" version ".tar.gz")) (sha256 (base32 - "0byri6xny770wwb2nciq44j5071122l14bvv65axdd70nfjf0q2s")))) - (build-system gnu-build-system) - (native-inputs - `(("pkg-config" ,pkg-config) - ("autoconf" ,autoconf) - ("automake" ,automake) - ("libtool" ,libtool))) + "03by9706gg0an6dn48pljx38vcb76ziv11bgm8ilwsf293x2k4hv")))) + (build-system cmake-build-system) (inputs - `(("openssl" ,openssl))) + `(("openssl", openssl))) (arguments - `(#:configure-flags - `("--without-gsf" - "--without-curl" - "--disable-dependency-tracking"))) + '(#:configure-flags + (list "-DCMAKE_DISABLE_FIND_PACKAGE_CURL=TRUE"))) (home-page "https://github.com/mtrojnar/osslsigncode") (synopsis "Authenticode signing and timestamping tool") (description "osslsigncode is a small tool that implements part of the @@ -607,6 +601,7 @@ inspecting signatures in Mach-O binaries.") (list zip (make-mingw-pthreads-cross-toolchain "x86_64-w64-mingw32") (make-nsis-for-gcc-10 nsis-x86_64) + nss-certs osslsigncode)) ((string-contains target "-linux-") (list (make-bitcoin-cross-toolchain target))) From fa721f1cab0de239a93f6bf70e3a8af26fddae8a Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 3 Jan 2023 13:12:45 +0100 Subject: [PATCH 29/72] Move ::nPruneTarget into BlockManager --- src/Makefile.am | 3 ++ src/bitcoin-chainstate.cpp | 2 +- src/init.cpp | 27 ++++++---------- src/kernel/blockmanager_opts.h | 20 ++++++++++++ src/node/blockmanager_args.cpp | 32 +++++++++++++++++++ src/node/blockmanager_args.h | 20 ++++++++++++ src/node/blockstorage.cpp | 15 ++++----- src/node/blockstorage.h | 10 ++++-- src/test/blockmanager_tests.cpp | 2 +- src/test/util/setup_common.cpp | 2 +- .../validation_chainstatemanager_tests.cpp | 6 ++-- src/validation.cpp | 4 ++- src/validation.h | 2 +- 13 files changed, 109 insertions(+), 36 deletions(-) create mode 100644 src/kernel/blockmanager_opts.h create mode 100644 src/node/blockmanager_args.cpp create mode 100644 src/node/blockmanager_args.h diff --git a/src/Makefile.am b/src/Makefile.am index a0c1670287afc..68ec92b27f6cf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -174,6 +174,7 @@ BITCOIN_CORE_H = \ interfaces/ipc.h \ interfaces/node.h \ interfaces/wallet.h \ + kernel/blockmanager_opts.h \ kernel/chain.h \ kernel/chainstatemanager_opts.h \ kernel/checks.h \ @@ -200,6 +201,7 @@ BITCOIN_CORE_H = \ netbase.h \ netgroup.h \ netmessagemaker.h \ + node/blockmanager_args.h \ node/blockstorage.h \ node/caches.h \ node/chainstate.h \ @@ -387,6 +389,7 @@ libbitcoin_node_a_SOURCES = \ net.cpp \ net_processing.cpp \ netgroup.cpp \ + node/blockmanager_args.cpp \ node/blockstorage.cpp \ node/caches.cpp \ node/chainstate.cpp \ diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp index 423fa79c6fe49..136904a0c0ae8 100644 --- a/src/bitcoin-chainstate.cpp +++ b/src/bitcoin-chainstate.cpp @@ -85,7 +85,7 @@ int main(int argc, char* argv[]) .datadir = gArgs.GetDataDirNet(), .adjusted_time_callback = NodeClock::now, }; - ChainstateManager chainman{chainman_opts}; + ChainstateManager chainman{chainman_opts, {}}; node::CacheSizes cache_sizes; cache_sizes.block_tree_db = 2 << 20; diff --git a/src/init.cpp b/src/init.cpp index 090a11a825d38..d68ba80b79fe0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -124,7 +125,6 @@ using node::ThreadImport; using node::VerifyLoadedChainstate; using node::fPruneMode; using node::fReindex; -using node::nPruneTarget; static constexpr bool DEFAULT_PROXYRANDOMIZE{true}; static constexpr bool DEFAULT_REST_ENABLE{false}; @@ -945,22 +945,6 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb init::SetLoggingCategories(args); init::SetLoggingLevel(args); - // block pruning; get the amount of disk space (in MiB) to allot for block & undo files - int64_t nPruneArg = args.GetIntArg("-prune", 0); - if (nPruneArg < 0) { - return InitError(_("Prune cannot be configured with a negative value.")); - } - nPruneTarget = (uint64_t) nPruneArg * 1024 * 1024; - if (nPruneArg == 1) { // manual pruning: -prune=1 - nPruneTarget = std::numeric_limits::max(); - fPruneMode = true; - } else if (nPruneTarget) { - if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) { - return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); - } - fPruneMode = true; - } - nConnectTimeout = args.GetIntArg("-timeout", DEFAULT_CONNECT_TIMEOUT); if (nConnectTimeout <= 0) { nConnectTimeout = DEFAULT_CONNECT_TIMEOUT; @@ -1051,6 +1035,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{}; + if (const auto error{ApplyArgsManOptions(args, blockman_opts_dummy)}) { + return InitError(*error); + } } return true; @@ -1450,6 +1438,9 @@ 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{}; + Assert(!ApplyArgsManOptions(args, blockman_opts)); // no error can happen, already checked in AppInitParameterInteraction + // cache size calculations CacheSizes cache_sizes = CalculateCacheSizes(args, g_enabled_filter_types.size()); @@ -1485,7 +1476,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) for (bool fLoaded = false; !fLoaded && !ShutdownRequested();) { node.mempool = std::make_unique(mempool_opts); - node.chainman = std::make_unique(chainman_opts); + node.chainman = std::make_unique(chainman_opts, blockman_opts); ChainstateManager& chainman = *node.chainman; node::ChainstateLoadOptions options; diff --git a/src/kernel/blockmanager_opts.h b/src/kernel/blockmanager_opts.h new file mode 100644 index 0000000000000..9dc93b6dd245b --- /dev/null +++ b/src/kernel/blockmanager_opts.h @@ -0,0 +1,20 @@ +// Copyright (c) 2022 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_KERNEL_BLOCKMANAGER_OPTS_H +#define BITCOIN_KERNEL_BLOCKMANAGER_OPTS_H + +namespace kernel { + +/** + * An options struct for `BlockManager`, more ergonomically referred to as + * `BlockManager::Options` due to the using-declaration in `BlockManager`. + */ +struct BlockManagerOpts { + uint64_t prune_target{0}; +}; + +} // namespace kernel + +#endif // BITCOIN_KERNEL_BLOCKMANAGER_OPTS_H diff --git a/src/node/blockmanager_args.cpp b/src/node/blockmanager_args.cpp new file mode 100644 index 0000000000000..cba44dafb9eed --- /dev/null +++ b/src/node/blockmanager_args.cpp @@ -0,0 +1,32 @@ +// 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 + +#include +#include + +namespace node { +std::optional ApplyArgsManOptions(const ArgsManager& args, BlockManager::Options& opts) +{ + // block pruning; get the amount of disk space (in MiB) to allot for block & undo files + int64_t nPruneArg{args.GetIntArg("-prune", opts.prune_target)}; + if (nPruneArg < 0) { + return _("Prune cannot be configured with a negative value."); + } + uint64_t nPruneTarget{uint64_t(nPruneArg) * 1024 * 1024}; + if (nPruneArg == 1) { // manual pruning: -prune=1 + nPruneTarget = std::numeric_limits::max(); + fPruneMode = true; + } else if (nPruneTarget) { + if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) { + return strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024); + } + fPruneMode = true; + } + opts.prune_target = nPruneTarget; + + return std::nullopt; +} +} // namespace node diff --git a/src/node/blockmanager_args.h b/src/node/blockmanager_args.h new file mode 100644 index 0000000000000..e657c6bb4568f --- /dev/null +++ b/src/node/blockmanager_args.h @@ -0,0 +1,20 @@ + +// 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_NODE_BLOCKMANAGER_ARGS_H +#define BITCOIN_NODE_BLOCKMANAGER_ARGS_H + +#include + +#include + +class ArgsManager; +struct bilingual_str; + +namespace node { +std::optional ApplyArgsManOptions(const ArgsManager& args, BlockManager::Options& opts); +} // namespace node + +#endif // BITCOIN_NODE_BLOCKMANAGER_ARGS_H diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 255b73b3472ff..5e364942d4935 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -29,7 +29,6 @@ namespace node { std::atomic_bool fImporting(false); std::atomic_bool fReindex(false); bool fPruneMode = false; -uint64_t nPruneTarget = 0; bool CBlockIndexWorkComparator::operator()(const CBlockIndex* pa, const CBlockIndex* pb) const { @@ -178,7 +177,7 @@ void BlockManager::FindFilesToPruneManual(std::set& setFilesToPrune, int nM void BlockManager::FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight, int chain_tip_height, int prune_height, bool is_ibd) { LOCK2(cs_main, cs_LastBlockFile); - if (chain_tip_height < 0 || nPruneTarget == 0) { + if (chain_tip_height < 0 || GetPruneTarget() == 0) { return; } if ((uint64_t)chain_tip_height <= nPruneAfterHeight) { @@ -194,14 +193,14 @@ void BlockManager::FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPr uint64_t nBytesToPrune; int count = 0; - if (nCurrentUsage + nBuffer >= nPruneTarget) { + if (nCurrentUsage + nBuffer >= GetPruneTarget()) { // On a prune event, the chainstate DB is flushed. // To avoid excessive prune events negating the benefit of high dbcache // values, we should not prune too rapidly. // So when pruning in IBD, increase the buffer a bit to avoid a re-prune too soon. if (is_ibd) { // Since this is only relevant during IBD, we use a fixed 10% - nBuffer += nPruneTarget / 10; + nBuffer += GetPruneTarget() / 10; } for (int fileNumber = 0; fileNumber < m_last_blockfile; fileNumber++) { @@ -211,7 +210,7 @@ void BlockManager::FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPr continue; } - if (nCurrentUsage + nBuffer < nPruneTarget) { // are we below our target? + if (nCurrentUsage + nBuffer < GetPruneTarget()) { // are we below our target? break; } @@ -229,9 +228,9 @@ void BlockManager::FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPr } LogPrint(BCLog::PRUNE, "target=%dMiB actual=%dMiB diff=%dMiB max_prune_height=%d removed %d blk/rev pairs\n", - nPruneTarget/1024/1024, nCurrentUsage/1024/1024, - ((int64_t)nPruneTarget - (int64_t)nCurrentUsage)/1024/1024, - nLastBlockWeCanPrune, count); + GetPruneTarget() / 1024 / 1024, nCurrentUsage / 1024 / 1024, + (int64_t(GetPruneTarget()) - int64_t(nCurrentUsage)) / 1024 / 1024, + nLastBlockWeCanPrune, count); } void BlockManager::UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) { diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 09aff7f08b71e..d76d916a93e3b 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -49,7 +50,6 @@ static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE = CMessageHeader::MESSAG extern std::atomic_bool fImporting; extern std::atomic_bool fReindex; extern bool fPruneMode; -extern uint64_t nPruneTarget; // Because validation code takes pointers to the map's CBlockIndex objects, if // we ever switch to another associative container, we need to either use a @@ -138,7 +138,13 @@ class BlockManager */ std::unordered_map m_prune_locks GUARDED_BY(::cs_main); + const kernel::BlockManagerOpts m_opts; + public: + using Options = kernel::BlockManagerOpts; + + explicit BlockManager(Options opts) : m_opts{std::move(opts)} {}; + BlockMap m_block_index GUARDED_BY(cs_main); std::vector GetAllBlockIndices() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); @@ -184,7 +190,7 @@ class BlockManager [[nodiscard]] bool IsPruneMode() const { return fPruneMode; } /** Attempt to stay below this number of bytes of block files. */ - [[nodiscard]] uint64_t GetPruneTarget() const { return nPruneTarget; } + [[nodiscard]] uint64_t GetPruneTarget() const { return m_opts.prune_target; } [[nodiscard]] bool LoadingBlocks() const { diff --git a/src/test/blockmanager_tests.cpp b/src/test/blockmanager_tests.cpp index d5825d0d7e5f2..2118f476cd931 100644 --- a/src/test/blockmanager_tests.cpp +++ b/src/test/blockmanager_tests.cpp @@ -21,7 +21,7 @@ BOOST_FIXTURE_TEST_SUITE(blockmanager_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(blockmanager_find_block_pos) { const auto params {CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN)}; - BlockManager blockman {}; + BlockManager blockman{{}}; CChain chain {}; // simulate adding a genesis block normally BOOST_CHECK_EQUAL(blockman.SaveBlockToDisk(params->GenesisBlock(), 0, chain, *params, nullptr).nPos, BLOCK_SERIALIZATION_HEADER_SIZE); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 4e0000cb3d0ed..58593c9d5bb9a 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -184,7 +184,7 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve .adjusted_time_callback = GetAdjustedTime, .check_block_index = true, }; - m_node.chainman = std::make_unique(chainman_opts); + m_node.chainman = std::make_unique(chainman_opts, node::BlockManager::Options{}); m_node.chainman->m_blockman.m_block_tree_db = std::make_unique(DBParams{ .path = m_args.GetDataDirNet() / "blocks" / "index", .cache_bytes = static_cast(m_cache_sizes.block_tree_db), diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp index 6fc9d0fa51e86..688aafdd46ce7 100644 --- a/src/test/validation_chainstatemanager_tests.cpp +++ b/src/test/validation_chainstatemanager_tests.cpp @@ -381,7 +381,7 @@ struct SnapshotTestSetup : TestChain100Setup { // For robustness, ensure the old manager is destroyed before creating a // new one. m_node.chainman.reset(); - m_node.chainman.reset(new ChainstateManager(chainman_opts)); + m_node.chainman = std::make_unique(chainman_opts, node::BlockManager::Options{}); } return *Assert(m_node.chainman); } @@ -588,7 +588,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_snapshot_completion, SnapshotTestSetup // chainstate_snapshot should still exist. BOOST_CHECK(fs::exists(snapshot_chainstate_dir)); - // Test that simulating a shutdown (reseting ChainstateManager) and then performing + // Test that simulating a shutdown (resetting ChainstateManager) and then performing // chainstate reinitializing successfully cleans up the background-validation // chainstate data, and we end up with a single chainstate that is at tip. ChainstateManager& chainman_restarted = this->SimulateNodeRestart(); @@ -660,7 +660,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_snapshot_completion_hash_mismatch, Sna fs::path snapshot_invalid_dir = gArgs.GetDataDirNet() / "chainstate_snapshot_INVALID"; BOOST_CHECK(fs::exists(snapshot_invalid_dir)); - // Test that simulating a shutdown (reseting ChainstateManager) and then performing + // Test that simulating a shutdown (resetting ChainstateManager) and then performing // chainstate reinitializing successfully loads only the fully-validated // chainstate data, and we end up with a single chainstate that is at tip. ChainstateManager& chainman_restarted = this->SimulateNodeRestart(); diff --git a/src/validation.cpp b/src/validation.cpp index f3c0401c0f026..47355b0850f1a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -5555,7 +5555,9 @@ static ChainstateManager::Options&& Flatten(ChainstateManager::Options&& opts) return std::move(opts); } -ChainstateManager::ChainstateManager(Options options) : m_options{Flatten(std::move(options))} {} +ChainstateManager::ChainstateManager(Options options, node::BlockManager::Options blockman_options) + : m_options{Flatten(std::move(options))}, + m_blockman{std::move(blockman_options)} {} ChainstateManager::~ChainstateManager() { diff --git a/src/validation.h b/src/validation.h index b0cef0d37bca6..8fac2f6091ae6 100644 --- a/src/validation.h +++ b/src/validation.h @@ -955,7 +955,7 @@ class ChainstateManager public: using Options = kernel::ChainstateManagerOpts; - explicit ChainstateManager(Options options); + explicit ChainstateManager(Options options, node::BlockManager::Options blockman_options); const CChainParams& GetParams() const { return m_options.chainparams; } const Consensus::Params& GetConsensus() const { return m_options.chainparams.GetConsensus(); } From 3faae99c3d8e512f9d3f6e7fb0785c60d4bed654 Mon Sep 17 00:00:00 2001 From: Gleb Naumenko Date: Tue, 14 Sep 2021 14:54:40 +0300 Subject: [PATCH 30/72] p2p: Diversify connections only w.r.t *persistent* outbound peers ADDR_FETCH and FEELER are short-lived connections, and they should not affect our choice of peers. Also, improve comments. --- src/net.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index d1895b7172c7d..e19decbda83a7 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1721,19 +1721,22 @@ void CConnman::ThreadOpenConnections(const std::vector connect) if (pnode->IsFullOutboundConn()) nOutboundFullRelay++; if (pnode->IsBlockOnlyConn()) nOutboundBlockRelay++; - // Netgroups for inbound and manual peers are not excluded because our goal here - // is to not use multiple of our limited outbound slots on a single netgroup - // but inbound and manual peers do not use our outbound slots. Inbound peers - // also have the added issue that they could be attacker controlled and used - // to prevent us from connecting to particular hosts if we used them here. + // Make sure our persistent outbound slots belong to different netgroups. switch (pnode->m_conn_type) { + // We currently don't take inbound connections into account. Since they are + // free to make, an attacker could make them to prevent us from connecting to + // certain peers. case ConnectionType::INBOUND: + // Manually selected connections should not affect how we select outbound + // peers from addrman. case ConnectionType::MANUAL: + // Short-lived outbound connections should not affect how we select outbound + // peers from addrman. + case ConnectionType::ADDR_FETCH: + case ConnectionType::FEELER: break; case ConnectionType::OUTBOUND_FULL_RELAY: case ConnectionType::BLOCK_RELAY: - case ConnectionType::ADDR_FETCH: - case ConnectionType::FEELER: setConnected.insert(m_netgroupman.GetGroup(pnode->addr)); } // no default case, so the compiler can warn about missing cases } From 72e8ffd7f8dbf908e65da6d012ede914596737ab Mon Sep 17 00:00:00 2001 From: Gleb Naumenko Date: Tue, 14 Sep 2021 15:19:41 +0300 Subject: [PATCH 31/72] p2p: Account for MANUAL conns when diversifying persistent outbound conns Previously, we would make connections to peer from the netgroups to which our MANUAL outbound connections belong. However, they should be seen as regular connections from Addrman when it comes to netgroup diversity check, since the same rationale can be applied. Note, this has nothing to do with how we connect to MANUAL connections: we connect to them unconditionally. --- src/net.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index e19decbda83a7..9b803180f9737 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1727,14 +1727,12 @@ void CConnman::ThreadOpenConnections(const std::vector connect) // free to make, an attacker could make them to prevent us from connecting to // certain peers. case ConnectionType::INBOUND: - // Manually selected connections should not affect how we select outbound - // peers from addrman. - case ConnectionType::MANUAL: // Short-lived outbound connections should not affect how we select outbound // peers from addrman. case ConnectionType::ADDR_FETCH: case ConnectionType::FEELER: break; + case ConnectionType::MANUAL: case ConnectionType::OUTBOUND_FULL_RELAY: case ConnectionType::BLOCK_RELAY: setConnected.insert(m_netgroupman.GetGroup(pnode->addr)); From fa177d7b6b3ad008d442ff9622c9b30e68d6e388 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 3 Jan 2023 12:47:38 +0100 Subject: [PATCH 32/72] Move ::fPruneMode into BlockManager --- src/init.cpp | 1 - src/node/blockmanager_args.cpp | 2 -- src/node/blockstorage.cpp | 7 +++---- src/node/blockstorage.h | 9 ++++++--- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index d68ba80b79fe0..8a45c38ce3654 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -123,7 +123,6 @@ using node::ShouldPersistMempool; using node::NodeContext; using node::ThreadImport; using node::VerifyLoadedChainstate; -using node::fPruneMode; using node::fReindex; static constexpr bool DEFAULT_PROXYRANDOMIZE{true}; diff --git a/src/node/blockmanager_args.cpp b/src/node/blockmanager_args.cpp index cba44dafb9eed..876d5d2e5713a 100644 --- a/src/node/blockmanager_args.cpp +++ b/src/node/blockmanager_args.cpp @@ -18,12 +18,10 @@ std::optional ApplyArgsManOptions(const ArgsManager& args, BlockM uint64_t nPruneTarget{uint64_t(nPruneArg) * 1024 * 1024}; if (nPruneArg == 1) { // manual pruning: -prune=1 nPruneTarget = std::numeric_limits::max(); - fPruneMode = true; } else if (nPruneTarget) { if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) { return strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024); } - fPruneMode = true; } opts.prune_target = nPruneTarget; diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 5e364942d4935..4d2d5daf0528a 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -28,7 +28,6 @@ namespace node { std::atomic_bool fImporting(false); std::atomic_bool fReindex(false); -bool fPruneMode = false; bool CBlockIndexWorkComparator::operator()(const CBlockIndex* pa, const CBlockIndex* pb) const { @@ -153,7 +152,7 @@ void BlockManager::PruneOneBlockFile(const int fileNumber) void BlockManager::FindFilesToPruneManual(std::set& setFilesToPrune, int nManualPruneHeight, int chain_tip_height) { - assert(fPruneMode && nManualPruneHeight > 0); + assert(IsPruneMode() && nManualPruneHeight > 0); LOCK2(cs_main, cs_LastBlockFile); if (chain_tip_height < 0) { @@ -656,7 +655,7 @@ bool BlockManager::FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigne if (out_of_space) { return AbortNode("Disk space is too low!", _("Disk space is too low!")); } - if (bytes_allocated != 0 && fPruneMode) { + if (bytes_allocated != 0 && IsPruneMode()) { m_check_for_pruning = true; } } @@ -680,7 +679,7 @@ bool BlockManager::FindUndoPos(BlockValidationState& state, int nFile, FlatFileP if (out_of_space) { return AbortNode(state, "Disk space is too low!", _("Disk space is too low!")); } - if (bytes_allocated != 0 && fPruneMode) { + if (bytes_allocated != 0 && IsPruneMode()) { m_check_for_pruning = true; } diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index d76d916a93e3b..78ca727c995d1 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -49,7 +49,6 @@ static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE = CMessageHeader::MESSAG extern std::atomic_bool fImporting; extern std::atomic_bool fReindex; -extern bool fPruneMode; // Because validation code takes pointers to the map's CBlockIndex objects, if // we ever switch to another associative container, we need to either use a @@ -124,6 +123,8 @@ class BlockManager */ bool m_check_for_pruning = false; + const bool m_prune_mode; + /** Dirty block index entries. */ std::set m_dirty_blockindex; @@ -143,7 +144,9 @@ class BlockManager public: using Options = kernel::BlockManagerOpts; - explicit BlockManager(Options opts) : m_opts{std::move(opts)} {}; + explicit BlockManager(Options opts) + : m_prune_mode{opts.prune_target > 0}, + m_opts{std::move(opts)} {}; BlockMap m_block_index GUARDED_BY(cs_main); @@ -187,7 +190,7 @@ class BlockManager FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp); /** Whether running in -prune mode. */ - [[nodiscard]] bool IsPruneMode() const { return fPruneMode; } + [[nodiscard]] bool IsPruneMode() const { return m_prune_mode; } /** Attempt to stay below this number of bytes of block files. */ [[nodiscard]] uint64_t GetPruneTarget() const { return m_opts.prune_target; } From fa442b137764e0b6c0d991ba641e90c3217be1bf Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 3 Jan 2023 13:06:03 +0100 Subject: [PATCH 33/72] Pass fImporting to ImportingNow helper class --- src/node/blockstorage.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 4d2d5daf0528a..46c306fc371c3 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -844,17 +844,20 @@ FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, CCha return blockPos; } -struct CImportingNow { - CImportingNow() +class ImportingNow +{ + std::atomic& m_importing; + +public: + ImportingNow(std::atomic& importing) : m_importing{importing} { - assert(fImporting == false); - fImporting = true; + assert(m_importing == false); + m_importing = true; } - - ~CImportingNow() + ~ImportingNow() { - assert(fImporting == true); - fImporting = false; + assert(m_importing == true); + m_importing = false; } }; @@ -864,7 +867,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector vImportFile ScheduleBatchPriority(); { - CImportingNow imp; + ImportingNow imp{fImporting}; // -reindex if (fReindex) { @@ -930,7 +933,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector vImportFile StartShutdown(); return; } - } // End scope of CImportingNow + } // End scope of ImportingNow chainman.ActiveChainstate().LoadMempool(mempool_path); } } // namespace node From fa9bd7be472f49b15f5f87711094095954322635 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Tue, 3 Jan 2023 13:09:55 +0100 Subject: [PATCH 34/72] Move ::fImporting to BlockManager --- src/node/blockstorage.cpp | 3 +-- src/node/blockstorage.h | 8 +++----- src/node/interfaces.cpp | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 46c306fc371c3..4356fc2b2a6ee 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -26,7 +26,6 @@ #include namespace node { -std::atomic_bool fImporting(false); std::atomic_bool fReindex(false); bool CBlockIndexWorkComparator::operator()(const CBlockIndex* pa, const CBlockIndex* pb) const @@ -867,7 +866,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector vImportFile ScheduleBatchPriority(); { - ImportingNow imp{fImporting}; + ImportingNow imp{chainman.m_blockman.m_importing}; // -reindex if (fReindex) { diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 78ca727c995d1..de9b1c0bb579f 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -47,7 +47,6 @@ static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB /** Size of header written by WriteBlockToDisk before a serialized CBlock */ static constexpr size_t BLOCK_SERIALIZATION_HEADER_SIZE = CMessageHeader::MESSAGE_START_SIZE + sizeof(unsigned int); -extern std::atomic_bool fImporting; extern std::atomic_bool fReindex; // Because validation code takes pointers to the map's CBlockIndex objects, if @@ -148,6 +147,8 @@ class BlockManager : m_prune_mode{opts.prune_target > 0}, m_opts{std::move(opts)} {}; + std::atomic m_importing{false}; + BlockMap m_block_index GUARDED_BY(cs_main); std::vector GetAllBlockIndices() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); @@ -195,10 +196,7 @@ class BlockManager /** Attempt to stay below this number of bytes of block files. */ [[nodiscard]] uint64_t GetPruneTarget() const { return m_opts.prune_target; } - [[nodiscard]] bool LoadingBlocks() const - { - return fImporting || fReindex; - } + [[nodiscard]] bool LoadingBlocks() const { return m_importing || fReindex; } /** Calculate the amount of disk space the block & undo files currently use */ uint64_t CalculateCurrentUsage(); diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 54aa21e984409..b397661df40c5 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -295,7 +295,7 @@ class NodeImpl : public Node bool isInitialBlockDownload() override { return chainman().ActiveChainstate().IsInitialBlockDownload(); } - bool isLoadingBlocks() override { return node::fReindex || node::fImporting; } + bool isLoadingBlocks() override { return chainman().m_blockman.LoadingBlocks(); } void setNetworkActive(bool active) override { if (m_context->connman) { From fadf8b818226dc60adf88e927160f9c9680473a4 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Wed, 15 Mar 2023 16:10:24 +0100 Subject: [PATCH 35/72] refactor: Add and use PRUNE_TARGET_MANUAL constexpr --- src/node/blockmanager_args.cpp | 2 +- src/node/blockstorage.h | 1 + src/node/chainstate.cpp | 2 +- src/rpc/blockchain.cpp | 4 +--- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/node/blockmanager_args.cpp b/src/node/blockmanager_args.cpp index 876d5d2e5713a..5fb5c8beed6b5 100644 --- a/src/node/blockmanager_args.cpp +++ b/src/node/blockmanager_args.cpp @@ -17,7 +17,7 @@ std::optional ApplyArgsManOptions(const ArgsManager& args, BlockM } uint64_t nPruneTarget{uint64_t(nPruneArg) * 1024 * 1024}; if (nPruneArg == 1) { // manual pruning: -prune=1 - nPruneTarget = std::numeric_limits::max(); + nPruneTarget = BlockManager::PRUNE_TARGET_MANUAL; } else if (nPruneTarget) { if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) { return strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024); diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index de9b1c0bb579f..5ba0045b8b3e5 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -195,6 +195,7 @@ class BlockManager /** Attempt to stay below this number of bytes of block files. */ [[nodiscard]] uint64_t GetPruneTarget() const { return m_opts.prune_target; } + static constexpr auto PRUNE_TARGET_MANUAL{std::numeric_limits::max()}; [[nodiscard]] bool LoadingBlocks() const { return m_importing || fReindex; } diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index 125d6de5a5493..cfd347259211b 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -169,7 +169,7 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize if (chainman.MinimumChainWork() < UintToArith256(chainman.GetConsensus().nMinimumChainWork)) { LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainman.GetConsensus().nMinimumChainWork.GetHex()); } - if (chainman.m_blockman.GetPruneTarget() == std::numeric_limits::max()) { + if (chainman.m_blockman.GetPruneTarget() == BlockManager::PRUNE_TARGET_MANUAL) { LogPrintf("Block pruning enabled. Use RPC call pruneblockchain(height) to manually prune block and undo files.\n"); } else if (chainman.m_blockman.GetPruneTarget()) { LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", chainman.m_blockman.GetPruneTarget() / 1024 / 1024); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 5afa460075803..1a9b265fbeab2 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1249,7 +1249,6 @@ RPCHelpMan getblockchaininfo() }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - const ArgsManager& args{EnsureAnyArgsman(request.context)}; ChainstateManager& chainman = EnsureAnyChainman(request.context); LOCK(cs_main); Chainstate& active_chainstate = chainman.ActiveChainstate(); @@ -1272,8 +1271,7 @@ RPCHelpMan getblockchaininfo() if (chainman.m_blockman.IsPruneMode()) { obj.pushKV("pruneheight", chainman.m_blockman.GetFirstStoredBlock(tip)->nHeight); - // if 0, execution bypasses the whole if block. - bool automatic_pruning{args.GetIntArg("-prune", 0) != 1}; + const bool automatic_pruning{chainman.m_blockman.GetPruneTarget() != BlockManager::PRUNE_TARGET_MANUAL}; obj.pushKV("automatic_pruning", automatic_pruning); if (automatic_pruning) { obj.pushKV("prune_target_size", chainman.m_blockman.GetPruneTarget()); From 76cd4e7c96242398172989609f1b9a8843c404b4 Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Wed, 9 Mar 2022 00:13:36 -0500 Subject: [PATCH 36/72] Decouple SigNetChainParams from ArgsManager SigNet chain params can now be initialized by configuring a SigNetOptions struct, or with ArgsManager. This offers an interface for creating SigNetChainParams without a gArgs object. --- src/chainparams.cpp | 39 ++++++++++++++++++++++++++------------- src/chainparams.h | 9 +++++++++ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 19b5c332f4c26..12b5a788b463e 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -277,11 +277,12 @@ class CTestNetParams : public CChainParams { */ class SigNetParams : public CChainParams { public: - explicit SigNetParams(const ArgsManager& args) { + explicit SigNetParams(const SigNetOptions& options) + { std::vector bin; vSeeds.clear(); - if (!args.IsArgSet("-signetchallenge")) { + if (!options.challenge) { bin = ParseHex("512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae"); vSeeds.emplace_back("seed.signet.bitcoin.sprovoost.nl."); @@ -300,12 +301,7 @@ class SigNetParams : public CChainParams { .dTxRate = 0.02336701143027275, }; } else { - const auto signet_challenge = args.GetArgs("-signetchallenge"); - if (signet_challenge.size() != 1) { - throw std::runtime_error(strprintf("%s: -signetchallenge cannot be multiple values.", __func__)); - } - bin = ParseHex(signet_challenge[0]); - + bin = *options.challenge; consensus.nMinimumChainWork = uint256{}; consensus.defaultAssumeValid = uint256{}; m_assumed_blockchain_size = 0; @@ -315,11 +311,11 @@ class SigNetParams : public CChainParams { 0, 0, }; - LogPrintf("Signet with challenge %s\n", signet_challenge[0]); + LogPrintf("Signet with challenge %s\n", HexStr(bin)); } - if (args.IsArgSet("-signetseednode")) { - vSeeds = args.GetArgs("-signetseednode"); + if (options.seeds) { + vSeeds = *options.seeds; } strNetworkID = CBaseChainParams::SIGNET; @@ -382,11 +378,26 @@ class SigNetParams : public CChainParams { } }; +void ReadSigNetArgs(const ArgsManager& args, CChainParams::SigNetOptions& options) +{ + if (args.IsArgSet("-signetseednode")) { + options.seeds.emplace(args.GetArgs("-signetseednode")); + } + if (args.IsArgSet("-signetchallenge")) { + const auto signet_challenge = args.GetArgs("-signetchallenge"); + if (signet_challenge.size() != 1) { + throw std::runtime_error(strprintf("%s: -signetchallenge cannot be multiple values.", __func__)); + } + options.challenge.emplace(ParseHex(signet_challenge[0])); + } +} + /** * Regression test: intended for private networks only. Has minimal difficulty to ensure that * blocks can be found instantly. */ -class CRegTestParams : public CChainParams { +class CRegTestParams : public CChainParams +{ public: explicit CRegTestParams(const ArgsManager& args) { strNetworkID = CBaseChainParams::REGTEST; @@ -570,7 +581,9 @@ std::unique_ptr CreateChainParams(const ArgsManager& args, c } else if (chain == CBaseChainParams::TESTNET) { return std::unique_ptr(new CTestNetParams()); } else if (chain == CBaseChainParams::SIGNET) { - return std::unique_ptr(new SigNetParams(args)); + auto opts = CChainParams::SigNetOptions{}; + ReadSigNetArgs(args, opts); + return std::make_unique(opts); } else if (chain == CBaseChainParams::REGTEST) { return std::unique_ptr(new CRegTestParams(args)); } diff --git a/src/chainparams.h b/src/chainparams.h index 66592ffddad06..2f6f3f0907e33 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -122,6 +122,15 @@ class CChainParams const MapAssumeutxo& Assumeutxo() const { return m_assumeutxo_data; } const ChainTxData& TxData() const { return chainTxData; } + + /** + * SigNetOptions holds configurations for creating a signet CChainParams. + */ + struct SigNetOptions { + std::optional> challenge{}; + std::optional> seeds{}; + }; + protected: CChainParams() {} From 84b85786f0f5cb23cc257a4464ae345e1d372313 Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Wed, 9 Mar 2022 16:11:39 -0500 Subject: [PATCH 37/72] Decouple RegTestChainParams from ArgsManager RegTest chain params can now be initialized by configuring a RegTestOptions struct, or with ArgsManager. This offers an interface for creating RegTestChainParams without a gArgs object. --- src/chainparams.cpp | 78 ++++++++++++++++++++++++++---------------- src/chainparams.h | 20 +++++++++++ src/deploymentinfo.cpp | 18 ++++++++++ src/deploymentinfo.h | 3 ++ 4 files changed, 89 insertions(+), 30 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 12b5a788b463e..e4a5a489a2f5a 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -399,7 +399,8 @@ void ReadSigNetArgs(const ArgsManager& args, CChainParams::SigNetOptions& option class CRegTestParams : public CChainParams { public: - explicit CRegTestParams(const ArgsManager& args) { + explicit CRegTestParams(const RegTestOptions& opts) + { strNetworkID = CBaseChainParams::REGTEST; consensus.signet_blocks = false; consensus.signet_challenge.clear(); @@ -437,11 +438,33 @@ class CRegTestParams : public CChainParams pchMessageStart[2] = 0xb5; pchMessageStart[3] = 0xda; nDefaultPort = 18444; - nPruneAfterHeight = args.GetBoolArg("-fastprune", false) ? 100 : 1000; + nPruneAfterHeight = opts.fastprune ? 100 : 1000; m_assumed_blockchain_size = 0; m_assumed_chain_state_size = 0; - UpdateActivationParametersFromArgs(args); + for (const auto& [dep, height] : opts.activation_heights) { + switch (dep) { + case Consensus::BuriedDeployment::DEPLOYMENT_SEGWIT: + consensus.SegwitHeight = int{height}; + break; + case Consensus::BuriedDeployment::DEPLOYMENT_HEIGHTINCB: + consensus.BIP34Height = int{height}; + break; + case Consensus::BuriedDeployment::DEPLOYMENT_DERSIG: + consensus.BIP66Height = int{height}; + break; + case Consensus::BuriedDeployment::DEPLOYMENT_CLTV: + consensus.BIP65Height = int{height}; + break; + case Consensus::BuriedDeployment::DEPLOYMENT_CSV: + consensus.CSVHeight = int{height}; + break; + } + } + + for (const auto& [deployment_pos, version_bits_params] : opts.version_bits_parameters) { + UpdateVersionBitsParameters(deployment_pos, version_bits_params.start_time, version_bits_params.timeout, version_bits_params.min_activation_height); + } genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 50 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); @@ -498,41 +521,31 @@ class CRegTestParams : public CChainParams consensus.vDeployments[d].nTimeout = nTimeout; consensus.vDeployments[d].min_activation_height = min_activation_height; } - void UpdateActivationParametersFromArgs(const ArgsManager& args); }; -static void MaybeUpdateHeights(const ArgsManager& args, Consensus::Params& consensus) +void ReadRegTestArgs(const ArgsManager& args, CChainParams::RegTestOptions& options) { + if (auto value = args.GetBoolArg("-fastprune")) options.fastprune = *value; + for (const std::string& arg : args.GetArgs("-testactivationheight")) { const auto found{arg.find('@')}; if (found == std::string::npos) { throw std::runtime_error(strprintf("Invalid format (%s) for -testactivationheight=name@height.", arg)); } - const auto name{arg.substr(0, found)}; + const auto value{arg.substr(found + 1)}; int32_t height; if (!ParseInt32(value, &height) || height < 0 || height >= std::numeric_limits::max()) { throw std::runtime_error(strprintf("Invalid height value (%s) for -testactivationheight=name@height.", arg)); } - if (name == "segwit") { - consensus.SegwitHeight = int{height}; - } else if (name == "bip34") { - consensus.BIP34Height = int{height}; - } else if (name == "dersig") { - consensus.BIP66Height = int{height}; - } else if (name == "cltv") { - consensus.BIP65Height = int{height}; - } else if (name == "csv") { - consensus.CSVHeight = int{height}; + + const auto deployment_name{arg.substr(0, found)}; + if (const auto buried_deployment = GetBuriedDeployment(deployment_name)) { + options.activation_heights[*buried_deployment] = height; } else { throw std::runtime_error(strprintf("Invalid name (%s) for -testactivationheight=name@height.", arg)); } } -} - -void CRegTestParams::UpdateActivationParametersFromArgs(const ArgsManager& args) -{ - MaybeUpdateHeights(args, consensus); if (!args.IsArgSet("-vbparams")) return; @@ -541,23 +554,26 @@ void CRegTestParams::UpdateActivationParametersFromArgs(const ArgsManager& args) if (vDeploymentParams.size() < 3 || 4 < vDeploymentParams.size()) { throw std::runtime_error("Version bits parameters malformed, expecting deployment:start:end[:min_activation_height]"); } - int64_t nStartTime, nTimeout; - int min_activation_height = 0; - if (!ParseInt64(vDeploymentParams[1], &nStartTime)) { + CChainParams::VersionBitsParameters vbparams{}; + if (!ParseInt64(vDeploymentParams[1], &vbparams.start_time)) { throw std::runtime_error(strprintf("Invalid nStartTime (%s)", vDeploymentParams[1])); } - if (!ParseInt64(vDeploymentParams[2], &nTimeout)) { + if (!ParseInt64(vDeploymentParams[2], &vbparams.timeout)) { throw std::runtime_error(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2])); } - if (vDeploymentParams.size() >= 4 && !ParseInt32(vDeploymentParams[3], &min_activation_height)) { - throw std::runtime_error(strprintf("Invalid min_activation_height (%s)", vDeploymentParams[3])); + if (vDeploymentParams.size() >= 4) { + if (!ParseInt32(vDeploymentParams[3], &vbparams.min_activation_height)) { + throw std::runtime_error(strprintf("Invalid min_activation_height (%s)", vDeploymentParams[3])); + } + } else { + vbparams.min_activation_height = 0; } bool found = false; for (int j=0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { if (vDeploymentParams[0] == VersionBitsDeploymentInfo[j].name) { - UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout, min_activation_height); + options.version_bits_parameters[Consensus::DeploymentPos(j)] = vbparams; found = true; - LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld, min_activation_height=%d\n", vDeploymentParams[0], nStartTime, nTimeout, min_activation_height); + LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld, min_activation_height=%d\n", vDeploymentParams[0], vbparams.start_time, vbparams.timeout, vbparams.min_activation_height); break; } } @@ -585,7 +601,9 @@ std::unique_ptr CreateChainParams(const ArgsManager& args, c ReadSigNetArgs(args, opts); return std::make_unique(opts); } else if (chain == CBaseChainParams::REGTEST) { - return std::unique_ptr(new CRegTestParams(args)); + auto opts = CChainParams::RegTestOptions{}; + ReadRegTestArgs(args, opts); + return std::make_unique(opts); } throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain)); } diff --git a/src/chainparams.h b/src/chainparams.h index 2f6f3f0907e33..f2e2eb8bc0a28 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -13,8 +13,10 @@ #include #include +#include #include #include +#include #include typedef std::map MapCheckpoints; @@ -131,6 +133,24 @@ class CChainParams std::optional> seeds{}; }; + /** + * VersionBitsParameters holds activation parameters + */ + struct VersionBitsParameters { + int64_t start_time; + int64_t timeout; + int min_activation_height; + }; + + /** + * RegTestOptions holds configurations for creating a regtest CChainParams. + */ + struct RegTestOptions { + std::unordered_map version_bits_parameters{}; + std::unordered_map activation_heights{}; + bool fastprune{false}; + }; + protected: CChainParams() {} diff --git a/src/deploymentinfo.cpp b/src/deploymentinfo.cpp index 246932e56da6a..185a7dcb54ce7 100644 --- a/src/deploymentinfo.cpp +++ b/src/deploymentinfo.cpp @@ -6,6 +6,8 @@ #include +#include + const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = { { /*.name =*/ "testdummy", @@ -34,3 +36,19 @@ std::string DeploymentName(Consensus::BuriedDeployment dep) } // no default case, so the compiler can warn about missing cases return ""; } + +std::optional GetBuriedDeployment(const std::string_view name) +{ + if (name == "segwit") { + return Consensus::BuriedDeployment::DEPLOYMENT_SEGWIT; + } else if (name == "bip34") { + return Consensus::BuriedDeployment::DEPLOYMENT_HEIGHTINCB; + } else if (name == "dersig") { + return Consensus::BuriedDeployment::DEPLOYMENT_DERSIG; + } else if (name == "cltv") { + return Consensus::BuriedDeployment::DEPLOYMENT_CLTV; + } else if (name == "csv") { + return Consensus::BuriedDeployment::DEPLOYMENT_CSV; + } + return std::nullopt; +} diff --git a/src/deploymentinfo.h b/src/deploymentinfo.h index 8b909dedb462b..72ba297ea0b55 100644 --- a/src/deploymentinfo.h +++ b/src/deploymentinfo.h @@ -7,6 +7,7 @@ #include +#include #include struct VBDeploymentInfo { @@ -26,4 +27,6 @@ inline std::string DeploymentName(Consensus::DeploymentPos pos) return VersionBitsDeploymentInfo[pos].name; } +std::optional GetBuriedDeployment(const std::string_view deployment_name); + #endif // BITCOIN_DEPLOYMENTINFO_H From d938098398814f37fed9b018b44716179cfa4b03 Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Wed, 9 Mar 2022 16:17:46 -0500 Subject: [PATCH 38/72] Remove UpdateVersionBitsParameters Moves setting struct member fields from a function to its call site. This improves readability by surfacing the code. --- src/chainparams.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index e4a5a489a2f5a..2445c379ebedf 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -463,7 +463,9 @@ class CRegTestParams : public CChainParams } for (const auto& [deployment_pos, version_bits_params] : opts.version_bits_parameters) { - UpdateVersionBitsParameters(deployment_pos, version_bits_params.start_time, version_bits_params.timeout, version_bits_params.min_activation_height); + consensus.vDeployments[deployment_pos].nStartTime = version_bits_params.start_time; + consensus.vDeployments[deployment_pos].nTimeout = version_bits_params.timeout; + consensus.vDeployments[deployment_pos].min_activation_height = version_bits_params.min_activation_height; } genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 50 * COIN); @@ -511,16 +513,6 @@ class CRegTestParams : public CChainParams bech32_hrp = "bcrt"; } - - /** - * Allows modifying the Version Bits regtest parameters. - */ - void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int min_activation_height) - { - consensus.vDeployments[d].nStartTime = nStartTime; - consensus.vDeployments[d].nTimeout = nTimeout; - consensus.vDeployments[d].min_activation_height = min_activation_height; - } }; void ReadRegTestArgs(const ArgsManager& args, CChainParams::RegTestOptions& options) From edabbc78a3bc272b2b802e1dbab73d6ed8e31e96 Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Thu, 10 Mar 2022 17:21:05 -0500 Subject: [PATCH 39/72] Add factory functions for Main/Test/Sig/Reg chainparams This normalizes the behavior of initializing Main/Test/Sig/Reg chainparams with RegTest/SigNet chainparams. These factory functions can also easily be used from a context without an instantiated ArgsManager, e.g. from libbitcoin kernel code, unlike the existing CreateChainParams method. --- src/chainparams.cpp | 28 ++++++++++++++++++++++++---- src/chainparams.h | 5 +++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 2445c379ebedf..7130141c1ce11 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -582,20 +582,40 @@ const CChainParams &Params() { return *globalChainParams; } +std::unique_ptr CChainParams::SigNet(const SigNetOptions& options) +{ + return std::make_unique(options); +} + +std::unique_ptr CChainParams::RegTest(const RegTestOptions& options) +{ + return std::make_unique(options); +} + +std::unique_ptr CChainParams::Main() +{ + return std::make_unique(); +} + +std::unique_ptr CChainParams::TestNet() +{ + return std::make_unique(); +} + std::unique_ptr CreateChainParams(const ArgsManager& args, const std::string& chain) { if (chain == CBaseChainParams::MAIN) { - return std::unique_ptr(new CMainParams()); + return CChainParams::Main(); } else if (chain == CBaseChainParams::TESTNET) { - return std::unique_ptr(new CTestNetParams()); + return CChainParams::TestNet(); } else if (chain == CBaseChainParams::SIGNET) { auto opts = CChainParams::SigNetOptions{}; ReadSigNetArgs(args, opts); - return std::make_unique(opts); + return CChainParams::SigNet(opts); } else if (chain == CBaseChainParams::REGTEST) { auto opts = CChainParams::RegTestOptions{}; ReadRegTestArgs(args, opts); - return std::make_unique(opts); + return CChainParams::RegTest(opts); } throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain)); } diff --git a/src/chainparams.h b/src/chainparams.h index f2e2eb8bc0a28..30488510d7166 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -151,6 +151,11 @@ class CChainParams bool fastprune{false}; }; + static std::unique_ptr RegTest(const RegTestOptions& options); + static std::unique_ptr SigNet(const SigNetOptions& options); + static std::unique_ptr Main(); + static std::unique_ptr TestNet(); + protected: CChainParams() {} From 382b692a503355df7347efd9c128aff465b5583e Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Thu, 10 Mar 2022 22:13:58 -0500 Subject: [PATCH 40/72] Split non/kernel chainparams Moves chainparams code not using the ArgsManager to the kernel. Subsequently use the kernel chainparams header now where possible in order to further decouple chainparams call sites from gArgs. --- src/Makefile.am | 3 + src/bitcoin-chainstate.cpp | 5 +- src/chainparams.cpp | 506 ----------------------------------- src/chainparams.h | 163 +----------- src/kernel/chainparams.cpp | 532 +++++++++++++++++++++++++++++++++++++ src/kernel/chainparams.h | 187 +++++++++++++ src/node/blockstorage.cpp | 2 +- src/node/mempool_args.cpp | 2 +- src/validation.cpp | 1 + src/validation.h | 4 +- 10 files changed, 732 insertions(+), 673 deletions(-) create mode 100644 src/kernel/chainparams.cpp create mode 100644 src/kernel/chainparams.h diff --git a/src/Makefile.am b/src/Makefile.am index a0c1670287afc..00db655e02213 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -175,6 +175,7 @@ BITCOIN_CORE_H = \ interfaces/node.h \ interfaces/wallet.h \ kernel/chain.h \ + kernel/chainparams.h \ kernel/chainstatemanager_opts.h \ kernel/checks.h \ kernel/coinstats.h \ @@ -651,6 +652,7 @@ libbitcoin_common_a_SOURCES = \ deploymentinfo.cpp \ external_signer.cpp \ init/common.cpp \ + kernel/chainparams.cpp \ key.cpp \ key_io.cpp \ merkleblock.cpp \ @@ -907,6 +909,7 @@ libbitcoinkernel_la_SOURCES = \ hash.cpp \ kernel/chain.cpp \ kernel/checks.cpp \ + kernel/chainparams.cpp \ kernel/coinstats.cpp \ kernel/context.cpp \ kernel/cs_main.cpp \ diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp index 423fa79c6fe49..12472356609fb 100644 --- a/src/bitcoin-chainstate.cpp +++ b/src/bitcoin-chainstate.cpp @@ -11,6 +11,7 @@ // // It is part of the libbitcoinkernel project. +#include #include #include #include @@ -52,7 +53,7 @@ int main(int argc, char* argv[]) // SETUP: Misc Globals SelectParams(CBaseChainParams::MAIN); - const CChainParams& chainparams = Params(); + auto chainparams = CChainParams::Main(); kernel::Context kernel_context{}; // We can't use a goto here, but we can use an assert since none of the @@ -81,7 +82,7 @@ int main(int argc, char* argv[]) // SETUP: Chainstate const ChainstateManager::Options chainman_opts{ - .chainparams = chainparams, + .chainparams = *chainparams, .datadir = gArgs.GetDataDirNet(), .adjusted_time_callback = NodeClock::now, }; diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 7130141c1ce11..6f48ee41b3c12 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -15,369 +15,6 @@ #include -static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) -{ - CMutableTransaction txNew; - txNew.nVersion = 1; - txNew.vin.resize(1); - txNew.vout.resize(1); - txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << std::vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); - txNew.vout[0].nValue = genesisReward; - txNew.vout[0].scriptPubKey = genesisOutputScript; - - CBlock genesis; - genesis.nTime = nTime; - genesis.nBits = nBits; - genesis.nNonce = nNonce; - genesis.nVersion = nVersion; - genesis.vtx.push_back(MakeTransactionRef(std::move(txNew))); - genesis.hashPrevBlock.SetNull(); - genesis.hashMerkleRoot = BlockMerkleRoot(genesis); - return genesis; -} - -/** - * Build the genesis block. Note that the output of its generation - * transaction cannot be spent since it did not originally exist in the - * database. - * - * CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1) - * CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0) - * CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73) - * CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B) - * vMerkleTree: 4a5e1e - */ -static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) -{ - const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; - const CScript genesisOutputScript = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; - return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward); -} - -/** - * Main network on which people trade goods and services. - */ -class CMainParams : public CChainParams { -public: - CMainParams() { - strNetworkID = CBaseChainParams::MAIN; - consensus.signet_blocks = false; - consensus.signet_challenge.clear(); - consensus.nSubsidyHalvingInterval = 210000; - consensus.script_flag_exceptions.emplace( // BIP16 exception - uint256S("0x00000000000002dc756eebf4f49723ed8d30cc28a5f108eb94b1ba88ac4f9c22"), SCRIPT_VERIFY_NONE); - consensus.script_flag_exceptions.emplace( // Taproot exception - uint256S("0x0000000000000000000f14c35b2d841e986ab5441de8c585d5ffe55ea1e395ad"), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS); - consensus.BIP34Height = 227931; - consensus.BIP34Hash = uint256S("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8"); - consensus.BIP65Height = 388381; // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0 - consensus.BIP66Height = 363725; // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931 - consensus.CSVHeight = 419328; // 000000000000000004a1b34462cb8aeebd5799177f7a29cf28f2d1961716b5b5 - consensus.SegwitHeight = 481824; // 0000000000000000001c8018d9cb3b742ef25114f27563e3fc4a1902167f9893 - consensus.MinBIP9WarningHeight = 483840; // segwit activation height + miner confirmation window - consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks - consensus.nPowTargetSpacing = 10 * 60; - consensus.fPowAllowMinDifficultyBlocks = false; - consensus.fPowNoRetargeting = false; - consensus.nRuleChangeActivationThreshold = 1815; // 90% of 2016 - consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay - - // Deployment of Taproot (BIPs 340-342) - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2; - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = 1619222400; // April 24th, 2021 - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1628640000; // August 11th, 2021 - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 709632; // Approximately November 12th, 2021 - - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000003404ba0801921119f903495e"); - consensus.defaultAssumeValid = uint256S("0x00000000000000000009c97098b5295f7e5f183ac811fb5d1534040adb93cabd"); // 751565 - - /** - * The message start string is designed to be unlikely to occur in normal data. - * The characters are rarely used upper ASCII, not valid as UTF-8, and produce - * a large 32-bit integer with any alignment. - */ - pchMessageStart[0] = 0xf9; - pchMessageStart[1] = 0xbe; - pchMessageStart[2] = 0xb4; - pchMessageStart[3] = 0xd9; - nDefaultPort = 8333; - nPruneAfterHeight = 100000; - m_assumed_blockchain_size = 496; - m_assumed_chain_state_size = 6; - - genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN); - consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")); - assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); - - // Note that of those which support the service bits prefix, most only support a subset of - // possible options. - // This is fine at runtime as we'll fall back to using them as an addrfetch if they don't support the - // service bits we want, but we should get them updated to support all service bits wanted by any - // release ASAP to avoid it where possible. - vSeeds.emplace_back("seed.bitcoin.sipa.be."); // Pieter Wuille, only supports x1, x5, x9, and xd - vSeeds.emplace_back("dnsseed.bluematt.me."); // Matt Corallo, only supports x9 - vSeeds.emplace_back("dnsseed.bitcoin.dashjr.org."); // Luke Dashjr - vSeeds.emplace_back("seed.bitcoinstats.com."); // Christian Decker, supports x1 - xf - vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch."); // Jonas Schnelli, only supports x1, x5, x9, and xd - vSeeds.emplace_back("seed.btc.petertodd.org."); // Peter Todd, only supports x1, x5, x9, and xd - vSeeds.emplace_back("seed.bitcoin.sprovoost.nl."); // Sjors Provoost - vSeeds.emplace_back("dnsseed.emzy.de."); // Stephan Oeste - vSeeds.emplace_back("seed.bitcoin.wiz.biz."); // Jason Maurice - - base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,0); - base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,5); - base58Prefixes[SECRET_KEY] = std::vector(1,128); - base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E}; - base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4}; - - bech32_hrp = "bc"; - - vFixedSeeds = std::vector(std::begin(chainparams_seed_main), std::end(chainparams_seed_main)); - - fDefaultConsistencyChecks = false; - fRequireStandard = true; - m_is_test_chain = false; - m_is_mockable_chain = false; - - checkpointData = { - { - { 11111, uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")}, - { 33333, uint256S("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")}, - { 74000, uint256S("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")}, - {105000, uint256S("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")}, - {134444, uint256S("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")}, - {168000, uint256S("0x000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763")}, - {193000, uint256S("0x000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317")}, - {210000, uint256S("0x000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e")}, - {216116, uint256S("0x00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")}, - {225430, uint256S("0x00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932")}, - {250000, uint256S("0x000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214")}, - {279000, uint256S("0x0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40")}, - {295000, uint256S("0x00000000000000004d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983")}, - } - }; - - m_assumeutxo_data = MapAssumeutxo{ - // TODO to be specified in a future patch. - }; - - chainTxData = ChainTxData{ - // Data from RPC: getchaintxstats 4096 00000000000000000009c97098b5295f7e5f183ac811fb5d1534040adb93cabd - .nTime = 1661697692, - .nTxCount = 760120522, - .dTxRate = 2.925802860942233, - }; - } -}; - -/** - * Testnet (v3): public test network which is reset from time to time. - */ -class CTestNetParams : public CChainParams { -public: - CTestNetParams() { - strNetworkID = CBaseChainParams::TESTNET; - consensus.signet_blocks = false; - consensus.signet_challenge.clear(); - consensus.nSubsidyHalvingInterval = 210000; - consensus.script_flag_exceptions.emplace( // BIP16 exception - uint256S("0x00000000dd30457c001f4095d208cc1296b0eed002427aa599874af7a432b105"), SCRIPT_VERIFY_NONE); - consensus.BIP34Height = 21111; - consensus.BIP34Hash = uint256S("0x0000000023b3a96d3484e5abb3755c413e7d41500f8e2a5c3f0dd01299cd8ef8"); - consensus.BIP65Height = 581885; // 00000000007f6655f22f98e72ed80d8b06dc761d5da09df0fa1dc4be4f861eb6 - consensus.BIP66Height = 330776; // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 - consensus.CSVHeight = 770112; // 00000000025e930139bac5c6c31a403776da130831ab85be56578f3fa75369bb - consensus.SegwitHeight = 834624; // 00000000002b980fcd729daaa248fd9316a5200e9b367f4ff2c42453e84201ca - consensus.MinBIP9WarningHeight = 836640; // segwit activation height + miner confirmation window - consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks - consensus.nPowTargetSpacing = 10 * 60; - consensus.fPowAllowMinDifficultyBlocks = true; - consensus.fPowNoRetargeting = false; - consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains - consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay - - // Deployment of Taproot (BIPs 340-342) - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2; - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = 1619222400; // April 24th, 2021 - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1628640000; // August 11th, 2021 - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay - - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000076f6e7cbd0beade5d20"); - consensus.defaultAssumeValid = uint256S("0x0000000000000004877fa2d36316398528de4f347df2f8a96f76613a298ce060"); // 2344474 - - pchMessageStart[0] = 0x0b; - pchMessageStart[1] = 0x11; - pchMessageStart[2] = 0x09; - pchMessageStart[3] = 0x07; - nDefaultPort = 18333; - nPruneAfterHeight = 1000; - m_assumed_blockchain_size = 42; - m_assumed_chain_state_size = 2; - - genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN); - consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943")); - assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); - - vFixedSeeds.clear(); - vSeeds.clear(); - // nodes with support for servicebits filtering should be at the top - vSeeds.emplace_back("testnet-seed.bitcoin.jonasschnelli.ch."); - vSeeds.emplace_back("seed.tbtc.petertodd.org."); - vSeeds.emplace_back("seed.testnet.bitcoin.sprovoost.nl."); - vSeeds.emplace_back("testnet-seed.bluematt.me."); // Just a static list of stable node(s), only supports x9 - - base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,111); - base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,196); - base58Prefixes[SECRET_KEY] = std::vector(1,239); - base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; - base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; - - bech32_hrp = "tb"; - - vFixedSeeds = std::vector(std::begin(chainparams_seed_test), std::end(chainparams_seed_test)); - - fDefaultConsistencyChecks = false; - fRequireStandard = false; - m_is_test_chain = true; - m_is_mockable_chain = false; - - checkpointData = { - { - {546, uint256S("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70")}, - } - }; - - m_assumeutxo_data = MapAssumeutxo{ - // TODO to be specified in a future patch. - }; - - chainTxData = ChainTxData{ - // Data from RPC: getchaintxstats 4096 0000000000000004877fa2d36316398528de4f347df2f8a96f76613a298ce060 - .nTime = 1661705221, - .nTxCount = 63531852, - .dTxRate = 0.1079119341520164, - }; - } -}; - -/** - * Signet: test network with an additional consensus parameter (see BIP325). - */ -class SigNetParams : public CChainParams { -public: - explicit SigNetParams(const SigNetOptions& options) - { - std::vector bin; - vSeeds.clear(); - - if (!options.challenge) { - bin = ParseHex("512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae"); - vSeeds.emplace_back("seed.signet.bitcoin.sprovoost.nl."); - - // Hardcoded nodes can be removed once there are more DNS seeds - vSeeds.emplace_back("178.128.221.177"); - vSeeds.emplace_back("v7ajjeirttkbnt32wpy3c6w3emwnfr3fkla7hpxcfokr3ysd3kqtzmqd.onion:38333"); - - consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000001291fc22898"); - consensus.defaultAssumeValid = uint256S("0x000000d1a0e224fa4679d2fb2187ba55431c284fa1b74cbc8cfda866fd4d2c09"); // 105495 - m_assumed_blockchain_size = 1; - m_assumed_chain_state_size = 0; - chainTxData = ChainTxData{ - // Data from RPC: getchaintxstats 4096 000000d1a0e224fa4679d2fb2187ba55431c284fa1b74cbc8cfda866fd4d2c09 - .nTime = 1661702566, - .nTxCount = 1903567, - .dTxRate = 0.02336701143027275, - }; - } else { - bin = *options.challenge; - consensus.nMinimumChainWork = uint256{}; - consensus.defaultAssumeValid = uint256{}; - m_assumed_blockchain_size = 0; - m_assumed_chain_state_size = 0; - chainTxData = ChainTxData{ - 0, - 0, - 0, - }; - LogPrintf("Signet with challenge %s\n", HexStr(bin)); - } - - if (options.seeds) { - vSeeds = *options.seeds; - } - - strNetworkID = CBaseChainParams::SIGNET; - consensus.signet_blocks = true; - consensus.signet_challenge.assign(bin.begin(), bin.end()); - consensus.nSubsidyHalvingInterval = 210000; - consensus.BIP34Height = 1; - consensus.BIP34Hash = uint256{}; - consensus.BIP65Height = 1; - consensus.BIP66Height = 1; - consensus.CSVHeight = 1; - consensus.SegwitHeight = 1; - consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks - consensus.nPowTargetSpacing = 10 * 60; - consensus.fPowAllowMinDifficultyBlocks = false; - consensus.fPowNoRetargeting = false; - consensus.nRuleChangeActivationThreshold = 1815; // 90% of 2016 - consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing - consensus.MinBIP9WarningHeight = 0; - consensus.powLimit = uint256S("00000377ae000000000000000000000000000000000000000000000000000000"); - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = Consensus::BIP9Deployment::NEVER_ACTIVE; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay - - // Activation of Taproot (BIPs 340-342) - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2; - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE; - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay - - // message start is defined as the first 4 bytes of the sha256d of the block script - HashWriter h{}; - h << consensus.signet_challenge; - uint256 hash = h.GetHash(); - memcpy(pchMessageStart, hash.begin(), 4); - - nDefaultPort = 38333; - nPruneAfterHeight = 1000; - - genesis = CreateGenesisBlock(1598918400, 52613770, 0x1e0377ae, 1, 50 * COIN); - consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6")); - assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); - - vFixedSeeds.clear(); - - base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,111); - base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,196); - base58Prefixes[SECRET_KEY] = std::vector(1,239); - base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; - base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; - - bech32_hrp = "tb"; - - fDefaultConsistencyChecks = false; - fRequireStandard = true; - m_is_test_chain = true; - m_is_mockable_chain = false; - } -}; - void ReadSigNetArgs(const ArgsManager& args, CChainParams::SigNetOptions& options) { if (args.IsArgSet("-signetseednode")) { @@ -392,129 +29,6 @@ void ReadSigNetArgs(const ArgsManager& args, CChainParams::SigNetOptions& option } } -/** - * Regression test: intended for private networks only. Has minimal difficulty to ensure that - * blocks can be found instantly. - */ -class CRegTestParams : public CChainParams -{ -public: - explicit CRegTestParams(const RegTestOptions& opts) - { - strNetworkID = CBaseChainParams::REGTEST; - consensus.signet_blocks = false; - consensus.signet_challenge.clear(); - consensus.nSubsidyHalvingInterval = 150; - consensus.BIP34Height = 1; // Always active unless overridden - consensus.BIP34Hash = uint256(); - consensus.BIP65Height = 1; // Always active unless overridden - consensus.BIP66Height = 1; // Always active unless overridden - consensus.CSVHeight = 1; // Always active unless overridden - consensus.SegwitHeight = 0; // Always active unless overridden - consensus.MinBIP9WarningHeight = 0; - consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks - consensus.nPowTargetSpacing = 10 * 60; - consensus.fPowAllowMinDifficultyBlocks = true; - consensus.fPowNoRetargeting = true; - consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains - consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016) - - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].min_activation_height = 0; // No activation delay - - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2; - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE; - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; - consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].min_activation_height = 0; // No activation delay - - consensus.nMinimumChainWork = uint256{}; - consensus.defaultAssumeValid = uint256{}; - - pchMessageStart[0] = 0xfa; - pchMessageStart[1] = 0xbf; - pchMessageStart[2] = 0xb5; - pchMessageStart[3] = 0xda; - nDefaultPort = 18444; - nPruneAfterHeight = opts.fastprune ? 100 : 1000; - m_assumed_blockchain_size = 0; - m_assumed_chain_state_size = 0; - - for (const auto& [dep, height] : opts.activation_heights) { - switch (dep) { - case Consensus::BuriedDeployment::DEPLOYMENT_SEGWIT: - consensus.SegwitHeight = int{height}; - break; - case Consensus::BuriedDeployment::DEPLOYMENT_HEIGHTINCB: - consensus.BIP34Height = int{height}; - break; - case Consensus::BuriedDeployment::DEPLOYMENT_DERSIG: - consensus.BIP66Height = int{height}; - break; - case Consensus::BuriedDeployment::DEPLOYMENT_CLTV: - consensus.BIP65Height = int{height}; - break; - case Consensus::BuriedDeployment::DEPLOYMENT_CSV: - consensus.CSVHeight = int{height}; - break; - } - } - - for (const auto& [deployment_pos, version_bits_params] : opts.version_bits_parameters) { - consensus.vDeployments[deployment_pos].nStartTime = version_bits_params.start_time; - consensus.vDeployments[deployment_pos].nTimeout = version_bits_params.timeout; - consensus.vDeployments[deployment_pos].min_activation_height = version_bits_params.min_activation_height; - } - - genesis = CreateGenesisBlock(1296688602, 2, 0x207fffff, 1, 50 * COIN); - consensus.hashGenesisBlock = genesis.GetHash(); - assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")); - assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); - - vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds. - vSeeds.clear(); - vSeeds.emplace_back("dummySeed.invalid."); - - fDefaultConsistencyChecks = true; - fRequireStandard = true; - m_is_test_chain = true; - m_is_mockable_chain = true; - - checkpointData = { - { - {0, uint256S("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")}, - } - }; - - m_assumeutxo_data = MapAssumeutxo{ - { - 110, - {AssumeutxoHash{uint256S("0x1ebbf5850204c0bdb15bf030f47c7fe91d45c44c712697e4509ba67adb01c618")}, 110}, - }, - { - 200, - {AssumeutxoHash{uint256S("0x51c8d11d8b5c1de51543c579736e786aa2736206d1e11e627568029ce092cf62")}, 200}, - }, - }; - - chainTxData = ChainTxData{ - 0, - 0, - 0 - }; - - base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,111); - base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,196); - base58Prefixes[SECRET_KEY] = std::vector(1,239); - base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; - base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; - - bech32_hrp = "bcrt"; - } -}; - void ReadRegTestArgs(const ArgsManager& args, CChainParams::RegTestOptions& options) { if (auto value = args.GetBoolArg("-fastprune")) options.fastprune = *value; @@ -582,26 +96,6 @@ const CChainParams &Params() { return *globalChainParams; } -std::unique_ptr CChainParams::SigNet(const SigNetOptions& options) -{ - return std::make_unique(options); -} - -std::unique_ptr CChainParams::RegTest(const RegTestOptions& options) -{ - return std::make_unique(options); -} - -std::unique_ptr CChainParams::Main() -{ - return std::make_unique(); -} - -std::unique_ptr CChainParams::TestNet() -{ - return std::make_unique(); -} - std::unique_ptr CreateChainParams(const ArgsManager& args, const std::string& chain) { if (chain == CBaseChainParams::MAIN) { diff --git a/src/chainparams.h b/src/chainparams.h index 30488510d7166..cb34d068e1a1b 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -6,6 +6,8 @@ #ifndef BITCOIN_CHAINPARAMS_H #define BITCOIN_CHAINPARAMS_H +#include + #include #include #include @@ -19,167 +21,6 @@ #include #include -typedef std::map MapCheckpoints; - -struct CCheckpointData { - MapCheckpoints mapCheckpoints; - - int GetHeight() const { - const auto& final_checkpoint = mapCheckpoints.rbegin(); - return final_checkpoint->first /* height */; - } -}; - -struct AssumeutxoHash : public BaseHash { - explicit AssumeutxoHash(const uint256& hash) : BaseHash(hash) {} -}; - -/** - * Holds configuration for use during UTXO snapshot load and validation. The contents - * here are security critical, since they dictate which UTXO snapshots are recognized - * as valid. - */ -struct AssumeutxoData { - //! The expected hash of the deserialized UTXO set. - const AssumeutxoHash hash_serialized; - - //! Used to populate the nChainTx value, which is used during BlockManager::LoadBlockIndex(). - //! - //! We need to hardcode the value here because this is computed cumulatively using block data, - //! which we do not necessarily have at the time of snapshot load. - const unsigned int nChainTx; -}; - -using MapAssumeutxo = std::map; - -/** - * Holds various statistics on transactions within a chain. Used to estimate - * verification progress during chain sync. - * - * See also: CChainParams::TxData, GuessVerificationProgress. - */ -struct ChainTxData { - int64_t nTime; //!< UNIX timestamp of last known number of transactions - int64_t nTxCount; //!< total number of transactions between genesis and that timestamp - double dTxRate; //!< estimated number of transactions per second after that timestamp -}; - -/** - * CChainParams defines various tweakable parameters of a given instance of the - * Bitcoin system. - */ -class CChainParams -{ -public: - enum Base58Type { - PUBKEY_ADDRESS, - SCRIPT_ADDRESS, - SECRET_KEY, - EXT_PUBLIC_KEY, - EXT_SECRET_KEY, - - MAX_BASE58_TYPES - }; - - const Consensus::Params& GetConsensus() const { return consensus; } - const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; } - uint16_t GetDefaultPort() const { return nDefaultPort; } - uint16_t GetDefaultPort(Network net) const - { - return net == NET_I2P ? I2P_SAM31_PORT : GetDefaultPort(); - } - uint16_t GetDefaultPort(const std::string& addr) const - { - CNetAddr a; - return a.SetSpecial(addr) ? GetDefaultPort(a.GetNetwork()) : GetDefaultPort(); - } - - const CBlock& GenesisBlock() const { return genesis; } - /** Default value for -checkmempool and -checkblockindex argument */ - bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; } - /** Policy: Filter transactions that do not match well-defined patterns */ - bool RequireStandard() const { return fRequireStandard; } - /** If this chain is exclusively used for testing */ - bool IsTestChain() const { return m_is_test_chain; } - /** If this chain allows time to be mocked */ - bool IsMockableChain() const { return m_is_mockable_chain; } - uint64_t PruneAfterHeight() const { return nPruneAfterHeight; } - /** Minimum free space (in GB) needed for data directory */ - uint64_t AssumedBlockchainSize() const { return m_assumed_blockchain_size; } - /** Minimum free space (in GB) needed for data directory when pruned; Does not include prune target*/ - 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 list of hostnames to look up for DNS seeds */ - const std::vector& DNSSeeds() const { return vSeeds; } - const std::vector& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } - const std::string& Bech32HRP() const { return bech32_hrp; } - const std::vector& FixedSeeds() const { return vFixedSeeds; } - const CCheckpointData& Checkpoints() const { return checkpointData; } - - //! Get allowed assumeutxo configuration. - //! @see ChainstateManager - const MapAssumeutxo& Assumeutxo() const { return m_assumeutxo_data; } - - const ChainTxData& TxData() const { return chainTxData; } - - /** - * SigNetOptions holds configurations for creating a signet CChainParams. - */ - struct SigNetOptions { - std::optional> challenge{}; - std::optional> seeds{}; - }; - - /** - * VersionBitsParameters holds activation parameters - */ - struct VersionBitsParameters { - int64_t start_time; - int64_t timeout; - int min_activation_height; - }; - - /** - * RegTestOptions holds configurations for creating a regtest CChainParams. - */ - struct RegTestOptions { - std::unordered_map version_bits_parameters{}; - std::unordered_map activation_heights{}; - bool fastprune{false}; - }; - - static std::unique_ptr RegTest(const RegTestOptions& options); - static std::unique_ptr SigNet(const SigNetOptions& options); - static std::unique_ptr Main(); - static std::unique_ptr TestNet(); - -protected: - CChainParams() {} - - Consensus::Params consensus; - CMessageHeader::MessageStartChars pchMessageStart; - uint16_t nDefaultPort; - uint64_t nPruneAfterHeight; - uint64_t m_assumed_blockchain_size; - uint64_t m_assumed_chain_state_size; - std::vector vSeeds; - std::vector base58Prefixes[MAX_BASE58_TYPES]; - std::string bech32_hrp; - std::string strNetworkID; - CBlock genesis; - std::vector vFixedSeeds; - bool fDefaultConsistencyChecks; - bool fRequireStandard; - bool m_is_test_chain; - bool m_is_mockable_chain; - CCheckpointData checkpointData; - MapAssumeutxo m_assumeutxo_data; - ChainTxData chainTxData; -}; - /** * Creates and returns a std::unique_ptr of the chosen chain. * @returns a CChainParams* of the chosen chain. diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp new file mode 100644 index 0000000000000..e0c4aff6f4dee --- /dev/null +++ b/src/kernel/chainparams.cpp @@ -0,0 +1,532 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2021 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include