diff --git a/ruff.toml b/ruff.toml index a252c2f46d8..61cf6d24db6 100644 --- a/ruff.toml +++ b/ruff.toml @@ -12,6 +12,5 @@ select = [ ] ignore = [ "E501", # line too long - "E731", # lambda assignment "E741", # ambiguous-variable-name ] diff --git a/test/functional/feature_addrman.py b/test/functional/feature_addrman.py index a80261eccc9..1930a277da4 100755 --- a/test/functional/feature_addrman.py +++ b/test/functional/feature_addrman.py @@ -52,12 +52,13 @@ class AddrmanTest(BitcoinTestFramework): def run_test(self): peers_dat = os.path.join(self.nodes[0].chain_path, "peers.dat") - init_error = lambda reason: ( - f"Error: Invalid or corrupt peers.dat \\({reason}\\). If you believe this " - f"is a bug, please report it to {self.config['environment']['CLIENT_BUGREPORT']}. " - f'As a workaround, you can move the file \\("{re.escape(peers_dat)}"\\) out of the way \\(rename, ' - "move, or delete\\) to have a new one created on the next start." - ) + def init_error(reason): + return ( + f"Error: Invalid or corrupt peers.dat \\({reason}\\). If you believe this " + f"is a bug, please report it to {self.config['environment']['CLIENT_BUGREPORT']}. " + f'As a workaround, you can move the file \\("{re.escape(peers_dat)}"\\) out of the way \\(rename, ' + "move, or delete\\) to have a new one created on the next start." + ) self.log.info("Check that mocked addrman is valid") self.stop_node(0) diff --git a/test/functional/feature_reindex_readonly.py b/test/functional/feature_reindex_readonly.py index 889d0c2a0e0..336fab6937d 100755 --- a/test/functional/feature_reindex_readonly.py +++ b/test/functional/feature_reindex_readonly.py @@ -35,13 +35,14 @@ class BlockstoreReindexTest(BitcoinTestFramework): filename = self.nodes[0].chain_path / "blocks" / "blk00000.dat" filename.chmod(stat.S_IREAD) - undo_immutable = lambda: None + undo_immutable_cmd = None + should_reindex = True # Linux try: subprocess.run(['chattr'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) try: subprocess.run(['chattr', '+i', filename], capture_output=True, check=True) - undo_immutable = lambda: subprocess.check_call(['chattr', '-i', filename]) + undo_immutable_cmd = ['chattr', '-i', filename] self.log.info("Made file immutable with chattr") except subprocess.CalledProcessError as e: self.log.warning(str(e)) @@ -53,14 +54,14 @@ class BlockstoreReindexTest(BitcoinTestFramework): self.log.warning("Return early on Linux under root, because chattr failed.") self.log.warning("This should only happen due to missing capabilities in a container.") self.log.warning("Make sure to --cap-add LINUX_IMMUTABLE if you want to run this test.") - undo_immutable = False + should_reindex = False except Exception: # macOS, and *BSD try: subprocess.run(['chflags'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) try: subprocess.run(['chflags', 'uchg', filename], capture_output=True, check=True) - undo_immutable = lambda: subprocess.check_call(['chflags', 'nouchg', filename]) + undo_immutable_cmd = ['chflags', 'nouchg', filename] self.log.info("Made file immutable with chflags") except subprocess.CalledProcessError as e: self.log.warning(str(e)) @@ -70,16 +71,17 @@ class BlockstoreReindexTest(BitcoinTestFramework): self.log.warning(f"stderr: {e.stderr}") if os.getuid() == 0: self.log.warning("Return early on BSD under root, because chflags failed.") - undo_immutable = False + should_reindex = False except Exception: pass - if undo_immutable: + if should_reindex: self.log.debug("Attempt to restart and reindex the node with the unwritable block file") with self.nodes[0].assert_debug_log(["Reindexing finished"], timeout=60): self.start_node(0, extra_args=['-reindex', '-fastprune']) assert_equal(block_count, self.nodes[0].getblockcount()) - undo_immutable() + if undo_immutable_cmd is not None: + subprocess.check_call(undo_immutable_cmd) filename.chmod(0o777) diff --git a/test/functional/feature_taproot.py b/test/functional/feature_taproot.py index 1a41527ee9e..a0c11fd6b81 100755 --- a/test/functional/feature_taproot.py +++ b/test/functional/feature_taproot.py @@ -764,7 +764,9 @@ def spenders_taproot_active(): add_spender(spenders, "sighash/scriptpath_hashtype_mis_%x" % hashtype, tap=tap, leaf="s0", key=secs[1], annex=annex, standard=no_annex, hashtype_actual=random.choice(VALID_SIGHASHES_TAPROOT_NO_SINGLE), **SINGLE_SIG, failure={"hashtype_actual": hashtype}, **ERR_SCHNORR_SIG_HASHTYPE, need_vin_vout_mismatch=True) # Test OP_CODESEPARATOR impact on sighashing. - hashtype = lambda _: random.choice(VALID_SIGHASHES_TAPROOT) + def hashtype(_): + return random.choice(VALID_SIGHASHES_TAPROOT) + common = {"annex": annex, "hashtype": hashtype, "standard": no_annex} scripts = [ ("pk_codesep", CScript(random_checksig_style(pubs[1]) + bytes([OP_CODESEPARATOR]))), # codesep after checksig @@ -792,7 +794,9 @@ def spenders_taproot_active(): add_spender(spenders, "sighash/keypath", tap=tap, key=secs[0], **common, failure={"sighash": override(default_sighash, leaf="pk_codesep")}, **ERR_SCHNORR_SIG) # Test that invalid hashtypes don't work, both in key path and script path spends - hashtype = lambda _: random.choice(VALID_SIGHASHES_TAPROOT) + def hashtype(_): + return random.choice(VALID_SIGHASHES_TAPROOT) + for invalid_hashtype in [x for x in range(0x100) if x not in VALID_SIGHASHES_TAPROOT]: add_spender(spenders, "sighash/keypath_unk_hashtype_%x" % invalid_hashtype, tap=tap, key=secs[0], hashtype=hashtype, failure={"hashtype": invalid_hashtype}, **ERR_SCHNORR_SIG_HASHTYPE) add_spender(spenders, "sighash/scriptpath_unk_hashtype_%x" % invalid_hashtype, tap=tap, leaf="pk_codesep", key=secs[1], **SINGLE_SIG, hashtype=hashtype, failure={"hashtype": invalid_hashtype}, **ERR_SCHNORR_SIG_HASHTYPE) @@ -1170,7 +1174,9 @@ def spenders_taproot_active(): add_spender(spenders, "unkver/1001inputs", standard=False, tap=tap, leaf="bare_unkver", inputs=[b'']*1001, failure={"leaf": "bare_c0"}, **ERR_STACK_SIZE) # OP_SUCCESSx tests. - hashtype = lambda _: random.choice(VALID_SIGHASHES_TAPROOT) + def hashtype(_): + return random.choice(VALID_SIGHASHES_TAPROOT) + for opval in range(76, 0x100): opcode = CScriptOp(opval) if not is_op_success(opcode): @@ -1215,7 +1221,9 @@ def spenders_taproot_active(): # == Test case for https://github.com/bitcoin/bitcoin/issues/24765 == - zero_fn = lambda h: bytes([0 for _ in range(32)]) + def zero_fn(h): + return bytes([0] * 32) + tap = taproot_construct(pubs[0], [("leaf", CScript([pubs[1], OP_CHECKSIG, pubs[1], OP_CHECKSIGADD, OP_2, OP_EQUAL])), zero_fn]) add_spender(spenders, "case24765", tap=tap, leaf="leaf", inputs=[getter("sign"), getter("sign")], key=secs[1], no_fail=True) diff --git a/test/functional/mempool_spend_coinbase.py b/test/functional/mempool_spend_coinbase.py index b09041c7952..3dac5e9d26a 100755 --- a/test/functional/mempool_spend_coinbase.py +++ b/test/functional/mempool_spend_coinbase.py @@ -32,7 +32,8 @@ class MempoolSpendCoinbaseTest(BitcoinTestFramework): # Coinbase at height chain_height-100+1 ok in mempool, should # get mined. Coinbase at height chain_height-100+2 is # too immature to spend. - coinbase_txid = lambda h: self.nodes[0].getblock(self.nodes[0].getblockhash(h))['tx'][0] + def coinbase_txid(h): + return self.nodes[0].getblock(self.nodes[0].getblockhash(h))['tx'][0] utxo_mature = wallet.get_utxo(txid=coinbase_txid(chain_height - 100 + 1)) utxo_immature = wallet.get_utxo(txid=coinbase_txid(chain_height - 100 + 2)) diff --git a/test/functional/mining_template_verification.py b/test/functional/mining_template_verification.py index f00268f6115..ad2a42b8eb3 100755 --- a/test/functional/mining_template_verification.py +++ b/test/functional/mining_template_verification.py @@ -253,10 +253,11 @@ class MiningTemplateVerificationTest(BitcoinTestFramework): def parallel_test(self, node, block_3): # Ensure that getblocktemplate can be called concurrently by many threads. self.log.info("Check blocks in parallel") - check_50_blocks = lambda n: [ - assert_template(n, block_3, "bad-txns-inputs-missingorspent", submit=False) - for _ in range(50) - ] + def check_50_blocks(n): + return [ + assert_template(n, block_3, "bad-txns-inputs-missingorspent", submit=False) + for _ in range(50) + ] rpcs = [node.cli for _ in range(6)] with ThreadPoolExecutor(max_workers=len(rpcs)) as threads: list(threads.map(check_50_blocks, rpcs)) diff --git a/test/functional/p2p_sendheaders.py b/test/functional/p2p_sendheaders.py index cc28fc05128..acef0329b9d 100755 --- a/test/functional/p2p_sendheaders.py +++ b/test/functional/p2p_sendheaders.py @@ -139,7 +139,9 @@ class BaseNode(P2PInterface): self.send_without_ping(getblocks_message) def wait_for_block_announcement(self, block_hash, timeout=60): - test_function = lambda: self.last_blockhash_announced == block_hash + def test_function(): + return self.last_blockhash_announced == block_hash + self.wait_until(test_function, timeout=timeout) def on_inv(self, message): @@ -165,7 +167,9 @@ class BaseNode(P2PInterface): def check_last_headers_announcement(self, headers): """Test whether the last headers announcements received are right. Headers may be announced across more than one message.""" - test_function = lambda: (len(self.recent_headers_announced) >= len(headers)) + def test_function(): + return len(self.recent_headers_announced) >= len(headers) + self.wait_until(test_function) with p2p_lock: assert_equal(self.recent_headers_announced, headers) @@ -177,7 +181,9 @@ class BaseNode(P2PInterface): """Test whether the last announcement received had the right inv. inv should be a list of block hashes.""" - test_function = lambda: self.block_announced + def test_function(): + return self.block_announced + self.wait_until(test_function) with p2p_lock: diff --git a/test/functional/rpc_generate.py b/test/functional/rpc_generate.py index a68d9c32247..97ebf936fd5 100755 --- a/test/functional/rpc_generate.py +++ b/test/functional/rpc_generate.py @@ -87,7 +87,9 @@ class RPCGenerateTest(BitcoinTestFramework): # Ensure that generateblock can be called concurrently by many threads. self.log.info('Generate blocks in parallel') - generate_50_blocks = lambda n: [n.generateblock(output=address, transactions=[]) for _ in range(50)] + def generate_50_blocks(n): + return [n.generateblock(output=address, transactions=[]) for _ in range(50)] + rpcs = [node.cli for _ in range(6)] with ThreadPoolExecutor(max_workers=len(rpcs)) as threads: list(threads.map(generate_50_blocks, rpcs)) diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py index 405d21fc1ad..81cf4da78db 100755 --- a/test/functional/rpc_net.py +++ b/test/functional/rpc_net.py @@ -202,7 +202,9 @@ class NetTest(BitcoinTestFramework): self.wait_until(lambda: (self.nodes[0].getnettotals()['totalbytesrecv'] >= net_totals_before['totalbytesrecv'] + ping_size * 2), timeout=1) for peer_before in peer_info_before: - peer_after = lambda: next(p for p in self.nodes[0].getpeerinfo() if p['id'] == peer_before['id']) + def peer_after(): + return next(p for p in self.nodes[0].getpeerinfo() if p['id'] == peer_before['id']) + self.wait_until(lambda: peer_after()['bytesrecv_per_msg'].get('pong', 0) >= peer_before['bytesrecv_per_msg'].get('pong', 0) + ping_size, timeout=1) self.wait_until(lambda: peer_after()['bytessent_per_msg'].get('ping', 0) >= peer_before['bytessent_per_msg'].get('ping', 0) + ping_size, timeout=1) diff --git a/test/functional/test_framework/p2p.py b/test/functional/test_framework/p2p.py index 803194791bf..65260b7d322 100755 --- a/test/functional/test_framework/p2p.py +++ b/test/functional/test_framework/p2p.py @@ -610,11 +610,15 @@ class P2PInterface(P2PConnection): wait_until_helper_internal(test_function, timeout=timeout, lock=p2p_lock, timeout_factor=self.timeout_factor, check_interval=check_interval) def wait_for_connect(self, *, timeout=60): - test_function = lambda: self.is_connected + def test_function(): + return self.is_connected + self.wait_until(test_function, timeout=timeout, check_connected=False) def wait_for_disconnect(self, *, timeout=60): - test_function = lambda: not self.is_connected + def test_function(): + return not self.is_connected + self.wait_until(test_function, timeout=timeout, check_connected=False) def wait_for_reconnect(self, *, timeout=60):