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
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))}