From c9bd0f64212cd600daf30c9c59035bfe9f07b81b Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 7 Mar 2017 14:08:59 -0500 Subject: [PATCH] Fix RPC failure testing (2 of 2) Commit 9db8eecac1c713c760c0217b6acb7455c657fa8b improved the assert_raises_jsonrpc() function for better testing of RPC failure modes. This commit completes the job by removing remaining broken try-except RPC testing from the individual test cases and replacing it with calls to assert_raises_jsonrpc(). --- qa/rpc-tests/bip65-cltv.py | 8 +- qa/rpc-tests/bip68-sequence.py | 46 +++------ qa/rpc-tests/bipdersig.py | 8 +- qa/rpc-tests/blockchain.py | 6 +- qa/rpc-tests/disablewallet.py | 17 +--- qa/rpc-tests/getblocktemplate_proposals.py | 4 +- qa/rpc-tests/keypool.py | 18 +--- qa/rpc-tests/mempool_packages.py | 29 +++--- qa/rpc-tests/mempool_reorg.py | 16 +++- qa/rpc-tests/mempool_spendcoinbase.py | 2 +- qa/rpc-tests/nulldummy.py | 31 ++---- qa/rpc-tests/prioritise_transaction.py | 10 +- qa/rpc-tests/replace-by-fee.py | 105 +++++---------------- qa/rpc-tests/rpcbind_test.py | 6 +- qa/rpc-tests/segwit.py | 58 +++++------- qa/rpc-tests/wallet.py | 20 ++-- 16 files changed, 119 insertions(+), 265 deletions(-) diff --git a/qa/rpc-tests/bip65-cltv.py b/qa/rpc-tests/bip65-cltv.py index c9d02a98f..7f13bb995 100755 --- a/qa/rpc-tests/bip65-cltv.py +++ b/qa/rpc-tests/bip65-cltv.py @@ -69,12 +69,8 @@ class BIP65Test(BitcoinTestFramework): if (self.nodes[0].getblockcount() != cnt + 1051): raise AssertionError("Failed to mine a version=4 block") - # Mine 1 old-version blocks - try: - self.nodes[1].generate(1) - raise AssertionError("Succeeded to mine a version=3 block after 950 version=4 blocks") - except JSONRPCException: - pass + # Mine 1 old-version blocks. This should fail + assert_raises_jsonrpc(-1,"CreateNewBlock: TestBlockValidity failed: bad-version(0x00000003)", self.nodes[1].generate, 1) self.sync_all() if (self.nodes[0].getblockcount() != cnt + 1051): raise AssertionError("Accepted a version=3 block after 950 version=4 blocks") diff --git a/qa/rpc-tests/bip68-sequence.py b/qa/rpc-tests/bip68-sequence.py index ffd461ccb..3ed6ebe04 100755 --- a/qa/rpc-tests/bip68-sequence.py +++ b/qa/rpc-tests/bip68-sequence.py @@ -90,12 +90,7 @@ class BIP68Test(BitcoinTestFramework): tx2.vout = [CTxOut(int(value-self.relayfee*COIN), CScript([b'a']))] tx2.rehash() - try: - self.nodes[0].sendrawtransaction(ToHex(tx2)) - except JSONRPCException as exp: - assert_equal(exp.error["message"], NOT_FINAL_ERROR) - else: - assert(False) + assert_raises_jsonrpc(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx2)) # Setting the version back down to 1 should disable the sequence lock, # so this should be accepted. @@ -190,14 +185,12 @@ class BIP68Test(BitcoinTestFramework): tx.vout.append(CTxOut(int(value-self.relayfee*tx_size*COIN/1000), CScript([b'a']))) rawtx = self.nodes[0].signrawtransaction(ToHex(tx))["hex"] - try: - self.nodes[0].sendrawtransaction(rawtx) - except JSONRPCException as exp: - assert(not should_pass and using_sequence_locks) - assert_equal(exp.error["message"], NOT_FINAL_ERROR) + if (using_sequence_locks and not should_pass): + # This transaction should be rejected + assert_raises_jsonrpc(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, rawtx) else: - assert(should_pass or not using_sequence_locks) - # Recalculate utxos if we successfully sent the transaction + # This raw transaction should be accepted + self.nodes[0].sendrawtransaction(rawtx) utxos = self.nodes[0].listunspent() # Test that sequence locks on unconfirmed inputs must have nSequence @@ -239,14 +232,13 @@ class BIP68Test(BitcoinTestFramework): tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee*COIN), CScript([b'a']))] tx.rehash() - try: - node.sendrawtransaction(ToHex(tx)) - except JSONRPCException as exp: - assert_equal(exp.error["message"], NOT_FINAL_ERROR) - assert(orig_tx.hash in node.getrawmempool()) + if (orig_tx.hash in node.getrawmempool()): + # sendrawtransaction should fail if the tx is in the mempool + assert_raises_jsonrpc(-26, NOT_FINAL_ERROR, node.sendrawtransaction, ToHex(tx)) else: - # orig_tx must not be in mempool - assert(orig_tx.hash not in node.getrawmempool()) + # sendrawtransaction should succeed if the tx is not in the mempool + node.sendrawtransaction(ToHex(tx)) + return tx test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=True) @@ -295,12 +287,7 @@ class BIP68Test(BitcoinTestFramework): tx5.vout[0].nValue += int(utxos[0]["amount"]*COIN) raw_tx5 = self.nodes[0].signrawtransaction(ToHex(tx5))["hex"] - try: - self.nodes[0].sendrawtransaction(raw_tx5) - except JSONRPCException as exp: - assert_equal(exp.error["message"], NOT_FINAL_ERROR) - else: - assert(False) + assert_raises_jsonrpc(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, raw_tx5) # Test mempool-BIP68 consistency after reorg # @@ -373,12 +360,7 @@ class BIP68Test(BitcoinTestFramework): tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))] tx3.rehash() - try: - self.nodes[0].sendrawtransaction(ToHex(tx3)) - except JSONRPCException as exp: - assert_equal(exp.error["message"], NOT_FINAL_ERROR) - else: - assert(False) + assert_raises_jsonrpc(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx3)) # make a block that violates bip68; ensure that the tip updates tip = int(self.nodes[0].getbestblockhash(), 16) diff --git a/qa/rpc-tests/bipdersig.py b/qa/rpc-tests/bipdersig.py index fa54bc274..371cc41bb 100755 --- a/qa/rpc-tests/bipdersig.py +++ b/qa/rpc-tests/bipdersig.py @@ -68,12 +68,8 @@ class BIP66Test(BitcoinTestFramework): if (self.nodes[0].getblockcount() != cnt + 1051): raise AssertionError("Failed to mine a version=3 block") - # Mine 1 old-version blocks - try: - self.nodes[1].generate(1) - raise AssertionError("Succeeded to mine a version=2 block after 950 version=3 blocks") - except JSONRPCException: - pass + # Mine 1 old-version blocks. This should fail + assert_raises_jsonrpc(-1, "CreateNewBlock: TestBlockValidity failed: bad-version(0x00000002)", self.nodes[1].generate, 1) self.sync_all() if (self.nodes[0].getblockcount() != cnt + 1051): raise AssertionError("Accepted a version=2 block after 950 version=3 blocks") diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py index 67b582684..596aed50e 100755 --- a/qa/rpc-tests/blockchain.py +++ b/qa/rpc-tests/blockchain.py @@ -14,10 +14,9 @@ Tests correspond to code in rpc/blockchain.cpp. from decimal import Decimal from test_framework.test_framework import BitcoinTestFramework -from test_framework.authproxy import JSONRPCException from test_framework.util import ( assert_equal, - assert_raises, + assert_raises_jsonrpc, assert_is_hex_string, assert_is_hash_string, start_nodes, @@ -58,8 +57,7 @@ class BlockchainTest(BitcoinTestFramework): def _test_getblockheader(self): node = self.nodes[0] - assert_raises( - JSONRPCException, lambda: node.getblockheader('nonsense')) + assert_raises_jsonrpc(-5, "Block not found", node.getblockheader, "nonsense") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) diff --git a/qa/rpc-tests/disablewallet.py b/qa/rpc-tests/disablewallet.py index ff7121659..2f729e19b 100755 --- a/qa/rpc-tests/disablewallet.py +++ b/qa/rpc-tests/disablewallet.py @@ -30,19 +30,10 @@ class DisableWalletTest (BitcoinTestFramework): x = self.nodes[0].validateaddress('mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ') assert(x['isvalid'] == True) - # Checking mining to an address without a wallet - try: - self.nodes[0].generatetoaddress(1, 'mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ') - except JSONRPCException as e: - assert("Invalid address" not in e.error['message']) - assert("ProcessNewBlock, block not accepted" not in e.error['message']) - assert("Couldn't create new block" not in e.error['message']) - - try: - self.nodes[0].generatetoaddress(1, '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy') - raise AssertionError("Must not mine to invalid address!") - except JSONRPCException as e: - assert("Invalid address" in e.error['message']) + # Checking mining to an address without a wallet. Generating to a valid address should succeed + # but generating to an invalid address will fail. + self.nodes[0].generatetoaddress(1, 'mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ') + assert_raises_jsonrpc(-5, "Invalid address", self.nodes[0].generatetoaddress, 1, '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy') if __name__ == '__main__': DisableWalletTest ().main () diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py index 3b17dfcfb..67745f77d 100755 --- a/qa/rpc-tests/getblocktemplate_proposals.py +++ b/qa/rpc-tests/getblocktemplate_proposals.py @@ -105,7 +105,7 @@ class GetBlockTemplateProposalTest(BitcoinTestFramework): # Test 3: Truncated final tx lastbyte = txlist[-1].pop() - assert_raises(JSONRPCException, assert_template, node, tmpl, txlist, 'n/a') + assert_raises_jsonrpc(-22, "Block decode failed", assert_template, node, tmpl, txlist, 'n/a') txlist[-1].append(lastbyte) # Test 4: Add an invalid tx to the end (duplicate of gen tx) @@ -126,7 +126,7 @@ class GetBlockTemplateProposalTest(BitcoinTestFramework): # Test 7: Bad tx count txlist.append(b'') - assert_raises(JSONRPCException, assert_template, node, tmpl, txlist, 'n/a') + assert_raises_jsonrpc(-22, 'Block decode failed', assert_template, node, tmpl, txlist, 'n/a') txlist.pop() # Test 8: Bad bits diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py index 4b9936a1f..cee58563f 100755 --- a/qa/rpc-tests/keypool.py +++ b/qa/rpc-tests/keypool.py @@ -28,11 +28,7 @@ class KeyPoolTest(BitcoinTestFramework): assert(addr_before_encrypting_data['hdmasterkeyid'] != wallet_info['hdmasterkeyid']) assert(addr_data['hdmasterkeyid'] == wallet_info['hdmasterkeyid']) - try: - addr = nodes[0].getnewaddress() - raise AssertionError('Keypool should be exhausted after one address') - except JSONRPCException as e: - assert(e.error['code']==-12) + assert_raises_jsonrpc(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress) # put three new keys in the keypool nodes[0].walletpassphrase('test', 12000) @@ -48,11 +44,7 @@ class KeyPoolTest(BitcoinTestFramework): # assert that four unique addresses were returned assert(len(addr) == 4) # the next one should fail - try: - addr = nodes[0].getrawchangeaddress() - raise AssertionError('Keypool should be exhausted after three addresses') - except JSONRPCException as e: - assert(e.error['code']==-12) + assert_raises_jsonrpc(-12, "Keypool ran out", nodes[0].getrawchangeaddress) # refill keypool with three new addresses nodes[0].walletpassphrase('test', 1) @@ -66,11 +58,7 @@ class KeyPoolTest(BitcoinTestFramework): nodes[0].generate(1) nodes[0].generate(1) nodes[0].generate(1) - try: - nodes[0].generate(1) - raise AssertionError('Keypool should be exhausted after three addesses') - except JSONRPCException as e: - assert(e.error['code']==-12) + assert_raises_jsonrpc(-12, "Keypool ran out", nodes[0].generate, 1) def __init__(self): super().__init__() diff --git a/qa/rpc-tests/mempool_packages.py b/qa/rpc-tests/mempool_packages.py index 915d17405..17e3a9a96 100755 --- a/qa/rpc-tests/mempool_packages.py +++ b/qa/rpc-tests/mempool_packages.py @@ -112,10 +112,7 @@ class MempoolPackagesTest(BitcoinTestFramework): assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN + 1000) # Adding one more transaction on to the chain should fail. - try: - self.chain_transaction(self.nodes[0], txid, vout, value, fee, 1) - except JSONRPCException as e: - self.log.info("too-long-ancestor-chain successfully rejected") + assert_raises_jsonrpc(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], txid, vout, value, fee, 1) # Check that prioritising a tx before it's added to the mempool works # First clear the mempool by mining a block. @@ -155,19 +152,19 @@ class MempoolPackagesTest(BitcoinTestFramework): for i in range(10): transaction_package.append({'txid': txid, 'vout': i, 'amount': sent_value}) - for i in range(MAX_DESCENDANTS): + # Sign and send up to MAX_DESCENDANT transactions chained off the parent tx + for i in range(MAX_DESCENDANTS - 1): utxo = transaction_package.pop(0) - try: - (txid, sent_value) = self.chain_transaction(self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) - for j in range(10): - transaction_package.append({'txid': txid, 'vout': j, 'amount': sent_value}) - if i == MAX_DESCENDANTS - 2: - mempool = self.nodes[0].getrawmempool(True) - assert_equal(mempool[parent_transaction]['descendantcount'], MAX_DESCENDANTS) - except JSONRPCException as e: - self.log.info(e.error['message']) - assert_equal(i, MAX_DESCENDANTS - 1) - self.log.info("tx that would create too large descendant package successfully rejected") + (txid, sent_value) = self.chain_transaction(self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) + for j in range(10): + transaction_package.append({'txid': txid, 'vout': j, 'amount': sent_value}) + + mempool = self.nodes[0].getrawmempool(True) + assert_equal(mempool[parent_transaction]['descendantcount'], MAX_DESCENDANTS) + + # Sending one more chained transaction will fail + utxo = transaction_package.pop(0) + assert_raises_jsonrpc(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) # TODO: check that node1's mempool is as expected diff --git a/qa/rpc-tests/mempool_reorg.py b/qa/rpc-tests/mempool_reorg.py index 585e4147b..812b54ffc 100755 --- a/qa/rpc-tests/mempool_reorg.py +++ b/qa/rpc-tests/mempool_reorg.py @@ -30,9 +30,10 @@ class MempoolCoinbaseTest(BitcoinTestFramework): self.sync_all() def run_test(self): - start_count = self.nodes[0].getblockcount() + # Start with a 200 block chain + assert_equal(self.nodes[0].getblockcount(), 200) - # Mine three blocks. After this, nodes[0] blocks + # Mine four blocks. After this, nodes[0] blocks # 101, 102, and 103 are spend-able. new_blocks = self.nodes[1].generate(4) self.sync_all() @@ -52,19 +53,21 @@ class MempoolCoinbaseTest(BitcoinTestFramework): spend_102_raw = create_tx(self.nodes[0], coinbase_txids[2], node0_address, 49.99) spend_103_raw = create_tx(self.nodes[0], coinbase_txids[3], node0_address, 49.99) - # Create a block-height-locked transaction which will be invalid after reorg + # Create a transaction which is time-locked to two blocks in the future timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 49.99}) # Set the time lock timelock_tx = timelock_tx.replace("ffffffff", "11111191", 1) timelock_tx = timelock_tx[:-8] + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000" timelock_tx = self.nodes[0].signrawtransaction(timelock_tx)["hex"] - assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, timelock_tx) + # This will raise an exception because the timelock transaction is too immature to spend + assert_raises_jsonrpc(-26, "non-final", self.nodes[0].sendrawtransaction, timelock_tx) # Broadcast and mine spend_102 and 103: spend_102_id = self.nodes[0].sendrawtransaction(spend_102_raw) spend_103_id = self.nodes[0].sendrawtransaction(spend_103_raw) self.nodes[0].generate(1) - assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, timelock_tx) + # Time-locked transaction is still too immature to spend + assert_raises_jsonrpc(-26,'non-final', self.nodes[0].sendrawtransaction, timelock_tx) # Create 102_1 and 103_1: spend_102_1_raw = create_tx(self.nodes[0], spend_102_id, node1_address, 49.98) @@ -73,6 +76,7 @@ class MempoolCoinbaseTest(BitcoinTestFramework): # Broadcast and mine 103_1: spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw) last_block = self.nodes[0].generate(1) + # Time-locked transaction can now be spent timelock_tx_id = self.nodes[0].sendrawtransaction(timelock_tx) # ... now put spend_101 and spend_102_1 in memory pools: @@ -85,6 +89,8 @@ class MempoolCoinbaseTest(BitcoinTestFramework): for node in self.nodes: node.invalidateblock(last_block[0]) + # Time-locked transaction is now too immature and has been removed from the mempool + # spend_103_1 has been re-orged out of the chain and is back in the mempool assert_equal(set(self.nodes[0].getrawmempool()), {spend_101_id, spend_102_1_id, spend_103_1_id}) # Use invalidateblock to re-org back and make all those coinbase spends diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py index 4818ad8bd..f562a93d8 100755 --- a/qa/rpc-tests/mempool_spendcoinbase.py +++ b/qa/rpc-tests/mempool_spendcoinbase.py @@ -45,7 +45,7 @@ class MempoolSpendCoinbaseTest(BitcoinTestFramework): spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0]) # coinbase at height 102 should be too immature to spend - assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, spends_raw[1]) + assert_raises_jsonrpc(-26,"bad-txns-premature-spend-of-coinbase", self.nodes[0].sendrawtransaction, spends_raw[1]) # mempool should have just spend_101: assert_equal(self.nodes[0].getrawmempool(), [ spend_101_id ]) diff --git a/qa/rpc-tests/nulldummy.py b/qa/rpc-tests/nulldummy.py index 4b215a70b..7b19fbfd8 100755 --- a/qa/rpc-tests/nulldummy.py +++ b/qa/rpc-tests/nulldummy.py @@ -66,38 +66,38 @@ class NULLDUMMYTest(BitcoinTestFramework): self.log.info("Test 1: NULLDUMMY compliant base transactions should be accepted to mempool and mined before activation [430]") test1txs = [self.create_transaction(self.nodes[0], coinbase_txid[0], self.ms_address, 49)] - txid1 = self.tx_submit(self.nodes[0], test1txs[0]) + txid1 = self.nodes[0].sendrawtransaction(bytes_to_hex_str(test1txs[0].serialize_with_witness()), True) test1txs.append(self.create_transaction(self.nodes[0], txid1, self.ms_address, 48)) - txid2 = self.tx_submit(self.nodes[0], test1txs[1]) + txid2 = self.nodes[0].sendrawtransaction(bytes_to_hex_str(test1txs[1].serialize_with_witness()), True) test1txs.append(self.create_transaction(self.nodes[0], coinbase_txid[1], self.wit_ms_address, 49)) - txid3 = self.tx_submit(self.nodes[0], test1txs[2]) + txid3 = self.nodes[0].sendrawtransaction(bytes_to_hex_str(test1txs[2].serialize_with_witness()), True) self.block_submit(self.nodes[0], test1txs, False, True) self.log.info("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation") test2tx = self.create_transaction(self.nodes[0], txid2, self.ms_address, 47) trueDummy(test2tx) - txid4 = self.tx_submit(self.nodes[0], test2tx, NULLDUMMY_ERROR) + assert_raises_jsonrpc(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, bytes_to_hex_str(test2tx.serialize_with_witness()), True) self.log.info("Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [431]") self.block_submit(self.nodes[0], [test2tx], False, True) - self.log.info("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation") - test4tx = self.create_transaction(self.nodes[0], txid4, self.address, 46) + self.log.info ("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation") + test4tx = self.create_transaction(self.nodes[0], test2tx.hash, self.address, 46) test6txs=[CTransaction(test4tx)] trueDummy(test4tx) - self.tx_submit(self.nodes[0], test4tx, NULLDUMMY_ERROR) + assert_raises_jsonrpc(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, bytes_to_hex_str(test4tx.serialize_with_witness()), True) self.block_submit(self.nodes[0], [test4tx]) - self.log.info("Test 5: Non-NULLDUMMY P2WSH multisig transaction invalid after activation") + print ("Test 5: Non-NULLDUMMY P2WSH multisig transaction invalid after activation") test5tx = self.create_transaction(self.nodes[0], txid3, self.wit_address, 48) test6txs.append(CTransaction(test5tx)) test5tx.wit.vtxinwit[0].scriptWitness.stack[0] = b'\x01' - self.tx_submit(self.nodes[0], test5tx, NULLDUMMY_ERROR) + assert_raises_jsonrpc(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, bytes_to_hex_str(test5tx.serialize_with_witness()), True) self.block_submit(self.nodes[0], [test5tx], True) self.log.info("Test 6: NULLDUMMY compliant base/witness transactions should be accepted to mempool and in block after activation [432]") for i in test6txs: - self.tx_submit(self.nodes[0], i) + self.nodes[0].sendrawtransaction(bytes_to_hex_str(i.serialize_with_witness()), True) self.block_submit(self.nodes[0], test6txs, True, True) @@ -112,17 +112,6 @@ class NULLDUMMYTest(BitcoinTestFramework): return tx - def tx_submit(self, node, tx, msg = ""): - tx.rehash() - try: - node.sendrawtransaction(bytes_to_hex_str(tx.serialize_with_witness()), True) - except JSONRPCException as exp: - assert_equal(exp.error["message"], msg) - else: - assert_equal('', msg) - return tx.hash - - def block_submit(self, node, txs, witness = False, accept = False): block = create_block(self.tip, create_coinbase(self.lastblockheight + 1), self.lastblocktime + 1) block.nVersion = 4 diff --git a/qa/rpc-tests/prioritise_transaction.py b/qa/rpc-tests/prioritise_transaction.py index 10f596b2c..0b04ad17a 100755 --- a/qa/rpc-tests/prioritise_transaction.py +++ b/qa/rpc-tests/prioritise_transaction.py @@ -107,13 +107,9 @@ class PrioritiseTransactionTest(BitcoinTestFramework): tx_hex = self.nodes[0].signrawtransaction(raw_tx)["hex"] tx_id = self.nodes[0].decoderawtransaction(tx_hex)["txid"] - try: - self.nodes[0].sendrawtransaction(tx_hex) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) # insufficient fee - assert(tx_id not in self.nodes[0].getrawmempool()) - else: - assert(False) + # This will raise an exception due to min relay fee not being met + assert_raises_jsonrpc(-26, "66: min relay fee not met", self.nodes[0].sendrawtransaction, tx_hex) + assert(tx_id not in self.nodes[0].getrawmempool()) # This is a less than 1000-byte transaction, so just set the fee # to be the minimum for a 1000 byte transaction and check that it is diff --git a/qa/rpc-tests/replace-by-fee.py b/qa/rpc-tests/replace-by-fee.py index 8e2abea6a..163c304eb 100755 --- a/qa/rpc-tests/replace-by-fee.py +++ b/qa/rpc-tests/replace-by-fee.py @@ -125,12 +125,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1b.vout = [CTxOut(1*COIN, CScript([b'b']))] tx1b_hex = txToHex(tx1b) - try: - tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) # insufficient fee - else: - assert(False) + # This will raise an exception due to insufficient fee + assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True) # Extra 0.1 BTC fee tx1b = CTransaction() @@ -172,12 +168,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): dbl_tx.vout = [CTxOut(initial_nValue - 30*COIN, CScript([1]))] dbl_tx_hex = txToHex(dbl_tx) - try: - self.nodes[0].sendrawtransaction(dbl_tx_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) # insufficient fee - else: - assert(False) # transaction mistakenly accepted! + # This will raise an exception due to insufficient fee + assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, True) # Accepted with sufficient fee dbl_tx = CTransaction() @@ -237,12 +229,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)] dbl_tx.vout = [CTxOut(initial_nValue - fee*n, CScript([1]))] dbl_tx_hex = txToHex(dbl_tx) - try: - self.nodes[0].sendrawtransaction(dbl_tx_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) # insufficient fee - else: - assert(False) + # This will raise an exception due to insufficient fee + assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, True) # 1 BTC fee is enough dbl_tx = CTransaction() @@ -269,13 +257,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)] dbl_tx.vout = [CTxOut(initial_nValue - 2*fee*n, CScript([1]))] dbl_tx_hex = txToHex(dbl_tx) - try: - self.nodes[0].sendrawtransaction(dbl_tx_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) - assert_equal("too many potential replacements" in exp.error['message'], True) - else: - assert(False) + # This will raise an exception + assert_raises_jsonrpc(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, dbl_tx_hex, True) for tx in tree_txs: tx.rehash() @@ -298,12 +281,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*999000]))] tx1b_hex = txToHex(tx1b) - try: - tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) # insufficient fee - else: - assert(False) + # This will raise an exception due to insufficient fee + assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True) def test_spends_of_conflicting_outputs(self): """Replacements that spend conflicting tx outputs are rejected""" @@ -325,12 +304,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx2.vout = tx1a.vout tx2_hex = txToHex(tx2) - try: - tx2_txid = self.nodes[0].sendrawtransaction(tx2_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) - else: - assert(False) + # This will raise an exception + assert_raises_jsonrpc(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, True) # Spend tx1a's output to test the indirect case. tx1b = CTransaction() @@ -346,12 +321,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx2.vout = tx1a.vout tx2_hex = txToHex(tx2) - try: - tx2_txid = self.nodes[0].sendrawtransaction(tx2_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) - else: - assert(False) + # This will raise an exception + assert_raises_jsonrpc(-26, "bad-txns-spends-conflicting-tx", self.nodes[0].sendrawtransaction, tx2_hex, True) def test_new_unconfirmed_inputs(self): """Replacements that add new unconfirmed inputs are rejected""" @@ -369,12 +340,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx2.vout = tx1.vout tx2_hex = txToHex(tx2) - try: - tx2_txid = self.nodes[0].sendrawtransaction(tx2_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) - else: - assert(False) + # This will raise an exception + assert_raises_jsonrpc(-26, "replacement-adds-unconfirmed", self.nodes[0].sendrawtransaction, tx2_hex, True) def test_too_many_replacements(self): """Replacements that evict too many transactions are rejected""" @@ -419,13 +386,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): double_tx.vout = [CTxOut(double_spend_value, CScript([b'a']))] double_tx_hex = txToHex(double_tx) - try: - self.nodes[0].sendrawtransaction(double_tx_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) - assert_equal("too many potential replacements" in exp.error['message'], True) - else: - assert(False) + # This will raise an exception + assert_raises_jsonrpc(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, double_tx_hex, True) # If we remove an input, it should pass double_tx = CTransaction() @@ -451,13 +413,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))] tx1b_hex = txToHex(tx1b) - try: - tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) - else: - self.log.info(tx1b_txid) - assert(False) + # This will raise an exception + assert_raises_jsonrpc(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx1b_hex, True) tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN)) @@ -474,12 +431,8 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx2b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))] tx2b_hex = txToHex(tx2b) - try: - tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) - else: - assert(False) + # This will raise an exception + assert_raises_jsonrpc(-26, "txn-mempool-conflict", self.nodes[0].sendrawtransaction, tx2b_hex, True) # Now create a new transaction that spends from tx1a and tx2a # opt-in on one of the inputs @@ -531,12 +484,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1b_hex = txToHex(tx1b) # Verify tx1b cannot replace tx1a. - try: - tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) - else: - assert(False) + assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx1b_hex, True) # Use prioritisetransaction to set tx1a's fee to 0. self.nodes[0].prioritisetransaction(tx1a_txid, int(-0.1*COIN)) @@ -563,12 +511,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx2b_hex = txToHex(tx2b) # Verify tx2b cannot replace tx2a. - try: - tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) - else: - assert(False) + assert_raises_jsonrpc(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx2b_hex, True) # Now prioritise tx2b to have a higher modified fee self.nodes[0].prioritisetransaction(tx2b.hash, int(0.1*COIN)) diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py index 220bf4ddd..8720a345c 100755 --- a/qa/rpc-tests/rpcbind_test.py +++ b/qa/rpc-tests/rpcbind_test.py @@ -92,11 +92,7 @@ class RPCBindTest(BitcoinTestFramework): # Check that with invalid rpcallowip, we are denied self.run_allowip_test([non_loopback_ip], non_loopback_ip, defaultport) - try: - self.run_allowip_test(['1.1.1.1'], non_loopback_ip, defaultport) - assert(not 'Connection not denied by rpcallowip as expected') - except JSONRPCException: - pass + assert_raises_jsonrpc(-342, "non-JSON HTTP response with '403 Forbidden' from server", self.run_allowip_test, ['1.1.1.1'], non_loopback_ip, defaultport) if __name__ == '__main__': RPCBindTest().main() diff --git a/qa/rpc-tests/segwit.py b/qa/rpc-tests/segwit.py index a6e3c29bd..5b1fba8ee 100755 --- a/qa/rpc-tests/segwit.py +++ b/qa/rpc-tests/segwit.py @@ -105,22 +105,12 @@ class SegWitTest(BitcoinTestFramework): assert_equal(len(node.getblock(block[0])["tx"]), 1) sync_blocks(self.nodes) - def fail_accept(self, node, txid, sign, redeem_script=""): - try: - send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script) - except JSONRPCException as exp: - assert(exp.error["code"] == -26) - else: - raise AssertionError("Tx should not have been accepted") + def fail_accept(self, node, error_msg, txid, sign, redeem_script=""): + assert_raises_jsonrpc(-26, error_msg, send_to_witness, 1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script) def fail_mine(self, node, txid, sign, redeem_script=""): send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script) - try: - node.generate(1) - except JSONRPCException as exp: - assert(exp.error["code"] == -1) - else: - raise AssertionError("Created valid block when TestBlockValidity should have failed") + assert_raises_jsonrpc(-1, "CreateNewBlock: TestBlockValidity failed", node.generate, 1) sync_blocks(self.nodes) def run_test(self): @@ -177,18 +167,18 @@ class SegWitTest(BitcoinTestFramework): self.log.info("Verify default node can't accept any witness format txs before fork") # unsigned, no scriptsig - self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], False) - self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], False) - self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False) - self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False) + self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V0][0], False) + self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V1][0], False) + self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False) + self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False) # unsigned with redeem script - self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False, witness_script(False, self.pubkey[0])) - self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False, witness_script(True, self.pubkey[0])) + self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False, witness_script(False, self.pubkey[0])) + self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False, witness_script(True, self.pubkey[0])) # signed - self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) - self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True) - self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) - self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) + self.fail_accept(self.nodes[0], "no-witness-yet", wit_ids[NODE_0][WIT_V0][0], True) + self.fail_accept(self.nodes[0], "no-witness-yet", wit_ids[NODE_0][WIT_V1][0], True) + self.fail_accept(self.nodes[0], "no-witness-yet", p2sh_ids[NODE_0][WIT_V0][0], True) + self.fail_accept(self.nodes[0], "no-witness-yet", p2sh_ids[NODE_0][WIT_V1][0], True) self.log.info("Verify witness txs are skipped for mining before the fork") self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][0], True) #block 424 @@ -203,8 +193,8 @@ class SegWitTest(BitcoinTestFramework): self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][1], False) #block 429 self.log.info("Verify unsigned p2sh witness txs without a redeem script are invalid") - self.fail_accept(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False) - self.fail_accept(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False) + self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V0][1], False) + self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V1][1], False) self.log.info("Verify unsigned p2sh witness txs with a redeem script in versionbits-settings blocks are valid before the fork") self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False, witness_script(False, self.pubkey[2])) #block 430 @@ -457,10 +447,13 @@ class SegWitTest(BitcoinTestFramework): importlist.append(bytes_to_hex_str(p2wshop1)) for i in importlist: + # import all generated addresses. The wallet already has the private keys for some of these, so catch JSON RPC + # exceptions and continue. try: self.nodes[0].importaddress(i,"",False,True) except JSONRPCException as exp: assert_equal(exp.error["message"], "The wallet already contains the private key for this address or script") + assert_equal(exp.error["code"], -4) self.nodes[0].importaddress(script_to_p2sh(op0)) # import OP_0 as address only self.nodes[0].importaddress(multisig_without_privkey_address) # Test multisig_without_privkey @@ -475,12 +468,7 @@ class SegWitTest(BitcoinTestFramework): # note that no witness address should be returned by unsolvable addresses # the multisig_without_privkey_address will fail because its keys were not added with importpubkey for i in uncompressed_spendable_address + uncompressed_solvable_address + unknown_address + unsolvable_address + [multisig_without_privkey_address]: - try: - self.nodes[0].addwitnessaddress(i) - except JSONRPCException as exp: - assert_equal(exp.error["message"], "Public key or redeemscript not known to wallet, or the key is uncompressed") - else: - assert(False) + assert_raises_jsonrpc(-4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i) for i in compressed_spendable_address + compressed_solvable_address: witaddress = self.nodes[0].addwitnessaddress(i) @@ -559,12 +547,8 @@ class SegWitTest(BitcoinTestFramework): # note that a multisig address returned by addmultisigaddress is not solvable until it is added with importaddress # premature_witaddress are not accepted until the script is added with addwitnessaddress first for i in uncompressed_spendable_address + uncompressed_solvable_address + premature_witaddress + [compressed_solvable_address[1]]: - try: - self.nodes[0].addwitnessaddress(i) - except JSONRPCException as exp: - assert_equal(exp.error["message"], "Public key or redeemscript not known to wallet, or the key is uncompressed") - else: - assert(False) + # This will raise an exception + assert_raises_jsonrpc(-4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i) # after importaddress it should pass addwitnessaddress v = self.nodes[0].validateaddress(compressed_solvable_address[1]) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index 00fe37563..80f74fa10 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -71,7 +71,7 @@ class WalletTest (BitcoinTestFramework): unspent_0 = self.nodes[2].listunspent()[0] unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]} self.nodes[2].lockunspent(False, [unspent_0]) - assert_raises_message(JSONRPCException, "Insufficient funds", self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20) + assert_raises_jsonrpc(-4, "Insufficient funds", self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20) assert_equal([unspent_0], self.nodes[2].listlockunspent()) self.nodes[2].lockunspent(True, [unspent_0]) assert_equal(len(self.nodes[2].listlockunspent()), 0) @@ -251,19 +251,11 @@ class WalletTest (BitcoinTestFramework): txObj = self.nodes[0].gettransaction(txId) assert_equal(txObj['amount'], Decimal('-0.0001')) - try: - txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1f-4") - except JSONRPCException as e: - assert("Invalid amount" in e.error['message']) - else: - raise AssertionError("Must not parse invalid amounts") + # This will raise an exception because the amount type is wrong + assert_raises_jsonrpc(-3, "Invalid amount", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4") - - try: - self.nodes[0].generate("2") - raise AssertionError("Must not accept strings as numeric") - except JSONRPCException as e: - assert("not an integer" in e.error['message']) + # This will raise an exception since generate does not accept a string + assert_raises_jsonrpc(-1, "not an integer", self.nodes[0].generate, "2") # Import address and private key to check correct behavior of spendable unspents # 1. Send some coins to generate new UTXO @@ -394,7 +386,7 @@ class WalletTest (BitcoinTestFramework): node0_balance = self.nodes[0].getbalance() # With walletrejectlongchains we will not create the tx and store it in our wallet. - assert_raises_message(JSONRPCException, "mempool chain", self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01')) + assert_raises_jsonrpc(-4, "Transaction has too long of a mempool chain", self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01')) # Verify nothing new in wallet assert_equal(total_txs, len(self.nodes[0].listtransactions("*",99999)))