1
0

Merge pull request #10459 from SomberNight/202602_lnaddr_format_rtags

lnwallet.pay_to_node: log r_tags from invoice
This commit is contained in:
ghost43
2026-02-09 17:06:21 +00:00
committed by GitHub
4 changed files with 66 additions and 6 deletions

View File

@@ -73,7 +73,7 @@ from electrum.exchange_rate import FxThread
from electrum.simple_config import SimpleConfig
from electrum.logging import Logger
from electrum.lntransport import extract_nodeid, ConnStringFormatError
from electrum.lnaddr import lndecode
from electrum.lnaddr import lndecode, LnAddr
from electrum.submarine_swaps import SwapServerTransport, NostrTransport
from electrum.fee_policy import FeePolicy
@@ -1746,7 +1746,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener):
grid.addWidget(QLabel(_('Text') + ':'), 8, 0)
grid.addWidget(invoice_e, 8, 1)
r_tags = lnaddr.get_routing_info('r')
r_tags = '\n'.join(repr([(x[0].hex(), format_short_id(x[1]), x[2], x[3]) for x in r]) for r in r_tags)
r_tags = '\n'.join(repr(r) for r in LnAddr.format_bolt11_routing_info_as_human_readable(r_tags))
routing_e = QTextEdit(str(r_tags))
routing_e.setReadOnly(True)
grid.addWidget(QLabel(_("Routing Hints") + ':'), 9, 0)

View File

@@ -302,6 +302,24 @@ class LnAddr(object):
random.shuffle(r_tags)
return r_tags
@staticmethod
def format_bolt11_routing_info_as_human_readable(r_tags, *, has_explicit_r_tagtype: bool = False):
"""Converts the node-id bytes->hex, and the SCID bytes->"AAAxBBBxCC", e.g. for logging."""
from .util import format_short_id
r_tags2 = []
for r_tag in r_tags:
if has_explicit_r_tagtype:
(tagtype, path) = r_tag
assert tagtype == "r", f"found unexpected {tagtype=}"
else:
path = r_tag
path2 = [
(edge[0].hex(), format_short_id(edge[1]), edge[2], edge[3], edge[4])
for edge in path]
r_tag2 = (tagtype, path2) if has_explicit_r_tagtype else path2
r_tags2.append(r_tag2)
return r_tags2
def get_amount_msat(self) -> Optional[int]:
if self.amount is None:
return None
@@ -374,8 +392,7 @@ class LnAddr(object):
'unknown_tags': self.unknown_tags,
}
if ln_routing_info := self.get_routing_info('r'):
# show the last hop of routing hints. (our invoices only have one hop)
d['r_tags'] = [str((a.hex(),b.hex(),c,d,e)) for a,b,c,d,e in ln_routing_info[-1]]
d['r_tags'] = self.format_bolt11_routing_info_as_human_readable(ln_routing_info)
return d

View File

@@ -1928,6 +1928,7 @@ class LNWallet(Logger):
f"pay_to_node starting session for RHASH={payment_hash.hex()}. "
f"using_trampoline={self.uses_trampoline()}. "
f"invoice_features={paysession.invoice_features.get_names()}. "
f"r_tags={LnAddr.format_bolt11_routing_info_as_human_readable(r_tags)}. "
f"{amount_to_pay=} msat. {budget=}")
if not self.uses_trampoline():
self.logger.info(
@@ -2570,7 +2571,8 @@ class LNWallet(Logger):
assert amount_msat is None or amount_msat > 0
timestamp = int(time.time())
routing_hints = self.calc_routing_hints_for_invoice(amount_msat, channels=channels)
self.logger.info(f"creating bolt11 invoice with routing_hints: {routing_hints}, sat: {(amount_msat or 0) // 1000}")
formatted_r_hints = LnAddr.format_bolt11_routing_info_as_human_readable(routing_hints, has_explicit_r_tagtype=True)
self.logger.info(f"creating bolt11 invoice with routing_hints: {formatted_r_hints}, sat: {(amount_msat or 0) // 1000}")
payment_secret = self.get_payment_secret(payment_info.payment_hash)
amount_btc = amount_msat/Decimal(COIN*1000) if amount_msat else None
min_final_cltv_delta = payment_info.min_final_cltv_delta + MIN_FINAL_CLTV_DELTA_BUFFER_INVOICE
@@ -3916,7 +3918,7 @@ class LNWallet(Logger):
invoice_features = payload["invoice_features"]["invoice_features"]
invoice_routing_info = payload["invoice_routing_info"]["invoice_routing_info"]
r_tags = decode_routing_info(invoice_routing_info)
self.logger.info(f'r_tags {r_tags}')
self.logger.info(f'r_tags {LnAddr.format_bolt11_routing_info_as_human_readable(r_tags)}')
# TODO legacy mpp payment, use total_msat from trampoline onion
else:
self.logger.info('forward_trampoline: end-to-end')

View File

@@ -9,6 +9,7 @@ from electrum.segwit_addr import bech32_encode, bech32_decode
from electrum import segwit_addr
from electrum.lnutil import UnknownEvenFeatureBits, LnFeatures, IncompatibleLightningFeatures
from electrum import constants
from electrum.util import bfh, ShortID
from . import ElectrumTestCase
@@ -169,3 +170,43 @@ class TestBolt11(ElectrumTestCase):
lnaddr.validate_and_compare_features(LnFeatures((1 << 8) + (1 << 14) + (1 << 15)))
with self.assertRaises(IncompatibleLightningFeatures):
lnaddr.validate_and_compare_features(LnFeatures((1 << 8) + (1 << 14) + (1 << 16)))
def test_format_bolt11_routing_info_as_human_readable(self):
r_tags_expl = [
['r', [(bfh('029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255'), bfh('0102030405060708'), 1, 20, 3),
(bfh('039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255'), bfh('030405060708090a'), 2, 30, 4)]],
['r', [(bfh('038863cf8ab91046230f561cd5b386cbff8309fa02e3f0c3ed161a3aeb64a643b9'), bfh('f4240000000002cd'), 0, 1, 40)]],
]
self.assertEqual(
[
('r', [('029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255',
'66051x263430x1800', 1, 20, 3),
('039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255',
'197637x395016x2314', 2, 30, 4)]
),
('r', [('038863cf8ab91046230f561cd5b386cbff8309fa02e3f0c3ed161a3aeb64a643b9',
'16000000x0x717', 0, 1, 40),]
),
],
LnAddr.format_bolt11_routing_info_as_human_readable(r_tags_expl, has_explicit_r_tagtype=True))
r_tags_impl = [
[(bfh('029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255'), bfh('0102030405060708'), 1, 20, 3),
(bfh('039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255'), bfh('030405060708090a'), 2, 30, 4)],
[(bfh('038863cf8ab91046230f561cd5b386cbff8309fa02e3f0c3ed161a3aeb64a643b9'), bfh('f4240000000002cd'), 0, 1, 40)],
]
self.assertEqual(
[
[('029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255',
'66051x263430x1800', 1, 20, 3),
('039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255',
'197637x395016x2314', 2, 30, 4)],
[('038863cf8ab91046230f561cd5b386cbff8309fa02e3f0c3ed161a3aeb64a643b9',
'16000000x0x717', 0, 1, 40),],
],
LnAddr.format_bolt11_routing_info_as_human_readable(r_tags_impl, has_explicit_r_tagtype=False))
for has_explicit_r_tagtype in (False, True):
self.assertEqual(
[],
LnAddr.format_bolt11_routing_info_as_human_readable([], has_explicit_r_tagtype=has_explicit_r_tagtype))