コード例 #1
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
コード例 #2
0
def create_mock_slashable_attestation(
    state: BeaconState,
    config: Eth2Config,
    keymap: Dict[BLSPubkey, int],
    attestation_slot: Slot,
) -> IndexedAttestation:
    """
    Create an `IndexedAttestation` that is signed by one attester.
    """
    attester_index = ValidatorIndex(0)
    committee = (attester_index, )
    shard = Shard(0)

    # Use genesis block root as `beacon_block_root`, only for tests.
    beacon_block_root = get_block_root_at_slot(
        state, attestation_slot, config.SLOTS_PER_HISTORICAL_ROOT)

    # Get `target_root`
    target_root = _get_target_root(state, config, beacon_block_root)
    # Get `source_root`
    source_root = get_block_root_at_slot(
        state,
        compute_start_slot_of_epoch(state.current_justified_checkpoint.epoch,
                                    config.SLOTS_PER_EPOCH),
        config.SLOTS_PER_HISTORICAL_ROOT,
    )
    previous_crosslink = state.current_crosslinks[shard]

    attestation_data = AttestationData(
        beacon_block_root=beacon_block_root,
        source=Checkpoint(epoch=state.current_justified_checkpoint.epoch,
                          root=source_root),
        target=Checkpoint(
            epoch=compute_epoch_of_slot(attestation_slot,
                                        config.SLOTS_PER_EPOCH),
            root=target_root,
        ),
        crosslink=previous_crosslink,
    )

    message_hash = _get_mock_message(attestation_data)
    attesting_indices = _get_mock_attesting_indices(committee,
                                                    num_voted_attesters=1)

    signature = sign_transaction(
        message_hash=message_hash,
        privkey=keymap[state.validators[attesting_indices[0]].pubkey],
        state=state,
        slot=attestation_slot,
        signature_domain=SignatureDomain.DOMAIN_ATTESTATION,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )
    validator_indices = tuple(committee[i] for i in attesting_indices)

    return IndexedAttestation(
        custody_bit_0_indices=validator_indices,
        custody_bit_1_indices=tuple(),
        data=attestation_data,
        signature=signature,
    )
コード例 #3
0
def get_attestation_data_slot(state: BeaconState,
                              data: AttestationData,
                              config: Eth2Config) -> Slot:
    active_validator_indices = get_active_validator_indices(
        state.validators,
        data.target.epoch,
    )
    committee_count = get_committee_count(
        len(active_validator_indices),
        config.SHARD_COUNT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    )
    offset = (
        data.crosslink.shard + config.SHARD_COUNT - get_start_shard(
            state,
            data.target.epoch,
            CommitteeConfig(config),
        )
    ) % config.SHARD_COUNT
    committees_per_slot = committee_count // config.SLOTS_PER_EPOCH
    return compute_start_slot_of_epoch(
        data.target.epoch,
        config.SLOTS_PER_EPOCH,
    ) + offset // committees_per_slot
