Skip to content

Commit e4f2142

Browse files
committed
Don't generate a commitment if we cannot afford a holding cell feerate
While an `update_fee` is in the holding cell, it is possible for HTLCs to get added to the commitment transaction such that when we release the holding cell, we can no longer afford this new feerate. In that case, we previously would drop the fee update, but still send a commitment (at the old feerate), which is a break of the specification. We now stop generating this lonely commitment when the fee update gets dropped upon release from the holding cell.
1 parent 6133a6c commit e4f2142

File tree

3 files changed

+160
-7
lines changed

3 files changed

+160
-7
lines changed

lightning/src/ln/channel.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6275,14 +6275,11 @@ impl<SP: Deref> FundedChannel<SP> where
62756275
}
62766276
}
62776277
}
6278-
if update_add_count == 0 && update_fulfill_count == 0 && update_fail_count == 0 && self.context.holding_cell_update_fee.is_none() {
6278+
let update_fee = self.context.holding_cell_update_fee.take().and_then(|feerate| self.send_update_fee(feerate, false, fee_estimator, logger));
6279+
6280+
if update_add_count == 0 && update_fulfill_count == 0 && update_fail_count == 0 && update_fee.is_none() {
62796281
return (None, htlcs_to_fail);
62806282
}
6281-
let update_fee = if let Some(feerate) = self.context.holding_cell_update_fee.take() {
6282-
self.send_update_fee(feerate, false, fee_estimator, logger)
6283-
} else {
6284-
None
6285-
};
62866283

62876284
let mut additional_update = self.build_commitment_no_status_check(logger);
62886285
// build_commitment_no_status_check and get_update_fulfill_htlc may bump latest_monitor_id

lightning/src/ln/channelmanager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6586,7 +6586,7 @@ where
65866586
NotifyOption::DoPersist
65876587
}
65886588

6589-
#[cfg(fuzzing)]
6589+
#[cfg(any(test, fuzzing, feature = "_externalize_tests"))]
65906590
/// In chanmon_consistency we want to sometimes do the channel fee updates done in
65916591
/// timer_tick_occurred, but we can't generate the disabled channel updates as it considers
65926592
/// these a fuzz failure (as they usually indicate a channel force-close, which is exactly what

