Merge #13547: Make signrawtransaction* give an error when amount is needed but missing
685d1d8115
[tests] Check signrawtransaction* errors on missing prevtx info (Anthony Towns)a3b065b51f
Error on missing amount in signrawtransaction* (Anthony Towns) Pull request description: 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. Based on Ben Woosley's #12458, Fixes: #12429. Tree-SHA512: 8e2ff89d5bcf79548e569210af0d850028bc98d86c149b92207c9300ab1d63664a7e2b222c1be403a15941aa5cf36ccc3c0d570ee1c1466f3496b4fe06c17e11
This commit is contained in:
commit
fad42e8c4a
2 changed files with 61 additions and 1 deletions
|
@ -811,7 +811,7 @@ UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival
|
||||||
}
|
}
|
||||||
Coin newcoin;
|
Coin newcoin;
|
||||||
newcoin.out.scriptPubKey = scriptPubKey;
|
newcoin.out.scriptPubKey = scriptPubKey;
|
||||||
newcoin.out.nValue = 0;
|
newcoin.out.nValue = MAX_MONEY;
|
||||||
if (prevOut.exists("amount")) {
|
if (prevOut.exists("amount")) {
|
||||||
newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
|
newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
|
||||||
}
|
}
|
||||||
|
@ -883,6 +883,11 @@ UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival
|
||||||
|
|
||||||
UpdateInput(txin, sigdata);
|
UpdateInput(txin, 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;
|
ScriptError serror = SCRIPT_ERR_OK;
|
||||||
if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
|
if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
|
||||||
if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
|
if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
|
||||||
|
|
|
@ -137,6 +137,61 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||||
self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}, {'data': '99'}, {'data': '99'}]),
|
self.nodes[2].createrawtransaction(inputs=[{'txid': txid, 'vout': 9}], outputs=[{address: 99}, {'data': '99'}, {'data': '99'}]),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for type in ["bech32", "p2sh-segwit", "legacy"]:
|
||||||
|
addr = self.nodes[0].getnewaddress("", type)
|
||||||
|
addrinfo = self.nodes[0].getaddressinfo(addr)
|
||||||
|
pubkey = addrinfo["scriptPubKey"]
|
||||||
|
|
||||||
|
self.log.info('sendrawtransaction with missing prevtx info (%s)' %(type))
|
||||||
|
|
||||||
|
# Test `signrawtransactionwithwallet` 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].signrawtransactionwithwallet(rawtx, [prevtx])
|
||||||
|
assert succ["complete"]
|
||||||
|
if type == "legacy":
|
||||||
|
del prevtx["amount"]
|
||||||
|
succ = self.nodes[0].signrawtransactionwithwallet(rawtx, [prevtx])
|
||||||
|
assert succ["complete"]
|
||||||
|
|
||||||
|
if type != "legacy":
|
||||||
|
assert_raises_rpc_error(-3, "Missing amount", self.nodes[0].signrawtransactionwithwallet, rawtx, [
|
||||||
|
{
|
||||||
|
"txid": txid,
|
||||||
|
"scriptPubKey": pubkey,
|
||||||
|
"vout": 3,
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
assert_raises_rpc_error(-3, "Missing vout", self.nodes[0].signrawtransactionwithwallet, rawtx, [
|
||||||
|
{
|
||||||
|
"txid": txid,
|
||||||
|
"scriptPubKey": pubkey,
|
||||||
|
"amount": 1,
|
||||||
|
}
|
||||||
|
])
|
||||||
|
assert_raises_rpc_error(-3, "Missing txid", self.nodes[0].signrawtransactionwithwallet, rawtx, [
|
||||||
|
{
|
||||||
|
"scriptPubKey": pubkey,
|
||||||
|
"vout": 3,
|
||||||
|
"amount": 1,
|
||||||
|
}
|
||||||
|
])
|
||||||
|
assert_raises_rpc_error(-3, "Missing scriptPubKey", self.nodes[0].signrawtransactionwithwallet, rawtx, [
|
||||||
|
{
|
||||||
|
"txid": txid,
|
||||||
|
"vout": 3,
|
||||||
|
"amount": 1
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# sendrawtransaction with missing input #
|
||||||
|
#########################################
|
||||||
|
|
||||||
self.log.info('sendrawtransaction with missing input')
|
self.log.info('sendrawtransaction with missing input')
|
||||||
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1}] #won't exists
|
inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1}] #won't exists
|
||||||
outputs = { self.nodes[0].getnewaddress() : 4.998 }
|
outputs = { self.nodes[0].getnewaddress() : 4.998 }
|
||||||
|
|
Loading…
Reference in a new issue