def ecrecover(computation: BaseComputation) -> BaseComputation: computation.consume_gas(constants.GAS_ECRECOVER, reason="ECRecover Precompile") raw_message_hash = computation.msg.data[:32] message_hash = pad32r(raw_message_hash) v_bytes = pad32r(computation.msg.data[32:64]) v = big_endian_to_int(v_bytes) r_bytes = pad32r(computation.msg.data[64:96]) r = big_endian_to_int(r_bytes) s_bytes = pad32r(computation.msg.data[96:128]) s = big_endian_to_int(s_bytes) try: validate_lt_secpk1n(r, title="ECRecover: R") validate_lt_secpk1n(s, title="ECRecover: S") validate_lte(v, 28, title="ECRecover: V") validate_gte(v, 27, title="ECRecover: V") except ValidationError: return computation canonical_v = v - 27 try: signature = keys.Signature(vrs=(canonical_v, r, s)) public_key = signature.recover_public_key_from_msg_hash(message_hash) except BadSignature: return computation address = public_key.to_canonical_address() padded_address = pad32(address) computation.output = padded_address return computation
def write(self, start_position: int, size: int, value: bytes) -> None: if size: validate_uint256(start_position) validate_uint256(size) validate_is_bytes(value) validate_length(value, length=size) validate_lte(start_position + size, maximum=len(self)) for idx, v in enumerate(value): self._bytes[start_position + idx] = v
def check_pow(block_number: int, mining_hash: Hash32, mix_hash: Hash32, nonce: bytes, difficulty: int) -> None: validate_length(mix_hash, 32, title="Mix Hash") validate_length(mining_hash, 32, title="Mining Hash") validate_length(nonce, 8, title="POW Nonce") cache = get_cache(block_number) mining_output = hashimoto_light(block_number, cache, mining_hash, big_endian_to_int(nonce)) if mining_output[b'mix digest'] != mix_hash: raise ValidationError("mix hash mismatch; {0} != {1}".format( encode_hex(mining_output[b'mix digest']), encode_hex(mix_hash))) result = big_endian_to_int(mining_output[b'result']) validate_lte(result, 2**256 // difficulty, title="POW Difficulty")
def check_pow(block_number: int, mining_hash: Hash32, mix_hash: Hash32, nonce: bytes, difficulty: int) -> None: validate_length(mix_hash, 32, title="Mix Hash") validate_length(mining_hash, 32, title="Mining Hash") validate_length(nonce, 8, title="POW Nonce") cache = get_cache(block_number) mining_output = hashimoto_light(block_number, cache, mining_hash, big_endian_to_int(nonce)) if mining_output[b'mix digest'] != mix_hash: raise ValidationError( f"mix hash mismatch; expected: {encode_hex(mining_output[b'mix digest'])} " f"!= actual: {encode_hex(mix_hash)}. " f"Mix hash calculated from block #{block_number}, " f"mine hash {encode_hex(mining_hash)}, nonce {encode_hex(nonce)}" f", difficulty {difficulty}, cache hash {encode_hex(keccak(cache))}" ) result = big_endian_to_int(mining_output[b'result']) validate_lte(result, 2**256 // difficulty, title="POW Difficulty")
def write(self, start_position: int, size: int, value: bytes) -> None: """ Write `value` into memory. """ if size: validate_uint256(start_position) validate_uint256(size) validate_is_bytes(value) validate_length(value, length=size) validate_lte(start_position + size, maximum=len(self)) if len(self._bytes) < start_position + size: self._bytes.extend( itertools.repeat( 0, len(self._bytes) - (start_position + size), )) for idx, v in enumerate(value): self._bytes[start_position + idx] = v
def validate(self) -> None: validate_uint256(self.nonce, title="Transaction.nonce") validate_uint256(self.gas_price, title="Transaction.gas_price") validate_uint256(self.gas, title="Transaction.gas") if self.to != CREATE_CONTRACT_ADDRESS: validate_canonical_address(self.to, title="Transaction.to") validate_uint256(self.value, title="Transaction.value") validate_is_bytes(self.data, title="Transaction.data") validate_uint256(self.v, title="Transaction.v") validate_uint256(self.r, title="Transaction.r") validate_uint256(self.s, title="Transaction.s") validate_lt_secpk1n(self.r, title="Transaction.r") validate_gte(self.r, minimum=1, title="Transaction.r") validate_lt_secpk1n(self.s, title="Transaction.s") validate_gte(self.s, minimum=1, title="Transaction.s") validate_gte(self.v, minimum=self.v_min, title="Transaction.v") validate_lte(self.v, maximum=self.v_max, title="Transaction.v") super().validate()
def get_uncle_reward(block_reward: int, block_number: int, uncle: BlockAPI) -> int: block_number_delta = block_number - uncle.block_number validate_lte(block_number_delta, MAX_UNCLE_DEPTH) return (8 - block_number_delta) * block_reward // 8
def get_uncle_reward(block_reward, block_number, uncle): block_number_delta = block_number - uncle.block_number validate_lte(block_number_delta, MAX_UNCLE_DEPTH) return (8 - block_number_delta) * block_reward // 8
def get_uncle_reward(block_number, uncle): block_number_delta = block_number - uncle.block_number validate_lte(block_number_delta, MAX_UNCLE_DEPTH) return (8 - block_number_delta) * EIP649_BLOCK_REWARD // 8
def test_validate_lte(value, maximum, is_valid): if is_valid: validate_lte(value, maximum) else: with pytest.raises(ValidationError): validate_lte(value, maximum)
def validate_slot(slot: int, title: str = "Slot") -> None: validate_is_integer(slot, title) validate_gte(slot, 0, title) validate_lte(slot, 2**64 - 1, title)