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

Validator epochs/ZIP25 #1298

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
18 changes: 9 additions & 9 deletions z2/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use std::path::PathBuf;
use alloy::primitives::{address, Address};
use anyhow::{anyhow, Result};
use k256::ecdsa::SigningKey;
use libp2p::PeerId;
use tokio::fs;
use toml;
use zilliqa::cfg::GenesisDeposit;
/// This module should eventually generate configuration files
/// For now, it just generates secret keys (which should be different each run, or we will become dependent on their values)
use zilliqa::crypto::{SecretKey, TransactionPublicKey};
Expand All @@ -20,7 +20,6 @@ use zilliqa::{
minimum_time_left_for_empty_block_default, scilla_address_default, scilla_lib_dir_default,
state_rpc_limit_default, Amount, ConsensusConfig,
},
crypto::NodePublicKey,
transaction::EvmGas,
};

Expand Down Expand Up @@ -164,17 +163,18 @@ impl Setup {

pub async fn generate_config(&self) -> Result<()> {
// The genesis deposits.
let mut genesis_deposits: Vec<(NodePublicKey, PeerId, Amount, Address)> = Vec::new();
let mut genesis_deposits: Vec<GenesisDeposit> = Vec::new();
for i in 0..self.how_many {
genesis_deposits.push((
self.secret_keys[i].node_public_key(),
self.secret_keys[i]
genesis_deposits.push(GenesisDeposit {
public_key: self.secret_keys[i].node_public_key(),
peer_id: self.secret_keys[i]
.to_libp2p_keypair()
.public()
.to_peer_id(),
GENESIS_DEPOSIT.into(),
self.node_addresses[i],
))
stake: GENESIS_DEPOSIT.into(),
reward_address: self.node_addresses[i],
control_address: self.node_addresses[i],
})
}

let genesis_accounts: Vec<(Address, Amount)> = vec![
Expand Down
12 changes: 11 additions & 1 deletion zilliqa/src/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ pub struct ConsensusConfig {
/// The initially staked deposits in the deposit contract at genesis, composed of
/// (public key, peerId, amount, reward address) tuples.
#[serde(default)]
pub genesis_deposits: Vec<(NodePublicKey, PeerId, Amount, Address)>,
pub genesis_deposits: Vec<GenesisDeposit>,
/// Accounts that will be pre-funded at genesis.
#[serde(default)]
pub genesis_accounts: Vec<(Address, Amount)>,
Expand Down Expand Up @@ -243,6 +243,16 @@ pub struct ConsensusConfig {
pub gas_price: Amount,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct GenesisDeposit {
pub public_key: NodePublicKey,
pub peer_id: PeerId,
pub stake: Amount,
pub reward_address: Address,
pub control_address: Address,
}

pub fn consensus_timeout_default() -> Duration {
Duration::from_secs(5)
}
Expand Down
58 changes: 36 additions & 22 deletions zilliqa/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,16 @@ impl Consensus {

let node_config = &self.config;

if self.block_is_first_in_epoch(parent.number() + 1) {
// Here we ignore any errors and proceed with block creation, under the philosophy that
// it is better to have the network run but with broken epochs, than it would be to
// crash the entire network on a failing epoch transition.
match state.tick_epoch() {
Ok(()) => (),
Err(e) => error!("Unable to transition the epoch - EVM error: {e}"),
};
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our consensus now depends on successful EVM calls - and not just read-only checks as before, but a complex write transaction.

This raises the question of what to do if the tick_epoch() call fails for any reason. Should we assume that it must never fail, and crash the node if it does (potentially crashing the network if a buggy state is reached)? The approach taken here is to soft-ignore errors; the network then will remain alive, but with a static validator set since epoch changes will be broken. Measures can then be taken to upgrade to fix the root cause of the issue (e.g. upgrading the deposit contract) to restore normal functionality.

But, especially right now in the early testnet phases, perhaps hard-crashing the network on any bugs might be preferable to discover any issues immediately.


while let Some(tx) = transaction_pool.best_transaction() {
let result = Self::apply_transaction_at(
state,
Expand Down Expand Up @@ -1659,28 +1669,26 @@ impl Consensus {
}
}

if self.block_is_first_in_epoch(block.number()) && !block.is_genesis() {
// TODO: handle epochs (#1140)

if self.config.do_checkpoints
&& self.epoch_is_checkpoint(self.epoch_number(block.number()))
{
if let Some(checkpoint_path) = self.db.get_checkpoint_dir()? {
let parent =
self.db
.get_block_by_hash(&block.parent_hash())?
.ok_or(anyhow!(
"Trying to checkpoint block, but we don't have its parent"
))?;
self.message_sender.send_message_to_coordinator(
InternalMessage::ExportBlockCheckpoint(
Box::new(block),
Box::new(parent),
self.db.state_trie()?.clone(),
checkpoint_path,
),
)?;
}
if self.block_is_first_in_epoch(block.number())
&& !block.is_genesis()
&& self.config.do_checkpoints
&& self.epoch_is_checkpoint(self.epoch_number(block.number()))
{
if let Some(checkpoint_path) = self.db.get_checkpoint_dir()? {
let parent = self
.db
.get_block_by_hash(&block.parent_hash())?
.ok_or(anyhow!(
"Trying to checkpoint block, but we don't have its parent"
))?;
self.message_sender.send_message_to_coordinator(
InternalMessage::ExportBlockCheckpoint(
Box::new(block),
Box::new(parent),
self.db.state_trie()?.clone(),
checkpoint_path,
),
)?;
}
}

Expand Down Expand Up @@ -2298,6 +2306,12 @@ impl Consensus {
}

self.apply_rewards_raw(committee, &parent, block.view(), &block.qc.cosigned)?;
if self.block_is_first_in_epoch(block.number()) {
match self.state.tick_epoch() {
Ok(()) => (),
Err(e) => warn!("Unable to transition the epoch - EVM error {e}"),
}
}

let mut block_receipts = Vec::new();
let mut cumulative_gas_used = EvmGas(0);
Expand Down
Loading
Loading