@@ -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,8 @@ impl OnchainEventEntry {
345
346
}
346
347
}
347
348
349
+ type CommitmentTxCounterpartyOutputInfo = Option < ( u32 , u64 ) > ;
350
+
348
351
/// Upon discovering of some classes of onchain tx by ChannelMonitor, we may have to take actions on it
349
352
/// once they mature to enough confirmations (ANTI_REORG_DELAY)
350
353
#[ derive( PartialEq ) ]
@@ -372,6 +375,9 @@ enum OnchainEvent {
372
375
/// The CSV delay for the output of the funding spend transaction (implying it is a local
373
376
/// commitment transaction, and this is the delay on the to_self output).
374
377
on_local_output_csv : Option < u16 > ,
378
+ /// If the funding spend transaction was a known remote commitment transaction, we track
379
+ /// the output index and amount of the counterparty's `to_self` output here.
380
+ commitment_tx_to_counterparty_output : CommitmentTxCounterpartyOutputInfo ,
375
381
} ,
376
382
/// A spend of a commitment transaction HTLC output, set in the cases where *no* `HTLCUpdate`
377
383
/// is constructed. This is used when
@@ -436,6 +442,7 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
436
442
} ,
437
443
( 3 , FundingSpendConfirmation ) => {
438
444
( 0 , on_local_output_csv, option) ,
445
+ ( 1 , commitment_tx_to_counterparty_output, option) ,
439
446
} ,
440
447
( 5 , HTLCSpendConfirmation ) => {
441
448
( 0 , commitment_tx_output_idx, required) ,
@@ -714,6 +721,7 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
714
721
funding_spend_seen : bool ,
715
722
716
723
funding_spend_confirmed : Option < Txid > ,
724
+ confirmed_commitment_tx_counterparty_output : CommitmentTxCounterpartyOutputInfo ,
717
725
/// The set of HTLCs which have been either claimed or failed on chain and have reached
718
726
/// the requisite confirmations on the claim/fail transaction (either ANTI_REORG_DELAY or the
719
727
/// spending CSV for revocable outputs).
@@ -783,6 +791,7 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
783
791
self . holder_tx_signed != other. holder_tx_signed ||
784
792
self . funding_spend_seen != other. funding_spend_seen ||
785
793
self . funding_spend_confirmed != other. funding_spend_confirmed ||
794
+ self . confirmed_commitment_tx_counterparty_output != other. confirmed_commitment_tx_counterparty_output ||
786
795
self . htlcs_resolved_on_chain != other. htlcs_resolved_on_chain
787
796
{
788
797
false
@@ -962,6 +971,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
962
971
( 5 , self . pending_monitor_events, vec_type) ,
963
972
( 7 , self . funding_spend_seen, required) ,
964
973
( 9 , self . counterparty_node_id, option) ,
974
+ ( 11 , self . confirmed_commitment_tx_counterparty_output, option) ,
965
975
} ) ;
966
976
967
977
Ok ( ( ) )
@@ -1062,6 +1072,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
1062
1072
holder_tx_signed : false ,
1063
1073
funding_spend_seen : false ,
1064
1074
funding_spend_confirmed : None ,
1075
+ confirmed_commitment_tx_counterparty_output : None ,
1065
1076
htlcs_resolved_on_chain : Vec :: new ( ) ,
1066
1077
1067
1078
best_block,
@@ -1900,7 +1911,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
1900
1911
// First check if a counterparty commitment transaction has been broadcasted:
1901
1912
macro_rules! claim_htlcs {
1902
1913
( $commitment_number: expr, $txid: expr) => {
1903
- let htlc_claim_reqs = self . get_counterparty_htlc_output_claim_reqs ( $commitment_number, $txid, None ) ;
1914
+ let ( htlc_claim_reqs, _ ) = self . get_counterparty_output_claim_info ( $commitment_number, $txid, None ) ;
1904
1915
self . onchain_tx_handler. update_claims_view( & Vec :: new( ) , htlc_claim_reqs, self . best_block. height( ) , self . best_block. height( ) , broadcaster, fee_estimator, logger) ;
1905
1916
}
1906
1917
}
@@ -2080,11 +2091,14 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2080
2091
/// HTLC-Success/HTLC-Timeout transactions.
2081
2092
/// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
2082
2093
/// revoked counterparty commitment tx
2083
- fn check_spend_counterparty_transaction < L : Deref > ( & mut self , tx : & Transaction , height : u32 , logger : & L ) -> ( Vec < PackageTemplate > , TransactionOutputs ) where L :: Target : Logger {
2094
+ fn check_spend_counterparty_transaction < L : Deref > ( & mut self , tx : & Transaction , height : u32 , logger : & L )
2095
+ -> ( Vec < PackageTemplate > , TransactionOutputs , CommitmentTxCounterpartyOutputInfo )
2096
+ where L :: Target : Logger {
2084
2097
// Most secp and related errors trying to create keys means we have no hope of constructing
2085
2098
// a spend transaction...so we return no transactions to broadcast
2086
2099
let mut claimable_outpoints = Vec :: new ( ) ;
2087
2100
let mut watch_outputs = Vec :: new ( ) ;
2101
+ let mut to_counterparty_output_info = None ;
2088
2102
2089
2103
let commitment_txid = tx. txid ( ) ; //TODO: This is gonna be a performance bottleneck for watchtowers!
2090
2104
let per_commitment_option = self . counterparty_claimable_outpoints . get ( & commitment_txid) ;
@@ -2093,7 +2107,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2093
2107
( $thing : expr ) => {
2094
2108
match $thing {
2095
2109
Ok ( a) => a,
2096
- Err ( _) => return ( claimable_outpoints, ( commitment_txid, watch_outputs) )
2110
+ Err ( _) => return ( claimable_outpoints, ( commitment_txid, watch_outputs) , to_counterparty_output_info )
2097
2111
}
2098
2112
} ;
2099
2113
}
@@ -2115,6 +2129,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2115
2129
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 ) ;
2116
2130
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) ;
2117
2131
claimable_outpoints. push ( justice_package) ;
2132
+ to_counterparty_output_info =
2133
+ Some ( ( idx. try_into ( ) . expect ( "Txn can't have more than 2^32 outputs" ) , outp. value ) ) ;
2118
2134
}
2119
2135
}
2120
2136
@@ -2124,7 +2140,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2124
2140
if let Some ( transaction_output_index) = htlc. transaction_output_index {
2125
2141
if transaction_output_index as usize >= tx. output . len ( ) ||
2126
2142
tx. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 {
2127
- return ( claimable_outpoints, ( commitment_txid, watch_outputs) ) ; // Corrupted per_commitment_data, fuck this user
2143
+ // per_commitment_data is corrupt or our commitment signing key leaked!
2144
+ return ( claimable_outpoints, ( commitment_txid, watch_outputs) ,
2145
+ to_counterparty_output_info) ;
2128
2146
}
2129
2147
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 ( ) ) ;
2130
2148
let justice_package = PackageTemplate :: build_package ( commitment_txid, transaction_output_index, PackageSolvingData :: RevokedHTLCOutput ( revk_htlc_outp) , htlc. cltv_expiry , true , height) ;
@@ -2172,17 +2190,22 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2172
2190
( htlc, htlc_source. as_ref( ) . map( |htlc_source| htlc_source. as_ref( ) ) )
2173
2191
) , logger) ;
2174
2192
2175
- let htlc_claim_reqs = self . get_counterparty_htlc_output_claim_reqs ( commitment_number, commitment_txid, Some ( tx) ) ;
2193
+ let ( htlc_claim_reqs, counterparty_output_info) =
2194
+ self . get_counterparty_output_claim_info ( commitment_number, commitment_txid, Some ( tx) ) ;
2195
+ to_counterparty_output_info = counterparty_output_info;
2176
2196
for req in htlc_claim_reqs {
2177
2197
claimable_outpoints. push ( req) ;
2178
2198
}
2179
2199
2180
2200
}
2181
- ( claimable_outpoints, ( commitment_txid, watch_outputs) )
2201
+ ( claimable_outpoints, ( commitment_txid, watch_outputs) , to_counterparty_output_info )
2182
2202
}
2183
2203
2184
- fn get_counterparty_htlc_output_claim_reqs ( & self , commitment_number : u64 , commitment_txid : Txid , tx : Option < & Transaction > ) -> Vec < PackageTemplate > {
2204
+ /// Returns the HTLC claim package templates and the counterparty output info
2205
+ fn get_counterparty_output_claim_info ( & self , commitment_number : u64 , commitment_txid : Txid , tx : Option < & Transaction > )
2206
+ -> ( Vec < PackageTemplate > , CommitmentTxCounterpartyOutputInfo ) {
2185
2207
let mut claimable_outpoints = Vec :: new ( ) ;
2208
+ let mut to_counterparty_output_info: CommitmentTxCounterpartyOutputInfo = None ;
2186
2209
if let Some ( htlc_outputs) = self . counterparty_claimable_outpoints . get ( & commitment_txid) {
2187
2210
if let Some ( per_commitment_points) = self . their_cur_per_commitment_points {
2188
2211
let per_commitment_point_option =
@@ -2196,12 +2219,43 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2196
2219
if per_commitment_points. 0 == commitment_number + 1 { Some ( point) } else { None }
2197
2220
} else { None } ;
2198
2221
if let Some ( per_commitment_point) = per_commitment_point_option {
2222
+ if let Some ( transaction) = tx {
2223
+ let revokeable_p2wsh_opt =
2224
+ if let Ok ( revocation_pubkey) = chan_utils:: derive_public_revocation_key (
2225
+ & self . secp_ctx , & per_commitment_point, & self . holder_revocation_basepoint )
2226
+ {
2227
+ if let Ok ( delayed_key) = chan_utils:: derive_public_key ( & self . secp_ctx ,
2228
+ & per_commitment_point,
2229
+ & self . counterparty_commitment_params . counterparty_delayed_payment_base_key )
2230
+ {
2231
+ Some ( chan_utils:: get_revokeable_redeemscript ( & revocation_pubkey,
2232
+ self . counterparty_commitment_params . on_counterparty_tx_csv ,
2233
+ & delayed_key) . to_v0_p2wsh ( ) )
2234
+ } else {
2235
+ debug_assert ! ( false , "Failed to derive a delayed payment key for a commitment state we accepted" ) ;
2236
+ None
2237
+ }
2238
+ } else {
2239
+ debug_assert ! ( false , "Failed to derive a delayed payment key for a commitment state we accepted" ) ;
2240
+ None
2241
+ } ;
2242
+ if let Some ( revokeable_p2wsh) = revokeable_p2wsh_opt {
2243
+ for ( idx, outp) in transaction. output . iter ( ) . enumerate ( ) {
2244
+ if outp. script_pubkey == revokeable_p2wsh {
2245
+ to_counterparty_output_info =
2246
+ Some ( ( idx. try_into ( ) . expect ( "Can't have > 2^32 outputs" ) , outp. value ) ) ;
2247
+ }
2248
+ }
2249
+ }
2250
+ }
2251
+
2199
2252
for ( _, & ( ref htlc, _) ) in htlc_outputs. iter ( ) . enumerate ( ) {
2200
2253
if let Some ( transaction_output_index) = htlc. transaction_output_index {
2201
2254
if let Some ( transaction) = tx {
2202
2255
if transaction_output_index as usize >= transaction. output . len ( ) ||
2203
2256
transaction. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 {
2204
- return claimable_outpoints; // Corrupted per_commitment_data, fuck this user
2257
+ // per_commitment_data is corrupt or our commitment signing key leaked!
2258
+ return ( claimable_outpoints, to_counterparty_output_info) ;
2205
2259
}
2206
2260
}
2207
2261
let preimage = if htlc. offered { if let Some ( p) = self . payment_preimages . get ( & htlc. payment_hash ) { Some ( * p) } else { None } } else { None } ;
@@ -2228,7 +2282,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2228
2282
}
2229
2283
}
2230
2284
}
2231
- claimable_outpoints
2285
+ ( claimable_outpoints, to_counterparty_output_info )
2232
2286
}
2233
2287
2234
2288
/// Attempts to claim a counterparty HTLC-Success/HTLC-Timeout's outputs using the revocation key
@@ -2482,14 +2536,19 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2482
2536
log_info ! ( logger, "Channel {} closed by funding output spend in txid {}." ,
2483
2537
log_bytes!( self . funding_info. 0 . to_channel_id( ) ) , tx. txid( ) ) ;
2484
2538
self . funding_spend_seen = true ;
2539
+ let mut commitment_tx_to_counterparty_output = None ;
2485
2540
if ( tx. input [ 0 ] . sequence >> 8 * 3 ) as u8 == 0x80 && ( tx. lock_time >> 8 * 3 ) as u8 == 0x20 {
2486
- let ( mut new_outpoints, new_outputs) = self . check_spend_counterparty_transaction ( & tx, height, & logger) ;
2541
+ let ( mut new_outpoints, new_outputs, counterparty_output_idx_sats) =
2542
+ self . check_spend_counterparty_transaction ( & tx, height, & logger) ;
2543
+ commitment_tx_to_counterparty_output = counterparty_output_idx_sats;
2487
2544
if !new_outputs. 1 . is_empty ( ) {
2488
2545
watch_outputs. push ( new_outputs) ;
2489
2546
}
2490
2547
claimable_outpoints. append ( & mut new_outpoints) ;
2491
2548
if new_outpoints. is_empty ( ) {
2492
2549
if let Some ( ( mut new_outpoints, new_outputs) ) = self . check_spend_holder_transaction ( & tx, height, & logger) {
2550
+ debug_assert ! ( commitment_tx_to_counterparty_output. is_none( ) ,
2551
+ "A commitment transaction matched as both a counterparty and local commitment tx?" ) ;
2493
2552
if !new_outputs. 1 . is_empty ( ) {
2494
2553
watch_outputs. push ( new_outputs) ;
2495
2554
}
@@ -2505,6 +2564,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2505
2564
height : height,
2506
2565
event : OnchainEvent :: FundingSpendConfirmation {
2507
2566
on_local_output_csv : balance_spendable_csv,
2567
+ commitment_tx_to_counterparty_output,
2508
2568
} ,
2509
2569
} ) ;
2510
2570
} else {
@@ -2641,8 +2701,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
2641
2701
OnchainEvent :: HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => {
2642
2702
self . htlcs_resolved_on_chain . push ( IrrevocablyResolvedHTLC { commitment_tx_output_idx, payment_preimage : preimage } ) ;
2643
2703
} ,
2644
- OnchainEvent :: FundingSpendConfirmation { .. } => {
2704
+ OnchainEvent :: FundingSpendConfirmation { commitment_tx_to_counterparty_output , .. } => {
2645
2705
self . funding_spend_confirmed = Some ( entry. txid ) ;
2706
+ self . confirmed_commitment_tx_counterparty_output = commitment_tx_to_counterparty_output;
2646
2707
} ,
2647
2708
}
2648
2709
}
@@ -3354,12 +3415,14 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
3354
3415
let mut htlcs_resolved_on_chain = Some ( Vec :: new ( ) ) ;
3355
3416
let mut funding_spend_seen = Some ( false ) ;
3356
3417
let mut counterparty_node_id = None ;
3418
+ let mut confirmed_commitment_tx_counterparty_output = None ;
3357
3419
read_tlv_fields ! ( reader, {
3358
3420
( 1 , funding_spend_confirmed, option) ,
3359
3421
( 3 , htlcs_resolved_on_chain, vec_type) ,
3360
3422
( 5 , pending_monitor_events, vec_type) ,
3361
3423
( 7 , funding_spend_seen, option) ,
3362
3424
( 9 , counterparty_node_id, option) ,
3425
+ ( 11 , confirmed_commitment_tx_counterparty_output, option) ,
3363
3426
} ) ;
3364
3427
3365
3428
let mut secp_ctx = Secp256k1 :: new ( ) ;
@@ -3411,6 +3474,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
3411
3474
holder_tx_signed,
3412
3475
funding_spend_seen : funding_spend_seen. unwrap ( ) ,
3413
3476
funding_spend_confirmed,
3477
+ confirmed_commitment_tx_counterparty_output,
3414
3478
htlcs_resolved_on_chain : htlcs_resolved_on_chain. unwrap ( ) ,
3415
3479
3416
3480
best_block,
0 commit comments