@@ -29,7 +29,7 @@ use bitcoin::hash_types::{Txid, BlockHash};
29
29
use crate :: chain;
30
30
use crate :: chain:: { ChannelMonitorUpdateStatus , Filter , WatchedOutput } ;
31
31
use crate :: chain:: chaininterface:: { BroadcasterInterface , FeeEstimator } ;
32
- use crate :: chain:: channelmonitor:: { ChannelMonitor , ChannelMonitorUpdate , Balance , MonitorEvent , TransactionOutputs , WithChannelMonitor } ;
32
+ use crate :: chain:: channelmonitor:: { ChannelMonitor , StubChannelMonitor , ChannelMonitorUpdate , Balance , MonitorEvent , TransactionOutputs , WithChannelMonitor , LATENCY_GRACE_PERIOD_BLOCKS } ;
33
33
use crate :: chain:: transaction:: { OutPoint , TransactionData } ;
34
34
use crate :: ln:: types:: ChannelId ;
35
35
use crate :: sign:: ecdsa:: EcdsaChannelSigner ;
@@ -162,6 +162,9 @@ pub trait Persist<ChannelSigner: EcdsaChannelSigner> {
162
162
/// Archiving the data in a backup location (rather than deleting it fully) is useful for
163
163
/// hedging against data loss in case of unexpected failure.
164
164
fn archive_persisted_channel ( & self , channel_funding_outpoint : OutPoint ) ;
165
+ /// Persist a new channel's data in response to a [`chain::Watch::watch_dummy`] call. This is
166
+ /// called by [`ChannelManager`] for new stub channels received from peer storage backup,
167
+ fn persist_new_stub_channel ( & self , funding_txo : OutPoint , stub_monitor : & StubChannelMonitor < ChannelSigner > ) -> Result < ( ) , std:: io:: Error > ;
165
168
}
166
169
167
170
struct MonitorHolder < ChannelSigner : EcdsaChannelSigner > {
@@ -190,6 +193,19 @@ pub struct LockedChannelMonitor<'a, ChannelSigner: EcdsaChannelSigner> {
190
193
funding_txo : OutPoint ,
191
194
}
192
195
196
+ /// A read-only reference to a current StubChannelMonitors similar to [LockedChannelMonitor]
197
+ pub struct LockedStubChannelMonitor < ' a , ChannelSigner : EcdsaChannelSigner > {
198
+ lock : RwLockReadGuard < ' a , HashMap < OutPoint , StubChannelMonitor < ChannelSigner > > > ,
199
+ funding_txo : OutPoint ,
200
+ }
201
+
202
+ impl < ChannelSigner : EcdsaChannelSigner > Deref for LockedStubChannelMonitor < ' _ , ChannelSigner > {
203
+ type Target = StubChannelMonitor < ChannelSigner > ;
204
+ fn deref ( & self ) -> & StubChannelMonitor < ChannelSigner > {
205
+ & self . lock . get ( & self . funding_txo ) . expect ( "Checked at construction" )
206
+ }
207
+ }
208
+
193
209
impl < ChannelSigner : EcdsaChannelSigner > Deref for LockedChannelMonitor < ' _ , ChannelSigner > {
194
210
type Target = ChannelMonitor < ChannelSigner > ;
195
211
fn deref ( & self ) -> & ChannelMonitor < ChannelSigner > {
@@ -221,6 +237,8 @@ pub struct ChainMonitor<ChannelSigner: EcdsaChannelSigner, C: Deref, T: Deref, F
221
237
P :: Target : Persist < ChannelSigner > ,
222
238
{
223
239
monitors : RwLock < HashMap < OutPoint , MonitorHolder < ChannelSigner > > > ,
240
+ stub_monitors : RwLock < HashMap < OutPoint , StubChannelMonitor < ChannelSigner > > > ,
241
+
224
242
chain_source : Option < C > ,
225
243
broadcaster : T ,
226
244
logger : L ,
@@ -255,9 +273,10 @@ where C::Target: chain::Filter,
255
273
/// updated `txdata`.
256
274
///
257
275
/// Calls which represent a new blockchain tip height should set `best_height`.
258
- fn process_chain_data < FN > ( & self , header : & Header , best_height : Option < u32 > , txdata : & TransactionData , process : FN )
276
+ fn process_chain_data < FN , SN > ( & self , header : & Header , best_height : Option < u32 > , txdata : & TransactionData , process : FN , stub_process : SN )
259
277
where
260
- FN : Fn ( & ChannelMonitor < ChannelSigner > , & TransactionData ) -> Vec < TransactionOutputs >
278
+ FN : Fn ( & ChannelMonitor < ChannelSigner > , & TransactionData ) -> Vec < TransactionOutputs > ,
279
+ SN : Fn ( & StubChannelMonitor < ChannelSigner > , & TransactionData ) -> Vec < TransactionOutputs >
261
280
{
262
281
let err_str = "ChannelMonitor[Update] persistence failed unrecoverably. This indicates we cannot continue normal operation and must shut down." ;
263
282
let funding_outpoints = hash_set_from_iter ( self . monitors . read ( ) . unwrap ( ) . keys ( ) . cloned ( ) ) ;
@@ -287,6 +306,14 @@ where C::Target: chain::Filter,
287
306
}
288
307
}
289
308
309
+ let stub_monitors = self . stub_monitors . write ( ) . unwrap ( ) ;
310
+ for ( funding_outpoint, stub_monitor) in stub_monitors. iter ( ) {
311
+ if self . update_stub_with_chain_data ( header, best_height, txdata, & stub_process, funding_outpoint, stub_monitor) . is_err ( ) {
312
+ log_error ! ( self . logger, "{}" , err_str) ;
313
+ panic ! ( "{}" , err_str) ;
314
+ } ;
315
+ }
316
+
290
317
if let Some ( height) = best_height {
291
318
// If the best block height is being updated, update highest_chain_height under the
292
319
// monitors write lock.
@@ -298,6 +325,34 @@ where C::Target: chain::Filter,
298
325
}
299
326
}
300
327
328
+ fn update_stub_with_chain_data < SN > ( & self , header : & Header , _best_height : Option < u32 > , txdata : & TransactionData , stub_process : SN ,
329
+ _funding_outpoint : & OutPoint , stub_monitor : & StubChannelMonitor < ChannelSigner > ) -> Result < ( ) , ( ) >
330
+ where SN : Fn ( & StubChannelMonitor < ChannelSigner > , & TransactionData ) -> Vec < TransactionOutputs > {
331
+ let logger = WithChannelMonitor :: from_stub ( & self . logger , stub_monitor) ;
332
+ let mut txn_outputs;
333
+ {
334
+ txn_outputs = stub_process ( stub_monitor, txdata) ;
335
+ }
336
+
337
+ if let Some ( ref chain_source) = self . chain_source {
338
+ let block_hash = header. block_hash ( ) ;
339
+ for ( txid, mut outputs) in txn_outputs. drain ( ..) {
340
+ for ( idx, output) in outputs. drain ( ..) {
341
+ // Register any new outputs with the chain source for filtering
342
+ let output = WatchedOutput {
343
+ block_hash : Some ( block_hash) ,
344
+ outpoint : OutPoint { txid, index : idx as u16 } ,
345
+ script_pubkey : output. script_pubkey ,
346
+ } ;
347
+ log_trace ! ( logger, "Adding monitoring for spends of outpoint from stub {} to the filter" , output. outpoint) ;
348
+ chain_source. register_output ( output) ;
349
+ }
350
+ }
351
+ }
352
+
353
+ Ok ( ( ) )
354
+ }
355
+
301
356
fn update_monitor_with_chain_data < FN > (
302
357
& self , header : & Header , best_height : Option < u32 > , txdata : & TransactionData , process : FN , funding_outpoint : & OutPoint ,
303
358
monitor_state : & MonitorHolder < ChannelSigner > , channel_count : usize ,
@@ -367,6 +422,7 @@ where C::Target: chain::Filter,
367
422
pub fn new ( chain_source : Option < C > , broadcaster : T , logger : L , feeest : F , persister : P ) -> Self {
368
423
Self {
369
424
monitors : RwLock :: new ( new_hash_map ( ) ) ,
425
+ stub_monitors : RwLock :: new ( new_hash_map ( ) ) ,
370
426
chain_source,
371
427
broadcaster,
372
428
logger,
@@ -417,6 +473,15 @@ where C::Target: chain::Filter,
417
473
}
418
474
}
419
475
476
+ pub fn get_stub_monitor ( & self , funding_txo : OutPoint ) -> Result < LockedStubChannelMonitor < ' _ , ChannelSigner > , ( ) > {
477
+ let lock = self . stub_monitors . read ( ) . unwrap ( ) ;
478
+ if lock. get ( & funding_txo) . is_some ( ) {
479
+ Ok ( LockedStubChannelMonitor { lock, funding_txo } )
480
+ } else {
481
+ Err ( ( ) )
482
+ }
483
+ }
484
+
420
485
/// Lists the funding outpoint and channel ID of each [`ChannelMonitor`] being monitored.
421
486
///
422
487
/// Note that [`ChannelMonitor`]s are not removed when a channel is closed as they are always
@@ -428,6 +493,13 @@ where C::Target: chain::Filter,
428
493
} ) . collect ( )
429
494
}
430
495
496
+ pub fn list_stub_monitors ( & self ) -> Vec < ( OutPoint , ChannelId ) > {
497
+ self . stub_monitors . read ( ) . unwrap ( ) . iter ( ) . map ( |( outpoint, stub_monitor) | {
498
+ let channel_id = stub_monitor. channel_id ( ) ;
499
+ ( * outpoint, channel_id)
500
+ } ) . collect ( )
501
+ }
502
+
431
503
#[ cfg( not( c_bindings) ) ]
432
504
/// Lists the pending updates for each [`ChannelMonitor`] (by `OutPoint` being monitored).
433
505
/// Each `Vec<u64>` contains `update_id`s from [`ChannelMonitor::get_latest_update_id`] for updates
@@ -654,6 +726,9 @@ where
654
726
self . process_chain_data ( header, Some ( height) , & txdata, |monitor, txdata| {
655
727
monitor. block_connected (
656
728
header, txdata, height, & * self . broadcaster , & * self . fee_estimator , & self . logger )
729
+ } , |stub_monitor, txdata| {
730
+ stub_monitor. block_connected (
731
+ header, txdata, height, & * self . broadcaster , & * self . fee_estimator , & self . logger )
657
732
} ) ;
658
733
// Assume we may have some new events and wake the event processor
659
734
self . event_notifier . notify ( ) ;
@@ -683,6 +758,9 @@ where
683
758
self . process_chain_data ( header, None , txdata, |monitor, txdata| {
684
759
monitor. transactions_confirmed (
685
760
header, txdata, height, & * self . broadcaster , & * self . fee_estimator , & self . logger )
761
+ } , |stub_monitor, txdata| {
762
+ stub_monitor. transactions_confirmed (
763
+ header, txdata, height, & * self . broadcaster , & * self . fee_estimator , & self . logger )
686
764
} ) ;
687
765
// Assume we may have some new events and wake the event processor
688
766
self . event_notifier . notify ( ) ;
@@ -705,6 +783,10 @@ where
705
783
monitor. best_block_updated (
706
784
header, height, & * self . broadcaster , & * self . fee_estimator , & self . logger
707
785
)
786
+ } , |stub_monitor, txdata| {
787
+ debug_assert ! ( txdata. is_empty( ) ) ;
788
+ stub_monitor. best_block_updated (
789
+ header, height, & * self . broadcaster , & * self . fee_estimator , & self . logger )
708
790
} ) ;
709
791
// Assume we may have some new events and wake the event processor
710
792
self . event_notifier . notify ( ) ;
@@ -731,6 +813,39 @@ where C::Target: chain::Filter,
731
813
L :: Target : Logger ,
732
814
P :: Target : Persist < ChannelSigner > ,
733
815
{
816
+ fn watch_dummy ( & self , funding_outpoint : OutPoint , stub_monitor : StubChannelMonitor < ChannelSigner > ) -> Result < ( ) , ( ) > {
817
+ let logger = WithChannelMonitor :: from_stub ( & self . logger , & stub_monitor) ;
818
+ let mut monitors = self . monitors . write ( ) . unwrap ( ) ;
819
+ match monitors. entry ( funding_outpoint) {
820
+ hash_map:: Entry :: Occupied ( _) => {
821
+ log_error ! ( logger, "Failed to add new channel data: channel monitor for given outpoint is already present" ) ;
822
+ return Err ( ( ) ) ;
823
+ } ,
824
+ hash_map:: Entry :: Vacant ( e) => e,
825
+ } ;
826
+ let mut stub_monitors = self . stub_monitors . write ( ) . unwrap ( ) ;
827
+ let entry = match stub_monitors. entry ( funding_outpoint) {
828
+ hash_map:: Entry :: Occupied ( _) => {
829
+ log_error ! ( logger, "Failed to add new channel data: channel monitor for given outpoint is already present" ) ;
830
+ return Err ( ( ) ) ;
831
+ } ,
832
+ hash_map:: Entry :: Vacant ( e) => e,
833
+ } ;
834
+ log_trace ! ( logger, "Got new StubChannelMonitor for channel {}" , stub_monitor. channel_id( ) ) ;
835
+ let persist_res = self . persister . persist_new_stub_channel ( funding_outpoint, & stub_monitor) ;
836
+
837
+ if persist_res. is_err ( ) {
838
+ log_error ! ( logger, "Failed to add new dummy channel data" ) ;
839
+ return Err ( ( ) ) ;
840
+ }
841
+ if let Some ( ref chain_source) = self . chain_source {
842
+ stub_monitor. load_outputs_to_watch ( chain_source , & self . logger ) ;
843
+ }
844
+ entry. insert ( stub_monitor) ;
845
+
846
+ Ok ( ( ) )
847
+ }
848
+
734
849
fn watch_channel ( & self , funding_outpoint : OutPoint , monitor : ChannelMonitor < ChannelSigner > ) -> Result < ChannelMonitorUpdateStatus , ( ) > {
735
850
let logger = WithChannelMonitor :: from ( & self . logger , & monitor, None ) ;
736
851
let mut monitors = self . monitors . write ( ) . unwrap ( ) ;
0 commit comments