コード例 #4
0
def test_get_matching_head_attestations(genesis_state, config):
    some_epoch = config.GENESIS_EPOCH + 20
    some_slot = (
        compute_start_slot_of_epoch(some_epoch, config.SLOTS_PER_EPOCH) +
        config.SLOTS_PER_EPOCH // 4)
    some_target_root = b"\x33" * 32
    target_attestations = tuple((PendingAttestation(data=AttestationData(
        beacon_block_root=some_target_root,
        target=Checkpoint(epoch=some_epoch - 1),
        crosslink=Crosslink(shard=i),
    )) for i in range(3)))
    current_epoch_attestations = target_attestations + tuple(
        (PendingAttestation(data=AttestationData(
            beacon_block_root=b"\x44" * 32,
            target=Checkpoint(epoch=some_epoch - 1),
        )) for _ in range(3)))
    state = genesis_state.copy(
        slot=some_slot - 1,
        block_roots=tuple(some_target_root
                          for _ in range(config.SLOTS_PER_HISTORICAL_ROOT)),
        current_epoch_attestations=current_epoch_attestations,
    )

    attestations = get_matching_head_attestations(state, some_epoch, config)

    assert attestations == target_attestations
コード例 #5
0
def test_get_unslashed_attesting_indices(genesis_state, config):
    state = genesis_state.copy(
        slot=compute_start_slot_of_epoch(3, config.SLOTS_PER_EPOCH))
    target_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    target_shard = (state.start_shard + 3) % config.SHARD_COUNT
    some_committee = get_crosslink_committee(state, target_epoch, target_shard,
                                             CommitteeConfig(config))

    data = AttestationData(target=Checkpoint(epoch=target_epoch),
                           crosslink=Crosslink(shard=target_shard))
    some_subset_count = random.randrange(1, len(some_committee) // 2)
    some_subset = random.sample(some_committee, some_subset_count)

    bitfield = get_empty_bitfield(len(some_committee))
    for i, index in enumerate(some_committee):
        if index in some_subset:
            if random.choice([True, False]):
                state = state.update_validator_with_fn(
                    index, lambda v, *_: v.copy(slashed=True))
            bitfield = set_voted(bitfield, i)

    some_subset = tuple(
        filter(lambda index: not state.validators[index].slashed, some_subset))

    indices = get_unslashed_attesting_indices(
        state,
        (PendingAttestation(data=data, aggregation_bits=bitfield), ),
        CommitteeConfig(config),
    )

    assert set(indices) == set(some_subset)
    assert len(indices) == len(some_subset)
コード例 #6
0
def test_get_matching_source_attestations(genesis_state, current_epoch,
                                          target_epoch, success, config):
    state = genesis_state.copy(
        slot=compute_start_slot_of_epoch(current_epoch,
                                         config.SLOTS_PER_EPOCH),
        current_epoch_attestations=tuple(
            PendingAttestation(data=AttestationData(
                beacon_block_root=current_epoch.to_bytes(32, "little")))),
        previous_epoch_attestations=tuple(
            PendingAttestation(data=AttestationData(
                beacon_block_root=(current_epoch -
                                   1).to_bytes(32, "little")))),
    )

    if success:
        attestations = get_matching_source_attestations(
            state, target_epoch, config)
    else:
        with pytest.raises(InvalidEpochError):
            get_matching_source_attestations(state, target_epoch, config)
        return

    if current_epoch == target_epoch:
        assert attestations == state.current_epoch_attestations
    else:
        assert attestations == state.previous_epoch_attestations
コード例 #7
0
ファイル: validator.py プロジェクト: AndrewBezold/trinity
def create_mock_attester_slashing_is_surround_vote(
    state: BeaconState,
    config: Eth2Config,
    keymap: Dict[BLSPubkey, int],
    attestation_epoch: Epoch,
) -> AttesterSlashing:
    # target_epoch_2 < target_epoch_1
    attestation_slot_2 = compute_start_slot_of_epoch(attestation_epoch,
                                                     config.SLOTS_PER_EPOCH)
    attestation_slot_1 = Slot(attestation_slot_2 + config.SLOTS_PER_EPOCH)

    slashable_attestation_1 = create_mock_slashable_attestation(
        state.copy(slot=attestation_slot_1,
                   current_justified_epoch=config.GENESIS_EPOCH),
        config,
        keymap,
        attestation_slot_1,
    )
    slashable_attestation_2 = create_mock_slashable_attestation(
        state.copy(
            slot=attestation_slot_1,
            current_justified_epoch=config.GENESIS_EPOCH +
            1,  # source_epoch_1 < source_epoch_2
        ),
        config,
        keymap,
        attestation_slot_2,
    )

    return AttesterSlashing(attestation_1=slashable_attestation_1,
                            attestation_2=slashable_attestation_2)
コード例 #8
0
def test_validate_validator_minimum_lifespan(
    genesis_state,
    keymap,
    current_epoch,
    activation_epoch,
    slots_per_epoch,
    persistent_committee_period,
    success,
):
    state = genesis_state.copy(
        slot=compute_start_slot_of_epoch(current_epoch, slots_per_epoch))
    validator_index = 0
    validator = state.validators[validator_index].copy(
        activation_epoch=activation_epoch)
    state = state.update_validator(validator_index, validator)

    if success:
        _validate_validator_minimum_lifespan(
            validator, state.current_epoch(slots_per_epoch),
            persistent_committee_period)
    else:
        with pytest.raises(ValidationError):
            _validate_validator_minimum_lifespan(
                validator,
                state.current_epoch(slots_per_epoch),
                persistent_committee_period,
            )
コード例 #9
0
def test_validate_eligible_exit_epoch(
    genesis_state,
    keymap,
    current_epoch,
    voluntary_exit_epoch,
    slots_per_epoch,
    config,
    success,
):
    state = genesis_state.copy(
        slot=compute_start_slot_of_epoch(current_epoch, slots_per_epoch))

    validator_index = 0
    voluntary_exit = create_mock_voluntary_exit(
        state,
        config,
        keymap,
        validator_index,
        exit_epoch=voluntary_exit_epoch)
    if success:
        _validate_eligible_exit_epoch(voluntary_exit.epoch,
                                      state.current_epoch(slots_per_epoch))
    else:
        with pytest.raises(ValidationError):
            _validate_eligible_exit_epoch(voluntary_exit.epoch,
                                          state.current_epoch(slots_per_epoch))
コード例 #10
0
ファイル: node.py プロジェクト: renaynay/trinity
    async def _validate_hello_req(self,
                                  hello_other_side: HelloRequest) -> None:
        state_machine = self.chain.get_state_machine()
        state = self.chain.get_head_state()
        config = state_machine.config
        if hello_other_side.fork_version != state.fork.current_version:
            raise ValidationError(
                "`fork_version` mismatches: "
                f"hello_other_side.fork_version={hello_other_side.fork_version}, "
                f"state.fork.current_version={state.fork.current_version}")

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

        # Get the finalized root at `hello_other_side.finalized_epoch`
        # Edge case where nothing is finalized yet
        if (hello_other_side.finalized_epoch == 0
                and hello_other_side.finalized_root == ZERO_SIGNING_ROOT):
            return

        finalized_epoch_start_slot = compute_start_slot_of_epoch(
            hello_other_side.finalized_epoch,
            config.SLOTS_PER_EPOCH,
        )
        finalized_root = self.chain.get_canonical_block_root(
            finalized_epoch_start_slot)

        if hello_other_side.finalized_root != finalized_root:
            raise ValidationError(
                "`finalized_root` mismatches: "
                f"hello_other_side.finalized_root={hello_other_side.finalized_root}, "
                f"hello_other_side.finalized_epoch={hello_other_side.finalized_epoch}, "
                f"our `finalized_root` at the same `finalized_epoch`={finalized_root}"
            )
コード例 #11
0
ファイル: utils.py プロジェクト: voith/trinity
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_SIGNING_ROOT):
        return

    finalized_epoch_start_slot = compute_start_slot_of_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}, "
            f"peer_status.finalized_epoch={peer_status.finalized_epoch}, "
            f"our `finalized_root` at the same `finalized_epoch`={finalized_root}"
        )
