Ejemplo n.º 1
0
def sync_input(handle, next_revoke_secret_hash, client_pubkey,
               payments, commit, revokes):
    connection = hub_connection(handle)
    validate.hash160(next_revoke_secret_hash)
    _channel_client(handle, client_pubkey)

    if revokes:
        jsonschema.validate(revokes, REVOKES_SCHEMA)
        # TODO check revokes match commits?

    if commit:
        jsonschema.validate(commit, COMMIT_SCHEMA)
        c2h_commit(handle, commit["rawtx"], commit["script"])

    payments = copy.deepcopy(payments) or []
    connection_terms = db.terms(id=connection["terms_id"])
    payments.insert(0, {
        "payee_handle": None,  # to hub
        "amount": connection_terms["sync_fee"],
        "token": "deadbeef"  # sync_fee
    })
    jsonschema.validate(payments, PAYMENT_SCHEMA)
    payer = _check_payment_payer(handle, payments, commit, revokes)
    for payment in payments:
        validate.is_hex(payment["token"])
        validate.is_quantity(payment["amount"])
        if payment["payee_handle"] is not None:
            validate.is_hex(payment["payee_handle"])
        _check_payment_payee(payer, payment)
Ejemplo n.º 2
0
def sync_input(handle, next_revoke_secret_hash, client_pubkey, payments,
               commit, revokes):
    connection = hub_connection(handle)
    validate.hash160(next_revoke_secret_hash)
    _channel_client(handle, client_pubkey)

    if revokes:
        jsonschema.validate(revokes, REVOKES_SCHEMA)
        # TODO check revokes match commits?

    if commit:
        jsonschema.validate(commit, COMMIT_SCHEMA)
        c2h_commit(handle, commit["rawtx"], commit["script"])

    payments = copy.deepcopy(payments) or []
    connection_terms = db.terms(id=connection["terms_id"])
    payments.insert(
        0,
        {
            "payee_handle": None,  # to hub
            "amount": connection_terms["sync_fee"],
            "token": "deadbeef"  # sync_fee
        })
    jsonschema.validate(payments, PAYMENT_SCHEMA)
    payer = _check_payment_payer(handle, payments, commit, revokes)
    for payment in payments:
        validate.is_hex(payment["token"])
        validate.is_quantity(payment["amount"])
        if payment["payee_handle"] is not None:
            validate.is_hex(payment["payee_handle"])
        _check_payment_payee(payer, payment)
Ejemplo n.º 3
0
def fund_deposits():
    """Fund or top off open channels."""
    with etc.database_lock:
        deposits = []
        cursor = sql.get_cursor()
        for hub_connection in db.hub_connections_open(cursor=cursor):

            asset = hub_connection["asset"]
            terms = db.terms(id=hub_connection["terms_id"], cursor=cursor)

            # load client to hub data
            c2h_mpc_id = hub_connection["c2h_channel_id"]
            c2h_state = db.load_channel_state(c2h_mpc_id, asset, cursor=cursor)
            c2h_deposit_address = lib.deposit_address(c2h_state)
            c2h_deposit_balance = lib.get_balances(c2h_deposit_address,
                                                   assets=[asset])[asset]

            if c2h_deposit_balance < terms["deposit_min"]:
                continue  # ignore if client deposit insufficient
            if lib.is_expired(c2h_state, etc.expire_clearance):
                continue  # ignore if expires soon
            if lib.has_unconfirmed_transactions(c2h_deposit_address):
                continue  # ignore if unconfirmed transaction inputs/outputs
            if api.mpc_published_commits(state=c2h_state):
                continue  # ignore if c2h commit published

            # load hub to client data
            h2c_mpc_id = hub_connection["h2c_channel_id"]
            h2c_state = db.load_channel_state(h2c_mpc_id, asset, cursor=cursor)
            h2c_deposit_address = lib.deposit_address(h2c_state)
            h2c_deposit_balance = lib.get_balances(h2c_deposit_address,
                                                   assets=[asset])[asset]

            if lib.is_expired(h2c_state, etc.expire_clearance):
                continue  # ignore if expires soon
            if lib.has_unconfirmed_transactions(h2c_deposit_address):
                continue  # ignore if unconfirmed transaction inputs/outputs
            if api.mpc_published_commits(state=h2c_state):
                continue  # ignore if h2c commit published

            # fund hub to client if needed
            deposit_max = terms["deposit_max"]
            deposit_ratio = terms["deposit_ratio"]
            if deposit_max:
                target = min(deposit_max, c2h_deposit_balance) * deposit_ratio
            else:
                target = int(c2h_deposit_balance * deposit_ratio)
            quantity = target - h2c_deposit_balance
            if quantity > 0:
                txid = lib.send_funds(h2c_deposit_address, asset, quantity)
                deposits.append({
                    "txid": txid,
                    "asset": asset,
                    "address": h2c_deposit_address,
                    "quantity": quantity,
                    "handle": hub_connection["handle"]
                })

        return deposits
