Example #1
0
def verify_state_test(test):
    print("Verifying state test")
    if "env" not in test:
        raise EnvNotFoundException("Env not found")
    _state = init_state(test["env"], test["pre"])
    for config_name, results in test["post"].items():
        # Old protocol versions may not be supported
        if config_name not in configs:
            continue
        print("Testing for %s" % config_name)
        for result in results:
            data = test["transaction"]['data'][result["indexes"]["data"]]
            if len(data) > 2000:
                data = "data<%d>" % (len(data) // 2 - 1)
            print("Checking for values: g %d v %d d %s (indexes g %d v %d d %d)" % (
                  parse_int_or_hex(test["transaction"]['gasLimit'][result["indexes"]["gas"]]),
                  parse_int_or_hex(test["transaction"]['value'][result["indexes"]["value"]]),
                  data,
                  result["indexes"]["gas"],
                  result["indexes"]["value"],
                  result["indexes"]["data"]))
            computed = compute_state_test_unit(_state, test["transaction"], result["indexes"], configs[config_name])
            if computed["hash"][-64:] != result["hash"][-64:]:
                for k in computed["diff"]:
                    print(k, computed["diff"][k])
                raise Exception("Hash mismatch, computed: %s, supplied: %s" % (computed["hash"], result["hash"]))
            else:
                # for k in computed["diff"]:
                #     print(k, computed["diff"][k])
                print("Hash matched!: %s" % computed["hash"])
    return True
Example #2
0
def compute_state_test_unit(state, txdata, indices, konfig):
    state.env.config = konfig
    s = state.snapshot()
    try:
        # Create the transaction
        tx = transactions.Transaction(
            nonce=parse_int_or_hex(txdata['nonce'] or b"0"),
            gasprice=parse_int_or_hex(txdata['gasPrice'] or b"0"),
            startgas=parse_int_or_hex(
                txdata['gasLimit'][indices["gas"]] or b"0"),
            to=decode_hex(remove_0x_head(txdata['to'])),
            value=parse_int_or_hex(txdata['value'][indices["value"]] or b"0"),
            data=decode_hex(remove_0x_head(txdata['data'][indices["data"]])))
        if 'secretKey' in txdata:
            tx.sign(decode_hex(remove_0x_head(txdata['secretKey'])))
        else:
            tx.v = parse_int_or_hex(txdata['v'])
        # Run it
        prev = state.to_dict()
        success, output = apply_transaction(state, tx)
        print("Applied tx")
    except InvalidTransaction as e:
        print("Exception: %r" % e)
        success, output = False, b''
    # state.set_code('0x3e180b1862f9d158abb5e519a6d8605540c23682', b'')
    state.commit()
    post = state.to_dict()
    # print('pozt', post)
    output_decl = {
        "hash": '0x' + encode_hex(state.trie.root_hash),
        "indexes": indices,
        "diff": mk_state_diff(prev, post)
    }
    state.revert(s)
    return output_decl
Example #3
0
def compute_state_test_unit(state, txdata, konfig):
    state.env.config = konfig
    s = state.snapshot()
    try:
        # Create the transaction
        tx = transactions.Transaction(
            nonce=parse_int_or_hex(txdata['nonce'] or b"0"),
            gasprice=parse_int_or_hex(txdata['gasPrice'] or b"0"),
            startgas=parse_int_or_hex(txdata['gasLimit'] or b"0"),
            to=decode_hex(remove_0x_head(txdata['to'])),
            value=parse_int_or_hex(txdata['value'] or b"0"),
            data=decode_hex(remove_0x_head(txdata['data'])))
        if 'secretKey' in txdata:
            tx.sign(decode_hex(remove_0x_head(txdata['secretKey'])))
        else:
            tx.v = parse_int_or_hex(txdata['v'])
        # Run it
        prev = state.to_dict()
        print("calling apply_transaction")
        success, output = apply_transaction(state, tx)
        print("Applied tx")
    except InvalidTransaction as e:
        print("Exception: %r" % e)
        success, output = False, b''
    state.commit()
    post = state.to_dict()
    output_decl = {
        "hash": '0x' + encode_hex(state.trie.root_hash),
        #"indexes": indices,
        #"diff": mk_state_diff(prev, post)
    }
    state.revert(s)
    return output_decl
Example #4
0
def acct_standard_form(a):
    return {
        "balance": parse_int_or_hex(a["balance"]),
        "nonce": parse_int_or_hex(a["nonce"]),
        "code": to_string(a["code"]),
        "storage": {normalize_hex(k): normalize_hex(v) for
                    k, v in a["storage"].items() if normalize_hex(v).rstrip(b'0') != b'0x'}
    }
Example #5
0
def acct_standard_form(a):
    return {
        "balance": parse_int_or_hex(a["balance"]),
        "nonce": parse_int_or_hex(a["nonce"]),
        "code": to_string(a["code"]),
        "storage": {normalize_hex(k): normalize_hex(v) for
                    k, v in a["storage"].items() if normalize_hex(v).rstrip(b'0') != b'0x'}
    }
Example #6
0
def getIntrinsicGas(test_tx):
    tx = transactions.Transaction(
        nonce=parse_int_or_hex(test_tx['nonce'] or b"0"),
        gasprice=parse_int_or_hex(test_tx['gasPrice'] or b"0"),
        startgas=parse_int_or_hex(test_tx['gasLimit'] or b"0"),
        to=decode_hex(remove_0x_head(test_tx['to'])),
        value=parse_int_or_hex(test_tx['value'] or b"0"),
        data=decode_hex(remove_0x_head(test_tx['data'])))

    return tx.intrinsic_gas_used
Example #7
0
def getTxSender(test_tx):
    tx = transactions.Transaction(
        nonce=parse_int_or_hex(test_tx['nonce'] or b"0"),
        gasprice=parse_int_or_hex(test_tx['gasPrice'] or b"0"),
        startgas=parse_int_or_hex(test_tx['gasLimit'] or b"0"),
        to=decode_hex(remove_0x_head(test_tx['to'])),
        value=parse_int_or_hex(test_tx['value'] or b"0"),
        data=decode_hex(remove_0x_head(test_tx['data'])))
    if 'secretKey' in test_tx:
        tx.sign(decode_hex(remove_0x_head(test_tx['secretKey'])))
    return encode_hex(tx.sender)
Example #8
0
def init_state(env, pre):
    # Setup env
    state = State(
        env=Env(config=konfig),
        block_prevhash=decode_hex(remove_0x_head(env['previousHash'])),
        prev_headers=[mk_fake_header(i) for i in range(parse_int_or_hex(env['currentNumber']) - 1,
                                                       max(-1, parse_int_or_hex(env['currentNumber']) - 257), -1)],
        block_number=parse_int_or_hex(env['currentNumber']),
        block_coinbase=decode_hex(remove_0x_head(env['currentCoinbase'])),
        block_difficulty=parse_int_or_hex(env['currentDifficulty']),
        gas_limit=parse_int_or_hex(env['currentGasLimit']),
        timestamp=parse_int_or_hex(env['currentTimestamp']))

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

    state.commit(allow_empties=True)
    # state.commit()
    return state
Example #9
0
def update_config_from_genesis_json(config, genesis_json_filename):
    with open(genesis_json_filename, "r") as genesis_json_file:
        genesis_dict = yaml.load(genesis_json_file)

    config.setdefault('eth', {}).setdefault('block', {})
    cfg = config['eth']['block']
    cfg['GENESIS_INITIAL_ALLOC'] = genesis_dict['alloc']
    cfg['GENESIS_DIFFICULTY'] = parse_int_or_hex(genesis_dict['difficulty'])
    cfg['GENESIS_TIMESTAMP'] = parse_int_or_hex(genesis_dict['timestamp'])
    cfg['GENESIS_EXTRA_DATA'] = decode_hex(remove_0x_head(genesis_dict['extraData']))
    cfg['GENESIS_GAS_LIMIT'] = parse_int_or_hex(genesis_dict['gasLimit'])
    cfg['GENESIS_MIXHASH'] = decode_hex(remove_0x_head(genesis_dict['mixhash']))
    cfg['GENESIS_PREVHASH'] = decode_hex(remove_0x_head(genesis_dict['parentHash']))
    cfg['GENESIS_COINBASE'] = decode_hex(remove_0x_head(genesis_dict['coinbase']))
    cfg['GENESIS_NONCE'] = decode_hex(remove_0x_head(genesis_dict['nonce']))

    return config
Example #10
0
 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
Example #11
0
 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
def update_config_from_genesis_json(config, genesis_json_filename):
    with open(genesis_json_filename, "r") as genesis_json_file:
        genesis_dict = yaml.load(genesis_json_file)

    config.setdefault('eth', {}).setdefault('block', {})
    cfg = config['eth']['block']
    cfg['GENESIS_INITIAL_ALLOC'] = genesis_dict['alloc']
    cfg['GENESIS_DIFFICULTY'] = parse_int_or_hex(genesis_dict['difficulty'])
    cfg['GENESIS_TIMESTAMP'] = parse_int_or_hex(genesis_dict['timestamp'])
    cfg['GENESIS_EXTRA_DATA'] = decode_hex(
        remove_0x_head(genesis_dict['extraData']))
    cfg['GENESIS_GAS_LIMIT'] = parse_int_or_hex(genesis_dict['gasLimit'])
    cfg['GENESIS_MIXHASH'] = decode_hex(remove_0x_head(
        genesis_dict['mixhash']))
    cfg['GENESIS_PREVHASH'] = decode_hex(
        remove_0x_head(genesis_dict['parentHash']))
    cfg['GENESIS_COINBASE'] = decode_hex(
        remove_0x_head(genesis_dict['coinbase']))
    cfg['GENESIS_NONCE'] = decode_hex(remove_0x_head(genesis_dict['nonce']))

    return config
Example #13
0
def deploy_contract_and_accounts(state,
                                 n_devs,
                                 start=1,
                                 end=2,
                                 deploy_contract=True):
    dev_keys = []
    dev_accounts = []

    milestone = int(math.log10(n_devs))
    notify_step = milestone - 2
    notify_value = 10**notify_step if notify_step > 0 else 1

    # create developer accounts and keys in fashion of testers
    for account_number in range(n_devs):
        if account_number % notify_value == 0:
            print "Account", account_number + 1, "out of", n_devs

        dev_keys.append(sha3('dev' + to_string(account_number)))
        dev_accounts.append(privtoaddr(dev_keys[-1]))

    # developer balances
    block = state.block

    for i in range(n_devs):
        if i % notify_value == 0:
            print "Balance", i + 1, "out of", n_devs

        addr, data = dev_accounts[i], {'wei': 10**24}
        if len(addr) == 40:
            addr = decode_hex(addr)
        assert len(addr) == 20
        block.set_balance(addr, parse_int_or_hex(data['wei']))

    block.commit_state()
    block.state.db.commit()

    dev_addresses = [ContractHelper.dev_address(a) for a in dev_accounts]

    # deploy the gnt contract with updated developer accounts
    if deploy_contract:
        contract, _, _ = deploy_gnt(state,
                                    tester.accounts[9],
                                    start,
                                    end,
                                    replacements=[(dev_addresses,
                                                   DEV_ADDR_REGEX)])
        alloc_addr = mk_contract_address(contract.address, 0)
        allocation = tester.ABIContract(state, ALLOC_ABI, alloc_addr)
    else:
        contract, allocation = None, None

    return contract, allocation, dev_keys, dev_accounts
Example #14
0
def run_block_test(params):
    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))
    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))
Example #15
0
def mktest(code,
           language,
           data=None,
           fun=None,
           args=None,
           gas=1000000,
           value=0,
           test_type=VM):
    s = t.state(1)
    if language == 'evm':
        ca = s.contract('x = 5')
        s.block.set_code(ca, code)
        d = data or b''
    else:
        c = s.abi_contract(code, language=language)
        d = c._translator.encode(fun, args) if fun else (data or b'')
        ca = c.address
    pre = s.block.to_dict(True)['state']
    if test_type == VM:
        exek = {
            "address": ca,
            "caller": t.a0,
            "code": b'0x' + encode_hex(s.block.get_code(ca)),
            "data": b'0x' + encode_hex(d),
            "gas": to_string(gas),
            "gasPrice": to_string(1),
            "origin": t.a0,
            "value": to_string(value)
        }
        return fill_vm_test({"env": env, "pre": pre, "exec": exek})
    else:
        tx = {
            "data": b'0x' + encode_hex(d),
            "gasLimit": parse_int_or_hex(gas),
            "gasPrice": to_string(1),
            "nonce": to_string(s.block.get_nonce(t.a0)),
            "secretKey": encode_hex(t.k0),
            "to": ca,
            "value": to_string(value)
        }
        return fill_state_test({"env": env, "pre": pre, "transaction": tx})
