aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/functional/feature_proxy.py41
-rwxr-xr-xtest/functional/feature_taproot.py20
-rwxr-xr-xtest/functional/interface_zmq.py42
-rwxr-xr-xtest/functional/p2p_invalid_tx.py2
-rwxr-xr-xtest/functional/p2p_leak.py64
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py20
-rwxr-xr-xtest/functional/rpc_getblockfilter.py6
-rwxr-xr-xtest/functional/rpc_net.py4
-rwxr-xr-xtest/functional/rpc_signmessage.py22
-rw-r--r--test/functional/test_framework/script.py6
-rwxr-xr-xtest/fuzz/test_runner.py54
11 files changed, 204 insertions, 77 deletions
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/feature_taproot.py b/test/functional/feature_taproot.py
index 5027a9828f..183a43abd4 100755
--- a/test/functional/feature_taproot.py
+++ b/test/functional/feature_taproot.py
@@ -177,17 +177,17 @@ def default_negflag(ctx):
"""Default expression for "negflag": tap.negflag."""
return get(ctx, "tap").negflag
-def default_pubkey_inner(ctx):
- """Default expression for "pubkey_inner": tap.inner_pubkey."""
- return get(ctx, "tap").inner_pubkey
+def default_pubkey_internal(ctx):
+ """Default expression for "pubkey_internal": tap.internal_pubkey."""
+ return get(ctx, "tap").internal_pubkey
def default_merklebranch(ctx):
"""Default expression for "merklebranch": tapleaf.merklebranch."""
return get(ctx, "tapleaf").merklebranch
def default_controlblock(ctx):
- """Default expression for "controlblock": combine leafversion, negflag, pubkey_inner, merklebranch."""
- return bytes([get(ctx, "leafversion") + get(ctx, "negflag")]) + get(ctx, "pubkey_inner") + get(ctx, "merklebranch")
+ """Default expression for "controlblock": combine leafversion, negflag, pubkey_internal, merklebranch."""
+ return bytes([get(ctx, "leafversion") + get(ctx, "negflag")]) + get(ctx, "pubkey_internal") + get(ctx, "merklebranch")
def default_sighash(ctx):
"""Default expression for "sighash": depending on mode, compute BIP341, BIP143, or legacy sighash."""
@@ -341,9 +341,9 @@ DEFAULT_CONTEXT = {
"tapleaf": default_tapleaf,
# The script to push, and include in the sighash, for a taproot script path spend.
"script_taproot": default_script_taproot,
- # The inner pubkey for a taproot script path spend (32 bytes).
- "pubkey_inner": default_pubkey_inner,
- # The negation flag of the inner pubkey for a taproot script path spend.
+ # The internal pubkey for a taproot script path spend (32 bytes).
+ "pubkey_internal": default_pubkey_internal,
+ # The negation flag of the internal pubkey for a taproot script path spend.
"negflag": default_negflag,
# The leaf version to include in the sighash (this does not affect the one in the control block).
"leafversion": default_leafversion,
@@ -780,8 +780,8 @@ def spenders_taproot_active():
add_spender(spenders, "spendpath/negflag", tap=tap, leaf="128deep", **SINGLE_SIG, key=secs[0], failure={"negflag": lambda ctx: 1 - default_negflag(ctx)}, **ERR_WITNESS_PROGRAM_MISMATCH)
# Test that bitflips in the Merkle branch invalidate it.
add_spender(spenders, "spendpath/bitflipmerkle", tap=tap, leaf="128deep", **SINGLE_SIG, key=secs[0], failure={"merklebranch": bitflipper(default_merklebranch)}, **ERR_WITNESS_PROGRAM_MISMATCH)
- # Test that bitflips in the inner pubkey invalidate it.
- add_spender(spenders, "spendpath/bitflippubkey", tap=tap, leaf="128deep", **SINGLE_SIG, key=secs[0], failure={"pubkey_inner": bitflipper(default_pubkey_inner)}, **ERR_WITNESS_PROGRAM_MISMATCH)
+ # Test that bitflips in the internal pubkey invalidate it.
+ add_spender(spenders, "spendpath/bitflippubkey", tap=tap, leaf="128deep", **SINGLE_SIG, key=secs[0], failure={"pubkey_internal": bitflipper(default_pubkey_internal)}, **ERR_WITNESS_PROGRAM_MISMATCH)
# Test that empty witnesses are invalid.
add_spender(spenders, "spendpath/emptywit", tap=tap, leaf="128deep", **SINGLE_SIG, key=secs[0], failure={"witness": []}, **ERR_EMPTY_WITNESS)
# Test that adding garbage to the control block invalidates it.
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/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py
index cca7390ae3..8783c244c3 100755
--- a/test/functional/p2p_invalid_tx.py
+++ b/test/functional/p2p_invalid_tx.py
@@ -154,7 +154,7 @@ class InvalidTxRequestTest(BitcoinTestFramework):
orphan_tx_pool[i].vin.append(CTxIn(outpoint=COutPoint(i, 333)))
orphan_tx_pool[i].vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
- with node.assert_debug_log(['mapOrphan overflow, removed 1 tx']):
+ with node.assert_debug_log(['orphanage overflow, removed 1 tx']):
node.p2ps[0].send_txs_and_test(orphan_tx_pool, node, success=False)
rejected_parent = CTransaction()
diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py
index 12b8b7baff..71d5ca92b3 100755
--- a/test/functional/p2p_leak.py
+++ b/test/functional/p2p_leak.py
@@ -4,8 +4,8 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test message sending before handshake completion.
-A node should never send anything other than VERSION/VERACK until it's
-received a VERACK.
+Before receiving a VERACK, a node should not send anything but VERSION/VERACK
+and feature negotiation messages (WTXIDRELAY, SENDADDRV2).
This test connects to a node and sends it a few messages, trying to entice it
into sending us something it shouldn't."""
@@ -35,10 +35,12 @@ class LazyPeer(P2PInterface):
super().__init__()
self.unexpected_msg = False
self.ever_connected = False
+ self.got_wtxidrelay = False
+ self.got_sendaddrv2 = False
def bad_message(self, message):
self.unexpected_msg = True
- self.log.info("should not have received message: %s" % message.msgtype)
+ print("should not have received message: %s" % message.msgtype)
def on_open(self):
self.ever_connected = True
@@ -64,6 +66,8 @@ class LazyPeer(P2PInterface):
def on_cmpctblock(self, message): self.bad_message(message)
def on_getblocktxn(self, message): self.bad_message(message)
def on_blocktxn(self, message): self.bad_message(message)
+ def on_wtxidrelay(self, message): self.got_wtxidrelay = True
+ def on_sendaddrv2(self, message): self.got_sendaddrv2 = True
# Peer that sends a version but not a verack.
@@ -94,32 +98,61 @@ class P2PVersionStore(P2PInterface):
class P2PLeakTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
+ self.extra_args = [['-peertimeout=4']]
+
+ def create_old_version(self, nversion):
+ old_version_msg = msg_version()
+ old_version_msg.nVersion = nversion
+ old_version_msg.strSubVer = P2P_SUBVERSION
+ old_version_msg.nServices = P2P_SERVICES
+ old_version_msg.relay = P2P_VERSION_RELAY
+ return old_version_msg
def run_test(self):
- # Another peer that never sends a version, nor any other messages. It shouldn't receive anything from the node.
+ self.log.info('Check that the node doesn\'t send unexpected messages before handshake completion')
+ # Peer that never sends a version, nor any other messages. It shouldn't receive anything from the node.
no_version_idle_peer = self.nodes[0].add_p2p_connection(LazyPeer(), send_version=False, wait_for_verack=False)
# Peer that sends a version but not a verack.
no_verack_idle_peer = self.nodes[0].add_p2p_connection(NoVerackIdlePeer(), wait_for_verack=False)
- # Wait until we got the verack in response to the version. Though, don't wait for the node to receive the
- # verack, since we never sent one
+ # Pre-wtxidRelay peer that sends a version but not a verack and does not support feature negotiation
+ # messages which start at nVersion == 70016
+ pre_wtxidrelay_peer = self.nodes[0].add_p2p_connection(NoVerackIdlePeer(), send_version=False, wait_for_verack=False)
+ pre_wtxidrelay_peer.send_message(self.create_old_version(70015))
+
+ # Wait until the peer gets the verack in response to the version. Though, don't wait for the node to receive the
+ # verack, since the peer never sent one
no_verack_idle_peer.wait_for_verack()
+ pre_wtxidrelay_peer.wait_for_verack()
no_version_idle_peer.wait_until(lambda: no_version_idle_peer.ever_connected)
no_verack_idle_peer.wait_until(lambda: no_verack_idle_peer.version_received)
+ pre_wtxidrelay_peer.wait_until(lambda: pre_wtxidrelay_peer.version_received)
# Mine a block and make sure that it's not sent to the connected peers
self.nodes[0].generate(nblocks=1)
- #Give the node enough time to possibly leak out a message
+ # Give the node enough time to possibly leak out a message
time.sleep(5)
- self.nodes[0].disconnect_p2ps()
+ # Make sure only expected messages came in
+ assert not no_version_idle_peer.unexpected_msg
+ assert not no_version_idle_peer.got_wtxidrelay
+ assert not no_version_idle_peer.got_sendaddrv2
- # Make sure no unexpected messages came in
- assert no_version_idle_peer.unexpected_msg == False
- assert no_verack_idle_peer.unexpected_msg == False
+ assert not no_verack_idle_peer.unexpected_msg
+ assert no_verack_idle_peer.got_wtxidrelay
+ assert no_verack_idle_peer.got_sendaddrv2
+
+ assert not pre_wtxidrelay_peer.unexpected_msg
+ assert not pre_wtxidrelay_peer.got_wtxidrelay
+ assert not pre_wtxidrelay_peer.got_sendaddrv2
+
+ # Expect peers to be disconnected due to timeout
+ assert not no_version_idle_peer.is_connected
+ assert not no_verack_idle_peer.is_connected
+ assert not pre_wtxidrelay_peer.is_connected
self.log.info('Check that the version message does not leak the local address of the node')
p2p_version_store = self.nodes[0].add_p2p_connection(P2PVersionStore())
@@ -134,13 +167,8 @@ class P2PLeakTest(BitcoinTestFramework):
self.log.info('Check that old peers are disconnected')
p2p_old_peer = self.nodes[0].add_p2p_connection(P2PInterface(), send_version=False, wait_for_verack=False)
- old_version_msg = msg_version()
- old_version_msg.nVersion = 31799
- old_version_msg.strSubVer = P2P_SUBVERSION
- old_version_msg.nServices = P2P_SERVICES
- old_version_msg.relay = P2P_VERSION_RELAY
- with self.nodes[0].assert_debug_log(['peer=3 using obsolete version 31799; disconnecting']):
- p2p_old_peer.send_message(old_version_msg)
+ with self.nodes[0].assert_debug_log(['peer=4 using obsolete version 31799; disconnecting']):
+ p2p_old_peer.send_message(self.create_old_version(31799))
p2p_old_peer.wait_for_disconnect()
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index 569471dc87..6b300e7231 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -94,6 +94,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.test_address_reuse()
self.test_option_subtract_fee_from_outputs()
self.test_subtract_fee_with_presets()
+ self.test_transaction_too_large()
def test_change_position(self):
"""Ensure setting changePosition in fundraw with an exact match is handled properly."""
@@ -907,5 +908,24 @@ class RawTransactionsTest(BitcoinTestFramework):
signedtx = self.nodes[0].signrawtransactionwithwallet(fundedtx['hex'])
self.nodes[0].sendrawtransaction(signedtx['hex'])
+ def test_transaction_too_large(self):
+ self.log.info("Test fundrawtx where BnB solution would result in a too large transaction, but Knapsack would not")
+
+ self.nodes[0].createwallet("large")
+ wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
+ recipient = self.nodes[0].get_wallet_rpc("large")
+ outputs = {}
+ rawtx = recipient.createrawtransaction([], {wallet.getnewaddress(): 147.99899260})
+
+ # Make 1500 0.1 BTC outputs
+ # The amount that we target for funding is in the BnB range when these outputs are used.
+ # However if these outputs are selected, the transaction will end up being too large, so it shouldn't use BnB and instead fallback to Knapsack
+ # but that behavior is not implemented yet. For now we just check that we get an error.
+ for i in range(0, 1500):
+ outputs[recipient.getnewaddress()] = 0.1
+ wallet.sendmany("", outputs)
+ self.nodes[0].generate(10)
+ assert_raises_rpc_error(-4, "Transaction too large", recipient.fundrawtransaction, rawtx)
+
if __name__ == '__main__':
RawTransactionsTest().main()
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/script.py b/test/functional/test_framework/script.py
index c35533698c..3c9b8a6e69 100644
--- a/test/functional/test_framework/script.py
+++ b/test/functional/test_framework/script.py
@@ -826,11 +826,11 @@ def taproot_tree_helper(scripts):
# A TaprootInfo object has the following fields:
# - scriptPubKey: the scriptPubKey (witness v1 CScript)
-# - inner_pubkey: the inner pubkey (32 bytes)
-# - negflag: whether the pubkey in the scriptPubKey was negated from inner_pubkey+tweak*G (bool).
+# - internal_pubkey: the internal pubkey (32 bytes)
+# - negflag: whether the pubkey in the scriptPubKey was negated from internal_pubkey+tweak*G (bool).
# - tweak: the tweak (32 bytes)
# - leaves: a dict of name -> TaprootLeafInfo objects for all known leaves
-TaprootInfo = namedtuple("TaprootInfo", "scriptPubKey,inner_pubkey,negflag,tweak,leaves")
+TaprootInfo = namedtuple("TaprootInfo", "scriptPubKey,internal_pubkey,negflag,tweak,leaves")
# A TaprootLeafInfo object has the following fields:
# - script: the leaf script (CScript or bytes)
diff --git a/test/fuzz/test_runner.py b/test/fuzz/test_runner.py
index 611061072f..eeff7a4515 100755
--- a/test/fuzz/test_runner.py
+++ b/test/fuzz/test_runner.py
@@ -27,7 +27,7 @@ def get_fuzz_env(*, target, source_dir):
def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
- description='''Run the fuzz targets with all inputs from the seed_dir once.''',
+ description='''Run the fuzz targets with all inputs from the corpus_dir once.''',
)
parser.add_argument(
"-l",
@@ -54,8 +54,8 @@ def main():
help='How many targets to merge or execute in parallel.',
)
parser.add_argument(
- 'seed_dir',
- help='The seed corpus to run on (must contain subfolders for each fuzz target).',
+ 'corpus_dir',
+ help='The corpus to run on (must contain subfolders for each fuzz target).',
)
parser.add_argument(
'target',
@@ -64,15 +64,15 @@ def main():
)
parser.add_argument(
'--m_dir',
- help='Merge inputs from this directory into the seed_dir.',
+ help='Merge inputs from this directory into the corpus_dir.',
)
parser.add_argument(
'-g',
'--generate',
action='store_true',
- help='Create new corpus seeds (or extend the existing ones) by running'
+ help='Create new corpus (or extend the existing ones) by running'
' the given targets for a finite number of times. Outputs them to'
- ' the passed seed_dir.'
+ ' the passed corpus_dir.'
)
args = parser.parse_args()
@@ -119,19 +119,19 @@ def main():
logging.info("{} of {} detected fuzz target(s) selected: {}".format(len(test_list_selection), len(test_list_all), " ".join(test_list_selection)))
if not args.generate:
- test_list_seedless = []
+ test_list_missing_corpus = []
for t in test_list_selection:
- corpus_path = os.path.join(args.seed_dir, t)
+ corpus_path = os.path.join(args.corpus_dir, t)
if not os.path.exists(corpus_path) or len(os.listdir(corpus_path)) == 0:
- test_list_seedless.append(t)
- test_list_seedless.sort()
- if test_list_seedless:
+ test_list_missing_corpus.append(t)
+ test_list_missing_corpus.sort()
+ if test_list_missing_corpus:
logging.info(
- "Fuzzing harnesses lacking a seed corpus: {}".format(
- " ".join(test_list_seedless)
+ "Fuzzing harnesses lacking a corpus: {}".format(
+ " ".join(test_list_missing_corpus)
)
)
- logging.info("Please consider adding a fuzz seed corpus at https://github.com/bitcoin-core/qa-assets")
+ logging.info("Please consider adding a fuzz corpus at https://github.com/bitcoin-core/qa-assets")
try:
help_output = subprocess.run(
@@ -154,18 +154,18 @@ def main():
with ThreadPoolExecutor(max_workers=args.par) as fuzz_pool:
if args.generate:
- return generate_corpus_seeds(
+ return generate_corpus(
fuzz_pool=fuzz_pool,
src_dir=config['environment']['SRCDIR'],
build_dir=config["environment"]["BUILDDIR"],
- seed_dir=args.seed_dir,
+ corpus_dir=args.corpus_dir,
targets=test_list_selection,
)
if args.m_dir:
merge_inputs(
fuzz_pool=fuzz_pool,
- corpus=args.seed_dir,
+ corpus=args.corpus_dir,
test_list=test_list_selection,
src_dir=config['environment']['SRCDIR'],
build_dir=config["environment"]["BUILDDIR"],
@@ -175,7 +175,7 @@ def main():
run_once(
fuzz_pool=fuzz_pool,
- corpus=args.seed_dir,
+ corpus=args.corpus_dir,
test_list=test_list_selection,
src_dir=config['environment']['SRCDIR'],
build_dir=config["environment"]["BUILDDIR"],
@@ -183,13 +183,13 @@ def main():
)
-def generate_corpus_seeds(*, fuzz_pool, src_dir, build_dir, seed_dir, targets):
- """Generates new corpus seeds.
+def generate_corpus(*, fuzz_pool, src_dir, build_dir, corpus_dir, targets):
+ """Generates new corpus.
- Run {targets} without input, and outputs the generated corpus seeds to
- {seed_dir}.
+ Run {targets} without input, and outputs the generated corpus to
+ {corpus_dir}.
"""
- logging.info("Generating corpus seeds to {}".format(seed_dir))
+ logging.info("Generating corpus to {}".format(corpus_dir))
def job(command, t):
logging.debug("Running '{}'\n".format(" ".join(command)))
@@ -205,12 +205,12 @@ def generate_corpus_seeds(*, fuzz_pool, src_dir, build_dir, seed_dir, targets):
futures = []
for target in targets:
- target_seed_dir = os.path.join(seed_dir, target)
- os.makedirs(target_seed_dir, exist_ok=True)
+ target_corpus_dir = os.path.join(corpus_dir, target)
+ os.makedirs(target_corpus_dir, exist_ok=True)
command = [
os.path.join(build_dir, 'src', 'test', 'fuzz', 'fuzz'),
"-runs=100000",
- target_seed_dir,
+ target_corpus_dir,
]
futures.append(fuzz_pool.submit(job, command, target))
@@ -219,7 +219,7 @@ def generate_corpus_seeds(*, fuzz_pool, src_dir, build_dir, seed_dir, targets):
def merge_inputs(*, fuzz_pool, corpus, test_list, src_dir, build_dir, merge_dir):
- logging.info("Merge the inputs from the passed dir into the seed_dir. Passed dir {}".format(merge_dir))
+ logging.info("Merge the inputs from the passed dir into the corpus_dir. Passed dir {}".format(merge_dir))
jobs = []
for t in test_list:
args = [