Skip to content

Commit ca9e050

Browse files
Store inbound committed update_adds in Channel
We have an overarching goal of (mostly) getting rid of ChannelManager persistence and rebuilding the ChannelManager's state from existing ChannelMonitors, due to issues when the two structs are out-of-sync on restart. The main issue that can arise is channel force closure. As part of this, we plan to store at least parts of Channels in ChannelMonitors, and that Channel data will be used in rebuilding the manager. Once we store update_adds in Channels, we can use them on restart when reconstructing ChannelManager maps such as forward_htlcs and pending_intercepted_htlcs. Upcoming commits will start doing this reconstruction.
1 parent 4561bc5 commit ca9e050

File tree

1 file changed

+63
-31
lines changed

1 file changed

+63
-31
lines changed

lightning/src/ln/channel.rs

Lines changed: 63 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,14 @@ enum InboundHTLCState {
211211
/// channel (before it can then get forwarded and/or removed).
212212
/// Implies AwaitingRemoteRevoke.
213213
AwaitingAnnouncedRemoteRevoke(InboundHTLCResolution),
214-
Committed,
214+
/// An HTLC irrevocably committed in the latest commitment transaction, ready to be forwarded or
215+
/// removed.
216+
Committed {
217+
/// Used to rebuild `ChannelManager` HTLC state on restart. Previously the manager would track
218+
/// and persist all HTLC forwards and receives itself, but newer LDK versions avoid relying on
219+
/// its persistence and instead reconstruct state based on `Channel` and `ChannelMonitor` data.
220+
update_add_htlc_opt: Option<msgs::UpdateAddHTLC>,
221+
},
215222
/// Removed by us and a new commitment_signed was sent (if we were AwaitingRemoteRevoke when we
216223
/// created it we would have put it in the holding cell instead). When they next revoke_and_ack
217224
/// we'll drop it.
@@ -235,7 +242,7 @@ impl From<&InboundHTLCState> for Option<InboundHTLCStateDetails> {
235242
InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => {
236243
Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToAdd)
237244
},
238-
InboundHTLCState::Committed => Some(InboundHTLCStateDetails::Committed),
245+
InboundHTLCState::Committed { .. } => Some(InboundHTLCStateDetails::Committed),
239246
InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(_)) => {
240247
Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFail)
241248
},
@@ -256,7 +263,7 @@ impl fmt::Display for InboundHTLCState {
256263
InboundHTLCState::RemoteAnnounced(_) => write!(f, "RemoteAnnounced"),
257264
InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => write!(f, "AwaitingRemoteRevokeToAnnounce"),
258265
InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => write!(f, "AwaitingAnnouncedRemoteRevoke"),
259-
InboundHTLCState::Committed => write!(f, "Committed"),
266+
InboundHTLCState::Committed { .. } => write!(f, "Committed"),
260267
InboundHTLCState::LocalRemoved(_) => write!(f, "LocalRemoved"),
261268
}
262269
}
@@ -268,7 +275,7 @@ impl InboundHTLCState {
268275
InboundHTLCState::RemoteAnnounced(_) => !generated_by_local,
269276
InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => !generated_by_local,
270277
InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => true,
271-
InboundHTLCState::Committed => true,
278+
InboundHTLCState::Committed { .. } => true,
272279
InboundHTLCState::LocalRemoved(_) => !generated_by_local,
273280
}
274281
}
@@ -296,7 +303,7 @@ impl InboundHTLCState {
296303
},
297304
InboundHTLCResolution::Resolved { .. } => false,
298305
},
299-
InboundHTLCState::Committed | InboundHTLCState::LocalRemoved(_) => false,
306+
InboundHTLCState::Committed { .. } | InboundHTLCState::LocalRemoved(_) => false,
300307
}
301308
}
302309
}
@@ -4102,7 +4109,7 @@ where
41024109