コード例 #12
0
def test_validate_attestation_data(genesis_state,
                                   sample_attestation_data_params,
                                   attestation_source_epoch,
                                   attestation_target_epoch,
                                   current_epoch,
                                   previous_justified_epoch,
                                   current_justified_epoch,
                                   slots_per_epoch,
                                   config,
                                   is_valid):
    state = genesis_state.copy(
        slot=compute_start_slot_of_epoch(current_epoch, slots_per_epoch) + 5,
        previous_justified_checkpoint=Checkpoint(
            epoch=previous_justified_epoch,
        ),
        current_justified_checkpoint=Checkpoint(
            epoch=current_justified_epoch,
        ),
    )
    start_shard = get_start_shard(
        state,
        current_epoch,
        CommitteeConfig(config),
    )
    if attestation_target_epoch == current_epoch:
        crosslinks = state.current_crosslinks
    else:
        crosslinks = state.previous_crosslinks

    parent_crosslink = crosslinks[start_shard]
    attestation_data = AttestationData(**sample_attestation_data_params).copy(
        source=Checkpoint(
            epoch=attestation_source_epoch,
        ),
        target=Checkpoint(
            epoch=attestation_target_epoch,
        ),
        crosslink=Crosslink(
            start_epoch=parent_crosslink.end_epoch,
            end_epoch=attestation_target_epoch,
            parent_root=parent_crosslink.hash_tree_root,
            shard=start_shard,
        ),
    )

    if is_valid:
        _validate_attestation_data(
            state,
            attestation_data,
            config,
        )
    else:
        with pytest.raises(ValidationError):
            _validate_attestation_data(
                state,
                attestation_data,
                config,
            )
コード例 #13
0
def test_validate_voluntary_exit(genesis_state, keymap, slots_per_epoch,
                                 persistent_committee_period, config):
    state = genesis_state.copy(slot=compute_start_slot_of_epoch(
        config.GENESIS_EPOCH + persistent_committee_period, slots_per_epoch))
    validator_index = 0
    valid_voluntary_exit = create_mock_voluntary_exit(state, config, keymap,
                                                      validator_index)
    validate_voluntary_exit(state, valid_voluntary_exit, slots_per_epoch,
                            persistent_committee_period)
コード例 #14
0
ファイル: utils.py プロジェクト: voith/trinity
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_of_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})")
コード例 #15
0
ファイル: validator.py プロジェクト: AndrewBezold/trinity
def _get_target_root(state: BeaconState, config: Eth2Config,
                     beacon_block_root: Hash32) -> Hash32:

    epoch = compute_epoch_of_slot(state.slot, config.SLOTS_PER_EPOCH)
    epoch_start_slot = compute_start_slot_of_epoch(epoch,
                                                   config.SLOTS_PER_EPOCH)
    if epoch_start_slot == state.slot:
        return beacon_block_root
    else:
        return get_block_root(state, epoch, config.SLOTS_PER_EPOCH,
                              config.SLOTS_PER_HISTORICAL_ROOT)
