@@ -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,
@@ -1918,7 +1932,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1918
1932
// First check if a counterparty commitment transaction has been broadcasted:
1919
1933
macro_rules! claim_htlcs {
1920
1934
( $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 ) ;
1922
1936
self . onchain_tx_handler. update_claims_view( & Vec :: new( ) , htlc_claim_reqs, self . best_block. height( ) , self . best_block. height( ) , broadcaster, fee_estimator, logger) ;
1923
1937
}
1924
1938
}
@@ -2097,13 +2111,18 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2097
2111
/// data in counterparty_claimable_outpoints. Will directly claim any HTLC outputs which expire at a
2098
2112
/// height > height + CLTV_SHARED_CLAIM_BUFFER. In any case, will install monitoring for
2099
2113
/// 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 {
2103
2121
// Most secp and related errors trying to create keys means we have no hope of constructing
2104
2122
// a spend transaction...so we return no transactions to broadcast
2105
2123
let mut claimable_outpoints = Vec :: new ( ) ;
2106
2124
let mut watch_outputs = Vec :: new ( ) ;
2125
+ let mut to_counterparty_output_info = None ;
2107
2126
2108
2127
let commitment_txid = tx. txid ( ) ; //TODO: This is gonna be a performance bottleneck for watchtowers!
2109
2128
let per_commitment_option = self . counterparty_claimable_outpoints . get ( & commitment_txid) ;
@@ -2112,7 +2131,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2112
2131
( $thing : expr ) => {
2113
2132
match $thing {
2114
2133
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 )
2116
2135
}
2117
2136
} ;
2118
2137
}
@@ -2134,6 +2153,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2134
2153
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 ) ;
2135
2154
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) ;
2136
2155
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 ) ) ;
2137
2158
}
2138
2159
}
2139
2160
@@ -2143,7 +2164,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2143
2164
if let Some ( transaction_output_index) = htlc. transaction_output_index {
2144
2165
if transaction_output_index as usize >= tx. output . len ( ) ||
2145
2166
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) ;
2147
2170
}
2148
2171
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 ( ) ) ;
2149
2172
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> {
2191
2214
( htlc, htlc_source. as_ref( ) . map( |htlc_source| htlc_source. as_ref( ) ) )
2192
2215
) , logger) ;
2193
2216
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;
2195
2220
for req in htlc_claim_reqs {
2196
2221
claimable_outpoints. push ( req) ;
2197
2222
}
2198
2223
2199
2224
}
2200
- ( claimable_outpoints, ( commitment_txid, watch_outputs) )
2225
+ ( claimable_outpoints, ( commitment_txid, watch_outputs) , to_counterparty_output_info )
2201
2226
}
2202
2227
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 ) {
2204
2231
let mut claimable_outpoints = Vec :: new ( ) ;
2232
+ let mut to_counterparty_output_info: CommitmentTxCounterpartyOutputInfo = None ;
2205
2233
if let Some ( htlc_outputs) = self . counterparty_claimable_outpoints . get ( & commitment_txid) {
2206
2234
if let Some ( per_commitment_points) = self . their_cur_per_commitment_points {
2207
2235
let per_commitment_point_option =
@@ -2215,12 +2243,43 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2215
2243
if per_commitment_points. 0 == commitment_number + 1 { Some ( point) } else { None }
2216
2244
} else { None } ;
2217
2245
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
+
2218
2276
for ( _, & ( ref htlc, _) ) in htlc_outputs. iter ( ) . enumerate ( ) {
2219
2277
if let Some ( transaction_output_index) = htlc. transaction_output_index {
2220
2278
if let Some ( transaction) = tx {
2221
2279
if transaction_output_index as usize >= transaction. output . len ( ) ||
2222
2280
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) ;
2224
2283
}
2225
2284
}
2226
2285
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> {
2247
2306
}
2248
2307
}
2249
2308
}
2250
- claimable_outpoints
2309
+ ( claimable_outpoints, to_counterparty_output_info )
2251
2310
}
2252
2311
2253
2312
/// Attempts to claim a counterparty HTLC-Success/HTLC-Timeout's outputs using the revocation key
@@ -2502,14 +2561,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2502
2561
log_info ! ( logger, "Channel {} closed by funding output spend in txid {}." ,
2503
2562
log_bytes!( self . funding_info. 0 . to_channel_id( ) ) , tx. txid( ) ) ;
2504
2563
self . funding_spend_seen = true ;
2564
+ let mut commitment_tx_to_counterparty_output = None ;
2505
2565
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;
2507
2569
if !new_outputs. 1 . is_empty ( ) {
2508
2570
watch_outputs. push ( new_outputs) ;
2509
2571
}
2510
2572
claimable_outpoints. append ( & mut new_outpoints) ;
2511
2573
if new_outpoints. is_empty ( ) {
2512
2574
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?" ) ;
2513
2577
if !new_outputs. 1 . is_empty ( ) {
2514
2578
watch_outputs. push ( new_outputs) ;
2515
2579
}
@@ -2525,6 +2589,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2525
2589
height : height,
2526
2590
event : OnchainEvent :: FundingSpendConfirmation {
2527
2591
on_local_output_csv : balance_spendable_csv,
2592
+ commitment_tx_to_counterparty_output,
2528
2593
} ,
2529
2594
} ) ;
2530
2595
} else {
@@ -2661,8 +2726,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2661
2726
OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => {
2662
2727
self . htlcs_resolved_on_chain . push ( IrrevocablyResolvedHTLC { commitment_tx_output_idx, payment_preimage : preimage } ) ;
2663
2728
} ,
2664
- OnchainEvent :: FundingSpendConfirmation { .. } => {
2729
+ OnchainEvent :: FundingSpendConfirmation { commitment_tx_to_counterparty_output , .. } => {
2665
2730
self . funding_spend_confirmed = Some ( entry. txid ) ;
2731
+ self . confirmed_commitment_tx_counterparty_output = commitment_tx_to_counterparty_output;
2666
2732
} ,
2667
2733
}
2668
2734
}
@@ -3375,12 +3441,14 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
3375
3441
let mut htlcs_resolved_on_chain = Some ( Vec :: new ( ) ) ;
3376
3442
let mut funding_spend_seen = Some ( false ) ;
3377
3443
let mut counterparty_node_id = None ;
3444
+ let mut confirmed_commitment_tx_counterparty_output = None ;
3378
3445
read_tlv_fields ! ( reader, {
3379
3446
( 1 , funding_spend_confirmed, option) ,
3380
3447
( 3 , htlcs_resolved_on_chain, vec_type) ,
3381
3448
( 5 , pending_monitor_events, vec_type) ,
3382
3449
( 7 , funding_spend_seen, option) ,
3383
3450
( 9 , counterparty_node_id, option) ,
3451
+ ( 11 , confirmed_commitment_tx_counterparty_output, option) ,
3384
3452
} ) ;
3385
3453
3386
3454
let mut secp_ctx = Secp256k1 :: new ( ) ;
@@ -3431,6 +3499,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
3431
3499
holder_tx_signed,
3432
3500
funding_spend_seen : funding_spend_seen. unwrap ( ) ,
3433
3501
funding_spend_confirmed,
3502
+ confirmed_commitment_tx_counterparty_output,
3434
3503
htlcs_resolved_on_chain : htlcs_resolved_on_chain. unwrap ( ) ,
3435
3504
3436
3505
best_block,
0 commit comments