Bläddra i källkod

consensus: fixed finalization logic

aggstam 3 år sedan
förälder
incheckning
71222f50c5
3 ändrade filer med 30 tillägg och 35 borttagningar
  1. 1 1
      src/consensus/proto/protocol_sync_consensus.rs
  2. 11 1
      src/consensus/state.rs
  3. 18 33
      src/consensus/validator.rs

+ 1 - 1
src/consensus/proto/protocol_sync_consensus.rs

@@ -147,7 +147,7 @@ impl ProtocolSyncConsensus {
             // Extra validations can be added here.
             // Extra validations can be added here.
             let lock = self.state.read().await;
             let lock = self.state.read().await;
             let bootstrap_slot = lock.consensus.bootstrap_slot;
             let bootstrap_slot = lock.consensus.bootstrap_slot;
-            let is_empty = lock.consensus.slot_checkpoints.is_empty();
+            let is_empty = lock.consensus.slot_checkpoints_is_empty();
             let response = ConsensusSlotCheckpointsResponse { bootstrap_slot, is_empty };
             let response = ConsensusSlotCheckpointsResponse { bootstrap_slot, is_empty };
             if let Err(e) = self.channel.send(response).await {
             if let Err(e) = self.channel.send(response).await {
                 error!(
                 error!(

+ 11 - 1
src/consensus/state.rs

@@ -595,7 +595,6 @@ impl ConsensusState {
                 }
                 }
             }
             }
         }
         }
-        //self.leaders_history.push(0);
     }
     }
 
 
     /// Utility function to extract leader selection lottery randomness(eta),
     /// Utility function to extract leader selection lottery randomness(eta),
@@ -628,6 +627,17 @@ impl ConsensusState {
         Err(Error::SlotCheckpointNotFound(slot))
         Err(Error::SlotCheckpointNotFound(slot))
     }
     }
 
 
+    /// Auxillary function to check if node has seen current or previous slot checkpoints.
+    /// This check ensures that either the slots exist in memory or node has seen the finalization of these slots.
+    pub fn slot_checkpoints_is_empty(&self) -> bool {
+        let current_slot = self.current_slot();
+        if self.get_slot_checkpoint(current_slot).is_ok() {
+            return false
+        }
+        let previous_slot = current_slot - 1;
+        !self.get_slot_checkpoint(previous_slot).is_ok()
+    }
+
     /// Auxillary function to update all fork state checkpoints to nodes coins current canonical states.
     /// Auxillary function to update all fork state checkpoints to nodes coins current canonical states.
     /// Note: This function should only be invoked once on nodes' coins creation.
     /// Note: This function should only be invoked once on nodes' coins creation.
     pub fn update_forks_checkpoints(&mut self) {
     pub fn update_forks_checkpoints(&mut self) {

+ 18 - 33
src/consensus/validator.rs

@@ -588,11 +588,10 @@ impl ValidatorState {
 
 
     /// Node checks if any of the fork chains can be finalized.
     /// Node checks if any of the fork chains can be finalized.
     /// Consensus finalization logic:
     /// Consensus finalization logic:
-    /// - If the node has observed the creation of 3 proposals in a fork chain and no other
-    ///   forks exists at same or greater height, it finalizes (appends to canonical blockchain)
-    ///   all proposals up to the last one.
+    /// - If the node has observed the creation of a fork chain and no other forks exists at same or greater height,
+    ///   it finalizes (appends to canonical blockchain) all proposals in that fork chain.
     /// When fork chain proposals are finalized, the rest of fork chains are removed and all
     /// When fork chain proposals are finalized, the rest of fork chains are removed and all
-    /// slot checkpoints until current slot are apppended to canonical state.
+    /// slot checkpoints are apppended to canonical state.
     pub async fn chain_finalization(&mut self) -> Result<(Vec<BlockInfo>, Vec<SlotCheckpoint>)> {
     pub async fn chain_finalization(&mut self) -> Result<(Vec<BlockInfo>, Vec<SlotCheckpoint>)> {
         let slot = self.consensus.current_slot();
         let slot = self.consensus.current_slot();
         info!(target: "consensus::validator", "chain_finalization(): Started finalization check for slot: {}", slot);
         info!(target: "consensus::validator", "chain_finalization(): Started finalization check for slot: {}", slot);
@@ -600,7 +599,7 @@ impl ValidatorState {
         self.consensus.checked_finalization = slot;
         self.consensus.checked_finalization = slot;
 
 
         // First we find longest fork without any other forks at same height
         // First we find longest fork without any other forks at same height
-        let mut fork_index = 0;
+        let mut fork_index = -1;
         // Use this index to extract leaders count sequence from longest fork
         // Use this index to extract leaders count sequence from longest fork
         let mut index_for_history = -1;
         let mut index_for_history = -1;
         let mut max_length_for_history = 0;
         let mut max_length_for_history = 0;
@@ -635,32 +634,27 @@ impl ValidatorState {
                 self.consensus.set_leader_history(index_for_history, slot);
                 self.consensus.set_leader_history(index_for_history, slot);
                 return Ok((vec![], vec![]))
                 return Ok((vec![], vec![]))
             }
             }
+            -1 => {
+                info!(target: "consensus::validator", "chain_finalization(): Nothing to finalize.");
+            }
             _ => {
             _ => {
                 info!(target: "consensus::validator", "chain_finalization(): Chain {} can be finalized!", fork_index)
                 info!(target: "consensus::validator", "chain_finalization(): Chain {} can be finalized!", fork_index)
             }
             }
         }
         }
-        if max_length == 0 {
-            return Ok((vec![], vec![]))
-        }
+
         if max_length == 0 {
         if max_length == 0 {
             return Ok((vec![], vec![]))
             return Ok((vec![], vec![]))
         }
         }
 
 
         // Starting finalization
         // Starting finalization
-        let mut fork = self.consensus.forks[fork_index as usize].clone();
+        let fork = self.consensus.forks[fork_index as usize].clone();
 
 
         // Retrieving proposals to finalize
         // Retrieving proposals to finalize
-        let bound = max_length - 1;
         let mut finalized: Vec<BlockInfo> = vec![];
         let mut finalized: Vec<BlockInfo> = vec![];
-        let mut last_state_checkpoint = fork.sequence.first().unwrap().clone();
-        for state_checkpoint in &fork.sequence[..bound] {
+        for state_checkpoint in &fork.sequence {
             finalized.push(state_checkpoint.proposal.clone().into());
             finalized.push(state_checkpoint.proposal.clone().into());
-            last_state_checkpoint = state_checkpoint.clone();
         }
         }
 
 
-        // Removing finalized proposals state checkpoins from fork
-        fork.sequence.drain(..bound);
-
         // Adding finalized proposals to canonical
         // Adding finalized proposals to canonical
         info!(target: "consensus::validator", "consensus: Adding {} finalized block to canonical chain.", finalized.len());
         info!(target: "consensus::validator", "consensus: Adding {} finalized block to canonical chain.", finalized.len());
         match self.blockchain.add(&finalized) {
         match self.blockchain.add(&finalized) {
@@ -699,12 +693,9 @@ impl ValidatorState {
         }
         }
 
 
         // Setting leaders history to last proposal leaders count
         // Setting leaders history to last proposal leaders count
+        let last_state_checkpoint = fork.sequence.last().unwrap().clone();
         self.consensus.leaders_history =
         self.consensus.leaders_history =
-            vec![fork.sequence.last().unwrap().proposal.block.lead_info.leaders];
-
-        // Removing rest forks
-        self.consensus.forks = vec![];
-        self.consensus.forks.push(fork);
+            vec![last_state_checkpoint.proposal.block.lead_info.leaders];
 
 
         // Setting canonical states from last finalized checkpoint
         // Setting canonical states from last finalized checkpoint
         self.consensus.coins = last_state_checkpoint.coins;
         self.consensus.coins = last_state_checkpoint.coins;
@@ -712,18 +703,8 @@ impl ValidatorState {
         self.consensus.nullifiers = last_state_checkpoint.nullifiers;
         self.consensus.nullifiers = last_state_checkpoint.nullifiers;
 
 
         // Adding finalized slot checkpoints to canonical
         // Adding finalized slot checkpoints to canonical
-        let mut bound = 0;
-        let mut finalized_slot_checkpoints: Vec<SlotCheckpoint> = vec![];
-        for (index, slot_checkpoint) in self.consensus.slot_checkpoints.iter().enumerate() {
-            if slot_checkpoint.slot >= slot {
-                break
-            }
-            bound = index;
-            finalized_slot_checkpoints.push(slot_checkpoint.clone());
-        }
-
-        // Removing finalized proposals from chain
-        self.consensus.slot_checkpoints.drain(..bound);
+        let finalized_slot_checkpoints: Vec<SlotCheckpoint> =
+            self.consensus.slot_checkpoints.clone();
 
 
         debug!(
         debug!(
             target: "consensus::validator",
             target: "consensus::validator",
@@ -742,6 +723,10 @@ impl ValidatorState {
             }
             }
         };
         };
 
 
+        // Resetting forks and slot checkpoints
+        self.consensus.forks = vec![];
+        self.consensus.slot_checkpoints = vec![];
+
         Ok((finalized, finalized_slot_checkpoints))
         Ok((finalized, finalized_slot_checkpoints))
     }
     }