def validate_attestation_signature(state: BeaconState, attestation: Attestation, config: Eth2Config) -> None: indexed_attestation = get_indexed_attestation(state, attestation, config) validate_indexed_attestation_aggregate_signature(state, indexed_attestation, config.SLOTS_PER_EPOCH)
def validate_attestation(state: BeaconState, attestation: Attestation, config: Eth2Config) -> None: """ Validate the given ``attestation``. Raise ``ValidationError`` if it's invalid. """ _validate_attestation_data(state, attestation.data, config) validate_indexed_attestation( state, get_indexed_attestation(state, attestation, CommitteeConfig(config)), config.MAX_VALIDATORS_PER_COMMITTEE, config.SLOTS_PER_EPOCH, )
def validate_attestation( state: BeaconState, attestation: Attestation, config: Eth2Config ) -> None: """ Validate the given ``attestation``. Raise ``ValidationError`` if it's invalid. """ _validate_attestation_data(state, attestation.data, config) _validate_aggregation_bits(state, attestation, config) validate_indexed_attestation( state, get_indexed_attestation(state, attestation, config), config.SLOTS_PER_EPOCH, )
def on_attestation(self, attestation: Attestation, validate_signature: bool = True) -> None: target = attestation.data.target current_epoch = compute_epoch_at_slot(self.get_current_slot(), self._config.SLOTS_PER_EPOCH) previous_epoch = (current_epoch - 1 if current_epoch > self._config.GENESIS_EPOCH else self._config.GENESIS_EPOCH) if target.epoch not in (current_epoch, previous_epoch): raise ValidationError( "Attestations must be from the current or previous epoch") if target.root not in self._context.blocks: raise ValidationError( "Attestation targets a block we have not seen") base_state = self._context.block_states[target.root] time_of_target_epoch = ( base_state.genesis_time + compute_start_slot_at_epoch( target.epoch, self._config.SLOTS_PER_EPOCH) * self._config.SECONDS_PER_SLOT) if self._context.time < time_of_target_epoch: raise ValidationError("Attestation cannot be for a future epoch") beacon_block_root = attestation.data.beacon_block_root if beacon_block_root not in self._context.blocks: raise ValidationError("Attestations must be for a known block") if self._context.blocks[beacon_block_root].slot > attestation.data.slot: raise ValidationError( "Attestations must not be for a block in the future") if target not in self._context.checkpoint_states: base_state = process_slots( base_state, compute_start_slot_at_epoch(target.epoch, self._config.SLOTS_PER_EPOCH), self._config, ) self._context.checkpoint_states[target] = base_state target_state = self._context.checkpoint_states[target] if (self._context.time < (attestation.data.slot + 1) * self._config.SECONDS_PER_SLOT): raise ValidationError( "Attestations can only affect the fork choice of future slots") # TODO: has this validation already been performed? indexed_attestation = get_indexed_attestation( target_state, attestation, CommitteeConfig(self._config)) validate_indexed_attestation( target_state, indexed_attestation, self._config.MAX_VALIDATORS_PER_COMMITTEE, self._config.SLOTS_PER_EPOCH, validate_signature=validate_signature, ) for i in indexed_attestation.attesting_indices: if (i not in self._context.latest_messages or target.epoch > self._context.latest_messages[i].epoch): self._context.latest_messages[i] = LatestMessage( epoch=target.epoch, root=attestation.data.beacon_block_root)