예제 #1
0
def compose(db, source, order_match_id):
    tx0_hash, tx1_hash = order_match_id[:64], order_match_id[
        64:]  # UTF-8 encoding means that the indices are doubled.

    destination, btc_quantity, escrowed_asset, escrowed_quantity, order_match, problems = validate(
        db, source, order_match_id,
        util.last_block(db)['block_index'])
    if problems: raise exceptions.ComposeError(problems)

    # Warn if down to the wire.
    time_left = order_match['match_expire_index'] - util.last_block(
        db)['block_index']
    if time_left < 4:
        logging.warning(
            'WARNING: Only {} blocks until that order match expires. The payment might not make into the blockchain in time.'
            .format(time_left))
    if 10 - time_left < 4:
        logging.warning(
            'WARNING: Order match has only {} confirmation(s).'.format(
                10 - time_left))

    tx0_hash_bytes, tx1_hash_bytes = binascii.unhexlify(
        bytes(tx0_hash, 'utf-8')), binascii.unhexlify(bytes(tx1_hash, 'utf-8'))
    data = struct.pack(config.TXTYPE_FORMAT, ID)
    data += struct.pack(FORMAT, tx0_hash_bytes, tx1_hash_bytes)
    return (source, [(destination, btc_quantity)], data)
예제 #2
0
def compose (db, source, fraction, asset):
    call_price, callback_total, outputs, problems = validate(db, source, fraction, asset, util.last_block(db)['block_time'], util.last_block(db)['block_index'], parse=False)
    if problems: raise exceptions.ComposeError(problems)
    logging.info('Total quantity to be called back: {} {}'.format(util.devise(db, callback_total, asset, 'output'), asset))

    asset_id = util.get_asset_id(db, asset, util.last_block(db)['block_index'])
    data = struct.pack(config.TXTYPE_FORMAT, ID)
    data += struct.pack(FORMAT, fraction, asset_id)
    return (source, [], data)
예제 #3
0
def compose(db, source, offer_hash):

    # Check that offer exists.
    offer, offer_type, problems = validate(db, source, offer_hash)
    if problems: raise exceptions.ComposeError(problems)

    offer_hash_bytes = binascii.unhexlify(bytes(offer_hash, 'utf-8'))
    data = struct.pack(config.TXTYPE_FORMAT, ID)
    data += struct.pack(FORMAT, offer_hash_bytes)
    return (source, [], data)
예제 #4
0
def compose (db, source, give_asset, give_quantity, get_asset, get_quantity, expiration, fee_required):
    cursor = db.cursor()

    # Check balance.
    if give_asset != config.BTC:
        balances = list(cursor.execute('''SELECT * FROM balances WHERE (address = ? AND asset = ?)''', (source, give_asset)))
        if (not balances or balances[0]['quantity'] < give_quantity):
            raise exceptions.ComposeError('insufficient funds')

    problems = validate(db, source, give_asset, give_quantity, get_asset, get_quantity, expiration, fee_required, util.last_block(db)['block_index'])
    if problems: raise exceptions.ComposeError(problems)

    give_id = util.get_asset_id(db, give_asset, util.last_block(db)['block_index'])
    get_id = util.get_asset_id(db, get_asset, util.last_block(db)['block_index'])
    data = struct.pack(config.TXTYPE_FORMAT, ID)
    data += struct.pack(FORMAT, give_id, give_quantity, get_id, get_quantity,
                        expiration, fee_required)
    cursor.close()
    return (source, [], data)
예제 #5
0
def compose(db, source, possible_moves, wager, move_random_hash, expiration):

    problems = validate(db, source, possible_moves, wager, move_random_hash,
                        expiration,
                        util.last_block(db)['block_index'])

    if problems: raise exceptions.ComposeError(problems)

    data = struct.pack(config.TXTYPE_FORMAT, ID)
    data += struct.pack(FORMAT, possible_moves, wager,
                        binascii.unhexlify(move_random_hash), expiration)

    return (source, [], data)
예제 #6
0
def compose (db, source, quantity_per_unit, asset, dividend_asset):

    dividend_total, outputs, problems, fee = validate(db, source, quantity_per_unit, asset, dividend_asset, util.last_block(db)['block_index'])
    if problems: raise exceptions.ComposeError(problems)
    logging.info('Total quantity to be distributed in dividends: {} {}'.format(util.devise(db, dividend_total, dividend_asset, 'output'), dividend_asset))

    if dividend_asset == config.BTC:
        return (source, [(output['address'], output['dividend_quantity']) for output in outputs], None)

    asset_id = util.get_asset_id(db, asset, util.last_block(db)['block_index'])
    dividend_asset_id = util.get_asset_id(db, dividend_asset, util.last_block(db)['block_index'])
    data = struct.pack(config.TXTYPE_FORMAT, ID)
    data += struct.pack(FORMAT_2, quantity_per_unit, asset_id, dividend_asset_id)
    return (source, [], data)
