Skip to content

Commit eb95368

Browse files
committed
Merge bitcoin/bitcoin#28166: test, rpc: invalid sighashtype coverage
90c8f79 test: remove redundant test values (Jon Atack) c3f2033 test: use common assert_signing_completed_successfully helper (Jon Atack) 647d95a test: add coverage for passing an invalid sighashtype (Jon Atack) Pull request description: Add test coverage for passing an invalid sighashtype to RPCs signrawtransactionwithwallet, signrawtransactionwithkey, walletprocesspsbt, and descriptorprocesspsbt. ACKs for top commit: MarcoFalke: lgtm ACK 90c8f79 🎥 brunoerg: light crACK 90c8f79 Tree-SHA512: 3861658487edd0d9a377390acf3d43f45c3dd9e324894f0fdb8f5312b618301a55479b1f70c61daee0b20785e768ffde6fa5abe6af190b73c0d0e017f3976704
2 parents ceda819 + 90c8f79 commit eb95368

File tree

7 files changed

+49
-33
lines changed

7 files changed

+49
-33
lines changed

test/functional/rpc_psbt.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ def run_test(self):
327327
assert_raises_rpc_error(-3, "Invalid amount",
328328
self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: invalid_value, "add_inputs": True})
329329
# Test fee_rate values that cannot be represented in sat/vB.
330-
for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999, "0.0001", "0.00000001", "0.00099999", "31.99999999"]:
330+
for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999]:
331331
assert_raises_rpc_error(-3, "Invalid amount",
332332
self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": invalid_value, "add_inputs": True})
333333

@@ -883,6 +883,9 @@ def test_psbt_input_keys(psbt_input, keys):
883883
comb_psbt = self.nodes[0].combinepsbt([psbt, parsed_psbt.to_base64()])
884884
assert_equal(comb_psbt, psbt)
885885

886+
self.log.info("Test walletprocesspsbt raises if an invalid sighashtype is passed")
887+
assert_raises_rpc_error(-8, "all is not a valid sighash parameter.", self.nodes[0].walletprocesspsbt, psbt, sighashtype="all")
888+
886889
self.log.info("Test decoding PSBT with per-input preimage types")
887890
# note that the decodepsbt RPC doesn't check whether preimages and hashes match
888891
hash_ripemd160, preimage_ripemd160 = random_bytes(20), random_bytes(50)
@@ -982,5 +985,9 @@ def test_psbt_input_keys(psbt_input, keys):
982985
rawtx = self.nodes[2].finalizepsbt(psbt)["hex"]
983986
self.nodes[2].sendrawtransaction(rawtx)
984987

988+
self.log.info("Test descriptorprocesspsbt raises if an invalid sighashtype is passed")
989+
assert_raises_rpc_error(-8, "all is not a valid sighash parameter.", self.nodes[2].descriptorprocesspsbt, psbt, [descriptor], sighashtype="all")
990+
991+
985992
if __name__ == '__main__':
986993
PSBTTest().main()

test/functional/rpc_signrawtransactionwithkey.py

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from test_framework.test_framework import BitcoinTestFramework
1515
from test_framework.util import (
1616
assert_equal,
17+
assert_raises_rpc_error,
1718
find_vout_for_address,
1819
)
1920
from test_framework.script_util import (
@@ -33,6 +34,14 @@
3334
Decimal,
3435
)
3536

37+
INPUTS = [
38+
# Valid pay-to-pubkey scripts
39+
{'txid': '9b907ef1e3c26fc71fe4a4b3580bc75264112f95050014157059c736f0202e71', 'vout': 0,
40+
'scriptPubKey': '76a91460baa0f494b38ce3c940dea67f3804dc52d1fb9488ac'},
41+
{'txid': '83a4f6a6b73660e13ee6cb3c6063fa3759c50c9b7521d0536022961898f4fb02', 'vout': 0,
42+
'scriptPubKey': '76a914669b857c03a5ed269d5d85a1ffac9ed5d663072788ac'},
43+
]
44+
OUTPUTS = {'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB': 0.1}
3645

3746
class SignRawTransactionWithKeyTest(BitcoinTestFramework):
3847
def set_test_params(self):
@@ -47,6 +56,11 @@ def send_to_address(self, addr, amount):
4756
txid = self.nodes[0].sendrawtransaction(self.nodes[0].signrawtransactionwithkey(rawtx, [self.nodes[0].get_deterministic_priv_key().key])["hex"], 0)
4857
return txid
4958

59+
def assert_signing_completed_successfully(self, signed_tx):
60+
assert 'errors' not in signed_tx
61+
assert 'complete' in signed_tx
62+
assert_equal(signed_tx['complete'], True)
63+
5064
def successful_signing_test(self):
5165
"""Create and sign a valid raw transaction with one input.
5266
@@ -56,25 +70,10 @@ def successful_signing_test(self):
5670
2) No script verification error occurred"""
5771
self.log.info("Test valid raw transaction with one input")
5872
privKeys = ['cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N', 'cVKpPfVKSJxKqVpE9awvXNWuLHCa5j5tiE7K6zbUSptFpTEtiFrA']
73+
rawTx = self.nodes[0].createrawtransaction(INPUTS, OUTPUTS)
74+
rawTxSigned = self.nodes[0].signrawtransactionwithkey(rawTx, privKeys, INPUTS)
5975

60-
inputs = [
61-
# Valid pay-to-pubkey scripts
62-
{'txid': '9b907ef1e3c26fc71fe4a4b3580bc75264112f95050014157059c736f0202e71', 'vout': 0,
63-
'scriptPubKey': '76a91460baa0f494b38ce3c940dea67f3804dc52d1fb9488ac'},
64-
{'txid': '83a4f6a6b73660e13ee6cb3c6063fa3759c50c9b7521d0536022961898f4fb02', 'vout': 0,
65-
'scriptPubKey': '76a914669b857c03a5ed269d5d85a1ffac9ed5d663072788ac'},
66-
]
67-
68-
outputs = {'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB': 0.1}
69-
70-
rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
71-
rawTxSigned = self.nodes[0].signrawtransactionwithkey(rawTx, privKeys, inputs)
72-
73-
# 1) The transaction has a complete set of signatures
74-
assert rawTxSigned['complete']
75-
76-
# 2) No script verification error occurred
77-
assert 'errors' not in rawTxSigned
76+
self.assert_signing_completed_successfully(rawTxSigned)
7877

7978
def witness_script_test(self):
8079
self.log.info("Test signing transaction to P2SH-P2WSH addresses without wallet")
@@ -95,9 +94,7 @@ def witness_script_test(self):
9594
# Now create and sign a transaction spending that output on node[0], which doesn't know the scripts or keys
9695
spending_tx = self.nodes[0].createrawtransaction([unspent_output], {getnewdestination()[2]: Decimal("49.998")})
9796
spending_tx_signed = self.nodes[0].signrawtransactionwithkey(spending_tx, [embedded_privkey], [unspent_output])
98-
# Check the signing completed successfully
99-
assert 'complete' in spending_tx_signed
100-
assert_equal(spending_tx_signed['complete'], True)
97+
self.assert_signing_completed_successfully(spending_tx_signed)
10198

10299
# Now test with P2PKH and P2PK scripts as the witnessScript
103100
for tx_type in ['P2PKH', 'P2PK']: # these tests are order-independent
@@ -120,14 +117,19 @@ def verify_txn_with_witness_script(self, tx_type):
120117
# Now create and sign a transaction spending that output on node[0], which doesn't know the scripts or keys
121118
spending_tx = self.nodes[0].createrawtransaction([{'txid': txid, 'vout': vout}], {getnewdestination()[2]: Decimal("9.999")})
122119
spending_tx_signed = self.nodes[0].signrawtransactionwithkey(spending_tx, [embedded_privkey], [{'txid': txid, 'vout': vout, 'scriptPubKey': script_pub_key, 'redeemScript': redeem_script, 'witnessScript': witness_script, 'amount': 10}])
123-
# Check the signing completed successfully
124-
assert 'complete' in spending_tx_signed
125-
assert_equal(spending_tx_signed['complete'], True)
120+
self.assert_signing_completed_successfully(spending_tx_signed)
126121
self.nodes[0].sendrawtransaction(spending_tx_signed['hex'])
127122

123+
def invalid_sighashtype_test(self):
124+
self.log.info("Test signing transaction with invalid sighashtype")
125+
tx = self.nodes[0].createrawtransaction(INPUTS, OUTPUTS)
126+
privkeys = [self.nodes[0].get_deterministic_priv_key().key]
127+
assert_raises_rpc_error(-8, "all is not a valid sighash parameter.", self.nodes[0].signrawtransactionwithkey, tx, privkeys, sighashtype="all")
128+
128129
def run_test(self):
129130
self.successful_signing_test()
130131
self.witness_script_test()
132+
self.invalid_sighashtype_test()
131133

132134

133135
if __name__ == '__main__':

test/functional/wallet_basic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ def run_test(self):
328328
for invalid_value in ["", 0.000000001, 1e-09, 1.111111111, 1111111111111111, "31.999999999999999999999"]:
329329
assert_raises_rpc_error(-3, msg, self.nodes[2].sendmany, amounts={address: 1.0}, fee_rate=invalid_value)
330330
# Test fee_rate values that cannot be represented in sat/vB.
331-
for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999, "0.0001", "0.00000001", "0.00099999", "31.99999999"]:
331+
for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999]:
332332
assert_raises_rpc_error(-3, msg, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=invalid_value)
333333
# Test fee_rate out of range (negative number).
334334
assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=-1)
@@ -523,7 +523,7 @@ def run_test(self):
523523
for invalid_value in ["", 0.000000001, 1e-09, 1.111111111, 1111111111111111, "31.999999999999999999999"]:
524524
assert_raises_rpc_error(-3, msg, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=invalid_value)
525525
# Test fee_rate values that cannot be represented in sat/vB.
526-
for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999, "0.0001", "0.00000001", "0.00099999", "31.99999999"]:
526+
for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999]:
527527
assert_raises_rpc_error(-3, msg, self.nodes[2].sendtoaddress, address=address, amount=10, fee_rate=invalid_value)
528528
# Test fee_rate out of range (negative number).
529529
assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=-1)

