async def do_run(cls, boot_info: BootInfo, event_bus: EndpointAPI) -> None: trinity_config = boot_info.trinity_config key_pair = cls._load_or_create_node_key(boot_info) beacon_app_config = trinity_config.get_app_config(BeaconAppConfig) base_db = DBClient.connect(trinity_config.database_ipc_path) if boot_info.args.debug_libp2p: logging.getLogger("libp2p").setLevel(logging.DEBUG) else: logging.getLogger("libp2p").setLevel(logging.INFO) with base_db: chain_config = beacon_app_config.get_chain_config() chain = chain_config.beacon_chain_class( base_db, chain_config.genesis_config) # TODO: To simplify, subsribe all subnets subnets: Set[SubnetId] = set( SubnetId(subnet_id) for subnet_id in range(ATTESTATION_SUBNET_COUNT)) # TODO: Handle `bootstrap_nodes`. libp2p_node = Node( key_pair=key_pair, listen_ip="0.0.0.0", listen_port=boot_info.args.port, preferred_nodes=trinity_config.preferred_nodes, chain=chain, subnets=subnets, event_bus=event_bus, ) receive_server = BCCReceiveServer( chain=chain, p2p_node=libp2p_node, topic_msg_queues=libp2p_node.pubsub.my_topics, subnets=subnets, cancel_token=libp2p_node.cancel_token, ) state = chain.get_state_by_slot( chain_config.genesis_config.GENESIS_SLOT) registry_pubkeys = [ v_record.pubkey for v_record in state.validators ] validator_privkeys = {} validator_keymap = chain_config.genesis_data.validator_keymap for pubkey in validator_keymap: try: validator_index = cast(ValidatorIndex, registry_pubkeys.index(pubkey)) except ValueError: cls.logger.error( f'Could not find pubkey {pubkey.hex()} in genesis state' ) raise validator_privkeys[validator_index] = validator_keymap[pubkey] validator = Validator( chain=chain, p2p_node=libp2p_node, validator_privkeys=validator_privkeys, event_bus=event_bus, token=libp2p_node.cancel_token, get_ready_attestations_fn=receive_server. get_ready_attestations, get_aggregatable_attestations_fn=receive_server. get_aggregatable_attestations, import_attestation_fn=receive_server.import_attestation, ) slot_ticker = SlotTicker( genesis_slot=chain_config.genesis_config.GENESIS_SLOT, genesis_time=chain_config.genesis_data.genesis_time, seconds_per_slot=chain_config.genesis_config.SECONDS_PER_SLOT, event_bus=event_bus, token=libp2p_node.cancel_token, ) syncer = BeaconChainSyncer( chain_db=AsyncBeaconChainDB( base_db, chain_config.genesis_config, ), peer_pool=libp2p_node.handshaked_peers, block_importer=SyncBlockImporter(chain), genesis_config=chain_config.genesis_config, event_bus=event_bus, token=libp2p_node.cancel_token, ) metrics_server = HTTPServer( handler=MetricsHandler.handle(chain)(event_bus), port=boot_info.args.metrics_port, ) api_server = HTTPServer( handler=APIHandler.handle(chain)(event_bus), port=boot_info.args.api_port, ) services: Tuple[BaseService, ...] = (libp2p_node, receive_server, slot_ticker, validator, syncer) if boot_info.args.enable_metrics: services += (metrics_server, ) if boot_info.args.enable_api: services += (api_server, ) async with AsyncExitStack() as stack: for service in services: await stack.enter_async_context(run_service(service)) await asyncio.gather(*(service.cancellation() for service in services))
async def attest(self, slot: Slot) -> Tuple[Attestation, ...]: """ Attest the block at the given ``slot`` and broadcast them. """ result_attestations: Tuple[Attestation, ...] = () head = self.chain.get_canonical_head() state_machine = self.chain.get_state_machine() state = self.chain.get_head_state() epoch = compute_epoch_at_slot(slot, self.slots_per_epoch) attesting_committee_assignments_at_slot = self._get_attesting_assignments_at_slot( slot) for committee_assignment in attesting_committee_assignments_at_slot: committee_index = committee_assignment.committee_index committee = committee_assignment.committee attesting_validators_indices = tuple( filter( lambda attester: self.latest_attested_epoch[attester] < epoch, self._get_local_attesters_at_assignment( committee_assignment), )) # Get the validator_index -> privkey map of the attesting validators attesting_validator_privkeys = { index: self.validator_privkeys[index] for index in attesting_validators_indices } attestations = create_signed_attestations_at_slot( state, state_machine.config, state_machine, slot, head.message.hash_tree_root, attesting_validator_privkeys, committee, committee_index, tuple( CommitteeValidatorIndex(committee.index(index)) for index in attesting_validators_indices), ) self.logger.debug( bold_green( "validators %s attesting to block %s with attestation %s"), attesting_validators_indices, head, attestations, ) # await self.p2p_node.broadcast_attestation(attestation) subnet_id = SubnetId(committee_index % ATTESTATION_SUBNET_COUNT) # Import attestation to pool and then broadcast it for attestation in attestations: self.import_attestation(attestation, False) await self.p2p_node.broadcast_attestation_to_subnet( attestation, subnet_id) # Log the last epoch that the validator attested for index in attesting_validators_indices: self.latest_attested_epoch[index] = epoch metrics.validator_sent_attestation.inc() result_attestations = result_attestations + attestations # TODO: Aggregate attestations return result_attestations
async def do_run(cls, boot_info: BootInfo, event_bus: EndpointAPI) -> None: trinity_config = boot_info.trinity_config key_pair = _load_secp256k1_key_pair_from(trinity_config) beacon_app_config = trinity_config.get_app_config(BeaconAppConfig) base_db = DBClient.connect(trinity_config.database_ipc_path) if boot_info.args.debug_libp2p: logging.getLogger("libp2p").setLevel(logging.DEBUG) else: logging.getLogger("libp2p").setLevel(logging.INFO) with base_db: chain_config = beacon_app_config.get_chain_config() chain = chain_config.beacon_chain_class( base_db, chain_config.genesis_config) # TODO: To simplify, subsribe all subnets subnets: Set[SubnetId] = set( SubnetId(subnet_id) for subnet_id in range(ATTESTATION_SUBNET_COUNT)) # TODO: Handle `bootstrap_nodes`. libp2p_node = Node( key_pair=key_pair, listen_ip="0.0.0.0", listen_port=boot_info.args.port, preferred_nodes=trinity_config.preferred_nodes, chain=chain, subnets=subnets, event_bus=event_bus, ) receive_server = BCCReceiveServer( chain=chain, p2p_node=libp2p_node, topic_msg_queues=libp2p_node.pubsub.my_topics, subnets=subnets, cancel_token=libp2p_node.cancel_token, ) chain_maintainer = ChainMaintainer(chain=chain, event_bus=event_bus, token=libp2p_node.cancel_token) validator_handler = ValidatorHandler( chain=chain, p2p_node=libp2p_node, event_bus=event_bus, get_ready_attestations_fn=receive_server. get_ready_attestations, get_aggregatable_attestations_fn=receive_server. get_aggregatable_attestations, import_attestation_fn=receive_server.import_attestation, token=libp2p_node.cancel_token, ) slot_ticker = SlotTicker( genesis_slot=chain_config.genesis_config.GENESIS_SLOT, genesis_time=chain_config.genesis_time, seconds_per_slot=chain_config.genesis_config.SECONDS_PER_SLOT, event_bus=event_bus, token=libp2p_node.cancel_token, ) syncer = BeaconChainSyncer( chain_db=AsyncBeaconChainDB(base_db, chain_config.genesis_config), peer_pool=libp2p_node.handshaked_peers, block_importer=SyncBlockImporter(chain), genesis_config=chain_config.genesis_config, event_bus=event_bus, token=libp2p_node.cancel_token, ) metrics_server = HTTPServer( handler=MetricsHandler.handle(chain)(event_bus), port=boot_info.args.metrics_port, ) # NOTE: this API server provides an interface into the beacon node api_server = HTTPServer( handler=APIHandler.handle(chain)(event_bus), port=boot_info.args.api_port, ) # NOTE: this API server provides an interface between the beacon node and # any connected validator clients. validator_api_handler = ValidatorAPIHandler( chain, event_bus, chain_config.genesis_time) validator_api_server = HTTPAppServer( routes=validator_api_handler.make_routes(), port=30303) services: Tuple[BaseService, ...] = ( libp2p_node, receive_server, slot_ticker, syncer, validator_api_server, ) if boot_info.args.enable_metrics: services += (metrics_server, ) if boot_info.args.enable_api: services += (api_server, ) if boot_info.args.bn_only: services += (chain_maintainer, validator_handler) async with AsyncExitStack() as stack: for service in services: await stack.enter_async_context(run_service(service)) await asyncio.gather(*(service.cancellation() for service in services))