Example #16
0
def run_genesis_test(params, mode):
    params = copy.deepcopy(params)
    if 'difficulty' not in params:
        params['difficulty'] = int_to_hex(2**34)
    if 'mixhash' not in params:
        params['mixhash'] = '0x' + '0' * 64
    if 'nonce' not in params:
        params['nonce'] = '0x0000000000000042'
    if 'timestamp' not in params:
        params['timestamp'] = int_to_hex(5000)
    if 'parentHash' not in params:
        params['parentHash'] = '0x' + '0' * 64
    if 'gasLimit' not in params:
        params['gasLimit'] = int_to_hex(5000)
    if 'extraData' not in params:
        params['extraData'] = '0x'
    if 'coinbase' not in params:
        params['coinbase'] = '0x' + '3' * 40
    x = time.time()
    b = blocks.genesis(
        EphemDB(),
        start_alloc=params['alloc'],
        difficulty=parse_int_or_hex(params['difficulty']),
        timestamp=parse_int_or_hex(params['timestamp']),
        extra_data=decode_hex(remove_0x_head(params['extraData'])),
        gas_limit=parse_int_or_hex(params['gasLimit']),
        mixhash=decode_hex(remove_0x_head(params['mixhash'])),
        prevhash=decode_hex(remove_0x_head(params['parentHash'])),
        coinbase=decode_hex(remove_0x_head(params['coinbase'])),
        nonce=decode_hex(remove_0x_head(params['nonce'])))
    assert b.difficulty == parse_int_or_hex(params['difficulty'])
    assert b.timestamp == parse_int_or_hex(params['timestamp'])
    assert b.extra_data == decode_hex(remove_0x_head(params['extraData']))
    assert b.gas_limit == parse_int_or_hex(params['gasLimit'])
    assert b.mixhash == decode_hex(remove_0x_head(params['mixhash']))
    assert b.prevhash == decode_hex(remove_0x_head(params['parentHash']))
    assert b.nonce == decode_hex(remove_0x_head(params['nonce']))
    print 9
    if mode == FILL:
        params['result'] = encode_hex(rlp.encode(b))
        return params
    elif mode == VERIFY:
        assert params['result'] == encode_hex(rlp.encode(b))
    elif mode == TIME:
        return {'creation': time.time() - x}
Example #17
0
def run_genesis_test(params, mode):
    params = copy.deepcopy(params)
    if 'difficulty' not in params:
        params['difficulty'] = int_to_hex(2 ** 34)
    if 'mixhash' not in params:
        params['mixhash'] = '0x' + '0' * 64
    if 'nonce' not in params:
        params['nonce'] = '0x0000000000000042'
    if 'timestamp' not in params:
        params['timestamp'] = int_to_hex(5000)
    if 'parentHash' not in params:
        params['parentHash'] = '0x' + '0' * 64
    if 'gasLimit' not in params:
        params['gasLimit'] = int_to_hex(5000)
    if 'extraData' not in params:
        params['extraData'] = '0x'
    if 'coinbase' not in params:
        params['coinbase'] = '0x' + '3' * 40
    x = time.time()
    b = blocks.genesis(EphemDB(), start_alloc=params['alloc'],
                       difficulty=parse_int_or_hex(params['difficulty']),
                       timestamp=parse_int_or_hex(params['timestamp']),
                       extra_data=decode_hex(remove_0x_head(params['extraData'])),
                       gas_limit=parse_int_or_hex(params['gasLimit']),
                       mixhash=decode_hex(remove_0x_head(params['mixhash'])),
                       prevhash=decode_hex(remove_0x_head(params['parentHash'])),
                       coinbase=decode_hex(remove_0x_head(params['coinbase'])),
                       nonce=decode_hex(remove_0x_head(params['nonce'])))
    assert b.difficulty == parse_int_or_hex(params['difficulty'])
    assert b.timestamp == parse_int_or_hex(params['timestamp'])
    assert b.extra_data == decode_hex(remove_0x_head(params['extraData']))
    assert b.gas_limit == parse_int_or_hex(params['gasLimit'])
    assert b.mixhash == decode_hex(remove_0x_head(params['mixhash']))
    assert b.prevhash == decode_hex(remove_0x_head(params['parentHash']))
    assert b.nonce == decode_hex(remove_0x_head(params['nonce']))
    print(9)
    if mode == FILL:
        params['result'] = encode_hex(rlp.encode(b))
        return params
    elif mode == VERIFY:
        assert params['result'] == encode_hex(rlp.encode(b))
    elif mode == TIME:
        return {
            'creation': time.time() - x
        }
