Skip to content

Commit 3333b6d

Browse files
authored
Merge pull request #3828 from tankyleo/lonely-commitment
Don't generate a commitment if we cannot afford a holding cell feerate
2 parents afe4285 + d693047 commit 3333b6d

File tree

3 files changed

+188
-7
lines changed

3 files changed

+188
-7
lines changed

lightning/src/ln/channel.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6717,14 +6717,11 @@ where
67176717
}
67186718
}
67196719
}
6720-
if update_add_count == 0 && update_fulfill_count == 0 && update_fail_count == 0 && self.context.holding_cell_update_fee.is_none() {
6720+
let update_fee = self.context.holding_cell_update_fee.take().and_then(|feerate| self.send_update_fee(feerate, false, fee_estimator, logger));
6721+
6722+
if update_add_count == 0 && update_fulfill_count == 0 && update_fail_count == 0 && update_fee.is_none() {
67216723
return (None, htlcs_to_fail);
67226724
}
6723-
let update_fee = if let Some(feerate) = self.context.holding_cell_update_fee.take() {
6724-
self.send_update_fee(feerate, false, fee_estimator, logger)
6725-
} else {
6726-
None
6727-
};
67286725

67296726
let mut additional_update = self.build_commitment_no_status_check(logger);
67306727
// 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
@@ -6852,7 +6852,7 @@ where
68526852
NotifyOption::DoPersist
68536853
}
68546854

