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

feat: support time-based forking #985

Merged
merged 17 commits into from
Jan 27, 2023
Merged
Show file tree
Hide file tree
Changes from 13 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
13 changes: 7 additions & 6 deletions bin/reth/src/test_eth_chain/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use reth_db::{
Error as DbError,
};
use reth_primitives::{
keccak256, Account as RethAccount, Address, ChainSpec, JsonU256, SealedBlock, SealedHeader,
StorageEntry, H256, U256,
keccak256, Account as RethAccount, Address, ChainSpec, Hardfork, JsonU256, SealedBlock,
SealedHeader, StorageEntry, H256, U256,
};
use reth_rlp::Decodable;
use reth_stages::{stages::execution::ExecutionStage, ExecInput, Stage, StageId, Transaction};
Expand All @@ -20,7 +20,7 @@ use std::{
ffi::OsStr,
path::{Path, PathBuf},
};
use tracing::{debug, trace};
use tracing::{debug, trace, warn};

/// The outcome of a test.
#[derive(Debug)]
Expand Down Expand Up @@ -125,7 +125,7 @@ pub async fn run_test(path: PathBuf) -> eyre::Result<TestOutcome> {

let chain_spec: ChainSpec = suite.network.into();
// if paris aka merge is not activated we dont have block rewards;
let has_block_reward = chain_spec.paris_status().block_number().is_some();
let has_block_reward = chain_spec.fork_block(Hardfork::Paris).is_some();

// Create db and acquire transaction
let db = create_test_rw_db::<WriteMap>();
Expand Down Expand Up @@ -198,8 +198,9 @@ pub async fn run_test(path: PathBuf) -> eyre::Result<TestOutcome> {
{
let mut transaction = Transaction::new(db.as_ref())?;

// ignore error
let _ = stage.execute(&mut transaction, input).await;
if let Err(err) = stage.execute(&mut transaction, input).await {
warn!("{:#}", err);
}
transaction.commit()?;
}

Expand Down
20 changes: 17 additions & 3 deletions crates/consensus/src/consensus.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//! Consensus for ethereum network
use crate::verification;
use reth_interfaces::consensus::{Consensus, Error, ForkchoiceState};
use reth_primitives::{BlockNumber, ChainSpec, SealedBlock, SealedHeader, H256};
use reth_primitives::{
BlockNumber, ChainSpec, ForkDiscriminant, Hardfork, SealedBlock, SealedHeader, H256,
};
use tokio::sync::{watch, watch::error::SendError};

/// Ethereum beacon consensus
Expand Down Expand Up @@ -46,7 +48,13 @@ impl Consensus for BeaconConsensus {
verification::validate_header_standalone(header, &self.chain_spec)?;
verification::validate_header_regarding_parent(parent, header, &self.chain_spec)?;

if Some(header.number) < self.chain_spec.paris_status().block_number() {
if !self.chain_spec.fork_active(
Hardfork::Paris,
ForkDiscriminant::tdd(
self.chain_spec.terminal_total_difficulty().unwrap_or_default(),
Some(header.number),
),
) {
// TODO Consensus checks for old blocks:
// * difficulty, mix_hash & nonce aka PoW stuff
// low priority as syncing is done in reverse order
Expand All @@ -59,6 +67,12 @@ impl Consensus for BeaconConsensus {
}

fn has_block_reward(&self, block_num: BlockNumber) -> bool {
Some(block_num) < self.chain_spec.paris_status().block_number()
!self.chain_spec.fork_active(
Hardfork::Paris,
ForkDiscriminant::tdd(
self.chain_spec.terminal_total_difficulty().unwrap_or_default(),
Some(block_num),
),
)
}
}
25 changes: 7 additions & 18 deletions crates/consensus/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ impl<Client: HeaderProvider + BlockProvider + StateProvider> ConsensusEngine
};

if let Some(parent_td) = self.client.header_td(&block.parent_hash)? {
if Some(parent_td) <= self.chain_spec.paris_status().terminal_total_difficulty() {
if Some(parent_td) <= self.chain_spec.terminal_total_difficulty() {
return Ok(PayloadStatus::from_status(PayloadStatusEnum::Invalid {
validation_error: EngineApiError::PayloadPreMerge.to_string(),
}))
Expand Down Expand Up @@ -271,7 +271,6 @@ impl<Client: HeaderProvider + BlockProvider + StateProvider> ConsensusEngine

let merge_terminal_td = self
.chain_spec
.paris_status()
.terminal_total_difficulty()
.ok_or(EngineApiError::UnknownMergeTerminalTotalDifficulty)?;

Expand Down Expand Up @@ -516,8 +515,7 @@ mod tests {

let (result_tx, result_rx) = oneshot::channel();
let parent = transform_block(random_block(100, None, None, Some(0)), |mut b| {
b.header.difficulty =
chain_spec.paris_status().terminal_total_difficulty().unwrap();
b.header.difficulty = chain_spec.terminal_total_difficulty().unwrap();
b
});
let block = random_block(101, Some(parent.hash()), None, Some(0));
Expand Down Expand Up @@ -555,7 +553,7 @@ mod tests {
let parent = transform_block(random_block(100, None, None, Some(0)), |mut b| {
b.header.timestamp = parent_timestamp;
b.header.difficulty =
chain_spec.paris_status().terminal_total_difficulty().unwrap() + U256::from(1);
chain_spec.terminal_total_difficulty().unwrap() + U256::from(1);
b
});
let block =
Expand Down Expand Up @@ -633,10 +631,7 @@ mod tests {
tokio::spawn(engine);

let transition_config = TransitionConfiguration {
terminal_total_difficulty: chain_spec
.paris_status()
.terminal_total_difficulty()
.unwrap() +
terminal_total_difficulty: chain_spec.terminal_total_difficulty().unwrap() +
U256::from(1),
..Default::default()
};
Expand All @@ -651,7 +646,7 @@ mod tests {
assert_matches!(
result_rx.await,
Ok(Err(EngineApiError::TerminalTD { execution, consensus }))
if execution == chain_spec.paris_status().terminal_total_difficulty().unwrap()
if execution == chain_spec.terminal_total_difficulty().unwrap()
&& consensus == U256::from(transition_config.terminal_total_difficulty)
);
}
Expand All @@ -675,10 +670,7 @@ mod tests {
let execution_terminal_block = random_block(terminal_block_number, None, None, None);

let transition_config = TransitionConfiguration {
terminal_total_difficulty: chain_spec
.paris_status()
.terminal_total_difficulty()
.unwrap(),
terminal_total_difficulty: chain_spec.terminal_total_difficulty().unwrap(),
terminal_block_hash: consensus_terminal_block.hash(),
terminal_block_number: terminal_block_number.into(),
};
Expand Down Expand Up @@ -737,10 +729,7 @@ mod tests {
let terminal_block = random_block(terminal_block_number, None, None, None);

let transition_config = TransitionConfiguration {
terminal_total_difficulty: chain_spec
.paris_status()
.terminal_total_difficulty()
.unwrap(),
terminal_total_difficulty: chain_spec.terminal_total_difficulty().unwrap(),
terminal_block_hash: terminal_block.hash(),
terminal_block_number: terminal_block_number.into(),
};
Expand Down
32 changes: 23 additions & 9 deletions crates/consensus/src/verification.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//! ALl functions for verification of block
use reth_interfaces::{consensus::Error, Result as RethResult};
use reth_primitives::{
BlockNumber, ChainSpec, Hardfork, Header, SealedBlock, SealedHeader, Transaction,
TransactionSignedEcRecovered, TxEip1559, TxEip2930, TxLegacy, EMPTY_OMMER_ROOT, U256,
BlockNumber, ChainSpec, ForkDiscriminant, Hardfork, Header, SealedBlock, SealedHeader,
Transaction, TransactionSignedEcRecovered, TxEip1559, TxEip2930, TxLegacy, EMPTY_OMMER_ROOT,
U256,
};
use reth_provider::{AccountProvider, HeaderProvider};
use std::{
Expand Down Expand Up @@ -39,14 +40,21 @@ pub fn validate_header_standalone(
}

// Check if base fee is set.
if chain_spec.fork_active(Hardfork::London, header.number) && header.base_fee_per_gas.is_none()
if chain_spec.fork_active(Hardfork::London, header.number.into()) &&
header.base_fee_per_gas.is_none()
{
return Err(Error::BaseFeeMissing)
}

// EIP-3675: Upgrade consensus to Proof-of-Stake:
// https://eips.ethereum.org/EIPS/eip-3675#replacing-difficulty-with-0
if Some(header.number) >= chain_spec.paris_status().block_number() {
if chain_spec.fork_active(
Hardfork::Paris,
ForkDiscriminant::tdd(
chain_spec.terminal_total_difficulty().unwrap_or_default(),
Some(header.number),
),
) {
if header.difficulty != U256::ZERO {
return Err(Error::TheMergeDifficultyIsNotZero)
}
Expand Down Expand Up @@ -78,7 +86,7 @@ pub fn validate_transaction_regarding_header(
let chain_id = match transaction {
Transaction::Legacy(TxLegacy { chain_id, .. }) => {
// EIP-155: Simple replay attack protection: https://eips.ethereum.org/EIPS/eip-155
if chain_spec.fork_active(Hardfork::SpuriousDragon, at_block_number) &&
if chain_spec.fork_active(Hardfork::SpuriousDragon, at_block_number.into()) &&
chain_id.is_some()
{
return Err(Error::TransactionOldLegacyChainId)
Expand All @@ -87,7 +95,7 @@ pub fn validate_transaction_regarding_header(
}
Transaction::Eip2930(TxEip2930 { chain_id, .. }) => {
// EIP-2930: Optional access lists: https://eips.ethereum.org/EIPS/eip-2930 (New transaction type)
if !chain_spec.fork_active(Hardfork::Berlin, at_block_number) {
if !chain_spec.fork_active(Hardfork::Berlin, at_block_number.into()) {
return Err(Error::TransactionEip2930Disabled)
}
Some(*chain_id)
Expand All @@ -99,7 +107,7 @@ pub fn validate_transaction_regarding_header(
..
}) => {
// EIP-1559: Fee market change for ETH 1.0 chain https://eips.ethereum.org/EIPS/eip-1559
if !chain_spec.fork_active(Hardfork::Berlin, at_block_number) {
if !chain_spec.fork_active(Hardfork::Berlin, at_block_number.into()) {
return Err(Error::TransactionEip1559Disabled)
}

Expand Down Expand Up @@ -259,7 +267,13 @@ pub fn validate_header_regarding_parent(
}

// difficulty check is done by consensus.
if chain_spec.paris_status().block_number() > Some(child.number) {
if !chain_spec.fork_active(
Hardfork::Paris,
ForkDiscriminant::tdd(
chain_spec.terminal_total_difficulty().unwrap_or_default(),
Some(child.number),
),
) {
// TODO how this needs to be checked? As ice age did increment it by some formula
}

Expand Down Expand Up @@ -287,7 +301,7 @@ pub fn validate_header_regarding_parent(
}

// EIP-1559 check base fee
if chain_spec.fork_active(Hardfork::London, child.number) {
if chain_spec.fork_active(Hardfork::London, child.number.into()) {
let base_fee = child.base_fee_per_gas.ok_or(Error::BaseFeeMissing)?;

let expected_base_fee = if chain_spec.fork_block(Hardfork::London) == Some(child.number) {
Expand Down
Loading