aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/functional/feature_coinstatsindex.py1
-rwxr-xr-xtest/functional/interface_bitcoin_cli.py8
-rwxr-xr-xtest/functional/p2p_addr_relay.py55
-rwxr-xr-xtest/functional/p2p_compactblocks_hb.py97
-rwxr-xr-xtest/functional/rpc_setban.py31
-rw-r--r--test/functional/test_framework/blocktools.py5
-rwxr-xr-xtest/functional/test_framework/test_framework.py4
-rw-r--r--test/functional/test_framework/wallet.py22
-rwxr-xr-xtest/functional/test_runner.py1
-rwxr-xr-xtest/functional/wallet_taproot.py27
-rw-r--r--test/lint/lint-spelling.ignore-words.txt1
-rw-r--r--test/util/data/bitcoin-util-test.json30
12 files changed, 233 insertions, 49 deletions
diff --git a/test/functional/feature_coinstatsindex.py b/test/functional/feature_coinstatsindex.py
index 48c6d82c13..5d8ec2a8da 100755
--- a/test/functional/feature_coinstatsindex.py
+++ b/test/functional/feature_coinstatsindex.py
@@ -280,6 +280,7 @@ class CoinStatsIndexTest(BitcoinTestFramework):
# Add another block, so we don't depend on reconsiderblock remembering which
# blocks were touched by invalidateblock
index_node.generate(1)
+ self.sync_all()
# Ensure that removing and re-adding blocks yields consistent results
block = index_node.getblockhash(99)
diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py
index 30cd499b3f..22eec59600 100755
--- a/test/functional/interface_bitcoin_cli.py
+++ b/test/functional/interface_bitcoin_cli.py
@@ -10,10 +10,12 @@ from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
+ assert_greater_than_or_equal,
assert_raises_process_error,
assert_raises_rpc_error,
get_auth_cookie,
)
+import time
# The block reward of coinbaseoutput.nValue (50) BTC/block matures after
# COINBASE_MATURITY (100) blocks. Therefore, after mining 101 blocks we expect
@@ -248,6 +250,12 @@ class TestBitcoinCli(BitcoinTestFramework):
self.nodes[0].wait_for_rpc_connection()
assert_equal(blocks, BLOCKS + 25)
+ self.log.info("Test -rpcwait option waits at most -rpcwaittimeout seconds for startup")
+ self.stop_node(0) # stop the node so we time out
+ start_time = time.time()
+ assert_raises_process_error(1, "Could not connect to the server", self.nodes[0].cli('-rpcwait', '-rpcwaittimeout=5').echo)
+ assert_greater_than_or_equal(time.time(), start_time + 5)
+
if __name__ == '__main__':
TestBitcoinCli().main()
diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py
index 87297989ba..1a414959b9 100755
--- a/test/functional/p2p_addr_relay.py
+++ b/test/functional/p2p_addr_relay.py
@@ -23,30 +23,29 @@ import time
class AddrReceiver(P2PInterface):
num_ipv4_received = 0
+ test_addr_contents = False
- def on_addr(self, message):
- for addr in message.addrs:
- assert_equal(addr.nServices, 9)
- if not 8333 <= addr.port < 8343:
- raise AssertionError("Invalid addr.port of {} (8333-8342 expected)".format(addr.port))
- assert addr.ip.startswith('123.123.123.')
- self.num_ipv4_received += 1
-
-
-class GetAddrStore(P2PInterface):
- getaddr_received = False
- num_ipv4_received = 0
-
- def on_getaddr(self, message):
- self.getaddr_received = True
+ def __init__(self, test_addr_contents=False):
+ super().__init__()
+ self.test_addr_contents = test_addr_contents
def on_addr(self, message):
for addr in message.addrs:
self.num_ipv4_received += 1
+ if(self.test_addr_contents):
+ # relay_tests checks the content of the addr messages match
+ # expectations based on the message creation in setup_addr_msg
+ assert_equal(addr.nServices, 9)
+ if not 8333 <= addr.port < 8343:
+ raise AssertionError("Invalid addr.port of {} (8333-8342 expected)".format(addr.port))
+ assert addr.ip.startswith('123.123.123.')
def addr_received(self):
return self.num_ipv4_received != 0
+ def getaddr_received(self):
+ return self.message_count['getaddr'] > 0
+
class AddrTest(BitcoinTestFramework):
counter = 0
@@ -79,7 +78,7 @@ class AddrTest(BitcoinTestFramework):
def send_addr_msg(self, source, msg, receivers):
source.send_and_ping(msg)
# pop m_next_addr_send timer
- self.mocktime += 5 * 60
+ self.mocktime += 10 * 60
self.nodes[0].setmocktime(self.mocktime)
for peer in receivers:
peer.sync_send_with_ping()
@@ -101,7 +100,7 @@ class AddrTest(BitcoinTestFramework):
num_receivers = 7
receivers = []
for _ in range(num_receivers):
- receivers.append(self.nodes[0].add_p2p_connection(AddrReceiver()))
+ receivers.append(self.nodes[0].add_p2p_connection(AddrReceiver(test_addr_contents=True)))
# Keep this with length <= 10. Addresses from larger messages are not
# relayed.
@@ -125,8 +124,8 @@ class AddrTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps()
self.log.info('Check relay of addresses received from outbound peers')
- inbound_peer = self.nodes[0].add_p2p_connection(AddrReceiver())
- full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(GetAddrStore(), p2p_idx=0, connection_type="outbound-full-relay")
+ inbound_peer = self.nodes[0].add_p2p_connection(AddrReceiver(test_addr_contents=True))
+ full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type="outbound-full-relay")
msg = self.setup_addr_msg(2)
self.send_addr_msg(full_outbound_peer, msg, [inbound_peer])
self.log.info('Check that the first addr message received from an outbound peer is not relayed')
@@ -142,7 +141,7 @@ class AddrTest(BitcoinTestFramework):
assert_equal(inbound_peer.num_ipv4_received, 2)
self.log.info('Check address relay to outbound peers')
- block_relay_peer = self.nodes[0].add_outbound_p2p_connection(GetAddrStore(), p2p_idx=1, connection_type="block-relay-only")
+ block_relay_peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=1, connection_type="block-relay-only")
msg3 = self.setup_addr_msg(2)
self.send_addr_msg(inbound_peer, msg3, [full_outbound_peer, block_relay_peer])
@@ -156,17 +155,17 @@ class AddrTest(BitcoinTestFramework):
def getaddr_tests(self):
self.log.info('Test getaddr behavior')
self.log.info('Check that we send a getaddr message upon connecting to an outbound-full-relay peer')
- full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(GetAddrStore(), p2p_idx=0, connection_type="outbound-full-relay")
+ full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type="outbound-full-relay")
full_outbound_peer.sync_with_ping()
- assert full_outbound_peer.getaddr_received
+ assert full_outbound_peer.getaddr_received()
self.log.info('Check that we do not send a getaddr message upon connecting to a block-relay-only peer')
- block_relay_peer = self.nodes[0].add_outbound_p2p_connection(GetAddrStore(), p2p_idx=1, connection_type="block-relay-only")
+ block_relay_peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=1, connection_type="block-relay-only")
block_relay_peer.sync_with_ping()
- assert_equal(block_relay_peer.getaddr_received, False)
+ assert_equal(block_relay_peer.getaddr_received(), False)
self.log.info('Check that we answer getaddr messages only from inbound peers')
- inbound_peer = self.nodes[0].add_p2p_connection(GetAddrStore())
+ inbound_peer = self.nodes[0].add_p2p_connection(AddrReceiver())
inbound_peer.sync_with_ping()
# Add some addresses to addrman
@@ -182,7 +181,7 @@ class AddrTest(BitcoinTestFramework):
self.mocktime += 5 * 60
self.nodes[0].setmocktime(self.mocktime)
- inbound_peer.wait_until(inbound_peer.addr_received)
+ inbound_peer.wait_until(lambda: inbound_peer.addr_received() is True)
assert_equal(full_outbound_peer.num_ipv4_received, 0)
assert_equal(block_relay_peer.num_ipv4_received, 0)
@@ -196,9 +195,9 @@ class AddrTest(BitcoinTestFramework):
self.mocktime = int(time.time())
self.log.info('Check that we send getaddr messages')
- full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(GetAddrStore(), p2p_idx=0, connection_type="outbound-full-relay")
+ full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type="outbound-full-relay")
full_outbound_peer.sync_with_ping()
- assert full_outbound_peer.getaddr_received
+ assert full_outbound_peer.getaddr_received()
self.log.info('Check that we relay address messages')
addr_source = self.nodes[0].add_p2p_connection(P2PInterface())
diff --git a/test/functional/p2p_compactblocks_hb.py b/test/functional/p2p_compactblocks_hb.py
new file mode 100755
index 0000000000..a3d30a6f04
--- /dev/null
+++ b/test/functional/p2p_compactblocks_hb.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python3
+# Copyright (c) 2021 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 compact blocks HB selection logic."""
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
+
+
+class CompactBlocksConnectionTest(BitcoinTestFramework):
+ """Test class for verifying selection of HB peer connections."""
+
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 6
+
+ def peer_info(self, from_node, to_node):
+ """Query from_node for its getpeerinfo about to_node."""
+ for peerinfo in self.nodes[from_node].getpeerinfo():
+ if "(testnode%i)" % to_node in peerinfo['subver']:
+ return peerinfo
+ return None
+
+ def setup_network(self):
+ self.setup_nodes()
+ # Start network with everyone disconnected
+ self.sync_all()
+
+ def relay_block_through(self, peer):
+ """Relay a new block through peer peer, and return HB status between 1 and [2,3,4,5]."""
+ self.connect_nodes(peer, 0)
+ self.nodes[0].generate(1)
+ self.sync_blocks()
+ self.disconnect_nodes(peer, 0)
+ status_to = [self.peer_info(1, i)['bip152_hb_to'] for i in range(2, 6)]
+ status_from = [self.peer_info(i, 1)['bip152_hb_from'] for i in range(2, 6)]
+ assert_equal(status_to, status_from)
+ return status_to
+
+ def run_test(self):
+ self.log.info("Testing reserved high-bandwidth mode slot for outbound peer...")
+
+ # Connect everyone to node 0, and mine some blocks to get all nodes out of IBD.
+ for i in range(1, 6):
+ self.connect_nodes(i, 0)
+ self.nodes[0].generate(2)
+ self.sync_blocks()
+ for i in range(1, 6):
+ self.disconnect_nodes(i, 0)
+
+ # Construct network topology:
+ # - Node 0 is the block producer
+ # - Node 1 is the "target" node being tested
+ # - Nodes 2-5 are intermediaries.
+ # - Node 1 has an outbound connection to node 2
+ # - Node 1 has inbound connections from nodes 3-5
+ self.connect_nodes(3, 1)
+ self.connect_nodes(4, 1)
+ self.connect_nodes(5, 1)
+ self.connect_nodes(1, 2)
+
+ # Mine blocks subsequently relaying through nodes 3,4,5 (inbound to node 1)
+ for nodeid in range(3, 6):
+ status = self.relay_block_through(nodeid)
+ assert_equal(status, [False, nodeid >= 3, nodeid >= 4, nodeid >= 5])
+
+ # And again through each. This should not change HB status.
+ for nodeid in range(3, 6):
+ status = self.relay_block_through(nodeid)
+ assert_equal(status, [False, True, True, True])
+
+ # Now relay one block through peer 2 (outbound from node 1), so it should take HB status
+ # from one of the inbounds.
+ status = self.relay_block_through(2)
+ assert_equal(status[0], True)
+ assert_equal(sum(status), 3)
+
+ # Now relay again through nodes 3,4,5. Since 2 is outbound, it should remain HB.
+ for nodeid in range(3, 6):
+ status = self.relay_block_through(nodeid)
+ assert status[0]
+ assert status[nodeid - 2]
+ assert_equal(sum(status), 3)
+
+ # Reconnect peer 2, and retry. Now the three inbounds should be HB again.
+ self.disconnect_nodes(1, 2)
+ self.connect_nodes(1, 2)
+ for nodeid in range(3, 6):
+ status = self.relay_block_through(nodeid)
+ assert not status[0]
+ assert status[nodeid - 2]
+ assert_equal(status, [False, True, True, True])
+
+
+if __name__ == '__main__':
+ CompactBlocksConnectionTest().main()
diff --git a/test/functional/rpc_setban.py b/test/functional/rpc_setban.py
index fd5f8aa098..36873f964b 100755
--- a/test/functional/rpc_setban.py
+++ b/test/functional/rpc_setban.py
@@ -22,7 +22,7 @@ class SetBanTests(BitcoinTestFramework):
# Node 0 connects to Node 1, check that the noban permission is not granted
self.connect_nodes(0, 1)
peerinfo = self.nodes[1].getpeerinfo()[0]
- assert(not 'noban' in peerinfo['permissions'])
+ assert not "noban" in peerinfo["permissions"]
# Node 0 get banned by Node 1
self.nodes[1].setban("127.0.0.1", "add")
@@ -36,27 +36,40 @@ class SetBanTests(BitcoinTestFramework):
self.restart_node(1, ['-whitelist=127.0.0.1'])
self.connect_nodes(0, 1)
peerinfo = self.nodes[1].getpeerinfo()[0]
- assert('noban' in peerinfo['permissions'])
+ assert "noban" in peerinfo["permissions"]
# If we remove the ban, Node 0 should be able to reconnect even without noban permission
self.nodes[1].setban("127.0.0.1", "remove")
self.restart_node(1, [])
self.connect_nodes(0, 1)
peerinfo = self.nodes[1].getpeerinfo()[0]
- assert(not 'noban' in peerinfo['permissions'])
+ assert not "noban" in peerinfo["permissions"]
self.log.info("Test that a non-IP address can be banned/unbanned")
node = self.nodes[1]
tor_addr = "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"
ip_addr = "1.2.3.4"
- assert(not self.is_banned(node, tor_addr))
- assert(not self.is_banned(node, ip_addr))
+ assert not self.is_banned(node, tor_addr)
+ assert not self.is_banned(node, ip_addr)
+
node.setban(tor_addr, "add")
- assert(self.is_banned(node, tor_addr))
- assert(not self.is_banned(node, ip_addr))
+ assert self.is_banned(node, tor_addr)
+ assert not self.is_banned(node, ip_addr)
+
+ self.log.info("Test the ban list is preserved through restart")
+
+ self.restart_node(1)
+ assert self.is_banned(node, tor_addr)
+ assert not self.is_banned(node, ip_addr)
+
node.setban(tor_addr, "remove")
- assert(not self.is_banned(self.nodes[1], tor_addr))
- assert(not self.is_banned(node, ip_addr))
+ assert not self.is_banned(self.nodes[1], tor_addr)
+ assert not self.is_banned(node, ip_addr)
+
+ self.restart_node(1)
+ assert not self.is_banned(node, tor_addr)
+ assert not self.is_banned(node, ip_addr)
+
if __name__ == '__main__':
SetBanTests().main()
diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py
index fa943cb716..bc43438810 100644
--- a/test/functional/test_framework/blocktools.py
+++ b/test/functional/test_framework/blocktools.py
@@ -180,11 +180,6 @@ def create_raw_transaction(node, txid, to_address, *, amount):
signed_psbt = wrpc.walletprocesspsbt(psbt)
psbt = signed_psbt['psbt']
final_psbt = node.finalizepsbt(psbt)
- if not final_psbt["complete"]:
- node.log.info(f'final_psbt={final_psbt}')
- for w in node.listwallets():
- wrpc = node.get_wallet_rpc(w)
- node.log.info(f'listunspent={wrpc.listunspent()}')
assert_equal(final_psbt["complete"], True)
return final_psbt['hex']
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index a89a26caea..40360c54a0 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -194,6 +194,10 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
help="Run test using legacy wallets", dest='descriptors')
self.add_options(parser)
+ # Running TestShell in a Jupyter notebook causes an additional -f argument
+ # To keep TestShell from failing with an "unrecognized argument" error, we add a dummy "-f" argument
+ # source: https://stackoverflow.com/questions/48796169/how-to-fix-ipykernel-launcher-py-error-unrecognized-arguments-in-jupyter/56349168#56349168
+ parser.add_argument("-f", "--fff", help="a dummy argument to fool ipython", default="1")
self.options = parser.parse_args()
self.options.previous_releases_path = previous_releases_path
diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py
index ad58a62e28..47ec6b0be2 100644
--- a/test/functional/test_framework/wallet.py
+++ b/test/functional/test_framework/wallet.py
@@ -88,12 +88,20 @@ class MiniWallet:
if out['scriptPubKey']['hex'] == self._scriptPubKey.hex():
self._utxos.append({'txid': tx['txid'], 'vout': out['n'], 'value': out['value']})
- def sign_tx(self, tx):
+ def sign_tx(self, tx, fixed_length=True):
"""Sign tx that has been created by MiniWallet in P2PK mode"""
assert self._priv_key is not None
(sighash, err) = LegacySignatureHash(CScript(self._scriptPubKey), tx, 0, SIGHASH_ALL)
assert err is None
- tx.vin[0].scriptSig = CScript([self._priv_key.sign_ecdsa(sighash) + bytes(bytearray([SIGHASH_ALL]))])
+ # for exact fee calculation, create only signatures with fixed size by default (>49.89% probability):
+ # 65 bytes: high-R val (33 bytes) + low-S val (32 bytes)
+ # with the DER header/skeleton data of 6 bytes added, this leads to a target size of 71 bytes
+ der_sig = b''
+ while not len(der_sig) == 71:
+ der_sig = self._priv_key.sign_ecdsa(sighash)
+ if not fixed_length:
+ break
+ tx.vin[0].scriptSig = CScript([der_sig + bytes(bytearray([SIGHASH_ALL]))])
def generate(self, num_blocks):
"""Generate blocks with coinbase outputs to the internal address, and append the outputs to the internal list"""
@@ -134,7 +142,10 @@ class MiniWallet:
"""Create and return a tx with the specified fee_rate. Fee may be exact or at most one satoshi higher than needed."""
self._utxos = sorted(self._utxos, key=lambda k: k['value'])
utxo_to_spend = utxo_to_spend or self._utxos.pop() # Pick the largest utxo (if none provided) and hope it covers the fee
- vsize = Decimal(96)
+ if self._priv_key is None:
+ vsize = Decimal(96) # anyone-can-spend
+ else:
+ vsize = Decimal(168) # P2PK (73 bytes scriptSig + 35 bytes scriptPubKey + 60 bytes other)
send_value = satoshi_round(utxo_to_spend['value'] - fee_rate * (vsize / 1000))
fee = utxo_to_spend['value'] - send_value
assert send_value > 0
@@ -159,10 +170,7 @@ class MiniWallet:
tx_info = from_node.testmempoolaccept([tx_hex])[0]
assert_equal(mempool_valid, tx_info['allowed'])
if mempool_valid:
- # TODO: for P2PK, vsize is not constant due to varying scriptSig length,
- # so only check this for anyone-can-spend outputs right now
- if self._priv_key is None:
- assert_equal(tx_info['vsize'], vsize)
+ assert_equal(tx_info['vsize'], vsize)
assert_equal(tx_info['fees']['base'], fee)
return {'txid': tx_info['txid'], 'wtxid': tx_info['wtxid'], 'hex': tx_hex, 'tx': tx}
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 76347b052d..ad1acd2e2f 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -174,6 +174,7 @@ BASE_SCRIPTS = [
'wallet_groups.py --legacy-wallet',
'p2p_addrv2_relay.py',
'wallet_groups.py --descriptors',
+ 'p2p_compactblocks_hb.py',
'p2p_disconnect_ban.py',
'rpc_decodescript.py',
'rpc_blockchain.py',
diff --git a/test/functional/wallet_taproot.py b/test/functional/wallet_taproot.py
index 1547a90125..0eac814c52 100755
--- a/test/functional/wallet_taproot.py
+++ b/test/functional/wallet_taproot.py
@@ -230,6 +230,12 @@ class WalletTaprootTest(BitcoinTestFramework):
if treefn is not None:
addr_r = self.make_addr(treefn, keys, i)
assert_equal(addr_g, addr_r)
+ desc_a = self.addr_gen.getaddressinfo(addr_g)['desc']
+ if desc.startswith("tr("):
+ assert desc_a.startswith("tr(")
+ rederive = self.nodes[1].deriveaddresses(desc_a)
+ assert_equal(len(rederive), 1)
+ assert_equal(rederive[0], addr_g)
# tr descriptors cannot be imported when Taproot is not active
result = self.privs_tr_enabled.importdescriptors([{"desc": desc, "timestamp": "now"}])
@@ -375,12 +381,33 @@ class WalletTaprootTest(BitcoinTestFramework):
2
)
self.do_test(
+ "tr(XPRV,{XPUB,XPUB})",
+ "tr($1/*,{pk($2/*),pk($2/*)})",
+ [True, False],
+ lambda k1, k2: (key(k1), [pk(k2), pk(k2)]),
+ 2
+ )
+ self.do_test(
+ "tr(XPRV,{{XPUB,H},{H,XPUB}})",
+ "tr($1/*,{{pk($2/*),pk($H)},{pk($H),pk($2/*)}})",
+ [True, False],
+ lambda k1, k2: (key(k1), [[pk(k2), pk(H_POINT)], [pk(H_POINT), pk(k2)]]),
+ 2
+ )
+ self.do_test(
"tr(XPUB,{{H,{H,XPUB}},{H,{H,{H,XPRV}}}})",
"tr($1/*,{{pk($H),{pk($H),pk($2/*)}},{pk($H),{pk($H),{pk($H),pk($3/*)}}}})",
[False, False, True],
lambda k1, k2, k3: (key(k1), [[pk(H_POINT), [pk(H_POINT), pk(k2)]], [pk(H_POINT), [pk(H_POINT), [pk(H_POINT), pk(k3)]]]]),
3
)
+ self.do_test(
+ "tr(XPRV,{XPUB,{{XPUB,{H,H}},{{H,H},XPUB}}})",
+ "tr($1/*,{pk($2/*),{{pk($2/*),{pk($H),pk($H)}},{{pk($H),pk($H)},pk($2/*)}}})",
+ [True, False],
+ lambda k1, k2: (key(k1), [pk(k2), [[pk(k2), [pk(H_POINT), pk(H_POINT)]], [[pk(H_POINT), pk(H_POINT)], pk(k2)]]]),
+ 2
+ )
self.log.info("Sending everything back...")
diff --git a/test/lint/lint-spelling.ignore-words.txt b/test/lint/lint-spelling.ignore-words.txt
index 267c06ea20..9906b15e9a 100644
--- a/test/lint/lint-spelling.ignore-words.txt
+++ b/test/lint/lint-spelling.ignore-words.txt
@@ -7,6 +7,7 @@ hights
hist
inout
invokable
+keypair
mor
nin
ser
diff --git a/test/util/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json
index 0a9846b4be..a648c0287a 100644
--- a/test/util/data/bitcoin-util-test.json
+++ b/test/util/data/bitcoin-util-test.json
@@ -1,4 +1,34 @@
[
+ { "exec": "./bitcoin-util",
+ "args": ["foo"],
+ "return_code": 1,
+ "error_txt": "Error parsing command line arguments: Invalid command 'foo'",
+ "description": ""
+ },
+ { "exec": "./bitcoin-util",
+ "args": ["help"],
+ "return_code": 1,
+ "error_txt": "Error parsing command line arguments: Invalid command 'help'",
+ "description": "`help` raises an error. Use `-help`"
+ },
+ { "exec": "./bitcoin-util",
+ "args": ["grind"],
+ "return_code": 1,
+ "error_txt": "Must specify block header to grind",
+ "description": ""
+ },
+ { "exec": "./bitcoin-util",
+ "args": ["grind", "1", "2"],
+ "return_code": 1,
+ "error_txt": "Must specify block header to grind",
+ "description": ""
+ },
+ { "exec": "./bitcoin-util",
+ "args": ["grind", "aa"],
+ "return_code": 1,
+ "error_txt": "Could not decode block header",
+ "description": ""
+ },
{ "exec": "./bitcoin-tx",
"args": ["-create", "nversion=1"],
"output_cmp": "blanktxv1.hex",