Просмотр исходного кода

blockchain: store block inverse diff instead of actual one

skoupidi 1 год назад
Родитель
Сommit
c5395206d0
5 измененных файлов с 76 добавлено и 62 удалено
  1. 5 4
      bin/darkfid/src/task/unknown_proposal.rs
  2. 40 36
      src/blockchain/block_store.rs
  3. 7 6
      src/blockchain/mod.rs
  4. 2 2
      src/error.rs
  5. 22 14
      src/validator/mod.rs

+ 5 - 4
bin/darkfid/src/task/unknown_proposal.rs

@@ -367,10 +367,11 @@ async fn handle_reorg(
     peer_fork.targets_rank = last_difficulty.ranks.targets_rank.clone();
     peer_fork.hashes_rank = last_difficulty.ranks.hashes_rank.clone();
 
-    // Grab all state diffs after last common height and add their inverse to the fork
-    let diffs = validator.blockchain.blocks.get_state_diffs_after(last_common_height)?;
-    for diff in diffs.iter().rev() {
-        peer_fork.overlay.lock().unwrap().overlay.lock().unwrap().add_diff(&diff.inverse())?;
+    // Grab all state inverse diffs after last common height, and add them to the fork
+    let inverse_diffs =
+        validator.blockchain.blocks.get_state_inverse_diffs_after(last_common_height)?;
+    for inverse_diff in inverse_diffs.iter().rev() {
+        peer_fork.overlay.lock().unwrap().overlay.lock().unwrap().add_diff(inverse_diff)?;
     }
 
     // Retrieve the proposals of the hashes sequence, in batches

+ 40 - 36
src/blockchain/block_store.rs

@@ -238,7 +238,7 @@ impl BlockDifficulty {
 pub const SLED_BLOCK_TREE: &[u8] = b"_blocks";
 pub const SLED_BLOCK_ORDER_TREE: &[u8] = b"_block_order";
 pub const SLED_BLOCK_DIFFICULTY_TREE: &[u8] = b"_block_difficulty";
-pub const SLED_BLOCK_STATE_DIFF_TREE: &[u8] = b"_block_state_diff";
+pub const SLED_BLOCK_STATE_INVERSE_DIFF_TREE: &[u8] = b"_block_state_inverse_diff";
 
 /// The `BlockStore` is a structure representing all `sled` trees related
 /// to storing the blockchain's blocks information.
@@ -255,10 +255,10 @@ pub struct BlockStore {
     /// blockchain's blocks, where the key is the block height number,
     /// and the value is the blocks' hash.
     pub difficulty: sled::Tree,
-    /// The `sled` tree storing each blocks' full database state changes,
-    /// where the key is the block height number, and the value is the
-    /// serialized database diff.
-    pub state_diff: sled::Tree,
+    /// The `sled` tree storing each blocks' full database state inverse
+    /// changes, where the key is the block height number, and the value
+    /// is the serialized database inverse diff.
+    pub state_inverse_diff: sled::Tree,
 }
 
 impl BlockStore {
@@ -267,8 +267,8 @@ impl BlockStore {
         let main = db.open_tree(SLED_BLOCK_TREE)?;
         let order = db.open_tree(SLED_BLOCK_ORDER_TREE)?;
         let difficulty = db.open_tree(SLED_BLOCK_DIFFICULTY_TREE)?;
-        let state_diff = db.open_tree(SLED_BLOCK_STATE_DIFF_TREE)?;
-        Ok(Self { main, order, difficulty, state_diff })
+        let state_inverse_diff = db.open_tree(SLED_BLOCK_STATE_INVERSE_DIFF_TREE)?;
+        Ok(Self { main, order, difficulty, state_inverse_diff })
     }
 
     /// Insert a slice of [`Block`] into the store's main tree.
@@ -294,15 +294,15 @@ impl BlockStore {
         Ok(())
     }
 
-    /// Insert a slice of `u32` and block diffs into the store's
-    /// database diffs tree.
-    pub fn insert_state_diff(
+    /// Insert a slice of `u32` and block inverse diffs into the
+    /// store's database inverse diffs tree.
+    pub fn insert_state_inverse_diff(
         &self,
         heights: &[u32],
         diffs: &[SledDbOverlayStateDiff],
     ) -> Result<()> {
-        let batch = self.insert_batch_state_diff(heights, diffs);
-        self.state_diff.apply_batch(batch)?;
+        let batch = self.insert_batch_state_inverse_diff(heights, diffs);
+        self.state_inverse_diff.apply_batch(batch)?;
         Ok(())
     }
 
@@ -351,11 +351,11 @@ impl BlockStore {
         batch
     }
 
-    /// Generate the sled batch corresponding to an insert to the database diffs
-    /// tree, so caller can handle the write operation.
-    /// The block height is used as the key, and the serialized database diff is
-    /// used as value.
-    pub fn insert_batch_state_diff(
+    /// Generate the sled batch corresponding to an insert to the database
+    /// inverse diffs tree, so caller can handle the write operation.
+    /// The block height is used as the key, and the serialized database
+    /// inverse diff is used as value.
+    pub fn insert_batch_state_inverse_diff(
         &self,
         heights: &[u32],
         diffs: &[SledDbOverlayStateDiff],
@@ -453,13 +453,13 @@ impl BlockStore {
         Ok(ret)
     }
 
-    /// Fetch given block height numbers from the store's state diffs tree.
-    /// The resulting vector contains `Option`, which is `Some` if the block
-    /// height number was found in the block database diffs store, and otherwise
-    /// it is `None`, if it has not.
-    /// The second parameter is a boolean which tells the function to fail in
-    /// case at least one block height number was not found.
-    pub fn get_state_diff(
+    /// Fetch given block height numbers from the store's state inverse
+    /// diffs tree. The resulting vector contains `Option`, which is
+    /// `Some` if the block height number was found in the block database
+    /// inverse diffs store, and otherwise it is `None`, if it has not.
+    /// The second parameter is a boolean which tells the function to fail
+    /// in case at least one block height number was not found.
+    pub fn get_state_inverse_diff(
         &self,
         heights: &[u32],
         strict: bool,
@@ -467,13 +467,13 @@ impl BlockStore {
         let mut ret = Vec::with_capacity(heights.len());
 
         for height in heights {
-            if let Some(found) = self.state_diff.get(height.to_be_bytes())? {
-                let state_diff = deserialize(&found)?;
-                ret.push(Some(state_diff));
+            if let Some(found) = self.state_inverse_diff.get(height.to_be_bytes())? {
+                let state_inverse_diff = deserialize(&found)?;
+                ret.push(Some(state_inverse_diff));
                 continue
             }
             if strict {
-                return Err(Error::BlockStateDiffNotFound(*height))
+                return Err(Error::BlockStateInverseDiffNotFound(*height))
             }
             ret.push(None);
         }
@@ -663,17 +663,21 @@ impl BlockStore {
         Ok(ret)
     }
 
-    /// Fetch all state diffs after given height. In the iteration, if a state
-    /// diff is not found, the iteration stops and the function returns what
-    /// it has found so far in the store's state diffs tree.
-    pub fn get_state_diffs_after(&self, height: u32) -> Result<Vec<SledDbOverlayStateDiff>> {
+    /// Fetch all state inverse diffs after given height. In the iteration,
+    /// if a state inverse diff is not found, the iteration stops and the
+    /// function returns what it has found so far in the store's state
+    /// inverse diffs tree.
+    pub fn get_state_inverse_diffs_after(
+        &self,
+        height: u32,
+    ) -> Result<Vec<SledDbOverlayStateDiff>> {
         let mut ret = vec![];
 
         let mut key = height;
-        while let Some(found) = self.state_diff.get_gt(key.to_be_bytes())? {
-            let (height, state_diff) = parse_u32_key_record(found)?;
+        while let Some(found) = self.state_inverse_diff.get_gt(key.to_be_bytes())? {
+            let (height, state_inverse_diff) = parse_u32_key_record(found)?;
             key = height;
-            ret.push(state_diff);
+            ret.push(state_inverse_diff);
         }
 
         Ok(ret)
@@ -698,7 +702,7 @@ impl BlockStoreOverlay {
         overlay.lock().unwrap().open_tree(SLED_BLOCK_TREE, true)?;
         overlay.lock().unwrap().open_tree(SLED_BLOCK_ORDER_TREE, true)?;
         overlay.lock().unwrap().open_tree(SLED_BLOCK_DIFFICULTY_TREE, true)?;
-        overlay.lock().unwrap().open_tree(SLED_BLOCK_STATE_DIFF_TREE, true)?;
+        overlay.lock().unwrap().open_tree(SLED_BLOCK_STATE_INVERSE_DIFF_TREE, true)?;
         Ok(Self(overlay.clone()))
     }
 

+ 7 - 6
src/blockchain/mod.rs

@@ -28,7 +28,7 @@ use crate::{tx::Transaction, util::time::Timestamp, Error, Result};
 pub mod block_store;
 pub use block_store::{
     Block, BlockDifficulty, BlockInfo, BlockStore, BlockStoreOverlay, SLED_BLOCK_DIFFICULTY_TREE,
-    SLED_BLOCK_ORDER_TREE, SLED_BLOCK_STATE_DIFF_TREE, SLED_BLOCK_TREE,
+    SLED_BLOCK_ORDER_TREE, SLED_BLOCK_STATE_INVERSE_DIFF_TREE, SLED_BLOCK_TREE,
 };
 
 /// Header definition and storage implementation
@@ -366,9 +366,10 @@ impl Blockchain {
             return Ok(())
         }
 
-        // Grab all state diffs until requested height going backwards
+        // Grab all state inverse diffs until requested height,
+        // going backwards.
         let heights: Vec<u32> = (height + 1..=last).rev().collect();
-        let diffs = self.blocks.get_state_diff(&heights, true)?;
+        let inverse_diffs = self.blocks.get_state_inverse_diff(&heights, true)?;
 
         // Create an overlay to apply the reverse diffs
         let overlay = BlockchainOverlay::new(self)?;
@@ -376,9 +377,9 @@ impl Blockchain {
         // Apply the inverse diffs sequence
         let overlay_lock = overlay.lock().unwrap();
         let mut lock = overlay_lock.overlay.lock().unwrap();
-        for diff in diffs {
+        for inverse_diff in inverse_diffs {
             // Since we used strict retrieval it's safe to unwrap here
-            let inverse_diff = diff.unwrap().inverse();
+            let inverse_diff = inverse_diff.unwrap();
             lock.add_diff(&inverse_diff)?;
             lock.apply_diff(&inverse_diff)?;
             self.sled_db.flush()?;
@@ -418,7 +419,7 @@ impl BlockchainOverlay {
             SLED_BLOCK_TREE,
             SLED_BLOCK_ORDER_TREE,
             SLED_BLOCK_DIFFICULTY_TREE,
-            SLED_BLOCK_STATE_DIFF_TREE,
+            SLED_BLOCK_STATE_INVERSE_DIFF_TREE,
             SLED_HEADER_TREE,
             SLED_SYNC_HEADER_TREE,
             SLED_TX_TREE,

+ 2 - 2
src/error.rs

@@ -368,8 +368,8 @@ pub enum Error {
     #[error("Block difficulty for height number {0} not found in database")]
     BlockDifficultyNotFound(u32),
 
-    #[error("Block state diff for height number {0} not found in database")]
-    BlockStateDiffNotFound(u32),
+    #[error("Block state inverse diff for height number {0} not found in database")]
+    BlockStateInverseDiffNotFound(u32),
 
     #[error("Block {0} contains 0 transactions")]
     BlockContainsNoTransactions(String),

+ 22 - 14
src/validator/mod.rs

@@ -379,8 +379,8 @@ impl Validator {
         // Apply confirmed proposals diffs and update PoW module
         let mut module = self.consensus.module.write().await;
         let mut confirmed_txs = vec![];
-        let mut state_diffs_heights = vec![];
-        let mut state_diffs = vec![];
+        let mut state_inverse_diffs_heights = vec![];
+        let mut state_inverse_diffs = vec![];
         info!(target: "validator::confirmation", "Confirming proposals:");
         for (index, proposal) in confirmed_proposals.iter().enumerate() {
             info!(target: "validator::confirmation", "\t{} - {}", proposal, confirmed_blocks[index].header.height);
@@ -388,14 +388,16 @@ impl Validator {
             let next_difficulty = module.next_difficulty()?;
             module.append(confirmed_blocks[index].header.timestamp, &next_difficulty);
             confirmed_txs.extend_from_slice(&confirmed_blocks[index].txs);
-            state_diffs_heights.push(confirmed_blocks[index].header.height);
-            state_diffs.push(diffs[index].clone());
+            state_inverse_diffs_heights.push(confirmed_blocks[index].header.height);
+            state_inverse_diffs.push(diffs[index].inverse());
         }
         drop(module);
         drop(forks);
 
-        // Store the block diffs
-        self.blockchain.blocks.insert_state_diff(&state_diffs_heights, &state_diffs)?;
+        // Store the block inverse diffs
+        self.blockchain
+            .blocks
+            .insert_state_inverse_diff(&state_inverse_diffs_heights, &state_inverse_diffs)?;
 
         // Reset forks starting with the confirmed blocks
         self.consensus.reset_forks(&confirmed_proposals, &confirmed_fork, &confirmed_txs).await?;
@@ -438,9 +440,10 @@ impl Validator {
         // Keep track of all blocks transactions to remove them from pending txs store
         let mut removed_txs = vec![];
 
-        // Keep track of all block database state diffs
+        // Keep track of all block database state diffs and their inverse
         let mut diffs_heights = vec![];
         let mut diffs = vec![];
+        let mut inverse_diffs = vec![];
 
         // Validate and insert each block
         for (index, block) in blocks.iter().enumerate() {
@@ -489,16 +492,18 @@ impl Validator {
                 removed_txs.push(tx.clone());
             }
 
-            // Store block database state diff
+            // Store block database state diff and its inverse
             diffs_heights.push(block.header.height);
-            diffs.push(overlay.lock().unwrap().overlay.lock().unwrap().diff(&diffs)?);
+            let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(&diffs)?;
+            inverse_diffs.push(diff.inverse());
+            diffs.push(diff);
         }
 
         debug!(target: "validator::add_checkpoint_blocks", "Applying overlay changes");
         overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
 
         // Store the block diffs
-        self.blockchain.blocks.insert_state_diff(&diffs_heights, &diffs)?;
+        self.blockchain.blocks.insert_state_inverse_diff(&diffs_heights, &inverse_diffs)?;
 
         // Remove blocks transactions from pending txs store
         self.blockchain.remove_pending_txs(&removed_txs)?;
@@ -534,9 +539,10 @@ impl Validator {
         // Keep track of all blocks transactions to remove them from pending txs store
         let mut removed_txs = vec![];
 
-        // Keep track of all block database state diffs
+        // Keep track of all block database state diffs and their inverse
         let mut diffs_heights = vec![];
         let mut diffs = vec![];
+        let mut inverse_diffs = vec![];
 
         // Validate and insert each block
         for block in blocks {
@@ -588,9 +594,11 @@ impl Validator {
                 removed_txs.push(tx.clone());
             }
 
-            // Store block database state diff
+            // Store block database state diff and its inverse
             diffs_heights.push(block.header.height);
-            diffs.push(overlay.lock().unwrap().overlay.lock().unwrap().diff(&diffs)?);
+            let diff = overlay.lock().unwrap().overlay.lock().unwrap().diff(&diffs)?;
+            inverse_diffs.push(diff.inverse());
+            diffs.push(diff);
 
             // Use last inserted block as next iteration previous
             previous = block;
@@ -600,7 +608,7 @@ impl Validator {
         overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
 
         // Store the block diffs
-        self.blockchain.blocks.insert_state_diff(&diffs_heights, &diffs)?;
+        self.blockchain.blocks.insert_state_inverse_diff(&diffs_heights, &inverse_diffs)?;
 
         // Purge pending erroneous txs since canonical state has been changed
         self.blockchain.remove_pending_txs(&removed_txs)?;