@@ -54,6 +54,7 @@ use util::events::Event;
5454use prelude:: * ;
5555use core:: { cmp, mem} ;
5656use io:: { self , Error } ;
57+ use core:: convert:: TryInto ;
5758use core:: ops:: Deref ;
5859use sync:: Mutex ;
5960
@@ -345,6 +346,11 @@ impl OnchainEventEntry {
345346 }
346347}
347348
349+ /// The (output index, sats value) for the counterparty's output in a commitment transaction.
350+ ///
351+ /// This was added as an `Option` in 0.0.110.
352+ type CommitmentTxCounterpartyOutputInfo = Option < ( u32 , u64 ) > ;
353+
348354/// Upon discovering of some classes of onchain tx by ChannelMonitor, we may have to take actions on it
349355/// once they mature to enough confirmations (ANTI_REORG_DELAY)
350356#[ derive( PartialEq ) ]
@@ -372,6 +378,9 @@ enum OnchainEvent {
372378 /// The CSV delay for the output of the funding spend transaction (implying it is a local
373379 /// commitment transaction, and this is the delay on the to_self output).
374380 on_local_output_csv : Option < u16 > ,
381+ /// If the funding spend transaction was a known remote commitment transaction, we track
382+ /// the output index and amount of the counterparty's `to_self` output here.
383+ commitment_tx_to_counterparty_output : CommitmentTxCounterpartyOutputInfo ,
375384 } ,
376385 /// A spend of a commitment transaction HTLC output, set in the cases where *no* `HTLCUpdate`
377386 /// is constructed. This is used when
@@ -436,6 +445,7 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
436445 } ,
437446 ( 3 , FundingSpendConfirmation ) => {
438447 ( 0 , on_local_output_csv, option) ,
448+ ( 1 , commitment_tx_to_counterparty_output, option) ,
439449 } ,
440450 ( 5 , HTLCSpendConfirmation ) => {
441451 ( 0 , commitment_tx_output_idx, required) ,
@@ -714,6 +724,7 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
714724 funding_spend_seen : bool ,
715725
716726 funding_spend_confirmed : Option < Txid > ,
727+ confirmed_commitment_tx_counterparty_output : CommitmentTxCounterpartyOutputInfo ,
717728 /// The set of HTLCs which have been either claimed or failed on chain and have reached
718729 /// the requisite confirmations on the claim/fail transaction (either ANTI_REORG_DELAY or the
719730 /// spending CSV for revocable outputs).
@@ -783,6 +794,7 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
783794 self . holder_tx_signed != other. holder_tx_signed ||
784795 self . funding_spend_seen != other. funding_spend_seen ||
785796 self . funding_spend_confirmed != other. funding_spend_confirmed ||
797+ self . confirmed_commitment_tx_counterparty_output != other. confirmed_commitment_tx_counterparty_output ||
786798 self . htlcs_resolved_on_chain != other. htlcs_resolved_on_chain
787799 {
788800 false
@@ -962,6 +974,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
962974 ( 5 , self . pending_monitor_events, vec_type) ,
963975 ( 7 , self . funding_spend_seen, required) ,
964976 ( 9 , self . counterparty_node_id, option) ,
977+ ( 11 , self . confirmed_commitment_tx_counterparty_output, option) ,
965978 } ) ;
966979
967980 Ok ( ( ) )
@@ -1068,6 +1081,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
10681081 holder_tx_signed : false ,
10691082 funding_spend_seen : false ,
10701083 funding_spend_confirmed : None ,
1084+ confirmed_commitment_tx_counterparty_output : None ,
10711085 htlcs_resolved_on_chain : Vec :: new ( ) ,
10721086
10731087 best_block,
@@ -1918,7 +1932,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
19181932 // First check if a counterparty commitment transaction has been broadcasted:
19191933 macro_rules! claim_htlcs {
19201934 ( $commitment_number: expr, $txid: expr) => {
1921- let htlc_claim_reqs = self . get_counterparty_htlc_output_claim_reqs ( $commitment_number, $txid, None ) ;
1935+ let ( htlc_claim_reqs, _ ) = self . get_counterparty_output_claim_info ( $commitment_number, $txid, None ) ;
19221936 self . onchain_tx_handler. update_claims_view( & Vec :: new( ) , htlc_claim_reqs, self . best_block. height( ) , self . best_block. height( ) , broadcaster, fee_estimator, logger) ;
19231937 }
19241938 }
@@ -2097,13 +2111,18 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
20972111 /// data in counterparty_claimable_outpoints. Will directly claim any HTLC outputs which expire at a
20982112 /// height > height + CLTV_SHARED_CLAIM_BUFFER. In any case, will install monitoring for
20992113 /// HTLC-Success/HTLC-Timeout transactions.
2100- /// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
2101- /// revoked counterparty commitment tx
2102- fn check_spend_counterparty_transaction < L : Deref > ( & mut self , tx : & Transaction , height : u32 , logger : & L ) -> ( Vec < PackageTemplate > , TransactionOutputs ) where L :: Target : Logger {
2114+ ///
2115+ /// Returns packages to claim the revoked output(s), as well as additional outputs to watch and
2116+ /// general information about the output that is to the counterparty in the commitment
2117+ /// transaction.
2118+ fn check_spend_counterparty_transaction < L : Deref > ( & mut self , tx : & Transaction , height : u32 , logger : & L )
2119+ -> ( Vec < PackageTemplate > , TransactionOutputs , CommitmentTxCounterpartyOutputInfo )
2120+ where L :: Target : Logger {
21032121 // Most secp and related errors trying to create keys means we have no hope of constructing
21042122 // a spend transaction...so we return no transactions to broadcast
21052123 let mut claimable_outpoints = Vec :: new ( ) ;
21062124 let mut watch_outputs = Vec :: new ( ) ;
2125+ let mut to_counterparty_output_info = None ;
21072126
21082127 let commitment_txid = tx. txid ( ) ; //TODO: This is gonna be a performance bottleneck for watchtowers!
21092128 let per_commitment_option = self . counterparty_claimable_outpoints . get ( & commitment_txid) ;
@@ -2112,7 +2131,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
21122131 ( $thing : expr ) => {
21132132 match $thing {
21142133 Ok ( a) => a,
2115- Err ( _) => return ( claimable_outpoints, ( commitment_txid, watch_outputs) )
2134+ Err ( _) => return ( claimable_outpoints, ( commitment_txid, watch_outputs) , to_counterparty_output_info )
21162135 }
21172136 } ;
21182137 }
@@ -2134,6 +2153,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
21342153 let revk_outp = RevokedOutput :: build ( per_commitment_point, self . counterparty_commitment_params . counterparty_delayed_payment_base_key , self . counterparty_commitment_params . counterparty_htlc_base_key , per_commitment_key, outp. value , self . counterparty_commitment_params . on_counterparty_tx_csv ) ;
21352154 let justice_package = PackageTemplate :: build_package ( commitment_txid, idx as u32 , PackageSolvingData :: RevokedOutput ( revk_outp) , height + self . counterparty_commitment_params . on_counterparty_tx_csv as u32 , true , height) ;
21362155 claimable_outpoints. push ( justice_package) ;
2156+ to_counterparty_output_info =
2157+ Some ( ( idx. try_into ( ) . expect ( "Txn can't have more than 2^32 outputs" ) , outp. value ) ) ;
21372158 }
21382159 }
21392160
@@ -2143,7 +2164,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
21432164 if let Some ( transaction_output_index) = htlc. transaction_output_index {
21442165 if transaction_output_index as usize >= tx. output . len ( ) ||
21452166 tx. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 {
2146- return ( claimable_outpoints, ( commitment_txid, watch_outputs) ) ; // Corrupted per_commitment_data, fuck this user
2167+ // per_commitment_data is corrupt or our commitment signing key leaked!
2168+ return ( claimable_outpoints, ( commitment_txid, watch_outputs) ,
2169+ to_counterparty_output_info) ;
21472170 }
21482171 let revk_htlc_outp = RevokedHTLCOutput :: build ( per_commitment_point, self . counterparty_commitment_params . counterparty_delayed_payment_base_key , self . counterparty_commitment_params . counterparty_htlc_base_key , per_commitment_key, htlc. amount_msat / 1000 , htlc. clone ( ) , self . onchain_tx_handler . channel_transaction_parameters . opt_anchors . is_some ( ) ) ;
21492172 let justice_package = PackageTemplate :: build_package ( commitment_txid, transaction_output_index, PackageSolvingData :: RevokedHTLCOutput ( revk_htlc_outp) , htlc. cltv_expiry , true , height) ;
@@ -2191,17 +2214,22 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
21912214 ( htlc, htlc_source. as_ref( ) . map( |htlc_source| htlc_source. as_ref( ) ) )
21922215 ) , logger) ;
21932216
2194- let htlc_claim_reqs = self . get_counterparty_htlc_output_claim_reqs ( commitment_number, commitment_txid, Some ( tx) ) ;
2217+ let ( htlc_claim_reqs, counterparty_output_info) =
2218+ self . get_counterparty_output_claim_info ( commitment_number, commitment_txid, Some ( tx) ) ;
2219+ to_counterparty_output_info = counterparty_output_info;
21952220 for req in htlc_claim_reqs {
21962221 claimable_outpoints. push ( req) ;
21972222 }
21982223
21992224 }
2200- ( claimable_outpoints, ( commitment_txid, watch_outputs) )
2225+ ( claimable_outpoints, ( commitment_txid, watch_outputs) , to_counterparty_output_info )
22012226 }
22022227
2203- fn get_counterparty_htlc_output_claim_reqs ( & self , commitment_number : u64 , commitment_txid : Txid , tx : Option < & Transaction > ) -> Vec < PackageTemplate > {
2228+ /// Returns the HTLC claim package templates and the counterparty output info
2229+ fn get_counterparty_output_claim_info ( & self , commitment_number : u64 , commitment_txid : Txid , tx : Option < & Transaction > )
2230+ -> ( Vec < PackageTemplate > , CommitmentTxCounterpartyOutputInfo ) {
22042231 let mut claimable_outpoints = Vec :: new ( ) ;
2232+ let mut to_counterparty_output_info: CommitmentTxCounterpartyOutputInfo = None ;
22052233 if let Some ( htlc_outputs) = self . counterparty_claimable_outpoints . get ( & commitment_txid) {
22062234 if let Some ( per_commitment_points) = self . their_cur_per_commitment_points {
22072235 let per_commitment_point_option =
@@ -2215,12 +2243,43 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
22152243 if per_commitment_points. 0 == commitment_number + 1 { Some ( point) } else { None }
22162244 } else { None } ;
22172245 if let Some ( per_commitment_point) = per_commitment_point_option {
2246+ if let Some ( transaction) = tx {
2247+ let revokeable_p2wsh_opt =
2248+ if let Ok ( revocation_pubkey) = chan_utils:: derive_public_revocation_key (
2249+ & self . secp_ctx , & per_commitment_point, & self . holder_revocation_basepoint )
2250+ {
2251+ if let Ok ( delayed_key) = chan_utils:: derive_public_key ( & self . secp_ctx ,
2252+ & per_commitment_point,
2253+ & self . counterparty_commitment_params . counterparty_delayed_payment_base_key )
2254+ {
2255+ Some ( chan_utils:: get_revokeable_redeemscript ( & revocation_pubkey,
2256+ self . counterparty_commitment_params . on_counterparty_tx_csv ,
2257+ & delayed_key) . to_v0_p2wsh ( ) )
2258+ } else {
2259+ debug_assert ! ( false , "Failed to derive a delayed payment key for a commitment state we accepted" ) ;
2260+ None
2261+ }
2262+ } else {
2263+ debug_assert ! ( false , "Failed to derive a revocation pubkey key for a commitment state we accepted" ) ;
2264+ None
2265+ } ;
2266+ if let Some ( revokeable_p2wsh) = revokeable_p2wsh_opt {
2267+ for ( idx, outp) in transaction. output . iter ( ) . enumerate ( ) {
2268+ if outp. script_pubkey == revokeable_p2wsh {
2269+ to_counterparty_output_info =
2270+ Some ( ( idx. try_into ( ) . expect ( "Can't have > 2^32 outputs" ) , outp. value ) ) ;
2271+ }
2272+ }
2273+ }
2274+ }
2275+
22182276 for ( _, & ( ref htlc, _) ) in htlc_outputs. iter ( ) . enumerate ( ) {
22192277 if let Some ( transaction_output_index) = htlc. transaction_output_index {
22202278 if let Some ( transaction) = tx {
22212279 if transaction_output_index as usize >= transaction. output . len ( ) ||
22222280 transaction. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 {
2223- return claimable_outpoints; // Corrupted per_commitment_data, fuck this user
2281+ // per_commitment_data is corrupt or our commitment signing key leaked!
2282+ return ( claimable_outpoints, to_counterparty_output_info) ;
22242283 }
22252284 }
22262285 let preimage = if htlc. offered { if let Some ( p) = self . payment_preimages . get ( & htlc. payment_hash ) { Some ( * p) } else { None } } else { None } ;
@@ -2247,7 +2306,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
22472306 }
22482307 }
22492308 }
2250- claimable_outpoints
2309+ ( claimable_outpoints, to_counterparty_output_info )
22512310 }
22522311
22532312 /// Attempts to claim a counterparty HTLC-Success/HTLC-Timeout's outputs using the revocation key
@@ -2502,14 +2561,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
25022561 log_info ! ( logger, "Channel {} closed by funding output spend in txid {}." ,
25032562 log_bytes!( self . funding_info. 0 . to_channel_id( ) ) , tx. txid( ) ) ;
25042563 self . funding_spend_seen = true ;
2564+ let mut commitment_tx_to_counterparty_output = None ;
25052565 if ( tx. input [ 0 ] . sequence . 0 >> 8 * 3 ) as u8 == 0x80 && ( tx. lock_time . 0 >> 8 * 3 ) as u8 == 0x20 {
2506- let ( mut new_outpoints, new_outputs) = self . check_spend_counterparty_transaction ( & tx, height, & logger) ;
2566+ let ( mut new_outpoints, new_outputs, counterparty_output_idx_sats) =
2567+ self . check_spend_counterparty_transaction ( & tx, height, & logger) ;
2568+ commitment_tx_to_counterparty_output = counterparty_output_idx_sats;
25072569 if !new_outputs. 1 . is_empty ( ) {
25082570 watch_outputs. push ( new_outputs) ;
25092571 }
25102572 claimable_outpoints. append ( & mut new_outpoints) ;
25112573 if new_outpoints. is_empty ( ) {
25122574 if let Some ( ( mut new_outpoints, new_outputs) ) = self . check_spend_holder_transaction ( & tx, height, & logger) {
2575+ debug_assert ! ( commitment_tx_to_counterparty_output. is_none( ) ,
2576+ "A commitment transaction matched as both a counterparty and local commitment tx?" ) ;
25132577 if !new_outputs. 1 . is_empty ( ) {
25142578 watch_outputs. push ( new_outputs) ;
25152579 }
@@ -2525,6 +2589,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
25252589 height : height,
25262590 event : OnchainEvent :: FundingSpendConfirmation {
25272591 on_local_output_csv : balance_spendable_csv,
2592+ commitment_tx_to_counterparty_output,
25282593 } ,
25292594 } ) ;
25302595 } else {
@@ -2661,8 +2726,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
26612726 OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => {
26622727 self . htlcs_resolved_on_chain . push ( IrrevocablyResolvedHTLC { commitment_tx_output_idx, payment_preimage : preimage } ) ;
26632728 } ,
2664- OnchainEvent :: FundingSpendConfirmation { .. } => {
2729+ OnchainEvent :: FundingSpendConfirmation { commitment_tx_to_counterparty_output , .. } => {
26652730 self . funding_spend_confirmed = Some ( entry. txid ) ;
2731+ self . confirmed_commitment_tx_counterparty_output = commitment_tx_to_counterparty_output;
26662732 } ,
26672733 }
26682734 }
@@ -3375,12 +3441,14 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
33753441 let mut htlcs_resolved_on_chain = Some ( Vec :: new ( ) ) ;
33763442 let mut funding_spend_seen = Some ( false ) ;
33773443 let mut counterparty_node_id = None ;
3444+ let mut confirmed_commitment_tx_counterparty_output = None ;
33783445 read_tlv_fields ! ( reader, {
33793446 ( 1 , funding_spend_confirmed, option) ,
33803447 ( 3 , htlcs_resolved_on_chain, vec_type) ,
33813448 ( 5 , pending_monitor_events, vec_type) ,
33823449 ( 7 , funding_spend_seen, option) ,
33833450 ( 9 , counterparty_node_id, option) ,
3451+ ( 11 , confirmed_commitment_tx_counterparty_output, option) ,
33843452 } ) ;
33853453
33863454 let mut secp_ctx = Secp256k1 :: new ( ) ;
@@ -3431,6 +3499,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
34313499 holder_tx_signed,
34323500 funding_spend_seen : funding_spend_seen. unwrap ( ) ,
34333501 funding_spend_confirmed,
3502+ confirmed_commitment_tx_counterparty_output,
34343503 htlcs_resolved_on_chain : htlcs_resolved_on_chain. unwrap ( ) ,
34353504
34363505 best_block,
0 commit comments