diff options
author | Andrew Chow <achow101-github@achow101.com> | 2021-12-20 14:40:00 -0500 |
---|---|---|
committer | Andrew Chow <achow101-github@achow101.com> | 2021-12-20 14:48:22 -0500 |
commit | 3ac38058ce0e80a9f4276bfa82951decdb237e9a (patch) | |
tree | a0bb6697b1fd82fac83cb6431635d11a30dc74f4 /src | |
parent | 9ac064d245f0fd4cb0362cfc472b65836328bffe (diff) | |
parent | fada6c65d23f7bd4682fac281026612b835c4f8b (diff) |
Merge bitcoin/bitcoin#23789: wallet: Strictly match tx change type to improve privacy
fada6c65d23f7bd4682fac281026612b835c4f8b wallet: Strictly match tx change type to improve privacy (MarcoFalke)
Pull request description:
Currently the change type will only match a destination by accident, making it easier to determine the change.
Fix that by strictly matching one of the destinations.
ACKs for top commit:
S3RK:
Concept & Approach ACK fada6c6. Also did light code review .
achow101:
ACK fada6c65d23f7bd4682fac281026612b835c4f8b
prayank23:
tACK https://github.com/bitcoin/bitcoin/pull/23789/commits/fada6c65d23f7bd4682fac281026612b835c4f8b
w0xlt:
tACK fada6c6
Tree-SHA512: 2b072c3c32debac7b0bef07a6df9a8f1a631e0f7d556b859973f18894ca490225582dc13e4588b29fa205ffbcd30fb632d5313b304d10ad17a26adc3f7684471
Diffstat (limited to 'src')
-rw-r--r-- | src/wallet/wallet.cpp | 61 |
1 files changed, 45 insertions, 16 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index decdbc7090..6e1552abd7 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1967,29 +1967,58 @@ OutputType CWallet::TransactionChangeType(const std::optional<OutputType>& chang return *change_type; } - // if m_default_address_type is legacy, use legacy address as change (even - // if some of the outputs are P2WPKH or P2WSH). + // if m_default_address_type is legacy, use legacy address as change. if (m_default_address_type == OutputType::LEGACY) { return OutputType::LEGACY; } - // if any destination is P2WPKH or P2WSH, use P2WPKH for the change - // output. + bool any_tr{false}; + bool any_wpkh{false}; + bool any_sh{false}; + bool any_pkh{false}; + for (const auto& recipient : vecSend) { - // Check if any destination contains a witness program: - int witnessversion = 0; - std::vector<unsigned char> witnessprogram; - if (recipient.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) { - if (GetScriptPubKeyMan(OutputType::BECH32M, true)) { - return OutputType::BECH32M; - } else if (GetScriptPubKeyMan(OutputType::BECH32, true)) { - return OutputType::BECH32; - } else { - return m_default_address_type; - } - } + std::vector<std::vector<uint8_t>> dummy; + const TxoutType type{Solver(recipient.scriptPubKey, dummy)}; + if (type == TxoutType::WITNESS_V1_TAPROOT) { + any_tr = true; + } else if (type == TxoutType::WITNESS_V0_KEYHASH) { + any_wpkh = true; + } else if (type == TxoutType::SCRIPTHASH) { + any_sh = true; + } else if (type == TxoutType::PUBKEYHASH) { + any_pkh = true; + } + } + + const bool has_bech32m_spkman(GetScriptPubKeyMan(OutputType::BECH32M, /*internal=*/true)); + if (has_bech32m_spkman && any_tr) { + // Currently tr is the only type supported by the BECH32M spkman + return OutputType::BECH32M; + } + const bool has_bech32_spkman(GetScriptPubKeyMan(OutputType::BECH32, /*internal=*/true)); + if (has_bech32_spkman && any_wpkh) { + // Currently wpkh is the only type supported by the BECH32 spkman + return OutputType::BECH32; + } + const bool has_p2sh_segwit_spkman(GetScriptPubKeyMan(OutputType::P2SH_SEGWIT, /*internal=*/true)); + if (has_p2sh_segwit_spkman && any_sh) { + // Currently sh_wpkh is the only type supported by the P2SH_SEGWIT spkman + // As of 2021 about 80% of all SH are wrapping WPKH, so use that + return OutputType::P2SH_SEGWIT; + } + const bool has_legacy_spkman(GetScriptPubKeyMan(OutputType::LEGACY, /*internal=*/true)); + if (has_legacy_spkman && any_pkh) { + // Currently pkh is the only type supported by the LEGACY spkman + return OutputType::LEGACY; } + if (has_bech32m_spkman) { + return OutputType::BECH32M; + } + if (has_bech32_spkman) { + return OutputType::BECH32; + } // else use m_default_address_type for change return m_default_address_type; } |