Exemplo n.º 1
0
def test_transaction(filename, testname, testdata):
    testdata = fixture_to_bytes(testdata)

    try:
        rlpdata = decode_hex(testdata["rlp"][2:])
        o = {}
        tx = rlp.decode(rlpdata, transactions.Transaction)
        blknum = int(testdata["blocknumber"])
        if blknum >= config.default_config["HOMESTEAD_FORK_BLKNUM"]:
            tx.check_low_s()
        o["sender"] = tx.sender
        o["transaction"] = {
            "data": b'0x' * (len(tx.data) > 0) + encode_hex(tx.data),
            "gasLimit": str_to_bytes(str(tx.startgas)),
            "gasPrice": str_to_bytes(str(tx.gasprice)),
            "nonce": str_to_bytes(str(tx.nonce)),
            "r": b'0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.r), 32)),
            "s": b'0x' + encode_hex(utils.zpad(utils.int_to_big_endian(tx.s), 32)),
            "v": str_to_bytes(str(tx.v)),
            "value": str_to_bytes(str(tx.value)),
            "to": encode_hex(tx.to),
        }
    except Exception as e:
        tx = None
        sys.stderr.write(str(e))
    if 'transaction' not in testdata:  # expected to fail
        assert tx is None
    else:
        assert set(o['transaction'].keys()) == set(testdata.get("transaction", dict()).keys())
        o.get("transaction", None) == testdata.get("transaction", None)
        assert encode_hex(o.get("sender", '')) == testdata.get("sender", '')
Exemplo n.º 2
0
def coerce_addr_to_hex(x):
    if is_numeric(x):
        return encode_hex(zpad(big_endian_int.serialize(x), 20))
    elif len(x) == 40 or len(x) == 0:
        return x
    else:
        return encode_hex(zpad(x, 20)[-20:])
Exemplo n.º 3
0
def make_keystore_json(priv, pw, kdf="pbkdf2", cipher="aes-128-ctr"):
    # Get the hash function and default parameters
    if kdf not in kdfs:
        raise Exception("Hash algo %s not supported" % kdf)
    kdfeval = kdfs[kdf]["calc"]
    kdfparams = kdfs[kdf]["mkparams"]()
    # Compute derived key
    derivedkey = kdfeval(pw, kdfparams)
    # Get the cipher and default parameters
    if cipher not in ciphers:
        raise Exception("Encryption algo %s not supported" % cipher)
    encrypt = ciphers[cipher]["encrypt"]
    cipherparams = ciphers[cipher]["mkparams"]()
    # Produce the encryption key and encrypt
    enckey = derivedkey[:16]
    c = encrypt(priv, enckey, cipherparams)
    # Compute the MAC
    mac = sha3(derivedkey[16:32] + c)
    # Make a UUID
    u = encode_hex(os.urandom(16))
    uuid = b'-'.join((u[:8], u[8:12], u[12:16], u[16:20], u[20:]))
    # Return the keystore json
    return {
        "crypto": {
            "cipher": cipher,
            "ciphertext": encode_hex(c),
            "cipherparams": cipherparams,
            "kdf": kdf,
            "kdfparams": kdfparams,
            "mac": encode_hex(mac),
            "version": 1
        },
        "id": uuid,
        "version": 3
    }
Exemplo n.º 4
0
def run_test(filename, testname, testdata):
    testdata = fixture_to_bytes(testdata)

    try:
        rlpdata = decode_hex(testdata["rlp"][2:])
        print rlpdata.encode("hex")
        o = {}
        tx = rlp.decode(rlpdata, transactions.Transaction)
        o["sender"] = tx.sender
        o["transaction"] = {
            "data": b"0x" * (len(tx.data) > 0) + encode_hex(tx.data),
            "gasLimit": str_to_bytes(str(tx.startgas)),
            "gasPrice": str_to_bytes(str(tx.gasprice)),
            "nonce": str_to_bytes(str(tx.nonce)),
            "r": b"0x" + encode_hex(utils.zpad(utils.int_to_big_endian(tx.r), 32)),
            "s": b"0x" + encode_hex(utils.zpad(utils.int_to_big_endian(tx.s), 32)),
            "v": str_to_bytes(str(tx.v)),
            "value": str_to_bytes(str(tx.value)),
            "to": encode_hex(tx.to),
        }
    except:
        tx = None
    if "transaction" not in testdata:  # expected to fail
        assert tx is None
    else:
        assert set(o["transaction"].keys()) == set(testdata.get("transaction", dict()).keys())
        o.get("transaction", None) == testdata.get("transaction", None)
        assert encode_hex(o.get("sender", "")) == testdata.get("sender", "")
Exemplo n.º 5
0
 def msg_wrapper(msg):
     hexdata = encode_hex(msg.data.extract_all())
     apply_message_calls.append(dict(gasLimit=to_string(msg.gas),
                                     value=to_string(msg.value),
                                     destination=encode_hex(msg.to),
                                     data=b'0x' + hexdata))
     return 1, msg.gas, b''
Exemplo n.º 6
0
def decode_single(typ, data):
    base, sub, _ = typ
    if base == 'address':
        return 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)
    elif base == 'int':
        o = big_endian_to_int(data)
        return (o - 2 ** int(sub)) if o >= 2 ** (int(sub) - 1) else o
    elif base == 'ureal':
        high, low = [int(x) for x in sub.split('x')]
        return big_endian_to_int(data) * 1.0 // 2 ** low
    elif base == 'real':
        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 == 'bool':
        return bool(int(encode_hex(data), 16))
Exemplo n.º 7
0
 def to_dict(self):
     return {
         "bloom": encode_hex(bloom.b64(bloom.bloom_from_list(self.bloomables()))),
         "address": encode_hex(self.address),
         "data": b"0x" + encode_hex(self.data),
         "topics": [encode_hex(utils.int32.serialize(t)) for t in self.topics],
     }
Exemplo n.º 8
0
def decode_single(typ, data):
    try:
        base, sub, arrlist = typ
    except ValueError:
        base, sub, arrlist = process_type(typ)

    if is_hex_encoded_value(data):
        data = decode_hex(strip_0x_prefix(data))

    if base == 'address':
        return 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)
    elif base == 'int':
        o = big_endian_to_int(data)
        return (o - 2**int(sub)) if o >= 2**(int(sub) - 1) else o
    elif base == 'ureal':
        high, low = [int(x) for x in sub.split('x')]
        return big_endian_to_int(data) * 1.0 / 2**low
    elif base == 'real':
        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 == 'bool':
        return bool(int(encode_hex(data), 16))
Exemplo n.º 9
0
 def on_receive_blockhashes(self, proto, blockhashes):
     if blockhashes:
         log.debug("on_receive_blockhashes", count=len(blockhashes), remote_id=proto,
                   first=encode_hex(blockhashes[0]), last=encode_hex(blockhashes[-1]))
     else:
         log.debug("recv 0 remote block hashes, signifying genesis block")
     self.synchronizer.receive_blockhashes(proto, blockhashes)
Exemplo n.º 10
0
def gen_test(code, val, data):
    while 1:
        s = t.state(1)
        c = s.contract(code)
        pre = s.block.to_dict()['state']
        env = {
            "currentCoinbase": s.block.coinbase,
            "currentDifficulty": str(s.block.difficulty),
            "currentGasLimit": str(s.block.gas_limit),
            "currentNumber": str(s.block.number),
            "currentTimestamp": str(s.block.timestamp),
            "previousHash": encode_hex(s.block.prevhash)
        }
        apply_message_calls = []

        orig_apply_msg = pb.apply_msg

        def apply_msg_wrapper(_block, _tx, msg, code):
            apply_message_calls.append(dict(gasLimit=msg.gas, value=msg.value,
                                            desgination=msg.to,
                                            data=encode_hex(msg.data)))
            result, gas_rem, data = orig_apply_msg(_block, _tx, msg, code)
            return result, gas_rem, data

        pb.apply_msg = apply_msg_wrapper

        d = serpent.encode_datalist(map(int, data))
        tx = pyethereum.transactions.Transaction(1, 10**12, 10000, c, val, data)\
            .sign(t.keys[0])
        msg = pb.Message(t.accounts[0], c, val, 10000, d)
        exek = {
            "address": msg.to,
            "caller": msg.sender,
            "code": '0x' + encode_hex(s.block.get_code(c)),
            "data": '0x' + encode_hex(d),
            "gas": str(10000),
            "gasPrice": str(10**12),
            "origin": tx.sender,
            "value": str(val)
        }
        success, gas, o = pb.apply_msg(s.block, tx, msg, s.block.get_code(c))
        post = s.block.to_dict()['state']
        callcreates = apply_message_calls[1:]
        if success:
            break

    return {
        "callcreates": callcreates,
        "env": env,
        "pre": pre,
        "post": post,
        "exec": exek,
        "gas": str(gas),
        "out": '0x'+encode_hex(''.join(map(ascii_chr, o)))
    }
Exemplo n.º 11
0
def eth_getBlockByNumber(block_number, full_tx):
    block_number = format_block_number(block_number)
    #if block_number >= len(
    block = evm.blocks[block_number]

    return {
        "number": "0x" + int_to_hex(block.number),
        "hash": "0x" + encode_hex(block.hash),
        "parentHash": "0x" + encode_hex(block.prevhash),
        "nonce": "0x" + encode_hex(block.nonce),
        "sha3Uncles": "0x" + encode_hex(block.uncles_hash),
        # TODO logsBloom / padding
        "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "transactionsRoot": "0x" + encode_hex(block.tx_list_root),
        "stateRoot": "0x" + encode_hex(block.state_root),
        "miner": "0x" + encode_hex(block.coinbase),
        "difficulty": "0x" + int_to_hex(block.difficulty),
        # https://github.com/ethereum/pyethereum/issues/266
        # "totalDifficulty": "0x" + int_to_hex(block.chain_difficulty()),
        "size": "0x" + int_to_hex(len(rlp.encode(block))),
        "extraData": "0x" + encode_hex(block.extra_data),
        "gasLimit": "0x" + int_to_hex(block.gas_limit),
        "gasUsed": "0x" + int_to_hex(block.gas_used),
        "timestamp": "0x" + int_to_hex(block.timestamp),
        "transactions": jsonTxs(block.get_transactions()) if full_tx else [encode_hex(tx) for tx in block.get_transaction_hashes()],
        "uncles": block.uncles
    }