lightning/src/ln/update_fee_tests.rs

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,3 +1009,159 @@ pub fn accept_busted_but_better_fee() {
10091009
_ => panic!("Unexpected event"),
10101010
};
10111011
}
1012+
1013+
#[xtest(feature = "_externalize_tests")]
1014+
pub fn cannot_afford_on_holding_cell_release() {
1015+
do_cannot_afford_on_holding_cell_release(ChannelTypeFeatures::only_static_remote_key(), true);
1016+
do_cannot_afford_on_holding_cell_release(ChannelTypeFeatures::only_static_remote_key(), false);
1017+
do_cannot_afford_on_holding_cell_release(
1018+
ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(),
1019+
true,
1020+
);
1021+
do_cannot_afford_on_holding_cell_release(
1022+
ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(),
1023+
false,
1024+
);
1025+
}
1026+
1027+
pub fn do_cannot_afford_on_holding_cell_release(
1028+
channel_type_features: ChannelTypeFeatures, can_afford: bool,
1029+
) {
1030+
// Test that if we can't afford a feerate update when releasing an
1031+
// update_fee from its holding cell, we do not generate any msg events
1032+
let chanmon_cfgs = create_chanmon_cfgs(2);
1033+
1034+
let mut default_config = test_default_channel_config();
1035+
default_config.channel_handshake_config.max_inbound_htlc_value_in_flight_percent_of_channel =
1036+
100;
1037+
if channel_type_features.supports_anchors_zero_fee_htlc_tx() {
1038+
default_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx = true;
1039+
default_config.manually_accept_inbound_channels = true;
1040+
}
1041+
1042+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
1043+
let node_chanmgrs =
1044+
create_node_chanmgrs(2, &node_cfgs, &[Some(default_config.clone()), Some(default_config)]);
1045+
1046+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
1047+
1048+
let node_a_id = nodes[0].node.get_our_node_id();
1049+
let node_b_id = nodes[1].node.get_our_node_id();
1050+
1051+
let target_feerate = 1000;
1052+
// This is the number of htlcs that `send_update_fee` will account for when checking whether
1053+
// it can afford the new feerate upon releasing an update_fee from its holding cell,
1054+
// ie the buffer + the inbound HTLC we will add while the update_fee is in the holding cell
1055+
let num_htlcs = crate::ln::channel::CONCURRENT_INBOUND_HTLC_FEE_BUFFER + 1;
1056+
let commit_tx_fee_sat =
1057+
chan_utils::commit_tx_fee_sat(target_feerate, num_htlcs as usize, &channel_type_features);
1058+
let anchor_value_satoshis = if channel_type_features.supports_anchors_zero_fee_htlc_tx() {
1059+
2 * crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI
1060+
} else {
1061+
0
1062+
};
1063+
let channel_reserve_satoshis = 1000;
1064+
1065+
let channel_value_sat = 100_000;
1066+
let node_0_balance_sat = commit_tx_fee_sat + anchor_value_satoshis + channel_reserve_satoshis
1067+
- if can_afford { 0 } else { 1 };
1068+
let node_1_balance_sat = channel_value_sat - node_0_balance_sat;
1069+
1070+
let chan_id =
1071+
create_chan_between_nodes_with_value(&nodes[0], &nodes[1], channel_value_sat, 0).3;
1072+
1073+
// Set node 0's balance to the can/can't afford threshold
1074+
send_payment(&nodes[0], &[&nodes[1]], node_1_balance_sat * 1000);
1075+
1076+
{
1077+
// Sanity check the reserve
1078+
let per_peer_state_lock;
1079+
let mut peer_state_lock;
1080+
let chan =
1081+
get_channel_ref!(nodes[1], nodes[0], per_peer_state_lock, peer_state_lock, chan_id);
1082+
assert_eq!(
1083+
chan.funding().holder_selected_channel_reserve_satoshis,
1084+
channel_reserve_satoshis
1085+
);
1086+
}
1087+
1088+
{
1089+
// Bump the feerate
1090+
let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
1091+
*feerate_lock = target_feerate;
1092+
}
1093+
1094+
// Put the update fee into the holding cell of node 0
1095+
1096+
nodes[0].node.maybe_update_chan_fees();
1097+
1098+
// While the update_fee is in the holding cell, add an inbound HTLC
1099+
1100+
let (route, payment_hash, _, payment_secret) =
1101+
get_route_and_payment_hash!(nodes[1], nodes[0], 5000 * 1000);
1102+
let onion = RecipientOnionFields::secret_only(payment_secret);
1103+
let id = PaymentId(payment_hash.0);
1104+
nodes[1].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
1105+
check_added_monitors(&nodes[1], 1);
1106+
1107+
let payment_event = {
1108+
let mut events_1 = nodes[1].node.get_and_clear_pending_msg_events();
1109+
assert_eq!(events_1.len(), 1);
1110+
SendEvent::from_event(events_1.pop().unwrap())
1111+
};
1112+
assert_eq!(payment_event.node_id, node_a_id);
1113+
assert_eq!(payment_event.msgs.len(), 1);
1114+
1115+
nodes[0].node.handle_update_add_htlc(node_b_id, &payment_event.msgs[0]);
1116+
nodes[0].node.handle_commitment_signed(node_b_id, &payment_event.commitment_msg[0]);
1117+
check_added_monitors(&nodes[0], 1);
1118+
1119+
let (revoke_ack, commitment_signed) = get_revoke_commit_msgs!(nodes[0], node_b_id);
1120+
1121+
nodes[1].node.handle_revoke_and_ack(node_a_id, &revoke_ack);
1122+
check_added_monitors(&nodes[1], 1);
1123+
nodes[1].node.handle_commitment_signed(node_a_id, &commitment_signed[0]);
1124+
check_added_monitors(&nodes[1], 1);
1125+
1126+
let mut events = nodes[1].node.get_and_clear_pending_msg_events();
1127+
assert_eq!(events.len(), 1);
1128+
1129+
if let MessageSendEvent::SendRevokeAndACK { node_id, msg } = events.pop().unwrap() {
1130+
assert_eq!(node_id, node_a_id);
1131+
nodes[0].node.handle_revoke_and_ack(node_b_id, &msg);
1132+
check_added_monitors!(nodes[0], 1);
1133+
} else {
1134+
panic!();
1135+
}
1136+
1137+
let events = nodes[0].node.get_and_clear_pending_events();
1138+
assert_eq!(events.len(), 1);
1139+
assert!(matches!(events[0], Event::PendingHTLCsForwardable { .. }));
1140+
1141+
// Release the update_fee from its holding cell
1142+
1143+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
1144+
if can_afford {
1145+
// We could afford the update_fee, sanity check everything
1146+
if let MessageSendEvent::UpdateHTLCs { node_id, channel_id, updates } =
1147+
events.pop().unwrap()
1148+
{
1149+
assert_eq!(node_id, node_b_id);
1150+
assert_eq!(channel_id, chan_id);
1151+
assert_eq!(updates.commitment_signed.len(), 1);
1152+
assert_eq!(updates.commitment_signed[0].htlc_signatures.len(), 1);
1153+
assert_eq!(updates.update_add_htlcs.len(), 0);
1154+
assert_eq!(updates.update_fulfill_htlcs.len(), 0);
1155+
assert_eq!(updates.update_fail_htlcs.len(), 0);
1156+
assert_eq!(updates.update_fail_malformed_htlcs.len(), 0);
1157+
let update_fee = updates.update_fee.unwrap();
1158+
assert_eq!(update_fee.channel_id, chan_id);
1159+
assert_eq!(update_fee.feerate_per_kw, target_feerate);
1160+
} else {
1161+
panic!();
1162+
}
1163+
} else {
1164+
// We could not afford the update_fee, no events should be generated
1165+
assert_eq!(events.len(), 0);
1166+
}
1167+
}

0 commit comments

Comments
 (0)