def chain_for_config( self, trinity_config: TrinityConfig ) -> Union[AsyncChainAPI, AsyncBeaconChainDB]: if trinity_config.has_app_config(BeaconAppConfig): beacon_app_config = trinity_config.get_app_config(BeaconAppConfig) return self.chain_for_beacon_config(trinity_config, beacon_app_config) elif trinity_config.has_app_config(Eth1AppConfig): eth1_app_config = trinity_config.get_app_config(Eth1AppConfig) return self.chain_for_eth1_config(trinity_config, eth1_app_config) else: raise Exception("Unsupported Node Type")
def chain_for_config(trinity_config: TrinityConfig, event_bus: EndpointAPI, ) -> Iterator[Union[AsyncChainAPI, AsyncBeaconChainDB]]: if trinity_config.has_app_config(BeaconAppConfig): beacon_app_config = trinity_config.get_app_config(BeaconAppConfig) with chain_for_beacon_config(trinity_config, beacon_app_config) as beacon_chain: yield beacon_chain elif trinity_config.has_app_config(Eth1AppConfig): eth1_app_config = trinity_config.get_app_config(Eth1AppConfig) with chain_for_eth1_config(trinity_config, eth1_app_config, event_bus) as eth1_chain: yield eth1_chain else: raise Exception("Unsupported Node Type")
def run_shell(cls, args: Namespace, trinity_config: TrinityConfig) -> None: config: BaseAppConfig if trinity_config.has_app_config(Eth1AppConfig): config = trinity_config.get_app_config(Eth1AppConfig) context = get_eth1_shell_context(config.database_dir, trinity_config) db_shell(is_ipython_available(), context) elif trinity_config.has_app_config(BeaconAppConfig): config = trinity_config.get_app_config(BeaconAppConfig) context = get_beacon_shell_context(config.database_dir, trinity_config) db_shell(is_ipython_available(), context) else: cls.logger.error( "DB Shell only supports the Ethereum 1 and Beacon nodes at this time" )
def run_shell(self, args: Namespace, trinity_config: TrinityConfig) -> None: if trinity_config.has_app_config(Eth1AppConfig): config = trinity_config.get_app_config(Eth1AppConfig) db_shell(self.use_ipython, config.database_dir, trinity_config) else: self.logger.error("DB Shell does only support the Ethereum 1 node at this time")
def setup_eth1_modules( self, trinity_config: TrinityConfig) -> Tuple[Eth1ChainRPCModule, ...]: db_manager = create_db_consumer_manager( trinity_config.database_ipc_path) eth1_app_config = trinity_config.get_app_config(Eth1AppConfig) chain_config = trinity_config.get_chain_config() chain: BaseAsyncChain if eth1_app_config.database_mode is Eth1DbMode.LIGHT: header_db = db_manager.get_headerdb() # type: ignore event_bus_light_peer_chain = EventBusLightPeerChain( self.context.event_bus) chain = chain_config.light_chain_class( header_db, peer_chain=event_bus_light_peer_chain) elif eth1_app_config.database_mode is Eth1DbMode.FULL: db = db_manager.get_db() # type: ignore chain = chain_config.full_chain_class(db) else: raise Exception( f"Unsupported Database Mode: {eth1_app_config.database_mode}") return initialize_eth1_modules(chain, self.event_bus)
def setup_eth1_modules( self, trinity_config: TrinityConfig) -> Tuple[Eth1ChainRPCModule, ...]: db_manager = create_db_manager(trinity_config.database_ipc_path) db_manager.connect() eth1_app_config = trinity_config.get_app_config(Eth1AppConfig) chain_config = trinity_config.get_chain_config() chain: BaseAsyncChain if eth1_app_config.is_light_mode: header_db = db_manager.get_headerdb() # type: ignore event_bus_light_peer_chain = EventBusLightPeerChain( self.context.event_bus) chain = chain_config.light_chain_class( header_db, peer_chain=event_bus_light_peer_chain) elif eth1_app_config.is_full_mode: db = db_manager.get_db() # type: ignore chain = chain_config.full_chain_class(db) else: raise NotImplementedError( f"Unsupported mode: {trinity_config.sync_mode}") return initialize_eth1_modules(chain, self.event_bus)
def get_beacon_shell_context(database_dir: Path, trinity_config: TrinityConfig) -> Dict[str, Any]: app_config = trinity_config.get_app_config(BeaconAppConfig) ipc_path = trinity_config.database_ipc_path db: DatabaseAPI trinity_already_running = ipc_path.exists() if trinity_already_running: db = DBClient.connect(ipc_path) else: db = LevelDB(database_dir) chain_config = app_config.get_chain_config() chain = chain_config.beacon_chain_class(db, chain_config.genesis_config) chaindb = BeaconChainDB(db, chain_config.genesis_config) head = chaindb.get_canonical_head(BeaconBlock) return { 'db': db, 'chaindb': chaindb, 'trinity_config': trinity_config, 'chain_config': chain_config, 'chain': chain, 'block_number': head.slot, 'hex_hash': head.hash_tree_root.hex(), 'state_root_hex': encode_hex(head.state_root), 'trinity_already_running': trinity_already_running }
def create_db_server_manager(trinity_config: TrinityConfig, base_db: BaseAtomicDB) -> BaseManager: app_config = trinity_config.get_app_config(BeaconAppConfig) chain_config = app_config.get_chain_config() chaindb = BeaconChainDB(base_db, chain_config.genesis_config) if not is_beacon_database_initialized(chaindb, BeaconBlock): initialize_beacon_database(chain_config, chaindb, base_db, BeaconBlock) # This enables connection when clients launch from another process on the shell multiprocessing.current_process().authkey = AUTH_KEY class DBManager(BaseManager): pass DBManager.register('get_db', callable=lambda: TracebackRecorder(base_db), proxytype=AsyncDBProxy) DBManager.register( 'get_chaindb', callable=lambda: TracebackRecorder(chaindb), proxytype=AsyncBeaconChainDBProxy, ) manager = DBManager(address=str( trinity_config.database_ipc_path)) # type: ignore return manager
def get_eth1_shell_context(database_dir: Path, trinity_config: TrinityConfig) -> Dict[str, Any]: app_config = trinity_config.get_app_config(Eth1AppConfig) ipc_path = trinity_config.database_ipc_path trinity_already_running = ipc_path.exists() if trinity_already_running: db_manager = eth1.manager.create_db_consumer_manager( ipc_path) # type: ignore db = db_manager.get_db() else: db = LevelDB(database_dir) chaindb = ChainDB(db) head = chaindb.get_canonical_head() chain_config = app_config.get_chain_config() chain = chain_config.full_chain_class(db) return { 'db': db, 'chaindb': chaindb, 'trinity_config': trinity_config, 'chain_config': chain_config, 'chain': chain, 'block_number': head.block_number, 'hex_hash': head.hex_hash, 'state_root_hex': encode_hex(head.state_root), 'trinity_already_running': trinity_already_running, }
def get_beacon_shell_context(database_dir: Path, trinity_config: TrinityConfig) -> Dict[str, Any]: app_config = trinity_config.get_app_config(BeaconAppConfig) ipc_path = trinity_config.database_ipc_path trinity_already_running = ipc_path.exists() if trinity_already_running: db_manager = beacon.manager.create_db_consumer_manager( ipc_path) # type: ignore db = db_manager.get_db() else: db = LevelDB(database_dir) chain_config = app_config.get_chain_config() chain = chain_config.beacon_chain_class attestation_pool = AttestationPool() chain = chain_config.beacon_chain_class(db, attestation_pool, chain_config.genesis_config) chaindb = BeaconChainDB(db, chain_config.genesis_config) head = chaindb.get_canonical_head(BeaconBlock) return { 'db': db, 'chaindb': chaindb, 'trinity_config': trinity_config, 'chain_config': chain_config, 'chain': chain, 'block_number': head.slot, 'hex_hash': head.hash_tree_root.hex(), 'state_root_hex': encode_hex(head.state_root), 'trinity_already_running': trinity_already_running }
def get_eth1_shell_context( database_dir: Path, trinity_config: TrinityConfig) -> Iterator[Dict[str, Any]]: app_config = trinity_config.get_app_config(Eth1AppConfig) ipc_path = trinity_config.database_ipc_path trinity_already_running = ipc_path.exists() with _get_base_db(database_dir, ipc_path) as db: chaindb = ChainDB(db) head = chaindb.get_canonical_head() chain_config = app_config.get_chain_config() chain = chain_config.full_chain_class(db) mining_chain_class = MiningChain.configure( __name__=chain_config.full_chain_class.__name__, vm_configuration=chain.vm_configuration, consensus_context_class=chain.consensus_context_class, chain_id=chain.chain_id, ) mining_chain = mining_chain_class(db) yield { 'db': db, 'chaindb': chaindb, 'trinity_config': trinity_config, 'chain_config': chain_config, 'chain': chain, 'mining_chain': mining_chain, 'block_number': head.block_number, 'hex_hash': head.hex_hash, 'state_root_hex': encode_hex(head.state_root), 'trinity_already_running': trinity_already_running, }
def trinity_boot(args: Namespace, trinity_config: TrinityConfig, extra_kwargs: Dict[str, Any], listener: logging.handlers.QueueListener, logger: logging.Logger) -> Tuple[multiprocessing.Process, ...]: # start the listener thread to handle logs produced by other processes in # the local logger. listener.start() ensure_beacon_dirs(trinity_config.get_app_config(BeaconAppConfig)) # First initialize the database process. database_server_process = ctx.Process( name="DB", target=run_database_process, args=( trinity_config, LevelDB, ), kwargs=extra_kwargs, ) # start the processes database_server_process.start() logger.info("Started DB server process (pid=%d)", database_server_process.pid) try: wait_for_ipc(trinity_config.database_ipc_path) except TimeoutError as e: logger.error("Timeout waiting for database to start. Exiting...") kill_process_gracefully(database_server_process, logger) ArgumentParser().error(message="Timed out waiting for database start") return None return (database_server_process,)
def create_db_server_manager(trinity_config: TrinityConfig, base_db: BaseAtomicDB) -> BaseManager: app_config = trinity_config.get_app_config(BeaconAppConfig) chain_config = app_config.get_chain_config() chaindb = BeaconChainDB(base_db) if not is_beacon_database_initialized(chaindb, BeaconBlock): initialize_beacon_database(chain_config, chaindb, base_db, BeaconBlock) class DBManager(BaseManager): pass DBManager.register('get_db', callable=lambda: TracebackRecorder(base_db), proxytype=AsyncDBProxy) DBManager.register( 'get_chaindb', callable=lambda: TracebackRecorder(chaindb), proxytype=AsyncBeaconChainDBProxy, ) manager = DBManager(address=str( trinity_config.database_ipc_path)) # type: ignore return manager
def get_beacon_shell_context( database_dir: Path, trinity_config: TrinityConfig) -> Iterator[Dict[str, Any]]: app_config = trinity_config.get_app_config(BeaconAppConfig) ipc_path = trinity_config.database_ipc_path trinity_already_running = ipc_path.exists() with _get_base_db(database_dir, ipc_path) as db: chain_config = app_config.get_chain_config() chain = chain_config.beacon_chain_class(db, chain_config.genesis_config) chaindb = BeaconChainDB(db, chain_config.genesis_config) head = chaindb.get_canonical_head(BeaconBlock) yield { 'db': db, 'chaindb': chaindb, 'trinity_config': trinity_config, 'chain_config': chain_config, 'chain': chain, 'block_number': head.slot, 'hex_hash': head.hash_tree_root.hex(), 'state_root_hex': encode_hex(head.state_root), 'trinity_already_running': trinity_already_running }
def get_eth1_shell_context(database_dir: Path, trinity_config: TrinityConfig) -> Dict[str, Any]: app_config = trinity_config.get_app_config(Eth1AppConfig) ipc_path = trinity_config.database_ipc_path db: DatabaseAPI trinity_already_running = ipc_path.exists() if trinity_already_running: db = DBClient.connect(ipc_path) else: db = LevelDB(database_dir) chaindb = ChainDB(db) head = chaindb.get_canonical_head() chain_config = app_config.get_chain_config() chain = chain_config.full_chain_class(db) mining_chain_class = MiningChain.configure( __name__=chain_config.full_chain_class.__name__, vm_configuration=chain.vm_configuration, chain_id=chain.chain_id, ) mining_chain = mining_chain_class(db) return { 'db': db, 'chaindb': chaindb, 'trinity_config': trinity_config, 'chain_config': chain_config, 'chain': chain, 'mining_chain': mining_chain, 'block_number': head.block_number, 'hex_hash': head.hex_hash, 'state_root_hex': encode_hex(head.state_root), 'trinity_already_running': trinity_already_running, }
def test_trinity_config_sub_configs(): trinity_config = TrinityConfig(network_id=1) trinity_config.initialize_app_configs(None, (BeaconAppConfig,)) assert trinity_config.has_app_config(BeaconAppConfig) beacon_config = trinity_config.get_app_config(BeaconAppConfig) assert type(beacon_config) is BeaconAppConfig
async def launch_node_coro(args: Namespace, trinity_config: TrinityConfig) -> None: endpoint = TrinityEventBusEndpoint() NodeClass = trinity_config.get_app_config(Eth1AppConfig).node_class node = NodeClass(endpoint, trinity_config) networking_connection_config = ConnectionConfig.from_name( NETWORKING_EVENTBUS_ENDPOINT, trinity_config.ipc_dir) await endpoint.start_serving(networking_connection_config) endpoint.auto_connect_new_announced_endpoints() await endpoint.connect_to_endpoints( ConnectionConfig.from_name(MAIN_EVENTBUS_ENDPOINT, trinity_config.ipc_dir), # Plugins that run within the networking process broadcast and receive on the # the same endpoint networking_connection_config, ) await endpoint.announce_endpoint() # This is a second PluginManager instance governing plugins in a shared process. plugin_manager = PluginManager(SharedProcessScope(endpoint), get_all_plugins()) plugin_manager.prepare(args, trinity_config) asyncio.ensure_future( handle_networking_exit(node, plugin_manager, endpoint)) asyncio.ensure_future(node.run())
def get_protocol(trinity_config: TrinityConfig) -> Type[Protocol]: # For now DiscoveryByTopicProtocol supports a single topic, so we use the latest # version of our supported protocols. Maybe this could be more generic? eth1_config = trinity_config.get_app_config(Eth1AppConfig) if eth1_config.database_mode is Eth1DbMode.LIGHT: return LESProtocolV2 else: return ETHProtocol
def run_database_process(trinity_config: TrinityConfig, db_class: Type[BaseDB]) -> None: with trinity_config.process_id_file('database'): app_config = trinity_config.get_app_config(Eth1AppConfig) base_db = db_class(db_path=app_config.database_dir) manager = create_db_server_manager(trinity_config, base_db) serve_until_sigint(manager)
def chain_for_config(self, trinity_config: TrinityConfig) -> AsyncChainAPI: if trinity_config.has_app_config(BeaconAppConfig): return None elif trinity_config.has_app_config(Eth1AppConfig): eth1_app_config = trinity_config.get_app_config(Eth1AppConfig) return self.chain_for_eth1_config(trinity_config, eth1_app_config) else: raise Exception("Unsupported Node Type")
def run_shell(cls, args: Namespace, trinity_config: TrinityConfig) -> None: if trinity_config.has_app_config(Eth1AppConfig): config = trinity_config.get_app_config(Eth1AppConfig) db_shell(is_ipython_available(), config.database_dir, trinity_config) else: cls.get_logger().error( "DB Shell only supports the Ethereum 1 node at this time")
def trinity_boot(args: Namespace, trinity_config: TrinityConfig, extra_kwargs: Dict[str, Any], plugin_manager: PluginManager, listener: logging.handlers.QueueListener, main_endpoint: TrinityMainEventBusEndpoint, logger: logging.Logger) -> None: # start the listener thread to handle logs produced by other processes in # the local logger. listener.start() ensure_beacon_dirs(trinity_config.get_app_config(BeaconAppConfig)) # First initialize the database process. database_server_process = ctx.Process( name="DB", target=run_database_process, args=( trinity_config, LevelDB, ), kwargs=extra_kwargs, ) # start the processes database_server_process.start() logger.info("Started DB server process (pid=%d)", database_server_process.pid) try: wait_for_ipc(trinity_config.database_ipc_path) except TimeoutError as e: logger.error("Timeout waiting for database to start. Exiting...") kill_process_gracefully(database_server_process, logger) ArgumentParser().error(message="Timed out waiting for database start") def kill_trinity_with_reason(reason: str) -> None: kill_trinity_gracefully(trinity_config, logger, (), plugin_manager, main_endpoint, reason=reason) main_endpoint.subscribe(ShutdownRequest, lambda ev: kill_trinity_with_reason(ev.reason)) plugin_manager.prepare(args, trinity_config, extra_kwargs) try: loop = asyncio.get_event_loop() loop.add_signal_handler(signal.SIGTERM, lambda: kill_trinity_with_reason("SIGTERM")) loop.run_forever() loop.close() except KeyboardInterrupt: kill_trinity_with_reason("CTRL+C / Keyboard Interrupt")
def get_protocol(trinity_config: TrinityConfig) -> Type[ProtocolAPI]: # For now DiscoveryByTopicProtocol supports a single topic, so we use the latest # version of our supported protocols. Maybe this could be more generic? # TODO: This needs to support the beacon protocol when we have a way to # check the config, if trinity is being run as a beacon node. eth1_config = trinity_config.get_app_config(Eth1AppConfig) if eth1_config.database_mode is Eth1DbMode.LIGHT: return LESProtocolV2 else: return ETHProtocol
def __init__(self, event_bus: Endpoint, trinity_config: TrinityConfig) -> None: super().__init__(event_bus, trinity_config) self._bootstrap_nodes = trinity_config.bootstrap_nodes self._preferred_nodes = trinity_config.preferred_nodes self._node_key = trinity_config.nodekey self._node_port = trinity_config.port self._max_peers = trinity_config.max_peers app_config = trinity_config.get_app_config(Eth1AppConfig) self._nodedb_path = app_config.nodedb_path
def get_chain(trinity_config: TrinityConfig) -> ChainAPI: app_config = trinity_config.get_app_config(Eth1AppConfig) ensure_eth1_dirs(app_config) base_db = LevelDB(db_path=app_config.database_dir) chain_config = app_config.get_chain_config() chain = chain_config.full_chain_class(AtomicDB(base_db)) initialize_database(chain_config, chain.chaindb, base_db) return chain
def run_database_process(trinity_config: TrinityConfig, db_class: Type[AtomicDatabaseAPI]) -> None: with trinity_config.process_id_file('database'): app_config = trinity_config.get_app_config(BeaconAppConfig) base_db = db_class(db_path=app_config.database_dir) manager = DBManager(base_db) with manager.run(trinity_config.database_ipc_path): try: manager.wait_stopped() except KeyboardInterrupt: pass
def trinity_boot( args: Namespace, trinity_config: TrinityConfig, extra_kwargs: Dict[str, Any], plugin_manager: PluginManager, listener: logging.handlers.QueueListener, main_endpoint: TrinityMainEventBusEndpoint, logger: logging.Logger) -> Tuple[multiprocessing.Process, ...]: # start the listener thread to handle logs produced by other processes in # the local logger. listener.start() ensure_eth1_dirs(trinity_config.get_app_config(Eth1AppConfig)) # First initialize the database process. database_server_process: multiprocessing.Process = ctx.Process( name="DB", target=run_database_process, args=( trinity_config, LevelDB, ), kwargs=extra_kwargs, ) networking_process: multiprocessing.Process = ctx.Process( name="networking", target=launch_node, args=( args, trinity_config, ), kwargs=extra_kwargs, ) # start the processes database_server_process.start() logger.info("Started DB server process (pid=%d)", database_server_process.pid) # networking process needs the IPC socket file provided by the database process try: wait_for_ipc(trinity_config.database_ipc_path) except TimeoutError as e: logger.error("Timeout waiting for database to start. Exiting...") kill_process_gracefully(database_server_process, logger) ArgumentParser().error(message="Timed out waiting for database start") return None networking_process.start() logger.info("Started networking process (pid=%d)", networking_process.pid) return (database_server_process, networking_process)
def get_protocol(trinity_config: TrinityConfig) -> Protocol: # For now DiscoveryByTopicProtocol supports a single topic, so we use the latest # version of our supported protocols. Maybe this could be more generic? # TODO: This needs to support the beacon protocol when we have a way to # check the config, if trinity is being run as a beacon node. if trinity_config.has_app_config(BeaconAppConfig): return BCCProtocol else: eth1_config = trinity_config.get_app_config(Eth1AppConfig) if eth1_config.is_light_mode: return LESProtocolV2 else: return ETHProtocol
def run_database_process(trinity_config: TrinityConfig, db_class: Type[LevelDB]) -> None: with trinity_config.process_id_file('database'): app_config = trinity_config.get_app_config(BeaconAppConfig) chain_config = app_config.get_chain_config() base_db = db_class(db_path=app_config.database_dir) chaindb = BeaconChainDB(base_db, chain_config.genesis_config) if not is_beacon_database_initialized(chaindb, BeaconBlock): initialize_beacon_database(chain_config, chaindb, base_db, BeaconBlock) manager = DBManager(base_db) with manager.run(trinity_config.database_ipc_path): try: manager.wait_stopped() except KeyboardInterrupt: pass
def run_database_process(trinity_config: TrinityConfig, db_class: Type[AtomicDatabaseAPI]) -> None: with trinity_config.process_id_file('database'): app_config = trinity_config.get_app_config(Eth1AppConfig) base_db = db_class(db_path=app_config.database_dir) chaindb = ChainDB(base_db) if not is_database_initialized(chaindb): chain_config = app_config.get_chain_config() initialize_database(chain_config, chaindb, base_db) manager = DBManager(base_db) with manager.run(trinity_config.database_ipc_path): try: manager.wait_stopped() except KeyboardInterrupt: pass