commit 3c0df28c98a275e9eafac409d383dc383c1c5065
parent 0acd0c23d32f43bb91c29cf7e8d1288d40d8cc74
Author: ThomasV <thomasv@electrum.org>
Date: Sun, 19 May 2019 11:55:55 +0200
do not include 'force_closing' in channel states, because it is not part of the peer protocol
Diffstat:
4 files changed, 18 insertions(+), 20 deletions(-)
diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py
@@ -145,6 +145,7 @@ class Channel(Logger):
self.short_channel_id = bfh(state["short_channel_id"]) if type(state["short_channel_id"]) not in (bytes, type(None)) else state["short_channel_id"]
self.short_channel_id_predicted = self.short_channel_id
self.onion_keys = str_bytes_dict_from_save(state.get('onion_keys', {}))
+ self.force_closed = state.get('force_closed')
# FIXME this is a tx serialised in the custom electrum partial tx format.
# we should not persist txns in this format. we should persist htlcs, and be able to derive
@@ -162,11 +163,7 @@ class Channel(Logger):
self._is_funding_txo_spent = None # "don't know"
self._state = None
- if state.get('force_closed', False):
- self.set_state('FORCE_CLOSING')
- else:
- self.set_state('DISCONNECTED')
-
+ self.set_state('DISCONNECTED')
self.lnwatcher = None
self.local_commitment = None
@@ -203,18 +200,21 @@ class Channel(Logger):
self.config[LOCAL] = self.config[LOCAL]._replace(ctn=0, current_commitment_signature=remote_sig)
self.set_state('OPENING')
+ def set_force_closed(self):
+ self.force_closed = True
+
def set_state(self, state: str):
- if self._state == 'FORCE_CLOSING':
- assert state == 'FORCE_CLOSING', 'new state was not FORCE_CLOSING: ' + state
self._state = state
def get_state(self):
return self._state
def is_closed(self):
- return self.get_state() in ['CLOSED', 'FORCE_CLOSING']
+ return self.force_closed or self.get_state() in ['CLOSED', 'CLOSING']
def _check_can_pay(self, amount_msat: int) -> None:
+ if self.is_closed():
+ raise PaymentFailure('Channel closed')
if self.get_state() != 'OPEN':
raise PaymentFailure('Channel not open')
if self.available_to_spend(LOCAL) < amount_msat:
@@ -672,7 +672,7 @@ class Channel(Logger):
"remote_commitment_to_be_revoked": str(self.remote_commitment_to_be_revoked),
"log": self.hm.to_save(),
"onion_keys": str_bytes_dict_to_save(self.onion_keys),
- "force_closed": self.get_state() == 'FORCE_CLOSING',
+ "force_closed": self.force_closed,
}
return to_save
diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py
@@ -1342,7 +1342,7 @@ class Peer(Logger):
while True:
our_sig, closing_tx = chan.make_closing_tx(scriptpubkey, payload['scriptpubkey'], fee_sat=our_fee)
self.send_message('closing_signed', channel_id=chan.channel_id, fee_satoshis=our_fee, signature=our_sig)
- cs_payload = await asyncio.wait_for(self.closing_signed[chan.channel_id].get(), 1)
+ cs_payload = await asyncio.wait_for(self.closing_signed[chan.channel_id].get(), 10)
their_fee = int.from_bytes(cs_payload['fee_satoshis'], 'big')
their_sig = cs_payload['signature']
if our_fee == their_fee:
diff --git a/electrum/lnworker.py b/electrum/lnworker.py
@@ -334,8 +334,7 @@ class LNWallet(LNWorker):
def peer_closed(self, peer):
for chan in self.channels_for_peer(peer.pubkey).values():
- if chan.get_state() != 'FORCE_CLOSING':
- chan.set_state('DISCONNECTED')
+ chan.set_state('DISCONNECTED')
self.network.trigger_callback('channel', chan)
self.peers.pop(peer.pubkey)
@@ -485,7 +484,7 @@ class LNWallet(LNWorker):
chan = self.channel_by_txo(funding_outpoint)
if not chan:
return
- self.logger.info(f'on_channel_open {funding_outpoint}')
+ self.logger.debug(f'on_channel_open {funding_outpoint}')
self.channel_timestamps[bh2u(chan.channel_id)] = funding_txid, funding_height.height, funding_height.timestamp, None, None, None
self.storage.put('lightning_channel_timestamps', self.channel_timestamps)
chan.set_funding_txo_spentness(False)
@@ -497,13 +496,12 @@ class LNWallet(LNWorker):
chan = self.channel_by_txo(funding_outpoint)
if not chan:
return
- self.logger.info(f'on_channel_closed {funding_outpoint}')
+ self.logger.debug(f'on_channel_closed {funding_outpoint}')
self.channel_timestamps[bh2u(chan.channel_id)] = funding_txid, funding_height.height, funding_height.timestamp, closing_txid, closing_height.height, closing_height.timestamp
self.storage.put('lightning_channel_timestamps', self.channel_timestamps)
chan.set_funding_txo_spentness(True)
- if chan.get_state() != 'FORCE_CLOSING':
- chan.set_state("CLOSED")
- self.on_channels_updated()
+ chan.set_state('CLOSED')
+ self.on_channels_updated()
self.network.trigger_callback('channel', chan)
# remove from channel_db
if chan.short_channel_id is not None:
@@ -588,7 +586,7 @@ class LNWallet(LNWorker):
await peer.bitcoin_fee_update(chan)
conf = lnwatcher.get_tx_height(chan.funding_outpoint.txid).conf
peer.on_network_update(chan, conf)
- elif chan.get_state() == 'FORCE_CLOSING':
+ elif chan.force_closed and chan.get_state() != 'CLOSED':
txid = chan.force_close_tx().txid()
height = lnwatcher.get_tx_height(txid).height
self.logger.info(f"force closing tx {txid}, height {height}")
@@ -871,7 +869,7 @@ class LNWallet(LNWorker):
async def force_close_channel(self, chan_id):
chan = self.channels[chan_id]
tx = chan.force_close_tx()
- chan.set_state('FORCE_CLOSING')
+ chan.set_force_closed()
self.save_channel(chan)
self.on_channels_updated()
await self.network.broadcast_transaction(tx)
diff --git a/electrum/tests/test_lnpeer.py b/electrum/tests/test_lnpeer.py
@@ -262,7 +262,7 @@ class TestPeer(SequentialTestCase):
# route finding should fail when channel is closed
async def f():
await asyncio.gather(w1._pay_to_route(route, addr, pay_req), p1._message_loop(), p2._message_loop())
- with self.assertRaises(AssertionError):
+ with self.assertRaises(PaymentFailure):
run(f())
def run(coro):