Skip to content

Commit 4a2314f

Browse files
authored
feat: validate exeution header and ancestors (#47)
1 parent 2a379cd commit 4a2314f

File tree

5 files changed

+36
-17
lines changed

5 files changed

+36
-17
lines changed

Cargo.lock

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

crates/client-executor/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ rsp-mpt.workspace = true
2323

2424
# reth
2525
reth-chainspec.workspace = true
26-
reth-primitives.workspace = true
26+
reth-consensus.workspace = true
27+
reth-ethereum-consensus.workspace = true
2728
reth-evm.workspace = true
2829
reth-evm-ethereum.workspace = true
30+
reth-primitives.workspace = true
2931

3032
# revm
3133
revm.workspace = true

crates/client-executor/src/lib.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ use alloy_trie::root::ordered_trie_root_with_encoder;
1010
use eyre::OptionExt;
1111
use io::EvmSketchInput;
1212
use reth_chainspec::ChainSpec;
13+
use reth_consensus::HeaderValidator;
14+
use reth_ethereum_consensus::EthBeaconConsensus;
1315
use reth_evm::{ConfigureEvm, EvmEnv};
1416
use reth_evm_ethereum::{EthEvm, EthEvmConfig};
15-
use reth_primitives::Header;
17+
use reth_primitives::{Header, SealedHeader};
1618
use revm::{
1719
context::TxEnv, database::CacheDB, inspector::NoOpInspector, Context, MainBuilder, MainContext,
1820
};
@@ -156,7 +158,7 @@ pub struct ClientExecutor<'a> {
156158
/// The block anchor.
157159
pub anchor: &'a Anchor,
158160
/// The genesis block specification.
159-
pub genesis: &'a Genesis,
161+
pub chain_spec: Arc<ChainSpec>,
160162
/// The database that the executor uses to access state.
161163
pub witness_db: TrieDB<'a>,
162164
/// All logs in the block.
@@ -166,16 +168,24 @@ pub struct ClientExecutor<'a> {
166168
impl<'a> ClientExecutor<'a> {
167169
/// Instantiates a new [`ClientExecutor`]
168170
pub fn new(state_sketch: &'a EvmSketchInput) -> Result<Self, ClientError> {
169-
assert_eq!(
170-
state_sketch.anchor.header().state_root,
171-
state_sketch.state.state_root(),
172-
"State root mismatch"
173-
);
171+
let chain_spec = Arc::new(ChainSpec::try_from(&state_sketch.genesis).unwrap());
172+
let validator = EthBeaconConsensus::new(chain_spec.clone());
173+
let header = state_sketch.anchor.header();
174+
175+
validator
176+
.validate_header(&SealedHeader::new_unhashed(header.clone()))
177+
.expect("the header in not valid");
178+
179+
assert_eq!(header.state_root, state_sketch.state.state_root(), "State root mismatch");
174180

175181
// verify that ancestors form a valid chain
176-
let mut previous_header = state_sketch.anchor.header();
182+
let mut previous_header = header;
177183
for ancestor in &state_sketch.ancestor_headers {
178184
let ancestor_hash = ancestor.hash_slow();
185+
186+
validator
187+
.validate_header(&SealedHeader::new_unhashed(ancestor.clone()))
188+
.unwrap_or_else(|_| panic!("the ancestor {} header in not valid", ancestor.number));
179189
assert_eq!(
180190
previous_header.parent_hash, ancestor_hash,
181191
"block {} is not the parent of {}",
@@ -200,7 +210,7 @@ impl<'a> ClientExecutor<'a> {
200210

201211
Ok(Self {
202212
anchor: &state_sketch.anchor,
203-
genesis: &state_sketch.genesis,
213+
chain_spec,
204214
witness_db: state_sketch.witness_db()?,
205215
logs,
206216
})
@@ -211,7 +221,7 @@ impl<'a> ClientExecutor<'a> {
211221
/// Storage accesses are already validated against the `witness_db`'s state root.
212222
pub fn execute(&self, call: ContractInput) -> eyre::Result<ContractPublicValues> {
213223
let cache_db = CacheDB::new(&self.witness_db);
214-
let mut evm = new_evm(cache_db, self.anchor.header(), U256::ZERO, self.genesis);
224+
let mut evm = new_evm(cache_db, self.anchor.header(), U256::ZERO, self.chain_spec.clone());
215225
let tx_output = evm.transact(&call)?;
216226
let tx_output_bytes = tx_output.result.output().ok_or_eyre("Error decoding result")?;
217227
let resolved = self.anchor.resolve();
@@ -247,13 +257,11 @@ pub fn new_evm<DB>(
247257
db: DB,
248258
header: &Header,
249259
difficulty: U256,
250-
genesis: &Genesis,
260+
chain_spec: Arc<ChainSpec>,
251261
) -> EthEvm<DB, NoOpInspector>
252262
where
253263
DB: Database,
254264
{
255-
let chain_spec = Arc::new(ChainSpec::try_from(genesis).unwrap());
256-
257265
let EvmEnv { cfg_env, mut block_env, .. } = EthEvmConfig::new(chain_spec).evm_env(header);
258266

259267
// Set the base fee to 0 to enable 0 gas price transactions.

crates/host-executor/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ rsp-rpc-db.workspace = true
2828
rsp-primitives.workspace = true
2929
rsp-mpt.workspace = true
3030

31+
# reth
32+
reth-chainspec.workspace = true
33+
3134
# revm
3235
revm.workspace = true
3336
revm-primitives.workspace = true

crates/host-executor/src/sketch.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::BTreeSet;
1+
use std::{collections::BTreeSet, sync::Arc};
22

33
use alloy_consensus::ReceiptEnvelope;
44
use alloy_eips::{eip2718::Eip2718Error, Decodable2718, Encodable2718};
@@ -7,6 +7,7 @@ use alloy_primitives::{Bytes, B256, U256};
77
use alloy_provider::{network::AnyNetwork, Provider};
88
use alloy_rpc_types::{AnyReceiptEnvelope, Filter, Log as RpcLog};
99
use eyre::eyre;
10+
use reth_chainspec::ChainSpec;
1011
use revm::{context::result::ExecutionResult, database::CacheDB};
1112
use rsp_mpt::EthereumState;
1213
use rsp_primitives::{account_proof::eip1186_proof_to_account_proof, genesis::Genesis};
@@ -15,7 +16,8 @@ use sp1_cc_client_executor::{io::EvmSketchInput, new_evm, Anchor, ContractInput}
1516

1617
use crate::{EvmSketchBuilder, HostError};
1718

18-
/// ['EvmSketch'] is used to prefetch all the data required to execute a block and query logs in the zkVM.
19+
/// ['EvmSketch'] is used to prefetch all the data required to execute a block and query logs in the
20+
/// zkVM.
1921
#[derive(Debug)]
2022
pub struct EvmSketch<P> {
2123
/// The genesis block specification.
@@ -43,7 +45,8 @@ where
4345
/// Executes the smart contract call with the given [`ContractInput`].
4446
pub async fn call(&self, input: ContractInput) -> eyre::Result<Bytes> {
4547
let cache_db = CacheDB::new(&self.rpc_db);
46-
let mut evm = new_evm(cache_db, self.anchor.header(), U256::ZERO, &self.genesis);
48+
let chain_spec = Arc::new(ChainSpec::try_from(&self.genesis)?);
49+
let mut evm = new_evm(cache_db, self.anchor.header(), U256::ZERO, chain_spec);
4750

4851
let output = evm.transact(&input)?;
4952

0 commit comments

Comments
 (0)