diff --git a/electrum/channel_db.py b/electrum/channel_db.py index 88e4a7d67..49c0934bf 100644 --- a/electrum/channel_db.py +++ b/electrum/channel_db.py @@ -569,12 +569,14 @@ class ChannelDB(SqlDB): c.execute("INSERT INTO address (node_id, host, port, timestamp) VALUES (?,?,?,?)", (addr.pubkey, addr.host, addr.port, 0)) @classmethod - def verify_channel_update(cls, payload) -> None: + def verify_channel_update(cls, payload, *, start_node: bytes = None) -> None: short_channel_id = payload['short_channel_id'] short_channel_id = ShortChannelID(short_channel_id) if constants.net.rev_genesis_bytes() != payload['chain_hash']: raise InvalidGossipMsg('wrong chain hash') - if not verify_sig_for_channel_update(payload, payload['start_node']): + start_node = payload.get('start_node', None) or start_node + assert start_node is not None + if not verify_sig_for_channel_update(payload, start_node): raise InvalidGossipMsg(f'failed verifying channel update for {short_channel_id}') @classmethod diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py index 0b04d3bd8..1d9504df0 100644 --- a/electrum/lnchannel.py +++ b/electrum/lnchannel.py @@ -580,7 +580,14 @@ class Channel(AbstractChannel): raise Exception('lnworker not set for channel!') return self.lnworker.node_keypair.pubkey - def set_remote_update(self, raw: bytes) -> None: + def set_remote_update(self, payload: dict) -> None: + """Save the ChannelUpdate message for the incoming direction of this channel. + This message contains info we need to populate private route hints when + creating invoices. + """ + from .channel_db import ChannelDB + ChannelDB.verify_channel_update(payload, start_node=self.node_id) + raw = payload['raw'] self.storage['remote_update'] = raw.hex() def get_remote_update(self) -> Optional[bytes]: diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py index ab072b812..bd4efa802 100644 --- a/electrum/lnpeer.py +++ b/electrum/lnpeer.py @@ -97,7 +97,7 @@ class Peer(Logger): self.funding_signed_sent = set() # for channels in PREOPENING self.shutdown_received = {} # chan_id -> asyncio.Future() self.announcement_signatures = defaultdict(asyncio.Queue) - self.orphan_channel_updates = OrderedDict() + self.orphan_channel_updates = OrderedDict() # type: OrderedDict[ShortChannelID, dict] Logger.__init__(self) self.taskgroup = SilentTaskGroup() # HTLCs offered by REMOTE, that we started removing but are still active: @@ -273,7 +273,7 @@ class Peer(Logger): return for chan in self.channels.values(): if chan.short_channel_id == payload['short_channel_id']: - chan.set_remote_update(payload['raw']) + chan.set_remote_update(payload) self.logger.info("saved remote_update") break else: @@ -1149,7 +1149,7 @@ class Peer(Logger): # peer may have sent us a channel update for the incoming direction previously pending_channel_update = self.orphan_channel_updates.get(chan.short_channel_id) if pending_channel_update: - chan.set_remote_update(pending_channel_update['raw']) + chan.set_remote_update(pending_channel_update) self.logger.info(f"CHANNEL OPENING COMPLETED ({chan.get_id_for_log()})") forwarding_enabled = self.network.config.get('lightning_forward_payments', False) if forwarding_enabled: diff --git a/electrum/lnworker.py b/electrum/lnworker.py index a31b5ebbd..8863fd16d 100644 --- a/electrum/lnworker.py +++ b/electrum/lnworker.py @@ -1284,10 +1284,11 @@ class LNWallet(LNWorker): short_channel_id = ShortChannelID(payload['short_channel_id']) if r == UpdateStatus.GOOD: self.logger.info(f"applied channel update to {short_channel_id}") - # TODO: test this + # TODO: add test for this + # FIXME: this does not work for our own unannounced channels. for chan in self.channels.values(): if chan.short_channel_id == short_channel_id: - chan.set_remote_update(payload['raw']) + chan.set_remote_update(payload) update = True elif r == UpdateStatus.ORPHANED: # maybe it is a private channel (and data in invoice was outdated)