Ejemplo n.º 1
0
def test_simulation_xcp():

    # fund server
    for i in range(2):
        address = lib.get_funding_addresses([ASSET])[ASSET]
        rawtx = api.create_send(**{
            'source': FUNDING_ADDRESS,
            'destination': address,
            'asset': ASSET,
            'quantity': 1000000,
            'regular_dust_size': 1000000
        })
        api.sendrawtransaction(tx_hex=rawtx)

    # connect clients
    clients = []
    for i in range(2):
        bob_wif = util.gen_funded_wif(ASSET, 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=bob_wif))
        txid = client.connect(1000000, 65535, asset=ASSET)
        assert txid is not None

        status = client.get_status()
        assert status["send_balance"] == 1000000
        assert status["send_deposit_ttl"] is not None
        assert status["recv_deposit_ttl"] is None  # hub deposit not yet made

        clients.append(client)

    # server funds deposits
    cron.run_all()
    for client in clients:
        status = client.get_status()
        assert status["recv_deposit_ttl"] is not None  # hub deposit now made
Ejemplo n.º 2
0
def connect(asset, quantity, expire_time=1024, delay_time=2):
    """ Create micropayment connection with hub.

    Args:
        asset (str): Asset to exchange in connection.
        quantity (str): Quantity to be bound in the deposit, this determins
                        the maximum amount that can bet transferred.
        expire_time (int, default=1024): Time in blocks after which the
                                         deposit expires and can be recovered.
        delay_time (int, default=2): Blocks hub must wait before payout,
                                     protects against publish revoked commits.

    Returns:
        {
            "send_deposit_txid": "published bitcoin transaction id",
            "handle": "handle for created connection"
        }
    """

    # connect to hub
    client = Mph(_hub_api())
    send_deposit_txid = client.connect(quantity,
                                       expire_time=expire_time,
                                       asset=asset,
                                       delay_time=delay_time)

    # save to data
    data = _load_data()
    data["connections"][client.handle] = client.serialize()
    _save_data(data)

    return {"send_deposit_txid": send_deposit_txid, "handle": client.handle}
Ejemplo n.º 3
0
def test_hub_lacks_funds(server_db):
    try:
        auth_wif = util.gen_funded_wif("XCP", 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=auth_wif))
        client.connect(1000000, 65535, asset="XCP")
        cron.fund_deposits()
        assert False
    except err.InsufficientFunds:
        assert True
def test_serialization():
    auth_wif = util.gen_funded_wif("XCP", 1000000, 1000000)

    hub_api = util.MockAPI(auth_wif=auth_wif)
    client_alpha = Mph(hub_api)
    serialized_alpha = client_alpha.serialize()

    client_beta = Mph.deserialize(api=hub_api, data=serialized_alpha)
    serialized_beta = client_beta.serialize()

    assert serialized_alpha == serialized_beta
Ejemplo n.º 5
0
def sync(handle=None):
    """ Sync payments and recover funds from closed connections.

    This WILL cost a fee per channnel synced as defined in the hub terms.

    * Synchronize open connections to send/receive payments.
    * Recover funds of closed connections.

    Args:
        handle (str, default=None): Optionally limit to given handle.

    Returns:
        {
          "connection handle": {
            "rawtxs": ["of transactions publish while recovering funds"],
            "received_payments": [
              {
                "payer_handle": "sender handle",
                "amount": 1337,
                "token": "provided by sender"
              }
            ]
          }
        }
    """
    result = {}
    hub_api = _hub_api()
    data = _load_data()
    for _handle, connection_data in copy.deepcopy(data)["connections"].items():
        if handle is not None and _handle != handle:
            continue
        client = Mph.deserialize(hub_api, connection_data)
        if client.can_cull():
            continue  # dont sync closed inactive
        status = client.get_status()

        # sync open connections
        if status["status"] == "open":
            result[_handle] = {
                "rawtxs": [],
                "received_payments": client.sync()
            }

        # update closed connections
        elif status["status"] == "closed":
            result[_handle] = {
                "rawtxs": client.update(),
                "received_payments": []
            }

        data["connections"][client.handle] = client.serialize()

    _save_data(data)
    return result
Ejemplo n.º 6
0
def status(handle=None, verbose=False):
    """ Get status of connections and wallet.

    Args:
        handle (str, default=None): Optionally limit to given handle.
        verbose (bool, default=False): Optionally show additional information.

    Returns:
        {
          "connections": {
            "a0b206d1f68edb1aa24084752b5693a9022349dc547fb9952aa510003e93": {
              "asset": "XCP",
              "balance": 31337,
              "status": "open",
              "ttl": 404
            }
          },
          "wallet": {
            "address": "n2WQGAvnDS1vf7uXToLou6kLxJXRGFHo2b",
            "balances": {
              "BTC": 926109330,
              "XCP": 140982404156
            }
          }
        }
    """
    data = _load_data()
    hub_api = _hub_api()
    result = {
        "connections": {},
        "wallet": {
            "address": keys.address_from_wif(load_wif()),
            "balances": balances()
        }
    }
    for _handle, connection_data in data["connections"].items():
        if handle is not None and _handle != handle:
            continue
        client = Mph.deserialize(hub_api, connection_data)
        status = client.get_status()
        if verbose:
            status["data"] = connection_data
            result["connections"][_handle] = status
        else:
            result["connections"][_handle] = {
                "asset": status["asset"],
                "balance": status["balance"],
                "ttl": status["ttl"],
                "status": status["status"],
                "payments_queued": connection_data["payments_queued"]
            }
    return result
Ejemplo n.º 7
0
def connect(asset, quantity, expire_time=1024, delay_time=2):
    """ Create micropayment connection with hub.

    Args:
        asset (str): Asset to exchange in connection.
        quantity (str): Quantity to be bound in the deposit, this determins
                        the maximum amount that can bet transferred.
        expire_time (int, default=1024): Time in blocks after which the
                                         deposit expires and can be recovered.
        delay_time (int, default=2): Blocks hub must wait before payout,
                                     protects against publish revoked commits.

    Returns:
        {
            "send_deposit_txid": "published bitcoin transaction id",
            "handle": "handle for created connection"
        }
    """

    # check if funds available
    _status = status()
    _quantity = _status["wallet"]["balances"].get(asset, 0)
    err_msg = "Insufficient {0}: {1} required, {2} available!"
    assert _quantity > quantity, err_msg.format(asset, quantity, _quantity)

    # connect to hub
    client = Mph(_hub_api())
    send_deposit_txid = client.connect(quantity, expire_time=expire_time,
                                       asset=asset, delay_time=delay_time)

    # save to data
    data = _load_data()
    data["connections"][client.handle] = client.serialize()
    _save_data(data)

    return {
        "send_deposit_txid": send_deposit_txid,
        "handle": client.handle
    }
Ejemplo n.º 8
0
def connected_clients():

    # create asset
    unsigned_rawtx = api.create_issuance(
        source=FUNDING_ADDRESS,
        asset="A7736697071037023001",
        quantity=100000000
    )
    signed_rawtx = scripts.sign_deposit(
        get_txs, FUNDING_WIF, unsigned_rawtx
    )
    api.sendrawtransaction(tx_hex=signed_rawtx)

    # fund server
    for i in range(3):
        address = lib.get_funding_address()
        for asset in ["XCP", "A7736697071037023001"]:
            unsigned_rawtx = api.create_send(**{
                'source': FUNDING_ADDRESS,
                'destination': address,
                'asset': asset,
                'quantity': 1000000,
                'regular_dust_size': 1000000
            })
            signed_rawtx = scripts.sign_deposit(
                get_txs, FUNDING_WIF, unsigned_rawtx
            )
            api.sendrawtransaction(tx_hex=signed_rawtx)

    # connect clients
    clients = []

    # fund XCP clients
    for i in range(3):
        wif = util.gen_funded_wif("XCP", 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=wif))
        client.connect(1000000, expire_time=42, asset="XCP")
        clients.append(client)

    # fund A7736697071037023001 clients
    for i in range(3):
        wif = util.gen_funded_wif("A7736697071037023001", 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=wif))
        client.connect(1000000, expire_time=42, asset="A7736697071037023001")
        clients.append(client)

    cron.fund_deposits()

    return clients
Ejemplo n.º 9
0
def test_simulation_xcp():

    # fund server
    for i in range(2):
        address = lib.get_funding_address()
        unsigned_rawtx = api.create_send(**{
            'source': FUNDING_ADDRESS,
            'destination': address,
            'asset': ASSET,
            'quantity': 1000000,
            'regular_dust_size': 1000000
        })
        signed_rawtx = scripts.sign_deposit(
            get_txs, FUNDING_WIF, unsigned_rawtx)
        api.sendrawtransaction(tx_hex=signed_rawtx)

    # connect clients
    clients = []
    for i in range(2):
        bob_wif = util.gen_funded_wif(ASSET, 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=bob_wif))
        txid = client.connect(1000000, 65535, asset=ASSET)
        assert txid is not None

        status = client.get_status()
        assert status["send_balance"] == 1000000
        assert status["send_deposit_ttl"] is not None
        assert status["recv_deposit_ttl"] is None  # hub deposit not yet made

        clients.append(client)

    # server funds deposits
    cron.run_all()
    for client in clients:
        status = client.get_status()
        assert status["recv_deposit_ttl"] is not None  # hub deposit now made
Ejemplo n.º 10
0
def close(handle):
    """ Close open connection and settle to blockchain.

    Args:
        handle (str): Handle of connection to close.

    Returns:
        Commit txid or None if no assets received from hub.
    """
    hub_api = _hub_api()
    data = _load_data()
    client = Mph.deserialize(hub_api, data["connections"][handle])
    commit_txid = client.close()
    # FIXME recover now if possible
    data["connections"][handle] = client.serialize()
    _save_data(data)
    return commit_txid
