feat: display hardforks on startup (#3227)

Co-authored-by: seroze <serozekim@gmail.com>
This commit is contained in:
Bjerg
2023-06-19 15:47:34 +02:00
committed by GitHub
parent 4709fcf16c
commit 0ffb9c5653
4 changed files with 211 additions and 6 deletions

View File

@ -76,6 +76,7 @@ use crate::{
};
use reth_interfaces::p2p::headers::client::HeadersClient;
use reth_payload_builder::PayloadBuilderService;
use reth_primitives::DisplayHardforks;
use reth_provider::providers::BlockchainProvider;
use reth_stages::stages::{
AccountHashingStage, IndexAccountHistoryStage, IndexStorageHistoryStage, MerkleStage,
@ -171,6 +172,8 @@ impl Command {
let genesis_hash = init_genesis(db.clone(), self.chain.clone())?;
info!(target: "reth::cli", "{}", DisplayHardforks::from(self.chain.hardforks().clone()));
let consensus: Arc<dyn Consensus> = if self.auto_mine {
debug!(target: "reth::cli", "Using auto seal");
Arc::new(AutoSealConsensus::new(Arc::clone(&self.chain)))

View File

@ -11,7 +11,8 @@ use std::{fmt, str::FromStr};
// The chain spec module.
mod spec;
pub use spec::{
AllGenesisFormats, ChainSpec, ChainSpecBuilder, ForkCondition, GOERLI, MAINNET, SEPOLIA,
AllGenesisFormats, ChainSpec, ChainSpecBuilder, DisplayHardforks, ForkCondition, GOERLI,
MAINNET, SEPOLIA,
};
// The chain info module.

View File

@ -9,7 +9,11 @@ use crate::{
use hex_literal::hex;
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, sync::Arc};
use std::{
collections::BTreeMap,
fmt::{Display, Formatter},
sync::Arc,
};
/// The Ethereum mainnet spec
pub static MAINNET: Lazy<Arc<ChainSpec>> = Lazy::new(|| {
@ -706,11 +710,164 @@ impl ForkCondition {
}
}
/// A container to pretty-print a hardfork.
///
/// The fork is formatted depending on its fork condition:
///
/// - Block and timestamp based forks are formatted in the same manner (`{name} <({eip})>
/// @{condition}`)
/// - TTD based forks are formatted separately as `{name} <({eip})> @{ttd} (network is <not> known
/// to be merged)`
///
/// An optional EIP can be attached to the fork to display as well. This should generally be in the
/// form of just `EIP-x`, e.g. `EIP-1559`.
#[derive(Debug)]
struct DisplayFork {
/// The name of the hardfork (e.g. Frontier)
name: String,
/// The fork condition
activated_at: ForkCondition,
/// An optional EIP (e.g. `EIP-1559`).
eip: Option<String>,
}
impl Display for DisplayFork {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let name_with_eip = if let Some(eip) = &self.eip {
format!("{} ({})", self.name, eip)
} else {
self.name.clone()
};
match self.activated_at {
ForkCondition::Block(at) | ForkCondition::Timestamp(at) => {
write!(f, "{:32} @{}", name_with_eip, at)?;
}
ForkCondition::TTD { fork_block, total_difficulty } => {
writeln!(
f,
"{:32} @{} ({})",
name_with_eip,
total_difficulty,
if fork_block.is_some() {
"network is known to be merged"
} else {
"network is not known to be merged"
}
)?;
}
ForkCondition::Never => unreachable!(),
}
Ok(())
}
}
/// A container for pretty-printing a list of hardforks.
///
/// # Example
///
/// ```
/// # use reth_primitives::MAINNET;
/// # use reth_primitives::DisplayHardforks;
/// println!("{}", DisplayHardforks::from(MAINNET.hardforks().clone()));
/// ```
///
/// An example of the output:
///
/// ```text
/// Pre-merge hard forks (block based):
// - Frontier @0
// - Homestead @1150000
// - Dao @1920000
// - Tangerine @2463000
// - SpuriousDragon @2675000
// - Byzantium @4370000
// - Constantinople @7280000
// - Petersburg @7280000
// - Istanbul @9069000
// - MuirGlacier @9200000
// - Berlin @12244000
// - London @12965000
// - ArrowGlacier @13773000
// - GrayGlacier @15050000
// Merge hard forks:
// - Paris @58750000000000000000000 (network is not known to be merged)
//
// Post-merge hard forks (timestamp based):
// - Shanghai @1681338455
/// ```
#[derive(Debug)]
pub struct DisplayHardforks {
/// A list of pre-merge (block based) hardforks
pre_merge: Vec<DisplayFork>,
/// A list of merge (TTD based) hardforks
with_merge: Vec<DisplayFork>,
/// A list of post-merge (timestamp based) hardforks
post_merge: Vec<DisplayFork>,
}
impl Display for DisplayHardforks {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Pre-merge hard forks (block based):")?;
for fork in self.pre_merge.iter() {
writeln!(f, "- {fork}")?;
}
if !self.with_merge.is_empty() {
writeln!(f, "Merge hard forks:")?;
for fork in self.with_merge.iter() {
writeln!(f, "- {fork}")?;
}
}
if !self.post_merge.is_empty() {
writeln!(f, "Post-merge hard forks (timestamp based):")?;
for fork in self.post_merge.iter() {
writeln!(f, "- {fork}")?;
}
}
Ok(())
}
}
impl<I> From<I> for DisplayHardforks
where
I: IntoIterator<Item = (Hardfork, ForkCondition)>,
{
fn from(iter: I) -> Self {
let mut pre_merge = Vec::new();
let mut with_merge = Vec::new();
let mut post_merge = Vec::new();
for (fork, condition) in iter.into_iter() {
let display_fork =
DisplayFork { name: fork.to_string(), activated_at: condition, eip: None };
match condition {
ForkCondition::Block(_) => {
pre_merge.push(display_fork);
}
ForkCondition::TTD { .. } => {
with_merge.push(display_fork);
}
ForkCondition::Timestamp(_) => {
post_merge.push(display_fork);
}
ForkCondition::Never => continue,
}
}
Self { pre_merge, with_merge, post_merge }
}
}
#[cfg(test)]
mod tests {
use crate::{
AllGenesisFormats, Chain, ChainSpec, ChainSpecBuilder, ForkCondition, ForkHash, ForkId,
Genesis, Hardfork, Head, GOERLI, H256, MAINNET, SEPOLIA, U256,
AllGenesisFormats, Chain, ChainSpec, ChainSpecBuilder, DisplayHardforks, ForkCondition,
ForkHash, ForkId, Genesis, Hardfork, Head, GOERLI, H256, MAINNET, SEPOLIA, U256,
};
use bytes::BytesMut;
use ethers_core::types as EtherType;
@ -726,6 +883,50 @@ mod tests {
}
}
#[test]
fn test_hardfork_list_display_mainnet() {
assert_eq!(
DisplayHardforks::from(MAINNET.hardforks().clone()).to_string(),
r##"Pre-merge hard forks (block based):
- Frontier @0
- Homestead @1150000
- Dao @1920000
- Tangerine @2463000
- SpuriousDragon @2675000
- Byzantium @4370000
- Constantinople @7280000
- Petersburg @7280000
- Istanbul @9069000
- MuirGlacier @9200000
- Berlin @12244000
- London @12965000
- ArrowGlacier @13773000
- GrayGlacier @15050000
Merge hard forks:
- Paris @58750000000000000000000 (network is not known to be merged)
Post-merge hard forks (timestamp based):
- Shanghai @1681338455
"##
);
}
#[test]
fn test_hardfork_list_ignores_disabled_forks() {
let spec = ChainSpec::builder()
.chain(Chain::mainnet())
.genesis(Genesis::default())
.with_fork(Hardfork::Frontier, ForkCondition::Block(0))
.with_fork(Hardfork::Shanghai, ForkCondition::Never)
.build();
assert_eq!(
DisplayHardforks::from(spec.hardforks().clone()).to_string(),
r##"Pre-merge hard forks (block based):
- Frontier @0
"##
);
}
// Tests that the ForkTimestamps are correctly set up.
#[test]
fn test_fork_timestamps() {

View File

@ -47,8 +47,8 @@ pub use block::{
};
pub use bloom::Bloom;
pub use chain::{
AllGenesisFormats, Chain, ChainInfo, ChainSpec, ChainSpecBuilder, ForkCondition, GOERLI,
MAINNET, SEPOLIA,
AllGenesisFormats, Chain, ChainInfo, ChainSpec, ChainSpecBuilder, DisplayHardforks,
ForkCondition, GOERLI, MAINNET, SEPOLIA,
};
pub use compression::*;
pub use constants::{