コード例 #16
0
def test_get_start_shard(genesis_state, current_epoch, target_epoch,
                         expected_epoch_start_shard, config):
    state = genesis_state.copy(slot=compute_start_slot_of_epoch(
        current_epoch, config.SLOTS_PER_EPOCH), )

    if expected_epoch_start_shard is None:
        with pytest.raises(ValidationError):
            get_start_shard(state, target_epoch, CommitteeConfig(config))
    else:
        epoch_start_shard = get_start_shard(state, target_epoch,
                                            CommitteeConfig(config))
        assert epoch_start_shard == expected_epoch_start_shard
コード例 #17
0
def test_get_seed(genesis_state,
                  committee_config,
                  slots_per_epoch,
                  min_seed_lookahead,
                  activation_exit_delay,
                  epochs_per_historical_vector):
    def mock_get_randao_mix(state,
                            epoch,
                            epochs_per_historical_vector):
        return hash_eth2(
            state.hash_tree_root +
            epoch.to_bytes(32, byteorder='little') +
            epochs_per_historical_vector.to_bytes(32, byteorder='little')
        )

    def mock_get_active_index_root(state,
                                   epoch,
                                   epochs_per_historical_vector):
        return hash_eth2(
            state.hash_tree_root +
            epoch.to_bytes(32, byteorder='little') +
            slots_per_epoch.to_bytes(32, byteorder='little') +
            epochs_per_historical_vector.to_bytes(32, byteorder='little')
        )

    state = genesis_state
    epoch = 1
    state = state.copy(
        slot=compute_start_slot_of_epoch(epoch, committee_config.SLOTS_PER_EPOCH),
    )

    epoch_as_bytes = epoch.to_bytes(32, 'little')

    seed = _get_seed(
        state=state,
        epoch=epoch,
        randao_provider=mock_get_randao_mix,
        active_index_root_provider=mock_get_active_index_root,
        epoch_provider=lambda *_: epoch_as_bytes,
        committee_config=committee_config,
    )
    assert seed == hash_eth2(
        mock_get_randao_mix(
            state=state,
            epoch=(epoch + epochs_per_historical_vector - min_seed_lookahead - 1),
            epochs_per_historical_vector=epochs_per_historical_vector,
        ) + mock_get_active_index_root(
            state=state,
            epoch=epoch,
            epochs_per_historical_vector=epochs_per_historical_vector,
        ) + epoch_as_bytes
    )
コード例 #18
0
def test_find_winning_crosslink_and_attesting_indices_from_candidates(
        genesis_state, number_of_candidates, config):
    some_epoch = config.GENESIS_EPOCH + 20
    some_shard = 3

    state = genesis_state.copy(
        slot=compute_start_slot_of_epoch(some_epoch, config.SLOTS_PER_EPOCH),
        start_shard=some_shard,
        current_crosslinks=tuple(
            Crosslink(shard=i, data_root=(i).to_bytes(32, "little"))
            for i in range(config.SHARD_COUNT)),
    )

    full_committee = get_crosslink_committee(state, some_epoch, some_shard,
                                             CommitteeConfig(config))

    # break the committees up into different subsets to simulate different
    # attestations for the same crosslink
    committees = tuple(
        random_sample(
            len(full_committee) // number_of_candidates, full_committee)
        for _ in range(number_of_candidates))
    seen = set()
    filtered_committees = tuple()
    for committee in committees:
        deduplicated_committee = tuple()
        for index in committee:
            if index in seen:
                pass
            else:
                seen.add(index)
                deduplicated_committee += (index, )
        filtered_committees += (deduplicated_committee, )

    candidates = tuple(
        mk_pending_attestation_from_committee(
            state.current_crosslinks[some_shard],
            len(full_committee),
            some_shard,
            target_epoch=some_epoch,
        ) for committee in filtered_committees)

    if number_of_candidates == 0:
        expected_result = (Crosslink(), set())
    else:
        expected_result = (candidates[0].data.crosslink,
                           set(sorted(full_committee)))

    result = _find_winning_crosslink_and_attesting_indices_from_candidates(
        state, candidates, config)
    assert result == expected_result
コード例 #19
0
ファイル: committee_assignment.py プロジェクト: voith/trinity
def get_committee_assignment(
    state: BeaconState,
    config: Eth2Config,
    epoch: Epoch,
    validator_index: ValidatorIndex,
) -> CommitteeAssignment:
    """
    Return the ``CommitteeAssignment`` in the ``epoch`` for ``validator_index``.
    ``CommitteeAssignment.committee`` is the tuple array of validators in the committee
    ``CommitteeAssignment.shard`` is the shard to which the committee is assigned
    ``CommitteeAssignment.slot`` is the slot at which the committee is assigned
    ``CommitteeAssignment.is_proposer`` is a bool signalling if the validator is expected to
        propose a beacon block at the assigned slot.
    """
    next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH)
    if epoch > next_epoch:
        raise ValidationError(
            f"Epoch for committee assignment ({epoch}) must not be after next epoch {next_epoch}."
        )

    active_validators = get_active_validator_indices(state.validators, epoch)
    committees_per_slot = (
        get_committee_count(
            len(active_validators),
            config.SHARD_COUNT,
            config.SLOTS_PER_EPOCH,
            config.TARGET_COMMITTEE_SIZE,
        )
        // config.SLOTS_PER_EPOCH
    )
    epoch_start_slot = compute_start_slot_of_epoch(epoch, config.SLOTS_PER_EPOCH)
    epoch_start_shard = get_start_shard(state, epoch, CommitteeConfig(config))

    for slot in range(epoch_start_slot, epoch_start_slot + config.SLOTS_PER_EPOCH):
        offset = committees_per_slot * (slot % config.SLOTS_PER_EPOCH)
        slot_start_shard = (epoch_start_shard + offset) % config.SHARD_COUNT
        for i in range(committees_per_slot):
            shard = Shard((slot_start_shard + i) % config.SHARD_COUNT)
            committee = get_crosslink_committee(
                state, epoch, shard, CommitteeConfig(config)
            )
            if validator_index in committee:
                is_proposer = validator_index == get_beacon_proposer_index(
                    state.copy(slot=slot), CommitteeConfig(config)
                )
                return CommitteeAssignment(
                    committee, Shard(shard), Slot(slot), is_proposer
                )

    raise NoCommitteeAssignment
