Skip to content

Commit 9d4ad0b

Browse files
committed
regular dependency upgrade
1 parent 9baa4b6 commit 9d4ad0b

File tree

9 files changed

+888
-841
lines changed

9 files changed

+888
-841
lines changed

Cargo.lock

Lines changed: 751 additions & 755 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,39 @@ name = "reth"
1212
path = "src/main.rs"
1313

1414
[dependencies]
15-
reth = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
16-
reth-evm = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
17-
reth-engine-primitives = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
18-
reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
19-
reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
20-
reth-ethereum-consensus = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
21-
reth-chainspec = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
22-
reth-chain-state = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
23-
reth-consensus = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
24-
reth-cli-util = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
25-
reth-auto-seal-consensus = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
26-
reth-prune-types = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
27-
reth-basic-payload-builder = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
28-
reth-ethereum-payload-builder = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
29-
reth-ethereum-engine-primitives = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
30-
reth-provider = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9", features = ["test-utils"] }
31-
reth-errors = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
32-
reth-db = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
33-
reth-db-api = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
34-
reth-rpc = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
35-
reth-stages = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
36-
reth-stages-api = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
37-
reth-stages-types = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
38-
reth-primitives = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
39-
reth-trie = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
40-
reth-trie-db = { git = "https://github.com/paradigmxyz/reth", rev = "bd8c4eceb20c39c6e501d06cf906469329340bb9" }
41-
eyre = "0.6.12"
15+
reth = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
16+
reth-evm = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
17+
reth-engine-primitives = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
18+
reth-node-ethereum = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
19+
reth-evm-ethereum = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
20+
reth-ethereum-consensus = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
21+
reth-chainspec = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
22+
reth-chain-state = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
23+
reth-consensus = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
24+
reth-cli-util = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
25+
# reth-auto-seal-consensus = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
26+
reth-prune-types = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
27+
reth-basic-payload-builder = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
28+
reth-ethereum-payload-builder = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
29+
reth-ethereum-engine-primitives = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
30+
reth-provider = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40", features = ["test-utils"] }
31+
reth-errors = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
32+
reth-db = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
33+
reth-db-api = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
34+
reth-rpc = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
35+
reth-stages = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
36+
reth-stages-api = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
37+
reth-stages-types = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
38+
reth-primitives = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
39+
reth-trie = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
40+
reth-trie-db = { git = "https://github.com/paradigmxyz/reth", rev = "496bf0bf715f0a1fafc198f8d72ccd71913d1a40" }
41+
eyre = "0.6"
4242
clap = { version = "4.5.6", features = ["derive"] }
4343

