def fill_recent_block_hashes(active_state, parent_block, block): 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 get_updated_block_vote_cache(crystallized_state, active_state, attestation, block, block_vote_cache, config): 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
def process_updated_crosslinks(crystallized_state, active_state, config=DEFAULT_CONFIG): total_attestation_balance = {} 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, hash=attestation.shard_block_hash) return crosslinks
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 initialize_new_cycle(crystallized_state, active_state, block, config=DEFAULT_CONFIG): 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 # 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 * crystallized_state.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, config) # remove attestations older than last_state_recalc pending_attestations = [ a for a in active_state.pending_attestations if a.slot >= last_state_recalc ] dynasty = crystallized_state.current_dynasty # STUB dynasty_seed = crystallized_state.dynasty_seed # STUB dynasty_seed_last_reset = crystallized_state.dynasty_seed_last_reset # STUB crosslinking_start_shard = 0 # stub. Needs to see where this epoch left off validators = deepcopy(crystallized_state.validators) # STUB indices_for_heights = ( crystallized_state.indices_for_heights[cycle_length:] + # this is a stub and will be addressed by shuffling at dynasty change crystallized_state.indices_for_heights[cycle_length:]) active_validator_indices = get_active_validator_indices( dynasty, validators) new_crystallized_state = CrystallizedState( validators=validators, last_state_recalc=last_state_recalc + cycle_length, indices_for_heights=indices_for_heights, last_justified_slot=last_justified_slot, justified_streak=justified_streak, last_finalized_slot=last_finalized_slot, current_dynasty=crystallized_state.current_dynasty, crosslinking_start_shard=crosslinking_start_shard, crosslink_records=crosslink_records, total_deposits=sum( map(lambda i: validators[i].balance, active_validator_indices)), dynasty_seed=dynasty_seed, dynasty_seed_last_reset=dynasty_seed_last_reset) 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)) return new_crystallized_state, new_active_state
def _initialize_new_epoch(crystallized_state, active_state): print('Processing epoch transition') # Process rewards from FFG/crosslink votes new_validator_records = deepcopy(crystallized_state.active_validators) # Who voted in the last epoch ffg_voter_bitfield = bytearray(active_state.ffg_voter_bitfield) # Balance changes, and total vote counts for FFG deltas1, total_vote_count, total_vote_deposits, justify, finalize = \ process_ffg_deposits(crystallized_state, ffg_voter_bitfield) # Balance changes, and total vote counts for crosslinks deltas2, new_crosslink_records = process_crosslinks( crystallized_state, active_state.partial_crosslinks) # Process other balance deltas deltas3 = process_balance_deltas(crystallized_state, active_state.balance_deltas) for i, v in enumerate(new_validator_records): v.balance += deltas1[i] + deltas2[i] + deltas3[i] total_deposits = crystallized_state.total_deposits + sum(deltas1 + deltas2 + deltas3) print('New total deposits: %d' % total_deposits) if justify: last_justified_epoch = crystallized_state.current_epoch else: last_justified_epoch = crystallized_state.last_justified_epoch if finalize: last_finalized_epoch = crystallized_state.current_epoch - 1 dynasty = crystallized_state.dynasty + 1 new_queued_validators, new_active_validators, new_exited_validators = \ get_incremented_validator_sets(crystallized_state, new_validator_records) else: last_finalized_epoch = crystallized_state.last_finalized_epoch dynasty = crystallized_state.dynasty new_queued_validators = crystallized_state.queued_validators new_active_validators = crystallized_state.active_validators new_exited_validators = crystallized_state.exited_validators crystallized_state = CrystallizedState( queued_validators=new_queued_validators, active_validators=new_active_validators, exited_validators=new_exited_validators, current_shuffling=get_shuffling(active_state.randao, len(new_active_validators)), last_justified_epoch=last_justified_epoch, last_finalized_epoch=last_finalized_epoch, dynasty=dynasty, next_shard=0, current_epoch=crystallized_state.current_epoch + 1, crosslink_records=new_crosslink_records, total_deposits=total_deposits) # Reset the active state active_state = ActiveState( height=active_state.height, randao=active_state.randao, ffg_voter_bitfield=bytearray( (len(crystallized_state.active_validators) + 7) // 8), balance_deltas=[], partial_crosslinks=[], total_skip_count=active_state.total_skip_count) return crystallized_state, active_state
def _initialize_new_epoch(crystallized_state, active_state, config=DEFAULT_CONFIG): print('Processing epoch transition') # Process rewards from FFG/crosslink votes new_validator_records = deepcopy(crystallized_state.active_validators) # Who voted in the last epoch ffg_voter_bitfield = active_state.ffg_voter_bitfield # Balance changes, and total vote counts for FFG deltas_casper, total_vote_count, total_vote_deposits, justify, finalize = \ process_ffg_deposits(crystallized_state, ffg_voter_bitfield) # Balance changes, and total vote counts for crosslinks deltas_crosslinks, new_crosslink_records = process_crosslinks( crystallized_state, active_state.partial_crosslinks, config=config, ) # process recent attesters balance deltas deltas_recent_attesters = process_recent_attesters( crystallized_state, active_state.recent_attesters, config=config, ) # process recent proposers balance deltas deltas_recent_proposers = process_recent_proposers( crystallized_state, active_state.recent_proposers) for i, validator in enumerate(new_validator_records): validator.balance += (deltas_casper[i] + deltas_crosslinks[i] + deltas_recent_attesters[i] + deltas_recent_proposers[i]) total_deposits = crystallized_state.total_deposits + sum( deltas_casper + deltas_crosslinks + deltas_recent_attesters + deltas_recent_proposers) print('New total deposits: %d' % total_deposits) if justify: last_justified_epoch = crystallized_state.current_epoch else: last_justified_epoch = crystallized_state.last_justified_epoch if finalize: last_finalized_epoch = crystallized_state.current_epoch - 1 dynasty = crystallized_state.dynasty + 1 new_queued_validators, new_active_validators, new_exited_validators = \ get_incremented_validator_sets(crystallized_state, new_validator_records) else: last_finalized_epoch = crystallized_state.last_finalized_epoch dynasty = crystallized_state.dynasty new_queued_validators = crystallized_state.queued_validators new_active_validators = crystallized_state.active_validators new_exited_validators = crystallized_state.exited_validators crystallized_state = CrystallizedState( queued_validators=new_queued_validators, active_validators=new_active_validators, exited_validators=new_exited_validators, current_shuffling=get_shuffling(active_state.randao, len(new_active_validators), config=config), last_justified_epoch=last_justified_epoch, last_finalized_epoch=last_finalized_epoch, dynasty=dynasty, next_shard=0, current_epoch=crystallized_state.current_epoch + 1, crosslink_records=new_crosslink_records, total_deposits=total_deposits) # Reset the active state active_state = ActiveState(height=active_state.height, randao=active_state.randao, ffg_voter_bitfield=get_empty_bitfield( crystallized_state.num_active_validators), balance_deltas=[], partial_crosslinks=[], total_skip_count=active_state.total_skip_count, recent_proposers=[]) return crystallized_state, active_state