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