Ejemplo n.º 11
0
def connected_clients():

    # create asset
    rawtx = api.create_issuance(source=FUNDING_ADDRESS,
                                asset="A7736697071037023001",
                                quantity=100000000)
    api.sendrawtransaction(tx_hex=rawtx)

    # fund server
    for i in range(3):
        addresses = lib.get_funding_addresses(["XCP", "A7736697071037023001"])
        for asset, address in addresses.items():
            rawtx = api.create_send(
                **{
                    'source': FUNDING_ADDRESS,
                    'destination': address,
                    'asset': asset,
                    'quantity': 1000000,
                    'regular_dust_size': 1000000
                })
            api.sendrawtransaction(tx_hex=rawtx)

    # connect clients
    clients = []

    # fund XCP clients
    for i in range(3):
        bob_wif = util.gen_funded_wif("XCP", 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=bob_wif))
        client.connect(1000000, 42, asset="XCP")
        clients.append(client)

    # fund A7736697071037023001 clients
    for i in range(3):
        bob_wif = util.gen_funded_wif("A7736697071037023001", 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=bob_wif))
        client.connect(1000000, 42, asset="A7736697071037023001")
        clients.append(client)

    cron.fund_deposits()

    return clients
Ejemplo n.º 12
0
def queuepayment(source, destination, quantity, token=None):
    """ Queue micropayment channel send (sent on sync).

    Args:
        source (str): Handle of connection to send funds from.
        destination (str): Handle of connection to receive funds.
        quantity (int): Quantity of channel asset to transfer.
        token (str, default=None): Optional token payee will
                                   receive with the payment.

    Returns:
        Provided token or generated token if None given.
    """
    hub_api = _hub_api()
    data = _load_data()
    client = Mph.deserialize(hub_api, data["connections"][source])
    # FIXME check dest can receive payment
    result = client.micro_send(destination, quantity, token=token)
    data["connections"][source] = client.serialize()
    _save_data(data)
    return result
Ejemplo n.º 13
0
def cull(handle=None):
    """ Removes closed channels if all funds have been recovered.

    Args:
        handle (str): Optional handle of specific connection to be cull.

    Returns:
        List of with handles of culled connections.
    """
    data = _load_data()
    hub_api = _hub_api()
    culled = []
    for _handle, connection_data in copy.deepcopy(data)["connections"].items():
        if handle is not None and _handle != handle:
            continue
        client = Mph.deserialize(hub_api, connection_data)
        if client.can_cull():
            culled.append(_handle)
            del data["connections"][_handle]
    _save_data(data)
    return culled
