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:
dustinface 2023-06-14 03:12:25 +02:00 committed by GitHub
parent 46a244ae09
commit 49140b2b3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 288 additions and 112 deletions

View File

@ -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

View File

@ -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

View File

@ -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])

View File

@ -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

View File

@ -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

View File

@ -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(

View File

@ -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(

View 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:
...

View File

@ -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,

View File

@ -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:

View File

@ -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")

View File

@ -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(

View File

@ -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"]]

View File

@ -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:

View File

@ -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,

View File

@ -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 = {

View File

@ -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"]]

View File

@ -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:

View File

@ -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)

View File

@ -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

View File

@ -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}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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}"

View File

@ -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)

View File

@ -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)

View File

@ -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]

View File

@ -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]

View File

@ -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(

View File

@ -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]

View File

@ -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:

View File

@ -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()

View File

@ -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]: