Esempio n. 1
0
    def test_reveal_returns_entropy(self):
        assert self.c.commit(1, self.COW_HASH, value=self.DEPOSIT_COST) == [1]
        assert self.c.request_entropy(sender=tester.k1,
                                      value=self.ENTROPY_COST) == [0, 4]
        assert self.c.get_block(self.s.block.number + 1) == [0, 1, 0, 1]

        self.s.mine(2)

        COW_SEED = utils.big_endian_to_int(
            utils.sha3(
                utils.sha3(utils.zpad('cow', 32)) + utils.zpad('cow', 32)))
        COW_HASH_1 = utils.big_endian_to_int(
            utils.sha3(utils.int_to_big_endian(COW_SEED)))

        balance = self.s.block.get_balance(tester.a0)
        assert self.c.reveal(1, self.COW_INT) == [1]
        assert self.s.block.get_balance(
            tester.a0
        ) - balance == self.DEPOSIT_COST + self.ENTROPY_COST  # deposit return + payout of committer share

        assert self.c.get_block(1) == [COW_SEED, 1, 1, 1]

        # signed vs unsigned as introduced by tester.send
        assert self.c.get_entropy_ticket(0) == [
            int(tester.a1, 16), 1, 1, COW_HASH_1 - 2**256
        ]
        assert self.c.get_entropy(
            0, sender=tester.k1) == [1, COW_HASH_1 - 2**256]  # ready
Esempio n. 2
0
def weight(a, b):
    # calc distance
    max_distance = 2 ** 32
    # distance = big_endian_to_int(sha3(a.decode('hex'))) ^ big_endian_to_int(sha3(b.decode('hex')))
    distance = big_endian_to_int(a.decode('hex')) ^ big_endian_to_int(b.decode('hex'))
    # same node is weight == 1
    return 1 - distance / max_distance
def weight(a, b):
    # calc distance
    max_distance = 2**32
    #distance = big_endian_to_int(sha3(a.decode('hex'))) ^ big_endian_to_int(sha3(b.decode('hex')))
    distance = big_endian_to_int(a.decode('hex')) ^ big_endian_to_int(
        b.decode('hex'))
    # same node is weight == 1
    return 1 - distance / max_distance
Esempio n. 4
0
def test_prevhashes():
    s = tester.state()
    c = s.abi_contract(prevhashes_code)
    s.mine(7)
    # Hashes of last 14 blocks including existing one
    o1 = [x % 2**256 for x in c.get_prevhashes(14)]
    # hash of self = 0, hash of blocks back to genesis block as is, hash of
    # blocks before genesis block = 0
    t1 = [0] + [utils.big_endian_to_int(b.hash) for b in s.blocks[-2::-1]] \
        + [0] * 6
    assert o1 == t1
    s.mine(256)
    # Test 256 limit: only 1 <= g <= 256 generation ancestors get hashes shown
    o2 = [x % 2**256 for x in c.get_prevhashes(270)]
    t2 = [0] + [utils.big_endian_to_int(b.hash) for b in s.blocks[-2:-258:-1]] \
        + [0] * 13
    assert o2 == t2
