Skip to content

Commit 4f055ac

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 4f055ac

File tree

1 file changed

+61
-31
lines changed

1 file changed

+61
-31
lines changed

lightning/src/ln/channel.rs

Lines changed: 61 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,21 @@ 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.0.123 version of LDK. In this case, the HTLC is
8768+
// required to be resolved prior to upgrading to 0.1+ per CHANGELOG.md.
8769+
update_add_htlc_opt: None,
8770+
};
87598771
},
87608772
}
87618773
},
87628774
InboundHTLCResolution::Pending { update_add_htlc } => {
87638775
log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed", &htlc.payment_hash);
8764-
pending_update_adds.push(update_add_htlc);
8765-
htlc.state = InboundHTLCState::Committed;
8776+
pending_update_adds.push(update_add_htlc.clone());
8777+
htlc.state = InboundHTLCState::Committed {
8778+
update_add_htlc_opt: Some(update_add_htlc),
8779+
};
87668780
},
87678781
}
87688782
}
@@ -9297,7 +9311,7 @@ where
92979311
// in response to it yet, so don't touch it.
92989312
true
92999313
},
9300-
InboundHTLCState::Committed => true,
9314+
InboundHTLCState::Committed { .. } => true,
93019315
InboundHTLCState::LocalRemoved(_) => {
93029316
// We (hopefully) sent a commitment_signed updating this HTLC (which we can
93039317
// re-transmit if needed) and they may have even sent a revoke_and_ack back
@@ -14518,6 +14532,7 @@ where
1451814532
}
1451914533
}
1452014534
let mut removed_htlc_attribution_data: Vec<&Option<AttributionData>> = Vec::new();
14535+
let mut inbound_committed_update_adds: Vec<Option<msgs::UpdateAddHTLC>> = Vec::new();
1452114536
(self.context.pending_inbound_htlcs.len() as u64 - dropped_inbound_htlcs).write(writer)?;
1452214537
for htlc in self.context.pending_inbound_htlcs.iter() {
1452314538
if let &InboundHTLCState::RemoteAnnounced(_) = &htlc.state {
@@ -14537,8 +14552,9 @@ where
1453714552
2u8.write(writer)?;
1453814553
htlc_resolution.write(writer)?;
1453914554
},
14540-
&InboundHTLCState::Committed => {
14555+
&InboundHTLCState::Committed { ref update_add_htlc_opt } => {
1454114556
3u8.write(writer)?;
14557+
inbound_committed_update_adds.push(update_add_htlc_opt.clone());
1454214558
},
1454314559
&InboundHTLCState::LocalRemoved(ref removal_reason) => {
1454414560
4u8.write(writer)?;
@@ -14914,6 +14930,7 @@ where
1491414930
(69, holding_cell_held_htlc_flags, optional_vec), // Added in 0.2
1491514931
(71, holder_commitment_point_previous_revoked, option), // Added in 0.3
1491614932
(73, holder_commitment_point_last_revoked, option), // Added in 0.3
14933+
(75, inbound_committed_update_adds, optional_vec),
1491714934
});
1491814935

1491914936
Ok(())
@@ -14997,7 +15014,7 @@ where
1499715014
};
1499815015
InboundHTLCState::AwaitingAnnouncedRemoteRevoke(resolution)
1499915016
},
15000-
3 => InboundHTLCState::Committed,
15017+
3 => InboundHTLCState::Committed { update_add_htlc_opt: None },
1500115018
4 => {
1500215019
let reason = match <u8 as Readable>::read(reader)? {
1500315020
0 => InboundHTLCRemovalReason::FailRelay(msgs::OnionErrorPacket {
@@ -15301,6 +15318,7 @@ where
1530115318

1530215319
let mut pending_outbound_held_htlc_flags_opt: Option<Vec<Option<()>>> = None;
1530315320
let mut holding_cell_held_htlc_flags_opt: Option<Vec<Option<()>>> = None;
15321+
let mut inbound_committed_update_adds_opt: Option<Vec<Option<msgs::UpdateAddHTLC>>> = None;
1530415322

1530515323
read_tlv_fields!(reader, {
1530615324
(0, announcement_sigs, option),
@@ -15350,6 +15368,7 @@ where
1535015368
(69, holding_cell_held_htlc_flags_opt, optional_vec), // Added in 0.2
1535115369
(71, holder_commitment_point_previous_revoked_opt, option), // Added in 0.3
1535215370
(73, holder_commitment_point_last_revoked_opt, option), // Added in 0.3
15371+
(75, inbound_committed_update_adds_opt, optional_vec),
1535315372
});
1535415373

1535515374
let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
@@ -15473,6 +15492,17 @@ where
1547315492
return Err(DecodeError::InvalidValue);
1547415493
}
1547515494
}
15495+
if let Some(update_adds) = inbound_committed_update_adds_opt {
15496+
let mut iter = update_adds.into_iter();
15497+
for htlc in pending_inbound_htlcs.iter_mut() {
15498+
if let InboundHTLCState::Committed { ref mut update_add_htlc_opt } = htlc.state {
15499+
*update_add_htlc_opt = iter.next().ok_or(DecodeError::InvalidValue)?;
15500+
}
15501+
}
15502+
if iter.next().is_some() {
15503+
return Err(DecodeError::InvalidValue);
15504+
}
15505+
}
1547615506

1547715507
if let Some(attribution_data_list) = removed_htlc_attribution_data {
1547815508
let mut removed_htlcs = pending_inbound_htlcs.iter_mut().filter_map(|status| {
@@ -16057,7 +16087,7 @@ mod tests {
1605716087
amount_msat: htlc_amount_msat,
1605816088
payment_hash: PaymentHash(Sha256::hash(&[42; 32]).to_byte_array()),
1605916089
cltv_expiry: 300000000,
16060-
state: InboundHTLCState::Committed,
16090+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1606116091
});
1606216092

1606316093
node_a_chan.context.pending_outbound_htlcs.push(OutboundHTLCOutput {
@@ -16903,7 +16933,7 @@ mod tests {
1690316933
amount_msat: 1000000,
1690416934
cltv_expiry: 500,
1690516935
payment_hash: PaymentHash::from(payment_preimage_0),
16906-
state: InboundHTLCState::Committed,
16936+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1690716937
});
1690816938

1690916939
let payment_preimage_1 =
@@ -16913,7 +16943,7 @@ mod tests {
1691316943
amount_msat: 2000000,
1691416944
cltv_expiry: 501,
1691516945
payment_hash: PaymentHash::from(payment_preimage_1),
16916-
state: InboundHTLCState::Committed,
16946+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1691716947
});
1691816948

1691916949
let payment_preimage_2 =
@@ -16953,7 +16983,7 @@ mod tests {
1695316983
amount_msat: 4000000,
1695416984
cltv_expiry: 504,
1695516985
payment_hash: PaymentHash::from(payment_preimage_4),
16956-
state: InboundHTLCState::Committed,
16986+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1695716987
});
1695816988

1695916989
// commitment tx with all five HTLCs untrimmed (minimum feerate)
@@ -17342,7 +17372,7 @@ mod tests {
1734217372
amount_msat: 2000000,
1734317373
cltv_expiry: 501,
1734417374
payment_hash: PaymentHash::from(payment_preimage_1),
17345-
state: InboundHTLCState::Committed,
17375+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1734617376
});
1734717377

1734817378
chan.context.pending_outbound_htlcs.clear();
@@ -17593,7 +17623,7 @@ mod tests {
1759317623
amount_msat: 5000000,
1759417624
cltv_expiry: 920150,
1759517625
payment_hash: PaymentHash::from(htlc_in_preimage),
17596-
state: InboundHTLCState::Committed,
17626+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1759717627
}));
1759817628

