@@ -19,11 +19,12 @@ use crate::core::core::hash::{Hash, Hashed};
1919use crate :: core:: core:: { Block , BlockHeader , BlockSums } ;
2020use crate :: core:: pow:: Difficulty ;
2121use crate :: core:: ser:: ProtocolVersion ;
22- use crate :: types:: Tip ;
22+ use crate :: types:: { CommitPos , Tip } ;
2323use crate :: util:: secp:: pedersen:: Commitment ;
2424use croaring:: Bitmap ;
2525use grin_store as store;
2626use grin_store:: { option_to_not_found, to_key, Error , SerIterator } ;
27+ use std:: convert:: TryInto ;
2728use std:: sync:: Arc ;
2829
2930const STORE_SUBPATH : & str = "chain" ;
@@ -35,6 +36,7 @@ const TAIL_PREFIX: u8 = b'T';
3536const OUTPUT_POS_PREFIX : u8 = b'p' ;
3637const BLOCK_INPUT_BITMAP_PREFIX : u8 = b'B' ;
3738const BLOCK_SUMS_PREFIX : u8 = b'M' ;
39+ const BLOCK_SPENT_PREFIX : u8 = b'S' ;
3840
3941/// All chain-related database operations
4042pub struct ChainStore {
@@ -178,16 +180,19 @@ impl<'a> Batch<'a> {
178180 self . db . exists ( & to_key ( BLOCK_PREFIX , & mut h. to_vec ( ) ) )
179181 }
180182
181- /// Save the block and the associated input bitmap .
183+ /// Save the block to the db .
182184 /// Note: the block header is not saved to the db here, assumes this has already been done.
183185 pub fn save_block ( & self , b : & Block ) -> Result < ( ) , Error > {
184- // Build the "input bitmap" for this new block and store it in the db.
185- self . build_and_store_block_input_bitmap ( & b) ?;
186-
187- // Save the block itself to the db.
188186 self . db
189187 . put_ser ( & to_key ( BLOCK_PREFIX , & mut b. hash ( ) . to_vec ( ) ) [ ..] , b) ?;
188+ Ok ( ( ) )
189+ }
190190
191+ /// We maintain a "spent" index for each full block to allow the output_pos
192+ /// to be easily reverted during rewind.
193+ pub fn save_spent_index ( & self , h : & Hash , spent : & Vec < CommitPos > ) -> Result < ( ) , Error > {
194+ self . db
195+ . put_ser ( & to_key ( BLOCK_SPENT_PREFIX , & mut h. to_vec ( ) ) [ ..] , spent) ?;
191196 Ok ( ( ) )
192197 }
193198
@@ -217,7 +222,7 @@ impl<'a> Batch<'a> {
217222 // Not an error if these fail.
218223 {
219224 let _ = self . delete_block_sums ( bh) ;
220- let _ = self . delete_block_input_bitmap ( bh) ;
225+ let _ = self . delete_spent_index ( bh) ;
221226 }
222227
223228 Ok ( ( ) )
@@ -247,6 +252,20 @@ impl<'a> Batch<'a> {
247252 )
248253 }
249254
255+ /// Delete the output_pos index entry for a spent output.
256+ pub fn delete_output_pos_height ( & self , commit : & Commitment ) -> Result < ( ) , Error > {
257+ self . db
258+ . delete ( & to_key ( OUTPUT_POS_PREFIX , & mut commit. as_ref ( ) . to_vec ( ) ) )
259+ }
260+
261+ /// When using the output_pos iterator we have access to the index keys but not the
262+ /// original commitment that the key is constructed from. So we need a way of comparing
263+ /// a key with another commitment without reconstructing the commitment from the key bytes.
264+ pub fn is_match_output_pos_key ( & self , key : & [ u8 ] , commit : & Commitment ) -> bool {
265+ let commit_key = to_key ( OUTPUT_POS_PREFIX , & mut commit. as_ref ( ) . to_vec ( ) ) ;
266+ commit_key == key
267+ }
268+
250269 /// Iterator over the output_pos index.
251270 pub fn output_pos_iter ( & self ) -> Result < SerIterator < ( u64 , u64 ) > , Error > {
252271 let key = to_key ( OUTPUT_POS_PREFIX , & mut "" . to_string ( ) . into_bytes ( ) ) ;
@@ -281,18 +300,15 @@ impl<'a> Batch<'a> {
281300 )
282301 }
283302
284- /// Save the input bitmap for the block.
285- fn save_block_input_bitmap ( & self , bh : & Hash , bm : & Bitmap ) -> Result < ( ) , Error > {
286- self . db . put (
287- & to_key ( BLOCK_INPUT_BITMAP_PREFIX , & mut bh. to_vec ( ) ) [ ..] ,
288- & bm. serialize ( ) ,
289- )
290- }
303+ /// Delete the block spent index.
304+ fn delete_spent_index ( & self , bh : & Hash ) -> Result < ( ) , Error > {
305+ // Clean up the legacy input bitmap as well.
306+ let _ = self
307+ . db
308+ . delete ( & to_key ( BLOCK_INPUT_BITMAP_PREFIX , & mut bh. to_vec ( ) ) ) ;
291309
292- /// Delete the block input bitmap.
293- fn delete_block_input_bitmap ( & self , bh : & Hash ) -> Result < ( ) , Error > {
294310 self . db
295- . delete ( & to_key ( BLOCK_INPUT_BITMAP_PREFIX , & mut bh. to_vec ( ) ) )
311+ . delete ( & to_key ( BLOCK_SPENT_PREFIX , & mut bh. to_vec ( ) ) )
296312 }
297313
298314 /// Save block_sums for the block.
@@ -314,47 +330,41 @@ impl<'a> Batch<'a> {
314330 self . db . delete ( & to_key ( BLOCK_SUMS_PREFIX , & mut bh. to_vec ( ) ) )
315331 }
316332
317- /// Build the input bitmap for the given block.
318- fn build_block_input_bitmap ( & self , block : & Block ) -> Result < Bitmap , Error > {
319- let bitmap = block
320- . inputs ( )
321- . iter ( )
322- . filter_map ( |x| self . get_output_pos ( & x. commitment ( ) ) . ok ( ) )
323- . map ( |x| x as u32 )
324- . collect ( ) ;
325- Ok ( bitmap)
326- }
327-
328- /// Build and store the input bitmap for the given block.
329- fn build_and_store_block_input_bitmap ( & self , block : & Block ) -> Result < Bitmap , Error > {
330- // Build the bitmap.
331- let bitmap = self . build_block_input_bitmap ( block) ?;
332-
333- // Save the bitmap to the db (via the batch).
334- self . save_block_input_bitmap ( & block. hash ( ) , & bitmap) ?;
335-
336- Ok ( bitmap)
333+ /// Get the block input bitmap based on our spent index.
334+ /// Fallback to legacy block input bitmap from the db.
335+ pub fn get_block_input_bitmap ( & self , bh : & Hash ) -> Result < Bitmap , Error > {
336+ if let Ok ( spent) = self . get_spent_index ( bh) {
337+ let bitmap = spent
338+ . into_iter ( )
339+ . map ( |x| x. pos . try_into ( ) . unwrap ( ) )
340+ . collect ( ) ;
341+ Ok ( bitmap)
342+ } else {
343+ self . get_legacy_input_bitmap ( bh)
344+ }
337345 }
338346
339- /// Get the block input bitmap from the db or build the bitmap from
340- /// the full block from the db (if the block is found).
341- pub fn get_block_input_bitmap ( & self , bh : & Hash ) -> Result < Bitmap , Error > {
347+ fn get_legacy_input_bitmap ( & self , bh : & Hash ) -> Result < Bitmap , Error > {
342348 if let Ok ( Some ( bytes) ) = self
343349 . db
344350 . get ( & to_key ( BLOCK_INPUT_BITMAP_PREFIX , & mut bh. to_vec ( ) ) )
345351 {
346352 Ok ( Bitmap :: deserialize ( & bytes) )
347353 } else {
348- match self . get_block ( bh) {
349- Ok ( block) => {
350- let bitmap = self . build_and_store_block_input_bitmap ( & block) ?;
351- Ok ( bitmap)
352- }
353- Err ( e) => Err ( e) ,
354- }
354+ Err ( Error :: NotFoundErr ( "legacy block input bitmap" . to_string ( ) ) . into ( ) )
355355 }
356356 }
357357
358+ /// Get the "spent index" from the db for the specified block.
359+ /// If we need to rewind a block then we use this to "unspend" the spent outputs.
360+ pub fn get_spent_index ( & self , bh : & Hash ) -> Result < Vec < CommitPos > , Error > {
361+ option_to_not_found (
362+ self . db
363+ . get_ser ( & to_key ( BLOCK_SPENT_PREFIX , & mut bh. to_vec ( ) ) ) ,
364+ || format ! ( "spent index: {}" , bh) ,
365+ )
366+ }
367+
358368 /// Commits this batch. If it's a child batch, it will be merged with the
359369 /// parent, otherwise the batch is written to db.
360370 pub fn commit ( self ) -> Result < ( ) , Error > {
0 commit comments