So much has changed since I originally got the RPC tests working many years ago, most notably modern Linux distros don't even have a way to install python2 via packages, you have to install from source. Continuing with python2 does not seem like a good idea, so we begin migrating thigns to Python 3. Currently running ./test.sh will successfully spin up a test chain but then the test suite crashes when attempting to send an RPC request, which looks to be caused by the test suite internals still expecting python2.
309 lines
12 KiB
Python
Executable File
309 lines
12 KiB
Python
Executable File
#!/usr/bin/env python2
|
|
# Copyright (c) 2014 The Bitcoin Core developers
|
|
# Copyright (c) 2016-2024 The Hush developers
|
|
# Distributed under the GPLv3 software license, see the accompanying
|
|
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
# Base class for RPC testing
|
|
# Add python-bitcoinrpc to module search path:
|
|
import os
|
|
import sys
|
|
import shutil
|
|
import tempfile
|
|
import traceback
|
|
|
|
from authproxy import JSONRPCException
|
|
from util import assert_equal, check_json_precision, \
|
|
initialize_chain, initialize_chain_clean, \
|
|
start_nodes, connect_nodes_bi, stop_nodes, \
|
|
sync_blocks, sync_mempools, wait_bitcoinds
|
|
|
|
class BitcoinTestFramework(object):
|
|
|
|
# These may be over-ridden by subclasses:
|
|
def run_test(self):
|
|
for node in self.nodes:
|
|
assert_equal(node.getblockcount(), 200)
|
|
assert_equal(node.getbalance(), 25*10)
|
|
|
|
def add_options(self, parser):
|
|
pass
|
|
|
|
def setup_chain(self):
|
|
print("Initializing test directory "+self.options.tmpdir)
|
|
initialize_chain(self.options.tmpdir)
|
|
|
|
def setup_nodes(self):
|
|
return start_nodes(4, self.options.tmpdir)
|
|
|
|
def setup_network(self, split = False):
|
|
self.nodes = self.setup_nodes()
|
|
|
|
# Connect the nodes as a "chain". This allows us
|
|
# to split the network between nodes 1 and 2 to get
|
|
# two halves that can work on competing chains.
|
|
|
|
# If we joined network halves, connect the nodes from the joint
|
|
# on outward. This ensures that chains are properly reorganised.
|
|
if not split:
|
|
connect_nodes_bi(self.nodes, 1, 2)
|
|
sync_blocks(self.nodes[1:3])
|
|
sync_mempools(self.nodes[1:3])
|
|
|
|
connect_nodes_bi(self.nodes, 0, 1)
|
|
connect_nodes_bi(self.nodes, 2, 3)
|
|
self.is_network_split = split
|
|
self.sync_all()
|
|
|
|
def split_network(self):
|
|
"""
|
|
Split the network of four nodes into nodes 0/1 and 2/3.
|
|
"""
|
|
assert not self.is_network_split
|
|
stop_nodes(self.nodes)
|
|
wait_bitcoinds()
|
|
self.setup_network(True)
|
|
|
|
def sync_all(self):
|
|
if self.is_network_split:
|
|
sync_blocks(self.nodes[:2])
|
|
sync_blocks(self.nodes[2:])
|
|
sync_mempools(self.nodes[:2])
|
|
sync_mempools(self.nodes[2:])
|
|
else:
|
|
sync_blocks(self.nodes)
|
|
sync_mempools(self.nodes)
|
|
|
|
def join_network(self):
|
|
"""
|
|
Join the (previously split) network halves together.
|
|
"""
|
|
assert self.is_network_split
|
|
stop_nodes(self.nodes)
|
|
wait_bitcoinds()
|
|
self.setup_network(False)
|
|
|
|
def main(self):
|
|
import optparse
|
|
|
|
parser = optparse.OptionParser(usage="%prog [options]")
|
|
parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true",
|
|
help="Leave binaries and test.* datadir on exit or error")
|
|
parser.add_option("--noshutdown", dest="noshutdown", default=False, action="store_true",
|
|
help="Don't stop nodes after the test execution")
|
|
parser.add_option("--srcdir", dest="srcdir", default="../../src",
|
|
help="Source directory containing hushd/hush-cli (default: %default)")
|
|
parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"),
|
|
help="Root directory for datadirs")
|
|
parser.add_option("--tracerpc", dest="trace_rpc", default=False, action="store_true",
|
|
help="Print out all RPC calls as they are made")
|
|
self.add_options(parser)
|
|
(self.options, self.args) = parser.parse_args()
|
|
|
|
if self.options.trace_rpc:
|
|
import logging
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
|
|
os.environ['PATH'] = self.options.srcdir+":"+os.environ['PATH']
|
|
|
|
check_json_precision()
|
|
|
|
success = False
|
|
try:
|
|
if not os.path.isdir(self.options.tmpdir):
|
|
os.makedirs(self.options.tmpdir)
|
|
self.setup_chain()
|
|
|
|
self.setup_network()
|
|
|
|
self.run_test()
|
|
|
|
success = True
|
|
|
|
except JSONRPCException as e:
|
|
print("JSONRPC error: "+e.error['message'])
|
|
traceback.print_tb(sys.exc_info()[2])
|
|
except AssertionError as e:
|
|
print("Assertion failed: "+e.message)
|
|
traceback.print_tb(sys.exc_info()[2])
|
|
except Exception as e:
|
|
print("Unexpected exception caught during testing: "+str(e))
|
|
traceback.print_tb(sys.exc_info()[2])
|
|
|
|
if not self.options.noshutdown:
|
|
print("Stopping nodes")
|
|
stop_nodes(self.nodes)
|
|
wait_bitcoinds()
|
|
else:
|
|
print("Note: hushds were not stopped and may still be running")
|
|
|
|
if not self.options.nocleanup and not self.options.noshutdown:
|
|
print("Cleaning up")
|
|
shutil.rmtree(self.options.tmpdir)
|
|
|
|
if success:
|
|
print("Tests successful")
|
|
sys.exit(0)
|
|
else:
|
|
print("Failed")
|
|
sys.exit(1)
|
|
|
|
|
|
# Test framework for doing p2p comparison testing, which sets up some hushd
|
|
# binaries:
|
|
# 1 binary: test binary
|
|
# 2 binaries: 1 test binary, 1 ref binary
|
|
# n>2 binaries: 1 test binary, n-1 ref binaries
|
|
|
|
class ComparisonTestFramework(BitcoinTestFramework):
|
|
|
|
# Can override the num_nodes variable to indicate how many nodes to run.
|
|
def __init__(self):
|
|
self.num_nodes = 2
|
|
|
|
def add_options(self, parser):
|
|
parser.add_option("--testbinary", dest="testbinary",
|
|
default=os.getenv("BITCOIND", "hush-arrakis-chain"),
|
|
help="bitcoind binary to test")
|
|
parser.add_option("--refbinary", dest="refbinary",
|
|
default=os.getenv("BITCOIND", "hush-arrakis-chain"),
|
|
help="bitcoind binary to use for reference nodes (if any)")
|
|
|
|
def setup_chain(self):
|
|
print("Initializing test directory "+self.options.tmpdir)
|
|
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
|
|
|
|
def setup_network(self):
|
|
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
|
|
extra_args=[['-debug', '-allowlist=127.0.0.1']] * self.num_nodes,
|
|
binary=[self.options.testbinary] +
|
|
[self.options.refbinary]*(self.num_nodes-1))
|
|
|
|
|
|
class HushTestFramework(BitcoinTestFramework):
|
|
def __init__(self):
|
|
self.num_nodes = 2
|
|
|
|
def setup_chain(self):
|
|
print("Initializing Hush regtest directory "+self.options.tmpdir)
|
|
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
|
|
|
|
def setup_network(self, split = False):
|
|
print("Setting up Hush regtest network...")
|
|
self.addr = "RWPg8B91kfK5UtUN7z6s6TeV9cHSGtVY8D"
|
|
self.pubkey = "02676d00110c2cd14ae24f95969e8598f7ccfaa675498b82654a5b5bd57fc1d8cf"
|
|
self.privkey = "UqMgxk7ySPNQ4r9nKAFPjkXy6r5t898yhuNCjSZJLg3RAM4WW1m9"
|
|
self.addr1 = "RXEXoa1nRmKhMbuZovpcYwQMsicwzccZBp"
|
|
self.pubkey1 = "024026d4ad4ecfc1f705a9b42ca64af6d2ad947509c085534a30b8861d756c6ff0"
|
|
self.privkey1 = "UtdydP56pGTFmawHzHr1wDrc4oUwCNW1ttX8Pc3KrvH3MA8P49Wi"
|
|
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
|
|
extra_args=[[
|
|
# always give -ac_name as first extra_arg and port as third
|
|
'-ac_name=REGTEST',
|
|
'-conf='+self.options.tmpdir+'/node0/REGTEST.conf',
|
|
'-port=64367',
|
|
'-rpcport=64368',
|
|
'-regtest',
|
|
'-addressindex=1',
|
|
'-spentindex=1',
|
|
'-ac_supply=5555555',
|
|
'-ac_reward=10000000000000',
|
|
'-pubkey=' + self.pubkey,
|
|
'-ac_cc=2',
|
|
'-allowlist=127.0.0.1',
|
|
'-debug',
|
|
'--daemon',
|
|
'-rpcuser=rt',
|
|
'-rpcpassword=rt'
|
|
],
|
|
['-ac_name=REGTEST',
|
|
'-conf='+self.options.tmpdir+'/node1/REGTEST.conf',
|
|
'-port=64365',
|
|
'-rpcport=64366',
|
|
'-regtest',
|
|
'-addressindex=1',
|
|
'-spentindex=1',
|
|
'-ac_supply=5555555',
|
|
'-ac_reward=10000000000000',
|
|
'-pubkey=' + self.pubkey1,
|
|
'-ac_cc=2',
|
|
'-allowlist=127.0.0.1',
|
|
'-debug',
|
|
'-addnode=127.0.0.1:64367',
|
|
'--daemon',
|
|
'-rpcuser=rt',
|
|
'-rpcpassword=rt']]
|
|
)
|
|
self.is_network_split = split
|
|
self.rpc = self.nodes[0]
|
|
self.rpc1 = self.nodes[1]
|
|
self.sync_all()
|
|
print("Done setting up network")
|
|
|
|
class CryptoconditionsTestFramework(BitcoinTestFramework):
|
|
|
|
def __init__(self):
|
|
self.num_nodes = 2
|
|
|
|
def setup_chain(self):
|
|
print("Initializing CC test directory "+self.options.tmpdir)
|
|
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
|
|
|
|
def setup_network(self, split = False):
|
|
print("Setting up network...")
|
|
self.addr = "RWPg8B91kfK5UtUN7z6s6TeV9cHSGtVY8D"
|
|
self.pubkey = "02676d00110c2cd14ae24f95969e8598f7ccfaa675498b82654a5b5bd57fc1d8cf"
|
|
self.privkey = "UqMgxk7ySPNQ4r9nKAFPjkXy6r5t898yhuNCjSZJLg3RAM4WW1m9"
|
|
self.addr1 = "RXEXoa1nRmKhMbuZovpcYwQMsicwzccZBp"
|
|
self.pubkey1 = "024026d4ad4ecfc1f705a9b42ca64af6d2ad947509c085534a30b8861d756c6ff0"
|
|
self.privkey1 = "UtdydP56pGTFmawHzHr1wDrc4oUwCNW1ttX8Pc3KrvH3MA8P49Wi"
|
|
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
|
|
extra_args=[[
|
|
# always give -ac_name as first extra_arg and port as third
|
|
'-ac_name=REGTEST',
|
|
'-conf='+self.options.tmpdir+'/node0/REGTEST.conf',
|
|
'-port=64367',
|
|
'-rpcport=64368',
|
|
'-regtest',
|
|
'-addressindex=1',
|
|
'-spentindex=1',
|
|
'-ac_supply=5555555',
|
|
'-ac_reward=10000000000000',
|
|
'-pubkey=' + self.pubkey,
|
|
'-ac_cc=2',
|
|
'-allowlist=127.0.0.1',
|
|
'-debug',
|
|
'--daemon',
|
|
'-rpcuser=rt',
|
|
'-rpcpassword=rt'
|
|
],
|
|
['-ac_name=REGTEST',
|
|
'-conf='+self.options.tmpdir+'/node1/REGTEST.conf',
|
|
'-port=64365',
|
|
'-rpcport=64366',
|
|
'-regtest',
|
|
'-addressindex=1',
|
|
'-spentindex=1',
|
|
'-ac_supply=5555555',
|
|
'-ac_reward=10000000000000',
|
|
'-pubkey=' + self.pubkey1,
|
|
'-ac_cc=2',
|
|
'-allowlist=127.0.0.1',
|
|
'-debug',
|
|
'-addnode=127.0.0.1:64367',
|
|
'--daemon',
|
|
'-rpcuser=rt',
|
|
'-rpcpassword=rt']]
|
|
)
|
|
self.is_network_split = split
|
|
self.rpc = self.nodes[0]
|
|
self.rpc1 = self.nodes[1]
|
|
self.sync_all()
|
|
print("Done setting up network")
|
|
|
|
def send_and_mine(self, xtn, rpc_connection):
|
|
txid = rpc_connection.sendrawtransaction(xtn)
|
|
assert txid, 'got txid'
|
|
# we need the tx above to be confirmed in the next block
|
|
rpc_connection.generate(1)
|
|
return txid
|