Skip to content

Commit ea0341f

Browse files
carlaKCTheBlueMatt
andcommitted
ln: do not send and reject receive of update_fee for zero fee commits
Co-authored-by: Matt Corallo <[email protected]>
1 parent ccf3ef5 commit ea0341f

File tree

4 files changed

+76
-3
lines changed

4 files changed

+76
-3
lines changed

lightning/src/chain/package.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ pub(crate) fn verify_channel_type_features(channel_type_features: &Option<Channe
9999
supported_feature_set.set_scid_privacy_required();
100100
supported_feature_set.set_zero_conf_required();
101101

102+
#[cfg(test)]
103+
supported_feature_set.set_anchor_zero_fee_commitments_required();
104+
102105
// allow the passing of an additional necessary permitted flag
103106
if let Some(additional_permitted_features) = additional_permitted_features {
104107
supported_feature_set |= additional_permitted_features;

lightning/src/ln/channel.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7709,6 +7709,10 @@ where
77097709
panic!("Cannot update fee while peer is disconnected/we're awaiting a monitor update (ChannelManager should have caught this)");
77107710
}
77117711

7712+
// Sending a fee update for zero fee commitments will trigger a warning and disconnect
7713+
// from our peer, but does not result in a loss of funds so we do not panic here.
7714+
debug_assert!(!self.funding.get_channel_type().supports_anchor_zero_fee_commitments());
7715+
77127716
let can_send_update_fee = core::iter::once(&self.funding)
77137717
.chain(self.pending_funding.iter())
77147718
.all(|funding| self.context.can_send_update_fee(funding, feerate_per_kw, fee_estimator, logger));
@@ -8004,6 +8008,9 @@ where
80048008
if self.context.channel_state.is_remote_stfu_sent() || self.context.channel_state.is_quiescent() {
80058009
return Err(ChannelError::WarnAndDisconnect("Got fee update message while quiescent".to_owned()));
80068010
}
8011+
if self.funding.get_channel_type().supports_anchor_zero_fee_commitments() {
8012+
return Err(ChannelError::WarnAndDisconnect("Update fee message received for zero fee commitment channel".to_owned()));
8013+
}
80078014

80088015
core::iter::once(&self.funding)
80098016
.chain(self.pending_funding.iter())

lightning/src/ln/channelmanager.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7191,10 +7191,17 @@ where
71917191

71927192
let logger = WithChannelContext::from(&self.logger, &chan.context, None);
71937193

7194-
// If the feerate has decreased by less than half, don't bother
7195-
if new_feerate <= chan.context.get_feerate_sat_per_1000_weight() && new_feerate * 2 > chan.context.get_feerate_sat_per_1000_weight() {
7196-
return NotifyOption::SkipPersistNoEvents;
7194+
let current_feerate = chan.context.get_feerate_sat_per_1000_weight();
7195+
let update_fee_required = match new_feerate.cmp(&current_feerate) {
7196+
cmp::Ordering::Greater => true,
7197+
cmp::Ordering::Equal => false,
7198+
// Only bother with a fee update if feerate has decreased at least half.
7199+
cmp::Ordering::Less => new_feerate * 2 <= current_feerate,
7200+
};
7201+
if !update_fee_required {
7202+
return NotifyOption::SkipPersistNoEvents
71977203
}
7204+
71987205
if !chan.context.is_live() {
71997206
log_trace!(logger, "Channel {} does not qualify for a feerate change from {} to {} as it cannot currently be updated (probably the peer is disconnected).",
72007207
chan_id, chan.context.get_feerate_sat_per_1000_weight(), new_feerate);

lightning/src/ln/update_fee_tests.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,3 +1375,59 @@ pub fn do_can_afford_given_trimmed_htlcs(inequality_regions: core::cmp::Ordering
13751375
nodes[0].logger.assert_log("lightning::ln::channel", err, 1);
13761376
}
13771377
}
1378+
1379+
#[test]
1380+
pub fn test_zero_fee_commitments_no_update_fee() {
1381+
// Tests that option_zero_fee_commitment channels do not sent update_fee messages, and that
1382+
// they'll disconnect and warn if they receive them.
1383+
let mut cfg = test_default_channel_config();
1384+
cfg.channel_handshake_config.negotiate_anchor_zero_fee_commitments = true;
1385+
cfg.manually_accept_inbound_channels = true;
1386+
1387+
let chanmon_cfgs = create_chanmon_cfgs(2);
1388+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
1389+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(cfg.clone()), Some(cfg)]);
1390+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
1391+
1392+
let channel = create_chan_between_nodes(&nodes[0], &nodes[1]);
1393+
1394+
let assert_zero_fee = || {
1395+
for node in nodes.iter() {
1396+
let channels = node.node.list_channels();
1397+
assert_eq!(channels.len(), 1);
1398+
assert!(channels[0]
1399+
.channel_type
1400+
.as_ref()
1401+
.unwrap()
1402+
.supports_anchor_zero_fee_commitments());
1403+
assert_eq!(channels[0].feerate_sat_per_1000_weight.unwrap(), 0);
1404+
}
1405+
};
1406+
assert_zero_fee();
1407+
1408+
// Sender should not queue an update_fee message.
1409+
nodes[0].node.timer_tick_occurred();
1410+
let events_0 = nodes[0].node.get_and_clear_pending_msg_events();
1411+
assert_eq!(events_0.len(), 0);
1412+
1413+
// Receiver should ignore and warn if sent update_fee.
1414+
let channel_id = channel.3;
1415+
let update_fee_msg = msgs::UpdateFee { channel_id, feerate_per_kw: 5000 };
1416+
nodes[1].node.handle_update_fee(nodes[0].node.get_our_node_id(), &update_fee_msg);
1417+
1418+
let events_1 = nodes[1].node.get_and_clear_pending_msg_events();
1419+
assert_eq!(events_1.len(), 1);
1420+
match events_1[0] {
1421+
MessageSendEvent::HandleError { ref action, .. } => match action {
1422+
ErrorAction::DisconnectPeerWithWarning { ref msg, .. } => {
1423+
assert_eq!(msg.channel_id, channel_id);
1424+
assert!(msg
1425+
.data
1426+
.contains("Update fee message received for zero fee commitment channel"));
1427+
},
1428+
_ => panic!("Expected DisconnectPeerWithWarning, got {:?}", action),
1429+
},
1430+
_ => panic!("Expected HandleError event, got {:?}", events_1[0]),
1431+
}
1432+
assert_zero_fee();
1433+
}

0 commit comments

Comments
 (0)