Ejemplo n.º 14
0
def test_standard_usage(server_db):

    # fund server
    for i in range(4):
        address = lib.get_funding_address()
        unsigned_rawtx = api.create_send(**{
            'source': FUNDING_ADDRESS,
            'destination': address,
            'asset': ASSET,
            'quantity': 1000000,
            'regular_dust_size': 1000000
        })
        signed_rawtx = scripts.sign_deposit(
            get_txs, FUNDING_WIF, unsigned_rawtx
        )
        api.sendrawtransaction(tx_hex=signed_rawtx)

    # connect clients
    status = api.mph_status()
    assert len(status["connections"]) == 0
    clients = []
    for i in range(4):
        auth_wif = util.gen_funded_wif(ASSET, 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=auth_wif))
        txid = client.connect(1000000, 42, asset=ASSET)
        assert txid is not None

        status = client.get_status()
        assert status["send_balance"] == 1000000
        assert status["send_deposit_ttl"] is not None
        assert status["recv_deposit_ttl"] is None  # hub deposit not yet made
        clients.append(client)
    assert len(api.mph_status()["connections"]) == 4

    # server funds deposits
    assert len(cron.fund_deposits()) == 4
    assert len(cron.fund_deposits()) == 0
    for client in clients:
        status = client.get_status()
        assert status["recv_deposit_ttl"] is not None  # hub deposit now made

    # before status
    alpha, beta, gamma, delta = clients
    alpha_before_status = alpha.get_status()
    beta_before_status = beta.get_status()
    gamma_before_status = gamma.get_status()

    # can send multiple payments
    alpha.micro_send(beta.handle, 5, "0000")
    alpha.micro_send(gamma.handle, 6, "0001")
    assert alpha.sync() == []
    assert beta.sync() == [{
        "payer_handle": alpha.handle,
        "amount": 5,
        "token": "0000"
    }]
    assert gamma.sync(), [{
        "payer_handle": alpha.handle,
        "amount": 6,
        "token": "0001"
    }]

    # send more back, commits are revoked to maximize liquidity
    beta.micro_send(alpha.handle, 42, "0003")
    assert beta.sync() == []
    assert alpha.sync() == [{
        "payer_handle": beta.handle,
        "amount": 42,
        "token": "0003"
    }]

    # multiple syncs/commtis from single client
    alpha.micro_send(beta.handle, 1, "0004")
    assert alpha.sync() == []

    # get after status
    alpha_after_status = alpha.get_status()
    beta_after_status = beta.get_status()
    gamma_after_status = gamma.get_status()

    # compare statuses
    alpha_after_status["send_balance"] == alpha_before_status[
        "send_balance"] + 27
    beta_after_status["send_balance"] == beta_before_status[
        "send_balance"] - 40
    gamma_after_status["send_balance"] == gamma_before_status[
        "send_balance"] + 5

    # client | c2h active | h2c active
    # -------+------------+-----------
    # alpha  | 1 commit   | 1 commit
    # beta   | 1 commit   | 0 commit
    # gamma  | 0 commit   | 1 commit
    # delta  | 0 commit   | 0 commit
    assert len(alpha.c2h_state["commits_active"]) == 1
    assert len(alpha.h2c_state["commits_active"]) == 1
    assert len(beta.c2h_state["commits_active"]) == 1
    assert len(beta.h2c_state["commits_active"]) == 0
    assert len(gamma.c2h_state["commits_active"]) == 0
    assert len(gamma.h2c_state["commits_active"]) == 1
    assert len(delta.c2h_state["commits_active"]) == 0
    assert len(delta.h2c_state["commits_active"]) == 0

    # close alpha payment channel
    #        | h2c | c2h |
    # -------+-----+-----+
    # commit |  X  |  X  |
    # payout |  X  |  X  |
    # change |  X  |  X  |
    assert len(api.mph_status()["connections"]) == 4
    assert alpha.close() is not None        # H2C COMMIT TX
    assert len(api.mph_status()["connections"]) == 3
    assert _check_rawtxs(alpha.update())  # h2c payout delay not yet passed
    util_test.create_next_block(server_db)  # let payout delay pass
    assert _check_rawtxs(alpha.update(), payout=1)  # H2C PAYOUT TX

    # H2C CHANGE TX, C2H COMMIT TX
    assert _check_rawtxs(cron.run_all(), change=1, commit=1)

    util_test.create_next_block(server_db)  # let c2h payout delay pass
    assert _check_rawtxs(cron.run_all(), payout=1)  # C2H PAYOUT TX
    assert _check_rawtxs(alpha.update(), change=1)  # C2H CHANGE TX

    # close beta payment channel
    # recover | h2c | c2h |
    # --------+-----+-----+
    # commit  |  -  |  X  |
    # payout  |  -  |  X  |
    # change  |  X  |  X  |
    assert len(api.mph_status()["connections"]) == 3
    assert beta.close() is None
    assert len(api.mph_status()["connections"]) == 2
    # H2C CHANGE TX, C2H COMMIT TX
    assert _check_rawtxs(cron.run_all(), change=1, commit=1)
    util_test.create_next_block(server_db)  # let payout delay pass
    assert _check_rawtxs(cron.run_all(), payout=1)  # C2H PAYOUT TX
    assert _check_rawtxs(beta.update(), change=1)  # C2H CHANGE TX

    # close gamma payment channel
    # recover | h2c | c2h |
    # --------+-----+-----+
    # commit  |  X  |  -  |
    # payout  |  X  |  -  |
    # change  |  X  |  X  |
    assert len(api.mph_status()["connections"]) == 2
    assert gamma.close() is not None        # H2C COMMIT TX
    assert len(api.mph_status()["connections"]) == 1
    assert _check_rawtxs(gamma.update(), change=1)  # C2H CHANGE TX
    assert _check_rawtxs(gamma.update(), payout=1)  # H2C PAYOUT TX
    assert _check_rawtxs(cron.run_all(), change=1)  # H2C CHANGE TX

    # close delta payment channel
    # recover | h2c | c2h |
    # --------+-----+-----+
    # commit  |  -  |  -  |
    # payout  |  -  |  -  |
    # change  |  X  |  X  |
    assert len(api.mph_status()["connections"]) == 1
    assert delta.close() is None
    assert len(api.mph_status()["connections"]) == 0
    assert _check_rawtxs(delta.update(), change=1)  # C2H CHANGE TX
    assert _check_rawtxs(cron.run_all(), change=1)  # H2C CHANGE TX

    _assert_states_synced(alpha.handle, alpha.c2h_state, alpha.h2c_state)
    _assert_states_synced(beta.handle, beta.c2h_state, beta.h2c_state)
    _assert_states_synced(gamma.handle, gamma.c2h_state, gamma.h2c_state)
    _assert_states_synced(delta.handle, delta.c2h_state, delta.h2c_state)
