mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-09-02 18:25:21 +00:00
Fix #5975: Forget or redeem channels that are never funded.
- initiator: wait until double spent - non-initiator: wait until timeout
This commit is contained in:
parent
ed29a45d50
commit
5785c2fa2f
5 changed files with 36 additions and 5 deletions
|
@ -120,10 +120,12 @@ class ChannelsList(MyTreeView):
|
|||
menu.addAction(_("Close channel"), lambda: self.close_channel(channel_id))
|
||||
menu.addAction(_("Force-close channel"), lambda: self.force_close(channel_id))
|
||||
else:
|
||||
txid, height, timestamp = chan.get_closing_height()
|
||||
closing_tx = self.lnworker.lnwatcher.db.get_transaction(txid)
|
||||
if closing_tx:
|
||||
menu.addAction(_("View closing transaction"), lambda: self.parent.show_transaction(closing_tx))
|
||||
item = chan.get_closing_height()
|
||||
if item:
|
||||
txid, height, timestamp = item
|
||||
closing_tx = self.lnworker.lnwatcher.db.get_transaction(txid)
|
||||
if closing_tx:
|
||||
menu.addAction(_("View closing transaction"), lambda: self.parent.show_transaction(closing_tx))
|
||||
if chan.is_redeemed():
|
||||
menu.addAction(_("Remove"), lambda: self.remove_channel(channel_id))
|
||||
menu.exec_(self.viewport().mapToGlobal(position))
|
||||
|
|
|
@ -97,6 +97,7 @@ state_transitions = [
|
|||
(cs.CLOSING, cs.CLOSED),
|
||||
(cs.FORCE_CLOSING, cs.CLOSED),
|
||||
(cs.CLOSED, cs.REDEEMED),
|
||||
(cs.PREOPENING, cs.REDEEMED), # channel never funded
|
||||
]
|
||||
del cs # delete as name is ambiguous without context
|
||||
|
||||
|
|
|
@ -590,6 +590,7 @@ class Peer(Logger):
|
|||
sweep_address=self.lnworker.sweep_address,
|
||||
lnworker=self.lnworker,
|
||||
initial_feerate=feerate)
|
||||
chan.storage['funding_inputs'] = [txin.prevout for txin in funding_tx.inputs()]
|
||||
sig_64, _ = chan.sign_next_commitment()
|
||||
self.temp_id_to_id[temp_channel_id] = channel_id
|
||||
self.send_message("funding_created",
|
||||
|
@ -684,6 +685,7 @@ class Peer(Logger):
|
|||
sweep_address=self.lnworker.sweep_address,
|
||||
lnworker=self.lnworker,
|
||||
initial_feerate=feerate)
|
||||
chan.storage['init_timestamp'] = int(time.time())
|
||||
remote_sig = funding_created['signature']
|
||||
chan.receive_new_commitment(remote_sig, [])
|
||||
sig_64, _ = chan.sign_next_commitment()
|
||||
|
|
|
@ -322,6 +322,9 @@ class WatchTower(LNWatcher):
|
|||
pass
|
||||
|
||||
|
||||
|
||||
CHANNEL_OPENING_TIMEOUT = 24*60*60
|
||||
|
||||
class LNWalletWatcher(LNWatcher):
|
||||
|
||||
def __init__(self, lnworker, network):
|
||||
|
@ -337,7 +340,7 @@ class LNWalletWatcher(LNWatcher):
|
|||
return
|
||||
if funding_height.height == TX_HEIGHT_LOCAL:
|
||||
chan.delete_funding_height()
|
||||
return
|
||||
await self.lnworker.update_unfunded_channel(chan, funding_txid)
|
||||
elif closing_height.height == TX_HEIGHT_LOCAL:
|
||||
chan.save_funding_height(funding_txid, funding_height.height, funding_height.timestamp)
|
||||
await self.lnworker.update_open_channel(chan, funding_txid, funding_height)
|
||||
|
|
|
@ -654,6 +654,29 @@ class LNWallet(LNWorker):
|
|||
if chan.funding_outpoint.to_str() == txo:
|
||||
return chan
|
||||
|
||||
async def update_unfunded_channel(self, chan, funding_txid):
|
||||
if chan.get_state() in [channel_states.PREOPENING, channel_states.OPENING]:
|
||||
if chan.constraints.is_initiator:
|
||||
inputs = chan.storage.get('funding_inputs', [])
|
||||
if not inputs:
|
||||
self.logger.info(f'channel funding inputs are not provided')
|
||||
chan.set_state(channel_states.REDEEMED)
|
||||
for i in inputs:
|
||||
spender_txid = self.wallet.db.get_spent_outpoint(*i)
|
||||
if spender_txid is None:
|
||||
continue
|
||||
if spender_txid != funding_txid:
|
||||
tx_mined_height = self.wallet.get_tx_height(spender_txid)
|
||||
if tx_mined_height.conf > 6:
|
||||
self.logger.info(f'channel is double spent {inputs}, {ds}')
|
||||
# set to REDEEMED so that it can be removed manually
|
||||
chan.set_state(channel_states.REDEEMED)
|
||||
break
|
||||
else:
|
||||
now = int(time.time())
|
||||
if now - chan.storage.get('init_timestamp', 0) > CHANNEL_INIT_TIMEOUT:
|
||||
self.remove_channel(chan.channel_id)
|
||||
|
||||
async def update_open_channel(self, chan, funding_txid, funding_height):
|
||||
|
||||
if chan.get_state() == channel_states.OPEN and self.should_channel_be_closed_due_to_expiring_htlcs(chan):
|
||||
|
|
Loading…
Add table
Reference in a new issue