test/functional/wallet_bumpfee.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ def test_invalid_parameters(self, rbf_node, peer_node, dest_address):
141141
for invalid_value in ["", 0.000000001, 1e-09, 1.111111111, 1111111111111111, "31.999999999999999999999"]:
142142
assert_raises_rpc_error(-3, msg, rbf_node.bumpfee, rbfid, fee_rate=invalid_value)
143143
# Test fee_rate values that cannot be represented in sat/vB.
144-
for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999, "0.0001", "0.00000001", "0.00099999", "31.99999999"]:
144+
for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999]:
145145
assert_raises_rpc_error(-3, msg, rbf_node.bumpfee, rbfid, fee_rate=invalid_value)
146146
# Test fee_rate out of range (negative number).
147147
assert_raises_rpc_error(-3, "Amount out of range", rbf_node.bumpfee, rbfid, fee_rate=-1)

test/functional/wallet_fundrawtransaction.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ def test_option_feerate(self):
832832
for invalid_value in ["", 0.000000001, 1e-09, 1.111111111, 1111111111111111, "31.999999999999999999999"]:
833833
assert_raises_rpc_error(-3, "Invalid amount", node.fundrawtransaction, rawtx, add_inputs=True, **{param: invalid_value})
834834
# Test fee_rate values that cannot be represented in sat/vB.
835-
for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999, "0.0001", "0.00000001", "0.00099999", "31.99999999"]:
835+
for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999]:
836836
assert_raises_rpc_error(-3, "Invalid amount",
837837
node.fundrawtransaction, rawtx, fee_rate=invalid_value, add_inputs=True)
838838