Esempio n. 5
0
def run_test_vm(params):
    print params
    pre = params['pre']
    exek = params['exec']
    callcreates = params.get('callcreates', [])
    env = params['env']
    post = params.get('post', {})

    check_testdata(env.keys(), ['currentGasLimit', 'currentTimestamp',
                                'previousHash', 'currentCoinbase',
                                'currentDifficulty', 'currentNumber'])
    # setup env
    blk = blocks.Block(db,
                       prevhash=env['previousHash'].decode('hex'),
                       number=int(env['currentNumber']),
                       coinbase=env['currentCoinbase'],
                       difficulty=int(env['currentDifficulty']),
                       gas_limit=int(env['currentGasLimit']),
                       timestamp=int(env['currentTimestamp']))

    # code FIXME WHAT TO DO WITH THIS CODE???
    # if isinstance(env['code'], str):
    #     continue
    # else:
    # addr = 0 # FIXME
    #     blk.set_code(addr, ''.join(map(chr, env['code'])))

    # setup state
    for address, h in pre.items():
        check_testdata(h.keys(), ['code', 'nonce', 'balance', 'storage'])
        blk.set_nonce(address, int(h['nonce']))
        blk.set_balance(address, int(h['balance']))
        blk.set_code(address, h['code'][2:].decode('hex'))
        for k, v in h['storage'].iteritems():
            blk.set_storage_data(address,
                                 u.big_endian_to_int(k[2:].decode('hex')),
                                 u.big_endian_to_int(v[2:].decode('hex')))

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

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

    ext = pb.VMExt(blk, tx)

    def call_wrapper(msg):
        ext.set_balance(msg.sender, ext.get_balance(msg.sender) - msg.value)
        hexdata = msg.data.extract_all().encode('hex')
        apply_message_calls.append(dict(gasLimit=msg.gas, value=msg.value,
                                        destination=msg.to, data=hexdata))
        return 1, msg.gas, ''

    def sendmsg_wrapper(msg, code):
        ext.set_balance(msg.sender, ext.get_balance(msg.sender) - msg.value)
        hexdata = msg.data.extract_all().encode('hex')
        apply_message_calls.append(dict(gasLimit=msg.gas, value=msg.value,
                                        destination=msg.to, data=hexdata))
        return 1, msg.gas, ''

    def create_wrapper(msg):
        ext.set_balance(msg.sender, ext.get_balance(msg.sender) - msg.value)
        sender = msg.sender.decode('hex') if len(msg.sender) == 40 else msg.sender
        nonce = u.encode_int(ext._block.get_nonce(msg.sender))
        addr = u.sha3(rlp.encode([sender, nonce]))[12:].encode('hex')
        hexdata = msg.data.extract_all().encode('hex')
        apply_message_calls.append(dict(gasLimit=msg.gas, value=msg.value,
                                        destination='', data=hexdata))
        return 1, msg.gas, addr

    ext.sendmsg = sendmsg_wrapper
    ext.call = call_wrapper
    ext.create = create_wrapper

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

    ext.block_hash = blkhash

    msg = vm.Message(tx.sender, tx.to, tx.value, tx.startgas,
                     vm.CallData([ord(x) for x in tx.data]))
    success, gas_remained, output = \
        vm.vm_execute(ext, msg, exek['code'][2:].decode('hex'))
    pb.apply_msg = orig_apply_msg
    blk.commit_state()

    """
     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.
     """

    if not success:
        assert 'gas' not in params
        assert 'post' not in params
        return

    for k in ['gas', 'logs', 'out', 'post', 'callcreates']:
        assert k in params
    assert len(callcreates) == len(apply_message_calls)

    # check against callcreates
    for i, callcreate in enumerate(callcreates):
        amc = apply_message_calls[i]
        assert callcreate['data'] == '0x' + amc['data']
        assert callcreate['gasLimit'] == str(amc['gasLimit'])
        assert callcreate['value'] == str(amc['value'])
        assert callcreate['destination'] == amc['destination']

    if 'out' in params:
        assert '0x' + ''.join(map(chr, output)).encode('hex') == params['out']
    if 'gas' in params:
        assert str(gas_remained) == params['gas']
    if 'logs' in params:
        """
        The logs sections is a mapping between the blooms and their corresponding logentries.
        Each logentry has the format:
        address: The address of the logentry.
        data: The data of the logentry.
        topics: The topics of the logentry, given as an array of values.
        """
        test_logs = params['logs']
        vm_logs = []
        for log in tx.logs:
            vm_logs.append({
                "bloom": bloom.b64(bloom.bloom_from_list(log.bloomables())).encode('hex'),
                "address": log.address,
                "data": '0x' + log.data.encode('hex'),
                "topics": [u.zpad(u.int_to_big_endian(t), 32).encode('hex') for t in log.topics]
            })

        assert len(vm_logs) == len(test_logs)
        assert vm_logs == test_logs

    # check state
    for address, data in post.items():
        state = blk.account_to_dict(address, for_vmtest=True)
        state.pop('storage_root', None)  # attribute not present in vmtest fixtures
        assert data == state
Esempio n. 6
0
def run_test_vm(params):
    pre = params['pre']
    exek = params['exec']
    callcreates = params.get('callcreates', [])
    env = params['env']
    post = params.get('post', {})

    check_testdata(env.keys(), [
        'currentGasLimit', 'currentTimestamp', 'previousHash',
        'currentCoinbase', 'currentDifficulty', 'currentNumber'
    ])
    # setup env
    db = new_db()
    blk = blocks.Block(db,
                       prevhash=env['previousHash'].decode('hex'),
                       number=int(env['currentNumber']),
                       coinbase=env['currentCoinbase'],
                       difficulty=int(env['currentDifficulty']),
                       gas_limit=int(env['currentGasLimit']),
                       timestamp=int(env['currentTimestamp']))

    # code FIXME WHAT TO DO WITH THIS CODE???
    # if isinstance(env['code'], str):
    #     continue
    # else:
    # addr = 0 # FIXME
    #     blk.set_code(addr, ''.join(map(chr, env['code'])))

    # setup state
    for address, h in pre.items():
        check_testdata(h.keys(), ['code', 'nonce', 'balance', 'storage'])
        blk.set_nonce(address, int(h['nonce']))
        blk.set_balance(address, int(h['balance']))
        blk.set_code(address, h['code'][2:].decode('hex'))
        for k, v in h['storage']:
            blk.set_storage_data(address, u.big_endian_to_int(k.decode('hex')),
                                 u.big_endian_to_int(v.decode('hex')))

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

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

    def apply_msg_wrapper(_ext, msg, code, toplevel=False):
        hexdata = msg.data.extract_all().encode('hex')
        apply_message_calls.append(
            dict(gasLimit=msg.gas,
                 value=msg.value,
                 destination=msg.to,
                 data=hexdata))
        if not toplevel:
            pb.apply_msg = orig_apply_msg
        result, gas_rem, data = orig_apply_msg(_ext, msg, code)
        if not toplevel:
            pb.apply_msg = apply_msg_wrapper
        return result, gas_rem, data

    pb.apply_msg = apply_msg_wrapper

    ext = pb.VMExt(blk, tx)
    msg = vm.Message(tx.sender, tx.to, tx.value, tx.startgas,
                     vm.CallData([ord(x) for x in tx.data]))
    success, gas_remained, output = \
        vm.vm_execute(ext, msg, exek['code'][2:].decode('hex'))
    pb.apply_msg = orig_apply_msg
    blk.commit_state()
    """
     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.
     """

    if not success:
        return

    for k in ['gas', 'logs', 'out', 'post', 'callcreates']:
        assert k in params
    assert len(callcreates) == len(apply_message_calls)

    # check against callcreates
    for i, callcreate in enumerate(callcreates):
        amc = apply_message_calls[i]
        assert callcreate['data'] == '0x' + amc['data']
        assert callcreate['gasLimit'] == str(amc['gasLimit'])
        assert callcreate['value'] == str(amc['value'])
        assert callcreate['destination'] == amc['destination']

    if 'out' in params:
        assert '0x' + ''.join(map(chr, output)).encode('hex') == params['out']
    if 'gas' in params:
        assert str(gas_remained) == params['gas']
    if 'logs' in params:
        """
        The logs sections is a mapping between the blooms and their corresponding logentries.
        Each logentry has the format:
        address: The address of the logentry.
        data: The data of the logentry.
        topics: The topics of the logentry, given as an array of values.
        """
        test_logs = params['logs']
        vm_logs = []
        for log in tx.logs:
            vm_logs.append({
                "bloom":
                bloom.b64(bloom.bloom_from_list(
                    log.bloomables())).encode('hex'),
                "address":
                log.address,
                "data":
                '0x' + log.data.encode('hex'),
                "topics": [
                    u.zpad(u.int_to_big_endian(t), 32).encode('hex')
                    for t in log.topics
                ]
            })

        assert len(vm_logs) == len(test_logs)
        assert vm_logs == test_logs

    # check state
    for address, data in post.items():
        state = blk.account_to_dict(address, for_vmtest=True)
        state.pop('storage_root',
                  None)  # attribute not present in vmtest fixtures
        assert data == state

    db.delete_db()
Esempio n. 7
0
 def get_proposal_id(self, proposal):
     return big_endian_to_int(sha3(zpad(proposal, 32)))
Esempio n. 8
0
def do_test_vm(name):
    logger.debug('running test:%r', name)
    for testname in vm_tests_fixtures(name).keys():

        logger.debug('running test:%r', testname)

        params = vm_tests_fixtures(name)[testname]

        pre = params['pre']
        exek = params['exec']
        callcreates = params['callcreates']
        env = params['env']
        post = params['post']

        check_testdata(env.keys(), [
            'currentGasLimit', 'currentTimestamp', 'previousHash',
            'currentCoinbase', 'currentDifficulty', 'currentNumber'
        ])
        # setup env
        blk = blocks.Block(prevhash=env['previousHash'].decode('hex'),
                           number=int(env['currentNumber']),
                           coinbase=env['currentCoinbase'],
                           difficulty=int(env['currentDifficulty']),
                           gas_limit=int(env['currentGasLimit']),
                           timestamp=int(env['currentTimestamp']))

        # code FIXME WHAT TO DO WITH THIS CODE???
        # if isinstance(env['code'], str):
        #     continue
        # else:
        #     addr = 0 # FIXME
        #     blk.set_code(addr, ''.join(map(chr, env['code'])))

        # setup state
        for address, h in pre.items():
            check_testdata(h.keys(), ['code', 'nonce', 'balance', 'storage'])
            blk.set_nonce(address, int(h['nonce']))
            blk.set_balance(address, int(h['balance']))
            blk.set_code(address, h['code'][2:].decode('hex'))
            for k, v in h['storage']:
                blk.set_storage_data(address,
                                     u.big_endian_to_int(k.decode('hex')),
                                     u.big_endian_to_int(v.decode('hex')))
            pblogger.log('PRE Balance', address=address, balance=h['balance'])

        # execute transactions
        sender = exek['caller']  # a party that originates a call
        recvaddr = exek['address']
        tx = transactions.Transaction(nonce=blk._get_acct_item(
            exek['caller'], 'nonce'),
                                      gasprice=int(exek['gasPrice']),
                                      startgas=int(exek['gas']),
                                      to=recvaddr,
                                      value=int(exek['value']),
                                      data=exek['data'][2:].decode('hex'))
        tx.sender = sender
        pblogger.log('TX',
                     tx=tx.hex_hash(),
                     sender=sender,
                     to=recvaddr,
                     value=tx.value,
                     startgas=tx.startgas,
                     gasprice=tx.gasprice)

        # capture apply_message calls
        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,
                     destination=msg.to,
                     data=msg.data.encode('hex')))
            result, gas_rem, data = orig_apply_msg(_block, _tx, msg, code)
            return result, gas_rem, data

        pb.apply_msg = apply_msg_wrapper

        msg = pb.Message(tx.sender, tx.to, tx.value, tx.startgas, tx.data)
        blk.delta_balance(exek['caller'], tx.value)
        blk.delta_balance(exek['address'], -tx.value)
        try:
            success, gas_remained, output = \
                pb.apply_msg(blk, tx, msg, exek['code'][2:].decode('hex'))
        except MemoryError:
            print "A memory error exception has been thrown and catched!\n"

        pb.apply_msg = orig_apply_msg
        apply_message_calls.pop(0)
        blk.commit_state()

        assert success
        assert len(callcreates) == len(apply_message_calls)

        # check against callcreates
        for i, callcreate in enumerate(callcreates):
            amc = apply_message_calls[i]
            assert callcreate['data'] == '0x' + amc['data'].encode('hex')
            assert callcreate['gasLimit'] == str(amc['gasLimit'])
            assert callcreate['value'] == str(amc['value'])
            assert callcreate['destination'] == amc['destination']

        assert '0x' + ''.join(map(chr, output)).encode('hex') == params['out']
        if gas_remained < 0: gas_remained = 0
        assert str(gas_remained) == params['gas']

        # check state

        for address, data in post.items():
            state = blk.account_to_dict(address)
            state.pop('storage_root',
                      None)  # attribute not present in vmtest fixtures

            # check hex values in same format

            def newFormat(x):
                if x == '0x':
                    return '0x00'
                elif x[:2] == '0x':
                    return "0x%0.2X" % int(x, 0)
                else:
                    return x

            data['storage'] = {
                newFormat(k): newFormat(v[0])
                for k, v in data['storage'].items()
                if int(newFormat(v[0]), 0) != 0
            }
            state['storage'] = {
                newFormat(k): newFormat(v)
                for k, v in state['storage'].items()
            }

            assert data == state
