Changeset View
Changeset View
Standalone View
Standalone View
test/functional/rpc_signrawtransaction.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2015-2016 The Bitcoin Core developers | # Copyright (c) 2015-2016 The Bitcoin Core developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
"""Test transaction signing using the signrawtransactionwithwallet RPC.""" | """Test transaction signing using the signrawtransaction* RPCs.""" | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import assert_equal, assert_raises_rpc_error | from test_framework.util import assert_equal, assert_raises_rpc_error | ||||
class SignRawTransactionsTest(BitcoinTestFramework): | class SignRawTransactionsTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
Show All 21 Lines | def successful_signing_test(self): | ||||
outputs = {'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB': 0.1} | outputs = {'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB': 0.1} | ||||
rawTx = self.nodes[0].createrawtransaction(inputs, outputs) | rawTx = self.nodes[0].createrawtransaction(inputs, outputs) | ||||
rawTxSigned = self.nodes[0].signrawtransactionwithkey( | rawTxSigned = self.nodes[0].signrawtransactionwithkey( | ||||
rawTx, privKeys, inputs) | rawTx, privKeys, inputs) | ||||
# 1) The transaction has a complete set of signatures | # 1) The transaction has a complete set of signatures | ||||
assert 'complete' in rawTxSigned | assert rawTxSigned['complete'] | ||||
assert_equal(rawTxSigned['complete'], True) | |||||
# 2) No script verification error occurred | # 2) No script verification error occurred | ||||
assert 'errors' not in rawTxSigned | assert 'errors' not in rawTxSigned | ||||
# Perform the same test on signrawtransaction | |||||
rawTxSigned2 = self.nodes[0].signrawtransaction( | |||||
rawTx, inputs, privKeys) | |||||
assert_equal(rawTxSigned, rawTxSigned2) | |||||
def script_verification_error_test(self): | def script_verification_error_test(self): | ||||
"""Creates and signs a raw transaction with valid (vin 0), invalid (vin 1) and one missing (vin 2) input script. | """Creates and signs a raw transaction with valid (vin 0), invalid (vin 1) and one missing (vin 2) input script. | ||||
Expected results: | Expected results: | ||||
3) The transaction has no complete set of signatures | 3) The transaction has no complete set of signatures | ||||
4) Two script verification errors occurred | 4) Two script verification errors occurred | ||||
5) Script verification errors have certain properties ("txid", "vout", "scriptSig", "sequence", "error") | 5) Script verification errors have certain properties ("txid", "vout", "scriptSig", "sequence", "error") | ||||
Show All 36 Lines | def script_verification_error_test(self): | ||||
# Make sure decoderawtransaction throws if there is extra data | # Make sure decoderawtransaction throws if there is extra data | ||||
assert_raises_rpc_error(-22, "TX decode failed", | assert_raises_rpc_error(-22, "TX decode failed", | ||||
self.nodes[0].decoderawtransaction, rawTx + "00") | self.nodes[0].decoderawtransaction, rawTx + "00") | ||||
rawTxSigned = self.nodes[0].signrawtransactionwithkey( | rawTxSigned = self.nodes[0].signrawtransactionwithkey( | ||||
rawTx, privKeys, scripts) | rawTx, privKeys, scripts) | ||||
# 3) The transaction has no complete set of signatures | # 3) The transaction has no complete set of signatures | ||||
assert 'complete' in rawTxSigned | assert not rawTxSigned['complete'] | ||||
assert_equal(rawTxSigned['complete'], False) | |||||
# 4) Two script verification errors occurred | # 4) Two script verification errors occurred | ||||
assert 'errors' in rawTxSigned | assert 'errors' in rawTxSigned | ||||
assert_equal(len(rawTxSigned['errors']), 2) | assert_equal(len(rawTxSigned['errors']), 2) | ||||
# 5) Script verification errors have certain properties | # 5) Script verification errors have certain properties | ||||
assert 'txid' in rawTxSigned['errors'][0] | assert 'txid' in rawTxSigned['errors'][0] | ||||
assert 'vout' in rawTxSigned['errors'][0] | assert 'vout' in rawTxSigned['errors'][0] | ||||
assert 'scriptSig' in rawTxSigned['errors'][0] | assert 'scriptSig' in rawTxSigned['errors'][0] | ||||
assert 'sequence' in rawTxSigned['errors'][0] | assert 'sequence' in rawTxSigned['errors'][0] | ||||
assert 'error' in rawTxSigned['errors'][0] | assert 'error' in rawTxSigned['errors'][0] | ||||
# 6) The verification errors refer to the invalid (vin 1) and missing | # 6) The verification errors refer to the invalid (vin 1) and missing | ||||
# input (vin 2) | # input (vin 2) | ||||
assert_equal(rawTxSigned['errors'][0]['txid'], inputs[1]['txid']) | assert_equal(rawTxSigned['errors'][0]['txid'], inputs[1]['txid']) | ||||
assert_equal(rawTxSigned['errors'][0]['vout'], inputs[1]['vout']) | assert_equal(rawTxSigned['errors'][0]['vout'], inputs[1]['vout']) | ||||
assert_equal(rawTxSigned['errors'][1]['txid'], inputs[2]['txid']) | assert_equal(rawTxSigned['errors'][1]['txid'], inputs[2]['txid']) | ||||
assert_equal(rawTxSigned['errors'][1]['vout'], inputs[2]['vout']) | assert_equal(rawTxSigned['errors'][1]['vout'], inputs[2]['vout']) | ||||
# Perform same test with signrawtransaction | |||||
rawTxSigned2 = self.nodes[0].signrawtransaction( | |||||
rawTx, scripts, privKeys) | |||||
assert_equal(rawTxSigned, rawTxSigned2) | |||||
def test_sighashes(self): | def test_sighashes(self): | ||||
"""Creates and signs a raw transaction with various sighashes. | """Creates and signs a raw transaction with various sighashes. | ||||
Expected result: | Expected result: | ||||
1) The transaction is complete if the sighash is valid and has FORKID. | 1) The transaction is complete if the sighash is valid and has FORKID. | ||||
2) The RPC throws an error if the sighash does not contain FORKID. | 2) The RPC throws an error if the sighash does not contain FORKID. | ||||
3) The RPC throws an error if the sighash is invalid.""" | 3) The RPC throws an error if the sighash is invalid.""" | ||||
Show All 31 Lines | def test_sighashes(self): | ||||
"", | "", | ||||
"ALL|SINGLE|FORKID", | "ALL|SINGLE|FORKID", | ||||
str(0), | str(0), | ||||
str(0x20) | str(0x20) | ||||
] | ] | ||||
# 1) If the sighash is valid with FORKID, the signature is complete | # 1) If the sighash is valid with FORKID, the signature is complete | ||||
for sighash in valid_sighashes: | for sighash in valid_sighashes: | ||||
rawTxSigned = self.nodes[0].signrawtransaction(rawTx, inputs, | rawTxSigned = self.nodes[0].signrawtransactionwithkey( | ||||
privKeys, sighash) | rawTx, privKeys, inputs, sighash) | ||||
assert 'complete' in rawTxSigned | assert 'complete' in rawTxSigned | ||||
assert_equal(rawTxSigned['complete'], True) | assert_equal(rawTxSigned['complete'], True) | ||||
assert 'errors' not in rawTxSigned | assert 'errors' not in rawTxSigned | ||||
# 2) If FORKID is missing in the sighash, the RPC throws an error | # 2) If FORKID is missing in the sighash, the RPC throws an error | ||||
for sighash in no_forkid_sighashes: | for sighash in no_forkid_sighashes: | ||||
assert_raises_rpc_error(-8, "Signature must use SIGHASH_FORKID", | assert_raises_rpc_error(-8, "Signature must use SIGHASH_FORKID", | ||||
self.nodes[0].signrawtransaction, | self.nodes[0].signrawtransactionwithkey, | ||||
rawTx, inputs, privKeys, sighash) | rawTx, privKeys, inputs, sighash) | ||||
# 3) If the sighash is invalid the RPC throws an error | # 3) If the sighash is invalid the RPC throws an error | ||||
for sighash in invalid_sighashes: | for sighash in invalid_sighashes: | ||||
assert_raises_rpc_error(-8, "Invalid sighash param", | assert_raises_rpc_error(-8, "Invalid sighash param", | ||||
self.nodes[0].signrawtransaction, | self.nodes[0].signrawtransactionwithkey, | ||||
rawTx, inputs, privKeys, sighash) | rawTx, privKeys, inputs, sighash) | ||||
def run_test(self): | def run_test(self): | ||||
self.successful_signing_test() | self.successful_signing_test() | ||||
self.script_verification_error_test() | self.script_verification_error_test() | ||||
self.test_sighashes() | self.test_sighashes() | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
SignRawTransactionsTest().main() | SignRawTransactionsTest().main() |