Ejemplo n.º 4
0
def fund_deposits():
    """Fund or top off open channels."""
    with etc.database_lock:
        deposits = []
        cursor = sql.get_cursor()
        for hub_connection in db.hub_connections_open(cursor=cursor):

            asset = hub_connection["asset"]
            terms = db.terms(id=hub_connection["terms_id"], cursor=cursor)

            # load client to hub data
            c2h_mpc_id = hub_connection["c2h_channel_id"]
            c2h_state = db.load_channel_state(c2h_mpc_id, asset, cursor=cursor)
            c2h_deposit_address = lib.deposit_address(c2h_state)
            c2h_deposit_balance = lib.get_balances(c2h_deposit_address,
                                                   assets=[asset])[asset]

            if c2h_deposit_balance < terms["deposit_min"]:
                continue  # ignore if client deposit insufficient
            if lib.is_expired(c2h_state, etc.expire_clearance):
                continue  # ignore if expires soon
            if lib.has_unconfirmed_transactions(c2h_deposit_address):
                continue  # ignore if unconfirmed transaction inputs/outputs
            if api.mpc_published_commits(state=c2h_state):
                continue  # ignore if c2h commit published

            # load hub to client data
            h2c_mpc_id = hub_connection["h2c_channel_id"]
            h2c_state = db.load_channel_state(h2c_mpc_id, asset, cursor=cursor)
            h2c_deposit_address = lib.deposit_address(h2c_state)
            h2c_deposit_balance = lib.get_balances(h2c_deposit_address,
                                                   assets=[asset])[asset]

            if lib.is_expired(h2c_state, etc.expire_clearance):
                continue  # ignore if expires soon
            if lib.has_unconfirmed_transactions(h2c_deposit_address):
                continue  # ignore if unconfirmed transaction inputs/outputs
            if api.mpc_published_commits(state=h2c_state):
                continue  # ignore if h2c commit published

            # fund hub to client if needed
            deposit_max = terms["deposit_max"]
            deposit_ratio = terms["deposit_ratio"]
            if deposit_max:
                target = min(deposit_max, c2h_deposit_balance) * deposit_ratio
            else:
                target = int(c2h_deposit_balance * deposit_ratio)
            quantity = target - h2c_deposit_balance
            if quantity > 0:
                txid = lib.send_funds(h2c_deposit_address, asset, quantity)
                deposits.append({
                    "txid": txid,
                    "asset": asset,
                    "address": h2c_deposit_address,
                    "quantity": quantity,
                    "handle": hub_connection["handle"]
                })

        return deposits
Ejemplo n.º 5
0
def _process_payments(payer_handle, payments, hub_connection, cursor):

    # add sync fee payment
    connection_terms = db.terms(id=hub_connection["terms_id"])
    payments.insert(0, {
        "payee_handle": None,  # to hub
        "amount": connection_terms["sync_fee"],
        "token": "sync_fee"
    })

    # process payments
    for payment in payments:
        payment["payer_handle"] = payer_handle
        db.add_payment(cursor=cursor, **payment)
Ejemplo n.º 6
0
def _process_payments(payer_handle, payments, hub_connection, cursor):

    # add sync fee payment
    connection_terms = db.terms(id=hub_connection["terms_id"])
    payments.insert(
        0,
        {
            "payee_handle": None,  # to hub
            "amount": connection_terms["sync_fee"],
            "token": "sync_fee"
        })

    # process payments
    for payment in payments:
        payment["payer_handle"] = payer_handle
        db.add_payment(cursor=cursor, **payment)
