async def test_beacon_node_and_validator_client_can_talk( autojump_clock, node_key, eth2_config, chain_config, database_dir, chain_class, get_trio_time, ): client_id = construct_trinity_client_identifier() validator_api_port = 0 node = BeaconNode( node_key, eth2_config, chain_config, database_dir, chain_class, validator_api_port, client_id, get_trio_time, ) a_short_timeout = 5 with trio.move_on_after(a_short_timeout): async with trio.open_nursery() as nursery: await nursery.start(node.run) api_client = BeaconNodeClient( chain_config.genesis_time, f"http://localhost:{node.validator_api_port}", eth2_config.SECONDS_PER_SLOT, ) await api_client.load_client_version() assert api_client.client_version == client_id
async def test_beacon_node_can_count_slots( autojump_clock, node_key, eth2_config, chain_config, database_dir, chain_class, get_trio_time, ): validator_api_port = 0 client_id = construct_trinity_client_identifier() node = BeaconNode( node_key, eth2_config, chain_config, database_dir, chain_class, validator_api_port, client_id, get_trio_time, ) some_slots = 10 a_future_slot = node.current_tick.slot + some_slots seconds = some_slots * eth2_config.SECONDS_PER_SLOT with trio.move_on_after(seconds): await node.run() assert node.current_tick.slot == a_future_slot
def __init__( self, chain: BaseBeaconChain, event_bus: EndpointAPI, genesis_time: int ): self._chain = chain self._event_bus = event_bus self._genesis_time = genesis_time self._client_identifier = construct_trinity_client_identifier()
def display_launch_logs(trinity_config: TrinityConfig) -> None: logger = logging.getLogger('trinity') logger.info(TRINITY_HEADER) logger.info("Started main process (pid=%d)", os.getpid()) logger.info(construct_trinity_client_identifier()) logger.info("Trinity DEBUG log file is created at %s", str(trinity_config.logfile_path))
def main_entry_trio( app_identifier: str, component_types: Tuple[Type[BaseComponentAPI], ...], sub_configs: Sequence[Type[BaseAppConfig]], ) -> None: boot_info, _ = construct_boot_info(app_identifier, component_types, sub_configs) args = boot_info.args trinity_config = boot_info.trinity_config # Components can provide a subcommand with a `func` which does then control # the entire process from here. if hasattr(args, "func"): args.func(args, trinity_config) return _initialize_beacon_filesystem(boot_info) logger = logging.getLogger("trinity") pid = os.getpid() identifier = construct_trinity_client_identifier() logger.info("Booted client with identifier: %s and process id %d", identifier, pid) runtime_component_types = tuple( component_cls for component_cls in component_types if issubclass(component_cls, TrioComponent)) trio.run(_run_trio_components_until_interrupt, runtime_component_types, boot_info) # NOTE: mypy bug that does not type this... it works in `./bootstrap.py` if trinity_config.trinity_tmp_root_dir: # type: ignore shutil.rmtree(trinity_config.trinity_root_dir)
def send_handshake(self) -> None: # TODO: move import out once this is in the trinity codebase from trinity._utils.version import construct_trinity_client_identifier data = dict( version=self.version, client_version_string=construct_trinity_client_identifier(), capabilities=self.peer.capabilities, listen_port=self.peer.listen_port, remote_pubkey=self.peer.privkey.public_key.to_bytes()) header, body = Hello(self.cmd_id_offset).encode(data) self.send(header, body)
def _make_peer_pool(self) -> BCCPeerPool: context = BeaconContext( chain_db=cast(BaseAsyncBeaconChainDB, self.chaindb), network_id=self.network_id, client_version_string=construct_trinity_client_identifier(), listen_port=self.port, ) return BCCPeerPool(privkey=self.privkey, max_peers=self.max_peers, context=context, token=self.cancel_token, event_bus=self.event_bus)
def get_node_info(self) -> EthstatsData: """Getter for data that should be sent once, on start-up.""" return { 'name': self.node_id, 'contact': self.node_contact, 'node': construct_trinity_client_identifier(), 'net': self.boot_info.trinity_config.network_id, 'port': self.boot_info.trinity_config.port, 'os': platform.system(), 'os_v': platform.release(), 'client': __version__, 'canUpdateHistory': False, }
def _make_peer_pool(self) -> LESPeerPool: context = ChainContext( headerdb=self.headerdb, network_id=self.network_id, vm_configuration=self.chain.vm_configuration, client_version_string=construct_trinity_client_identifier(), listen_port=self.port, ) return LESPeerPool(privkey=self.privkey, max_peers=self.max_peers, context=context, token=self.cancel_token, event_bus=self.event_bus)
def __init__( self, config: TrinityConfig, p2p_maddr: Multiaddr, orchestration_profile: str, bootstrap_nodes: Tuple[Multiaddr, ...] = (), preferred_nodes: Tuple[Multiaddr, ...] = (), ) -> None: super().__init__(config) self.p2p_maddr = p2p_maddr self.bootstrap_nodes = config.bootstrap_nodes self.preferred_nodes = config.preferred_nodes self.client_identifier = construct_trinity_client_identifier() self.orchestration_profile = orchestration_profile
async def nodeInfo(self) -> RpcNodeInfoResponse: response = await self.event_bus.request( GetProtocolCapabilitiesRequest(), TO_NETWORKING_BROADCAST_CONFIG) return { 'enode': format_enode(self.trinity_config), # TODO: get the external ip from the upnp service 'ip': "::", 'listenAddr': f"[::]:{self.trinity_config.port}", 'name': construct_trinity_client_identifier(), 'ports': { 'discovery': self.trinity_config.port, 'listener': self.trinity_config.port }, 'protocols': await self._generate_protocol_info(response.capabilities) }
def __init__( self, privkey: datatypes.PrivateKey, port: int, chain: AsyncChainAPI, chaindb: BaseAsyncChainDB, headerdb: BaseAsyncHeaderDB, base_db: AtomicDatabaseAPI, network_id: int, max_peers: int = DEFAULT_MAX_PEERS, bootstrap_nodes: Sequence[NodeAPI] = None, preferred_nodes: Sequence[NodeAPI] = None, event_bus: EndpointAPI = None, token: CancelToken = None, ) -> None: super().__init__(token) # cross process event bus self.event_bus = event_bus # setup parameters for the base devp2p handshake. self.p2p_handshake_params = DevP2PHandshakeParams( client_version_string=construct_trinity_client_identifier(), listen_port=port, version=DEVP2P_V5, ) # chain information self.chain = chain self.chaindb = chaindb self.headerdb = headerdb self.base_db = base_db # node information self.privkey = privkey self.port = port self.network_id = network_id self.max_peers = max_peers self.bootstrap_nodes = bootstrap_nodes self.preferred_nodes = preferred_nodes if self.preferred_nodes is None and network_id in DEFAULT_PREFERRED_NODES: self.preferred_nodes = DEFAULT_PREFERRED_NODES[self.network_id] # child services self.peer_pool = self._make_peer_pool() if not bootstrap_nodes: self.logger.warning("Running with no bootstrap nodes")
def __init__( self, config: TrinityConfig, network_name: str, network_config: Eth2Config, p2p_maddr: Multiaddr, validator_api_port: int, bootstrap_nodes: Tuple[Multiaddr, ...] = (), preferred_nodes: Tuple[Multiaddr, ...] = (), genesis_state_ssz: Optional[Path] = None, ) -> None: super().__init__(config) self.p2p_maddr = p2p_maddr self.network_name = network_name self.network_config = network_config self.validator_api_port = validator_api_port self.bootstrap_nodes = bootstrap_nodes self.preferred_nodes = preferred_nodes self.client_identifier = construct_trinity_client_identifier() self.genesis_state_ssz = genesis_state_ssz
def __init__( self, privkey: datatypes.PrivateKey, port: int, chain: AsyncChainAPI, chaindb: BaseAsyncChainDB, headerdb: BaseAsyncHeaderDB, base_db: AtomicDatabaseAPI, network_id: int, max_peers: int = DEFAULT_MAX_PEERS, event_bus: EndpointAPI = None, metrics_registry: MetricsRegistry = None, ) -> None: self.logger = get_logger(self.__module__ + '.' + self.__class__.__name__) # cross process event bus self.event_bus = event_bus self.metrics_registry = metrics_registry # setup parameters for the base devp2p handshake. self.p2p_handshake_params = DevP2PHandshakeParams( client_version_string=construct_trinity_client_identifier(), listen_port=port, version=DEVP2P_V5, ) # chain information self.chain = chain self.chaindb = chaindb self.headerdb = headerdb self.base_db = base_db # node information self.privkey = privkey self.port = port self.network_id = network_id self.max_peers = max_peers # child services self.peer_pool = self._make_peer_pool()
def _main() -> None: logging.basicConfig(level=DEBUG2_LEVEL_NUM, format='%(asctime)s %(levelname)s: %(message)s') parser = argparse.ArgumentParser() parser.add_argument('-enode', type=str, help="The enode we should connect to", required=True) parser.add_argument('-mainnet', action='store_true') parser.add_argument('-light', action='store_true', help="Connect as a light node") args = parser.parse_args() peer_class: Union[Type[ETHPeer], Type[LESPeer]] pool_class: Union[Type[ETHPeerPool], Type[LESPeerPool]] if args.light: peer_class = LESPeer pool_class = LESPeerPool else: peer_class = ETHPeer pool_class = ETHPeerPool if args.mainnet: chain_id = MainnetChain.chain_id vm_config = MAINNET_VM_CONFIGURATION genesis = MAINNET_GENESIS_HEADER else: chain_id = RopstenChain.chain_id vm_config = ROPSTEN_VM_CONFIGURATION genesis = ROPSTEN_GENESIS_HEADER headerdb = AsyncHeaderDB(AtomicDB(MemoryDB())) headerdb.persist_header(genesis) loop = asyncio.get_event_loop() nodes = [Node.from_uri(args.enode)] context = ChainContext( headerdb=headerdb, network_id=chain_id, vm_configuration=vm_config, client_version_string=construct_trinity_client_identifier(), listen_port=30309, p2p_version=DEVP2P_V5, ) peer_pool = pool_class( privkey=ecies.generate_privkey(), context=context, ) asyncio.ensure_future(peer_pool.run()) peer_pool.run_task(connect_to_peers_loop(peer_pool, nodes)) async def request_stuff() -> None: # Request some stuff from ropsten's block 2440319 # (https://ropsten.etherscan.io/block/2440319), just as a basic test. nonlocal peer_pool while not peer_pool.connected_nodes: peer_pool.logger.info("Waiting for peer connection...") await asyncio.sleep(0.2) peer = peer_pool.highest_td_peer headers = await cast(ETHPeer, peer).eth_api.get_block_headers( BlockNumber(2440319), max_headers=100 ) hashes = tuple(header.hash for header in headers) if peer_class == ETHPeer: peer = cast(ETHPeer, peer) peer.eth_api.send_get_block_bodies(hashes) peer.eth_api.send_get_receipts(hashes) else: peer = cast(LESPeer, peer) peer.les_api.send_get_block_bodies(list(hashes)) peer.les_api.send_get_receipts(hashes[0]) sigint_received = asyncio.Event() for sig in [signal.SIGINT, signal.SIGTERM]: loop.add_signal_handler(sig, sigint_received.set) async def exit_on_sigint() -> None: await sigint_received.wait() await peer_pool.cancel() loop.stop() asyncio.ensure_future(exit_on_sigint()) asyncio.ensure_future(request_stuff()) loop.set_debug(True) loop.run_forever() loop.close()
async def clientVersion(self) -> str: """ Returns the current client version. """ return construct_trinity_client_identifier()
def __init__(self, config: TrinityConfig) -> None: super().__init__(config) self.bootstrap_nodes = config.bootstrap_nodes self.preferred_nodes = config.preferred_nodes self.client_identifier = construct_trinity_client_identifier()
), ( build_request('eth_mining'), {'result': False, 'id': 3, 'jsonrpc': '2.0'}, ), ( build_request('eth_coinbase'), {'result': '0x0000000000000000000000000000000000000000', 'id': 3, 'jsonrpc': '2.0'}, ), ( build_request('eth_hashrate'), {'result': '0x0', 'id': 3, 'jsonrpc': '2.0'}, ), ( build_request('web3_clientVersion'), {'result': construct_trinity_client_identifier(), 'id': 3, 'jsonrpc': '2.0'}, ), ( build_request('web3_sha3', ['0x89987239849872']), { 'result': '0xb3406131994d9c859de3c4400e12f630638e1e992c6453358c16d0e6ce2b1a70', 'id': 3, 'jsonrpc': '2.0', }, ), ( build_request('web3_sha3', ['0x']), { 'result': '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', 'id': 3, 'jsonrpc': '2.0',
async def _main() -> None: parser = argparse.ArgumentParser() parser.add_argument('-enode', type=str, help="The enode we should connect to", required=True) parser.add_argument('-mainnet', action='store_true') parser.add_argument('-light', action='store_true', help="Connect as a light node") parser.add_argument('-debug', action="store_true") args = parser.parse_args() log_level = logging.INFO if args.debug: log_level = DEBUG2_LEVEL_NUM logging.basicConfig(level=log_level, format='%(asctime)s %(levelname)s: %(message)s', datefmt='%H:%M:%S') peer_class: Union[Type[ETHPeer], Type[LESPeer]] pool_class: Union[Type[ETHPeerPool], Type[LESPeerPool]] if args.light: peer_class = LESPeer pool_class = LESPeerPool else: peer_class = ETHPeer pool_class = ETHPeerPool bootnodes: Tuple[str, ...] if args.mainnet: bootnodes = MAINNET_BOOTNODES chain_id = MainnetChain.chain_id vm_config = MAINNET_VM_CONFIGURATION genesis = MAINNET_GENESIS_HEADER else: bootnodes = ROPSTEN_BOOTNODES chain_id = RopstenChain.chain_id vm_config = ROPSTEN_VM_CONFIGURATION genesis = ROPSTEN_GENESIS_HEADER headerdb = AsyncHeaderDB(AtomicDB(MemoryDB())) headerdb.persist_header(genesis) loop = asyncio.get_event_loop() if args.enode == "bootnodes": nodes = [Node.from_uri(enode) for enode in bootnodes] else: nodes = [Node.from_uri(args.enode)] context = ChainContext( headerdb=headerdb, network_id=chain_id, vm_configuration=vm_config, client_version_string=construct_trinity_client_identifier(), listen_port=30309, p2p_version=DEVP2P_V5, ) peer_pool = pool_class(privkey=ecies.generate_privkey(), context=context) async def request_stuff() -> None: nonlocal peer_pool # Request some stuff from ropsten's block 2440319 # (https://ropsten.etherscan.io/block/2440319), just as a basic test. peer = peer_pool.highest_td_peer if peer_class == ETHPeer: peer = cast(ETHPeer, peer) headers = await peer.eth_api.get_block_headers( BlockNumber(2440319), max_headers=100) hashes = tuple(header.hash for header in headers) peer.eth_api.send_get_block_bodies(hashes) peer.eth_api.send_get_receipts(hashes) else: peer = cast(LESPeer, peer) headers = await peer.les_api.get_block_headers( BlockNumber(2440319), max_headers=100) peer.les_api.send_get_block_bodies(list(hashes)) peer.les_api.send_get_receipts(hashes[:1]) async with background_asyncio_service(peer_pool) as manager: for sig in [signal.SIGINT, signal.SIGTERM]: loop.add_signal_handler(sig, manager.cancel) await peer_pool.connect_to_nodes(nodes) await asyncio.sleep(1) if len(peer_pool) == 0: peer_pool.logger.error(f"Unable to connect to any of {nodes}") return try: await asyncio.wait_for(request_stuff(), timeout=2) except asyncio.TimeoutError: peer_pool.logger.error("Timeout waiting for replies") await manager.wait_finished()
def client_id(): return construct_trinity_client_identifier()
def test_construct_trinity_client_identifier(): assert construct_trinity_client_identifier().startswith('Trinity/')
async def _main() -> None: parser = argparse.ArgumentParser() parser.add_argument('-db', type=str, required=True) parser.add_argument('-light', action="store_true") parser.add_argument('-nodekey', type=str) parser.add_argument('-enode', type=str, required=False, help="The enode we should connect to") parser.add_argument('-debug', action="store_true") args = parser.parse_args() logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s: %(message)s', datefmt='%H:%M:%S') log_level = logging.INFO if args.debug: log_level = logging.DEBUG loop = asyncio.get_event_loop() base_db = LevelDB(args.db) headerdb = AsyncHeaderDB(AtomicDB(base_db)) chaindb = AsyncChainDB(AtomicDB(base_db)) try: genesis = chaindb.get_canonical_block_header_by_number(BlockNumber(0)) except HeaderNotFound: genesis = ROPSTEN_GENESIS_HEADER chaindb.persist_header(genesis) peer_pool_class: Type[Union[ETHPeerPool, LESPeerPool]] = ETHPeerPool if args.light: peer_pool_class = LESPeerPool chain_class: Union[Type[AsyncRopstenChain], Type[AsyncMainnetChain]] if genesis.hash == ROPSTEN_GENESIS_HEADER.hash: chain_id = RopstenChain.chain_id vm_config = ROPSTEN_VM_CONFIGURATION chain_class = AsyncRopstenChain elif genesis.hash == MAINNET_GENESIS_HEADER.hash: chain_id = MainnetChain.chain_id vm_config = MAINNET_VM_CONFIGURATION # type: ignore chain_class = AsyncMainnetChain else: raise RuntimeError("Unknown genesis: %s", genesis) if args.nodekey: privkey = load_nodekey(Path(args.nodekey)) else: privkey = ecies.generate_privkey() context = ChainContext( headerdb=headerdb, network_id=chain_id, vm_configuration=vm_config, client_version_string=construct_trinity_client_identifier(), listen_port=30309, p2p_version=DEVP2P_V5, ) peer_pool = peer_pool_class(privkey=privkey, context=context) if args.enode: nodes = tuple([Node.from_uri(args.enode)]) else: nodes = DEFAULT_PREFERRED_NODES[chain_id] async with background_asyncio_service(peer_pool) as manager: manager.run_task(connect_to_peers_loop(peer_pool, nodes)) # type: ignore chain = chain_class(base_db) syncer: Service = None if args.light: syncer = LightChainSyncer(chain, headerdb, cast(LESPeerPool, peer_pool)) else: syncer = RegularChainSyncer(chain, chaindb, cast(ETHPeerPool, peer_pool)) logging.getLogger().setLevel(log_level) sigint_received = asyncio.Event() for sig in [signal.SIGINT, signal.SIGTERM]: loop.add_signal_handler(sig, sigint_received.set) async def exit_on_sigint() -> None: await sigint_received.wait() syncer.get_manager().cancel() asyncio.ensure_future(exit_on_sigint()) async with background_asyncio_service(syncer) as syncer_manager: await syncer_manager.wait_finished()
'id': 3, 'jsonrpc': '2.0' }, ), ( build_request('eth_hashrate'), { 'result': '0x0', 'id': 3, 'jsonrpc': '2.0' }, ), ( build_request('web3_clientVersion'), { 'result': construct_trinity_client_identifier(), 'id': 3, 'jsonrpc': '2.0' }, ), ( build_request('web3_sha3', ['0x89987239849872']), { 'result': '0xb3406131994d9c859de3c4400e12f630638e1e992c6453358c16d0e6ce2b1a70', 'id': 3, 'jsonrpc': '2.0', }, ), ( build_request('web3_sha3', ['0x']),
class Network(enum.IntEnum): MAINNET = MAINNET_NETWORK_ID GOERLI = GOERLI_NETWORK_ID ROPSTEN = ROPSTEN_NETWORK_ID API_URLS = { Network.MAINNET: "https://api.etherscan.io/api", Network.GOERLI: "https://api-goerli.etherscan.io/api", Network.ROPSTEN: "https://api-ropsten.etherscan.io/api", } # The Etherscan API for Goerli and Ropsten rejects any requests without User-Agent COMMON_REQUEST_HEADERS = {'User-Agent': construct_trinity_client_identifier()} class Etherscan: def __init__(self, api_key: str) -> None: if not api_key: raise ValueError( "Must provide an API key for Etherscan API access") self.api_key = api_key def get_proxy_api_url(self, network: Network) -> str: return f"{API_URLS[network]}?module=proxy&apikey={self.api_key}" def post(self, action: str, network: Network) -> Any: response = requests.post(