Esempio n. 1
0
def fill_recent_block_hashes(active_state: ActiveState, parent_block: 'Block',
                             block: 'Block') -> ActiveState:
    return ActiveState(
        pending_attestations=deepcopy(active_state.pending_attestations),
        recent_block_hashes=get_new_recent_block_hashes(
            active_state.recent_block_hashes, parent_block.slot_number,
            block.slot_number, block.parent_hash),
        block_vote_cache=deepcopy(active_state.block_vote_cache))
def apply_rewards_and_penalties(
        crystallized_state: CrystallizedState,
        active_state: ActiveState,
        block: 'Block',
        config: Dict[str, Any] = DEFAULT_CONFIG) -> List['ValidatorRecord']:
    # FFG Rewards
    ffg_rewards = calculate_ffg_rewards(crystallized_state,
                                        active_state,
                                        block,
                                        config=config)

    # Crosslink Rewards
    crosslink_rewards = calculate_crosslink_rewards(crystallized_state,
                                                    active_state,
                                                    block,
                                                    config=config)

    updated_validators = deepcopy(crystallized_state.validators)
    active_validator_indices = get_active_validator_indices(
        crystallized_state.current_dynasty, crystallized_state.validators)

    # apply rewards and penalties
    for index in active_validator_indices:
        updated_validators[index].balance += (ffg_rewards[index] +
                                              crosslink_rewards[index])
        # TODO: Keep the balance nonnegative now until we have clear rule of forced exit.
        if updated_validators[index].balance < 0:
            updated_validators[index].balance = 0

    return updated_validators
def process_block(crystallized_state: CrystallizedState,
                  active_state: ActiveState,
                  block: 'Block',
                  parent_block: 'Block',
                  config: dict = DEFAULT_CONFIG) -> ActiveState:
    new_block_vote_cache = deepcopy(active_state.block_vote_cache)

    validate_parent_block_proposer(block,
                                   parent_block,
                                   crystallized_state,
                                   config=config)

    for attestation in block.attestations:
        validate_attestation(crystallized_state, active_state, attestation,
                             block, parent_block, config)
        new_block_vote_cache = get_updated_block_vote_cache(
            crystallized_state, active_state, attestation, block,
            new_block_vote_cache, config)

    new_attestations = active_state.pending_attestations + block.attestations
    new_chain = Chain(head=block, blocks=active_state.chain.blocks + [block])

    new_active_state = ActiveState(
        pending_attestations=new_attestations,
        recent_block_hashes=active_state.recent_block_hashes[:],
        block_vote_cache=new_block_vote_cache,
        chain=new_chain)
    return new_active_state
def get_updated_block_vote_cache(
        crystallized_state: CrystallizedState,
        active_state: ActiveState,
        attestation: 'AttestationRecord',
        block: 'Block',
        block_vote_cache: BlockVoteCache,
        config: Dict[str, Any] = DEFAULT_CONFIG) -> BlockVoteCache:
    new_block_vote_cache = deepcopy(block_vote_cache)

    parent_hashes = get_signed_parent_hashes(active_state, block, attestation,
                                             config)
    attestation_indices = get_attestation_indices(crystallized_state,
                                                  attestation, config)

    for parent_hash in parent_hashes:
        if parent_hash in attestation.oblique_parent_hashes:
            continue
        if parent_hash not in new_block_vote_cache:
            new_block_vote_cache[parent_hash] = {
                'voter_indices': set(),
                'total_voter_deposits': 0
            }
        for i, index in enumerate(attestation_indices):
            if (has_voted(attestation.attester_bitfield, i) and index
                    not in new_block_vote_cache[parent_hash]['voter_indices']):
                new_block_vote_cache[parent_hash]['voter_indices'].add(index)
                new_block_vote_cache[parent_hash]['total_voter_deposits'] += (
                    crystallized_state.validators[index].balance)

    return new_block_vote_cache
Esempio n. 5
0
def process_block(crystallized_state: CrystallizedState,
                  active_state: ActiveState,
                  block: 'Block',
                  config: dict = DEFAULT_CONFIG) -> ActiveState:
    new_block_vote_cache = deepcopy(active_state.block_vote_cache)
    for attestation in block.attestations:
        validate_attestation(crystallized_state, active_state, attestation,
                             block, config)
        new_block_vote_cache = get_updated_block_vote_cache(
            crystallized_state, active_state, attestation, block,
            new_block_vote_cache, config)

    new_attestations = active_state.pending_attestations + block.attestations

    new_active_state = ActiveState(
        pending_attestations=new_attestations,
        recent_block_hashes=active_state.recent_block_hashes[:],
        block_vote_cache=new_block_vote_cache)
    return new_active_state
