def keccak256_helper(expr, to_hash, context): _check_byteslike(to_hash.typ, expr) # Can hash literals # TODO this is dead code. if isinstance(to_hash, bytes): return IRnode.from_list(bytes_to_int(keccak256(to_hash)), typ=BaseType("bytes32")) # Can hash bytes32 objects if is_base_type(to_hash.typ, "bytes32"): return IRnode.from_list( [ "seq", ["mstore", MemoryPositions.FREE_VAR_SPACE, to_hash], ["sha3", MemoryPositions.FREE_VAR_SPACE, 32], ], typ=BaseType("bytes32"), add_gas_estimate=_gas_bound(1), ) to_hash = ensure_in_memory(to_hash, context) with to_hash.cache_when_complex("buf") as (b1, to_hash): data = bytes_data_ptr(to_hash) len_ = get_bytearray_length(to_hash) return b1.resolve( IRnode.from_list( ["sha3", data, len_], typ="bytes32", annotation="keccak256", add_gas_estimate=_gas_bound(ceil(to_hash.typ.maxlen / 32)), ))
def to_bytes_m(expr, arg, out_typ): out_info = out_typ._bytes_info _check_bytes(expr, arg, out_typ, max_bytes_allowed=out_info.m) if isinstance(arg.typ, ByteArrayType): bytes_val = LOAD(bytes_data_ptr(arg)) # zero out any dirty bytes (which can happen in the last # word of a bytearray) len_ = get_bytearray_length(arg) num_zero_bits = IRnode.from_list(["mul", ["sub", 32, len_], 8]) with num_zero_bits.cache_when_complex("bits") as (b, num_zero_bits): arg = shl(num_zero_bits, shr(num_zero_bits, bytes_val)) arg = b.resolve(arg) elif is_bytes_m_type(arg.typ): arg_info = arg.typ._bytes_info # clamp if it's a downcast if arg_info.m > out_info.m: arg = bytes_clamp(arg, out_info.m) elif is_integer_type(arg.typ) or is_base_type(arg.typ, "address"): int_bits = arg.typ._int_info.bits if out_info.m_bits < int_bits: # question: allow with runtime clamp? # arg = int_clamp(m_bits, signed=int_info.signed) _FAIL(arg.typ, out_typ, expr) # note: neg numbers not OOB. keep sign bit arg = shl(256 - out_info.m_bits, arg) elif is_decimal_type(arg.typ): if out_info.m_bits < arg.typ._decimal_info.bits: _FAIL(arg.typ, out_typ, expr) # note: neg numbers not OOB. keep sign bit arg = shl(256 - out_info.m_bits, arg) else: # bool arg = shl(256 - out_info.m_bits, arg) return IRnode.from_list(arg, typ=out_typ)
def _bytes_to_num(arg, out_typ, signed): # converting a bytestring to a number: # bytestring and bytes_m are right-padded with zeroes, int is left-padded. # convert by shr or sar the number of zero bytes (converted to bits) # e.g. "abcd000000000000" -> bitcast(000000000000abcd, output_type) if isinstance(arg.typ, ByteArrayLike): _len = get_bytearray_length(arg) arg = LOAD(bytes_data_ptr(arg)) num_zero_bits = ["mul", 8, ["sub", 32, _len]] elif is_bytes_m_type(arg.typ): info = arg.typ._bytes_info num_zero_bits = 8 * (32 - info.m) else: raise CompilerPanic("unreachable") # pragma: notest if signed: ret = sar(num_zero_bits, arg) else: ret = shr(num_zero_bits, arg) annotation = (f"__intrinsic__byte_array_to_num({out_typ})", ) return IRnode.from_list(ret, annotation=annotation)
def load_bytearray(side): return LOAD(bytes_data_ptr(side))