Example #1
0
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
Example #2
0
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
Example #4
0
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)