Merge pull request #10379 from SomberNight/202512_lnpeer_cleanup_anchors
LNWallet: require OPTION_CHANNEL_TYPE
This commit is contained in:
@@ -894,9 +894,6 @@ class Peer(Logger, EventListener):
|
||||
def is_shutdown_anysegwit(self):
|
||||
return self.features.supports(LnFeatures.OPTION_SHUTDOWN_ANYSEGWIT_OPT)
|
||||
|
||||
def is_channel_type(self):
|
||||
return self.features.supports(LnFeatures.OPTION_CHANNEL_TYPE_OPT)
|
||||
|
||||
def accepts_zeroconf(self):
|
||||
return self.features.supports(LnFeatures.OPTION_ZEROCONF_OPT)
|
||||
|
||||
@@ -936,10 +933,11 @@ class Peer(Logger, EventListener):
|
||||
# flexibility to decide an address at closing time
|
||||
upfront_shutdown_script = b''
|
||||
|
||||
if self.use_anchors():
|
||||
assert channel_type is not None
|
||||
if channel_type & ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX: # anchors
|
||||
static_payment_key = self.lnworker.static_payment_key
|
||||
static_remotekey = None
|
||||
else:
|
||||
else: # static_remotekey
|
||||
assert channel_type & channel_type.OPTION_STATIC_REMOTEKEY
|
||||
wallet = self.lnworker.wallet
|
||||
assert wallet.txin_type == 'p2wpkh'
|
||||
@@ -1055,13 +1053,12 @@ class Peer(Logger, EventListener):
|
||||
# Eclair accepts channel_type with that bit, but does not require it.
|
||||
|
||||
# if option_channel_type is negotiated: MUST set channel_type
|
||||
if self.is_channel_type():
|
||||
# if it includes channel_type: MUST set it to a defined type representing the type it wants.
|
||||
open_channel_tlvs['channel_type'] = {
|
||||
'type': our_channel_type.to_bytes_minimal()
|
||||
}
|
||||
# if it includes channel_type: MUST set it to a defined type representing the type it wants.
|
||||
open_channel_tlvs['channel_type'] = {
|
||||
'type': our_channel_type.to_bytes_minimal()
|
||||
}
|
||||
|
||||
if self.use_anchors():
|
||||
if our_channel_type & ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX:
|
||||
multisig_funding_keypair = lnutil.derive_multisig_funding_key_if_we_opened(
|
||||
funding_root_secret=self.lnworker.funding_root_keypair.privkey,
|
||||
remote_node_id_or_prefix=self.pubkey,
|
||||
@@ -1168,7 +1165,7 @@ class Peer(Logger, EventListener):
|
||||
initial_feerate_per_kw=feerate,
|
||||
config=self.network.config,
|
||||
peer_features=self.features,
|
||||
has_anchors=self.use_anchors(),
|
||||
channel_type=our_channel_type,
|
||||
)
|
||||
|
||||
# -> funding created
|
||||
@@ -1285,21 +1282,19 @@ class Peer(Logger, EventListener):
|
||||
channel_type = open_channel_tlvs.get('channel_type') if open_channel_tlvs else None
|
||||
# The receiving node MAY fail the channel if:
|
||||
# option_channel_type was negotiated but the message doesn't include a channel_type
|
||||
if self.is_channel_type() and channel_type is None:
|
||||
if channel_type is None:
|
||||
raise Exception("sender has advertised option_channel_type, but hasn't sent the channel type")
|
||||
# MUST fail the channel if it supports channel_type,
|
||||
# channel_type was set, and the type is not suitable.
|
||||
elif self.is_channel_type() and channel_type is not None:
|
||||
else:
|
||||
channel_type = ChannelType.from_bytes(channel_type['type'], byteorder='big').discard_unknown_and_check()
|
||||
if not channel_type.complies_with_features(self.features):
|
||||
raise Exception("sender has sent a channel type we don't support")
|
||||
assert isinstance(channel_type, ChannelType)
|
||||
|
||||
if self.is_channel_type():
|
||||
is_zeroconf = bool(channel_type & ChannelType.OPTION_ZEROCONF)
|
||||
if is_zeroconf and not self.network.config.ZEROCONF_TRUSTED_NODE.startswith(self.pubkey.hex()):
|
||||
raise Exception(f"not accepting zeroconf from node {self.pubkey}")
|
||||
else:
|
||||
is_zeroconf = False
|
||||
is_zeroconf = bool(channel_type & ChannelType.OPTION_ZEROCONF)
|
||||
if is_zeroconf and not self.network.config.ZEROCONF_TRUSTED_NODE.startswith(self.pubkey.hex()):
|
||||
raise Exception(f"not accepting zeroconf from node {self.pubkey}")
|
||||
|
||||
if self.lnworker.has_recoverable_channels() and not is_zeroconf:
|
||||
# FIXME: we might want to keep the connection open
|
||||
@@ -1324,7 +1319,7 @@ class Peer(Logger, EventListener):
|
||||
self.logger.info(f"just-in-time opening fee: {channel_opening_fee} msat")
|
||||
pass
|
||||
|
||||
if self.use_anchors():
|
||||
if channel_type & ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX:
|
||||
multisig_funding_keypair = lnutil.derive_multisig_funding_key_if_they_opened(
|
||||
funding_root_secret=self.lnworker.funding_root_keypair.privkey,
|
||||
remote_node_id_or_prefix=self.pubkey,
|
||||
@@ -1370,7 +1365,7 @@ class Peer(Logger, EventListener):
|
||||
initial_feerate_per_kw=feerate,
|
||||
config=self.network.config,
|
||||
peer_features=self.features,
|
||||
has_anchors=self.use_anchors(),
|
||||
channel_type=channel_type,
|
||||
)
|
||||
|
||||
channel_flags = ord(payload['channel_flags'])
|
||||
@@ -1390,12 +1385,10 @@ class Peer(Logger, EventListener):
|
||||
'upfront_shutdown_script': {
|
||||
'shutdown_scriptpubkey': local_config.upfront_shutdown_script
|
||||
},
|
||||
'channel_type': {
|
||||
'type': channel_type.to_bytes_minimal(),
|
||||
},
|
||||
}
|
||||
# The sender: if it sets channel_type: MUST set it to the channel_type from open_channel
|
||||
if self.is_channel_type():
|
||||
accept_channel_tlvs['channel_type'] = {
|
||||
'type': channel_type.to_bytes_minimal()
|
||||
}
|
||||
|
||||
self.send_message(
|
||||
'accept_channel',
|
||||
|
||||
@@ -170,8 +170,9 @@ class ChannelConfig(StoredObject):
|
||||
initial_feerate_per_kw: int,
|
||||
config: 'SimpleConfig',
|
||||
peer_features: 'LnFeatures',
|
||||
has_anchors: bool,
|
||||
channel_type: 'ChannelType',
|
||||
) -> None:
|
||||
has_anchors = bool(channel_type & ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX)
|
||||
# first we validate the configs separately
|
||||
local_config.validate_params(funding_sat=funding_sat, config=config, peer_features=peer_features)
|
||||
remote_config.validate_params(funding_sat=funding_sat, config=config, peer_features=peer_features)
|
||||
@@ -1469,12 +1470,6 @@ class LnFeatures(IntFlag):
|
||||
_ln_feature_contexts[OPTION_SUPPORT_LARGE_CHANNEL_OPT] = (LNFC.INIT | LNFC.NODE_ANN)
|
||||
_ln_feature_contexts[OPTION_SUPPORT_LARGE_CHANNEL_REQ] = (LNFC.INIT | LNFC.NODE_ANN)
|
||||
|
||||
OPTION_ANCHOR_OUTPUTS_REQ = 1 << 20
|
||||
OPTION_ANCHOR_OUTPUTS_OPT = 1 << 21
|
||||
_ln_feature_direct_dependencies[OPTION_ANCHOR_OUTPUTS_OPT] = {OPTION_STATIC_REMOTEKEY_OPT}
|
||||
_ln_feature_contexts[OPTION_ANCHOR_OUTPUTS_REQ] = (LNFC.INIT | LNFC.NODE_ANN)
|
||||
_ln_feature_contexts[OPTION_ANCHOR_OUTPUTS_OPT] = (LNFC.INIT | LNFC.NODE_ANN)
|
||||
|
||||
OPTION_ANCHORS_ZERO_FEE_HTLC_REQ = 1 << 22
|
||||
OPTION_ANCHORS_ZERO_FEE_HTLC_OPT = 1 << 23
|
||||
_ln_feature_direct_dependencies[OPTION_ANCHORS_ZERO_FEE_HTLC_OPT] = {OPTION_STATIC_REMOTEKEY_OPT}
|
||||
@@ -1623,12 +1618,11 @@ class LnFeatures(IntFlag):
|
||||
class ChannelType(IntFlag):
|
||||
OPTION_LEGACY_CHANNEL = 0
|
||||
OPTION_STATIC_REMOTEKEY = 1 << 12
|
||||
OPTION_ANCHOR_OUTPUTS = 1 << 20
|
||||
OPTION_ANCHORS_ZERO_FEE_HTLC_TX = 1 << 22
|
||||
OPTION_SCID_ALIAS = 1 << 46
|
||||
OPTION_ZEROCONF = 1 << 50
|
||||
|
||||
def discard_unknown_and_check(self):
|
||||
def discard_unknown_and_check(self) -> 'ChannelType':
|
||||
"""Discards unknown flags and checks flag combination."""
|
||||
flags = list_enabled_bits(self)
|
||||
known_channel_types = []
|
||||
@@ -1647,7 +1641,6 @@ class ChannelType(IntFlag):
|
||||
basic_type = self & ~(ChannelType.OPTION_SCID_ALIAS | ChannelType.OPTION_ZEROCONF)
|
||||
if basic_type not in [
|
||||
ChannelType.OPTION_STATIC_REMOTEKEY,
|
||||
ChannelType.OPTION_ANCHOR_OUTPUTS | ChannelType.OPTION_STATIC_REMOTEKEY,
|
||||
ChannelType.OPTION_ANCHORS_ZERO_FEE_HTLC_TX | ChannelType.OPTION_STATIC_REMOTEKEY
|
||||
]:
|
||||
raise ValueError("Channel type is not a valid flag combination.")
|
||||
|
||||
@@ -203,6 +203,7 @@ LNWALLET_FEATURES = (
|
||||
| LnFeatures.OPTION_SHUTDOWN_ANYSEGWIT_OPT
|
||||
| LnFeatures.OPTION_SCID_ALIAS_OPT
|
||||
| LnFeatures.OPTION_SUPPORT_LARGE_CHANNEL_OPT
|
||||
| LnFeatures.OPTION_CHANNEL_TYPE_REQ
|
||||
)
|
||||
|
||||
LNGOSSIP_FEATURES = (
|
||||
|
||||
Reference in New Issue
Block a user