From 082e406875e54d442e964bfd6ba99f64880adf1b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 14 Nov 2021 08:38:25 +0100 Subject: [PATCH 1/9] Merge bitcoin/bitcoin#23500: doc: fix typos 2de1ceb2e9180d40611a6d32b3a9470c242952e0 depends, wallet: fix typos (Dimitris Apostolou) Pull request description: ACKs for top commit: hebasto: ACK 2de1ceb2e9180d40611a6d32b3a9470c242952e0 Tree-SHA512: e33deef3ebd8cda69dd0f2c0e8d0fd5c39375eb014685318b2f131c7a700584d9b9e173e95ff290b1fe3b2dc88922583f2607750445baedf0c97a330a9ff35f2 --- src/wallet/test/fuzz/notifications.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/test/fuzz/notifications.cpp b/src/wallet/test/fuzz/notifications.cpp index 013878da5e35..daa9d5a8aa09 100644 --- a/src/wallet/test/fuzz/notifications.cpp +++ b/src/wallet/test/fuzz/notifications.cpp @@ -95,7 +95,7 @@ FUZZ_TARGET(wallet_notifications, .init = initialize_setup) using Coins = std::set>; std::vector> chain; { - // Add the inital entry + // Add the initial entry chain.emplace_back(); auto& [coins, block]{chain.back()}; coins.emplace(total_amount, COutPoint{uint256::ONE, 1}); From 47363537a080173b27cdfb35ce5e8d21fc86f334 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 7 Dec 2021 08:50:59 +0100 Subject: [PATCH 2/9] Merge bitcoin/bitcoin#23686: test: fix `interface_bitcoin_cli.py --descriptors` and add to test runner 035767f54a393ff9c0b4869b3142db12ecacb8e3 test: add interface_bitcoin_cli.py --descriptors to test_runner.py (Sebastian Falbesoner) e4fa28a3228619b58d0177a28dc016aac8a87afe test: fix test interface_bitcoin_cli.py for descriptor wallets (Sebastian Falbesoner) Pull request description: The functional test interface_bitcoin_cli.py currently fails on master branch, if descriptor wallets are used (argument `--descriptors`), see #23684. This is due to the fact that different change output types are used for created transactions (P2WPKH for legacy wallets, P2TR for descriptor wallets; the former doesn't have a ScriptPubKeyMan for bech32m), resulting in different tx sizes and hence also fees. Fix this by explicitely setting the output type via passing both `-addresstype=bech32` and `-changetype=bech32` as argument. The former would not be needed by now, but makes the test more deterministic and avoids a failure if bech32m becomes the default address type. Fixes #23684, should also pave the way for #23682. Top commit has no ACKs. Tree-SHA512: 39b780e25e4c7094cb3378e0f10d4a8aebac1500b7b2d68de47e54e23b9b5efe5afcf8765bb8398eeaf56968e2586a1b294a0f8773c7d90f4188a0f00b8501ff --- test/functional/interface_bitcoin_cli.py | 3 +++ test/functional/test_runner.py | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py index f92644baeedc..a81f6e25f11b 100755 --- a/test/functional/interface_bitcoin_cli.py +++ b/test/functional/interface_bitcoin_cli.py @@ -149,6 +149,9 @@ def run_test(self): if self.is_specified_wallet_compiled(): self.log.info("Test -getinfo and dash-cli getwalletinfo return expected wallet info") + # Explicitely set the output type in order to have constintent tx vsize / fees + # for both legacy and descriptor wallets (disables the change address type detection algorithm) + self.restart_node(0, extra_args=[]) assert_equal(Decimal(cli_get_info['Balance']), BALANCE) assert 'Balances' not in cli_get_info_string wallet_info = self.nodes[0].getwalletinfo() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index ddcd17a662a4..226b03c22a07 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -169,7 +169,8 @@ 'interface_zmq_dash.py --legacy-wallet', 'interface_zmq.py', 'rpc_invalid_address_message.py', - 'interface_bitcoin_cli.py', + 'interface_bitcoin_cli.py --legacy-wallet', + 'interface_bitcoin_cli.py --descriptors', 'feature_bind_extra.py', 'mempool_resurrect.py', 'wallet_txn_doublespend.py --mineblock', From e143ba2641d247f910b1d3edeff957533c723fd2 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 22 Nov 2021 10:55:19 +0100 Subject: [PATCH 3/9] partial Merge bitcoin/bitcoin#23521: test: refactor: dedup code by taking use of `create_block` parameters BACKPORT NOTE: missing changes are in: - wallet_taproot.py - feature_taproot.py e57c0eb865b4ce155b5a4a2e56e46791a47e85af test: refactor: replace OP_1/OP_TRUE magic numbers by constants (Sebastian Falbesoner) df5d783aef3e5af2d1294fc8ff9470a5dc878325 test: refactor: take use of `create_block` txlist parameter (Sebastian Falbesoner) ae9df4ef937ef77405f6edd7c13615df7b63446f test: refactor: take use of `create_block` version parameter (or use default) (Sebastian Falbesoner) Pull request description: The helper `create_block` offers two parameters `version` and `txlist` which set the `nVersion` field / extend the `vtx` array of the block, respectively. By taking use of those, we can remove a lot of code, including the recalculation of the merkle root. Both passing txs in string and `CTransaction` format is supported, i.e. we also save potential calls to `tx_from_hex`. The PR also contains another commit which replaces magic numbers for OP_TRUE/OP_1 (0x51) with the proper constant from the `script` module. Instances setting the block version of 4 explicitely after calling `create_block` are removed, as this is the default since #16333 got merged (see https://github.com/bitcoin/bitcoin/pull/23521#discussion_r751173671). ACKs for top commit: stratospher: tested ACK e57c0eb. Tree-SHA512: a56965168d36b40b84e7f334b00472b82c31e8482c9e2651c97a791abd7fee3b40ca15e943a7acafa3acf172066fdace38bb13240084b789fd6ff4f6e510e23a --- test/functional/feature_assumevalid.py | 5 +-- test/functional/feature_bip68_sequence.py | 3 +- test/functional/feature_block.py | 5 ++- test/functional/feature_cltv.py | 8 ++--- test/functional/feature_csv_activation.py | 5 +-- test/functional/feature_dersig.py | 7 ++-- .../functional/feature_versionbits_warning.py | 3 +- test/functional/p2p_invalid_block.py | 36 ++++++++----------- test/functional/p2p_unrequested_blocks.py | 5 ++- 9 files changed, 26 insertions(+), 51 deletions(-) diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py index 00a130ff6907..877ca5796122 100755 --- a/test/functional/feature_assumevalid.py +++ b/test/functional/feature_assumevalid.py @@ -126,10 +126,8 @@ def run_test(self): tx.vout.append(CTxOut(49 * 100000000, CScript([OP_TRUE]))) tx.calc_sha256() - block102 = create_block(self.tip, create_coinbase(height), self.block_time) + block102 = create_block(self.tip, create_coinbase(height), self.block_time, txlist=[tx]) self.block_time += 1 - block102.vtx.extend([tx]) - block102.hashMerkleRoot = block102.calc_merkle_root() block102.solve() self.blocks.append(block102) self.tip = block102.sha256 @@ -139,7 +137,6 @@ def run_test(self): # Bury the assumed valid block 8400 deep (Dash needs 4x as much blocks to allow -assumevalid to work) for _ in range(8400): block = create_block(self.tip, create_coinbase(height), self.block_time) - block.nVersion = 4 block.solve() self.blocks.append(block) self.tip = block.sha256 diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py index be8811e9eb53..c7ca1ec190f9 100755 --- a/test/functional/feature_bip68_sequence.py +++ b/test/functional/feature_bip68_sequence.py @@ -385,8 +385,7 @@ def test_bip68_not_consensus(self): assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.wallet.sendrawtransaction, from_node=self.nodes[0], tx_hex=tx3.serialize().hex()) # make a block that violates bip68; ensure that the tip updates - block = create_block(tmpl=self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)) - block.vtx.extend([tx1, tx2, tx3]) + block = create_block(tmpl=self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS), txlist=[tx1, tx2, tx3]) block.hashMerkleRoot = block.calc_merkle_root() block.solve() diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py index 99e70478f71f..a56288176f31 100755 --- a/test/functional/feature_block.py +++ b/test/functional/feature_block.py @@ -1380,11 +1380,10 @@ def next_block(self, number, spend=None, additional_coinbase_value=0, script=CSc else: coinbase.vout[0].nValue += spend.vout[0].nValue - 1 # all but one satoshi to fees coinbase.rehash() - block = create_block(base_block_hash, coinbase, block_time, version=version) tx = self.create_tx(spend, 0, 1, script) # spend 1 satoshi self.sign_tx(tx, spend) - self.add_transactions_to_block(block, [tx]) - block.hashMerkleRoot = block.calc_merkle_root() + tx.rehash() + block = create_block(base_block_hash, coinbase, block_time, version=version, txlist=[tx]) # Block is created. Find a valid nonce. block.solve() self.tip = block diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py index 907811c47250..eced70a78bdc 100755 --- a/test/functional/feature_cltv.py +++ b/test/functional/feature_cltv.py @@ -128,10 +128,7 @@ def run_test(self): tip = self.nodes[0].getbestblockhash() block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1 - block = create_block(int(tip, 16), create_coinbase(CLTV_HEIGHT - 1), block_time) - block.nVersion = 3 - block.vtx.extend(invalid_cltv_txs) - block.hashMerkleRoot = block.calc_merkle_root() + block = create_block(int(tip, 16), create_coinbase(CLTV_HEIGHT - 1), block_time, version=3, txlist=invalid_cltv_txs) block.solve() self.test_cltv_info(is_active=False) # Not active as of current tip and next block does not need to obey rules @@ -142,8 +139,7 @@ def run_test(self): self.log.info("Test that blocks must now be at least version 4") tip = block.sha256 block_time += 1 - block = create_block(tip, create_coinbase(CLTV_HEIGHT), block_time) - block.nVersion = 3 + block = create_block(tip, create_coinbase(CLTV_HEIGHT), block_time, version=3) block.solve() with self.nodes[0].assert_debug_log(expected_msgs=[f'{block.hash}, bad-version(0x00000003)']): diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py index 969ad4b0003f..4c6632ed869c 100755 --- a/test/functional/feature_csv_activation.py +++ b/test/functional/feature_csv_activation.py @@ -182,10 +182,7 @@ def generate_blocks(self, number): return test_blocks def create_test_block(self, txs): - block = create_block(self.tip, create_coinbase(self.tipheight + 1), self.last_block_time + 600) - block.nVersion = 4 - block.vtx.extend(txs) - block.hashMerkleRoot = block.calc_merkle_root() + block = create_block(self.tip, create_coinbase(self.tipheight + 1), self.last_block_time + 600, txlist=txs) block.solve() return block diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py index 604a471c4da0..0880321f02f4 100755 --- a/test/functional/feature_dersig.py +++ b/test/functional/feature_dersig.py @@ -89,9 +89,7 @@ def run_test(self): tip = self.nodes[0].getbestblockhash() block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1 - block = create_block(int(tip, 16), create_coinbase(DERSIG_HEIGHT - 1), block_time) - block.vtx.append(spendtx) - block.hashMerkleRoot = block.calc_merkle_root() + block = create_block(int(tip, 16), create_coinbase(DERSIG_HEIGHT - 1), block_time, txlist=[spendtx]) block.solve() assert_equal(self.nodes[0].getblockcount(), DERSIG_HEIGHT - 2) @@ -104,8 +102,7 @@ def run_test(self): self.log.info("Test that blocks must now be at least version 3") tip = block.sha256 block_time += 1 - block = create_block(tip, create_coinbase(DERSIG_HEIGHT), block_time) - block.nVersion = 2 + block = create_block(tip, create_coinbase(DERSIG_HEIGHT), block_time, version=2) block.solve() with self.nodes[0].assert_debug_log(expected_msgs=[f'{block.hash}, bad-version(0x00000002)']): diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py index 20e131c56899..e386fbae7179 100755 --- a/test/functional/feature_versionbits_warning.py +++ b/test/functional/feature_versionbits_warning.py @@ -45,8 +45,7 @@ def send_blocks_with_version(self, peer, numblocks, version): tip = int(tip, 16) for _ in range(numblocks): - block = create_block(tip, create_coinbase(height + 1), block_time) - block.nVersion = version + block = create_block(tip, create_coinbase(height + 1), block_time, version=version) block.solve() peer.send_message(msg_block(block)) block_time += 1 diff --git a/test/functional/p2p_invalid_block.py b/test/functional/p2p_invalid_block.py index e4555dba9cf7..1d8217b40289 100755 --- a/test/functional/p2p_invalid_block.py +++ b/test/functional/p2p_invalid_block.py @@ -14,9 +14,15 @@ """ import copy -from test_framework.blocktools import MAX_FUTURE_BLOCK_TIME, create_block, create_coinbase, create_tx_with_script +from test_framework.blocktools import ( + MAX_FUTURE_BLOCK_TIME, + create_block, + create_coinbase, + create_tx_with_script, +) from test_framework.messages import COIN from test_framework.p2p import P2PDataStore +from test_framework.script import OP_TRUE from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal @@ -61,15 +67,10 @@ def run_test(self): # For more information on merkle-root malleability see src/consensus/merkle.cpp. self.log.info("Test merkle root malleability.") - block2 = create_block(tip, create_coinbase(height), block_time) + tx1 = create_tx_with_script(block1.vtx[0], 0, script_sig=bytes([OP_TRUE]), amount=50 * COIN) + tx2 = create_tx_with_script(tx1, 0, script_sig=bytes([OP_TRUE]), amount=50 * COIN) + block2 = create_block(tip, create_coinbase(height), block_time, txlist=[tx1, tx2]) block_time += 1 - - # b'0x51' is OP_TRUE - tx1 = create_tx_with_script(block1.vtx[0], 0, script_sig=b'\x51', amount=50 * COIN) - tx2 = create_tx_with_script(tx1, 0, script_sig=b'\x51', amount=50 * COIN) - - block2.vtx.extend([tx1, tx2]) - block2.hashMerkleRoot = block2.calc_merkle_root() block2.solve() orig_hash = block2.sha256 block2_orig = copy.deepcopy(block2) @@ -94,12 +95,8 @@ def run_test(self): self.log.info("Test very broken block.") - block3 = create_block(tip, create_coinbase(height), block_time) + block3 = create_block(tip, create_coinbase(height, nValue=1000), block_time) block_time += 1 - block3.vtx[0].vout[0].nValue = 1000 * COIN # Too high! - block3.vtx[0].sha256 = None - block3.vtx[0].calc_sha256() - block3.hashMerkleRoot = block3.calc_merkle_root() block3.solve() peer.send_blocks_and_test([block3], node, success=False, reject_reason='bad-cb-amount') @@ -118,14 +115,10 @@ def run_test(self): # Complete testing of CVE-2018-17144, by checking for the inflation bug. # Create a block that spends the output of a tx in a previous block. - block4 = create_block(tip, create_coinbase(height), block_time) - tx3 = create_tx_with_script(tx2, 0, script_sig=b'\x51', amount=50 * COIN) - - # Duplicates input - tx3.vin.append(tx3.vin[0]) + tx3 = create_tx_with_script(tx2, 0, script_sig=bytes([OP_TRUE]), amount=50 * COIN) + tx3.vin.append(tx3.vin[0]) # Duplicates input tx3.rehash() - block4.vtx.append(tx3) - block4.hashMerkleRoot = block4.calc_merkle_root() + block4 = create_block(tip, create_coinbase(height), block_time, txlist=[tx3]) block4.solve() self.log.info("Test inflation by duplicating input") peer.send_blocks_and_test([block4], node, success=False, reject_reason='bad-txns-inputs-duplicate') @@ -134,7 +127,6 @@ def run_test(self): t = self.mocktime # Set block time +1 second past max future validity block = create_block(tip, create_coinbase(height), t + MAX_FUTURE_BLOCK_TIME + 1) - block.hashMerkleRoot = block.calc_merkle_root() block.solve() # Need force_send because the block will get rejected without a getdata otherwise peer.send_blocks_and_test([block], node, force_send=True, success=False, reject_reason='time-too-new') diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py index 6dec38007208..7bfc3f539a93 100755 --- a/test/functional/p2p_unrequested_blocks.py +++ b/test/functional/p2p_unrequested_blocks.py @@ -221,10 +221,9 @@ def run_test(self): block_289f.solve() block_290f = create_block(block_289f.sha256, create_coinbase(290), block_289f.nTime+1) block_290f.solve() - block_291 = create_block(block_290f.sha256, create_coinbase(291), block_290f.nTime+1) # block_291 spends a coinbase below maturity! - block_291.vtx.append(create_tx_with_script(block_290f.vtx[0], 0, script_sig=b"42", amount=1)) - block_291.hashMerkleRoot = block_291.calc_merkle_root() + tx_to_add = create_tx_with_script(block_290f.vtx[0], 0, script_sig=b"42", amount=1) + block_291 = create_block(block_290f.sha256, create_coinbase(291), block_290f.nTime+1, txlist=[tx_to_add]) block_291.solve() block_292 = create_block(block_291.sha256, create_coinbase(292), block_291.nTime+1) block_292.solve() From dcbc646eee4b65f2609397e5e55b94274b320b82 Mon Sep 17 00:00:00 2001 From: laanwj <126646+laanwj@users.noreply.github.com> Date: Tue, 22 Feb 2022 12:38:12 +0100 Subject: [PATCH 4/9] Merge bitcoin/bitcoin#24367: User-facing content and codebase doc fixups from transifex translator feedback BACKPORT NOTE: It has been partial, only missing changes in wallet_timelock.py. But changes in test/functional/rpc_decodescript.py has been lost when done bitcoin/bitcoin#23540, re-applied 48742693acc9de837735674057c9aae2fe90bd1d Replace "can not" with "cannot" in docs, user messages, and tests (Jon Atack) e670edd43441ecb6e5978d65348501c57d856030 User-facing content fixups from transifex translator feedback (Jon Atack) Pull request description: Closes #24366. ACKs for top commit: laanwj: Code review re-ACK 48742693acc9de837735674057c9aae2fe90bd1d hebasto: re-ACK 48742693acc9de837735674057c9aae2fe90bd1d, only suggested change since my previous [review](https://github.com/bitcoin/bitcoin/pull/24367#pullrequestreview-885938219). Tree-SHA512: 4dcdcb417251a413e65fab6070515e13a1267c8e0dbcf521386b842511391f24c84a0c2168fe13458c977682034466509bf2a3453719d4d94d3c568fd9f4adb4 --- test/functional/rpc_decodescript.py | 2 +- test/functional/wallet_timelock.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/functional/rpc_decodescript.py b/test/functional/rpc_decodescript.py index 4eb5dfb2e6d8..00e4ea883f03 100755 --- a/test/functional/rpc_decodescript.py +++ b/test/functional/rpc_decodescript.py @@ -51,7 +51,7 @@ def decodescript_script_sig(self): rpc_result = self.nodes[0].decodescript('5100') assert_equal('1 0', rpc_result['asm']) - # null data scriptSig - no such thing because null data scripts can not be spent. + # null data scriptSig - no such thing because null data scripts cannot be spent. # thus, no test case for that standard transaction type is here. def decodescript_script_pub_key(self): diff --git a/test/functional/wallet_timelock.py b/test/functional/wallet_timelock.py index cf233a00effd..a71cec6607de 100755 --- a/test/functional/wallet_timelock.py +++ b/test/functional/wallet_timelock.py @@ -30,7 +30,7 @@ def run_test(self): ) self.generate(node, 1) - self.log.info("Check that clock can not change finality of confirmed txs") + self.log.info("Check that clock cannot change finality of confirmed txs") amount_before_ad = node.getreceivedbyaddress(address) amount_before_lb = node.getreceivedbylabel(label) list_before_ad = node.listreceivedbyaddress(address_filter=address) From 33f9b142b8bc7a6b65bc3f000442f8cf7435b52e Mon Sep 17 00:00:00 2001 From: MacroFake Date: Mon, 24 Oct 2022 10:27:54 +0200 Subject: [PATCH 5/9] Merge bitcoin/bitcoin#26358: doc: Rearrange a few lines in the dependency graph of libraries 1184a66347afbaeca69e2d891a138e435fbfd5bb doc: Rearrange some lines in the dependency graph of libraries (Stacie Waleyko) Pull request description: In this PR, I've attempted to improve readability in the [dependency graph of libraries](https://github.com/bitcoin/bitcoin/blob/master/doc/design/libraries.md) by untangling a few crossed lines. I'm not sure if this is that big of an improvement but wanted to throw it out there. I used an extremely scientific method of manually counting the number of crossed lines in the original diagram and got 15. This PR reduces that number down to about 10. I also changed the curve of the lines to "basis" which rounds the edges out. Again, not sure if it really is that much of an improvement, but it seems marginally easier on the eyes. Here is what the new graph looks like rendered: ![Screenshot from 2022-10-20 22-09-30](https://user-images.githubusercontent.com/1823216/197095545-5fc90cce-a817-4db2-a0f5-1a8a95380b70.png) The changes can be verified independently with [Mermaid](https://mermaid-js.github.io/mermaid/#/), with the easiest way being the online editor: https://mermaid.live/ I did try moving some more stuff around, particularly the top level of library callers, but was not able to simplify the graph any further. ACKs for top commit: shaavan: ACK 1184a66347afbaeca69e2d891a138e435fbfd5bb Tree-SHA512: 61d33d68c1e6fa354aebdda5e06e9c7a722ca20886c6acc30dd08af7133d737130d7a646d87f9e5a8ae0bc5a5aabfbc64ded9ee04dfeed8f23d948444add916b --- doc/design/libraries.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/design/libraries.md b/doc/design/libraries.md index d3c421a0d319..755efe9ed143 100644 --- a/doc/design/libraries.md +++ b/doc/design/libraries.md @@ -37,7 +37,7 @@ Note: libbitcoin_kernel is a subject to be backported & dashified. ```mermaid -%%{ init : { "flowchart" : { "curve" : "linear" }}}%% +%%{ init : { "flowchart" : { "curve" : "basis" }}}%% graph TD; @@ -53,18 +53,19 @@ dash-qt[dash-qt]-->libbitcoin_wallet; dash-wallet[dash-wallet]-->libbitcoin_wallet; dash-wallet[dash-wallet]-->libbitcoin_wallet_tool; -libbitcoin_cli-->libbitcoin_common; libbitcoin_cli-->libbitcoin_util; +libbitcoin_cli-->libbitcoin_common; -libbitcoin_common-->libbitcoin_util; libbitcoin_common-->libdash_consensus; +libbitcoin_common-->libbitcoin_util; libbitcoin_kernel-->libdash_consensus; libbitcoin_kernel-->libbitcoin_util; -libbitcoin_node-->libbitcoin_common; libbitcoin_node-->libdash_consensus; +libbitcoin_node-->libbitcoin_common; libbitcoin_node-->libbitcoin_kernel; +libbitcoin_node-->libbitcoin_common; libbitcoin_node-->libbitcoin_util; libbitcoinqt-->libbitcoin_common; @@ -73,8 +74,8 @@ libbitcoinqt-->libbitcoin_util; libbitcoin_wallet-->libbitcoin_common; libbitcoin_wallet-->libbitcoin_util; -libbitcoin_wallet_tool-->libbitcoin_util; libbitcoin_wallet_tool-->libbitcoin_wallet; +libbitcoin_wallet_tool-->libbitcoin_util; classDef bold stroke-width:2px, font-weight:bold, font-size: smaller; class dash-qt,dashd,dash-cli,dash-wallet bold From ffc9892feb112f45a017a0bb59c3823c7533179b Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Wed, 26 Oct 2022 11:20:13 -0400 Subject: [PATCH 6/9] Merge bitcoin/bitcoin#23927: rpc: Pruning nodes can not fetch blocks before syncing past their height 5826bf546e83478947edbdf49978414f0b69eb1a test: Add test for getblockfrompeer on syncing pruned nodes (Fabian Jahr) 7fa851fba8570ef256317f7d5759aa3de9088bf1 rpc: Pruned nodes can not fetch unsynced blocks (Fabian Jahr) Pull request description: This PR prevents `getblockfrompeer` from getting used on blocks that the node has not synced past yet if the node is in running in prune mode. ### Problem While a node is still catching up to the tip that it is aware of via the headers, the user can currently use to fetch blocks close to or at the tip. These blocks are stored in the block/rev file that otherwise contains blocks the node is receiving as part of the syncing process. This creates a problem for pruned nodes: The files containing a fetched block are not pruned during syncing because they contain a block close to the tip. This means the entire file (~130MB) will not be pruned until the tip has moved on far enough from the fetched block. In extreme cases with heavy pruning (like 550) and multiple blocks being fetched this could mean that the disc usage far exceeds what the user expects, potentially running out of space. ### Approach There would be certainly other approaches that could fix the problem while still allowing the current behavior, but all of the ideas I came up with seemed like overkill for a niche problem on a new RPC where it's still unclear how and how much it will be used. ### Testing So far I did not see a simple enough way to test this I am still looking into it and if it's complex will potentially add it in a follow-up. What would be needed is a way to have a node fetch headers but not sync the blocks yet, that seems like a pattern that could be generally useful. To manually reproduce the problematic behavior: 1. Start a node with current `master` with `-prune=550` and an empty/new datadir, Testnet and Mainnet should both work. 2. While the node is syncing run `getblockfrompeer` on the current tip and a few other recent blocks. 3. Go to your datadir and observe the blocks folder: There should be a few full `blk*.dat` and `rev*.dat` files that are not being pruned. When you "pinned" a few of these files the blocks folder should be significantly above the target size of 550MB. ACKs for top commit: Sjors: utACK 5826bf546e83478947edbdf49978414f0b69eb1a achow101: ACK 5826bf546e83478947edbdf49978414f0b69eb1a aureleoules: tACK 5826bf546e83478947edbdf49978414f0b69eb1a Tree-SHA512: aa3f477ec755a9df2331c047cb10b3cd08292522bf6ad7a36a7ea36d7eba4894b84de8bd23003c9baea5ac0c53b77142c3c2819ae7528cece9d10a0d06c850d8 --- src/rpc/blockchain.cpp | 6 +++++ test/functional/rpc_getblockfrompeer.py | 36 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 8401e186c750..a2c4aa399072 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -517,6 +517,12 @@ static RPCHelpMan getblockfrompeer() throw JSONRPCError(RPC_MISC_ERROR, "Block header missing"); } + // Fetching blocks before the node has syncing past their height can prevent block files from + // being pruned, so we avoid it if the node is in prune mode. + if (index->nHeight > chainman.ActiveChain().Tip()->nHeight && node::fPruneMode) { + throw JSONRPCError(RPC_MISC_ERROR, "In prune mode, only blocks that the node has already synced previously can be fetched from a peer"); + } + const bool block_has_data = WITH_LOCK(::cs_main, return index->nStatus & BLOCK_HAVE_DATA); if (block_has_data) { throw JSONRPCError(RPC_MISC_ERROR, "Block already downloaded"); diff --git a/test/functional/rpc_getblockfrompeer.py b/test/functional/rpc_getblockfrompeer.py index 43c96641cfd4..6b460336e698 100755 --- a/test/functional/rpc_getblockfrompeer.py +++ b/test/functional/rpc_getblockfrompeer.py @@ -5,12 +5,22 @@ """Test the getblockfrompeer RPC.""" from test_framework.authproxy import JSONRPCException +from test_framework.governance import EXPECTED_STDERR_NO_GOV_PRUNE +from test_framework.messages import ( + CBlock, + from_hex, + msg_headers, +) +from test_framework.p2p import ( + P2PInterface, +) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, assert_raises_rpc_error, ) + class GetBlockFromPeerTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 @@ -69,5 +79,31 @@ def run_test(self): self.log.info("Don't fetch blocks we already have") assert_raises_rpc_error(-1, "Block already downloaded", self.nodes[0].getblockfrompeer, short_tip, peer_0_peer_1_id) + self.log.info("Don't fetch blocks while the node has not synced past it yet") + # For this test we need node 1 in prune mode and as a side effect this also disconnects + # the nodes which is also necessary for the rest of the test. + self.restart_node(1, ["-prune=550"]) + + # Generate a block on the disconnected node that the pruning node is not connected to + blockhash = self.generate(self.nodes[0], 1, sync_fun=self.no_op)[0] + block_hex = self.nodes[0].getblock(blockhash=blockhash, verbosity=0) + block = from_hex(CBlock(), block_hex) + + # Connect a P2PInterface to the pruning node and have it submit only the header of the + # block that the pruning node has not seen + node1_interface = self.nodes[1].add_p2p_connection(P2PInterface()) + node1_interface.send_message(msg_headers([block])) + + # Get the peer id of the P2PInterface from the pruning node + node1_peers = self.nodes[1].getpeerinfo() + assert_equal(len(node1_peers), 1) + node1_interface_id = node1_peers[0]["id"] + + # Trying to fetch this block from the P2PInterface should not be possible + error_msg = "In prune mode, only blocks that the node has already synced previously can be fetched from a peer" + assert_raises_rpc_error(-1, error_msg, self.nodes[1].getblockfrompeer, blockhash, node1_interface_id) + self.stop_node(1, expected_stderr=EXPECTED_STDERR_NO_GOV_PRUNE) + + if __name__ == '__main__': GetBlockFromPeerTest().main() From 53b12e52e724ab5e949142949fc7654a7062b3c6 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Mon, 1 Dec 2025 20:34:31 +0700 Subject: [PATCH 7/9] Merge #23212: lint: enable mypy import checking Leftover changes --- contrib/devtools/circular-dependencies.py | 2 +- contrib/devtools/optimize-pngs.py | 3 ++- test/functional/test_framework/messages.py | 2 +- test/lint/lint-python.py | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/contrib/devtools/circular-dependencies.py b/contrib/devtools/circular-dependencies.py index 4de4054118f4..e939ec6d45ba 100755 --- a/contrib/devtools/circular-dependencies.py +++ b/contrib/devtools/circular-dependencies.py @@ -5,7 +5,7 @@ import sys import re -from multiprocess import Pool +from multiprocess import Pool # type: ignore[import] from typing import Dict, List, Set MAPPING = { diff --git a/contrib/devtools/optimize-pngs.py b/contrib/devtools/optimize-pngs.py index ad8c65dba911..12de9e784633 100755 --- a/contrib/devtools/optimize-pngs.py +++ b/contrib/devtools/optimize-pngs.py @@ -10,7 +10,8 @@ import sys import subprocess import hashlib -from PIL import Image # pip3 install Pillow +# pip3 install Pillow +from PIL import Image # type: ignore[import] def file_hash(filename): '''Return hash of raw file contents''' diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index b22cb5475370..aa467d78f2be 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -30,7 +30,7 @@ from test_framework.crypto.siphash import siphash256 from test_framework.util import assert_equal -import dash_hash +import dash_hash # type: ignore[import] MAX_LOCATOR_SZ = 101 MAX_BLOCK_SIZE = 2000000 diff --git a/test/lint/lint-python.py b/test/lint/lint-python.py index fb6224b06e8a..84f4edc332a9 100755 --- a/test/lint/lint-python.py +++ b/test/lint/lint-python.py @@ -126,7 +126,7 @@ def main(): exit(1) mypy_files = subprocess.check_output(FILES_ARGS).decode("utf-8").splitlines() - mypy_args = ['mypy', '--ignore-missing-imports', '--show-error-codes'] + mypy_files + mypy_args = ['mypy', '--show-error-codes'] + mypy_files try: subprocess.check_call(mypy_args) From d01f33e56bcc573112abc54968991bf577ac0018 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Fri, 5 Dec 2025 02:11:18 +0700 Subject: [PATCH 8/9] fix: enable namespaces for mypy while version is too old --- test/lint/lint-python.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/lint/lint-python.py b/test/lint/lint-python.py index 84f4edc332a9..a81edfd2fc7f 100755 --- a/test/lint/lint-python.py +++ b/test/lint/lint-python.py @@ -126,7 +126,8 @@ def main(): exit(1) mypy_files = subprocess.check_output(FILES_ARGS).decode("utf-8").splitlines() - mypy_args = ['mypy', '--show-error-codes'] + mypy_files + # TODO: remove `--namespace-packages` after upgrade to mypy 0.991 or newer + mypy_args = ['mypy', '--namespace-packages', '--show-error-codes'] + mypy_files try: subprocess.check_call(mypy_args) From 19aed94085d5338852f704de9195079d51540cce Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 26 Oct 2021 15:54:46 +0100 Subject: [PATCH 9/9] Merge bitcoin/bitcoin#23006: multiprocess: Add new bitcoin-gui, bitcoin-qt, bitcoin-wallet init implementations d5f985e51f2863fda0c0d632e836eba42a5c3e15 multiprocess: Add new bitcoin-gui, bitcoin-qt, bitcoin-wallet init implementations (Russell Yanofsky) Pull request description: Add separate `interfaces::Init` subclasses for `bitcoin-wallet`, `bitcoin-gui`, and `bitcoin-qt` binaries instead of sharing `bitcoind` and `bitcoin-node` init subclasses in different binaries. After this, the new init subclasses can be customized in #10102, so node and wallet code is dropped from the `bitcoin-gui` binary and wallet code is dropped from into the `bitcoin-node` binary. --- This PR is part of the [process separation project](https://github.com/bitcoin/bitcoin/projects/10). ACKs for top commit: lsilva01: reACK d5f985e hebasto: re-ACK d5f985e51f2863fda0c0d632e836eba42a5c3e15, only suggested changes since my [previous](https://github.com/bitcoin/bitcoin/pull/23006#pullrequestreview-787537444) review. Tree-SHA512: 6784210bd9ce3a6fbc66852680d0e9bc513c072dc538aeb7f48cb6a41580d3f567ccef04f975ee767a714a4b05d4d87273e94a79abda1b9c25d5ac4bbe752006 --- src/Makefile.am | 1 + src/Makefile.qt.include | 6 ++--- src/Makefile.qttest.include | 2 +- src/bitcoin-wallet.cpp | 8 ++++++ src/init/bitcoin-gui.cpp | 52 +++++++++++++++++++++++++++++++++++++ src/init/bitcoin-qt.cpp | 47 +++++++++++++++++++++++++++++++++ src/init/bitcoin-wallet.cpp | 12 +++++++++ src/qt/bitcoin.cpp | 7 +---- src/qt/test/test_main.cpp | 6 +---- 9 files changed, 126 insertions(+), 15 deletions(-) create mode 100644 src/init/bitcoin-gui.cpp create mode 100644 src/init/bitcoin-qt.cpp create mode 100644 src/init/bitcoin-wallet.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 77b384d144e2..d62df14146fd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1090,6 +1090,7 @@ dash_tx_LDADD += $(BACKTRACE_LIBS) $(GMP_LIBS) # dash-wallet binary # dash_wallet_SOURCES = bitcoin-wallet.cpp +dash_wallet_SOURCES += init/bitcoin-wallet.cpp dash_wallet_CPPFLAGS = $(bitcoin_bin_cppflags) dash_wallet_CXXFLAGS = $(bitcoin_bin_cxxflags) dash_wallet_LDFLAGS = $(bitcoin_bin_ldflags) diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 488cbb21ff78..2b7a21a5e74e 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -424,15 +424,15 @@ bitcoin_qt_libtoolflags = $(AM_LIBTOOLFLAGS) --tag CXX qt_dash_qt_CPPFLAGS = $(bitcoin_qt_cppflags) qt_dash_qt_CXXFLAGS = $(bitcoin_qt_cxxflags) -qt_dash_qt_SOURCES = $(bitcoin_qt_sources) init/bitcoind.cpp +qt_dash_qt_SOURCES = $(bitcoin_qt_sources) init/bitcoin-qt.cpp qt_dash_qt_LDADD = $(bitcoin_qt_ldadd) qt_dash_qt_LDFLAGS = $(bitcoin_qt_ldflags) qt_dash_qt_LIBTOOLFLAGS = $(bitcoin_qt_libtoolflags) dash_gui_CPPFLAGS = $(bitcoin_qt_cppflags) dash_gui_CXXFLAGS = $(bitcoin_qt_cxxflags) -dash_gui_SOURCES = $(bitcoin_qt_sources) init/bitcoind.cpp -dash_gui_LDADD = $(bitcoin_qt_ldadd) +dash_gui_SOURCES = $(bitcoin_qt_sources) init/bitcoin-gui.cpp +dash_gui_LDADD = $(bitcoin_qt_ldadd) $(LIBBITCOIN_IPC) $(LIBBITCOIN_UTIL) $(LIBMULTIPROCESS_LIBS) dash_gui_LDFLAGS = $(bitcoin_qt_ldflags) dash_gui_LIBTOOLFLAGS = $(bitcoin_qt_libtoolflags) diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 83cdbefc1424..62071d40e5a5 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -33,7 +33,7 @@ qt_test_test_dash_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_ $(QT_INCLUDES) $(QT_TEST_INCLUDES) $(BOOST_CPPFLAGS) qt_test_test_dash_qt_SOURCES = \ - init/bitcoind.cpp \ + init/bitcoin-qt.cpp \ qt/test/apptests.cpp \ qt/test/optiontests.cpp \ qt/test/rpcnestedtests.cpp \ diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp index 7bc14502a3f1..6590188b9f9a 100644 --- a/src/bitcoin-wallet.cpp +++ b/src/bitcoin-wallet.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -100,6 +101,13 @@ MAIN_FUNCTION util::WinCmdLineArgs winArgs; std::tie(argc, argv) = winArgs.get(); #endif + + int exit_status; + std::unique_ptr init = interfaces::MakeWalletInit(argc, argv, exit_status); + if (!init) { + return exit_status; + } + SetupEnvironment(); RandomInit(); try { diff --git a/src/init/bitcoin-gui.cpp b/src/init/bitcoin-gui.cpp new file mode 100644 index 000000000000..7b21a33de5cc --- /dev/null +++ b/src/init/bitcoin-gui.cpp @@ -0,0 +1,52 @@ +// Copyright (c) 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 + +namespace init { +namespace { +const char* EXE_NAME = "dash-gui"; + +class BitcoinGuiInit : public interfaces::Init +{ +public: + BitcoinGuiInit(const char* arg0) : m_ipc(interfaces::MakeIpc(EXE_NAME, arg0, *this)) + { + m_node.args = &gArgs; + m_node.init = this; + } + std::unique_ptr makeNode() override { return interfaces::MakeNode(m_node); } + std::unique_ptr makeChain() override { return interfaces::MakeChain(m_node); } + std::unique_ptr makeCoinJoinLoader() override + { + return interfaces::MakeCoinJoinLoader(m_node); + } + std::unique_ptr makeWalletLoader(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoin_loader) override + { + return MakeWalletLoader(chain, *Assert(m_node.args), m_node, coinjoin_loader); + } + std::unique_ptr makeEcho() override { return interfaces::MakeEcho(); } + interfaces::Ipc* ipc() override { return m_ipc.get(); } + node::NodeContext m_node; + std::unique_ptr m_ipc; +}; +} // namespace +} // namespace init + +namespace interfaces { +std::unique_ptr MakeGuiInit(int argc, char* argv[]) +{ + return std::make_unique(argc > 0 ? argv[0] : ""); +} +} // namespace interfaces diff --git a/src/init/bitcoin-qt.cpp b/src/init/bitcoin-qt.cpp new file mode 100644 index 000000000000..38716895d110 --- /dev/null +++ b/src/init/bitcoin-qt.cpp @@ -0,0 +1,47 @@ +// Copyright (c) 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 + +namespace init { +namespace { +class BitcoinQtInit : public interfaces::Init +{ +public: + BitcoinQtInit() + { + m_node.args = &gArgs; + m_node.init = this; + } + std::unique_ptr makeNode() override { return interfaces::MakeNode(m_node); } + std::unique_ptr makeChain() override { return interfaces::MakeChain(m_node); } + std::unique_ptr makeCoinJoinLoader() override + { + return interfaces::MakeCoinJoinLoader(m_node); + } + std::unique_ptr makeWalletLoader(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoin_loader) override + { + return MakeWalletLoader(chain, *Assert(m_node.args), m_node, coinjoin_loader); + } + std::unique_ptr makeEcho() override { return interfaces::MakeEcho(); } + node::NodeContext m_node; +}; +} // namespace +} // namespace init + +namespace interfaces { +std::unique_ptr MakeGuiInit(int argc, char* argv[]) +{ + return std::make_unique(); +} +} // namespace interfaces diff --git a/src/init/bitcoin-wallet.cpp b/src/init/bitcoin-wallet.cpp new file mode 100644 index 000000000000..e9dcde72fe23 --- /dev/null +++ b/src/init/bitcoin-wallet.cpp @@ -0,0 +1,12 @@ +// Copyright (c) 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 + +namespace interfaces { +std::unique_ptr MakeWalletInit(int argc, char* argv[], int& exit_status) +{ + return std::make_unique(); +} +} // namespace interfaces diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index e78adbb79884..0b56f19e865a 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -81,8 +80,6 @@ Q_DECLARE_METATYPE(CAmount) Q_DECLARE_METATYPE(SynchronizationState) Q_DECLARE_METATYPE(uint256) -using node::NodeContext; - static void RegisterMetaTypes() { // Register meta types used for QMetaObject::invokeMethod and Qt::QueuedConnection @@ -511,9 +508,7 @@ int GuiMain(int argc, char* argv[]) std::tie(argc, argv) = winArgs.get(); #endif - NodeContext node_context; - int unused_exit_status; - std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); + std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); SetupEnvironment(); util::ThreadSetInternalName("main"); diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index d2f56ab891d6..a043b24ffe9c 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -45,8 +45,6 @@ Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin) #endif #endif -using node::NodeContext; - const std::function G_TEST_LOG_FUN{}; const std::function()> G_TEST_COMMAND_LINE_ARGUMENTS{}; @@ -64,9 +62,7 @@ int main(int argc, char* argv[]) BasicTestingSetup dummy{CBaseChainParams::REGTEST}; } - NodeContext node_context; - int unused_exit_status; - std::unique_ptr init = interfaces::MakeNodeInit(node_context, argc, argv, unused_exit_status); + std::unique_ptr init = interfaces::MakeGuiInit(argc, argv); gArgs.ForceSetArg("-listen", "0"); gArgs.ForceSetArg("-listenonion", "0"); gArgs.ForceSetArg("-discover", "0");