Exemplo n.º 12
0
    def test_allowances(self):

        # a
        # aa             ab
        # aaa  aab       aba
        # aaaa aaba aabb abaa

        genesis_hash = decode_hex("fca5e1a248b8fee34db137da5e38b41f95d11feb5a8fa192a150d8d5d8de1c59")

        null_hash = decode_hex("0000000000000000000000000000000000000000000000000000000000000000")
        # print encode_hex(null_hash)

        k0_addr = encode_hex(keys.privtoaddr(t.k0))
        k1_addr = encode_hex(keys.privtoaddr(t.k1))
        k2_addr = encode_hex(keys.privtoaddr(t.k2))

        contract_addr = encode_hex(keys.privtoaddr(t.k9))

        self.assertEqual(k1_addr, '7d577a597b2742b498cb5cf0c26cdcd726d39e6e')

        self.assertEqual(self.rc.balanceOf(keys.privtoaddr(t.k0), genesis_hash), 2100000000000000)

        self.rc.transfer(k1_addr, 1000000, genesis_hash, sender=t.k0, startgas=200000)

        # self.s.block.timestamp = self.s.block.timestamp + 100
        # self.s = t.state()

        window_index = 4 # index of genesis hash in struct

        self.assertEqual(self.rc.balanceOf(keys.privtoaddr(t.k0), genesis_hash), 2100000000000000-1000000)
        self.assertEqual(self.rc.balanceOf(k1_addr, genesis_hash), 1000000)

        with self.assertRaises(TransactionFailed):
            self.rc.transferFrom(k0_addr, k1_addr, 400000, genesis_hash, sender=t.k2, startgas=200000)

        self.rc.approve(k2_addr, 500000, genesis_hash, sender=t.k0, startgas=200000)

        with self.assertRaises(TransactionFailed):
            self.rc.transferFrom(k0_addr, k1_addr, 600000, genesis_hash, sender=t.k2, startgas=200000)


        self.mine()
        start_bal = self.rc.balanceOf(k0_addr, genesis_hash)

        self.rc.transferFrom(k0_addr, k1_addr, 400000, genesis_hash, sender=t.k2, startgas=200000)
        #self.assertEqual(self.rc.balanceOf(k1_addr, genesis_hash), 1000000-500000)

        self.mine()

        self.assertEqual(self.rc.balanceOf(k1_addr, genesis_hash), 400000+1000000)
        self.assertEqual(self.rc.balanceOf(k0_addr, genesis_hash), start_bal - 400000)

        with self.assertRaises(TransactionFailed):
            self.rc.transferFrom(k0_addr, 400000, genesis_hash, sender=t.k2, startgas=200000)
Exemplo n.º 13
0
def jsonTxs(txs):
    return [{
        "from": "0x" + encode_hex(tx._sender),
        "gas": tx.startgas,
        "gasPrice": tx.gasprice,
        "hash": "0x" + encode_hex(tx.hash),
        "input": "0x" + encode_hex(tx.data),
        "nonce": tx.nonce,
        "to": "0x" + encode_hex(tx.to) if tx.to else None,
        "transactionIndex": i,
        "value": tx.value
    } for i, tx in enumerate(txs)]
Exemplo n.º 14
0
def dump_genesis_block_tests_data(db):
    import json
    g = genesis(db)
    data = dict(
        genesis_state_root=encode_hex(g.state_root),
        genesis_hash=g.hex_hash(),
        genesis_rlp_hex=encode_hex(g.serialize()),
        initial_alloc=dict()
    )
    for addr, balance in GENESIS_INITIAL_ALLOC.items():
        data['initial_alloc'][addr] = to_string(balance)

    print(json.dumps(data, indent=1))
Exemplo n.º 15
0
    def synchronize_unknown_block(self, peer, block_hash, force=False):
        "Case: block with unknown parent. Fetches unknown ancestors and this block"
        log.debug('sync unknown', peer=peer, block=encode_hex(block_hash))
        if block_hash == self.chain_manager.genesis.hash or block_hash in self.chain_manager:
            log.debug('known_hash, skipping', peer=peer, hash=encode_hex(block_hash))
            return

        if peer and (not peer in self.synchronization_tasks) or force:
            log.debug('new sync task', peer=peer)
            self.synchronization_tasks[peer] = SynchronizationTask(
                self.chain_manager, peer, block_hash)
        else:
            log.debug('existing synctask', peer=peer)
Exemplo n.º 16
0
def send(transaction):
    if "from" in transaction:
        addr = decode_hex(strip_0x(transaction['from']))
        sender = keys[accounts.index(addr)]
    else:
        sender = keys[0]

    if "value" in transaction:
        value = int(strip_0x(transaction['value']), 16)
    else:
        value = 0

    if "to" in transaction:
        to = strip_0x(transaction['to'])
    else:
        to = None

    if "data" in transaction:
        data = decode_hex(strip_0x(transaction['data']))
    else:
        data = ""

    if "gas" in transaction:
        gas = int(strip_0x(transaction['gas']), 16)
    else:
        gas = None

    # print("value: " + encode_hex(value))
    # print("to: " + to)
    # print("from: " + encode_hex(accounts[keys.index(sender)]))
    # print("data: " + encode_hex(data))
    # print("gas: " + str(gas))

    if isContract(transaction):
        estimated_cost = len(encode_hex(data)) / 2 * 200

        print("Adding contract...")
        print("Estimated gas cost: " + str(estimated_cost))

        if gas != None and estimated_cost > gas:
            print("* ")
            print("* WARNING: Estimated cost higher than sent gas: " + str(estimated_cost) + " > " + str(gas))
            print("* ")

        r = encode_hex(evm.evm(data, sender, value, gas))
    else:
        r = encode_hex(evm.send(sender, to, value, data, gas))

    r = "0x" + r
    return r
 def encode_payments(payments):
     args = []
     value_sum = 0L
     for idx, v in payments:
         addr = tester.accounts[idx]
         value_sum += v
         v = long(v)
         assert v < 2**96
         vv = zpad(int_to_big_endian(v), 12)
         mix = vv + addr
         assert len(mix) == 32
         print encode_hex(mix), "v: ", v, "addr", encode_hex(addr)
         args.append(mix)
     return args, value_sum
Exemplo n.º 18
0
def _apply_msg(ext, msg, code):
    trace_msg = log_msg.is_active("trace")
    if trace_msg:
        log_msg.debug(
            "MSG APPLY",
            sender=encode_hex(msg.sender),
            to=encode_hex(msg.to),
            gas=msg.gas,
            value=msg.value,
            data=encode_hex(msg.data.extract_all()),
        )
        if log_state.is_active("trace"):
            log_state.trace(
                "MSG PRE STATE SENDER",
                account=encode_hex(msg.sender),
                bal=ext.get_balance(msg.sender),
                state=ext.log_storage(msg.sender),
            )
            log_state.trace(
                "MSG PRE STATE RECIPIENT",
                account=encode_hex(msg.to),
                bal=ext.get_balance(msg.to),
                state=ext.log_storage(msg.to),
            )
        # log_state.trace('CODE', code=code)
    # Transfer value, instaquit if not enough
    snapshot = ext._block.snapshot()
    if msg.transfers_value:
        if not ext._block.transfer_value(msg.sender, msg.to, msg.value):
            log_msg.debug("MSG TRANSFER FAILED", have=ext.get_balance(msg.to), want=msg.value)
            return 1, msg.gas, []
    # Main loop
    if msg.code_address in specials.specials:
        res, gas, dat = specials.specials[msg.code_address](ext, msg)
    else:
        res, gas, dat = vm.vm_execute(ext, msg, code)
    # gas = int(gas)
    # assert utils.is_numeric(gas)
    if trace_msg:
        log_msg.debug("MSG APPLIED", gas_remained=gas, sender=encode_hex(msg.sender), to=encode_hex(msg.to), data=dat)
        if log_state.is_active("trace"):
            log_state.trace(
                "MSG POST STATE SENDER",
                account=encode_hex(msg.sender),
                bal=ext.get_balance(msg.sender),
                state=ext.log_storage(msg.sender),
            )
            log_state.trace(
                "MSG POST STATE RECIPIENT",
                account=encode_hex(msg.to),
                bal=ext.get_balance(msg.to),
                state=ext.log_storage(msg.to),
            )

    if res == 0:
        log_msg.debug("REVERTING")
        ext._block.revert(snapshot)

    return res, gas, dat
Exemplo n.º 19
0
 def to_dict(self):
     """Serialize the header to a readable dictionary."""
     d = {}
     for field in ('prevhash', 'uncles_hash', 'extra_data', 'nonce',
                   'mixhash'):
         d[field] = b'0x' + encode_hex(getattr(self, field))
     for field in ('state_root', 'tx_list_root', 'receipts_root',
                   'coinbase'):
         d[field] = encode_hex(getattr(self, field))
     for field in ('number', 'difficulty', 'gas_limit', 'gas_used',
                   'timestamp'):
         d[field] = to_string(getattr(self, field))
     d['bloom'] = encode_hex(int256.serialize(self.bloom))
     assert len(d) == len(BlockHeader.fields)
     return d
