1
0

Do not use network callback to update channel states; call LNWorker methods directly instead.

A callback was used because a single LNWnwatcher object used to be shared for all wallets.
Since wallet now have their own LNWatcher instance, this can be simplified.
This commit is contained in:
ThomasV
2020-02-16 14:26:07 +01:00
parent 36f32651cc
commit 3a35f90aa0
2 changed files with 106 additions and 92 deletions

View File

@@ -61,7 +61,7 @@ from .i18n import _
from .lnrouter import RouteEdge, LNPaymentRoute, is_route_sane_to_use
from .address_synchronizer import TX_HEIGHT_LOCAL
from . import lnsweep
from .lnwatcher import LNWatcher
from .lnwatcher import LNWalletWatcher
if TYPE_CHECKING:
from .network import Network
@@ -408,12 +408,10 @@ class LNWallet(LNWorker):
def start_network(self, network: 'Network'):
assert network
self.lnwatcher = LNWatcher(network)
self.lnwatcher = LNWalletWatcher(self, network)
self.lnwatcher.start_network(network)
self.network = network
daemon = network.daemon
self.network.register_callback(self.on_update_open_channel, ['update_open_channel'])
self.network.register_callback(self.on_update_closed_channel, ['update_closed_channel'])
for chan_id, chan in self.channels.items():
self.lnwatcher.add_channel(chan.funding_outpoint.to_str(), chan.get_funding_address())
@@ -651,17 +649,10 @@ class LNWallet(LNWorker):
if chan.funding_outpoint.to_str() == txo:
return chan
@ignore_exceptions
@log_exceptions
async def on_update_open_channel(self, event, funding_outpoint, funding_txid, funding_height):
chan = self.channel_by_txo(funding_outpoint)
if not chan:
return
async def update_open_channel(self, chan, funding_txid, funding_height):
# return early to prevent overwriting closing_txid with None
if chan.is_closed():
return
# save timestamp regardless of state, so that funding tx is returned in get_history
self.channel_timestamps[bh2u(chan.channel_id)] = chan.funding_outpoint.txid, funding_height.height, funding_height.timestamp, None, None, None
@@ -699,12 +690,8 @@ class LNWallet(LNWorker):
self.logger.info('REBROADCASTING CLOSING TX')
await self.network.try_broadcasting(force_close_tx, 'force-close')
@ignore_exceptions
@log_exceptions
async def on_update_closed_channel(self, event, funding_outpoint, spenders, funding_txid, funding_height, closing_txid, closing_height, closing_tx, keep_watching):
chan = self.channel_by_txo(funding_outpoint)
if not chan:
return
async def update_closed_channel(self, chan, funding_txid, funding_height, closing_txid, closing_height, keep_watching):
# fixme: this is wasteful
self.channel_timestamps[bh2u(chan.channel_id)] = funding_txid, funding_height.height, funding_height.timestamp, closing_txid, closing_height.height, closing_height.timestamp
@@ -719,64 +706,6 @@ class LNWallet(LNWorker):
if chan.get_state() == channel_states.CLOSED and not keep_watching:
chan.set_state(channel_states.REDEEMED)
# detect who closed and set sweep_info
sweep_info_dict = chan.sweep_ctx(closing_tx)
self.logger.info(f'sweep_info_dict length: {len(sweep_info_dict)}')
# create and broadcast transaction
for prevout, sweep_info in sweep_info_dict.items():
name = sweep_info.name
spender_txid = spenders.get(prevout)
if spender_txid is not None:
# TODO handle exceptions for network.get_transaction
# TODO don't do network request every time... save tx at least in memory, or maybe wallet file?
spender_tx = await self.network.get_transaction(spender_txid)
spender_tx = Transaction(spender_tx)
e_htlc_tx = chan.sweep_htlc(closing_tx, spender_tx)
if e_htlc_tx:
spender2 = spenders.get(spender_txid+':0')
if spender2:
self.logger.info(f'htlc is already spent {name}: {prevout}')
else:
self.logger.info(f'trying to redeem htlc {name}: {prevout}')
await self.try_redeem(spender_txid+':0', e_htlc_tx)
else:
self.logger.info(f'outpoint already spent {name}: {prevout}')
else:
self.logger.info(f'trying to redeem {name}: {prevout}')
await self.try_redeem(prevout, sweep_info)
@log_exceptions
async def try_redeem(self, prevout: str, sweep_info: 'SweepInfo') -> None:
name = sweep_info.name
prev_txid, prev_index = prevout.split(':')
broadcast = True
if sweep_info.cltv_expiry:
local_height = self.network.get_local_height()
remaining = sweep_info.cltv_expiry - local_height
if remaining > 0:
self.logger.info('waiting for {}: CLTV ({} > {}), prevout {}'
.format(name, local_height, sweep_info.cltv_expiry, prevout))
broadcast = False
if sweep_info.csv_delay:
prev_height = self.lnwatcher.get_tx_height(prev_txid)
remaining = sweep_info.csv_delay - prev_height.conf
if remaining > 0:
self.logger.info('waiting for {}: CSV ({} >= {}), prevout: {}'
.format(name, prev_height.conf, sweep_info.csv_delay, prevout))
broadcast = False
tx = sweep_info.gen_tx()
if tx is None:
self.logger.info(f'{name} could not claim output: {prevout}, dust')
self.wallet.set_label(tx.txid(), name)
if broadcast:
await self.network.try_broadcasting(tx, name)
else:
# it's OK to add local transaction, the fee will be recomputed
try:
self.wallet.add_future_tx(tx, remaining)
self.logger.info(f'adding future tx: {name}. prevout: {prevout}')
except Exception as e:
self.logger.info(f'could not add future tx: {name}. prevout: {prevout} {str(e)}')
def should_channel_be_closed_due_to_expiring_htlcs(self, chan: Channel) -> bool:
local_height = self.network.get_local_height()