示例#1
0
def _validate_attestation_data(state: BeaconState, data: AttestationData,
                               config: Eth2Config) -> None:
    slots_per_epoch = config.SLOTS_PER_EPOCH
    current_epoch = state.current_epoch(slots_per_epoch)
    previous_epoch = state.previous_epoch(slots_per_epoch,
                                          config.GENESIS_EPOCH)

    attestation_slot = get_attestation_data_slot(state, data, config)

    if data.target.epoch == current_epoch:
        expected_checkpoint = state.current_justified_checkpoint
        parent_crosslink = state.current_crosslinks[data.crosslink.shard]
    else:
        expected_checkpoint = state.previous_justified_checkpoint
        parent_crosslink = state.previous_crosslinks[data.crosslink.shard]

    _validate_eligible_shard_number(data.crosslink.shard, config.SHARD_COUNT)
    _validate_eligible_target_epoch(data.target.epoch, current_epoch,
                                    previous_epoch)
    validate_attestation_slot(
        attestation_slot,
        state.slot,
        slots_per_epoch,
        config.MIN_ATTESTATION_INCLUSION_DELAY,
    )
    _validate_checkpoint(data.source, expected_checkpoint)
    _validate_crosslink(
        data.crosslink,
        data.target.epoch,
        parent_crosslink,
        config.MAX_EPOCHS_PER_CROSSLINK,
    )
示例#2
0
async def test_validator_attest(event_loop, event_bus, monkeypatch):
    alice_indices = [i for i in range(8)]
    alice = await get_validator(event_loop=event_loop,
                                event_bus=event_bus,
                                indices=alice_indices)
    head = alice.chain.get_canonical_head()
    state_machine = alice.chain.get_state_machine()
    state = state_machine.state

    epoch = slot_to_epoch(state.slot, state_machine.config.SLOTS_PER_EPOCH)
    assignment = alice._get_this_epoch_assignment(alice_indices[0], epoch)

    attestations = await alice.attest(assignment.slot)
    assert len(attestations) == 1
    attestation = attestations[0]
    assert get_attestation_data_slot(
        state,
        attestation.data,
        state_machine.config,
    ) == assignment.slot
    assert attestation.data.beacon_block_root == head.signing_root
    assert attestation.data.crosslink.shard == assignment.shard

    # Advance the state and validate the attestation
    config = state_machine.config
    future_state = state_machine.state_transition.apply_state_transition(
        state,
        future_slot=assignment.slot + config.MIN_ATTESTATION_INCLUSION_DELAY,
    )
    validate_attestation(
        future_state,
        attestation,
        config,
    )
示例#3
0
 def _find_attestation_targets(self):
     result = {}
     for _, attestation in self._attestation_pool:
         target_slot = get_attestation_data_slot(self._state,
                                                 attestation.data,
                                                 self._config)
         for validator_index in _iter_attestation_by_validator_index(
                 self._state, attestation, self._config):
             if validator_index in result:
                 existing = result[validator_index]
                 existing_slot = get_attestation_data_slot(
                     self._state, existing.data, self._config)
                 if existing_slot > target_slot:
                     continue
             result[validator_index] = attestation
     return result
示例#4
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
示例#5
0
def get_matching_head_attestations(
        state: BeaconState, epoch: Epoch,
        config: Eth2Config) -> Iterable[PendingAttestation]:
    for a in get_matching_source_attestations(state, epoch, config):
        beacon_block_root = get_block_root_at_slot(
            state,
            get_attestation_data_slot(state, a.data, config),
            config.SLOTS_PER_HISTORICAL_ROOT,
        )
        if a.data.beacon_block_root == beacon_block_root:
            yield a
