def unpack(db, message, block_index): try: memo_bytes_length = len(message) - LENGTH if memo_bytes_length < 0: raise exceptions.UnpackError('invalid message length') if memo_bytes_length > MAX_MEMO_LENGTH: raise exceptions.UnpackError('memo too long') struct_format = FORMAT + ('{}s'.format(memo_bytes_length)) short_address_bytes, flags, memo_bytes = struct.unpack(struct_format, message) if len(memo_bytes) == 0: memo_bytes = None elif not(flags & FLAG_BINARY_MEMO): memo_bytes = memo_bytes.decode('utf-8') # unpack address full_address = address.unpack(short_address_bytes) except (struct.error) as e: logger.warning("sweep send unpack error: {}".format(e)) raise exceptions.UnpackError('could not unpack') unpacked = { 'destination': full_address, 'flags': flags, 'memo': memo_bytes, } return unpacked
def unpack(db, message, block_index): try: unpacked = _decode_mpmaSendDecode(message, block_index) except (struct.error) as e: raise exceptions.UnpackError('could not unpack') except (exceptions.AssetNameError, exceptions.AssetIDError) as e: raise exceptions.UnpackError('invalid asset in mpma send') except (ReadError) as e: raise exceptions.UnpackError('truncated data') return unpacked
def unpack(db, message, block_index): try: # account for memo bytes memo_bytes_length = len(message) - LENGTH if memo_bytes_length < 0: raise exceptions.UnpackError('invalid message length') if memo_bytes_length > MAX_MEMO_LENGTH: raise exceptions.UnpackError('memo too long') struct_format = FORMAT + ('{}s'.format(memo_bytes_length)) asset_id, quantity, short_address_bytes, memo_bytes = struct.unpack( struct_format, message) if len(memo_bytes) == 0: memo_bytes = None # unpack address full_address = address.unpack(short_address_bytes) # asset id to name asset = util.generate_asset_name(asset_id, block_index) if asset == config.BTC: raise exceptions.AssetNameError('{} not allowed'.format( config.BTC)) except (struct.error) as e: logger.warning("enhanced send unpack error: {}".format(e)) raise exceptions.UnpackError('could not unpack') except (exceptions.AssetNameError, exceptions.AssetIDError) as e: logger.warning("enhanced send invalid asset id: {}".format(e)) raise exceptions.UnpackError('asset id invalid') unpacked = { 'asset': asset, 'quantity': quantity, 'address': full_address, 'memo': memo_bytes, } return unpacked
def parse(db, tx, message): if not config.TESTNET: # TODO return status = 'valid' output, gas_cost, gas_remained = None, None, None try: # TODO: Use unpack function. # Unpack message. curr_format = FORMAT + '{}s'.format(len(message) - LENGTH) try: contract_id, gasprice, startgas, value, payload = struct.unpack( curr_format, message) if gasprice > config.MAX_INT or startgas > config.MAX_INT or value > config.MAX_INT: # TODO: define max for gasprice and startgas raise exceptions.UnpackError() except (struct.error) as e: raise exceptions.UnpackError() gas_remained = startgas contract_id = util.hexlify(contract_id) if contract_id == '0000000000000000000000000000000000000000': contract_id = '' # ‘Apply transaction’! tx_obj = Transaction(tx, contract_id, gasprice, startgas, value, payload) block_obj = blocks.Block(db, tx['block_hash']) success, output, gas_remained = processblock.apply_transaction( db, tx_obj, block_obj) if not success and output == '': status = 'out of gas' gas_cost = gasprice * (startgas - gas_remained ) # different definition from pyethereum’s except exceptions.UnpackError as e: contract_id, gasprice, startgas, value, payload = None, None, None, None, None status = 'invalid: could not unpack' output = None except processblock.ContractError as e: status = 'invalid: no such contract' contract_id = None output = None except processblock.InsufficientStartGas as e: have, need = e.args logger.debug('Insufficient start gas: have {} and need {}'.format( have, need)) status = 'invalid: insufficient start gas' output = None except processblock.InsufficientBalance as e: have, need = e.args logger.debug('Insufficient balance: have {} and need {}'.format( have, need)) status = 'invalid: insufficient balance' output = None except processblock.OutOfGas as e: logger.debug('TX OUT_OF_GAS (startgas: {}, gas_remained: {})'.format( startgas, gas_remained)) status = 'out of gas' output = None finally: if status == 'valid': logger.debug('TX FINISHED (gas_remained: {})'.format(gas_remained)) # Add parsed transaction to message-type–specific table. bindings = { 'tx_index': tx['tx_index'], 'tx_hash': tx['tx_hash'], 'block_index': tx['block_index'], 'source': tx['source'], 'contract_id': contract_id, 'gasprice': gasprice, 'startgas': startgas, 'gas_cost': gas_cost, 'gas_remained': gas_remained, 'value': value, 'payload': payload, 'output': output, 'status': status } sql = 'insert into executions values(:tx_index, :tx_hash, :block_index, :source, :contract_id, :gasprice, :startgas, :gas_cost, :gas_remained, :value, :data, :output, :status)' cursor = db.cursor() cursor.execute(sql, bindings)