def store_canon_chain(session: Session, post: spec.BeaconState, signed_block: Optional[spec.SignedBeaconBlock]): proposer_index: spec.ValidatorIndex if signed_block is not None: block = signed_block.message assert post.slot == block.slot upsert( session, CanonBeaconBlock( slot=block.slot, block_root=block.hash_tree_root(), )) proposer_index = block.proposer_index else: proposer_index = calc_beacon_proposer_index(post, post.slot) upsert( session, CanonBeaconState(slot=post.slot, state_root=post.hash_tree_root(), proposer_index=proposer_index, empty_slot=(signed_block is None))) if post.slot % spec.SLOTS_PER_EPOCH == 0: upsert( session, CanonBeaconEpoch( state_root=post.hash_tree_root(), epoch=spec.compute_epoch_at_slot(post.slot), ))
def calc_beacon_proposer_index(state: BeaconState, slot: spec.Slot) -> spec.ValidatorIndex: epoch = spec.compute_epoch_at_slot(slot) seed = spec.hash( spec.get_seed(state, epoch, spec.DOMAIN_BEACON_PROPOSER) + spec.int_to_bytes(state.slot, length=8)) indices = spec.get_active_validator_indices(state, epoch) return spec.compute_proposer_index(state, indices, seed)
def get_current_epoch(): genesis_time_cache = r.get('genesis_time') if genesis_time_cache is None: genesis = query_eth2_api('/eth/v1/beacon/genesis') genesis_time = int(genesis["data"]["genesis_time"]) r.set('genesis_time', genesis_time) else: genesis_time = int(genesis_time_cache.decode('utf-8')) current_slot = (time.time() - genesis_time) // SECONDS_PER_SLOT return compute_epoch_at_slot(int(current_slot))
def store_validator_all(session: Session, curr_state: spec.BeaconState, is_canon: bool): header = curr_state.latest_block_header.copy() header.state_root = curr_state.hash_tree_root() block_root = header.hash_tree_root() slot = curr_state.slot result_validators = [] result_validator_statuses = [] result_balances = [] epoch = spec.compute_epoch_at_slot(slot) for i, (v, b) in enumerate( zip(curr_state.validators.readonly_iter(), curr_state.balances.readonly_iter())): # Create new validator result_validators.append( Validator( intro_block_root=block_root, validator_index=i, intro_slot=slot, pubkey=v.pubkey, withdrawal_credentials=v.withdrawal_credentials, )) # Update validator status if it's a new or changed validator result_validator_statuses.append( ValidatorStatus( intro_block_root=block_root, validator_index=i, intro_slot=slot, effective_balance=v.effective_balance, slashed=bool(v.slashed), activation_eligibility_epoch=format_epoch( v.activation_eligibility_epoch), activation_epoch=format_epoch(v.activation_epoch), exit_epoch=format_epoch(v.exit_epoch), withdrawable_epoch=format_epoch(v.withdrawable_epoch), )) # And its balance if canon and epoch if is_canon: result_balances.append( ValidatorEpochBalance( epoch=epoch, validator_index=i, balance=b, eff_balance=v.effective_balance, )) if len(result_validators) > 0: upsert_all(session, Validator, result_validators) if len(result_validator_statuses) > 0: upsert_all(session, ValidatorStatus, result_validator_statuses) if len(result_balances): upsert_all(session, ValidatorEpochBalance, result_balances)
except Exception: logging.exception( 'Error while reading "genesis_validators_root". Please make sure that "genesis_validators_root" is a well-formed, "0x"-prefixed, 32-byte root. Exiting program.' ) exit(1) logging.debug(f'Fetched Genesis information: {genesis}') genesis_time = int(genesis["genesis_time"]) current_time = int(time.time()) if current_time < genesis_time: logging.critical( f'Current time is lesser than genesis time - Current time: {current_time}, Genesis time: {genesis_time}. Exiting program.' ) exit(1) current_slot = (current_time - genesis_time) // SECONDS_PER_SLOT current_epoch = compute_epoch_at_slot(current_slot) logging.info( f'Current chain information - Slot: {current_slot}, Epoch: {current_epoch}' ) validator_pubkeys = VAL_PUBKEY logging.info( f'Rebuilding validator protection file using method "{METHOD}" for the folowing Validators - ' ) for i in range(len(validator_pubkeys)): logging.info(f'\tPUBKEY: {validator_pubkeys[i]}') if METHOD == "uc_safe": # Set the source and target epoch for attestation slashing protection to the previous epoch and current epoch respectively att_source_epoch = current_epoch - 1 att_target_epoch = current_epoch
def store_validator_diff(session: Session, prev_state: spec.BeaconState, curr_state: spec.BeaconState, is_canon: bool): header = curr_state.latest_block_header.copy() header.state_root = curr_state.hash_tree_root() block_root = header.hash_tree_root() slot = curr_state.slot if prev_state.validators.hash_tree_root( ) != curr_state.validators.hash_tree_root(): prev: Optional[spec.Validator] curr: Optional[spec.Validator] print("checking validators diff") # First put them in lists to avoid len() lookups reducing it to O(n^2) performance. prev_vals = list(prev_state.validators.readonly_iter()) curr_vals = list(curr_state.validators.readonly_iter()) result_validators = [] result_validator_statuses = [] for i, (prev, curr) in enumerate(zip_longest(prev_vals, curr_vals)): assert curr is not None if prev is None: # Create new validator result_validators.append( Validator( intro_block_root=block_root, validator_index=i, intro_slot=slot, pubkey=curr.pubkey, withdrawal_credentials=curr.withdrawal_credentials, )) if prev is None or prev != curr: # Update validator status if it's a new or changed validator result_validator_statuses.append( ValidatorStatus( intro_block_root=block_root, validator_index=i, intro_slot=slot, effective_balance=curr.effective_balance, slashed=bool(curr.slashed), activation_eligibility_epoch=format_epoch( curr.activation_eligibility_epoch), activation_epoch=format_epoch(curr.activation_epoch), exit_epoch=format_epoch(curr.exit_epoch), withdrawable_epoch=format_epoch( curr.withdrawable_epoch), )) if len(result_validators) > 0: print("Upserting validators") upsert_all(session, Validator, result_validators) if len(result_validator_statuses) > 0: print("Upserting validator statuses") upsert_all(session, ValidatorStatus, result_validator_statuses) if is_canon: if slot % spec.SLOTS_PER_EPOCH == 0: epoch = spec.compute_epoch_at_slot(slot) curr_bal: spec.Gwei curr_val: spec.Validator print("checking epoch balances diff") curr_bals = list(curr_state.balances.readonly_iter()) curr_vals = list(curr_state.validators.readonly_iter()) result_balances = [] for i, (curr_bal, curr_val) in enumerate(zip(curr_bals, curr_vals)): result_balances.append( ValidatorEpochBalance( epoch=epoch, validator_index=i, balance=curr_bal, eff_balance=curr_val.effective_balance, )) upsert_all(session, ValidatorEpochBalance, result_balances) elif prev_state.balances.hash_tree_root( ) != curr_state.balances.hash_tree_root(): prev_bals = list(prev_state.balances.readonly_iter()) curr_bals = list(curr_state.balances.readonly_iter()) result_balances = [] for i, (prev, curr) in enumerate(zip_longest(prev_bals, curr_bals)): if prev is None or prev != curr: # Only track changes, and key by block-root, to be able to reorg without overwrite/deletes. result_balances.append( ValidatorOddBalance( intro_block_root=block_root, intro_slot=slot, validator_index=i, balance=curr, )) if len(result_balances) > 0: print("Upserting odd validator balances") upsert_all(session, ValidatorOddBalance, result_balances)