Esempio n. 9
0
def do_test_vm(filename, testname=None, limit=99999999):
    if testname is None:
        for testname in vm_tests_fixtures()[filename].keys()[:limit]:
            do_test_vm(filename, testname)
        return
    if testname in faulty:
        logger.debug('skipping test:%r in %r' % (testname, filename))
        return
    logger.debug('running test:%r in %r' % (testname, filename))
    params = vm_tests_fixtures()[filename][testname]

    pre = params['pre']
    exek = params['transaction']
    env = params['env']
    post = params['post']

    check_testdata(env.keys(), ['currentGasLimit', 'currentTimestamp',
                                'previousHash', 'currentCoinbase',
                                'currentDifficulty', 'currentNumber'])
    # setup env
    blk = blocks.Block(new_db(),
                       prevhash=env['previousHash'].decode('hex'),
                       number=int(env['currentNumber']),
                       coinbase=env['currentCoinbase'],
                       difficulty=int(env['currentDifficulty']),
                       gas_limit=int(env['currentGasLimit']),
                       timestamp=int(env['currentTimestamp']))

    # code FIXME WHAT TO DO WITH THIS CODE???
    # if isinstance(env['code'], str):
    #     continue
    # else:
    # addr = 0 # FIXME
    #     blk.set_code(addr, ''.join(map(chr, env['code'])))

    # setup state
    for address, h in pre.items():
        check_testdata(h.keys(), ['code', 'nonce', 'balance', 'storage'])
        blk.set_nonce(address, int(h['nonce']))
        blk.set_balance(address, int(h['balance']))
        blk.set_code(address, h['code'][2:].decode('hex'))
        for k, v in h['storage'].iteritems():
            blk.set_storage_data(address,
                                 u.big_endian_to_int(k[2:].decode('hex')),
                                 u.big_endian_to_int(v[2:].decode('hex')))

    # execute transactions
    tx = transactions.Transaction(
        nonce=int(exek['nonce'] or "0"),
        gasprice=int(exek['gasPrice'] or "0"),
        startgas=int(exek['gasLimit'] or "0"),
        to=exek['to'],
        value=int(exek['value'] or "0"),
        data=exek['data'][2:].decode('hex')).sign(exek['secretKey'])

    orig_apply_msg = pb.apply_msg

    def apply_msg_wrapper(ext, msg, code):

        def blkhash(n):
            if n >= blk.number or n < blk.number - 256:
                return ''
            else:
                return u.sha3(str(n))

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

    pb.apply_msg = apply_msg_wrapper

    try:
        success, output = pb.apply_transaction(blk, tx)
        blk.commit_state()
    except pb.InvalidTransaction:
        output = ''
        logger.debug('Transaction not valid')
        pass

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

    pb.apply_msg = orig_apply_msg

    assert '0x' + output.encode('hex') == params['out']

    # check state
    for address, data in post.items():
        state = blk.account_to_dict(address, for_vmtest=True)
        state.pop('storage_root', None)
        assert state == data
Esempio n. 10
0
def hash_value(value):
    return utils.big_endian_to_int(utils.sha3(utils.zpad(value, 32)))
Esempio n. 11
0
 def get_proposal_id(self, proposal):
     return big_endian_to_int(sha3(zpad(proposal, 32)))
Esempio n. 12
0
def prepare_state_test(params):

    pre = params['pre']
    exek = params['transaction']
    env = params['env']
    # setup env
    blk = blocks.Block(db,
                       prevhash=env['previousHash'].decode('hex'),
                       number=int(env['currentNumber']),
                       coinbase=env['currentCoinbase'],
                       difficulty=int(env['currentDifficulty']),
                       gas_limit=int(env['currentGasLimit']),
                       timestamp=int(env['currentTimestamp']))

    for address, h in pre.items():
        blk.set_nonce(address, int(h['nonce']))
        blk.set_balance(address, int(h['balance']))
        blk.set_code(address, h['code'][2:].decode('hex'))
        for k, v in h['storage'].iteritems():
            blk.set_storage_data(address,
                                 u.big_endian_to_int(k[2:].decode('hex')),
                                 u.big_endian_to_int(v[2:].decode('hex')))

    # execute transactions
    tx = transactions.Transaction(nonce=int(exek['nonce'] or "0"),
                                  gasprice=int(exek['gasPrice'] or "0"),
                                  startgas=int(exek['gasLimit'] or "0"),
                                  to=exek['to'],
                                  value=int(exek['value'] or "0"),
                                  data=exek['data'][2:].decode('hex')).sign(
                                      exek['secretKey'])

    orig_apply_msg = pb.apply_msg

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

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

    pb.apply_msg = apply_msg_wrapper

    blk2 = blocks.Block.deserialize(db, blk.serialize())
    t1 = time.time()
    try:
        pb.apply_transaction(blk, tx)
    except:
        print 'exception'
        pass
    t2 = time.time()
    recorder = LogRecorder()
    try:
        pb.apply_transaction(blk2, tx)
    except:
        print 'exception'
        pass
    trace = recorder.pop_records()
    ops = [x['op'] for x in trace if x['event'] == 'vm']
    opdict = {}
    for op in ops:
        opdict[op] = opdict.get(op, 0) + 1
    return {"ops": opdict, "time": t2 - t1}
