Browse Source

persist_lnwatcher: split try_redeem into two methods:

- maybe_add_redeem_tx
 - maybe_broadcast

Before this commit, local tx that are now persisted
are bot broadcast
patch-4
ThomasV 3 years ago
parent
commit
0ca3d66d15
  1. 7
      electrum/address_synchronizer.py
  2. 66
      electrum/lnwatcher.py

7
electrum/address_synchronizer.py

@ -639,12 +639,9 @@ class AddressSynchronizer(Logger):
return cached_local_height return cached_local_height
return self.network.get_local_height() if self.network else self.db.get('stored_height', 0) return self.network.get_local_height() if self.network else self.db.get('stored_height', 0)
def add_future_tx(self, tx: Transaction, wanted_height: int) -> bool: def set_future_tx(self, txid:str, wanted_height: int):
with self.lock: with self.lock:
tx_was_added = self.add_transaction(tx) self.future_tx[txid] = wanted_height
if tx_was_added:
self.future_tx[tx.txid()] = wanted_height
return tx_was_added
def get_tx_height(self, tx_hash: str) -> TxMinedInfo: def get_tx_height(self, tx_hash: str) -> TxMinedInfo:
if tx_hash is None: # ugly backwards compat... if tx_hash is None: # ugly backwards compat...

66
electrum/lnwatcher.py