Ejemplo n.º 15
0
def test_user_doesnt_publish_commit(server_db):

    # fund server
    for i in range(2):
        address = lib.get_funding_address()
        unsigned_rawtx = api.create_send(**{
            'source': FUNDING_ADDRESS,
            'destination': address,
            'asset': ASSET,
            'quantity': 1000000,
            'regular_dust_size': 1000000
        })
        signed_rawtx = scripts.sign_deposit(get_txs, FUNDING_WIF,
                                            unsigned_rawtx)
        api.sendrawtransaction(tx_hex=signed_rawtx)

    # connect clients
    assert len(api.mph_status()["connections"]) == 0
    clients = []
    for i in range(2):
        auth_wif = util.gen_funded_wif(ASSET, 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=auth_wif))
        txid = client.connect(1000000, 42, asset=ASSET)
        assert txid is not None

        status = client.get_status()
        assert status["send_balance"] == 1000000
        assert status["send_deposit_ttl"] is not None
        assert status["recv_deposit_ttl"] is None  # hub deposit not yet made
        clients.append(client)
    assert len(api.mph_status()["connections"]) == 2

    # server funds deposits
    assert len(cron.fund_deposits()) == 2
    assert len(cron.fund_deposits()) == 0
    for client in clients:
        status = client.get_status()
        assert status["recv_deposit_ttl"] is not None  # hub deposit now made

    # before status
    alpha, beta = clients

    # send funds to beta
    alpha.micro_send(beta.handle, 42)
    alpha.sync()
    alpha_status = alpha.get_status()
    assert alpha_status["send_balance"] == 1000000 - 42 - 1

    # beta received funds
    beta.sync()
    beta_status = beta.get_status()
    assert beta_status["send_balance"] == 1000000 + 42 - 1

    # return some funds to alpha
    beta.micro_send(alpha.handle, 13)
    beta.sync()
    beta_status = beta.get_status()
    assert beta_status["send_balance"] == 1000000 + 42 - 1 - 13 - 1

    # alpha received funds
    alpha.sync()
    alpha_status = alpha.get_status()
    assert alpha_status["send_balance"] == 1000000 - 42 - 1 + 13 - 1

    # beta settles
    assert len(api.mph_status()["connections"]) == 2
    assert beta.close() is not None  # H2C COMMIT TX
    assert len(api.mph_status()["connections"]) == 1
    assert _check_rawtxs(beta.update())  # h2c payout delay not yet passed
    util_test.create_next_block(server_db)  # let payout delay pass
    assert _check_rawtxs(beta.update(), payout=1)  # H2C PAYOUT TX
    # H2C CHANGE TX, C2H COMMIT TX
    assert _check_rawtxs(cron.run_all(), change=1, commit=1)
    util_test.create_next_block(server_db)  # let c2h payout delay pass
    assert _check_rawtxs(cron.run_all(), payout=1)  # C2H PAYOUT TX
    assert _check_rawtxs(beta.update(), change=1)  # C2H CHANGE TX

    # let channel expire
    for i in range(50):
        util_test.create_next_block(server_db)

    # hub closes alice channel
    #        | h2c | c2h |
    # -------+-----+-----+
    # commit |  -  |  X  |
    # payout |  -  |  X  |
    # change |  -  |  -  |
    # expire |  X  |  -  |
    # C2H COMMIT TX, H2C EXPIRE TX
    assert _check_rawtxs(cron.run_all(), commit=1, expire=1)
    assert _check_rawtxs(cron.run_all(), payout=1)  # C2H PAYOUT TX
Ejemplo n.º 16
0
def test_user_doesnt_publish_commit(server_db):

    # fund server
    for i in range(2):
        address = lib.get_funding_addresses([ASSET])[ASSET]
        unsigned_rawtx = api.create_send(
            **{
                'source': FUNDING_ADDRESS,
                'destination': address,
                'asset': ASSET,
                'quantity': 1000000,
                'regular_dust_size': 1000000
            })
        signed_rawtx = scripts.sign_deposit(get_tx, FUNDING_WIF,
                                            unsigned_rawtx)
        api.sendrawtransaction(tx_hex=signed_rawtx)

    # connect clients
    assert len(api.mph_status()["connections"]) == 0
    clients = []
    for i in range(2):
        auth_wif = util.gen_funded_wif(ASSET, 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=auth_wif))
        txid = client.connect(1000000, 42, asset=ASSET)
        assert txid is not None

        status = client.get_status()
        assert status["send_balance"] == 1000000
        assert status["send_deposit_ttl"] is not None
        assert status["recv_deposit_ttl"] is None  # hub deposit not yet made
        clients.append(client)
    assert len(api.mph_status()["connections"]) == 2

    # server funds deposits
    assert len(cron.fund_deposits()) == 2
    assert len(cron.fund_deposits()) == 0
    for client in clients:
        status = client.get_status()
        assert status["recv_deposit_ttl"] is not None  # hub deposit now made

    # before status
    alpha, beta = clients

    # send funds to beta
    alpha.micro_send(beta.handle, 42)
    alpha.sync()
    alpha_status = alpha.get_status()
    assert alpha_status["send_balance"] == 1000000 - 42 - 1

    # beta received funds
    beta.sync()
    beta_status = beta.get_status()
    assert beta_status["send_balance"] == 1000000 + 42 - 1

    # return some funds to alpha
    beta.micro_send(alpha.handle, 13)
    beta.sync()
    beta_status = beta.get_status()
    assert beta_status["send_balance"] == 1000000 + 42 - 1 - 13 - 1

    # alpha received funds
    alpha.sync()
    alpha_status = alpha.get_status()
    assert alpha_status["send_balance"] == 1000000 - 42 - 1 + 13 - 1

    # beta settles
    assert len(api.mph_status()["connections"]) == 2
    assert beta.close() is not None  # H2C COMMIT TX
    assert len(api.mph_status()["connections"]) == 1
    assert _check_rawtxs(beta.update())  # h2c payout delay not yet passed
    util_test.create_next_block(server_db)  # let payout delay pass
    assert _check_rawtxs(beta.update(), payout=1)  # H2C PAYOUT TX
    # H2C CHANGE TX, C2H COMMIT TX
    assert _check_rawtxs(cron.run_all(), change=1, commit=1)
    util_test.create_next_block(server_db)  # let c2h payout delay pass
    assert _check_rawtxs(cron.run_all(), payout=1)  # C2H PAYOUT TX
    assert _check_rawtxs(beta.update(), change=1)  # C2H CHANGE TX

    # let channel expire
    for i in range(50):
        util_test.create_next_block(server_db)

    # hub closes alice channel
    #        | h2c | c2h |
    # -------+-----+-----+
    # commit |  -  |  X  |
    # payout |  -  |  X  |
    # change |  -  |  -  |
    # expire |  X  |  -  |
    # C2H COMMIT TX, H2C EXPIRE TX
    assert _check_rawtxs(cron.run_all(), commit=1, expire=1)
    assert _check_rawtxs(cron.run_all(), payout=1)  # C2H PAYOUT TX