コード例 #20
0
def test_determine_slashing_penalty(genesis_state, config, slots_per_epoch,
                                    current_epoch, epochs_per_slashings_vector,
                                    total_penalties, total_balance,
                                    expected_penalty):
    state = genesis_state.copy(slot=compute_start_slot_of_epoch(
        current_epoch, slots_per_epoch), )
    # if the size of the v-set changes then update the parameters above
    assert len(state.validators) == 10
    validator_index = 0
    penalty = _determine_slashing_penalty(
        total_penalties,
        total_balance,
        state.validators[validator_index].effective_balance,
        config.EFFECTIVE_BALANCE_INCREMENT,
    )
    assert penalty == expected_penalty
コード例 #21
0
def test_randao_processing(sample_beacon_block_params,
                           sample_beacon_block_body_params,
                           sample_beacon_state_params,
                           keymap,
                           config):
    proposer_pubkey, proposer_privkey = first(keymap.items())
    state = SerenityBeaconState(**sample_beacon_state_params).copy(
        validators=tuple(
            create_mock_validator(proposer_pubkey, config)
            for _ in range(config.TARGET_COMMITTEE_SIZE)
        ),
        balances=(config.MAX_EFFECTIVE_BALANCE,) * config.TARGET_COMMITTEE_SIZE,

        randao_mixes=tuple(
            ZERO_HASH32
            for _ in range(config.EPOCHS_PER_HISTORICAL_VECTOR)
        ),
    )

    epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    slot = compute_start_slot_of_epoch(epoch, config.SLOTS_PER_EPOCH)

    randao_reveal = _generate_randao_reveal(
        privkey=proposer_privkey,
        slot=slot,
        state=state,
        config=config,
    )

    block_body = BeaconBlockBody(**sample_beacon_block_body_params).copy(
        randao_reveal=randao_reveal,
    )

    block = SerenityBeaconBlock(**sample_beacon_block_params).copy(
        body=block_body,
    )

    new_state = process_randao(state, block, config)

    updated_index = epoch % config.EPOCHS_PER_HISTORICAL_VECTOR
    original_mixes = state.randao_mixes
    updated_mixes = new_state.randao_mixes

    assert all(
        updated == original if index != updated_index else updated != original
        for index, (updated, original) in enumerate(zip(updated_mixes, original_mixes))
    )
