Skip to content

Commit cdb822a

Browse files
Add a test for what happens when an HTLC is put in the holding cell when a fee update is pending.
1 parent 437bcf2 commit cdb822a

File tree

2 files changed

+60
-3
lines changed

2 files changed

+60
-3
lines changed

lightning/src/ln/channel.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,9 +2115,11 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
21152115
match err {
21162116
None => {
21172117
if update_add_htlcs.is_empty() && update_fulfill_htlcs.is_empty() && update_fail_htlcs.is_empty() && self.holding_cell_update_fee.is_none() {
2118-
// This should never actually happen and indicates we got some Errs back
2119-
// from update_fulfill_htlc/update_fail_htlc, but we handle it anyway in
2120-
// case there is some strange way to hit duplicate HTLC removes.
2118+
// Reaching this clause is an edge case: a user must (a) be at the edge
2119+
// of their channel send limits and (b) have a race occur where e.g.
2120+
// the remote adds an HTLC while another HTLC is in the holding cell
2121+
// or e.g. a fee update is finalized while an HTLC is in the holding
2122+
// cell.
21212123
return Ok(None);
21222124
}
21232125
let update_fee = if let Some(feerate) = self.holding_cell_update_fee {

lightning/src/ln/functional_tests.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5778,6 +5778,61 @@ fn bolt2_open_channel_sending_node_checks_part2() {
57785778
assert!(PublicKey::from_slice(&node0_to_1_send_open_channel.delayed_payment_basepoint.serialize()).is_ok());
57795779
}
57805780

5781+
#[test]
5782+
fn test_holding_cell_htlc_with_pending_fee_update() {
5783+
let chanmon_cfgs = create_chanmon_cfgs(2);
5784+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
5785+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
5786+
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
5787+
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::supported(), InitFeatures::supported());
5788+
5789+
// First nodes[0] generates an update_fee, setting the channel's
5790+
// pending_update_fee.
5791+
nodes[0].node.update_fee(chan.2, get_feerate!(nodes[0], chan.2) + 20).unwrap();
5792+
check_added_monitors!(nodes[0], 1);
5793+
5794+
let events_0 = nodes[0].node.get_and_clear_pending_msg_events();
5795+
assert_eq!(events_0.len(), 1);
5796+
let (update_msg, commitment_signed) = match events_0[0] { // (1)
5797+
MessageSendEvent::UpdateHTLCs { updates: msgs::CommitmentUpdate { ref update_fee, ref commitment_signed, .. }, .. } => {
5798+
(update_fee.as_ref(), commitment_signed)
5799+
},
5800+
_ => panic!("Unexpected event"),
5801+
};
5802+
5803+
nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), update_msg.unwrap());
5804+
5805+
let mut chan_stat = get_channel_value_stat!(nodes[0], chan.2);
5806+
let their_channel_reserve = chan_stat.channel_reserve_msat;
5807+
let feerate = get_feerate!(nodes[0], chan.2);
5808+
5809+
// +2 HTLCs on the commit tx fee calculation for the fee spike reserve.
5810+
let max_can_send = 5000000 - their_channel_reserve - commit_tx_fee_msat(feerate, 1 + 2);
5811+
let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], max_can_send, TEST_FINAL_CLTV).unwrap();
5812+
let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
5813+
5814+
// Send a payment which passes reserve checks but gets stuck in the holding cell.
5815+
nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
5816+
chan_stat = get_channel_value_stat!(nodes[0], chan.2);
5817+
assert_eq!(chan_stat.holding_cell_outbound_amount_msat, max_can_send);
5818+
5819+
// Flush the pending fee update.
5820+
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), commitment_signed);
5821+
let (as_revoke_and_ack, _) = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id());
5822+
check_added_monitors!(nodes[1], 1);
5823+
nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &as_revoke_and_ack);
5824+
check_added_monitors!(nodes[0], 1);
5825+
5826+
// Upon receipt of the RAA, there will be an attempt to resend the holding cell
5827+
// HTLC, but now that the fee has been raised the payment will now fail, causing
5828+
// it to be put back in the holding cell.
5829+
chan_stat = get_channel_value_stat!(nodes[0], chan.2);
5830+
assert_eq!(chan_stat.holding_cell_outbound_amount_msat, max_can_send);
5831+
nodes[0].logger.assert_log("lightning::ln::channel".to_string(), "Freeing holding cell with 1 HTLC updates".to_string(), 1);
5832+
let failure_log = format!("Failed to send HTLC with payment_hash {} due to Cannot send value that would put us over their reserve value", log_bytes!(our_payment_hash.0));
5833+
nodes[0].logger.assert_log("lightning::ln::channel".to_string(), failure_log.to_string(), 1);
5834+
}
5835+
57815836
// BOLT 2 Requirements for the Sender when constructing and sending an update_add_htlc message.
57825837
// BOLT 2 Requirement: MUST NOT offer amount_msat it cannot pay for in the remote commitment transaction at the current feerate_per_kw (see "Updating Fees") while maintaining its channel reserve.
57835838
//TODO: I don't believe this is explicitly enforced when sending an HTLC but as the Fee aspect of the BOLT specs is in flux leaving this as a TODO.

0 commit comments

Comments
 (0)