Ejemplo n.º 17
0
def test_standard_usage(server_db):

    # fund server
    for i in range(4):
        address = lib.get_funding_addresses([ASSET])[ASSET]
        unsigned_rawtx = api.create_send(
            **{
                'source': FUNDING_ADDRESS,
                'destination': address,
                'asset': ASSET,
                'quantity': 1000000,
                'regular_dust_size': 1000000
            })
        signed_rawtx = scripts.sign_deposit(get_tx, FUNDING_WIF,
                                            unsigned_rawtx)
        api.sendrawtransaction(tx_hex=signed_rawtx)

    # connect clients
    assert len(api.mph_status()["connections"]) == 0
    clients = []
    for i in range(4):
        auth_wif = util.gen_funded_wif(ASSET, 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=auth_wif))
        txid = client.connect(1000000, 42, asset=ASSET)
        assert txid is not None

        status = client.get_status()
        assert status["send_balance"] == 1000000
        assert status["send_deposit_ttl"] is not None
        assert status["recv_deposit_ttl"] is None  # hub deposit not yet made
        clients.append(client)
    assert len(api.mph_status()["connections"]) == 4

    # server funds deposits
    assert len(cron.fund_deposits()) == 4
    assert len(cron.fund_deposits()) == 0
    for client in clients:
        status = client.get_status()
        assert status["recv_deposit_ttl"] is not None  # hub deposit now made

    # before status
    alpha, beta, gamma, delta = clients
    alpha_before_status = alpha.get_status()
    beta_before_status = beta.get_status()
    gamma_before_status = gamma.get_status()

    # can send multiple payments
    alpha.micro_send(beta.handle, 5, "0000")
    alpha.micro_send(gamma.handle, 6, "0001")
    assert alpha.sync() == []
    assert beta.sync() == [{
        "payer_handle": alpha.handle,
        "amount": 5,
        "token": "0000"
    }]
    assert gamma.sync(), [{
        "payer_handle": alpha.handle,
        "amount": 6,
        "token": "0001"
    }]

    # send more back, commits are revoked to maximize liquidity
    beta.micro_send(alpha.handle, 42, "0003")
    assert beta.sync() == []
    assert alpha.sync() == [{
        "payer_handle": beta.handle,
        "amount": 42,
        "token": "0003"
    }]

    # multiple syncs/commtis from single client
    alpha.micro_send(beta.handle, 1, "0004")
    assert alpha.sync() == []

    # get after status
    alpha_after_status = alpha.get_status()
    beta_after_status = beta.get_status()
    gamma_after_status = gamma.get_status()

    # compare statuses
    alpha_after_status[
        "send_balance"] == alpha_before_status["send_balance"] + 27
    beta_after_status[
        "send_balance"] == beta_before_status["send_balance"] - 40
    gamma_after_status[
        "send_balance"] == gamma_before_status["send_balance"] + 5

    # client | c2h active | h2c active
    # -------+------------+-----------
    # alpha  | 1 commit   | 1 commit
    # beta   | 1 commit   | 0 commit
    # gamma  | 0 commit   | 1 commit
    # delta  | 0 commit   | 0 commit
    assert len(alpha.c2h_state["commits_active"]) == 1
    assert len(alpha.h2c_state["commits_active"]) == 1
    assert len(beta.c2h_state["commits_active"]) == 1
    assert len(beta.h2c_state["commits_active"]) == 0
    assert len(gamma.c2h_state["commits_active"]) == 0
    assert len(gamma.h2c_state["commits_active"]) == 1
    assert len(delta.c2h_state["commits_active"]) == 0
    assert len(delta.h2c_state["commits_active"]) == 0

    # close alpha payment channel
    #        | h2c | c2h |
    # -------+-----+-----+
    # commit |  X  |  X  |
    # payout |  X  |  X  |
    # change |  X  |  X  |
    assert len(api.mph_status()["connections"]) == 4
    assert alpha.close() is not None  # H2C COMMIT TX
    assert len(api.mph_status()["connections"]) == 3
    assert _check_rawtxs(alpha.update())  # h2c payout delay not yet passed
    util_test.create_next_block(server_db)  # let payout delay pass
    assert _check_rawtxs(alpha.update(), payout=1)  # H2C PAYOUT TX

    # H2C CHANGE TX, C2H COMMIT TX
    assert _check_rawtxs(cron.run_all(), change=1, commit=1)

    util_test.create_next_block(server_db)  # let c2h payout delay pass
    assert _check_rawtxs(cron.run_all(), payout=1)  # C2H PAYOUT TX
    assert _check_rawtxs(alpha.update(), change=1)  # C2H CHANGE TX

    # close beta payment channel
    # recover | h2c | c2h |
    # --------+-----+-----+
    # commit  |  -  |  X  |
    # payout  |  -  |  X  |
    # change  |  X  |  X  |
    assert len(api.mph_status()["connections"]) == 3
    assert beta.close() is None
    assert len(api.mph_status()["connections"]) == 2
    # H2C CHANGE TX, C2H COMMIT TX
    assert _check_rawtxs(cron.run_all(), change=1, commit=1)
    util_test.create_next_block(server_db)  # let payout delay pass
    assert _check_rawtxs(cron.run_all(), payout=1)  # C2H PAYOUT TX
    assert _check_rawtxs(beta.update(), change=1)  # C2H CHANGE TX

    # close gamma payment channel
    # recover | h2c | c2h |
    # --------+-----+-----+
    # commit  |  X  |  -  |
    # payout  |  X  |  -  |
    # change  |  X  |  X  |
    assert len(api.mph_status()["connections"]) == 2
    assert gamma.close() is not None  # H2C COMMIT TX
    assert len(api.mph_status()["connections"]) == 1
    assert _check_rawtxs(gamma.update(), change=1)  # C2H CHANGE TX
    assert _check_rawtxs(gamma.update(), payout=1)  # H2C PAYOUT TX
    assert _check_rawtxs(cron.run_all(), change=1)  # H2C CHANGE TX

    # close delta payment channel
    # recover | h2c | c2h |
    # --------+-----+-----+
    # commit  |  -  |  -  |
    # payout  |  -  |  -  |
    # change  |  X  |  X  |
    assert len(api.mph_status()["connections"]) == 1
    assert delta.close() is None
    assert len(api.mph_status()["connections"]) == 0
    assert _check_rawtxs(delta.update(), change=1)  # C2H CHANGE TX
    assert _check_rawtxs(cron.run_all(), change=1)  # H2C CHANGE TX

    _assert_states_synced(alpha.handle, alpha.c2h_state, alpha.h2c_state)
    _assert_states_synced(beta.handle, beta.c2h_state, beta.h2c_state)
    _assert_states_synced(gamma.handle, gamma.c2h_state, gamma.h2c_state)
    _assert_states_synced(delta.handle, delta.c2h_state, delta.h2c_state)
