예제 #1
0
def test_difficulty(filename, testname, testdata):
    testdata = fixture_to_bytes(testdata)

    parent_timestamp = int(testdata["parentTimestamp"],
                           10 if testdata["parentTimestamp"].isdigit() else 16)
    parent_difficulty = int(
        testdata["parentDifficulty"],
        10 if testdata["parentDifficulty"].isdigit() else 16)
    parent_blk_number = int(
        testdata["currentBlockNumber"],
        10 if testdata["currentBlockNumber"].isdigit() else 16) - 1
    cur_blk_timestamp = int(
        testdata["currentTimestamp"],
        10 if testdata["currentTimestamp"].isdigit() else 16)
    reference_dif = int(testdata["currentDifficulty"],
                        10 if testdata["currentDifficulty"].isdigit() else 16)

    env = tester.state().env
    if 'Homestead' in filename:
        env.config['HOMESTEAD_FORK_BLKNUM'] = 0
    if 'difficultyMorden' in filename:
        env.config['HOMESTEAD_FORK_BLKNUM'] = 494000

    parent_bh = blocks.BlockHeader(timestamp=parent_timestamp,
                                   difficulty=parent_difficulty,
                                   number=parent_blk_number)
    block = blocks.Block(parent_bh, [], env=env, making=True)

    calculated_dif = blocks.calc_difficulty(block, cur_blk_timestamp)

    print(calculated_dif)
    print(reference_dif)
    assert calculated_dif == reference_dif
예제 #2
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
예제 #3
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
예제 #4
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