Ejemplo n.º 7
0
def load_connection_data(handle, new_c2h_commit=None,
                         new_h2c_revokes=None, cursor=None):
    from picopayments_hub import api
    # TODO this is getting dangerous, used in lib and verify, split it up!

    # connection data
    connection = db.hub_connection(handle=handle, cursor=cursor)
    if not connection:
        raise err.HandleNotFound(handle)
    asset = connection["asset"]
    terms = db.terms(id=connection["terms_id"], cursor=cursor)

    # h2c data
    h2c_state = db.load_channel_state(
        connection["h2c_channel_id"], connection["asset"], cursor=cursor
    )
    if new_h2c_revokes is not None:
        h2c_state = api.mpc_revoke_all(state=h2c_state,
                                       secrets=new_h2c_revokes)
    h2c_deposit_address = deposit_address(h2c_state)
    h2c_transferred = get_transferred_quantity(h2c_state)
    h2c_deposit = get_balances(h2c_deposit_address, [asset])[asset]

    # TODO remove now impossable unnotified commit?
    h2c_unnotified_commit = db.unnotified_commit(
        channel_id=connection["h2c_channel_id"], cursor=cursor
    )

    # c2h data
    c2h_state = db.load_channel_state(
        connection["c2h_channel_id"], connection["asset"], cursor=cursor
    )
    if new_c2h_commit is not None:
        c2h_state = api.mpc_add_commit(
            state=c2h_state,
            commit_rawtx=new_c2h_commit["rawtx"],
            commit_script=new_c2h_commit["script"]
        )
    c2h_transferred = get_transferred_quantity(c2h_state)

    # payments
    send_payments_sum = db.send_payments_sum(handle=handle, cursor=cursor)
    recv_payments_sum = db.recv_payments_sum(handle=handle, cursor=cursor)
    payments_sum = recv_payments_sum - send_payments_sum

    # sendable (what this channel can send to another)
    sendable_amount = c2h_transferred + payments_sum - h2c_transferred
    assert sendable_amount >= 0

    # receivable (what this channel can receive from another)
    receivable_amount = h2c_deposit + c2h_transferred - payments_sum
    assert receivable_amount >= 0

    return {
        "connection": connection,
        "h2c_state": h2c_state,
        "h2c_expired": is_expired(h2c_state, etc.expire_clearance),
        "c2h_state": c2h_state,
        "c2h_expired": is_expired(c2h_state, etc.expire_clearance),
        "h2c_unnotified_commit": h2c_unnotified_commit,
        "sendable_amount": sendable_amount,
        "receivable_amount": receivable_amount,
        "terms": terms,
    }
Ejemplo n.º 8
0
def load_connection_data(handle,
                         new_c2h_commit=None,
                         new_h2c_revokes=None,
                         cursor=None):
    from picopayments_hub import api
    # FIXME this is getting dangerous, used in lib and verify, split it up!

    # connection data
    connection = db.hub_connection(handle=handle, cursor=cursor)
    if not connection:
        raise err.HandleNotFound(handle)
    asset = connection["asset"]
    terms = db.terms(id=connection["terms_id"], cursor=cursor)

    # h2c data
    h2c_state = db.load_channel_state(connection["h2c_channel_id"],
                                      connection["asset"],
                                      cursor=cursor)
    if new_h2c_revokes is not None:
        h2c_state = api.mpc_revoke_all(state=h2c_state,
                                       secrets=new_h2c_revokes)
    h2c_deposit_address = deposit_address(h2c_state)
    h2c_transferred = get_transferred_quantity(h2c_state)
    h2c_deposit = get_balances(h2c_deposit_address, [asset])[asset]
    h2c_unnotified_commit = db.unnotified_commit(
        channel_id=connection["h2c_channel_id"], cursor=cursor)

    # c2h data
    c2h_state = db.load_channel_state(connection["c2h_channel_id"],
                                      connection["asset"],
                                      cursor=cursor)
    if new_c2h_commit is not None:
        c2h_state = api.mpc_add_commit(state=c2h_state,
                                       commit_rawtx=new_c2h_commit["rawtx"],
                                       commit_script=new_c2h_commit["script"])
    c2h_transferred = get_transferred_quantity(c2h_state)

    # payments
    send_payments_sum = db.send_payments_sum(handle=handle, cursor=cursor)
    recv_payments_sum = db.recv_payments_sum(handle=handle, cursor=cursor)
    payments_sum = recv_payments_sum - send_payments_sum

    # sendable (what this channel can send to another)
    sendable_amount = c2h_transferred + payments_sum - h2c_transferred
    assert sendable_amount >= 0

    # receivable (what this channel can receive from another)
    receivable_amount = h2c_deposit + c2h_transferred - payments_sum
    assert receivable_amount >= 0

    return {
        "connection": connection,
        "h2c_state": h2c_state,
        "h2c_expired": is_expired(h2c_state, etc.expire_clearance),
        "c2h_state": c2h_state,
        "c2h_expired": is_expired(c2h_state, etc.expire_clearance),
        "h2c_unnotified_commit": h2c_unnotified_commit,  # FIXME remove
        "sendable_amount": sendable_amount,
        "receivable_amount": receivable_amount,
        "terms": terms,
    }