Ejemplo n.º 18
0
def test_standard_usage(server_db):

    # fund server
    for i in range(4):
        address = lib.get_funding_address()
        unsigned_rawtx = api.create_send(
            **{
                'source': FUNDING_ADDRESS,
                'destination': address,
                'asset': ASSET,
                'quantity': 1000000,
                'regular_dust_size': 1000000
            })
        signed_rawtx = scripts.sign_deposit(get_txs, FUNDING_WIF,
                                            unsigned_rawtx)
        api.sendrawtransaction(tx_hex=signed_rawtx)

    # connect clients
    assert len(api.mph_status()["connections"]) == 0
    clients = []
    for i in range(4):
        auth_wif = util.gen_funded_wif(ASSET, 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=auth_wif))
        txid = client.connect(1000000, 42, asset=ASSET)
        assert txid is not None

        status = client.get_status()
        assert status["send_balance"] == 1000000
        assert status["send_deposit_ttl"] is not None
        assert status["recv_deposit_ttl"] is None  # hub deposit not yet made
        clients.append(client)
    assert len(api.mph_status()["connections"]) == 4

    # server funds deposits
    assert len(cron.fund_deposits()) == 4
    assert len(cron.fund_deposits()) == 0
    for client in clients:
        status = client.get_status()
        assert status["recv_deposit_ttl"] is not None  # hub deposit now made

    # before status
    alpha, beta, gamma, delta = clients
    alpha_before_status = alpha.get_status()
    beta_before_status = beta.get_status()
    gamma_before_status = gamma.get_status()

    # can send multiple payments
    alpha.micro_send(beta.handle, 5, "0000")
    alpha.micro_send(gamma.handle, 6, "0001")
    assert alpha.sync() == []
    assert beta.sync() == [{
        "payer_handle": alpha.handle,
        "amount": 5,
        "token": "0000"
    }]
    assert gamma.sync(), [{
        "payer_handle": alpha.handle,
        "amount": 6,
        "token": "0001"
    }]

    # send more back, commits are revoked to maximize liquidity
    beta.micro_send(alpha.handle, 42, "0003")
    assert beta.sync() == []
    assert alpha.sync() == [{
        "payer_handle": beta.handle,
        "amount": 42,
        "token": "0003"
    }]

    # multiple syncs/commtis from single client
    alpha.micro_send(beta.handle, 1, "0004")
    assert alpha.sync() == []

    # get after status
    alpha_after_status = alpha.get_status()
    beta_after_status = beta.get_status()
    gamma_after_status = gamma.get_status()

    # compare statuses
    alpha_after_status[
        "send_balance"] == alpha_before_status["send_balance"] + 27
    beta_after_status[
        "send_balance"] == beta_before_status["send_balance"] - 40
    gamma_after_status[
        "send_balance"] == gamma_before_status["send_balance"] + 5

    # client | c2h active | h2c active
    # -------+------------+-----------
    # alpha  | 1 commit   | 1 commit
    # beta   | 1 commit   | 0 commit
    # gamma  | 0 commit   | 1 commit
    # delta  | 0 commit   | 0 commit
    assert len(alpha.c2h_state["commits_active"]) == 1
    assert len(alpha.h2c_state["commits_active"]) == 1
    assert len(beta.c2h_state["commits_active"]) == 1
    assert len(beta.h2c_state["commits_active"]) == 0
    assert len(gamma.c2h_state["commits_active"]) == 0
    assert len(gamma.h2c_state["commits_active"]) == 1
    assert len(delta.c2h_state["commits_active"]) == 0
    assert len(delta.h2c_state["commits_active"]) == 0