4444
# revm
45-
revm = { version = "17.0.0", features = [
46-
"std",
47-
"secp256k1",
48-
"blst",
49-
], default-features = false }
50-
revm-inspectors = "0.10.0"
51-
revm-primitives = { version = "13.0.0", features = [
45+
revm = { version = "18.0.0", features = ["std"], default-features = false }
46+
revm-inspectors = "0.11.0"
47+
revm-primitives = { version = "14.0.0", features = [
5248
"std",
5349
], default-features = false }
5450

@@ -62,16 +58,16 @@ thiserror-no-std = { version = "2.0.2", default-features = false }
6258

6359
# eth
6460
alloy-chains = "0.1.32"
65-
alloy-dyn-abi = "0.8.0"
66-
alloy-primitives = { version = "0.8.9", default-features = false }
61+
alloy-dyn-abi = "0.8.11"
62+
alloy-primitives = { version = "0.8.11", default-features = false }
6763
alloy-rlp = "0.3.4"
68-
alloy-sol-types = "0.8.0"
64+
alloy-sol-types = "0.8.11"
6965
alloy-trie = { version = "0.7", default-features = false }
7066

71-
alloy-consensus = { version = "0.5.4", default-features = false }
72-
alloy-eips = { version = "0.5.4", default-features = false }
67+
alloy-consensus = { version = "0.6.4", default-features = false }
68+
alloy-eips = { version = "0.6.4", default-features = false }
7369
alloy-sol-macro = "0.8.9"
74-
alloy-serde = { version = "0.5.4", default-features = false }
70+
alloy-serde = { version = "0.6.4", default-features = false }
7571
rayon = "1.7"
7672

7773
tracing = "0.1.0"

src/consensus.rs

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1-
use reth::primitives::{BlockWithSenders, Header, SealedBlock, SealedHeader};
2-
use reth_chainspec::ChainSpec;
1+
use alloy_consensus::Header;
2+
use reth::{
3+
consensus_common::validation::{
4+
validate_against_parent_4844, validate_against_parent_eip1559_base_fee,
5+
validate_against_parent_hash_number, validate_body_against_header, validate_cancun_gas,
6+
validate_header_base_fee, validate_header_gas, validate_shanghai_withdrawals,
7+
},
8+
primitives::{BlockBody, BlockWithSenders, SealedBlock, SealedHeader},
9+
};
10+
use reth_chainspec::{ChainSpec, EthereumHardforks};
311
use reth_consensus::{Consensus, ConsensusError, PostExecutionInput};
12+
use reth_primitives::GotExpected;
413
use revm_primitives::U256;
514
use std::sync::Arc;
615

@@ -18,17 +27,27 @@ impl GnosisBeaconConsensus {
1827

1928
// `validate_header`, `validate_header_against_parent`, `validate_header_with_total_difficulty`, `validate_block_pre_execution`, `validate_block_post_execution`
2029
impl Consensus for GnosisBeaconConsensus {
21-
fn validate_header(&self, _header: &SealedHeader) -> Result<(), ConsensusError> {
22-
// TODO
23-
Ok(())
30+
fn validate_header(&self, header: &SealedHeader) -> Result<(), ConsensusError> {
31+
validate_header_gas(header)?;
32+
validate_header_base_fee(header, &self.chain_spec)
2433
}
2534

2635
fn validate_header_against_parent(
2736
&self,
28-
_header: &SealedHeader,
29-
_parent: &SealedHeader,
37+
header: &SealedHeader,
38+
parent: &SealedHeader,
3039
) -> Result<(), ConsensusError> {
31-
// TODO
40+
validate_against_parent_hash_number(header, parent)?;
41+
validate_against_parent_eip1559_base_fee(header, parent, &self.chain_spec)?;
42+
43+
// ensure that the blob gas fields for this block
44+
if self
45+
.chain_spec
46+
.is_cancun_active_at_timestamp(header.timestamp)
47+
{
48+
validate_against_parent_4844(header, parent)?;
49+
}
50+
3251
Ok(())
3352
}
3453

@@ -41,8 +60,52 @@ impl Consensus for GnosisBeaconConsensus {
4160
Ok(())
4261
}
4362

44-
fn validate_block_pre_execution(&self, _block: &SealedBlock) -> Result<(), ConsensusError> {
45-
// TODO
63+
fn validate_body_against_header(
64+
&self,
65+
body: &BlockBody,
66+
header: &SealedHeader,
67+
) -> Result<(), ConsensusError> {
68+
validate_body_against_header(body, header)
69+
}
70+
71+
// fn validate_block_pre_execution(&self, _block: &SealedBlock) -> Result<(), ConsensusError> {
72+
// // TODO
73+
// Ok(())
74+
// }
75+
76+
fn validate_block_pre_execution(&self, block: &SealedBlock) -> Result<(), ConsensusError> {
77+
// Check ommers hash
78+
let ommers_hash = reth_primitives::proofs::calculate_ommers_root(&block.body.ommers);
79+
if block.header.ommers_hash != ommers_hash {
80+
return Err(ConsensusError::BodyOmmersHashDiff(
81+
GotExpected {
82+
got: ommers_hash,
83+
expected: block.header.ommers_hash,
84+
}
85+
.into(),
86+
));
87+
}
88+
89+
// Check transaction root
90+
if let Err(error) = block.ensure_transaction_root_valid() {
91+
return Err(ConsensusError::BodyTransactionRootDiff(error.into()));
92+
}
93+
94+
// EIP-4895: Beacon chain push withdrawals as operations
95+
if self
96+
.chain_spec
97+
.is_shanghai_active_at_timestamp(block.timestamp)
98+
{
99+
validate_shanghai_withdrawals(block)?;
100+
}
101+
102+
if self
103+
.chain_spec
104+
.is_cancun_active_at_timestamp(block.timestamp)
105+
{
106+
validate_cancun_gas(block)?;
107+
}
108+
46109
Ok(())
47110
}
48111

src/evm_config.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1+
use alloy_consensus::Header;
12
use alloy_primitives::{Address, U256};
23
use reth::revm::{inspector_handle_register, Database, GetInspector};
34
use reth::revm::{Evm, EvmBuilder};
45
use reth_chainspec::ChainSpec;
56
use reth_evm::{ConfigureEvm, ConfigureEvmEnv};
67
use reth_evm_ethereum::{revm_spec, revm_spec_by_timestamp_after_merge};
7-
use reth_primitives::{
8-
revm_primitives::{AnalysisKind, CfgEnvWithHandlerCfg, TxEnv},
9-
transaction::FillTxEnv,
10-
Head, Header, TransactionSigned,
11-
};
8+
use reth_primitives::{transaction::FillTxEnv, Head, TransactionSigned};
129
use revm::{
1310
handler::mainnet::reward_beneficiary as reward_beneficiary_mainnet, interpreter::Gas, Context,
1411
};
1512
use revm_primitives::{
16-
spec_to_generic, BlobExcessGasAndPrice, BlockEnv, Bytes, CfgEnv, EVMError, Env, HandlerCfg,
17-
Spec, SpecId, TxKind,
13+
spec_to_generic, AnalysisKind, BlobExcessGasAndPrice, BlockEnv, Bytes, CfgEnv,
14+
CfgEnvWithHandlerCfg, EVMError, Env, HandlerCfg, Spec, SpecId, TxEnv, TxKind,
1815
};
1916
use std::{convert::Infallible, sync::Arc};
2017

src/execute.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::evm_config::GnosisEvmConfig;
33

44
use crate::gnosis::apply_post_block_system_calls;
55
use alloc::{boxed::Box, sync::Arc};
6-
use alloy_consensus::Transaction as _;
6+
use alloy_consensus::{Header, Transaction as _};
77
use alloy_eips::eip7685::Requests;
88
use alloy_primitives::Address;
99
use core::fmt::Display;
@@ -19,7 +19,7 @@ use reth_evm::{
1919
};
2020
use reth_evm_ethereum::eip6110::parse_deposits_from_receipts;
2121
use reth_node_ethereum::BasicBlockExecutorProvider;
22-
use reth_primitives::{BlockWithSenders, Header, Receipt};
22+
use reth_primitives::{BlockWithSenders, Receipt};
2323
use revm::State;
2424
use revm_primitives::{
2525
db::{Database, DatabaseCommit},
@@ -101,7 +101,7 @@ where
101101
EvmConfig: Clone,
102102
{
103103
pub fn new(state: State<DB>, chain_spec: Arc<ChainSpec>, evm_config: EvmConfig) -> Self {
104-
let system_caller = SystemCaller::new(evm_config.clone(), (*chain_spec).clone());
104+
let system_caller = SystemCaller::new(evm_config.clone(), chain_spec.clone());
105105
let block_rewards_contract = chain_spec
106106
.genesis()
107107
.config

src/gnosis.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
use std::collections::HashMap;
22

33
use crate::errors::GnosisBlockExecutionError;
4+
use alloy_eips::eip4895::{Withdrawal, Withdrawals};
45
use alloy_primitives::{address, Address, U256};
56
use alloy_sol_macro::sol;
67
use alloy_sol_types::SolCall;
7-
use reth::{
8-
primitives::Withdrawal,
9-
revm::{
10-
interpreter::Host,
11-
primitives::{ExecutionResult, Output, ResultAndState},
12-
Database, DatabaseCommit, Evm, State,
13-
},
8+
use reth::revm::{
9+
interpreter::Host,
10+
primitives::{ExecutionResult, Output, ResultAndState},
11+
Database, DatabaseCommit, Evm, State,
1412
};
1513
use reth_chainspec::ChainSpec;
1614
use reth_chainspec::EthereumHardforks;
1715
use reth_errors::BlockValidationError;
1816
use reth_evm::{execute::BlockExecutionError, ConfigureEvm};
19-
use reth_primitives::Withdrawals;
2017
use reth_provider::ProviderError;
2118
use revm_primitives::{
2219
Account, AccountInfo, AccountStatus, BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg,

src/lib.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,7 @@ where
180180
type Consensus = Arc<dyn reth_consensus::Consensus>;
181181

182182
async fn build_consensus(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Consensus> {
183-
if ctx.is_dev() {
184-
Ok(Arc::new(reth_auto_seal_consensus::AutoSealConsensus::new(
185-
ctx.chain_spec(),
186-
)))
187-
} else {
188-
Ok(Arc::new(GnosisBeaconConsensus::new(ctx.chain_spec())))
189-
}
183+
Ok(Arc::new(GnosisBeaconConsensus::new(ctx.chain_spec())))
190184
}
191185
}
192186

src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,5 @@ fn main() {
6666
}
6767
}
6868
}
69+
70+
// ./target/debug/reth --chain ./scripts/chiado_genesis_alloc.json init-state ./state_at_26478650.jsonl --without-evm --header ./alt_header.rlp --total-difficulty 8626000110427540000000000000000000000000000000 --header-hash 3eaf85f384900ee9cf4e23f8e7584ef7f3118bcb960d3f56c62cff5ca95166f3

src/payload_builder.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::sync::Arc;
22

3-
use alloy_consensus::EMPTY_OMMER_ROOT_HASH;
3+
use alloy_consensus::{Header, EMPTY_OMMER_ROOT_HASH};
44
use alloy_eips::{eip4844::MAX_DATA_GAS_PER_BLOCK, eip7685::Requests, merge::BEACON_NONCE};
55
use eyre::eyre;
66
use reth::{
@@ -12,7 +12,7 @@ use reth::{
1212
},
1313
primitives::{
1414
proofs::{self},
15-
Block, Header, Receipt,
15+
Block, Receipt,
1616
},
1717
revm::database::StateProviderDatabase,
1818
transaction_pool::{noop::NoopTransactionPool, BestTransactionsAttributes, TransactionPool},
@@ -508,13 +508,15 @@ where
508508
// only determine cancun fields when active
509509
if chain_spec.is_cancun_active_at_timestamp(attributes.timestamp) {
510510
// grab the blob sidecars from the executed txs
511-
blob_sidecars = pool.get_all_blobs_exact(
512-
executed_txs
513-
.iter()
514-
.filter(|tx| tx.is_eip4844())
515-
.map(|tx| tx.hash)
516-
.collect(),
517-
)?;
511+
blob_sidecars = pool
512+
.get_all_blobs_exact(
513+
executed_txs
514+
.iter()
515+
.filter(|tx| tx.is_eip4844())
516+
.map(|tx| tx.hash)
517+
.collect(),
518+
)
519+
.map_err(PayloadBuilderError::other)?;
518520

519521
excess_blob_gas = if chain_spec.is_cancun_active_at_timestamp(parent_header.timestamp) {
520522
let parent_excess_blob_gas = parent_header.excess_blob_gas.unwrap_or_default();
@@ -566,12 +568,12 @@ where
566568
},
567569
};
568570

569-
let sealed_block = block.seal_slow();
571+
let sealed_block = Arc::new(block.seal_slow());
570572
debug!(target: "payload_builder", ?sealed_block, "sealed built block");
571573

572574
// create the executed block data
573575
let executed = ExecutedBlock {
574-
block: Arc::new(sealed_block.clone()),
576+
block: sealed_block.clone(),
575577
senders: Arc::new(executed_senders),
576578
execution_output: Arc::new(execution_outcome),
577579
hashed_state: Arc::new(hashed_state),

0 commit comments

Comments
 (0)