consensus: empty slots and offste calculations tunning

This commit is contained in:
aggstam
2022-11-27 15:57:38 +02:00
parent b7f015dfd1
commit 931e1dd3cc
5 changed files with 47 additions and 24 deletions

View File

@@ -193,11 +193,11 @@ impl Blockchain {
}
/// Retrieve last finalized block slot offset
pub fn get_last_offset(&self) -> Result<u64> {
let (_, hash) = self.last().unwrap();
pub fn get_last_offset(&self) -> Result<(u64, u64)> {
let (slot, hash) = self.last().unwrap();
let blocks = self.blocks.get(&[hash], true)?;
// Since we used strict get, its safe to unwrap here
let block = blocks[0].clone().unwrap();
Ok(block.lead_info.offset)
Ok((slot, block.lead_info.offset))
}
}

View File

@@ -64,6 +64,9 @@ pub const EPOCH_LENGTH: usize = 10;
/// Slot time in seconds
pub const SLOT_TIME: u64 = 20;
/// Finalization sync period duration (should be >=1/4 of slot time)
pub const FINAL_SYNC_DUR: u64 = 5;
/// Block leader reward
pub const REWARD: u64 = 420;

View File

@@ -18,7 +18,7 @@
use async_std::sync::Arc;
use async_trait::async_trait;
use log::{debug, error, info};
use log::{debug, error, trace};
use smol::Executor;
use url::Url;
@@ -75,8 +75,8 @@ impl ProtocolProposal {
}
};
info!("ProtocolProposal::handle_receive_proposal(): recv: {}", proposal);
debug!("ProtocolProposal::handle_receive_proposal(): Full proposal: {:?}", proposal);
debug!("ProtocolProposal::handle_receive_proposal(): recv: {}", proposal);
trace!("ProtocolProposal::handle_receive_proposal(): Full proposal: {:?}", proposal);
let proposal_copy = (*proposal).clone();

View File

@@ -432,9 +432,9 @@ impl ValidatorState {
// Generate sigmas
let mut total_stake = self.total_stake(); // Only used for fine-tuning
// at genesis epoch first slot, of absolute index 0,
// the total stake would be 0, to avoid division by zero,
// we asume total stake at first division is GENESIS_TOTAL_STAKE.
// at genesis epoch first slot, of absolute index 0,
// the total stake would be 0, to avoid division by zero,
// we asume total stake at first division is GENESIS_TOTAL_STAKE.
if total_stake == 0 {
total_stake = constants::GENESIS_TOTAL_STAKE;
}
@@ -519,13 +519,14 @@ impl ValidatorState {
/// Auxillary function to receive current slot offset.
/// If offset is None, its setted up as last block slot offset.
fn get_current_offset(&mut self) -> u64 {
fn get_current_offset(&mut self, current_slot: u64) -> u64 {
// This is the case were we restarted our node, didn't receive offset from other nodes,
// so we need to find offset from last block
// so we need to find offset from last block, exluding network dead period.
if self.consensus.offset.is_none() {
let last = self.blockchain.get_last_offset().unwrap();
info!("get_current_offset(): Setting slot offset: {}", last);
self.consensus.offset = Some(last);
let (last_slot, last_offset) = self.blockchain.get_last_offset().unwrap();
let offset = last_offset + (current_slot - last_slot);
info!("get_current_offset(): Setting slot offset: {}", offset);
self.consensus.offset = Some(offset);
}
self.consensus.offset.unwrap()
@@ -545,8 +546,10 @@ impl ValidatorState {
);
self.consensus.offset = Some(current_slot);
}
// Retrieve longest fork length, to also those proposals in the calculation
let max_fork_length = self.longest_chain_length() as u64;
current_slot - blocks - self.get_current_offset()
current_slot - blocks - self.get_current_offset(current_slot) - max_fork_length
}
/// total stake
@@ -617,6 +620,7 @@ impl ValidatorState {
one.clone() / constants::TI.clone() * i.clone() +
constants::TD.clone() * d.clone());
while f <= zero.clone() || f >= one.clone() {
info!("Consensus::win_prob_with_full_stake(): f: {}", f);
let mut clipped_f = f;
if clipped_f >= one {
clipped_f = one.clone() - constants::PID_OUT_STEP.clone();
@@ -632,7 +636,6 @@ impl ValidatorState {
(p.clone() +
one.clone() / constants::TI.clone() * i.clone() +
constants::TD.clone() * d.clone());
info!("Consensus::win_prob_with_full_stake(): f: {}", f);
}
info!("Consensus::win_prob_with_full_stake(): last f: {}", f);
f
@@ -719,7 +722,7 @@ impl ValidatorState {
coin.public_inputs(sigma1, sigma2),
eta.to_repr(),
LeadProof::from(proof),
self.get_current_offset(),
self.get_current_offset(slot),
self.consensus.leaders_history.last().unwrap().clone(),
);
// Replacing old coin with the derived coin
@@ -780,6 +783,18 @@ impl ValidatorState {
Ok((hash, index))
}
/// Finds the length of longest fork chain the node holds.
pub fn longest_chain_length(&self) -> usize {
let mut max = 0;
for proposal in &self.consensus.proposals {
if proposal.proposals.len() > max {
max = proposal.proposals.len();
}
}
max
}
/// Given a proposal, the node verify its sender (slot leader) and finds which blockchain
/// it extends. If the proposal extends the canonical blockchain, a new fork chain is created.
pub async fn receive_proposal(&mut self, proposal: &BlockProposal) -> Result<()> {
@@ -831,7 +846,7 @@ impl ValidatorState {
}
// Verify proposal offset
let offset = self.get_current_offset();
let offset = self.get_current_offset(current);
if offset != lf.offset {
warn!(
"receive_proposal(): Received proposal contains different offset: {} - {}",

View File

@@ -21,18 +21,22 @@ use std::time::Duration;
use log::{debug, error, info};
use super::consensus_sync_task;
use crate::{consensus::ValidatorStatePtr, net::P2pPtr, util::async_util::sleep};
use crate::{
consensus::{constants, ValidatorStatePtr},
net::P2pPtr,
util::async_util::sleep,
};
/// async task used for participating in the consensus protocol
pub async fn proposal_task(consensus_p2p: P2pPtr, sync_p2p: P2pPtr, state: ValidatorStatePtr) {
// Node waits just before the current or next epoch last finalization syncing period, so it can
// start syncing latest state.
let mut seconds_until_next_epoch = state.read().await.next_n_epoch_start(1);
let three_secs = Duration::new(3, 0);
let sync_offset = Duration::new(constants::FINAL_SYNC_DUR + 1, 0);
loop {
if seconds_until_next_epoch > three_secs {
seconds_until_next_epoch -= three_secs;
if seconds_until_next_epoch > sync_offset {
seconds_until_next_epoch -= sync_offset;
break
}
@@ -60,8 +64,9 @@ pub async fn proposal_task(consensus_p2p: P2pPtr, sync_p2p: P2pPtr, state: Valid
loop {
// Node sleeps until finalization sync period start (2 seconds before next slot)
let seconds_sync_period =
(state.read().await.next_n_slot_start(1) - Duration::new(2, 0)).as_secs();
let seconds_sync_period = (state.read().await.next_n_slot_start(1) -
Duration::new(constants::FINAL_SYNC_DUR, 0))
.as_secs();
info!("consensus: Waiting for finalization sync period ({} sec)", seconds_sync_period);
sleep(seconds_sync_period).await;