Esempio n. 13
0
def profile_vm_test(params):
    pre = params['pre']
    exek = params['exec']
    env = params['env']

    # setup env
    blk = blocks.Block(db,
                       prevhash=env['previousHash'].decode('hex'),
                       number=int(env['currentNumber']),
                       coinbase=env['currentCoinbase'],
                       difficulty=int(env['currentDifficulty']),
                       gas_limit=int(env['currentGasLimit']),
                       timestamp=int(env['currentTimestamp']))

    # setup state
    for address, h in pre.items():
        blk.set_nonce(address, int(h['nonce']))
        blk.set_balance(address, int(h['balance']))
        blk.set_code(address, h['code'][2:].decode('hex'))
        for k, v in h['storage'].iteritems():
            blk.set_storage_data(address,
                                 u.big_endian_to_int(k[2:].decode('hex')),
                                 u.big_endian_to_int(v[2:].decode('hex')))

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

    ext = pb.VMExt(blk, tx)

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

    ext.block_hash = blkhash

    msg = vm.Message(tx.sender, tx.to, tx.value, tx.startgas,
                     vm.CallData([ord(x) for x in tx.data]))
    blk2 = blocks.Block.deserialize(db, blk.serialize())
    t1 = time.time()
    success, gas_remained, output = \
        vm.vm_execute(ext, msg, exek['code'][2:].decode('hex'))
    blk.commit_state()
    t2 = time.time()
    recorder = LogRecorder()
    ext = pb.VMExt(blk2, tx)
    ext.block_hash = blkhash
    success, gas_remained, output = \
        vm.vm_execute(ext, msg, exek['code'][2:].decode('hex'))
    trace = recorder.pop_records()
    ops = [x['op'] for x in trace if x['event'] == 'vm']
    opdict = {}
    for op in ops:
        opdict[op] = opdict.get(op, 0) + 1
    return {"ops": opdict, "time": t2 - t1}
Esempio n. 14
0
def step_impl(context):
    length = big_endian_to_int(context.packet[4:8])
    assert length == len(context.encoded_data)
Esempio n. 15
0
def do_test_vm(name):
    logger.debug('running test:%r', name)
    params = vm_tests_fixtures()[name]

    pre = params['pre']
    exek = params['exec']
    callcreates = params['callcreates']
    env = params['env']
    post = params['post']

    check_testdata(env.keys(), ['currentGasLimit', 'currentTimestamp',
                                'previousHash', 'currentCoinbase',
                                'currentDifficulty', 'currentNumber'])
    # setup env
    blk = blocks.Block(
        prevhash=env['previousHash'].decode('hex'),
        number=int(env['currentNumber']),
        coinbase=env['currentCoinbase'],
        difficulty=int(env['currentDifficulty']),
        gas_limit=int(env['currentGasLimit']),
        timestamp=int(env['currentTimestamp']))

    # code FIXME WHAT TO DO WITH THIS CODE???
    # if isinstance(env['code'], str):
    #     continue
    # else:
    #     addr = 0 # FIXME
    #     blk.set_code(addr, ''.join(map(chr, env['code'])))

    # setup state
    for address, h in pre.items():
        check_testdata(h.keys(), ['code', 'nonce', 'balance', 'storage'])
        blk.set_nonce(address, int(h['nonce']))
        blk.set_balance(address, int(h['balance']))
        blk.set_code(address, h['code'][2:].decode('hex'))
        for k, v in h['storage']:
            blk.set_storage_data(address,
                                 u.big_endian_to_int(k.decode('hex')),
                                 u.big_endian_to_int(v.decode('hex')))
        logger.debug('PRE Balance: %r: %r', address, h['balance'])

    # execute transactions
    pb.enable_debug()
    sender = exek['caller']  # a party that originates a call
    recvaddr = exek['address']
    tx = transactions.Transaction(
        nonce=blk._get_acct_item(exek['caller'], 'nonce'),
        gasprice=int(exek['gasPrice']),
        startgas=int(exek['gas']),
        to=recvaddr,
        value=int(exek['value']),
        data=exek['data'][2:].decode('hex'))
    tx.sender = sender
    logger.debug('TX %r > %r v:%r gas:%s @price:%s',
                 sender, recvaddr, tx.value, tx.startgas, tx.gasprice)

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

    def apply_msg_wrapper(_block, _tx, msg, code):
        pb.enable_debug()
        apply_message_calls.append(dict(gasLimit=msg.gas, value=msg.value,
                                        destination=msg.to,
                                        data=msg.data.encode('hex')))
        result, gas_rem, data = orig_apply_msg(_block, _tx, msg, code)
        pb.disable_debug()
        return result, gas_rem, data

    pb.apply_msg = apply_msg_wrapper

    msg = pb.Message(tx.sender, tx.to, tx.value, tx.startgas, tx.data)
    blk.delta_balance(exek['caller'], tx.value)
    blk.delta_balance(exek['address'], -tx.value)
    success, gas_remained, output = \
        pb.apply_msg(blk, tx, msg, exek['code'][2:].decode('hex'))
    pb.apply_msg = orig_apply_msg
    apply_message_calls.pop(0)
    blk.commit_state()

    assert success
    assert len(callcreates) == len(apply_message_calls)

    # check against callcreates
    for i, callcreate in enumerate(callcreates):
        amc = apply_message_calls[i]
        assert callcreate['data'] == '0x'+amc['data'].encode('hex')
        assert callcreate['gasLimit'] == str(amc['gasLimit'])
        assert callcreate['value'] == str(amc['value'])
        assert callcreate['destination'] == amc['destination']

    assert '0x'+''.join(map(chr, output)).encode('hex') == params['out']
    assert str(gas_remained) == params['gas']

    # check state
    for address, data in post.items():
        state = blk.account_to_dict(address)
        state.pop('storage_root', None)  # attribute not present in vmtest fixtures
        assert data == state