1759917629
chan.context.pending_outbound_htlcs.extend(
@@ -17656,7 +17686,7 @@ mod tests {
1765617686
amount_msat,
1765717687
cltv_expiry: 920150,
1765817688
payment_hash: PaymentHash::from(htlc_in_preimage),
17659-
state: InboundHTLCState::Committed,
17689+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1766017690
},
1766117691
));
1766217692

@@ -17722,7 +17752,7 @@ mod tests {
1772217752
amount_msat: 100000,
1772317753
cltv_expiry: 920125,
1772417754
payment_hash: htlc_0_in_hash,
17725-
state: InboundHTLCState::Committed,
17755+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1772617756
});
1772717757

1772817758
let htlc_1_in_preimage =
@@ -17740,7 +17770,7 @@ mod tests {
1774017770
amount_msat: 49900000,
1774117771
cltv_expiry: 920125,
1774217772
payment_hash: htlc_1_in_hash,
17743-
state: InboundHTLCState::Committed,
17773+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1774417774
});
1774517775

1774617776
chan.context.pending_outbound_htlcs.extend(
@@ -17792,7 +17822,7 @@ mod tests {
1779217822
amount_msat: 30000,
1779317823
payment_hash,
1779417824
cltv_expiry: 920125,
17795-
state: InboundHTLCState::Committed,
17825+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1779617826
},
1779717827
));
1779817828

@@ -17833,7 +17863,7 @@ mod tests {
1783317863
amount_msat: 29525,
1783417864
payment_hash,
1783517865
cltv_expiry: 920125,
17836-
state: InboundHTLCState::Committed,
17866+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1783717867
},
1783817868
));
1783917869

@@ -17870,7 +17900,7 @@ mod tests {
1787017900
amount_msat: 29525,
1787117901
payment_hash,
1787217902
cltv_expiry: 920125,
17873-
state: InboundHTLCState::Committed,
17903+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1787417904
},
1787517905
));
1787617906

@@ -17907,7 +17937,7 @@ mod tests {
1790717937
amount_msat: 29753,
1790817938
payment_hash,
1790917939
cltv_expiry: 920125,
17910-
state: InboundHTLCState::Committed,
17940+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1791117941
},
1791217942
));
1791317943

@@ -17959,7 +17989,7 @@ mod tests {
1795917989
amount_msat,
1796017990
cltv_expiry,
1796117991
payment_hash,
17962-
state: InboundHTLCState::Committed,
17992+
state: InboundHTLCState::Committed { update_add_htlc_opt: None },
1796317993
}),
1796417994
);
1796517995

0 commit comments

Comments
 (0)