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