Example #18
0
def mktest(code, language, data=None, fun=None, args=None,
           gas=1000000, value=0, test_type=VM):
    s = t.state(1)
    if language == 'evm':
        ca = s.contract('x = 5')
        s.block.set_code(ca, code)
        d = data or b''
    else:
        c = s.abi_contract(code, language=language)
        d = c._translator.encode(fun, args) if fun else (data or b'')
        ca = c.address
    pre = s.block.to_dict(True)['state']
    if test_type == VM:
        exek = {"address": ca, "caller": t.a0,
                "code": b'0x' + encode_hex(s.block.get_code(ca)),
                "data": b'0x' + encode_hex(d), "gas": to_string(gas),
                "gasPrice": to_string(1), "origin": t.a0,
                "value": to_string(value)}
        return fill_vm_test({"env": env, "pre": pre, "exec": exek})
    else:
        tx = {"data": b'0x' + encode_hex(d), "gasLimit": parse_int_or_hex(gas),
              "gasPrice": to_string(1), "nonce": to_string(s.block.get_nonce(t.a0)),
              "secretKey": encode_hex(t.k0), "to": ca, "value": to_string(value)}
        return fill_state_test({"env": env, "pre": pre, "transaction": tx})
Example #19
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']),
        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()):
        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=decode_hex(exek['to'][2:] if exek['to'][:2] ==
                          b'0x' else exek['to']),
            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:
            success, output = pb.apply_transaction(blk, tx)
            blk.commit_state()
        except pb.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)
    assert 'post' in params  # we always have a post state in the tests

    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 shouldbe != reallyis:
                raise Exception("Mismatch: " + k +
                                ':\n shouldbe %r\n reallyis %r' %
                                (shouldbe, reallyis))

    elif mode == TIME:
        return time_post - time_pre
Example #20
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()):
        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
Example #21
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()):
        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
Example #22
0
def toHexQuantities(vals):
    quantities = []
    for val in vals:
        val_int = parse_int_or_hex(val)
        quantities.append('0x{0:01x}'.format(val_int))
    return quantities
Example #23
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(2 ** 63 - 1, 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 _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
Example #24
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)
    try:
        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"]]
    finally:
        env.config = old_config
Example #25
0
def callcreate_standard_form(c):
    return {
        "gasLimit": parse_int_or_hex(c["gasLimit"]),
        "value": parse_int_or_hex(c["value"]),
        "data": to_string(c["data"])
    }
Example #26
0
def update_config_from_genesis_json(config, genesis_json_filename_or_dict):
    """ Sets the genesis configuration.

    Note: This function will not copy config, it will be modified in place and
        then returned.

    Args:
        config (dict): The app full configuration.
        genesis_json_filename_or_dict: The path to a yaml file or a dictionary
        with the genesis configuration, the required keys are:

            - alloc: a mapping from address to balance
            - difficulty: the difficulty hex encoded
            - timestamp: the timestamp hex encoded
            - extraData: extra binary data hex encoded
            - gasLimit: gas limit hex encoded
            - mixhash: mixhash hex encoded
            - parentHash: the parent hash hex encoded
            - coinbase: coinbase hex encoded
            - nonce: nonce hex encoded

    Returns:
        dict: The first function argument.
    """
    if isinstance(genesis_json_filename_or_dict, dict):
        genesis_dict = genesis_json_filename_or_dict
    else:
        with open(genesis_json_filename_or_dict, 'r') as genesis_json_file:
            genesis_dict = yaml.load(genesis_json_file)

    valid_keys = set((
        'alloc',
        'difficulty',
        'timestamp',
        'extraData',
        'gasLimit',
        'mixhash',
        'parentHash',
        'coinbase',
        'nonce',
    ))

    unknown_keys = set(genesis_dict.keys()) - valid_keys
    if unknown_keys:
        raise ValueError('genesis_dict contains invalid keys.')

    config.setdefault('eth', {}).setdefault('block', {})
    ethblock_config = config['eth']['block']

    def _dec(data):
        return decode_hex(remove_0x_head(data))

    if 'alloc' in genesis_dict:
        ethblock_config['GENESIS_INITIAL_ALLOC'] = genesis_dict['alloc']

    if 'difficulty' in genesis_dict:
        ethblock_config['GENESIS_DIFFICULTY'] = parse_int_or_hex(
            genesis_dict['difficulty'])

    if 'timestamp' in genesis_dict:
        ethblock_config['GENESIS_TIMESTAMP'] = parse_int_or_hex(
            genesis_dict['timestamp'])

    if 'extraData' in genesis_dict:
        ethblock_config['GENESIS_EXTRA_DATA'] = _dec(genesis_dict['extraData'])

    if 'gasLimit' in genesis_dict:
        ethblock_config['GENESIS_GAS_LIMIT'] = parse_int_or_hex(
            genesis_dict['gasLimit'])

    if 'mixhash' in genesis_dict:
        ethblock_config['GENESIS_MIXHASH'] = _dec(genesis_dict['mixhash'])

    if 'parentHash' in genesis_dict:
        ethblock_config['GENESIS_PREVHASH'] = _dec(genesis_dict['parentHash'])

    if 'coinbase' in genesis_dict:
        ethblock_config['GENESIS_COINBASE'] = _dec(genesis_dict['coinbase'])

    if 'nonce' in genesis_dict:
        ethblock_config['GENESIS_NONCE'] = _dec(genesis_dict['nonce'])

    return config
