mirror of
https://github.com/fusion44/blitz_api.git
synced 2026-08-18 12:27:50 +02:00
Merge 84a888f0ba into d694f8498a
This commit is contained in:
commit
dbf9dda5b8
4 changed files with 116 additions and 6 deletions
|
|
@ -49,7 +49,7 @@ async def _make_local_call(*args: str):
|
|||
# in the CLN grpc interface yet.
|
||||
|
||||
# Pass the command as a discrete argv list (create_subprocess_exec, not
|
||||
# _shell) so user-controlled arguments such as the bolt11 in decodepay
|
||||
# _shell) so user-controlled arguments such as the string in decode
|
||||
# can never be interpreted as shell syntax.
|
||||
testnet = config("BAPI_NETWORK") == "testnet"
|
||||
argv = ["lightning-cli", "-k", *(["--testnet"] if testnet else []), *args]
|
||||
|
|
@ -551,7 +551,7 @@ class LnNodeCLNgRPC(LightningNodeBase):
|
|||
async def decode_pay_request(self, pay_req: str) -> PaymentRequest:
|
||||
logger.trace(f"decode_pay_request(pay_req={pay_req})")
|
||||
|
||||
res = await _make_local_call("decodepay", f"bolt11={pay_req}")
|
||||
res = await _make_local_call("decode", f"string={pay_req}")
|
||||
|
||||
if not res:
|
||||
raise HTTPException(
|
||||
|
|
@ -569,7 +569,21 @@ class LnNodeCLNgRPC(LightningNodeBase):
|
|||
|
||||
raise_for_pay_req_decode_error(decoded)
|
||||
|
||||
return PaymentRequest.from_cln_json(json.loads(decoded))
|
||||
data = json.loads(decoded)
|
||||
if not data.get("valid", True):
|
||||
# unlike decodepay, decode reports recognized-but-invalid strings
|
||||
# as a normal result with valid=false + warning_* fields instead
|
||||
# of an RPC error
|
||||
m = "; ".join(
|
||||
str(data[k]) for k in sorted(data) if k.startswith("warning")
|
||||
) or "invalid payment request"
|
||||
logger.error(m)
|
||||
raise HTTPException(
|
||||
status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"Could not decode the payment request: {m}",
|
||||
)
|
||||
|
||||
return PaymentRequest.from_cln_json(data)
|
||||
|
||||
@logger.catch(exclude=(HTTPException,))
|
||||
async def get_fee_revenue(self) -> FeeRevenue:
|
||||
|
|
|
|||
|
|
@ -467,10 +467,22 @@ class LnNodeCLNjRPC(LightningNodeBase):
|
|||
return self._bolt11_cache[pay_req]
|
||||
|
||||
params = [pay_req]
|
||||
res = await self._send_request("decodepay", params)
|
||||
res = await self._send_request("decode", params)
|
||||
|
||||
if "error" not in res:
|
||||
res = res["result"]
|
||||
if not res.get("valid", True):
|
||||
# unlike decodepay, decode reports recognized-but-invalid
|
||||
# strings as a normal result with valid=false + warning_*
|
||||
# fields instead of an RPC error
|
||||
m = "; ".join(
|
||||
str(res[k]) for k in sorted(res) if k.startswith("warning")
|
||||
) or "invalid payment request"
|
||||
logger.error(m)
|
||||
raise HTTPException(
|
||||
status.HTTP_400_BAD_REQUEST,
|
||||
detail=f"Could not decode the payment request: {m}",
|
||||
)
|
||||
req = PaymentRequest.from_cln_json(res)
|
||||
self._bolt11_cache[pay_req] = req
|
||||
return req
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ async def test_make_local_call_passes_args_without_a_shell(capture_exec):
|
|||
from app.lightning.impl import cln_grpc
|
||||
|
||||
payload = "lnbc1pdummy; touch /tmp/pwned"
|
||||
await cln_grpc._make_local_call("decodepay", f"bolt11={payload}")
|
||||
await cln_grpc._make_local_call("decode", f"string={payload}")
|
||||
|
||||
assert capture_exec["shell_used"] is False, (
|
||||
"must not run user input through a shell"
|
||||
|
|
@ -54,7 +54,7 @@ async def test_make_local_call_passes_args_without_a_shell(capture_exec):
|
|||
assert argv is not None, "create_subprocess_exec was not called"
|
||||
# the whole bolt11 value, metacharacters and all, must arrive as one
|
||||
# discrete argv token so the shell never sees it
|
||||
assert f"bolt11={payload}" in argv
|
||||
assert f"string={payload}" in argv
|
||||
assert argv[0] == "lightning-cli"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -125,3 +125,87 @@ async def test_cln_grpc_wrong_network_returns_400(monkeypatch):
|
|||
await node.decode_pay_request("lnbcrt500u1pjvvyly-grpc")
|
||||
|
||||
assert exc.value.status_code == 400
|
||||
|
||||
|
||||
# --- CLN decodepay removal ----------------------------------------------------
|
||||
# CLN deprecated `decodepay` in v24.11, disables it by default in v25.12
|
||||
# (JSON-RPC -32601 'Command "decodepay" is deprecated') and removes it in
|
||||
# v26.04. Calling it turned every Transactions load into a 500; both CLN
|
||||
# backends must use `decode` instead.
|
||||
|
||||
_DECODE_RESULT = {
|
||||
"type": "bolt11 invoice",
|
||||
"valid": True,
|
||||
"currency": "bc",
|
||||
"created_at": 1759640918,
|
||||
"expiry": 3599,
|
||||
"payee": "027cd974e47086291bb8a5b0160a889c738f2712a703b8ea939985fd16f3aae67e",
|
||||
"amount_msat": 100000,
|
||||
"description": "test",
|
||||
"min_final_cltv_expiry": 80,
|
||||
"payment_secret": (
|
||||
"097795ffadc7849ab82737572eb3dd36c5dc5d17277effcdf2de709c07cd4a9a"
|
||||
),
|
||||
"payment_hash": (
|
||||
"4620a5027133dd4f049df5e6c2024368e7ed804e9ad759feb349af2c2f60cde6"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
async def test_cln_jrpc_uses_decode_not_decodepay():
|
||||
node = LnNodeCLNjRPC()
|
||||
seen = {}
|
||||
|
||||
async def fake_send(method, params=None):
|
||||
seen["method"] = method
|
||||
return {"result": dict(_DECODE_RESULT)}
|
||||
|
||||
node._send_request = fake_send
|
||||
|
||||
req = await node.decode_pay_request("lnbc100u1p-jrpc-decode")
|
||||
|
||||
assert seen["method"] == "decode"
|
||||
assert req.payment_hash == _DECODE_RESULT["payment_hash"]
|
||||
|
||||
|
||||
async def test_cln_jrpc_decode_valid_false_returns_400():
|
||||
# unlike decodepay, decode reports recognized-but-invalid strings as a
|
||||
# normal result with valid=false + warning_* fields instead of an error
|
||||
node = LnNodeCLNjRPC()
|
||||
|
||||
async def fake_send(method, params=None):
|
||||
return {
|
||||
"result": {
|
||||
"type": "bolt12 invoice",
|
||||
"valid": False,
|
||||
"warning_invoice_missing_amount": "invoice without an amount",
|
||||
}
|
||||
}
|
||||
|
||||
node._send_request = fake_send
|
||||
|
||||
with pytest.raises(HTTPException) as exc:
|
||||
await node.decode_pay_request("lni1-invalid")
|
||||
|
||||
assert exc.value.status_code == 400
|
||||
assert "invoice without an amount" in str(exc.value.detail)
|
||||
|
||||
|
||||
async def test_cln_grpc_uses_decode_not_decodepay(monkeypatch):
|
||||
import json
|
||||
|
||||
from app.lightning.impl import cln_grpc
|
||||
|
||||
node = LnNodeCLNgRPC()
|
||||
seen = {}
|
||||
|
||||
async def fake_call(*args):
|
||||
seen["args"] = args
|
||||
return (json.dumps(_DECODE_RESULT).encode(), b"")
|
||||
|
||||
monkeypatch.setattr(cln_grpc, "_make_local_call", fake_call)
|
||||
|
||||
req = await node.decode_pay_request("lnbc100u1p-grpc-decode")
|
||||
|
||||
assert seen["args"] == ("decode", "string=lnbc100u1p-grpc-decode")
|
||||
assert req.payment_hash == _DECODE_RESULT["payment_hash"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue