@@ -66,17 +66,18 @@ impl Drop for Guard {
66
66
}
67
67
68
68
/// External database restoration handler
69
- pub trait DatabaseRestore : Send + Sync {
69
+ pub trait DatabaseRestore < T : ChainRestorationParams > : Send + Sync {
70
70
/// Restart with a new backend. Takes ownership of passed database and moves it to a new location.
71
- fn restore_db ( & self , new_db : & str ) -> Result < ( ) , Error > ;
71
+ fn restore_db ( & self , new_db : & str , params : & T ) -> Result < ( ) , Error > ;
72
72
}
73
73
74
74
/// State restoration manager.
75
- struct Restoration {
75
+ pub struct Restoration {
76
76
manifest : ManifestData ,
77
77
state_chunks_left : HashSet < H256 > ,
78
78
block_chunks_left : HashSet < H256 > ,
79
- state : StateRebuilder ,
79
+ // TODO: maybe a more type-safe API?
80
+ state : Option < StateRebuilder > ,
80
81
secondary : Box < Rebuilder > ,
81
82
writer : Option < LooseWriter > ,
82
83
snappy_buffer : Bytes ,
@@ -118,7 +119,7 @@ impl Restoration {
118
119
manifest : manifest,
119
120
state_chunks_left : state_chunks,
120
121
block_chunks_left : block_chunks,
121
- state : StateRebuilder :: new ( raw_db. clone ( ) , params. pruning ) ,
122
+ state : Some ( StateRebuilder :: new ( raw_db. clone ( ) , params. pruning ) ) ,
122
123
secondary : secondary,
123
124
writer : params. writer ,
124
125
snappy_buffer : Vec :: new ( ) ,
@@ -130,6 +131,10 @@ impl Restoration {
130
131
131
132
// feeds a state chunk, aborts early if `flag` becomes false.
132
133
fn feed_state ( & mut self , hash : H256 , chunk : & [ u8 ] , flag : & AtomicBool ) -> Result < ( ) , Error > {
134
+ if self . state . is_none ( ) {
135
+ trace ! ( target: "snapshot" , "Feeding a chunk state to a light client" ) ;
136
+ return Ok ( ( ) ) ;
137
+ }
133
138
if self . state_chunks_left . contains ( & hash) {
134
139
let expected_len = snappy:: decompressed_len ( chunk) ?;
135
140
if expected_len > MAX_CHUNK_SIZE {
@@ -138,7 +143,10 @@ impl Restoration {
138
143
}
139
144
let len = snappy:: decompress_into ( chunk, & mut self . snappy_buffer ) ?;
140
145
141
- self . state . feed ( & self . snappy_buffer [ ..len] , flag) ?;
146
+ self . state
147
+ . as_mut ( )
148
+ . expect ( "checked above; qed" )
149
+ . feed ( & self . snappy_buffer [ ..len] , flag) ?;
142
150
143
151
if let Some ( ref mut writer) = self . writer . as_mut ( ) {
144
152
writer. write_state_chunk ( hash, chunk) ?;
@@ -177,15 +185,17 @@ impl Restoration {
177
185
178
186
if !self . is_done ( ) { return Ok ( ( ) ) }
179
187
180
- // verify final state root.
181
- let root = self . state . state_root ( ) ;
182
- if root != self . final_state_root {
183
- warn ! ( "Final restored state has wrong state root: expected {:?}, got {:?}" , self . final_state_root, root) ;
184
- bail ! ( TrieError :: InvalidStateRoot ( root) ) ;
185
- }
188
+ if let Some ( state) = self . state {
189
+ // verify final state root.
190
+ let root = state. state_root ( ) ;
191
+ if root != self . final_state_root {
192
+ warn ! ( "Final restored state has wrong state root: expected {:?}, got {:?}" , self . final_state_root, root) ;
193
+ bail ! ( TrieError :: InvalidStateRoot ( root) ) ;
194
+ }
186
195
187
- // check for missing code.
188
- self . state . finalize ( self . manifest . block_number , self . manifest . block_hash ) ?;
196
+ // check for missing code.
197
+ state. finalize ( self . manifest . block_number , self . manifest . block_hash ) ?;
198
+ }
189
199
190
200
// connect out-of-order chunks and verify chain integrity.
191
201
self . secondary . finalize ( engine) ?;
@@ -208,13 +218,11 @@ impl Restoration {
208
218
pub type Channel = IoChannel < ClientIoMessage > ;
209
219
210
220
/// Snapshot service parameters.
211
- pub struct ServiceParams {
221
+ pub struct ServiceParams < T : ChainRestorationParams > {
212
222
/// The consensus engine this is built on.
213
223
pub engine : Arc < EthEngine > ,
214
- /// The chain's genesis block.
215
- pub genesis_block : Bytes ,
216
- /// State pruning algorithm.
217
- pub pruning : Algorithm ,
224
+ /// Additional chain specific restoration params.
225
+ pub chain_params : T ,
218
226
/// Handler for opening a restoration DB.
219
227
pub restoration_db_handler : Box < KeyValueDBHandler > ,
220
228
/// Async IO channel for sending messages.
@@ -223,42 +231,88 @@ pub struct ServiceParams {
223
231
/// Usually "<chain hash>/snapshot"
224
232
pub snapshot_root : PathBuf ,
225
233
/// A handle for database restoration.
226
- pub db_restore : Arc < DatabaseRestore > ,
234
+ pub db_restore : Arc < DatabaseRestore < T > > ,
235
+ }
236
+
237
+ /// Full node specific restoration parameters.
238
+ pub struct FullNodeRestorationParams {
239
+ /// The chain's genesis block.
240
+ pub genesis_block : Bytes ,
241
+ /// State pruning algorithm.
242
+ pub pruning : Algorithm ,
243
+ }
244
+
245
+ /// TODO: document
246
+ pub trait ChainRestorationParams : Send + Sync {
247
+ /// TODO: document
248
+ fn restoration (
249
+ & self ,
250
+ manifest : ManifestData ,
251
+ rest_db : PathBuf ,
252
+ restoration_db_handler : & KeyValueDBHandler ,
253
+ writer : Option < LooseWriter > ,
254
+ engine : & EthEngine ,
255
+ ) -> Result < Restoration , Error > ;
256
+
257
+ /// TODO: document
258
+ fn is_light ( & self ) -> bool {
259
+ false
260
+ }
261
+ }
262
+
263
+ impl ChainRestorationParams for FullNodeRestorationParams {
264
+ fn restoration (
265
+ & self ,
266
+ manifest : ManifestData ,
267
+ rest_db : PathBuf ,
268
+ restoration_db_handler : & KeyValueDBHandler ,
269
+ writer : Option < LooseWriter > ,
270
+ engine : & EthEngine ,
271
+ ) -> Result < Restoration , Error > {
272
+ let params = RestorationParams {
273
+ manifest : manifest. clone ( ) ,
274
+ pruning : self . pruning ,
275
+ db : restoration_db_handler. open ( & rest_db) ?,
276
+ writer : writer,
277
+ genesis : & self . genesis_block ,
278
+ guard : Guard :: new ( rest_db) ,
279
+ engine : engine,
280
+ } ;
281
+ Restoration :: new ( params)
282
+ }
227
283
}
228
284
229
285
/// `SnapshotService` implementation.
230
286
/// This controls taking snapshots and restoring from them.
231
- pub struct Service {
287
+ pub struct Service < T : ChainRestorationParams > {
232
288
restoration : Mutex < Option < Restoration > > ,
233
289
restoration_db_handler : Box < KeyValueDBHandler > ,
234
290
snapshot_root : PathBuf ,
235
291
io_channel : Mutex < Channel > ,
236
- pruning : Algorithm ,
237
292
status : Mutex < RestorationStatus > ,
238
293
reader : RwLock < Option < LooseReader > > ,
239
294
engine : Arc < EthEngine > ,
240
- genesis_block : Bytes ,
295
+ chain_params : T ,
241
296
state_chunks : AtomicUsize ,
242
297
block_chunks : AtomicUsize ,
243
- db_restore : Arc < DatabaseRestore > ,
298
+ db_restore : Arc < DatabaseRestore < T > > ,
244
299
progress : super :: Progress ,
245
300
taking_snapshot : AtomicBool ,
246
301
restoring_snapshot : AtomicBool ,
247
302
}
248
303
249
- impl Service {
304
+ impl < T : ChainRestorationParams > Service < T > {
250
305
/// Create a new snapshot service from the given parameters.
251
- pub fn new ( params : ServiceParams ) -> Result < Self , Error > {
306
+ pub fn new ( params : ServiceParams < T > ) -> Result < Self , Error > {
252
307
let mut service = Service {
253
308
restoration : Mutex :: new ( None ) ,
254
309
restoration_db_handler : params. restoration_db_handler ,
255
310
snapshot_root : params. snapshot_root ,
256
311
io_channel : Mutex :: new ( params. channel ) ,
257
- pruning : params. pruning ,
312
+ chain_params : params. chain_params ,
258
313
status : Mutex :: new ( RestorationStatus :: Inactive ) ,
259
314
reader : RwLock :: new ( None ) ,
260
315
engine : params. engine ,
261
- genesis_block : params. genesis_block ,
262
316
state_chunks : AtomicUsize :: new ( 0 ) ,
263
317
block_chunks : AtomicUsize :: new ( 0 ) ,
264
318
db_restore : params. db_restore ,
@@ -340,7 +394,7 @@ impl Service {
340
394
fn replace_client_db ( & self ) -> Result < ( ) , Error > {
341
395
let our_db = self . restoration_db ( ) ;
342
396
343
- self . db_restore . restore_db ( & * our_db. to_string_lossy ( ) ) ?;
397
+ self . db_restore . restore_db ( & * our_db. to_string_lossy ( ) , & self . chain_params ) ?;
344
398
Ok ( ( ) )
345
399
}
346
400
@@ -464,20 +518,21 @@ impl Service {
464
518
false => None
465
519
} ;
466
520
467
- let params = RestorationParams {
468
- manifest : manifest. clone ( ) ,
469
- pruning : self . pruning ,
470
- db : self . restoration_db_handler . open ( & rest_db) ?,
471
- writer : writer,
472
- genesis : & self . genesis_block ,
473
- guard : Guard :: new ( rest_db) ,
474
- engine : & * self . engine ,
521
+ let state_chunks = if self . chain_params . is_light ( ) {
522
+ 0
523
+ } else {
524
+ manifest. state_hashes . len ( )
475
525
} ;
476
-
477
- let state_chunks = manifest. state_hashes . len ( ) ;
478
526
let block_chunks = manifest. block_hashes . len ( ) ;
479
527
480
- * res = Some ( Restoration :: new ( params) ?) ;
528
+ * res = Some ( ChainRestorationParams :: restoration (
529
+ & self . chain_params ,
530
+ manifest. clone ( ) ,
531
+ rest_db,
532
+ & * self . restoration_db_handler ,
533
+ writer,
534
+ & * self . engine ,
535
+ ) ?) ;
481
536
482
537
self . restoring_snapshot . store ( true , Ordering :: SeqCst ) ;
483
538
@@ -668,7 +723,7 @@ impl Service {
668
723
}
669
724
}
670
725
671
- impl SnapshotService for Service {
726
+ impl < T : ChainRestorationParams > SnapshotService for Service < T > {
672
727
fn manifest ( & self ) -> Option < ManifestData > {
673
728
self . reader . read ( ) . as_ref ( ) . map ( |r| r. manifest ( ) . clone ( ) )
674
729
}
@@ -752,7 +807,7 @@ impl SnapshotService for Service {
752
807
}
753
808
}
754
809
755
- impl Drop for Service {
810
+ impl < T : ChainRestorationParams > Drop for Service < T > {
756
811
fn drop ( & mut self ) {
757
812
self . abort_restore ( ) ;
758
813
}
0 commit comments