Esempio n. 16
0
class TestCommitRevealEntropyContract(object):

    CONTRACT = 'contracts/commit_reveal_entropy.se'
    COW_HASH = hash_value('cow')
    COW_INT = utils.big_endian_to_int('cow')
    MONKEY_INT = utils.big_endian_to_int('monkey')

    ENTROPY_COST = 10**15
    DEPOSIT_COST = 10**18

    def setup_class(cls):
        cls.s = tester.state()
        cls.c = cls.s.abi_contract(cls.CONTRACT)
        cls.snapshot = cls.s.snapshot()

    def setup_method(self, method):
        self.s.revert(self.snapshot)

    def test_request_entropy(self):
        assert self.c.request_entropy(value=self.ENTROPY_COST) == [0, 4]
        assert self.c.get_entropy_ticket(0) == [
            int(tester.a0, 16), 0, self.s.block.number + 1, 0
        ]
        assert self.c.get_entropy(0) == [0, 0]  # pending
        assert self.c.get_block(self.s.block.number + 1) == [0, 0, 0, 1]

        assert self.s.block.get_balance(
            tester.a0) == 10**24 - self.ENTROPY_COST

    def test_request_entropy_insufficient_fee(self):
        assert self.c.request_entropy(value=0) == [0]
        assert self.c.get_entropy_ticket(0) == [0, 0, 0, 0]
        assert self.c.get_entropy(0) == [3, 0]  # not found

    def test_request_multiple_entropy_tickets(self):
        assert self.c.request_entropy(value=self.ENTROPY_COST) == [0, 4]
        assert self.c.request_entropy(value=self.ENTROPY_COST) == [1, 4]
        assert self.c.request_entropy(value=self.ENTROPY_COST) == [2, 4]

        assert self.c.get_entropy_ticket(0) == [
            int(tester.a0, 16), 0, self.s.block.number + 1, 0
        ]
        assert self.c.get_entropy_ticket(1) == [
            int(tester.a0, 16), 0, self.s.block.number + 1, 0
        ]
        assert self.c.get_entropy_ticket(2) == [
            int(tester.a0, 16), 0, self.s.block.number + 1, 0
        ]

        assert self.c.get_block(self.s.block.number + 1) == [0, 0, 0, 3]

    def test_request_multiple_entropy_tickets_different_senders(self):
        assert self.c.request_entropy(value=self.ENTROPY_COST) == [0, 4]
        assert self.c.request_entropy(sender=tester.k1,
                                      value=self.ENTROPY_COST) == [1, 4]

        assert self.c.get_entropy_ticket(0) == [
            int(tester.a0, 16), 0, self.s.block.number + 1, 0
        ]
        assert self.c.get_entropy_ticket(1) == [
            int(tester.a1, 16), 0, self.s.block.number + 1, 0
        ]

        assert self.c.get_block(self.s.block.number + 1) == [0, 0, 0, 2]

    def test_request_entropy_target_depends_on_block_number(self):
        self.s.mine()
        assert self.c.request_entropy(value=self.ENTROPY_COST) == [0, 5]
        assert self.c.get_entropy_ticket(0) == [
            int(tester.a0, 16), 0, self.s.block.number + 1, 0
        ]

        self.s.mine(10)
        assert self.c.request_entropy(value=self.ENTROPY_COST) == [1, 15]
        assert self.c.get_entropy_ticket(1) == [
            int(tester.a0, 16), 0, self.s.block.number + 1, 0
        ]

    def test_request_entropy_get_expired(self):
        assert self.c.request_entropy(value=self.ENTROPY_COST) == [0, 4]

        # XXX off by one?
        self.s.mine(4)
        assert self.s.block.number == 4
        assert self.c.get_entropy(0) == [2, 0]  # expired

    def test_hash_sha3(self):
        value = 'cow'
        assert self.c.hash(self.COW_INT) == [hash_value(value)]

    def test_commit(self):
        assert self.c.commit(1, self.COW_HASH, value=self.DEPOSIT_COST) == [1]
        assert self.c.get_block(1) == [0, 1, 0, 0]

        assert self.s.block.get_balance(
            tester.a0) == 10**24 - self.DEPOSIT_COST

    def test_commit_insufficient_deposit(self):
        assert self.c.commit(4, self.COW_HASH, cost=0) == [0]
        assert self.c.get_block(4) == [0, 0, 0, 0]

    def test_commit_invalid_target(self):
        assert self.c.commit(0, self.COW_HASH, value=self.DEPOSIT_COST) == [0]
        assert self.c.get_block(0) == [0, 0, 0, 0]

        self.s.mine(4)
        assert self.c.commit(4, self.COW_HASH, value=self.DEPOSIT_COST) == [0]
        assert self.c.get_block(4) == [0, 0, 0, 0]

    def test_commit_twice(self):
        assert self.c.commit(4, self.COW_HASH, value=self.DEPOSIT_COST) == [1]
        assert self.c.get_block(4) == [0, 1, 0, 0]

        assert self.c.commit(4, self.COW_HASH, value=self.DEPOSIT_COST) == [0]
        assert self.c.get_block(4) == [0, 1, 0, 0]

    def test_commit_twice_different_senders(self):
        assert self.c.commit(4, self.COW_HASH, value=self.DEPOSIT_COST) == [1]
        assert self.c.commit(4,
                             self.COW_HASH,
                             sender=tester.k1,
                             value=self.DEPOSIT_COST) == [1]
        assert self.c.get_block(4) == [0, 2, 0, 0]

    def test_commit_invalid_hash(self):
        assert self.c.commit(1, 0, value=self.DEPOSIT_COST) == [0]
        assert self.c.get_block(0) == [0, 0, 0, 0]

    def test_reveal(self):
        self.test_commit()
        self.s.mine(2)

        balance = self.s.block.get_balance(tester.a0)
        assert self.c.reveal(1, self.COW_INT) == [1]
        assert self.c.get_block(1) == [
            0x6d8d9b450dd77c907e2bc2b6612699789c3464ea8757c2c154621057582287a3,
            1, 1, 0
        ]
        assert self.s.block.get_balance(
            tester.a0) - balance == self.DEPOSIT_COST  # deposit return

    def test_reveal_not_yet_allowed(self):
        self.test_commit()

        assert self.c.reveal(1, self.COW_INT) == [90]

    def test_reveal_window_expired(self):
        self.test_commit()
        self.s.mine(5)

        assert self.c.reveal(1, self.COW_INT) == [91]

    def test_reveal_not_committed(self):
        self.s.mine(2)

        assert self.c.reveal(1, self.COW_INT) == [92]

    def test_reveal_already_revealed(self):
        self.test_commit()
        self.s.mine(2)

        assert self.c.reveal(1, self.COW_INT) == [1]
        assert self.c.reveal(1, self.COW_INT) == [93]

    def test_reveal_hash_mismatch(self):
        self.test_commit()
        self.s.mine(2)

        assert self.c.reveal(1, self.MONKEY_INT) == [94]

    def test_reveal_calculates_seed_when_all_reveals_are_in(self):
        assert self.c.commit(1, self.COW_HASH, value=self.DEPOSIT_COST) == [1]
        assert self.c.commit(1,
                             self.COW_HASH,
                             sender=tester.k1,
                             value=self.DEPOSIT_COST) == [1]
        self.s.mine(2)

        assert self.c.reveal(1, self.COW_INT) == [1]
        assert self.c.get_block(1) == [0, 2, 1, 0]
        assert self.c.reveal(1, self.COW_INT, sender=tester.k1) == [1]
        assert self.c.get_block(1) == [
            0x2c996eb68c74cec2b2acd81abe0f75fe67b2b941702b8dc25e96a106800eb922,
            2, 2, 0
        ]

    def test_reveal_returns_entropy(self):
        assert self.c.commit(1, self.COW_HASH, value=self.DEPOSIT_COST) == [1]
        assert self.c.request_entropy(sender=tester.k1,
                                      value=self.ENTROPY_COST) == [0, 4]
        assert self.c.get_block(self.s.block.number + 1) == [0, 1, 0, 1]

        self.s.mine(2)

        COW_SEED = utils.big_endian_to_int(
            utils.sha3(
                utils.sha3(utils.zpad('cow', 32)) + utils.zpad('cow', 32)))
        COW_HASH_1 = utils.big_endian_to_int(
            utils.sha3(utils.int_to_big_endian(COW_SEED)))

        balance = self.s.block.get_balance(tester.a0)
        assert self.c.reveal(1, self.COW_INT) == [1]
        assert self.s.block.get_balance(
            tester.a0
        ) - balance == self.DEPOSIT_COST + self.ENTROPY_COST  # deposit return + payout of committer share

        assert self.c.get_block(1) == [COW_SEED, 1, 1, 1]

        # signed vs unsigned as introduced by tester.send
        assert self.c.get_entropy_ticket(0) == [
            int(tester.a1, 16), 1, 1, COW_HASH_1 - 2**256
        ]
        assert self.c.get_entropy(
            0, sender=tester.k1) == [1, COW_HASH_1 - 2**256]  # ready
