mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2025-01-08 10:25:24 +03:00
server: Introduce ApiProtocol
(#15466)
* server: Introduce `ApiProtocol` * genericize (#5) * `ApiProtocol.api_ready` -> `ApiProtocol.ready()` * Add `ApiProtocol.log` and give APIs separate loggers * Fix `CrawlerAPI` * Drop some unrelated removals * Fix some of the generic hinting * Revert some changes in `timelord_api.py` * Fix `CawlerAPI` readiness * Fix hinting * Get some `CrawlerAPI` coverage --------- Co-authored-by: Kyle Altendorf <sda@fstab.net>
This commit is contained in:
parent
46a244ae09
commit
49140b2b3c
@ -7,9 +7,11 @@ from chia.server.server import ChiaServer
|
||||
|
||||
|
||||
class DataLayerAPI:
|
||||
log: logging.Logger
|
||||
data_layer: DataLayer
|
||||
|
||||
def __init__(self, data_layer: DataLayer) -> None:
|
||||
self.log = logging.getLogger(__name__)
|
||||
self.data_layer = data_layer
|
||||
|
||||
# def _set_state_changed_callback(self, callback: StateChangedProtocol) -> None:
|
||||
@ -19,10 +21,5 @@ class DataLayerAPI:
|
||||
def server(self) -> ChiaServer:
|
||||
return self.data_layer.server
|
||||
|
||||
@property
|
||||
def log(self) -> logging.Logger:
|
||||
return self.data_layer.log
|
||||
|
||||
@property
|
||||
def api_ready(self) -> bool:
|
||||
def ready(self) -> bool:
|
||||
return self.data_layer.initialized
|
||||
|
@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
@ -53,11 +54,16 @@ def strip_old_entries(pairs: List[Tuple[float, Any]], before: float) -> List[Tup
|
||||
|
||||
|
||||
class FarmerAPI:
|
||||
log: logging.Logger
|
||||
farmer: Farmer
|
||||
|
||||
def __init__(self, farmer: Farmer) -> None:
|
||||
self.log = logging.getLogger(__name__)
|
||||
self.farmer = farmer
|
||||
|
||||
def ready(self) -> bool:
|
||||
return self.farmer.started
|
||||
|
||||
@api_request(peer_required=True)
|
||||
async def new_proof_of_space(
|
||||
self, new_proof_of_space: harvester_protocol.NewProofOfSpace, peer: WSChiaConnection
|
||||
|
@ -69,10 +69,12 @@ else:
|
||||
|
||||
|
||||
class FullNodeAPI:
|
||||
log: logging.Logger
|
||||
full_node: FullNode
|
||||
executor: ThreadPoolExecutor
|
||||
|
||||
def __init__(self, full_node: FullNode) -> None:
|
||||
self.log = logging.getLogger(__name__)
|
||||
self.full_node = full_node
|
||||
self.executor = ThreadPoolExecutor(max_workers=1)
|
||||
|
||||
@ -81,12 +83,7 @@ class FullNodeAPI:
|
||||
assert self.full_node.server is not None
|
||||
return self.full_node.server
|
||||
|
||||
@property
|
||||
def log(self) -> logging.Logger:
|
||||
return self.full_node.log
|
||||
|
||||
@property
|
||||
def api_ready(self) -> bool:
|
||||
def ready(self) -> bool:
|
||||
return self.full_node.initialized
|
||||
|
||||
@api_request(peer_required=True, reply_types=[ProtocolMessageTypes.respond_peers])
|
||||
|
@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import List, Optional, Tuple
|
||||
@ -29,11 +30,16 @@ from chia.wallet.derive_keys import master_sk_to_local_sk
|
||||
|
||||
|
||||
class HarvesterAPI:
|
||||
log: logging.Logger
|
||||
harvester: Harvester
|
||||
|
||||
def __init__(self, harvester: Harvester):
|
||||
self.log = logging.getLogger(__name__)
|
||||
self.harvester = harvester
|
||||
|
||||
def ready(self) -> bool:
|
||||
return True
|
||||
|
||||
@api_request(peer_required=True)
|
||||
async def harvester_handshake(
|
||||
self, harvester_handshake: harvester_protocol.HarvesterHandshake, peer: WSChiaConnection
|
||||
|
@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from chia.introducer.introducer import Introducer
|
||||
@ -14,11 +15,16 @@ from chia.util.ints import uint64
|
||||
|
||||
|
||||
class IntroducerAPI:
|
||||
log: logging.Logger
|
||||
introducer: Introducer
|
||||
|
||||
def __init__(self, introducer) -> None:
|
||||
self.log = logging.getLogger(__name__)
|
||||
self.introducer = introducer
|
||||
|
||||
def ready(self) -> bool:
|
||||
return True
|
||||
|
||||
def _set_state_changed_callback(self, callback: StateChangedProtocol) -> None:
|
||||
pass
|
||||
|
||||
|
@ -12,9 +12,11 @@ from chia.util.api_decorators import api_request
|
||||
|
||||
|
||||
class CrawlerAPI:
|
||||
log: logging.Logger
|
||||
crawler: Crawler
|
||||
|
||||
def __init__(self, crawler: Crawler) -> None:
|
||||
self.log = logging.getLogger(__name__)
|
||||
self.crawler = crawler
|
||||
|
||||
@property
|
||||
@ -22,9 +24,8 @@ class CrawlerAPI:
|
||||
assert self.crawler.server is not None
|
||||
return self.crawler.server
|
||||
|
||||
@property
|
||||
def log(self) -> logging.Logger:
|
||||
return self.crawler.log
|
||||
def ready(self) -> bool:
|
||||
return True
|
||||
|
||||
@api_request(peer_required=True)
|
||||
async def request_peers(
|
||||
|
@ -29,7 +29,7 @@ def create_full_node_crawler_service(
|
||||
config: Dict,
|
||||
consensus_constants: ConsensusConstants,
|
||||
connect_to_daemon: bool = True,
|
||||
) -> Service[Crawler]:
|
||||
) -> Service[Crawler, CrawlerAPI]:
|
||||
service_config = config[SERVICE_NAME]
|
||||
|
||||
crawler = Crawler(
|
||||
|
12
chia/server/api_protocol.py
Normal file
12
chia/server/api_protocol.py
Normal file
@ -0,0 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from logging import Logger
|
||||
|
||||
from typing_extensions import Protocol
|
||||
|
||||
|
||||
class ApiProtocol(Protocol):
|
||||
log: Logger
|
||||
|
||||
def ready(self) -> bool:
|
||||
...
|
@ -28,6 +28,7 @@ from chia.protocols.protocol_message_types import ProtocolMessageTypes
|
||||
from chia.protocols.protocol_state_machine import message_requires_reply
|
||||
from chia.protocols.protocol_timing import INVALID_PROTOCOL_BAN_SECONDS
|
||||
from chia.protocols.shared_protocol import protocol_version
|
||||
from chia.server.api_protocol import ApiProtocol
|
||||
from chia.server.introducer_peers import IntroducerPeers
|
||||
from chia.server.outbound_message import Message, NodeType
|
||||
from chia.server.ssl_context import private_ssl_paths, public_ssl_paths
|
||||
@ -122,7 +123,7 @@ class ChiaServer:
|
||||
_network_id: str
|
||||
_inbound_rate_limit_percent: int
|
||||
_outbound_rate_limit_percent: int
|
||||
api: Any
|
||||
api: ApiProtocol
|
||||
node: Any
|
||||
root_path: Path
|
||||
config: Dict[str, Any]
|
||||
@ -147,7 +148,7 @@ class ChiaServer:
|
||||
cls,
|
||||
port: int,
|
||||
node: Any,
|
||||
api: Any,
|
||||
api: ApiProtocol,
|
||||
local_type: NodeType,
|
||||
ping_interval: int,
|
||||
network_id: str,
|
||||
|
@ -17,6 +17,7 @@ from chia.util.config import load_config, load_config_cli
|
||||
from chia.util.default_root import DEFAULT_ROOT_PATH
|
||||
from chia.util.ints import uint16
|
||||
from chia.wallet.wallet_node import WalletNode
|
||||
from chia.wallet.wallet_node_api import WalletNodeAPI
|
||||
|
||||
# See: https://bugs.python.org/issue29288
|
||||
"".encode("idna")
|
||||
@ -31,9 +32,9 @@ def create_data_layer_service(
|
||||
config: Dict[str, Any],
|
||||
downloaders: List[str],
|
||||
uploaders: List[str], # dont add FilesystemUploader to this, it is the default uploader
|
||||
wallet_service: Optional[Service[WalletNode]] = None,
|
||||
wallet_service: Optional[Service[WalletNode, WalletNodeAPI]] = None,
|
||||
connect_to_daemon: bool = True,
|
||||
) -> Service[DataLayer]:
|
||||
) -> Service[DataLayer, DataLayerAPI]:
|
||||
if uploaders is None:
|
||||
uploaders = []
|
||||
if downloaders is None:
|
||||
|
@ -30,7 +30,7 @@ def create_farmer_service(
|
||||
consensus_constants: ConsensusConstants,
|
||||
keychain: Optional[Keychain] = None,
|
||||
connect_to_daemon: bool = True,
|
||||
) -> Service[Farmer]:
|
||||
) -> Service[Farmer, FarmerAPI]:
|
||||
service_config = config[SERVICE_NAME]
|
||||
|
||||
fnp = service_config.get("full_node_peer")
|
||||
|
@ -33,7 +33,7 @@ def create_full_node_service(
|
||||
consensus_constants: ConsensusConstants,
|
||||
connect_to_daemon: bool = True,
|
||||
override_capabilities: Optional[List[Tuple[uint16, str]]] = None,
|
||||
) -> Service[FullNode]:
|
||||
) -> Service[FullNode, FullNodeAPI]:
|
||||
service_config = config[SERVICE_NAME]
|
||||
|
||||
full_node = FullNode(
|
||||
|
@ -28,7 +28,7 @@ def create_harvester_service(
|
||||
consensus_constants: ConsensusConstants,
|
||||
farmer_peer: Optional[UnresolvedPeerInfo],
|
||||
connect_to_daemon: bool = True,
|
||||
) -> Service[Harvester]:
|
||||
) -> Service[Harvester, HarvesterAPI]:
|
||||
service_config = config[SERVICE_NAME]
|
||||
|
||||
overrides = service_config["network_overrides"]["constants"][service_config["selected_network"]]
|
||||
|
@ -23,7 +23,7 @@ def create_introducer_service(
|
||||
config: Dict[str, Any],
|
||||
advertised_port: Optional[int] = None,
|
||||
connect_to_daemon: bool = True,
|
||||
) -> Service[Introducer]:
|
||||
) -> Service[Introducer, IntroducerAPI]:
|
||||
service_config = config[SERVICE_NAME]
|
||||
|
||||
if advertised_port is None:
|
||||
|
@ -14,6 +14,7 @@ from typing import Any, Awaitable, Callable, Coroutine, Dict, Generic, List, Opt
|
||||
from chia.cmds.init_funcs import chia_full_version_str
|
||||
from chia.daemon.server import service_launch_lock_path
|
||||
from chia.rpc.rpc_server import RpcApiProtocol, RpcServer, RpcServiceProtocol, start_rpc_server
|
||||
from chia.server.api_protocol import ApiProtocol
|
||||
from chia.server.chia_policy import set_chia_policy
|
||||
from chia.server.outbound_message import NodeType
|
||||
from chia.server.server import ChiaServer
|
||||
@ -34,6 +35,7 @@ main_pid: Optional[int] = None
|
||||
|
||||
T = TypeVar("T")
|
||||
_T_RpcServiceProtocol = TypeVar("_T_RpcServiceProtocol", bound=RpcServiceProtocol)
|
||||
_T_ApiProtocol = TypeVar("_T_ApiProtocol", bound=ApiProtocol)
|
||||
|
||||
RpcInfo = Tuple[Type[RpcApiProtocol], int]
|
||||
|
||||
@ -42,12 +44,12 @@ class ServiceException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Service(Generic[_T_RpcServiceProtocol]):
|
||||
class Service(Generic[_T_RpcServiceProtocol, _T_ApiProtocol]):
|
||||
def __init__(
|
||||
self,
|
||||
root_path: Path,
|
||||
node: _T_RpcServiceProtocol,
|
||||
peer_api: Any,
|
||||
peer_api: _T_ApiProtocol,
|
||||
node_type: NodeType,
|
||||
advertised_port: int,
|
||||
service_name: str,
|
||||
|
@ -31,7 +31,7 @@ def create_timelord_service(
|
||||
config: Dict[str, Any],
|
||||
constants: ConsensusConstants,
|
||||
connect_to_daemon: bool = True,
|
||||
) -> Service[Timelord]:
|
||||
) -> Service[Timelord, TimelordAPI]:
|
||||
service_config = config[SERVICE_NAME]
|
||||
|
||||
connect_peers = {
|
||||
|
@ -33,7 +33,7 @@ def create_wallet_service(
|
||||
consensus_constants: ConsensusConstants,
|
||||
keychain: Optional[Keychain] = None,
|
||||
connect_to_daemon: bool = True,
|
||||
) -> Service[WalletNode]:
|
||||
) -> Service[WalletNode, WalletNodeAPI]:
|
||||
service_config = config[SERVICE_NAME]
|
||||
|
||||
overrides = service_config["network_overrides"]["constants"][service_config["selected_network"]]
|
||||
|
@ -21,6 +21,7 @@ from chia.protocols.protocol_message_types import ProtocolMessageTypes
|
||||
from chia.protocols.protocol_state_machine import message_response_ok
|
||||
from chia.protocols.protocol_timing import API_EXCEPTION_BAN_SECONDS, INTERNAL_PROTOCOL_ERROR_BAN_SECONDS
|
||||
from chia.protocols.shared_protocol import Capability, Handshake
|
||||
from chia.server.api_protocol import ApiProtocol
|
||||
from chia.server.capabilities import known_active_capabilities
|
||||
from chia.server.outbound_message import Message, NodeType, make_msg
|
||||
from chia.server.rate_limits import RateLimiter
|
||||
@ -66,7 +67,7 @@ class WSChiaConnection:
|
||||
"""
|
||||
|
||||
ws: WebSocket = field(repr=False)
|
||||
api: Any = field(repr=False)
|
||||
api: ApiProtocol = field(repr=False)
|
||||
local_type: NodeType
|
||||
local_port: int
|
||||
local_capabilities_for_handshake: List[Tuple[uint16, str]] = field(repr=False)
|
||||
@ -123,7 +124,7 @@ class WSChiaConnection:
|
||||
cls,
|
||||
local_type: NodeType,
|
||||
ws: WebSocket,
|
||||
api: Any,
|
||||
api: ApiProtocol,
|
||||
server_port: int,
|
||||
log: logging.Logger,
|
||||
is_outbound: bool,
|
||||
@ -373,9 +374,9 @@ class WSChiaConnection:
|
||||
raise ProtocolError(Err.INVALID_PROTOCOL_MESSAGE, [message_type])
|
||||
|
||||
# If api is not ready ignore the request
|
||||
if hasattr(self.api, "api_ready"):
|
||||
if self.api.api_ready is False:
|
||||
return None
|
||||
if not self.api.ready():
|
||||
self.log.warning(f"API not ready, ignore request: {full_message}")
|
||||
return None
|
||||
|
||||
timeout: Optional[int] = 600
|
||||
if metadata.execute_task:
|
||||
|
@ -3,14 +3,16 @@ from __future__ import annotations
|
||||
import asyncio
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Any, AsyncGenerator, AsyncIterator, Dict, List, Optional, Tuple, Union
|
||||
from typing import Any, AsyncGenerator, AsyncIterator, Dict, List, Optional, Tuple, Union, cast
|
||||
|
||||
from chia.consensus.constants import ConsensusConstants
|
||||
from chia.daemon.server import WebSocketServer
|
||||
from chia.farmer.farmer import Farmer
|
||||
from chia.farmer.farmer_api import FarmerAPI
|
||||
from chia.full_node.full_node import FullNode
|
||||
from chia.full_node.full_node_api import FullNodeAPI
|
||||
from chia.harvester.harvester import Harvester
|
||||
from chia.harvester.harvester_api import HarvesterAPI
|
||||
from chia.protocols.shared_protocol import Capability
|
||||
from chia.server.server import ChiaServer
|
||||
from chia.server.start_service import Service
|
||||
@ -31,15 +33,19 @@ from chia.simulator.setup_services import (
|
||||
from chia.simulator.socket import find_available_listen_port
|
||||
from chia.simulator.time_out_assert import time_out_assert_custom_interval
|
||||
from chia.timelord.timelord import Timelord
|
||||
from chia.timelord.timelord_api import TimelordAPI
|
||||
from chia.types.blockchain_format.sized_bytes import bytes32
|
||||
from chia.types.peer_info import UnresolvedPeerInfo
|
||||
from chia.util.hash import std_hash
|
||||
from chia.util.ints import uint16, uint32
|
||||
from chia.util.keychain import Keychain
|
||||
from chia.wallet.wallet_node import WalletNode
|
||||
from chia.wallet.wallet_node_api import WalletNodeAPI
|
||||
|
||||
SimulatorsAndWallets = Tuple[List[FullNodeSimulator], List[Tuple[WalletNode, ChiaServer]], BlockTools]
|
||||
SimulatorsAndWalletsServices = Tuple[List[Service[FullNode]], List[Service[WalletNode]], BlockTools]
|
||||
SimulatorsAndWalletsServices = Tuple[
|
||||
List[Service[FullNode, FullNodeSimulator]], List[Service[WalletNode, WalletNodeAPI]], BlockTools
|
||||
]
|
||||
|
||||
|
||||
def cleanup_keyring(keyring: TempKeyring) -> None:
|
||||
@ -146,7 +152,7 @@ async def setup_simulators_and_wallets(
|
||||
db_version: int = 1,
|
||||
config_overrides: Optional[Dict[str, int]] = None,
|
||||
disable_capabilities: Optional[List[Capability]] = None,
|
||||
) -> AsyncGenerator[Tuple[List[FullNodeAPI], List[Tuple[WalletNode, ChiaServer]], BlockTools], None]:
|
||||
) -> AsyncGenerator[Tuple[List[FullNodeSimulator], List[Tuple[WalletNode, ChiaServer]], BlockTools], None]:
|
||||
with TempKeyring(populate=True) as keychain1, TempKeyring(populate=True) as keychain2:
|
||||
res = await setup_simulators_and_wallets_inner(
|
||||
db_version,
|
||||
@ -189,7 +195,9 @@ async def setup_simulators_and_wallets_service(
|
||||
db_version: int = 1,
|
||||
config_overrides: Optional[Dict[str, int]] = None,
|
||||
disable_capabilities: Optional[List[Capability]] = None,
|
||||
) -> AsyncGenerator[Tuple[List[Service[FullNode]], List[Service[WalletNode]], BlockTools], None]:
|
||||
) -> AsyncGenerator[
|
||||
Tuple[List[Service[FullNode, FullNodeSimulator]], List[Service[WalletNode, WalletNodeAPI]], BlockTools], None
|
||||
]:
|
||||
with TempKeyring(populate=True) as keychain1, TempKeyring(populate=True) as keychain2:
|
||||
res = await setup_simulators_and_wallets_inner(
|
||||
db_version,
|
||||
@ -227,13 +235,15 @@ async def setup_simulators_and_wallets_inner(
|
||||
disable_capabilities: Optional[List[Capability]],
|
||||
) -> Tuple[
|
||||
List[BlockTools],
|
||||
List[AsyncGenerator[Union[Service[FullNode], Service[WalletNode]], None]],
|
||||
List[Service[FullNode]],
|
||||
List[Service[WalletNode]],
|
||||
List[AsyncGenerator[Union[Service[FullNode, FullNodeSimulator], Service[WalletNode, WalletNodeAPI]], None]],
|
||||
List[Service[FullNode, FullNodeSimulator]],
|
||||
List[Service[WalletNode, WalletNodeAPI]],
|
||||
]:
|
||||
simulators: List[Service[FullNode]] = []
|
||||
wallets: List[Service[WalletNode]] = []
|
||||
node_iters: List[AsyncGenerator[Union[Service[FullNode], Service[WalletNode]], None]] = []
|
||||
simulators: List[Service[FullNode, FullNodeSimulator]] = []
|
||||
wallets: List[Service[WalletNode, WalletNodeAPI]] = []
|
||||
node_iters: List[
|
||||
AsyncGenerator[Union[Service[FullNode, FullNodeSimulator], Service[WalletNode, WalletNodeAPI]], None]
|
||||
] = []
|
||||
bt_tools: List[BlockTools] = []
|
||||
consensus_constants: ConsensusConstants = constants_for_dic(dic)
|
||||
for index in range(0, simulator_count):
|
||||
@ -243,14 +253,17 @@ async def setup_simulators_and_wallets_inner(
|
||||
consensus_constants, const_dict=dic, keychain=keychain1, config_overrides=config_overrides
|
||||
)
|
||||
) # block tools modifies constants
|
||||
sim = setup_full_node(
|
||||
consensus_constants=bt_tools[index].constants,
|
||||
db_name=db_name,
|
||||
self_hostname=bt_tools[index].config["self_hostname"],
|
||||
local_bt=bt_tools[index],
|
||||
simulator=True,
|
||||
db_version=db_version,
|
||||
disable_capabilities=disable_capabilities,
|
||||
sim = cast(
|
||||
AsyncGenerator[Service[FullNode, FullNodeSimulator], None],
|
||||
setup_full_node(
|
||||
consensus_constants=bt_tools[index].constants,
|
||||
db_name=db_name,
|
||||
self_hostname=bt_tools[index].config["self_hostname"],
|
||||
local_bt=bt_tools[index],
|
||||
simulator=True,
|
||||
db_version=db_version,
|
||||
disable_capabilities=disable_capabilities,
|
||||
),
|
||||
)
|
||||
service = await sim.__anext__()
|
||||
simulators.append(service)
|
||||
@ -289,7 +302,7 @@ async def setup_farmer_multi_harvester(
|
||||
consensus_constants: ConsensusConstants,
|
||||
*,
|
||||
start_services: bool,
|
||||
) -> AsyncIterator[Tuple[List[Service[Harvester]], Service[Farmer], BlockTools]]:
|
||||
) -> AsyncIterator[Tuple[List[Service[Harvester, HarvesterAPI]], Service[Farmer, FarmerAPI], BlockTools]]:
|
||||
farmer_node_iterators = [
|
||||
setup_farmer(
|
||||
block_tools,
|
||||
@ -342,7 +355,9 @@ async def setup_full_system(
|
||||
b_tools: Optional[BlockTools] = None,
|
||||
b_tools_1: Optional[BlockTools] = None,
|
||||
db_version: int = 1,
|
||||
) -> AsyncGenerator[Tuple[Any, Any, Harvester, Farmer, Any, Service[Timelord], object, object, Any, ChiaServer], None]:
|
||||
) -> AsyncGenerator[
|
||||
Tuple[Any, Any, Harvester, Farmer, Any, Service[Timelord, TimelordAPI], object, object, Any, ChiaServer], None
|
||||
]:
|
||||
with TempKeyring(populate=True) as keychain1, TempKeyring(populate=True) as keychain2:
|
||||
daemon_ws, node_iters, ret = await setup_full_system_inner(
|
||||
b_tools, b_tools_1, False, consensus_constants, db_version, keychain1, keychain2, shared_b_tools
|
||||
@ -361,7 +376,17 @@ async def setup_full_system_connect_to_deamon(
|
||||
db_version: int = 1,
|
||||
) -> AsyncGenerator[
|
||||
Tuple[
|
||||
Any, Any, Harvester, Farmer, Any, Service[Timelord], object, object, Any, ChiaServer, Optional[WebSocketServer]
|
||||
Any,
|
||||
Any,
|
||||
Harvester,
|
||||
Farmer,
|
||||
Any,
|
||||
Service[Timelord, TimelordAPI],
|
||||
object,
|
||||
object,
|
||||
Any,
|
||||
ChiaServer,
|
||||
Optional[WebSocketServer],
|
||||
],
|
||||
None,
|
||||
]:
|
||||
@ -387,7 +412,7 @@ async def setup_full_system_inner(
|
||||
) -> Tuple[
|
||||
Optional[WebSocketServer],
|
||||
List[AsyncGenerator[object, None]],
|
||||
Tuple[Any, Any, Harvester, Farmer, Any, Service[Timelord], object, object, Any, ChiaServer],
|
||||
Tuple[Any, Any, Harvester, Farmer, Any, Service[Timelord, TimelordAPI], object, object, Any, ChiaServer],
|
||||
]:
|
||||
if b_tools is None:
|
||||
b_tools = await create_block_tools_async(constants=consensus_constants, keychain=keychain1)
|
||||
|
@ -14,11 +14,16 @@ from chia.cmds.init_funcs import init
|
||||
from chia.consensus.constants import ConsensusConstants
|
||||
from chia.daemon.server import WebSocketServer, daemon_launch_lock_path
|
||||
from chia.farmer.farmer import Farmer
|
||||
from chia.farmer.farmer_api import FarmerAPI
|
||||
from chia.full_node.full_node import FullNode
|
||||
from chia.full_node.full_node_api import FullNodeAPI
|
||||
from chia.harvester.harvester import Harvester
|
||||
from chia.harvester.harvester_api import HarvesterAPI
|
||||
from chia.introducer.introducer import Introducer
|
||||
from chia.introducer.introducer_api import IntroducerAPI
|
||||
from chia.protocols.shared_protocol import Capability, capabilities
|
||||
from chia.seeder.crawler import Crawler
|
||||
from chia.seeder.crawler_api import CrawlerAPI
|
||||
from chia.seeder.start_crawler import create_full_node_crawler_service
|
||||
from chia.server.start_farmer import create_farmer_service
|
||||
from chia.server.start_full_node import create_full_node_service
|
||||
@ -31,6 +36,7 @@ from chia.simulator.block_tools import BlockTools
|
||||
from chia.simulator.keyring import TempKeyring
|
||||
from chia.simulator.start_simulator import create_full_node_simulator_service
|
||||
from chia.timelord.timelord import Timelord
|
||||
from chia.timelord.timelord_api import TimelordAPI
|
||||
from chia.timelord.timelord_launcher import kill_processes, spawn_process
|
||||
from chia.types.peer_info import UnresolvedPeerInfo
|
||||
from chia.util.bech32m import encode_puzzle_hash
|
||||
@ -39,6 +45,7 @@ from chia.util.ints import uint16
|
||||
from chia.util.keychain import bytes_to_mnemonic
|
||||
from chia.util.lock import Lockfile
|
||||
from chia.wallet.wallet_node import WalletNode
|
||||
from chia.wallet.wallet_node_api import WalletNodeAPI
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -102,7 +109,7 @@ async def setup_full_node(
|
||||
disable_capabilities: Optional[List[Capability]] = None,
|
||||
*,
|
||||
reuse_db: bool = False,
|
||||
) -> AsyncGenerator[Service[FullNode], None]:
|
||||
) -> AsyncGenerator[Service[FullNode, FullNodeAPI], None]:
|
||||
db_path = local_bt.root_path / f"{db_name}"
|
||||
if not reuse_db and db_path.exists():
|
||||
# TODO: remove (maybe) when fixed https://github.com/python/cpython/issues/97641
|
||||
@ -169,7 +176,7 @@ async def setup_full_node(
|
||||
|
||||
async def setup_crawler(
|
||||
bt: BlockTools,
|
||||
) -> AsyncGenerator[Service[Crawler], None]:
|
||||
) -> AsyncGenerator[Service[Crawler, CrawlerAPI], None]:
|
||||
config = bt.config
|
||||
service_config = config["seeder"]
|
||||
service_config["selected_network"] = "testnet0"
|
||||
@ -205,7 +212,7 @@ async def setup_wallet_node(
|
||||
introducer_port: Optional[uint16] = None,
|
||||
key_seed: Optional[bytes] = None,
|
||||
initial_num_public_keys: int = 5,
|
||||
) -> AsyncGenerator[Service[WalletNode], None]:
|
||||
) -> AsyncGenerator[Service[WalletNode, WalletNodeAPI], None]:
|
||||
with TempKeyring(populate=True) as keychain:
|
||||
config = local_bt.config
|
||||
service_config = config["wallet"]
|
||||
@ -275,7 +282,7 @@ async def setup_harvester(
|
||||
farmer_peer: Optional[UnresolvedPeerInfo],
|
||||
consensus_constants: ConsensusConstants,
|
||||
start_service: bool = True,
|
||||
) -> AsyncGenerator[Service[Harvester], None]:
|
||||
) -> AsyncGenerator[Service[Harvester, HarvesterAPI], None]:
|
||||
with create_lock_and_load_config(b_tools.root_path / "config" / "ssl" / "ca", root_path) as config:
|
||||
config["logging"]["log_stdout"] = True
|
||||
config["selected_network"] = "testnet0"
|
||||
@ -309,7 +316,7 @@ async def setup_farmer(
|
||||
full_node_port: Optional[uint16] = None,
|
||||
start_service: bool = True,
|
||||
port: uint16 = uint16(0),
|
||||
) -> AsyncGenerator[Service[Farmer], None]:
|
||||
) -> AsyncGenerator[Service[Farmer, FarmerAPI], None]:
|
||||
with create_lock_and_load_config(b_tools.root_path / "config" / "ssl" / "ca", root_path) as root_config:
|
||||
root_config["logging"]["log_stdout"] = True
|
||||
root_config["selected_network"] = "testnet0"
|
||||
@ -348,7 +355,7 @@ async def setup_farmer(
|
||||
await service.wait_closed()
|
||||
|
||||
|
||||
async def setup_introducer(bt: BlockTools, port: int) -> AsyncGenerator[Service[Introducer], None]:
|
||||
async def setup_introducer(bt: BlockTools, port: int) -> AsyncGenerator[Service[Introducer, IntroducerAPI], None]:
|
||||
service = create_introducer_service(
|
||||
bt.root_path,
|
||||
bt.config,
|
||||
@ -411,7 +418,7 @@ async def setup_timelord(
|
||||
consensus_constants: ConsensusConstants,
|
||||
b_tools: BlockTools,
|
||||
vdf_port: uint16 = uint16(0),
|
||||
) -> AsyncGenerator[Service[Timelord], None]:
|
||||
) -> AsyncGenerator[Service[Timelord, TimelordAPI], None]:
|
||||
config = b_tools.config
|
||||
service_config = config["timelord"]
|
||||
service_config["full_node_peer"]["port"] = full_node_port
|
||||
|
@ -5,6 +5,7 @@ from typing import Dict, List
|
||||
|
||||
from chia.rpc.full_node_rpc_api import FullNodeRpcApi
|
||||
from chia.rpc.rpc_server import Endpoint, EndpointResult
|
||||
from chia.simulator.full_node_simulator import FullNodeSimulator
|
||||
from chia.simulator.simulator_protocol import FarmNewBlockProtocol, GetAllCoinsProtocol, ReorgProtocol
|
||||
from chia.types.blockchain_format.sized_bytes import bytes32
|
||||
from chia.types.coin_record import CoinRecord
|
||||
@ -14,6 +15,11 @@ from chia.util.ints import uint32
|
||||
|
||||
|
||||
class SimulatorFullNodeRpcApi(FullNodeRpcApi):
|
||||
@property
|
||||
def simulator_api(self) -> FullNodeSimulator:
|
||||
assert isinstance(self.service.server.api, FullNodeSimulator)
|
||||
return self.service.server.api
|
||||
|
||||
def get_routes(self) -> Dict[str, Endpoint]:
|
||||
routes = super().get_routes()
|
||||
routes["/get_all_blocks"] = self.get_all_blocks
|
||||
@ -28,7 +34,7 @@ class SimulatorFullNodeRpcApi(FullNodeRpcApi):
|
||||
return routes
|
||||
|
||||
async def get_all_blocks(self, _request: Dict[str, object]) -> EndpointResult:
|
||||
all_blocks: List[FullBlock] = await self.service.server.api.get_all_full_blocks()
|
||||
all_blocks: List[FullBlock] = await self.simulator_api.get_all_full_blocks()
|
||||
return {"blocks": [block.to_json_dict() for block in all_blocks]}
|
||||
|
||||
async def farm_block(self, _request: Dict[str, object]) -> EndpointResult:
|
||||
@ -40,30 +46,30 @@ class SimulatorFullNodeRpcApi(FullNodeRpcApi):
|
||||
cur_height = self.service.blockchain.get_peak_height()
|
||||
if guarantee_tx_block:
|
||||
for i in range(blocks): # these can only be tx blocks
|
||||
await self.service.server.api.farm_new_transaction_block(req)
|
||||
await self.simulator_api.farm_new_transaction_block(req)
|
||||
else:
|
||||
for i in range(blocks): # these can either be full blocks or tx blocks
|
||||
await self.service.server.api.farm_new_block(req)
|
||||
await self.simulator_api.farm_new_block(req)
|
||||
return {"new_peak_height": (cur_height if cur_height is not None else 0) + blocks}
|
||||
|
||||
async def set_auto_farming(self, _request: Dict[str, object]) -> EndpointResult:
|
||||
auto_farm = bool(_request["auto_farm"])
|
||||
result = await self.service.server.api.update_autofarm_config(auto_farm)
|
||||
result = await self.simulator_api.update_autofarm_config(auto_farm)
|
||||
return {"auto_farm_enabled": result}
|
||||
|
||||
async def get_auto_farming(self, _request: Dict[str, object]) -> EndpointResult:
|
||||
return {"auto_farm_enabled": self.service.server.api.auto_farm}
|
||||
return {"auto_farm_enabled": self.simulator_api.auto_farm}
|
||||
|
||||
async def get_farming_ph(self, _request: Dict[str, object]) -> EndpointResult:
|
||||
return {"puzzle_hash": self.service.server.api.bt.farmer_ph.hex()}
|
||||
return {"puzzle_hash": self.simulator_api.bt.farmer_ph.hex()}
|
||||
|
||||
async def get_all_coins(self, _request: Dict[str, object]) -> EndpointResult:
|
||||
p_request = GetAllCoinsProtocol(bool((_request.get("include_spent_coins", False))))
|
||||
result: List[CoinRecord] = await self.service.server.api.get_all_coins(p_request)
|
||||
result: List[CoinRecord] = await self.simulator_api.get_all_coins(p_request)
|
||||
return {"coin_records": [coin_record.to_json_dict() for coin_record in result]}
|
||||
|
||||
async def get_all_puzzle_hashes(self, _request: Dict[str, object]) -> EndpointResult:
|
||||
result = await self.service.server.api.get_all_puzzle_hashes()
|
||||
result = await self.simulator_api.get_all_puzzle_hashes()
|
||||
return {
|
||||
"puzzle_hashes": {puzzle_hash.hex(): (amount, num_tx) for (puzzle_hash, (amount, num_tx)) in result.items()}
|
||||
}
|
||||
@ -76,7 +82,7 @@ class SimulatorFullNodeRpcApi(FullNodeRpcApi):
|
||||
raise ValueError("No blocks to revert")
|
||||
new_height = (height - blocks) if not all_blocks else 1
|
||||
assert new_height >= 1
|
||||
await self.service.server.api.revert_block_height(new_height)
|
||||
await self.simulator_api.revert_block_height(uint32(new_height))
|
||||
return {"new_peak_height": new_height}
|
||||
|
||||
async def reorg_blocks(self, _request: Dict[str, object]) -> EndpointResult:
|
||||
@ -91,8 +97,6 @@ class SimulatorFullNodeRpcApi(FullNodeRpcApi):
|
||||
fork_height = (cur_height - fork_blocks) if not all_blocks else 1
|
||||
new_height = cur_height + new_blocks # any number works as long as its not 0
|
||||
assert fork_height >= 1 and new_height - 1 >= cur_height
|
||||
request = ReorgProtocol(
|
||||
uint32(fork_height), uint32(new_height), self.service.server.api.bt.farmer_ph, random_seed
|
||||
)
|
||||
await self.service.server.api.reorg_from_index_to_new_index(request)
|
||||
request = ReorgProtocol(uint32(fork_height), uint32(new_height), self.simulator_api.bt.farmer_ph, random_seed)
|
||||
await self.simulator_api.reorg_from_index_to_new_index(request)
|
||||
return {"new_peak_height": new_height}
|
||||
|
@ -7,6 +7,7 @@ from pathlib import Path
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
from chia.full_node.full_node import FullNode
|
||||
from chia.full_node.full_node_api import FullNodeAPI
|
||||
from chia.server.outbound_message import NodeType
|
||||
from chia.server.start_service import Service, async_run
|
||||
from chia.simulator.block_tools import BlockTools, test_constants
|
||||
@ -34,7 +35,7 @@ def create_full_node_simulator_service(
|
||||
bt: BlockTools,
|
||||
connect_to_daemon: bool = True,
|
||||
override_capabilities: List[Tuple[uint16, str]] = None,
|
||||
) -> Service[FullNode]:
|
||||
) -> Service[FullNode, FullNodeAPI]:
|
||||
service_config = config[SERVICE_NAME]
|
||||
constants = bt.constants
|
||||
|
||||
|
@ -16,11 +16,16 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TimelordAPI:
|
||||
log: logging.Logger
|
||||
timelord: Timelord
|
||||
|
||||
def __init__(self, timelord) -> None:
|
||||
self.log = logging.getLogger(__name__)
|
||||
self.timelord = timelord
|
||||
|
||||
def ready(self) -> bool:
|
||||
return True
|
||||
|
||||
def _set_state_changed_callback(self, callback: StateChangedProtocol) -> None:
|
||||
self.timelord.state_changed_callback = callback
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from chia.protocols import full_node_protocol, introducer_protocol, wallet_protocol
|
||||
from chia.server.outbound_message import NodeType
|
||||
from chia.server.ws_connection import WSChiaConnection
|
||||
@ -10,17 +12,14 @@ from chia.wallet.wallet_node import PeerPeak, WalletNode
|
||||
|
||||
|
||||
class WalletNodeAPI:
|
||||
log: logging.Logger
|
||||
wallet_node: WalletNode
|
||||
|
||||
def __init__(self, wallet_node) -> None:
|
||||
self.log = logging.getLogger(__name__)
|
||||
self.wallet_node = wallet_node
|
||||
|
||||
@property
|
||||
def log(self):
|
||||
return self.wallet_node.log
|
||||
|
||||
@property
|
||||
def api_ready(self):
|
||||
def ready(self) -> bool:
|
||||
return self.wallet_node.logged_in
|
||||
|
||||
@api_request(peer_required=True)
|
||||
|
@ -25,6 +25,7 @@ from chia.full_node.full_node_api import FullNodeAPI
|
||||
from chia.protocols import full_node_protocol
|
||||
from chia.rpc.wallet_rpc_client import WalletRpcClient
|
||||
from chia.seeder.crawler import Crawler
|
||||
from chia.seeder.crawler_api import CrawlerAPI
|
||||
from chia.server.server import ChiaServer
|
||||
from chia.server.start_service import Service
|
||||
from chia.simulator.full_node_simulator import FullNodeSimulator
|
||||
@ -48,6 +49,7 @@ from chia.util.task_timing import main as task_instrumentation_main
|
||||
from chia.util.task_timing import start_task_instrumentation, stop_task_instrumentation
|
||||
from chia.wallet.wallet import Wallet
|
||||
from chia.wallet.wallet_node import WalletNode
|
||||
from chia.wallet.wallet_node_api import WalletNodeAPI
|
||||
from tests.core.data_layer.util import ChiaRoot
|
||||
from tests.core.node_height import node_height_at_least
|
||||
from tests.simulation.test_simulation import test_constants_modified
|
||||
@ -378,7 +380,7 @@ async def two_wallet_nodes(request):
|
||||
|
||||
@pytest_asyncio.fixture(scope="function")
|
||||
async def two_wallet_nodes_services() -> AsyncIterator[
|
||||
Tuple[List[Service[FullNode]], List[Service[WalletNode]], BlockTools]
|
||||
Tuple[List[Service[FullNode, FullNodeSimulator]], List[Service[WalletNode, WalletNodeAPI]], BlockTools]
|
||||
]:
|
||||
async for _ in setup_simulators_and_wallets_service(1, 2, {}):
|
||||
yield _
|
||||
@ -821,7 +823,7 @@ async def timelord_service(bt):
|
||||
|
||||
|
||||
@pytest_asyncio.fixture(scope="function")
|
||||
async def crawler_service(bt: BlockTools) -> AsyncIterator[Service[Crawler]]:
|
||||
async def crawler_service(bt: BlockTools) -> AsyncIterator[Service[Crawler, CrawlerAPI]]:
|
||||
async for service in setup_crawler(bt):
|
||||
yield service
|
||||
|
||||
|
@ -33,6 +33,7 @@ from chia.wallet.trading.offer import Offer as TradingOffer
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.wallet import Wallet
|
||||
from chia.wallet.wallet_node import WalletNode
|
||||
from chia.wallet.wallet_node_api import WalletNodeAPI
|
||||
|
||||
pytestmark = pytest.mark.data_layer
|
||||
nodes = Tuple[WalletNode, FullNodeSimulator]
|
||||
@ -43,7 +44,10 @@ two_wallets_with_port = Tuple[Tuple[wallet_and_port_tuple, wallet_and_port_tuple
|
||||
|
||||
@contextlib.asynccontextmanager
|
||||
async def init_data_layer(
|
||||
wallet_rpc_port: uint16, bt: BlockTools, db_path: Path, wallet_service: Optional[Service[WalletNode]] = None
|
||||
wallet_rpc_port: uint16,
|
||||
bt: BlockTools,
|
||||
db_path: Path,
|
||||
wallet_service: Optional[Service[WalletNode, WalletNodeAPI]] = None,
|
||||
) -> AsyncIterator[DataLayer]:
|
||||
config = bt.config
|
||||
config["data_layer"]["wallet_peer"]["port"] = int(wallet_rpc_port)
|
||||
|
@ -5,7 +5,7 @@ import dataclasses
|
||||
import random
|
||||
import time
|
||||
from secrets import token_bytes
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
from typing import Dict, List, Optional, Tuple, cast
|
||||
|
||||
import pytest
|
||||
from blspy import AugSchemeMPL, G2Element, PrivateKey
|
||||
@ -26,6 +26,7 @@ from chia.server.address_manager import AddressManager
|
||||
from chia.server.outbound_message import Message, NodeType
|
||||
from chia.server.server import ChiaServer
|
||||
from chia.simulator.block_tools import BlockTools, create_block_tools_async, get_signage_point
|
||||
from chia.simulator.full_node_simulator import FullNodeSimulator
|
||||
from chia.simulator.keyring import TempKeyring
|
||||
from chia.simulator.setup_services import setup_full_node
|
||||
from chia.simulator.simulator_protocol import FarmNewBlockProtocol
|
||||
@ -2018,10 +2019,12 @@ async def test_node_start_with_existing_blocks(db_version: int) -> None:
|
||||
db_version=db_version,
|
||||
reuse_db=True,
|
||||
):
|
||||
await service._api.farm_blocks_to_puzzlehash(count=blocks_per_cycle)
|
||||
simulator_api = cast(FullNodeSimulator, service._api)
|
||||
await simulator_api.farm_blocks_to_puzzlehash(count=blocks_per_cycle)
|
||||
|
||||
expected_height += blocks_per_cycle
|
||||
block_record = service._api.full_node._blockchain.get_peak()
|
||||
assert simulator_api.full_node._blockchain is not None
|
||||
block_record = simulator_api.full_node._blockchain.get_peak()
|
||||
|
||||
assert block_record is not None, f"block_record is None on cycle {cycle + 1}"
|
||||
assert block_record.height == expected_height, f"wrong height on cycle {cycle + 1}"
|
||||
|
@ -1,18 +1,23 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Callable, Tuple
|
||||
import logging
|
||||
from typing import Callable, Tuple, cast
|
||||
|
||||
import pytest
|
||||
from packaging.version import Version
|
||||
|
||||
from chia.cmds.init_funcs import chia_full_version_str
|
||||
from chia.full_node.full_node_api import FullNodeAPI
|
||||
from chia.protocols.protocol_message_types import ProtocolMessageTypes
|
||||
from chia.protocols.shared_protocol import protocol_version
|
||||
from chia.protocols.wallet_protocol import RejectHeaderRequest
|
||||
from chia.server.outbound_message import make_msg
|
||||
from chia.server.server import ChiaServer
|
||||
from chia.simulator.block_tools import BlockTools
|
||||
from chia.simulator.setup_nodes import SimulatorsAndWalletsServices
|
||||
from chia.simulator.time_out_assert import time_out_assert
|
||||
from chia.types.peer_info import PeerInfo
|
||||
from chia.util.ints import uint16
|
||||
from chia.util.ints import uint16, uint32
|
||||
from tests.connection_utils import connect_and_get_peer
|
||||
|
||||
|
||||
@ -48,10 +53,38 @@ async def test_connection_versions(
|
||||
[full_node_service], [wallet_service], _ = one_wallet_and_one_simulator_services
|
||||
wallet_node = wallet_service._node
|
||||
full_node = full_node_service._node
|
||||
await wallet_node.server.start_client(PeerInfo(self_hostname, uint16(full_node_service._api.server._port)), None)
|
||||
await wallet_node.server.start_client(
|
||||
PeerInfo(self_hostname, uint16(cast(FullNodeAPI, full_node_service._api).server._port)), None
|
||||
)
|
||||
outgoing_connection = wallet_node.server.all_connections[full_node.server.node_id]
|
||||
incoming_connection = full_node.server.all_connections[wallet_node.server.node_id]
|
||||
for connection in [outgoing_connection, incoming_connection]:
|
||||
assert connection.protocol_version == Version(protocol_version)
|
||||
assert connection.version == Version(chia_full_version_str())
|
||||
assert connection.get_version() == chia_full_version_str()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_api_not_ready(
|
||||
self_hostname: str,
|
||||
one_wallet_and_one_simulator_services: SimulatorsAndWalletsServices,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
[full_node_service], [wallet_service], _ = one_wallet_and_one_simulator_services
|
||||
wallet_node = wallet_service._node
|
||||
full_node = full_node_service._node
|
||||
await wallet_node.server.start_client(
|
||||
PeerInfo(self_hostname, uint16(cast(FullNodeAPI, full_node_service._api).server._port)), None
|
||||
)
|
||||
wallet_node.log_out()
|
||||
assert not wallet_service._api.ready()
|
||||
connection = full_node.server.all_connections[wallet_node.server.node_id]
|
||||
|
||||
def request_ignored() -> bool:
|
||||
return "API not ready, ignore request: {'data': '0x00000000', 'id': None, 'type': 53}" in caplog.text
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
assert await connection.send_message(
|
||||
make_msg(ProtocolMessageTypes.reject_header_request, RejectHeaderRequest(uint32(0)))
|
||||
)
|
||||
await time_out_assert(10, request_ignored)
|
||||
|
@ -6,23 +6,25 @@ from typing import cast
|
||||
import pytest
|
||||
|
||||
from chia.full_node.full_node_api import FullNodeAPI
|
||||
from chia.protocols.full_node_protocol import NewPeak
|
||||
from chia.protocols.protocol_message_types import ProtocolMessageTypes
|
||||
from chia.protocols.wallet_protocol import RequestChildren
|
||||
from chia.seeder.crawler import Crawler
|
||||
from chia.seeder.crawler_api import CrawlerAPI
|
||||
from chia.server.outbound_message import make_msg
|
||||
from chia.server.start_service import Service
|
||||
from chia.simulator.setup_nodes import SimulatorsAndWalletsServices
|
||||
from chia.simulator.time_out_assert import time_out_assert
|
||||
from chia.types.blockchain_format.sized_bytes import bytes32
|
||||
from chia.types.peer_info import PeerInfo
|
||||
from chia.util.ints import uint16
|
||||
from chia.util.ints import uint16, uint32, uint128
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unknown_messages(
|
||||
self_hostname: str,
|
||||
one_node: SimulatorsAndWalletsServices,
|
||||
crawler_service: Service[Crawler],
|
||||
crawler_service: Service[Crawler, CrawlerAPI],
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
[full_node_service], _, _ = one_node
|
||||
@ -40,3 +42,29 @@ async def test_unknown_messages(
|
||||
msg = make_msg(ProtocolMessageTypes.request_children, RequestChildren(bytes32(b"\0" * 32)))
|
||||
assert await connection.send_message(msg)
|
||||
await time_out_assert(10, receiving_failed)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_valid_message(
|
||||
self_hostname: str,
|
||||
one_node: SimulatorsAndWalletsServices,
|
||||
crawler_service: Service[Crawler, CrawlerAPI],
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
[full_node_service], _, _ = one_node
|
||||
crawler = crawler_service._node
|
||||
full_node = full_node_service._node
|
||||
assert await crawler.server.start_client(
|
||||
PeerInfo(self_hostname, uint16(cast(FullNodeAPI, full_node_service._api).server._port)), None
|
||||
)
|
||||
connection = full_node.server.all_connections[crawler.server.node_id]
|
||||
|
||||
def peer_added() -> bool:
|
||||
return crawler.server.all_connections[full_node.server.node_id].get_peer_logging() in crawler.with_peak
|
||||
|
||||
msg = make_msg(
|
||||
ProtocolMessageTypes.new_peak,
|
||||
NewPeak(bytes32(b"\0" * 32), uint32(2), uint128(1), uint32(1), bytes32(b"\1" * 32)),
|
||||
)
|
||||
assert await connection.send_message(msg)
|
||||
await time_out_assert(10, peer_added)
|
||||
|
@ -16,7 +16,9 @@ import pytest_asyncio
|
||||
|
||||
from chia.consensus.coinbase import create_puzzlehash_for_pk
|
||||
from chia.farmer.farmer import Farmer
|
||||
from chia.farmer.farmer_api import FarmerAPI
|
||||
from chia.harvester.harvester import Harvester
|
||||
from chia.harvester.harvester_api import HarvesterAPI
|
||||
from chia.plot_sync.receiver import Receiver
|
||||
from chia.plotting.util import add_plot_directory
|
||||
from chia.protocols import farmer_protocol
|
||||
@ -64,12 +66,15 @@ async def wait_for_synced_receiver(farmer: Farmer, harvester_id: bytes32) -> Non
|
||||
await time_out_assert(30, wait)
|
||||
|
||||
|
||||
HarvesterFarmerEnvironment = Tuple[Service[Farmer], FarmerRpcClient, Service[Harvester], HarvesterRpcClient, BlockTools]
|
||||
HarvesterFarmerEnvironment = Tuple[
|
||||
Service[Farmer, FarmerAPI], FarmerRpcClient, Service[Harvester, HarvesterAPI], HarvesterRpcClient, BlockTools
|
||||
]
|
||||
|
||||
|
||||
@pytest_asyncio.fixture(scope="function")
|
||||
async def harvester_farmer_environment(
|
||||
farmer_one_harvester: Tuple[List[Service[Harvester]], Service[Farmer], BlockTools], self_hostname: str
|
||||
farmer_one_harvester: Tuple[List[Service[Harvester, HarvesterAPI]], Service[Farmer, FarmerAPI], BlockTools],
|
||||
self_hostname: str,
|
||||
) -> AsyncIterator[HarvesterFarmerEnvironment]:
|
||||
harvesters, farmer_service, bt = farmer_one_harvester
|
||||
harvester_service = harvesters[0]
|
||||
|
@ -6,7 +6,9 @@ from typing import List, Tuple
|
||||
import pytest
|
||||
|
||||
from chia.farmer.farmer import Farmer
|
||||
from chia.farmer.farmer_api import FarmerAPI
|
||||
from chia.harvester.harvester import Harvester
|
||||
from chia.harvester.harvester_api import HarvesterAPI
|
||||
from chia.server.start_service import Service
|
||||
from chia.simulator.block_tools import BlockTools
|
||||
from chia.simulator.time_out_assert import time_out_assert
|
||||
@ -20,7 +22,9 @@ def farmer_is_started(farmer: Farmer) -> bool:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_start_with_empty_keychain(
|
||||
farmer_one_harvester_not_started: Tuple[List[Service[Harvester]], Service[Farmer], BlockTools]
|
||||
farmer_one_harvester_not_started: Tuple[
|
||||
List[Service[Harvester, HarvesterAPI]], Service[Farmer, FarmerAPI], BlockTools
|
||||
]
|
||||
) -> None:
|
||||
_, farmer_service, bt = farmer_one_harvester_not_started
|
||||
farmer: Farmer = farmer_service._node
|
||||
@ -45,7 +49,9 @@ async def test_start_with_empty_keychain(
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_harvester_handshake(
|
||||
farmer_one_harvester_not_started: Tuple[List[Service[Harvester]], Service[Farmer], BlockTools]
|
||||
farmer_one_harvester_not_started: Tuple[
|
||||
List[Service[Harvester, HarvesterAPI]], Service[Farmer, FarmerAPI], BlockTools
|
||||
]
|
||||
) -> None:
|
||||
harvesters, farmer_service, bt = farmer_one_harvester_not_started
|
||||
harvester_service = harvesters[0]
|
||||
|
@ -11,6 +11,7 @@ from chia.rpc.full_node_rpc_api import FullNodeRpcApi
|
||||
from chia.rpc.full_node_rpc_client import FullNodeRpcClient
|
||||
from chia.server.start_service import Service
|
||||
from chia.simulator.block_tools import BlockTools
|
||||
from chia.simulator.full_node_simulator import FullNodeSimulator
|
||||
from chia.simulator.simulator_protocol import FarmNewBlockProtocol
|
||||
from chia.simulator.wallet_tools import WalletTool
|
||||
from chia.types.blockchain_format.coin import Coin
|
||||
@ -18,16 +19,19 @@ from chia.types.blockchain_format.sized_bytes import bytes32
|
||||
from chia.types.spend_bundle import SpendBundle
|
||||
from chia.util.ints import uint64
|
||||
from chia.wallet.wallet_node import WalletNode
|
||||
from chia.wallet.wallet_node_api import WalletNodeAPI
|
||||
|
||||
|
||||
@pytest_asyncio.fixture(scope="function")
|
||||
async def setup_node_and_rpc(
|
||||
two_wallet_nodes_services: Tuple[List[Service[FullNode]], List[Service[WalletNode]], BlockTools],
|
||||
two_wallet_nodes_services: Tuple[
|
||||
List[Service[FullNode, FullNodeSimulator]], List[Service[WalletNode, WalletNodeAPI]], BlockTools
|
||||
],
|
||||
) -> Tuple[FullNodeRpcClient, FullNodeRpcApi]:
|
||||
full_nodes, wallets, bt = two_wallet_nodes_services
|
||||
wallet = wallets[0]._node.wallet_state_manager.main_wallet
|
||||
full_node_apis = [full_node_service._api for full_node_service in full_nodes]
|
||||
full_node_api = full_node_apis[0]
|
||||
full_node_api: FullNodeSimulator = full_node_apis[0]
|
||||
full_node_service_1 = full_nodes[0]
|
||||
assert full_node_service_1.rpc_server is not None
|
||||
client = await FullNodeRpcClient.create(
|
||||
@ -48,11 +52,11 @@ async def setup_node_and_rpc(
|
||||
|
||||
@pytest_asyncio.fixture(scope="function")
|
||||
async def one_node_no_blocks(
|
||||
one_node: Tuple[List[Service[FullNode]], List[Service[WalletNode]], BlockTools]
|
||||
one_node: Tuple[List[Service[FullNode, FullNodeSimulator]], List[Service[WalletNode, WalletNodeAPI]], BlockTools]
|
||||
) -> Tuple[FullNodeRpcClient, FullNodeRpcApi]:
|
||||
full_nodes, wallets, bt = one_node
|
||||
full_node_apis = [full_node_service._api for full_node_service in full_nodes]
|
||||
full_node_api = full_node_apis[0]
|
||||
full_node_api: FullNodeSimulator = full_node_apis[0]
|
||||
full_node_service_1 = full_nodes[0]
|
||||
assert full_node_service_1.rpc_server is not None
|
||||
client = await FullNodeRpcClient.create(
|
||||
|
@ -12,7 +12,9 @@ import pytest_asyncio
|
||||
from blspy import G1Element
|
||||
|
||||
from chia.farmer.farmer import Farmer
|
||||
from chia.farmer.farmer_api import FarmerAPI
|
||||
from chia.harvester.harvester import Harvester
|
||||
from chia.harvester.harvester_api import HarvesterAPI
|
||||
from chia.plot_sync.delta import Delta, PathListDelta, PlotListDelta
|
||||
from chia.plot_sync.receiver import Receiver
|
||||
from chia.plot_sync.sender import Sender
|
||||
@ -108,8 +110,8 @@ class ExpectedResult:
|
||||
@dataclass
|
||||
class Environment:
|
||||
root_path: Path
|
||||
harvester_services: List[Service[Harvester]]
|
||||
farmer_service: Service[Farmer]
|
||||
harvester_services: List[Service[Harvester, HarvesterAPI]]
|
||||
farmer_service: Service[Farmer, FarmerAPI]
|
||||
harvesters: List[Harvester]
|
||||
farmer: Farmer
|
||||
dir_1: Directory
|
||||
@ -272,7 +274,10 @@ class Environment:
|
||||
|
||||
@pytest_asyncio.fixture(scope="function")
|
||||
async def environment(
|
||||
tmp_path: Path, farmer_two_harvester_not_started: Tuple[List[Service[Harvester]], Service[Farmer], BlockTools]
|
||||
tmp_path: Path,
|
||||
farmer_two_harvester_not_started: Tuple[
|
||||
List[Service[Harvester, HarvesterAPI]], Service[Farmer, FarmerAPI], BlockTools
|
||||
],
|
||||
) -> Environment:
|
||||
def new_test_dir(name: str, plot_list: List[Path]) -> Directory:
|
||||
return Directory(tmp_path / "plots" / name, plot_list)
|
||||
@ -558,7 +563,7 @@ async def test_farmer_restart(environment: Environment) -> None:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sync_start_and_disconnect_while_sync_is_active(
|
||||
farmer_one_harvester: Tuple[List[Service[Harvester]], Service[Farmer], BlockTools]
|
||||
farmer_one_harvester: Tuple[List[Service[Harvester, HarvesterAPI]], Service[Farmer, FarmerAPI], BlockTools]
|
||||
) -> None:
|
||||
harvesters, farmer_service, _ = farmer_one_harvester
|
||||
harvester_service = harvesters[0]
|
||||
|
@ -14,7 +14,9 @@ import pytest
|
||||
from blspy import G1Element
|
||||
|
||||
from chia.farmer.farmer import Farmer
|
||||
from chia.farmer.farmer_api import FarmerAPI
|
||||
from chia.harvester.harvester import Harvester
|
||||
from chia.harvester.harvester_api import HarvesterAPI
|
||||
from chia.plot_sync.receiver import Receiver
|
||||
from chia.plot_sync.sender import Sender
|
||||
from chia.plot_sync.util import Constants
|
||||
@ -239,8 +241,8 @@ async def _testable_process(
|
||||
|
||||
|
||||
async def create_test_runner(
|
||||
harvester_services: List[Service[Harvester]],
|
||||
farmer_service: Service[Farmer],
|
||||
harvester_services: List[Service[Harvester, HarvesterAPI]],
|
||||
farmer_service: Service[Farmer, FarmerAPI],
|
||||
event_loop: asyncio.events.AbstractEventLoop,
|
||||
) -> TestRunner:
|
||||
await farmer_service.start()
|
||||
@ -288,7 +290,9 @@ def create_example_plots(count: int) -> List[PlotInfo]:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sync_simulated(
|
||||
farmer_three_harvester_not_started: Tuple[List[Service[Harvester]], Service[Farmer], BlockTools],
|
||||
farmer_three_harvester_not_started: Tuple[
|
||||
List[Service[Harvester, HarvesterAPI]], Service[Farmer, FarmerAPI], BlockTools
|
||||
],
|
||||
event_loop: asyncio.events.AbstractEventLoop,
|
||||
) -> None:
|
||||
harvester_services, farmer_service, _ = farmer_three_harvester_not_started
|
||||
@ -367,7 +371,9 @@ async def test_sync_simulated(
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_farmer_error_simulation(
|
||||
farmer_one_harvester_not_started: Tuple[List[Service[Harvester]], Service[Farmer], BlockTools],
|
||||
farmer_one_harvester_not_started: Tuple[
|
||||
List[Service[Harvester, HarvesterAPI]], Service[Farmer, FarmerAPI], BlockTools
|
||||
],
|
||||
event_loop: asyncio.events.AbstractEventLoop,
|
||||
simulate_error: ErrorSimulation,
|
||||
) -> None:
|
||||
@ -392,7 +398,9 @@ async def test_farmer_error_simulation(
|
||||
@pytest.mark.parametrize("simulate_error", [ErrorSimulation.NonRecoverableError, ErrorSimulation.NotConnected])
|
||||
@pytest.mark.asyncio
|
||||
async def test_sync_reset_cases(
|
||||
farmer_one_harvester_not_started: Tuple[List[Service[Harvester]], Service[Farmer], BlockTools],
|
||||
farmer_one_harvester_not_started: Tuple[
|
||||
List[Service[Harvester, HarvesterAPI]], Service[Farmer, FarmerAPI], BlockTools
|
||||
],
|
||||
event_loop: asyncio.events.AbstractEventLoop,
|
||||
simulate_error: ErrorSimulation,
|
||||
) -> None:
|
||||
|
@ -6,7 +6,9 @@ from secrets import token_bytes
|
||||
from typing import Optional
|
||||
|
||||
from chia.farmer.farmer import Farmer
|
||||
from chia.farmer.farmer_api import FarmerAPI
|
||||
from chia.harvester.harvester import Harvester
|
||||
from chia.harvester.harvester_api import HarvesterAPI
|
||||
from chia.plot_sync.sender import Sender
|
||||
from chia.protocols.harvester_protocol import PlotSyncIdentifier
|
||||
from chia.server.outbound_message import Message, NodeType
|
||||
@ -36,7 +38,9 @@ def plot_sync_identifier(current_sync_id: uint64, message_id: uint64) -> PlotSyn
|
||||
return PlotSyncIdentifier(uint64(int(time.time())), current_sync_id, message_id)
|
||||
|
||||
|
||||
async def start_harvester_service(harvester_service: Service[Harvester], farmer_service: Service[Farmer]) -> Harvester:
|
||||
async def start_harvester_service(
|
||||
harvester_service: Service[Harvester, HarvesterAPI], farmer_service: Service[Farmer, FarmerAPI]
|
||||
) -> Harvester:
|
||||
# Set the `last_refresh_time` of the plot manager to avoid initial plot loading
|
||||
harvester: Harvester = harvester_service._node
|
||||
harvester.plot_manager.last_refresh_time = time.time()
|
||||
|
@ -36,6 +36,7 @@ from chia.wallet.derive_keys import find_authentication_sk, find_owner_sk
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
from chia.wallet.wallet_node import WalletNode
|
||||
from chia.wallet.wallet_node_api import WalletNodeAPI
|
||||
|
||||
# TODO: Compare deducted fees in all tests against reported total_fee
|
||||
|
||||
@ -136,7 +137,9 @@ Setup = Tuple[FullNodeSimulator, WalletNode, bytes32, int, WalletRpcClient]
|
||||
|
||||
@pytest_asyncio.fixture(scope="function")
|
||||
async def setup(
|
||||
one_wallet_and_one_simulator_services: Tuple[List[Service[FullNode]], List[Service[WalletNode]], BlockTools],
|
||||
one_wallet_and_one_simulator_services: Tuple[
|
||||
List[Service[FullNode, FullNodeSimulator]], List[Service[WalletNode, WalletNodeAPI]], BlockTools
|
||||
],
|
||||
trusted: bool,
|
||||
self_hostname: str,
|
||||
) -> AsyncIterator[Setup]:
|
||||
|
Loading…
Reference in New Issue
Block a user