6
6
//!
7
7
8
8
use std:: collections:: BTreeMap ;
9
+ use std:: collections:: btree_map:: Entry ;
9
10
10
11
use log:: { debug, trace, warn} ;
11
12
use thiserror:: Error ;
@@ -101,6 +102,27 @@ impl SlotBlockData {
101
102
}
102
103
}
103
104
105
+ /// Returned value from [`try_reconstruct_slice`]
106
+ enum ReconstructSliceResult {
107
+ /// Either slice was already reconstructed or not enough data.
108
+ NoAction ,
109
+ /// Encountered an error reconstructing the slice.
110
+ Error ,
111
+ /// Slice successfully reconstructed.
112
+ Complete ,
113
+ }
114
+
115
+ /// Returned value from [`try_reconstruct_block`]
116
+ enum ReconstructBlockResult {
117
+ /// Either block was already reconstructed or not enough data.
118
+ NoAction ,
119
+ /// Encountered an error reconstructing the block.
120
+ Error ,
121
+ /// Block successfully reconstructed.
122
+ /// [`BlockInfo`] describing the block is returned.
123
+ Complete ( BlockInfo ) ,
124
+ }
125
+
104
126
/// Holds all data corresponding to a single block.
105
127
pub struct BlockData {
106
128
/// Slot number this block is in.
@@ -161,14 +183,16 @@ impl BlockData {
161
183
}
162
184
163
185
// maybe reconstruct slice and block
164
- if self . try_reconstruct_slice ( slice_index) {
165
- self . try_reconstruct_block ( )
166
- . map ( |block_info| VotorEvent :: Block {
186
+ // TODO: handle error cases.
187
+ match self . try_reconstruct_slice ( slice_index) {
188
+ ReconstructSliceResult :: NoAction | ReconstructSliceResult :: Error => None ,
189
+ ReconstructSliceResult :: Complete => match self . try_reconstruct_block ( ) {
190
+ ReconstructBlockResult :: NoAction | ReconstructBlockResult :: Error => None ,
191
+ ReconstructBlockResult :: Complete ( block_info) => Some ( VotorEvent :: Block {
167
192
slot : self . slot ,
168
193
block_info,
169
- } )
170
- } else {
171
- None
194
+ } ) ,
195
+ } ,
172
196
}
173
197
}
174
198
@@ -217,55 +241,59 @@ impl BlockData {
217
241
218
242
/// Reconstructs the slice if the blockstore contains enough shreds.
219
243
///
220
- /// Returns `true` if a slice was reconstructed, `false` otherwise .
221
- fn try_reconstruct_slice ( & mut self , slice : SliceIndex ) -> bool {
244
+ /// See [`ReconstructSliceResult`] for more info on what the function returns .
245
+ fn try_reconstruct_slice ( & mut self , index : SliceIndex ) -> ReconstructSliceResult {
222
246
if self . completed . is_some ( ) {
223
247
trace ! ( "already have block for slot {}" , self . slot) ;
224
- return false ;
248
+ return ReconstructSliceResult :: NoAction ;
225
249
}
226
- if self . slices . contains_key ( & slice) {
227
- trace ! ( "already have slice {} in slot {}" , slice, self . slot) ;
228
- return false ;
229
- }
230
- let slice_shreds = self . shreds . get_mut ( & slice) . unwrap ( ) ;
250
+
251
+ let entry = match self . slices . entry ( index) {
252
+ Entry :: Occupied ( _) => return ReconstructSliceResult :: NoAction ,
253
+ Entry :: Vacant ( entry) => entry,
254
+ } ;
255
+
256
+ // assuming caller has inserted at least one valid shred so unwrap() should be safe
257
+ let slice_shreds = self . shreds . get_mut ( & index) . unwrap ( ) ;
231
258
let ( reconstructed_slice, mut reconstructed_shreds) =
232
259
match RegularShredder :: deshred ( slice_shreds) {
233
260
Ok ( output) => output,
234
- Err ( DeshredError :: NotEnoughShreds ) => return false ,
261
+ Err ( DeshredError :: NotEnoughShreds ) => return ReconstructSliceResult :: NoAction ,
235
262
rest => {
236
263
warn ! ( "deshreding failed with {rest:?}" ) ;
237
- return false ;
264
+ return ReconstructSliceResult :: Error ;
238
265
}
239
266
} ;
240
267
if reconstructed_slice. parent . is_none ( ) && reconstructed_slice. slice_index . is_first ( ) {
241
268
warn ! (
242
269
"reconstructed slice {} in slot {} expected to contain parent" ,
243
- slice , self . slot
270
+ index , self . slot
244
271
) ;
245
- return false ;
272
+ return ReconstructSliceResult :: Error ;
246
273
}
247
274
248
275
// insert reconstructed slice and shreds
249
- self . slices . insert ( slice , reconstructed_slice) ;
276
+ entry . insert ( reconstructed_slice) ;
250
277
std:: mem:: swap ( slice_shreds, & mut reconstructed_shreds) ;
251
- trace ! ( "reconstructed slice {} in slot {}" , slice , self . slot) ;
278
+ trace ! ( "reconstructed slice {} in slot {}" , index , self . slot) ;
252
279
253
- true
280
+ ReconstructSliceResult :: Complete
254
281
}
255
282
256
283
/// Reconstructs the block if the blockstore contains all slices.
257
284
///
258
- /// Returns `Some(block_info)` if a block was reconstructed, `None` otherwise.
259
- /// In the `Some`-case, `block_info` is the [`BlockInfo`] of the reconstructed block.
260
- fn try_reconstruct_block ( & mut self ) -> Option < BlockInfo > {
285
+ /// See [`ReconstructBlockResult`] for more info on what the function returns.
286
+ fn try_reconstruct_block ( & mut self ) -> ReconstructBlockResult {
261
287
if self . completed . is_some ( ) {
262
288
trace ! ( "already have block for slot {}" , self . slot) ;
263
- return None ;
289
+ return ReconstructBlockResult :: NoAction ;
264
290
}
265
- let last_slice = self . last_slice ?;
291
+ let Some ( last_slice) = self . last_slice else {
292
+ return ReconstructBlockResult :: NoAction ;
293
+ } ;
266
294
if self . slices . len ( ) != last_slice. inner ( ) + 1 {
267
295
trace ! ( "don't have all slices for slot {} yet" , self . slot) ;
268
- return None ;
296
+ return ReconstructBlockResult :: NoAction ;
269
297
}
270
298
271
299
// calculate double-Merkle tree & block hash
@@ -292,11 +320,11 @@ impl BlockData {
292
320
{
293
321
if new_parent == parent {
294
322
warn ! ( "parent switched to same value" ) ;
295
- return None ;
323
+ return ReconstructBlockResult :: Error ;
296
324
}
297
325
if parent_switched {
298
326
warn ! ( "parent switched more than once" ) ;
299
- return None ;
327
+ return ReconstructBlockResult :: Error ;
300
328
}
301
329
parent_switched = true ;
302
330
parent = new_parent;
@@ -307,7 +335,7 @@ impl BlockData {
307
335
Ok ( r) => r,
308
336
Err ( err) => {
309
337
warn ! ( "decoding slice {ind} failed with {err:?}" ) ;
310
- return None ;
338
+ return ReconstructBlockResult :: Error ;
311
339
}
312
340
} ;
313
341
if bytes_read != slice. data . len ( ) {
@@ -317,7 +345,7 @@ impl BlockData {
317
345
bytes_read,
318
346
slice. data. len( )
319
347
) ;
320
- return None ;
348
+ return ReconstructBlockResult :: Error ;
321
349
}
322
350
transactions. append ( & mut txs) ;
323
351
}
@@ -337,7 +365,7 @@ impl BlockData {
337
365
self . slices . remove ( & slice_index) ;
338
366
}
339
367
340
- Some ( block_info)
368
+ ReconstructBlockResult :: Complete ( block_info)
341
369
}
342
370
}
343
371
0 commit comments