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_at_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.mset("slot", attestation_slot_1, "current_justified_epoch", config.GENESIS_EPOCH), config, keymap, attestation_slot_1, ) slashable_attestation_2 = create_mock_slashable_attestation( state.mset( "slot", attestation_slot_1, "current_justified_epoch", config.GENESIS_EPOCH + 1, # source_epoch_1 < source_epoch_2 ), config, keymap, attestation_slot_2, ) return AttesterSlashing.create(attestation_1=slashable_attestation_1, attestation_2=slashable_attestation_2)
def create_mock_deposit( state: BeaconState, pubkey: BLSPubkey, keymap: Dict[BLSPubkey, int], withdrawal_credentials: Hash32, config: Eth2Config, leaves: Sequence[Hash32] = None, ) -> Tuple[BeaconState, Deposit]: deposits, root = create_mock_deposits_and_root( (pubkey, ), keymap, config, withdrawal_credentials=(withdrawal_credentials, ), leaves=leaves, ) # sanity check assert len(deposits) == 1 deposit = deposits[0] eth1_data = state.eth1_data.mset( "deposit_root", root, "deposit_count", state.eth1_data.deposit_count + len(deposits), ) state = state.mset("eth1_data", eth1_data, "eth1_deposit_index", 0 if not leaves else len(leaves)) return state, deposit
def process_justification_and_finalization(state: BeaconState, config: Eth2Config) -> BeaconState: current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH) if current_epoch <= GENESIS_EPOCH + 1: return state ( new_current_justified_checkpoint, justification_bits, ) = _determine_new_justified_checkpoint_and_bitfield(state, config) new_finalized_checkpoint = _determine_new_finalized_checkpoint( state, justification_bits, config) return state.mset( "justification_bits", justification_bits, "previous_justified_checkpoint", state.current_justified_checkpoint, "current_justified_checkpoint", new_current_justified_checkpoint, "finalized_checkpoint", new_finalized_checkpoint, )
def process_attestations(state: BeaconState, block: BaseBeaconBlock, config: Eth2Config) -> BeaconState: if len(block.body.attestations) > config.MAX_ATTESTATIONS: raise ValidationError( f"The block has too many attestations:\n" f"\tFound {len(block.body.attestations)} attestations, " f"maximum: {config.MAX_ATTESTATIONS}") current_epoch = state.current_epoch(config.SLOTS_PER_EPOCH) current_epoch_attestations = state.current_epoch_attestations previous_epoch_attestations = state.previous_epoch_attestations for attestation in block.body.attestations: validate_attestation(state, attestation, config) proposer_index = get_beacon_proposer_index(state, config) pending_attestation = PendingAttestation.create( aggregation_bits=attestation.aggregation_bits, data=attestation.data, inclusion_delay=state.slot - attestation.data.slot, proposer_index=proposer_index, ) if attestation.data.target.epoch == current_epoch: current_epoch_attestations = current_epoch_attestations.append( pending_attestation) else: previous_epoch_attestations = previous_epoch_attestations.append( pending_attestation) return state.mset( "current_epoch_attestations", current_epoch_attestations, "previous_epoch_attestations", previous_epoch_attestations, )
def process_eth1_data(state: BeaconState, block: BaseBeaconBlock, config: Eth2Config) -> BeaconState: body = block.body new_eth1_data_votes = state.eth1_data_votes.append(body.eth1_data) new_eth1_data = state.eth1_data if (new_eth1_data_votes.count(body.eth1_data) * 2 > config.SLOTS_PER_ETH1_VOTING_PERIOD): new_eth1_data = body.eth1_data return state.mset("eth1_data", new_eth1_data, "eth1_data_votes", new_eth1_data_votes)
def process_deposit(state: BeaconState, deposit: Deposit, config: Eth2Config) -> BeaconState: """ Process a deposit from Ethereum 1.0. """ validate_deposit_proof(state, deposit, DEPOSIT_CONTRACT_TREE_DEPTH) # Increment the next deposit index we are expecting. Note that this # needs to be done here because while the deposit contract will never # create an invalid Merkle branch, it may admit an invalid deposit # object, and we need to be able to skip over it state = state.set("eth1_deposit_index", state.eth1_deposit_index + 1) pubkey = deposit.data.pubkey amount = deposit.data.amount withdrawal_credentials = deposit.data.withdrawal_credentials validator_pubkeys = tuple(v.pubkey for v in state.validators) if pubkey not in validator_pubkeys: # Verify the deposit signature (proof of possession) for new validators. # Note: The deposit contract does not check signatures. # Note: Deposits are valid across forks, thus the deposit domain # is retrieved directly from `compute_domain`. deposit_message = DepositMessage.create( pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, amount=amount) domain = compute_domain(SignatureDomain.DOMAIN_DEPOSIT, fork_version=config.GENESIS_FORK_VERSION) signing_root = compute_signing_root(deposit_message, domain) is_valid_proof_of_possession = bls.verify(signing_root, deposit.data.signature, pubkey) if not is_valid_proof_of_possession: return state validator = Validator.create_pending_validator(pubkey, withdrawal_credentials, amount, config) return state.mset( "validators", state.validators.append(validator), "balances", state.balances.append(amount), ) else: index = ValidatorIndex(validator_pubkeys.index(pubkey)) return increase_balance(state, index, amount)
def _process_slot(state: BeaconState, config: Eth2Config) -> BeaconState: slots_per_historical_root = config.SLOTS_PER_HISTORICAL_ROOT previous_state_root = state.hash_tree_root updated_state_roots = _update_historical_root(state.state_roots, state.slot, slots_per_historical_root, previous_state_root) if state.latest_block_header.state_root == ZERO_HASH32: state = state.transform(("latest_block_header", "state_root"), previous_state_root) updated_block_roots = _update_historical_root( state.block_roots, state.slot, slots_per_historical_root, state.latest_block_header.signing_root, ) return state.mset("block_roots", updated_block_roots, "state_roots", updated_state_roots)
def process_final_updates(state: BeaconState, config: Eth2Config) -> BeaconState: new_eth1_data_votes = _determine_next_eth1_votes(state, config) new_validators = _update_effective_balances(state, config) new_slashings = _compute_next_slashings(state, config) new_randao_mixes = _compute_next_randao_mixes(state, config) new_historical_roots = _compute_next_historical_roots(state, config) return state.mset( "eth1_data_votes", new_eth1_data_votes, "validators", new_validators, "slashings", new_slashings, "randao_mixes", new_randao_mixes, "historical_roots", new_historical_roots, "previous_epoch_attestations", state.current_epoch_attestations, "current_epoch_attestations", HashableList.from_iterable( (), sedes=state.current_epoch_attestations.sedes), )
def _mini_stf(state: BeaconState, block: Optional[BeaconBlock], config: Eth2Config) -> BeaconState: """ A simplified state transition for testing state storage. - updates ``state_roots`` with the previous slot's state root - updates ``block_roots`` with the previous slot's block root - updates ``randao_mixes`` with an arbitrary mix at the current epoch - creates a new ``latest_block_header`` and adds it to the state - fills in the rest of the attributes with arbitrary values """ current_slot = state.slot + 1 current_epoch = current_slot // config.SLOTS_PER_EPOCH if block: latest_block_header = block.header else: latest_block_header = state.latest_block_header # state changes that depend on the previous state for retrieval randao_mix = Root(Hash32(current_slot.to_bytes(32, byteorder="little"))) state = (state.transform( ("state_roots", state.slot % config.SLOTS_PER_HISTORICAL_ROOT), state.hash_tree_root, ).transform( ("block_roots", state.slot % config.SLOTS_PER_HISTORICAL_ROOT), state.latest_block_header.hash_tree_root, ).transform( ("randao_mixes", current_epoch % config.EPOCHS_PER_HISTORICAL_VECTOR), randao_mix, ).mset("slot", current_slot, "latest_block_header", latest_block_header)) # state changes that do not depend on the previous state for retrieval new_validators = [ Validator.create(pubkey=BLSPubkey(n.to_bytes(48, byteorder="little"))) for n in range(current_slot, current_slot + 20) ] new_eth1_data_votes = [ Eth1Data.create( deposit_root=Root(Hash32(n.to_bytes(32, byteorder="little")))) for n in range(current_slot, current_slot + 7) ] new_previous_epoch_attestations = [ PendingAttestation.create(proposer_index=ValidatorIndex(n)) for n in range(current_slot, current_slot + 5) ] new_current_epoch_attestations = [ PendingAttestation.create(proposer_index=ValidatorIndex(n)) for n in range(current_slot + 5, current_slot + 10) ] state = state.mset( "validators", new_validators, "balances", (32, ) * len(new_validators), "eth1_data_votes", new_eth1_data_votes, "eth1_data", new_eth1_data_votes[0], "previous_epoch_attestations", new_previous_epoch_attestations, "current_epoch_attestations", new_current_epoch_attestations, "previous_justified_checkpoint", Checkpoint.create(epoch=Epoch(current_slot + 42)), "current_justified_checkpoint", Checkpoint.create(epoch=Epoch(current_slot + 43)), "finalized_checkpoint", Checkpoint.create(epoch=Epoch(current_slot + 44)), ) return state