41034110
if self.pending_inbound_htlcs.iter()
41044111
.any(|htlc| match htlc.state {
4105-
InboundHTLCState::Committed => false,
4112+
InboundHTLCState::Committed { .. } => false,
41064113
// An HTLC removal from the local node is pending on the remote commitment.
41074114
InboundHTLCState::LocalRemoved(_) => true,
41084115
// An HTLC add from the remote node is pending on the local commitment.
@@ -4531,7 +4538,7 @@ where
45314538
(InboundHTLCState::RemoteAnnounced(..), _) => true,
45324539
(InboundHTLCState::AwaitingRemoteRevokeToAnnounce(..), _) => true,
45334540
(InboundHTLCState::AwaitingAnnouncedRemoteRevoke(..), _) => true,
4534-
(InboundHTLCState::Committed, _) => true,
4541+
(InboundHTLCState::Committed { .. }, _) => true,
45354542
(InboundHTLCState::LocalRemoved(..), true) => true,
45364543
(InboundHTLCState::LocalRemoved(..), false) => false,
45374544
})
@@ -7320,7 +7327,7 @@ where
73207327
payment_preimage_arg
73217328
);
73227329
match htlc.state {
7323-
InboundHTLCState::Committed => {},
7330+
InboundHTLCState::Committed { .. } => {},
73247331
InboundHTLCState::LocalRemoved(ref reason) => {
73257332
if let &InboundHTLCRemovalReason::Fulfill { .. } = reason {
73267333
} else {
@@ -7413,7 +7420,7 @@ where
74137420

74147421
{
74157422
let htlc = &mut self.context.pending_inbound_htlcs[pending_idx];
7416-
if let InboundHTLCState::Committed = htlc.state {
7423+
if let InboundHTLCState::Committed { .. } = htlc.state {
74177424
} else {
74187425
debug_assert!(
74197426
false,
@@ -7548,7 +7555,7 @@ where
75487555
for (idx, htlc) in self.context.pending_inbound_htlcs.iter().enumerate() {
75497556
if htlc.htlc_id == htlc_id_arg {
75507557
match htlc.state {
7551-
InboundHTLCState::Committed => {},
7558+
InboundHTLCState::Committed { .. } => {},
75527559
InboundHTLCState::LocalRemoved(_) => {
75537560
return Err(ChannelError::Ignore(format!("HTLC {} was already resolved", htlc.htlc_id)));
75547561
},
@@ -8716,7 +8723,7 @@ where
87168723
false
87178724
};
87188725
if swap {
8719-
let mut state = InboundHTLCState::Committed;
8726+
let mut state = InboundHTLCState::Committed { update_add_htlc_opt: None };
87208727
mem::swap(&mut state, &mut htlc.state);
87218728

87228729
if let InboundHTLCState::AwaitingRemoteRevokeToAnnounce(resolution) = state {
@@ -8755,14 +8762,23 @@ where
87558762
PendingHTLCStatus::Forward(forward_info) => {
87568763
log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed, attempting to forward", &htlc.payment_hash);
87578764
to_forward_infos.push((forward_info, htlc.htlc_id));
8758-
htlc.state = InboundHTLCState::Committed;
8765+
htlc.state = InboundHTLCState::Committed {
8766+
// HTLCs will only be in state `InboundHTLCResolution::Resolved` if they were
8767+
// received on an old pre-0.1 version of LDK. In this case, we can't set
8768+
// `update_add_htlc_opt` here, but the HTLC will be present in the legacy
8769+
// `ChannelManager` maps so we'll process it from there if it's still around
8770+
// on the next restart.
8771+
update_add_htlc_opt: None,
8772+
};
87598773
},
87608774
}
87618775
},
87628776
InboundHTLCResolution::Pending { update_add_htlc } => {
87638777
log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed", &htlc.payment_hash);
8764-
pending_update_adds.push(update_add_htlc);
8765-
htlc.state = InboundHTLCState::Committed;
8778+
pending_update_adds.push(update_add_htlc.clone());
8779+
htlc.state = InboundHTLCState::Committed {
8780+
update_add_htlc_opt: Some(update_add_htlc),
8781+
};
87668782
},
87678783
}
87688784
}
@@ -9297,7 +9313,7 @@ where
92979313
// in response to it yet, so don't touch it.
92989314
true
92999315
},
9300-
InboundHTLCState::Committed => true,
9316+
InboundHTLCState::Committed { .. } => true,
93019317
InboundHTLCState::LocalRemoved(_) => {
93029318
// We (hopefully) sent a commitment_signed updating this HTLC (which we can
93039319
// re-transmit if needed) and they may have even sent a revoke_and_ack back
@@ -14518,6 +14534,7 @@ where
1451814534
}
1451914535
}
1452014536
let mut removed_htlc_attribution_data: Vec<&Option<AttributionData>> = Vec::new();
14537+
let mut inbound_committed_update_adds: Vec<Option<msgs::UpdateAddHTLC>> = Vec::new();
1452114538
(self.context.pending_inbound_htlcs.len() as u64 - dropped_inbound_htlcs).write(writer)?;
1452214539
for htlc in self.context.pending_inbound_htlcs.iter() {
1452314540
if let &InboundHTLCState::RemoteAnnounced(_) = &htlc.state {
@@ -14537,8 +14554,9 @@ where
1453714554
2u8.write(writer)?;
1453814555
htlc_resolution.write(writer)?;
1453914556
},
14540-
&InboundHTLCState::Committed => {
14557+
&InboundHTLCState::Committed { ref update_add_htlc_opt } => {
1454114558
3u8.write(writer)?;
14559+
inbound_committed_update_adds.push(update_add_htlc_opt.clone());
1454214560
},
1454314561
&InboundHTLCState::LocalRemoved(ref removal_reason) => {
1454414562
4u8.write(writer)?;
@@ -14914,6 +14932,7 @@ where
1491414932
(69, holding_cell_held_htlc_flags, optional_vec), // Added in 0.2
1491514933
(71, holder_commitment_point_previous_revoked, option), // Added in 0.3
1491614934
(73, holder_commitment_point_last_revoked, option), // Added in 0.3
14935+
(75, inbound_committed_update_adds, optional_vec),
1491714936
});
1491814937

1491914938
Ok(())
@@ -14997,7 +15016,7 @@ where
1499715016
};
1499815017
InboundHTLCState::AwaitingAnnouncedRemoteRevoke(resolution)
1499915018
},
15000-
3 => InboundHTLCState::Committed,
15019+
3 => InboundHTLCState::Committed { update_add_htlc_opt: None },
1500115020
4 => {
1500215021
let reason = match <u8 as Readable>::read(reader)? {
1500315022
0 => InboundHTLCRemovalReason::FailRelay(msgs::OnionErrorPacket {
@@ -15301,6 +15320,7 @@ where
1530115320

1530215321
let mut pending_outbound_held_htlc_flags_opt: Option<Vec<Option<()>>> = None;
1530315322
let mut holding_cell_held_htlc_flags_opt: Option<Vec<Option<()>>> = None;
15323+
let mut inbound_committed_update_adds_opt: Option<Vec<Option<msgs::UpdateAddHTLC>>> = None;
1530415324

1530515325
read_tlv_fields!(reader, {
1530615326
(0, announcement_sigs, option),
@@ -15350,6 +15370,7 @@ where
1535015370
(69, holding_cell_held_htlc_flags_opt, optional_vec), // Added in 0.2
1535115371
(71, holder_commitment_point_previous_revoked_opt, option), // Added in 0.3
1535215372
(73, holder_commitment_point_last_revoked_opt, option), // Added in 0.3
15373+
(75, inbound_committed_update_adds_opt, optional_vec),
1535315374
});
1535415375

1535515376
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
@@ -15473,6 +15494,17 @@ where
1547315494
return Err(DecodeError::InvalidValue);
1547415495
}
1547515496
}
15497+
if let Some(update_adds) = inbound_committed_update_adds_opt {
15498+
let mut iter = update_adds.into_iter();
15499+
for htlc in pending_inbound_htlcs.iter_mut() {
15500+
if let InboundHTLCState::Committed { ref mut update_add_htlc_opt } = htlc.state {
15501+
*update_add_htlc_opt = iter.next().ok_or(DecodeError::InvalidValue)?;
15502+
}
15503+
}
15504+
if iter.next().is_some() {
15505+
return Err(DecodeError::InvalidValue);
15506+
}
15507+
}
1547615508

1547715509
if let Some(attribution_data_list) = removed_htlc_attribution_data {
1547815510
let mut removed_htlcs = pending_inbound_htlcs.iter_mut().filter_map(|status| {
@@ -16057,7 +16089,7 @@ mod tests {
1605716089
amount_msat: htlc_amount_msat,
1605816090
payment_hash: PaymentHash(Sha256::hash(&[42; 32]).to_byte_array()),
1605916091
cltv_expiry: 300000000,
16060-
state: InboundHTLCState::Committed,
16092+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1606116093
});
1606216094

1606316095
node_a_chan.context.pending_outbound_htlcs.push(OutboundHTLCOutput {
@@ -16903,7 +16935,7 @@ mod tests {
1690316935
amount_msat: 1000000,
1690416936
cltv_expiry: 500,
1690516937
payment_hash: PaymentHash::from(payment_preimage_0),
16906-
state: InboundHTLCState::Committed,
16938+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1690716939
});
1690816940

1690916941
let payment_preimage_1 =
@@ -16913,7 +16945,7 @@ mod tests {
1691316945
amount_msat: 2000000,
1691416946
cltv_expiry: 501,
1691516947
payment_hash: PaymentHash::from(payment_preimage_1),
16916-
state: InboundHTLCState::Committed,
16948+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1691716949
});
1691816950

1691916951
let payment_preimage_2 =
@@ -16953,7 +16985,7 @@ mod tests {
1695316985
amount_msat: 4000000,
1695416986
cltv_expiry: 504,
1695516987
payment_hash: PaymentHash::from(payment_preimage_4),
16956-
state: InboundHTLCState::Committed,
16988+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1695716989
});
1695816990

1695916991
// commitment tx with all five HTLCs untrimmed (minimum feerate)
@@ -17342,7 +17374,7 @@ mod tests {
1734217374
amount_msat: 2000000,
1734317375
cltv_expiry: 501,
1734417376
payment_hash: PaymentHash::from(payment_preimage_1),
17345-
state: InboundHTLCState::Committed,
17377+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1734617378
});
1734717379

1734817380
chan.context.pending_outbound_htlcs.clear();
@@ -17593,7 +17625,7 @@ mod tests {
1759317625
amount_msat: 5000000,
1759417626
cltv_expiry: 920150,
1759517627
payment_hash: PaymentHash::from(htlc_in_preimage),
17596-
state: InboundHTLCState::Committed,
17628+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1759717629
}));
1759817630

1759917631
chan.context.pending_outbound_htlcs.extend(
@@ -17656,7 +17688,7 @@ mod tests {
1765617688
amount_msat,
1765717689
cltv_expiry: 920150,
1765817690
payment_hash: PaymentHash::from(htlc_in_preimage),
17659-
state: InboundHTLCState::Committed,
17691+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1766017692
},
1766117693
));
1766217694

@@ -17722,7 +17754,7 @@ mod tests {
1772217754
amount_msat: 100000,
1772317755
cltv_expiry: 920125,
1772417756
payment_hash: htlc_0_in_hash,
17725-
state: InboundHTLCState::Committed,
17757+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1772617758
});
1772717759

1772817760
let htlc_1_in_preimage =
@@ -17740,7 +17772,7 @@ mod tests {
1774017772
amount_msat: 49900000,
1774117773
cltv_expiry: 920125,
1774217774
payment_hash: htlc_1_in_hash,
17743-
state: InboundHTLCState::Committed,
17775+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1774417776
});
1774517777

1774617778
chan.context.pending_outbound_htlcs.extend(
@@ -17792,7 +17824,7 @@ mod tests {
1779217824
amount_msat: 30000,
1779317825
payment_hash,
1779417826
cltv_expiry: 920125,
17795-
state: InboundHTLCState::Committed,
17827+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1779617828
},
1779717829
));
1779817830

@@ -17833,7 +17865,7 @@ mod tests {
1783317865
amount_msat: 29525,
1783417866
payment_hash,
1783517867
cltv_expiry: 920125,
17836-
state: InboundHTLCState::Committed,
17868+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1783717869
},
1783817870
));
1783917871

@@ -17870,7 +17902,7 @@ mod tests {
1787017902
amount_msat: 29525,
1787117903
payment_hash,
1787217904
cltv_expiry: 920125,
17873-
state: InboundHTLCState::Committed,
17905+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1787417906
},
1787517907
));
1787617908

@@ -17907,7 +17939,7 @@ mod tests {
1790717939
amount_msat: 29753,
1790817940
payment_hash,
1790917941
cltv_expiry: 920125,
17910-
state: InboundHTLCState::Committed,
17942+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1791117943
},
1791217944
));
1791317945

@@ -17959,7 +17991,7 @@ mod tests {
1795917991
amount_msat,
1796017992
cltv_expiry,
1796117993
payment_hash,
17962-
state: InboundHTLCState::Committed,
17994+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1796317995
}),
1796417996
);
1796517997

0 commit comments

Comments
 (0)