From 1825e37075aa7885930cb48c5452ba3e8952b78a Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 27 Jun 2018 17:54:32 +1000 Subject: [PATCH 1/2] Error on missing amount in signrawtransaction* Signatures using segregated witness commit to the amount being spent, so that value must be passed into signrawtransactionwithkey and signrawtransactionwithwallet. This ensures an error is issued if that doesn't happen, rather than just assuming the value is 0 and producing a signature that is almost certainly invalid. Github-Pull: #13547 Rebased-From: a3b065b51fb333d976108a1fe34b7f663fd67285 --- src/rpc/rawtransaction.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 82399e156..3fbea1ff7 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -820,7 +820,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) } Coin newcoin; newcoin.out.scriptPubKey = scriptPubKey; - newcoin.out.nValue = 0; + newcoin.out.nValue = MAX_MONEY; if (prevOut.exists("amount")) { newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount")); } @@ -898,6 +898,11 @@ UniValue signrawtransaction(const JSONRPCRequest& request) UpdateTransaction(mtx, i, sigdata); + // amount must be specified for valid segwit signature + if (amount == MAX_MONEY && !txin.scriptWitness.IsNull()) { + throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coin.out.ToString())); + } + ScriptError serror = SCRIPT_ERR_OK; if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) { if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) { From 212ef1f9547e27295a94eaa9d5ae552d858e2d9f Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 27 Jun 2018 17:54:42 +1000 Subject: [PATCH 2/2] [tests] Check signrawtransaction* errors on missing prevtx info Github-Pull: #13547 Rebased-From: 685d1d8115f61b15115d80523dd8273f0a816534 --- test/functional/rpc_rawtransaction.py | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py index d39d86b31..ce34c64d3 100755 --- a/test/functional/rpc_rawtransaction.py +++ b/test/functional/rpc_rawtransaction.py @@ -94,6 +94,57 @@ class RawTransactionsTest(BitcoinTestFramework): # Test `createrawtransaction` invalid `replaceable` assert_raises_rpc_error(-3, "Expected type bool", self.nodes[0].createrawtransaction, [], {}, 0, 'foo') + for type in ["bech32", "p2sh-segwit", "legacy"]: + addr = self.nodes[0].getnewaddress("", type) + addrinfo = self.nodes[0].validateaddress(addr) + pubkey = addrinfo["scriptPubKey"] + + self.log.info('sendrawtransaction with missing prevtx info (%s)' %(type)) + + # Test `signrawtransaction` invalid `prevtxs` + inputs = [ {'txid' : txid, 'vout' : 3, 'sequence' : 1000}] + outputs = { self.nodes[0].getnewaddress() : 1 } + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + + prevtx = dict(txid=txid, scriptPubKey=pubkey, vout=3, amount=1) + succ = self.nodes[0].signrawtransaction(rawtx, [prevtx]) + assert succ["complete"] + if type == "legacy": + del prevtx["amount"] + succ = self.nodes[0].signrawtransaction(rawtx, [prevtx]) + assert succ["complete"] + + if type != "legacy": + assert_raises_rpc_error(-3, "Missing amount", self.nodes[0].signrawtransaction, rawtx, [ + { + "txid": txid, + "scriptPubKey": pubkey, + "vout": 3, + } + ]) + + assert_raises_rpc_error(-3, "Missing vout", self.nodes[0].signrawtransaction, rawtx, [ + { + "txid": txid, + "scriptPubKey": pubkey, + "amount": 1, + } + ]) + assert_raises_rpc_error(-3, "Missing txid", self.nodes[0].signrawtransaction, rawtx, [ + { + "scriptPubKey": pubkey, + "vout": 3, + "amount": 1, + } + ]) + assert_raises_rpc_error(-3, "Missing scriptPubKey", self.nodes[0].signrawtransaction, rawtx, [ + { + "txid": txid, + "vout": 3, + "amount": 1 + } + ]) + ######################################### # sendrawtransaction with missing input # #########################################