@ -12,7 +12,7 @@ from . import util
from .sql_db import SqlDB, sql from .sql_db import SqlDB, sql
from .wallet_db import WalletDB from .wallet_db import WalletDB
from .util import bh2u, bfh, log_exceptions, ignore_exceptions, TxMinedInfo, random_shuffled_copy from .util import bh2u, bfh, log_exceptions, ignore_exceptions, TxMinedInfo, random_shuffled_copy
from .address_synchronizer import AddressSynchronizer, TX_HEIGHT_LOCAL, TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_UNCONFIRMED from .address_synchronizer import AddressSynchronizer, TX_HEIGHT_LOCAL, TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_FUTURE
from .transaction import Transaction, TxOutpoint from .transaction import Transaction, TxOutpoint
from .transaction import match_script_against_template from .transaction import match_script_against_template
from .lnutil import WITNESS_TEMPLATE_RECEIVED_HTLC, WITNESS_TEMPLATE_OFFERED_HTLC from .lnutil import WITNESS_TEMPLATE_RECEIVED_HTLC, WITNESS_TEMPLATE_OFFERED_HTLC
@ -308,7 +308,7 @@ class LNWatcher(Logger):
return TxMinedDepth.SHALLOW return TxMinedDepth.SHALLOW
elif height in (TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT): elif height in (TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT):
return TxMinedDepth.MEMPOOL return TxMinedDepth.MEMPOOL
elif height == TX_HEIGHT_LOCAL: elif height in (TX_HEIGHT_LOCAL, TX_HEIGHT_FUTURE):
return TxMinedDepth.FREE return TxMinedDepth.FREE
elif height > 0 and conf == 0: elif height > 0 and conf == 0:
# unverified but claimed to be mined # unverified but claimed to be mined
@ -432,6 +432,7 @@ class LNWalletWatcher(LNWatcher):
keep_watching=keep_watching) keep_watching=keep_watching)
await self.lnworker.on_channel_update(chan) await self.lnworker.on_channel_update(chan)
@log_exceptions
async def do_breach_remedy(self, funding_outpoint, closing_tx, spenders): async def do_breach_remedy(self, funding_outpoint, closing_tx, spenders):
chan = self.lnworker.channel_by_txo(funding_outpoint) chan = self.lnworker.channel_by_txo(funding_outpoint)
if not chan: if not chan:
@ -443,19 +444,20 @@ class LNWalletWatcher(LNWatcher):
# create and broadcast transaction # create and broadcast transaction
for prevout, sweep_info in sweep_info_dict.items(): for prevout, sweep_info in sweep_info_dict.items():
name = sweep_info.name + ' ' + chan.get_id_for_log() name = sweep_info.name + ' ' + chan.get_id_for_log()
spender_txid = spenders.get(prevout) spender_txid = self.maybe_add_redeem_tx(spenders, prevout, sweep_info, name)
if spender_txid is not None: if spender_txid is not None:
spender_tx = self.adb.get_transaction(spender_txid) spender_tx = self.adb.get_transaction(spender_txid)
if not spender_tx: if not spender_tx:
keep_watching = True keep_watching = True
continue continue
await self.maybe_broadcast(prevout, sweep_info, name, spender_txid)
e_htlc_tx = chan.maybe_sweep_revoked_htlc(closing_tx, spender_tx) e_htlc_tx = chan.maybe_sweep_revoked_htlc(closing_tx, spender_tx)
if e_htlc_tx: if e_htlc_tx:
spender2 = spenders.get(spender_txid+':0') spender2 = self.maybe_add_redeem_tx(spenders, spender_txid+':0', e_htlc_tx, name)
if spender2: if spender2:
await self.maybe_broadcast(prevout, sweep_info, name, spender2)
keep_watching |= not self.is_deeply_mined(spender2) keep_watching |= not self.is_deeply_mined(spender2)
else: else:
await self.try_redeem(spender_txid+':0', e_htlc_tx, chan_id_for_log, name)
keep_watching = True keep_watching = True
else: else:
keep_watching |= not self.is_deeply_mined(spender_txid) keep_watching |= not self.is_deeply_mined(spender_txid)
@ -464,12 +466,37 @@ class LNWalletWatcher(LNWatcher):
spender_txin = spender_tx.inputs()[txin_idx] spender_txin = spender_tx.inputs()[txin_idx]
chan.extract_preimage_from_htlc_txin(spender_txin) chan.extract_preimage_from_htlc_txin(spender_txin)
else: else:
await self.try_redeem(prevout, sweep_info, chan_id_for_log, name)
keep_watching = True keep_watching = True
return keep_watching return keep_watching
@log_exceptions def maybe_add_redeem_tx(self, spenders, prevout: str, sweep_info: 'SweepInfo', name: str):
async def try_redeem(self, prevout: str, sweep_info: 'SweepInfo', chan_id_for_log: str, name: str) -> None: txid = spenders.get(prevout)
if txid:
return txid
prev_txid, prev_index = prevout.split(':')
tx = sweep_info.gen_tx()
if tx is None:
self.logger.info(f'{name} could not claim output: {prevout}, dust')
return
txid = tx.txid()
# it's OK to add local transaction, the fee will be recomputed
try:
tx_was_added = self.adb.add_transaction(tx)
except Exception as e:
self.logger.info(f'could not add future tx: {name}. prevout: {prevout} {str(e)}')
tx_was_added = False
if tx_was_added:
self.lnworker.wallet.set_label(txid, name)
self.logger.info(f'added redeem tx: {name}. prevout: {prevout}')
util.trigger_callback('wallet_updated', self.lnworker.wallet)
return txid
async def maybe_broadcast(self, prevout, sweep_info: 'SweepInfo', name: str, txid: str) -> None:
if self.get_tx_mined_depth(txid) != TxMinedDepth.FREE:
return
tx = self.adb.get_transaction(txid)
if tx is None:
return
prev_txid, prev_index = prevout.split(':') prev_txid, prev_index = prevout.split(':')
broadcast = True broadcast = True
local_height = self.network.get_local_height() local_height = self.network.get_local_height()
@ -477,32 +504,15 @@ class LNWalletWatcher(LNWatcher):
wanted_height = sweep_info.cltv_expiry wanted_height = sweep_info.cltv_expiry
if wanted_height - local_height > 0: if wanted_height - local_height > 0:
broadcast = False broadcast = False
reason = 'waiting for {}: CLTV ({} > {}), prevout {}'.format(name, local_height, sweep_info.cltv_expiry, prevout) reason = 'waiting for {}: CLTV ({} > {})'.format(name, local_height, sweep_info.cltv_expiry)
if sweep_info.csv_delay: if sweep_info.csv_delay:
prev_height = self.adb.get_tx_height(prev_txid) prev_height = self.adb.get_tx_height(prev_txid)
wanted_height = sweep_info.csv_delay + prev_height.height - 1 wanted_height = sweep_info.csv_delay + prev_height.height - 1
if prev_height.height <= 0 or wanted_height - local_height > 0: if prev_height.height <= 0 or wanted_height - local_height > 0:
broadcast = False broadcast = False
reason = 'waiting for {}: CSV ({} >= {}), prevout: {}'.format(name, prev_height.conf, sweep_info.csv_delay, prevout) reason = 'waiting for {}: CSV ({} >= {})'.format(name, prev_height.conf, sweep_info.csv_delay)
tx = sweep_info.gen_tx()
if tx is None:
self.logger.info(f'{name} could not claim output: {prevout}, dust')
return
txid = tx.txid()
self.lnworker.wallet.set_label(txid, name)
if broadcast: if broadcast:
await self.network.try_broadcasting(tx, name) await self.network.try_broadcasting(tx, name)
else: else:
if txid in self.adb.future_tx: self.adb.set_future_tx(tx.txid(), wanted_height)
return
self.logger.debug(f'(chan {chan_id_for_log}) trying to redeem {name}: {prevout}')
self.logger.info(reason)
# it's OK to add local transaction, the fee will be recomputed
try:
tx_was_added = self.adb.add_future_tx(tx, wanted_height)
except Exception as e:
self.logger.info(f'could not add future tx: {name}. prevout: {prevout} {str(e)}')
tx_was_added = False
if tx_was_added:
self.logger.info(f'added future tx: {name}. prevout: {prevout}')
util.trigger_callback('wallet_updated', self.lnworker.wallet) util.trigger_callback('wallet_updated', self.lnworker.wallet)

Loading…
Cancel
Save