From 40c1597c0a96ac89558e01b31dd74ac2714abbe6 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Wed, 16 Feb 2022 18:53:24 +0100 Subject: [PATCH] lntransport: change name used in logs to make collisions unlikely In particular, in the regtests, with incoming peers, we can have multiple transports open with the same node simultaneously (see e.g. lnworker._request_force_close_from_backup). We now use the first few bytes of peer_pubkey, as that is potentially familiar to users, and the first few bytes of sha256(id(self)) to mitigate collisions in case the peer_pubkeys collide. log excerpt: ``` I/P | lnpeer.Peer.[LNWallet, 030f0bf260-e0b33756] | handshake done for 030f0bf260acdbd3edcad84d7588ec7c5df4711e87e6a23016f989b8d3a4147230@163.172.94.64:9735 D/P | lnpeer.Peer.[LNWallet, 030f0bf260-e0b33756] | Sending INIT I/P | lnpeer.Peer.[LNWallet, 03933884aa-5e5dce45] | handshake done for 03933884aaf1d6b108397e5efe5c86bcf2d8ca8d2f700eda99db9214fc2712b134@34.250.234.192:9735 D/P | lnpeer.Peer.[LNWallet, 03933884aa-5e5dce45] | Sending INIT D/P | lnpeer.Peer.[LNWallet, 030f0bf260-e0b33756] | Received INIT I/P | lnpeer.Peer.[LNWallet, 02651acf4a-79696c42] | handshake done for 02651acf4a7096091bf42baad19b3643ea318d6979f6dcc16ebaec43d5b0f4baf2@82.119.233.36:19735 D/P | lnpeer.Peer.[LNWallet, 02651acf4a-79696c42] | Sending INIT D/P | lnpeer.Peer.[LNWallet, 03933884aa-5e5dce45] | Received INIT I/P | lnpeer.Peer.[LNWallet, 030f0bf260-e0b33756] | saved remote_update D/P | lnpeer.Peer.[LNWallet, 030f0bf260-e0b33756] | Received CHANNEL_REESTABLISH ``` --- electrum/lnpeer.py | 2 ++ electrum/lntransport.py | 21 +++++++++++++-------- electrum/tests/test_lnpeer.py | 1 + 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py index 167fa1961..669b594bf 100644 --- a/electrum/lnpeer.py +++ b/electrum/lnpeer.py @@ -150,8 +150,10 @@ class Peer(Logger): and self.initialized.result() is True) async def initialize(self): + # If outgoing transport, do handshake now. For incoming, it has already been done. if isinstance(self.transport, LNTransport): await self.transport.handshake() + self.logger.info(f"handshake done for {self.transport.peer_addr or self.pubkey.hex()}") features = self.features.for_init_message() b = int.bit_length(features) flen = b // 8 + int(bool(b % 8)) diff --git a/electrum/lntransport.py b/electrum/lntransport.py index 8a4abe423..a919688c5 100644 --- a/electrum/lntransport.py +++ b/electrum/lntransport.py @@ -9,6 +9,7 @@ import hashlib import asyncio from asyncio import StreamReader, StreamWriter from typing import Optional +from functools import cached_property from .crypto import sha256, hmac_oneshot, chacha20_poly1305_encrypt, chacha20_poly1305_decrypt from .lnutil import (get_ecdh, privkey_to_pubkey, LightningPeerConnectionClosed, @@ -92,9 +93,18 @@ class LNTransportBase: reader: StreamReader writer: StreamWriter privkey: bytes + peer_addr: Optional[LNPeerAddr] = None def name(self) -> str: - raise NotImplementedError() + pubkey = self.remote_pubkey() + pubkey_hex = pubkey.hex() if pubkey else pubkey + return f"{pubkey_hex[:10]}-{self._id_hash[:8]}" + + @cached_property + def _id_hash(self) -> str: + id_int = id(self) + id_bytes = id_int.to_bytes((id_int.bit_length() + 7) // 8, byteorder='big') + return sha256(id_bytes).hex() def send_bytes(self, msg: bytes) -> None: l = len(msg).to_bytes(2, 'big') @@ -169,10 +179,8 @@ class LNResponderTransport(LNTransportBase): self.privkey = privkey self._pubkey = None # remote pubkey - def name(self): - pubkey = self.remote_pubkey() - pubkey_hex = pubkey.hex() if pubkey else pubkey - return f"{pubkey_hex}(in)" + def name(self) -> str: + return f"{super().name()}(in)" async def handshake(self, **kwargs): hs = HandshakeState(privkey_to_pubkey(self.privkey)) @@ -243,9 +251,6 @@ class LNTransport(LNTransportBase): self.peer_addr = peer_addr self.proxy = MySocksProxy.from_proxy_dict(proxy) - def name(self): - return self.peer_addr.net_addr_str() - async def handshake(self): if not self.proxy: self.reader, self.writer = await asyncio.open_connection(self.peer_addr.host, self.peer_addr.port) diff --git a/electrum/tests/test_lnpeer.py b/electrum/tests/test_lnpeer.py index e8cceacec..0f74d36a7 100644 --- a/electrum/tests/test_lnpeer.py +++ b/electrum/tests/test_lnpeer.py @@ -249,6 +249,7 @@ class MockTransport: def __init__(self, name): self.queue = asyncio.Queue() self._name = name + self.peer_addr = None def name(self): return self._name