remove support for channels without static remote pubkey
This commit is contained in:
@@ -179,7 +179,6 @@ class AbstractChannel(Logger, ABC):
|
|||||||
config: Dict[HTLCOwner, Union[LocalConfig, RemoteConfig]]
|
config: Dict[HTLCOwner, Union[LocalConfig, RemoteConfig]]
|
||||||
_sweep_info: Dict[str, Dict[str, 'SweepInfo']]
|
_sweep_info: Dict[str, Dict[str, 'SweepInfo']]
|
||||||
lnworker: Optional['LNWallet']
|
lnworker: Optional['LNWallet']
|
||||||
_fallback_sweep_address: str
|
|
||||||
channel_id: bytes
|
channel_id: bytes
|
||||||
short_channel_id: Optional[ShortChannelID] = None
|
short_channel_id: Optional[ShortChannelID] = None
|
||||||
funding_outpoint: Outpoint
|
funding_outpoint: Outpoint
|
||||||
@@ -355,19 +354,6 @@ class AbstractChannel(Logger, ABC):
|
|||||||
# auto-remove redeemed backups
|
# auto-remove redeemed backups
|
||||||
self.lnworker.remove_channel_backup(self.channel_id)
|
self.lnworker.remove_channel_backup(self.channel_id)
|
||||||
|
|
||||||
@property
|
|
||||||
def sweep_address(self) -> str:
|
|
||||||
# TODO: in case of unilateral close with pending HTLCs, this address will be reused
|
|
||||||
addr = None
|
|
||||||
if self.is_static_remotekey_enabled():
|
|
||||||
our_payment_pubkey = self.config[LOCAL].payment_basepoint.pubkey
|
|
||||||
addr = make_commitment_output_to_remote_address(our_payment_pubkey)
|
|
||||||
if addr is None:
|
|
||||||
addr = self._fallback_sweep_address
|
|
||||||
assert addr
|
|
||||||
if self.lnworker:
|
|
||||||
assert self.lnworker.wallet.is_mine(addr)
|
|
||||||
return addr
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def is_initiator(self) -> bool:
|
def is_initiator(self) -> bool:
|
||||||
@@ -456,13 +442,12 @@ class ChannelBackup(AbstractChannel):
|
|||||||
- will need to sweep their ctx to_remote
|
- will need to sweep their ctx to_remote
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, cb: ChannelBackupStorage, *, sweep_address=None, lnworker=None):
|
def __init__(self, cb: ChannelBackupStorage, *, lnworker=None):
|
||||||
self.name = None
|
self.name = None
|
||||||
Logger.__init__(self)
|
Logger.__init__(self)
|
||||||
self.cb = cb
|
self.cb = cb
|
||||||
self.is_imported = isinstance(self.cb, ImportedChannelBackupStorage)
|
self.is_imported = isinstance(self.cb, ImportedChannelBackupStorage)
|
||||||
self._sweep_info = {}
|
self._sweep_info = {}
|
||||||
self._fallback_sweep_address = sweep_address
|
|
||||||
self.storage = {} # dummy storage
|
self.storage = {} # dummy storage
|
||||||
self._state = ChannelState.OPENING
|
self._state = ChannelState.OPENING
|
||||||
self.node_id = cb.node_id if self.is_imported else cb.node_id_prefix
|
self.node_id = cb.node_id if self.is_imported else cb.node_id_prefix
|
||||||
@@ -566,10 +551,13 @@ class ChannelBackup(AbstractChannel):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def is_static_remotekey_enabled(self) -> bool:
|
def is_static_remotekey_enabled(self) -> bool:
|
||||||
# Return False so that self.sweep_address will return self._fallback_sweep_address
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sweep_address(self) -> str:
|
||||||
# Since channel backups do not save the static_remotekey, payment_basepoint in
|
# Since channel backups do not save the static_remotekey, payment_basepoint in
|
||||||
# their local config is not static)
|
# their local config is not static)
|
||||||
return False
|
return self.lnworker.wallet.get_new_sweep_address_for_channel()
|
||||||
|
|
||||||
def get_local_pubkey(self) -> bytes:
|
def get_local_pubkey(self) -> bytes:
|
||||||
cb = self.cb
|
cb = self.cb
|
||||||
@@ -600,13 +588,12 @@ class Channel(AbstractChannel):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "Channel(%s)"%self.get_id_for_log()
|
return "Channel(%s)"%self.get_id_for_log()
|
||||||
|
|
||||||
def __init__(self, state: 'StoredDict', *, sweep_address=None, name=None, lnworker=None, initial_feerate=None):
|
def __init__(self, state: 'StoredDict', *, name=None, lnworker=None, initial_feerate=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.channel_id = bfh(state["channel_id"])
|
self.channel_id = bfh(state["channel_id"])
|
||||||
self.short_channel_id = ShortChannelID.normalize(state["short_channel_id"])
|
self.short_channel_id = ShortChannelID.normalize(state["short_channel_id"])
|
||||||
Logger.__init__(self) # should be after short_channel_id is set
|
Logger.__init__(self) # should be after short_channel_id is set
|
||||||
self.lnworker = lnworker
|
self.lnworker = lnworker
|
||||||
self._fallback_sweep_address = sweep_address
|
|
||||||
self.storage = state
|
self.storage = state
|
||||||
self.db_lock = self.storage.db.lock if self.storage.db else threading.RLock()
|
self.db_lock = self.storage.db.lock if self.storage.db else threading.RLock()
|
||||||
self.config = {}
|
self.config = {}
|
||||||
@@ -763,13 +750,22 @@ class Channel(AbstractChannel):
|
|||||||
channel_type = ChannelType(self.storage.get('channel_type'))
|
channel_type = ChannelType(self.storage.get('channel_type'))
|
||||||
return bool(channel_type & ChannelType.OPTION_STATIC_REMOTEKEY)
|
return bool(channel_type & ChannelType.OPTION_STATIC_REMOTEKEY)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sweep_address(self) -> str:
|
||||||
|
# TODO: in case of unilateral close with pending HTLCs, this address will be reused
|
||||||
|
addr = None
|
||||||
|
assert self.is_static_remotekey_enabled()
|
||||||
|
our_payment_pubkey = self.config[LOCAL].payment_basepoint.pubkey
|
||||||
|
addr = make_commitment_output_to_remote_address(our_payment_pubkey)
|
||||||
|
if self.lnworker:
|
||||||
|
assert self.lnworker.wallet.is_mine(addr)
|
||||||
|
return addr
|
||||||
|
|
||||||
def get_wallet_addresses_channel_might_want_reserved(self) -> Sequence[str]:
|
def get_wallet_addresses_channel_might_want_reserved(self) -> Sequence[str]:
|
||||||
ret = []
|
assert self.is_static_remotekey_enabled()
|
||||||
if self.is_static_remotekey_enabled():
|
our_payment_pubkey = self.config[LOCAL].payment_basepoint.pubkey
|
||||||
our_payment_pubkey = self.config[LOCAL].payment_basepoint.pubkey
|
to_remote_address = make_commitment_output_to_remote_address(our_payment_pubkey)
|
||||||
to_remote_address = make_commitment_output_to_remote_address(our_payment_pubkey)
|
return [to_remote_address]
|
||||||
ret.append(to_remote_address)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def get_feerate(self, subject: HTLCOwner, *, ctn: int) -> int:
|
def get_feerate(self, subject: HTLCOwner, *, ctn: int) -> int:
|
||||||
# returns feerate in sat/kw
|
# returns feerate in sat/kw
|
||||||
@@ -1471,12 +1467,8 @@ class Channel(AbstractChannel):
|
|||||||
feerate=feerate,
|
feerate=feerate,
|
||||||
is_local_initiator=self.constraints.is_initiator == (subject == LOCAL),
|
is_local_initiator=self.constraints.is_initiator == (subject == LOCAL),
|
||||||
)
|
)
|
||||||
|
assert self.is_static_remotekey_enabled()
|
||||||
if self.is_static_remotekey_enabled():
|
payment_pubkey = other_config.payment_basepoint.pubkey
|
||||||
payment_pubkey = other_config.payment_basepoint.pubkey
|
|
||||||
else:
|
|
||||||
payment_pubkey = derive_pubkey(other_config.payment_basepoint.pubkey, this_point)
|
|
||||||
|
|
||||||
return make_commitment(
|
return make_commitment(
|
||||||
ctn=ctn,
|
ctn=ctn,
|
||||||
local_funding_pubkey=this_config.multisig_key.pubkey,
|
local_funding_pubkey=this_config.multisig_key.pubkey,
|
||||||
|
|||||||
@@ -847,7 +847,6 @@ class Peer(Logger):
|
|||||||
channel_id, outpoint, local_config, remote_config, constraints, our_channel_type)
|
channel_id, outpoint, local_config, remote_config, constraints, our_channel_type)
|
||||||
chan = Channel(
|
chan = Channel(
|
||||||
storage,
|
storage,
|
||||||
sweep_address=self.lnworker.sweep_address,
|
|
||||||
lnworker=self.lnworker,
|
lnworker=self.lnworker,
|
||||||
initial_feerate=feerate
|
initial_feerate=feerate
|
||||||
)
|
)
|
||||||
@@ -1026,7 +1025,6 @@ class Peer(Logger):
|
|||||||
channel_id, outpoint, local_config, remote_config, constraints, channel_type)
|
channel_id, outpoint, local_config, remote_config, constraints, channel_type)
|
||||||
chan = Channel(
|
chan = Channel(
|
||||||
chan_dict,
|
chan_dict,
|
||||||
sweep_address=self.lnworker.sweep_address,
|
|
||||||
lnworker=self.lnworker,
|
lnworker=self.lnworker,
|
||||||
initial_feerate=feerate
|
initial_feerate=feerate
|
||||||
)
|
)
|
||||||
@@ -1154,18 +1152,7 @@ class Peer(Logger):
|
|||||||
f"channel_reestablish ({chan.get_id_for_log()}): "
|
f"channel_reestablish ({chan.get_id_for_log()}): "
|
||||||
f"(DLP) local PCS mismatch: {bh2u(our_pcs)} != {bh2u(their_claim_of_our_last_per_commitment_secret)}")
|
f"(DLP) local PCS mismatch: {bh2u(our_pcs)} != {bh2u(their_claim_of_our_last_per_commitment_secret)}")
|
||||||
return False
|
return False
|
||||||
if chan.is_static_remotekey_enabled():
|
assert chan.is_static_remotekey_enabled()
|
||||||
return True
|
|
||||||
try:
|
|
||||||
__, our_remote_pcp = chan.get_secret_and_point(REMOTE, their_next_local_ctn - 1)
|
|
||||||
except RemoteCtnTooFarInFuture:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if our_remote_pcp != their_local_pcp:
|
|
||||||
self.logger.error(
|
|
||||||
f"channel_reestablish ({chan.get_id_for_log()}): "
|
|
||||||
f"(DLP) remote PCP mismatch: {bh2u(our_remote_pcp)} != {bh2u(their_local_pcp)}")
|
|
||||||
return False
|
|
||||||
return True
|
return True
|
||||||
if not are_datalossprotect_fields_valid():
|
if not are_datalossprotect_fields_valid():
|
||||||
raise RemoteMisbehaving("channel_reestablish: data loss protect fields invalid")
|
raise RemoteMisbehaving("channel_reestablish: data loss protect fields invalid")
|
||||||
@@ -1215,10 +1202,8 @@ class Peer(Logger):
|
|||||||
# BOLT-02: "A node [...] upon disconnection [...] MUST reverse any uncommitted updates sent by the other side"
|
# BOLT-02: "A node [...] upon disconnection [...] MUST reverse any uncommitted updates sent by the other side"
|
||||||
chan.hm.discard_unsigned_remote_updates()
|
chan.hm.discard_unsigned_remote_updates()
|
||||||
# send message
|
# send message
|
||||||
if chan.is_static_remotekey_enabled():
|
assert chan.is_static_remotekey_enabled()
|
||||||
latest_secret, latest_point = chan.get_secret_and_point(LOCAL, 0)
|
latest_secret, latest_point = chan.get_secret_and_point(LOCAL, 0)
|
||||||
else:
|
|
||||||
latest_secret, latest_point = chan.get_secret_and_point(LOCAL, latest_local_ctn)
|
|
||||||
if oldest_unrevoked_remote_ctn == 0:
|
if oldest_unrevoked_remote_ctn == 0:
|
||||||
last_rev_secret = 0
|
last_rev_secret = 0
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -205,8 +205,8 @@ def create_sweeptxs_for_our_ctx(
|
|||||||
their_revocation_pubkey, to_self_delay, our_localdelayed_pubkey))
|
their_revocation_pubkey, to_self_delay, our_localdelayed_pubkey))
|
||||||
to_local_address = redeem_script_to_address('p2wsh', to_local_witness_script)
|
to_local_address = redeem_script_to_address('p2wsh', to_local_witness_script)
|
||||||
# to remote address
|
# to remote address
|
||||||
bpk = their_conf.payment_basepoint.pubkey
|
assert chan.is_static_remotekey_enabled()
|
||||||
their_payment_pubkey = bpk if chan.is_static_remotekey_enabled() else derive_pubkey(their_conf.payment_basepoint.pubkey, our_pcp)
|
their_payment_pubkey = their_conf.payment_basepoint.pubkey
|
||||||
to_remote_address = make_commitment_output_to_remote_address(their_payment_pubkey)
|
to_remote_address = make_commitment_output_to_remote_address(their_payment_pubkey)
|
||||||
# test ctx
|
# test ctx
|
||||||
_logger.debug(f'testing our ctx: {to_local_address} {to_remote_address}')
|
_logger.debug(f'testing our ctx: {to_local_address} {to_remote_address}')
|
||||||
@@ -356,8 +356,8 @@ def create_sweeptxs_for_their_ctx(
|
|||||||
our_revocation_pubkey, our_conf.to_self_delay, their_delayed_pubkey))
|
our_revocation_pubkey, our_conf.to_self_delay, their_delayed_pubkey))
|
||||||
to_local_address = redeem_script_to_address('p2wsh', witness_script)
|
to_local_address = redeem_script_to_address('p2wsh', witness_script)
|
||||||
# to remote address
|
# to remote address
|
||||||
bpk = our_conf.payment_basepoint.pubkey
|
assert chan.is_static_remotekey_enabled()
|
||||||
our_payment_pubkey = bpk if chan.is_static_remotekey_enabled() else derive_pubkey(bpk, their_pcp)
|
our_payment_pubkey = our_conf.payment_basepoint.pubkey
|
||||||
to_remote_address = make_commitment_output_to_remote_address(our_payment_pubkey)
|
to_remote_address = make_commitment_output_to_remote_address(our_payment_pubkey)
|
||||||
# test if this is their ctx
|
# test if this is their ctx
|
||||||
_logger.debug(f'testing their ctx: {to_local_address} {to_remote_address}')
|
_logger.debug(f'testing their ctx: {to_local_address} {to_remote_address}')
|
||||||
@@ -379,27 +379,6 @@ def create_sweeptxs_for_their_ctx(
|
|||||||
our_htlc_privkey = ecc.ECPrivkey.from_secret_scalar(our_htlc_privkey)
|
our_htlc_privkey = ecc.ECPrivkey.from_secret_scalar(our_htlc_privkey)
|
||||||
their_htlc_pubkey = derive_pubkey(their_conf.htlc_basepoint.pubkey, their_pcp)
|
their_htlc_pubkey = derive_pubkey(their_conf.htlc_basepoint.pubkey, their_pcp)
|
||||||
# to_local is handled by lnwatcher
|
# to_local is handled by lnwatcher
|
||||||
# to_remote
|
|
||||||
if not chan.is_static_remotekey_enabled():
|
|
||||||
our_payment_bp_privkey = ecc.ECPrivkey(our_conf.payment_basepoint.privkey)
|
|
||||||
our_payment_privkey = derive_privkey(our_payment_bp_privkey.secret_scalar, their_pcp)
|
|
||||||
our_payment_privkey = ecc.ECPrivkey.from_secret_scalar(our_payment_privkey)
|
|
||||||
assert our_payment_pubkey == our_payment_privkey.get_public_key_bytes(compressed=True)
|
|
||||||
output_idxs = ctx.get_output_idxs_from_address(to_remote_address)
|
|
||||||
if output_idxs:
|
|
||||||
output_idx = output_idxs.pop()
|
|
||||||
prevout = ctx.txid() + ':%d'%output_idx
|
|
||||||
sweep_tx = lambda: create_sweeptx_their_ctx_to_remote(
|
|
||||||
sweep_address=sweep_address,
|
|
||||||
ctx=ctx,
|
|
||||||
output_idx=output_idx,
|
|
||||||
our_payment_privkey=our_payment_privkey,
|
|
||||||
config=chan.lnworker.config)
|
|
||||||
txs[prevout] = SweepInfo(
|
|
||||||
name='their_ctx_to_remote',
|
|
||||||
csv_delay=0,
|
|
||||||
cltv_expiry=0,
|
|
||||||
gen_tx=sweep_tx)
|
|
||||||
# HTLCs
|
# HTLCs
|
||||||
def create_sweeptx_for_htlc(
|
def create_sweeptx_for_htlc(
|
||||||
*, htlc: 'UpdateAddHtlc',
|
*, htlc: 'UpdateAddHtlc',
|
||||||
|
|||||||
@@ -630,7 +630,6 @@ class LNWallet(LNWorker):
|
|||||||
self.payment_info = self.db.get_dict('lightning_payments') # RHASH -> amount, direction, is_paid
|
self.payment_info = self.db.get_dict('lightning_payments') # RHASH -> amount, direction, is_paid
|
||||||
self.preimages = self.db.get_dict('lightning_preimages') # RHASH -> preimage
|
self.preimages = self.db.get_dict('lightning_preimages') # RHASH -> preimage
|
||||||
# note: this sweep_address is only used as fallback; as it might result in address-reuse
|
# note: this sweep_address is only used as fallback; as it might result in address-reuse
|
||||||
self.sweep_address = wallet.get_new_sweep_address_for_channel()
|
|
||||||
self.logs = defaultdict(list) # type: Dict[str, List[HtlcLog]] # key is RHASH # (not persisted)
|
self.logs = defaultdict(list) # type: Dict[str, List[HtlcLog]] # key is RHASH # (not persisted)
|
||||||
# used in tests
|
# used in tests
|
||||||
self.enable_htlc_settle = True
|
self.enable_htlc_settle = True
|
||||||
@@ -640,14 +639,14 @@ class LNWallet(LNWorker):
|
|||||||
self._channels = {} # type: Dict[bytes, Channel]
|
self._channels = {} # type: Dict[bytes, Channel]
|
||||||
channels = self.db.get_dict("channels")
|
channels = self.db.get_dict("channels")
|
||||||
for channel_id, c in random_shuffled_copy(channels.items()):
|
for channel_id, c in random_shuffled_copy(channels.items()):
|
||||||
self._channels[bfh(channel_id)] = Channel(c, sweep_address=self.sweep_address, lnworker=self)
|
self._channels[bfh(channel_id)] = Channel(c, lnworker=self)
|
||||||
|
|
||||||
self._channel_backups = {} # type: Dict[bytes, ChannelBackup]
|
self._channel_backups = {} # type: Dict[bytes, ChannelBackup]
|
||||||
# order is important: imported should overwrite onchain
|
# order is important: imported should overwrite onchain
|
||||||
for name in ["onchain_channel_backups", "imported_channel_backups"]:
|
for name in ["onchain_channel_backups", "imported_channel_backups"]:
|
||||||
channel_backups = self.db.get_dict(name)
|
channel_backups = self.db.get_dict(name)
|
||||||
for channel_id, storage in channel_backups.items():
|
for channel_id, storage in channel_backups.items():
|
||||||
self._channel_backups[bfh(channel_id)] = ChannelBackup(storage, sweep_address=self.sweep_address, lnworker=self)
|
self._channel_backups[bfh(channel_id)] = ChannelBackup(storage, lnworker=self)
|
||||||
|
|
||||||
self.sent_htlcs = defaultdict(asyncio.Queue) # type: Dict[bytes, asyncio.Queue[HtlcLog]]
|
self.sent_htlcs = defaultdict(asyncio.Queue) # type: Dict[bytes, asyncio.Queue[HtlcLog]]
|
||||||
self.sent_htlcs_info = dict() # (RHASH, scid, htlc_id) -> route, payment_secret, amount_msat, bucket_msat, trampoline_fee_level
|
self.sent_htlcs_info = dict() # (RHASH, scid, htlc_id) -> route, payment_secret, amount_msat, bucket_msat, trampoline_fee_level
|
||||||
@@ -2502,7 +2501,7 @@ class LNWallet(LNWorker):
|
|||||||
d = self.db.get_dict("imported_channel_backups")
|
d = self.db.get_dict("imported_channel_backups")
|
||||||
d[channel_id.hex()] = cb_storage
|
d[channel_id.hex()] = cb_storage
|
||||||
with self.lock:
|
with self.lock:
|
||||||
cb = ChannelBackup(cb_storage, sweep_address=self.sweep_address, lnworker=self)
|
cb = ChannelBackup(cb_storage, lnworker=self)
|
||||||
self._channel_backups[channel_id] = cb
|
self._channel_backups[channel_id] = cb
|
||||||
self.wallet.save_db()
|
self.wallet.save_db()
|
||||||
util.trigger_callback('channels_updated', self.wallet)
|
util.trigger_callback('channels_updated', self.wallet)
|
||||||
@@ -2616,7 +2615,7 @@ class LNWallet(LNWorker):
|
|||||||
self.logger.info(f"adding backup from tx")
|
self.logger.info(f"adding backup from tx")
|
||||||
d = self.db.get_dict("onchain_channel_backups")
|
d = self.db.get_dict("onchain_channel_backups")
|
||||||
d[channel_id] = cb_storage
|
d[channel_id] = cb_storage
|
||||||
cb = ChannelBackup(cb_storage, sweep_address=self.sweep_address, lnworker=self)
|
cb = ChannelBackup(cb_storage, lnworker=self)
|
||||||
self.wallet.save_db()
|
self.wallet.save_db()
|
||||||
with self.lock:
|
with self.lock:
|
||||||
self._channel_backups[bfh(channel_id)] = cb
|
self._channel_backups[bfh(channel_id)] = cb
|
||||||
|
|||||||
Reference in New Issue
Block a user