diff options
-rw-r--r-- | src/rpc/net.cpp | 4 | ||||
-rw-r--r-- | src/wallet/db.h | 1 | ||||
-rw-r--r-- | src/wallet/scriptpubkeyman.cpp | 12 | ||||
-rw-r--r-- | src/wallet/scriptpubkeyman.h | 6 | ||||
-rw-r--r-- | src/wallet/wallet.cpp | 8 | ||||
-rw-r--r-- | src/wallet/wallet.h | 4 | ||||
-rwxr-xr-x | test/functional/feature_anchors.py | 2 | ||||
-rwxr-xr-x | test/functional/p2p_add_connections.py | 2 | ||||
-rwxr-xr-x | test/functional/p2p_addr_relay.py | 1 | ||||
-rwxr-xr-x | test/functional/p2p_sendtxrcncl.py | 4 | ||||
-rwxr-xr-x | test/functional/test_framework/p2p.py | 41 | ||||
-rw-r--r-- | test/functional/test_framework/v2_p2p.py | 1 |
12 files changed, 45 insertions, 41 deletions
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index ff43edba3e..5e6f42b596 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -371,7 +371,7 @@ static RPCHelpMan addconnection() { {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP address and port to attempt connecting to."}, {"connection_type", RPCArg::Type::STR, RPCArg::Optional::NO, "Type of connection to open (\"outbound-full-relay\", \"block-relay-only\", \"addr-fetch\" or \"feeler\")."}, - {"v2transport", RPCArg::Type::BOOL, RPCArg::Default{false}, "Attempt to connect using BIP324 v2 transport protocol"}, + {"v2transport", RPCArg::Type::BOOL, RPCArg::Optional::NO, "Attempt to connect using BIP324 v2 transport protocol"}, }, RPCResult{ RPCResult::Type::OBJ, "", "", @@ -403,7 +403,7 @@ static RPCHelpMan addconnection() } else { throw JSONRPCError(RPC_INVALID_PARAMETER, self.ToString()); } - bool use_v2transport = !request.params[2].isNull() && request.params[2].get_bool(); + bool use_v2transport = self.Arg<bool>(2); NodeContext& node = EnsureAnyNodeContext(request.context); CConnman& connman = EnsureConnman(node); diff --git a/src/wallet/db.h b/src/wallet/db.h index c263f54144..084fcadc24 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -20,7 +20,6 @@ class ArgsManager; struct bilingual_str; namespace wallet { -void SplitWalletPath(const fs::path& wallet_path, fs::path& env_directory, std::string& database_filename); class DatabaseCursor { diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp index dc5c442b95..e07771b17f 100644 --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -225,7 +225,7 @@ isminetype LegacyScriptPubKeyMan::IsMine(const CScript& script) const assert(false); } -bool LegacyScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys) +bool LegacyScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master_key) { { LOCK(cs_KeyStore); @@ -258,7 +258,7 @@ bool LegacyScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master_key LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n"); throw std::runtime_error("Error unlocking wallet: some keys decrypt but not all. Your wallet file may be corrupt."); } - if (keyFail || (!keyPass && !accept_no_keys)) + if (keyFail || !keyPass) return false; fDecryptionThoroughlyChecked = true; } @@ -652,8 +652,6 @@ TransactionError LegacyScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psb // There's no UTXO so we can just skip this now continue; } - SignatureData sigdata; - input.FillSignatureData(sigdata); SignPSBTInput(HidingSigningProvider(this, !sign, !bip32derivs), psbtx, i, &txdata, sighash_type, nullptr, finalize); bool signed_one = PSBTInputSigned(input); @@ -2049,7 +2047,7 @@ isminetype DescriptorScriptPubKeyMan::IsMine(const CScript& script) const return ISMINE_NO; } -bool DescriptorScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys) +bool DescriptorScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master_key) { LOCK(cs_desc_man); if (!m_map_keys.empty()) { @@ -2074,7 +2072,7 @@ bool DescriptorScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master LogPrintf("The wallet is probably corrupted: Some keys decrypt but not all.\n"); throw std::runtime_error("Error unlocking wallet: some keys decrypt but not all. Your wallet file may be corrupt."); } - if (keyFail || (!keyPass && !accept_no_keys)) { + if (keyFail || !keyPass) { return false; } m_decryption_thoroughly_checked = true; @@ -2528,8 +2526,6 @@ TransactionError DescriptorScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& // There's no UTXO so we can just skip this now continue; } - SignatureData sigdata; - input.FillSignatureData(sigdata); std::unique_ptr<FlatSigningProvider> keys = std::make_unique<FlatSigningProvider>(); std::unique_ptr<FlatSigningProvider> script_keys = GetSigningProvider(script, /*include_private=*/sign); diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h index b63ba5bda0..1c99e5ffcd 100644 --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -179,7 +179,7 @@ public: virtual isminetype IsMine(const CScript& script) const { return ISMINE_NO; } //! Check that the given decryption key is valid for this ScriptPubKeyMan, i.e. it decrypts all of the keys handled by it. - virtual bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) { return false; } + virtual bool CheckDecryptionKey(const CKeyingMaterial& master_key) { return false; } virtual bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) { return false; } virtual util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) { return util::Error{Untranslated("Not supported")}; } @@ -379,7 +379,7 @@ public: util::Result<CTxDestination> GetNewDestination(const OutputType type) override; isminetype IsMine(const CScript& script) const override; - bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override; + bool CheckDecryptionKey(const CKeyingMaterial& master_key) override; bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override; util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override; @@ -610,7 +610,7 @@ public: util::Result<CTxDestination> GetNewDestination(const OutputType type) override; isminetype IsMine(const CScript& script) const override; - bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override; + bool CheckDecryptionKey(const CKeyingMaterial& master_key) override; bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override; util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3b59715917..d03a3e979f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -555,7 +555,7 @@ void CWallet::UpgradeDescriptorCache() SetWalletFlag(WALLET_FLAG_LAST_HARDENED_XPUB_CACHED); } -bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys) +bool CWallet::Unlock(const SecureString& strWalletPassphrase) { CCrypter crypter; CKeyingMaterial _vMasterKey; @@ -568,7 +568,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_key return false; if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey)) continue; // try another master key - if (Unlock(_vMasterKey, accept_no_keys)) { + if (Unlock(_vMasterKey)) { // Now that we've unlocked, upgrade the key metadata UpgradeKeyMetadata(); // Now that we've unlocked, upgrade the descriptor cache @@ -3374,12 +3374,12 @@ bool CWallet::Lock() return true; } -bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys) +bool CWallet::Unlock(const CKeyingMaterial& vMasterKeyIn) { { LOCK(cs_wallet); for (const auto& spk_man_pair : m_spk_managers) { - if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn, accept_no_keys)) { + if (!spk_man_pair.second->CheckDecryptionKey(vMasterKeyIn)) { return false; } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index cc961068a5..3c7b0ea490 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -302,7 +302,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati private: CKeyingMaterial vMasterKey GUARDED_BY(cs_wallet); - bool Unlock(const CKeyingMaterial& vMasterKeyIn, bool accept_no_keys = false); + bool Unlock(const CKeyingMaterial& vMasterKeyIn); std::atomic<bool> fAbortRescan{false}; std::atomic<bool> fScanningWallet{false}; // controlled by WalletRescanReserver @@ -578,7 +578,7 @@ public: // Used to prevent deleting the passphrase from memory when it is still in use. RecursiveMutex m_relock_mutex; - bool Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys = false); + bool Unlock(const SecureString& strWalletPassphrase); bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); bool EncryptWallet(const SecureString& strWalletPassphrase); diff --git a/test/functional/feature_anchors.py b/test/functional/feature_anchors.py index 3b75a06d9e..5d68f50f58 100755 --- a/test/functional/feature_anchors.py +++ b/test/functional/feature_anchors.py @@ -99,7 +99,7 @@ class AnchorsTest(BitcoinTestFramework): self.restart_node(0, extra_args=[f"-onion={onion_conf.addr[0]}:{onion_conf.addr[1]}"]) self.log.info("Add 256-bit-address block-relay-only connections to node") - self.nodes[0].addconnection(ONION_ADDR, 'block-relay-only') + self.nodes[0].addconnection(ONION_ADDR, 'block-relay-only', v2transport=False) self.log.debug("Stop node") with self.nodes[0].assert_debug_log([f"DumpAnchors: Flush 1 outbound block-relay-only peer addresses to anchors.dat"]): diff --git a/test/functional/p2p_add_connections.py b/test/functional/p2p_add_connections.py index f4462673f2..bd766a279e 100755 --- a/test/functional/p2p_add_connections.py +++ b/test/functional/p2p_add_connections.py @@ -17,7 +17,7 @@ class P2PFeelerReceiver(P2PInterface): # message is received from the test framework. Don't send any responses # to the node's version message since the connection will already be # closed. - pass + self.send_version() class P2PAddConnections(BitcoinTestFramework): def set_test_params(self): diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py index 2adcaf178c..b23ec1028b 100755 --- a/test/functional/p2p_addr_relay.py +++ b/test/functional/p2p_addr_relay.py @@ -75,6 +75,7 @@ class AddrReceiver(P2PInterface): return self.num_ipv4_received != 0 def on_version(self, message): + self.send_version() self.send_message(msg_verack()) if (self.send_getaddr): self.send_message(msg_getaddr()) diff --git a/test/functional/p2p_sendtxrcncl.py b/test/functional/p2p_sendtxrcncl.py index 0e349ef70c..8f5e6c0387 100755 --- a/test/functional/p2p_sendtxrcncl.py +++ b/test/functional/p2p_sendtxrcncl.py @@ -29,6 +29,7 @@ class PeerNoVerack(P2PInterface): # Avoid sending verack in response to version. # When calling add_p2p_connection, wait_for_verack=False must be set (see # comment in add_p2p_connection). + self.send_version() if message.nVersion >= 70016 and self.wtxidrelay: self.send_message(msg_wtxidrelay()) @@ -43,7 +44,8 @@ class SendTxrcnclReceiver(P2PInterface): class P2PFeelerReceiver(SendTxrcnclReceiver): def on_version(self, message): - pass # feeler connections can not send any message other than their own version + # feeler connections can not send any message other than their own version + self.send_version() class PeerTrackMsgOrder(P2PInterface): diff --git a/test/functional/test_framework/p2p.py b/test/functional/test_framework/p2p.py index c113a4c8d8..dc04696114 100755 --- a/test/functional/test_framework/p2p.py +++ b/test/functional/test_framework/p2p.py @@ -224,11 +224,10 @@ class P2PConnection(asyncio.Protocol): if self.supports_v2_p2p and self.v2_state.initiating and not self.v2_state.tried_v2_handshake: send_handshake_bytes = self.v2_state.initiate_v2_handshake() self.send_raw_message(send_handshake_bytes) - # if v2 connection, send `on_connection_send_msg` after initial v2 handshake. - # if reconnection situation, send `on_connection_send_msg` after version message is received in `on_version()`. - if self.on_connection_send_msg and not self.supports_v2_p2p and not self.reconnect: - self.send_message(self.on_connection_send_msg) - self.on_connection_send_msg = None # Never used again + # for v1 outbound connections, send version message immediately after opening + # (for v2 outbound connections, send it after the initial v2 handshake) + if self.p2p_connected_to_node and not self.supports_v2_p2p: + self.send_version() self.on_open() def connection_lost(self, exc): @@ -243,7 +242,7 @@ class P2PConnection(asyncio.Protocol): self.on_close() # v2 handshake method - def v2_handshake(self): + def _on_data_v2_handshake(self): """v2 handshake performed before P2P messages are exchanged (see BIP324). P2PConnection is the initiator (in inbound connections to TestNode) and the responder (in outbound connections from TestNode). Performed by: @@ -284,9 +283,13 @@ class P2PConnection(asyncio.Protocol): if not is_mac_auth: raise ValueError("invalid v2 mac tag in handshake authentication") self.recvbuf = self.recvbuf[length:] - if self.v2_state.tried_v2_handshake and self.on_connection_send_msg: - self.send_message(self.on_connection_send_msg) - self.on_connection_send_msg = None + if self.v2_state.tried_v2_handshake: + # for v2 outbound connections, send version message immediately after v2 handshake + if self.p2p_connected_to_node: + self.send_version() + # process post-v2-handshake data immediately, if available + if len(self.recvbuf) > 0: + self._on_data() # Socket read methods @@ -295,7 +298,7 @@ class P2PConnection(asyncio.Protocol): if len(t) > 0: self.recvbuf += t if self.supports_v2_p2p and not self.v2_state.tried_v2_handshake: - self.v2_handshake() + self._on_data_v2_handshake() else: self._on_data() @@ -557,11 +560,10 @@ class P2PInterface(P2PConnection): def on_version(self, message): assert message.nVersion >= MIN_P2P_VERSION_SUPPORTED, "Version {} received. Test framework only supports versions greater than {}".format(message.nVersion, MIN_P2P_VERSION_SUPPORTED) - # reconnection using v1 P2P has happened since version message can be processed, previously unsent version message is sent using v1 P2P here - if self.reconnect: - if self.on_connection_send_msg: - self.send_message(self.on_connection_send_msg) - self.on_connection_send_msg = None + # for inbound connections, reply to version with own version message + # (could be due to v1 reconnect after a failed v2 handshake) + if not self.p2p_connected_to_node: + self.send_version() self.reconnect = False if message.nVersion >= 70016 and self.wtxidrelay: self.send_message(msg_wtxidrelay()) @@ -593,9 +595,7 @@ class P2PInterface(P2PConnection): def wait_for_reconnect(self, timeout=60): def test_function(): - if not (self.is_connected and self.last_message.get('version') and self.v2_state is None): - return False - return True + return self.is_connected and self.last_message.get('version') and not self.supports_v2_p2p self.wait_until(test_function, timeout=timeout, check_connected=False) # Message receiving helper methods @@ -676,6 +676,11 @@ class P2PInterface(P2PConnection): # Message sending helper functions + def send_version(self): + if self.on_connection_send_msg: + self.send_message(self.on_connection_send_msg) + self.on_connection_send_msg = None # Never used again + def send_and_ping(self, message, timeout=60): self.send_message(message) self.sync_with_ping(timeout=timeout) diff --git a/test/functional/test_framework/v2_p2p.py b/test/functional/test_framework/v2_p2p.py index 0b3979fba2..8f79623bd8 100644 --- a/test/functional/test_framework/v2_p2p.py +++ b/test/functional/test_framework/v2_p2p.py @@ -220,6 +220,7 @@ class EncryptedP2PState: # decoy packets have contents = None. v2 handshake is complete only when version packet # (can be empty with contents = b"") with contents != None is received. if contents is not None: + assert contents == b"" # currently TestNode sends an empty version packet self.tried_v2_handshake = True return processed_length, True response = response[length:] |