Exemplo n.º 20
0
def test_encode(name, in_out):
    msg_format = 'Test {} failed (encoded {} to {} instead of {})'
    data = in_out['in']
    result = utils.encode_hex(encode(data)).upper()
    expected = in_out['out'].upper()
    if result != expected:
        pytest.fail(msg_format.format(name, data, result, expected))
Exemplo n.º 21
0
 def apply_msg_wrapper(_block, _tx, msg, code):
     apply_message_calls.append(dict(gasLimit=msg.gas,
                                     value=msg.value,
                                     desgination=msg.to,
                                     data=encode_hex(msg.data)))
     result, gas_rem, out = orig_apply_msg(_block, _tx, msg, code)
     return result, gas_rem, out
Exemplo n.º 22
0
def eth_getCode(address, block_number="latest"):
    address = strip_0x(address)

    block_number = format_block_number(block_number)
    block = evm.blocks[block_number]

    return "0x" + encode_hex(block.get_code(address))
Exemplo n.º 23
0
    def on_receive_getblockhashes(self, proto, child_block_hash, count):
        log.debug('----------------------------------')
        log.debug("handle_get_blockhashes", count=count, block_hash=encode_hex(child_block_hash))
        max_hashes = min(count, self.wire_protocol.max_getblockhashes_count)
        found = []
        if child_block_hash not in self.chain:
            log.debug("unknown block")
            proto.send_blockhashes(*[])
            return

        last = child_block_hash
        while len(found) < max_hashes:
            try:
                last = rlp.decode_lazy(self.chain.db.get(last))[0][0]  # [head][prevhash]
            except KeyError:
                # this can happen if we started a chain download, which did not complete
                # should not happen if the hash is part of the canonical chain
                log.warn('KeyError in getblockhashes', hash=last)
                break
            if last:
                found.append(last)
            else:
                break

        log.debug("sending: found block_hashes", count=len(found))
        proto.send_blockhashes(*found)
Exemplo n.º 24
0
def run_test(name):

    logger.debug('testing %s' % name)
    pairs = load_tests()[name]

    def _dec(x):
        if is_string(x) and x.startswith(b'0x'):
            return decode_hex(x[2:])
        return x

    pairs['in'] = [(_dec(k), _dec(v)) for k, v in pairs['in']]
    deletes = [(k, v) for k, v in pairs['in'] if v is None]

    N_PERMUTATIONS = 1000
    for i, permut in enumerate(itertools.permutations(pairs['in'])):
        if i > N_PERMUTATIONS:
            break
        t = trie.Trie(db.EphemDB())
        for k, v in permut:
            #logger.debug('updating with (%s, %s)' %(k, v))
            if v is not None:
                t.update(k, v)
            else:
                t.delete(k)
        # make sure we have deletes at the end
        for k, v in deletes:
            t.delete(k)
        assert pairs['root'] == b'0x' + encode_hex(t.root_hash), (i, list(permut) + deletes)
Exemplo n.º 25
0
 def big_endian_to_int(value):
     if len(value) == 1:
         return ord(value)
     elif len(value) <= 8:
         return struct.unpack('>Q', value.rjust(8, b'\x00'))[0]
     else:
         return int(encode_hex(value), 16)
