Exemplo n.º 1
0
    async def resolve_invoice_subscription(self,
                                           info,
                                           add_index=None,
                                           settle_index=None):
        try:
            if not info.context["user"].is_authenticated:
                yield Unauthenticated()
        except AttributeError as exc:
            print(exc)
            yield ServerError(
                "A server internal error (AttributeError) has occurred. :-(")

        res = LNDWallet.objects.filter(owner=info.context["user"])

        if not res:
            yield WalletInstanceNotFound()

        cfg = build_lnd_wallet_config(res.first().pk)

        channel_data = build_grpc_channel_manual(
            rpc_server="127.0.0.1",
            rpc_port=cfg.rpc_listen_port_ipv4,
            cert_path=cfg.tls_cert_path,
            macaroon_path=cfg.admin_macaroon_path,
            is_async=True)

        if channel_data.error is not None:
            yield ServerError(error_message=channel_data.error)

        try:
            stub = lnrpc.LightningStub(channel_data.channel)
            request = ln.InvoiceSubscription(
                add_index=add_index,
                settle_index=settle_index,
            )
        except Exception as exc:
            print(exc)
            yield ServerError(error_message=exc)

        try:
            async for response in stub.SubscribeInvoices(
                    request, metadata=[('macaroon', channel_data.macaroon)]):
                if not info.context["user"].is_authenticated:
                    yield Unauthenticated()
                else:
                    json_data = json.loads(MessageToJson(response))
                    invoice = InvoiceSubSuccess(LnInvoice(json_data))
                    yield invoice
        except Exception as exc:
            print(exc)
            yield ServerError(error_message=exc)
Exemplo n.º 2
0
    def _open_channel(self, rpc_server, rpc_port, cert_path, macaroon_path,
                      is_async) -> ChannelData:
        try:
            macaroon = ""
            if macaroon_path is not None:
                with open(macaroon_path, 'rb') as f:
                    macaroon_bytes = f.read()
                    macaroon = codecs.encode(macaroon_bytes, 'hex')

            rpc_url = "{}:{}".format(rpc_server, rpc_port)

            cert = open(cert_path, "rb").read()
        except FileNotFoundError as file_error:
            print(file_error)
            return ChannelData(
                channel=None,
                macaroon=None,
                error=ServerError(error_message=str(file_error)))

        try:
            if is_async:
                creds = aiogrpc.ssl_channel_credentials(cert)
                channel = aiogrpc.secure_channel(rpc_url, creds)
            else:
                creds = grpc.ssl_channel_credentials(cert)
                channel = grpc.secure_channel(rpc_url, creds)
                grpc.channel_ready_future(channel).result(timeout=2)

        except grpc.RpcError as exc:
            # pylint: disable=E1101
            print(exc)
            return ChannelData(
                channel=None,
                macaroon=None,
                error=ServerError.generic_rpc_error(exc.code(), exc.details()))
        except grpc.FutureTimeoutError as exc:
            print(exc)
            return ChannelData(
                channel=None, macaroon=None, error=WalletInstanceNotRunning())

        return ChannelData(channel=channel, macaroon=macaroon, error=None)
Exemplo n.º 3
0
def test_get_ln_wallet_status(monkeypatch: MonkeyPatch):
    channel_data = ChannelData(
        channel=object(), macaroon="macaroon_data".encode(), error=None)
    monkeypatch.setattr(
        backend.lnd.implementations.queries.get_ln_wallet_status,
        "build_grpc_channel_manual",
        lambda rpc_server, rpc_port, cert_path, macaroon_path: channel_data)

    monkeypatch.setattr(
        backend.lnd.implementations.queries.get_ln_wallet_status,
        "build_lnd_wallet_config", lambda pk: utils.fake_lnd_wallet_config())

    query = GetLnWalletStatusQuery()
    req = RequestFactory().get("/")
    req.user = AnonymousUser()
    resolve_info = utils.mock_resolve_info(req)

    query = GetLnWalletStatusQuery()
    ret = query.resolve_get_ln_wallet_status(resolve_info)

    assert isinstance(
        ret, Unauthenticated), "Should be an instance of Unauthenticated"

    # "login" a user
    req.user = mixer.blend("auth.User")
    ret = query.resolve_get_ln_wallet_status(resolve_info)
    assert isinstance(ret, WalletInstanceNotFound
                      ), "Should be an instance of WalletInstanceNotFound"

    wallet = LNDWallet()
    wallet.owner = req.user
    wallet.public_alias = "public_alias"
    wallet.name = "name"
    wallet.testnet = True
    wallet.initialized = False
    wallet.save()

    ret = query.resolve_get_ln_wallet_status(resolve_info)
    assert isinstance(
        ret, GetLnWalletStatusNotInitialized
    ), "Should be an instance of GetLnWalletStatusNotInitialized"

    wallet.initialized = True
    wallet.save()

    # Test build channel failure
    monkeypatch.setattr(
        backend.lnd.implementations.queries.get_ln_wallet_status,
        "build_grpc_channel_manual",
        lambda *args, **kwargs: utils.fake_build_grpc_channel_manual(
            ServerError(error_message="Some error occurred!")))

    ret = query.resolve_get_ln_wallet_status(resolve_info)
    assert isinstance(ret, ServerError), "Should be an instance of ServerError"

    # Test the get info request
    monkeypatch.setattr(
        backend.lnd.implementations.queries.get_ln_wallet_status,
        "build_grpc_channel_manual",
        lambda *args, **kwargs: utils.fake_build_grpc_channel_manual())

    monkeypatch.setattr(
        backend.lnd.implementations.queries.get_ln_wallet_status.lnrpc,
        "LightningStub", FakeLightningStubUnimplemented)

    monkeypatch.setattr(
        backend.lnd.implementations.queries.get_ln_wallet_status.ln,
        "GetInfoRequest", object)

    ret = query.resolve_get_ln_wallet_status(resolve_info)
    assert isinstance(ret, GetLnWalletStatusLocked
                      ), "Should be an instance of GetLnWalletStatusLocked"

    monkeypatch.setattr(
        backend.lnd.implementations.queries.get_ln_wallet_status.lnrpc,
        "LightningStub", FakeLightningStubNoError)

    ret = query.resolve_get_ln_wallet_status(resolve_info)
    assert isinstance(
        ret, GetLnWalletStatusOperational
    ), "Should be an instance of GetLnWalletStatusOperational"
Exemplo n.º 4
0
    async def resolve_open_channel_subscription(self,
                                                info,
                                                node_pubkey,
                                                local_funding_amount,
                                                push_sat,
                                                private,
                                                min_htlc_msat,
                                                min_confs,
                                                spend_unconfirmed,
                                                sat_per_byte=None,
                                                remote_csv_delay=None,
                                                target_conf=None):
        try:
            if not info.context["user"].is_authenticated:
                yield Unauthenticated()
        except AttributeError as exc:
            print(exc)
            yield ServerError(
                "A server internal error (AttributeError) has occurred. :-(")

        res = LNDWallet.objects.filter(owner=info.context["user"])

        if not res:
            yield WalletInstanceNotFound()

        cfg = build_lnd_wallet_config(res.first().pk)

        channel_data = build_grpc_channel_manual(
            rpc_server="127.0.0.1",
            rpc_port=cfg.rpc_listen_port_ipv4,
            cert_path=cfg.tls_cert_path,
            macaroon_path=cfg.admin_macaroon_path,
            is_async=True)

        if channel_data.error is not None:
            yield channel_data.error

        try:
            stub = lnrpc.LightningStub(channel_data.channel)

            request = ln.OpenChannelRequest(
                node_pubkey=codecs.decode(node_pubkey, 'hex'),
                local_funding_amount=local_funding_amount,
                push_sat=push_sat,
                target_conf=target_conf,
                sat_per_byte=sat_per_byte,
                private=private,
                min_htlc_msat=min_htlc_msat,
                remote_csv_delay=remote_csv_delay,
                min_confs=min_confs,
                # spend_unconfirmed=spend_unconfirmed
            )
        except Exception as exc:
            print(exc)
            yield ServerError(error_message=str(exc))
            return

        try:
            async for response in stub.OpenChannel(request,
                                                   metadata=[
                                                       ('macaroon',
                                                        channel_data.macaroon)
                                                   ]):
                if not info.context["user"].is_authenticated:
                    yield Unauthenticated()
                else:
                    json_data = json.loads(MessageToJson(response))

                    if "chan_pending" in json_data:
                        cp = json_data["chan_pending"]
                        txid = cp["txid"] if "txid" in cp else ""
                        output_index = cp[
                            "output_index"] if "output_index" in cp else 0

                        yield ChannelPendingUpdate(
                            channel_point=ChannelPoint(txid, output_index))
                    elif "confirmation" in json_data:
                        conf = json_data["confirmation"]
                        block_sha = conf[
                            "block_sha"] if "block_sha" in conf else ""
                        block_height = conf[
                            "block_height"] if "block_height" in conf else 0
                        num_confs_left = conf[
                            "num_confs_left"] if "num_confs_left" in conf else 0
                        yield ChannelConfirmationUpdate(
                            block_sha=block_sha,
                            block_height=block_height,
                            num_confs_left=num_confs_left)
                    elif "chan_open" in json_data:
                        co = json_data["chan_open"]["channel_point"]
                        txid = co[
                            "funding_txid_bytes"] if "funding_txid_bytes" in co else ""
                        output_index = cp[
                            "output_index"] if "output_index" in co else 0
                        yield ChannelOpenUpdate(
                            channel_point=ChannelPoint(txid, output_index))
        except RpcError as grpc_error:
            # pylint: disable=E1101
            print(grpc_error)
            print(grpc_error.details())
            yield OpenChannelError(grpc_error.details())
        except Exception as exc:
            print(exc)
            yield ServerError(error_message=exc)