def process_updated_crosslinks(
        crystallized_state: CrystallizedState,
        active_state: ActiveState,
        block: 'Block',
        config: Dict[str, Any] = DEFAULT_CONFIG) -> List[CrosslinkRecord]:
    total_attestation_balance = {}  # type: Dict[Tuple[ShardId, Hash32], int]

    crosslinks = deepcopy(crystallized_state.crosslink_records)

    for attestation in active_state.pending_attestations:
        shard_tuple = (attestation.shard_id, attestation.shard_block_hash)
        if shard_tuple not in total_attestation_balance:
            total_attestation_balance[shard_tuple] = 0

        attestation_indices = get_attestation_indices(crystallized_state,
                                                      attestation, config)
        # find total committee size by balance
        total_committee_balance = sum([
            crystallized_state.validators[index].balance
            for index in attestation_indices
        ])
        # find votes cast in attestation by balance
        total_attestation_balance[shard_tuple] += sum([
            crystallized_state.validators[index].balance
            for in_cycle_slot_height, index in enumerate(attestation_indices)
            if has_voted(attestation.attester_bitfield, in_cycle_slot_height)
        ])

        # if 2/3 of committee voted on crosslink and do no yet have crosslink
        # for this shard, for this dynasty, add updated crosslink
        if (3 * total_attestation_balance[shard_tuple] >=
                2 * total_committee_balance
                and crystallized_state.current_dynasty >
                crosslinks[attestation.shard_id].dynasty):
            crosslinks[attestation.shard_id] = CrosslinkRecord(
                dynasty=crystallized_state.current_dynasty,
                slot=crystallized_state.last_state_recalc +
                config['cycle_length'],
                hash=attestation.shard_block_hash)
    return crosslinks
def compute_dynasty_transition(
        crystallized_state: CrystallizedState,
        block: 'Block',
        config: Dict[str, Any] = DEFAULT_CONFIG) -> CrystallizedState:
    crystallized_state = deepcopy(crystallized_state)
    crystallized_state.current_dynasty += 1

    # Not current in spec, but should be added soon
    crystallized_state.dynasty_start = crystallized_state.last_state_recalc

    next_start_shard = (
        (crystallized_state.shard_and_committee_for_slots[-1][-1].shard_id + 1)
        % config['shard_count'])

    crystallized_state.shard_and_committee_for_slots[
        config['cycle_length']:] = get_new_shuffling(
            block.parent_hash,  # stub until better RNG
            crystallized_state.validators,
            crystallized_state.current_dynasty,
            next_start_shard)

    return crystallized_state
def initialize_new_cycle(
    crystallized_state: CrystallizedState,
    active_state: ActiveState,
    block: 'Block',
    config: Dict[str, Any] = DEFAULT_CONFIG
) -> Tuple[CrystallizedState, ActiveState]:
    cycle_length = config['cycle_length']
    last_state_recalc = crystallized_state.last_state_recalc
    last_justified_slot = crystallized_state.last_justified_slot
    last_finalized_slot = crystallized_state.last_finalized_slot
    justified_streak = crystallized_state.justified_streak

    total_deposits = crystallized_state.total_deposits

    # walk through slots last_state_recalc - CYCLE_LENGTH ... last_state_recalc - 1
    # and check for justification, streaks, and finality
    for i in range(cycle_length):
        slot = i + (last_state_recalc - cycle_length)

        block_hash = active_state.recent_block_hashes[i]
        if block_hash in active_state.block_vote_cache:
            vote_balance = active_state.block_vote_cache[block_hash][
                'total_voter_deposits']
        else:
            vote_balance = 0

        if 3 * vote_balance >= 2 * total_deposits:
            last_justified_slot = max(last_justified_slot, slot)
            justified_streak += 1
        else:
            justified_streak = 0

        if justified_streak >= cycle_length + 1:
            last_finalized_slot = max(last_finalized_slot,
                                      slot - cycle_length - 1)

    crosslink_records = process_updated_crosslinks(crystallized_state,
                                                   active_state, block, config)

    # remove attestations older than last_state_recalc
    pending_attestations = [
        a for a in active_state.pending_attestations
        if a.slot >= last_state_recalc
    ]

    validators = apply_rewards_and_penalties(crystallized_state,
                                             active_state,
                                             block,
                                             config=config)

    shard_and_committee_for_slots = (
        crystallized_state.shard_and_committee_for_slots[cycle_length:] +
        # this is a stub and will be addressed by shuffling at dynasty change
        crystallized_state.shard_and_committee_for_slots[cycle_length:])

    new_crystallized_state = CrystallizedState(
        validators=validators,
        last_state_recalc=last_state_recalc + cycle_length,
        shard_and_committee_for_slots=shard_and_committee_for_slots,
        last_justified_slot=last_justified_slot,
        justified_streak=justified_streak,
        last_finalized_slot=last_finalized_slot,
        current_dynasty=crystallized_state.current_dynasty,
        crosslink_records=crosslink_records,
        dynasty_seed=crystallized_state.dynasty_seed,
        dynasty_start=crystallized_state.dynasty_start)

    new_active_state = ActiveState(
        pending_attestations=pending_attestations,
        recent_block_hashes=active_state.recent_block_hashes[:],
        # Should probably clean up block_vote_cache but old records won't break cache
        # so okay for now
        block_vote_cache=deepcopy(active_state.block_vote_cache),
        chain=deepcopy(active_state.chain),
    )

    return new_crystallized_state, new_active_state