aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/qt/bitcoinstrings.cpp9
-rw-r--r--src/qt/locale/bitcoin_en.ts52
-rw-r--r--src/wallet/coincontrol.h4
-rw-r--r--src/wallet/init.cpp8
-rw-r--r--src/wallet/rpcwallet.cpp32
-rw-r--r--src/wallet/wallet.cpp8
-rw-r--r--src/wallet/wallet.h2
-rwxr-xr-xtest/functional/fundrawtransaction.py13
-rwxr-xr-xtest/functional/nulldummy.py2
-rwxr-xr-xtest/functional/segwit.py5
10 files changed, 71 insertions, 64 deletions
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 03aceb4d9e..adf001c968 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -251,13 +251,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Warning: We do not appear to fully agree with our peers! You may need to "
"upgrade, or other nodes may need to upgrade."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"What type of addresses to use (\"legacy\", \"p2sh-segwit\", or \"bech32\", "
-"default: \"%s\")"),
-QT_TRANSLATE_NOOP("bitcoin-core", ""
-"What type of change to use (\"legacy\", \"p2sh-segwit\", or \"bech32\"). "
-"Default is same as -addresstype, except when -addresstype=p2sh-segwit a "
-"native segwit output is used when sending to a native segwit address)"),
-QT_TRANSLATE_NOOP("bitcoin-core", ""
"Whether to save the mempool on shutdown and load on restart (default: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR "
@@ -414,8 +407,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind r
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer. %s is probably already running."),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to generate initial keys"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to start HTTP server. See debug log for details."),
-QT_TRANSLATE_NOOP("bitcoin-core", "Unknown address type '%s'"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Unknown change type '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported argument -benchmark ignored, use -debug=bench."),
QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported argument -debugnet ignored, use -debug=net."),
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index a892da4cbd..2b712b4317 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -4025,7 +4025,7 @@
<context>
<name>bitcoin-core</name>
<message>
- <location filename="../bitcoinstrings.cpp" line="+358"/>
+ <location filename="../bitcoinstrings.cpp" line="+351"/>
<source>Options:</source>
<translation>Options:</translation>
</message>
@@ -4050,7 +4050,7 @@
<translation>Accept command line and JSON-RPC commands</translation>
</message>
<message>
- <location line="-216"/>
+ <location line="-209"/>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
<translation type="unfinished"></translation>
</message>
@@ -4075,7 +4075,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+158"/>
+ <location line="+151"/>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation type="unfinished"></translation>
</message>
@@ -4100,7 +4100,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-404"/>
+ <location line="-397"/>
<source>Bitcoin Core</source>
<translation type="unfinished">Bitcoin Core</translation>
</message>
@@ -4265,7 +4265,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
+ <location line="+3"/>
<source>Whether to save the mempool on shutdown and load on restart (default: %u)</source>
<translation type="unfinished"></translation>
</message>
@@ -4565,7 +4565,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+4"/>
<source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
<translation type="unfinished"></translation>
</message>
@@ -4625,7 +4625,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-406"/>
+ <location line="-397"/>
<source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times</source>
<translation type="unfinished"></translation>
</message>
@@ -4685,7 +4685,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+71"/>
+ <location line="+64"/>
<source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
<translation type="unfinished"></translation>
</message>
@@ -4870,17 +4870,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
- <source>Unknown address type &apos;%s&apos;</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
- <source>Unknown change type &apos;%s&apos;</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+6"/>
+ <location line="+7"/>
<source>Upgrade wallet to latest format on startup</source>
<translation type="unfinished"></translation>
</message>
@@ -4930,22 +4920,22 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-82"/>
+ <location line="-80"/>
<source>Password for JSON-RPC connections</source>
<translation>Password for JSON-RPC connections</translation>
</message>
<message>
- <location line="-270"/>
+ <location line="-263"/>
<source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
<translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation>
</message>
<message>
- <location line="+192"/>
+ <location line="+185"/>
<source>Allow DNS lookups for -addnode, -seednode and -connect</source>
<translation>Allow DNS lookups for -addnode, -seednode and -connect</translation>
</message>
<message>
- <location line="-267"/>
+ <location line="-260"/>
<source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
<translation type="unfinished"></translation>
</message>
@@ -5085,17 +5075,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
- <source>What type of addresses to use (&quot;legacy&quot;, &quot;p2sh-segwit&quot;, or &quot;bech32&quot;, default: &quot;%s&quot;)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+3"/>
- <source>What type of change to use (&quot;legacy&quot;, &quot;p2sh-segwit&quot;, or &quot;bech32&quot;). Default is same as -addresstype, except when -addresstype=p2sh-segwit a native segwit output is used when sending to a native segwit address)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+6"/>
+ <location line="+9"/>
<source>Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.</source>
<translation type="unfinished"></translation>
</message>
@@ -5265,12 +5245,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+9"/>
+ <location line="+7"/>
<source>Unknown network specified in -onlynet: &apos;%s&apos;</source>
<translation>Unknown network specified in -onlynet: &apos;%s&apos;</translation>
</message>
<message>
- <location line="-87"/>
+ <location line="-85"/>
<source>Insufficient funds</source>
<translation>Insufficient funds</translation>
</message>
diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h
index e1afa2de03..458e770e03 100644
--- a/src/wallet/coincontrol.h
+++ b/src/wallet/coincontrol.h
@@ -16,7 +16,10 @@
class CCoinControl
{
public:
+ //! Custom change destination, if not set an address is generated
CTxDestination destChange;
+ //! Custom change type, ignored if destChange is set, defaults to g_change_type
+ OutputType change_type;
//! If false, allows unselected inputs, but requires all selected inputs be used
bool fAllowOtherInputs;
//! Includes watch only addresses which match the ISMINE_WATCH_SOLVABLE criteria
@@ -40,6 +43,7 @@ public:
void SetNull()
{
destChange = CNoDestination();
+ change_type = g_change_type;
fAllowOtherInputs = false;
fAllowWatchOnly = false;
setSelected.clear();
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index c7f19bc90a..ace95204b8 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -16,8 +16,8 @@
std::string GetWalletHelpString(bool showDebug)
{
std::string strUsage = HelpMessageGroup(_("Wallet options:"));
- strUsage += HelpMessageOpt("-addresstype", strprintf(_("What type of addresses to use (\"legacy\", \"p2sh-segwit\", or \"bech32\", default: \"%s\")"), FormatOutputType(OUTPUT_TYPE_DEFAULT)));
- strUsage += HelpMessageOpt("-changetype", _("What type of change to use (\"legacy\", \"p2sh-segwit\", or \"bech32\"). Default is same as -addresstype, except when -addresstype=p2sh-segwit a native segwit output is used when sending to a native segwit address)"));
+ strUsage += HelpMessageOpt("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", or \"bech32\", default: \"%s\")", FormatOutputType(OUTPUT_TYPE_DEFAULT)));
+ strUsage += HelpMessageOpt("-changetype", "What type of change to use (\"legacy\", \"p2sh-segwit\", or \"bech32\"). Default is same as -addresstype, except when -addresstype=p2sh-segwit a native segwit output is used when sending to a native segwit address)");
strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"));
strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), DEFAULT_KEYPOOL_SIZE));
strUsage += HelpMessageOpt("-fallbackfee=<amt>", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"),
@@ -179,14 +179,14 @@ bool WalletParameterInteraction()
g_address_type = ParseOutputType(gArgs.GetArg("-addresstype", ""));
if (g_address_type == OUTPUT_TYPE_NONE) {
- return InitError(strprintf(_("Unknown address type '%s'"), gArgs.GetArg("-addresstype", "")));
+ return InitError(strprintf("Unknown address type '%s'", gArgs.GetArg("-addresstype", "")));
}
// If changetype is set in config file or parameter, check that it's valid.
// Default to OUTPUT_TYPE_NONE if not set.
g_change_type = ParseOutputType(gArgs.GetArg("-changetype", ""), OUTPUT_TYPE_NONE);
if (g_change_type == OUTPUT_TYPE_NONE && !gArgs.GetArg("-changetype", "").empty()) {
- return InitError(strprintf(_("Unknown change type '%s'"), gArgs.GetArg("-changetype", "")));
+ return InitError(strprintf("Unknown change type '%s'", gArgs.GetArg("-changetype", "")));
}
return true;
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 6849671dcf..fcee22a14a 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1169,9 +1169,8 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
- {
- std::string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
+ if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) {
+ std::string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" \"address_type\" )\n"
"\nAdd a nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n"
"Each key is a Bitcoin address or hex-encoded public key.\n"
"This functionality is only intended for use with non-watchonly addresses.\n"
@@ -1186,6 +1185,7 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
" ...,\n"
" ]\n"
"3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n"
+ "4. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -addresstype.\n"
"\nResult:\n"
"{\n"
@@ -1224,10 +1224,18 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
}
}
+ OutputType output_type = g_address_type;
+ if (!request.params[3].isNull()) {
+ output_type = ParseOutputType(request.params[3].get_str(), output_type);
+ if (output_type == OUTPUT_TYPE_NONE) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[3].get_str()));
+ }
+ }
+
// Construct using pay-to-script-hash:
CScript inner = CreateMultisigRedeemscript(required, pubkeys);
pwallet->AddCScript(inner);
- CTxDestination dest = pwallet->AddAndGetDestinationForScript(inner, g_address_type);
+ CTxDestination dest = pwallet->AddAndGetDestinationForScript(inner, output_type);
pwallet->SetAddressBook(dest, strAccount, "send");
// Return old style interface
@@ -3057,6 +3065,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
" {\n"
" \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n"
" \"changePosition\" (numeric, optional, default random) The index of the change output\n"
+ " \"change_type\" (string, optional) The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is set by -changetype.\n"
" \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
" \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
" \"feeRate\" (numeric, optional, default not set: makes wallet determine the fee) Set a specific fee rate in " + CURRENCY_UNIT + "/kB\n"
@@ -3077,7 +3086,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
" for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
"3. iswitness (boolean, optional) Whether the transaction hex is a serialized witness transaction \n"
" If iswitness is not present, heuristic tests will be used in decoding\n"
-
+
"\nResult:\n"
"{\n"
" \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
@@ -3122,6 +3131,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
{
{"changeAddress", UniValueType(UniValue::VSTR)},
{"changePosition", UniValueType(UniValue::VNUM)},
+ {"change_type", UniValueType(UniValue::VSTR)},
{"includeWatching", UniValueType(UniValue::VBOOL)},
{"lockUnspents", UniValueType(UniValue::VBOOL)},
{"reserveChangeKey", UniValueType(UniValue::VBOOL)}, // DEPRECATED (and ignored), should be removed in 0.16 or so.
@@ -3146,6 +3156,16 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
if (options.exists("changePosition"))
changePosition = options["changePosition"].get_int();
+ if (options.exists("change_type")) {
+ if (options.exists("changeAddress")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both changeAddress and address_type options");
+ }
+ coinControl.change_type = ParseOutputType(options["change_type"].get_str(), coinControl.change_type);
+ if (coinControl.change_type == OUTPUT_TYPE_NONE) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown change type '%s'", options["change_type"].get_str()));
+ }
+ }
+
if (options.exists("includeWatching"))
coinControl.fAllowWatchOnly = options["includeWatching"].get_bool();
@@ -3519,7 +3539,7 @@ static const CRPCCommand commands[] =
{ "hidden", "resendwallettransactions", &resendwallettransactions, {} },
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },
{ "wallet", "abortrescan", &abortrescan, {} },
- { "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account"} },
+ { "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","account","address_type"} },
{ "hidden", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} },
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 7fb26900e1..07a23ce249 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2674,11 +2674,11 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
return true;
}
-OutputType CWallet::TransactionChangeType(const std::vector<CRecipient>& vecSend)
+OutputType CWallet::TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend)
{
// If -changetype is specified, always use that change type.
- if (g_change_type != OUTPUT_TYPE_NONE) {
- return g_change_type;
+ if (change_type != OUTPUT_TYPE_NONE) {
+ return change_type;
}
// if g_address_type is legacy, use legacy address as change (even
@@ -2797,7 +2797,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
return false;
}
- const OutputType change_type = TransactionChangeType(vecSend);
+ const OutputType change_type = TransactionChangeType(coin_control.change_type, vecSend);
LearnRelatedScripts(vchPubKey, change_type);
scriptChange = GetScriptForDestination(GetDestinationForKey(vchPubKey, change_type));
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index e8f536634e..a4684c2935 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -965,7 +965,7 @@ public:
CAmount GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account) const;
CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const;
- OutputType TransactionChangeType(const std::vector<CRecipient>& vecSend);
+ OutputType TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend);
/**
* Insert additional inputs into the transaction by
diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py
index b3d6549229..5f7a0586e0 100755
--- a/test/functional/fundrawtransaction.py
+++ b/test/functional/fundrawtransaction.py
@@ -212,6 +212,19 @@ class RawTransactionsTest(BitcoinTestFramework):
out = dec_tx['vout'][0]
assert_equal(change, out['scriptPubKey']['addresses'][0])
+ #########################################################
+ # test a fundrawtransaction with a provided change type #
+ #########################################################
+ utx = get_unspent(self.nodes[2].listunspent(), 5)
+
+ inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
+ outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[2].fundrawtransaction, rawtx, {'change_type': None})
+ assert_raises_rpc_error(-5, "Unknown change type", self.nodes[2].fundrawtransaction, rawtx, {'change_type': ''})
+ rawtx = self.nodes[2].fundrawtransaction(rawtx, {'change_type': 'bech32'})
+ tx = self.nodes[2].decoderawtransaction(rawtx['hex'])
+ assert_equal('witness_v0_keyhash', tx['vout'][rawtx['changepos']]['scriptPubKey']['type'])
#########################################################################
# test a fundrawtransaction with a VIN smaller than the required amount #
diff --git a/test/functional/nulldummy.py b/test/functional/nulldummy.py
index fac620bc8d..e4f413cc2a 100755
--- a/test/functional/nulldummy.py
+++ b/test/functional/nulldummy.py
@@ -48,7 +48,7 @@ class NULLDUMMYTest(BitcoinTestFramework):
self.address = self.nodes[0].getnewaddress()
self.ms_address = self.nodes[0].addmultisigaddress(1,[self.address])['address']
self.wit_address = self.nodes[0].addwitnessaddress(self.address)
- self.wit_ms_address = self.nodes[0].addwitnessaddress(self.ms_address)
+ self.wit_ms_address = self.nodes[0].addmultisigaddress(1, [self.address], '', 'p2sh-segwit')['address']
network_thread_start()
self.coinbase_blocks = self.nodes[0].generate(2) # Block 2
diff --git a/test/functional/segwit.py b/test/functional/segwit.py
index 931ebdea39..ba6373fa33 100755
--- a/test/functional/segwit.py
+++ b/test/functional/segwit.py
@@ -95,12 +95,11 @@ class SegWitTest(BitcoinTestFramework):
for i in range(3):
newaddress = self.nodes[i].getnewaddress()
self.pubkey.append(self.nodes[i].validateaddress(newaddress)["pubkey"])
- multiaddress = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]])['address']
multiscript = CScript([OP_1, hex_str_to_bytes(self.pubkey[-1]), OP_1, OP_CHECKMULTISIG])
p2sh_addr = self.nodes[i].addwitnessaddress(newaddress)
bip173_addr = self.nodes[i].addwitnessaddress(newaddress, False)
- p2sh_ms_addr = self.nodes[i].addwitnessaddress(multiaddress)
- bip173_ms_addr = self.nodes[i].addwitnessaddress(multiaddress, False)
+ p2sh_ms_addr = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]], '', 'p2sh-segwit')['address']
+ bip173_ms_addr = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]], '', 'bech32')['address']
assert_equal(p2sh_addr, key_to_p2sh_p2wpkh(self.pubkey[-1]))
assert_equal(bip173_addr, key_to_p2wpkh(self.pubkey[-1]))
assert_equal(p2sh_ms_addr, script_to_p2sh_p2wsh(multiscript))