lnchannel: chan.lnworker must now always be set, even in unit tests
This commit is contained in:
@@ -183,7 +183,7 @@ class HTLCWithStatus(NamedTuple):
|
|||||||
class AbstractChannel(Logger, ABC):
|
class AbstractChannel(Logger, ABC):
|
||||||
storage: Union['StoredDict', dict]
|
storage: Union['StoredDict', dict]
|
||||||
config: Dict[HTLCOwner, Union[LocalConfig, RemoteConfig]]
|
config: Dict[HTLCOwner, Union[LocalConfig, RemoteConfig]]
|
||||||
lnworker: Optional['LNWallet']
|
lnworker: 'LNWallet'
|
||||||
channel_id: bytes
|
channel_id: bytes
|
||||||
short_channel_id: Optional[ShortChannelID] = None
|
short_channel_id: Optional[ShortChannelID] = None
|
||||||
funding_outpoint: Outpoint
|
funding_outpoint: Outpoint
|
||||||
@@ -218,8 +218,7 @@ class AbstractChannel(Logger, ABC):
|
|||||||
self.logger.debug(f'Setting channel state: {old_state.name} -> {state.name}')
|
self.logger.debug(f'Setting channel state: {old_state.name} -> {state.name}')
|
||||||
self._state = state
|
self._state = state
|
||||||
self.storage['state'] = self._state.name
|
self.storage['state'] = self._state.name
|
||||||
if self.lnworker:
|
self.lnworker.channel_state_changed(self)
|
||||||
self.lnworker.channel_state_changed(self)
|
|
||||||
|
|
||||||
def get_state(self) -> ChannelState:
|
def get_state(self) -> ChannelState:
|
||||||
return self._state
|
return self._state
|
||||||
@@ -250,18 +249,16 @@ class AbstractChannel(Logger, ABC):
|
|||||||
# note: tx might not be directly related to the wallet, e.g. chan opened by remote
|
# note: tx might not be directly related to the wallet, e.g. chan opened by remote
|
||||||
if (funding_item := self.get_funding_height()) is None:
|
if (funding_item := self.get_funding_height()) is None:
|
||||||
return True
|
return True
|
||||||
if self.lnworker:
|
funding_txid, funding_height, funding_timestamp = funding_item
|
||||||
funding_txid, funding_height, funding_timestamp = funding_item
|
if self.lnworker.wallet.adb.get_transaction(funding_txid) is None:
|
||||||
if self.lnworker.wallet.adb.get_transaction(funding_txid) is None:
|
return True
|
||||||
return True
|
|
||||||
# check we have closing tx
|
# check we have closing tx
|
||||||
# note: tx might not be directly related to the wallet, e.g. local-fclose
|
# note: tx might not be directly related to the wallet, e.g. local-fclose
|
||||||
if (closing_item := self.get_closing_height()) is None:
|
if (closing_item := self.get_closing_height()) is None:
|
||||||
return True
|
return True
|
||||||
if self.lnworker:
|
closing_txid, closing_height, closing_timestamp = closing_item
|
||||||
closing_txid, closing_height, closing_timestamp = closing_item
|
if self.lnworker.wallet.adb.get_transaction(closing_txid) is None:
|
||||||
if self.lnworker.wallet.adb.get_transaction(closing_txid) is None:
|
return True
|
||||||
return True
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@@ -354,8 +351,6 @@ class AbstractChannel(Logger, ABC):
|
|||||||
def update_unfunded_state(self) -> None:
|
def update_unfunded_state(self) -> None:
|
||||||
self.delete_funding_height()
|
self.delete_funding_height()
|
||||||
self.delete_closing_height()
|
self.delete_closing_height()
|
||||||
if not self.lnworker:
|
|
||||||
return
|
|
||||||
state = self.get_state()
|
state = self.get_state()
|
||||||
if state in [ChannelState.PREOPENING, ChannelState.OPENING, ChannelState.FORCE_CLOSING]:
|
if state in [ChannelState.PREOPENING, ChannelState.OPENING, ChannelState.FORCE_CLOSING]:
|
||||||
if self.is_initiator():
|
if self.is_initiator():
|
||||||
@@ -395,6 +390,7 @@ class AbstractChannel(Logger, ABC):
|
|||||||
f"we may have been scammed out of {local_balance_sat} sat by our "
|
f"we may have been scammed out of {local_balance_sat} sat by our "
|
||||||
f"JIT provider: {self.lnworker.config.ZEROCONF_TRUSTED_NODE} or he didn't use our preimage")
|
f"JIT provider: {self.lnworker.config.ZEROCONF_TRUSTED_NODE} or he didn't use our preimage")
|
||||||
self.lnworker.config.ZEROCONF_TRUSTED_NODE = ''
|
self.lnworker.config.ZEROCONF_TRUSTED_NODE = ''
|
||||||
|
# FIXME this is broken: lnwatcher.unwatch_channel does not exist
|
||||||
self.lnworker.lnwatcher.unwatch_channel(self.get_funding_address(), self.funding_outpoint.to_str())
|
self.lnworker.lnwatcher.unwatch_channel(self.get_funding_address(), self.funding_outpoint.to_str())
|
||||||
# remove remaining local transactions from the wallet, this will also remove child transactions (closing tx)
|
# remove remaining local transactions from the wallet, this will also remove child transactions (closing tx)
|
||||||
self.lnworker.lnwatcher.adb.remove_transaction(self.funding_outpoint.txid)
|
self.lnworker.lnwatcher.adb.remove_transaction(self.funding_outpoint.txid)
|
||||||
@@ -417,7 +413,7 @@ class AbstractChannel(Logger, ABC):
|
|||||||
if not self.is_funding_tx_mined(funding_height):
|
if not self.is_funding_tx_mined(funding_height):
|
||||||
# funding tx is invalid (invalid amount or address) we need to get rid of the channel again
|
# funding tx is invalid (invalid amount or address) we need to get rid of the channel again
|
||||||
self.should_request_force_close = True
|
self.should_request_force_close = True
|
||||||
if self.lnworker and (peer := self.lnworker.lnpeermgr.get_peer_by_pubkey(self.node_id)):
|
if peer := self.lnworker.lnpeermgr.get_peer_by_pubkey(self.node_id):
|
||||||
# reconnect to trigger force close request
|
# reconnect to trigger force close request
|
||||||
peer.close_and_cleanup()
|
peer.close_and_cleanup()
|
||||||
else:
|
else:
|
||||||
@@ -436,19 +432,17 @@ class AbstractChannel(Logger, ABC):
|
|||||||
conf = closing_height.conf
|
conf = closing_height.conf
|
||||||
if conf > 0:
|
if conf > 0:
|
||||||
self.set_state(ChannelState.CLOSED)
|
self.set_state(ChannelState.CLOSED)
|
||||||
if self.lnworker:
|
self.lnworker.wallet.txbatcher.set_password_future(None)
|
||||||
self.lnworker.wallet.txbatcher.set_password_future(None)
|
|
||||||
else:
|
else:
|
||||||
# we must not trust the server with unconfirmed transactions,
|
# we must not trust the server with unconfirmed transactions,
|
||||||
# because the state transition is irreversible. if the remote
|
# because the state transition is irreversible. if the remote
|
||||||
# force closed, we remain OPEN until the closing tx is confirmed
|
# force closed, we remain OPEN until the closing tx is confirmed
|
||||||
self.unconfirmed_closing_txid = closing_txid
|
self.unconfirmed_closing_txid = closing_txid
|
||||||
if self.lnworker:
|
util.trigger_callback('channel', self.lnworker.wallet, self)
|
||||||
util.trigger_callback('channel', self.lnworker.wallet, self)
|
|
||||||
|
|
||||||
if self.get_state() == ChannelState.CLOSED and not keep_watching:
|
if self.get_state() == ChannelState.CLOSED and not keep_watching:
|
||||||
self.set_state(ChannelState.REDEEMED)
|
self.set_state(ChannelState.REDEEMED)
|
||||||
if self.lnworker and self.is_backup():
|
if self.is_backup():
|
||||||
# auto-remove redeemed backups
|
# auto-remove redeemed backups
|
||||||
self.lnworker.remove_channel_backup(self.channel_id)
|
self.lnworker.remove_channel_backup(self.channel_id)
|
||||||
|
|
||||||
@@ -578,7 +572,7 @@ class ChannelBackup(AbstractChannel):
|
|||||||
- will need to sweep their ctx to_remote
|
- will need to sweep their ctx to_remote
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, cb: ChannelBackupStorage, *, lnworker=None):
|
def __init__(self, cb: ChannelBackupStorage, *, lnworker: 'LNWallet'):
|
||||||
self.name = None
|
self.name = None
|
||||||
self.cb = cb
|
self.cb = cb
|
||||||
self.is_imported = isinstance(self.cb, ImportedChannelBackupStorage)
|
self.is_imported = isinstance(self.cb, ImportedChannelBackupStorage)
|
||||||
@@ -779,7 +773,7 @@ class Channel(AbstractChannel):
|
|||||||
self,
|
self,
|
||||||
state: 'StoredDict', *,
|
state: 'StoredDict', *,
|
||||||
name=None,
|
name=None,
|
||||||
lnworker: 'LNWallet' = None, # None only in unittests
|
lnworker: 'LNWallet',
|
||||||
initial_feerate=None,
|
initial_feerate=None,
|
||||||
jit_opening_fee: Optional[int] = None,
|
jit_opening_fee: Optional[int] = None,
|
||||||
):
|
):
|
||||||
@@ -893,8 +887,6 @@ class Channel(AbstractChannel):
|
|||||||
return self.data_loss_protect_remote_pcp.get(key)
|
return self.data_loss_protect_remote_pcp.get(key)
|
||||||
|
|
||||||
def get_local_pubkey(self) -> bytes:
|
def get_local_pubkey(self) -> bytes:
|
||||||
if not self.lnworker:
|
|
||||||
raise Exception('lnworker not set for channel!')
|
|
||||||
return self.lnworker.node_keypair.pubkey
|
return self.lnworker.node_keypair.pubkey
|
||||||
|
|
||||||
def set_remote_update(self, payload: dict) -> None:
|
def set_remote_update(self, payload: dict) -> None:
|
||||||
@@ -945,8 +937,6 @@ class Channel(AbstractChannel):
|
|||||||
"""
|
"""
|
||||||
if self._outgoing_channel_update is not None and scid is None:
|
if self._outgoing_channel_update is not None and scid is None:
|
||||||
return self._outgoing_channel_update
|
return self._outgoing_channel_update
|
||||||
if not self.lnworker:
|
|
||||||
raise Exception('lnworker not set for channel!')
|
|
||||||
if scid is None:
|
if scid is None:
|
||||||
scid = self.short_channel_id
|
scid = self.short_channel_id
|
||||||
sorted_node_ids = list(sorted([self.node_id, self.get_local_pubkey()]))
|
sorted_node_ids = list(sorted([self.node_id, self.get_local_pubkey()]))
|
||||||
@@ -1022,8 +1012,7 @@ class Channel(AbstractChannel):
|
|||||||
elif self.is_static_remotekey_enabled():
|
elif self.is_static_remotekey_enabled():
|
||||||
our_payment_pubkey = self.config[LOCAL].payment_basepoint.pubkey
|
our_payment_pubkey = self.config[LOCAL].payment_basepoint.pubkey
|
||||||
addr = make_commitment_output_to_remote_address(our_payment_pubkey, has_anchors=self.has_anchors())
|
addr = make_commitment_output_to_remote_address(our_payment_pubkey, has_anchors=self.has_anchors())
|
||||||
if self.lnworker:
|
assert self.lnworker.wallet.is_mine(addr)
|
||||||
assert self.lnworker.wallet.is_mine(addr)
|
|
||||||
return addr
|
return addr
|
||||||
|
|
||||||
def has_anchors(self) -> bool:
|
def has_anchors(self) -> bool:
|
||||||
@@ -1103,7 +1092,7 @@ class Channel(AbstractChannel):
|
|||||||
return self.can_update_ctx(proposer=LOCAL) and self.is_open()
|
return self.can_update_ctx(proposer=LOCAL) and self.is_open()
|
||||||
|
|
||||||
def is_frozen_for_sending(self) -> bool:
|
def is_frozen_for_sending(self) -> bool:
|
||||||
if self.lnworker and self.lnworker.uses_trampoline() and not self.lnworker.is_trampoline_peer(self.node_id):
|
if self.lnworker.uses_trampoline() and not self.lnworker.is_trampoline_peer(self.node_id):
|
||||||
return True
|
return True
|
||||||
return self.storage.get('frozen_for_sending', False)
|
return self.storage.get('frozen_for_sending', False)
|
||||||
|
|
||||||
@@ -1112,7 +1101,7 @@ class Channel(AbstractChannel):
|
|||||||
util.trigger_callback('channel', self.lnworker.wallet, self)
|
util.trigger_callback('channel', self.lnworker.wallet, self)
|
||||||
|
|
||||||
def is_frozen_for_receiving(self) -> bool:
|
def is_frozen_for_receiving(self) -> bool:
|
||||||
if self.lnworker and self.lnworker.uses_trampoline() and not self.lnworker.is_trampoline_peer(self.node_id):
|
if self.lnworker.uses_trampoline() and not self.lnworker.is_trampoline_peer(self.node_id):
|
||||||
return True
|
return True
|
||||||
return self.storage.get('frozen_for_receiving', False)
|
return self.storage.get('frozen_for_receiving', False)
|
||||||
|
|
||||||
@@ -1426,17 +1415,16 @@ class Channel(AbstractChannel):
|
|||||||
self.config[REMOTE].next_per_commitment_point=revocation.next_per_commitment_point
|
self.config[REMOTE].next_per_commitment_point=revocation.next_per_commitment_point
|
||||||
assert new_ctn == self.get_oldest_unrevoked_ctn(REMOTE)
|
assert new_ctn == self.get_oldest_unrevoked_ctn(REMOTE)
|
||||||
# lnworker callbacks
|
# lnworker callbacks
|
||||||
if self.lnworker:
|
sent = self.hm.sent_in_ctn(new_ctn)
|
||||||
sent = self.hm.sent_in_ctn(new_ctn)
|
for htlc in sent:
|
||||||
for htlc in sent:
|
self.lnworker.htlc_fulfilled(self, htlc.payment_hash, htlc.htlc_id)
|
||||||
self.lnworker.htlc_fulfilled(self, htlc.payment_hash, htlc.htlc_id)
|
failed = self.hm.failed_in_ctn(new_ctn)
|
||||||
failed = self.hm.failed_in_ctn(new_ctn)
|
for htlc in failed:
|
||||||
for htlc in failed:
|
try:
|
||||||
try:
|
error_bytes, failure_message = self._receive_fail_reasons.pop(htlc.htlc_id)
|
||||||
error_bytes, failure_message = self._receive_fail_reasons.pop(htlc.htlc_id)
|
except KeyError:
|
||||||
except KeyError:
|
error_bytes, failure_message = None, None
|
||||||
error_bytes, failure_message = None, None
|
self.lnworker.htlc_failed(self, htlc.payment_hash, htlc.htlc_id, error_bytes, failure_message)
|
||||||
self.lnworker.htlc_failed(self, htlc.payment_hash, htlc.htlc_id, error_bytes, failure_message)
|
|
||||||
|
|
||||||
def extract_preimage_from_htlc_txin(self, txin: TxInput, *, is_deeply_mined: bool) -> None:
|
def extract_preimage_from_htlc_txin(self, txin: TxInput, *, is_deeply_mined: bool) -> None:
|
||||||
from . import lnutil
|
from . import lnutil
|
||||||
|
|||||||
Reference in New Issue
Block a user