diff --git a/test/functional/bip65-cltv.py b/test/functional/bip65-cltv.py --- a/test/functional/bip65-cltv.py +++ b/test/functional/bip65-cltv.py @@ -72,13 +72,9 @@ 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( diff --git a/test/functional/bip68-sequence.py b/test/functional/bip68-sequence.py --- a/test/functional/bip68-sequence.py +++ b/test/functional/bip68-sequence.py @@ -98,12 +98,8 @@ 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. @@ -211,14 +207,13 @@ rawtx = self.nodes[0].signrawtransaction( ToHex(tx), None, None, "ALL|FORKID")["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 @@ -264,14 +259,14 @@ 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( @@ -331,12 +326,8 @@ raw_tx5 = self.nodes[0].signrawtransaction( ToHex(tx5), None, None, "ALL|FORKID")["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 # @@ -414,12 +405,8 @@ 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/test/functional/bipdersig.py b/test/functional/bipdersig.py --- a/test/functional/bipdersig.py +++ b/test/functional/bipdersig.py @@ -71,13 +71,9 @@ 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( diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -11,10 +11,9 @@ 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, @@ -88,8 +87,8 @@ 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/test/functional/disablewallet.py b/test/functional/disablewallet.py --- a/test/functional/disablewallet.py +++ b/test/functional/disablewallet.py @@ -27,22 +27,12 @@ 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__': diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/getblocktemplate_proposals.py @@ -119,8 +119,8 @@ # 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) @@ -141,8 +141,8 @@ # 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/test/functional/keypool.py b/test/functional/keypool.py --- a/test/functional/keypool.py +++ b/test/functional/keypool.py @@ -33,12 +33,8 @@ '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) @@ -54,12 +50,8 @@ # 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) @@ -73,12 +65,7 @@ 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/test/functional/mempool_packages.py b/test/functional/mempool_packages.py --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -128,10 +128,8 @@ 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. @@ -176,23 +174,23 @@ 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/test/functional/mempool_reorg.py b/test/functional/mempool_reorg.py --- a/test/functional/mempool_reorg.py +++ b/test/functional/mempool_reorg.py @@ -25,9 +25,10 @@ alert_filename = None # Set by setup_network 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() @@ -50,25 +51,26 @@ 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 = timelock_tx[:-8] + \ + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000" timelock_tx = self.nodes[0].signrawtransaction( timelock_tx, None, None, "ALL|FORKID")["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, "bad-txns-nonfinal", + 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, 'bad-txns-nonfinal', + self.nodes[0].sendrawtransaction, timelock_tx) # Create 102_1 and 103_1: spend_102_1_raw = create_tx( @@ -79,6 +81,7 @@ # 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: @@ -92,6 +95,8 @@ 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}) diff --git a/test/functional/mempool_spendcoinbase.py b/test/functional/mempool_spendcoinbase.py --- a/test/functional/mempool_spendcoinbase.py +++ b/test/functional/mempool_spendcoinbase.py @@ -45,8 +45,8 @@ 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/test/functional/nulldummy.py b/test/functional/nulldummy.py --- a/test/functional/nulldummy.py +++ b/test/functional/nulldummy.py @@ -66,10 +66,12 @@ "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) self.block_submit(self.nodes[0], test1txs, False, True) self.log.info( @@ -77,7 +79,8 @@ test2tx = self.create_transaction( self.nodes[0], txid2, self.ms_address, 48) 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]") @@ -93,17 +96,6 @@ tx.deserialize(f) 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) diff --git a/test/functional/prioritise_transaction.py b/test/functional/prioritise_transaction.py --- a/test/functional/prioritise_transaction.py +++ b/test/functional/prioritise_transaction.py @@ -130,13 +130,10 @@ raw_tx2, None, None, "ALL|FORKID")["hex"] tx2_id = self.nodes[0].decoderawtransaction(tx2_hex)["txid"] - try: - self.nodes[0].sendrawtransaction(tx2_hex) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) # insufficient fee - assert(tx2_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: insufficient priority", + self.nodes[0].sendrawtransaction, tx2_hex) + assert(tx2_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/test/functional/rpcbind_test.py b/test/functional/rpcbind_test.py --- a/test/functional/rpcbind_test.py +++ b/test/functional/rpcbind_test.py @@ -103,11 +103,8 @@ # 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__': diff --git a/test/functional/rpcnamedargs.py b/test/functional/rpcnamedargs.py --- a/test/functional/rpcnamedargs.py +++ b/test/functional/rpcnamedargs.py @@ -33,8 +33,8 @@ h = node.help(command='getinfo') assert(h.startswith('getinfo\n')) - assert_raises_jsonrpc( - -8, 'Unknown named parameter', node.help, random='getinfo') + assert_raises_jsonrpc(-8, 'Unknown named parameter', + node.help, random='getinfo') h = node.getblockhash(height=0) node.getblock(blockhash=h) diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -680,8 +680,7 @@ try: fun(*args, **kwds) except JSONRPCException as e: - # JSONRPCException was thrown as expected. Check the code and message - # values are correct. + # JSONRPCException was thrown as expected. Check the code and message values are correct. if (code is not None) and (code != e.error["code"]): raise AssertionError( "Unexpected JSONRPC error code %i" % e.error["code"]) diff --git a/test/functional/wallet.py b/test/functional/wallet.py --- a/test/functional/wallet.py +++ b/test/functional/wallet.py @@ -72,8 +72,8 @@ 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) @@ -272,19 +272,13 @@ 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 @@ -428,10 +422,9 @@ assert_equal(len(self.nodes[0].getrawmempool()), chainlimit * 2) 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')) + # With walletrejectlongchains we will not create the tx and store it in our wallet. + 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(