Example #1
0
def consume_length_prefix(rlp, start):
    """Read a length prefix from an RLP string.

    :param rlp: the rlp string to read from
    :param start: the position at which to start reading
    :returns: a tuple ``(type, length, end)``, where ``type`` is either ``str``
              or ``list`` depending on the type of the following payload,
              ``length`` is the length of the payload in bytes, and ``end`` is
              the position of the first payload byte in the rlp string
    """
    b0 = safe_ord(rlp[start])
    if b0 < 128:  # single byte
        return (str, 1, start)
    elif b0 < 128 + 56:  # short string
        return (str, b0 - 128, start + 1)
    elif b0 < 192:  # long string
        ll = b0 - 128 - 56 + 1
        l = big_endian_to_int(rlp[start + 1:start + 1 + ll])
        return (str, l, start + 1 + ll)
    elif b0 < 192 + 56:  # short list
        return (list, b0 - 192, start + 1)
    else:  # long list
        ll = b0 - 192 - 56 + 1
        l = big_endian_to_int(rlp[start + 1:start + 1 + ll])
        return (list, l, start + 1 + ll)
Example #2
0
def mk_test(b, e, m, execgas):
    encoded = mk_modexp_data(b, e, m)
    s = c.snapshot()
    x = c.contract(kode %
                   (len(encoded) + 36, max(intlen(m), 1), max(intlen(m), 1)),
                   language='viper')
    pre = tester.mk_state_test_prefill(c)
    try:
        o = x.foo(
            encoded,
            startgas=21000 +
            intrinsic_gas_of_data(x.translator.encode('foo', [encoded])) +
            execgas)
        if big_endian_to_int(o[:intlen(m)]) != (pow(b, e, m) if m else 0):
            raise Exception(
                "Mismatch! %d %d %d expected %d computed %d" %
                (b, e, m, pow(b, e, m), big_endian_to_int(o[:intlen(m)])))
        print("Succeeded %d %d %d sg %d" % (b, e, m, execgas))
    except tester.TransactionFailed:
        print('OOG %d %d %d sg %d' % (b, e, m, execgas))
    print(c.last_sender)
    o = tester.mk_state_test_postfill(c, pre)
    o2 = tester.mk_state_test_postfill(c, pre, filler_mode=True)
    assert new_statetest_utils.verify_state_test(o)
    c.revert(s)
    return o, o2
def init_state(env, pre):
    # Setup env
    state = State(
        env=Env(config=konfig),
        block_prevhash=decode_hex(remove_0x_head(env['previousHash'])),
        prev_headers=[
            mk_fake_header(i) for i in range(
                parse_int_or_hex(env['currentNumber']) -
                1, max(-1,
                       parse_int_or_hex(env['currentNumber']) - 257), -1)
        ],
        block_number=parse_int_or_hex(env['currentNumber']),
        block_coinbase=decode_hex(remove_0x_head(env['currentCoinbase'])),
        block_difficulty=parse_int_or_hex(env['currentDifficulty']),
        gas_limit=parse_int_or_hex(env['currentGasLimit']),
        timestamp=parse_int_or_hex(env['currentTimestamp']))

    # Fill up pre
    for address, h in list(pre.items()):
        assert len(address) in (40, 42)
        address = decode_hex(remove_0x_head(address))
        assert set(h.keys()) == set(['code', 'nonce', 'balance', 'storage'])
        state.set_nonce(address, parse_int_or_hex(h['nonce']))
        state.set_balance(address, parse_int_or_hex(h['balance']))
        state.set_code(address, decode_hex(remove_0x_head(h['code'])))
        for k, v in h['storage'].items():
            state.set_storage_data(address,
                                   big_endian_to_int(decode_hex(k[2:])),
                                   big_endian_to_int(decode_hex(v[2:])))

    state.commit(allow_empties=True)
    # state.commit()
    return state
Example #4
0
def mk_test(p1, m, execgas, datarestrict=96):
    encoded = mk_ecmul_data(p1, m)[:datarestrict] + \
        b'\x00' * max(datarestrict - 96, 0)
    pre = tester.mk_state_test_prefill(c)
    try:
        o = x1.foo(
            encoded,
            startgas=21000 +
            intrinsic_gas_of_data(
                x1.translator.encode(
                    'foo',
                    [encoded])) +
            execgas)
        x, y = big_endian_to_int(o[:32]), big_endian_to_int(o[32:])
        if py_pairing.normalize(py_pairing.multiply(p1, m)) != (
                py_pairing.FQ(x), py_pairing.FQ(y)):
            raise Exception("Mismatch! %r %r %d, expected %r computed %r" %
                            (p1, m, datarestrict, py_pairing.normalize(py_pairing.multiply(p1, m)), (x, y)))
        print('Succeeded! %r %d %d %r' % (p1, m, datarestrict, (x, y)))
    except tester.TransactionFailed:
        print('OOG %r %d %d %d' % (p1, m, datarestrict, execgas))
    o = tester.mk_state_test_postfill(c, pre)
    o2 = tester.mk_state_test_postfill(c, pre, filler_mode=True)
    assert new_statetest_utils.verify_state_test(o)
    return o, o2
Example #5
0
 def get_tx_position(self, tx):
     if not isinstance(tx, (str, bytes)):
         tx = tx.hash
     if b'txindex:' + tx in self.db:
         data = rlp.decode(self.db.get(b'txindex:' + tx))
         return big_endian_to_int(data[0]), big_endian_to_int(data[1])
     else:
         return None