Esempio n. 17
0
def do_test_vm(filename, testname=None, limit=99999999):
    if testname is None:
        for testname in vm_tests_fixtures()[filename].keys()[:limit]:
            do_test_vm(filename, testname)
        return
    if testname in faulty:
        logger.debug('skipping test:%r in %r' % (testname, filename))
        return
    logger.debug('running test:%r in %r' % (testname, filename))
    params = vm_tests_fixtures()[filename][testname]

    pre = params['pre']
    exek = params['transaction']
    env = params['env']
    post = params['post']

    check_testdata(env.keys(), [
        'currentGasLimit', 'currentTimestamp', 'previousHash',
        'currentCoinbase', 'currentDifficulty', 'currentNumber'
    ])
    # setup env
    blk = blocks.Block(new_db(),
                       prevhash=env['previousHash'].decode('hex'),
                       number=int(env['currentNumber']),
                       coinbase=env['currentCoinbase'],
                       difficulty=int(env['currentDifficulty']),
                       gas_limit=int(env['currentGasLimit']),
                       timestamp=int(env['currentTimestamp']))

    # code FIXME WHAT TO DO WITH THIS CODE???
    # if isinstance(env['code'], str):
    #     continue
    # else:
    # addr = 0 # FIXME
    #     blk.set_code(addr, ''.join(map(chr, env['code'])))

    # setup state
    for address, h in pre.items():
        check_testdata(h.keys(), ['code', 'nonce', 'balance', 'storage'])
        blk.set_nonce(address, int(h['nonce']))
        blk.set_balance(address, int(h['balance']))
        blk.set_code(address, h['code'][2:].decode('hex'))
        for k, v in h['storage'].iteritems():
            blk.set_storage_data(address,
                                 u.big_endian_to_int(k[2:].decode('hex')),
                                 u.big_endian_to_int(v[2:].decode('hex')))

    # execute transactions
    tx = transactions.Transaction(nonce=int(exek['nonce'] or "0"),
                                  gasprice=int(exek['gasPrice'] or "0"),
                                  startgas=int(exek['gasLimit'] or "0"),
                                  to=exek['to'],
                                  value=int(exek['value'] or "0"),
                                  data=exek['data'][2:].decode('hex')).sign(
                                      exek['secretKey'])

    orig_apply_msg = pb.apply_msg

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

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

    pb.apply_msg = apply_msg_wrapper

    try:
        success, output = pb.apply_transaction(blk, tx)
        blk.commit_state()
    except pb.InvalidTransaction:
        output = ''
        logger.debug('Transaction not valid')
        pass

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

    pb.apply_msg = orig_apply_msg

    assert '0x' + output.encode('hex') == params['out']

    # check state
    for address, data in post.items():
        state = blk.account_to_dict(address, for_vmtest=True)
        state.pop('storage_root', None)
        assert state == data
