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 = alice.chain.get_head_state() epoch = compute_epoch_at_slot(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 attestation.data.slot == assignment.slot assert attestation.data.beacon_block_root == head.signing_root assert attestation.data.index == assignment.committee_index # 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, )
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
async def test_validator_aggregate(event_loop, event_bus, monkeypatch): num_validators = 50 alice_indices = [i for i in range(num_validators)] alice = await get_validator( event_loop=event_loop, event_bus=event_bus, monkeypatch=monkeypatch, indices=alice_indices, num_validators=num_validators, ) alice.skip_block( slot=alice.chain.get_canonical_head().slot + 100, state=alice.chain.get_head_state(), state_machine=alice.chain.get_state_machine(), ) state_machine = alice.chain.get_state_machine() state = alice.chain.get_head_state() head = alice.chain.get_canonical_head() epoch = compute_epoch_at_slot(state.slot, state_machine.config.SLOTS_PER_EPOCH) assignment = alice._get_local_current_epoch_assignment( alice_indices[0], epoch) attested_attsetation = await alice.attest(assignment.slot) assert len(attested_attsetation) >= 1 aggregate_and_proofs = await alice.aggregate(assignment.slot) assert len(aggregate_and_proofs) >= 1 for aggregate_and_proof in aggregate_and_proofs: attestation = aggregate_and_proof.aggregate assert attestation.data.slot == assignment.slot assert attestation.data.beacon_block_root == head.signing_root assert attestation.data.index == assignment.committee_index # 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, )
def _validate_attestations(self, attestations: Iterable[Attestation]) -> Iterable[Attestation]: state_machine = self.chain.get_state_machine() config = state_machine.config state = state_machine.state for attestation in attestations: # Fast forward to state in future slot in order to pass # attestation.data.slot validity check future_state = state_machine.state_transition.apply_state_transition_without_block( state, attestation.data.slot + config.MIN_ATTESTATION_INCLUSION_DELAY, ) try: validate_attestation( future_state, attestation, config.MIN_ATTESTATION_INCLUSION_DELAY, config.SLOTS_PER_HISTORICAL_ROOT, CommitteeConfig(config), ) yield attestation except ValidationError: pass
def _validate_attestations( self, attestations: Iterable[Attestation]) -> Iterable[Attestation]: state_machine = self.chain.get_state_machine() config = state_machine.config state = state_machine.state for attestation in attestations: # Fast forward to state in future slot in order to pass # attestation.data.slot validity check future_state = state_machine.state_transition.apply_state_transition( state, future_slot=attestation.data.slot + config.MIN_ATTESTATION_INCLUSION_DELAY, ) try: validate_attestation( future_state, attestation, config, ) yield attestation except ValidationError: pass