Skip to content

Commit

Permalink
Fix RPC failure testing (2 of 2)
Browse files Browse the repository at this point in the history
Commit 9db8eec 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().
  • Loading branch information
jnewbery committed Mar 15, 2017
1 parent ce01e62 commit c9bd0f6
Show file tree
Hide file tree
Showing 16 changed files with 119 additions and 265 deletions.
8 changes: 2 additions & 6 deletions qa/rpc-tests/bip65-cltv.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,8 @@ def run_test(self):
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")
Expand Down
46 changes: 14 additions & 32 deletions qa/rpc-tests/bip68-sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,7 @@ def test_disable_flag(self):
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.
Expand Down Expand Up @@ -190,14 +185,12 @@ def test_sequence_lock_confirmed_inputs(self):
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
Expand Down Expand Up @@ -239,14 +232,13 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
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)
Expand Down Expand Up @@ -295,12 +287,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
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
#
Expand Down Expand Up @@ -373,12 +360,7 @@ def test_bip68_not_consensus(self):
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)
Expand Down
8 changes: 2 additions & 6 deletions qa/rpc-tests/bipdersig.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,8 @@ def run_test(self):
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")
Expand Down
6 changes: 2 additions & 4 deletions qa/rpc-tests/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,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,
Expand Down Expand Up @@ -58,8 +57,7 @@ def _test_gettxoutsetinfo(self):
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)
Expand Down
17 changes: 4 additions & 13 deletions qa/rpc-tests/disablewallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,10 @@ def run_test (self):
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 ()
4 changes: 2 additions & 2 deletions qa/rpc-tests/getblocktemplate_proposals.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def run_test(self):

# 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)
Expand All @@ -126,7 +126,7 @@ def run_test(self):

# 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
Expand Down
18 changes: 3 additions & 15 deletions qa/rpc-tests/keypool.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,7 @@ def run_test(self):
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)
Expand All @@ -48,11 +44,7 @@ def run_test(self):
# 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)
Expand All @@ -66,11 +58,7 @@ def run_test(self):
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__()
Expand Down
29 changes: 13 additions & 16 deletions qa/rpc-tests/mempool_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,7 @@ def run_test(self):
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.
Expand Down Expand Up @@ -155,19 +152,19 @@ def run_test(self):
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

Expand Down
16 changes: 11 additions & 5 deletions qa/rpc-tests/mempool_reorg.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ def setup_network(self):
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()
Expand All @@ -52,19 +53,21 @@ def run_test(self):
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)
Expand All @@ -73,6 +76,7 @@ def run_test(self):
# 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:
Expand All @@ -85,6 +89,8 @@ def run_test(self):

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
Expand Down
2 changes: 1 addition & 1 deletion qa/rpc-tests/mempool_spendcoinbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def run_test(self):
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 ])
Expand Down
31 changes: 10 additions & 21 deletions qa/rpc-tests/nulldummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,38 +66,38 @@ def run_test(self):

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)


Expand All @@ -112,17 +112,6 @@ def create_transaction(self, node, txid, to_address, amount):
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
Expand Down

0 comments on commit c9bd0f6

Please sign in to comment.