示例#1
0
    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
示例#2
0
    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
示例#3
0
    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
示例#4
0
    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
示例#5
0
 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
示例#6
0
    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
示例#7
0
    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)
示例#8
0
 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)
示例#9
0
 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
示例#10
0
 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)
示例#11
0
 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,
         )
示例#12
0
    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,
            )
示例#13
0
 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)
示例#14
0
    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
示例#15
0
    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