@@ -306,6 +306,8 @@ enum Storage {
306
306
prev_latest_per_commitment_point : Option < PublicKey > ,
307
307
latest_per_commitment_point : Option < PublicKey > ,
308
308
funding_info : Option < ( OutPoint , Script ) > ,
309
+ current_remote_commitment_txid : Option < Sha256dHash > ,
310
+ prev_remote_commitment_txid : Option < Sha256dHash > ,
309
311
} ,
310
312
Watchtower {
311
313
revocation_base_key : PublicKey ,
@@ -433,6 +435,8 @@ impl ChannelMonitor {
433
435
prev_latest_per_commitment_point : None ,
434
436
latest_per_commitment_point : None ,
435
437
funding_info : None ,
438
+ current_remote_commitment_txid : None ,
439
+ prev_remote_commitment_txid : None ,
436
440
} ,
437
441
their_htlc_base_key : None ,
438
442
their_delayed_payment_base_key : None ,
@@ -495,8 +499,24 @@ impl ChannelMonitor {
495
499
return Err ( MonitorUpdateError ( "Previous secret did not match new one" ) ) ;
496
500
}
497
501
}
502
+ if self . get_min_seen_secret ( ) <= idx {
503
+ return Ok ( ( ) ) ;
504
+ }
498
505
self . old_secrets [ pos as usize ] = ( secret, idx) ;
499
506
507
+ // Prune HTLCs from the previous remote commitment tx so we don't generate failure/fulfill
508
+ // events for now-revoked/fulfilled HTLCs.
509
+ // TODO: We should probably consider whether we're really getting the next secret here.
510
+ if let Storage :: Local { ref mut prev_remote_commitment_txid, .. } = self . key_storage {
511
+ if let Some ( txid) = prev_remote_commitment_txid. take ( ) {
512
+ for & mut ( _, ref mut htlc_data) in self . remote_claimable_outpoints . get_mut ( & txid) . unwrap ( ) {
513
+ // This potentially frees a Route-contained Vec, but ideally we'd convert the
514
+ // HTLC data to an Option<Box<>> to make this free a bunch more memory
515
+ htlc_data. take ( ) ;
516
+ }
517
+ }
518
+ }
519
+
500
520
if !self . payment_preimages . is_empty ( ) {
501
521
let local_signed_commitment_tx = self . current_local_signed_commitment_tx . as_ref ( ) . expect ( "Channel needs at least an initial commitment tx !" ) ;
502
522
let prev_local_signed_commitment_tx = self . prev_local_signed_commitment_tx . as_ref ( ) ;
@@ -544,14 +564,13 @@ impl ChannelMonitor {
544
564
for & ( ref htlc, _) in & htlc_outputs {
545
565
self . remote_hash_commitment_number . insert ( htlc. payment_hash , commitment_number) ;
546
566
}
547
- // We prune old claimable outpoints, useless to pass backward state when remote commitment
548
- // tx get revoked, optimize for storage
549
- for ( _, htlc_data) in self . remote_claimable_outpoints . iter_mut ( ) {
550
- for & mut ( _, ref mut source) in htlc_data. iter_mut ( ) {
551
- source. take ( ) ;
552
- }
567
+
568
+ let new_txid = unsigned_commitment_tx. txid ( ) ;
569
+ if let Storage :: Local { ref mut current_remote_commitment_txid, ref mut prev_remote_commitment_txid, .. } = self . key_storage {
570
+ * prev_remote_commitment_txid = current_remote_commitment_txid. take ( ) ;
571
+ * current_remote_commitment_txid = Some ( new_txid) ;
553
572
}
554
- self . remote_claimable_outpoints . insert ( unsigned_commitment_tx . txid ( ) , htlc_outputs) ;
573
+ self . remote_claimable_outpoints . insert ( new_txid , htlc_outputs) ;
555
574
self . current_remote_commitment_number = commitment_number;
556
575
//TODO: Merge this into the other per-remote-transaction output storage stuff
557
576
match self . their_cur_revocation_points {
@@ -753,7 +772,7 @@ impl ChannelMonitor {
753
772
U48 ( self . commitment_transaction_number_obscure_factor ) . write ( writer) ?;
754
773
755
774
match self . key_storage {
756
- Storage :: Local { ref revocation_base_key, ref htlc_base_key, ref delayed_payment_base_key, ref payment_base_key, ref shutdown_pubkey, ref prev_latest_per_commitment_point, ref latest_per_commitment_point, ref funding_info } => {
775
+ Storage :: Local { ref revocation_base_key, ref htlc_base_key, ref delayed_payment_base_key, ref payment_base_key, ref shutdown_pubkey, ref prev_latest_per_commitment_point, ref latest_per_commitment_point, ref funding_info, current_remote_commitment_txid , prev_remote_commitment_txid } => {
757
776
writer. write_all ( & [ 0 ; 1 ] ) ?;
758
777
writer. write_all ( & revocation_base_key[ ..] ) ?;
759
778
writer. write_all ( & htlc_base_key[ ..] ) ?;
@@ -782,6 +801,18 @@ impl ChannelMonitor {
782
801
debug_assert ! ( false , "Try to serialize a useless Local monitor !" ) ;
783
802
} ,
784
803
}
804
+ if let Some ( ref txid) = current_remote_commitment_txid {
805
+ writer. write_all ( & [ 1 ; 1 ] ) ?;
806
+ writer. write_all ( & txid[ ..] ) ?;
807
+ } else {
808
+ writer. write_all ( & [ 0 ; 1 ] ) ?;
809
+ }
810
+ if let Some ( ref txid) = prev_remote_commitment_txid {
811
+ writer. write_all ( & [ 1 ; 1 ] ) ?;
812
+ writer. write_all ( & txid[ ..] ) ?;
813
+ } else {
814
+ writer. write_all ( & [ 0 ; 1 ] ) ?;
815
+ }
785
816
} ,
786
817
Storage :: Watchtower { .. } => unimplemented ! ( ) ,
787
818
}
@@ -1169,6 +1200,27 @@ impl ChannelMonitor {
1169
1200
output : spend_tx. output [ 0 ] . clone ( ) ,
1170
1201
} ) ;
1171
1202
txn_to_broadcast. push ( spend_tx) ;
1203
+
1204
+ // TODO: We really should only fail backwards after our revocation claims have been
1205
+ // confirmed, but we also need to do more other tracking of in-flight pre-confirm
1206
+ // on-chain claims, so we can do that at the same time.
1207
+ if let Storage :: Local { ref current_remote_commitment_txid, ref prev_remote_commitment_txid, .. } = self . key_storage {
1208
+ if let & Some ( ref txid) = current_remote_commitment_txid {
1209
+ for & ( ref htlc, ref source_option) in self . remote_claimable_outpoints . get ( & txid) . unwrap ( ) {
1210
+ if let Some ( ref source) = source_option. as_ref ( ) {
1211
+ htlc_updated. push ( ( ( * source) . clone ( ) , None , htlc. payment_hash . clone ( ) ) ) ;
1212
+ }
1213
+ }
1214
+ }
1215
+ if let & Some ( ref txid) = prev_remote_commitment_txid {
1216
+ for & ( ref htlc, ref source_option) in self . remote_claimable_outpoints . get ( & txid) . unwrap ( ) {
1217
+ if let Some ( ref source) = source_option. as_ref ( ) {
1218
+ htlc_updated. push ( ( ( * source) . clone ( ) , None , htlc. payment_hash . clone ( ) ) ) ;
1219
+ }
1220
+ }
1221
+ }
1222
+ }
1223
+ // No need to check local commitment txn, symmetric HTLCSource must be present as per-htlc data on remote commitment tx
1172
1224
} else if let Some ( per_commitment_data) = per_commitment_option {
1173
1225
// While this isn't useful yet, there is a potential race where if a counterparty
1174
1226
// revokes a state at the same time as the commitment transaction for that state is
@@ -1809,6 +1861,16 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
1809
1861
index : Readable :: read ( reader) ?,
1810
1862
} ;
1811
1863
let funding_info = Some ( ( outpoint, Readable :: read ( reader) ?) ) ;
1864
+ let current_remote_commitment_txid = match <u8 as Readable < R > >:: read ( reader) ? {
1865
+ 0 => None ,
1866
+ 1 => Some ( Readable :: read ( reader) ?) ,
1867
+ _ => return Err ( DecodeError :: InvalidValue ) ,
1868
+ } ;
1869
+ let prev_remote_commitment_txid = match <u8 as Readable < R > >:: read ( reader) ? {
1870
+ 0 => None ,
1871
+ 1 => Some ( Readable :: read ( reader) ?) ,
1872
+ _ => return Err ( DecodeError :: InvalidValue ) ,
1873
+ } ;
1812
1874
Storage :: Local {
1813
1875
revocation_base_key,
1814
1876
htlc_base_key,
@@ -1818,6 +1880,8 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
1818
1880
prev_latest_per_commitment_point,
1819
1881
latest_per_commitment_point,
1820
1882
funding_info,
1883
+ current_remote_commitment_txid,
1884
+ prev_remote_commitment_txid,
1821
1885
}
1822
1886
} ,
1823
1887
_ => return Err ( DecodeError :: InvalidValue ) ,
0 commit comments