Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always Propose when empty_block_timeout is reached and remove redundant proposal conditions #1706

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions z2/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ use zilliqa::{
self, allowed_timestamp_skew_default, block_request_batch_size_default,
block_request_limit_default, consensus_timeout_default, empty_block_timeout_default,
eth_chain_id_default, failed_request_sleep_duration_default, local_address_default,
max_blocks_in_flight_default, minimum_time_left_for_empty_block_default,
scilla_address_default, scilla_ext_libs_path_default, scilla_stdlib_dir_default,
state_rpc_limit_default, total_native_token_supply_default, Amount, ApiServer,
ConsensusConfig, GenesisDeposit,
max_blocks_in_flight_default, scilla_address_default, scilla_ext_libs_path_default,
scilla_stdlib_dir_default, state_rpc_limit_default, total_native_token_supply_default,
Amount, ApiServer, ConsensusConfig, GenesisDeposit,
},
transaction::EvmGas,
};
Expand Down Expand Up @@ -521,7 +520,6 @@ impl Setup {
scilla_address: scilla_address_default(),
scilla_stdlib_dir: scilla_stdlib_dir_default(),
scilla_ext_libs_path: scilla_ext_libs_path_default(),
minimum_time_left_for_empty_block: minimum_time_left_for_empty_block_default(),
main_shard_id: None,
local_address: local_address_default(),
consensus_timeout: consensus_timeout_default(),
Expand Down
9 changes: 0 additions & 9 deletions zilliqa/src/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,6 @@ pub struct ConsensusConfig {
/// Minimum time to wait for consensus to propose new block if there are no transactions. This therefore acts also as the minimum block time.
#[serde(default = "empty_block_timeout_default")]
pub empty_block_timeout: Duration,
/// Minimum remaining time before end of round in which Proposer has the opportunity to broadcast empty block proposal.
/// If there is less time than this value left in a round then the view will likely move on before a proposal has time to be finalised.
#[serde(default = "minimum_time_left_for_empty_block_default")]
pub minimum_time_left_for_empty_block: Duration,
/// Address of the Scilla server. Defaults to "http://localhost:3000".
#[serde(default = "scilla_address_default")]
pub scilla_address: String,
Expand Down Expand Up @@ -349,7 +345,6 @@ impl Default for ConsensusConfig {
genesis_deposits: vec![],
genesis_accounts: vec![],
empty_block_timeout: empty_block_timeout_default(),
minimum_time_left_for_empty_block: minimum_time_left_for_empty_block_default(),
scilla_address: scilla_address_default(),
scilla_stdlib_dir: scilla_stdlib_dir_default(),
scilla_ext_libs_path: scilla_ext_libs_path_default(),
Expand Down Expand Up @@ -385,10 +380,6 @@ pub fn empty_block_timeout_default() -> Duration {
Duration::from_millis(1000)
}

pub fn minimum_time_left_for_empty_block_default() -> Duration {
Duration::from_millis(3000)
}

pub fn scilla_address_default() -> String {
String::from("http://localhost:3000")
}
Expand Down
88 changes: 24 additions & 64 deletions zilliqa/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,29 +493,16 @@ impl Consensus {
return Ok(None);
}

let (
time_since_last_view_change,
exponential_backoff_timeout,
minimum_time_left_for_empty_block,
) = self.get_consensus_timeout_params()?;
let (time_since_last_view_change, exponential_backoff_timeout, empty_block_timeout) =
self.get_consensus_timeout_params()?;

trace!(
"timeout reached create_next_block_on_timeout: {}",
self.create_next_block_on_timeout
);
if self.create_next_block_on_timeout {
let empty_block_timeout_ms =
self.config.consensus.empty_block_timeout.as_millis() as u64;

let has_txns_for_next_block = self.transaction_pool.has_txn_ready();

// Check if enough time elapsed or there's something in mempool or we don't have enough
// time but let's try at least until new view can happen
if time_since_last_view_change > empty_block_timeout_ms
|| has_txns_for_next_block
|| (time_since_last_view_change + minimum_time_left_for_empty_block
>= exponential_backoff_timeout)
{
// Check if enough time elapsed to propose block
if time_since_last_view_change > empty_block_timeout {
if let Ok(Some((block, transactions))) = self.propose_new_block() {
self.create_next_block_on_timeout = false;
return Ok(Some((
Expand All @@ -524,19 +511,15 @@ impl Consensus {
)));
};
} else {
self.reset_timeout.send(
self.config
.consensus
.empty_block_timeout
.saturating_sub(Duration::from_millis(time_since_last_view_change)),
)?;
self.reset_timeout.send(Duration::from_millis(
empty_block_timeout.saturating_sub(time_since_last_view_change),
))?;
return Ok(None);
}
}

// Now consider whether we want to timeout - the timeout duration doubles every time, so it
// Should eventually have all nodes on the same view

if time_since_last_view_change < exponential_backoff_timeout {
trace!(
"Not proceeding with view change. Current view: {} - time since last: {}, timeout requires: {}",
Expand Down Expand Up @@ -594,28 +577,24 @@ impl Consensus {
}

fn get_consensus_timeout_params(&self) -> Result<(u64, u64, u64)> {
let consensus_timeout_ms = self.config.consensus.consensus_timeout.as_millis() as u64;
let time_since_last_view_change = SystemTime::now()
.duration_since(self.view_updated_at)
.unwrap_or_default()
.as_millis() as u64;
let exponential_backoff_timeout = self.exponential_backoff_timeout(self.get_view()?);

let minimum_time_left_for_empty_block = self
.config
.consensus
.minimum_time_left_for_empty_block
.as_millis() as u64;
let empty_block_timeout = self.config.consensus.empty_block_timeout.as_millis() as u64;

trace!(
time_since_last_view_change,
exponential_backoff_timeout,
minimum_time_left_for_empty_block,
empty_block_timeout
);

Ok((
time_since_last_view_change,
exponential_backoff_timeout,
minimum_time_left_for_empty_block,
empty_block_timeout,
))
}

Expand Down Expand Up @@ -1366,22 +1345,13 @@ impl Consensus {
// Assemble new block with whatever is in the mempool
while let Some(tx) = self.transaction_pool.best_transaction(&state)? {
// First - check if we have time left to process txns and give enough time for block propagation
let (
time_since_last_view_change,
exponential_backoff_timeout,
minimum_time_left_for_empty_block,
) = self.get_consensus_timeout_params()?;
let (time_since_last_view_change, _, empty_block_timeout) =
self.get_consensus_timeout_params()?;

if time_since_last_view_change + minimum_time_left_for_empty_block
>= exponential_backoff_timeout
{
if time_since_last_view_change > empty_block_timeout {
debug!(
time_since_last_view_change,
exponential_backoff_timeout,
minimum_time_left_for_empty_block,
"timeout proposal {} for view {}",
proposal.header.number,
proposal.header.view,
"timeout proposal {} for view {}", proposal.header.number, proposal.header.view,
);
// don't have time
break;
Expand Down Expand Up @@ -1486,15 +1456,10 @@ impl Consensus {
/// Either propose now or set timeout to allow for txs to come in.
fn ready_for_block_proposal(&mut self) -> Result<Option<(Block, Vec<VerifiedTransaction>)>> {
// Check if there's enough time to wait on a timeout and then propagate an empty block in the network before other participants trigger NewView
let (
time_since_last_view_change,
exponential_backoff_timeout,
minimum_time_left_for_empty_block,
) = self.get_consensus_timeout_params()?;
let (time_since_last_view_change, _, empty_block_timeout) =
self.get_consensus_timeout_params()?;

if time_since_last_view_change + minimum_time_left_for_empty_block
>= exponential_backoff_timeout
{
if time_since_last_view_change > empty_block_timeout {
return self.propose_new_block();
}

Expand Down Expand Up @@ -1564,15 +1529,10 @@ impl Consensus {

for txn in pending.into_iter() {
// First - check for time
let (
time_since_last_view_change,
exponential_backoff_timeout,
minimum_time_left_for_empty_block,
) = self.get_consensus_timeout_params()?;
let (time_since_last_view_change, _, empty_block_timeout) =
self.get_consensus_timeout_params()?;

if time_since_last_view_change + minimum_time_left_for_empty_block
>= exponential_backoff_timeout
{
if time_since_last_view_change > empty_block_timeout {
break;
}

Expand Down Expand Up @@ -2567,9 +2527,9 @@ impl Consensus {
/// Calculate how long we should wait before timing out for this view
pub fn exponential_backoff_timeout(&self, view: u64) -> u64 {
let view_difference = view.saturating_sub(self.high_qc.view);
// in view N our highQC is the one we obtained in view N-1 (or before) and its view is N-2 (or lower)
// in other words, the current view is always at least 2 views ahead of the highQC's view
// i.e. to get `consensus_timeout_ms * 2^0` we have to subtract 2 from `view_difference`
// In view N our highQC is the one we obtained in view N-1 (or before) and its view is N-2 (or lower)
// in other words, the current view is always at least 2 views ahead of the highQC's view.
// Therefore to get `consensus_timeout_ms * 2^0` we have to subtract 2 from `view_difference`
let consensus_timeout = self.config.consensus.consensus_timeout.as_millis() as u64;
consensus_timeout * 2u64.pow((view_difference as u32).saturating_sub(2))
}
Expand Down
10 changes: 4 additions & 6 deletions zilliqa/tests/it/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ use zilliqa::{
cfg::{
allowed_timestamp_skew_default, block_request_batch_size_default,
block_request_limit_default, eth_chain_id_default, failed_request_sleep_duration_default,
max_blocks_in_flight_default, minimum_time_left_for_empty_block_default,
scilla_address_default, scilla_ext_libs_path_default, scilla_stdlib_dir_default,
state_cache_size_default, state_rpc_limit_default, total_native_token_supply_default,
Amount, ApiServer, Checkpoint, ConsensusConfig, GenesisDeposit, NodeConfig,
max_blocks_in_flight_default, scilla_address_default, scilla_ext_libs_path_default,
scilla_stdlib_dir_default, state_cache_size_default, state_rpc_limit_default,
total_native_token_supply_default, Amount, ApiServer, Checkpoint, ConsensusConfig,
GenesisDeposit, NodeConfig,
},
crypto::{SecretKey, TransactionPublicKey},
db,
Expand Down Expand Up @@ -321,7 +321,6 @@ impl Network {
genesis_deposits: genesis_deposits.clone(),
is_main: send_to_parent.is_none(),
consensus_timeout: Duration::from_secs(5),
minimum_time_left_for_empty_block: minimum_time_left_for_empty_block_default(),
// Give a genesis account 1 billion ZIL.
genesis_accounts: Self::genesis_accounts(&genesis_key),
empty_block_timeout: Duration::from_millis(25),
Expand Down Expand Up @@ -464,7 +463,6 @@ impl Network {
eth_block_gas_limit: EvmGas(84000000),
gas_price: 4_761_904_800_000u128.into(),
main_shard_id: None,
minimum_time_left_for_empty_block: minimum_time_left_for_empty_block_default(),
scilla_address: scilla_address_default(),
blocks_per_epoch: self.blocks_per_epoch,
epochs_per_checkpoint: 1,
Expand Down
8 changes: 3 additions & 5 deletions zilliqa/tests/it/persistence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ use zilliqa::{
allowed_timestamp_skew_default, block_request_batch_size_default,
block_request_limit_default, consensus_timeout_default, eth_chain_id_default,
failed_request_sleep_duration_default, max_blocks_in_flight_default,
minimum_time_left_for_empty_block_default, scilla_address_default,
scilla_ext_libs_path_default, scilla_stdlib_dir_default, state_cache_size_default,
state_rpc_limit_default, total_native_token_supply_default, ApiServer, Checkpoint,
ConsensusConfig, NodeConfig,
scilla_address_default, scilla_ext_libs_path_default, scilla_stdlib_dir_default,
state_cache_size_default, state_rpc_limit_default, total_native_token_supply_default,
ApiServer, Checkpoint, ConsensusConfig, NodeConfig,
},
crypto::{Hash, SecretKey},
transaction::EvmGas,
Expand Down Expand Up @@ -108,7 +107,6 @@ async fn block_and_tx_data_persistence(mut network: Network) {
consensus_timeout: consensus_timeout_default(),
genesis_deposits: Vec::new(),
main_shard_id: None,
minimum_time_left_for_empty_block: minimum_time_left_for_empty_block_default(),
scilla_address: scilla_address_default(),
blocks_per_epoch: 10,
epochs_per_checkpoint: 1,
Expand Down
Loading