Exemplo n.º 26
0
def test_ecrecover():
    s = tester.state()
    c = s.abi_contract(ecrecover_code)

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

    msghash = encode_hex(utils.sha3('the quick brown fox jumps over the lazy dog'))
    V, R, S = bitcoin.ecdsa_raw_sign(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 = c.test_ecrecover(utils.big_endian_to_int(decode_hex(msghash)), V, R, S)
    assert result == addr
Exemplo n.º 27
0
def test_library_from_code():
    with open(path.join(CONTRACTS_DIR, 'seven_library.sol')) as handler:
        library_code = handler.read()

    with open(path.join(CONTRACTS_DIR, 'seven_contract_without_import.sol')) as handler:
        contract_code = handler.read()

    state = tester.state()
    state.env.config['HOMESTEAD_FORK_BLKNUM'] = 0  # enable CALLCODE opcode

    library = state.abi_contract(
        library_code,
        path=None,
        language='solidity',
    )

    libraries = {
        'SevenLibrary': encode_hex(library.address),
    }
    contract = state.abi_contract(
        contract_code,
        path=None,
        libraries=libraries,
        language='solidity',
    )

    # pylint: disable=no-member
    assert library.seven() == 7
    assert contract.test() == 7
Exemplo n.º 28
0
 def get_call_data(self, args):
     """
     TODO: this needs tests.
     """
     prefix = self.encoded_abi_signature
     suffix = self.abi_args_signature(args)
     return encode_hex(prefix + suffix)
Exemplo n.º 29
0
def encode_data(data, length=None):
    """Encode unformatted binary `data`.

    If `length` is given, the result will be padded like this: ``quantity_encoder(255, 3) ==
    '0x0000ff'``.
    """
    return add_0x(encode_hex(zpad(data, length or 0)))
Exemplo n.º 30
0
 def to_dict(self):
     # TODO: previous version used printers
     d = {}
     for name, _ in self.__class__.fields:
         d[name] = getattr(self, name)
     d['sender'] = self.sender
     d['hash'] = encode_hex(self.hash)
     return d
Exemplo n.º 31
0
def bytes2Hex(string) -> str:
    return '0x' + encode_hex(string)
Exemplo n.º 32
0
def dump_state(trie):
    res = ''
    for k, v in list(trie.to_dict().items()):
        res += '%r:%r\n' % (encode_hex(k), encode_hex(v))
    return res
Exemplo n.º 33
0
    args.data = decode_hex(args.data[2:])

amount = Decimal(args.amount) * 10**18

tx = Transaction(nonce=int(args.nonce),
                 gasprice=int(args.gasprice),
                 startgas=int(args.startgas),
                 to=decode_hex(args.to[2:]),
                 value=int(amount),
                 data=args.data)

encodedTx = encode(tx, UnsignedTransaction)

donglePath = parse_bip32_path(args.path)
apdu = "e0040000".decode('hex') + chr(len(donglePath) + 1 +
                                      len(encodedTx)) + chr(
                                          len(donglePath) /
                                          4) + donglePath + encodedTx

dongle = getDongle(True)
result = dongle.exchange(bytes(apdu))

v = result[0]
r = int(str(result[1:1 + 32]).encode('hex'), 16)
s = int(str(result[1 + 32:1 + 32 + 32]).encode('hex'), 16)

tx = Transaction(tx.nonce, tx.gasprice, tx.startgas, tx.to, tx.value, tx.data,
                 v, r, s)

print "Signed transaction " + encode_hex(encode(tx))
Exemplo n.º 34
0
def create_contract(ext, msg):
    log_msg.debug("CONTRACT CREATION")

    if msg.is_cross_shard:
        return 0, msg.gas, b""

    code = msg.data.extract_all()

    if ext.tx_origin != msg.sender:
        ext.increment_nonce(msg.sender)

    if ext.post_constantinople_hardfork() and msg.sender == null_address:
        msg.to = mk_contract_address(msg.sender, msg.to_full_shard_id, 0)
        # msg.to = sha3(msg.sender + code)[12:]
    else:
        nonce = utils.encode_int(ext.get_nonce(msg.sender) - 1)
        msg.to = mk_contract_address(msg.sender, msg.to_full_shard_id, nonce)

    if ext.post_metropolis_hardfork() and (ext.get_nonce(msg.to)
                                           or len(ext.get_code(msg.to))):
        log_msg.debug("CREATING CONTRACT ON TOP OF EXISTING CONTRACT")
        return 0, 0, b""

    b = ext.get_balance(msg.to)
    if b > 0:
        ext.set_balance(msg.to, b)
        ext.set_nonce(msg.to, 0)
        ext.set_code(msg.to, b"")
        # ext.reset_storage(msg.to)

    msg.is_create = True
    # assert not ext.get_code(msg.to)
    msg.data = vm.CallData([], 0, 0)
    snapshot = ext.snapshot()

    ext.set_nonce(msg.to, 1 if ext.post_spurious_dragon_hardfork() else 0)
    res, gas, dat = _apply_msg(ext, msg, code)

    log_msg.debug(
        "CONTRACT CREATION FINISHED",
        res=res,
        gas=gas,
        dat=dat if len(dat) < 2500 else ("data<%d>" % len(dat)),
    )

    if res:
        if not len(dat):
            # ext.set_code(msg.to, b'')
            return 1, gas, msg.to
        gcost = len(dat) * opcodes.GCONTRACTBYTE
        if gas >= gcost and (len(dat) <= 24576
                             or not ext.post_spurious_dragon_hardfork()):
            gas -= gcost
        else:
            dat = []
            log_msg.debug(
                "CONTRACT CREATION FAILED",
                have=gas,
                want=gcost,
                block_number=ext.block_number,
            )
            if ext.post_homestead_hardfork():
                ext.revert(snapshot)
                return 0, 0, b""
        ext.set_code(msg.to, bytearray_to_bytestr(dat))
        log_msg.debug("SETTING CODE", addr=encode_hex(msg.to), lendat=len(dat))
        return 1, gas, msg.to
    else:
        ext.revert(snapshot)
        return 0, gas, dat
Exemplo n.º 35
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')

    # Initialize stack, memory, program counter, etc
    compustate = Compustate(gas=msg.gas)
    stk = compustate.stack
    mem = compustate.memory

    # Compute
    jumpdest_mask, pushcache = preprocess_code(code)
    codelen = len(code)

    # For tracing purposes
    op = None
    steps = 0
    _prevop = None  # for trace only

    while compustate.pc < codelen:

        opcode = safe_ord(code[compustate.pc])

        # Invalid operation
        if opcode not in opcodes.opcodes:
            return vm_exception('INVALID OP', opcode=opcode)

        op, in_args, out_args, fee = opcodes.opcodes[opcode]

        # out of gas error
        if fee > compustate.gas:
            return vm_exception('OUT OF GAS')

        # empty stack error
        if in_args > len(compustate.stack):
            return vm_exception('INSUFFICIENT STACK',
                                op=op,
                                needed=to_string(in_args),
                                available=to_string(len(compustate.stack)))

        # overfull stack error
        if len(compustate.stack) - in_args + out_args > 1024:
            return vm_exception('STACK SIZE LIMIT EXCEEDED',
                                op=op,
                                pre_height=to_string(len(compustate.stack)))

        # Apply operation
        compustate.gas -= fee
        compustate.pc += 1

        # Tracing
        if trace_vm:
            """
            This diverges from normal logging, as we use the logging namespace
            only to decide which features get logged in 'eth.vm.op'
            i.e. tracing can not be activated by activating a sub
            like 'eth.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 + fee)
            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'] = pushcache[compustate.pc - 1]
            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:
            stk.append(pushcache[compustate.pc - 1])
            compustate.pc += opcode - 0x5f  # Move 1 byte forward for 0x60, up to 32 bytes for 0x7f
        # Arithmetic
        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_spurious_dragon_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)
        # Comparisons
        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)
        # SHA3 and environment info
        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(codelen)
            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 < codelen:
                        mem[mstart + i] = 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] = safe_ord(extcode[s2 + i])
                    else:
                        mem[start + i] = 0
        # Block info
        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)
        # VM state manipulations
        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
                ext.add_refund(
                    refund)  # adds neg gascost as a refund if below zero
                ext.set_storage_data(msg.to, s0, s1)
            elif op == 'JUMP':
                compustate.pc = stk.pop()
                if compustate.pc >= codelen or not (
                    (1 << compustate.pc) & jumpdest_mask):
                    return vm_exception('BAD JUMPDEST')
            elif op == 'JUMPI':
                s0, s1 = stk.pop(), stk.pop()
                if s1:
                    compustate.pc = s0
                    if compustate.pc >= codelen or not (
                        (1 << compustate.pc) & jumpdest_mask):
                        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
        # DUPn (eg. DUP1: a b c -> a b c c, DUP3: a b c -> a b c a)
        elif op[:3] == 'DUP':
            stk.append(
                stk[0x7f - opcode]
            )  # 0x7f - opcode is a negative number, -1 for 0x80 ... -16 for 0x8f
        # SWAPn (eg. SWAP1: a b c d -> a b d c, SWAP3: a b c d -> d b c a)
        elif op[:4] == 'SWAP':
            temp = stk[
                0x8e -
                opcode]  # 0x8e - opcode is a negative number, -2 for 0x90 ... -17 for 0x9f
            stk[0x8e - opcode] = stk[-1]
            stk[-1] = temp
        # Logs (aka "events")
        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)))
        # Create a new contract
        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)
        # Calls
        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 and op == 'CALL':
                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 various factors
            extra_gas = 0
            # Creating a new account
            if op == 'CALL' and not ext.account_exists(to) and (
                    value > 0 or not ext.post_spurious_dragon_hardfork()):
                extra_gas += opcodes.GCALLNEWACCOUNT
            # Value transfer
            if value > 0:
                extra_gas += opcodes.GCALLVALUETRANSFER
            # Cost increased from 40 to 700 in Tangerine Whistle
            if ext.post_anti_dos_hardfork():
                extra_gas += 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 ext.post_metropolis_hardfork() and op == 'STATICCALL':
                    call_msg = Message(msg.to,
                                       to,
                                       value,
                                       submsg_gas,
                                       cd,
                                       msg.depth + 1,
                                       code_address=to,
                                       static=True)
                elif op in ('DELEGATECALL', 'STATICCALL'):
                    return vm_exception('OPCODE %s INACTIVE' % op)
                elif op == 'CALLCODE':
                    call_msg = Message(msg.to,
                                       msg.to,
                                       value,
                                       submsg_gas,
                                       cd,
                                       msg.depth + 1,
                                       code_address=to,
                                       static=msg.static)
                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)
        # Return opcode
        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])
        # Revert opcode (Metropolis)
        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])
        # SUICIDE opcode (also called SELFDESTRUCT)
        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_spurious_dragon_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 peaceful_exit('SUICIDED', compustate.gas, [])

    return peaceful_exit('CODE OUT OF RANGE', compustate.gas, [])
Exemplo n.º 36
0
    def __init__(self, genesis=None, env=None,
                 new_head_cb=None, reset_genesis=False, localtime=None, max_history=1000, **kwargs):
        self.env = env or Env()
        self.patricia = PatriciaState()
        self.patricia.from_db()  # TODO: test
        # Initialize the state
        if 'head_hash' in self.db:  # new head tag
            self.state = self.mk_poststate_of_blockhash(self.db.get('head_hash'))
            self.state.executing_on_head = True
            databaseLog.info('Initializing chain from saved head, #%d (%s)',self.state.prev_headers[0].number, encode_hex(self.state.prev_headers[0].hash))
        elif genesis is None:
            raise Exception("Need genesis decl!")
        elif isinstance(genesis, State):
            assert env is None
            self.state = genesis
            self.env = self.state.env
            databaseLog.info('Initializing chain from provided state')
        elif isinstance(genesis, dict):
            databaseLog.info('Initializing chain from new state based on alloc')
            diction = {}
            self.state = state_from_genesis_declaration(
                genesis, self.env, executing_on_head=True, pytricia=diction)

            for key in diction:
                self.patricia.set_value(str(key), str(diction[key]))
            self.patricia.to_db()
            reset_genesis = True
        assert self.env.db == self.state.db

        initialize(self.state)
        self.new_head_cb = new_head_cb

        if self.state.block_number == 0:
            assert self.state.block_number == self.state.prev_headers[0].number
        else:
            assert self.state.block_number == self.state.prev_headers[0].number

        if reset_genesis:
            if isinstance(self.state.prev_headers[0], FakeHeader):
                header = self.state.prev_headers[0].to_block_header()
            else:
                header = self.state.prev_headers[0]
            self.genesis = Block(header)
            self.state.prev_headers[0] = header
            initialize_genesis_keys(self.state, self.genesis)
        else:
            self.genesis = self.get_block_by_number(0)

        self.head_hash = self.state.prev_headers[0].hash
        self.time_queue = []
        self.parent_queue = {}
        self.localtime = time.time() if localtime is None else localtime
        self.max_history = max_history
Exemplo n.º 37
0
 def event_topic(self):
     return b'0x' + encode_hex(utils.sha3(self.signature))
Exemplo n.º 38
0
def _apply_msg(ext, msg, code):
    trace_msg = log_msg.is_active("trace")
    if trace_msg:
        log_msg.debug(
            "MSG APPLY",
            sender=encode_hex(msg.sender),
            to=encode_hex(msg.to),
            gas=msg.gas,
            value=msg.value,
            codelen=len(code),
            data=encode_hex(msg.data.extract_all())
            if msg.data.size < 2500 else ("data<%d>" % msg.data.size),
            pre_storage=ext.log_storage(msg.to),
            static=msg.static,
            depth=msg.depth,
        )

    # transfer value, quit if not enough
    snapshot = ext.snapshot()
    if msg.transfers_value:
        if msg.is_cross_shard:
            if not ext.deduct_value(msg.sender, msg.value):
                return 1, msg.gas, []
            ext.add_cross_shard_transaction_deposit(
                quarkchain.core.CrossShardTransactionDeposit(
                    tx_hash=msg.tx_hash,
                    from_address=quarkchain.core.Address(
                        msg.sender, msg.from_full_shard_id),
                    to_address=quarkchain.core.Address(msg.to,
                                                       msg.to_full_shard_id),
                    value=msg.value,
                    gas_price=ext.tx_gasprice,
                ))
        elif not ext.transfer_value(msg.sender, msg.to, msg.value):
            log_msg.debug("MSG TRANSFER FAILED",
                          have=ext.get_balance(msg.to),
                          want=msg.value)
            return 1, msg.gas, []

    if msg.is_cross_shard:
        # Cross shard contract call is not supported
        return 1, msg.gas, []

    # Main loop
    if msg.code_address in ext.specials:
        res, gas, dat = ext.specials[msg.code_address](ext, msg)
    else:
        res, gas, dat = vm.vm_execute(ext, msg, code)

    if trace_msg:
        log_msg.debug(
            "MSG APPLIED",
            gas_remained=gas,
            sender=encode_hex(msg.sender),
            to=encode_hex(msg.to),
            data=dat if len(dat) < 2500 else ("data<%d>" % len(dat)),
            post_storage=ext.log_storage(msg.to),
        )

    if res == 0:
        log_msg.debug("REVERTING")
        ext.revert(snapshot)

    return res, gas, dat
Exemplo n.º 39
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

    codelen = len(processed_code)

    op = None
    steps = 0
    _prevop = None  # for trace only

    while 1:
        # stack size limit error
        if compustate.pc >= codelen:
            return peaceful_exit('CODE OUT OF RANGE', compustate.gas, [])

        op, in_args, out_args, fee, opcode, pushval = \
            processed_code[compustate.pc]

        # out of gas error
        if fee > compustate.gas:
            return vm_exception('OUT OF GAS')

        # empty stack error
        if in_args > len(compustate.stack):
            return vm_exception('INSUFFICIENT STACK',
                                op=op,
                                needed=to_string(in_args),
                                available=to_string(len(compustate.stack)))

        if len(compustate.stack) - in_args + out_args > 1024:
            return vm_exception('STACK SIZE LIMIT EXCEEDED',
                                op=op,
                                pre_height=to_string(len(compustate.stack)))

        # Apply operation
        compustate.gas -= fee
        compustate.pc += 1

        if trace_vm:
            """
            This diverges from normal logging, as we use the logging namespace
            only to decide which features get logged in 'eth.vm.op'
            i.e. tracing can not be activated by activating a sub
            like 'eth.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'] = \
                        b''.join([encode_hex(ascii_chr(x)) for x
                                  in compustate.memory])
                else:
                    trace_data['sha3memory'] = \
                        encode_hex(utils.sha3(''.join([ascii_chr(x) for
                                              x in compustate.memory])))
            if _prevop in ('SSTORE', 'SLOAD') or steps == 0:
                trace_data['storage'] = ext.log_storage(msg.to)
            trace_data['gas'] = to_string(compustate.gas + fee)
            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['op'] = op
            trace_data['steps'] = steps
            if op[:4] == 'PUSH':
                trace_data['pushvalue'] = pushval
            log_vm_op.trace('vm', **trace_data)
            steps += 1
            _prevop = op

        # Invalid operation
        if op == 'INVALID':
            return vm_exception('INVALID OP', opcode=opcode)

        # Valid operations
        if 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 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 = b''.join(map(ascii_chr, 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':
                # EIP150: Increase the gas cost of BALANCE to 400
                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(processed_code))
            elif op == 'CODECOPY':
                start, s1, size = stk.pop(), stk.pop(), stk.pop()
                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 s1 + i < len(processed_code):
                        mem[start + i] = processed_code[s1 + i][4]
                    else:
                        mem[start + i] = 0
            elif op == 'GASPRICE':
                stk.append(ext.tx_gasprice)
            elif op == 'EXTCODESIZE':
                # EIP150: Increase the gas cost of EXTCODESIZE to 700
                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':
                # EIP150: Increase the base gas cost of EXTCODECOPY to 700
                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':
                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')
                data = b''.join(map(ascii_chr, mem[s0:s0 + 32]))
                stk.append(utils.big_endian_to_int(data))
            elif op == 'MSTORE':
                s0, s1 = stk.pop(), stk.pop()
                if not mem_extend(mem, compustate, op, s0, 32):
                    return vm_exception('OOG EXTENDING MEMORY')
                v = s1
                for i in range(31, -1, -1):
                    mem[s0 + i] = v % 256
                    v //= 256
            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':
                # EIP150: Increase the gas cost of SLOAD to 200
                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 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
                ext.add_refund(
                    refund)  # adds neg gascost as a refund if below zero
                ext.set_storage_data(msg.to, s0, s1)
            elif op == 'JUMP':
                compustate.pc = stk.pop()
                opnew = processed_code[compustate.pc][0] if \
                    compustate.pc < len(processed_code) else 'STOP'
                if opnew != 'JUMPDEST':
                    return vm_exception('BAD JUMPDEST')
            elif op == 'JUMPI':
                s0, s1 = stk.pop(), stk.pop()
                if s1:
                    compustate.pc = s0
                    opnew = processed_code[compustate.pc][0] if \
                        compustate.pc < len(processed_code) else 'STOP'
                    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[:4] == 'PUSH':
            pushnum = int(op[4:])
            compustate.pc += pushnum
            stk.append(pushval)
        elif op[:3] == 'DUP':
            depth = int(op[3:])
            stk.append(stk[-depth])
        elif op[:4] == 'SWAP':
            depth = int(op[4:])
            temp = stk[-depth - 1]
            stk[-depth - 1] = 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 not mem_extend(mem, compustate, op, mstart, msz):
                return vm_exception('OOG EXTENDING MEMORY')
            data = b''.join(map(ascii_chr, 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 ext.get_balance(msg.to) >= value and msg.depth < 1024:
                cd = CallData(mem, mstart, msz)
                ingas = compustate.gas
                # EIP150(1b) CREATE only provides all but one 64th of the
                # parent gas to the child call
                if ext.post_anti_dos_hardfork:
                    ingas = max_call_gas(ingas)

                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))
                    compustate.gas -= (ingas - gas)
                else:
                    stk.append(0)
                    compustate.gas -= ingas
            else:
                stk.append(0)
        elif op == 'CALL':
            gas, to, value, meminstart, meminsz, memoutstart, memoutsz = \
                stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop(), stk.pop()
            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.encode_int(to)
            to = ((b'\x00' * (32 - len(to))) + to)[12:]
            extra_gas = (not ext.account_exists(to)) * opcodes.GCALLNEWACCOUNT + \
                    (value > 0) * opcodes.GCALLVALUETRANSFER + \
                    ext.post_anti_dos_hardfork * opcodes.CALL_SUPPLEMENTAL_GAS
            # ^ EIP150 Increase the gas cost of CALL to 700

            if ext.post_anti_dos_hardfork:
                # EIP150(1b) if a call asks for more gas than all but one 64th of
                # the maximum allowed amount, call with all but one 64th of the
                # maximum allowed amount of gas
                if compustate.gas < extra_gas:
                    return vm_exception('OUT OF GAS', needed=extra_gas)
                gas = min(gas, max_call_gas(compustate.gas - extra_gas))
            else:
                if compustate.gas < gas + extra_gas:
                    return vm_exception('OUT OF GAS', needed=gas + extra_gas)

            submsg_gas = gas + opcodes.GSTIPEND * (value > 0)
            if ext.get_balance(msg.to) >= value and msg.depth < 1024:
                compustate.gas -= (gas + extra_gas)
                cd = CallData(mem, meminstart, meminsz)
                call_msg = Message(msg.to,
                                   to,
                                   value,
                                   submsg_gas,
                                   cd,
                                   msg.depth + 1,
                                   code_address=to)
                result, gas, data = ext.msg(call_msg)
                if result == 0:
                    stk.append(0)
                else:
                    stk.append(1)
                    compustate.gas += gas
                    for i in range(min(len(data), memoutsz)):
                        mem[memoutstart + i] = data[i]
            else:
                compustate.gas -= (gas + extra_gas - submsg_gas)
                stk.append(0)
        elif op == 'CALLCODE' or op == 'DELEGATECALL':
            if op == '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
            if not mem_extend(mem, compustate, op, meminstart, meminsz) or \
                    not mem_extend(mem, compustate, op, memoutstart, memoutsz):
                return vm_exception('OOG EXTENDING MEMORY')
            extra_gas = (value > 0) * opcodes.GCALLVALUETRANSFER + \
                    ext.post_anti_dos_hardfork * opcodes.CALL_SUPPLEMENTAL_GAS
            # ^ EIP150 Increase the gas cost of CALLCODE, DELEGATECALL to 700

            if ext.post_anti_dos_hardfork:
                # EIP150(1b) if a call asks for more gas than all but one 64th of
                # the maximum allowed amount, call with all but one 64th of the
                # maximum allowed amount of gas
                if compustate.gas < extra_gas:
                    return vm_exception('OUT OF GAS', needed=extra_gas)
                gas = min(gas, max_call_gas(compustate.gas - extra_gas))
            else:
                if compustate.gas < gas + extra_gas:
                    return vm_exception('OUT OF GAS', needed=gas + extra_gas)

            submsg_gas = gas + opcodes.GSTIPEND * (value > 0)
            if ext.get_balance(msg.to) >= value and msg.depth < 1024:
                compustate.gas -= (gas + extra_gas)
                to = utils.encode_int(to)
                to = ((b'\x00' * (32 - len(to))) + to)[12:]
                cd = CallData(mem, meminstart, meminsz)
                if 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)
                elif op == 'DELEGATECALL':
                    return vm_exception('OPCODE INACTIVE')
                else:
                    call_msg = Message(msg.to,
                                       msg.to,
                                       value,
                                       submsg_gas,
                                       cd,
                                       msg.depth + 1,
                                       code_address=to)
                result, gas, data = ext.msg(call_msg)
                if result == 0:
                    stk.append(0)
                else:
                    stk.append(1)
                    compustate.gas += gas
                    for i in range(min(len(data), memoutsz)):
                        mem[memoutstart + i] = data[i]
            else:
                compustate.gas -= (gas + extra_gas - submsg_gas)
                stk.append(0)
        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 == 'SUICIDE':
            to = utils.encode_int(stk.pop())
            to = ((b'\x00' * (32 - len(to))) + to)[12:]

            if ext.post_anti_dos_hardfork:
                # EIP150 Increase the gas cost of SUICIDE to 5000
                extra_gas = opcodes.SUICIDE_SUPPLEMENTAL_GAS + \
                        (not ext.account_exists(to)) * opcodes.GCALLNEWACCOUNT
                # ^ EIP150(1c) If SUICIDE hits a newly created account, it
                # triggers an additional gas cost of 25000 (similar to CALLs)
                if not eat_gas(compustate, extra_gas):
                    return vm_exception("OUT OF GAS")

            xfer = ext.get_balance(msg.to)
            ext.set_balance(to, ext.get_balance(to) + xfer)
            ext.set_balance(msg.to, 0)
            ext.add_suicide(msg.to)
            # print('suiciding %s %s %d' % (msg.to, to, xfer))
            return 1, compustate.gas, []
