let holder_signer = keys_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
let pubkeys = holder_signer.pubkeys().clone();
+ let mut config = LegacyChannelConfig {
+ options: user_config.channel_config.clone(),
+ announced_channel: user_config.channel_handshake_config.announced_channel,
+ commit_upfront_shutdown_pubkey: user_config.channel_handshake_config.commit_upfront_shutdown_pubkey,
+ };
+
+ if !their_features.supports_inbound_fees() {
+ config.options.inbound_forwarding_fee_proportional_millionths = 0;
+ config.options.inbound_forwarding_fee_base_msat = 0;
+ }
+
if !their_features.supports_wumbo() && channel_value_satoshis > MAX_FUNDING_SATOSHIS_NO_WUMBO {
return Err(APIError::APIMisuseError{err: format!("funding_value must not exceed {}, it was {}", MAX_FUNDING_SATOSHIS_NO_WUMBO, channel_value_satoshis)});
}
Ok(Channel {
user_id,
- config: LegacyChannelConfig {
- options: user_config.channel_config.clone(),
- announced_channel: user_config.channel_handshake_config.announced_channel,
- commit_upfront_shutdown_pubkey: user_config.channel_handshake_config.commit_upfront_shutdown_pubkey,
- },
-
+ config,
prev_config: None,
inbound_handshake_limits_override: Some(user_config.channel_handshake_limits.clone()),
let opt_anchors = false; // TODO - should be based on features
let announced_channel = if (msg.channel_flags & 1) == 1 { true } else { false };
+ let mut config = LegacyChannelConfig {
+ options: user_config.channel_config.clone(),
+ announced_channel,
+ commit_upfront_shutdown_pubkey: user_config.channel_handshake_config.commit_upfront_shutdown_pubkey,
+ };
+
+ if !their_features.supports_inbound_fees() {
+ config.options.inbound_forwarding_fee_proportional_millionths = 0;
+ config.options.inbound_forwarding_fee_base_msat = 0;
+ }
+
// First check the channel type is known, failing before we do anything else if we don't
// support this channel type.
let channel_type = if let Some(channel_type) = &msg.channel_type {
let chan = Channel {
user_id,
- config: LegacyChannelConfig {
- options: user_config.channel_config.clone(),
- announced_channel,
- commit_upfront_shutdown_pubkey: user_config.channel_handshake_config.commit_upfront_shutdown_pubkey,
- },
-
+ config,
prev_config: None,
inbound_handshake_limits_override: None,
/// Updates the channel's config. A bool is returned indicating whether the config update
/// applied resulted in a new ChannelUpdate message.
- pub fn update_config(&mut self, config: &ChannelConfig) -> bool {
+ pub fn update_config(&mut self, their_features: &InitFeatures, mut config: ChannelConfig) -> bool {
+ if !their_features.supports_inbound_fees() {
+ config.inbound_forwarding_fee_proportional_millionths = 0;
+ config.inbound_forwarding_fee_base_msat = 0;
+ }
+
let did_channel_update =
self.config.options.forwarding_fee_proportional_millionths != config.forwarding_fee_proportional_millionths ||
self.config.options.forwarding_fee_base_msat != config.forwarding_fee_base_msat ||
// policy change to propagate throughout the network.
self.update_time_counter += 1;
}
- self.config.options = *config;
+ self.config.options = config;
did_channel_update
}
/// [`ChannelUnavailable`]: APIError::ChannelUnavailable
/// [`APIMisuseError`]: APIError::APIMisuseError
pub fn update_channel_config(
- &self, counterparty_node_id: &PublicKey, channel_ids: &[[u8; 32]], config: &ChannelConfig,
+ &self, counterparty_node_id: &PublicKey, channel_ids: &[[u8; 32]], config: ChannelConfig,
) -> Result<(), APIError> {
if config.cltv_expiry_delta < MIN_CLTV_EXPIRY_DELTA {
return Err(APIError::APIMisuseError {
}
for channel_id in channel_ids {
let channel = channel_state.by_id.get_mut(channel_id).unwrap();
- if !channel.update_config(config) {
- continue;
- }
+
+ //XXX : do this in the same per_peer_state lock post-#1507
+ let per_peer_state = self.per_peer_state.read().unwrap();
+ if let Some(peer_state) = per_peer_state.get(counterparty_node_id) {
+ if !channel.update_config(&peer_state.lock().unwrap().latest_features, config) {
+ continue;
+ }
+ } else { return Err(APIError::APIMisuseError { err: format!("XXX: DROP THIS CODE") }); }
if let Ok(msg) = self.get_channel_update_for_broadcast(channel) {
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { msg });
} else if let Ok(msg) = self.get_channel_update_for_unicast(channel) {
};
// Closure to update and retrieve the latest ChannelUpdate.
- let update_and_get_channel_update = |config: &ChannelConfig, expect_new_update: bool,
+ let update_and_get_channel_update = |config: ChannelConfig, expect_new_update: bool,
prev_update: Option<&msgs::ChannelUpdate>, should_expire_prev_config: bool| -> Option<msgs::ChannelUpdate> {
nodes[1].node.update_channel_config(
channel_to_update_counterparty, &[channel_to_update.0], config,
let mut invalid_config = default_config.clone();
invalid_config.cltv_expiry_delta = 0;
match nodes[1].node.update_channel_config(
- channel_to_update_counterparty, &[channel_to_update.0], &invalid_config,
+ channel_to_update_counterparty, &[channel_to_update.0], invalid_config,
) {
Err(APIError::APIMisuseError{ .. }) => {},
_ => panic!("unexpected result applying invalid cltv_expiry_delta"),
.find(|channel| channel.channel_id == channel_to_update.0).unwrap()
.config.unwrap();
config.forwarding_fee_base_msat = u32::max_value();
- let msg = update_and_get_channel_update(&config, true, None, false).unwrap();
+ let msg = update_and_get_channel_update(config, true, None, false).unwrap();
// The old policy should still be in effect until a new block is connected.
send_along_route_with_secret(&nodes[0], route.clone(), &[&[&nodes[1], &nodes[2]]], PAYMENT_AMT,
expect_onion_failure("fee_insufficient", UPDATE|12, &msg);
// Redundant updates should not trigger a new ChannelUpdate.
- assert!(update_and_get_channel_update(&config, false, None, false).is_none());
+ assert!(update_and_get_channel_update(config, false, None, false).is_none());
// Similarly, updates that do not have an affect on ChannelUpdate should not trigger a new one.
config.force_close_avoidance_max_fee_satoshis *= 2;
- assert!(update_and_get_channel_update(&config, false, None, false).is_none());
+ assert!(update_and_get_channel_update(config, false, None, false).is_none());
// Reset the base fee to the default and increase the proportional fee which should trigger a
// new ChannelUpdate.
config.forwarding_fee_base_msat = default_config.forwarding_fee_base_msat;
config.cltv_expiry_delta = u16::max_value();
- let msg = update_and_get_channel_update(&config, true, Some(&msg), true).unwrap();
+ let msg = update_and_get_channel_update(config, true, Some(&msg), true).unwrap();
expect_onion_failure("incorrect_cltv_expiry", UPDATE|13, &msg);
// Reset the proportional fee and increase the CLTV expiry delta which should trigger a new
// ChannelUpdate.
config.cltv_expiry_delta = default_config.cltv_expiry_delta;
config.forwarding_fee_proportional_millionths = u32::max_value();
- let msg = update_and_get_channel_update(&config, true, Some(&msg), true).unwrap();
+ let msg = update_and_get_channel_update(config, true, Some(&msg), true).unwrap();
expect_onion_failure("fee_insufficient", UPDATE|12, &msg);
// To test persistence of the updated config, we'll re-initialize the ChannelManager.
let mut channel = channel_state.by_id.get_mut(&chan_id_2).unwrap();
let mut new_config = channel.config();
new_config.forwarding_fee_base_msat += 100_000;
- channel.update_config(&new_config);
+ channel.update_config(&channelmanager::provided_init_features(), new_config);
new_route.paths[0][0].fee_msat += 100_000;
}