[rpc] fundrawtransaction: add_inputs option to control automatic input adding

This commit is contained in:
Sjors Provoost 2020-02-20 16:19:59 +01:00
parent 79804fe24b
commit e5327f947c
No known key found for this signature in database
GPG key ID: 57FF9BDBCC301009
3 changed files with 20 additions and 4 deletions

View file

@ -4,3 +4,6 @@ RPC changes
`Insufficient funds` when inputs are manually selected but are not enough to cover
the outputs and fee. Additional inputs can automatically be added through the
new `add_inputs` option.
- The `fundrawtransaction` RPC now supports `add_inputs` option that when `false`
prevents adding more inputs if necessary and consequently the RPC fails.

View file

@ -3148,8 +3148,8 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
}
RPCHelpMan{"fundrawtransaction",
"\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 at most one change output to the outputs.\n"
"\nIf the transaction has no inputs, they will be automatically selected to meet its out value.\n"
"It will add at most one change output to the outputs.\n"
"No existing outputs will be modified unless \"subtractFeeFromOutputs\" is specified.\n"
"Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
"The inputs added will not be signed, use signrawtransactionwithkey\n"
@ -3163,6 +3163,7 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
{"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex string of the raw transaction"},
{"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}",
{
{"add_inputs", RPCArg::Type::BOOL, /* default */ "true", "For a transaction with existing inputs, automatically include more if they are not enough."},
{"changeAddress", RPCArg::Type::STR, /* default */ "pool address", "The bitcoin address to receive the change"},
{"changePosition", RPCArg::Type::NUM, /* default */ "random", "The index of the change output"},
{"change_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
@ -3229,6 +3230,8 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
CAmount fee;
int change_position;
CCoinControl coin_control;
// Automatically select (additional) coins. Can be overriden by options.add_inputs.
coin_control.m_add_inputs = true;
FundTransaction(pwallet, tx, fee, change_position, request.params[1], coin_control);
UniValue result(UniValue::VOBJ);

View file

@ -271,7 +271,11 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
assert_equal("00", dec_tx['vin'][0]['scriptSig']['hex'])
# Should fail without add_inputs:
assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].fundrawtransaction, rawtx, {"add_inputs": False})
# add_inputs is enabled by default
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
totalOut = 0
matchingOuts = 0
@ -299,7 +303,10 @@ class RawTransactionsTest(BitcoinTestFramework):
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
# Should fail without add_inputs:
assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].fundrawtransaction, rawtx, {"add_inputs": False})
rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {"add_inputs": True})
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
totalOut = 0
matchingOuts = 0
@ -330,7 +337,10 @@ class RawTransactionsTest(BitcoinTestFramework):
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
# Should fail without add_inputs:
assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].fundrawtransaction, rawtx, {"add_inputs": False})
rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {"add_inputs": True})
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
totalOut = 0
matchingOuts = 0