Esempio n. 18
0
def do_test_vm(name):
    logger.debug('running test:%r', name)
    for testname in vm_tests_fixtures(name).keys():

        logger.debug('running test:%r', testname)
               
        params = vm_tests_fixtures(name)[testname]

        pre = params['pre']
        exek = params['exec']
        callcreates = params['callcreates']
        env = params['env']
        post = params['post']

        check_testdata(env.keys(), ['currentGasLimit', 'currentTimestamp',
                                    'previousHash', 'currentCoinbase',
                                    'currentDifficulty', 'currentNumber'])
        # setup env
        blk = blocks.Block(
            prevhash=env['previousHash'].decode('hex'),
            number=int(env['currentNumber']),
            coinbase=env['currentCoinbase'],
            difficulty=int(env['currentDifficulty']),
            gas_limit=int(env['currentGasLimit']),
            timestamp=int(env['currentTimestamp']))

        # code FIXME WHAT TO DO WITH THIS CODE???
        # if isinstance(env['code'], str):
        #     continue
        # else:
        #     addr = 0 # FIXME
        #     blk.set_code(addr, ''.join(map(chr, env['code'])))

        # setup state
        for address, h in pre.items():
            check_testdata(h.keys(), ['code', 'nonce', 'balance', 'storage'])
            blk.set_nonce(address, int(h['nonce']))
            blk.set_balance(address, int(h['balance']))
            blk.set_code(address, h['code'][2:].decode('hex'))
            for k, v in h['storage']:
                blk.set_storage_data(address,
                                     u.big_endian_to_int(k.decode('hex')),
                                     u.big_endian_to_int(v.decode('hex')))
            pblogger.log('PRE Balance', address=address, balance=h['balance'])
    
        # execute transactions
        sender = exek['caller']  # a party that originates a call
        recvaddr = exek['address']
        tx = transactions.Transaction(
            nonce=blk._get_acct_item(exek['caller'], 'nonce'),
            gasprice=int(exek['gasPrice']),
            startgas=int(exek['gas']),
            to=recvaddr,
            value=int(exek['value']),
            data=exek['data'][2:].decode('hex'))
        tx.sender = sender
        pblogger.log('TX', tx=tx.hex_hash(), sender=sender, to=recvaddr, value=tx.value, startgas=tx.startgas, gasprice=tx.gasprice)
    
        # capture apply_message calls
        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,
                                            destination=msg.to,
                                            data=msg.data.encode('hex')))
            result, gas_rem, data = orig_apply_msg(_block, _tx, msg, code)
            return result, gas_rem, data

        pb.apply_msg = apply_msg_wrapper

        msg = pb.Message(tx.sender, tx.to, tx.value, tx.startgas, tx.data)
        blk.delta_balance(exek['caller'], tx.value)
        blk.delta_balance(exek['address'], -tx.value)
	try:
	    success, gas_remained, output = \
	        pb.apply_msg(blk, tx, msg, exek['code'][2:].decode('hex'))
	except MemoryError:
	    print "A memory error exception has been thrown and catched!\n"

        pb.apply_msg = orig_apply_msg
        apply_message_calls.pop(0)
        blk.commit_state()
    
        assert success
        assert len(callcreates) == len(apply_message_calls)
    
        # check against callcreates
        for i, callcreate in enumerate(callcreates):
            amc = apply_message_calls[i]
            assert callcreate['data'] == '0x'+amc['data'].encode('hex')
            assert callcreate['gasLimit'] == str(amc['gasLimit'])
            assert callcreate['value'] == str(amc['value'])
            assert callcreate['destination'] == amc['destination']
    
        assert '0x'+''.join(map(chr, output)).encode('hex') == params['out']
        if gas_remained <0:  gas_remained = 0
        assert str(gas_remained) == params['gas']
    
        # check state
        
        for address, data in post.items():
            state = blk.account_to_dict(address)
            state.pop('storage_root', None)  # attribute not present in vmtest fixtures

            # check hex values in same format

            def newFormat(x):
                if x == '0x':
                    return '0x00'
		elif x[:2] == '0x':
		    return "0x%0.2X" % int(x,0)
		else:
		    return x

	    data['storage'] = {  newFormat(k) : newFormat(v[0]) for k,v in data['storage'].items() if int(newFormat(v[0]),0)!=0 }
            state['storage'] = { newFormat(k) : newFormat(v) for k,v in state['storage'].items()}   

            assert data == state