Merge #12766: [Tests] Tidy up REST interface functional tests

55efc1f [tests] simplify binary and hex response parsing in interface_rest.py (Roman Zeyde)
ade5964 [tests] only use 2 nodes in interface_rest.py (John Newbery)
ad00fbe [tests] refactor interface_rest.py to avoid code repetition (John Newbery)
7a3181a [tests] Make json request building more consistent in interface_rest.py (John Newbery)
3fd4490 [tests] improve logging and documentation in interface_rest.py (John Newbery)
abf190e [tests] fix flake8 warnings in interface_rest.py test (John Newbery)

Pull request description:

  Following the comment at https://github.com/bitcoin/bitcoin/pull/12717#pullrequestreview-106189117.

Tree-SHA512: b55560f0d8f3069584f5a2398285483a0a23514b2b2bd2c1ced2db1cb30dc24f60f720d0fa4de30259f7918d3178d94680ae9321649544d1d04d687a2e672559
This commit is contained in:
Wladimir J. van der Laan 2018-04-07 15:56:55 +02:00
commit 69310a342f
No known key found for this signature in database
GPG Key ID: 1E4AED62986CD25D
1 changed files with 180 additions and 234 deletions

View File

@ -4,350 +4,296 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php. # file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the REST API.""" """Test the REST API."""
from test_framework.test_framework import BitcoinTestFramework import binascii
from test_framework.util import * from decimal import Decimal
from struct import * from enum import Enum
from io import BytesIO from io import BytesIO
from codecs import encode import json
from struct import pack, unpack
import http.client import http.client
import urllib.parse import urllib.parse
def deser_uint256(f): from test_framework.test_framework import BitcoinTestFramework
r = 0 from test_framework.util import (
for i in range(8): assert_equal,
t = unpack(b"<I", f.read(4))[0] assert_greater_than,
r += t << (i * 32) assert_greater_than_or_equal,
return r hex_str_to_bytes,
)
#allows simple http get calls class ReqType(Enum):
def http_get_call(host, port, path, response_object = 0): JSON = 1
conn = http.client.HTTPConnection(host, port) BIN = 2
conn.request('GET', path) HEX = 3
if response_object: class RetType(Enum):
return conn.getresponse() OBJ = 1
BYTES = 2
JSON = 3
return conn.getresponse().read().decode('utf-8') def filter_output_indices_by_value(vouts, value):
for vout in vouts:
#allows simple http post calls with a request body if vout['value'] == value:
def http_post_call(host, port, path, requestdata = '', response_object = 0): yield vout['n']
conn = http.client.HTTPConnection(host, port)
conn.request('POST', path, requestdata)
if response_object:
return conn.getresponse()
return conn.getresponse().read()
class RESTTest (BitcoinTestFramework): class RESTTest (BitcoinTestFramework):
FORMAT_SEPARATOR = "."
def set_test_params(self): def set_test_params(self):
self.setup_clean_chain = True self.setup_clean_chain = True
self.num_nodes = 3 self.num_nodes = 2
self.extra_args = [["-rest"]] * self.num_nodes self.extra_args = [["-rest"], []]
def setup_network(self, split=False): def test_rest_request(self, uri, http_method='GET', req_type=ReqType.JSON, body='', status=200, ret_type=RetType.JSON):
super().setup_network() rest_uri = '/rest' + uri
connect_nodes_bi(self.nodes, 0, 2) if req_type == ReqType.JSON:
rest_uri += '.json'
elif req_type == ReqType.BIN:
rest_uri += '.bin'
elif req_type == ReqType.HEX:
rest_uri += '.hex'
conn = http.client.HTTPConnection(self.url.hostname, self.url.port)
self.log.debug('%s %s %s', http_method, rest_uri, body)
if http_method == 'GET':
conn.request('GET', rest_uri)
elif http_method == 'POST':
conn.request('POST', rest_uri, body)
resp = conn.getresponse()
assert_equal(resp.status, status)
if ret_type == RetType.OBJ:
return resp
elif ret_type == RetType.BYTES:
return resp.read()
elif ret_type == RetType.JSON:
return json.loads(resp.read().decode('utf-8'), parse_float=Decimal)
def run_test(self): def run_test(self):
url = urllib.parse.urlparse(self.nodes[0].url) self.url = urllib.parse.urlparse(self.nodes[0].url)
self.log.info("Mining blocks...") self.log.info("Mine blocks and send Bitcoin to node 1")
# Random address so node1's balance doesn't increase
not_related_address = "2MxqoHEdNQTyYeX1mHcbrrpzgojbosTpCvJ"
self.nodes[0].generate(1) self.nodes[0].generate(1)
self.sync_all() self.sync_all()
self.nodes[2].generate(100) self.nodes[1].generatetoaddress(100, not_related_address)
self.sync_all() self.sync_all()
assert_equal(self.nodes[0].getbalance(), 50) assert_equal(self.nodes[0].getbalance(), 50)
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1) txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
self.sync_all() self.sync_all()
self.nodes[2].generate(1) self.nodes[1].generatetoaddress(1, not_related_address)
self.sync_all() self.sync_all()
bb_hash = self.nodes[0].getbestblockhash() bb_hash = self.nodes[0].getbestblockhash()
assert_equal(self.nodes[1].getbalance(), Decimal("0.1")) #balance now should be 0.1 on node 1 assert_equal(self.nodes[1].getbalance(), Decimal("0.1"))
# load the latest 0.1 tx over the REST API self.log.info("Load the transaction using the /tx URI")
json_string = http_get_call(url.hostname, url.port, '/rest/tx/'+txid+self.FORMAT_SEPARATOR+"json")
json_obj = json.loads(json_string) json_obj = self.test_rest_request("/tx/{}".format(txid))
vintx = json_obj['vin'][0]['txid'] # get the vin to later check for utxo (should be spent by then) spent = (json_obj['vin'][0]['txid'], json_obj['vin'][0]['vout']) # get the vin to later check for utxo (should be spent by then)
# get n of 0.1 outpoint # get n of 0.1 outpoint
n = 0 n, = filter_output_indices_by_value(json_obj['vout'], Decimal('0.1'))
for vout in json_obj['vout']: spending = (txid, n)
if vout['value'] == 0.1:
n = vout['n']
self.log.info("Query an unspent TXO using the /getutxos URI")
####################################### json_obj = self.test_rest_request("/getutxos/{}-{}".format(*spending))
# GETUTXOS: query an unspent outpoint #
#######################################
json_request = '/'+txid+'-'+str(n)
json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json')
json_obj = json.loads(json_string)
#check chainTip response # Check chainTip response
assert_equal(json_obj['chaintipHash'], bb_hash) assert_equal(json_obj['chaintipHash'], bb_hash)
#make sure there is one utxo # Make sure there is one utxo
assert_equal(len(json_obj['utxos']), 1) assert_equal(len(json_obj['utxos']), 1)
assert_equal(json_obj['utxos'][0]['value'], 0.1) assert_equal(json_obj['utxos'][0]['value'], Decimal('0.1'))
self.log.info("Query a spent TXO using the /getutxos URI")
################################################# json_obj = self.test_rest_request("/getutxos/{}-{}".format(*spent))
# GETUTXOS: now query an already spent outpoint #
#################################################
json_request = '/'+vintx+'-0'
json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json')
json_obj = json.loads(json_string)
#check chainTip response # Check chainTip response
assert_equal(json_obj['chaintipHash'], bb_hash) assert_equal(json_obj['chaintipHash'], bb_hash)
#make sure there is no utxo in the response because this oupoint has been spent # Make sure there is no utxo in the response because this outpoint has been spent
assert_equal(len(json_obj['utxos']), 0) assert_equal(len(json_obj['utxos']), 0)
#check bitmap # Check bitmap
assert_equal(json_obj['bitmap'], "0") assert_equal(json_obj['bitmap'], "0")
self.log.info("Query two TXOs using the /getutxos URI")
json_obj = self.test_rest_request("/getutxos/{}-{}/{}-{}".format(*(spending + spent)))
##################################################
# GETUTXOS: now check both with the same request #
##################################################
json_request = '/'+txid+'-'+str(n)+'/'+vintx+'-0'
json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json')
json_obj = json.loads(json_string)
assert_equal(len(json_obj['utxos']), 1) assert_equal(len(json_obj['utxos']), 1)
assert_equal(json_obj['bitmap'], "10") assert_equal(json_obj['bitmap'], "10")
#test binary response self.log.info("Query the TXOs using the /getutxos URI with a binary response")
bb_hash = self.nodes[0].getbestblockhash()
binaryRequest = b'\x01\x02' bin_request = b'\x01\x02'
binaryRequest += hex_str_to_bytes(txid) for txid, n in [spending, spent]:
binaryRequest += pack("i", n) bin_request += hex_str_to_bytes(txid)
binaryRequest += hex_str_to_bytes(vintx) bin_request += pack("i", n)
binaryRequest += pack("i", 0)
bin_response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', binaryRequest) bin_response = self.test_rest_request("/getutxos", http_method='POST', req_type=ReqType.BIN, body=bin_request, ret_type=RetType.BYTES)
output = BytesIO() output = BytesIO(bin_response)
output.write(bin_response) chain_height, = unpack("i", output.read(4))
output.seek(0) response_hash = binascii.hexlify(output.read(32)[::-1]).decode('ascii')
chainHeight = unpack("i", output.read(4))[0]
hashFromBinResponse = hex(deser_uint256(output))[2:].zfill(64)
assert_equal(bb_hash, hashFromBinResponse) #check if getutxo's chaintip during calculation was fine assert_equal(bb_hash, response_hash) # check if getutxo's chaintip during calculation was fine
assert_equal(chainHeight, 102) #chain height must be 102 assert_equal(chain_height, 102) # chain height must be 102
self.log.info("Test the /getutxos URI with and without /checkmempool")
############################ # Create a transaction, check that it's found with /checkmempool, but
# GETUTXOS: mempool checks # # not found without. Then confirm the transaction and check that it's
############################ # found with or without /checkmempool.
# do a tx and don't sync # do a tx and don't sync
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1) txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
json_string = http_get_call(url.hostname, url.port, '/rest/tx/'+txid+self.FORMAT_SEPARATOR+"json") json_obj = self.test_rest_request("/tx/{}".format(txid))
json_obj = json.loads(json_string)
# get the spent output to later check for utxo (should be spent by then) # get the spent output to later check for utxo (should be spent by then)
spent = '{}-{}'.format(json_obj['vin'][0]['txid'], json_obj['vin'][0]['vout']) spent = (json_obj['vin'][0]['txid'], json_obj['vin'][0]['vout'])
# get n of 0.1 outpoint # get n of 0.1 outpoint
n = 0 n, = filter_output_indices_by_value(json_obj['vout'], Decimal('0.1'))
for vout in json_obj['vout']: spending = (txid, n)
if vout['value'] == 0.1:
n = vout['n']
spending = '{}-{}'.format(txid, n)
json_request = '/'+spending json_obj = self.test_rest_request("/getutxos/{}-{}".format(*spending))
json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json') assert_equal(len(json_obj['utxos']), 0)
json_obj = json.loads(json_string)
assert_equal(len(json_obj['utxos']), 0) #there should be no outpoint because it has just added to the mempool
json_request = '/checkmempool/'+spending json_obj = self.test_rest_request("/getutxos/checkmempool/{}-{}".format(*spending))
json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json') assert_equal(len(json_obj['utxos']), 1)
json_obj = json.loads(json_string)
assert_equal(len(json_obj['utxos']), 1) #there should be an outpoint because it has just added to the mempool
json_request = '/'+spent json_obj = self.test_rest_request("/getutxos/{}-{}".format(*spent))
json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json') assert_equal(len(json_obj['utxos']), 1)
json_obj = json.loads(json_string)
assert_equal(len(json_obj['utxos']), 1) #there should be an outpoint because its spending tx is not confirmed
json_request = '/checkmempool/'+spent json_obj = self.test_rest_request("/getutxos/checkmempool/{}-{}".format(*spent))
json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json') assert_equal(len(json_obj['utxos']), 0)
json_obj = json.loads(json_string)
assert_equal(len(json_obj['utxos']), 0) #there should be no outpoint because it has just spent (by mempool tx)
self.nodes[0].generate(1) self.nodes[0].generate(1)
self.sync_all() self.sync_all()
json_request = '/'+spending json_obj = self.test_rest_request("/getutxos/{}-{}".format(*spending))
json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json') assert_equal(len(json_obj['utxos']), 1)
json_obj = json.loads(json_string)
assert_equal(len(json_obj['utxos']), 1) #there should be an outpoint because it was mined
json_request = '/checkmempool/'+spending json_obj = self.test_rest_request("/getutxos/checkmempool/{}-{}".format(*spending))
json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json') assert_equal(len(json_obj['utxos']), 1)
json_obj = json.loads(json_string)
assert_equal(len(json_obj['utxos']), 1) #there should be an outpoint because it was mined
#do some invalid requests # Do some invalid requests
json_request = '{"checkmempool' self.test_rest_request("/getutxos", http_method='POST', req_type=ReqType.JSON, body='{"checkmempool', status=400, ret_type=RetType.OBJ)
response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request, True) self.test_rest_request("/getutxos", http_method='POST', req_type=ReqType.BIN, body='{"checkmempool', status=400, ret_type=RetType.OBJ)
assert_equal(response.status, 400) #must be a 400 because we send an invalid json request self.test_rest_request("/getutxos/checkmempool", http_method='POST', req_type=ReqType.JSON, status=400, ret_type=RetType.OBJ)
json_request = '{"checkmempool' # Test limits
response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', json_request, True) long_uri = '/'.join(["{}-{}".format(txid, n) for n in range(20)])
assert_equal(response.status, 400) #must be a 400 because we send an invalid bin request self.test_rest_request("/getutxos/checkmempool/{}".format(long_uri), http_method='POST', status=400, ret_type=RetType.OBJ)
response = http_post_call(url.hostname, url.port, '/rest/getutxos/checkmempool'+self.FORMAT_SEPARATOR+'bin', '', True) long_uri = '/'.join(['{}-{}'.format(txid, n) for n in range(15)])
assert_equal(response.status, 400) #must be a 400 because we send an invalid bin request self.test_rest_request("/getutxos/checkmempool/{}".format(long_uri), http_method='POST', status=200)
#test limits
json_request = '/checkmempool/'
for x in range(0, 20):
json_request += txid+'-'+str(n)+'/'
json_request = json_request.rstrip("/")
response = http_post_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json', '', True)
assert_equal(response.status, 400) #must be a 400 because we exceeding the limits
json_request = '/checkmempool/'
for x in range(0, 15):
json_request += txid+'-'+str(n)+'/'
json_request = json_request.rstrip("/")
response = http_post_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json', '', True)
assert_equal(response.status, 200) #must be a 200 because we are within the limits
self.nodes[0].generate(1) # generate block to not affect upcoming tests self.nodes[0].generate(1) # generate block to not affect upcoming tests
self.sync_all() self.sync_all()
################ self.log.info("Test the /block and /headers URIs")
# /rest/block/ # bb_hash = self.nodes[0].getbestblockhash()
################
# check binary format # Check binary format
response = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+"bin", True) response = self.test_rest_request("/block/{}".format(bb_hash), req_type=ReqType.BIN, ret_type=RetType.OBJ)
assert_equal(response.status, 200)
assert_greater_than(int(response.getheader('content-length')), 80) assert_greater_than(int(response.getheader('content-length')), 80)
response_str = response.read() response_bytes = response.read()
# compare with block header # Compare with block header
response_header = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"bin", True) response_header = self.test_rest_request("/headers/1/{}".format(bb_hash), req_type=ReqType.BIN, ret_type=RetType.OBJ)
assert_equal(response_header.status, 200)
assert_equal(int(response_header.getheader('content-length')), 80) assert_equal(int(response_header.getheader('content-length')), 80)
response_header_str = response_header.read() response_header_bytes = response_header.read()
assert_equal(response_str[0:80], response_header_str) assert_equal(response_bytes[:80], response_header_bytes)
# check block hex format # Check block hex format
response_hex = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+"hex", True) response_hex = self.test_rest_request("/block/{}".format(bb_hash), req_type=ReqType.HEX, ret_type=RetType.OBJ)
assert_equal(response_hex.status, 200)
assert_greater_than(int(response_hex.getheader('content-length')), 160) assert_greater_than(int(response_hex.getheader('content-length')), 160)
response_hex_str = response_hex.read() response_hex_bytes = response_hex.read().strip(b'\n')
assert_equal(encode(response_str, "hex_codec")[0:160], response_hex_str[0:160]) assert_equal(binascii.hexlify(response_bytes), response_hex_bytes)
# compare with hex block header # Compare with hex block header
response_header_hex = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"hex", True) response_header_hex = self.test_rest_request("/headers/1/{}".format(bb_hash), req_type=ReqType.HEX, ret_type=RetType.OBJ)
assert_equal(response_header_hex.status, 200)
assert_greater_than(int(response_header_hex.getheader('content-length')), 160) assert_greater_than(int(response_header_hex.getheader('content-length')), 160)
response_header_hex_str = response_header_hex.read() response_header_hex_bytes = response_header_hex.read(160)
assert_equal(response_hex_str[0:160], response_header_hex_str[0:160]) assert_equal(binascii.hexlify(response_bytes[:80]), response_header_hex_bytes)
assert_equal(encode(response_header_str, "hex_codec")[0:160], response_header_hex_str[0:160])
# check json format # Check json format
block_json_string = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+'json') block_json_obj = self.test_rest_request("/block/{}".format(bb_hash))
block_json_obj = json.loads(block_json_string)
assert_equal(block_json_obj['hash'], bb_hash) assert_equal(block_json_obj['hash'], bb_hash)
# compare with json block header # Compare with json block header
response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"json", True) json_obj = self.test_rest_request("/headers/1/{}".format(bb_hash))
assert_equal(response_header_json.status, 200)
response_header_json_str = response_header_json.read().decode('utf-8')
json_obj = json.loads(response_header_json_str, parse_float=Decimal)
assert_equal(len(json_obj), 1) # ensure that there is one header in the json response assert_equal(len(json_obj), 1) # ensure that there is one header in the json response
assert_equal(json_obj[0]['hash'], bb_hash) # request/response hash should be the same assert_equal(json_obj[0]['hash'], bb_hash) # request/response hash should be the same
#compare with normal RPC block response # Compare with normal RPC block response
rpc_block_json = self.nodes[0].getblock(bb_hash) rpc_block_json = self.nodes[0].getblock(bb_hash)
assert_equal(json_obj[0]['hash'], rpc_block_json['hash']) for key in ['hash', 'confirmations', 'height', 'version', 'merkleroot', 'time', 'nonce', 'bits', 'difficulty', 'chainwork', 'previousblockhash']:
assert_equal(json_obj[0]['confirmations'], rpc_block_json['confirmations']) assert_equal(json_obj[0][key], rpc_block_json[key])
assert_equal(json_obj[0]['height'], rpc_block_json['height'])
assert_equal(json_obj[0]['version'], rpc_block_json['version'])
assert_equal(json_obj[0]['merkleroot'], rpc_block_json['merkleroot'])
assert_equal(json_obj[0]['time'], rpc_block_json['time'])
assert_equal(json_obj[0]['nonce'], rpc_block_json['nonce'])
assert_equal(json_obj[0]['bits'], rpc_block_json['bits'])
assert_equal(json_obj[0]['difficulty'], rpc_block_json['difficulty'])
assert_equal(json_obj[0]['chainwork'], rpc_block_json['chainwork'])
assert_equal(json_obj[0]['previousblockhash'], rpc_block_json['previousblockhash'])
#see if we can get 5 headers in one response # See if we can get 5 headers in one response
self.nodes[1].generate(5) self.nodes[1].generate(5)
self.sync_all() self.sync_all()
response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/5/'+bb_hash+self.FORMAT_SEPARATOR+"json", True) json_obj = self.test_rest_request("/headers/5/{}".format(bb_hash))
assert_equal(response_header_json.status, 200)
response_header_json_str = response_header_json.read().decode('utf-8')
json_obj = json.loads(response_header_json_str)
assert_equal(len(json_obj), 5) # now we should have 5 header objects assert_equal(len(json_obj), 5) # now we should have 5 header objects
# do tx test self.log.info("Test the /tx URI")
tx_hash = block_json_obj['tx'][0]['txid'] tx_hash = block_json_obj['tx'][0]['txid']
json_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"json") json_obj = self.test_rest_request("/tx/{}".format(tx_hash))
json_obj = json.loads(json_string)
assert_equal(json_obj['txid'], tx_hash) assert_equal(json_obj['txid'], tx_hash)
# check hex format response # Check hex format response
hex_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"hex", True) hex_response = self.test_rest_request("/tx/{}".format(tx_hash), req_type=ReqType.HEX, ret_type=RetType.OBJ)
assert_equal(hex_string.status, 200) assert_greater_than_or_equal(int(hex_response.getheader('content-length')),
assert_greater_than(int(response.getheader('content-length')), 10) json_obj['size']*2)
self.log.info("Test tx inclusion in the /mempool and /block URIs")
# check block tx details # Make 3 tx and mine them on node 1
# let's make 3 tx and mine them on node 1
txs = [] txs = []
txs.append(self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)) txs.append(self.nodes[0].sendtoaddress(not_related_address, 11))
txs.append(self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)) txs.append(self.nodes[0].sendtoaddress(not_related_address, 11))
txs.append(self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)) txs.append(self.nodes[0].sendtoaddress(not_related_address, 11))
self.sync_all() self.sync_all()
# check that there are exactly 3 transactions in the TX memory pool before generating the block # Check that there are exactly 3 transactions in the TX memory pool before generating the block
json_string = http_get_call(url.hostname, url.port, '/rest/mempool/info'+self.FORMAT_SEPARATOR+'json') json_obj = self.test_rest_request("/mempool/info")
json_obj = json.loads(json_string)
assert_equal(json_obj['size'], 3) assert_equal(json_obj['size'], 3)
# the size of the memory pool should be greater than 3x ~100 bytes # the size of the memory pool should be greater than 3x ~100 bytes
assert_greater_than(json_obj['bytes'], 300) assert_greater_than(json_obj['bytes'], 300)
# check that there are our submitted transactions in the TX memory pool # Check that there are our submitted transactions in the TX memory pool
json_string = http_get_call(url.hostname, url.port, '/rest/mempool/contents'+self.FORMAT_SEPARATOR+'json') json_obj = self.test_rest_request("/mempool/contents")
json_obj = json.loads(json_string)
for i, tx in enumerate(txs): for i, tx in enumerate(txs):
assert_equal(tx in json_obj, True) assert tx in json_obj
assert_equal(json_obj[tx]['spentby'], txs[i + 1:i + 2]) assert_equal(json_obj[tx]['spentby'], txs[i + 1:i + 2])
assert_equal(json_obj[tx]['depends'], txs[i - 1:i]) assert_equal(json_obj[tx]['depends'], txs[i - 1:i])
# now mine the transactions # Now mine the transactions
newblockhash = self.nodes[1].generate(1) newblockhash = self.nodes[1].generate(1)
self.sync_all() self.sync_all()
#check if the 3 tx show up in the new block # Check if the 3 tx show up in the new block
json_string = http_get_call(url.hostname, url.port, '/rest/block/'+newblockhash[0]+self.FORMAT_SEPARATOR+'json') json_obj = self.test_rest_request("/block/{}".format(newblockhash[0]))
json_obj = json.loads(json_string) non_coinbase_txs = {tx['txid'] for tx in json_obj['tx']
for tx in json_obj['tx']: if 'coinbase' not in tx['vin'][0]}
if not 'coinbase' in tx['vin'][0]: #exclude coinbase assert_equal(non_coinbase_txs, set(txs))
assert_equal(tx['txid'] in txs, True)
#check the same but without tx details # Check the same but without tx details
json_string = http_get_call(url.hostname, url.port, '/rest/block/notxdetails/'+newblockhash[0]+self.FORMAT_SEPARATOR+'json') json_obj = self.test_rest_request("/block/notxdetails/{}".format(newblockhash[0]))
json_obj = json.loads(json_string)
for tx in txs: for tx in txs:
assert_equal(tx in json_obj['tx'], True) assert tx in json_obj['tx']
self.log.info("Test the /chaininfo URI")
#test rest bestblock
bb_hash = self.nodes[0].getbestblockhash() bb_hash = self.nodes[0].getbestblockhash()
json_string = http_get_call(url.hostname, url.port, '/rest/chaininfo.json') json_obj = self.test_rest_request("/chaininfo")
json_obj = json.loads(json_string)
assert_equal(json_obj['bestblockhash'], bb_hash) assert_equal(json_obj['bestblockhash'], bb_hash)
if __name__ == '__main__': if __name__ == '__main__':