def prepare_empty_pow_block(spec, rng=Random(3131)): return spec.PowBlock( block_hash=spec.Hash32(spec.hash(bytearray(rng.getrandbits(8) for _ in range(32)))), parent_hash=spec.Hash32(spec.hash(bytearray(rng.getrandbits(8) for _ in range(32)))), total_difficulty=uint256(0), difficulty=uint256(0) )
def test_too_early_for_merge(spec, state): test_steps = [] # Initialization state = build_state_with_incomplete_transition(spec, state) store, anchor_block = get_genesis_forkchoice_store_and_block(spec, state) yield 'anchor_state', state yield 'anchor_block', anchor_block current_time = state.slot * spec.config.SECONDS_PER_SLOT + store.genesis_time on_tick_and_append_step(spec, store, current_time, test_steps) assert store.time == current_time pow_block_parent = prepare_empty_pow_block(spec) pow_block_parent.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256( 2) pow_block = prepare_empty_pow_block(spec) pow_block.parent_hash = pow_block_parent.block_hash pow_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256( 1) pow_blocks = [pow_block, pow_block_parent] for pb in pow_blocks: yield from add_pow_block(spec, store, pb, test_steps) def run_func(): block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_block.block_hash signed_block = state_transition_and_sign_block(spec, state, block) yield from tick_and_add_block(spec, store, signed_block, test_steps, valid=False, merge_block=True) yield from with_pow_block_patch(spec, pow_blocks, run_func) yield 'steps', test_steps
def test_is_valid_terminal_pow_block_fail_before_terminal(spec, state): parent_block = prepare_random_pow_block(spec) parent_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256( 2) block = prepare_random_pow_block(spec) block.parent_hash = parent_block.block_hash block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1) assert not spec.is_valid_terminal_pow_block(block, parent_block)
def test_validate_merge_block_tbh_override_success(spec, state): pow_chain = prepare_random_pow_chain(spec, 2) # should fail if TTD check is reached pow_chain.head( -1 ).total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(2) pow_chain.head( ).total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1) pow_chain.head().block_hash = TERMINAL_BLOCK_HASH block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_chain.head().block_hash run_validate_merge_block(spec, pow_chain, block)
def test_validate_merge_block_fail_after_terminal(spec, state): pow_chain = prepare_random_pow_chain(spec, 2) pow_chain.head(-1).total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY pow_chain.head( ).total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY + uint256(1) block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_chain.head().block_hash run_validate_merge_block(spec, pow_chain, block, valid=False)
def test_validate_merge_block_fail_block_lookup(spec, state): pow_chain = prepare_random_pow_chain(spec, 2) pow_chain.head( -1 ).total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1) pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY block = build_empty_block_for_next_slot(spec, state) run_validate_merge_block(spec, pow_chain, block, valid=False)
def test_valid_terminal_pow_block_fail_just_after_terminal(spec, state): parent_block = prepare_empty_pow_block(spec) parent_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY block = prepare_empty_pow_block(spec) block.parent_hash = parent_block.block_hash block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY + uint256(1) assert not spec.is_valid_terminal_pow_block(block, parent_block)
def test_valid_terminal_pow_block_success_valid(spec, state): parent_block = prepare_empty_pow_block(spec) parent_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256( 1) block = prepare_empty_pow_block(spec) block.parent_hash = parent_block.block_hash block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY assert spec.is_valid_terminal_pow_block(block, parent_block)
def test_validate_merge_block_fail_parent_hash_is_not_tbh(spec, state): pow_chain = prepare_random_pow_chain(spec, 2) # shouldn't fail if TTD check is reached pow_chain.head( -1 ).total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256(1) pow_chain.head().total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY block = build_empty_block_for_next_slot(spec, state) block.body.execution_payload.parent_hash = pow_chain.head().block_hash run_validate_merge_block(spec, pow_chain, block, valid=False)
def test_validate_transition_execution_payload_success(spec, state): parent_block = prepare_empty_pow_block(spec) parent_block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY - uint256( 1) block = prepare_empty_pow_block(spec) block.parent_hash = parent_block.block_hash block.total_difficulty = spec.config.TERMINAL_TOTAL_DIFFICULTY payload = spec.ExecutionPayload() payload.parent_hash = block.block_hash run_validate_transition_execution_payload(spec, block, parent_block, payload)
def translate_value(value, typ): """ Translate a value output from Py-SSZ deserialization into the given spec type. :param value: The PySSZ value :param typ: The type from the spec to translate into :return: the translated value """ if spec_ssz.is_uint_type(typ): size = spec_ssz.uint_byte_size(typ) if size == 1: return spec_ssz.uint8(value) elif size == 2: return spec_ssz.uint16(value) elif size == 4: return spec_ssz.uint32(value) elif size == 8: # uint64 is default (TODO this is changing soon) return value elif size == 16: return spec_ssz.uint128(value) elif size == 32: return spec_ssz.uint256(value) else: raise TypeError("invalid uint size") elif spec_ssz.is_list_type(typ): elem_typ = spec_ssz.read_elem_type(typ) return [translate_value(elem, elem_typ) for elem in value] elif spec_ssz.is_bool_type(typ): return value elif spec_ssz.is_vector_type(typ): elem_typ = spec_ssz.read_elem_type(typ) return typ(*(translate_value(elem, elem_typ) for elem in value)) elif spec_ssz.is_bytesn_type(typ): return typ(value) elif spec_ssz.is_bytes_type(typ): return value elif spec_ssz.is_container_type(typ): return typ( **{ f_name: translate_value(f_val, f_typ) for (f_name, f_val, f_typ) in zip(typ.get_field_names(), value, typ.get_field_types()) }) else: raise TypeError("Type not supported: {}".format(typ))
def translate_value(value, typ): """ Translate a value output from Py-SSZ deserialization into the given spec type. :param value: The PySSZ value :param typ: The type from the spec to translate into :return: the translated value """ if issubclass(typ, spec_ssz.uint): if typ.byte_len == 1: return spec_ssz.uint8(value) elif typ.byte_len == 2: return spec_ssz.uint16(value) elif typ.byte_len == 4: return spec_ssz.uint32(value) elif typ.byte_len == 8: return spec_ssz.uint64(value) elif typ.byte_len == 16: return spec_ssz.uint128(value) elif typ.byte_len == 32: return spec_ssz.uint256(value) else: raise TypeError("invalid uint size") elif issubclass(typ, spec_ssz.List): return [translate_value(elem, typ.elem_type) for elem in value] elif issubclass(typ, spec_ssz.boolean): return value elif issubclass(typ, spec_ssz.Vector): return typ(*(translate_value(elem, typ.elem_type) for elem in value)) elif issubclass(typ, spec_ssz.Bitlist): return typ(value) elif issubclass(typ, spec_ssz.Bitvector): return typ(value) elif issubclass(typ, spec_ssz.BytesN): return typ(value) elif issubclass(typ, spec_ssz.Bytes): return value if issubclass(typ, spec_ssz.Container): return typ( **{ f_name: translate_value(f_val, f_typ) for (f_val, (f_name, f_typ)) in zip(value, typ.get_fields().items()) }) else: raise TypeError("Type not supported: {}".format(typ))