diff --git a/chia/cmds/chia.py b/chia/cmds/chia.py index a54e24146def..1439cfca7bf3 100644 --- a/chia/cmds/chia.py +++ b/chia/cmds/chia.py @@ -8,6 +8,7 @@ from chia.cmds.keys import keys_cmd from chia.cmds.netspace import netspace_cmd from chia.cmds.passphrase import passphrase_cmd +from chia.cmds.peer import peer_cmd from chia.cmds.plots import plots_cmd from chia.cmds.rpc import rpc_cmd from chia.cmds.show import show_cmd @@ -132,6 +133,7 @@ def run_daemon_cmd(ctx: click.Context, wait_for_unlock: bool) -> None: cli.add_command(farm_cmd) cli.add_command(plotters_cmd) cli.add_command(db_cmd) +cli.add_command(peer_cmd) cli.add_command(passphrase_cmd) diff --git a/chia/cmds/cmds_util.py b/chia/cmds/cmds_util.py index f2c764bfc9a1..c7de05fc5433 100644 --- a/chia/cmds/cmds_util.py +++ b/chia/cmds/cmds_util.py @@ -1,7 +1,23 @@ +from pathlib import Path +from typing import Any, Callable, Dict, Optional, Type + +from chia.rpc.farmer_rpc_client import FarmerRpcClient +from chia.rpc.full_node_rpc_client import FullNodeRpcClient +from chia.rpc.harvester_rpc_client import HarvesterRpcClient +from chia.rpc.rpc_client import RpcClient +from chia.rpc.wallet_rpc_client import WalletRpcClient from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.mempool_submission_status import MempoolSubmissionStatus +from chia.util.default_root import DEFAULT_ROOT_PATH from chia.wallet.transaction_record import TransactionRecord +NODE_TYPES: Dict[str, Type[RpcClient]] = { + "farmer": FarmerRpcClient, + "wallet": WalletRpcClient, + "full_node": FullNodeRpcClient, + "harvester": HarvesterRpcClient, +} + def transaction_submitted_msg(tx: TransactionRecord) -> str: sent_to = [MempoolSubmissionStatus(s[0], s[1], s[2]).to_json_dict_convenience() for s in tx.sent_to] @@ -10,3 +26,48 @@ def transaction_submitted_msg(tx: TransactionRecord) -> str: def transaction_status_msg(fingerprint: int, tx_id: bytes32) -> str: return f"Run 'chia wallet get_transaction -f {fingerprint} -tx 0x{tx_id}' to get status" + + +async def check_client_connection(rpc_client: RpcClient, node_type: str, rpc_port: int) -> bool: + from aiohttp import ClientConnectorError + + try: + await rpc_client.healthz() + except ClientConnectorError: + print(f"Connection error. Check if {node_type.replace('_', ' ')} rpc is running at {rpc_port}") + print(f"This is normal if {node_type.replace('_', ' ')} is still starting up") + return False + return True + + +async def execute_with_any_service( + node_type: str, + rpc_port: Optional[int], + function: Callable, + root_path: Path = DEFAULT_ROOT_PATH, + *args, +) -> Any: + from chia.util.config import load_config + from chia.util.ints import uint16 + + if node_type not in NODE_TYPES.keys(): + print(f"Invalid node type: {node_type}") + return + # load variables from config file + config = load_config(root_path, "config.yaml") + self_hostname = config["self_hostname"] + if rpc_port is None: + rpc_port = config[node_type]["rpc_port"] + # select node client type based on string + node_client_type = NODE_TYPES[node_type] + result = None + try: + node_client = await node_client_type.create(self_hostname, uint16(rpc_port), root_path, config) + # check if we can connect to node, this makes the code cleaner + if await check_client_connection(node_client, node_type, rpc_port): + result = await function(node_client, config, *args) + finally: + if node_client is not None: + node_client.close() + await node_client.await_closed() + return result diff --git a/chia/cmds/peer.py b/chia/cmds/peer.py new file mode 100644 index 000000000000..956ecfeab45e --- /dev/null +++ b/chia/cmds/peer.py @@ -0,0 +1,49 @@ +from typing import Optional + +import click + +from chia.cmds.cmds_util import NODE_TYPES, execute_with_any_service +from chia.cmds.peer_funcs import peer_async + + +@click.command("peer", short_help="Show, or modify peering connections", no_args_is_help=True) +@click.option( + "-p", + "--rpc-port", + help=( + "Set the port where the farmer, wallet, full node or harvester " + "is hosting the RPC interface. See the rpc_port in config.yaml" + ), + type=int, + default=None, +) +@click.option( + "-c", "--connections", help="List nodes connected to this Full Node", is_flag=True, type=bool, default=False +) +@click.option("-a", "--add-connection", help="Connect to another Full Node by ip:port", type=str, default="") +@click.option( + "-r", "--remove-connection", help="Remove a Node by the first 8 characters of NodeID", type=str, default="" +) +@click.argument("node_type", type=click.Choice(list(NODE_TYPES.keys())), nargs=1, required=True) +@click.pass_context +def peer_cmd( + ctx: click.Context, + rpc_port: Optional[int], + connections: bool, + add_connection: str, + remove_connection: str, + node_type: str, +) -> None: + import asyncio + + asyncio.run( + execute_with_any_service( + node_type, + rpc_port, + peer_async, + ctx.obj["root_path"], + connections, + add_connection, + remove_connection, + ) + ) diff --git a/chia/cmds/peer_funcs.py b/chia/cmds/peer_funcs.py new file mode 100644 index 000000000000..a6f49fb35e04 --- /dev/null +++ b/chia/cmds/peer_funcs.py @@ -0,0 +1,117 @@ +from typing import Any, Dict + +from chia.rpc.rpc_client import RpcClient + + +async def add_node_connection(rpc_client: RpcClient, add_connection: str) -> None: + if ":" not in add_connection: + print("Enter a valid IP and port in the following format: 10.5.4.3:8000") + else: + ip, port = ( + ":".join(add_connection.split(":")[:-1]), + add_connection.split(":")[-1], + ) + print(f"Connecting to {ip}, {port}") + try: + await rpc_client.open_connection(ip, int(port)) + except Exception: + print(f"Failed to connect to {ip}:{port}") + + +async def remove_node_connection(rpc_client: RpcClient, remove_connection: str) -> None: + from chia.server.outbound_message import NodeType + + result_txt = "" + if len(remove_connection) != 8: + result_txt = "Invalid NodeID. Do not include '.'" + else: + connections = await rpc_client.get_connections() + for con in connections: + if remove_connection == con["node_id"].hex()[:8]: + print("Attempting to disconnect", "NodeID", remove_connection) + try: + await rpc_client.close_connection(con["node_id"]) + except Exception: + result_txt = f"Failed to disconnect NodeID {remove_connection}" + else: + result_txt = ( + f"NodeID {remove_connection}... {NodeType(con['type']).name} {con['peer_host']} disconnected" + ) + elif result_txt == "": + result_txt = f"NodeID {remove_connection}... not found" + print(result_txt) + + +async def print_connections(rpc_client: RpcClient, trusted_peers: Dict[str, Any]) -> None: + import time + + from chia.server.outbound_message import NodeType + from chia.util.network import is_trusted_inner + + connections = await rpc_client.get_connections() + print("Connections:") + print("Type IP Ports NodeID Last Connect" + " MiB Up|Dwn") + for con in connections: + last_connect_tuple = time.struct_time(time.localtime(con["last_message_time"])) + last_connect = time.strftime("%b %d %T", last_connect_tuple) + mb_down = con["bytes_read"] / (1024 * 1024) + mb_up = con["bytes_written"] / (1024 * 1024) + + host = con["peer_host"] + # Strip IPv6 brackets + host = host.strip("[]") + + trusted: bool = is_trusted_inner(host, con["node_id"], trusted_peers, False) + # Nodetype length is 9 because INTRODUCER will be deprecated + if NodeType(con["type"]) is NodeType.FULL_NODE: + peak_height = con.get("peak_height", None) + connection_peak_hash = con.get("peak_hash", None) + if connection_peak_hash is None: + connection_peak_hash = "No Info" + else: + if connection_peak_hash.startswith(("0x", "0X")): + connection_peak_hash = connection_peak_hash[2:] + connection_peak_hash = f"{connection_peak_hash[:8]}..." + con_str = ( + f"{NodeType(con['type']).name:9} {host:38} " + f"{con['peer_port']:5}/{con['peer_server_port']:<5}" + f" {con['node_id'].hex()[:8]}... " + f"{last_connect} " + f"{mb_up:7.1f}|{mb_down:<7.1f}" + f"\n " + ) + if peak_height is not None: + con_str += f"-Height: {peak_height:8.0f} -Hash: {connection_peak_hash}" + else: + con_str += f"-Height: No Info -Hash: {connection_peak_hash}" + # Only show when Trusted is True + if trusted: + con_str += f" -Trusted: {trusted}" + else: + con_str = ( + f"{NodeType(con['type']).name:9} {host:38} " + f"{con['peer_port']:5}/{con['peer_server_port']:<5}" + f" {con['node_id'].hex()[:8]}... " + f"{last_connect} " + f"{mb_up:7.1f}|{mb_down:<7.1f}" + ) + print(con_str) + + +async def peer_async( + rpc_client: RpcClient, + config: Dict[str, Any], + show_connections: bool, + add_connection: str, + remove_connection: str, + # trusted_peers: Dict[str, Any], +) -> None: + # Check or edit node connections + if show_connections: + trusted_peers: Dict[str, Any] = config["full_node"].get("trusted_peers", {}) + await print_connections(rpc_client, trusted_peers) + # if called together with state, leave a blank line + if add_connection: + await add_node_connection(rpc_client, add_connection) + if remove_connection: + await remove_node_connection(rpc_client, remove_connection) diff --git a/chia/cmds/show.py b/chia/cmds/show.py index 0e83dc78e836..2e961ba112fb 100644 --- a/chia/cmds/show.py +++ b/chia/cmds/show.py @@ -1,328 +1,8 @@ -from typing import Any, Callable, Dict, List, Optional, Union - +from typing import Optional import click - -async def print_connections(node_client, trusted_peers: Dict): - import time - - from chia.server.outbound_message import NodeType - from chia.util.network import is_trusted_inner - - connections = await node_client.get_connections() - print("Connections:") - print("Type IP Ports NodeID Last Connect" + " MiB Up|Dwn") - for con in connections: - last_connect_tuple = time.struct_time(time.localtime(con["last_message_time"])) - last_connect = time.strftime("%b %d %T", last_connect_tuple) - mb_down = con["bytes_read"] / (1024 * 1024) - mb_up = con["bytes_written"] / (1024 * 1024) - - host = con["peer_host"] - # Strip IPv6 brackets - host = host.strip("[]") - - trusted: bool = is_trusted_inner(host, con["node_id"], trusted_peers, False) - # Nodetype length is 9 because INTRODUCER will be deprecated - if NodeType(con["type"]) is NodeType.FULL_NODE: - peak_height = con.get("peak_height", None) - connection_peak_hash = con.get("peak_hash", None) - if connection_peak_hash is None: - connection_peak_hash = "No Info" - else: - if connection_peak_hash.startswith(("0x", "0X")): - connection_peak_hash = connection_peak_hash[2:] - connection_peak_hash = f"{connection_peak_hash[:8]}..." - con_str = ( - f"{NodeType(con['type']).name:9} {host:38} " - f"{con['peer_port']:5}/{con['peer_server_port']:<5}" - f" {con['node_id'].hex()[:8]}... " - f"{last_connect} " - f"{mb_up:7.1f}|{mb_down:<7.1f}" - f"\n " - ) - if peak_height is not None: - con_str += f"-Height: {peak_height:8.0f} -Hash: {connection_peak_hash}" - else: - con_str += f"-Height: No Info -Hash: {connection_peak_hash}" - # Only show when Trusted is True - if trusted: - con_str += f" -Trusted: {trusted}" - else: - con_str = ( - f"{NodeType(con['type']).name:9} {host:38} " - f"{con['peer_port']:5}/{con['peer_server_port']:<5}" - f" {con['node_id'].hex()[:8]}... " - f"{last_connect} " - f"{mb_up:7.1f}|{mb_down:<7.1f}" - ) - print(con_str) - - -async def print_blockchain_state(node_client, config: Dict): - # node_client is FullNodeRpcClient - import time - - from chia.consensus.block_record import BlockRecord - from chia.util.ints import uint64 - from chia.util.misc import format_bytes - - blockchain_state = await node_client.get_blockchain_state() - if blockchain_state is None: - print("There is no blockchain found yet. Try again shortly") - return True - peak: Optional[BlockRecord] = blockchain_state["peak"] - node_id = blockchain_state["node_id"] - difficulty = blockchain_state["difficulty"] - sub_slot_iters = blockchain_state["sub_slot_iters"] - synced = blockchain_state["sync"]["synced"] - sync_mode = blockchain_state["sync"]["sync_mode"] - total_iters = peak.total_iters if peak is not None else 0 - num_blocks: int = 10 - network_name = config["selected_network"] - genesis_challenge = config["farmer"]["network_overrides"]["constants"][network_name]["GENESIS_CHALLENGE"] - full_node_port = config["full_node"]["port"] - full_node_rpc_port = config["full_node"]["rpc_port"] - - print(f"Network: {network_name} Port: {full_node_port} RPC Port: {full_node_rpc_port}") - print(f"Node ID: {node_id}") - print(f"Genesis Challenge: {genesis_challenge}") - - if synced: - print("Current Blockchain Status: Full Node Synced") - print("\nPeak: Hash:", peak.header_hash if peak is not None else "") - elif peak is not None and sync_mode: - sync_max_block = blockchain_state["sync"]["sync_tip_height"] - sync_current_block = blockchain_state["sync"]["sync_progress_height"] - print( - f"Current Blockchain Status: Syncing {sync_current_block}/{sync_max_block} " - f"({sync_max_block - sync_current_block} behind)." - ) - print("Peak: Hash:", peak.header_hash if peak is not None else "") - elif peak is not None: - print(f"Current Blockchain Status: Not Synced. Peak height: {peak.height}") - else: - print("\nSearching for an initial chain\n") - print("You may be able to expedite with 'chia show -a host:port' using a known node.\n") - - if peak is not None: - if peak.is_transaction_block: - peak_time = peak.timestamp - else: - peak_hash = peak.header_hash - curr = await node_client.get_block_record(peak_hash) - while curr is not None and not curr.is_transaction_block: - curr = await node_client.get_block_record(curr.prev_hash) - if curr is not None: - peak_time = curr.timestamp - else: - peak_time = uint64(0) - peak_time_struct = time.struct_time(time.localtime(peak_time)) - - print( - " Time:", - f"{time.strftime('%a %b %d %Y %T %Z', peak_time_struct)}", - f" Height: {peak.height:>10}\n", - ) - - print("Estimated network space: ", end="") - print(format_bytes(blockchain_state["space"])) - print(f"Current difficulty: {difficulty}") - print(f"Current VDF sub_slot_iters: {sub_slot_iters}") - print("Total iterations since the start of the blockchain:", total_iters) - print("\n Height: | Hash:") - - added_blocks: List[BlockRecord] = [] - curr = await node_client.get_block_record(peak.header_hash) - while curr is not None and len(added_blocks) < num_blocks and curr.height > 0: - added_blocks.append(curr) - curr = await node_client.get_block_record(curr.prev_hash) - - for b in added_blocks: - print(f"{b.height:>9} | {b.header_hash}") - else: - print("Blockchain has no blocks yet") - - -async def print_block_from_hash(node_client, config: Dict, block_by_header_hash: str): - import time - - from chia.consensus.block_record import BlockRecord - from chia.types.blockchain_format.sized_bytes import bytes32 - from chia.types.full_block import FullBlock - from chia.util.bech32m import encode_puzzle_hash - from chia.util.byte_types import hexstr_to_bytes - - block: Optional[BlockRecord] = await node_client.get_block_record(hexstr_to_bytes(block_by_header_hash)) - full_block: Optional[FullBlock] = await node_client.get_block(hexstr_to_bytes(block_by_header_hash)) - # Would like to have a verbose flag for this - if block is not None: - assert full_block is not None - prev_b = await node_client.get_block_record(block.prev_hash) - if prev_b is not None: - difficulty = block.weight - prev_b.weight - else: - difficulty = block.weight - if block.is_transaction_block: - assert full_block.transactions_info is not None - block_time = time.struct_time( - time.localtime( - full_block.foliage_transaction_block.timestamp if full_block.foliage_transaction_block else None - ) - ) - block_time_string = time.strftime("%a %b %d %Y %T %Z", block_time) - cost = str(full_block.transactions_info.cost) - tx_filter_hash: Union[str, bytes32] = "Not a transaction block" - if full_block.foliage_transaction_block: - tx_filter_hash = full_block.foliage_transaction_block.filter_hash - fees: Any = block.fees - else: - block_time_string = "Not a transaction block" - cost = "Not a transaction block" - tx_filter_hash = "Not a transaction block" - fees = "Not a transaction block" - address_prefix = config["network_overrides"]["config"][config["selected_network"]]["address_prefix"] - farmer_address = encode_puzzle_hash(block.farmer_puzzle_hash, address_prefix) - pool_address = encode_puzzle_hash(block.pool_puzzle_hash, address_prefix) - pool_pk = ( - full_block.reward_chain_block.proof_of_space.pool_public_key - if full_block.reward_chain_block.proof_of_space.pool_public_key is not None - else "Pay to pool puzzle hash" - ) - print( - f"Block Height {block.height}\n" - f"Header Hash 0x{block.header_hash.hex()}\n" - f"Timestamp {block_time_string}\n" - f"Weight {block.weight}\n" - f"Previous Block 0x{block.prev_hash.hex()}\n" - f"Difficulty {difficulty}\n" - f"Sub-slot iters {block.sub_slot_iters}\n" - f"Cost {cost}\n" - f"Total VDF Iterations {block.total_iters}\n" - f"Is a Transaction Block?{block.is_transaction_block}\n" - f"Deficit {block.deficit}\n" - f"PoSpace 'k' Size {full_block.reward_chain_block.proof_of_space.size}\n" - f"Plot Public Key 0x{full_block.reward_chain_block.proof_of_space.plot_public_key}\n" - f"Pool Public Key {pool_pk}\n" - f"Tx Filter Hash {tx_filter_hash}\n" - f"Farmer Address {farmer_address}\n" - f"Pool Address {pool_address}\n" - f"Fees Amount {fees}\n" - ) - else: - print("Block with header hash", block_by_header_hash, "not found") - - -async def add_node_connection(node_client, add_connection: str): - if ":" not in add_connection: - print("Enter a valid IP and port in the following format: 10.5.4.3:8000") - else: - ip, port = ( - ":".join(add_connection.split(":")[:-1]), - add_connection.split(":")[-1], - ) - print(f"Connecting to {ip}, {port}") - try: - await node_client.open_connection(ip, int(port)) - except Exception: - print(f"Failed to connect to {ip}:{port}") - - -async def remove_node_connection(node_client, remove_connection: str): - from chia.server.outbound_message import NodeType - - result_txt = "" - if len(remove_connection) != 8: - result_txt = "Invalid NodeID. Do not include '.'" - else: - connections = await node_client.get_connections() - for con in connections: - if remove_connection == con["node_id"].hex()[:8]: - print("Attempting to disconnect", "NodeID", remove_connection) - try: - await node_client.close_connection(con["node_id"]) - except Exception: - result_txt = f"Failed to disconnect NodeID {remove_connection}" - else: - result_txt = f"NodeID {remove_connection}... {NodeType(con['type']).name} " - f"{con['peer_host']} disconnected" - elif result_txt == "": - result_txt = f"NodeID {remove_connection}... not found" - print(result_txt) - - -async def execute_with_node(rpc_port: Optional[int], function: Callable, *args): - import traceback - - from aiohttp import ClientConnectorError - - from chia.rpc.full_node_rpc_client import FullNodeRpcClient - from chia.util.config import load_config - from chia.util.default_root import DEFAULT_ROOT_PATH - from chia.util.ints import uint16 - - config = load_config(DEFAULT_ROOT_PATH, "config.yaml") - self_hostname = config["self_hostname"] - if rpc_port is None: - rpc_port = config["full_node"]["rpc_port"] - try: - node_client: FullNodeRpcClient = await FullNodeRpcClient.create( - self_hostname, uint16(rpc_port), DEFAULT_ROOT_PATH, config - ) - await function(node_client, config, *args) - - except Exception as e: - if isinstance(e, ClientConnectorError): - print(f"Connection error. Check if full node rpc is running at {rpc_port}") - print("This is normal if full node is still starting up") - else: - tb = traceback.format_exc() - print(f"Exception from 'show' {tb}") - - node_client.close() - await node_client.await_closed() - - -async def show_async( - node_client, - config: Dict, - state: bool, - show_connections: bool, - add_connection: str, - remove_connection: str, - block_header_hash_by_height: str, - block_by_header_hash: str, -) -> None: - - # Check State - if state: - if await print_blockchain_state(node_client, config) is True: - return None # if no blockchain is found - # if called together with show_connections, leave a blank line - if show_connections: - print("") - - # Check or edit node connections - if show_connections: - trusted_peers: Dict = config["full_node"].get("trusted_peers", {}) - await print_connections(node_client, trusted_peers) - # if called together with state, leave a blank line - if state: - print("") - if add_connection: - await add_node_connection(node_client, add_connection) - if remove_connection: - await remove_node_connection(node_client, remove_connection) - - # Get Block Information - if block_header_hash_by_height != "": - block_header = await node_client.get_block_record_by_height(block_header_hash_by_height) - if block_header is not None: - print(f"Header hash of block {block_header_hash_by_height}: " f"{block_header.header_hash.hex()}") - else: - print("Block height", block_header_hash_by_height, "not found") - if block_by_header_hash != "": - await print_block_from_hash(node_client, config, block_by_header_hash) +from chia.cmds.cmds_util import execute_with_any_service +from chia.cmds.show_funcs import show_async @click.command("show", short_help="Show node information", no_args_is_help=True) @@ -355,7 +35,9 @@ async def show_async( "-bh", "--block-header-hash-by-height", help="Look up a block header hash by block height", type=str, default="" ) @click.option("-b", "--block-by-header-hash", help="Look up a block by block header hash", type=str, default="") +@click.pass_context def show_cmd( + ctx: click.Context, rpc_port: Optional[int], wallet_rpc_port: Optional[int], state: bool, @@ -367,14 +49,21 @@ def show_cmd( ) -> None: import asyncio + if connections: + print("'chia show -c' has been renamed to 'chia peer -c' ") + if add_connection != "": + print("'chia show -a' has been renamed to 'chia peer -a' ") + if remove_connection != "": + print("'chia show -r' has been renamed to 'chia peer -r' ") + if wallet_rpc_port is not None: + print("'chia show -wp' is not used, please remove it from your command.") asyncio.run( - execute_with_node( + execute_with_any_service( + "full_node", rpc_port, show_async, + ctx.obj["root_path"], state, - connections, - add_connection, - remove_connection, block_header_hash_by_height, block_by_header_hash, ) diff --git a/chia/cmds/show_funcs.py b/chia/cmds/show_funcs.py new file mode 100644 index 000000000000..79d764f1ca19 --- /dev/null +++ b/chia/cmds/show_funcs.py @@ -0,0 +1,182 @@ +from typing import Any, Dict, List, Optional, Union + +from chia.rpc.full_node_rpc_client import FullNodeRpcClient + + +async def print_blockchain_state(node_client: FullNodeRpcClient, config: Dict[str, Any]) -> bool: + import time + + from chia.consensus.block_record import BlockRecord + from chia.util.ints import uint64 + from chia.util.misc import format_bytes + + blockchain_state = await node_client.get_blockchain_state() + if blockchain_state is None: + print("There is no blockchain found yet. Try again shortly") + return True + peak: Optional[BlockRecord] = blockchain_state["peak"] + node_id = blockchain_state["node_id"] + difficulty = blockchain_state["difficulty"] + sub_slot_iters = blockchain_state["sub_slot_iters"] + synced = blockchain_state["sync"]["synced"] + sync_mode = blockchain_state["sync"]["sync_mode"] + total_iters = peak.total_iters if peak is not None else 0 + num_blocks: int = 10 + network_name = config["selected_network"] + genesis_challenge = config["farmer"]["network_overrides"]["constants"][network_name]["GENESIS_CHALLENGE"] + full_node_port = config["full_node"]["port"] + full_node_rpc_port = config["full_node"]["rpc_port"] + + print(f"Network: {network_name} Port: {full_node_port} RPC Port: {full_node_rpc_port}") + print(f"Node ID: {node_id}") + print(f"Genesis Challenge: {genesis_challenge}") + + if synced: + print("Current Blockchain Status: Full Node Synced") + print("\nPeak: Hash:", peak.header_hash if peak is not None else "") + elif peak is not None and sync_mode: + sync_max_block = blockchain_state["sync"]["sync_tip_height"] + sync_current_block = blockchain_state["sync"]["sync_progress_height"] + print( + f"Current Blockchain Status: Syncing {sync_current_block}/{sync_max_block} " + f"({sync_max_block - sync_current_block} behind)." + ) + print("Peak: Hash:", peak.header_hash if peak is not None else "") + elif peak is not None: + print(f"Current Blockchain Status: Not Synced. Peak height: {peak.height}") + else: + print("\nSearching for an initial chain\n") + print("You may be able to expedite with 'chia show -a host:port' using a known node.\n") + + if peak is not None: + if peak.is_transaction_block: + peak_time = peak.timestamp + else: + peak_hash = peak.header_hash + curr = await node_client.get_block_record(peak_hash) + while curr is not None and not curr.is_transaction_block: + curr = await node_client.get_block_record(curr.prev_hash) + if curr is not None: + peak_time = curr.timestamp + else: + peak_time = uint64(0) + peak_time_struct = time.struct_time(time.localtime(peak_time)) + + print( + " Time:", + f"{time.strftime('%a %b %d %Y %T %Z', peak_time_struct)}", + f" Height: {peak.height:>10}\n", + ) + + print("Estimated network space: ", end="") + print(format_bytes(blockchain_state["space"])) + print(f"Current difficulty: {difficulty}") + print(f"Current VDF sub_slot_iters: {sub_slot_iters}") + print("Total iterations since the start of the blockchain:", total_iters) + print("\n Height: | Hash:") + + added_blocks: List[BlockRecord] = [] + curr = await node_client.get_block_record(peak.header_hash) + while curr is not None and len(added_blocks) < num_blocks and curr.height > 0: + added_blocks.append(curr) + curr = await node_client.get_block_record(curr.prev_hash) + + for b in added_blocks: + print(f"{b.height:>9} | {b.header_hash}") + else: + print("Blockchain has no blocks yet") + return True + + +async def print_block_from_hash( + node_client: FullNodeRpcClient, config: Dict[str, Any], block_by_header_hash: str +) -> None: + import time + + from chia.consensus.block_record import BlockRecord + from chia.types.blockchain_format.sized_bytes import bytes32 + from chia.types.full_block import FullBlock + from chia.util.bech32m import encode_puzzle_hash + from chia.util.byte_types import hexstr_to_bytes + + block: Optional[BlockRecord] = await node_client.get_block_record(hexstr_to_bytes(block_by_header_hash)) + full_block: Optional[FullBlock] = await node_client.get_block(hexstr_to_bytes(block_by_header_hash)) + # Would like to have a verbose flag for this + if block is not None: + assert full_block is not None + prev_b = await node_client.get_block_record(block.prev_hash) + if prev_b is not None: + difficulty = block.weight - prev_b.weight + else: + difficulty = block.weight + if block.is_transaction_block: + assert full_block.transactions_info is not None + block_time = time.struct_time( + time.localtime( + full_block.foliage_transaction_block.timestamp if full_block.foliage_transaction_block else None + ) + ) + block_time_string = time.strftime("%a %b %d %Y %T %Z", block_time) + cost = str(full_block.transactions_info.cost) + tx_filter_hash: Union[str, bytes32] = "Not a transaction block" + if full_block.foliage_transaction_block: + tx_filter_hash = full_block.foliage_transaction_block.filter_hash + fees: Any = block.fees + else: + block_time_string = "Not a transaction block" + cost = "Not a transaction block" + tx_filter_hash = "Not a transaction block" + fees = "Not a transaction block" + address_prefix = config["network_overrides"]["config"][config["selected_network"]]["address_prefix"] + farmer_address = encode_puzzle_hash(block.farmer_puzzle_hash, address_prefix) + pool_address = encode_puzzle_hash(block.pool_puzzle_hash, address_prefix) + pool_pk = ( + full_block.reward_chain_block.proof_of_space.pool_public_key + if full_block.reward_chain_block.proof_of_space.pool_public_key is not None + else "Pay to pool puzzle hash" + ) + print( + f"Block Height {block.height}\n" + f"Header Hash 0x{block.header_hash.hex()}\n" + f"Timestamp {block_time_string}\n" + f"Weight {block.weight}\n" + f"Previous Block 0x{block.prev_hash.hex()}\n" + f"Difficulty {difficulty}\n" + f"Sub-slot iters {block.sub_slot_iters}\n" + f"Cost {cost}\n" + f"Total VDF Iterations {block.total_iters}\n" + f"Is a Transaction Block?{block.is_transaction_block}\n" + f"Deficit {block.deficit}\n" + f"PoSpace 'k' Size {full_block.reward_chain_block.proof_of_space.size}\n" + f"Plot Public Key 0x{full_block.reward_chain_block.proof_of_space.plot_public_key}\n" + f"Pool Public Key {pool_pk}\n" + f"Tx Filter Hash {tx_filter_hash}\n" + f"Farmer Address {farmer_address}\n" + f"Pool Address {pool_address}\n" + f"Fees Amount {fees}\n" + ) + else: + print("Block with header hash", block_by_header_hash, "not found") + + +async def show_async( + node_client: FullNodeRpcClient, + config: Dict[str, Any], + state: bool, + block_header_hash_by_height: str, + block_by_header_hash: str, +) -> None: + + # Check State + if state: + if await print_blockchain_state(node_client, config) is True: + return None # if no blockchain is found + # Get Block Information + if block_header_hash_by_height != "": + block_header = await node_client.get_block_record_by_height(block_header_hash_by_height) + if block_header is not None: + print(f"Header hash of block {block_header_hash_by_height}: " f"{block_header.header_hash.hex()}") + else: + print("Block height", block_header_hash_by_height, "not found") + if block_by_header_hash != "": + await print_block_from_hash(node_client, config, block_by_header_hash) diff --git a/chia/cmds/wallet_funcs.py b/chia/cmds/wallet_funcs.py index f7124dbb7c5b..723be4472a5e 100644 --- a/chia/cmds/wallet_funcs.py +++ b/chia/cmds/wallet_funcs.py @@ -9,7 +9,7 @@ import aiohttp from chia.cmds.cmds_util import transaction_status_msg, transaction_submitted_msg -from chia.cmds.show import print_connections +from chia.cmds.peer_funcs import print_connections from chia.cmds.units import units from chia.rpc.wallet_rpc_client import WalletRpcClient from chia.server.start_wallet import SERVICE_NAME diff --git a/chia/rpc/rpc_client.py b/chia/rpc/rpc_client.py index 4e7b8f94def2..90f1647617dc 100644 --- a/chia/rpc/rpc_client.py +++ b/chia/rpc/rpc_client.py @@ -70,9 +70,9 @@ async def stop_node(self) -> Dict: async def healthz(self) -> Dict: return await self.fetch("healthz", {}) - def close(self): + def close(self) -> None: self.closing_task = asyncio.create_task(self.session.close()) - async def await_closed(self): + async def await_closed(self) -> None: if self.closing_task is not None: await self.closing_task diff --git a/mypy.ini b/mypy.ini index 0abf4f555388..a9f190d7d2da 100644 --- a/mypy.ini +++ b/mypy.ini @@ -17,7 +17,7 @@ no_implicit_reexport = True strict_equality = True # list created by: venv/bin/mypy | sed -n 's/.py:.*//p' | sort | uniq | tr '/' '.' | tr '\n' ',' -[mypy-benchmarks.block_ref,benchmarks.block_store,benchmarks.coin_store,benchmarks.utils,build_scripts.installer-version,chia.cmds.configure,chia.cmds.db,chia.cmds.db_upgrade_func,chia.cmds.farm_funcs,chia.cmds.init,chia.cmds.init_funcs,chia.cmds.keys,chia.cmds.keys_funcs,chia.cmds.passphrase,chia.cmds.passphrase_funcs,chia.cmds.plotnft,chia.cmds.plotnft_funcs,chia.cmds.plots,chia.cmds.plotters,chia.cmds.show,chia.cmds.start_funcs,chia.cmds.wallet,chia.cmds.wallet_funcs,chia.daemon.client,chia.daemon.keychain_proxy,chia.daemon.keychain_server,chia.daemon.server,chia.farmer.farmer,chia.farmer.farmer_api,chia.full_node.block_height_map,chia.full_node.block_store,chia.full_node.bundle_tools,chia.full_node.coin_store,chia.full_node.full_node,chia.full_node.full_node_api,chia.full_node.full_node_store,chia.full_node.generator,chia.full_node.hint_store,chia.full_node.lock_queue,chia.full_node.mempool,chia.full_node.mempool_check_conditions,chia.full_node.mempool_manager,chia.full_node.pending_tx_cache,chia.full_node.sync_store,chia.full_node.weight_proof,chia.harvester.harvester,chia.harvester.harvester_api,chia.introducer.introducer,chia.introducer.introducer_api,chia.plotters.bladebit,chia.plotters.chiapos,chia.plotters.install_plotter,chia.plotters.madmax,chia.plotters.plotters,chia.plotters.plotters_util,chia.plotting.check_plots,chia.plotting.create_plots,chia.plotting.manager,chia.plotting.util,chia.pools.pool_config,chia.pools.pool_puzzles,chia.pools.pool_wallet,chia.pools.pool_wallet_info,chia.protocols.pool_protocol,chia.rpc.crawler_rpc_api,chia.rpc.farmer_rpc_api,chia.rpc.farmer_rpc_client,chia.rpc.full_node_rpc_api,chia.rpc.full_node_rpc_client,chia.rpc.harvester_rpc_api,chia.rpc.harvester_rpc_client,chia.rpc.rpc_client,chia.rpc.timelord_rpc_api,chia.rpc.util,chia.rpc.wallet_rpc_api,chia.rpc.wallet_rpc_client,chia.seeder.crawler,chia.seeder.crawler_api,chia.seeder.crawl_store,chia.seeder.dns_server,chia.seeder.peer_record,chia.seeder.start_crawler,chia.server.address_manager,chia.server.address_manager_store,chia.server.connection_utils,chia.server.introducer_peers,chia.server.node_discovery,chia.server.peer_store_resolver,chia.server.rate_limits,chia.server.reconnect_task,chia.server.server,chia.server.ssl_context,chia.server.start_farmer,chia.server.start_full_node,chia.server.start_harvester,chia.server.start_introducer,chia.server.start_service,chia.server.start_timelord,chia.server.start_wallet,chia.server.ws_connection,chia.simulator.full_node_simulator,chia.simulator.start_simulator,chia.ssl.create_ssl,chia.timelord.iters_from_block,chia.timelord.timelord,chia.timelord.timelord_api,chia.timelord.timelord_launcher,chia.timelord.timelord_state,chia.types.announcement,chia.types.blockchain_format.classgroup,chia.types.blockchain_format.coin,chia.types.blockchain_format.program,chia.types.blockchain_format.proof_of_space,chia.types.blockchain_format.tree_hash,chia.types.blockchain_format.vdf,chia.types.full_block,chia.types.header_block,chia.types.mempool_item,chia.types.name_puzzle_condition,chia.types.peer_info,chia.types.spend_bundle,chia.types.transaction_queue_entry,chia.types.unfinished_block,chia.types.unfinished_header_block,chia.util.api_decorators,chia.util.block_cache,chia.util.cached_bls,chia.util.check_fork_next_block,chia.util.chia_logging,chia.util.config,chia.util.db_wrapper,chia.util.dump_keyring,chia.util.file_keyring,chia.util.files,chia.util.hash,chia.util.json_util,chia.util.keychain,chia.util.keyring_wrapper,chia.util.log_exceptions,chia.util.lru_cache,chia.util.make_test_constants,chia.util.merkle_set,chia.util.network,chia.util.partial_func,chia.util.pip_import,chia.util.profiler,chia.util.safe_cancel_task,chia.util.service_groups,chia.util.ssl_check,chia.util.validate_alert,chia.wallet.block_record,chia.wallet.cat_wallet.cat_utils,chia.wallet.cat_wallet.cat_wallet,chia.wallet.cat_wallet.lineage_store,chia.wallet.chialisp,chia.wallet.did_wallet.did_wallet,chia.wallet.did_wallet.did_wallet_puzzles,chia.wallet.key_val_store,chia.wallet.lineage_proof,chia.wallet.nft_wallet.nft_wallet,chia.wallet.payment,chia.wallet.puzzles.load_clvm,chia.wallet.puzzles.p2_conditions,chia.wallet.puzzles.p2_delegated_conditions,chia.wallet.puzzles.p2_delegated_puzzle,chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle,chia.wallet.puzzles.p2_m_of_n_delegate_direct,chia.wallet.puzzles.p2_puzzle_hash,chia.wallet.puzzles.prefarm.spend_prefarm,chia.wallet.puzzles.puzzle_utils,chia.wallet.puzzles.rom_bootstrap_generator,chia.wallet.puzzles.singleton_top_layer,chia.wallet.puzzles.tails,chia.wallet.rl_wallet.rl_wallet,chia.wallet.rl_wallet.rl_wallet_puzzles,chia.wallet.secret_key_store,chia.wallet.settings.user_settings,chia.wallet.trade_manager,chia.wallet.trade_record,chia.wallet.trading.offer,chia.wallet.trading.trade_store,chia.wallet.transaction_record,chia.wallet.util.debug_spend_bundle,chia.wallet.util.new_peak_queue,chia.wallet.util.peer_request_cache,chia.wallet.util.wallet_sync_utils,chia.wallet.wallet,chia.wallet.wallet_action_store,chia.wallet.wallet_blockchain,chia.wallet.wallet_coin_store,chia.wallet.wallet_interested_store,chia.wallet.wallet_node,chia.wallet.wallet_node_api,chia.wallet.wallet_pool_store,chia.wallet.wallet_puzzle_store,chia.wallet.wallet_state_manager,chia.wallet.wallet_sync_store,chia.wallet.wallet_transaction_store,chia.wallet.wallet_user_store,chia.wallet.wallet_weight_proof_handler,installhelper,tests.blockchain.blockchain_test_utils,tests.blockchain.test_blockchain,tests.blockchain.test_blockchain_transactions,chia.simulator.block_tools,tests.build-init-files,tests.build-workflows,tests.clvm.coin_store,tests.clvm.test_chialisp_deserialization,tests.clvm.test_clvm_compilation,tests.clvm.test_program,tests.clvm.test_puzzle_compression,tests.clvm.test_puzzles,tests.clvm.test_serialized_program,tests.clvm.test_singletons,tests.clvm.test_spend_sim,tests.conftest,tests.connection_utils,tests.core.cmds.test_keys,tests.core.consensus.test_pot_iterations,tests.core.custom_types.test_coin,tests.core.custom_types.test_proof_of_space,tests.core.custom_types.test_spend_bundle,tests.core.daemon.test_daemon,tests.core.full_node.full_sync.test_full_sync,tests.core.full_node.stores.test_block_store,tests.core.full_node.stores.test_coin_store,tests.core.full_node.stores.test_full_node_store,tests.core.full_node.stores.test_hint_store,tests.core.full_node.stores.test_sync_store,tests.core.full_node.test_address_manager,tests.core.full_node.test_block_height_map,tests.core.full_node.test_conditions,tests.core.full_node.test_full_node,tests.core.full_node.test_mempool,tests.core.full_node.test_mempool_performance,tests.core.full_node.test_node_load,tests.core.full_node.test_peer_store_resolver,tests.core.full_node.test_performance,tests.core.full_node.test_transactions,tests.core.make_block_generator,tests.core.node_height,tests.core.server.test_dos,tests.core.server.test_rate_limits,tests.core.ssl.test_ssl,tests.core.test_cost_calculation,tests.core.test_crawler_rpc,tests.core.test_daemon_rpc,tests.core.test_db_conversion,tests.core.test_db_validation,tests.core.test_farmer_harvester_rpc,tests.core.test_filter,tests.core.test_full_node_rpc,tests.core.test_merkle_set,tests.core.test_setproctitle,tests.core.util.test_cached_bls,tests.core.util.test_config,tests.core.util.test_file_keyring_synchronization,tests.core.util.test_files,tests.core.util.test_keychain,tests.core.util.test_keyring_wrapper,tests.core.util.test_lru_cache,tests.core.util.test_significant_bits,tests.farmer_harvester.test_farmer_harvester,tests.generator.test_compression,tests.generator.test_generator_types,tests.generator.test_list_to_batches,tests.generator.test_rom,tests.generator.test_scan,tests.plotting.test_plot_manager,tests.pools.test_pool_cmdline,tests.pools.test_pool_config,tests.pools.test_pool_puzzles_lifecycle,tests.pools.test_pool_rpc,tests.pools.test_wallet_pool_store,tests.setup_nodes,tests.setup_services,tests.simulation.test_simulation,chia.simulator.time_out_assert,tests.tools.test_full_sync,tests.tools.test_run_block,tests.util.alert_server,tests.util.benchmark_cost,tests.util.blockchain,tests.util.build_network_protocol_files,tests.util.db_connection,tests.util.generator_tools_testing,tests.util.keyring,tests.util.key_tool,tests.util.rpc,tests.util.test_full_block_utils,tests.util.test_lock_queue,tests.util.test_misc,tests.util.test_network,tests.util.test_network_protocol_files,tests.wallet.cat_wallet.test_cat_lifecycle,tests.wallet.cat_wallet.test_cat_wallet,tests.wallet.cat_wallet.test_offer_lifecycle,tests.wallet.cat_wallet.test_trades,tests.wallet.did_wallet.test_did,tests.wallet.did_wallet.test_did_rpc,tests.wallet.did_wallet.test_nft_rpc,tests.wallet.did_wallet.test_nft_wallet,tests.wallet.rl_wallet.test_rl_rpc,tests.wallet.rl_wallet.test_rl_wallet,tests.wallet.rpc.test_wallet_rpc,tests.wallet.simple_sync.test_simple_sync_protocol,tests.wallet.sync.test_wallet_sync,tests.wallet.test_bech32m,tests.wallet.test_chialisp,tests.wallet.test_puzzle_store,tests.wallet.test_singleton,tests.wallet.test_singleton_lifecycle,tests.wallet.test_singleton_lifecycle_fast,tests.wallet.test_taproot,tests.wallet.test_wallet_blockchain,tests.wallet.test_wallet_interested_store,tests.wallet.test_wallet_key_val_store,tests.wallet.test_wallet_user_store,chia.simulator.wallet_tools,tests.weight_proof.test_weight_proof,tools.analyze-chain,tools.run_block,tools.test_full_sync,tests.wallet.nft_wallet.test_nft_wallet,chia.wallet.nft_wallet.nft_puzzles,tests.wallet.nft_wallet.test_nft_puzzles] +[mypy-benchmarks.block_ref,benchmarks.block_store,benchmarks.coin_store,benchmarks.utils,build_scripts.installer-version,chia.cmds.configure,chia.cmds.db,chia.cmds.db_upgrade_func,chia.cmds.farm_funcs,chia.cmds.init,chia.cmds.init_funcs,chia.cmds.keys,chia.cmds.keys_funcs,chia.cmds.passphrase,chia.cmds.passphrase_funcs,chia.cmds.plotnft,chia.cmds.plotnft_funcs,chia.cmds.plots,chia.cmds.plotters,chia.cmds.cmds_util,chia.cmds.start_funcs,chia.cmds.wallet,chia.cmds.wallet_funcs,chia.daemon.client,chia.daemon.keychain_proxy,chia.daemon.keychain_server,chia.daemon.server,chia.farmer.farmer,chia.farmer.farmer_api,chia.full_node.block_height_map,chia.full_node.block_store,chia.full_node.bundle_tools,chia.full_node.coin_store,chia.full_node.full_node,chia.full_node.full_node_api,chia.full_node.full_node_store,chia.full_node.generator,chia.full_node.hint_store,chia.full_node.lock_queue,chia.full_node.mempool,chia.full_node.mempool_check_conditions,chia.full_node.mempool_manager,chia.full_node.pending_tx_cache,chia.full_node.sync_store,chia.full_node.weight_proof,chia.harvester.harvester,chia.harvester.harvester_api,chia.introducer.introducer,chia.introducer.introducer_api,chia.plotters.bladebit,chia.plotters.chiapos,chia.plotters.install_plotter,chia.plotters.madmax,chia.plotters.plotters,chia.plotters.plotters_util,chia.plotting.check_plots,chia.plotting.create_plots,chia.plotting.manager,chia.plotting.util,chia.pools.pool_config,chia.pools.pool_puzzles,chia.pools.pool_wallet,chia.pools.pool_wallet_info,chia.protocols.pool_protocol,chia.rpc.crawler_rpc_api,chia.rpc.farmer_rpc_api,chia.rpc.farmer_rpc_client,chia.rpc.full_node_rpc_api,chia.rpc.full_node_rpc_client,chia.rpc.harvester_rpc_api,chia.rpc.harvester_rpc_client,chia.rpc.rpc_client,chia.rpc.timelord_rpc_api,chia.rpc.util,chia.rpc.wallet_rpc_api,chia.rpc.wallet_rpc_client,chia.seeder.crawler,chia.seeder.crawler_api,chia.seeder.crawl_store,chia.seeder.dns_server,chia.seeder.peer_record,chia.seeder.start_crawler,chia.server.address_manager,chia.server.address_manager_store,chia.server.connection_utils,chia.server.introducer_peers,chia.server.node_discovery,chia.server.peer_store_resolver,chia.server.rate_limits,chia.server.reconnect_task,chia.server.server,chia.server.ssl_context,chia.server.start_farmer,chia.server.start_full_node,chia.server.start_harvester,chia.server.start_introducer,chia.server.start_service,chia.server.start_timelord,chia.server.start_wallet,chia.server.ws_connection,chia.simulator.full_node_simulator,chia.simulator.start_simulator,chia.ssl.create_ssl,chia.timelord.iters_from_block,chia.timelord.timelord,chia.timelord.timelord_api,chia.timelord.timelord_launcher,chia.timelord.timelord_state,chia.types.announcement,chia.types.blockchain_format.classgroup,chia.types.blockchain_format.coin,chia.types.blockchain_format.program,chia.types.blockchain_format.proof_of_space,chia.types.blockchain_format.tree_hash,chia.types.blockchain_format.vdf,chia.types.full_block,chia.types.header_block,chia.types.mempool_item,chia.types.name_puzzle_condition,chia.types.peer_info,chia.types.spend_bundle,chia.types.transaction_queue_entry,chia.types.unfinished_block,chia.types.unfinished_header_block,chia.util.api_decorators,chia.util.block_cache,chia.util.cached_bls,chia.util.check_fork_next_block,chia.util.chia_logging,chia.util.config,chia.util.db_wrapper,chia.util.dump_keyring,chia.util.file_keyring,chia.util.files,chia.util.hash,chia.util.json_util,chia.util.keychain,chia.util.keyring_wrapper,chia.util.log_exceptions,chia.util.lru_cache,chia.util.make_test_constants,chia.util.merkle_set,chia.util.network,chia.util.partial_func,chia.util.pip_import,chia.util.profiler,chia.util.safe_cancel_task,chia.util.service_groups,chia.util.ssl_check,chia.util.validate_alert,chia.wallet.block_record,chia.wallet.cat_wallet.cat_utils,chia.wallet.cat_wallet.cat_wallet,chia.wallet.cat_wallet.lineage_store,chia.wallet.chialisp,chia.wallet.did_wallet.did_wallet,chia.wallet.did_wallet.did_wallet_puzzles,chia.wallet.key_val_store,chia.wallet.lineage_proof,chia.wallet.nft_wallet.nft_wallet,chia.wallet.payment,chia.wallet.puzzles.load_clvm,chia.wallet.puzzles.p2_conditions,chia.wallet.puzzles.p2_delegated_conditions,chia.wallet.puzzles.p2_delegated_puzzle,chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle,chia.wallet.puzzles.p2_m_of_n_delegate_direct,chia.wallet.puzzles.p2_puzzle_hash,chia.wallet.puzzles.prefarm.spend_prefarm,chia.wallet.puzzles.puzzle_utils,chia.wallet.puzzles.rom_bootstrap_generator,chia.wallet.puzzles.singleton_top_layer,chia.wallet.puzzles.tails,chia.wallet.rl_wallet.rl_wallet,chia.wallet.rl_wallet.rl_wallet_puzzles,chia.wallet.secret_key_store,chia.wallet.settings.user_settings,chia.wallet.trade_manager,chia.wallet.trade_record,chia.wallet.trading.offer,chia.wallet.trading.trade_store,chia.wallet.transaction_record,chia.wallet.util.debug_spend_bundle,chia.wallet.util.new_peak_queue,chia.wallet.util.peer_request_cache,chia.wallet.util.wallet_sync_utils,chia.wallet.wallet,chia.wallet.wallet_action_store,chia.wallet.wallet_blockchain,chia.wallet.wallet_coin_store,chia.wallet.wallet_interested_store,chia.wallet.wallet_node,chia.wallet.wallet_node_api,chia.wallet.wallet_pool_store,chia.wallet.wallet_puzzle_store,chia.wallet.wallet_state_manager,chia.wallet.wallet_sync_store,chia.wallet.wallet_transaction_store,chia.wallet.wallet_user_store,chia.wallet.wallet_weight_proof_handler,installhelper,tests.blockchain.blockchain_test_utils,tests.blockchain.test_blockchain,tests.blockchain.test_blockchain_transactions,chia.simulator.block_tools,tests.build-init-files,tests.build-workflows,tests.clvm.coin_store,tests.clvm.test_chialisp_deserialization,tests.clvm.test_clvm_compilation,tests.clvm.test_program,tests.clvm.test_puzzle_compression,tests.clvm.test_puzzles,tests.clvm.test_serialized_program,tests.clvm.test_singletons,tests.clvm.test_spend_sim,tests.conftest,tests.connection_utils,tests.core.cmds.test_keys,tests.core.consensus.test_pot_iterations,tests.core.custom_types.test_coin,tests.core.custom_types.test_proof_of_space,tests.core.custom_types.test_spend_bundle,tests.core.daemon.test_daemon,tests.core.full_node.full_sync.test_full_sync,tests.core.full_node.stores.test_block_store,tests.core.full_node.stores.test_coin_store,tests.core.full_node.stores.test_full_node_store,tests.core.full_node.stores.test_hint_store,tests.core.full_node.stores.test_sync_store,tests.core.full_node.test_address_manager,tests.core.full_node.test_block_height_map,tests.core.full_node.test_conditions,tests.core.full_node.test_full_node,tests.core.full_node.test_mempool,tests.core.full_node.test_mempool_performance,tests.core.full_node.test_node_load,tests.core.full_node.test_peer_store_resolver,tests.core.full_node.test_performance,tests.core.full_node.test_transactions,tests.core.make_block_generator,tests.core.node_height,tests.core.server.test_dos,tests.core.server.test_rate_limits,tests.core.ssl.test_ssl,tests.core.test_cost_calculation,tests.core.test_crawler_rpc,tests.core.test_daemon_rpc,tests.core.test_db_conversion,tests.core.test_db_validation,tests.core.test_farmer_harvester_rpc,tests.core.test_filter,tests.core.test_full_node_rpc,tests.core.test_merkle_set,tests.core.test_setproctitle,tests.core.util.test_cached_bls,tests.core.util.test_config,tests.core.util.test_file_keyring_synchronization,tests.core.util.test_files,tests.core.util.test_keychain,tests.core.util.test_keyring_wrapper,tests.core.util.test_lru_cache,tests.core.util.test_significant_bits,tests.farmer_harvester.test_farmer_harvester,tests.generator.test_compression,tests.generator.test_generator_types,tests.generator.test_list_to_batches,tests.generator.test_rom,tests.generator.test_scan,tests.plotting.test_plot_manager,tests.pools.test_pool_cmdline,tests.pools.test_pool_config,tests.pools.test_pool_puzzles_lifecycle,tests.pools.test_pool_rpc,tests.pools.test_wallet_pool_store,tests.setup_nodes,tests.setup_services,tests.simulation.test_simulation,chia.simulator.time_out_assert,tests.tools.test_full_sync,tests.tools.test_run_block,tests.util.alert_server,tests.util.benchmark_cost,tests.util.blockchain,tests.util.build_network_protocol_files,tests.util.db_connection,tests.util.generator_tools_testing,tests.util.keyring,tests.util.key_tool,tests.util.rpc,tests.util.test_full_block_utils,tests.util.test_lock_queue,tests.util.test_misc,tests.util.test_network,tests.util.test_network_protocol_files,tests.wallet.cat_wallet.test_cat_lifecycle,tests.wallet.cat_wallet.test_cat_wallet,tests.wallet.cat_wallet.test_offer_lifecycle,tests.wallet.cat_wallet.test_trades,tests.wallet.did_wallet.test_did,tests.wallet.did_wallet.test_did_rpc,tests.wallet.did_wallet.test_nft_rpc,tests.wallet.did_wallet.test_nft_wallet,tests.wallet.rl_wallet.test_rl_rpc,tests.wallet.rl_wallet.test_rl_wallet,tests.wallet.rpc.test_wallet_rpc,tests.wallet.simple_sync.test_simple_sync_protocol,tests.wallet.sync.test_wallet_sync,tests.wallet.test_bech32m,tests.wallet.test_chialisp,tests.wallet.test_puzzle_store,tests.wallet.test_singleton,tests.wallet.test_singleton_lifecycle,tests.wallet.test_singleton_lifecycle_fast,tests.wallet.test_taproot,tests.wallet.test_wallet_blockchain,tests.wallet.test_wallet_interested_store,tests.wallet.test_wallet_key_val_store,tests.wallet.test_wallet_user_store,chia.simulator.wallet_tools,tests.weight_proof.test_weight_proof,tools.analyze-chain,tools.run_block,tools.test_full_sync,tests.wallet.nft_wallet.test_nft_wallet,chia.wallet.nft_wallet.nft_puzzles,tests.wallet.nft_wallet.test_nft_puzzles] disallow_any_generics = False disallow_subclassing_any = False disallow_untyped_calls = False