@@ -3823,7 +3823,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
38233823 // First check if a counterparty commitment transaction has been broadcasted:
38243824 macro_rules! claim_htlcs {
38253825 ( $commitment_number: expr, $txid: expr, $htlcs: expr) => {
3826- let ( htlc_claim_reqs, _ ) = self . get_counterparty_output_claim_info ( funding_spent, $commitment_number, $txid, None , $htlcs, confirmed_spend_height) ;
3826+ let htlc_claim_reqs = self . get_counterparty_output_claims_for_preimage ( * payment_preimage , funding_spent, $commitment_number, $txid, $htlcs, confirmed_spend_height) ;
38273827 let conf_target = self . closure_conf_target( ) ;
38283828 self . onchain_tx_handler. update_claims_view_from_requests(
38293829 htlc_claim_reqs, self . best_block. height, self . best_block. height, broadcaster,
@@ -4722,7 +4722,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
47224722 ( htlc, htlc_source. as_ref( ) . map( |htlc_source| htlc_source. as_ref( ) ) )
47234723 ) , logger) ;
47244724 let ( htlc_claim_reqs, counterparty_output_info) =
4725- self . get_counterparty_output_claim_info ( funding_spent, commitment_number, commitment_txid, Some ( commitment_tx) , per_commitment_option , Some ( height) ) ;
4725+ self . get_counterparty_output_claim_info ( funding_spent, commitment_number, commitment_txid, commitment_tx, per_commitment_claimable_data , Some ( height) ) ;
47264726 to_counterparty_output_info = counterparty_output_info;
47274727 for req in htlc_claim_reqs {
47284728 claimable_outpoints. push ( req) ;
@@ -4732,75 +4732,119 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
47324732 ( claimable_outpoints, to_counterparty_output_info)
47334733 }
47344734
4735+ fn get_point_for_commitment_number ( & self , commitment_number : u64 ) -> Option < PublicKey > {
4736+ let per_commitment_points = & self . their_cur_per_commitment_points ?;
4737+
4738+ // If the counterparty commitment tx is the latest valid state, use their latest
4739+ // per-commitment point
4740+ if per_commitment_points. 0 == commitment_number {
4741+ Some ( per_commitment_points. 1 )
4742+ } else if let Some ( point) = per_commitment_points. 2 . as_ref ( ) {
4743+ // If counterparty commitment tx is the state previous to the latest valid state, use
4744+ // their previous per-commitment point (non-atomicity of revocation means it's valid for
4745+ // them to temporarily have two valid commitment txns from our viewpoint)
4746+ if per_commitment_points. 0 == commitment_number + 1 {
4747+ Some ( * point)
4748+ } else {
4749+ None
4750+ }
4751+ } else {
4752+ None
4753+ }
4754+ }
4755+
4756+ fn get_counterparty_output_claims_for_preimage (
4757+ & self , preimage : PaymentPreimage , funding_spent : & FundingScope , commitment_number : u64 ,
4758+ commitment_txid : Txid ,
4759+ per_commitment_option : Option < & Vec < ( HTLCOutputInCommitment , Option < Box < HTLCSource > > ) > > ,
4760+ confirmation_height : Option < u32 > ,
4761+ ) -> Vec < PackageTemplate > {
4762+ let per_commitment_claimable_data = match per_commitment_option {
4763+ Some ( outputs) => outputs,
4764+ None => return Vec :: new ( ) ,
4765+ } ;
4766+ let per_commitment_point = match self . get_point_for_commitment_number ( commitment_number) {
4767+ Some ( point) => point,
4768+ None => return Vec :: new ( ) ,
4769+ } ;
4770+
4771+ let matching_payment_hash = PaymentHash :: from ( preimage) ;
4772+ per_commitment_claimable_data
4773+ . iter ( )
4774+ . filter_map ( |( htlc, _) | {
4775+ if let Some ( transaction_output_index) = htlc. transaction_output_index {
4776+ if htlc. offered && htlc. payment_hash == matching_payment_hash {
4777+ let htlc_data = PackageSolvingData :: CounterpartyOfferedHTLCOutput (
4778+ CounterpartyOfferedHTLCOutput :: build (
4779+ per_commitment_point,
4780+ preimage,
4781+ htlc. clone ( ) ,
4782+ funding_spent. channel_parameters . clone ( ) ,
4783+ confirmation_height,
4784+ ) ,
4785+ ) ;
4786+ Some ( PackageTemplate :: build_package (
4787+ commitment_txid,
4788+ transaction_output_index,
4789+ htlc_data,
4790+ htlc. cltv_expiry ,
4791+ ) )
4792+ } else {
4793+ None
4794+ }
4795+ } else {
4796+ None
4797+ }
4798+ } )
4799+ . collect ( )
4800+ }
4801+
47354802 /// Returns the HTLC claim package templates and the counterparty output info
47364803 fn get_counterparty_output_claim_info (
47374804 & self , funding_spent : & FundingScope , commitment_number : u64 , commitment_txid : Txid ,
4738- tx : Option < & Transaction > ,
4739- per_commitment_option : Option < & Vec < ( HTLCOutputInCommitment , Option < Box < HTLCSource > > ) > > ,
4805+ tx : & Transaction ,
4806+ per_commitment_claimable_data : & [ ( HTLCOutputInCommitment , Option < Box < HTLCSource > > ) ] ,
47404807 confirmation_height : Option < u32 > ,
47414808 ) -> ( Vec < PackageTemplate > , CommitmentTxCounterpartyOutputInfo ) {
47424809 let mut claimable_outpoints = Vec :: new ( ) ;
47434810 let mut to_counterparty_output_info: CommitmentTxCounterpartyOutputInfo = None ;
47444811
4745- let per_commitment_claimable_data = match per_commitment_option {
4746- Some ( outputs) => outputs,
4747- None => return ( claimable_outpoints, to_counterparty_output_info) ,
4748- } ;
4749- let per_commitment_points = match self . their_cur_per_commitment_points {
4750- Some ( points) => points,
4812+ let per_commitment_point = match self . get_point_for_commitment_number ( commitment_number) {
4813+ Some ( point) => point,
47514814 None => return ( claimable_outpoints, to_counterparty_output_info) ,
47524815 } ;
47534816
4754- let per_commitment_point =
4755- // If the counterparty commitment tx is the latest valid state, use their latest
4756- // per-commitment point
4757- if per_commitment_points. 0 == commitment_number { & per_commitment_points. 1 }
4758- else if let Some ( point) = per_commitment_points. 2 . as_ref ( ) {
4759- // If counterparty commitment tx is the state previous to the latest valid state, use
4760- // their previous per-commitment point (non-atomicity of revocation means it's valid for
4761- // them to temporarily have two valid commitment txns from our viewpoint)
4762- if per_commitment_points. 0 == commitment_number + 1 {
4763- point
4764- } else { return ( claimable_outpoints, to_counterparty_output_info) ; }
4765- } else { return ( claimable_outpoints, to_counterparty_output_info) ; } ;
4766-
4767- if let Some ( transaction) = tx {
4768- let revocation_pubkey = RevocationKey :: from_basepoint (
4769- & self . onchain_tx_handler . secp_ctx ,
4770- & self . holder_revocation_basepoint ,
4771- & per_commitment_point,
4772- ) ;
4773-
4774- let delayed_key = DelayedPaymentKey :: from_basepoint (
4775- & self . onchain_tx_handler . secp_ctx ,
4776- & self . counterparty_commitment_params . counterparty_delayed_payment_base_key ,
4777- & per_commitment_point,
4778- ) ;
4779-
4780- let revokeable_p2wsh = chan_utils:: get_revokeable_redeemscript (
4781- & revocation_pubkey,
4782- self . counterparty_commitment_params . on_counterparty_tx_csv ,
4783- & delayed_key,
4784- )
4785- . to_p2wsh ( ) ;
4786- for ( idx, outp) in transaction. output . iter ( ) . enumerate ( ) {
4787- if outp. script_pubkey == revokeable_p2wsh {
4788- to_counterparty_output_info =
4789- Some ( ( idx. try_into ( ) . expect ( "Can't have > 2^32 outputs" ) , outp. value ) ) ;
4790- }
4817+ let revocation_pubkey = RevocationKey :: from_basepoint (
4818+ & self . onchain_tx_handler . secp_ctx ,
4819+ & self . holder_revocation_basepoint ,
4820+ & per_commitment_point,
4821+ ) ;
4822+ let delayed_key = DelayedPaymentKey :: from_basepoint (
4823+ & self . onchain_tx_handler . secp_ctx ,
4824+ & self . counterparty_commitment_params . counterparty_delayed_payment_base_key ,
4825+ & per_commitment_point,
4826+ ) ;
4827+ let revokeable_p2wsh = chan_utils:: get_revokeable_redeemscript (
4828+ & revocation_pubkey,
4829+ self . counterparty_commitment_params . on_counterparty_tx_csv ,
4830+ & delayed_key,
4831+ )
4832+ . to_p2wsh ( ) ;
4833+ for ( idx, outp) in tx. output . iter ( ) . enumerate ( ) {
4834+ if outp. script_pubkey == revokeable_p2wsh {
4835+ to_counterparty_output_info =
4836+ Some ( ( idx. try_into ( ) . expect ( "Can't have > 2^32 outputs" ) , outp. value ) ) ;
47914837 }
47924838 }
47934839
47944840 for & ( ref htlc, _) in per_commitment_claimable_data. iter ( ) {
47954841 if let Some ( transaction_output_index) = htlc. transaction_output_index {
4796- if let Some ( transaction) = tx {
4797- if transaction_output_index as usize >= transaction. output . len ( )
4798- || transaction. output [ transaction_output_index as usize ] . value
4799- != htlc. to_bitcoin_amount ( )
4800- {
4801- // per_commitment_data is corrupt or our commitment signing key leaked!
4802- return ( claimable_outpoints, to_counterparty_output_info) ;
4803- }
4842+ if transaction_output_index as usize >= tx. output . len ( )
4843+ || tx. output [ transaction_output_index as usize ] . value
4844+ != htlc. to_bitcoin_amount ( )
4845+ {
4846+ // per_commitment_data is corrupt or our commitment signing key leaked!
4847+ return ( claimable_outpoints, to_counterparty_output_info) ;
48044848 }
48054849 let preimage = if htlc. offered {
48064850 if let Some ( ( p, _) ) = self . payment_preimages . get ( & htlc. payment_hash ) {
@@ -4815,7 +4859,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
48154859 let counterparty_htlc_outp = if htlc. offered {
48164860 PackageSolvingData :: CounterpartyOfferedHTLCOutput (
48174861 CounterpartyOfferedHTLCOutput :: build (
4818- * per_commitment_point,
4862+ per_commitment_point,
48194863 preimage. unwrap ( ) ,
48204864 htlc. clone ( ) ,
48214865 funding_spent. channel_parameters . clone ( ) ,
@@ -4825,7 +4869,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
48254869 } else {
48264870 PackageSolvingData :: CounterpartyReceivedHTLCOutput (
48274871 CounterpartyReceivedHTLCOutput :: build (
4828- * per_commitment_point,
4872+ per_commitment_point,
48294873 htlc. clone ( ) ,
48304874 funding_spent. channel_parameters . clone ( ) ,
48314875 confirmation_height,
0 commit comments