예제 #7
0
def compose(db, source, quantity, overburn=False):
    cursor = db.cursor()
    destination = config.UNSPENDABLE
    problems = validate(db,
                        source,
                        destination,
                        quantity,
                        util.last_block(db)['block_index'],
                        overburn=overburn)
    if problems: raise exceptions.ComposeError(problems)

    # Check that a maximum of 1 BTC total is burned per address.
    burns = list(
        cursor.execute(
            '''SELECT * FROM burns WHERE (status = ? AND source = ?)''',
            ('valid', source)))
    already_burned = sum([burn['burned'] for burn in burns])
    if quantity > (1 * config.UNIT - already_burned) and not overburn:
        raise exceptions.ComposeError('1 {} may be burned per address'.format(
            config.BTC))

    cursor.close()
    return (source, [(destination, quantity)], None)
예제 #8
0
def compose(db, source, feed_address, bet_type, deadline, wager_quantity,
            counterwager_quantity, target_value, leverage, expiration):

    problems, leverage = validate(db, source, feed_address, bet_type, deadline,
                                  wager_quantity, counterwager_quantity,
                                  target_value, leverage, expiration,
                                  util.last_block(db)['block_index'])
    if util.date_passed(deadline):
        problems.append('deadline passed')
    if problems: raise exceptions.ComposeError(problems)

    data = struct.pack(config.TXTYPE_FORMAT, ID)
    data += struct.pack(FORMAT, bet_type, deadline, wager_quantity,
                        counterwager_quantity, target_value, leverage,
                        expiration)
    return (source, [(feed_address, None)], data)
예제 #9
0
def compose(db, source, timestamp, value, fee_fraction, text):

    # Store the fee fraction as an integer.
    fee_fraction_int = int(fee_fraction * 1e8)

    problems = validate(db, source, timestamp, value, fee_fraction_int, text,
                        util.last_block(db)['block_index'])
    if problems: raise exceptions.ComposeError(problems)

    data = struct.pack(config.TXTYPE_FORMAT, ID)
    if len(text) <= 52:
        curr_format = FORMAT + '{}p'.format(len(text) + 1)
    else:
        curr_format = FORMAT + '{}s'.format(len(text))
    data += struct.pack(curr_format, timestamp, value, fee_fraction_int,
                        text.encode('utf-8'))
    return (source, [], data)
예제 #10
0
def compose(db, source, move, random, rps_match_id):
    tx0_hash, tx1_hash = util.parse_id(rps_match_id)

    txn, rps_match, problems = validate(db, source, move, random, rps_match_id)
    if problems: raise exceptions.ComposeError(problems)

    # Warn if down to the wire.
    time_left = rps_match['match_expire_index'] - util.last_block(
        db)['block_index']
    if time_left < 4:
        logger.warning(
            'Only {} blocks until that rps match expires. The conclusion might not make into the blockchain in time.'
            .format(time_left))

    tx0_hash_bytes = binascii.unhexlify(bytes(tx0_hash, 'utf-8'))
    tx1_hash_bytes = binascii.unhexlify(bytes(tx1_hash, 'utf-8'))
    random_bytes = binascii.unhexlify(bytes(random, 'utf-8'))
    data = struct.pack(config.TXTYPE_FORMAT, ID)
    data += struct.pack(FORMAT, move, random_bytes, tx0_hash_bytes,
                        tx1_hash_bytes)
    return (source, [], data)
예제 #11
0
def compose(db, source, transfer_destination, asset, quantity, divisible,
            description):
    callable_, call_date, call_price = False, 0, 0.0
    call_date, call_price, problems, fee, description, divisible, reissuance = validate(
        db, source, transfer_destination, asset, quantity, divisible,
        callable_, call_date, call_price, description,
        util.last_block(db)['block_index'])
    if problems: raise exceptions.ComposeError(problems)

    asset_id = util.generate_asset_id(asset,
                                      util.last_block(db)['block_index'])
    data = struct.pack(config.TXTYPE_FORMAT, ID)
    if len(description) <= 42:
        curr_format = FORMAT_2 + '{}p'.format(len(description) + 1)
    else:
        curr_format = FORMAT_2 + '{}s'.format(len(description))
    data += struct.pack(curr_format, asset_id, quantity, 1 if divisible else 0,
                        1 if callable_ else 0, call_date or 0, call_price
                        or 0.0, description.encode('utf-8'))
    if transfer_destination:
        destination_outputs = [(transfer_destination, None)]
    else:
        destination_outputs = []
    return (source, destination_outputs, data)