Skip to content

Commit 28a9735

Browse files
carlaKCTheBlueMatt
andcommitted
ln+util: add test option to enable negotiation of zero fee channels
To allow testing along the way in this PR, turn on negotiation of zero fee channels. Co-authored-by: Matt Corallo <[email protected]>
1 parent a74d1f4 commit 28a9735

File tree

4 files changed

+133
-10
lines changed

4 files changed

+133
-10
lines changed

lightning-types/src/features.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,15 @@ impl ChannelTypeFeatures {
10241024
<sealed::ChannelTypeContext as sealed::AnchorsZeroFeeHtlcTx>::set_required_bit(&mut ret);
10251025
ret
10261026
}
1027+
1028+
/// Constructs a ChannelTypeFeatures with zero fee commitment anchors support.
1029+
pub fn anchors_zero_fee_commitments() -> Self {
1030+
let mut ret = Self::empty();
1031+
<sealed::ChannelTypeContext as sealed::AnchorZeroFeeCommitments>::set_required_bit(
1032+
&mut ret,
1033+
);
1034+
ret
1035+
}
10271036
}
10281037

10291038
impl<T: sealed::Context> Features<T> {

lightning/src/ln/channel.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4867,18 +4867,33 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
48674867
let channel_type = &funding.channel_transaction_parameters.channel_type_features;
48684868
let mut eligible_features = their_features.clone();
48694869

4870-
if channel_type.supports_anchors_zero_fee_htlc_tx() {
4870+
if channel_type.supports_anchor_zero_fee_commitments() {
4871+
eligible_features.clear_anchor_zero_fee_commitments();
4872+
assert!(!eligible_features.supports_anchor_zero_fee_commitments());
4873+
} else if channel_type.supports_anchors_zero_fee_htlc_tx() {
4874+
eligible_features.clear_anchor_zero_fee_commitments();
48714875
eligible_features.clear_anchors_zero_fee_htlc_tx();
4876+
assert!(!eligible_features.supports_anchor_zero_fee_commitments());
48724877
assert!(!eligible_features.supports_anchors_nonzero_fee_htlc_tx());
48734878
} else if channel_type.supports_scid_privacy() {
48744879
eligible_features.clear_scid_privacy();
48754880
eligible_features.clear_anchors_zero_fee_htlc_tx();
4881+
eligible_features.clear_anchor_zero_fee_commitments();
48764882
assert!(!eligible_features.supports_scid_privacy());
48774883
assert!(!eligible_features.supports_anchors_nonzero_fee_htlc_tx());
4884+
assert!(!eligible_features.supports_anchor_zero_fee_commitments());
48784885
}
48794886

48804887
let next_channel_type = get_initial_channel_type(user_config, &eligible_features);
48814888

4889+
// Note that we can't get `anchor_zero_fee_commitments` type here, which requires zero
4890+
// fees, because we downgrade from this channel type first. If there were a superior
4891+
// channel type that downgrades to `anchor_zero_fee_commitments`, we'd need to handle
4892+
// fee setting differently here. If we proceeded to open a `anchor_zero_fee_commitments`
4893+
// channel with non-zero fees, we could produce a non-standard commitment transaction that
4894+
// puts us at risk of losing funds. We would expect our peer to reject such a channel
4895+
// open, but we don't want to rely on their validation.
4896+
assert!(!next_channel_type.supports_anchor_zero_fee_commitments());
48824897
let conf_target = if next_channel_type.supports_anchors_zero_fee_htlc_tx() {
48834898
ConfirmationTarget::AnchorChannelFee
48844899
} else {
@@ -9927,8 +9942,9 @@ pub(super) fn channel_type_from_open_channel(
99279942

99289943
// We only support the channel types defined by the `ChannelManager` in
99299944
// `provided_channel_type_features`. The channel type must always support
9930-
// `static_remote_key`.
9931-
if !channel_type.requires_static_remote_key() {
9945+
// `static_remote_key`, either implicitly with `option_zero_fee_commitments`
9946+
// or explicitly.
9947+
if !channel_type.requires_static_remote_key() && !channel_type.requires_anchor_zero_fee_commitments() {
99329948
return Err(ChannelError::close("Channel Type was not understood - we require static remote key".to_owned()));
99339949
}
99349950
// Make sure we support all of the features behind the channel type.
@@ -10516,10 +10532,21 @@ fn get_initial_channel_type(config: &UserConfig, their_features: &InitFeatures)
1051610532
ret.set_scid_privacy_required();
1051710533
}
1051810534

10519-
// Optionally, if the user would like to negotiate the `anchors_zero_fee_htlc_tx` option, we
10520-
// set it now. If they don't understand it, we'll fall back to our default of
10521-
// `only_static_remotekey`.
10522-
if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx &&
10535+
// Optionally, if the user would like to negotiate `option_zero_fee_commitments` we set it now.
10536+
// If they don't understand it (or we don't want it), we check the same conditions for
10537+
// `option_anchors_zero_fee_htlc_tx`. The counterparty can still refuse the channel and we'll
10538+
// try to fall back (all the way to `only_static_remotekey`).
10539+
#[cfg(not(test))]
10540+
let negotiate_zero_fee_commitments = false;
10541+
10542+
#[cfg(test)]
10543+
let negotiate_zero_fee_commitments = config.channel_handshake_config.negotiate_anchor_zero_fee_commitments;
10544+
10545+
if negotiate_zero_fee_commitments && their_features.supports_anchor_zero_fee_commitments() {
10546+
ret.set_anchor_zero_fee_commitments_required();
10547+
// `option_static_remote_key` is assumed by `option_zero_fee_commitments`.
10548+
ret.clear_static_remote_key();
10549+
} else if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx &&
1052310550
their_features.supports_anchors_zero_fee_htlc_tx() {
1052410551
ret.set_anchors_zero_fee_htlc_tx_required();
1052510552
}

lightning/src/ln/channelmanager.rs

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12932,6 +12932,12 @@ pub fn provided_init_features(config: &UserConfig) -> InitFeatures {
1293212932
// quiescent-dependent protocols (e.g., splicing).
1293312933
#[cfg(any(test, fuzzing))]
1293412934
features.set_quiescence_optional();
12935+
12936+
#[cfg(test)]
12937+
if config.channel_handshake_config.negotiate_anchor_zero_fee_commitments {
12938+
features.set_anchor_zero_fee_commitments_optional();
12939+
}
12940+
1293512941
features
1293612942
}
1293712943

@@ -16173,29 +16179,71 @@ mod tests {
1617316179

1617416180
#[test]
1617516181
fn test_scid_privacy_downgrade() {
16176-
// Tests downgrade from `anchors_zero_fee_htlc_tx` with `option_scid_alias` when the
16182+
// Tests downgrade from `anchors_zero_fee_commitments` with `option_scid_alias` when the
1617716183
// remote node advertises the features but does not accept the channel, asserting that
1617816184
// `option_scid_alias` is the last feature to be downgraded.
1617916185
let mut initiator_cfg = test_default_channel_config();
16186+
initiator_cfg.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
1618016187
initiator_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
1618116188
initiator_cfg.channel_handshake_config.negotiate_scid_privacy = true;
1618216189
initiator_cfg.channel_handshake_config.announce_for_forwarding = false;
1618316190

1618416191
let mut receiver_cfg = test_default_channel_config();
16192+
receiver_cfg.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
1618516193
receiver_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
1618616194
receiver_cfg.channel_handshake_config.negotiate_scid_privacy = true;
1618716195
receiver_cfg.manually_accept_inbound_channels = true;
1618816196

16189-
let mut start_type = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
16197+
let mut start_type = ChannelTypeFeatures::anchors_zero_fee_commitments();
1619016198
start_type.set_scid_privacy_required();
16199+
let mut with_anchors = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies();
16200+
with_anchors.set_scid_privacy_required();
1619116201
let mut with_scid_privacy = ChannelTypeFeatures::only_static_remote_key();
1619216202
with_scid_privacy.set_scid_privacy_required();
1619316203
let static_remote = ChannelTypeFeatures::only_static_remote_key();
16194-
let downgrade_types = vec![with_scid_privacy, static_remote];
16204+
let downgrade_types = vec![with_anchors, with_scid_privacy, static_remote];
16205+
16206+
do_test_channel_type_downgrade(initiator_cfg, receiver_cfg, start_type, downgrade_types);
16207+
}
16208+
16209+
#[test]
16210+
fn test_zero_fee_commitments_downgrade() {
16211+
// Tests that the local node will retry without zero fee commitments in the case where the
16212+
// remote node supports the feature but does not accept it.
16213+
let mut initiator_cfg = test_default_channel_config();
16214+
initiator_cfg.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
16215+
initiator_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
16216+
16217+
let mut receiver_cfg = test_default_channel_config();
16218+
receiver_cfg.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
16219+
receiver_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
16220+
receiver_cfg.manually_accept_inbound_channels = true;
1619516221

16222+
let start_type = ChannelTypeFeatures::anchors_zero_fee_commitments();
16223+
let downgrade_types = vec![
16224+
ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(),
16225+
ChannelTypeFeatures::only_static_remote_key(),
16226+
];
1619616227
do_test_channel_type_downgrade(initiator_cfg, receiver_cfg, start_type, downgrade_types);
1619716228
}
1619816229

16230+
#[test]
16231+
fn test_zero_fee_commitments_downgrade_to_static_remote() {
16232+
// Tests that the local node will retry with static remote key when zero fee commitments
16233+
// are supported (but not accepted), but not legacy anchors.
16234+
let mut initiator_cfg = test_default_channel_config();
16235+
initiator_cfg.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
16236+
initiator_cfg.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
16237+
16238+
let mut receiver_cfg = test_default_channel_config();
16239+
receiver_cfg.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
16240+
receiver_cfg.manually_accept_inbound_channels = true;
16241+
16242+
let start_type = ChannelTypeFeatures::anchors_zero_fee_commitments();
16243+
let end_type = ChannelTypeFeatures::only_static_remote_key();
16244+
do_test_channel_type_downgrade(initiator_cfg, receiver_cfg, start_type, vec![end_type]);
16245+
}
16246+
1619916247
fn do_test_channel_type_downgrade(initiator_cfg: UserConfig, acceptor_cfg: UserConfig,
1620016248
start_type: ChannelTypeFeatures, downgrade_types: Vec<ChannelTypeFeatures>) {
1620116249
let chanmon_cfgs = create_chanmon_cfgs(2);

lightning/src/util/config.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,41 @@ pub struct ChannelHandshakeConfig {
183183
/// [`DecodeError::InvalidValue`]: crate::ln::msgs::DecodeError::InvalidValue
184184
pub negotiate_anchors_zero_fee_htlc_tx: bool,
185185

186+
/// If set, we attempt to negotiate the `zero_fee_commitments` option for all future channels.
187+
///
188+
/// These channels operate very similarly to the `anchors_zero_fee_htlc` channels but rely on
189+
/// [TRUC] to assign zero fee to the commitment transactions themselves, avoiding many protocol
190+
/// edge-cases involving fee updates and greatly simplifying the concept of your "balance" in
191+
/// lightning.
192+
///
193+
/// Like `anchors_zero_fee_htlc` channels, this feature requires having a reserve of onchain
194+
/// funds readily available to bump transactions in the event of a channel force close to avoid
195+
/// the possibility of losing funds.
196+
///
197+
/// Note that if you wish accept inbound channels with anchor outputs, you must enable
198+
/// [`UserConfig::manually_accept_inbound_channels`] and manually accept them with
199+
/// [`ChannelManager::accept_inbound_channel`]. This is done to give you the chance to check
200+
/// whether your reserve of onchain funds is enough to cover the fees for all existing and new
201+
/// channels featuring anchor outputs in the event of a force close.
202+
///
203+
/// If this option is set, channels may be created that will not be readable by LDK versions
204+
/// prior to 0.2, causing [`ChannelManager`]'s read method to return a
205+
/// [`DecodeError::InvalidValue`].
206+
///
207+
/// Note that setting this to true does *not* prevent us from opening channels with
208+
/// counterparties that do not support the `zero_fee_commitments` option; we will simply fall
209+
/// back to a `anchors_zero_fee_htlc` (if [`Self::negotiate_anchors_zero_fee_htlc_tx`]
210+
/// is set) or `static_remote_key` channel.
211+
///
212+
/// Default value: `false` (This value is likely to change to `true` in the future.)
213+
///
214+
/// [TRUC]: (https://bitcoinops.org/en/topics/version-3-transaction-relay/)
215+
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
216+
/// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
217+
/// [`DecodeError::InvalidValue`]: crate::ln::msgs::DecodeError::InvalidValue
218+
#[cfg(test)]
219+
pub negotiate_anchor_zero_fee_commitments: bool,
220+
186221
/// The maximum number of HTLCs in-flight from our counterparty towards us at the same time.
187222
///
188223
/// Increasing the value can help improve liquidity and stability in
@@ -212,6 +247,8 @@ impl Default for ChannelHandshakeConfig {
212247
commit_upfront_shutdown_pubkey: true,
213248
their_channel_reserve_proportional_millionths: 10_000,
214249
negotiate_anchors_zero_fee_htlc_tx: false,
250+
#[cfg(test)]
251+
negotiate_anchor_zero_fee_commitments: false,
215252
our_max_accepted_htlcs: 50,
216253
}
217254
}
@@ -233,6 +270,8 @@ impl Readable for ChannelHandshakeConfig {
233270
commit_upfront_shutdown_pubkey: Readable::read(reader)?,
234271
their_channel_reserve_proportional_millionths: Readable::read(reader)?,
235272
negotiate_anchors_zero_fee_htlc_tx: Readable::read(reader)?,
273+
#[cfg(test)]
274+
negotiate_anchor_zero_fee_commitments: Readable::read(reader)?,
236275
our_max_accepted_htlcs: Readable::read(reader)?,
237276
})
238277
}

0 commit comments

Comments
 (0)