Example #1
0
def test_get_committee_assignment_no_assignment(genesis_state, genesis_epoch,
                                                slots_per_epoch, config):
    state = genesis_state
    validator_index = 1
    current_epoch = state.current_epoch(slots_per_epoch)
    validator = state.validators[validator_index].copy(
        exit_epoch=genesis_epoch)
    state = state.update_validator(validator_index, validator)
    assert not validator.is_active(current_epoch)

    with pytest.raises(NoCommitteeAssignment):
        get_committee_assignment(state, config, current_epoch, validator_index)
Example #2
0
def test_get_committee_assignment_no_assignment(genesis_state, genesis_epoch,
                                                slots_per_epoch, config):
    state = genesis_state
    validator_index = 1
    current_epoch = state.current_epoch(slots_per_epoch)
    validator = state.validators[validator_index].set("exit_epoch",
                                                      genesis_epoch)
    state = state.transform(["validators", validator_index], validator)
    assert not validator.is_active(current_epoch)

    with pytest.raises(NoCommitteeAssignment):
        get_committee_assignment(state, config, current_epoch, validator_index)
Example #3
0
    def get_attestation(self, public_key: BLSPubkey, slot: Slot,
                        committee_index: CommitteeIndex) -> Attestation:
        current_tick = self.clock.compute_current_tick()
        state = advance_state_to_slot(self.chain, current_tick.slot)
        block = self.chain.get_block_by_slot(slot)
        if not block:
            # try to find earlier block, assuming skipped slots
            block = self.chain.get_canonical_head()
            # sanity check the assumption in this leg of the conditional
            assert block.slot < slot
        else:
            block = block.message

        target_checkpoint = _get_target_checkpoint(state, block.hash_tree_root,
                                                   self.eth2_config)
        data = AttestationData.create(
            slot=slot,
            index=committee_index,
            beacon_block_root=block.hash_tree_root,
            source=state.current_justified_checkpoint,
            target=target_checkpoint,
        )

        validator_index = state.get_validator_index_for_public_key(public_key)
        epoch = compute_epoch_at_slot(slot, self.eth2_config.SLOTS_PER_EPOCH)
        committee_assignment = get_committee_assignment(
            state, self.eth2_config, epoch, validator_index)
        committee = committee_assignment.committee
        committee_validator_index = committee.index(validator_index)
        aggregation_bits = Bitfield(
            tuple(i == committee_validator_index
                  for i in range(len(committee))))
        return Attestation.create(aggregation_bits=aggregation_bits, data=data)
Example #4
0
    def get_validator_duties(self, public_keys: Collection[BLSPubkey],
                             epoch: Epoch) -> Iterable[ValidatorDuty]:
        if epoch < GENESIS_EPOCH:
            return ()

        current_tick = self.clock.compute_current_tick()
        state = advance_state_to_slot(self.chain, current_tick.slot)
        for public_key in public_keys:
            validator_index = state.get_validator_index_for_public_key(
                public_key)
            try:
                committee_assignment = get_committee_assignment(
                    state, self.eth2_config, epoch, validator_index)
            except NoCommitteeAssignment:
                continue

            if is_proposer(state, validator_index, self.eth2_config):
                # TODO (ralexstokes) clean this up!
                if state.slot != 0:
                    block_proposal_slot = state.slot
                else:
                    block_proposal_slot = Slot((1 << 64) - 1)
            else:
                # NOTE: temporary sentinel value for "no slot"
                # The API has since been updated w/ much better ergonomics
                block_proposal_slot = Slot((1 << 64) - 1)
            yield ValidatorDuty(
                public_key,
                committee_assignment.slot,
                committee_assignment.committee_index,
                block_proposal_slot,
            )
Example #5
0
    def _get_local_current_epoch_assignment(
        self, validator_index: ValidatorIndex, epoch: Epoch
    ) -> CommitteeAssignment:
        """
        Return the validator's epoch assignment at the given epoch.

        Note that ``epoch`` <= next_epoch.
        """
        is_new_local_validator = (
            validator_index not in self.local_validator_epoch_assignment
        )
        should_update = is_new_local_validator or (
            not is_new_local_validator
            and (epoch > self.local_validator_epoch_assignment[validator_index][0])
        )
        if should_update:
            state_machine = self.chain.get_state_machine()
            state = self.chain.get_head_state()
            self.local_validator_epoch_assignment[validator_index] = (
                epoch,
                get_committee_assignment(
                    state, state_machine.config, epoch, validator_index
                ),
            )
        return self.local_validator_epoch_assignment[validator_index][1]
Example #6
0
def test_get_committee_assignment(
    genesis_state,
    slots_per_epoch,
    shard_count,
    config,
    validator_count,
    state_epoch,
    epoch,
    fixture_sm_class,
):
    state_slot = compute_start_slot_of_epoch(state_epoch, slots_per_epoch)
    state = genesis_state.copy(slot=state_slot)
    proposer_count = 0
    shard_validator_count = [0 for _ in range(shard_count)]
    slots = []

    epoch_start_slot = compute_start_slot_of_epoch(epoch, slots_per_epoch)

    for validator_index in range(validator_count):
        assignment = get_committee_assignment(state, config, epoch,
                                              validator_index)
        assert assignment.slot >= epoch_start_slot
        assert assignment.slot < epoch_start_slot + slots_per_epoch
        if assignment.is_proposer:
            proposer_count += 1

        shard_validator_count[assignment.shard] += 1
        slots.append(assignment.slot)

    assert proposer_count == slots_per_epoch
    assert sum(shard_validator_count) == validator_count
Example #7
0
def test_get_committee_assignment(
    genesis_state,
    slots_per_epoch,
    max_committees_per_slot,
    config,
    validator_count,
    state_epoch,
    epoch,
):
    state_slot = compute_start_slot_at_epoch(state_epoch, slots_per_epoch)
    state = genesis_state.set("slot", state_slot)
    committee_validator_count = [0 for _ in range(max_committees_per_slot)]
    slots = []

    epoch_start_slot = compute_start_slot_at_epoch(epoch, slots_per_epoch)

    for validator_index in range(validator_count):
        assignment = get_committee_assignment(state, config, epoch,
                                              validator_index)
        assert assignment.slot >= epoch_start_slot
        assert assignment.slot < epoch_start_slot + slots_per_epoch

        committee_validator_count[assignment.committee_index] += 1
        slots.append(assignment.slot)

    assert sum(committee_validator_count) == validator_count
Example #8
0
 def _get_this_epoch_assignment(self, validator_index: ValidatorIndex,
                                this_epoch: Epoch) -> CommitteeAssignment:
     # update `this_epoch_assignment` if it's outdated
     if this_epoch > self.this_epoch_assignment[validator_index][0]:
         state_machine = self.chain.get_state_machine()
         state = self.chain.get_head_state()
         self.this_epoch_assignment[validator_index] = (
             this_epoch,
             get_committee_assignment(
                 state,
                 state_machine.config,
                 this_epoch,
                 validator_index,
             ))
     return self.this_epoch_assignment[validator_index][1]
Example #9
0
def _get_slot_with_validator_selected(candidate_indices, state, config):
    epoch = state.current_epoch(config.SLOTS_PER_EPOCH)

    for index in candidate_indices:
        try:
            committee, shard, slot, is_proposer = get_committee_assignment(
                state,
                config,
                epoch,
                index,
            )
            if is_proposer:
                return slot, index
        except NoCommitteeAssignment:
            continue
    raise Exception(
        "Check the parameters of the genesis state; the above code should return"
        " some proposer if the set of ``candidate_indices`` is big enough.")