tln: fix race in on_network_update - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 2fd5f8613a822c90f24648331b8507f9157be40c DIR parent d5cb21143ff47bd400a8af454e82d0dcf25ccb88 HTML Author: Janus <ysangkok@gmail.com> Date: Tue, 17 Jul 2018 15:32:47 +0200 ln: fix race in on_network_update Diffstat: M electrum/lnworker.py | 36 ++++++++++++++++++------------- 1 file changed, 21 insertions(+), 15 deletions(-) --- DIR diff --git a/electrum/lnworker.py b/electrum/lnworker.py t@@ -114,21 +114,27 @@ class LNWorker(PrintError): self.network.trigger_callback('channel', chan) def on_network_update(self, event, *args): - for chan in self.channels.values(): - if chan.state == "OPENING": - res = self.save_short_chan_id(chan) - if not res: - self.print_error("network update but funding tx is still not at sufficient depth") - continue - # this results in the channel being marked OPEN - peer = self.peers[chan.node_id] - peer.funding_locked(chan) - elif chan.state == "OPEN": - if event == 'fee_histogram': - peer.on_bitcoin_fee_update(chan) - conf = self.wallet.get_tx_height(chan.funding_outpoint.txid)[1] - peer = self.peers[chan.node_id] - peer.on_network_update(chan, conf) + """ called from network thread """ + # Race discovered in save_channel (assertion failing): + # since short_channel_id could be changed while saving. + # Mitigated by posting to loop: + async def network_jobs(): + for chan in self.channels.values(): + if chan.state == "OPENING": + res = self.save_short_chan_id(chan) + if not res: + self.print_error("network update but funding tx is still not at sufficient depth") + continue + # this results in the channel being marked OPEN + peer = self.peers[chan.node_id] + peer.funding_locked(chan) + elif chan.state == "OPEN": + if event == 'fee_histogram': + peer.on_bitcoin_fee_update(chan) + conf = self.wallet.get_tx_height(chan.funding_outpoint.txid)[1] + peer = self.peers[chan.node_id] + peer.on_network_update(chan, conf) + asyncio.run_coroutine_threadsafe(network_jobs(), self.network.asyncio_loop).result() async def _open_channel_coroutine(self, node_id, local_amount_sat, push_sat, password): peer = self.peers[node_id]