Example #6
0
 def from_snapshot(cls, snapshot_data, env, executing_on_head=False):
     state = State(env=env)
     if "alloc" in snapshot_data:
         for addr, data in snapshot_data["alloc"].items():
             if len(addr) == 40:
                 addr = decode_hex(addr)
             assert len(addr) == 20
             if 'wei' in data:
                 state.set_balance(addr, parse_as_int(data['wei']))
             if 'balance' in data:
                 state.set_balance(addr, parse_as_int(data['balance']))
             if 'code' in data:
                 state.set_code(addr, parse_as_bin(data['code']))
             if 'nonce' in data:
                 state.set_nonce(addr, parse_as_int(data['nonce']))
             if 'storage' in data:
                 for k, v in data['storage'].items():
                     state.set_storage_data(
                         addr, big_endian_to_int(parse_as_bin(k)),
                         big_endian_to_int(parse_as_bin(v)))
     elif "state_root" in snapshot_data:
         state.trie.root_hash = parse_as_bin(snapshot_data["state_root"])
     else:
         raise Exception(
             "Must specify either alloc or state root parameter")
     for k, default in STATE_DEFAULTS.items():
         default = copy.copy(default)
         v = snapshot_data[k] if k in snapshot_data else None
         if is_numeric(default):
             setattr(state, k,
                     parse_as_int(v) if k in snapshot_data else default)
         elif is_string(default):
             setattr(state, k,
                     parse_as_bin(v) if k in snapshot_data else default)
         elif k == 'prev_headers':
             if k in snapshot_data:
                 headers = [dict_to_prev_header(h) for h in v]
             else:
                 headers = default
             setattr(state, k, headers)
         elif k == 'recent_uncles':
             if k in snapshot_data:
                 uncles = {}
                 for height, _uncles in v.items():
                     uncles[int(height)] = []
                     for uncle in _uncles:
                         uncles[int(height)].append(parse_as_bin(uncle))
             else:
                 uncles = default
             setattr(state, k, uncles)
     if executing_on_head:
         state.executing_on_head = True
     state.commit()
     state.changed = {}
     return state
Example #7
0
 def get_transaction(self, tx):
     if not isinstance(tx, (str, bytes)):
         tx = tx.hash
     if b'txindex:' + tx in self.db:
         data = rlp.decode(self.db.get(b'txindex:' + tx))
         blk, index = self.get_block_by_number(big_endian_to_int(
             data[0])), big_endian_to_int(data[1])
         tx = blk.transactions[index]
         return tx, blk, index
     else:
         return None
Example #8
0
def test_returnten():
    c = tester.Chain()
    open(filename, 'w').write(mul2_code)
    x = c.contract(returnten_code, language='serpent')
    o1 = c.tx(tester.k0, x.address, 0)
    os.remove(filename)
    assert utils.big_endian_to_int(o1) == 10
Example #9
0
def induct_validator(chain, casper, key, value):
    valcode_addr = chain.tx(key, "", 0,
                            mk_validation_code(utils.privtoaddr(key)))
    assert utils.big_endian_to_int(
        chain.tx(key, purity_checker_address, 0,
                 purity_translator.encode('submit', [valcode_addr]))) == 1
    casper.deposit(valcode_addr, utils.privtoaddr(key), value=value)
Example #10
0
def test_callcode():
    c = tester.Chain()
    open(filename3, 'w').write(add1_code)
    x = c.contract(callcode_test_code, language='serpent')
    c.mine(1)
    o1 = c.tx(tester.k0, x.address, 0)
    os.remove(filename3)
    assert utils.big_endian_to_int(o1) == 64
Example #11
0
def optimized_decode_single(x, pos):
    z = safe_ord(x[pos])
    if z < 128:
        return x[pos:pos + 1], 1
    elif z < 184:
        return x[pos + 1:pos + z - 127], z - 127
    else:
        ll = big_endian_to_int(x[pos + 1:pos + z - 182])
        return x[pos + z - 182:pos + z - 182 + ll], z - 182 + ll
Example #12
0
def test_ecrecover():
    c = tester.Chain()
    x = c.contract(ecrecover_code, language='serpent')

    priv = utils.sha3('some big long brainwallet password')
    pub = bitcoin.privtopub(priv)

    msghash = utils.sha3('the quick brown fox jumps over the lazy dog')

    V, R, S = utils.ecsign(msghash, priv)

    assert bitcoin.ecdsa_raw_verify(msghash, (V, R, S), pub)

    addr = utils.big_endian_to_int(
        utils.sha3(bitcoin.encode_pubkey(pub, 'bin')[1:])[12:])
    assert utils.big_endian_to_int(utils.privtoaddr(priv)) == addr

    result = x.test_ecrecover(utils.big_endian_to_int(msghash), V, R, S)
    assert result == addr
