diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py index 6c4147c07..56567b029 100644 --- a/electrum/lnchannel.py +++ b/electrum/lnchannel.py @@ -99,6 +99,7 @@ state_transitions = [ (cs.CLOSING, cs.CLOSING), # if we reestablish (cs.CLOSING, cs.CLOSED), (cs.FORCE_CLOSING, cs.CLOSED), + (cs.FORCE_CLOSING, cs.REDEEMED), (cs.CLOSED, cs.REDEEMED), (cs.OPENING, cs.REDEEMED), # channel never funded (dropped from mempool) (cs.PREOPENING, cs.REDEEMED), # channel never funded diff --git a/electrum/lnutil.py b/electrum/lnutil.py index 0976748ee..3a7eec25d 100644 --- a/electrum/lnutil.py +++ b/electrum/lnutil.py @@ -135,6 +135,7 @@ class PaymentFailure(UserFacingException): pass # TODO make some of these values configurable? DEFAULT_TO_SELF_DELAY = 144 +REDEEM_AFTER_DOUBLE_SPENT_DELAY = 30 ##### CLTV-expiry-delta-related values # see https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#cltv_expiry_delta-selection diff --git a/electrum/lnworker.py b/electrum/lnworker.py index c79bae2e1..637085118 100644 --- a/electrum/lnworker.py +++ b/electrum/lnworker.py @@ -704,8 +704,11 @@ class LNWallet(LNWorker): return chan async def update_unfunded_channel(self, chan, funding_txid): - if chan.get_state() in [channel_states.PREOPENING, channel_states.OPENING]: + if chan.get_state() in [channel_states.PREOPENING, channel_states.OPENING, channel_states.FORCE_CLOSING]: if chan.constraints.is_initiator: + # set channel state to REDEEMED so that it can be removed manually + # to protect ourselves against a server lying by omission, + # we check that funding_inputs have been double spent and deeply mined inputs = chan.storage.get('funding_inputs', []) if not inputs: self.logger.info(f'channel funding inputs are not provided') @@ -716,9 +719,8 @@ class LNWallet(LNWorker): continue if spender_txid != funding_txid: tx_mined_height = self.wallet.get_tx_height(spender_txid) - if tx_mined_height.conf > 6: + if tx_mined_height.conf > lnutil.REDEEM_AFTER_DOUBLE_SPENT_DELAY: self.logger.info(f'channel is double spent {inputs}') - # set to REDEEMED so that it can be removed manually chan.set_state(channel_states.REDEEMED) break else: