@@ -54,6 +54,7 @@ use util::events::Event;
54
54
use prelude:: * ;
55
55
use core:: { cmp, mem} ;
56
56
use io:: { self , Error } ;
57
+ use core:: convert:: TryInto ;
57
58
use core:: ops:: Deref ;
58
59
use sync:: Mutex ;
59
60
@@ -345,6 +346,11 @@ impl OnchainEventEntry {
345
346
}
346
347
}
347
348
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
+
348
354
/// Upon discovering of some classes of onchain tx by ChannelMonitor, we may have to take actions on it
349
355
/// once they mature to enough confirmations (ANTI_REORG_DELAY)
350
356
#[ derive( PartialEq ) ]
@@ -372,6 +378,9 @@ enum OnchainEvent {
372
378
/// The CSV delay for the output of the funding spend transaction (implying it is a local
373
379
/// commitment transaction, and this is the delay on the to_self output).
374
380
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 ,
375
384
} ,
376
385
/// A spend of a commitment transaction HTLC output, set in the cases where *no* `HTLCUpdate`
377
386
/// is constructed. This is used when
@@ -436,6 +445,7 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
436
445
} ,
437
446
( 3 , FundingSpendConfirmation ) => {
438
447
( 0 , on_local_output_csv, option) ,
448
+ ( 1 , commitment_tx_to_counterparty_output, option) ,
439
449
} ,
440
450
( 5 , HTLCSpendConfirmation ) => {
441
451
( 0 , commitment_tx_output_idx, required) ,
@@ -714,6 +724,7 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
714
724
funding_spend_seen : bool ,
715
725
716
726
funding_spend_confirmed : Option < Txid > ,
727
+ confirmed_commitment_tx_counterparty_output : CommitmentTxCounterpartyOutputInfo ,
717
728
/// The set of HTLCs which have been either claimed or failed on chain and have reached
718
729
/// the requisite confirmations on the claim/fail transaction (either ANTI_REORG_DELAY or the
719
730
/// spending CSV for revocable outputs).
@@ -783,6 +794,7 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
783
794
self . holder_tx_signed != other. holder_tx_signed ||
784
795
self . funding_spend_seen != other. funding_spend_seen ||
785
796
self . funding_spend_confirmed != other. funding_spend_confirmed ||
797
+ self . confirmed_commitment_tx_counterparty_output != other. confirmed_commitment_tx_counterparty_output ||
786
798
self . htlcs_resolved_on_chain != other. htlcs_resolved_on_chain
787
799
{
788
800
false
@@ -962,6 +974,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
962
974
( 5 , self . pending_monitor_events, vec_type) ,
963
975
( 7 , self . funding_spend_seen, required) ,
964
976
( 9 , self . counterparty_node_id, option) ,
977
+ ( 11 , self . confirmed_commitment_tx_counterparty_output, option) ,
965
978
} ) ;
966
979
967
980
Ok ( ( ) )
@@ -1068,6 +1081,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1068
1081
holder_tx_signed : false ,
1069
1082
funding_spend_seen : false ,
1070
1083
funding_spend_confirmed : None ,
1084
+ confirmed_commitment_tx_counterparty_output : None ,
1071
1085
htlcs_resolved_on_chain : Vec :: new ( ) ,
1072
1086
1073
1087
best_block,
@@ -1910,7 +1924,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1910
1924
// First check if a counterparty commitment transaction has been broadcasted:
1911
1925
macro_rules! claim_htlcs {
1912
1926
( $commitment_number: expr, $txid: expr) => {
1913
- let htlc_claim_reqs = self . get_counterparty_htlc_output_claim_reqs ( $commitment_number, $txid, None ) ;
1927
+ let ( htlc_claim_reqs, _ ) = self . get_counterparty_output_claim_info ( $commitment_number, $txid, None ) ;
1914
1928
self . onchain_tx_handler. update_claims_view( & Vec :: new( ) , htlc_claim_reqs, self . best_block. height( ) , self . best_block. height( ) , broadcaster, fee_estimator, logger) ;
1915
1929
}
1916
1930
}
@@ -2089,13 +2103,18 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2089
2103
/// data in counterparty_claimable_outpoints. Will directly claim any HTLC outputs which expire at a
2090
2104
/// height > height + CLTV_SHARED_CLAIM_BUFFER. In any case, will install monitoring for
2091
2105
/// HTLC-Success/HTLC-Timeout transactions.
2092
- /// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
2093
- /// revoked counterparty commitment tx
2094
- fn check_spend_counterparty_transaction < L : Deref > ( & mut self , tx : & Transaction , height : u32 , logger : & L ) -> ( Vec < PackageTemplate > , TransactionOutputs ) where L :: Target : Logger {
2106
+ ///
2107
+ /// Returns packages to claim the revoked output(s), as well as additional outputs to watch and
2108
+ /// general information about the output that is to the counterparty in the commitment
2109
+ /// transaction.
2110
+ fn check_spend_counterparty_transaction < L : Deref > ( & mut self , tx : & Transaction , height : u32 , logger : & L )
2111
+ -> ( Vec < PackageTemplate > , TransactionOutputs , CommitmentTxCounterpartyOutputInfo )
2112
+ where L :: Target : Logger {
2095
2113
// Most secp and related errors trying to create keys means we have no hope of constructing
2096
2114
// a spend transaction...so we return no transactions to broadcast
2097
2115
let mut claimable_outpoints = Vec :: new ( ) ;
2098
2116
let mut watch_outputs = Vec :: new ( ) ;
2117
+ let mut to_counterparty_output_info = None ;
2099
2118
2100
2119
let commitment_txid = tx. txid ( ) ; //TODO: This is gonna be a performance bottleneck for watchtowers!
2101
2120
let per_commitment_option = self . counterparty_claimable_outpoints . get ( & commitment_txid) ;
@@ -2104,7 +2123,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2104
2123
( $thing : expr ) => {
2105
2124
match $thing {
2106
2125
Ok ( a) => a,
2107
- Err ( _) => return ( claimable_outpoints, ( commitment_txid, watch_outputs) )
2126
+ Err ( _) => return ( claimable_outpoints, ( commitment_txid, watch_outputs) , to_counterparty_output_info )
2108
2127
}
2109
2128
} ;
2110
2129
}
@@ -2126,6 +2145,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2126
2145
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 ) ;
2127
2146
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) ;
2128
2147
claimable_outpoints. push ( justice_package) ;
2148
+ to_counterparty_output_info =
2149
+ Some ( ( idx. try_into ( ) . expect ( "Txn can't have more than 2^32 outputs" ) , outp. value ) ) ;
2129
2150
}
2130
2151
}
2131
2152
@@ -2135,7 +2156,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2135
2156
if let Some ( transaction_output_index) = htlc. transaction_output_index {
2136
2157
if transaction_output_index as usize >= tx. output . len ( ) ||
2137
2158
tx. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 {
2138
- return ( claimable_outpoints, ( commitment_txid, watch_outputs) ) ; // Corrupted per_commitment_data, fuck this user
2159
+ // per_commitment_data is corrupt or our commitment signing key leaked!
2160
+ return ( claimable_outpoints, ( commitment_txid, watch_outputs) ,
2161
+ to_counterparty_output_info) ;
2139
2162
}
2140
2163
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 ( ) ) ;
2141
2164
let justice_package = PackageTemplate :: build_package ( commitment_txid, transaction_output_index, PackageSolvingData :: RevokedHTLCOutput ( revk_htlc_outp) , htlc. cltv_expiry , true , height) ;
@@ -2183,17 +2206,22 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2183
2206
( htlc, htlc_source. as_ref( ) . map( |htlc_source| htlc_source. as_ref( ) ) )
2184
2207
) , logger) ;
2185
2208
2186
- let htlc_claim_reqs = self . get_counterparty_htlc_output_claim_reqs ( commitment_number, commitment_txid, Some ( tx) ) ;
2209
+ let ( htlc_claim_reqs, counterparty_output_info) =
2210
+ self . get_counterparty_output_claim_info ( commitment_number, commitment_txid, Some ( tx) ) ;
2211
+ to_counterparty_output_info = counterparty_output_info;
2187
2212
for req in htlc_claim_reqs {
2188
2213
claimable_outpoints. push ( req) ;
2189
2214
}
2190
2215
2191
2216
}
2192
- ( claimable_outpoints, ( commitment_txid, watch_outputs) )
2217
+ ( claimable_outpoints, ( commitment_txid, watch_outputs) , to_counterparty_output_info )
2193
2218
}
2194
2219
2195
- fn get_counterparty_htlc_output_claim_reqs ( & self , commitment_number : u64 , commitment_txid : Txid , tx : Option < & Transaction > ) -> Vec < PackageTemplate > {
2220
+ /// Returns the HTLC claim package templates and the counterparty output info
2221
+ fn get_counterparty_output_claim_info ( & self , commitment_number : u64 , commitment_txid : Txid , tx : Option < & Transaction > )
2222
+ -> ( Vec < PackageTemplate > , CommitmentTxCounterpartyOutputInfo ) {
2196
2223
let mut claimable_outpoints = Vec :: new ( ) ;
2224
+ let mut to_counterparty_output_info: CommitmentTxCounterpartyOutputInfo = None ;
2197
2225
if let Some ( htlc_outputs) = self . counterparty_claimable_outpoints . get ( & commitment_txid) {
2198
2226
if let Some ( per_commitment_points) = self . their_cur_per_commitment_points {
2199
2227
let per_commitment_point_option =
@@ -2207,12 +2235,43 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2207
2235
if per_commitment_points. 0 == commitment_number + 1 { Some ( point) } else { None }
2208
2236
} else { None } ;
2209
2237
if let Some ( per_commitment_point) = per_commitment_point_option {
2238
+ if let Some ( transaction) = tx {
2239
+ let revokeable_p2wsh_opt =
2240
+ if let Ok ( revocation_pubkey) = chan_utils:: derive_public_revocation_key (
2241
+ & self . secp_ctx , & per_commitment_point, & self . holder_revocation_basepoint )
2242
+ {
2243
+ if let Ok ( delayed_key) = chan_utils:: derive_public_key ( & self . secp_ctx ,
2244
+ & per_commitment_point,
2245
+ & self . counterparty_commitment_params . counterparty_delayed_payment_base_key )
2246
+ {
2247
+ Some ( chan_utils:: get_revokeable_redeemscript ( & revocation_pubkey,
2248
+ self . counterparty_commitment_params . on_counterparty_tx_csv ,
2249
+ & delayed_key) . to_v0_p2wsh ( ) )
2250
+ } else {
2251
+ debug_assert ! ( false , "Failed to derive a delayed payment key for a commitment state we accepted" ) ;
2252
+ None
2253
+ }
2254
+ } else {
2255
+ debug_assert ! ( false , "Failed to derive a revocation pubkey key for a commitment state we accepted" ) ;
2256
+ None
2257
+ } ;
2258
+ if let Some ( revokeable_p2wsh) = revokeable_p2wsh_opt {
2259
+ for ( idx, outp) in transaction. output . iter ( ) . enumerate ( ) {
2260
+ if outp. script_pubkey == revokeable_p2wsh {
2261
+ to_counterparty_output_info =
2262
+ Some ( ( idx. try_into ( ) . expect ( "Can't have > 2^32 outputs" ) , outp. value ) ) ;
2263
+ }
2264
+ }
2265
+ }
2266
+ }
2267
+
2210
2268
for ( _, & ( ref htlc, _) ) in htlc_outputs. iter ( ) . enumerate ( ) {
2211
2269
if let Some ( transaction_output_index) = htlc. transaction_output_index {
2212
2270
if let Some ( transaction) = tx {
2213
2271
if transaction_output_index as usize >= transaction. output . len ( ) ||
2214
2272
transaction. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 {
2215
- return claimable_outpoints; // Corrupted per_commitment_data, fuck this user
2273
+ // per_commitment_data is corrupt or our commitment signing key leaked!
2274
+ return ( claimable_outpoints, to_counterparty_output_info) ;
2216
2275
}
2217
2276
}
2218
2277
let preimage = if htlc. offered { if let Some ( p) = self . payment_preimages . get ( & htlc. payment_hash ) { Some ( * p) } else { None } } else { None } ;
@@ -2239,7 +2298,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2239
2298
}
2240
2299
}
2241
2300
}
2242
- claimable_outpoints
2301
+ ( claimable_outpoints, to_counterparty_output_info )
2243
2302
}
2244
2303
2245
2304
/// Attempts to claim a counterparty HTLC-Success/HTLC-Timeout's outputs using the revocation key
@@ -2494,14 +2553,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2494
2553
log_info ! ( logger, "Channel {} closed by funding output spend in txid {}." ,
2495
2554
log_bytes!( self . funding_info. 0 . to_channel_id( ) ) , tx. txid( ) ) ;
2496
2555
self . funding_spend_seen = true ;
2556
+ let mut commitment_tx_to_counterparty_output = None ;
2497
2557
if ( tx. input [ 0 ] . sequence >> 8 * 3 ) as u8 == 0x80 && ( tx. lock_time >> 8 * 3 ) as u8 == 0x20 {
2498
- let ( mut new_outpoints, new_outputs) = self . check_spend_counterparty_transaction ( & tx, height, & logger) ;
2558
+ let ( mut new_outpoints, new_outputs, counterparty_output_idx_sats) =
2559
+ self . check_spend_counterparty_transaction ( & tx, height, & logger) ;
2560
+ commitment_tx_to_counterparty_output = counterparty_output_idx_sats;
2499
2561
if !new_outputs. 1 . is_empty ( ) {
2500
2562
watch_outputs. push ( new_outputs) ;
2501
2563
}
2502
2564
claimable_outpoints. append ( & mut new_outpoints) ;
2503
2565
if new_outpoints. is_empty ( ) {
2504
2566
if let Some ( ( mut new_outpoints, new_outputs) ) = self . check_spend_holder_transaction ( & tx, height, & logger) {
2567
+ debug_assert ! ( commitment_tx_to_counterparty_output. is_none( ) ,
2568
+ "A commitment transaction matched as both a counterparty and local commitment tx?" ) ;
2505
2569
if !new_outputs. 1 . is_empty ( ) {
2506
2570
watch_outputs. push ( new_outputs) ;
2507
2571
}
@@ -2517,6 +2581,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2517
2581
height : height,
2518
2582
event : OnchainEvent :: FundingSpendConfirmation {
2519
2583
on_local_output_csv : balance_spendable_csv,
2584
+ commitment_tx_to_counterparty_output,
2520
2585
} ,
2521
2586
} ) ;
2522
2587
} else {
@@ -2653,8 +2718,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2653
2718
OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => {
2654
2719
self . htlcs_resolved_on_chain . push ( IrrevocablyResolvedHTLC { commitment_tx_output_idx, payment_preimage : preimage } ) ;
2655
2720
} ,
2656
- OnchainEvent :: FundingSpendConfirmation { .. } => {
2721
+ OnchainEvent :: FundingSpendConfirmation { commitment_tx_to_counterparty_output , .. } => {
2657
2722
self . funding_spend_confirmed = Some ( entry. txid ) ;
2723
+ self . confirmed_commitment_tx_counterparty_output = commitment_tx_to_counterparty_output;
2658
2724
} ,
2659
2725
}
2660
2726
}
@@ -3367,12 +3433,14 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
3367
3433
let mut htlcs_resolved_on_chain = Some ( Vec :: new ( ) ) ;
3368
3434
let mut funding_spend_seen = Some ( false ) ;
3369
3435
let mut counterparty_node_id = None ;
3436
+ let mut confirmed_commitment_tx_counterparty_output = None ;
3370
3437
read_tlv_fields ! ( reader, {
3371
3438
( 1 , funding_spend_confirmed, option) ,
3372
3439
( 3 , htlcs_resolved_on_chain, vec_type) ,
3373
3440
( 5 , pending_monitor_events, vec_type) ,
3374
3441
( 7 , funding_spend_seen, option) ,
3375
3442
( 9 , counterparty_node_id, option) ,
3443
+ ( 11 , confirmed_commitment_tx_counterparty_output, option) ,
3376
3444
} ) ;
3377
3445
3378
3446
let mut secp_ctx = Secp256k1 :: new ( ) ;
@@ -3423,6 +3491,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
3423
3491
holder_tx_signed,
3424
3492
funding_spend_seen : funding_spend_seen. unwrap ( ) ,
3425
3493
funding_spend_confirmed,
3494
+ confirmed_commitment_tx_counterparty_output,
3426
3495
htlcs_resolved_on_chain : htlcs_resolved_on_chain. unwrap ( ) ,
3427
3496
3428
3497
best_block,
0 commit comments