コード例 #22
0
def _find_collision(state, config, index, epoch):
    """
    Given a target epoch, make the attestation expected for the
    validator w/ the given index.
    """
    active_validators = get_active_validator_indices(state.validators, epoch)
    committees_per_slot = get_committee_count(
        len(active_validators),
        config.SHARD_COUNT,
        config.SLOTS_PER_EPOCH,
        config.TARGET_COMMITTEE_SIZE,
    ) // config.SLOTS_PER_EPOCH
    epoch_start_slot = compute_start_slot_of_epoch(
        epoch,
        config.SLOTS_PER_EPOCH,
    )
    epoch_start_shard = get_start_shard(state, epoch, CommitteeConfig(config))

    for slot in range(epoch_start_slot, epoch_start_slot + config.SLOTS_PER_EPOCH):
        offset = committees_per_slot * (slot % config.SLOTS_PER_EPOCH)
        slot_start_shard = (epoch_start_shard + offset) % config.SHARD_COUNT
        for i in range(committees_per_slot):
            shard = Shard((slot_start_shard + i) % config.SHARD_COUNT)
            committee = get_crosslink_committee(state, epoch, shard, CommitteeConfig(config))
            if index in committee:
                # TODO(ralexstokes) refactor w/ tools/builder
                attestation_data = AttestationData(
                    target=Checkpoint(
                        epoch=epoch,
                    ),
                    crosslink=Crosslink(
                        shard=shard,
                    ),
                )
                committee_count = len(committee)
                aggregation_bits = bitfield.get_empty_bitfield(committee_count)
                for i in range(committee_count):
                    aggregation_bits = bitfield.set_voted(aggregation_bits, i)

                return {
                    index: (
                        slot, (aggregation_bits, attestation_data)
                    )
                    for index in committee
                }
    else:
        raise Exception("should have found a duplicate validator")
コード例 #23
0
ファイル: validator.py プロジェクト: AndrewBezold/trinity
def create_mock_attester_slashing_is_double_vote(
    state: BeaconState,
    config: Eth2Config,
    keymap: Dict[BLSPubkey, int],
    attestation_epoch: Epoch,
) -> AttesterSlashing:
    attestation_slot_1 = compute_start_slot_of_epoch(attestation_epoch,
                                                     config.SLOTS_PER_EPOCH)
    attestation_slot_2 = Slot(attestation_slot_1 + 1)

    slashable_attestation_1 = create_mock_slashable_attestation(
        state, config, keymap, attestation_slot_1)
    slashable_attestation_2 = create_mock_slashable_attestation(
        state, config, keymap, attestation_slot_2)

    return AttesterSlashing(attestation_1=slashable_attestation_1,
                            attestation_2=slashable_attestation_2)
コード例 #24
0
def test_process_slashings(genesis_state, config, current_epoch, slashings,
                           slots_per_epoch, epochs_per_slashings_vector,
                           expected_penalty):
    state = genesis_state.copy(
        slot=compute_start_slot_of_epoch(current_epoch, slots_per_epoch),
        slashings=slashings,
    )
    slashing_validator_index = 0
    validator = state.validators[slashing_validator_index].copy(
        slashed=True,
        withdrawable_epoch=current_epoch + epochs_per_slashings_vector // 2)
    state = state.update_validator(slashing_validator_index, validator)

    result_state = process_slashings(state, config)
    penalty = (state.balances[slashing_validator_index] -
               result_state.balances[slashing_validator_index])
    assert penalty == expected_penalty
コード例 #25
0
ファイル: validator.py プロジェクト: AndrewBezold/trinity
def create_mock_voluntary_exit(
    state: BeaconState,
    config: Eth2Config,
    keymap: Dict[BLSPubkey, int],
    validator_index: ValidatorIndex,
    exit_epoch: Epoch = None,
) -> VoluntaryExit:
    current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    target_epoch = current_epoch if exit_epoch is None else exit_epoch
    voluntary_exit = VoluntaryExit(epoch=target_epoch,
                                   validator_index=validator_index)
    return voluntary_exit.copy(signature=sign_transaction(
        message_hash=voluntary_exit.signing_root,
        privkey=keymap[state.validators[validator_index].pubkey],
        state=state,
        slot=compute_start_slot_of_epoch(target_epoch, config.SLOTS_PER_EPOCH),
        signature_domain=SignatureDomain.DOMAIN_VOLUNTARY_EXIT,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    ))
コード例 #26
0
def test_randao_reveal_validation(is_valid,
                                  epoch,
                                  expected_epoch,
                                  proposer_key_index,
                                  expected_proposer_key_index,
                                  privkeys,
                                  pubkeys,
                                  sample_fork_params,
                                  genesis_state,
                                  config):
    state = genesis_state.copy(
        slot=compute_start_slot_of_epoch(epoch, config.SLOTS_PER_EPOCH),
    )
    message_hash = epoch.to_bytes(32, byteorder="little")
    slots_per_epoch = config.SLOTS_PER_EPOCH
    domain = get_domain(
        state,
        SignatureDomain.DOMAIN_RANDAO,
        slots_per_epoch,
    )

    proposer_privkey = privkeys[proposer_key_index]
    randao_reveal = bls.sign(
        message_hash=message_hash,
        privkey=proposer_privkey,
        domain=domain,
    )

    try:
        validate_randao_reveal(
            state=state,
            proposer_index=expected_proposer_key_index,
            epoch=expected_epoch,
            randao_reveal=randao_reveal,
            slots_per_epoch=slots_per_epoch,
        )
    except ValidationError:
        if is_valid:
            raise
    else:
        if not is_valid:
            pytest.fail("Did not raise")
コード例 #27
0
def test_get_matching_target_attestations(genesis_state, config):
    some_epoch = config.GENESIS_EPOCH + 20
    some_slot = compute_start_slot_of_epoch(some_epoch, config.SLOTS_PER_EPOCH)
    some_target_root = b"\x33" * 32
    target_attestations = tuple((PendingAttestation(data=AttestationData(
        target=Checkpoint(root=some_target_root))) for _ in range(3)))
    current_epoch_attestations = target_attestations + tuple(
        (PendingAttestation(data=AttestationData(target=Checkpoint(
            root=b"\x44" * 32))) for _ in range(3)))
    state = genesis_state.copy(
        slot=some_slot + 1,
        block_roots=update_tuple_item(
            genesis_state.block_roots,
            some_slot % config.SLOTS_PER_HISTORICAL_ROOT,
            some_target_root,
        ),
        current_epoch_attestations=current_epoch_attestations,
    )

    attestations = get_matching_target_attestations(state, some_epoch, config)

    assert attestations == target_attestations
コード例 #28
0
def test_get_attesting_indices(genesis_state, config):
    state = genesis_state.copy(
        slot=compute_start_slot_of_epoch(3, config.SLOTS_PER_EPOCH))
    target_epoch = state.current_epoch(config.SLOTS_PER_EPOCH)
    target_shard = (state.start_shard + 3) % config.SHARD_COUNT
    some_committee = get_crosslink_committee(state, target_epoch, target_shard,
                                             CommitteeConfig(config))

    data = AttestationData(target=Checkpoint(epoch=target_epoch),
                           crosslink=Crosslink(shard=target_shard))
    some_subset_count = random.randrange(1, len(some_committee) // 2)
    some_subset = random.sample(some_committee, some_subset_count)

    bitfield = get_empty_bitfield(len(some_committee))
    for i, index in enumerate(some_committee):
        if index in some_subset:
            bitfield = set_voted(bitfield, i)

    indices = get_attesting_indices(state, data, bitfield,
                                    CommitteeConfig(config))

    assert set(indices) == set(some_subset)
    assert len(indices) == len(some_subset)
コード例 #29
0
def test_process_rewards_and_penalties_for_crosslinks(
        genesis_state, config, slots_per_epoch, target_committee_size,
        shard_count, current_slot, num_attesting_validators,
        max_effective_balance, min_attestation_inclusion_delay,
        sample_attestation_data_params,
        sample_pending_attestation_record_params):
    state = genesis_state.copy(slot=current_slot, )
    previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH,
                                          config.GENESIS_EPOCH)

    prev_epoch_start_slot = compute_start_slot_of_epoch(
        previous_epoch, slots_per_epoch)
    prev_epoch_crosslink_committees = [
        get_crosslink_committees_at_slot(
            state,
            slot,
            CommitteeConfig(config),
        )[0] for slot in range(prev_epoch_start_slot, prev_epoch_start_slot +
                               slots_per_epoch)
    ]

    # Record which validators attest during each slot for reward collation.
    each_slot_attestion_validators_list = []

    epoch_start_shard = get_start_shard(
        state,
        previous_epoch,
        CommitteeConfig(config),
    )
    shard_delta = get_shard_delta(
        state,
        previous_epoch,
        CommitteeConfig(config),
    )

    a = epoch_start_shard
    b = epoch_start_shard + shard_delta
    if a > b:
        valid_shards_for_epoch = range(b, a)
    else:
        valid_shards_for_epoch = range(a, b)

    indices_to_check = set()

    previous_epoch_attestations = []
    for committee, shard in prev_epoch_crosslink_committees:
        if shard not in valid_shards_for_epoch:
            continue
        for index in committee:
            indices_to_check.add(index)
        # Randomly sample `num_attesting_validators` validators
        # from the committee to attest in this slot.
        crosslink_attesting_validators = random.sample(
            committee,
            num_attesting_validators,
        )
        each_slot_attestion_validators_list.append(
            crosslink_attesting_validators)
        participants_bitfield = get_empty_bitfield(len(committee))
        for index in crosslink_attesting_validators:
            participants_bitfield = set_voted(participants_bitfield,
                                              committee.index(index))
        previous_epoch_attestations.append(
            PendingAttestation(
                **sample_pending_attestation_record_params).copy(
                    aggregation_bits=participants_bitfield,
                    data=AttestationData(
                        **sample_attestation_data_params).copy(
                            target=Checkpoint(epoch=previous_epoch, ),
                            crosslink=Crosslink(
                                shard=shard,
                                parent_root=Crosslink().hash_tree_root,
                            ),
                        ),
                ))
    state = state.copy(
        previous_epoch_attestations=tuple(previous_epoch_attestations), )

    rewards_received, penalties_received = get_crosslink_deltas(
        state,
        config,
    )

    expected_rewards_received = {
        index: 0
        for index in range(len(state.validators))
    }
    validator_balance = max_effective_balance
    for i in range(slots_per_epoch):
        crosslink_committee, shard = prev_epoch_crosslink_committees[i]
        if shard not in valid_shards_for_epoch:
            continue
        attesting_validators = each_slot_attestion_validators_list[i]
        total_attesting_balance = len(attesting_validators) * validator_balance
        total_committee_balance = len(crosslink_committee) * validator_balance
        for index in crosslink_committee:
            if index in attesting_validators:
                reward = get_base_reward(
                    state=state,
                    index=index,
                    config=config,
                ) * total_attesting_balance // total_committee_balance
                expected_rewards_received[index] += reward
            else:
                penalty = get_base_reward(
                    state=state,
                    index=index,
                    config=config,
                )
                expected_rewards_received[index] -= penalty

    # Check the rewards/penalties match
    for index in range(len(state.validators)):
        if index not in indices_to_check:
            continue
        assert (rewards_received[index] -
                penalties_received[index] == expected_rewards_received[index])
コード例 #30
0
def test_get_attestation_deltas(genesis_state, config, slots_per_epoch,
                                target_committee_size, shard_count,
                                min_attestation_inclusion_delay,
                                inactivity_penalty_quotient, finalized_epoch,
                                current_slot,
                                sample_pending_attestation_record_params,
                                sample_attestation_data_params):
    state = genesis_state.copy(slot=current_slot,
                               finalized_checkpoint=Checkpoint(
                                   epoch=finalized_epoch, ))
    previous_epoch = state.previous_epoch(config.SLOTS_PER_EPOCH,
                                          config.GENESIS_EPOCH)
    epoch_start_shard = get_start_shard(
        state,
        previous_epoch,
        CommitteeConfig(config),
    )
    shard_delta = get_shard_delta(
        state,
        previous_epoch,
        CommitteeConfig(config),
    )

    a = epoch_start_shard
    b = epoch_start_shard + shard_delta
    if a > b:
        valid_shards_for_epoch = range(b, a)
    else:
        valid_shards_for_epoch = range(a, b)

    indices_to_check = set()

    prev_epoch_start_slot = compute_start_slot_of_epoch(
        previous_epoch, slots_per_epoch)
    prev_epoch_attestations = tuple()
    for slot in range(prev_epoch_start_slot,
                      prev_epoch_start_slot + slots_per_epoch):
        committee, shard = get_crosslink_committees_at_slot(
            state,
            slot,
            CommitteeConfig(config),
        )[0]
        if not committee:
            continue
        if shard not in valid_shards_for_epoch:
            continue
        participants_bitfield = get_empty_bitfield(len(committee))
        for i, index in enumerate(committee):
            indices_to_check.add(index)
            participants_bitfield = set_voted(participants_bitfield, i)
        prev_epoch_attestations += (PendingAttestation(
            **sample_pending_attestation_record_params).copy(
                aggregation_bits=participants_bitfield,
                inclusion_delay=min_attestation_inclusion_delay,
                proposer_index=get_beacon_proposer_index(
                    state.copy(slot=slot, ),
                    CommitteeConfig(config),
                ),
                data=AttestationData(**sample_attestation_data_params).copy(
                    crosslink=Crosslink(shard=shard, ),
                    target=Checkpoint(
                        epoch=previous_epoch,
                        root=get_block_root(
                            state,
                            previous_epoch,
                            config.SLOTS_PER_EPOCH,
                            config.SLOTS_PER_HISTORICAL_ROOT,
                        ),
                    ),
                    beacon_block_root=get_block_root_at_slot(
                        state,
                        slot,
                        config.SLOTS_PER_HISTORICAL_ROOT,
                    ),
                ),
            ), )
    state = state.copy(previous_epoch_attestations=prev_epoch_attestations, )

    rewards_received, penalties_received = get_attestation_deltas(
        state,
        config,
    )

    # everyone attested, no penalties
    assert (sum(penalties_received) == 0)
    the_reward = rewards_received[0]
    # everyone performed the same, equal rewards
    assert (sum(rewards_received) // len(rewards_received) == the_reward)