Example #27
0
def callcreate_standard_form(c):
    return {
        "gasLimit": parse_int_or_hex(c["gasLimit"]),
        "value": parse_int_or_hex(c["value"]),
        "data": to_string(c["data"])
    }
Example #28
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
def startGeth(test_case, test_tx):
    logger.info("running state test in geth.")
    genesis = gen.Genesis()
    for account_key in test_case['pre']:
        account = test_case['pre'][account_key]
        account['address'] = account_key
        genesis.addPrestateAccount(account)
    genesis.setCoinbase(test_case['env']['currentCoinbase'])
    genesis.setTimestamp(test_case['env']['currentTimestamp'])
    genesis.setGasLimit(test_case['env']['currentGasLimit'])
    genesis.setDifficulty(test_case['env']['currentDifficulty'])
    genesis.setBlockNumber(test_case['env']['currentNumber'])

    if cfg['FORK_CONFIG'] == 'Metropolis' or cfg['FORK_CONFIG'] == 'Byzantium':
        genesis.setConfigMetropolis()
    if cfg['FORK_CONFIG'] == 'Homestead':
        genesis.setConfigHomestead()

    geth_genesis = genesis.geth()
    g_path = genesis.export_geth()
    if sys.platform == "darwin":
        # OS X workaround for https://github.com/docker/for-mac/issues/1298 "The path /var/folders/wb/d8qys65575g8m2691vvglpmm0000gn/T/tmpctxz3buh.json is not shared from OS X and is not known to Docker."
        g_path = "/private" + g_path

    input_data = test_tx['data']
    if input_data[0:2] == "0x":
        input_data = input_data[2:]

    tx_to = test_tx['to']
    tx_value = parse_int_or_hex(test_tx['value'])
    gas_limit = parse_int_or_hex(test_tx['gasLimit'])
    gas_price = parse_int_or_hex(test_tx['gasPrice'])
    block_gaslimit = parse_int_or_hex(test_case['env']['currentGasLimit'])

    if gas_limit > block_gaslimit:
        logger.info("Tx gas limit exceeds block gas limit. not calling geth")
        return []

    sender = '0x' + getTxSender(test_tx)
    sender_balance = parse_int_or_hex(test_case['pre'][sender]['balance'])
    balance_required = (gas_price * gas_limit) + tx_value

    if balance_required > sender_balance:
        logger.info("Insufficient balance. not calling geth")
        return []

    intrinsic_gas = getIntrinsicGas(test_tx)
    if tx_to == "":
        # create contract cost not included in getIntrinsicGas
        intrinsic_gas += 32000

    if gas_limit < intrinsic_gas:
        logger.info("Insufficient startgas. not calling geth")
        return []

    if tx_to == "" and input_data == "":
        logger.info("no init code. not calling geth")
        return []

    if tx_to in test_case['pre']:
        if 'code' in test_case['pre'][tx_to]:
            if test_case['pre'][tx_to]['code'] == '':
                logger.info(
                    "To account in prestate has no code. not calling geth")
                return []

    vm = VMUtils.GethVM(executable=cfg['GETH_DOCKER_NAME'], docker=True)

    return vm.start(genesis=g_path,
                    gas=gas_limit,
                    price=gas_price,
                    json=True,
                    sender=sender,
                    receiver=tx_to,
                    input=input_data,
                    value=tx_value)
Example #30
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