From d8b5a6d402b70172908ca7bca356eb4c76aaf522 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Wed, 5 Oct 2022 21:20:24 +0200 Subject: [PATCH 1/5] validate pay --- cashu/core/base.py | 6 +++++- cashu/lightning/lnbits.py | 2 ++ cashu/mint/ledger.py | 15 +++++++++++---- cashu/mint/router.py | 2 +- cashu/wallet/wallet.py | 11 +++++++++++ 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/cashu/core/base.py b/cashu/core/base.py index 63d7f5c..e30168b 100644 --- a/cashu/core/base.py +++ b/cashu/core/base.py @@ -153,7 +153,11 @@ class CheckRequest(BaseModel): proofs: List[Proof] +class CheckInternalRequest(BaseModel): + pr: str + + class MeltRequest(BaseModel): proofs: List[Proof] - amount: int + amount: int = None # deprecated invoice: str diff --git a/cashu/lightning/lnbits.py b/cashu/lightning/lnbits.py index f174f2d..0df13b2 100644 --- a/cashu/lightning/lnbits.py +++ b/cashu/lightning/lnbits.py @@ -87,6 +87,8 @@ class LNbitsWallet(Wallet): except: error_message = r.json()["detail"] return PaymentResponse(None, None, None, None, error_message) + if r.status_code != 200: + return PaymentResponse(None, None, None, None, f"HTTP status: {r.reason}") if "detail" in r.json(): return PaymentResponse(None, None, None, None, r.json()["detail"]) ok, checking_id, fee_msat, preimage, error_message = ( diff --git a/cashu/mint/ledger.py b/cashu/mint/ledger.py index 12c610d..e6b780b 100644 --- a/cashu/mint/ledger.py +++ b/cashu/mint/ledger.py @@ -6,7 +6,7 @@ import hashlib from inspect import signature from signal import signal from typing import List, Set - +import math import cashu.core.b_dhke as b_dhke from cashu.core.base import BlindedMessage, BlindedSignature, Invoice, Proof from cashu.core.db import Database @@ -24,6 +24,7 @@ from cashu.mint.crud import ( store_promise, update_lightning_invoice, ) +import cashu.core.bolt11 as bolt11 class Ledger: @@ -197,7 +198,7 @@ class Ledger: async def _pay_lightning_invoice(self, invoice: str, amount: int): """Returns an invoice from the Lightning backend.""" - error, balance = await WALLET.status() + error, _ = await WALLET.status() if error: raise Exception(f"Lightning wallet not responding: {error}") ok, checking_id, fee_msat, preimage, error_message = await WALLET.pay_invoice( @@ -250,10 +251,16 @@ class Ledger: ] return promises - async def melt(self, proofs: List[Proof], amount: int, invoice: str): + async def melt(self, proofs: List[Proof], invoice: str): """Invalidates proofs and pays a Lightning invoice.""" - # if not LIGHTNING: + # Verify proofs + if not all([self._verify_proof(p) for p in proofs]): + raise Exception("could not verify proofs.") + total = sum([p["amount"] for p in proofs]) + invoice_obj = bolt11.decode(invoice) + amount = math.ceil(invoice_obj.amount_msat / 1000) + # check that lightning fees are included assert total + fee_reserve(amount * 1000) >= amount, Exception( "provided proofs not enough for Lightning payment." diff --git a/cashu/mint/router.py b/cashu/mint/router.py index bb91695..7a0378c 100644 --- a/cashu/mint/router.py +++ b/cashu/mint/router.py @@ -62,7 +62,7 @@ async def melt(payload: MeltRequest): """ Requests tokens to be destroyed and sent out via Lightning. """ - ok, preimage = await ledger.melt(payload.proofs, payload.amount, payload.invoice) + ok, preimage = await ledger.melt(payload.proofs, payload.invoice) resp = GetMeltResponse(paid=ok, preimage=preimage) return resp diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py index e7f97bb..9dcd764 100644 --- a/cashu/wallet/wallet.py +++ b/cashu/wallet/wallet.py @@ -17,6 +17,7 @@ from cashu.core.base import ( P2SHScript, Proof, SplitRequest, + CheckInternalRequest, ) from cashu.core.db import Database from cashu.core.script import ( @@ -210,6 +211,16 @@ class LedgerAPI: return return_dict + async def check_internal(self, payment_request: str): + """Checks whether the Lightning payment is internal.""" + payload = CheckInternalRequest(pr=payment_request) + return_dict = requests.post( + self.url + "/checkinternal", + json=payload.dict(), + ).json() + + return return_dict + async def pay_lightning(self, proofs: List[Proof], amount: int, invoice: str): payload = MeltRequest(proofs=proofs, amount=amount, invoice=invoice) return_dict = requests.post( From a6eb39d2786bf4576ee8c670f89d05b1ec846209 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Wed, 5 Oct 2022 21:31:15 +0200 Subject: [PATCH 2/5] lnbits error check --- cashu/lightning/lnbits.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cashu/lightning/lnbits.py b/cashu/lightning/lnbits.py index 0df13b2..ed655bf 100644 --- a/cashu/lightning/lnbits.py +++ b/cashu/lightning/lnbits.py @@ -87,7 +87,7 @@ class LNbitsWallet(Wallet): except: error_message = r.json()["detail"] return PaymentResponse(None, None, None, None, error_message) - if r.status_code != 200: + if r.status_code > 299: return PaymentResponse(None, None, None, None, f"HTTP status: {r.reason}") if "detail" in r.json(): return PaymentResponse(None, None, None, None, r.json()["detail"]) From 47042bdcb32e0c6ed7a0e5e0729fab1cde286239 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Wed, 5 Oct 2022 21:31:44 +0200 Subject: [PATCH 3/5] bump version --- cashu/core/settings.py | 2 +- pyproject.toml | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cashu/core/settings.py b/cashu/core/settings.py index 4337e9b..377e88a 100644 --- a/cashu/core/settings.py +++ b/cashu/core/settings.py @@ -46,4 +46,4 @@ LNBITS_ENDPOINT = env.str("LNBITS_ENDPOINT", default=None) LNBITS_KEY = env.str("LNBITS_KEY", default=None) MAX_ORDER = 64 -VERSION = "0.2.3" +VERSION = "0.2.4" diff --git a/pyproject.toml b/pyproject.toml index d5a6abc..c16d54e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "cashu" -version = "0.2.3" +version = "0.2.4" description = "Ecash wallet and mint." authors = ["calle "] license = "MIT" diff --git a/setup.py b/setup.py index 5c04243..050b1d5 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ entry_points = {"console_scripts": ["cashu = cashu.wallet.cli:cli"]} setuptools.setup( name="cashu", - version="0.2.3", + version="0.2.4", description="Ecash wallet and mint with Bitcoin Lightning support", long_description=long_description, long_description_content_type="text/markdown", From 6599215934132802366adf89a1c2ef5f311d8af6 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Wed, 5 Oct 2022 21:34:36 +0200 Subject: [PATCH 4/5] format --- cashu/mint/ledger.py | 5 +++-- cashu/wallet/wallet.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cashu/mint/ledger.py b/cashu/mint/ledger.py index e6b780b..97c621f 100644 --- a/cashu/mint/ledger.py +++ b/cashu/mint/ledger.py @@ -3,11 +3,13 @@ Implementation of https://gist.github.com/phyro/935badc682057f418842c72961cf096c """ import hashlib +import math from inspect import signature from signal import signal from typing import List, Set -import math + import cashu.core.b_dhke as b_dhke +import cashu.core.bolt11 as bolt11 from cashu.core.base import BlindedMessage, BlindedSignature, Invoice, Proof from cashu.core.db import Database from cashu.core.helpers import fee_reserve @@ -24,7 +26,6 @@ from cashu.mint.crud import ( store_promise, update_lightning_invoice, ) -import cashu.core.bolt11 as bolt11 class Ledger: diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py index 9dcd764..2245837 100644 --- a/cashu/wallet/wallet.py +++ b/cashu/wallet/wallet.py @@ -11,13 +11,13 @@ import cashu.core.b_dhke as b_dhke from cashu.core.base import ( BlindedMessage, BlindedSignature, + CheckInternalRequest, CheckRequest, MeltRequest, MintRequest, P2SHScript, Proof, SplitRequest, - CheckInternalRequest, ) from cashu.core.db import Database from cashu.core.script import ( From 953af045d074f0fb2c90c8bf7a153372e6c4fc2c Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Wed, 5 Oct 2022 21:35:58 +0200 Subject: [PATCH 5/5] client sends no amount --- cashu/wallet/cli.py | 2 +- cashu/wallet/wallet.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cashu/wallet/cli.py b/cashu/wallet/cli.py index 84a9a92..f53eb78 100755 --- a/cashu/wallet/cli.py +++ b/cashu/wallet/cli.py @@ -136,7 +136,7 @@ async def pay(ctx, invoice: str): print("Error: Balance too low.") return _, send_proofs = await wallet.split_to_send(wallet.proofs, amount) - await wallet.pay_lightning(send_proofs, amount, invoice) + await wallet.pay_lightning(send_proofs, invoice) wallet.status() diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py index 2245837..cfd6a3a 100644 --- a/cashu/wallet/wallet.py +++ b/cashu/wallet/wallet.py @@ -221,8 +221,8 @@ class LedgerAPI: return return_dict - async def pay_lightning(self, proofs: List[Proof], amount: int, invoice: str): - payload = MeltRequest(proofs=proofs, amount=amount, invoice=invoice) + async def pay_lightning(self, proofs: List[Proof], invoice: str): + payload = MeltRequest(proofs=proofs, invoice=invoice) return_dict = requests.post( self.url + "/melt", json=payload.dict(), @@ -294,9 +294,9 @@ class Wallet(LedgerAPI): await invalidate_proof(proof, db=self.db) return frst_proofs, scnd_proofs - async def pay_lightning(self, proofs: List[Proof], amount: int, invoice: str): + async def pay_lightning(self, proofs: List[Proof], invoice: str): """Pays a lightning invoice""" - status = await super().pay_lightning(proofs, amount, invoice) + status = await super().pay_lightning(proofs, invoice) if status["paid"] == True: await self.invalidate(proofs) else: