def beacon_block_validator(msg_forwarder: ID, msg: rpc_pb2.Message) -> bool: try: block = ssz.decode(msg.data, BeaconBlock) except (TypeError, ssz.DeserializationError) as error: logger.debug( bold_red("Failed to validate block=%s, error=%s"), encode_hex(block.signing_root), str(error), ) return False state_machine = chain.get_state_machine(block.slot - 1) state_transition = state_machine.state_transition state = chain.get_head_state() # Fast forward to state in future slot in order to pass # block.slot validity check state = state_transition.apply_state_transition( state, future_slot=block.slot, ) try: validate_proposer_signature(state, block, CommitteeConfig(state_machine.config)) except ValidationError as error: logger.debug( bold_red("Failed to validate block=%s, error=%s"), encode_hex(block.signing_root), str(error), ) return False else: return True
def beacon_attestation_validator(msg_forwarder: ID, msg: rpc_pb2.Message) -> bool: try: attestation = ssz.decode(msg.data, sedes=Attestation) except (TypeError, ssz.DeserializationError) as error: # Not correctly encoded logger.debug( bold_red("Failed to validate attestation=%s, error=%s"), attestation, str(error), ) return False state_machine = chain.get_state_machine() config = state_machine.config state = chain.get_head_state() # Check that beacon blocks attested to by the attestation are validated try: chain.get_block_by_root(attestation.data.beacon_block_root) except BlockNotFound: logger.debug( bold_red( "Failed to validate attestation=%s, attested block=%s is not validated yet" ), attestation, encode_hex(attestation.data.beacon_block_root), ) return False # Fast forward to state in future slot in order to pass # attestation.data.slot validity check attestation_data_slot = get_attestation_data_slot( state, attestation.data, config, ) future_state = state_machine.state_transition.apply_state_transition( state, future_slot=Slot(attestation_data_slot + config.MIN_ATTESTATION_INCLUSION_DELAY), ) try: validate_attestation( future_state, attestation, config, ) except ValidationError as error: logger.debug( bold_red("Failed to validate attestation=%s, error=%s"), attestation, str(error), ) return False return True
def beacon_attestation_validator(msg_forwarder: ID, msg: rpc_pb2.Message) -> bool: try: attestation = ssz.decode(msg.data, sedes=Attestation) except (TypeError, ssz.DeserializationError) as error: # Not correctly encoded logger.debug( bold_red( "Failed to deserialize Attestation from %s, error=%s"), encode_hex(msg.data), str(error), ) return False state = chain.get_head_state() state_machine = chain.get_state_machine() try: validate_voting_beacon_block(chain, attestation) validate_attestation_signature( state, attestation, CommitteeConfig(state_machine.config), ) except InvalidGossipMessage as error: logger.debug("%s", str(error)) return False else: return True
def beacon_aggregate_and_proof_validator(msg_forwarder: ID, msg: rpc_pb2.Message) -> bool: try: aggregate_and_proof = ssz.decode(msg.data, sedes=AggregateAndProof) except (TypeError, ssz.DeserializationError) as error: # Not correctly encoded logger.debug( bold_red( "Failed to deserialize AggregateAndProof from %s, error=%s" ), encode_hex(msg.data), str(error), ) return False state = chain.get_head_state() state_machine = chain.get_state_machine() attestation = aggregate_and_proof.aggregate try: validate_voting_beacon_block(chain, attestation) run_validate_aggregate_and_proof( state, aggregate_and_proof, state_machine.config, ) except InvalidGossipMessage as error: logger.debug("%s", str(error)) return False return True
def propose_block(self, proposer_index: ValidatorIndex, slot: Slot, state: BeaconState, state_machine: BaseBeaconStateMachine, head_block: BaseBeaconBlock) -> BaseBeaconBlock: ready_attestations = self.get_ready_attestations() block = self._make_proposing_block( proposer_index=proposer_index, slot=slot, state=state, state_machine=state_machine, parent_block=head_block, attestations=ready_attestations, ) self.logger.info( bold_green("Validator=%s proposing block=%s with attestations=%s"), proposer_index, block, block.body.attestations, ) for peer in self.peer_pool.connected_nodes.values(): peer = cast(BCCPeer, peer) self.logger.debug(bold_red("Sending block=%s to peer=%s"), block, peer) peer.sub_proto.send_new_block(block) self.chain.import_block(block) return block
def committee_index_beacon_attestation_validator( msg_forwarder: ID, msg: rpc_pb2.Message) -> bool: try: attestation = ssz.decode(msg.data, sedes=Attestation) except (TypeError, ssz.DeserializationError) as error: # Not correctly encoded logger.debug( bold_red("Failed to validate attestation=%s, error=%s"), encode_hex(msg.data), str(error), ) return False state_machine = chain.get_state_machine() state = chain.get_head_state() try: validate_subnet_id(attestation, subnet_id) validate_is_unaggregated(attestation) validate_voting_beacon_block(chain, attestation) validate_attestation_propagation_slot_range( state, attestation, ATTESTATION_PROPAGATION_SLOT_RANGE, ) validate_attestation_signature( state, attestation, CommitteeConfig(state_machine.config), ) except InvalidGossipMessage as error: logger.debug("%s", str(error)) return False else: return True
def format(self, record: logging.LogRecord) -> str: record.shortname = record.name.split('.')[-1] # type: ignore if record.levelno >= logging.ERROR: return bold_red(super().format(record)) elif record.levelno >= logging.WARNING: return bold_yellow(super().format(record)) else: return super().format(record)
def _broadcast_block(self, block: BaseBeaconBlock, from_peer: BCCPeer = None) -> None: """ Broadcast the block to peers, except for ``from_peer``. """ for peer in self._peer_pool.connected_nodes.values(): peer = cast(BCCPeer, peer) # skip the peer who send the block to us if from_peer is not None and peer == from_peer: continue self.logger.debug(bold_red("Send block=%s to peer=%s"), block, peer) peer.sub_proto.send_new_block(block=block)
def propose_block(self, slot: Slot, state: BeaconState, state_machine: BaseBeaconStateMachine, head_block: BaseBeaconBlock) -> BaseBeaconBlock: block = self._make_proposing_block(slot, state, state_machine, head_block) self.logger.debug(bold_green(f"proposing block, block={block}")) for peer in self.peer_pool.connected_nodes.values(): peer = cast(BCCPeer, peer) self.logger.debug(bold_red(f"sending block to peer={peer}")) peer.sub_proto.send_new_block(block) self.chain.import_block(block) return block
def _broadcast_attestations(self, attestations: Tuple[Attestation, ...], from_peer: BCCPeer = None) ->None: """ Broadcast the attestations to peers, except for ``from_peer``. """ for peer in self._peer_pool.connected_nodes.values(): peer = cast(BCCPeer, peer) # skip the peer who send the attestations to us if from_peer is not None and peer == from_peer: continue self.logger.debug(bold_red("Send attestations=%s to peer=%s"), attestations, peer) peer.sub_proto.send_attestation_records(attestations)
def _request_block_from_peers(self, block_root: Hash32) -> None: for peer in self._peer_pool.connected_nodes.values(): peer = cast(BCCPeer, peer) request_id = gen_request_id() self.logger.debug( bold_red( f"send block request to: request_id={request_id}, peer={peer}" )) self.map_request_id_block_root[request_id] = block_root peer.sub_proto.send_get_blocks( block_root, max_blocks=1, request_id=request_id, )
def _request_block_from_peers(self, block_root: Hash32) -> None: for peer in self._peer_pool.connected_nodes.values(): peer = cast(BCCPeer, peer) request_id = gen_request_id() self.logger.debug( bold_red("Send block request with request_id=%s root=%s to peer=%s"), request_id, encode_hex(block_root), peer, ) self.map_request_id_block_root[request_id] = block_root peer.sub_proto.send_get_blocks( block_root, max_blocks=1, request_id=request_id, )
def _broadcast_block(self, block: BaseBeaconBlock, from_peer: BCCPeer = None) -> None: """ Broadcast a block to the peers, except for ``from_peer``. """ for peer in self._peer_pool.connected_nodes.values(): peer = cast(BCCPeer, peer) # skip the peer who send the block to use if from_peer is not None and peer == from_peer: continue request_id = gen_request_id() self.logger.debug( bold_red( f"send block request to: request_id={request_id}, peer={peer}" )) peer.sub_proto.send_new_block(block=block)
def beacon_block_validator(msg_forwarder: ID, msg: rpc_pb2.Message) -> bool: try: block = ssz.decode(msg.data, BeaconBlock) except (TypeError, ssz.DeserializationError) as error: logger.debug( bold_red("Failed to decode block=%s, error=%s"), encode_hex(msg.data), str(error), ) return False state_machine = chain.get_state_machine(block.slot - 1) state = chain.get_head_state() try: run_validate_block_proposer_signature(state, state_machine, block) except InvalidGossipMessage as error: logger.debug("%s", str(error)) return False else: return True
async def attest(self, slot: Slot) -> Tuple[Attestation, ...]: attestations: Tuple[Attestation, ...] = () head = self.chain.get_canonical_head() state_machine = self.chain.get_state_machine() state = state_machine.state epoch = slot_to_epoch(slot, self.slots_per_epoch) validator_assignments = { validator_index: self._get_this_epoch_assignment( validator_index, epoch, ) for validator_index in self.validator_privkeys } attesting_validators = self._get_attesting_validator_and_shard( validator_assignments, slot, epoch, ) if len(attesting_validators) == 0: return () # Sort the attesting validators by shard sorted_attesting_validators = sorted( attesting_validators, key=itemgetter(1), ) # Group the attesting validators by shard attesting_validators_groups = groupby( sorted_attesting_validators, key=itemgetter(1), ) for shard, group in attesting_validators_groups: # Get the validator_index -> privkey map of the attesting validators attesting_validator_privkeys = { attesting_data[0]: self.validator_privkeys[attesting_data[0]] for attesting_data in group } attesting_validators_indices = tuple(attesting_validator_privkeys.keys()) # Get one of the attesting validator's assignment in order to get the committee info assignment = self._get_this_epoch_assignment( attesting_validators_indices[0], epoch, ) attestation = create_signed_attestation_at_slot( state, state_machine.config, state_machine, slot, head.signing_root, attesting_validator_privkeys, assignment.committee, shard, ) self.logger.debug( bold_green("Validators=%s attest to block=%s attestation=%s"), attesting_validators_indices, head, attestation, ) for validator_index in attesting_validators_indices: self.latest_attested_epoch[validator_index] = epoch attestations = attestations + (attestation,) for peer in self.peer_pool.connected_nodes.values(): peer = cast(BCCPeer, peer) self.logger.debug(bold_red("Sending attestations=%s to peer=%s"), attestations, peer) peer.sub_proto.send_attestation_records(attestations) return attestations