def get_msg_state(block, msg, code):
    msg_state = {}
    # msg_state['contract'] = msg.to
    msg_state['balance'] = block.get_balance(msg.to)
    storages = ['{}: {}'.format(utils.hexprint(storage['key']), utils.hexprint(storage['value'])) for storage in block.get_storage_data(msg.to)]
    msg_state['storage'] = storages
    msg_state['code'] = code
    return msg_state
def log (name, obj):
    assert type(obj) == dict

    # Convert binary.
    for key in obj.keys():
        if type(obj[key]) == bytes:
            obj[key] = utils.hexprint(obj[key])

    # Truncate long lines.
    for key in obj.keys():
        if type(obj[key]) == str and len(obj[key]) > 120:
            obj[key] = obj[key][:60] + '…' + obj[key][-60:]

    # Sort
    if name == 'OP':
        keyorder = ['pc', 'gas', 'op', 'stackargs', 'value', 'stack']
        obj = sorted(obj.items(), key=lambda i:keyorder.index(i[0]))
    else:
        obj = sorted(obj.items())
    lines = ['{}: {}'.format(pair[0], pair[1]) for pair in obj]

    if 'op' == name.lower():
        string = str(lines).replace("'", "")[1:-1]
        logger.debug('\tOP ' + string)
    else:
        if name:
            logger.debug(name)
        for line in lines:
            logger.debug('\t' + str(line))
def apply_msg(db, block, tx, msg, code):
    """
    logger.debug('\n')
    new_dict = vars(msg).copy()
    new_dict.update(get_msg_state(block, msg, code))
    logger.debug('\nBEGIN MESSAGE')
    log('', new_dict)
    """

    pblogger.log("MSG APPLY", tx=tx.hex_hash(), sender=msg.sender, to=msg.to,
                                  gas=msg.gas, value=msg.value, data=utils.hexprint(msg.data))
    pblogger.log('MSG PRE STATE', account=msg.to, state=block.account_to_dict(msg.to))
    # Transfer value, instaquit if not enough
    o = block.transfer_value(tx, msg.sender, msg.to, msg.value)
    if not o:
        return 1, msg.gas, []

    # logger.info('CODE {}'.format(util.hexlify(code)))
    if code in code_cache:
        processed_code = code_cache[code]
    else:
        processed_code = [opcodes.opcodes.get(c, ['INVALID', 0, 0, [], 0]) +
                          [c] for c in code]
        code_cache[code] = processed_code
    # logger.info('PROCESSED_CODE {}'.format(processed_code))

    try:
        # Snapshot.
        # NOTE: If I use explicit savepoints and rollbacks instead of this `with`,
        # then I can stop passing around `db`.
        with db:

            # Initialise compustate.
            compustate = Compustate(gas=msg.gas)
            t, ops = time.time(), 0

            # Main loop
            # logger.debug('')
            while True:
                o = apply_op(db, block, tx, msg, processed_code, compustate)
                ops += 1

                if o is not None:
                    """"
                    if data == OUT_OF_GAS:
                        data_printable = -1
                    else:
                        data_printable = bytes(data)

                    msg_applied = {'data (result)': data_printable,
                                   'sender': msg.sender,
                                   'to': msg.to,
                                   'gas': gas_remaining}
                    new_dict = msg_applied.copy()
                    new_dict.update(get_msg_state(msg, code))
                    logger.debug('')
                    log('', new_dict)
                    logger.debug('END MESSAGE\n')
                    """

                    pblogger.log('MSG APPLIED', result=o, gas_remained=compustate.gas,
                                sender=msg.sender, to=msg.to, ops=ops,
                                time_per_op=(time.time() - t) / ops)
                    pblogger.log('MSG POST STATE', account=msg.to,
                                state=block.account_to_dict(msg.to))

                    if o == OUT_OF_GAS:
                        block.revert()
                        raise OutOfGas
                    else:
                        return 1, compustate.gas, o

    # When out of gas, break out of the `with` and then `return`.
    except OutOfGas as e:
        result = 0
        data = []
        gas_remained = compustate.gas
        return result, gas_remained, data
Example #4
0
 def account_to_dict(self, address):
     return {'nonce': Block.get_nonce(self, address), 'balance': Block.get_balance(self, address), 'storage': Block.get_storage_data(self, address), 'code': utils.hexprint(Block.get_code(self, address))}