@@ -166,6 +166,7 @@ pub struct ChannelMonitor {
166
166
key_storage : KeyStorage ,
167
167
delayed_payment_base_key : PublicKey ,
168
168
their_htlc_base_key : Option < PublicKey > ,
169
+ their_delayed_payment_base_key : Option < PublicKey > ,
169
170
// first is the idx of the first of the two revocation points
170
171
their_cur_revocation_points : Option < ( u64 , PublicKey , Option < PublicKey > ) > ,
171
172
@@ -207,6 +208,7 @@ impl Clone for ChannelMonitor {
207
208
key_storage : self . key_storage . clone ( ) ,
208
209
delayed_payment_base_key : self . delayed_payment_base_key . clone ( ) ,
209
210
their_htlc_base_key : self . their_htlc_base_key . clone ( ) ,
211
+ their_delayed_payment_base_key : self . their_delayed_payment_base_key . clone ( ) ,
210
212
their_cur_revocation_points : self . their_cur_revocation_points . clone ( ) ,
211
213
212
214
our_to_self_delay : self . our_to_self_delay ,
@@ -238,6 +240,7 @@ impl PartialEq for ChannelMonitor {
238
240
self . key_storage != other. key_storage ||
239
241
self . delayed_payment_base_key != other. delayed_payment_base_key ||
240
242
self . their_htlc_base_key != other. their_htlc_base_key ||
243
+ self . their_delayed_payment_base_key != other. their_delayed_payment_base_key ||
241
244
self . their_cur_revocation_points != other. their_cur_revocation_points ||
242
245
self . our_to_self_delay != other. our_to_self_delay ||
243
246
self . their_to_self_delay != other. their_to_self_delay ||
@@ -274,6 +277,7 @@ impl ChannelMonitor {
274
277
} ,
275
278
delayed_payment_base_key : delayed_payment_base_key. clone ( ) ,
276
279
their_htlc_base_key : None ,
280
+ their_delayed_payment_base_key : None ,
277
281
their_cur_revocation_points : None ,
278
282
279
283
our_to_self_delay : our_to_self_delay,
@@ -478,8 +482,10 @@ impl ChannelMonitor {
478
482
self . funding_txo = Some ( funding_info) ;
479
483
}
480
484
481
- pub ( super ) fn set_their_htlc_base_key ( & mut self , their_htlc_base_key : & PublicKey ) {
485
+ /// We log these base keys at channel opening to being able to rebuild redeemscript in case of leaked revoked commit tx
486
+ pub ( super ) fn set_their_base_keys ( & mut self , their_htlc_base_key : & PublicKey , their_delayed_payment_base_key : & PublicKey ) {
482
487
self . their_htlc_base_key = Some ( their_htlc_base_key. clone ( ) ) ;
488
+ self . their_delayed_payment_base_key = Some ( their_delayed_payment_base_key. clone ( ) ) ;
483
489
}
484
490
485
491
pub ( super ) fn set_their_to_self_delay ( & mut self , their_to_self_delay : u16 ) {
@@ -531,6 +537,7 @@ impl ChannelMonitor {
531
537
532
538
res. extend_from_slice ( & self . delayed_payment_base_key . serialize ( ) ) ;
533
539
res. extend_from_slice ( & self . their_htlc_base_key . as_ref ( ) . unwrap ( ) . serialize ( ) ) ;
540
+ res. extend_from_slice ( & self . their_delayed_payment_base_key . as_ref ( ) . unwrap ( ) . serialize ( ) ) ;
534
541
535
542
match self . their_cur_revocation_points {
536
543
Some ( ( idx, pubkey, second_option) ) => {
@@ -705,6 +712,7 @@ impl ChannelMonitor {
705
712
706
713
let delayed_payment_base_key = unwrap_obj ! ( PublicKey :: from_slice( & secp_ctx, read_bytes!( 33 ) ) ) ;
707
714
let their_htlc_base_key = Some ( unwrap_obj ! ( PublicKey :: from_slice( & secp_ctx, read_bytes!( 33 ) ) ) ) ;
715
+ let their_delayed_payment_base_key = Some ( unwrap_obj ! ( PublicKey :: from_slice( & secp_ctx, read_bytes!( 33 ) ) ) ) ;
708
716
709
717
let their_cur_revocation_points = {
710
718
let first_idx = byte_utils:: slice_to_be48 ( read_bytes ! ( 6 ) ) ;
@@ -867,6 +875,7 @@ impl ChannelMonitor {
867
875
key_storage,
868
876
delayed_payment_base_key,
869
877
their_htlc_base_key,
878
+ their_delayed_payment_base_key,
870
879
their_cur_revocation_points,
871
880
872
881
our_to_self_delay,
@@ -915,8 +924,7 @@ impl ChannelMonitor {
915
924
/// Attempts to claim a remote commitment transaction's outputs using the revocation key and
916
925
/// data in remote_claimable_outpoints. Will directly claim any HTLC outputs which expire at a
917
926
/// height > height + CLTV_SHARED_CLAIM_BUFFER. In any case, will install monitoring for
918
- /// HTLC-Success/HTLC-Timeout transactions, and claim them using the revocation key (if
919
- /// applicable) as well.
927
+ /// HTLC-Success/HTLC-Timeout transactions.
920
928
fn check_spend_remote_transaction ( & self , tx : & Transaction , height : u32 ) -> ( Vec < Transaction > , ( Sha256dHash , Vec < TxOut > ) ) {
921
929
// Most secp and related errors trying to create keys means we have no hope of constructing
922
930
// a spend transaction...so we return no transactions to broadcast
@@ -1196,13 +1204,97 @@ impl ChannelMonitor {
1196
1204
txn_to_broadcast. push ( spend_tx) ;
1197
1205
}
1198
1206
}
1199
- } else {
1200
- //TODO: For each input check if its in our remote_commitment_txn_on_chain map!
1201
1207
}
1202
1208
1203
1209
( txn_to_broadcast, ( commitment_txid, watch_outputs) )
1204
1210
}
1205
1211
1212
+ /// Attempst to claim a remote HTLC-Success/HTLC-Timeout s outputs using the revocation key
1213
+ fn check_spend_remote_htlc ( & self , tx : & Transaction , commitment_number : u64 ) -> Vec < Transaction > {
1214
+ let mut txn_to_broadcast = Vec :: new ( ) ;
1215
+
1216
+ let htlc_txid = tx. txid ( ) ; //TODO: This is gonna be a performance bottleneck for watchtowers!
1217
+
1218
+ macro_rules! ignore_error {
1219
+ ( $thing : expr ) => {
1220
+ match $thing {
1221
+ Ok ( a) => a,
1222
+ Err ( _) => return txn_to_broadcast
1223
+ }
1224
+ } ;
1225
+ }
1226
+
1227
+ let secret = self . get_secret ( commitment_number) . unwrap ( ) ;
1228
+ let per_commitment_key = ignore_error ! ( SecretKey :: from_slice( & self . secp_ctx, & secret) ) ;
1229
+ let revocation_pubkey = match self . key_storage {
1230
+ KeyStorage :: PrivMode { ref revocation_base_key, .. } => {
1231
+ let per_commitment_point = PublicKey :: from_secret_key ( & self . secp_ctx , & per_commitment_key) ;
1232
+ ignore_error ! ( chan_utils:: derive_public_revocation_key( & self . secp_ctx, & per_commitment_point, & PublicKey :: from_secret_key( & self . secp_ctx, & revocation_base_key) ) )
1233
+ } ,
1234
+ KeyStorage :: SigsMode { ref revocation_base_key, .. } => {
1235
+ let per_commitment_point = PublicKey :: from_secret_key ( & self . secp_ctx , & per_commitment_key) ;
1236
+ ignore_error ! ( chan_utils:: derive_public_revocation_key( & self . secp_ctx, & per_commitment_point, & revocation_base_key) )
1237
+ } ,
1238
+ } ;
1239
+ let delayed_key = match self . their_delayed_payment_base_key {
1240
+ None => return txn_to_broadcast,
1241
+ Some ( their_delayed_payment_base_key) => ignore_error ! ( chan_utils:: derive_public_key( & self . secp_ctx, & PublicKey :: from_secret_key( & self . secp_ctx, & per_commitment_key) , & their_delayed_payment_base_key) ) ,
1242
+ } ;
1243
+ let redeemscript = chan_utils:: get_revokeable_redeemscript ( & revocation_pubkey, self . their_to_self_delay . unwrap ( ) , & delayed_key) ;
1244
+ let revokeable_p2wsh = redeemscript. to_v0_p2wsh ( ) ;
1245
+
1246
+ let mut inputs = Vec :: new ( ) ;
1247
+ let mut amount = 0 ;
1248
+
1249
+ if tx. output [ 0 ] . script_pubkey == revokeable_p2wsh { //HTLC transactions have one txin, one txout
1250
+ inputs. push ( TxIn {
1251
+ previous_output : BitcoinOutPoint {
1252
+ txid : htlc_txid,
1253
+ vout : 0 ,
1254
+ } ,
1255
+ script_sig : Script :: new ( ) ,
1256
+ sequence : 0xfffffffd ,
1257
+ witness : Vec :: new ( ) ,
1258
+ } ) ;
1259
+ amount = tx. output [ 0 ] . value ;
1260
+ }
1261
+
1262
+ if !inputs. is_empty ( ) {
1263
+ let outputs = vec ! ( TxOut {
1264
+ script_pubkey: self . destination_script. clone( ) ,
1265
+ value: amount, //TODO: - fee
1266
+ } ) ;
1267
+
1268
+ let mut spend_tx = Transaction {
1269
+ version : 2 ,
1270
+ lock_time : 0 ,
1271
+ input : inputs,
1272
+ output : outputs,
1273
+ } ;
1274
+
1275
+
1276
+ let sighash_parts = bip143:: SighashComponents :: new ( & spend_tx) ;
1277
+
1278
+ let sig = match self . key_storage {
1279
+ KeyStorage :: PrivMode { ref revocation_base_key, .. } => {
1280
+ let sighash = ignore_error ! ( Message :: from_slice( & sighash_parts. sighash_all( & spend_tx. input[ 0 ] , & redeemscript, amount) [ ..] ) ) ;
1281
+ let revocation_key = ignore_error ! ( chan_utils:: derive_private_revocation_key( & self . secp_ctx, & per_commitment_key, & revocation_base_key) ) ;
1282
+ self . secp_ctx . sign ( & sighash, & revocation_key)
1283
+ }
1284
+ KeyStorage :: SigsMode { .. } => {
1285
+ unimplemented ! ( ) ;
1286
+ }
1287
+ } ;
1288
+ spend_tx. input [ 0 ] . witness . push ( sig. serialize_der ( & self . secp_ctx ) . to_vec ( ) ) ;
1289
+ spend_tx. input [ 0 ] . witness [ 0 ] . push ( SigHashType :: All as u8 ) ;
1290
+ spend_tx. input [ 0 ] . witness . push ( vec ! ( 1 ) ) ;
1291
+ spend_tx. input [ 0 ] . witness . push ( redeemscript. into_bytes ( ) ) ;
1292
+
1293
+ txn_to_broadcast. push ( spend_tx) ;
1294
+ }
1295
+ txn_to_broadcast
1296
+ }
1297
+
1206
1298
fn broadcast_by_local_state ( & self , local_tx : & LocalSignedTx ) -> Vec < Transaction > {
1207
1299
let mut res = Vec :: with_capacity ( local_tx. htlc_outputs . len ( ) ) ;
1208
1300
@@ -1264,19 +1356,26 @@ impl ChannelMonitor {
1264
1356
fn block_connected ( & self , txn_matched : & [ & Transaction ] , height : u32 , broadcaster : & BroadcasterInterface ) -> Vec < ( Sha256dHash , Vec < TxOut > ) > {
1265
1357
let mut watch_outputs = Vec :: new ( ) ;
1266
1358
for tx in txn_matched {
1359
+ let mut txn: Vec < Transaction > = Vec :: new ( ) ;
1267
1360
for txin in tx. input . iter ( ) {
1268
1361
if self . funding_txo . is_none ( ) || ( txin. previous_output . txid == self . funding_txo . as_ref ( ) . unwrap ( ) . 0 . txid && txin. previous_output . vout == self . funding_txo . as_ref ( ) . unwrap ( ) . 0 . index as u32 ) {
1269
- let ( mut txn, new_outputs) = self . check_spend_remote_transaction ( tx, height) ;
1362
+ let ( remote_txn, new_outputs) = self . check_spend_remote_transaction ( tx, height) ;
1363
+ txn = remote_txn;
1270
1364
if !new_outputs. 1 . is_empty ( ) {
1271
1365
watch_outputs. push ( new_outputs) ;
1272
1366
}
1273
1367
if txn. is_empty ( ) {
1274
1368
txn = self . check_spend_local_transaction ( tx, height) ;
1275
1369
}
1276
- for tx in txn. iter ( ) {
1277
- broadcaster. broadcast_transaction ( tx) ;
1370
+ } else {
1371
+ let remote_commitment_txn_on_chain = self . remote_commitment_txn_on_chain . lock ( ) . unwrap ( ) ;
1372
+ for commitment_number in remote_commitment_txn_on_chain. get ( & txin. previous_output . txid ) {
1373
+ txn = self . check_spend_remote_htlc ( tx, * commitment_number) ;
1278
1374
}
1279
1375
}
1376
+ for tx in txn. iter ( ) {
1377
+ broadcaster. broadcast_transaction ( tx) ;
1378
+ }
1280
1379
}
1281
1380
}
1282
1381
if let Some ( ref cur_local_tx) = self . current_local_signed_commitment_tx {
0 commit comments