@@ -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}
@@ -4091,7 +4093,7 @@ where
40914093
40924094 if self.pending_inbound_htlcs.iter()
40934095 .any(|htlc| match htlc.state {
4094- InboundHTLCState::Committed => false,
4096+ InboundHTLCState::Committed { .. } => false,
40954097 // An HTLC removal from the local node is pending on the remote commitment.
40964098 InboundHTLCState::LocalRemoved(_) => true,
40974099 // An HTLC add from the remote node is pending on the local commitment.
@@ -4520,7 +4522,7 @@ where
45204522 (InboundHTLCState::RemoteAnnounced(..), _) => true,
45214523 (InboundHTLCState::AwaitingRemoteRevokeToAnnounce(..), _) => true,
45224524 (InboundHTLCState::AwaitingAnnouncedRemoteRevoke(..), _) => true,
4523- (InboundHTLCState::Committed, _) => true,
4525+ (InboundHTLCState::Committed { .. } , _) => true,
45244526 (InboundHTLCState::LocalRemoved(..), true) => true,
45254527 (InboundHTLCState::LocalRemoved(..), false) => false,
45264528 })
@@ -7303,7 +7305,7 @@ where
73037305 payment_preimage_arg
73047306 );
73057307 match htlc.state {
7306- InboundHTLCState::Committed => {},
7308+ InboundHTLCState::Committed { .. } => {},
73077309 InboundHTLCState::LocalRemoved(ref reason) => {
73087310 if let &InboundHTLCRemovalReason::Fulfill(_, _) = reason {
73097311 } else {
@@ -7396,7 +7398,7 @@ where
73967398
73977399 {
73987400 let htlc = &mut self.context.pending_inbound_htlcs[pending_idx];
7399- if let InboundHTLCState::Committed = htlc.state {
7401+ if let InboundHTLCState::Committed { .. } = htlc.state {
74007402 } else {
74017403 debug_assert!(
74027404 false,
@@ -7531,7 +7533,7 @@ where
75317533 for (idx, htlc) in self.context.pending_inbound_htlcs.iter().enumerate() {
75327534 if htlc.htlc_id == htlc_id_arg {
75337535 match htlc.state {
7534- InboundHTLCState::Committed => {},
7536+ InboundHTLCState::Committed { .. } => {},
75357537 InboundHTLCState::LocalRemoved(_) => {
75367538 return Err(ChannelError::Ignore(format!("HTLC {} was already resolved", htlc.htlc_id)));
75377539 },
@@ -8690,7 +8692,7 @@ where
86908692 false
86918693 };
86928694 if swap {
8693- let mut state = InboundHTLCState::Committed;
8695+ let mut state = InboundHTLCState::Committed { update_add_htlc_opt: None } ;
86948696 mem::swap(&mut state, &mut htlc.state);
86958697
86968698 if let InboundHTLCState::AwaitingRemoteRevokeToAnnounce(resolution) = state {
@@ -8729,14 +8731,19 @@ where
87298731 PendingHTLCStatus::Forward(forward_info) => {
87308732 log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed, attempting to forward", &htlc.payment_hash);
87318733 to_forward_infos.push((forward_info, htlc.htlc_id));
8732- htlc.state = InboundHTLCState::Committed;
8734+ // TODO: this is currently unreachable, so is it okay? will we lose a forward?
8735+ htlc.state = InboundHTLCState::Committed {
8736+ update_add_htlc_opt: None,
8737+ };
87338738 },
87348739 }
87358740 },
87368741 InboundHTLCResolution::Pending { update_add_htlc } => {
87378742 log_trace!(logger, " ...promoting inbound AwaitingAnnouncedRemoteRevoke {} to Committed", &htlc.payment_hash);
8738- pending_update_adds.push(update_add_htlc);
8739- htlc.state = InboundHTLCState::Committed;
8743+ pending_update_adds.push(update_add_htlc.clone());
8744+ htlc.state = InboundHTLCState::Committed {
8745+ update_add_htlc_opt: Some(update_add_htlc),
8746+ };
87408747 },
87418748 }
87428749 }
@@ -9266,7 +9273,7 @@ where
92669273 // in response to it yet, so don't touch it.
92679274 true
92689275 },
9269- InboundHTLCState::Committed => true,
9276+ InboundHTLCState::Committed { .. } => true,
92709277 InboundHTLCState::LocalRemoved(_) => {
92719278 // We (hopefully) sent a commitment_signed updating this HTLC (which we can
92729279 // re-transmit if needed) and they may have even sent a revoke_and_ack back
@@ -14467,6 +14474,7 @@ where
1446714474 }
1446814475 }
1446914476 let mut removed_htlc_attribution_data: Vec<&Option<AttributionData>> = Vec::new();
14477+ let mut inbound_committed_update_adds: Vec<Option<msgs::UpdateAddHTLC>> = Vec::new();
1447014478 (self.context.pending_inbound_htlcs.len() as u64 - dropped_inbound_htlcs).write(writer)?;
1447114479 for htlc in self.context.pending_inbound_htlcs.iter() {
1447214480 if let &InboundHTLCState::RemoteAnnounced(_) = &htlc.state {
@@ -14486,8 +14494,9 @@ where
1448614494 2u8.write(writer)?;
1448714495 htlc_resolution.write(writer)?;
1448814496 },
14489- &InboundHTLCState::Committed => {
14497+ &InboundHTLCState::Committed { ref update_add_htlc_opt } => {
1449014498 3u8.write(writer)?;
14499+ inbound_committed_update_adds.push(update_add_htlc_opt.clone());
1449114500 },
1449214501 &InboundHTLCState::LocalRemoved(ref removal_reason) => {
1449314502 4u8.write(writer)?;
@@ -14860,6 +14869,7 @@ where
1486014869 (69, holding_cell_held_htlc_flags, optional_vec), // Added in 0.2
1486114870 (71, holder_commitment_point_previous_revoked, option), // Added in 0.3
1486214871 (73, holder_commitment_point_last_revoked, option), // Added in 0.3
14872+ (75, inbound_committed_update_adds, optional_vec),
1486314873 });
1486414874
1486514875 Ok(())
@@ -14943,7 +14953,7 @@ where
1494314953 };
1494414954 InboundHTLCState::AwaitingAnnouncedRemoteRevoke(resolution)
1494514955 },
14946- 3 => InboundHTLCState::Committed,
14956+ 3 => InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1494714957 4 => {
1494814958 let reason = match <u8 as Readable>::read(reader)? {
1494914959 0 => InboundHTLCRemovalReason::FailRelay(msgs::OnionErrorPacket {
@@ -15229,6 +15239,7 @@ where
1522915239
1523015240 let mut pending_outbound_held_htlc_flags_opt: Option<Vec<Option<()>>> = None;
1523115241 let mut holding_cell_held_htlc_flags_opt: Option<Vec<Option<()>>> = None;
15242+ let mut inbound_committed_update_adds_opt: Option<Vec<Option<msgs::UpdateAddHTLC>>> = None;
1523215243
1523315244 read_tlv_fields!(reader, {
1523415245 (0, announcement_sigs, option),
@@ -15278,6 +15289,7 @@ where
1527815289 (69, holding_cell_held_htlc_flags_opt, optional_vec), // Added in 0.2
1527915290 (71, holder_commitment_point_previous_revoked_opt, option), // Added in 0.3
1528015291 (73, holder_commitment_point_last_revoked_opt, option), // Added in 0.3
15292+ (75, inbound_committed_update_adds_opt, optional_vec),
1528115293 });
1528215294
1528315295 let holder_signer = signer_provider.derive_channel_signer(channel_keys_id);
@@ -15401,6 +15413,17 @@ where
1540115413 return Err(DecodeError::InvalidValue);
1540215414 }
1540315415 }
15416+ if let Some(update_adds) = inbound_committed_update_adds_opt {
15417+ let mut iter = update_adds.into_iter();
15418+ for htlc in pending_inbound_htlcs.iter_mut() {
15419+ if let InboundHTLCState::Committed { ref mut update_add_htlc_opt } = htlc.state {
15420+ *update_add_htlc_opt = iter.next().ok_or(DecodeError::InvalidValue)?;
15421+ }
15422+ }
15423+ if iter.next().is_some() {
15424+ return Err(DecodeError::InvalidValue);
15425+ }
15426+ }
1540415427
1540515428 if let Some(attribution_data_list) = removed_htlc_attribution_data {
1540615429 let mut removed_htlcs = pending_inbound_htlcs.iter_mut().filter_map(|status| {
@@ -15985,7 +16008,7 @@ mod tests {
1598516008 amount_msat: htlc_amount_msat,
1598616009 payment_hash: PaymentHash(Sha256::hash(&[42; 32]).to_byte_array()),
1598716010 cltv_expiry: 300000000,
15988- state: InboundHTLCState::Committed,
16011+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1598916012 });
1599016013
1599116014 node_a_chan.context.pending_outbound_htlcs.push(OutboundHTLCOutput {
@@ -16831,7 +16854,7 @@ mod tests {
1683116854 amount_msat: 1000000,
1683216855 cltv_expiry: 500,
1683316856 payment_hash: PaymentHash::from(payment_preimage_0),
16834- state: InboundHTLCState::Committed,
16857+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1683516858 });
1683616859
1683716860 let payment_preimage_1 =
@@ -16841,7 +16864,7 @@ mod tests {
1684116864 amount_msat: 2000000,
1684216865 cltv_expiry: 501,
1684316866 payment_hash: PaymentHash::from(payment_preimage_1),
16844- state: InboundHTLCState::Committed,
16867+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1684516868 });
1684616869
1684716870 let payment_preimage_2 =
@@ -16881,7 +16904,7 @@ mod tests {
1688116904 amount_msat: 4000000,
1688216905 cltv_expiry: 504,
1688316906 payment_hash: PaymentHash::from(payment_preimage_4),
16884- state: InboundHTLCState::Committed,
16907+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1688516908 });
1688616909
1688716910 // commitment tx with all five HTLCs untrimmed (minimum feerate)
@@ -17270,7 +17293,7 @@ mod tests {
1727017293 amount_msat: 2000000,
1727117294 cltv_expiry: 501,
1727217295 payment_hash: PaymentHash::from(payment_preimage_1),
17273- state: InboundHTLCState::Committed,
17296+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1727417297 });
1727517298
1727617299 chan.context.pending_outbound_htlcs.clear();
@@ -17521,7 +17544,7 @@ mod tests {
1752117544 amount_msat: 5000000,
1752217545 cltv_expiry: 920150,
1752317546 payment_hash: PaymentHash::from(htlc_in_preimage),
17524- state: InboundHTLCState::Committed,
17547+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1752517548 }));
1752617549
1752717550 chan.context.pending_outbound_htlcs.extend(
@@ -17595,7 +17618,7 @@ mod tests {
1759517618 amount_msat: 100000,
1759617619 cltv_expiry: 920125,
1759717620 payment_hash: htlc_0_in_hash,
17598- state: InboundHTLCState::Committed,
17621+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1759917622 });
1760017623
1760117624 let htlc_1_in_preimage =
@@ -17613,7 +17636,7 @@ mod tests {
1761317636 amount_msat: 49900000,
1761417637 cltv_expiry: 920125,
1761517638 payment_hash: htlc_1_in_hash,
17616- state: InboundHTLCState::Committed,
17639+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1761717640 });
1761817641
1761917642 chan.context.pending_outbound_htlcs.extend(
@@ -17721,7 +17744,7 @@ mod tests {
1772117744 amount_msat,
1772217745 cltv_expiry,
1772317746 payment_hash,
17724- state: InboundHTLCState::Committed,
17747+ state: InboundHTLCState::Committed { update_add_htlc_opt: None } ,
1772517748 }),
1772617749 );
1772717750
0 commit comments