@@ -211,7 +211,9 @@ enum InboundHTLCState {
211211 /// channel (before it can then get forwarded and/or removed).
212212 /// Implies AwaitingRemoteRevoke.
213213 AwaitingAnnouncedRemoteRevoke(InboundHTLCResolution),
214- Committed,
214+ Committed {
215+ update_add_htlc_opt: Option<msgs::UpdateAddHTLC>,
216+ },
215217 /// Removed by us and a new commitment_signed was sent (if we were AwaitingRemoteRevoke when we
216218 /// created it we would have put it in the holding cell instead). When they next revoke_and_ack
217219 /// we'll drop it.
@@ -234,7 +236,7 @@ impl From<&InboundHTLCState> for Option<InboundHTLCStateDetails> {
234236 Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToAdd),
235237 InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) =>
236238 Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToAdd),
237- InboundHTLCState::Committed =>
239+ InboundHTLCState::Committed { .. } =>
238240 Some(InboundHTLCStateDetails::Committed),
239241 InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(_)) =>
240242 Some(InboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFail),
@@ -253,7 +255,7 @@ impl fmt::Display for InboundHTLCState {
253255 InboundHTLCState::RemoteAnnounced(_) => write!(f, "RemoteAnnounced"),
254256 InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => write!(f, "AwaitingRemoteRevokeToAnnounce"),
255257 InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => write!(f, "AwaitingAnnouncedRemoteRevoke"),
256- InboundHTLCState::Committed => write!(f, "Committed"),
258+ InboundHTLCState::Committed { .. } => write!(f, "Committed"),
257259 InboundHTLCState::LocalRemoved(_) => write!(f, "LocalRemoved"),
258260 }
259261 }
@@ -265,7 +267,7 @@ impl InboundHTLCState {
265267 InboundHTLCState::RemoteAnnounced(_) => !generated_by_local,
266268 InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => !generated_by_local,
267269 InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => true,
268- InboundHTLCState::Committed => true,
270+ InboundHTLCState::Committed { .. } => true,
269271 InboundHTLCState::LocalRemoved(_) => !generated_by_local,
270272 }
271273 }
@@ -293,7 +295,7 @@ impl InboundHTLCState {
293295 },
294296 InboundHTLCResolution::Resolved { .. } => false,
295297 },
296- InboundHTLCState::Committed | InboundHTLCState::LocalRemoved(_) => false,
298+ InboundHTLCState::Committed { .. } | InboundHTLCState::LocalRemoved(_) => false,
297299 }
298300 }
299301}
@@ -4066,7 +4068,7 @@ where
40664068
40674069 if self.pending_inbound_htlcs.iter()
40684070 .any(|htlc| match htlc.state {
4069- InboundHTLCState::Committed => false,
4071+ InboundHTLCState::Committed { .. } => false,
40704072 // An HTLC removal from the local node is pending on the remote commitment.
40714073 InboundHTLCState::LocalRemoved(_) => true,
40724074 // An HTLC add from the remote node is pending on the local commitment.
@@ -4495,7 +4497,7 @@ where
44954497 (InboundHTLCState::RemoteAnnounced(..), _) => true,
44964498 (InboundHTLCState::AwaitingRemoteRevokeToAnnounce(..), _) => true,
44974499 (InboundHTLCState::AwaitingAnnouncedRemoteRevoke(..), _) => true,
4498- (InboundHTLCState::Committed, _) => true,
4500+ (InboundHTLCState::Committed { .. } , _) => true,
44994501 (InboundHTLCState::LocalRemoved(..), true) => true,
45004502 (InboundHTLCState::LocalRemoved(..), false) => false,
45014503 })
@@ -7278,7 +7280,7 @@ where
72787280 payment_preimage_arg
72797281 );
72807282 match htlc.state {
7281- InboundHTLCState::Committed => {},
7283+ InboundHTLCState::Committed { .. } => {},
72827284 InboundHTLCState::LocalRemoved(ref reason) => {
72837285 if let &InboundHTLCRemovalReason::Fulfill(_, _) = reason {
72847286 } else {
@@ -7371,7 +7373,7 @@ where
73717373
73727374 {
73737375 let htlc = &mut self.context.pending_inbound_htlcs[pending_idx];
7374- if let InboundHTLCState::Committed = htlc.state {
7376+ if let InboundHTLCState::Committed { .. } = htlc.state {
73757377 } else {
73767378 debug_assert!(
73777379 false,
@@ -7506,7 +7508,7 @@ where
75067508 for (idx, htlc) in self.context.pending_inbound_htlcs.iter().enumerate() {
75077509 if htlc.htlc_id == htlc_id_arg {
75087510 match htlc.state {
7509- InboundHTLCState::Committed => {},
7511+ InboundHTLCState::Committed { .. } => {},
75107512 InboundHTLCState::LocalRemoved(_) => {
75117513 return Err(ChannelError::Ignore(format!("HTLC {} was already resolved", htlc.htlc_id)));
75127514 },
@@ -8665,7 +8667,7 @@ where
86658667 false
86668668 };
86678669 if swap {
8668- let mut state = InboundHTLCState::Committed;
8670+ let mut state = InboundHTLCState::Committed { update_add_htlc_opt: None } ;
86698671 mem::swap(&mut state, &mut htlc.state);
86708672
86718673 if let InboundHTLCState::AwaitingRemoteRevokeToAnnounce(resolution) = state {
@@ -8704,14 +8706,19 @@ where
87048706 PendingHTLCStatus::Forward(forward_info) => {
87058707 log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed, attempting to forward", &htlc.payment_hash);
87068708 to_forward_infos.push((forward_info, htlc.htlc_id));
8707- htlc.state = InboundHTLCState::Committed;
8709+ // TODO: this is currently unreachable, so is it okay? will we lose a forward?
8710+ htlc.state = InboundHTLCState::Committed {
8711+ update_add_htlc_opt: None,
8712+ };
87088713 },
87098714 }
87108715 },
87118716 InboundHTLCResolution::Pending { update_add_htlc } => {
87128717 log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed", &htlc.payment_hash);
8713- pending_update_adds.push(update_add_htlc);
8714- htlc.state = InboundHTLCState::Committed;
8718+ pending_update_adds.push(update_add_htlc.clone());
8719+ htlc.state = InboundHTLCState::Committed {
8720+ update_add_htlc_opt: Some(update_add_htlc),
8721+ };
87158722 },
87168723 }
87178724 }
@@ -9241,7 +9248,7 @@ where
92419248 // in response to it yet, so don't touch it.
92429249 true
92439250 },
9244- InboundHTLCState::Committed => true,
9251+ InboundHTLCState::Committed { .. } => true,
92459252 InboundHTLCState::LocalRemoved(_) => {
92469253 // We (hopefully) sent a commitment_signed updating this HTLC (which we can
92479254 // re-transmit if needed) and they may have even sent a revoke_and_ack back
@@ -14406,6 +14413,7 @@ where
1440614413 }
1440714414 }
1440814415 let mut removed_htlc_attribution_data: Vec<&Option<AttributionData>> = Vec::new();
14416+ let mut inbound_committed_update_adds: Vec<Option<msgs::UpdateAddHTLC>> = Vec::new();
1440914417 (self.context.pending_inbound_htlcs.len() as u64 - dropped_inbound_htlcs).write(writer)?;
1441014418 for htlc in self.context.pending_inbound_htlcs.iter() {
1441114419 if let &InboundHTLCState::RemoteAnnounced(_) = &htlc.state {
@@ -14425,8 +14433,9 @@ where
1442514433 2u8.write(writer)?;
1442614434 htlc_resolution.write(writer)?;
1442714435 },
14428- &InboundHTLCState::Committed => {
14436+ &InboundHTLCState::Committed { ref update_add_htlc_opt } => {
1442914437 3u8.write(writer)?;
14438+ inbound_committed_update_adds.push(update_add_htlc_opt.clone());
1443014439 },
1443114440 &InboundHTLCState::LocalRemoved(ref removal_reason) => {
1443214441 4u8.write(writer)?;
@@ -14793,6 +14802,7 @@ where
1479314802 (65, self.quiescent_action, option), // Added in 0.2
1479414803 (67, pending_outbound_held_htlc_flags, optional_vec), // Added in 0.2
1479514804 (69, holding_cell_held_htlc_flags, optional_vec), // Added in 0.2
14805+ (71, inbound_committed_update_adds, optional_vec),
1479614806 });
1479714807
1479814808 Ok(())
@@ -14876,7 +14886,7 @@ where
1487614886 };
1487714887 InboundHTLCState::AwaitingAnnouncedRemoteRevoke(resolution)
1487814888 },
14879- 3 => InboundHTLCState::Committed,
14889+ 3 => InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1488014890 4 => {
1488114891 let reason = match <u8 as Readable>::read(reader)? {
1488214892 0 => InboundHTLCRemovalReason::FailRelay(msgs::OnionErrorPacket {
@@ -15160,6 +15170,7 @@ where
1516015170
1516115171 let mut pending_outbound_held_htlc_flags_opt: Option<Vec<Option<()>>> = None;
1516215172 let mut holding_cell_held_htlc_flags_opt: Option<Vec<Option<()>>> = None;
15173+ let mut inbound_committed_update_adds_opt: Option<Vec<Option<msgs::UpdateAddHTLC>>> = None;
1516315174
1516415175 read_tlv_fields!(reader, {
1516515176 (0, announcement_sigs, option),
@@ -15207,6 +15218,7 @@ where
1520715218 (65, quiescent_action, upgradable_option), // Added in 0.2
1520815219 (67, pending_outbound_held_htlc_flags_opt, optional_vec), // Added in 0.2
1520915220 (69, holding_cell_held_htlc_flags_opt, optional_vec), // Added in 0.2
15221+ (71, inbound_committed_update_adds_opt, optional_vec),
1521015222 });
1521115223
1521215224 let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
@@ -15330,6 +15342,17 @@ where
1533015342 return Err(DecodeError::InvalidValue);
1533115343 }
1533215344 }
15345+ if let Some(update_adds) = inbound_committed_update_adds_opt {
15346+ let mut iter = update_adds.into_iter();
15347+ for htlc in pending_inbound_htlcs.iter_mut() {
15348+ if let InboundHTLCState::Committed { ref mut update_add_htlc_opt } = htlc.state {
15349+ *update_add_htlc_opt = iter.next().ok_or(DecodeError::InvalidValue)?;
15350+ }
15351+ }
15352+ if iter.next().is_some() {
15353+ return Err(DecodeError::InvalidValue);
15354+ }
15355+ }
1533315356
1533415357 if let Some(attribution_data_list) = removed_htlc_attribution_data {
1533515358 let mut removed_htlcs = pending_inbound_htlcs.iter_mut().filter_map(|status| {
@@ -15883,7 +15906,7 @@ mod tests {
1588315906 amount_msat: htlc_amount_msat,
1588415907 payment_hash: PaymentHash(Sha256::hash(&[42; 32]).to_byte_array()),
1588515908 cltv_expiry: 300000000,
15886- state: InboundHTLCState::Committed,
15909+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1588715910 });
1588815911
1588915912 node_a_chan.context.pending_outbound_htlcs.push(OutboundHTLCOutput {
@@ -16729,7 +16752,7 @@ mod tests {
1672916752 amount_msat: 1000000,
1673016753 cltv_expiry: 500,
1673116754 payment_hash: PaymentHash::from(payment_preimage_0),
16732- state: InboundHTLCState::Committed,
16755+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1673316756 });
1673416757
1673516758 let payment_preimage_1 =
@@ -16739,7 +16762,7 @@ mod tests {
1673916762 amount_msat: 2000000,
1674016763 cltv_expiry: 501,
1674116764 payment_hash: PaymentHash::from(payment_preimage_1),
16742- state: InboundHTLCState::Committed,
16765+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1674316766 });
1674416767
1674516768 let payment_preimage_2 =
@@ -16779,7 +16802,7 @@ mod tests {
1677916802 amount_msat: 4000000,
1678016803 cltv_expiry: 504,
1678116804 payment_hash: PaymentHash::from(payment_preimage_4),
16782- state: InboundHTLCState::Committed,
16805+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1678316806 });
1678416807
1678516808 // commitment tx with all five HTLCs untrimmed (minimum feerate)
@@ -17168,7 +17191,7 @@ mod tests {
1716817191 amount_msat: 2000000,
1716917192 cltv_expiry: 501,
1717017193 payment_hash: PaymentHash::from(payment_preimage_1),
17171- state: InboundHTLCState::Committed,
17194+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1717217195 });
1717317196
1717417197 chan.context.pending_outbound_htlcs.clear();
@@ -17419,7 +17442,7 @@ mod tests {
1741917442 amount_msat: 5000000,
1742017443 cltv_expiry: 920150,
1742117444 payment_hash: PaymentHash::from(htlc_in_preimage),
17422- state: InboundHTLCState::Committed,
17445+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1742317446 }));
1742417447
1742517448 chan.context.pending_outbound_htlcs.extend(
@@ -17493,7 +17516,7 @@ mod tests {
1749317516 amount_msat: 100000,
1749417517 cltv_expiry: 920125,
1749517518 payment_hash: htlc_0_in_hash,
17496- state: InboundHTLCState::Committed,
17519+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1749717520 });
1749817521
1749917522 let htlc_1_in_preimage =
@@ -17511,7 +17534,7 @@ mod tests {
1751117534 amount_msat: 49900000,
1751217535 cltv_expiry: 920125,
1751317536 payment_hash: htlc_1_in_hash,
17514- state: InboundHTLCState::Committed,
17537+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1751517538 });
1751617539
1751717540 chan.context.pending_outbound_htlcs.extend(
@@ -17578,7 +17601,7 @@ mod tests {
1757817601 amount_msat,
1757917602 cltv_expiry,
1758017603 payment_hash,
17581- state: InboundHTLCState::Committed,
17604+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1758217605 }),
1758317606 );
1758417607
@@ -17884,11 +17907,11 @@ mod tests {
1788417907 assert_eq!(
1788517908 check_v2_funding_inputs_sufficient(
1788617909 220_000,
17887- &[
17888- funding_input_sats(200_000),
17889- funding_input_sats(100_000),
17890- ],
17891- true,
17910+ &[
17911+ funding_input_sats(200_000),
17912+ funding_input_sats(100_000),
17913+ ],
17914+ true,
1789217915 true,
1789317916 2000,
1789417917 ).unwrap(),
@@ -17904,7 +17927,7 @@ mod tests {
1790417927 220_000,
1790517928 &[
1790617929 funding_input_sats(100_000),
17907- ],
17930+ ],
1790817931 true,
1790917932 true,
1791017933 2000,
@@ -17942,8 +17965,8 @@ mod tests {
1794217965 298032,
1794317966 &[
1794417967 funding_input_sats(200_000),
17945- funding_input_sats(100_000),
17946- ],
17968+ funding_input_sats(100_000),
17969+ ],
1794717970 true,
1794817971 true,
1794917972 2200,
0 commit comments