@@ -5,6 +5,18 @@ use bitcoin::blockdata::block::{Block, BlockHeader};
5
5
use bitcoin:: hash_types:: BlockHash ;
6
6
use bitcoin:: network:: constants:: Network ;
7
7
8
+ use lightning:: chain;
9
+ use lightning:: chain:: chainmonitor:: ChainMonitor ;
10
+ use lightning:: chain:: chaininterface;
11
+ use lightning:: chain:: channelmonitor;
12
+ use lightning:: chain:: channelmonitor:: ChannelMonitor ;
13
+ use lightning:: chain:: keysinterface;
14
+ use lightning:: ln:: channelmanager:: ChannelManager ;
15
+ use lightning:: util:: logger;
16
+
17
+ use std:: cell:: RefCell ;
18
+ use std:: ops:: Deref ;
19
+
8
20
/// Performs a one-time sync of chain listeners using a single *trusted* block source, bringing each
9
21
/// listener's view of the chain from its paired block hash to `block_source`'s best chain tip.
10
22
///
@@ -13,7 +25,88 @@ use bitcoin::network::constants::Network;
13
25
/// paired with.
14
26
///
15
27
/// Useful during startup to bring the [`ChannelManager`] and each [`ChannelMonitor`] in sync before
16
- /// switching to [`SpvClient`].
28
+ /// switching to [`SpvClient`]. For example:
29
+ ///
30
+ /// ```
31
+ /// use bitcoin::hash_types::BlockHash;
32
+ /// use bitcoin::network::constants::Network;
33
+ ///
34
+ /// use lightning::chain;
35
+ /// use lightning::chain::Watch;
36
+ /// use lightning::chain::chainmonitor::ChainMonitor;
37
+ /// use lightning::chain::channelmonitor;
38
+ /// use lightning::chain::channelmonitor::ChannelMonitor;
39
+ /// use lightning::chain::chaininterface::BroadcasterInterface;
40
+ /// use lightning::chain::chaininterface::FeeEstimator;
41
+ /// use lightning::chain::keysinterface::ChannelKeys;
42
+ /// use lightning::chain::keysinterface::KeysInterface;
43
+ /// use lightning::ln::channelmanager::ChannelManager;
44
+ /// use lightning::ln::channelmanager::ChannelManagerReadArgs;
45
+ /// use lightning::util::config::UserConfig;
46
+ /// use lightning::util::logger::Logger;
47
+ /// use lightning::util::ser::ReadableArgs;
48
+ ///
49
+ /// use lightning_block_sync::*;
50
+ ///
51
+ /// use std::cell::RefCell;
52
+ /// use std::io::Cursor;
53
+ ///
54
+ /// async fn init_sync<
55
+ /// B: BlockSource,
56
+ /// K: KeysInterface<ChanKeySigner = S>,
57
+ /// S: ChannelKeys,
58
+ /// T: BroadcasterInterface,
59
+ /// F: FeeEstimator,
60
+ /// L: Logger,
61
+ /// C: chain::Filter,
62
+ /// P: channelmonitor::Persist<S>,
63
+ /// >(
64
+ /// block_source: &mut B,
65
+ /// chain_monitor: &ChainMonitor<S, &C, &T, &F, &L, &P>,
66
+ /// config: UserConfig,
67
+ /// keys_manager: &K,
68
+ /// tx_broadcaster: &T,
69
+ /// fee_estimator: &F,
70
+ /// logger: &L,
71
+ /// persister: &P,
72
+ /// ) {
73
+ /// let serialized_monitor = "...";
74
+ /// let (monitor_block_hash, mut monitor) = <(BlockHash, ChannelMonitor<S>)>::read(
75
+ /// &mut Cursor::new(&serialized_monitor), keys_manager).unwrap();
76
+ ///
77
+ /// let serialized_manager = "...";
78
+ /// let (manager_block_hash, mut manager) = {
79
+ /// let read_args = ChannelManagerReadArgs::new(
80
+ /// keys_manager,
81
+ /// fee_estimator,
82
+ /// chain_monitor,
83
+ /// tx_broadcaster,
84
+ /// logger,
85
+ /// config,
86
+ /// vec![&mut monitor],
87
+ /// );
88
+ /// <(BlockHash, ChannelManager<S, &ChainMonitor<S, &C, &T, &F, &L, &P>, &T, &K, &F, &L>)>::read(
89
+ /// &mut Cursor::new(&serialized_manager), read_args).unwrap()
90
+ /// };
91
+ ///
92
+ /// let mut cache = UnboundedCache::new();
93
+ /// let mut monitor_listener = (RefCell::new(monitor), tx_broadcaster, fee_estimator, logger);
94
+ /// let mut manager_listener = &manager;
95
+ /// let listeners = vec![
96
+ /// (monitor_block_hash, &mut monitor_listener as &mut dyn ChainListener),
97
+ /// (manager_block_hash, &mut manager_listener as &mut dyn ChainListener),
98
+ /// ];
99
+ /// let chain_tip =
100
+ /// init::sync_listeners(block_source, Network::Bitcoin, &mut cache, listeners).await.unwrap();
101
+ ///
102
+ /// let monitor = monitor_listener.0.into_inner();
103
+ /// chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor);
104
+ ///
105
+ /// let chain_poller = poll::ChainPoller::new(block_source, Network::Bitcoin);
106
+ /// let chain_listener = (&chain_monitor, &manager_listener);
107
+ /// let spv_client = SpvClient::new(chain_tip, chain_poller, &mut cache, chain_listener);
108
+ /// }
109
+ /// ```
17
110
///
18
111
/// [`SpvClient`]: ../struct.SpvClient.html
19
112
/// [`ChannelManager`]: ../../lightning/ln/channelmanager/struct.ChannelManager.html
@@ -104,11 +197,11 @@ impl<'a, C: Cache> Cache for ReadOnlyCache<'a, C> {
104
197
struct DynamicChainListener < ' a > ( & ' a mut dyn ChainListener ) ;
105
198
106
199
impl < ' a > ChainListener for DynamicChainListener < ' a > {
107
- fn block_connected ( & mut self , _block : & Block , _height : u32 ) {
200
+ fn block_connected ( & self , _block : & Block , _height : u32 ) {
108
201
unreachable ! ( )
109
202
}
110
203
111
- fn block_disconnected ( & mut self , header : & BlockHeader , height : u32 ) {
204
+ fn block_disconnected ( & self , header : & BlockHeader , height : u32 ) {
112
205
self . 0 . block_disconnected ( header, height)
113
206
}
114
207
}
@@ -117,19 +210,86 @@ impl<'a> ChainListener for DynamicChainListener<'a> {
117
210
struct ChainListenerSet < ' a > ( Vec < ( u32 , & ' a mut dyn ChainListener ) > ) ;
118
211
119
212
impl < ' a > ChainListener for ChainListenerSet < ' a > {
120
- fn block_connected ( & mut self , block : & Block , height : u32 ) {
121
- for ( starting_height, chain_listener) in self . 0 . iter_mut ( ) {
213
+ fn block_connected ( & self , block : & Block , height : u32 ) {
214
+ for ( starting_height, chain_listener) in self . 0 . iter ( ) {
122
215
if height > * starting_height {
123
216
chain_listener. block_connected ( block, height) ;
124
217
}
125
218
}
126
219
}
127
220
128
- fn block_disconnected ( & mut self , _header : & BlockHeader , _height : u32 ) {
221
+ fn block_disconnected ( & self , _header : & BlockHeader , _height : u32 ) {
129
222
unreachable ! ( )
130
223
}
131
224
}
132
225
226
+ impl < S , B : Deref , F : Deref , L : Deref > ChainListener for ( RefCell < ChannelMonitor < S > > , B , F , L )
227
+ where
228
+ S : keysinterface:: ChannelKeys ,
229
+ B :: Target : chaininterface:: BroadcasterInterface ,
230
+ F :: Target : chaininterface:: FeeEstimator ,
231
+ L :: Target : logger:: Logger ,
232
+ {
233
+ fn block_connected ( & self , block : & Block , height : u32 ) {
234
+ let txdata: Vec < _ > = block. txdata . iter ( ) . enumerate ( ) . collect ( ) ;
235
+ self . 0 . borrow_mut ( ) . block_connected ( & block. header , & txdata, height, & * self . 1 , & * self . 2 , & * self . 3 ) ;
236
+ }
237
+
238
+ fn block_disconnected ( & self , header : & BlockHeader , height : u32 ) {
239
+ self . 0 . borrow_mut ( ) . block_disconnected ( header, height, & * self . 1 , & * self . 2 , & * self . 3 ) ;
240
+ }
241
+ }
242
+
243
+ impl < S , M : Deref , B : Deref , K : Deref , F : Deref , L : Deref > ChainListener for & ChannelManager < S , M , B , K , F , L >
244
+ where
245
+ S : keysinterface:: ChannelKeys ,
246
+ M :: Target : chain:: Watch < Keys = S > ,
247
+ B :: Target : chaininterface:: BroadcasterInterface ,
248
+ K :: Target : keysinterface:: KeysInterface < ChanKeySigner = S > ,
249
+ F :: Target : chaininterface:: FeeEstimator ,
250
+ L :: Target : logger:: Logger ,
251
+ {
252
+ fn block_connected ( & self , block : & Block , height : u32 ) {
253
+ let txdata: Vec < _ > = block. txdata . iter ( ) . enumerate ( ) . collect ( ) ;
254
+ ChannelManager :: block_connected ( self , & block. header , & txdata, height) ;
255
+ }
256
+
257
+ fn block_disconnected ( & self , header : & BlockHeader , _height : u32 ) {
258
+ ChannelManager :: block_disconnected ( self , header) ;
259
+ }
260
+ }
261
+
262
+ impl < S , C : Deref , T : Deref , F : Deref , L : Deref , P : Deref > ChainListener for & ChainMonitor < S , C , T , F , L , P >
263
+ where
264
+ S : keysinterface:: ChannelKeys ,
265
+ C :: Target : chain:: Filter ,
266
+ T :: Target : chaininterface:: BroadcasterInterface ,
267
+ F :: Target : chaininterface:: FeeEstimator ,
268
+ L :: Target : logger:: Logger ,
269
+ P :: Target : channelmonitor:: Persist < S > ,
270
+ {
271
+ fn block_connected ( & self , block : & Block , height : u32 ) {
272
+ let txdata: Vec < _ > = block. txdata . iter ( ) . enumerate ( ) . collect ( ) ;
273
+ ChainMonitor :: block_connected ( self , & block. header , & txdata, height) ;
274
+ }
275
+
276
+ fn block_disconnected ( & self , header : & BlockHeader , height : u32 ) {
277
+ ChainMonitor :: block_disconnected ( self , header, height) ;
278
+ }
279
+ }
280
+
281
+ impl < T : ChainListener , U : ChainListener > ChainListener for ( & T , & U ) {
282
+ fn block_connected ( & self , block : & Block , height : u32 ) {
283
+ self . 0 . block_connected ( block, height) ;
284
+ self . 1 . block_connected ( block, height) ;
285
+ }
286
+
287
+ fn block_disconnected ( & self , header : & BlockHeader , height : u32 ) {
288
+ self . 0 . block_disconnected ( header, height) ;
289
+ self . 1 . block_disconnected ( header, height) ;
290
+ }
291
+ }
292
+
133
293
#[ cfg( test) ]
134
294
mod tests {
135
295
use crate :: test_utils:: { Blockchain , MockChainListener } ;
0 commit comments