@@ -3813,7 +3813,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
38133813 // First check if a counterparty commitment transaction has been broadcasted:
38143814 macro_rules! claim_htlcs {
38153815 ( $commitment_number: expr, $txid: expr, $htlcs: expr) => {
3816- let htlc_claim_reqs = self . get_counterparty_output_claims_for_preimage( * payment_preimage, funding_spent, $commitment_number, $txid, $htlcs, confirmed_spend_height) ;
3816+ let htlc_claim_reqs = self . get_counterparty_output_claims_for_preimage( * payment_preimage, funding_spent, $commitment_number, $txid, $htlcs, confirmed_spend_height, logger ) ;
38173817 let conf_target = self . closure_conf_target( ) ;
38183818 self . onchain_tx_handler. update_claims_view_from_requests(
38193819 htlc_claim_reqs, self . best_block. height, self . best_block. height, broadcaster,
@@ -3862,6 +3862,9 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
38623862 None
38633863 } ;
38643864 if let Some ( holder_commitment_tx) = holder_commitment_tx {
3865+ self . log_holder_preimage_claim_after_htlc_resolved_on_chain (
3866+ logger, holder_commitment_tx, * payment_preimage,
3867+ ) ;
38653868 // Assume that the broadcasted commitment transaction confirmed in the current best
38663869 // block. Even if not, its a reasonable metric for the bump criteria on the HTLC
38673870 // transactions.
@@ -4965,11 +4968,11 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
49654968 }
49664969 }
49674970
4968- fn get_counterparty_output_claims_for_preimage (
4971+ fn get_counterparty_output_claims_for_preimage < L : Logger > (
49694972 & self , preimage : PaymentPreimage , funding_spent : & FundingScope , commitment_number : u64 ,
49704973 commitment_txid : Txid ,
49714974 per_commitment_option : Option < & Vec < ( HTLCOutputInCommitment , Option < Box < HTLCSource > > ) > > ,
4972- confirmation_height : Option < u32 > ,
4975+ confirmation_height : Option < u32 > , logger : & L ,
49734976 ) -> Vec < ClaimRequest > {
49744977 let per_commitment_claimable_data = match per_commitment_option {
49754978 Some ( outputs) => outputs,
@@ -4985,10 +4988,17 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
49854988 . iter ( )
49864989 . filter_map ( |( htlc, _) | {
49874990 if let Some ( transaction_output_index) = htlc. transaction_output_index {
4988- if htlc. offered
4989- && htlc. payment_hash == matching_payment_hash
4990- && !self . is_htlc_output_resolved_on_chain ( htlc)
4991- {
4991+ if htlc. offered && htlc. payment_hash == matching_payment_hash {
4992+ if let Some ( resolved_htlc) = self . htlc_output_resolution_on_chain ( htlc) {
4993+ self . log_preimage_claim_after_htlc_resolved_on_chain (
4994+ logger,
4995+ commitment_txid,
4996+ htlc,
4997+ preimage,
4998+ resolved_htlc,
4999+ ) ;
5000+ return None ;
5001+ }
49925002 let htlc_data = PackageSolvingData :: CounterpartyOfferedHTLCOutput (
49935003 CounterpartyOfferedHTLCOutput :: build (
49945004 per_commitment_point,
@@ -5014,17 +5024,57 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
50145024 . collect ( )
50155025 }
50165026
5017- fn is_htlc_output_resolved_on_chain ( & self , htlc : & HTLCOutputInCommitment ) -> bool {
5018- if let Some ( transaction_output_index) = htlc. transaction_output_index {
5027+ fn htlc_output_resolution_on_chain (
5028+ & self , htlc : & HTLCOutputInCommitment ,
5029+ ) -> Option < & IrrevocablyResolvedHTLC > {
5030+ htlc. transaction_output_index . and_then ( |transaction_output_index| {
50195031 // Only suppress claims once the commitment HTLC output spend has
50205032 // reached anti-reorg finality. Any output created by that spend may
50215033 // still be CSV-delayed, but the original HTLC outpoint should not be
50225034 // re-claimed.
5023- self . htlcs_resolved_on_chain . iter ( ) . any ( |resolved_htlc| {
5035+ self . htlcs_resolved_on_chain . iter ( ) . find ( |resolved_htlc| {
50245036 resolved_htlc. commitment_tx_output_idx == Some ( transaction_output_index)
50255037 } )
5026- } else {
5027- false
5038+ } )
5039+ }
5040+
5041+ fn log_preimage_claim_after_htlc_resolved_on_chain < L : Logger > (
5042+ & self , logger : & L , commitment_txid : Txid , htlc : & HTLCOutputInCommitment ,
5043+ preimage : PaymentPreimage , resolved_htlc : & IrrevocablyResolvedHTLC ,
5044+ ) {
5045+ if resolved_htlc. payment_preimage == Some ( preimage) {
5046+ return ;
5047+ }
5048+ if let Some ( transaction_output_index) = htlc. transaction_output_index {
5049+ let logger = WithContext :: from ( logger, None , None , Some ( htlc. payment_hash ) ) ;
5050+ if let Some ( resolving_txid) = resolved_htlc. resolving_txid . as_ref ( ) {
5051+ log_error ! ( logger, "WE HAVE LIKELY LOST FUNDS: HTLC output {}:{} was irrevocably resolved on-chain by transaction {} without the payment preimage we now know; not replaying the claim" ,
5052+ commitment_txid, transaction_output_index, resolving_txid) ;
5053+ } else {
5054+ log_error ! ( logger, "WE HAVE LIKELY LOST FUNDS: HTLC output {}:{} was irrevocably resolved on-chain by an unknown transaction without the payment preimage we now know; not replaying the claim" ,
5055+ commitment_txid, transaction_output_index) ;
5056+ }
5057+ }
5058+ }
5059+
5060+ fn log_holder_preimage_claim_after_htlc_resolved_on_chain < L : Logger > (
5061+ & self , logger : & L , holder_tx : & HolderCommitmentTransaction , preimage : PaymentPreimage ,
5062+ ) {
5063+ let matching_payment_hash = PaymentHash :: from ( preimage) ;
5064+ let tx = holder_tx. trust ( ) ;
5065+ for htlc in holder_tx. nondust_htlcs ( ) {
5066+ if htlc. offered || htlc. payment_hash != matching_payment_hash {
5067+ continue ;
5068+ }
5069+ if let Some ( resolved_htlc) = self . htlc_output_resolution_on_chain ( htlc) {
5070+ self . log_preimage_claim_after_htlc_resolved_on_chain (
5071+ logger,
5072+ tx. txid ( ) ,
5073+ htlc,
5074+ preimage,
5075+ resolved_htlc,
5076+ ) ;
5077+ }
50285078 }
50295079 }
50305080
@@ -5075,7 +5125,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
50755125 // per_commitment_data is corrupt or our commitment signing key leaked!
50765126 return ( claimable_outpoints, to_counterparty_output_info) ;
50775127 }
5078- if self . is_htlc_output_resolved_on_chain ( htlc) {
5128+ if self . htlc_output_resolution_on_chain ( htlc) . is_some ( ) {
50795129 continue ;
50805130 }
50815131 let preimage = if htlc. offered {
@@ -5179,7 +5229,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
51795229 let mut htlcs = Vec :: with_capacity ( holder_tx. nondust_htlcs ( ) . len ( ) ) ;
51805230 debug_assert_eq ! ( holder_tx. nondust_htlcs( ) . len( ) , holder_tx. counterparty_htlc_sigs. len( ) ) ;
51815231 for ( htlc, counterparty_sig) in holder_tx. nondust_htlcs ( ) . iter ( ) . zip ( holder_tx. counterparty_htlc_sigs . iter ( ) ) {
5182- if self . is_htlc_output_resolved_on_chain ( htlc) {
5232+ if self . htlc_output_resolution_on_chain ( htlc) . is_some ( ) {
51835233 continue ;
51845234 }
51855235 assert ! ( htlc. transaction_output_index. is_some( ) , "Expected transaction output index for non-dust HTLC" ) ;
0 commit comments