Esempio n. 1
0
def test_saves_state_revoked(connected_clients):
    alice, bob, charlie, david, eric, fred = connected_clients
    alice.micro_send(bob.handle, 5)
    alice.sync()

    # load alice c2h_state
    connection = db.hub_connection(handle=alice.handle)
    c2h_state = db.load_channel_state(
        connection["c2h_channel_id"], connection["asset"]
    )

    # revoke c2h commit
    revoke_hashes = api.mpc_revoke_hashes_until(state=c2h_state, quantity=0)
    secrets = [lib.get_secret(h) for h in revoke_hashes]
    updated_c2h_state = api.mpc_revoke_all(state=c2h_state, secrets=secrets)
    assert len(updated_c2h_state["commits_active"]) == 0
    assert len(updated_c2h_state["commits_revoked"]) == 1

    # save updated c2h state
    db.save_channel_state(
        connection["c2h_channel_id"], updated_c2h_state,
        unnotified_revoke_secrets=secrets
    )

    # load updated c2h state
    connection = db.hub_connection(handle=alice.handle)
    saved_c2h_state = db.load_channel_state(
        connection["c2h_channel_id"], connection["asset"]
    )

    assert len(saved_c2h_state["commits_active"]) == 0
    assert len(saved_c2h_state["commits_revoked"]) == 1
    assert updated_c2h_state == saved_c2h_state
Esempio n. 2
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. 3
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. 4
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. 5
0
def _assert_states_synced(handle, c2h_state, h2c_state):
    connection = db.hub_connection(handle=handle)
    db_h2c_state = db.load_channel_state(connection["h2c_channel_id"],
                                         connection["asset"])
    db_c2h_state = db.load_channel_state(connection["c2h_channel_id"],
                                         connection["asset"])
    assert c2h_state["asset"] == db_c2h_state["asset"]
    assert h2c_state["asset"] == db_h2c_state["asset"]
    assert c2h_state["deposit_script"] == db_c2h_state["deposit_script"]
    assert h2c_state["deposit_script"] == db_h2c_state["deposit_script"]

    c2h_scripts = [x["script"] for x in c2h_state["commits_active"]]
    db_c2h_scripts = [x["script"] for x in db_c2h_state["commits_active"]]
    assert c2h_scripts == db_c2h_scripts

    h2c_scripts = [x["script"] for x in h2c_state["commits_active"]]
    db_h2c_scripts = [x["script"] for x in db_h2c_state["commits_active"]]
    assert h2c_scripts == db_h2c_scripts
Esempio n. 6
0
def _assert_states_synced(handle, c2h_state, h2c_state):
    connection = db.hub_connection(handle=handle)
    db_h2c_state = db.load_channel_state(connection["h2c_channel_id"],
                                         connection["asset"])
    db_c2h_state = db.load_channel_state(connection["c2h_channel_id"],
                                         connection["asset"])
    assert c2h_state["asset"] == db_c2h_state["asset"]
    assert h2c_state["asset"] == db_h2c_state["asset"]
    assert c2h_state["deposit_script"] == db_c2h_state["deposit_script"]
    assert h2c_state["deposit_script"] == db_h2c_state["deposit_script"]

    c2h_scripts = [x["script"] for x in c2h_state["commits_active"]]
    db_c2h_scripts = [x["script"] for x in db_c2h_state["commits_active"]]
    assert c2h_scripts == db_c2h_scripts

    h2c_scripts = [x["script"] for x in h2c_state["commits_active"]]
    db_h2c_scripts = [x["script"] for x in db_h2c_state["commits_active"]]
    assert h2c_scripts == db_h2c_scripts
Esempio n. 7
0
def _load_incomplete_connection(handle, c2h_deposit_script_hex):

    client_pubkey = scripts.get_deposit_payer_pubkey(c2h_deposit_script_hex)
    hub_pubkey = scripts.get_deposit_payee_pubkey(c2h_deposit_script_hex)
    expire_time = scripts.get_deposit_expire_time(c2h_deposit_script_hex)

    hub_conn = db.hub_connection(handle=handle)
    assert(hub_conn is not None)
    assert(not hub_conn["complete"])

    h2c = db.micropayment_channel(id=hub_conn["h2c_channel_id"])
    assert(h2c["payer_pubkey"] == hub_pubkey)
    assert(h2c["payee_pubkey"] == client_pubkey)

    c2h = db.micropayment_channel(id=hub_conn["c2h_channel_id"])
    assert(c2h["payer_pubkey"] == client_pubkey)
    assert(c2h["payee_pubkey"] == hub_pubkey)

    hub_wif = get_wif(hub_pubkey)

    return hub_conn, h2c, expire_time, hub_wif
Esempio n. 8
0
def _load_incomplete_connection(handle, c2h_deposit_script_hex):

    client_pubkey = scripts.get_deposit_payer_pubkey(c2h_deposit_script_hex)
    hub_pubkey = scripts.get_deposit_payee_pubkey(c2h_deposit_script_hex)
    expire_time = scripts.get_deposit_expire_time(c2h_deposit_script_hex)

    hub_conn = db.hub_connection(handle=handle)
    assert (hub_conn is not None)
    assert (not hub_conn["complete"])

    h2c = db.micropayment_channel(id=hub_conn["h2c_channel_id"])
    assert (h2c["payer_pubkey"] == hub_pubkey)
    assert (h2c["payee_pubkey"] == client_pubkey)

    c2h = db.micropayment_channel(id=hub_conn["c2h_channel_id"])
    assert (c2h["payer_pubkey"] == client_pubkey)
    assert (c2h["payee_pubkey"] == hub_pubkey)

    hub_key = db.key(pubkey=hub_pubkey)

    return hub_conn, h2c, expire_time, hub_key
Esempio n. 9
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. 10
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,
    }
Esempio n. 11
0
def hub_connection(handle):
    validate.is_hex(handle)
    connection = db.hub_connection(handle=handle)
    if not connection:
        raise err.HandleNotFound(handle)
    return connection
Esempio n. 12
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,
    }
Esempio n. 13
0
def hub_connection(handle):
    validate.is_hex(handle)
    connection = db.hub_connection(handle=handle)
    if not connection:
        raise err.HandleNotFound(handle)
    return connection