Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mega-merge 3: CLN update client lib with descriptionhash support #792

Merged
merged 71 commits into from
Aug 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
b7a2e4d
CoreLightningWallet
callebtc Jul 27, 2022
d093a09
cln.py
callebtc Jul 27, 2022
7e60b95
deschash
callebtc Jul 27, 2022
4284524
cln error handling
callebtc Jul 27, 2022
c943634
add pyln-client
callebtc Jul 27, 2022
c7d1ae4
format
callebtc Jul 27, 2022
e9a142b
gitignore: add Nix ignores
MatthewCroughan Jul 8, 2022
b086981
Add Poetry as a build system
MatthewCroughan Jul 8, 2022
f4320a2
lnbits/server.py: init
MatthewCroughan Jul 8, 2022
d1e89b6
treewide: use StaticFiles() rather than rel path
MatthewCroughan Jul 8, 2022
dfa3f3a
Start using Nix as a reproducible build tool
MatthewCroughan Jul 8, 2022
b178afa
nix: remove forAllSystems from nixosModule
MatthewCroughan Jul 14, 2022
5d7d149
Fixed path for extension templates
arcbtc Jul 23, 2022
8b34ad8
Updated requirements
arcbtc Jul 27, 2022
c8e7b68
Update installation.md
arcbtc Jul 27, 2022
2f708ce
Update installation.md
arcbtc Jul 27, 2022
888d689
Update installation.md
arcbtc Jul 27, 2022
67981dd
Fix/hotfix tpos 2 (#783)
talvasconcelos Jul 27, 2022
35d8756
Made reliable
arcbtc Jul 27, 2022
fd70e07
Update wallets.md
arcbtc Jul 27, 2022
54de784
Added meta for api /docs
arcbtc Jul 27, 2022
9aace13
added swagger to extensions
arcbtc Jul 27, 2022
22d4786
disabled lnurlpayout again
arcbtc Jul 27, 2022
c384ae8
format
callebtc Jul 27, 2022
dd59e3e
CLIGHTNING_RPC -> CORELIGHTNING_RPC
callebtc Jul 27, 2022
cca5d69
fix path
callebtc Jul 28, 2022
296884a
Merge branch 'main' into wallets/cln_update_lib
callebtc Jul 28, 2022
c7574d7
logging
callebtc Jul 28, 2022
d889dbd
error handling
callebtc Jul 28, 2022
99d019d
Merge branch 'wallets/cln_update_lib' of github.com:lnbits/lnbits-leg…
callebtc Jul 28, 2022
3d0de9e
Merge branch 'main' into wallets/cln_update_lib
callebtc Jul 28, 2022
b43f5e9
I think I got it now
callebtc Jul 28, 2022
53e9fc1
nice
callebtc Jul 28, 2022
5399a7f
print eet
callebtc Jul 28, 2022
44f5eec
AAAAAHHHH
callebtc Jul 28, 2022
54314b9
print even moarrrr
callebtc Jul 28, 2022
096228f
were getting there
callebtc Jul 28, 2022
8cd083c
wal
callebtc Jul 28, 2022
c7a1261
no labels anymore
callebtc Jul 28, 2022
1c42512
check for description hash
callebtc Jul 30, 2022
54115cd
remove unnecessary asserts for clarity
callebtc Jul 30, 2022
d8775b9
assume that description_hash is a hash already
callebtc Jul 30, 2022
123ea6c
no lock
callebtc Jul 30, 2022
d34562b
Merge branch 'tests/description_hash_invoice' into wallets/cln_update…
callebtc Jul 30, 2022
1363f88
do not hex description_hash
callebtc Jul 30, 2022
b6cdf42
try hexlify
callebtc Jul 30, 2022
32ab0ba
really try hexlify
callebtc Jul 30, 2022
6416cd9
back to hex
callebtc Jul 30, 2022
9b02e72
CLN WHY U NO HAVE DOCUMENTATION
callebtc Jul 30, 2022
5679c4d
chaotic evil
callebtc Jul 30, 2022
c9baace
cmon cln lets do this
callebtc Jul 30, 2022
de9796a
description hashing in backend
callebtc Jul 31, 2022
8cb3170
restore bolt11.py
callebtc Jul 31, 2022
071e347
/api/v1/payments with hex of description
callebtc Jul 31, 2022
c79a650
comment
callebtc Jul 31, 2022
14c1fed
Merge branch 'tests/description_hash_invoice' into invoice/refactor_d…
callebtc Jul 31, 2022
74881ee
refactor wallets
callebtc Jul 31, 2022
9213c5f
cln wants the full description
callebtc Jul 31, 2022
5c4c5e4
merge
callebtc Jul 31, 2022
3ea178f
cln
callebtc Jul 31, 2022
8087aa8
forgot eclair
callebtc Jul 31, 2022
14b792c
fix lnpay
callebtc Jul 31, 2022
b7424cb
Merge branch 'invoice/refactor_description_hash' into wallets/cln_upd…
callebtc Jul 31, 2022
2c9fd0d
make format
callebtc Jul 31, 2022
ac2ab25
mypy check
callebtc Jul 31, 2022
e0d5a76
Merge branch 'invoice/refactor_description_hash' into wallets/cln_upd…
callebtc Jul 31, 2022
3e0fd4c
Merge branch 'main' into wallets/cln_update_lib
callebtc Jul 31, 2022
208372c
merge main
callebtc Aug 1, 2022
1ce2fad
Merge branch 'wallets/cln_update_lib' of github.com:lnbits/lnbits-leg…
callebtc Aug 1, 2022
b76231f
revert merge error
callebtc Aug 1, 2022
c677122
isort
callebtc Aug 1, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ LNBITS_THEME_OPTIONS="classic, bitcoin, freedom, mint, autumn, monochrome, salva
# LNBITS_CUSTOM_LOGO="https://lnbits.com/assets/images/logo/logo.svg"

# Choose from LNPayWallet, OpenNodeWallet, LntxbotWallet, ClicheWallet
# LndRestWallet, CLightningWallet, LNbitsWallet, SparkWallet, FakeWallet, EclairWallet
# LndRestWallet, CoreLightningWallet, LNbitsWallet, SparkWallet, FakeWallet, EclairWallet
LNBITS_BACKEND_WALLET_CLASS=VoidWallet
# VoidWallet is just a fallback that works without any actual Lightning capabilities,
# just so you can see the UI before dealing with this file.
Expand All @@ -49,8 +49,8 @@ CLICHE_ENDPOINT=ws://127.0.0.1:12000
SPARK_URL=http://localhost:9737/rpc
SPARK_TOKEN=myaccesstoken

# CLightningWallet
CLIGHTNING_RPC="/home/bob/.lightning/bitcoin/lightning-rpc"
# CoreLightningWallet
CORELIGHTNING_RPC="/home/bob/.lightning/bitcoin/lightning-rpc"

# LnbitsWallet
LNBITS_ENDPOINT=https://legend.lnbits.com
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/regtest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
python -m venv ${{ env.VIRTUAL_ENV }}
./venv/bin/python -m pip install --upgrade pip
./venv/bin/pip install -r requirements.txt
./venv/bin/pip install pylightning
./venv/bin/pip install pyln-client
./venv/bin/pip install pytest pytest-asyncio pytest-cov requests mock
- name: Run tests
env:
Expand All @@ -47,7 +47,7 @@ jobs:
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
CLightningWallet:
CoreLightningWallet:
runs-on: ubuntu-latest
strategy:
matrix:
Expand All @@ -73,15 +73,15 @@ jobs:
python -m venv ${{ env.VIRTUAL_ENV }}
./venv/bin/python -m pip install --upgrade pip
./venv/bin/pip install -r requirements.txt
./venv/bin/pip install pylightning
./venv/bin/pip install pyln-client
./venv/bin/pip install pytest pytest-asyncio pytest-cov requests mock
- name: Run tests
env:
PYTHONUNBUFFERED: 1
PORT: 5123
LNBITS_DATA_FOLDER: ./data
LNBITS_BACKEND_WALLET_CLASS: CLightningWallet
CLIGHTNING_RPC: ./docker/data/clightning-1/regtest/lightning-rpc
LNBITS_BACKEND_WALLET_CLASS: CoreLightningWallet
CORELIGHTNING_RPC: ./docker/data/clightning-1/regtest/lightning-rpc
run: |
sudo chmod -R a+rwx . && rm -rf ./data && mkdir -p ./data
make test-real-wallet
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ COPY requirements.txt /tmp/requirements.txt
RUN pip install -r /tmp/requirements.txt

# Install c-lightning specific deps
RUN pip install pylightning
RUN pip install pyln-client

# Install LND specific deps
RUN pip install lndgrpc
Expand Down
8 changes: 4 additions & 4 deletions docs/guide/wallets.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ Backend wallets
===============

LNbits can run on top of many lightning-network funding sources. Currently there is support for
CLightning, LND, LNbits, LNPay, lntxbot and OpenNode, with more being added regularily.
CoreLightning, LND, LNbits, LNPay, lntxbot and OpenNode, with more being added regularily.

A backend wallet can be configured using the following LNbits environment variables:


### CLightning
### CoreLightning

Using this wallet requires the installation of the `pylightning` Python package.

- `LNBITS_BACKEND_WALLET_CLASS`: **CLightningWallet**
- `CLIGHTNING_RPC`: /file/path/lightning-rpc
- `LNBITS_BACKEND_WALLET_CLASS`: **CoreLightningWallet**
- `CORELIGHTNING_RPC`: /file/path/lightning-rpc

### Spark (c-lightning)

Expand Down
3 changes: 2 additions & 1 deletion lnbits/wallets/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# flake8: noqa

from .cliche import ClicheWallet
from .clightning import CLightningWallet
from .cln import CoreLightningWallet # legacy .env support
from .cln import CoreLightningWallet as CLightningWallet
from .eclair import EclairWallet
from .fake import FakeWallet
from .lnbits import LNbitsWallet
Expand Down
84 changes: 49 additions & 35 deletions lnbits/wallets/clightning.py → lnbits/wallets/cln.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
try:
from lightning import LightningRpc, RpcError # type: ignore
from pyln.client import LightningRpc, RpcError # type: ignore
except ImportError: # pragma: nocover
LightningRpc = None

Expand All @@ -11,6 +11,8 @@
from os import getenv
from typing import AsyncGenerator, Optional

from loguru import logger

from lnbits import bolt11 as lnbits_bolt11

from .base import (
Expand Down Expand Up @@ -42,26 +44,20 @@ def _paid_invoices_stream(ln, last_pay_index):
return ln.waitanyinvoice(last_pay_index)


class CLightningWallet(Wallet):
class CoreLightningWallet(Wallet):
def __init__(self):
if LightningRpc is None: # pragma: nocover
raise ImportError(
"The `pylightning` library must be installed to use `CLightningWallet`."
"The `pyln-client` library must be installed to use `CoreLightningWallet`."
)

self.rpc = getenv("CLIGHTNING_RPC")
self.rpc = getenv("CORELIGHTNING_RPC") or getenv("CLIGHTNING_RPC")
self.ln = LightningRpc(self.rpc)

# check description_hash support (could be provided by a plugin)
self.supports_description_hash = False
try:
answer = self.ln.help("invoicewithdescriptionhash")
if answer["help"][0]["command"].startswith(
"invoicewithdescriptionhash msatoshi label description_hash"
):
self.supports_description_hash = True
except:
pass
# check if description_hash is supported (from CLN>=v0.11.0)
self.supports_description_hash = (
"deschashonly" in self.ln.help("invoice")["help"][0]["command"]
)

# check last payindex so we can listen from that point on
self.last_pay_index = 0
Expand Down Expand Up @@ -89,21 +85,32 @@ async def create_invoice(
) -> InvoiceResponse:
label = "lbl{}".format(random.random())
msat = amount * 1000

try:
if description_hash:
if not self.supports_description_hash:
raise Unsupported("description_hash")

params = [msat, label, hashlib.sha256(description_hash).hexdigest()]
r = self.ln.call("invoicewithdescriptionhash", params)
return InvoiceResponse(True, label, r["bolt11"], "")
else:
r = self.ln.invoice(msat, label, memo, exposeprivatechannels=True)
return InvoiceResponse(True, label, r["bolt11"], "")
if description_hash and not self.supports_description_hash:
raise Unsupported("description_hash")
r = self.ln.invoice(
msatoshi=msat,
label=label,
description=description_hash.decode("utf-8")
if description_hash
else memo,
exposeprivatechannels=True,
deschashonly=True
if description_hash
else False, # we can't pass None here
)

if r.get("code") and r.get("code") < 0:
raise Exception(r.get("message"))

return InvoiceResponse(True, r["payment_hash"], r["bolt11"], "")
except RpcError as exc:
error_message = f"lightningd '{exc.method}' failed with '{exc.error}'."
return InvoiceResponse(False, label, None, error_message)
logger.error("RPC error:", error_message)
return InvoiceResponse(False, None, None, error_message)
except Exception as e:
logger.error("error:", e)
return InvoiceResponse(False, None, None, str(e))

async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse:
invoice = lnbits_bolt11.decode(bolt11)
Expand All @@ -117,18 +124,19 @@ async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse
try:
wrapped = async_wrap(_pay_invoice)
r = await wrapped(self.ln, payload)
except RpcError as exc:
except Exception as exc:
return PaymentResponse(False, None, 0, None, str(exc))

fee_msat = r["msatoshi_sent"] - r["msatoshi"]
preimage = r["payment_preimage"]
return PaymentResponse(True, r["payment_hash"], fee_msat, preimage, None)
return PaymentResponse(
True, r["payment_hash"], fee_msat, r["payment_preimage"], None
)

async def get_invoice_status(self, checking_id: str) -> PaymentStatus:
r = self.ln.listinvoices(checking_id)
r = self.ln.listinvoices(payment_hash=checking_id)
if not r["invoices"]:
return PaymentStatus(False)
if r["invoices"][0]["label"] == checking_id:
if r["invoices"][0]["payment_hash"] == checking_id:
return PaymentStatus(r["invoices"][0]["status"] == "paid")
raise KeyError("supplied an invalid checking_id")

Expand All @@ -147,7 +155,13 @@ async def get_payment_status(self, checking_id: str) -> PaymentStatus:

async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
while True:
wrapped = async_wrap(_paid_invoices_stream)
paid = await wrapped(self.ln, self.last_pay_index)
self.last_pay_index = paid["pay_index"]
yield paid["label"]
try:
wrapped = async_wrap(_paid_invoices_stream)
paid = await wrapped(self.ln, self.last_pay_index)
self.last_pay_index = paid["pay_index"]
yield paid["payment_hash"]
except Exception as exc:
logger.error(
f"lost connection to cln invoices stream: '{exc}', retrying in 5 seconds"
)
await asyncio.sleep(5)