def translate_typ(typ) -> ssz.BaseSedes: """ Translates a spec type to a Py-SSZ type description (sedes). :param typ: The spec type, a class. :return: The Py-SSZ equivalent. """ if issubclass(typ, spec_ssz.Container): return ssz.Container([ translate_typ(field_typ) for field_name, field_typ in typ.get_fields().items() ]) elif issubclass(typ, spec_ssz.BytesN): return ssz.ByteVector(typ.length) elif issubclass(typ, spec_ssz.Bytes): return ssz.ByteList() elif issubclass(typ, spec_ssz.Vector): return ssz.Vector(translate_typ(typ.elem_type), typ.length) elif issubclass(typ, spec_ssz.List): # TODO: Make py-ssz List support the new fixed length list return ssz.List(translate_typ(typ.elem_type)) elif issubclass(typ, spec_ssz.Bitlist): # TODO: Once Bitlist implemented in py-ssz, use appropriate type return ssz.List(translate_typ(typ.elem_type)) elif issubclass(typ, spec_ssz.Bitvector): # TODO: Once Bitvector implemented in py-ssz, use appropriate type return ssz.Vector(translate_typ(typ.elem_type), typ.length) elif issubclass(typ, spec_ssz.boolean): return ssz.boolean elif issubclass(typ, spec_ssz.uint): if typ.byte_len == 1: return ssz.uint8 elif typ.byte_len == 2: return ssz.uint16 elif typ.byte_len == 4: return ssz.uint32 elif typ.byte_len == 8: return ssz.uint64 elif typ.byte_len == 16: return ssz.uint128 elif typ.byte_len == 32: return ssz.uint256 else: raise TypeError("invalid uint size") else: raise TypeError("Type not supported: {}".format(typ))
def _read_state_historical_roots( self, state_root: Root, HISTORICAL_ROOTS_LIMIT: int) -> Tuple[Root]: key = SchemaV1.state_root_to_historical_roots_root(state_root) historical_roots_root = self.db[key] return ssz.decode( self.db[historical_roots_root], ssz.List(ssz.bytes32, HISTORICAL_ROOTS_LIMIT), )
def _read_state_balances(self, state_root: Root, VALIDATOR_REGISTRY_LIMIT: int) -> Tuple[Gwei]: state_root_to_balances_root = SchemaV1.state_root_to_balances_root( state_root) balances_root = Root(Hash32(self.db[state_root_to_balances_root])) balances_root_to_balances = SchemaV1.balances_root_to_balances( balances_root) return ssz.decode( self.db[balances_root_to_balances], ssz.List(ssz.uint64, VALIDATOR_REGISTRY_LIMIT), )
def initialize_beacon_state_from_eth1(*, eth1_block_hash: Hash32, eth1_timestamp: Timestamp, deposits: Sequence[Deposit], config: Eth2Config) -> BeaconState: fork = Fork.create( previous_version=config.GENESIS_FORK_VERSION, current_version=config.GENESIS_FORK_VERSION, epoch=GENESIS_EPOCH, ) state = BeaconState.create( genesis_time=_genesis_time_from_eth1_timestamp(eth1_timestamp, config.GENESIS_DELAY), fork=fork, eth1_data=Eth1Data.create(block_hash=eth1_block_hash, deposit_count=len(deposits)), latest_block_header=BeaconBlockHeader.create( body_root=BeaconBlockBody.create().hash_tree_root), block_roots=(ZERO_ROOT, ) * config.SLOTS_PER_HISTORICAL_ROOT, state_roots=(ZERO_HASH32, ) * config.SLOTS_PER_HISTORICAL_ROOT, randao_mixes=(eth1_block_hash, ) * config.EPOCHS_PER_HISTORICAL_VECTOR, slashings=(Gwei(0), ) * config.EPOCHS_PER_SLASHINGS_VECTOR, config=config, ) # Process genesis deposits for index, deposit in enumerate(deposits): deposit_data_list = tuple(deposit.data for deposit in deposits[:index + 1]) deposit_root = ssz.get_hash_tree_root( deposit_data_list, ssz.List(DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH)) state = state.transform(("eth1_data", "deposit_root"), deposit_root) state = process_deposit(state=state, deposit=deposit, config=config) # Process genesis activations for validator_index in range(len(state.validators)): validator_index = ValidatorIndex(validator_index) balance = state.balances[validator_index] effective_balance = calculate_effective_balance(balance, config) state = state.transform( ("validators", validator_index, "effective_balance"), effective_balance) if effective_balance == config.MAX_EFFECTIVE_BALANCE: activated_validator = activate_validator( state.validators[validator_index], GENESIS_EPOCH) state = state.transform(("validators", validator_index), activated_validator) return state.set("genesis_validators_root", state.validators.hash_tree_root)
async def _recv_beacon_blocks_by_root(self, stream: INetStream) -> None: request_data = await _read_request(stream) request = _deserialize_ssz(request_data, ssz.List(ROOT_SEDES, MAX_REQUEST_BLOCKS)) for root in request: block = self._block_provider_by_root(root) if not block: continue response_payload = _serialize_ssz(block, SignedBeaconBlock) await _write_success_response_chunk(stream, response_payload) await stream.close()
def state_with_validator_digests(state: BeaconState, config: Eth2Config) -> BeaconState: active_validator_indices = get_active_validator_indices( state.validators, config.GENESIS_EPOCH) active_index_root = ssz.get_hash_tree_root( active_validator_indices, ssz.List(ssz.uint64, config.VALIDATOR_REGISTRY_LIMIT)) active_index_roots = ( active_index_root, ) * config.EPOCHS_PER_HISTORICAL_VECTOR committee_root = get_compact_committees_root(state, config.GENESIS_EPOCH, CommitteeConfig(config)) compact_committees_roots = ( committee_root, ) * config.EPOCHS_PER_HISTORICAL_VECTOR return state.copy( active_index_roots=active_index_roots, compact_committees_roots=compact_committees_roots, )
async def _recv_beacon_blocks_by_root(self, stream: INetStream) -> None: request_data = await _read_request(stream) element_sedes = ssz.sedes.bytes32 list_len = len(request_data) // element_sedes.length request = _deserialize_ssz(request_data, ssz.List(element_sedes, list_len)) for root in request: block = self._block_provider_by_root(root) if not block: continue response_payload = _serialize_ssz(block, SignedBeaconBlock) await _write_success_response_chunk(stream, response_payload) await stream.close()
async def get_blocks_by_root( self, stream: INetStream, *roots: Sequence[Root]) -> AsyncIterable[SignedBeaconBlock]: if not roots: return request_payload = _serialize_ssz( roots, ssz.List(ssz.sedes.bytes32, len(roots))) await _write_request(request_payload, stream) await stream.close() for _ in range(len(roots)): response_data = await _read_response(stream) if not response_data: break block = _deserialize_ssz(response_data, SignedBeaconBlock) yield block
def initialize_beacon_state_from_eth1(*, eth1_block_hash: Hash32, eth1_timestamp: Timestamp, deposits: Sequence[Deposit], config: Eth2Config) -> BeaconState: state = BeaconState( genesis_time=_genesis_time_from_eth1_timestamp(eth1_timestamp), eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=len(deposits)), latest_block_header=BeaconBlockHeader( body_root=BeaconBlockBody().hash_tree_root), randao_mixes=(eth1_block_hash, ) * config.EPOCHS_PER_HISTORICAL_VECTOR, config=config, ) # Process genesis deposits for index, deposit in enumerate(deposits): deposit_data_list = tuple(deposit.data for deposit in deposits[:index + 1]) state = state.copy(eth1_data=state.eth1_data.copy( deposit_root=ssz.get_hash_tree_root( deposit_data_list, ssz.List(DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH), ))) state = process_deposit(state=state, deposit=deposit, config=config) # Process genesis activations for validator_index in range(len(state.validators)): validator_index = ValidatorIndex(validator_index) balance = state.balances[validator_index] effective_balance = calculate_effective_balance(balance, config) state = state.update_validator_with_fn( validator_index, lambda v, *_: v.copy(effective_balance=effective_balance)) if effective_balance == config.MAX_EFFECTIVE_BALANCE: state = state.update_validator_with_fn(validator_index, activate_validator, config.GENESIS_EPOCH) return state
async def get_blocks_by_root( self, stream: INetStream, *roots: Sequence[Root]) -> AsyncIterable[SignedBeaconBlock]: if not roots: return # TODO ensure ssz error if ``len(roots) > MAX_REQUEST_BLOCKS`` request_payload = _serialize_ssz( roots, ssz.List(ROOT_SEDES, MAX_REQUEST_BLOCKS)) await _write_request(request_payload, stream) await stream.close() for _ in range(len(roots)): response_data = await _read_response(stream) if not response_data: break block = _deserialize_ssz(response_data, SignedBeaconBlock) yield block
def translate_typ(typ) -> ssz.BaseSedes: """ Translates a spec type to a Py-SSZ type description (sedes). :param typ: The spec type, a class. :return: The Py-SSZ equivalent. """ if spec_ssz.is_container_type(typ): return ssz.Container([ translate_typ(field_typ) for (field_name, field_typ) in typ.get_fields() ]) elif spec_ssz.is_bytesn_type(typ): return ssz.ByteVector(typ.length) elif spec_ssz.is_bytes_type(typ): return ssz.ByteList() elif spec_ssz.is_vector_type(typ): return ssz.Vector(translate_typ(spec_ssz.read_vector_elem_type(typ)), typ.length) elif spec_ssz.is_list_type(typ): return ssz.List(translate_typ(spec_ssz.read_list_elem_type(typ))) elif spec_ssz.is_bool_type(typ): return ssz.boolean elif spec_ssz.is_uint_type(typ): size = spec_ssz.uint_byte_size(typ) if size == 1: return ssz.uint8 elif size == 2: return ssz.uint16 elif size == 4: return ssz.uint32 elif size == 8: return ssz.uint64 elif size == 16: return ssz.uint128 elif size == 32: return ssz.uint256 else: raise TypeError("invalid uint size") else: raise TypeError("Type not supported: {}".format(typ))