validator/consensus: finalization check added

This commit is contained in:
aggstam
2023-08-10 19:58:17 +03:00
parent 80ffd5afd6
commit ff581982be

View File

@@ -22,7 +22,7 @@ use darkfi_sdk::{
pasta::{group::ff::PrimeField, pallas},
};
use darkfi_serial::{serialize, SerialDecodable, SerialEncodable};
use log::{error, warn};
use log::{error, info, warn};
use rand::rngs::OsRng;
use crate::{
@@ -163,8 +163,7 @@ impl Consensus {
// TODO: sign more stuff?
// Sign block header using provided secret key
let signature =
SecretKey::from(secret_key).sign(&mut OsRng, &header.headerhash().as_bytes()[..]);
let signature = secret_key.sign(&mut OsRng, &header.headerhash().as_bytes()[..]);
// Generate block producer info
let block_producer = BlockProducer::new(signature, proposal_tx, slot.last_eta);
@@ -369,6 +368,65 @@ impl Consensus {
Ok((fork, None))
}
/// Node checks if any of the forks can be finalized.
/// Consensus finalization logic:
/// - If the node has observed the creation of a fork and no other forks exists at same or greater height,
/// all proposals in that fork can be finalized (append to canonical blockchain).
/// When a fork can be finalized, blocks(proposals) should be appended to canonical,
/// and forks should be removed.
pub async fn forks_finalization(&mut self) -> Result<Vec<BlockInfo>> {
let slot = self.time_keeper.current_slot();
info!(target: "validator::consensus::forks_finalization", "Started finalization check for slot: {}", slot);
// Set last slot finalization check occured to current slot
self.checked_finalization = slot;
// First we find longest fork without any other forks at same height
let mut fork_index = -1;
let mut max_length = 0;
for (index, fork) in self.forks.iter().enumerate() {
let length = fork.proposals.len();
// Check if less than max
if length < max_length {
continue
}
// Check if same length as max
if length == max_length {
// Setting fork_index so we know we have multiple
// forks at same length.
fork_index = -2;
continue
}
// Set fork as max
fork_index = index as i64;
max_length = length;
}
// Check if we found any fork to finalize
match fork_index {
-2 => {
info!(target: "validator::consensus::forks_finalization", "Eligible forks with same height exist, nothing to finalize.");
return Ok(vec![])
}
-1 => {
info!(target: "validator::consensus::forks_finalization", "Nothing to finalize.");
}
_ => {
info!(target: "validator::consensus::forks_finalization", "Fork {} can be finalized!", fork_index)
}
}
if max_length == 0 {
return Ok(vec![])
}
// Starting finalization
let fork = &self.forks[fork_index as usize];
let finalized = fork.overlay.lock().unwrap().get_blocks_by_hash(&fork.proposals)?;
info!(target: "validator::consensus::forks_finalization", "Finalized blocks: {}", finalized.len());
Ok(finalized)
}
}
/// This struct represents a block proposal, used for consensus.
@@ -436,7 +494,7 @@ impl Fork {
let hash = if self.proposals.is_empty() {
self.overlay.lock().unwrap().last_block()?.blockhash()
} else {
self.proposals.last().unwrap().clone()
*self.proposals.last().unwrap()
};
// Read first 240 bits
@@ -479,7 +537,7 @@ impl Fork {
let overlay = self.overlay.lock().unwrap().full_clone()?;
// Verify transactions
let erroneous_txs = verify_transactions(&overlay, &time_keeper, &unproposed_txs).await?;
let erroneous_txs = verify_transactions(&overlay, time_keeper, &unproposed_txs).await?;
if !erroneous_txs.is_empty() {
unproposed_txs.retain(|x| !erroneous_txs.contains(x));
}