@@ -642,6 +642,21 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
642642 } ,
643643) ;
644644
645+ /// Information about an HTLC forward that was claimed via preimage on the outbound edge, included
646+ /// in [`ChannelMonitorUpdateStep`] so the monitor can generate events with the full claim context.
647+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
648+ pub ( crate ) struct OutboundHTLCClaim {
649+ pub htlc_id : SentHTLCId ,
650+ pub preimage : PaymentPreimage ,
651+ pub skimmed_fee_msat : Option < u64 > ,
652+ }
653+
654+ impl_writeable_tlv_based ! ( OutboundHTLCClaim , {
655+ ( 0 , htlc_id, required) ,
656+ ( 2 , preimage, required) ,
657+ ( 4 , skimmed_fee_msat, option) ,
658+ } ) ;
659+
645660#[ derive( Clone , Debug , PartialEq , Eq ) ]
646661pub ( crate ) enum ChannelMonitorUpdateStep {
647662 LatestHolderCommitmentTXInfo {
@@ -653,13 +668,13 @@ pub(crate) enum ChannelMonitorUpdateStep {
653668 /// `htlc_outputs` will only include dust HTLCs. We still have to track the
654669 /// `Option<Signature>` for backwards compatibility.
655670 htlc_outputs : Vec < ( HTLCOutputInCommitment , Option < Signature > , Option < HTLCSource > ) > ,
656- claimed_htlcs : Vec < ( SentHTLCId , PaymentPreimage ) > ,
671+ claimed_htlcs : Vec < OutboundHTLCClaim > ,
657672 nondust_htlc_sources : Vec < HTLCSource > ,
658673 } ,
659674 LatestHolderCommitment {
660675 commitment_txs : Vec < HolderCommitmentTransaction > ,
661676 htlc_data : CommitmentHTLCData ,
662- claimed_htlcs : Vec < ( SentHTLCId , PaymentPreimage ) > ,
677+ claimed_htlcs : Vec < OutboundHTLCClaim > ,
663678 } ,
664679 LatestCounterpartyCommitmentTXInfo {
665680 commitment_txid : Txid ,
@@ -740,9 +755,29 @@ impl ChannelMonitorUpdateStep {
740755impl_writeable_tlv_based_enum_upgradable ! ( ChannelMonitorUpdateStep ,
741756 ( 0 , LatestHolderCommitmentTXInfo ) => {
742757 ( 0 , commitment_tx, required) ,
743- ( 1 , claimed_htlcs, optional_vec) ,
758+ ( 1 , _legacy_claimed_htlcs, ( legacy, Vec <( SentHTLCId , PaymentPreimage ) >,
759+ |v: Option <& Vec <( SentHTLCId , PaymentPreimage ) >>| {
760+ // Only populate from legacy if the new-format tag 5 wasn't read.
761+ if let Some ( legacy) = v {
762+ if claimed_htlcs. as_ref( ) . map_or( true , |v| v. is_empty( ) ) {
763+ claimed_htlcs = Some ( legacy. iter( ) . map( |( htlc_id, preimage) | OutboundHTLCClaim {
764+ htlc_id: * htlc_id, preimage: * preimage, skimmed_fee_msat: None ,
765+ } ) . collect( ) ) ;
766+ }
767+ }
768+ Ok ( ( ) )
769+ } ,
770+ |us: & ChannelMonitorUpdateStep | match us {
771+ ChannelMonitorUpdateStep :: LatestHolderCommitmentTXInfo { claimed_htlcs, .. } => {
772+ let claims: Vec <( SentHTLCId , PaymentPreimage ) > =
773+ claimed_htlcs. iter( ) . map( |claim| ( claim. htlc_id, claim. preimage) ) . collect( ) ;
774+ Some ( claims)
775+ }
776+ _ => None
777+ } ) ) ,
744778 ( 2 , htlc_outputs, required_vec) ,
745779 ( 4 , nondust_htlc_sources, optional_vec) ,
780+ ( 5 , claimed_htlcs, optional_vec) , // Added in 0.4
746781 } ,
747782 ( 1 , LatestCounterpartyCommitmentTXInfo ) => {
748783 ( 0 , commitment_txid, required) ,
@@ -777,7 +812,27 @@ impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep,
777812 ( 8 , LatestHolderCommitment ) => {
778813 ( 1 , commitment_txs, required_vec) ,
779814 ( 3 , htlc_data, required) ,
780- ( 5 , claimed_htlcs, required_vec) ,
815+ ( 5 , _legacy_claimed_htlcs, ( legacy, Vec <( SentHTLCId , PaymentPreimage ) >,
816+ |v: Option <& Vec <( SentHTLCId , PaymentPreimage ) >>| {
817+ // Only populate from legacy if the new-format tag 7 wasn't read.
818+ if let Some ( legacy) = v {
819+ if claimed_htlcs. as_ref( ) . map_or( true , |v| v. is_empty( ) ) {
820+ claimed_htlcs = Some ( legacy. iter( ) . map( |( htlc_id, preimage) | OutboundHTLCClaim {
821+ htlc_id: * htlc_id, preimage: * preimage, skimmed_fee_msat: None ,
822+ } ) . collect( ) ) ;
823+ }
824+ }
825+ Ok ( ( ) )
826+ } ,
827+ |us: & ChannelMonitorUpdateStep | match us {
828+ ChannelMonitorUpdateStep :: LatestHolderCommitment { claimed_htlcs, .. } => {
829+ let claims: Vec <( SentHTLCId , PaymentPreimage ) > =
830+ claimed_htlcs. iter( ) . map( |claim| ( claim. htlc_id, claim. preimage) ) . collect( ) ;
831+ Some ( claims)
832+ }
833+ _ => None
834+ } ) ) ,
835+ ( 7 , claimed_htlcs, optional_vec) , // Added in 0.4
781836 } ,
782837 ( 10 , RenegotiatedFunding ) => {
783838 ( 1 , channel_parameters, ( required: ReadableArgs , None ) ) ,
@@ -3692,7 +3747,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
36923747 fn provide_latest_holder_commitment_tx (
36933748 & mut self , holder_commitment_tx : HolderCommitmentTransaction ,
36943749 htlc_outputs : & [ ( HTLCOutputInCommitment , Option < Signature > , Option < HTLCSource > ) ] ,
3695- claimed_htlcs : & [ ( SentHTLCId , PaymentPreimage ) ] , mut nondust_htlc_sources : Vec < HTLCSource > ,
3750+ claimed_htlcs : & [ OutboundHTLCClaim ] , mut nondust_htlc_sources : Vec < HTLCSource > ,
36963751 ) -> Result < ( ) , & ' static str > {
36973752 let dust_htlcs = if htlc_outputs. iter ( ) . any ( |( _, s, _) | s. is_some ( ) ) {
36983753 // If we have non-dust HTLCs in htlc_outputs, ensure they match the HTLCs in the
@@ -3813,7 +3868,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
38133868
38143869 fn update_holder_commitment_data (
38153870 & mut self , commitment_txs : Vec < HolderCommitmentTransaction > ,
3816- mut htlc_data : CommitmentHTLCData , claimed_htlcs : & [ ( SentHTLCId , PaymentPreimage ) ] ,
3871+ mut htlc_data : CommitmentHTLCData , claimed_htlcs : & [ OutboundHTLCClaim ] ,
38173872 ) -> Result < ( ) , & ' static str > {
38183873 self . verify_matching_commitment_transactions (
38193874 commitment_txs. iter ( ) . map ( |holder_commitment_tx| holder_commitment_tx. deref ( ) ) ,
@@ -3833,7 +3888,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
38333888 mem:: swap ( & mut htlc_data, & mut self . current_holder_htlc_data ) ;
38343889 self . prev_holder_htlc_data = Some ( htlc_data) ;
38353890
3836- for ( claimed_htlc_id , claimed_preimage ) in claimed_htlcs {
3891+ for claim in claimed_htlcs {
38373892 let htlc_opt = self
38383893 . funding
38393894 . counterparty_claimable_outpoints
@@ -3842,7 +3897,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
38423897 . iter ( )
38433898 . find_map ( |( htlc, source_opt) | {
38443899 if let Some ( source) = source_opt {
3845- if SentHTLCId :: from_source ( source) == * claimed_htlc_id {
3900+ if SentHTLCId :: from_source ( source) == claim . htlc_id {
38463901 return Some ( ( htlc, source) ) ;
38473902 }
38483903 }
@@ -3853,14 +3908,14 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
38533908 if let Some ( ( htlc, source) ) = htlc_opt {
38543909 self . push_monitor_event ( MonitorEvent :: HTLCEvent ( HTLCUpdate {
38553910 payment_hash : htlc. payment_hash ,
3856- payment_preimage : Some ( * claimed_preimage ) ,
3911+ payment_preimage : Some ( claim . preimage ) ,
38573912 source : * source. clone ( ) ,
38583913 htlc_value_msat : Some ( htlc. amount_msat ) ,
38593914 user_channel_id : self . user_channel_id ,
38603915 } ) ) ;
38613916 }
38623917 }
3863- self . counterparty_fulfilled_htlcs . insert ( * claimed_htlc_id , * claimed_preimage ) ;
3918+ self . counterparty_fulfilled_htlcs . insert ( claim . htlc_id , claim . preimage ) ;
38643919 }
38653920
38663921 Ok ( ( ) )
0 commit comments