6855-
#[cfg(fuzzing)]
6855+
#[cfg(any(test, fuzzing, feature = "_externalize_tests"))]
68566856
/// In chanmon_consistency we want to sometimes do the channel fee updates done in
68576857
/// timer_tick_occurred, but we can't generate the disabled channel updates as it considers
68586858
/// 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: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,3 +1009,187 @@ 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+
let expected_tx_fee_sat =
1053+
chan_utils::commit_tx_fee_sat(target_feerate, 1, &channel_type_features);
1054+
// This is the number of htlcs that `send_update_fee` will account for when checking whether
1055+
// it can afford the new feerate upon releasing an update_fee from its holding cell,
1056+
// ie the buffer + the inbound HTLC we will add while the update_fee is in the holding cell
1057+
let buffer_htlcs = crate::ln::channel::CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize + 1;
1058+
let buffer_tx_fee_sat =
1059+
chan_utils::commit_tx_fee_sat(target_feerate, buffer_htlcs, &channel_type_features);
1060+
let anchor_value_satoshis = if channel_type_features.supports_anchors_zero_fee_htlc_tx() {
1061+
2 * crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI
1062+
} else {
1063+
0
1064+
};
1065+
let channel_reserve_satoshis = 1000;
1066+
1067+
let channel_value_sat = 100_000;
1068+
let node_0_balance_sat = buffer_tx_fee_sat + anchor_value_satoshis + channel_reserve_satoshis
1069+
- if can_afford { 0 } else { 1 };
1070+
let node_1_balance_sat = channel_value_sat - node_0_balance_sat;
1071+
1072+
let chan_id =
1073+
create_chan_between_nodes_with_value(&nodes[0], &nodes[1], channel_value_sat, 0).3;
1074+
1075+
// Set node 0's balance to the can/can't afford threshold
1076+
send_payment(&nodes[0], &[&nodes[1]], node_1_balance_sat * 1000);
1077+
1078+
{
1079+
// Sanity check the reserve
1080+
let per_peer_state_lock;
1081+
let mut peer_state_lock;
1082+
let chan =
1083+
get_channel_ref!(nodes[1], nodes[0], per_peer_state_lock, peer_state_lock, chan_id);
1084+
assert_eq!(
1085+
chan.funding().holder_selected_channel_reserve_satoshis,
1086+
channel_reserve_satoshis
1087+
);
1088+
}
1089+
1090+
{
1091+
// Bump the feerate
1092+
let mut feerate_lock = chanmon_cfgs[0].fee_estimator.sat_per_kw.lock().unwrap();
1093+
*feerate_lock = target_feerate;
1094+
}
1095+
1096+
// Put the update fee into the holding cell of node 0
1097+
1098+
nodes[0].node.maybe_update_chan_fees();
1099+
1100+
// While the update_fee is in the holding cell, add an inbound HTLC
1101+
1102+
let (route, payment_hash, _, payment_secret) =
1103+
get_route_and_payment_hash!(nodes[1], nodes[0], 5000 * 1000);
1104+
let onion = RecipientOnionFields::secret_only(payment_secret);
1105+
let id = PaymentId(payment_hash.0);
1106+
nodes[1].node.send_payment_with_route(route, payment_hash, onion, id).unwrap();
1107+
check_added_monitors(&nodes[1], 1);
1108+
1109+
let payment_event = {
1110+
let mut events_1 = nodes[1].node.get_and_clear_pending_msg_events();
1111+
assert_eq!(events_1.len(), 1);
1112+
SendEvent::from_event(events_1.pop().unwrap())
1113+
};
1114+
assert_eq!(payment_event.node_id, node_a_id);
1115+
assert_eq!(payment_event.msgs.len(), 1);
1116+
1117+
nodes[0].node.handle_update_add_htlc(node_b_id, &payment_event.msgs[0]);
1118+
nodes[0].node.handle_commitment_signed(node_b_id, &payment_event.commitment_msg[0]);
1119+
check_added_monitors(&nodes[0], 1);
1120+
1121+
let (revoke_ack, commitment_signed) = get_revoke_commit_msgs!(nodes[0], node_b_id);
1122+
1123+
nodes[1].node.handle_revoke_and_ack(node_a_id, &revoke_ack);
1124+
check_added_monitors(&nodes[1], 1);
1125+
nodes[1].node.handle_commitment_signed(node_a_id, &commitment_signed[0]);
1126+
check_added_monitors(&nodes[1], 1);
1127+
1128+
let mut events = nodes[1].node.get_and_clear_pending_msg_events();
1129+
assert_eq!(events.len(), 1);
1130+
1131+
if let MessageSendEvent::SendRevokeAndACK { node_id, msg } = events.pop().unwrap() {
1132+
assert_eq!(node_id, node_a_id);
1133+
nodes[0].node.handle_revoke_and_ack(node_b_id, &msg);
1134+
check_added_monitors!(nodes[0], 1);
1135+
} else {
1136+
panic!();
1137+
}
1138+
1139+
let events = nodes[0].node.get_and_clear_pending_events();
1140+
assert_eq!(events.len(), 1);
1141+
assert!(matches!(events[0], Event::PendingHTLCsForwardable { .. }));
1142+
1143+
// Release the update_fee from its holding cell
1144+
1145+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
1146+
if can_afford {
1147+
// We could afford the update_fee, sanity check everything
1148+
assert_eq!(events.len(), 1);
1149+
if let MessageSendEvent::UpdateHTLCs { node_id, channel_id, updates } =
1150+
events.pop().unwrap()
1151+
{
1152+
assert_eq!(node_id, node_b_id);
1153+
assert_eq!(channel_id, chan_id);
1154+
assert_eq!(updates.commitment_signed.len(), 1);
1155+
assert_eq!(updates.commitment_signed[0].htlc_signatures.len(), 1);
1156+
assert_eq!(updates.update_add_htlcs.len(), 0);
1157+
assert_eq!(updates.update_fulfill_htlcs.len(), 0);
1158+
assert_eq!(updates.update_fail_htlcs.len(), 0);
1159+
assert_eq!(updates.update_fail_malformed_htlcs.len(), 0);
1160+
let update_fee = updates.update_fee.unwrap();
1161+
assert_eq!(update_fee.channel_id, chan_id);
1162+
assert_eq!(update_fee.feerate_per_kw, target_feerate);
1163+
1164+
nodes[1].node.handle_update_fee(node_a_id, &update_fee);
1165+
commitment_signed_dance!(nodes[1], nodes[0], updates.commitment_signed, false);
1166+
1167+
// Confirm the feerate on node 0's commitment transaction
1168+
{
1169+
let commitment_tx = get_local_commitment_txn!(nodes[0], channel_id)[0].clone();
1170+
1171+
let mut actual_fee =
1172+
commitment_tx.output.iter().fold(0, |acc, output| acc + output.value.to_sat());
1173+
actual_fee = channel_value_sat - actual_fee;
1174+
assert_eq!(expected_tx_fee_sat, actual_fee);
1175+
}
1176+
1177+
// Confirm the feerate on node 1's commitment transaction
1178+
{
1179+
let commitment_tx = get_local_commitment_txn!(nodes[1], channel_id)[0].clone();
1180+
1181+
let mut actual_fee =
1182+
commitment_tx.output.iter().fold(0, |acc, output| acc + output.value.to_sat());
1183+
actual_fee = channel_value_sat - actual_fee;
1184+
assert_eq!(expected_tx_fee_sat, actual_fee);
1185+
}
1186+
} else {
1187+
panic!();
1188+
}
1189+
} else {
1190+
// We could not afford the update_fee, no events should be generated
1191+
assert_eq!(events.len(), 0);
1192+
let err = format!("Cannot afford to send new feerate at {}", target_feerate);
1193+
nodes[0].logger.assert_log("lightning::ln::channel", err, 1);
1194+
}
1195+
}

0 commit comments

Comments
 (0)