Skip to content

Commit

Permalink
feat(l2): prove block validation (#973)
Browse files Browse the repository at this point in the history
**Motivation**

the block execution program is missing many validation steps, this PR
adds them.

**Description**

- adds validation steps to zkVM program
  • Loading branch information
xqft authored Oct 25, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 2c0f597 commit 7f84c9e
Showing 5 changed files with 47 additions and 13 deletions.
5 changes: 4 additions & 1 deletion crates/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
@@ -158,7 +158,10 @@ pub fn is_canonical(
}
}

fn validate_gas_used(receipts: &[Receipt], block_header: &BlockHeader) -> Result<(), ChainError> {
pub fn validate_gas_used(
receipts: &[Receipt],
block_header: &BlockHeader,
) -> Result<(), ChainError> {
if let Some(last) = receipts.last() {
if last.cumulative_gas_used != block_header.gas_used {
return Err(ChainError::InvalidBlock(InvalidBlockError::GasUsedMismatch));
15 changes: 13 additions & 2 deletions crates/l2/proposer/prover_server.rs
Original file line number Diff line number Diff line change
@@ -11,12 +11,13 @@ use std::{
use tokio::signal::unix::{signal, SignalKind};
use tracing::{debug, info, warn};

use ethereum_rust_core::types::Block;
use ethereum_rust_core::types::{Block, BlockHeader};

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct ProverInputData {
pub db: ExecutionDB,
pub block: Block,
pub parent_header: BlockHeader,
}

use crate::utils::config::prover_server::ProverServerConfig;
@@ -223,8 +224,18 @@ impl ProverServer {
};
let db = ExecutionDB::from_exec(&block, &self.store).map_err(|err| err.to_string())?;

let parent_header = self
.store
.get_block_header_by_hash(block.header.parent_hash)
.map_err(|err| err.to_string())?
.ok_or("missing parent header".to_string())?;

debug!("Created prover input for block {block_number}");

Ok(ProverInputData { db, block })
Ok(ProverInputData {
db,
block,
parent_header,
})
}
}
2 changes: 2 additions & 0 deletions crates/l2/prover/src/prover.rs
Original file line number Diff line number Diff line change
@@ -35,10 +35,12 @@ impl<'a> Prover<'a> {

pub fn set_input(&mut self, input: ProverInputData) -> &mut Self {
let head_block_rlp = input.block.encode_to_vec();
let parent_header_rlp = input.parent_header.encode_to_vec();

// We should pass the inputs as a whole struct
self.env_builder.write(&head_block_rlp).unwrap();
self.env_builder.write(&input.db).unwrap();
self.env_builder.write(&parent_header_rlp).unwrap();

self
}
1 change: 1 addition & 0 deletions crates/l2/prover/zkvm/interface/guest/Cargo.toml
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ risc0-zkvm = { version = "1.1.2", default-features = false, features = ['std'] }
ethereum_rust-core = { path = "../../../../../common", default-features = false }
ethereum_rust-rlp = { path = "../../../../../common/rlp" }
ethereum_rust-vm = { path = "../../../../../vm", default-features = false }
ethereum_rust-blockchain = { path = "../../../../../blockchain", default-features = false }

[patch.crates-io]
crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" }
37 changes: 27 additions & 10 deletions crates/l2/prover/zkvm/interface/guest/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,39 @@
use ethereum_rust_rlp::decode::RLPDecode;
use ethereum_rust_rlp::{decode::RLPDecode, error::RLPDecodeError};
use risc0_zkvm::guest::env;

use ethereum_rust_core::types::Block;
use ethereum_rust_vm::{execute_block, execution_db::ExecutionDB, EvmState};
use ethereum_rust_blockchain::{validate_block, validate_gas_used};
use ethereum_rust_core::types::{Block, BlockHeader};
use ethereum_rust_vm::{execute_block, execution_db::ExecutionDB, get_state_transitions, EvmState};

fn main() {
// Read inputs
let (block, execution_db, parent_header) = read_inputs().expect("failed to read inputs");
let mut state = EvmState::from_exec_db(execution_db.clone());

// Validate the block pre-execution
validate_block(&block, &parent_header, &state).expect("invalid block");

let receipts = execute_block(&block, &mut state).unwrap();

validate_gas_used(&receipts, &block.header).expect("invalid gas used");

let _account_updates = get_state_transitions(&mut state);

// TODO: compute new state root from account updates and check it matches with the block's
// header one.
}

fn read_inputs() -> Result<(Block, ExecutionDB, BlockHeader), RLPDecodeError> {
let head_block_bytes = env::read::<Vec<u8>>();
let execution_db = env::read::<ExecutionDB>();
let parent_header_bytes = env::read::<Vec<u8>>();

let block = Block::decode(&head_block_bytes).unwrap();
let block = Block::decode(&head_block_bytes)?;
let parent_header = BlockHeader::decode(&parent_header_bytes)?;

// Make inputs public
// make inputs public
env::commit(&block);
env::commit(&execution_db);
env::commit(&parent_header);

// Execute block
let mut state = EvmState::from_exec_db(execution_db);
let block_receipts = execute_block(&block, &mut state).unwrap();
env::commit(&block_receipts);
Ok((block, execution_db, parent_header))
}

0 comments on commit 7f84c9e

Please sign in to comment.