aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/functional/feature_blockfilterindex_prune.py55
-rwxr-xr-xtest/functional/feature_config_args.py51
-rwxr-xr-xtest/functional/feature_proxy.py41
-rwxr-xr-xtest/functional/interface_zmq.py42
-rwxr-xr-xtest/functional/rpc_blockchain.py13
-rwxr-xr-xtest/functional/rpc_getblockfilter.py6
-rwxr-xr-xtest/functional/rpc_net.py4
-rwxr-xr-xtest/functional/rpc_signmessage.py22
-rwxr-xr-xtest/functional/test_framework/test_framework.py8
-rw-r--r--test/functional/test_framework/util.py1
-rw-r--r--test/functional/test_framework/wallet.py9
-rwxr-xr-xtest/functional/wallet_listdescriptors.py16
-rwxr-xr-xtest/functional/wallet_txn_clone.py7
-rwxr-xr-xtest/functional/wallet_txn_doublespend.py7
14 files changed, 204 insertions, 78 deletions
diff --git a/test/functional/feature_blockfilterindex_prune.py b/test/functional/feature_blockfilterindex_prune.py
index 455073ef9c..d13d191b20 100755
--- a/test/functional/feature_blockfilterindex_prune.py
+++ b/test/functional/feature_blockfilterindex_prune.py
@@ -5,49 +5,60 @@
"""Test blockfilterindex in conjunction with prune."""
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
- assert_raises_rpc_error,
+ assert_equal,
assert_greater_than,
+ assert_raises_rpc_error,
)
class FeatureBlockfilterindexPruneTest(BitcoinTestFramework):
def set_test_params(self):
- self.num_nodes = 2
- self.extra_args = [["-fastprune", "-prune=1"], ["-fastprune", "-prune=1", "-blockfilterindex=1"]]
+ self.num_nodes = 1
+ self.extra_args = [["-fastprune", "-prune=1", "-blockfilterindex=1"]]
+
+ def sync_index(self, height):
+ expected = {'basic block filter index': {'synced': True, 'best_block_height': height}}
+ self.wait_until(lambda: self.nodes[0].getindexinfo() == expected)
def run_test(self):
- # test basic pruning compatibility & filter access of pruned blocks
self.log.info("check if we can access a blockfilter when pruning is enabled but no blocks are actually pruned")
- assert len(self.nodes[1].getblockfilter(self.nodes[1].getbestblockhash())['filter']) > 0
+ self.sync_index(height=200)
+ assert_greater_than(len(self.nodes[0].getblockfilter(self.nodes[0].getbestblockhash())['filter']), 0)
# Mine two batches of blocks to avoid hitting NODE_NETWORK_LIMITED_MIN_BLOCKS disconnection
- self.nodes[1].generate(250)
+ self.nodes[0].generate(250)
self.sync_all()
- self.nodes[1].generate(250)
+ self.nodes[0].generate(250)
self.sync_all()
+ self.sync_index(height=700)
+
self.log.info("prune some blocks")
- pruneheight = self.nodes[1].pruneblockchain(400)
- assert pruneheight != 0
+ pruneheight = self.nodes[0].pruneblockchain(400)
+ assert_equal(pruneheight, 250)
+
self.log.info("check if we can access the tips blockfilter when we have pruned some blocks")
- assert len(self.nodes[1].getblockfilter(self.nodes[1].getbestblockhash())['filter']) > 0
+ assert_greater_than(len(self.nodes[0].getblockfilter(self.nodes[0].getbestblockhash())['filter']), 0)
+
self.log.info("check if we can access the blockfilter of a pruned block")
- assert len(self.nodes[1].getblockfilter(self.nodes[1].getblockhash(2))['filter']) > 0
+ assert_greater_than(len(self.nodes[0].getblockfilter(self.nodes[0].getblockhash(2))['filter']), 0)
+
self.log.info("start node without blockfilterindex")
- self.stop_node(1)
- self.start_node(1, extra_args=self.extra_args[0])
+ self.restart_node(0, extra_args=["-fastprune", "-prune=1"])
+
self.log.info("make sure accessing the blockfilters throws an error")
- assert_raises_rpc_error(-1, "Index is not enabled for filtertype basic", self.nodes[1].getblockfilter, self.nodes[1].getblockhash(2))
- self.nodes[1].generate(1000)
+ assert_raises_rpc_error(-1, "Index is not enabled for filtertype basic", self.nodes[0].getblockfilter, self.nodes[0].getblockhash(2))
+ self.nodes[0].generate(1000)
+
self.log.info("prune below the blockfilterindexes best block while blockfilters are disabled")
- pruneheight_new = self.nodes[1].pruneblockchain(1000)
+ pruneheight_new = self.nodes[0].pruneblockchain(1000)
assert_greater_than(pruneheight_new, pruneheight)
- self.stop_node(1)
+ self.stop_node(0)
+
self.log.info("make sure we get an init error when starting the node again with block filters")
- with self.nodes[1].assert_debug_log(["basic block filter index best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"]):
- self.nodes[1].assert_start_raises_init_error(extra_args=self.extra_args[1])
+ with self.nodes[0].assert_debug_log(["basic block filter index best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"]):
+ self.nodes[0].assert_start_raises_init_error(extra_args=["-fastprune", "-prune=1", "-blockfilterindex=1"])
+
self.log.info("make sure the node starts again with the -reindex arg")
- reindex_args = self.extra_args[1]
- reindex_args.append("-reindex")
- self.start_node(1, extra_args=reindex_args)
+ self.start_node(0, extra_args = ["-fastprune", "-prune=1", "-blockfilterindex", "-reindex"])
if __name__ == '__main__':
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index 573760a8cb..a0bcd9f12a 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -19,7 +19,7 @@ class ConfArgsTest(BitcoinTestFramework):
self.wallet_names = []
def test_config_file_parser(self):
- # Assume node is stopped
+ self.stop_node(0)
inc_conf_file_path = os.path.join(self.nodes[0].datadir, 'include.conf')
with open(os.path.join(self.nodes[0].datadir, 'bitcoin.conf'), 'a', encoding='utf-8') as conf:
@@ -89,11 +89,12 @@ class ConfArgsTest(BitcoinTestFramework):
)
def test_log_buffer(self):
+ self.stop_node(0)
with self.nodes[0].assert_debug_log(expected_msgs=['Warning: parsed potentially confusing double-negative -connect=0\n']):
self.start_node(0, extra_args=['-noconnect=0'])
- self.stop_node(0)
def test_args_log(self):
+ self.stop_node(0)
self.log.info('Test config args logging')
with self.nodes[0].assert_debug_log(
expected_msgs=[
@@ -120,37 +121,41 @@ class ConfArgsTest(BitcoinTestFramework):
'-rpcuser=secret-rpcuser',
'-torpassword=secret-torpassword',
])
- self.stop_node(0)
def test_networkactive(self):
self.log.info('Test -networkactive option')
+ self.stop_node(0)
with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: true\n']):
self.start_node(0)
- self.stop_node(0)
+ self.stop_node(0)
with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: true\n']):
self.start_node(0, extra_args=['-networkactive'])
- self.stop_node(0)
+ self.stop_node(0)
with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: true\n']):
self.start_node(0, extra_args=['-networkactive=1'])
- self.stop_node(0)
+ self.stop_node(0)
with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: false\n']):
self.start_node(0, extra_args=['-networkactive=0'])
- self.stop_node(0)
+ self.stop_node(0)
with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: false\n']):
self.start_node(0, extra_args=['-nonetworkactive'])
- self.stop_node(0)
+ self.stop_node(0)
with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: false\n']):
self.start_node(0, extra_args=['-nonetworkactive=1'])
- self.stop_node(0)
def test_seed_peers(self):
self.log.info('Test seed peers')
default_data_dir = self.nodes[0].datadir
+ # Only regtest has no fixed seeds. To avoid connections to random
+ # nodes, regtest is the only network where it is safe to enable
+ # -fixedseeds in tests
+ util.assert_equal(self.nodes[0].getblockchaininfo()['chain'],'regtest')
+ self.stop_node(0)
# No peers.dat exists and -dnsseed=1
# We expect the node will use DNS Seeds, but Regtest mode has 0 DNS seeds
@@ -159,10 +164,12 @@ class ConfArgsTest(BitcoinTestFramework):
start = int(time.time())
with self.nodes[0].assert_debug_log(expected_msgs=[
"Loaded 0 addresses from peers.dat",
- "0 addresses found from DNS seeds"]):
- self.start_node(0, extra_args=['-dnsseed=1 -mocktime={}'.format(start)])
+ "0 addresses found from DNS seeds",
+ ]):
+ self.start_node(0, extra_args=['-dnsseed=1', '-fixedseeds=1', f'-mocktime={start}'])
with self.nodes[0].assert_debug_log(expected_msgs=[
- "Adding fixed seeds as 60 seconds have passed and addrman is empty"]):
+ "Adding fixed seeds as 60 seconds have passed and addrman is empty",
+ ]):
self.nodes[0].setmocktime(start + 65)
self.stop_node(0)
@@ -173,8 +180,9 @@ class ConfArgsTest(BitcoinTestFramework):
with self.nodes[0].assert_debug_log(expected_msgs=[
"Loaded 0 addresses from peers.dat",
"DNS seeding disabled",
- "Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n"]):
- self.start_node(0, extra_args=['-dnsseed=0'])
+ "Adding fixed seeds as -dnsseed=0, -addnode is not provided and all -seednode(s) attempted\n",
+ ]):
+ self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=1'])
assert time.time() - start < 60
self.stop_node(0)
@@ -185,7 +193,8 @@ class ConfArgsTest(BitcoinTestFramework):
with self.nodes[0].assert_debug_log(expected_msgs=[
"Loaded 0 addresses from peers.dat",
"DNS seeding disabled",
- "Fixed seeds are disabled"]):
+ "Fixed seeds are disabled",
+ ]):
self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=0'])
assert time.time() - start < 60
self.stop_node(0)
@@ -196,17 +205,15 @@ class ConfArgsTest(BitcoinTestFramework):
start = int(time.time())
with self.nodes[0].assert_debug_log(expected_msgs=[
"Loaded 0 addresses from peers.dat",
- "DNS seeding disabled"]):
- self.start_node(0, extra_args=['-dnsseed=0', '-addnode=fakenodeaddr -mocktime={}'.format(start)])
+ "DNS seeding disabled",
+ ]):
+ self.start_node(0, extra_args=['-dnsseed=0', '-fixedseeds=1', '-addnode=fakenodeaddr', f'-mocktime={start}'])
with self.nodes[0].assert_debug_log(expected_msgs=[
- "Adding fixed seeds as 60 seconds have passed and addrman is empty"]):
+ "Adding fixed seeds as 60 seconds have passed and addrman is empty",
+ ]):
self.nodes[0].setmocktime(start + 65)
- self.stop_node(0)
-
def run_test(self):
- self.stop_node(0)
-
self.test_log_buffer()
self.test_args_log()
self.test_seed_peers()
diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py
index 2983feaa0d..8bee43b8ad 100755
--- a/test/functional/feature_proxy.py
+++ b/test/functional/feature_proxy.py
@@ -49,9 +49,10 @@ NET_UNROUTABLE = "not_publicly_routable"
NET_IPV4 = "ipv4"
NET_IPV6 = "ipv6"
NET_ONION = "onion"
+NET_I2P = "i2p"
# Networks returned by RPC getnetworkinfo, defined in src/rpc/net.cpp::GetNetworksInfo()
-NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION})
+NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION, NET_I2P})
class ProxyTest(BitcoinTestFramework):
@@ -90,11 +91,15 @@ class ProxyTest(BitcoinTestFramework):
self.serv3 = Socks5Server(self.conf3)
self.serv3.start()
+ # We will not try to connect to this.
+ self.i2p_sam = ('127.0.0.1', 7656)
+
# Note: proxies are not used to connect to local nodes. This is because the proxy to
# use is based on CService.GetNetwork(), which returns NET_UNROUTABLE for localhost.
args = [
['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
- ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
+ ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),
+ '-i2psam=%s:%i' % (self.i2p_sam), '-i2pacceptincoming=0', '-proxyrandomize=0'],
['-listen', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
[]
]
@@ -199,9 +204,16 @@ class ProxyTest(BitcoinTestFramework):
n0 = networks_dict(self.nodes[0].getnetworkinfo())
assert_equal(NETWORKS, n0.keys())
for net in NETWORKS:
- assert_equal(n0[net]['proxy'], '%s:%i' % (self.conf1.addr))
- assert_equal(n0[net]['proxy_randomize_credentials'], True)
+ if net == NET_I2P:
+ expected_proxy = ''
+ expected_randomize = False
+ else:
+ expected_proxy = '%s:%i' % (self.conf1.addr)
+ expected_randomize = True
+ assert_equal(n0[net]['proxy'], expected_proxy)
+ assert_equal(n0[net]['proxy_randomize_credentials'], expected_randomize)
assert_equal(n0['onion']['reachable'], True)
+ assert_equal(n0['i2p']['reachable'], False)
n1 = networks_dict(self.nodes[1].getnetworkinfo())
assert_equal(NETWORKS, n1.keys())
@@ -211,21 +223,36 @@ class ProxyTest(BitcoinTestFramework):
assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr))
assert_equal(n1['onion']['proxy_randomize_credentials'], False)
assert_equal(n1['onion']['reachable'], True)
+ assert_equal(n1['i2p']['proxy'], '%s:%i' % (self.i2p_sam))
+ assert_equal(n1['i2p']['proxy_randomize_credentials'], False)
+ assert_equal(n1['i2p']['reachable'], True)
n2 = networks_dict(self.nodes[2].getnetworkinfo())
assert_equal(NETWORKS, n2.keys())
for net in NETWORKS:
- assert_equal(n2[net]['proxy'], '%s:%i' % (self.conf2.addr))
- assert_equal(n2[net]['proxy_randomize_credentials'], True)
+ if net == NET_I2P:
+ expected_proxy = ''
+ expected_randomize = False
+ else:
+ expected_proxy = '%s:%i' % (self.conf2.addr)
+ expected_randomize = True
+ assert_equal(n2[net]['proxy'], expected_proxy)
+ assert_equal(n2[net]['proxy_randomize_credentials'], expected_randomize)
assert_equal(n2['onion']['reachable'], True)
+ assert_equal(n2['i2p']['reachable'], False)
if self.have_ipv6:
n3 = networks_dict(self.nodes[3].getnetworkinfo())
assert_equal(NETWORKS, n3.keys())
for net in NETWORKS:
- assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr))
+ if net == NET_I2P:
+ expected_proxy = ''
+ else:
+ expected_proxy = '[%s]:%i' % (self.conf3.addr)
+ assert_equal(n3[net]['proxy'], expected_proxy)
assert_equal(n3[net]['proxy_randomize_credentials'], False)
assert_equal(n3['onion']['reachable'], False)
+ assert_equal(n3['i2p']['reachable'], False)
if __name__ == '__main__':
diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py
index d0967a9340..94e162b748 100755
--- a/test/functional/interface_zmq.py
+++ b/test/functional/interface_zmq.py
@@ -62,6 +62,31 @@ class ZMQSubscriber:
return (hash, label, mempool_sequence)
+class ZMQTestSetupBlock:
+ """Helper class for setting up a ZMQ test via the "sync up" procedure.
+ Generates a block on the specified node on instantiation and provides a
+ method to check whether a ZMQ notification matches, i.e. the event was
+ caused by this generated block. Assumes that a notification either contains
+ the generated block's hash, it's (coinbase) transaction id, the raw block or
+ raw transaction data.
+ """
+
+ def __init__(self, node):
+ self.block_hash = node.generate(1)[0]
+ coinbase = node.getblock(self.block_hash, 2)['tx'][0]
+ self.tx_hash = coinbase['txid']
+ self.raw_tx = coinbase['hex']
+ self.raw_block = node.getblock(self.block_hash, 0)
+
+ def caused_notification(self, notification):
+ return (
+ self.block_hash in notification
+ or self.tx_hash in notification
+ or self.raw_block in notification
+ or self.raw_tx in notification
+ )
+
+
class ZMQTest (BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
@@ -105,17 +130,18 @@ class ZMQTest (BitcoinTestFramework):
# Ensure that all zmq publisher notification interfaces are ready by
# running the following "sync up" procedure:
# 1. Generate a block on the node
- # 2. Try to receive a notification on all subscribers
- # 3. If all subscribers get a message within the timeout (1 second),
+ # 2. Try to receive the corresponding notification on all subscribers
+ # 3. If all subscribers get the message within the timeout (1 second),
# we are done, otherwise repeat starting from step 1
for sub in subscribers:
sub.socket.set(zmq.RCVTIMEO, 1000)
while True:
- self.nodes[0].generate(1)
+ test_block = ZMQTestSetupBlock(self.nodes[0])
recv_failed = False
for sub in subscribers:
try:
- sub.receive()
+ while not test_block.caused_notification(sub.receive().hex()):
+ self.log.debug("Ignoring sync-up notification for previously generated block.")
except zmq.error.Again:
self.log.debug("Didn't receive sync-up notification, trying again.")
recv_failed = True
@@ -340,7 +366,7 @@ class ZMQTest (BitcoinTestFramework):
block_count = self.nodes[0].getblockcount()
best_hash = self.nodes[0].getbestblockhash()
self.nodes[0].invalidateblock(best_hash)
- sleep(2) # Bit of room to make sure transaction things happened
+ sleep(2) # Bit of room to make sure transaction things happened
# Make sure getrawmempool mempool_sequence results aren't "queued" but immediately reflective
# of the time they were gathered.
@@ -389,8 +415,8 @@ class ZMQTest (BitcoinTestFramework):
assert_equal(label, "A")
# More transactions to be simply mined
for i in range(len(more_tx)):
- assert_equal((more_tx[i], "A", mempool_seq), seq.receive_sequence())
- mempool_seq += 1
+ assert_equal((more_tx[i], "A", mempool_seq), seq.receive_sequence())
+ mempool_seq += 1
# Bumped by rbf
assert_equal((orig_txid, "R", mempool_seq), seq.receive_sequence())
mempool_seq += 1
@@ -405,7 +431,7 @@ class ZMQTest (BitcoinTestFramework):
assert_equal((orig_txid_2, "A", mempool_seq), seq.receive_sequence())
mempool_seq += 1
self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_UNSPENDABLE)
- self.sync_all() # want to make sure we didn't break "consensus" for other tests
+ self.sync_all() # want to make sure we didn't break "consensus" for other tests
def test_mempool_sync(self):
"""
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index a6afbad0fc..e090030205 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -23,6 +23,7 @@ import http.client
import os
import subprocess
+from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE
from test_framework.blocktools import (
create_block,
create_coinbase,
@@ -71,11 +72,10 @@ class BlockchainTest(BitcoinTestFramework):
def mine_chain(self):
self.log.info('Create some old blocks')
- address = self.nodes[0].get_deterministic_priv_key().address
for t in range(TIME_GENESIS_BLOCK, TIME_GENESIS_BLOCK + 200 * 600, 600):
# ten-minute steps from genesis block time
self.nodes[0].setmocktime(t)
- self.nodes[0].generatetoaddress(1, address)
+ self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_P2WSH_OP_TRUE)
assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 200)
def _test_getblockchaininfo(self):
@@ -227,7 +227,7 @@ class BlockchainTest(BitcoinTestFramework):
assert_equal(res['transactions'], 200)
assert_equal(res['height'], 200)
assert_equal(res['txouts'], 200)
- assert_equal(res['bogosize'], 15000),
+ assert_equal(res['bogosize'], 16800),
assert_equal(res['bestblock'], node.getblockhash(200))
size = res['disk_size']
assert size > 6400
@@ -332,12 +332,12 @@ class BlockchainTest(BitcoinTestFramework):
def _test_stopatheight(self):
assert_equal(self.nodes[0].getblockcount(), 200)
- self.nodes[0].generatetoaddress(6, self.nodes[0].get_deterministic_priv_key().address)
+ self.nodes[0].generatetoaddress(6, ADDRESS_BCRT1_P2WSH_OP_TRUE)
assert_equal(self.nodes[0].getblockcount(), 206)
self.log.debug('Node should not stop at this height')
assert_raises(subprocess.TimeoutExpired, lambda: self.nodes[0].process.wait(timeout=3))
try:
- self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address)
+ self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_P2WSH_OP_TRUE)
except (ConnectionError, http.client.BadStatusLine):
pass # The node already shut down before response
self.log.debug('Node should stop at this height...')
@@ -387,8 +387,7 @@ class BlockchainTest(BitcoinTestFramework):
node = self.nodes[0]
miniwallet = MiniWallet(node)
- miniwallet.generate(5)
- node.generate(100)
+ miniwallet.scan_blocks(num=5)
fee_per_byte = Decimal('0.00000010')
fee_per_kb = 1000 * fee_per_byte
diff --git a/test/functional/rpc_getblockfilter.py b/test/functional/rpc_getblockfilter.py
index 044dbd35bf..a99e50f29f 100755
--- a/test/functional/rpc_getblockfilter.py
+++ b/test/functional/rpc_getblockfilter.py
@@ -54,5 +54,11 @@ class GetBlockFilterTest(BitcoinTestFramework):
genesis_hash = self.nodes[0].getblockhash(0)
assert_raises_rpc_error(-5, "Unknown filtertype", self.nodes[0].getblockfilter, genesis_hash, "unknown")
+ # Test getblockfilter fails on node without compact block filter index
+ self.restart_node(0, extra_args=["-blockfilterindex=0"])
+ for filter_type in FILTER_TYPES:
+ assert_raises_rpc_error(-1, "Index is not enabled for filtertype {}".format(filter_type),
+ self.nodes[0].getblockfilter, genesis_hash, filter_type)
+
if __name__ == '__main__':
GetBlockFilterTest().main()
diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py
index 2d41963beb..9adb32c3c5 100755
--- a/test/functional/rpc_net.py
+++ b/test/functional/rpc_net.py
@@ -105,7 +105,7 @@ class NetTest(BitcoinTestFramework):
assert_equal(peer_info[1][1]['connection_type'], 'inbound')
# Check dynamically generated networks list in getpeerinfo help output.
- assert "(ipv4, ipv6, onion, not_publicly_routable)" in self.nodes[0].help("getpeerinfo")
+ assert "(ipv4, ipv6, onion, i2p, not_publicly_routable)" in self.nodes[0].help("getpeerinfo")
def test_getnettotals(self):
self.log.info("Test getnettotals")
@@ -156,7 +156,7 @@ class NetTest(BitcoinTestFramework):
assert_net_servicesnames(int(info["localservices"], 0x10), info["localservicesnames"])
# Check dynamically generated networks list in getnetworkinfo help output.
- assert "(ipv4, ipv6, onion)" in self.nodes[0].help("getnetworkinfo")
+ assert "(ipv4, ipv6, onion, i2p)" in self.nodes[0].help("getnetworkinfo")
def test_getaddednodeinfo(self):
self.log.info("Test getaddednodeinfo")
diff --git a/test/functional/rpc_signmessage.py b/test/functional/rpc_signmessage.py
index 0cb3ce4215..1c71732a61 100755
--- a/test/functional/rpc_signmessage.py
+++ b/test/functional/rpc_signmessage.py
@@ -5,7 +5,10 @@
"""Test RPC commands for signing and verifying messages."""
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+)
class SignMessagesTest(BitcoinTestFramework):
def set_test_params(self):
@@ -38,5 +41,22 @@ class SignMessagesTest(BitcoinTestFramework):
assert not self.nodes[0].verifymessage(other_address, signature, message)
assert not self.nodes[0].verifymessage(address, other_signature, message)
+ self.log.info('test parameter validity and error codes')
+ # signmessage(withprivkey) have two required parameters
+ for num_params in [0, 1, 3, 4, 5]:
+ param_list = ["dummy"]*num_params
+ assert_raises_rpc_error(-1, "signmessagewithprivkey", self.nodes[0].signmessagewithprivkey, *param_list)
+ assert_raises_rpc_error(-1, "signmessage", self.nodes[0].signmessage, *param_list)
+ # verifymessage has three required parameters
+ for num_params in [0, 1, 2, 4, 5]:
+ param_list = ["dummy"]*num_params
+ assert_raises_rpc_error(-1, "verifymessage", self.nodes[0].verifymessage, *param_list)
+ # invalid key or address provided
+ assert_raises_rpc_error(-5, "Invalid private key", self.nodes[0].signmessagewithprivkey, "invalid_key", message)
+ assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].signmessage, "invalid_addr", message)
+ assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].verifymessage, "invalid_addr", signature, message)
+ # malformed signature provided
+ assert_raises_rpc_error(-3, "Malformed base64 encoding", self.nodes[0].verifymessage, self.nodes[0].getnewaddress(), "invalid_sig", message)
+
if __name__ == '__main__':
SignMessagesTest().main()
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index f7eaaa548f..02eb10b5a4 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -19,6 +19,7 @@ import tempfile
import time
from typing import List
+from .address import ADDRESS_BCRT1_P2WSH_OP_TRUE
from .authproxy import JSONRPCException
from . import coverage
from .p2p import NetworkThread
@@ -732,16 +733,17 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
# Set a time in the past, so that blocks don't end up in the future
cache_node.setmocktime(cache_node.getblockheader(cache_node.getbestblockhash())['time'])
- # Create a 199-block-long chain; each of the 4 first nodes
+ # Create a 199-block-long chain; each of the 3 first nodes
# gets 25 mature blocks and 25 immature.
- # The 4th node gets only 24 immature blocks so that the very last
+ # The 4th address gets 25 mature and only 24 immature blocks so that the very last
# block in the cache does not age too much (have an old tip age).
# This is needed so that we are out of IBD when the test starts,
# see the tip age check in IsInitialBlockDownload().
+ gen_addresses = [k.address for k in TestNode.PRIV_KEYS] + [ADDRESS_BCRT1_P2WSH_OP_TRUE]
for i in range(8):
cache_node.generatetoaddress(
nblocks=25 if i != 7 else 24,
- address=TestNode.PRIV_KEYS[i % 4].address,
+ address=gen_addresses[i % 4],
)
assert_equal(cache_node.getblockchaininfo()["blocks"], 199)
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 123c48852c..d335d4ea79 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -368,6 +368,7 @@ def write_config(config_path, *, n, chain, extra_config=""):
f.write("keypool=1\n")
f.write("discover=0\n")
f.write("dnsseed=0\n")
+ f.write("fixedseeds=0\n")
f.write("listenonion=0\n")
f.write("printtoconsole=0\n")
f.write("upnp=0\n")
diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py
index edd7792608..38fbf3c1a6 100644
--- a/test/functional/test_framework/wallet.py
+++ b/test/functional/test_framework/wallet.py
@@ -32,6 +32,15 @@ class MiniWallet:
self._address = ADDRESS_BCRT1_P2WSH_OP_TRUE
self._scriptPubKey = hex_str_to_bytes(self._test_node.validateaddress(self._address)['scriptPubKey'])
+ def scan_blocks(self, *, start=1, num):
+ """Scan the blocks for self._address outputs and add them to self._utxos"""
+ for i in range(start, start + num):
+ block = self._test_node.getblock(blockhash=self._test_node.getblockhash(i), verbosity=2)
+ for tx in block['tx']:
+ for out in tx['vout']:
+ if out['scriptPubKey']['hex'] == self._scriptPubKey.hex():
+ self._utxos.append({'txid': tx['txid'], 'vout': out['n'], 'value': out['value']})
+
def generate(self, num_blocks):
"""Generate blocks with coinbase outputs to the internal address, and append the outputs to the internal list"""
blocks = self._test_node.generatetoaddress(num_blocks, self._address)
diff --git a/test/functional/wallet_listdescriptors.py b/test/functional/wallet_listdescriptors.py
index 9f8c341bc7..8d02949ff4 100755
--- a/test/functional/wallet_listdescriptors.py
+++ b/test/functional/wallet_listdescriptors.py
@@ -50,6 +50,22 @@ class ListDescriptorsTest(BitcoinTestFramework):
assert item['range'] == [0, 0]
assert item['timestamp'] is not None
+ self.log.info('Test descriptors with hardened derivations are listed in importable form.')
+ xprv = 'tprv8ZgxMBicQKsPeuVhWwi6wuMQGfPKi9Li5GtX35jVNknACgqe3CY4g5xgkfDDJcmtF7o1QnxWDRYw4H5P26PXq7sbcUkEqeR4fg3Kxp2tigg'
+ xpub_acc = 'tpubDCMVLhErorrAGfApiJSJzEKwqeaf2z3NrkVMxgYQjZLzMjXMBeRw2muGNYbvaekAE8rUFLftyEar4LdrG2wXyyTJQZ26zptmeTEjPTaATts'
+ hardened_path = '/84\'/1\'/0\''
+ wallet = node.get_wallet_rpc('w2')
+ wallet.importdescriptors([{
+ 'desc': descsum_create('wpkh(' + xprv + hardened_path + '/0/*)'),
+ 'timestamp': 1296688602,
+ }])
+ expected = {'desc': descsum_create('wpkh([80002067' + hardened_path + ']' + xpub_acc + '/0/*)'),
+ 'timestamp': 1296688602,
+ 'active': False,
+ 'range': [0, 0],
+ 'next': 0}
+ assert_equal([expected], wallet.listdescriptors())
+
self.log.info('Test non-active non-range combo descriptor')
node.createwallet(wallet_name='w4', blank=True, descriptors=True)
wallet = node.get_wallet_rpc('w4')
diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py
index 893a2d9617..6fc1d13c53 100755
--- a/test/functional/wallet_txn_clone.py
+++ b/test/functional/wallet_txn_clone.py
@@ -11,9 +11,10 @@ from test_framework.util import (
)
from test_framework.messages import CTransaction, COIN
+
class TxnMallTest(BitcoinTestFramework):
def set_test_params(self):
- self.num_nodes = 4
+ self.num_nodes = 3
self.supports_cli = False
def skip_test_if_missing_module(self):
@@ -38,9 +39,8 @@ class TxnMallTest(BitcoinTestFramework):
# All nodes should start with 1,250 BTC:
starting_balance = 1250
- for i in range(4):
+ for i in range(3):
assert_equal(self.nodes[i].getbalance(), starting_balance)
- self.nodes[i].getnewaddress() # bug workaround, coins generated assigned to first getnewaddress!
self.nodes[0].settxfee(.001)
@@ -139,5 +139,6 @@ class TxnMallTest(BitcoinTestFramework):
expected -= 50
assert_equal(self.nodes[0].getbalance(), expected)
+
if __name__ == '__main__':
TxnMallTest().main()
diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py
index c7f7a8546a..0cb7328948 100755
--- a/test/functional/wallet_txn_doublespend.py
+++ b/test/functional/wallet_txn_doublespend.py
@@ -11,9 +11,10 @@ from test_framework.util import (
find_output,
)
+
class TxnMallTest(BitcoinTestFramework):
def set_test_params(self):
- self.num_nodes = 4
+ self.num_nodes = 3
self.supports_cli = False
def skip_test_if_missing_module(self):
@@ -39,9 +40,8 @@ class TxnMallTest(BitcoinTestFramework):
for n in self.nodes:
assert n.getblockchaininfo()["initialblockdownload"] == False
- for i in range(4):
+ for i in range(3):
assert_equal(self.nodes[i].getbalance(), starting_balance)
- self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress!
# Assign coins to foo and bar addresses:
node0_address_foo = self.nodes[0].getnewaddress()
@@ -136,5 +136,6 @@ class TxnMallTest(BitcoinTestFramework):
# Node1's balance should be its initial balance (1250 for 25 block rewards) plus the doublespend:
assert_equal(self.nodes[1].getbalance(), 1250 + 1240)
+
if __name__ == '__main__':
TxnMallTest().main()