Exemplo n.º 40
0
 def __repr__(self):
     return '<Log(address=%r, topics=%r, data=%r)>' %  \
         (encode_hex(self.address), self.topics, self.data)
def test_abi_signature_single_arg():
    func = Function("register", [{'type': 'bytes32', 'name': 'name'}])
    assert encode_hex(func.encoded_abi_signature) == b"e1fa8e84"
Exemplo n.º 42
0
def valueconv(k, v):
    if k in ['r', 's']:
        return '0x' + encode_hex(utils.int_to_big_endian(v))
    return v
Exemplo n.º 43
0
def run_state_test(params, mode):
    pre = params['pre']
    exek = params['transaction']
    env = params['env']

    assert set(env.keys()) == set([
        'currentGasLimit', 'currentTimestamp', 'previousHash',
        'currentCoinbase', 'currentDifficulty', 'currentNumber'
    ])
    assert len(env['currentCoinbase']) == 40

    # setup env
    header = blocks.BlockHeader(
        prevhash=decode_hex(env['previousHash']),
        number=parse_int_or_hex(env['currentNumber']),
        coinbase=decode_hex(env['currentCoinbase']),
        difficulty=parse_int_or_hex(env['currentDifficulty']),
        timestamp=parse_int_or_hex(env['currentTimestamp']),
        # work around https://github.com/ethereum/pyethereum/issues/390 [1]:
        gas_limit=min(db_env.config['MAX_GAS_LIMIT'],
                      parse_int_or_hex(env['currentGasLimit'])))
    blk = blocks.Block(header, env=db_env)

    # work around https://github.com/ethereum/pyethereum/issues/390 [2]:
    blk.gas_limit = parse_int_or_hex(env['currentGasLimit'])

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

    for address, h in list(pre.items()):
        address = decode_hex(address)
        assert blk.get_nonce(address) == parse_int_or_hex(h['nonce'])
        assert blk.get_balance(address) == parse_int_or_hex(h['balance'])
        assert blk.get_code(address) == decode_hex(h['code'][2:])
        for k, v in h['storage'].items():
            assert blk.get_storage_data(
                address, utils.big_endian_to_int(decode_hex(
                    k[2:]))) == utils.big_endian_to_int(decode_hex(v[2:]))

    # execute transactions
    orig_apply_msg = pb.apply_msg

    def apply_msg_wrapper(ext, msg):
        def blkhash(n):
            if n >= blk.number or n < blk.number - 256:
                return b''
            else:
                return utils.sha3(to_string(n))

        ext.block_hash = blkhash
        return orig_apply_msg(ext, msg)

    pb.apply_msg = apply_msg_wrapper

    try:
        tx = transactions.Transaction(
            nonce=parse_int_or_hex(exek['nonce'] or b"0"),
            gasprice=parse_int_or_hex(exek['gasPrice'] or b"0"),
            startgas=parse_int_or_hex(exek['gasLimit'] or b"0"),
            to=normalize_address(exek['to'], allow_blank=True),
            value=parse_int_or_hex(exek['value'] or b"0"),
            data=decode_hex(remove_0x_head(exek['data'])))
    except InvalidTransaction:
        tx = None
        success, output = False, b''
        time_pre = time.time()
        time_post = time_pre
    else:
        if 'secretKey' in exek:
            tx.sign(exek['secretKey'])
        elif all(key in exek for key in ['v', 'r', 's']):
            tx.v = decode_hex(remove_0x_head(exek['v']))
            tx.r = decode_hex(remove_0x_head(exek['r']))
            tx.s = decode_hex(remove_0x_head(exek['s']))
        else:
            assert False

        time_pre = time.time()
        try:
            print('trying')
            success, output = pb.apply_transaction(blk, tx)
            blk.commit_state()
            print('success', blk.get_receipts()[-1].gas_used)
        except InvalidTransaction:
            success, output = False, b''
            blk.commit_state()
            pass
        time_post = time.time()

        if tx.to == b'':
            output = blk.get_code(output)

    pb.apply_msg = orig_apply_msg

    params2 = copy.deepcopy(params)
    if success:
        params2['logs'] = [log.to_dict() for log in blk.get_receipt(0).logs]

    params2['out'] = b'0x' + encode_hex(output)
    params2['post'] = copy.deepcopy(blk.to_dict(True)['state'])
    params2['postStateRoot'] = encode_hex(blk.state.root_hash)

    if mode == FILL:
        return params2
    elif mode == VERIFY:
        params1 = copy.deepcopy(params)
        shouldbe, reallyis = params1.get('post',
                                         None), params2.get('post', None)
        compare_post_states(shouldbe, reallyis)
        for k in [
                'pre', 'exec', 'env', 'callcreates', 'out', 'gas', 'logs',
                'postStateRoot'
        ]:
            _shouldbe = params1.get(k, None)
            _reallyis = params2.get(k, None)
            if str_to_bytes(k) == b'out' and _shouldbe[:1] in ('#', b'#'):
                _reallyis = str_to_bytes('#%s' % ((len(_reallyis) - 2) // 2))
            if _shouldbe != _reallyis:
                print((
                    'Mismatch {key}: shouldbe {shouldbe_key} != reallyis {reallyis_key}.\n'
                    'post: {shouldbe_post} != {reallyis_post}').format(
                        shouldbe_key=_shouldbe,
                        reallyis_key=_reallyis,
                        shouldbe_post=shouldbe,
                        reallyis_post=reallyis,
                        key=k))
                raise Exception("Mismatch: " + k +
                                ':\n shouldbe %r\n reallyis %r' %
                                (_shouldbe, _reallyis))

    elif mode == TIME:
        return time_post - time_pre
Exemplo n.º 44
0
def int_to_32bytearray(i):
    o = [0] * 32
    for x in range(32):
        o[31 - x] = i & 0xff
        i >>= 8
    return o

# sha3_count = [0]


def sha3(seed):
    return sha3_256(to_string(seed))


assert encode_hex(
    sha3(b'')) == 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'


def privtoaddr(k):
    k = normalize_key(k)
    x, y = privtopub(k)
    return sha3(encode_int32(x) + encode_int32(y))[12:]


def checksum_encode(addr):  # Takes a 20-byte binary address as input
    addr = normalize_address(addr)
    o = ''
    v = big_endian_to_int(sha3(encode_hex(addr)))
    for i, c in enumerate(encode_hex(addr)):
        if c in '0123456789':
            o += c
Exemplo n.º 45
0
def run_block_test(params, config_overrides={}):
    b = blocks.genesis(env, start_alloc=params["pre"])
    gbh = params["genesisBlockHeader"]
    b.bloom = utils.scanners['int256b'](gbh["bloom"])
    b.timestamp = utils.scanners['int'](gbh["timestamp"])
    b.nonce = utils.scanners['bin'](gbh["nonce"])
    b.extra_data = utils.scanners['bin'](gbh["extraData"])
    b.gas_limit = utils.scanners['int'](gbh["gasLimit"])
    b.gas_used = utils.scanners['int'](gbh["gasUsed"])
    b.coinbase = utils.scanners['addr'](decode_hex(gbh["coinbase"]))
    b.difficulty = utils.parse_int_or_hex(gbh["difficulty"])
    b.prevhash = utils.scanners['bin'](gbh["parentHash"])
    b.mixhash = utils.scanners['bin'](gbh["mixHash"])
    assert b.receipts.root_hash == \
        utils.scanners['bin'](gbh["receiptTrie"])
    assert b.transactions.root_hash == \
        utils.scanners['bin'](gbh["transactionsTrie"])
    assert utils.sha3rlp(b.uncles) == \
        utils.scanners['bin'](gbh["uncleHash"])
    h = encode_hex(b.state.root_hash)
    if h != str_to_bytes(gbh["stateRoot"]):
        raise Exception("state root mismatch")
    if b.hash != utils.scanners['bin'](gbh["hash"]):
        raise Exception("header hash mismatch")
    # assert b.header.check_pow()
    blockmap = {b.hash: b}
    env.db.put(b.hash, rlp.encode(b))
    old_config = copy.deepcopy(env.config)
    for k, v in config_overrides.items():
        env.config[k] = v
    b2 = None
    for blk in params["blocks"]:
        if 'blockHeader' not in blk:
            try:
                rlpdata = decode_hex(blk["rlp"][2:])
                blkparent = rlp.decode(
                    rlp.encode(rlp.decode(rlpdata)[0]), blocks.BlockHeader).prevhash
                b2 = rlp.decode(rlpdata, blocks.Block, parent=blockmap[blkparent], env=env)
                success = b2.validate_uncles()
            except (ValueError, TypeError, AttributeError, VerificationFailed,
                    DecodingError, DeserializationError, InvalidTransaction, KeyError):
                success = False
            assert not success
        else:
            rlpdata = decode_hex(blk["rlp"][2:])
            blkparent = rlp.decode(rlp.encode(rlp.decode(rlpdata)[0]), blocks.BlockHeader).prevhash
            b2 = rlp.decode(rlpdata, blocks.Block, parent=blockmap[blkparent], env=env)
            assert b2.validate_uncles()
            blockmap[b2.hash] = b2
            env.db.put(b2.hash, rlp.encode(b2))
        if b2:
            print('Block %d with state root %s' % (b2.number, encode_hex(b2.state.root_hash)))
        # blkdict = b.to_dict(False, True, False, True)
        # assert blk["blockHeader"] == \
        #     translate_keys(blkdict["header"], translator_list, lambda y, x: x, [])
        # assert blk["transactions"] == \
        #     [translate_keys(t, translator_list, valueconv, ['hash'])
        #      for t in blkdict["transactions"]]
        # assert blk["uncleHeader"] == \
        #     [translate_keys(u, translator_list, lambda x: x, [])
        #      for u in blkdict["uncles"]]
    env.config = old_config
Exemplo n.º 46
0
import rlp
from rlp.utils import decode_hex, encode_hex, str_to_bytes
import ethereum.testutils as testutils
from ethereum.testutils import fixture_to_bytes
import sys
import json
import os

from ethereum.slogging import get_logger, configure_logging

logger = get_logger()
# customize VM log output to your needs
# hint: use 'py.test' with the '-s' option to dump logs to the console
# configure_logging(':trace')

encode_hex('')


def run_test(filename, testname, testdata):
    testdata = fixture_to_bytes(testdata)

    try:
        rlpdata = decode_hex(testdata["rlp"][2:])
        o = {}
        tx = rlp.decode(rlpdata, transactions.Transaction)
        o["sender"] = tx.sender
        o["transaction"] = {
            "data": b'0x' * (len(tx.data) > 0) + encode_hex(tx.data),
            "gasLimit": str_to_bytes(str(tx.startgas)),
            "gasPrice": str_to_bytes(str(tx.gasprice)),
            "nonce": str_to_bytes(str(tx.nonce)),
Exemplo n.º 47
0
import rlp
from rlp.utils import decode_hex, encode_hex, str_to_bytes
import ethereum.testutils as testutils
from ethereum.testutils import fixture_to_bytes
import ethereum.config as config
import sys
import json

from ethereum.slogging import get_logger

logger = get_logger()
# customize VM log output to your needs
# hint: use 'py.test' with the '-s' option to dump logs to the console
# configure_logging(':trace')

encode_hex('')


def test_transaction(filename, testname, testdata):
    testdata = fixture_to_bytes(testdata)

    try:
        rlpdata = decode_hex(testdata["rlp"][2:])
        o = {}
        tx = rlp.decode(rlpdata, transactions.Transaction)
        blknum = int(testdata["blocknumber"])
        if blknum >= config.default_config["HOMESTEAD_FORK_BLKNUM"]:
            tx.check_low_s()
        o["sender"] = tx.sender
        o["transaction"] = {
            "data": b'0x' * (len(tx.data) > 0) + encode_hex(tx.data),
Exemplo n.º 48
0
def encode(data):
    from rlp.utils import encode_hex
    return encode_hex(json.dumps(data))
Exemplo n.º 49
0
def to_hex(value):
    return '0x' + encode_hex(value)
Exemplo n.º 50
0
    "addr": decode_addr,
    "int": decode_int,
    "int256b": decode_int256,
}

# Encoding to RLP serialization
encoders = {
    "bin": encode_bin,
    "int": encode_int,
    "trie_root": encode_root,
    "int256b": encode_int256,
}

# Encoding to printable format
printers = {
    "bin": lambda v: b'0x' + encode_hex(v),
    "addr": lambda v: v,
    "int": lambda v: to_string(v),
    "trie_root": lambda v: encode_hex(v),
    "int256b": lambda x: encode_hex(zpad(encode_int256(x), 256))
}

# Decoding from printable format
scanners = {
    "bin": scan_bin,
    "addr": lambda x: x[2:] if x[:2] == b'0x' else x,
    "int": scan_int,
    "trie_root": lambda x: scan_bin,
    "int256b": lambda x: big_endian_to_int(decode_hex(x))
}
Exemplo n.º 51
0
def test_genesis_state_root(genesis_fixture):
    genesis = blocks.genesis(new_env())
    assert encode_hex(genesis.state_root) == utils.to_string(
        genesis_fixture['genesis_state_root'])
Exemplo n.º 52
0
def decode_addr(v):
    '''decodes an address from serialization'''
    if len(v) not in [0, 20]:
        raise Exception("Serialized addresses must be empty or 20 bytes long!")
    return encode_hex(v)
Exemplo n.º 53
0
def run_vm_test(params, mode, profiler=None):
    pre = params['pre']
    exek = params['exec']
    env = params['env']
    if 'previousHash' not in env:
        env['previousHash'] = encode_hex(db_env.config['GENESIS_PREVHASH'])

    assert set(env.keys()) == set([
        'currentGasLimit', 'currentTimestamp', 'previousHash',
        'currentCoinbase', 'currentDifficulty', 'currentNumber'
    ])
    # setup env
    header = blocks.BlockHeader(
        prevhash=decode_hex(env['previousHash']),
        number=parse_int_or_hex(env['currentNumber']),
        coinbase=decode_hex(env['currentCoinbase']),
        difficulty=parse_int_or_hex(env['currentDifficulty']),
        gas_limit=parse_int_or_hex(env['currentGasLimit']),
        timestamp=parse_int_or_hex(env['currentTimestamp']))

    blk = blocks.Block(header, env=db_env)

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

    # execute transactions
    sender = decode_hex(exek['caller'])  # a party that originates a call
    recvaddr = decode_hex(exek['address'])
    nonce = blk._get_acct_item(sender, 'nonce')
    gasprice = parse_int_or_hex(exek['gasPrice'])
    startgas = parse_int_or_hex(exek['gas'])
    value = parse_int_or_hex(exek['value'])
    data = decode_hex(exek['data'][2:])

    # bypass gas check in tx initialization by temporarily increasing startgas
    num_zero_bytes = str_to_bytes(data).count(ascii_chr(0))
    num_non_zero_bytes = len(data) - num_zero_bytes
    intrinsic_gas = (opcodes.GTXCOST + opcodes.GTXDATAZERO * num_zero_bytes +
                     opcodes.GTXDATANONZERO * num_non_zero_bytes)
    startgas += intrinsic_gas
    tx = transactions.Transaction(nonce=nonce,
                                  gasprice=gasprice,
                                  startgas=startgas,
                                  to=recvaddr,
                                  value=value,
                                  data=data)
    tx.startgas -= intrinsic_gas
    tx.sender = sender

    # capture apply_message calls
    apply_message_calls = []
    orig_apply_msg = pb.apply_msg

    ext = pb.VMExt(blk, tx)

    def msg_wrapper(msg):
        hexdata = encode_hex(msg.data.extract_all())
        apply_message_calls.append(
            dict(gasLimit=to_string(msg.gas),
                 value=to_string(msg.value),
                 destination=encode_hex(msg.to),
                 data=b'0x' + hexdata))
        return 1, msg.gas, b''

    def create_wrapper(msg):
        sender = decode_hex(msg.sender) if \
            len(msg.sender) == 40 else msg.sender
        nonce = utils.encode_int(ext._block.get_nonce(msg.sender))
        addr = utils.sha3(rlp.encode([sender, nonce]))[12:]
        hexdata = encode_hex(msg.data.extract_all())
        apply_message_calls.append(
            dict(gasLimit=to_string(msg.gas),
                 value=to_string(msg.value),
                 destination=b'',
                 data=b'0x' + hexdata))
        return 1, msg.gas, addr

    ext.msg = msg_wrapper
    ext.create = create_wrapper

    def blkhash(n):
        if n >= ext.block_number or n < ext.block_number - 256:
            return b''
        else:
            return utils.sha3(to_string(n))

    ext.block_hash = blkhash

    msg = vm.Message(tx.sender, tx.to, tx.value, tx.startgas,
                     vm.CallData([safe_ord(x) for x in tx.data]))
    code = decode_hex(exek['code'][2:])
    time_pre = time.time()
    if profiler:
        profiler.enable()
    success, gas_remained, output = vm.vm_execute(ext, msg, code)
    if profiler:
        profiler.disable()
    pb.apply_msg = orig_apply_msg
    blk.commit_state()
    for s in blk.suicides:
        blk.del_account(s)
    time_post = time.time()
    """
     generally expected that the test implementer will read env, exec and pre
     then check their results against gas, logs, out, post and callcreates.
     If an exception is expected, then latter sections are absent in the test.
     Since the reverting of the state is not part of the VM tests.
     """

    params2 = copy.deepcopy(params)

    if success:
        params2['callcreates'] = apply_message_calls
        params2['out'] = b'0x' + encode_hex(b''.join(map(ascii_chr, output)))
        params2['gas'] = to_string(gas_remained)
        params2['logs'] = [log.to_dict() for log in blk.logs]
        params2['post'] = blk.to_dict(with_state=True)['state']

    if mode == FILL:
        return params2
    elif mode == VERIFY:
        if not success:
            assert 'post' not in params, 'failed, but expected to succeed'

        params1 = copy.deepcopy(params)
        shouldbe, reallyis = params1.get('post',
                                         None), params2.get('post', None)
        compare_post_states(shouldbe, reallyis)

        def normalize_value(k, p):
            if k in p:
                if k == 'gas':
                    return parse_int_or_hex(p[k])
                elif k == 'callcreates':
                    return list(map(callcreate_standard_form, p[k]))
                else:
                    return utils.to_string(k)
            return None

        for k in ['pre', 'exec', 'env', 'callcreates', 'out', 'gas', 'logs']:
            shouldbe = normalize_value(k, params1)
            reallyis = normalize_value(k, params2)
            if shouldbe != reallyis:
                raise Exception("Mismatch: " + k +
                                ':\n shouldbe %r\n reallyis %r' %
                                (shouldbe, reallyis))
    elif mode == TIME:
        return time_post - time_pre
Exemplo n.º 54
0
def int_to_hex(x):
    o = encode_hex(encode_int(x))
    return '0x' + (o[1:] if (len(o) > 0 and o[0] == b'0') else o)
Exemplo n.º 55
0
    def add_block(self, block):
        now = self.localtime
        # Are we receiving the block too early?
        if block.header.timestamp > now:
            i = 0
            while i < len(self.time_queue
                          ) and block.timestamp > self.time_queue[i].timestamp:
                i += 1
            self.time_queue.insert(i, block)
            log.info(
                'Block received too early (%d vs %d). Delaying for %d seconds'
                % (now, block.header.timestamp, block.header.timestamp - now))
            return False
        # Is the block being added to the head?
        if block.header.prevhash == self.head_hash:
            log.info('Adding to head',
                     head=encode_hex(block.header.prevhash[:4]))
            self.state.deletes = []
            self.state.changed = {}
            try:
                apply_block(self.state, block)
            except (AssertionError, KeyError, ValueError, InvalidTransaction,
                    VerificationFailed) as e:
                log.info('Block %d (%s) with parent %s invalid, reason: %s' %
                         (block.number, encode_hex(block.header.hash[:4]),
                          encode_hex(block.header.prevhash[:4]), str(e)))
                return False
            self.db.put(b'block:%d' % block.header.number, block.header.hash)
            # side effect: put 'score:' cache in db
            block_score = self.get_score(block)
            self.head_hash = block.header.hash
            for i, tx in enumerate(block.transactions):
                self.db.put(b'txindex:' + tx.hash,
                            rlp.encode([block.number, i]))
            assert self.get_blockhash_by_number(
                block.header.number) == block.header.hash
            deletes = self.state.deletes
            changed = self.state.changed
        # Or is the block being added to a chain that is not currently the
        # head?
        elif block.header.prevhash in self.env.db:
            log.info(
                'Receiving block %d (%s) not on head (%s), adding to secondary post state %s'
                % (block.number, encode_hex(
                    block.header.hash[:4]), encode_hex(self.head_hash[:4]),
                   encode_hex(block.header.prevhash[:4])))
            temp_state = self.mk_poststate_of_blockhash(block.header.prevhash)
            try:
                apply_block(temp_state, block)
            except (AssertionError, KeyError, ValueError, InvalidTransaction,
                    VerificationFailed) as e:
                log.info('Block %s with parent %s invalid, reason: %s' %
                         (encode_hex(block.header.hash[:4]),
                          encode_hex(block.header.prevhash[:4]), str(e)))
                return False
            deletes = temp_state.deletes
            block_score = self.get_score(block)
            changed = temp_state.changed
            # If the block should be the new head, replace the head
            if block_score > self.get_score(self.head):
                b = block
                new_chain = {}
                # Find common ancestor
                while b.header.number >= int(self.db.get(b'GENESIS_NUMBER')):
                    new_chain[b.header.number] = b
                    key = b'block:%d' % b.header.number
                    orig_at_height = self.db.get(
                        key) if key in self.db else None
                    if orig_at_height == b.header.hash:
                        break
                    if b.prevhash not in self.db or self.db.get(
                            b.prevhash) == b'GENESIS':
                        break
                    b = self.get_parent(b)
                replace_from = b.header.number
                # Replace block index and tx indices, and edit the state cache

                # Get a list of all accounts that have been edited along the old and
                # new chains
                changed_accts = {}
                # Read: for i in range(common ancestor block number...new block
                # number)
                for i in itertools.count(replace_from):
                    log.info('Rewriting height %d' % i)
                    key = b'block:%d' % i
                    # Delete data for old blocks
                    orig_at_height = self.db.get(
                        key) if key in self.db else None
                    if orig_at_height:
                        orig_block_at_height = self.get_block(orig_at_height)
                        log.info('%s no longer in main chain' %
                                 encode_hex(orig_block_at_height.header.hash))
                        # Delete from block index
                        self.db.delete(key)
                        # Delete from txindex
                        for tx in orig_block_at_height.transactions:
                            if b'txindex:' + tx.hash in self.db:
                                self.db.delete(b'txindex:' + tx.hash)
                        # Add to changed list
                        acct_list = self.db.get(b'changed:' +
                                                orig_block_at_height.hash)
                        for j in range(0, len(acct_list), 20):
                            changed_accts[acct_list[j:j + 20]] = True
                    # Add data for new blocks
                    if i in new_chain:
                        new_block_at_height = new_chain[i]
                        log.info('%s now in main chain' %
                                 encode_hex(new_block_at_height.header.hash))
                        # Add to block index
                        self.db.put(key, new_block_at_height.header.hash)
                        # Add to txindex
                        for j, tx in enumerate(
                                new_block_at_height.transactions):
                            self.db.put(
                                b'txindex:' + tx.hash,
                                rlp.encode([new_block_at_height.number, j]))
                        # Add to changed list
                        if i < b.number:
                            acct_list = self.db.get(b'changed:' +
                                                    new_block_at_height.hash)
                            for j in range(0, len(acct_list), 20):
                                changed_accts[acct_list[j:j + 20]] = True
                    if i not in new_chain and not orig_at_height:
                        break
                # Add changed list from new head to changed list
                for c in changed.keys():
                    changed_accts[c] = True
                # Update the on-disk state cache
                for addr in changed_accts.keys():
                    data = temp_state.trie.get(addr)
                    if data:
                        self.state.db.put(b'address:' + addr, data)
                    else:
                        try:
                            self.state.db.delete(b'address:' + addr)
                        except KeyError:
                            pass
                self.head_hash = block.header.hash
                self.state = temp_state
                self.state.executing_on_head = True
        # Block has no parent yet
        else:
            if block.header.prevhash not in self.parent_queue:
                self.parent_queue[block.header.prevhash] = []
            self.parent_queue[block.header.prevhash].append(block)
            log.info(
                'Got block %d (%s) with prevhash %s, parent not found. Delaying for now'
                % (block.number, encode_hex(
                    block.hash[:4]), encode_hex(block.prevhash[:4])))
            return False
        self.add_child(block)

        self.db.put(b'head_hash', self.head_hash)

        self.db.put(block.hash, rlp.encode(block))
        self.db.put(
            b'changed:' + block.hash, b''.join([
                k.encode() if not is_string(k) else k
                for k in list(changed.keys())
            ]))
        print('Saved %d address change logs' % len(changed.keys()))
        self.db.put(b'deletes:' + block.hash, b''.join(deletes))
        log.debug('Saved %d trie node deletes for block %d (%s)' %
                  (len(deletes), block.number, utils.encode_hex(block.hash)))
        # Delete old junk data
        old_block_hash = self.get_blockhash_by_number(block.number -
                                                      self.max_history)
        if old_block_hash:
            try:
                deletes = self.db.get(b'deletes:' + old_block_hash)
                log.debug('Deleting up to %d trie nodes' %
                          (len(deletes) // 32))
                rdb = RefcountDB(self.db)
                for i in range(0, len(deletes), 32):
                    rdb.delete(deletes[i:i + 32])
                self.db.delete(b'deletes:' + old_block_hash)
                self.db.delete(b'changed:' + old_block_hash)
            except KeyError as e:
                print(e)
                pass
        self.db.commit()
        assert (b'deletes:' + block.hash) in self.db
        log.info('Added block %d (%s) with %d txs and %d gas' %
                 (block.header.number, encode_hex(block.header.hash)[:8],
                  len(block.transactions), block.header.gas_used))
        # Call optional callback
        if self.new_head_cb and block.header.number != 0:
            self.new_head_cb(block)
        # Are there blocks that we received that were waiting for this block?
        # If so, process them.
        if block.header.hash in self.parent_queue:
            for _blk in self.parent_queue[block.header.hash]:
                self.add_block(_blk)
            del self.parent_queue[block.header.hash]
        return True
Exemplo n.º 56
0
    def __init__(self,
                 genesis=None,
                 env=None,
                 new_head_cb=None,
                 reset_genesis=False,
                 localtime=None,
                 max_history=1000,
                 **kwargs):
        self.env = env or Env()
        # Initialize the state
        if b'head_hash' in self.db:  # new head tag
            self.state = self.mk_poststate_of_blockhash(
                self.db.get('head_hash'))
            self.state.executing_on_head = True
            print('Initializing chain from saved head, #%d (%s)' %
                  (self.state.prev_headers[0].number,
                   encode_hex(self.state.prev_headers[0].hash)))
        elif genesis is None:
            raise Exception("Need genesis decl!")
        elif isinstance(genesis, State):
            assert env is None
            self.state = genesis
            self.env = self.state.env
            print('Initializing chain from provided state')
            reset_genesis = True
        elif "extraData" in genesis:
            self.state = state_from_genesis_declaration(genesis,
                                                        self.env,
                                                        executing_on_head=True)
            reset_genesis = True
            print('Initializing chain from provided genesis declaration')
        elif "prev_headers" in genesis:
            self.state = State.from_snapshot(genesis,
                                             self.env,
                                             executing_on_head=True)
            reset_genesis = True
            print('Initializing chain from provided state snapshot, %d (%s)' %
                  (self.state.block_number,
                   encode_hex(self.state.prev_headers[0].hash[:8])))
        elif isinstance(genesis, dict):
            print('Initializing chain from new state based on alloc')
            self.state = mk_basic_state(
                genesis, {
                    "number":
                    kwargs.get('number', 0),
                    "gas_limit":
                    kwargs.get('gas_limit',
                               self.env.config['BLOCK_GAS_LIMIT']),
                    "gas_used":
                    kwargs.get('gas_used', 0),
                    "timestamp":
                    kwargs.get('timestamp', 1467446877),
                    "difficulty":
                    kwargs.get('difficulty', 2**25),
                    "hash":
                    kwargs.get('prevhash', '00' * 32),
                    "uncles_hash":
                    kwargs.get('uncles_hash',
                               '0x' + encode_hex(BLANK_UNCLES_HASH))
                }, self.env)
            reset_genesis = True

        assert self.env.db == self.state.db

        initialize(self.state)
        self.new_head_cb = new_head_cb

        if self.state.block_number == 0:
            assert self.state.block_number == self.state.prev_headers[0].number
        else:
            assert self.state.block_number - 1 == self.state.prev_headers[
                0].number

        if reset_genesis:
            if isinstance(self.state.prev_headers[0], FakeHeader):
                header = self.state.prev_headers[0].to_block_header()
            else:
                header = self.state.prev_headers[0]
            self.genesis = Block(header)
            self.state.prev_headers[0] = header
            initialize_genesis_keys(self.state, self.genesis)
        else:
            self.genesis = self.get_block_by_number(0)

        self.head_hash = self.state.prev_headers[0].hash
        self.time_queue = []
        self.parent_queue = {}
        self.localtime = time.time() if localtime is None else localtime
        self.max_history = max_history
def test_abi_signature_no_args():
    func = Function("doit", [])
    assert encode_hex(func.encoded_abi_signature) == b"4d536fe3"
Exemplo n.º 58
0
 def encode_node(nd):
     if is_string(nd):
         return encode_hex(nd)
     else:
         return encode_hex(rlp_encode(nd))
Exemplo n.º 59
0
def eth_coinbase():
    print 'eth_coinbase'
    return '0x' + encode_hex(evm.block.coinbase)
Exemplo n.º 60
0
 def __str__(self):
     if not isinstance(self.data, (str, unicode)):
         return repr(self.data)
     else:
         return encode_hex(self.data)