Example #1
0
async def validate_peer_status(chain: BaseBeaconChain,
                               peer_status: Status) -> None:
    state_machine = chain.get_state_machine()
    state = chain.get_head_state()
    config = state_machine.config
    if peer_status.head_fork_version != state.fork.current_version:
        raise IrrelevantNetwork(
            "`fork_version` mismatches: "
            f"peer_status.head_fork_version={peer_status.head_fork_version}, "
            f"state.fork.current_version={state.fork.current_version}")

    # Can not validate the checkpoint with `finalized_epoch` higher than ours
    if peer_status.finalized_epoch > state.finalized_checkpoint.epoch:
        return

    # Edge case where nothing is finalized yet
    if (peer_status.finalized_epoch == 0
            and peer_status.finalized_root == ZERO_ROOT):
        return

    finalized_epoch_start_slot = compute_start_slot_at_epoch(
        peer_status.finalized_epoch,
        config.SLOTS_PER_EPOCH,
    )
    finalized_root = chain.get_canonical_block_root(finalized_epoch_start_slot)

    if peer_status.finalized_root != finalized_root:
        raise IrrelevantNetwork(
            "`finalized_root` mismatches: "
            f"peer_status.finalized_root={peer_status.finalized_root.hex()}, "
            f"peer_status.finalized_epoch={peer_status.finalized_epoch}, "
            f"our `finalized_root` at the same `finalized_epoch`={finalized_root.hex()}"
        )
Example #2
0
def peer_is_ahead(chain: BaseBeaconChain, peer_status: Status) -> bool:
    checkpoint = chain.get_head_state().finalized_checkpoint
    head_block = chain.get_canonical_head()

    peer_has_higher_finalized_epoch = peer_status.finalized_epoch > checkpoint.epoch
    peer_has_equal_finalized_epoch = peer_status.finalized_epoch == checkpoint.epoch
    peer_has_higher_head_slot = peer_status.head_slot > head_block.slot
    return (peer_has_higher_finalized_epoch
            or (peer_has_equal_finalized_epoch and peer_has_higher_head_slot))
 def __init__(self,
              chain: BaseBeaconChain,
              event_bus: EndpointAPI,
              token: CancelToken = None) -> None:
     super().__init__(token)
     self.genesis_time = chain.get_head_state().genesis_time
     self.chain = chain
     self.event_bus = event_bus
     config = self.chain.get_state_machine().config
     self.slots_per_epoch = config.SLOTS_PER_EPOCH
Example #4
0
def validate_start_slot(chain: BaseBeaconChain, start_slot: Slot) -> None:
    config = chain.get_state_machine().config
    state = chain.get_head_state()
    finalized_epoch_start_slot = compute_start_slot_at_epoch(
        epoch=state.finalized_checkpoint.epoch,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )
    if start_slot < finalized_epoch_start_slot:
        raise ValidationError(
            f"`start_slot`({start_slot}) lower than our"
            f" latest finalized slot({finalized_epoch_start_slot})")
Example #5
0
def get_my_status(chain: BaseBeaconChain) -> Status:
    state = chain.get_head_state()
    head = chain.get_canonical_head()
    finalized_checkpoint = state.finalized_checkpoint
    return Status.create(
        head_fork_version=state.fork.current_version,
        finalized_root=finalized_checkpoint.root,
        finalized_epoch=finalized_checkpoint.epoch,
        head_root=head.message.hash_tree_root,
        head_slot=head.slot,
    )
Example #6
0
    def __init__(
            self,
            chain: BaseBeaconChain,
            p2p_node: Node,
            event_bus: EndpointAPI,
            get_ready_attestations_fn: GetReadyAttestationsFn,
            get_aggregatable_attestations_fn: GetAggregatableAttestationsFn,
            import_attestation_fn: ImportAttestationFn,
            token: CancelToken = None) -> None:
        super().__init__(token)
        self.genesis_time = chain.get_head_state().genesis_time
        self.chain = chain
        self.p2p_node = p2p_node
        self.event_bus = event_bus
        self.get_ready_attestations: GetReadyAttestationsFn = get_ready_attestations_fn
        self.get_aggregatable_attestations: GetAggregatableAttestationsFn = get_aggregatable_attestations_fn  # noqa: E501
        self.import_attestation: ImportAttestationFn = import_attestation_fn

        # `state.eth1_data` can be updated in the middle of voting period and thus
        # the starting `eth1_data.block_hash` must be stored separately.
        self.starting_eth1_block_hash = chain.get_head_state(
        ).eth1_data.block_hash
Example #7
0
    def __init__(
            self,
            chain: BaseBeaconChain,
            p2p_node: Node,
            validator_privkeys: Dict[ValidatorIndex, int],
            event_bus: EndpointAPI,
            get_ready_attestations_fn: GetReadyAttestationsFn,
            get_aggregatable_attestations_fn: GetAggregatableAttestationsFn,
            import_attestation_fn: ImportAttestationFn,
            token: CancelToken = None) -> None:
        super().__init__(token)
        self.genesis_time = chain.get_head_state().genesis_time
        self.chain = chain
        self.p2p_node = p2p_node
        self.validator_privkeys = validator_privkeys
        self.event_bus = event_bus
        config = self.chain.get_state_machine().config
        self.slots_per_epoch = config.SLOTS_PER_EPOCH
        # TODO: `latest_proposed_epoch` and `latest_attested_epoch` should be written
        # into/read from validator's own db.
        self.latest_proposed_epoch = {}
        self.latest_attested_epoch = {}
        self.local_validator_epoch_assignment = {}
        for validator_index in validator_privkeys:
            self.latest_proposed_epoch[validator_index] = Epoch(-1)
            self.latest_attested_epoch[validator_index] = Epoch(-1)
            self.local_validator_epoch_assignment[validator_index] = (
                Epoch(-1),
                CommitteeAssignment((), CommitteeIndex(-1), Slot(-1)),
            )
        self.get_ready_attestations: GetReadyAttestationsFn = get_ready_attestations_fn
        self.get_aggregatable_attestations: GetAggregatableAttestationsFn = get_aggregatable_attestations_fn  # noqa: E501
        self.import_attestation: ImportAttestationFn = import_attestation_fn

        # `state.eth1_data` can be updated in the middle of voting period and thus
        # the starting `eth1_data.block_hash` must be stored separately.
        self.starting_eth1_block_hash = chain.get_head_state(
        ).eth1_data.block_hash
Example #8
0
def compare_chain_tip_and_finalized_epoch(chain: BaseBeaconChain,
                                          peer_status: Status) -> None:
    checkpoint = chain.get_head_state().finalized_checkpoint
    head_block = chain.get_canonical_head()

    peer_has_higher_finalized_epoch = peer_status.finalized_epoch > checkpoint.epoch
    peer_has_equal_finalized_epoch = peer_status.finalized_epoch == checkpoint.epoch
    peer_has_higher_head_slot = peer_status.head_slot > head_block.slot
    if (peer_has_higher_finalized_epoch
            or (peer_has_equal_finalized_epoch and peer_has_higher_head_slot)):
        # TODO: kickoff syncing process with this peer
        logger.debug(
            "Peer's chain is ahead of us, start syncing with the peer.")
        pass