Beispiel #1
0
def close_connections():
    """Close connections almost expired and partially closed by client."""
    with etc.database_lock:
        closed_connections = []
        cursor = sql.get_cursor()
        for hub_connection in db.hub_connections_complete(cursor=cursor):
            asset = hub_connection["asset"]
            c2h_mpc_id = hub_connection["c2h_channel_id"]
            c2h_state = db.load_channel_state(c2h_mpc_id, asset, cursor=cursor)
            h2c_mpc_id = hub_connection["h2c_channel_id"]
            h2c_state = db.load_channel_state(h2c_mpc_id, asset, cursor=cursor)

            # connection expired or  commit published
            c2h_expired = lib.is_expired(c2h_state, etc.expire_clearance)
            h2c_expired = lib.is_expired(h2c_state, etc.expire_clearance)
            commit_published = api.mpc_published_commits(state=h2c_state)
            if c2h_expired or h2c_expired or commit_published:
                db.set_connection_closed(handle=hub_connection["handle"])
                commit_txid = Mpc(api).finalize_commit(lib.get_wif, c2h_state)
                closed_connections.append({
                    "handle": hub_connection["handle"],
                    "commit_txid": commit_txid
                })
                continue

        return closed_connections
Beispiel #2
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_complete(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
Beispiel #3
0
 def test_show_connections(self):
     with etc.database_lock:
         cursor = sql.get_cursor()
         for hub_connection in db.hub_connections_complete():
             handle = hub_connection["handle"]
             data = lib.load_connection_data(handle, cursor)
             print("handle:", handle)
             print("hub deposit:", data["h2c_deposit_amount"])
             print("client deposit:", data["c2h_deposit_amount"])
Beispiel #4
0
 def test_show_connections(self):
     with etc.database_lock:
         cursor = sql.get_cursor()
         for hub_connection in db.hub_connections_complete():
             handle = hub_connection["handle"]
             data = lib.load_connection_data(handle, cursor)
             print("handle:", handle)
             print("hub deposit:", data["h2c_deposit_amount"])
             print("client deposit:", data["c2h_deposit_amount"])
Beispiel #5
0
def sync_hub_connection(handle, next_revoke_secret_hash, sends, commit,
                        revokes):

    cursor = sql.get_cursor()

    # load receive channel
    hub_connection = db.hub_connection(handle=handle, cursor=cursor)
    connection_terms = db.terms(id=hub_connection["terms_id"])
    asset = hub_connection["asset"]
    c2h_id = hub_connection["c2h_channel_id"]
    h2c_id = hub_connection["h2c_channel_id"]

    # update channels state
    update_channel_state(c2h_id, asset, commit=commit, cursor=cursor)
    update_channel_state(h2c_id, asset, revokes=revokes, cursor=cursor)

    # add sync fee payment
    sends.insert(
        0,
        {
            "payee_handle": None,  # to hub
            "amount": connection_terms["sync_fee"],
            "token": "sync_fee"
        })

    # process payments
    for payment in sends:
        process_payment(handle, cursor, payment)

    # create next spend secret
    next_revoke_secret = create_secret()

    # load unnotified
    h2c_commit = db.unnotified_commit(channel_id=h2c_id)
    c2h_revokes = db.unnotified_revokes(channel_id=c2h_id)
    receive_payments = db.unnotified_payments(payee_handle=handle)

    # save sync data
    h2c_commit_id = None
    if h2c_commit:
        h2c_commit_id = h2c_commit.pop("id")
    _save_sync_data(cursor, handle, next_revoke_secret_hash, receive_payments,
                    h2c_commit_id, c2h_revokes, c2h_id, next_revoke_secret)

    hub_key = db.channel_payer_key(id=h2c_id)
    return ({
        "receive": receive_payments,
        "commit": h2c_commit,
        "revokes": [r["revoke_secret"] for r in c2h_revokes],
        "next_revoke_secret_hash": next_revoke_secret["secret_hash"]
    }, hub_key["wif"])
Beispiel #6
0
def recover_funds():
    """Recover funds where possible"""
    with etc.database_lock:
        txs = []
        cursor = sql.get_cursor()
        for hub_connection in db.hub_connections_recoverable(cursor=cursor):
            asset = hub_connection["asset"]
            c2h_mpc_id = hub_connection["c2h_channel_id"]
            c2h_state = db.load_channel_state(c2h_mpc_id, asset, cursor=cursor)
            h2c_mpc_id = hub_connection["h2c_channel_id"]
            h2c_state = db.load_channel_state(h2c_mpc_id, asset, cursor=cursor)
            txs += Mpc(api).full_duplex_recover_funds(lib.get_wif,
                                                      lib.get_secret,
                                                      c2h_state, h2c_state)
        return txs
Beispiel #7
0
def complete_hub_connection(data, cursor=None):
    cursor = cursor or sql.get_cursor()
    cursor.execute("BEGIN TRANSACTION")
    set_next_revoke_secret_hash(
        handle=data["handle"],
        next_revoke_secret_hash=data["next_revoke_secret_hash"],
        cursor=cursor)
    sql.execute(_COMPLETE_CONNECTION, data, cursor=cursor)
    add_revoke_secret_args = {
        "secret_hash": data["secret_hash"],
        "secret_value": data["secret_value"],
        "channel_id": data["c2h_channel_id"],
    }
    sql.execute(_ADD_REVOKE_SECRET, args=add_revoke_secret_args, cursor=cursor)
    cursor.execute("COMMIT")
Beispiel #8
0
def save_channel_state(channel_id,
                       state,
                       h2c_unnotified_commit=None,
                       unnotified_revoke_secrets=None,
                       cursor=None):

    cursor = cursor or sql.get_cursor()

    # reformat state data
    commits_requested = _fmt_requested(channel_id, state["commits_requested"])
    commits_active = _fmt_active(channel_id, h2c_unnotified_commit,
                                 state["commits_active"])
    commits_revoked = _fmt_revoked(
        channel_id,
        state["commits_revoked"],
        h2c_unnotified_commit=h2c_unnotified_commit,
        unnotified_revoke_secrets=unnotified_revoke_secrets)

    # save state to db
    cursor.execute(_RM_COMMITS, {"channel_id": channel_id})
    cursor.executemany(_ADD_COMMIT_REQUESTED, commits_requested)
    cursor.executemany(_ADD_COMMIT_ACTIVE, commits_active)
    cursor.executemany(_ADD_COMMIT_REVOKED, commits_revoked)
Beispiel #9
0
def add_keys(keys, cursor=None):
    cursor = cursor or sql.get_cursor()
    cursor.execute("BEGIN TRANSACTION")
    cursor.executemany(_ADD_KEY, keys)
    cursor.execute("COMMIT")
Beispiel #10
0
def set_revokes_notified(revoke_ids, cursor=None):
    cursor = cursor or sql.get_cursor()
    cursor.executemany(_SET_REVOKE_NOTIFIED, revoke_ids)
Beispiel #11
0
def set_payments_notified(payment_ids, cursor=None):
    cursor = cursor or sql.get_cursor()
    cursor.executemany(_SET_PAYMENT_NOTIFIED, payment_ids)
Beispiel #12
0
def handles_exist(handles, cursor=None):
    args = [(handle, ) for handle in handles]
    cursor = cursor or sql.get_cursor()
    result = cursor.executemany(_HANDLE_EXISTS, args).fetchall()
    return all([r[0] for r in result])
Beispiel #13
0
def add_hub_connection(data, cursor=None):
    cursor = cursor or sql.get_cursor()
    cursor.execute("BEGIN TRANSACTION")
    sql.execute(_ADD_HUB_CONNECTION, data, cursor=cursor)
    cursor.execute("COMMIT")