@@ -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,
@@ -1914,7 +1928,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1914
1928
// First check if a counterparty commitment transaction has been broadcasted:
1915
1929
macro_rules! claim_htlcs {
1916
1930
( $commitment_number: expr, $txid: expr) => {
1917
- let htlc_claim_reqs = self . get_counterparty_htlc_output_claim_reqs ( $commitment_number, $txid, None ) ;
1931
+ let ( htlc_claim_reqs, _ ) = self . get_counterparty_output_claim_info ( $commitment_number, $txid, None ) ;
1918
1932
self . onchain_tx_handler. update_claims_view( & Vec :: new( ) , htlc_claim_reqs, self . best_block. height( ) , self . best_block. height( ) , broadcaster, fee_estimator, logger) ;
1919
1933
}
1920
1934
}
@@ -2093,13 +2107,18 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2093
2107
/// data in counterparty_claimable_outpoints. Will directly claim any HTLC outputs which expire at a
2094
2108
/// height > height + CLTV_SHARED_CLAIM_BUFFER. In any case, will install monitoring for
2095
2109
/// HTLC-Success/HTLC-Timeout transactions.
2096
- /// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
2097
- /// revoked counterparty commitment tx
2098
- fn check_spend_counterparty_transaction < L : Deref > ( & mut self , tx : & Transaction , height : u32 , logger : & L ) -> ( Vec < PackageTemplate > , TransactionOutputs ) where L :: Target : Logger {
2110
+ ///
2111
+ /// Returns packages to claim the revoked output(s), as well as additional outputs to watch and
2112
+ /// general information about the output that is to the counterparty in the commitment
2113
+ /// transaction.
2114
+ fn check_spend_counterparty_transaction < L : Deref > ( & mut self , tx : & Transaction , height : u32 , logger : & L )
2115
+ -> ( Vec < PackageTemplate > , TransactionOutputs , CommitmentTxCounterpartyOutputInfo )
2116
+ where L :: Target : Logger {
2099
2117
// Most secp and related errors trying to create keys means we have no hope of constructing
2100
2118
// a spend transaction...so we return no transactions to broadcast
2101
2119
let mut claimable_outpoints = Vec :: new ( ) ;
2102
2120
let mut watch_outputs = Vec :: new ( ) ;
2121
+ let mut to_counterparty_output_info = None ;
2103
2122
2104
2123
let commitment_txid = tx. txid ( ) ; //TODO: This is gonna be a performance bottleneck for watchtowers!
2105
2124
let per_commitment_option = self . counterparty_claimable_outpoints . get ( & commitment_txid) ;
@@ -2108,7 +2127,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2108
2127
( $thing : expr ) => {
2109
2128
match $thing {
2110
2129
Ok ( a) => a,
2111
- Err ( _) => return ( claimable_outpoints, ( commitment_txid, watch_outputs) )
2130
+ Err ( _) => return ( claimable_outpoints, ( commitment_txid, watch_outputs) , to_counterparty_output_info )
2112
2131
}
2113
2132
} ;
2114
2133
}
@@ -2130,6 +2149,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2130
2149
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 ) ;
2131
2150
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) ;
2132
2151
claimable_outpoints. push ( justice_package) ;
2152
+ to_counterparty_output_info =
2153
+ Some ( ( idx. try_into ( ) . expect ( "Txn can't have more than 2^32 outputs" ) , outp. value ) ) ;
2133
2154
}
2134
2155
}
2135
2156
@@ -2139,7 +2160,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2139
2160
if let Some ( transaction_output_index) = htlc. transaction_output_index {
2140
2161
if transaction_output_index as usize >= tx. output . len ( ) ||
2141
2162
tx. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 {
2142
- return ( claimable_outpoints, ( commitment_txid, watch_outputs) ) ; // Corrupted per_commitment_data, fuck this user
2163
+ // per_commitment_data is corrupt or our commitment signing key leaked!
2164
+ return ( claimable_outpoints, ( commitment_txid, watch_outputs) ,
2165
+ to_counterparty_output_info) ;
2143
2166
}
2144
2167
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 ( ) ) ;
2145
2168
let justice_package = PackageTemplate :: build_package ( commitment_txid, transaction_output_index, PackageSolvingData :: RevokedHTLCOutput ( revk_htlc_outp) , htlc. cltv_expiry , true , height) ;
@@ -2187,17 +2210,22 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2187
2210
( htlc, htlc_source. as_ref( ) . map( |htlc_source| htlc_source. as_ref( ) ) )
2188
2211
) , logger) ;
2189
2212
2190
- let htlc_claim_reqs = self . get_counterparty_htlc_output_claim_reqs ( commitment_number, commitment_txid, Some ( tx) ) ;
2213
+ let ( htlc_claim_reqs, counterparty_output_info) =
2214
+ self . get_counterparty_output_claim_info ( commitment_number, commitment_txid, Some ( tx) ) ;
2215
+ to_counterparty_output_info = counterparty_output_info;
2191
2216
for req in htlc_claim_reqs {
2192
2217
claimable_outpoints. push ( req) ;
2193
2218
}
2194
2219
2195
2220
}
2196
- ( claimable_outpoints, ( commitment_txid, watch_outputs) )
2221
+ ( claimable_outpoints, ( commitment_txid, watch_outputs) , to_counterparty_output_info )
2197
2222
}
2198
2223
2199
- fn get_counterparty_htlc_output_claim_reqs ( & self , commitment_number : u64 , commitment_txid : Txid , tx : Option < & Transaction > ) -> Vec < PackageTemplate > {
2224
+ /// Returns the HTLC claim package templates and the counterparty output info
2225
+ fn get_counterparty_output_claim_info ( & self , commitment_number : u64 , commitment_txid : Txid , tx : Option < & Transaction > )
2226
+ -> ( Vec < PackageTemplate > , CommitmentTxCounterpartyOutputInfo ) {
2200
2227
let mut claimable_outpoints = Vec :: new ( ) ;
2228
+ let mut to_counterparty_output_info: CommitmentTxCounterpartyOutputInfo = None ;
2201
2229
if let Some ( htlc_outputs) = self . counterparty_claimable_outpoints . get ( & commitment_txid) {
2202
2230
if let Some ( per_commitment_points) = self . their_cur_per_commitment_points {
2203
2231
let per_commitment_point_option =
@@ -2211,12 +2239,43 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2211
2239
if per_commitment_points. 0 == commitment_number + 1 { Some ( point) } else { None }
2212
2240
} else { None } ;
2213
2241
if let Some ( per_commitment_point) = per_commitment_point_option {
2242
+ if let Some ( transaction) = tx {
2243
+ let revokeable_p2wsh_opt =
2244
+ if let Ok ( revocation_pubkey) = chan_utils:: derive_public_revocation_key (
2245
+ & self . secp_ctx , & per_commitment_point, & self . holder_revocation_basepoint )
2246
+ {
2247
+ if let Ok ( delayed_key) = chan_utils:: derive_public_key ( & self . secp_ctx ,
2248
+ & per_commitment_point,
2249
+ & self . counterparty_commitment_params . counterparty_delayed_payment_base_key )
2250
+ {
2251
+ Some ( chan_utils:: get_revokeable_redeemscript ( & revocation_pubkey,
2252
+ self . counterparty_commitment_params . on_counterparty_tx_csv ,
2253
+ & delayed_key) . to_v0_p2wsh ( ) )
2254
+ } else {
2255
+ debug_assert ! ( false , "Failed to derive a delayed payment key for a commitment state we accepted" ) ;
2256
+ None
2257
+ }
2258
+ } else {
2259
+ debug_assert ! ( false , "Failed to derive a revocation pubkey key for a commitment state we accepted" ) ;
2260
+ None
2261
+ } ;
2262
+ if let Some ( revokeable_p2wsh) = revokeable_p2wsh_opt {
2263
+ for ( idx, outp) in transaction. output . iter ( ) . enumerate ( ) {
2264
+ if outp. script_pubkey == revokeable_p2wsh {
2265
+ to_counterparty_output_info =
2266
+ Some ( ( idx. try_into ( ) . expect ( "Can't have > 2^32 outputs" ) , outp. value ) ) ;
2267
+ }
2268
+ }
2269
+ }
2270
+ }
2271
+
2214
2272
for ( _, & ( ref htlc, _) ) in htlc_outputs. iter ( ) . enumerate ( ) {
2215
2273
if let Some ( transaction_output_index) = htlc. transaction_output_index {
2216
2274
if let Some ( transaction) = tx {
2217
2275
if transaction_output_index as usize >= transaction. output . len ( ) ||
2218
2276
transaction. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 {
2219
- return claimable_outpoints; // Corrupted per_commitment_data, fuck this user
2277
+ // per_commitment_data is corrupt or our commitment signing key leaked!
2278
+ return ( claimable_outpoints, to_counterparty_output_info) ;
2220
2279
}
2221
2280
}
2222
2281
let preimage = if htlc. offered { if let Some ( p) = self . payment_preimages . get ( & htlc. payment_hash ) { Some ( * p) } else { None } } else { None } ;
@@ -2243,7 +2302,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2243
2302
}
2244
2303
}
2245
2304
}
2246
- claimable_outpoints
2305
+ ( claimable_outpoints, to_counterparty_output_info )
2247
2306
}
2248
2307
2249
2308
/// Attempts to claim a counterparty HTLC-Success/HTLC-Timeout's outputs using the revocation key
@@ -2498,14 +2557,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2498
2557
log_info ! ( logger, "Channel {} closed by funding output spend in txid {}." ,
2499
2558
log_bytes!( self . funding_info. 0 . to_channel_id( ) ) , tx. txid( ) ) ;
2500
2559
self . funding_spend_seen = true ;
2560
+ let mut commitment_tx_to_counterparty_output = None ;
2501
2561
if ( tx. input [ 0 ] . sequence >> 8 * 3 ) as u8 == 0x80 && ( tx. lock_time >> 8 * 3 ) as u8 == 0x20 {
2502
- let ( mut new_outpoints, new_outputs) = self . check_spend_counterparty_transaction ( & tx, height, & logger) ;
2562
+ let ( mut new_outpoints, new_outputs, counterparty_output_idx_sats) =
2563
+ self . check_spend_counterparty_transaction ( & tx, height, & logger) ;
2564
+ commitment_tx_to_counterparty_output = counterparty_output_idx_sats;
2503
2565
if !new_outputs. 1 . is_empty ( ) {
2504
2566
watch_outputs. push ( new_outputs) ;
2505
2567
}
2506
2568
claimable_outpoints. append ( & mut new_outpoints) ;
2507
2569
if new_outpoints. is_empty ( ) {
2508
2570
if let Some ( ( mut new_outpoints, new_outputs) ) = self . check_spend_holder_transaction ( & tx, height, & logger) {
2571
+ debug_assert ! ( commitment_tx_to_counterparty_output. is_none( ) ,
2572
+ "A commitment transaction matched as both a counterparty and local commitment tx?" ) ;
2509
2573
if !new_outputs. 1 . is_empty ( ) {
2510
2574
watch_outputs. push ( new_outputs) ;
2511
2575
}
@@ -2521,6 +2585,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2521
2585
height : height,
2522
2586
event : OnchainEvent :: FundingSpendConfirmation {
2523
2587
on_local_output_csv : balance_spendable_csv,
2588
+ commitment_tx_to_counterparty_output,
2524
2589
} ,
2525
2590
} ) ;
2526
2591
} else {
@@ -2657,8 +2722,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2657
2722
OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => {
2658
2723
self . htlcs_resolved_on_chain . push ( IrrevocablyResolvedHTLC { commitment_tx_output_idx, payment_preimage : preimage } ) ;
2659
2724
} ,
2660
- OnchainEvent :: FundingSpendConfirmation { .. } => {
2725
+ OnchainEvent :: FundingSpendConfirmation { commitment_tx_to_counterparty_output , .. } => {
2661
2726
self . funding_spend_confirmed = Some ( entry. txid ) ;
2727
+ self . confirmed_commitment_tx_counterparty_output = commitment_tx_to_counterparty_output;
2662
2728
} ,
2663
2729
}
2664
2730
}
@@ -3371,12 +3437,14 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
3371
3437
let mut htlcs_resolved_on_chain = Some ( Vec :: new ( ) ) ;
3372
3438
let mut funding_spend_seen = Some ( false ) ;
3373
3439
let mut counterparty_node_id = None ;
3440
+ let mut confirmed_commitment_tx_counterparty_output = None ;
3374
3441
read_tlv_fields ! ( reader, {
3375
3442
( 1 , funding_spend_confirmed, option) ,
3376
3443
( 3 , htlcs_resolved_on_chain, vec_type) ,
3377
3444
( 5 , pending_monitor_events, vec_type) ,
3378
3445
( 7 , funding_spend_seen, option) ,
3379
3446
( 9 , counterparty_node_id, option) ,
3447
+ ( 11 , confirmed_commitment_tx_counterparty_output, option) ,
3380
3448
} ) ;
3381
3449
3382
3450
let mut secp_ctx = Secp256k1 :: new ( ) ;
@@ -3427,6 +3495,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
3427
3495
holder_tx_signed,
3428
3496
funding_spend_seen : funding_spend_seen. unwrap ( ) ,
3429
3497
funding_spend_confirmed,
3498
+ confirmed_commitment_tx_counterparty_output,
3430
3499
htlcs_resolved_on_chain : htlcs_resolved_on_chain. unwrap ( ) ,
3431
3500
3432
3501
best_block,
0 commit comments