/// Maximum value: 1,000,000, any values larger than 1 Million will be treated as 1 Million (or 100%)
/// instead, although channel negotiations will fail in that case.
pub their_channel_reserve_proportional_millionths: u32,
- #[cfg(anchors)]
- /// If set, we attempt to negotiate the `anchors_zero_fee_htlc_tx`option for outbound channels.
+ /// If set, we attempt to negotiate the `anchors_zero_fee_htlc_tx`option for all future
+ /// channels. This feature requires having a reserve of onchain funds readily available to bump
+ /// transactions in the event of a channel force close to avoid the possibility of losing funds.
+ ///
+ /// Note that if you wish accept inbound channels with anchor outputs, you must enable
+ /// [`UserConfig::manually_accept_inbound_channels`] and manually accept them with
+ /// [`ChannelManager::accept_inbound_channel`]. This is done to give you the chance to check
+ /// whether your reserve of onchain funds is enough to cover the fees for all existing and new
+ /// channels featuring anchor outputs in the event of a force close.
///
/// If this option is set, channels may be created that will not be readable by LDK versions
- /// prior to 0.0.114, causing [`ChannelManager`]'s read method to return a
+ /// prior to 0.0.116, causing [`ChannelManager`]'s read method to return a
/// [`DecodeError::InvalidValue`].
///
/// Note that setting this to true does *not* prevent us from opening channels with
/// Default value: false. This value is likely to change to true in the future.
///
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
+ /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
/// [`DecodeError::InvalidValue`]: crate::ln::msgs::DecodeError::InvalidValue
/// [`SIGHASH_SINGLE + update_fee Considered Harmful`]: https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-September/002796.html
pub negotiate_anchors_zero_fee_htlc_tx: bool,
announced_channel: false,
commit_upfront_shutdown_pubkey: true,
their_channel_reserve_proportional_millionths: 10_000,
- #[cfg(anchors)]
negotiate_anchors_zero_fee_htlc_tx: false,
our_max_accepted_htlcs: 50,
}
/// [`Normal`]: crate::chain::chaininterface::ConfirmationTarget::Normal
/// [`Background`]: crate::chain::chaininterface::ConfirmationTarget::Background
pub force_close_avoidance_max_fee_satoshis: u64,
+ /// If set, allows this channel's counterparty to skim an additional fee off this node's inbound
+ /// HTLCs. Useful for liquidity providers to offload on-chain channel costs to end users.
+ ///
+ /// Usage:
+ /// - The payee will set this option and set its invoice route hints to use [intercept scids]
+ /// generated by this channel's counterparty.
+ /// - The counterparty will get an [`HTLCIntercepted`] event upon payment forward, and call
+ /// [`forward_intercepted_htlc`] with less than the amount provided in
+ /// [`HTLCIntercepted::expected_outbound_amount_msat`]. The difference between the expected and
+ /// actual forward amounts is their fee.
+ // TODO: link to LSP JIT channel invoice generation spec when it's merged
+ ///
+ /// # Note
+ /// It's important for payee wallet software to verify that [`PaymentClaimable::amount_msat`] is
+ /// as-expected if this feature is activated, otherwise they may lose money!
+ /// [`PaymentClaimable::counterparty_skimmed_fee_msat`] provides the fee taken by the
+ /// counterparty.
+ ///
+ /// # Note
+ /// Switching this config flag on may break compatibility with versions of LDK prior to 0.0.116.
+ /// Unsetting this flag between restarts may lead to payment receive failures.
+ ///
+ /// Default value: false.
+ ///
+ /// [intercept scids]: crate::ln::channelmanager::ChannelManager::get_intercept_scid
+ /// [`forward_intercepted_htlc`]: crate::ln::channelmanager::ChannelManager::forward_intercepted_htlc
+ /// [`HTLCIntercepted`]: crate::events::Event::HTLCIntercepted
+ /// [`HTLCIntercepted::expected_outbound_amount_msat`]: crate::events::Event::HTLCIntercepted::expected_outbound_amount_msat
+ /// [`PaymentClaimable::amount_msat`]: crate::events::Event::PaymentClaimable::amount_msat
+ /// [`PaymentClaimable::counterparty_skimmed_fee_msat`]: crate::events::Event::PaymentClaimable::counterparty_skimmed_fee_msat
+ // TODO: link to bLIP when it's merged
+ pub accept_underpaying_htlcs: bool,
+}
+
+impl ChannelConfig {
+ /// Applies the given [`ChannelConfigUpdate`] as a partial update to the [`ChannelConfig`].
+ pub fn apply(&mut self, update: &ChannelConfigUpdate) {
+ if let Some(forwarding_fee_proportional_millionths) = update.forwarding_fee_proportional_millionths {
+ self.forwarding_fee_proportional_millionths = forwarding_fee_proportional_millionths;
+ }
+ if let Some(forwarding_fee_base_msat) = update.forwarding_fee_base_msat {
+ self.forwarding_fee_base_msat = forwarding_fee_base_msat;
+ }
+ if let Some(cltv_expiry_delta) = update.cltv_expiry_delta {
+ self.cltv_expiry_delta = cltv_expiry_delta;
+ }
+ if let Some(max_dust_htlc_exposure_msat) = update.max_dust_htlc_exposure_msat {
+ self.max_dust_htlc_exposure_msat = max_dust_htlc_exposure_msat;
+ }
+ if let Some(force_close_avoidance_max_fee_satoshis) = update.force_close_avoidance_max_fee_satoshis {
+ self.force_close_avoidance_max_fee_satoshis = force_close_avoidance_max_fee_satoshis;
+ }
+ }
}
impl Default for ChannelConfig {
cltv_expiry_delta: 6 * 12, // 6 blocks/hour * 12 hours
max_dust_htlc_exposure_msat: 5_000_000,
force_close_avoidance_max_fee_satoshis: 1000,
+ accept_underpaying_htlcs: false,
}
}
}
impl_writeable_tlv_based!(ChannelConfig, {
(0, forwarding_fee_proportional_millionths, required),
+ (1, accept_underpaying_htlcs, (default_value, false)),
(2, forwarding_fee_base_msat, required),
(4, cltv_expiry_delta, required),
(6, max_dust_htlc_exposure_msat, required),
(10, force_close_avoidance_max_fee_satoshis, required),
});
+/// A parallel struct to [`ChannelConfig`] to define partial updates.
+#[allow(missing_docs)]
+pub struct ChannelConfigUpdate {
+ pub forwarding_fee_proportional_millionths: Option<u32>,
+ pub forwarding_fee_base_msat: Option<u32>,
+ pub cltv_expiry_delta: Option<u16>,
+ pub max_dust_htlc_exposure_msat: Option<u64>,
+ pub force_close_avoidance_max_fee_satoshis: Option<u64>,
+}
+
+impl Default for ChannelConfigUpdate {
+ fn default() -> ChannelConfigUpdate {
+ ChannelConfigUpdate {
+ forwarding_fee_proportional_millionths: None,
+ forwarding_fee_base_msat: None,
+ cltv_expiry_delta: None,
+ max_dust_htlc_exposure_msat: None,
+ force_close_avoidance_max_fee_satoshis: None,
+ }
+ }
+}
+
+impl From<ChannelConfig> for ChannelConfigUpdate {
+ fn from(config: ChannelConfig) -> ChannelConfigUpdate {
+ ChannelConfigUpdate {
+ forwarding_fee_proportional_millionths: Some(config.forwarding_fee_proportional_millionths),
+ forwarding_fee_base_msat: Some(config.forwarding_fee_base_msat),
+ cltv_expiry_delta: Some(config.cltv_expiry_delta),
+ max_dust_htlc_exposure_msat: Some(config.max_dust_htlc_exposure_msat),
+ force_close_avoidance_max_fee_satoshis: Some(config.force_close_avoidance_max_fee_satoshis),
+ }
+ }
+}
+
/// Legacy version of [`ChannelConfig`] that stored the static
/// [`ChannelHandshakeConfig::announced_channel`] and
/// [`ChannelHandshakeConfig::commit_upfront_shutdown_pubkey`] fields.
cltv_expiry_delta,
force_close_avoidance_max_fee_satoshis,
forwarding_fee_base_msat,
+ accept_underpaying_htlcs: false,
},
announced_channel,
commit_upfront_shutdown_pubkey,