Exemplo n.º 5
0
    async def resolve_close_channel_subscription(self,
                                                 info,
                                                 funding_txid,
                                                 output_index,
                                                 force,
                                                 target_conf=None,
                                                 sat_per_byte=None):
        try:
            if not info.context["user"].is_authenticated:
                yield Unauthenticated()
        except AttributeError as exc:
            print(exc)
            yield ServerError(
                "A server internal error (AttributeError) has occurred. :-(")

        res = LNDWallet.objects.filter(owner=info.context["user"])

        if not res:
            yield WalletInstanceNotFound()

        cfg = build_lnd_wallet_config(res.first().pk)

        channel_data = build_grpc_channel_manual(
            rpc_server="127.0.0.1",
            rpc_port=cfg.rpc_listen_port_ipv4,
            cert_path=cfg.tls_cert_path,
            macaroon_path=cfg.admin_macaroon_path,
            is_async=True)

        if channel_data.error is not None:
            yield channel_data.error

        try:
            stub = lnrpc.LightningStub(channel_data.channel)

            request = ln.CloseChannelRequest(
                channel_point={
                    "funding_txid_str": funding_txid,
                    "output_index": output_index
                },
                force=force,
                target_conf=target_conf,
                sat_per_byte=sat_per_byte,
            )
        except Exception as exc:
            print(exc)
            yield ServerError(error_message=str(exc))

        try:
            async for response in stub.CloseChannel(
                    request, metadata=[('macaroon', channel_data.macaroon)]):
                if not info.context["user"].is_authenticated:
                    yield Unauthenticated()
                else:
                    json_data = json.loads(MessageToJson(response))

                    if "close_pending" in json_data:
                        cp = json_data["close_pending"]
                        txid = cp["txid"] if "txid" in cp else ""
                        output_index = cp[
                            "output_index"] if "output_index" in cp else 0

                        yield ChannelClosePendingUpdate(txid=txid)
                    elif "chan_close" in json_data:
                        cc = json_data["chan_close"]
                        txid = cc[
                            "closing_txid"] if "closing_txid" in cc else ""
                        success = cc["success"] if "success" in cc else False
                        yield ChannelCloseUpdate(closing_txid=txid, success=success)
                    else:
                        msg = "Unknown update from LND: {}".format(json_data)
                        print(msg)
                        yield ServerError(error_message=msg)
        except RpcError as grpc_error:
            # pylint: disable=E1101
            print(grpc_error)
            print(grpc_error.details())
            yield CloseChannelError(grpc_error.details())
        except Exception as exc:
            print(exc)
            yield ServerError(error_message=exc)