test/functional/wallet_send.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ def run_test(self):
387387
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=invalid_value, expect_error=(-3, msg))
388388
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=invalid_value, expect_error=(-3, msg))
389389
# Test fee_rate values that cannot be represented in sat/vB.
390-
for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999, "0.0001", "0.00000001", "0.00099999", "31.99999999"]:
390+
for invalid_value in [0.0001, 0.00000001, 0.00099999, 31.99999999]:
391391
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=invalid_value, expect_error=(-3, msg))
392392
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=invalid_value, expect_error=(-3, msg))
393393
# Test fee_rate out of range (negative number).

test/functional/wallet_signrawtransactionwithwallet.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
getcontext,
3434
)
3535

36+
37+
RAW_TX = '020000000156b958f78e3f24e0b2f4e4db1255426b0902027cb37e3ddadb52e37c3557dddb0000000000ffffffff01c0a6b929010000001600149a2ee8c77140a053f36018ac8124a6ececc1668a00000000'
38+
39+
3640
class SignRawTransactionWithWalletTest(BitcoinTestFramework):
3741
def add_options(self, parser):
3842
self.add_wallet_options(parser)
@@ -47,10 +51,12 @@ def skip_test_if_missing_module(self):
4751
def test_with_lock_outputs(self):
4852
self.log.info("Test correct error reporting when trying to sign a locked output")
4953
self.nodes[0].encryptwallet("password")
54+
assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].signrawtransactionwithwallet, RAW_TX)
55+
self.nodes[0].walletpassphrase("password", 9999)
5056

51-
rawTx = '020000000156b958f78e3f24e0b2f4e4db1255426b0902027cb37e3ddadb52e37c3557dddb0000000000ffffffff01c0a6b929010000001600149a2ee8c77140a053f36018ac8124a6ececc1668a00000000'
52-
53-
assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].signrawtransactionwithwallet, rawTx)
57+
def test_with_invalid_sighashtype(self):
58+
self.log.info("Test signrawtransactionwithwallet raises if an invalid sighashtype is passed")
59+
assert_raises_rpc_error(-8, "all is not a valid sighash parameter.", self.nodes[0].signrawtransactionwithwallet, hexstring=RAW_TX, sighashtype="all")
5460

5561
def script_verification_error_test(self):
5662
"""Create and sign a raw transaction with valid (vin 0), invalid (vin 1) and one missing (vin 2) input script.
@@ -299,6 +305,7 @@ def run_test(self):
299305
self.script_verification_error_test()
300306
self.OP_1NEGATE_test()
301307
self.test_with_lock_outputs()
308+
self.test_with_invalid_sighashtype()
302309
self.test_fully_signed_tx()
303310
self.test_signing_with_csv()
304311
self.test_signing_with_cltv()

0 commit comments

Comments
 (0)