@@ -51,7 +51,7 @@ use ln::onion_utils;
51
51
use ln:: msgs:: { ChannelMessageHandler , DecodeError , LightningError , MAX_VALUE_MSAT , OptionalField } ;
52
52
use ln:: wire:: Encode ;
53
53
use chain:: keysinterface:: { Sign , KeysInterface , KeysManager , InMemorySigner , Recipient } ;
54
- use util:: config:: UserConfig ;
54
+ use util:: config:: { UserConfig , ChannelConfig } ;
55
55
use util:: events:: { EventHandler , EventsProvider , MessageSendEvent , MessageSendEventsProvider , ClosureReason } ;
56
56
use util:: { byte_utils, events} ;
57
57
use util:: scid_utils:: fake_scid;
@@ -1101,6 +1101,10 @@ pub struct ChannelDetails {
1101
1101
pub inbound_htlc_minimum_msat : Option < u64 > ,
1102
1102
/// The largest value HTLC (in msat) we currently will accept, for this channel.
1103
1103
pub inbound_htlc_maximum_msat : Option < u64 > ,
1104
+ /// Set of configurable parameters that affect channel operation.
1105
+ ///
1106
+ /// This field is only `None` for `ChannelDetails` objects serialized prior to LDK 0.0.109.
1107
+ pub config : Option < ChannelConfig > ,
1104
1108
}
1105
1109
1106
1110
impl ChannelDetails {
@@ -1765,7 +1769,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1765
1769
is_usable : channel. is_live ( ) ,
1766
1770
is_public : channel. should_announce ( ) ,
1767
1771
inbound_htlc_minimum_msat : Some ( channel. get_holder_htlc_minimum_msat ( ) ) ,
1768
- inbound_htlc_maximum_msat : channel. get_holder_htlc_maximum_msat ( )
1772
+ inbound_htlc_maximum_msat : channel. get_holder_htlc_maximum_msat ( ) ,
1773
+ config : Some ( channel. config ( ) ) ,
1769
1774
} ) ;
1770
1775
}
1771
1776
}
@@ -2231,7 +2236,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2231
2236
} ,
2232
2237
Some ( id) => Some ( id. clone ( ) ) ,
2233
2238
} ;
2234
- let ( chan_update_opt, forwardee_cltv_expiry_delta ) = if let Some ( forwarding_id) = forwarding_id_opt {
2239
+ let chan_update_opt = if let Some ( forwarding_id) = forwarding_id_opt {
2235
2240
let chan = channel_state. as_mut ( ) . unwrap ( ) . by_id . get_mut ( & forwarding_id) . unwrap ( ) ;
2236
2241
if !chan. should_announce ( ) && !self . default_configuration . accept_forwards_to_priv_channels {
2237
2242
// Note that the behavior here should be identical to the above block - we
@@ -2258,18 +2263,20 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2258
2263
if * amt_to_forward < chan. get_counterparty_htlc_minimum_msat ( ) { // amount_below_minimum
2259
2264
break Some ( ( "HTLC amount was below the htlc_minimum_msat" , 0x1000 | 11 , chan_update_opt) ) ;
2260
2265
}
2261
- let fee = amt_to_forward. checked_mul ( chan. get_fee_proportional_millionths ( ) as u64 )
2262
- . and_then ( |prop_fee| { ( prop_fee / 1000000 )
2263
- . checked_add ( chan. get_outbound_forwarding_fee_base_msat ( ) as u64 ) } ) ;
2264
- if fee. is_none ( ) || msg. amount_msat < fee. unwrap ( ) || ( msg. amount_msat - fee. unwrap ( ) ) < * amt_to_forward { // fee_insufficient
2265
- break Some ( ( "Prior hop has deviated from specified fees parameters or origin node has obsolete ones" , 0x1000 | 12 , chan_update_opt) ) ;
2266
+ if let Err ( ( err, code) ) = chan. htlc_satisfies_config ( & msg, * amt_to_forward, * outgoing_cltv_value) {
2267
+ break Some ( ( err, code, chan_update_opt) ) ;
2268
+ }
2269
+ chan_update_opt
2270
+ } else {
2271
+ if ( msg. cltv_expiry as u64 ) < ( * outgoing_cltv_value) as u64 + MIN_CLTV_EXPIRY_DELTA as u64 { // incorrect_cltv_expiry
2272
+ break Some ( (
2273
+ "Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta" ,
2274
+ 0x1000 | 13 , None ,
2275
+ ) ) ;
2266
2276
}
2267
- ( chan_update_opt , chan . get_cltv_expiry_delta ( ) )
2268
- } else { ( None , MIN_CLTV_EXPIRY_DELTA ) } ;
2277
+ None
2278
+ } ;
2269
2279
2270
- if ( msg. cltv_expiry as u64 ) < ( * outgoing_cltv_value) as u64 + forwardee_cltv_expiry_delta as u64 { // incorrect_cltv_expiry
2271
- break Some ( ( "Forwarding node has tampered with the intended HTLC values or origin node has an obsolete cltv_expiry_delta" , 0x1000 | 13 , chan_update_opt) ) ;
2272
- }
2273
2280
let cur_height = self . best_block . read ( ) . unwrap ( ) . height ( ) + 1 ;
2274
2281
// Theoretically, channel counterparty shouldn't send us a HTLC expiring now,
2275
2282
// but we want to be robust wrt to counterparty packet sanitization (see
@@ -2940,6 +2947,73 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2940
2947
}
2941
2948
}
2942
2949
2950
+ /// Atomically updates the [`ChannelConfig`] for the given channels.
2951
+ ///
2952
+ /// Once the updates are applied, each eligible channel (advertised with a known short channel
2953
+ /// ID and a change in [`forwarding_fee_proportional_millionths`], [`forwarding_fee_base_msat`],
2954
+ /// or [`cltv_expiry_delta`]) has a [`BroadcastChannelUpdate`] event message generated
2955
+ /// containing the new [`ChannelUpdate`] message which should be broadcast to the network.
2956
+ ///
2957
+ /// Returns [`ChannelUnavailable`] when a channel is not found or an incorrect
2958
+ /// `counterparty_node_id` is provided.
2959
+ ///
2960
+ /// Returns [`APIMisuseError`] when a [`cltv_expiry_delta`] update is to be applied with a value
2961
+ /// below [`MIN_CLTV_EXPIRY_DELTA`].
2962
+ ///
2963
+ /// If an error is returned, none of the updates should be considered applied.
2964
+ ///
2965
+ /// [`forwarding_fee_proportional_millionths`]: ChannelConfig::forwarding_fee_proportional_millionths
2966
+ /// [`forwarding_fee_base_msat`]: ChannelConfig::forwarding_fee_base_msat
2967
+ /// [`cltv_expiry_delta`]: ChannelConfig::cltv_expiry_delta
2968
+ /// [`BroadcastChannelUpdate`]: events::MessageSendEvent::BroadcastChannelUpdate
2969
+ /// [`ChannelUpdate`]: msgs::ChannelUpdate
2970
+ /// [`ChannelUnavailable`]: APIError::ChannelUnavailable
2971
+ /// [`APIMisuseError`]: APIError::APIMisuseError
2972
+ pub fn update_channel_config (
2973
+ & self , counterparty_node_id : & PublicKey , channel_ids : & [ [ u8 ; 32 ] ] , config : & ChannelConfig ,
2974
+ ) -> Result < ( ) , APIError > {
2975
+ if config. cltv_expiry_delta < MIN_CLTV_EXPIRY_DELTA {
2976
+ return Err ( APIError :: APIMisuseError {
2977
+ err : format ! ( "The chosen CLTV expiry delta is below the minimum of {}" , MIN_CLTV_EXPIRY_DELTA ) ,
2978
+ } ) ;
2979
+ }
2980
+
2981
+ let _persistence_guard = PersistenceNotifierGuard :: notify_on_drop (
2982
+ & self . total_consistency_lock , & self . persistence_notifier ,
2983
+ ) ;
2984
+ {
2985
+ let mut channel_state_lock = self . channel_state . lock ( ) . unwrap ( ) ;
2986
+ let channel_state = & mut * channel_state_lock;
2987
+ for channel_id in channel_ids {
2988
+ let channel_counterparty_node_id = channel_state. by_id . get ( channel_id)
2989
+ . ok_or ( APIError :: ChannelUnavailable {
2990
+ err : format ! ( "Channel with ID {} was not found" , log_bytes!( * channel_id) ) ,
2991
+ } ) ?
2992
+ . get_counterparty_node_id ( ) ;
2993
+ if channel_counterparty_node_id != * counterparty_node_id {
2994
+ return Err ( APIError :: APIMisuseError {
2995
+ err : "counterparty node id mismatch" . to_owned ( ) ,
2996
+ } ) ;
2997
+ }
2998
+ }
2999
+ for channel_id in channel_ids {
3000
+ let channel = channel_state. by_id . get_mut ( channel_id) . unwrap ( ) ;
3001
+ if !channel. update_config ( config) {
3002
+ continue ;
3003
+ }
3004
+ if let Ok ( msg) = self . get_channel_update_for_broadcast ( channel) {
3005
+ channel_state. pending_msg_events . push ( events:: MessageSendEvent :: BroadcastChannelUpdate { msg } ) ;
3006
+ } else if let Ok ( msg) = self . get_channel_update_for_unicast ( channel) {
3007
+ channel_state. pending_msg_events . push ( events:: MessageSendEvent :: SendChannelUpdate {
3008
+ node_id : channel. get_counterparty_node_id ( ) ,
3009
+ msg,
3010
+ } ) ;
3011
+ }
3012
+ }
3013
+ }
3014
+ Ok ( ( ) )
3015
+ }
3016
+
2943
3017
/// Processes HTLCs which are pending waiting on random forward delay.
2944
3018
///
2945
3019
/// Should only really ever be called in response to a PendingHTLCsForwardable event.
@@ -3465,6 +3539,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3465
3539
/// * Broadcasting `ChannelUpdate` messages if we've been disconnected from our peer for more
3466
3540
/// than a minute, informing the network that they should no longer attempt to route over
3467
3541
/// the channel.
3542
+ /// * Expiring a channel's previous `ChannelConfig` if necessary to only allow forwarding HTLCs
3543
+ /// with the current `ChannelConfig`.
3468
3544
///
3469
3545
/// Note that this may cause reentrancy through `chain::Watch::update_channel` calls or feerate
3470
3546
/// estimate fetches.
@@ -3523,6 +3599,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
3523
3599
_ => { } ,
3524
3600
}
3525
3601
3602
+ chan. maybe_expire_prev_config ( ) ;
3603
+
3526
3604
true
3527
3605
} ) ;
3528
3606
@@ -6115,6 +6193,7 @@ impl_writeable_tlv_based!(ChannelDetails, {
6115
6193
( 4 , counterparty, required) ,
6116
6194
( 5 , outbound_scid_alias, option) ,
6117
6195
( 6 , funding_txo, option) ,
6196
+ ( 7 , config, option) ,
6118
6197
( 8 , short_channel_id, option) ,
6119
6198
( 10 , channel_value_satoshis, required) ,
6120
6199
( 12 , unspendable_punishment_reserve, option) ,
0 commit comments