示例#6
0
def _mk_attestation_inputs_in_epoch(epoch, state, config):
    active_validators_indices = get_active_validator_indices(state.validators, epoch)
    epoch_committee_count = get_committee_count(
        len(active_validators_indices),
        config.SHARD_COUNT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    )
    epoch_start_shard = get_start_shard(
        state,
        epoch,
        CommitteeConfig(config),
    )
    for shard_offset in random.sample(range(epoch_committee_count), epoch_committee_count):
        shard = Shard((epoch_start_shard + shard_offset) % config.SHARD_COUNT)
        committee = get_crosslink_committee(
            state,
            epoch,
            shard,
            CommitteeConfig(config),
        )

        if not committee:
            # empty crosslink committee this epoch
            continue

        attestation_data = AttestationData(
            target=Checkpoint(
                epoch=epoch,
            ),
            crosslink=Crosslink(
                shard=shard,
            ),
        )
        committee_count = len(committee)
        aggregation_bits = bitfield.get_empty_bitfield(committee_count)
        for index in range(committee_count):
            aggregation_bits = bitfield.set_voted(aggregation_bits, index)

            for index in committee:
                yield (
                    index,
                    (
                        get_attestation_data_slot(
                            state,
                            attestation_data,
                            config,
                        ),
                        (
                            aggregation_bits,
                            attestation_data,
                        ),
                    ),
                )
示例#7
0
    def _mk_pre_index_from_attestation(
            self, state: BeaconState,
            attestation: AttestationLike) -> Iterable[PreIndex]:
        attestation_data = attestation.data
        slot = get_attestation_data_slot(state, attestation_data, self._config)

        return ({
            index: (slot, attestation_data)
        } for index in get_attesting_indices(
            state,
            attestation.data,
            attestation.aggregation_bits,
            CommitteeConfig(self._config),
        ))
示例#8
0
 def get_ready_attestations(self) -> Iterable[Attestation]:
     config = self.chain.get_state_machine().config
     state = self.chain.get_head_state()
     for attestation in self.attestation_pool.get_all():
         data = attestation.data
         attestation_slot = get_attestation_data_slot(state, data, config)
         try:
             validate_attestation_slot(
                 attestation_slot,
                 state.slot,
                 config.SLOTS_PER_EPOCH,
                 config.MIN_ATTESTATION_INCLUSION_DELAY,
             )
         except ValidationError:
             continue
         else:
             yield attestation
示例#9
0
def process_attestations(state: BeaconState, block: BaseBeaconBlock,
                         config: Eth2Config) -> BeaconState:
    if len(block.body.attestations) > config.MAX_ATTESTATIONS:
        raise ValidationError(
            f"The block has too many attestations:\n"
            f"\tFound {len(block.body.attestations)} attestations, "
            f"maximum: {config.MAX_ATTESTATIONS}")

    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    new_current_epoch_attestations: Tuple[PendingAttestation, ...] = tuple()
    new_previous_epoch_attestations: Tuple[PendingAttestation, ...] = tuple()
    for attestation in block.body.attestations:
        validate_attestation(
            state,
            attestation,
            config,
        )

        attestation_slot = get_attestation_data_slot(
            state,
            attestation.data,
            config,
        )
        proposer_index = get_beacon_proposer_index(
            state,
            CommitteeConfig(config),
        )
        pending_attestation = PendingAttestation(
            aggregation_bits=attestation.aggregation_bits,
            data=attestation.data,
            inclusion_delay=state.slot - attestation_slot,
            proposer_index=proposer_index,
        )

        if attestation.data.target.epoch == current_epoch:
            new_current_epoch_attestations += (pending_attestation, )
        else:
            new_previous_epoch_attestations += (pending_attestation, )

    return state.copy(
        current_epoch_attestations=(state.current_epoch_attestations +
                                    new_current_epoch_attestations),
        previous_epoch_attestations=(state.previous_epoch_attestations +
                                     new_previous_epoch_attestations),
    )
示例#10
0
 def get_ready_attestations(self) -> Iterable[Attestation]:
     state_machine = self.chain.get_state_machine()
     config = state_machine.config
     state = state_machine.state
     for attestation in self.attestation_pool.get_all():
         data = attestation.data
         attestation_slot = get_attestation_data_slot(state, data, config)
         try:
             validate_attestation_slot(
                 attestation_slot,
                 state.slot,
                 config.SLOTS_PER_EPOCH,
                 config.MIN_ATTESTATION_INCLUSION_DELAY,
             )
         except ValidationError:
             # TODO: Should clean up attestations with invalid slot because
             # they are no longer available for inclusion into block.
             continue
         else:
             yield attestation