Skip to content

Commit

Permalink
feat: support time-based forking (paradigmxyz#985)
Browse files Browse the repository at this point in the history
  • Loading branch information
leruaa authored and literallymarvellous committed Feb 6, 2023
1 parent 5c46f71 commit 3203dff
Show file tree
Hide file tree
Showing 17 changed files with 454 additions and 313 deletions.
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();
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::ttd(
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::ttd(
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::ttd(
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::ttd(
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

0 comments on commit 3203dff

Please sign in to comment.