Ejemplo n.º 19
0
def test_standard_usage(server_db):

    # fund server
    for i in range(4):
        address = lib.get_funding_address()
        unsigned_rawtx = api.create_send(**{
            'source': FUNDING_ADDRESS,
            'destination': address,
            'asset': ASSET,
            'quantity': 1000000,
            'regular_dust_size': 1000000
        })
        signed_rawtx = scripts.sign_deposit(
            get_txs, FUNDING_WIF, unsigned_rawtx
        )
        api.sendrawtransaction(tx_hex=signed_rawtx)

    # connect clients
    assert len(api.mph_status()["connections"]) == 0
    clients = []
    for i in range(4):
        auth_wif = util.gen_funded_wif(ASSET, 1000000, 1000000)
        client = Mph(util.MockAPI(auth_wif=auth_wif))
        txid = client.connect(1000000, 42, asset=ASSET)
        assert txid is not None

        status = client.get_status()
        assert status["send_balance"] == 1000000
        assert status["send_deposit_ttl"] is not None
        assert status["recv_deposit_ttl"] is None  # hub deposit not yet made
        clients.append(client)
    assert len(api.mph_status()["connections"]) == 4

    # server funds deposits
    assert len(cron.fund_deposits()) == 4
    assert len(cron.fund_deposits()) == 0
    for client in clients:
        status = client.get_status()
        assert status["recv_deposit_ttl"] is not None  # hub deposit now made

    # before status
    alpha, beta, gamma, delta = clients
    alpha_before_status = alpha.get_status()
    beta_before_status = beta.get_status()
    gamma_before_status = gamma.get_status()

    # can send multiple payments
    alpha.micro_send(beta.handle, 5, "0000")
    alpha.micro_send(gamma.handle, 6, "0001")
    assert alpha.sync() == []
    assert beta.sync() == [{
        "payer_handle": alpha.handle,
        "amount": 5,
        "token": "0000"
    }]
    assert gamma.sync(), [{
        "payer_handle": alpha.handle,
        "amount": 6,
        "token": "0001"
    }]

    # send more back, commits are revoked to maximize liquidity
    beta.micro_send(alpha.handle, 42, "0003")
    assert beta.sync() == []
    assert alpha.sync() == [{
        "payer_handle": beta.handle,
        "amount": 42,
        "token": "0003"
    }]

    # multiple syncs/commtis from single client
    alpha.micro_send(beta.handle, 1, "0004")
    assert alpha.sync() == []

    # get after status
    alpha_after_status = alpha.get_status()
    beta_after_status = beta.get_status()
    gamma_after_status = gamma.get_status()

    # compare statuses
    alpha_after_status["send_balance"] == alpha_before_status[
        "send_balance"] + 27
    beta_after_status["send_balance"] == beta_before_status[
        "send_balance"] - 40
    gamma_after_status["send_balance"] == gamma_before_status[
        "send_balance"] + 5

    # client | c2h active | h2c active
    # -------+------------+-----------
    # alpha  | 1 commit   | 1 commit
    # beta   | 1 commit   | 0 commit
    # gamma  | 0 commit   | 1 commit
    # delta  | 0 commit   | 0 commit
    assert len(alpha.c2h_state["commits_active"]) == 1
    assert len(alpha.h2c_state["commits_active"]) == 1
    assert len(beta.c2h_state["commits_active"]) == 1
    assert len(beta.h2c_state["commits_active"]) == 0
    assert len(gamma.c2h_state["commits_active"]) == 0
    assert len(gamma.h2c_state["commits_active"]) == 1
    assert len(delta.c2h_state["commits_active"]) == 0
    assert len(delta.h2c_state["commits_active"]) == 0