Ejemplo n.º 1
0
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)),
            ))
Ejemplo n.º 2
0
def to_bytes32(expr, args, kwargs, context):
    in_arg = args[0]
    input_type, _len = get_type(in_arg)

    if input_type == "Bytes":
        if _len > 32:
            raise TypeMismatch(
                f"Unable to convert bytes[{_len}] to bytes32, max length is too "
                "large.")

        with in_arg.cache_when_complex("bytes") as (b1, in_arg):
            op = load_op(in_arg.location)
            ofst = wordsize(in_arg.location) * DYNAMIC_ARRAY_OVERHEAD
            bytes_val = [op, ["add", in_arg, ofst]]

            # zero out any dirty bytes (which can happen in the last
            # word of a bytearray)
            len_ = get_bytearray_length(in_arg)
            num_zero_bits = LLLnode.from_list(["mul", ["sub", 32, len_], 8])
            with num_zero_bits.cache_when_complex("bits") as (b2,
                                                              num_zero_bits):
                ret = shl(num_zero_bits, shr(num_zero_bits, bytes_val))
                ret = b1.resolve(b2.resolve(ret))

    else:
        # literal
        ret = in_arg

    return LLLnode.from_list(ret, typ="bytes32", pos=getpos(expr))
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
def byte_array_to_num(arg, out_type):
    """
    Takes a <32 byte array as input, and outputs a number.
    """
    # the location of the bytestring
    bs_start = (LLLnode.from_list(
        "bs_start", typ=arg.typ, location=arg.location, encoding=arg.encoding)
                if arg.is_complex_lll else arg)

    if arg.location == "storage":
        len_ = get_bytearray_length(bs_start)
        data = LLLnode.from_list(["sload", add_ofst(bs_start, 1)],
                                 typ=BaseType("int256"))
    else:
        op = load_op(arg.location)
        len_ = LLLnode.from_list([op, bs_start], typ=BaseType("int256"))
        data = LLLnode.from_list([op, add_ofst(bs_start, 32)],
                                 typ=BaseType("int256"))

    # converting a bytestring to a number:
    # bytestring is right-padded with zeroes, int is left-padded.
    # convert by shr the number of zero bytes (converted to bits)
    # e.g. "abcd000000000000" -> bitcast(000000000000abcd, output_type)
    num_zero_bits = ["mul", 8, ["sub", 32, "len_"]]
    bitcasted = LLLnode.from_list(shr(num_zero_bits, "val"), typ=out_type)

    result = clamp_basetype(bitcasted)

    # TODO use cache_when_complex for these `with` values
    ret = ["with", "val", data, ["with", "len_", len_, result]]
    if arg.is_complex_lll:
        ret = ["with", "bs_start", arg, ret]
    return LLLnode.from_list(
        ret,
        typ=BaseType(out_type),
        annotation=f"__intrinsic__byte_array_to_num({out_type})",
    )