Esempio n. 1
0
def close_connection(handle, h2c_spend_secret=None):

    cursor = sql.get_cursor()
    hub_connection = db.hub_connection(handle=handle, cursor=cursor)

    # save secret if given and not already known
    if h2c_spend_secret is not None:
        secret_hash = util.hash160hex(h2c_spend_secret)
        if not get_secret(secret_hash):
            db.add_secret(secret_value=h2c_spend_secret,
                          secret_hash=secret_hash,
                          cursor=cursor)

    # close connection if not already done
    if not hub_connection["closed"]:
        db.set_connection_closed(handle=handle, cursor=cursor)

    # get c2h spend secret if no commits for channel
    c2h_spend_secret = None
    c2h_state = db.load_channel_state(hub_connection["c2h_channel_id"],
                                      hub_connection["asset"],
                                      cursor=cursor)
    if len(c2h_state["commits_active"]) == 0:
        c2h_spend_secret_hash = scripts.get_deposit_spend_secret_hash(
            c2h_state["deposit_script"])
        c2h_spend_secret = get_secret(c2h_spend_secret_hash)

    hub_key = db.channel_payer_key(id=hub_connection["h2c_channel_id"])
    return ({"spend_secret": c2h_spend_secret}, hub_key["wif"])
Esempio n. 2
0
def publish_commits():
    with etc.database_lock:
        commit_rawtxs = []
        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)
            h2c_spend_secret_hash = get_deposit_spend_secret_hash(
                h2c_state["deposit_script"]
            )
            h2c_spend_secret = lib.get_secret(h2c_spend_secret_hash)
            c2h_expired = lib.is_expired(c2h_state, etc.expire_clearance)
            h2c_expired = lib.is_expired(h2c_state, etc.expire_clearance)
            expired = c2h_expired or h2c_expired
            h2c_commits_published = api.mpc_published_commits(state=h2c_state)
            closed = hub_connection["closed"] != 0

            # connection expired or commit published or spend secret known
            if expired or closed or h2c_commits_published or h2c_spend_secret:
                if not closed:
                    db.set_connection_closed(handle=hub_connection["handle"])
                rawtx = Mpc(api).finalize_commit(lib.get_wif, c2h_state)
                if rawtx:
                    commit_rawtxs.append(rawtx)

        return commit_rawtxs
Esempio n. 3
0
def close_connection(handle, h2c_spend_secret=None):

    cursor = sql.get_cursor()
    hub_connection = db.hub_connection(handle=handle, cursor=cursor)

    # save secret if given and not already known
    if h2c_spend_secret is not None:
        secret_hash = util.hash160hex(h2c_spend_secret)
        if not get_secret(secret_hash):
            db.add_secret(secret_value=h2c_spend_secret,
                          secret_hash=secret_hash, cursor=cursor)

    # close connection if not already done
    if not hub_connection["closed"]:
        db.set_connection_closed(handle=handle, cursor=cursor)

    # get c2h spend secret if no commits for channel
    c2h_spend_secret = None
    c2h_state = db.load_channel_state(hub_connection["c2h_channel_id"],
                                      hub_connection["asset"], cursor=cursor)
    if len(c2h_state["commits_active"]) == 0:
        c2h_spend_secret_hash = scripts.get_deposit_spend_secret_hash(
            c2h_state["deposit_script"]
        )
        c2h_spend_secret = get_secret(c2h_spend_secret_hash)

    hub_wif = load_wif()
    return ({"spend_secret": c2h_spend_secret}, hub_wif)
Esempio n. 4
0
def sync_hub_connection(handle, next_revoke_secret_hash, payments, commit,
                        revokes):

    cursor = sql.get_cursor()
    hub_connection = db.hub_connection(handle=handle, cursor=cursor)

    _update_channel_state(hub_connection, commit, revokes, cursor)
    _process_payments(handle, payments, hub_connection, cursor)
    _balance_channel(handle, cursor)
    next_revoke_secret = create_secret()  # create next spend secret

    # load unnotified
    c2h_id = hub_connection["c2h_channel_id"]
    h2c_id = hub_connection["h2c_channel_id"]
    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"])
Esempio n. 5
0
def publish_commits():
    with etc.database_lock:
        txids = []
        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)
            h2c_spend_secret_hash = get_deposit_spend_secret_hash(
                h2c_state["deposit_script"])
            h2c_spend_secret = lib.get_secret(h2c_spend_secret_hash)
            c2h_expired = lib.is_expired(c2h_state, etc.expire_clearance)
            h2c_expired = lib.is_expired(h2c_state, etc.expire_clearance)
            expired = c2h_expired or h2c_expired
            h2c_commits_published = api.mpc_published_commits(state=h2c_state)
            closed = hub_connection["closed"] != 0

            # connection expired or commit published or spend secret known
            if expired or closed or h2c_commits_published or h2c_spend_secret:
                if not closed:
                    db.set_connection_closed(handle=hub_connection["handle"])
                c2h_commits_published = api.mpc_published_commits(
                    state=c2h_state)
                if len(c2h_commits_published) == 0:
                    txid = Mpc(api).finalize_commit(lib.get_wif, c2h_state)
                    if txid:
                        txids.append(txid)

        return txids
Esempio n. 6
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
Esempio n. 7
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
Esempio n. 8
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):
            txs += lib.recover_funds(hub_connection, cursor=cursor)
        return txs
Esempio n. 9
0
def recover_funds():
    """Recover funds where possible"""
    with etc.database_lock:
        rawtxs = {
            "payout": {},
            "revoke": {},
            "change": {},
            "expire": {},
            "commit": {}
        }
        cursor = sql.get_cursor()
        for hub_connection in db.hub_connections_recoverable(cursor=cursor):
            result = lib.recover_funds(hub_connection, cursor=cursor)
            rawtxs = _merge_rawtxs(rawtxs, result)
        return rawtxs
Esempio n. 10
0
def recover_funds():
    """Recover funds where possible"""
    with etc.database_lock:
        rawtxs = {
            "payout": {},
            "revoke": {},
            "change": {},
            "expire": {},
            "commit": {}
        }
        cursor = sql.get_cursor()
        for hub_connection in db.hub_connections_recoverable(cursor=cursor):
            result = lib.recover_funds(hub_connection, cursor=cursor)
            rawtxs = _merge_rawtxs(rawtxs, result)
        return rawtxs
Esempio n. 11
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")
Esempio n. 12
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")
Esempio n. 13
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)
Esempio n. 14
0
def sync_hub_connection(handle, next_revoke_secret_hash,
                        payments, commit, revokes):

    cursor = sql.get_cursor()
    hub_connection = db.hub_connection(handle=handle, cursor=cursor)

    _update_channel_state(hub_connection, commit, revokes, cursor)
    _process_payments(handle, payments, hub_connection, cursor)
    _balance_channel(handle, cursor)
    next_revoke_secret = create_secret()  # create next spend secret

    # load unnotified
    c2h_id = hub_connection["c2h_channel_id"]
    h2c_id = hub_connection["h2c_channel_id"]
    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_wif = load_wif()
    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_wif
    )
Esempio n. 15
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")
Esempio n. 16
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")
Esempio n. 17
0
def set_revokes_notified(revoke_ids, cursor=None):
    cursor = cursor or sql.get_cursor()
    cursor.executemany(_SET_REVOKE_NOTIFIED, revoke_ids)
Esempio n. 18
0
def set_payments_notified(payment_ids, cursor=None):
    cursor = cursor or sql.get_cursor()
    cursor.executemany(_SET_PAYMENT_NOTIFIED, payment_ids)
Esempio n. 19
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])