def test_root(): class Test(ssz.Serializable): fields = ( ("field1", uint8), ("field2", uint8), ) test = Test(1, 2) assert test.root == ssz.hash_tree_root(test, Test)
def run(): state = make_state(2**18) start_time = time.time() hash_tree_root(state) actual_performance = time.time() - start_time print("Performance of hash_tree_root", actual_performance) if actual_performance > TOLERABLE_PERFORMANCE: raise TimeoutError( "hash_tree_root is not fast enough. Tolerable: {}, Actual: {}". format( TOLERABLE_PERFORMANCE, actual_performance, ))
def test_container(bytes16_fields, result): field_names = tuple(f"field{index}" for index in range(len(bytes16_fields))) sedes = Container( tuple((field_name, bytes16) for field_name in field_names)) value = { field_name: field_value for field_name, field_value in zip(field_names, bytes16_fields) } assert ssz.hash_tree_root(value, sedes) == result
def test_bytes_n_list_randomized(data, length, sequence_type): sedes = List(BytesN(length)) items = data.draw( st.lists( st.binary( min_size=length, max_size=length, ) ) ) value = sequence_type(items) assert len(hash_tree_root(value, sedes)) == 32
def genesis_state_with_active_index_roots(state: BeaconState, config: Eth2Config) -> BeaconState: active_validator_indices = get_active_validator_indices( state.validators, config.GENESIS_EPOCH, ) genesis_active_index_root = ssz.hash_tree_root( active_validator_indices, ssz.sedes.List(ssz.uint64), ) active_index_roots = ( (genesis_active_index_root,) * config.EPOCHS_PER_HISTORICAL_VECTOR ) return state.copy( active_index_roots=active_index_roots, )
def validate_randao_reveal(state: BeaconState, proposer_index: int, epoch: Epoch, randao_reveal: Hash32, slots_per_epoch: int) -> None: proposer = state.validators[proposer_index] proposer_pubkey = proposer.pubkey message_hash = ssz.hash_tree_root(epoch, sedes=ssz.sedes.uint64) domain = get_domain(state, SignatureDomain.DOMAIN_RANDAO, slots_per_epoch) try: bls.validate( pubkey=proposer_pubkey, message_hash=message_hash, signature=cast(BLSSignature, randao_reveal), domain=domain, ) except SignatureError as error: raise ValidationError("RANDAO reveal is invalid", error)
def _compute_next_active_index_roots(state: BeaconState, config: Eth2Config) -> Tuple[Hash32, ...]: next_epoch = state.next_epoch(config.SLOTS_PER_EPOCH) index_root_position = ( next_epoch + config.ACTIVATION_EXIT_DELAY ) % config.EPOCHS_PER_HISTORICAL_VECTOR validator_indices_for_new_active_index_root = get_active_validator_indices( state.validators, Epoch(next_epoch + config.ACTIVATION_EXIT_DELAY), ) new_active_index_root = ssz.hash_tree_root( validator_indices_for_new_active_index_root, ssz.sedes.List(ssz.uint64), ) return update_tuple_item( state.active_index_roots, index_root_position, new_active_index_root, )
def test_update_active_index_roots(genesis_state, config, state_slot, slots_per_epoch, epochs_per_historical_vector, activation_exit_delay): state = genesis_state.copy(slot=state_slot, ) result = _compute_next_active_index_roots(state, config) index_root = ssz.hash_tree_root( get_active_validator_indices( state.validators, slot_to_epoch(state.slot, slots_per_epoch), ), ssz.sedes.List(ssz.uint64), ) target_epoch = state.next_epoch(slots_per_epoch) + activation_exit_delay assert result[target_epoch % epochs_per_historical_vector] == index_root
def _generate_randao_reveal(privkey: int, slot: Slot, fork: Fork, config: Eth2Config) -> BLSSignature: """ Return the RANDAO reveal for the validator represented by ``privkey``. The current implementation requires a validator to provide the BLS signature over the SSZ-serialized epoch in which they are proposing a block. """ epoch = slot_to_epoch(slot, config.SLOTS_PER_EPOCH) message_hash = ssz.hash_tree_root(epoch, sedes=ssz.sedes.uint64) randao_reveal = sign_transaction( message_hash=message_hash, privkey=privkey, fork=fork, slot=slot, signature_domain=SignatureDomain.DOMAIN_RANDAO, slots_per_epoch=config.SLOTS_PER_EPOCH, ) return randao_reveal
def validate_randao_reveal(randao_reveal: BLSSignature, proposer_index: ValidatorIndex, proposer_pubkey: BLSPubkey, epoch: Epoch, fork: Fork) -> None: message_hash = ssz.hash_tree_root(epoch, sedes=ssz.sedes.uint64) domain = get_domain(fork, epoch, SignatureDomain.DOMAIN_RANDAO) is_randao_reveal_valid = bls.verify( pubkey=proposer_pubkey, message_hash=message_hash, signature=randao_reveal, domain=domain, ) if not is_randao_reveal_valid: raise ValidationError( f"RANDAO reveal is invalid. " f"proposer_index={proposer_index}, proposer_pubkey={proposer_pubkey}, " f"reveal={randao_reveal}, " f"message_hash={message_hash}, domain={domain}, epoch={epoch}" )
def _update_latest_active_index_roots( state: BeaconState, committee_config: CommitteeConfig) -> BeaconState: """ Return the BeaconState with updated `latest_active_index_roots`. """ next_epoch = state.next_epoch(committee_config.SLOTS_PER_EPOCH) active_validator_indices = get_active_validator_indices( state.validator_registry, Epoch(next_epoch + committee_config.ACTIVATION_EXIT_DELAY), ) index_root = ssz.hash_tree_root( active_validator_indices, ssz.sedes.List(ssz.uint64), ) latest_active_index_roots = update_tuple_item( state.latest_active_index_roots, ((next_epoch + committee_config.ACTIVATION_EXIT_DELAY) % committee_config.LATEST_ACTIVE_INDEX_ROOTS_LENGTH), index_root, ) return state.copy(latest_active_index_roots=latest_active_index_roots, )
def test_byte(value): expected = ssz.hash_tree_root(int.from_bytes(value, byteorder="little"), uint8) assert ssz.hash_tree_root(value, byte) == expected
def hash_tree_root(self) -> Hash32: # NOTE: this is used in the fork choice calculation if self._hash_tree_root is None: self._hash_tree_root = ssz.hash_tree_root(self) return self._hash_tree_root
def execute_tree_hash_test_case(test_case): sedes = parse_type_definition(test_case["type"]) value = parse_value(test_case["value"], sedes) expected_root = decode_hex(test_case["root"]) calculated_root = ssz.hash_tree_root(value, sedes) assert calculated_root == expected_root
def test_byte_list(value): byte_sequence = tuple(bytes([byte_value]) for byte_value in value) assert ssz.hash_tree_root(value, byte_list) == ssz.hash_tree_root( byte_sequence, List(byte))
def test_vector_of_basics(serialized_uints128, result): sedes = Vector(uint128, len(serialized_uints128)) int_values = tuple( ssz.decode(value, uint128) for value in serialized_uints128) assert ssz.hash_tree_root(int_values, sedes) == result
def test_byte_vector(value): byte_sequence = tuple(bytes([byte_value]) for byte_value in value) expected_vector_root = ssz.hash_tree_root(byte_sequence, Vector(byte, len(value))) assert ssz.hash_tree_root(value, ByteVector(len(value))) == expected_vector_root
def root(self): return ssz.hash_tree_root(self)
def test_boolean(value, expected): assert ssz.hash_tree_root(value, boolean) == expected
def benchmark(): for data_item in data: ssz.hash_tree_root(data_item, byte_list)
def benchmark(): ssz.hash_tree_root(state)
def test_list_of_composite(bytes16_list, result): sedes = List(bytes16) assert ssz.hash_tree_root(bytes16_list, sedes) == result
def test_vector_of_composite(bytes16_vector, result): sedes = Vector(ByteVector(16), len(bytes16_vector)) assert ssz.hash_tree_root(bytes16_vector, sedes) == result
def test_list_of_basic(serialized_uints128, result): int_values = tuple( ssz.decode(value, uint128) for value in serialized_uints128) assert ssz.hash_tree_root(int_values, List(uint128)) == result
def hash_tree_root(self) -> Hash32: if self._hash_tree_root is None: self._hash_tree_root = ssz.hash_tree_root(self) return self._hash_tree_root
def execute_tree_hash_test_case(test_case): sedes = parse_type_definition(test_case["type"]) value = from_formatted_dict(test_case["value"], sedes, CustomCodec) expected_root = decode_hex(test_case["root"]) calculated_root = ssz.hash_tree_root(value, sedes) assert calculated_root == expected_root
def signed_root(self) -> Hash32: # TODO Use SSZ built-in function if self._signed_root is None: self._signed_root = ssz.hash_tree_root(self.copy(signature=EMPTY_SIGNATURE)) return Hash32(self._signed_root)
def signing_root(self): return ssz.hash_tree_root(self, self._meta.signed_container_sedes)
def test_uint(uint_and_value): uint, value = uint_and_value assert ssz.hash_tree_root(value, uint) == ssz.encode(value, uint).ljust( CHUNK_SIZE, b"\x00")
def test_container(bytes16_fields, result): sedes = Container(tuple(itertools.repeat(bytes16, len(bytes16_fields)))) assert ssz.hash_tree_root(bytes16_fields, sedes) == result