diff options
Diffstat (limited to 'qa/rpc-tests')
-rwxr-xr-x | qa/rpc-tests/mempool_resurrect_test.py | 88 | ||||
-rwxr-xr-x | qa/rpc-tests/mempool_spendcoinbase.py | 69 | ||||
-rwxr-xr-x | qa/rpc-tests/rest.py | 62 | ||||
-rw-r--r-- | qa/rpc-tests/util.py | 16 |
4 files changed, 234 insertions, 1 deletions
diff --git a/qa/rpc-tests/mempool_resurrect_test.py b/qa/rpc-tests/mempool_resurrect_test.py new file mode 100755 index 0000000000..907cbf98f9 --- /dev/null +++ b/qa/rpc-tests/mempool_resurrect_test.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test resurrection of mined transactions when +# the blockchain is re-organized. +# + +from test_framework import BitcoinTestFramework +from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException +from util import * +import os +import shutil + +# Create one-input, one-output, no-fee transaction: +class MempoolCoinbaseTest(BitcoinTestFramework): + + def setup_network(self): + # Just need one node for this test + args = ["-checkmempool", "-debug=mempool"] + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir, args)) + self.is_network_split = False + + def create_tx(self, from_txid, to_address, amount): + inputs = [{ "txid" : from_txid, "vout" : 0}] + outputs = { to_address : amount } + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + signresult = self.nodes[0].signrawtransaction(rawtx) + assert_equal(signresult["complete"], True) + return signresult["hex"] + + def run_test(self): + node0_address = self.nodes[0].getnewaddress() + + # Spend block 1/2/3's coinbase transactions + # Mine a block. + # Create three more transactions, spending the spends + # Mine another block. + # ... make sure all the transactions are confirmed + # Invalidate both blocks + # ... make sure all the transactions are put back in the mempool + # Mine a new block + # ... make sure all the transactions are confirmed again. + + b = [ self.nodes[0].getblockhash(n) for n in range(1, 4) ] + coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ] + spends1_raw = [ self.create_tx(txid, node0_address, 50) for txid in coinbase_txids ] + spends1_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends1_raw ] + + blocks = [] + blocks.extend(self.nodes[0].setgenerate(True, 1)) + + spends2_raw = [ self.create_tx(txid, node0_address, 49.99) for txid in spends1_id ] + spends2_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends2_raw ] + + blocks.extend(self.nodes[0].setgenerate(True, 1)) + + # mempool should be empty, all txns confirmed + assert_equal(set(self.nodes[0].getrawmempool()), set()) + for txid in spends1_id+spends2_id: + tx = self.nodes[0].gettransaction(txid) + assert(tx["confirmations"] > 0) + + # Use invalidateblock to re-org back; all transactions should + # end up unconfirmed and back in the mempool + for node in self.nodes: + node.invalidateblock(blocks[0]) + + # mempool should be empty, all txns confirmed + assert_equal(set(self.nodes[0].getrawmempool()), set(spends1_id+spends2_id)) + for txid in spends1_id+spends2_id: + tx = self.nodes[0].gettransaction(txid) + assert(tx["confirmations"] == 0) + + # Generate another block, they should all get mined + self.nodes[0].setgenerate(True, 1) + # mempool should be empty, all txns confirmed + assert_equal(set(self.nodes[0].getrawmempool()), set()) + for txid in spends1_id+spends2_id: + tx = self.nodes[0].gettransaction(txid) + assert(tx["confirmations"] > 0) + + +if __name__ == '__main__': + MempoolCoinbaseTest().main() diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py new file mode 100755 index 0000000000..0fc7c8577e --- /dev/null +++ b/qa/rpc-tests/mempool_spendcoinbase.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test spending coinbase transactions. +# The coinbase transaction in block N can appear in block +# N+100... so is valid in the mempool when the best block +# height is N+99. +# This test makes sure coinbase spends that will be mature +# in the next block are accepted into the memory pool, +# but less mature coinbase spends are NOT. +# + +from test_framework import BitcoinTestFramework +from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException +from util import * +import os +import shutil + +# Create one-input, one-output, no-fee transaction: +class MempoolSpendCoinbaseTest(BitcoinTestFramework): + + def setup_network(self): + # Just need one node for this test + args = ["-checkmempool", "-debug=mempool"] + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir, args)) + self.is_network_split = False + + def create_tx(self, from_txid, to_address, amount): + inputs = [{ "txid" : from_txid, "vout" : 0}] + outputs = { to_address : amount } + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + signresult = self.nodes[0].signrawtransaction(rawtx) + assert_equal(signresult["complete"], True) + return signresult["hex"] + + def run_test(self): + chain_height = self.nodes[0].getblockcount() + assert_equal(chain_height, 200) + node0_address = self.nodes[0].getnewaddress() + + # Coinbase at height chain_height-100+1 ok in mempool, should + # get mined. Coinbase at height chain_height-100+2 is + # is too immature to spend. + b = [ self.nodes[0].getblockhash(n) for n in range(101, 103) ] + coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ] + spends_raw = [ self.create_tx(txid, node0_address, 50) for txid in coinbase_txids ] + + 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]) + + # mempool should have just spend_101: + assert_equal(self.nodes[0].getrawmempool(), [ spend_101_id ]) + + # mine a block, spend_101 should get confirmed + self.nodes[0].setgenerate(True, 1) + assert_equal(set(self.nodes[0].getrawmempool()), set()) + + # ... and now height 102 can be spent: + spend_102_id = self.nodes[0].sendrawtransaction(spends_raw[1]) + assert_equal(self.nodes[0].getrawmempool(), [ spend_102_id ]) + +if __name__ == '__main__': + MempoolSpendCoinbaseTest().main() diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py new file mode 100755 index 0000000000..2d301bf4f8 --- /dev/null +++ b/qa/rpc-tests/rest.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test REST interface +# + +from test_framework import BitcoinTestFramework +from util import * +import json + +try: + import http.client as httplib +except ImportError: + import httplib +try: + import urllib.parse as urlparse +except ImportError: + import urlparse + +def http_get_call(host, port, path, response_object = 0): + conn = httplib.HTTPConnection(host, port) + conn.request('GET', path) + + if response_object: + return conn.getresponse() + + return conn.getresponse().read() + + +class RESTTest (BitcoinTestFramework): + FORMAT_SEPARATOR = "." + + def run_test(self): + url = urlparse.urlparse(self.nodes[0].url) + bb_hash = self.nodes[0].getbestblockhash() + + # check binary format + response = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+"bin", True) + assert_equal(response.status, 200) + assert_greater_than(int(response.getheader('content-length')), 10) + + # check json format + json_string = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+'json') + json_obj = json.loads(json_string) + assert_equal(json_obj['hash'], bb_hash) + + # do tx test + tx_hash = json_obj['tx'][0]; + json_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"json") + json_obj = json.loads(json_string) + assert_equal(json_obj['txid'], tx_hash) + + # check hex format response + hex_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"hex", True) + assert_equal(response.status, 200) + assert_greater_than(int(response.getheader('content-length')), 10) + +if __name__ == '__main__': + RESTTest ().main () diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py index bed7fed8ca..ec65f783e8 100644 --- a/qa/rpc-tests/util.py +++ b/qa/rpc-tests/util.py @@ -163,7 +163,7 @@ def start_node(i, dirname, extra_args=None, rpchost=None): Start a bitcoind and return RPC connection to it """ datadir = os.path.join(dirname, "node"+str(i)) - args = [ os.getenv("BITCOIND", "bitcoind"), "-datadir="+datadir, "-keypool=1", "-discover=0" ] + args = [ os.getenv("BITCOIND", "bitcoind"), "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ] if extra_args is not None: args.extend(extra_args) bitcoind_processes[i] = subprocess.Popen(args) devnull = open("/dev/null", "w+") @@ -327,3 +327,17 @@ def random_transaction(nodes, amount, min_fee, fee_increment, fee_variants): def assert_equal(thing1, thing2): if thing1 != thing2: raise AssertionError("%s != %s"%(str(thing1),str(thing2))) + +def assert_greater_than(thing1, thing2): + if thing1 <= thing2: + raise AssertionError("%s <= %s"%(str(thing1),str(thing2))) + +def assert_raises(exc, fun, *args, **kwds): + try: + fun(*args, **kwds) + except exc: + pass + except Exception as e: + raise AssertionError("Unexpected exception raised: "+type(e).__name__) + else: + raise AssertionError("No exception raised") |