aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/rpcwallet.cpp
diff options
context:
space:
mode:
authorJoão Barbosa <joao@uphold.com>2016-03-30 02:04:22 +0100
committerWladimir J. van der Laan <laanwj@gmail.com>2016-04-15 15:36:05 +0200
commitaf4fe7fd126eff2dd1942276ea91c8ab9dd717c6 (patch)
tree045831205072829b0bd7ce4795f9e65257caca22 /src/wallet/rpcwallet.cpp
parent41e835dd50d358c127bab17a1f2872471dbdfe9c (diff)
downloadbitcoin-af4fe7fd126eff2dd1942276ea91c8ab9dd717c6.tar.xz
Add change options to fundrawtransaction
Diffstat (limited to 'src/wallet/rpcwallet.cpp')
-rw-r--r--src/wallet/rpcwallet.cpp58
1 files changed, 48 insertions, 10 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 5511e9d3ab..5cd57fc385 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -2437,7 +2437,7 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
- "fundrawtransaction \"hexstring\" includeWatching\n"
+ "fundrawtransaction \"hexstring\" ( options )\n"
"\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
"This will not modify existing inputs, and will add one change output to the outputs.\n"
"Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
@@ -2447,8 +2447,14 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
"in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
"Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
"\nArguments:\n"
- "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
- "2. includeWatching (boolean, optional, default false) Also select inputs which are watch only\n"
+ "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
+ "2. options (object, optional)\n"
+ " {\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"
+ " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
+ " }\n"
+ " for backward compatibility: passing in a true instzead of an object will result in {\"includeWatching\":true}\n"
"\nResult:\n"
"{\n"
" \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
@@ -2467,7 +2473,40 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
);
- RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
+
+ CTxDestination changeAddress = CNoDestination();
+ int changePosition = -1;
+ bool includeWatching = false;
+
+ if (params.size() > 1) {
+ if (params[1].type() == UniValue::VBOOL) {
+ // backward compatibility bool only fallback
+ includeWatching = params[1].get_bool();
+ }
+ else {
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
+
+ UniValue options = params[1];
+
+ RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL), true, true);
+
+ if (options.exists("changeAddress")) {
+ CBitcoinAddress address(options["changeAddress"].get_str());
+
+ if (!address.IsValid())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "changeAddress must be a valid bitcoin address");
+
+ changeAddress = address.Get();
+ }
+
+ if (options.exists("changePosition"))
+ changePosition = options["changePosition"].get_int();
+
+ if (options.exists("includeWatching"))
+ includeWatching = options["includeWatching"].get_bool();
+ }
+ }
// parse hex string from parameter
CTransaction origTx;
@@ -2477,20 +2516,19 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
if (origTx.vout.size() == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
- bool includeWatching = false;
- if (params.size() > 1)
- includeWatching = params[1].get_bool();
+ if (changePosition != -1 && (changePosition < 0 || changePosition > origTx.vout.size()))
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
CMutableTransaction tx(origTx);
CAmount nFee;
string strFailReason;
- int nChangePos = -1;
- if(!pwalletMain->FundTransaction(tx, nFee, nChangePos, strFailReason, includeWatching))
+
+ if(!pwalletMain->FundTransaction(tx, nFee, changePosition, strFailReason, includeWatching, changeAddress))
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hex", EncodeHexTx(tx)));
- result.push_back(Pair("changepos", nChangePos));
+ result.push_back(Pair("changepos", changePosition));
result.push_back(Pair("fee", ValueFromAmount(nFee)));
return result;