Example #13
0
def decode_single(typ, data):
    base, sub, _ = typ
    if base == 'address':
        return '0x' + encode_hex(data[12:])
    elif base == 'hash':
        return data[32 - int(sub):]
    elif base == 'string' or base == 'bytes':
        if len(sub):
            return data[:int(sub)]
        else:
            l = big_endian_to_int(data[0:32])
            return data[32:][:l]
    elif base == 'uint':
        return big_endian_to_int(data) % 2**int(sub)
    elif base == 'int':
        o = big_endian_to_int(data) % 2 ** int(sub)
        return (o - 2 ** int(sub)) if o >= 2 ** (int(sub) - 1) else o
    elif base == 'ufixed':
        high, low = [int(x) for x in sub.split('x')]
        return big_endian_to_int(data) * 1.0 // 2 ** low
    elif base == 'fixed':
        high, low = [int(x) for x in sub.split('x')]
        o = big_endian_to_int(data)
        i = (o - 2 ** (high + low)) if o >= 2 ** (high + low - 1) else o
        return (i * 1.0 // 2 ** low)
    elif base == 'decimal':
        o = big_endian_to_int(data)
        i = (o - 2 ** 256 if o > 2 ** 255 else o)
        return i / 10 ** int(sub)
    elif base == 'bool':
        return bool(int(encode_hex(data), 16))
    else:
        raise EncodingError("Unhandled type: %r %r" % (base, sub))
Example #14
0
def dec(typ, arg):
    base, sub, arrlist = typ
    sz = get_size(typ)
    # Dynamic-sized strings are encoded as <len(str)> + <str>
    if base in ('string', 'bytes') and not sub:
        L = big_endian_to_int(arg[:32])
        assert len(arg[32:]) == ceil32(
            L), "Wrong data size for string/bytes object: expected %d actual %d" % (ceil32(L), len(arg[32:]))
        return arg[32:][:L]
    # Dynamic-sized arrays
    elif sz is None:
        L = big_endian_to_int(arg[:32])
        subtyp = base, sub, arrlist[:-1]
        subsize = get_size(subtyp)
        # If children are dynamic, use the head/tail mechanism. Fortunately,
        # here the code is simpler since we do not have to worry about
        # mixed dynamic and static children, as we do in the top-level multi-arg
        # case
        if subsize is None:
            assert len(arg) >= 32 + 32 * L, "Not enough data for head"
            start_positions = [big_endian_to_int(arg[32 + 32 * i: 64 + 32 * i])
                               for i in range(L)] + [len(arg)]
            outs = [arg[start_positions[i]: start_positions[i + 1]]
                    for i in range(L)]
            return [dec(subtyp, out) for out in outs]
        # If children are static, then grab the data slice for each one and
        # sequentially decode them manually
        else:
            return [dec(subtyp, arg[32 + subsize * i: 32 + subsize * (i + 1)])
                    for i in range(L)]
    # Static-sized arrays: decode piece-by-piece
    elif len(arrlist):
        L = arrlist[-1][0]
        subtyp = base, sub, arrlist[:-1]
        subsize = get_size(subtyp)
        return [dec(subtyp, arg[subsize * i:subsize * (i + 1)])
                for i in range(L)]
    else:
        return decode_single(typ, arg)
Example #15
0
def state_from_genesis_declaration(genesis_data,
                                   env,
                                   block=None,
                                   allow_empties=False,
                                   executing_on_head=False):
    if block:
        assert isinstance(block, Block)
    else:
        block = block_from_genesis_declaration(genesis_data, env)

    state = State(env=env)
    for addr, data in genesis_data["alloc"].items():
        addr = normalize_address(addr)
        assert len(addr) == 20
        if 'wei' in data:
            state.set_balance(addr, parse_as_int(data['wei']))
        if 'balance' in data:
            state.set_balance(addr, parse_as_int(data['balance']))
        if 'code' in data:
            state.set_code(addr, parse_as_bin(data['code']))
        if 'nonce' in data:
            state.set_nonce(addr, parse_as_int(data['nonce']))
        if 'storage' in data:
            for k, v in data['storage'].items():
                state.set_storage_data(addr,
                                       big_endian_to_int(parse_as_bin(k)),
                                       big_endian_to_int(parse_as_bin(v)))
    get_consensus_strategy(state.config).initialize(state, block)
    if executing_on_head:
        state.executing_on_head = True
    state.commit(allow_empties=allow_empties)
    print('deleting %d' % len(state.deletes))
    rdb = RefcountDB(state.db)
    for delete in state.deletes:
        rdb.delete(delete)
    block.header.state_root = state.trie.root_hash
    state.changed = {}
    state.prev_headers = [block.header]
    return state
Example #16
0
def proc_modexp(ext, msg):
    if not ext.post_metropolis_hardfork():
        return 1, msg.gas, []
    print('modexp proc', msg.gas)
    baselen = msg.data.extract32(0)
    explen = msg.data.extract32(32)
    modlen = msg.data.extract32(64)
    first_exp_bytes = msg.data.extract32(96 + baselen) >> (8 *
                                                           max(32 - explen, 0))
    bitlength = -1
    while first_exp_bytes:
        bitlength += 1
        first_exp_bytes >>= 1
    adjusted_explen = max(bitlength, 0) + 8 * max(explen - 32, 0)
    gas_cost = (mult_complexity(max(modlen, baselen)) *
                max(adjusted_explen, 1)) // opcodes.GMODEXPQUADDIVISOR
    print(baselen, explen, modlen, 'expected gas cost', gas_cost)
    if msg.gas < gas_cost:
        return 0, 0, []
    if baselen == 0:
        return 1, msg.gas - gas_cost, [0] * modlen
    if modlen == 0:
        return 1, msg.gas - gas_cost, []
    base = bytearray(baselen)
    msg.data.extract_copy(base, 0, 96, baselen)
    exp = bytearray(explen)
    msg.data.extract_copy(exp, 0, 96 + baselen, explen)
    mod = bytearray(modlen)
    msg.data.extract_copy(mod, 0, 96 + baselen + explen, modlen)
    if utils.big_endian_to_int(mod) == 0:
        return 1, msg.gas - gas_cost, [0] * modlen
    o = pow(utils.big_endian_to_int(base), utils.big_endian_to_int(exp),
            utils.big_endian_to_int(mod))
    return 1, msg.gas - \
        gas_cost, [
            safe_ord(x) for x in utils.zpad(
                utils.int_to_big_endian(o), modlen)]
Example #17
0
def decint(n, signed=False):  # pylint: disable=invalid-name,too-many-branches
    """ Decode an unsigned/signed integer. """

    if isinstance(n, str):
        n = utils.to_string(n)

    if n is True:
        return 1

    if n is False:
        return 0

    if n is None:
        return 0

    if is_numeric(n):
        if signed:
            if not -TT255 <= n <= TT255 - 1:
                raise EncodingError('Number out of range: %r' % n)
        else:
            if not 0 <= n <= TT256 - 1:
                raise EncodingError('Number out of range: %r' % n)

        return n

    if is_string(n):
        if len(n) > 32:
            raise EncodingError('String too long: %r' % n)

        if len(n) == 40:
            int_bigendian = decode_hex(n)
        else:
            int_bigendian = n  # pylint: disable=redefined-variable-type

        result = big_endian_to_int(int_bigendian)
        if signed:
            if result >= TT255:
                result -= TT256

            if not -TT255 <= result <= TT255 - 1:
                raise EncodingError('Number out of range: %r' % n)
        else:
            if not 0 <= result <= TT256 - 1:
                raise EncodingError('Number out of range: %r' % n)

        return result

    raise EncodingError('Cannot decode integer: %r' % n)
Example #18
0
def preprocess_code(code):
    o = 0
    i = 0
    pushcache = {}
    code = code + b'\x00' * 32
    while i < len(code) - 32:
        codebyte = safe_ord(code[i])
        if codebyte == 0x5b:
            o |= 1 << i
        if 0x60 <= codebyte <= 0x7f:
            pushcache[i] = utils.big_endian_to_int(
                code[i + 1: i + codebyte - 0x5e])
            i += codebyte - 0x5e
        else:
            i += 1
    return o, pushcache
Example #19
0
def check_pow(block_number, header_hash, mixhash, nonce, difficulty):
    """Check if the proof-of-work of the block is valid.

    :param nonce: if given the proof of work function will be evaluated
                  with this nonce instead of the one already present in
                  the header
    :returns: `True` or `False`
    """
    log.debug('checking pow', block_number=block_number)
    if len(mixhash) != 32 or len(header_hash) != 32 or len(nonce) != 8:
        return False

    # Grab current cache
    cache = get_cache(block_number)
    mining_output = hashimoto_light(block_number, cache, header_hash, nonce)
    if mining_output[b'mix digest'] != mixhash:
        return False
    return utils.big_endian_to_int(
        mining_output[b'result']) <= 2**256 // (difficulty or 1)
Example #20
0
def decode_abi(types, data):
    # Process types
    proctypes = [process_type(typ) for typ in types]
    # Get sizes of everything
    sizes = [get_size(typ) for typ in proctypes]
    # Initialize array of outputs
    outs = [None] * len(types)
    # Initialize array of start positions
    start_positions = [None] * len(types) + [len(data)]
    # If a type is static, grab the data directly, otherwise record
    # its start position
    pos = 0
    for i, typ in enumerate(types):
        if sizes[i] is None:
            start_positions[i] = big_endian_to_int(data[pos:pos + 32])
            j = i - 1
            while j >= 0 and start_positions[j] is None:
                start_positions[j] = start_positions[i]
                j -= 1
            pos += 32
        else:
            outs[i] = data[pos:pos + sizes[i]]
            pos += sizes[i]
    # We add a start position equal to the length of the entire data
    # for convenience.
    j = len(types) - 1
    while j >= 0 and start_positions[j] is None:
        start_positions[j] = start_positions[len(types)]
        j -= 1
    assert pos <= len(data), "Not enough data for head"
    # Grab the data for tail arguments using the start positions
    # calculated above
    for i, typ in enumerate(types):
        if sizes[i] is None:
            offset = start_positions[i]
            next_offset = start_positions[i + 1]
            outs[i] = data[offset:next_offset]
    # Recursively decode them all
    return [dec(proctypes[i], outs[i]) for i in range(len(outs))]
Example #21
0
def event_id(name, encode_types):
    """ Return the event id.

    Defined as:

        `keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")")`

    Where `canonical_type_of` is a function that simply returns the canonical
    type of a given argument, e.g. for uint indexed foo, it would return
    uint256). Note the lack of spaces.
    """

    event_types = [
        _canonical_type(type_)
        for type_ in encode_types
    ]

    event_signature = '{event_name}({canonical_types})'.format(
        event_name=name,
        canonical_types=','.join(event_types),
    )

    return big_endian_to_int(utils.sha3(event_signature))
Example #22
0
def method_id(name, encode_types):
    """ Return the unique method id.

    The signature is defined as the canonical expression of the basic
    prototype, i.e. the function name with the parenthesised list of parameter
    types. Parameter types are split by a single comma - no spaces are used.

    The method id is defined as the first four bytes (left, high-order in
    big-endian) of the Keccak (SHA-3) hash of the signature of the function.
    """
    function_types = [
        _canonical_type(type_)
        for type_ in encode_types
    ]

    function_signature = '{function_name}({canonical_types})'.format(
        function_name=name,
        canonical_types=','.join(function_types),
    )

    function_keccak = utils.sha3(function_signature)
    first_bytes = function_keccak[:4]

    return big_endian_to_int(first_bytes)
Example #23
0
def test_sixten():
    c = tester.Chain()
    addr = decode_hex('1231231231231234564564564564561231231231')
    c.head_state.set_code(addr, serpent.compile_lll(sixten_code))
    o1 = c.tx(tester.k0, addr, 0)
    assert utils.big_endian_to_int(o1) == 610
Example #24
0
def vm_execute(ext, msg, code):
    # precompute trace flag
    # if we trace vm, we're in slow mode anyway
    trace_vm = log_vm_op.is_active('trace')

    compustate = Compustate(gas=msg.gas)
    stk = compustate.stack
    mem = compustate.memory

    if code in code_cache:
        processed_code = code_cache[code]
    else:
        processed_code = preprocess_code(code)
        code_cache[code] = processed_code
        # print(processed_code.keys(), code)

    codelen = len(code)

    s = time.time()
    steps = 0
    _prevop = None  # for trace only

    while compustate.pc in processed_code:
        ops, minstack, maxstack, totgas, nextpos = processed_code[
            compustate.pc]

        if len(compustate.stack) < minstack:
            return vm_exception('INSUFFICIENT STACK')
        if len(compustate.stack) > maxstack:
            return vm_exception('STACK SIZE LIMIT EXCEEDED')
        if totgas > compustate.gas:
            return vm_exception('OUT OF GAS %d %d' % (totgas, compustate.gas))
        jumped = False

        compustate.gas -= totgas
        compustate.pc = nextpos

        # Invalid operation; can only come at the end of a chunk
        if ops[-1][0] == 'INVALID':
            return vm_exception('INVALID OP', opcode=ops[-1][1])

        for op, opcode, pushval in ops:

            if trace_vm:
                """
                This diverges from normal logging, as we use the logging namespace
                only to decide which features get logged in 'bible.vm.op'
                i.e. tracing can not be activated by activating a sub
                like 'bible.vm.op.stack'
                """
                trace_data = {}
                trace_data['stack'] = list(
                    map(to_string, list(compustate.stack)))
                if _prevop in ('MLOAD', 'MSTORE', 'MSTORE8', 'SHA3', 'CALL',
                               'CALLCODE', 'CREATE', 'CALLDATACOPY',
                               'CODECOPY', 'EXTCODECOPY'):
                    if len(compustate.memory) < 1024:
                        trace_data['memory'] = \
                            ''.join([encode_hex(ascii_chr(x)) for x
                                     in compustate.memory])
                    else:
                        trace_data['sha3memory'] = \
                            encode_hex(utils.sha3(b''.join([ascii_chr(x) for
                                                            x in compustate.memory])))
                if _prevop in ('SSTORE', ) or steps == 0:
                    trace_data['storage'] = ext.log_storage(msg.to)
                trace_data['gas'] = to_string(compustate.gas + totgas)
                trace_data['inst'] = opcode
                trace_data['pc'] = to_string(compustate.pc - 1)
                if steps == 0:
                    trace_data['depth'] = msg.depth
                    trace_data['address'] = msg.to
                trace_data['steps'] = steps
                trace_data['depth'] = msg.depth
                if op[:4] == 'PUSH':
                    trace_data['pushvalue'] = pushval
                log_vm_op.trace('vm', op=op, **trace_data)
                steps += 1
                _prevop = op

            # Valid operations
            # Pushes first because they are very frequent
            if 0x60 <= opcode <= 0x7f:
                # compustate.pc += opcode - 0x5f # Move 1 byte forward for
                # 0x60, up to 32 bytes for 0x7f
                stk.append(pushval)
            elif opcode < 0x10:
                if op == 'STOP':
                    return peaceful_exit('STOP', compustate.gas, [])
                elif op == 'ADD':
                    stk.append((stk.pop() + stk.pop()) & TT256M1)
                elif op == 'SUB':
                    stk.append((stk.pop() - stk.pop()) & TT256M1)
                elif op == 'MUL':
                    stk.append((stk.pop() * stk.pop()) & TT256M1)
                elif op == 'DIV':
                    s0, s1 = stk.pop(), stk.pop()
                    stk.append(0 if s1 == 0 else s0 // s1)
                elif op == 'MOD':
                    s0, s1 = stk.pop(), stk.pop()
                    stk.append(0 if s1 == 0 else s0 % s1)
                elif op == 'SDIV':
                    s0, s1 = utils.to_signed(stk.pop()), utils.to_signed(
                        stk.pop())
                    stk.append(0 if s1 == 0 else (abs(s0) // abs(s1) *
                                                  (-1 if s0 * s1 < 0 else 1))
                               & TT256M1)
                elif op == 'SMOD':
                    s0, s1 = utils.to_signed(stk.pop()), utils.to_signed(
                        stk.pop())
                    stk.append(0 if s1 == 0 else (abs(s0) % abs(s1) *
                                                  (-1 if s0 < 0 else 1))
                               & TT256M1)
                elif op == 'ADDMOD':
                    s0, s1, s2 = stk.pop(), stk.pop(), stk.pop()
                    stk.append((s0 + s1) % s2 if s2 else 0)
                elif op == 'MULMOD':
                    s0, s1, s2 = stk.pop(), stk.pop(), stk.pop()
                    stk.append((s0 * s1) % s2 if s2 else 0)
                elif op == 'EXP':
                    base, exponent = stk.pop(), stk.pop()
                    # fee for exponent is dependent on its bytes
                    # calc n bytes to represent exponent
                    nbytes = len(utils.encode_int(exponent))
                    expfee = nbytes * opcodes.GEXPONENTBYTE
                    if ext.post_clearing_hardfork():
                        expfee += opcodes.EXP_SUPPLEMENTAL_GAS * nbytes
                    if compustate.gas < expfee:
                        compustate.gas = 0
                        return vm_exception('OOG EXPONENT')
                    compustate.gas -= expfee
                    stk.append(pow(base, exponent, TT256))
                elif op == 'SIGNEXTEND':
                    s0, s1 = stk.pop(), stk.pop()
                    if s0 <= 31:
                        testbit = s0 * 8 + 7
                        if s1 & (1 << testbit):
                            stk.append(s1 | (TT256 - (1 << testbit)))
                        else:
                            stk.append(s1 & ((1 << testbit) - 1))
                    else:
                        stk.append(s1)
            elif opcode < 0x20:
                if op == 'LT':
                    stk.append(1 if stk.pop() < stk.pop() else 0)
                elif op == 'GT':
                    stk.append(1 if stk.pop() > stk.pop() else 0)
                elif op == 'SLT':
                    s0, s1 = utils.to_signed(stk.pop()), utils.to_signed(
                        stk.pop())
                    stk.append(1 if s0 < s1 else 0)
                elif op == 'SGT':
                    s0, s1 = utils.to_signed(stk.pop()), utils.to_signed(
                        stk.pop())
                    stk.append(1 if s0 > s1 else 0)
                elif op == 'EQ':
                    stk.append(1 if stk.pop() == stk.pop() else 0)
                elif op == 'ISZERO':
                    stk.append(0 if stk.pop() else 1)
                elif op == 'AND':
                    stk.append(stk.pop() & stk.pop())
                elif op == 'OR':
                    stk.append(stk.pop() | stk.pop())
                elif op == 'XOR':
                    stk.append(stk.pop() ^ stk.pop())
                elif op == 'NOT':
                    stk.append(TT256M1 - stk.pop())
                elif op == 'BYTE':
                    s0, s1 = stk.pop(), stk.pop()
                    if s0 >= 32:
                        stk.append(0)
                    else:
                        stk.append((s1 // 256**(31 - s0)) % 256)
            elif opcode < 0x40:
                if op == 'SHA3':
                    s0, s1 = stk.pop(), stk.pop()
                    compustate.gas -= opcodes.GSHA3WORD * \
                        (utils.ceil32(s1) // 32)
                    if compustate.gas < 0:
                        return vm_exception('OOG PAYING FOR SHA3')
                    if not mem_extend(mem, compustate, op, s0, s1):
                        return vm_exception('OOG EXTENDING MEMORY')
                    data = bytearray_to_bytestr(mem[s0:s0 + s1])
                    stk.append(utils.big_endian_to_int(utils.sha3(data)))
                elif op == 'ADDRESS':
                    stk.append(utils.coerce_to_int(msg.to))
                elif op == 'BALANCE':
                    if ext.post_anti_dos_hardfork():
                        if not eat_gas(compustate,
                                       opcodes.BALANCE_SUPPLEMENTAL_GAS):
                            return vm_exception("OUT OF GAS")
                    addr = utils.coerce_addr_to_hex(stk.pop() % 2**160)
                    stk.append(ext.get_balance(addr))
                elif op == 'ORIGIN':
                    stk.append(utils.coerce_to_int(ext.tx_origin))
                elif op == 'CALLER':
                    stk.append(utils.coerce_to_int(msg.sender))
                elif op == 'CALLVALUE':
                    stk.append(msg.value)
                elif op == 'CALLDATALOAD':
                    stk.append(msg.data.extract32(stk.pop()))
                elif op == 'CALLDATASIZE':
                    stk.append(msg.data.size)
                elif op == 'CALLDATACOPY':
                    mstart, dstart, size = stk.pop(), stk.pop(), stk.pop()
                    if not mem_extend(mem, compustate, op, mstart, size):
                        return vm_exception('OOG EXTENDING MEMORY')
                    if not data_copy(compustate, size):
                        return vm_exception('OOG COPY DATA')
                    msg.data.extract_copy(mem, mstart, dstart, size)
                elif op == 'CODESIZE':
                    stk.append(len(code))
                elif op == 'CODECOPY':
                    mstart, dstart, size = stk.pop(), stk.pop(), stk.pop()
                    if not mem_extend(mem, compustate, op, mstart, size):
                        return vm_exception('OOG EXTENDING MEMORY')
                    if not data_copy(compustate, size):
                        return vm_exception('OOG COPY DATA')
                    for i in range(size):
                        if dstart + i < len(code):
                            mem[mstart + i] = utils.safe_ord(code[dstart + i])
                        else:
                            mem[mstart + i] = 0
                elif op == 'RETURNDATACOPY':
                    mstart, dstart, size = stk.pop(), stk.pop(), stk.pop()
                    if not mem_extend(mem, compustate, op, mstart, size):
                        return vm_exception('OOG EXTENDING MEMORY')
                    if not data_copy(compustate, size):
                        return vm_exception('OOG COPY DATA')
                    if dstart + size > len(compustate.last_returned):
                        return vm_exception('RETURNDATACOPY out of range')
                    mem[mstart:mstart + size] = compustate.last_returned
                elif op == 'RETURNDATASIZE':
                    stk.append(len(compustate.last_returned))
                elif op == 'GASPRICE':
                    stk.append(ext.tx_gasprice)
                elif op == 'EXTCODESIZE':
                    if ext.post_anti_dos_hardfork():
                        if not eat_gas(compustate,
                                       opcodes.EXTCODELOAD_SUPPLEMENTAL_GAS):
                            return vm_exception("OUT OF GAS")
                    addr = utils.coerce_addr_to_hex(stk.pop() % 2**160)
                    stk.append(len(ext.get_code(addr) or b''))
                elif op == 'EXTCODECOPY':
                    if ext.post_anti_dos_hardfork():
                        if not eat_gas(compustate,
                                       opcodes.EXTCODELOAD_SUPPLEMENTAL_GAS):
                            return vm_exception("OUT OF GAS")
                    addr = utils.coerce_addr_to_hex(stk.pop() % 2**160)
                    start, s2, size = stk.pop(), stk.pop(), stk.pop()
                    extcode = ext.get_code(addr) or b''
                    assert utils.is_string(extcode)
                    if not mem_extend(mem, compustate, op, start, size):
                        return vm_exception('OOG EXTENDING MEMORY')
                    if not data_copy(compustate, size):
                        return vm_exception('OOG COPY DATA')
                    for i in range(size):
                        if s2 + i < len(extcode):
                            mem[start + i] = utils.safe_ord(extcode[s2 + i])
                        else:
                            mem[start + i] = 0
            elif opcode < 0x50:
                if op == 'BLOCKHASH':
                    if ext.post_metropolis_hardfork() and False:
                        bh_addr = ext.blockhash_store
                        stk.append(ext.get_storage_data(bh_addr, stk.pop()))
                    else:
                        stk.append(
                            utils.big_endian_to_int(ext.block_hash(stk.pop())))
                elif op == 'COINBASE':
                    stk.append(utils.big_endian_to_int(ext.block_coinbase))
                elif op == 'TIMESTAMP':
                    stk.append(ext.block_timestamp)
                elif op == 'NUMBER':
                    stk.append(ext.block_number)
                elif op == 'DIFFICULTY':
                    stk.append(ext.block_difficulty)
                elif op == 'GASLIMIT':
                    stk.append(ext.block_gas_limit)
            elif opcode < 0x60:
                if op == 'POP':
                    stk.pop()
                elif op == 'MLOAD':
                    s0 = stk.pop()
                    if not mem_extend(mem, compustate, op, s0, 32):
                        return vm_exception('OOG EXTENDING MEMORY')
                    stk.append(utils.bytes_to_int(mem[s0:s0 + 32]))
                elif op == 'MSTORE':
                    s0, s1 = stk.pop(), stk.pop()
                    if not mem_extend(mem, compustate, op, s0, 32):
                        return vm_exception('OOG EXTENDING MEMORY')
                    mem[s0:s0 + 32] = utils.encode_int32(s1)
                elif op == 'MSTORE8':
                    s0, s1 = stk.pop(), stk.pop()
                    if not mem_extend(mem, compustate, op, s0, 1):
                        return vm_exception('OOG EXTENDING MEMORY')
                    mem[s0] = s1 % 256
                elif op == 'SLOAD':
                    if ext.post_anti_dos_hardfork():
                        if not eat_gas(compustate,
                                       opcodes.SLOAD_SUPPLEMENTAL_GAS):
                            return vm_exception("OUT OF GAS")
                    stk.append(ext.get_storage_data(msg.to, stk.pop()))
                elif op == 'SSTORE':
                    s0, s1 = stk.pop(), stk.pop()
                    if msg.static:
                        return vm_exception(
                            'Cannot SSTORE inside a static context')
                    if ext.get_storage_data(msg.to, s0):
                        gascost = opcodes.GSTORAGEMOD if s1 else opcodes.GSTORAGEKILL
                        refund = 0 if s1 else opcodes.GSTORAGEREFUND
                    else:
                        gascost = opcodes.GSTORAGEADD if s1 else opcodes.GSTORAGEMOD
                        refund = 0
                    if compustate.gas < gascost:
                        return vm_exception('OUT OF GAS')
                    compustate.gas -= gascost
                    # adds neg gascost as a refund if below zero
                    ext.add_refund(refund)
                    ext.set_storage_data(msg.to, s0, s1)
                elif op == 'JUMP':
                    compustate.pc = stk.pop()
                    opnew = code[
                        compustate.pc] if compustate.pc < codelen else 0
                    jumped = True
                    if opnew != JUMPDEST:
                        return vm_exception('BAD JUMPDEST')
                elif op == 'JUMPI':
                    s0, s1 = stk.pop(), stk.pop()
                    if s1:
                        compustate.pc = s0
                        opnew = code[
                            compustate.pc] if compustate.pc < codelen else 0
                        jumped = True
                        if opnew != JUMPDEST:
                            return vm_exception('BAD JUMPDEST')
                elif op == 'PC':
                    stk.append(compustate.pc - 1)
                elif op == 'MSIZE':
                    stk.append(len(mem))
                elif op == 'GAS':
                    stk.append(compustate.gas)  # AFTER subtracting cost 1
            elif op[:3] == 'DUP':
                # 0x7f - opcode is a negative number, -1 for 0x80 ... -16 for
                # 0x8f
                stk.append(stk[0x7f - opcode])
            elif op[:4] == 'SWAP':
                # 0x8e - opcode is a negative number, -2 for 0x90 ... -17 for
                # 0x9f
                temp = stk[0x8e - opcode]
                stk[0x8e - opcode] = stk[-1]
                stk[-1] = temp

            elif op[:3] == 'LOG':
                """
                0xa0 ... 0xa4, 32/64/96/128/160 + len(data) gas
                a. Opcodes LOG0...LOG4 are added, takes 2-6 stack arguments
                        MEMSTART MEMSZ (TOPIC1) (TOPIC2) (TOPIC3) (TOPIC4)
                b. Logs are kept track of during tx execution exactly the same way as suicides
                   (except as an ordered list, not a set).
                   Each log is in the form [address, [topic1, ... ], data] where:
                   * address is what the ADDRESS opcode would output
                   * data is mem[MEMSTART: MEMSTART + MEMSZ]
                   * topics are as provided by the opcode
                c. The ordered list of logs in the transaction are expressed as [log0, log1, ..., logN].
                """
                depth = int(op[3:])
                mstart, msz = stk.pop(), stk.pop()
                topics = [stk.pop() for x in range(depth)]
                compustate.gas -= msz * opcodes.GLOGBYTE
                if msg.static:
                    return vm_exception('Cannot LOG inside a static context')
                if not mem_extend(mem, compustate, op, mstart, msz):
                    return vm_exception('OOG EXTENDING MEMORY')
                data = bytearray_to_bytestr(mem[mstart:mstart + msz])
                ext.log(msg.to, topics, data)
                log_log.trace('LOG',
                              to=msg.to,
                              topics=topics,
                              data=list(map(utils.safe_ord, data)))
                # print('LOG', msg.to, topics, list(map(ord, data)))

            elif op == 'CREATE':
                value, mstart, msz = stk.pop(), stk.pop(), stk.pop()
                if not mem_extend(mem, compustate, op, mstart, msz):
                    return vm_exception('OOG EXTENDING MEMORY')
                if msg.static:
                    return vm_exception(
                        'Cannot CREATE inside a static context')
                if ext.get_balance(msg.to) >= value and msg.depth < MAX_DEPTH:
                    cd = CallData(mem, mstart, msz)
                    ingas = compustate.gas
                    if ext.post_anti_dos_hardfork():
                        ingas = all_but_1n(ingas,
                                           opcodes.CALL_CHILD_LIMIT_DENOM)
                    create_msg = Message(msg.to, b'', value, ingas, cd,
                                         msg.depth + 1)
                    o, gas, addr = ext.create(create_msg)
                    if o:
                        stk.append(utils.coerce_to_int(addr))
                    else:
                        stk.append(0)
                    compustate.gas = compustate.gas - ingas + gas
                else:
                    stk.append(0)
            elif op in ('CALL', 'CALLCODE', 'DELEGATECALL', 'STATICCALL'):
                # Pull arguments from the stack
                if op in ('CALL', 'CALLCODE'):
                    gas, to, value, meminstart, meminsz, memoutstart, memoutsz = \
                        stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop()
                else:
                    gas, to, meminstart, meminsz, memoutstart, memoutsz = \
                        stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop()
                    value = 0
                # Static context prohibition
                if msg.static and value > 0:
                    return vm_exception(
                        'Cannot make a non-zero-value call inside a static context'
                    )
                # Expand memory
                if not mem_extend(mem, compustate, op, meminstart, meminsz) or \
                        not mem_extend(mem, compustate, op, memoutstart, memoutsz):
                    return vm_exception('OOG EXTENDING MEMORY')
                to = utils.int_to_addr(to)
                # Extra gas costs based on hard fork-dependent factors
                extra_gas = (not ext.account_exists(to)) * (op == 'CALL') * (value > 0 or not ext.post_clearing_hardfork()) * opcodes.GCALLNEWACCOUNT + \
                    (value > 0) * opcodes.GCALLVALUETRANSFER + \
                    ext.post_anti_dos_hardfork() * opcodes.CALL_SUPPLEMENTAL_GAS
                # Compute child gas limit
                if ext.post_anti_dos_hardfork():
                    if compustate.gas < extra_gas:
                        return vm_exception('OUT OF GAS', needed=extra_gas)
                    gas = min(
                        gas,
                        all_but_1n(compustate.gas - extra_gas,
                                   opcodes.CALL_CHILD_LIMIT_DENOM))
                else:
                    if compustate.gas < gas + extra_gas:
                        return vm_exception('OUT OF GAS',
                                            needed=gas + extra_gas)
                submsg_gas = gas + opcodes.GSTIPEND * (value > 0)
                # Verify that there is sufficient balance and depth
                if ext.get_balance(msg.to) < value or msg.depth >= MAX_DEPTH:
                    compustate.gas -= (gas + extra_gas - submsg_gas)
                    stk.append(0)
                else:
                    # Subtract gas from parent
                    compustate.gas -= (gas + extra_gas)
                    assert compustate.gas >= 0
                    cd = CallData(mem, meminstart, meminsz)
                    # Generate the message
                    if op == 'CALL':
                        call_msg = Message(msg.to,
                                           to,
                                           value,
                                           submsg_gas,
                                           cd,
                                           msg.depth + 1,
                                           code_address=to,
                                           static=msg.static)
                    elif ext.post_homestead_hardfork(
                    ) and op == 'DELEGATECALL':
                        call_msg = Message(msg.sender,
                                           msg.to,
                                           msg.value,
                                           submsg_gas,
                                           cd,
                                           msg.depth + 1,
                                           code_address=to,
                                           transfers_value=False,
                                           static=msg.static)
                    elif op == 'DELEGATECALL':
                        return vm_exception('OPCODE INACTIVE')
                    elif op == 'CALLCODE':
                        call_msg = Message(msg.to,
                                           msg.to,
                                           value,
                                           submsg_gas,
                                           cd,
                                           msg.depth + 1,
                                           code_address=to,
                                           static=msg.static)
                    elif op == 'STATICCALL':
                        call_msg = Message(msg.to,
                                           to,
                                           value,
                                           submsg_gas,
                                           cd,
                                           msg.depth + 1,
                                           code_address=to,
                                           static=True)
                    else:
                        raise Exception("Lolwut")
                    # Get result
                    result, gas, data = ext.msg(call_msg)
                    if result == 0:
                        stk.append(0)
                    else:
                        stk.append(1)
                    # Set output memory
                    for i in range(min(len(data), memoutsz)):
                        mem[memoutstart + i] = data[i]
                    compustate.gas += gas
                    compustate.last_returned = bytearray(data)
            elif op == 'RETURN':
                s0, s1 = stk.pop(), stk.pop()
                if not mem_extend(mem, compustate, op, s0, s1):
                    return vm_exception('OOG EXTENDING MEMORY')
                return peaceful_exit('RETURN', compustate.gas, mem[s0:s0 + s1])
            elif op == 'REVERT':
                if not ext.post_metropolis_hardfork():
                    return vm_exception('Opcode not yet enabled')
                s0, s1 = stk.pop(), stk.pop()
                if not mem_extend(mem, compustate, op, s0, s1):
                    return vm_exception('OOG EXTENDING MEMORY')
                return revert(compustate.gas, mem[s0:s0 + s1])
            elif op == 'SUICIDE':
                if msg.static:
                    return vm_exception(
                        'Cannot SUICIDE inside a static context')
                to = utils.encode_int(stk.pop())
                to = ((b'\x00' * (32 - len(to))) + to)[12:]
                xfer = ext.get_balance(msg.to)
                if ext.post_anti_dos_hardfork():
                    extra_gas = opcodes.SUICIDE_SUPPLEMENTAL_GAS + \
                        (not ext.account_exists(
                            to)) * (xfer > 0 or not ext.post_clearing_hardfork()) * opcodes.GCALLNEWACCOUNT
                    if not eat_gas(compustate, extra_gas):
                        return vm_exception("OUT OF GAS")
                ext.set_balance(to, ext.get_balance(to) + xfer)
                ext.set_balance(msg.to, 0)
                ext.add_suicide(msg.to)
                log_msg.debug('SUICIDING',
                              addr=utils.checksum_encode(msg.to),
                              to=utils.checksum_encode(to),
                              xferring=xfer)
                return 1, compustate.gas, []

            # assert utils.is_numeric(compustate.gas)
            # this is slow!
            # for a in stk:
            #     assert is_numeric(a), (op, stk)
            #     assert a >= 0 and a < 2**256, (a, op, stk)
        # if not jumped:
        #    assert compustate.pc == nextpos
        #    compustate.pc = nextpos
    if compustate.pc >= codelen:
        return peaceful_exit('CODE OUT OF RANGE', compustate.gas, [])
    return vm_exception('INVALID JUMP')
Example #25
0
    def hashimoto_light(s, c, h, n):        return \
pyethash.hashimoto_light(s, c, h, utils.big_endian_to_int(n))
else:
Example #26
0
def scan_int(v):
    if v[:2] in ('0x', b'0x'):
        v = v[2:]
    if len(v) % 2 != 0:
        v = '0' + v
    return big_endian_to_int(decode_hex(v))
Example #27
0
def perturb(inp, pos, by):
    return inp[:pos] + \
        encode_int32(big_endian_to_int(
            inp[pos: pos + 32]) + by) + inp[pos + 32:]
Example #28
0
 def __hash__(self):
     return utils.big_endian_to_int(self.hash)
Example #29
0
def test_types():
    c = tester.Chain()
    x = c.contract(type_code, language='serpent')
    assert utils.big_endian_to_int(c.tx(tester.k0, x.address, 0)) == 5
Example #30
0
    alloc[utils.int_to_addr(i)] = {'balance': 1}
alloc[t.a0] = {'balance': 10**22}
alloc[t.a1] = {'balance': 10**22}
genesis = casper_utils.make_casper_genesis(alloc, 5, 100, 0.02, 0.002)
c = t.Chain(genesis=genesis)
t.languages['viper'] = compiler.Compiler()
t.gas_limit = 9999999
t.STARTGAS = 2000000
c.mine(1)

EPOCH_LENGTH = c.chain.config['EPOCH_LENGTH']

ct = abi.ContractTranslator(purity_checker_abi)
# Check that the RLP decoding library and the sig hashing library are "pure"
assert utils.big_endian_to_int(
    c.tx(t.k0, purity_checker_address, 0,
         ct.encode('submit', [viper_rlp_decoder_address]))) == 1
assert utils.big_endian_to_int(
    c.tx(t.k0, purity_checker_address, 0,
         ct.encode('submit', [sig_hasher_address]))) == 1

casper = t.ABIContract(c, casper_abi, c.chain.config['CASPER_ADDRESS'])
c.mine(1)

# Begin the test

print("Starting tests")
# Initialize the first epoch
c.mine(EPOCH_LENGTH - c.head_state.block_number)
# casper.initialize_epoch(1)
assert casper.get_nextValidatorIndex() == 0