From 596c44633fd03e76cc12f2fd37452e223ba43115 Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Tue, 23 Jan 2018 17:56:15 +0100 Subject: [wallet] use P2WPKH change output if any destination is P2WPKH or P2WSH Only if -changetype is not set and -addresstype is not "legacy". --- src/wallet/wallet.cpp | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'src/wallet/wallet.cpp') diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index da721ea00..c80433895 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2644,6 +2644,34 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC return true; } +OutputType CWallet::TransactionChangeType(const std::vector& vecSend) +{ + // If -changetype is specified, always use that change type. + if (g_change_type != OUTPUT_TYPE_NONE) { + return g_change_type; + } + + // if g_address_type is legacy, use legacy address as change (even + // if some of the outputs are P2WPKH or P2WSH). + if (g_address_type == OUTPUT_TYPE_LEGACY) { + return OUTPUT_TYPE_LEGACY; + } + + // if any destination is P2WPKH or P2WSH, use P2WPKH for the change + // output. + for (const auto& recipient : vecSend) { + // Check if any destination contains a witness program: + int witnessversion = 0; + std::vector witnessprogram; + if (recipient.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) { + return OUTPUT_TYPE_BECH32; + } + } + + // else use g_address_type for change + return g_address_type; +} + bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign) { @@ -2739,8 +2767,10 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT return false; } - LearnRelatedScripts(vchPubKey, g_change_type); - scriptChange = GetScriptForDestination(GetDestinationForKey(vchPubKey, g_change_type)); + const OutputType change_type = TransactionChangeType(vecSend); + + LearnRelatedScripts(vchPubKey, change_type); + scriptChange = GetScriptForDestination(GetDestinationForKey(vchPubKey, change_type)); } CTxOut change_prototype_txout(0, scriptChange); size_t change_prototype_size = GetSerializeSize(change_prototype_txout, SER_DISK, 0); -- cgit v1.2.3