aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormerge-script <fanquake@gmail.com>2024-07-24 10:31:55 +0100
committermerge-script <fanquake@gmail.com>2024-07-24 10:31:55 +0100
commit0cbdc6b3802d10be7772006801b1dfe8a9eaaa83 (patch)
tree5cabf81b1e6e940e863ac5c49523a6afd866dad3
parentb6440f20f2cc4b30fc2e3432a57eaf9ba0f653cc (diff)
parent4f23c8636498f7e5adbe0264a0dc66a566c4b1b9 (diff)
Merge bitcoin/bitcoin#30467: [27.x] More backports
4f23c8636498f7e5adbe0264a0dc66a566c4b1b9 [WIP] doc: update release notes for 27.x (fanquake) 54bb9b0541d44972726a187e382a6b267942f47a test: add test for modififed walletprocesspsbt calls (willcl-ark) f22b9ca70c867a02d6f578dc56d4997b7a4ff9c9 wallet: fix FillPSBT errantly showing as complete (willcl-ark) 05192ba84c2d0ef727c9dbc1e6af4ce8a59458fa init: change shutdown order of load block thread and scheduler (Martin Zumsande) ab422066527992d53c92bb482c6b993f089b2999 Reapply "test: p2p: check that connecting to ourself leads to disconnect" (Sebastian Falbesoner) 064f2146735c88823f73f7531fc36d21d1ddb6f3 net: prevent sending messages in `NetEventsInterface::InitializeNode` (Sebastian Falbesoner) 0933cf53b48a160612873978f38ef4ff70e74847 net: fix race condition in self-connect detection (Sebastian Falbesoner) fa90989503494b77a0329390dc5e32d0c5e5c283 psbt: Check non witness utxo outpoint early (Ava Chow) Pull request description: Backports: * https://github.com/bitcoin/bitcoin/pull/29855 * https://github.com/bitcoin/bitcoin/pull/30357 * https://github.com/bitcoin/bitcoin/pull/30394 (modified test commit) * https://github.com/bitcoin/bitcoin/pull/30435 ACKs for top commit: stickies-v: ACK 4f23c8636498f7e5adbe0264a0dc66a566c4b1b9 willcl-ark: ACK 4f23c8636498f7e5adbe0264a0dc66a566c4b1b9 Tree-SHA512: 5c26445f0855f9d14890369ce19873b0686804eeb659e7d6da36a6f404f64d019436e1e6471579eaa60a96ebf8f64311883b4aef9d0ed528a95bd610c101c079
-rw-r--r--doc/release-notes.md20
-rw-r--r--src/init.cpp5
-rw-r--r--src/net.h4
-rw-r--r--src/net_processing.cpp20
-rw-r--r--src/psbt.h9
-rw-r--r--src/test/util/net.cpp3
-rw-r--r--src/wallet/wallet.cpp4
-rw-r--r--test/functional/data/rpc_psbt.json4
-rwxr-xr-xtest/functional/p2p_handshake.py26
-rwxr-xr-xtest/functional/rpc_psbt.py29
-rwxr-xr-xtest/functional/test_runner.py2
11 files changed, 107 insertions, 19 deletions
diff --git a/doc/release-notes.md b/doc/release-notes.md
index e14001bf77..c5e3e6826e 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -40,6 +40,22 @@ unsupported systems.
Notable changes
===============
+### P2P
+
+- #30394 net: fix race condition in self-connect detection
+
+### Init
+
+- #30435 init: change shutdown order of load block thread and scheduler
+
+### RPC
+
+- #30357 Fix cases of calls to FillPSBT errantly returning complete=true
+
+### PSBT
+
+- #29855 psbt: Check non witness utxo outpoint early
+
### Build
- #30283 upnp: fix build with miniupnpc 2.2.8
@@ -54,8 +70,12 @@ Credits
Thanks to everyone who directly contributed to this release:
+- Ava Chow
- Cory Fields
+- Martin Zumsande
- Max Edwards
+- Sebastian Falbesoner
+- willcl-ark
As well as to everyone that helped with translations on
[Transifex](https://www.transifex.com/bitcoin/bitcoin/).
diff --git a/src/init.cpp b/src/init.cpp
index 988daefeec..a569c3bd0d 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -296,10 +296,11 @@ void Shutdown(NodeContext& node)
StopTorControl();
+ if (node.chainman && node.chainman->m_thread_load.joinable()) node.chainman->m_thread_load.join();
// After everything has been shut down, but before things get flushed, stop the
- // scheduler and load block thread.
+ // the scheduler. After this point, SyncWithValidationInterfaceQueue() should not be called anymore
+ // as this would prevent the shutdown from completing.
if (node.scheduler) node.scheduler->stop();
- if (node.chainman && node.chainman->m_thread_load.joinable()) node.chainman->m_thread_load.join();
// After the threads that potentially access these pointers have been stopped,
// destruct and reset all to nullptr.
diff --git a/src/net.h b/src/net.h
index e78e122c44..b27474a836 100644
--- a/src/net.h
+++ b/src/net.h
@@ -999,8 +999,8 @@ public:
/** Mutex for anything that is only accessed via the msg processing thread */
static Mutex g_msgproc_mutex;
- /** Initialize a peer (setup state, queue any initial messages) */
- virtual void InitializeNode(CNode& node, ServiceFlags our_services) = 0;
+ /** Initialize a peer (setup state) */
+ virtual void InitializeNode(const CNode& node, ServiceFlags our_services) = 0;
/** Handle removal of a peer (clear state) */
virtual void FinalizeNode(const CNode& node) = 0;
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 99ae0e8fa1..15a6ddb8ae 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -245,6 +245,9 @@ struct Peer {
* Most peers use headers-first syncing, which doesn't use this mechanism */
uint256 m_continuation_block GUARDED_BY(m_block_inv_mutex) {};
+ /** Set to true once initial VERSION message was sent (only relevant for outbound peers). */
+ bool m_outbound_version_message_sent GUARDED_BY(NetEventsInterface::g_msgproc_mutex){false};
+
/** This peer's reported block height when we connected */
std::atomic<int> m_starting_height{-1};
@@ -499,7 +502,7 @@ public:
EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex);
/** Implement NetEventsInterface */
- void InitializeNode(CNode& node, ServiceFlags our_services) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
+ void InitializeNode(const CNode& node, ServiceFlags our_services) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
void FinalizeNode(const CNode& node) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_headers_presync_mutex);
bool HasAllDesirableServiceFlags(ServiceFlags services) const override;
bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override
@@ -1563,7 +1566,7 @@ void PeerManagerImpl::UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_s
if (state) state->m_last_block_announcement = time_in_seconds;
}
-void PeerManagerImpl::InitializeNode(CNode& node, ServiceFlags our_services)
+void PeerManagerImpl::InitializeNode(const CNode& node, ServiceFlags our_services)
{
NodeId nodeid = node.GetId();
{
@@ -1576,9 +1579,6 @@ void PeerManagerImpl::InitializeNode(CNode& node, ServiceFlags our_services)
LOCK(m_peer_mutex);
m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
}
- if (!node.IsInboundConn()) {
- PushNodeVersion(node, *peer);
- }
}
void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler)
@@ -5060,6 +5060,10 @@ bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt
PeerRef peer = GetPeerRef(pfrom->GetId());
if (peer == nullptr) return false;
+ // For outbound connections, ensure that the initial VERSION message
+ // has been sent first before processing any incoming messages
+ if (!pfrom->IsInboundConn() && !peer->m_outbound_version_message_sent) return false;
+
{
LOCK(peer->m_getdata_requests_mutex);
if (!peer->m_getdata_requests.empty()) {
@@ -5548,6 +5552,12 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
// disconnect misbehaving peers even before the version handshake is complete.
if (MaybeDiscourageAndDisconnect(*pto, *peer)) return true;
+ // Initiate version handshake for outbound connections
+ if (!pto->IsInboundConn() && !peer->m_outbound_version_message_sent) {
+ PushNodeVersion(*pto, *peer);
+ peer->m_outbound_version_message_sent = true;
+ }
+
// Don't send anything until the version handshake is complete
if (!pto->fSuccessfullyConnected || pto->fDisconnect)
return true;
diff --git a/src/psbt.h b/src/psbt.h
index 3f74083717..a6837fda49 100644
--- a/src/psbt.h
+++ b/src/psbt.h
@@ -1173,8 +1173,13 @@ struct PartiallySignedTransaction
inputs.push_back(input);
// Make sure the non-witness utxo matches the outpoint
- if (input.non_witness_utxo && input.non_witness_utxo->GetHash() != tx->vin[i].prevout.hash) {
- throw std::ios_base::failure("Non-witness UTXO does not match outpoint hash");
+ if (input.non_witness_utxo) {
+ if (input.non_witness_utxo->GetHash() != tx->vin[i].prevout.hash) {
+ throw std::ios_base::failure("Non-witness UTXO does not match outpoint hash");
+ }
+ if (tx->vin[i].prevout.n >= input.non_witness_utxo->vout.size()) {
+ throw std::ios_base::failure("Input specifies output index that does not exist");
+ }
}
++i;
}
diff --git a/src/test/util/net.cpp b/src/test/util/net.cpp
index 9257a4964a..7cbb9d737b 100644
--- a/src/test/util/net.cpp
+++ b/src/test/util/net.cpp
@@ -28,7 +28,8 @@ void ConnmanTestMsg::Handshake(CNode& node,
auto& connman{*this};
peerman.InitializeNode(node, local_services);
- FlushSendBuffer(node); // Drop the version message added by InitializeNode.
+ peerman.SendMessages(&node);
+ FlushSendBuffer(node); // Drop the version message added by SendMessages.
CSerializedNetMsg msg_version{
NetMsg::Make(NetMsgType::VERSION,
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 3ac09430d8..af85f561b6 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2184,8 +2184,8 @@ TransactionError CWallet::FillPSBT(PartiallySignedTransaction& psbtx, bool& comp
// Complete if every input is now signed
complete = true;
- for (const auto& input : psbtx.inputs) {
- complete &= PSBTInputSigned(input);
+ for (size_t i = 0; i < psbtx.inputs.size(); ++i) {
+ complete &= PSBTInputSignedAndVerified(psbtx, i, &txdata);
}
return TransactionError::OK;
diff --git a/test/functional/data/rpc_psbt.json b/test/functional/data/rpc_psbt.json
index 3127350872..1ccc5e0ba0 100644
--- a/test/functional/data/rpc_psbt.json
+++ b/test/functional/data/rpc_psbt.json
@@ -38,7 +38,9 @@
"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",
- "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"
+ "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"
],
"invalid_with_msg": [
[
diff --git a/test/functional/p2p_handshake.py b/test/functional/p2p_handshake.py
new file mode 100755
index 0000000000..29d88db3c9
--- /dev/null
+++ b/test/functional/p2p_handshake.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+# Copyright (c) 2024 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""
+Test P2P behaviour during the handshake phase.
+"""
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import p2p_port
+
+
+class P2PHandshakeTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+
+ def run_test(self):
+ node = self.nodes[0]
+ self.log.info("Check that connecting to ourself leads to immediate disconnect")
+ with node.assert_debug_log(["connected to self", "disconnecting"]):
+ node_listen_addr = f"127.0.0.1:{p2p_port(0)}"
+ node.addconnection(node_listen_addr, "outbound-full-relay", self.options.v2transport)
+ self.wait_until(lambda: len(node.getpeerinfo()) == 0)
+
+
+if __name__ == '__main__':
+ P2PHandshakeTest().main()
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py
index 117a65121d..c86fd8c921 100755
--- a/test/functional/rpc_psbt.py
+++ b/test/functional/rpc_psbt.py
@@ -69,6 +69,28 @@ class PSBTTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
+ def test_psbt_incomplete_after_invalid_modification(self):
+ self.log.info("Check that PSBT is correctly marked as incomplete after invalid modification")
+ node = self.nodes[2]
+ wallet = node.get_wallet_rpc(self.default_wallet_name)
+ address = wallet.getnewaddress()
+ wallet.sendtoaddress(address=address, amount=1.0)
+ self.generate(node, nblocks=1, sync_fun=lambda: self.sync_all(self.nodes[:2]))
+
+ utxos = wallet.listunspent(addresses=[address])
+ psbt = wallet.createpsbt([{"txid": utxos[0]["txid"], "vout": utxos[0]["vout"]}], [{wallet.getnewaddress(): 0.9999}])
+ signed_psbt = wallet.walletprocesspsbt(psbt)["psbt"]
+
+ # Modify the raw transaction by changing the output address, so the signature is no longer valid
+ signed_psbt_obj = PSBT.from_base64(signed_psbt)
+ substitute_addr = wallet.getnewaddress()
+ raw = wallet.createrawtransaction([{"txid": utxos[0]["txid"], "vout": utxos[0]["vout"]}], [{substitute_addr: 0.9999}])
+ signed_psbt_obj.g.map[PSBT_GLOBAL_UNSIGNED_TX] = bytes.fromhex(raw)
+
+ # Check that the walletprocesspsbt call succeeds but also recognizes that the transaction is not complete
+ signed_psbt_incomplete = wallet.walletprocesspsbt(signed_psbt_obj.to_base64(), finalize=False)
+ assert signed_psbt_incomplete["complete"] is False
+
def test_utxo_conversion(self):
self.log.info("Check that non-witness UTXOs are removed for segwit v1+ inputs")
mining_node = self.nodes[2]
@@ -590,6 +612,7 @@ class PSBTTest(BitcoinTestFramework):
if self.options.descriptors:
self.test_utxo_conversion()
+ self.test_psbt_incomplete_after_invalid_modification()
self.test_input_confs_control()
@@ -701,11 +724,9 @@ class PSBTTest(BitcoinTestFramework):
assert_equal(analysis['next'], 'creator')
assert_equal(analysis['error'], 'PSBT is not valid. Output amount invalid')
- analysis = self.nodes[0].analyzepsbt('cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==')
- assert_equal(analysis['next'], 'creator')
- assert_equal(analysis['error'], 'PSBT is not valid. Input 0 specifies invalid prevout')
+ assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].analyzepsbt, "cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==")
- assert_raises_rpc_error(-25, 'Inputs missing or spent', self.nodes[0].walletprocesspsbt, 'cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==')
+ assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].walletprocesspsbt, "cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==")
self.log.info("Test that we can fund psbts with external inputs specified")
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index a23c5f7333..3eb2733cc1 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -395,6 +395,8 @@ BASE_SCRIPTS = [
'rpc_getdescriptorinfo.py',
'rpc_mempool_info.py',
'rpc_help.py',
+ 'p2p_handshake.py',
+ 'p2p_handshake.py --v2transport',
'feature_dirsymlinks.py',
'feature_help.py',
'feature_shutdown.py',