Skip to content
This repository was archived by the owner on Feb 10, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 26 additions & 25 deletions blevm/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use celestia_types::{
use nmt_rs::simple_merkle::tree::MerkleHash;
use std::io::Read;
//use nmt_rs::{simple_merkle::proof::Proof, TmSha2Hasher};
use blevm_common::BlevmOutput;
use blevm_common::{BlevmInput, BlevmOutput};
use nmt_rs::{simple_merkle::proof::Proof, NamespacedHash, TmSha2Hasher};
use reth_primitives::Block;
use rsp_client_executor::{
Expand All @@ -21,26 +21,20 @@ use tendermint_proto::Protobuf;

pub fn main() {
println!("cycle-tracker-start: cloning and deserializing inputs");
let input: ClientExecutorInput = sp1_zkvm::io::read();
let namespace: Namespace = sp1_zkvm::io::read();
let celestia_header_hash: TmHash = sp1_zkvm::io::read();
let data_hash_bytes: Vec<u8> = sp1_zkvm::io::read_vec();
let data_hash: TmHash = TmHash::decode_vec(&data_hash_bytes).unwrap();
let proof_data_hash_to_celestia_hash: Proof<TmSha2Hasher> = sp1_zkvm::io::read();
let row_root_multiproof: Proof<TmSha2Hasher> = sp1_zkvm::io::read();
let nmt_multiproofs: Vec<NamespaceProof> = sp1_zkvm::io::read();
let row_roots: Vec<NamespacedHash<29>> = sp1_zkvm::io::read();

let block = input.current_block.clone();
let blevm_input: BlevmInput = sp1_zkvm::io::read();

let block = blevm_input.input.current_block.clone();
println!("cycle-tracker-end: cloning and deserializing inputs");

// Verify that the data root goes into the Celestia block hash
println!("cycle-tracker-start: verify data root");
let hasher = TmSha2Hasher {};
proof_data_hash_to_celestia_hash
blevm_input
.proof_data_hash_to_celestia_hash
.verify_range(
celestia_header_hash.as_bytes().try_into().unwrap(),
&[hasher.hash_leaf(&data_hash_bytes)],
&blevm_input.data_hash.clone().try_into().unwrap(),
&[hasher.hash_leaf(&blevm_input.data_hash.clone())],
)
.unwrap();
println!("cycle-tracker-end: verify data root");
Expand All @@ -50,7 +44,7 @@ pub fn main() {
println!("cycle-tracker-end: serializing EVM block");

println!("cycle-tracker-start: creating Blob");
let blob = Blob::new(namespace, block_bytes, AppVersion::V3).unwrap();
let blob = Blob::new(blevm_input.namespace, block_bytes, AppVersion::V3).unwrap();
println!("{}", hex::encode(blob.commitment.0));
println!("cycle-tracker-end: creating Blob");

Expand All @@ -61,11 +55,15 @@ pub fn main() {
// Verify NMT multiproofs of blob shares into row roots
println!("cycle-tracker-start: verify NMT multiproofs of blob shares into row roots");
let mut start = 0;
for i in 0..nmt_multiproofs.len() {
let proof = &nmt_multiproofs[i];
for i in 0..blevm_input.nmt_multiproofs.len() {
let proof = &blevm_input.nmt_multiproofs[i];
let end = start + (proof.end_idx() as usize - proof.start_idx() as usize);
proof
.verify_range(&row_roots[i], &shares[start..end], namespace.into())
.verify_range(
&blevm_input.row_roots[i],
&shares[start..end],
blevm_input.namespace.into(),
)
.expect("NMT multiproof into row root failed verification"); // Panicking should prevent an invalid proof from being generated
start = end;
}
Expand All @@ -74,20 +72,23 @@ pub fn main() {
// Verify row root inclusion into data root
println!("cycle-tracker-start: verify row root inclusion into data root");
let tm_hasher = TmSha2Hasher {};
let blob_row_root_hashes: Vec<[u8; 32]> = row_roots
let blob_row_root_hashes: Vec<[u8; 32]> = blevm_input
.row_roots
.iter()
.map(|root| tm_hasher.hash_leaf(&root.to_array()))
.collect();
let result = row_root_multiproof.verify_range(
data_hash.as_bytes().try_into().unwrap(),
let result = blevm_input.row_root_multiproof.verify_range(
&blevm_input.data_hash.try_into().unwrap(),
&blob_row_root_hashes,
);
println!("cycle-tracker-end: verify row root inclusion into data root");

// Execute the block
println!("cycle-tracker-start: executing EVM block");
let executor = ClientExecutor;
let header = executor.execute::<EthereumVariant>(input).unwrap(); // panicking should prevent a proof of invalid execution from being generated
let header = executor
.execute::<EthereumVariant>(blevm_input.input)
.unwrap(); // panicking should prevent a proof of invalid execution from being generated
println!("cycle-tracker-end: executing EVM block");

// Commit the header hash
Expand All @@ -97,13 +98,13 @@ pub fn main() {

let output = BlevmOutput {
blob_commitment: blob.commitment.0,
header_hash: header.hash_slow().into(),
prev_header_hash: header.parent_hash.into(),
evm_header_hash: header.hash_slow().into(),
prev_evm_header_hash: header.parent_hash.into(),
height: header.number,
gas_used: header.gas_used,
beneficiary: header.beneficiary.into(),
state_root: header.state_root.into(),
celestia_header_hash: celestia_header_hash.as_bytes().try_into().unwrap(),
celestia_header_hash: blevm_input.celestia_header_hash,
};
sp1_zkvm::io::commit(&output);

Expand Down
5 changes: 5 additions & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ edition = "2021"
[dependencies]
serde = { workspace = true }
bincode = { workspace = true }
celestia-types = { workspace = true }
tendermint = {workspace=true}
tendermint-proto = {workspace=true}
rsp-client-executor = {workspace=true}
nmt-rs = "*"
36 changes: 32 additions & 4 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,43 @@
use celestia_types::{nmt::Namespace, nmt::NamespaceProof, AppVersion, Blob};
use nmt_rs::{simple_merkle::proof::Proof, NamespacedHash, TmSha2Hasher};
use rsp_client_executor::{
io::ClientExecutorInput, ChainVariant, ClientExecutor, EthereumVariant, CHAIN_ID_ETH_MAINNET,
CHAIN_ID_LINEA_MAINNET, CHAIN_ID_OP_MAINNET,
};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct BlevmOutput {
pub struct BlevmInput {
// Fields shared with BlevmOutput
pub blob_commitment: [u8; 32],
pub header_hash: [u8; 32],
pub prev_header_hash: [u8; 32],
pub celestia_header_hash: [u8; 32],
pub state_root: [u8; 32],
pub evm_header_hash: [u8; 32],
pub prev_evm_header_hash: [u8; 32],
pub height: u64,
pub gas_used: u64,
pub beneficiary: [u8; 20],
pub state_root: [u8; 32],

// Additional fields specific to BlevmInput
pub input: ClientExecutorInput,
pub namespace: Namespace,
pub data_hash: [u8; 32],
pub proof_data_hash_to_celestia_hash: Proof<TmSha2Hasher>,
pub row_root_multiproof: Proof<TmSha2Hasher>,
pub nmt_multiproofs: Vec<NamespaceProof>,
pub row_roots: Vec<NamespacedHash<29>>,
}

#[derive(Serialize, Deserialize)]
pub struct BlevmOutput {
pub blob_commitment: [u8; 32],
pub celestia_header_hash: [u8; 32],
pub state_root: [u8; 32],
pub evm_header_hash: [u8; 32],
pub prev_evm_header_hash: [u8; 32],
pub height: u64,
pub gas_used: u64,
pub beneficiary: [u8; 20],
}

#[derive(Serialize, Deserialize)]
Expand Down
1 change: 1 addition & 0 deletions script/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ name = "blevm"
path = "src/bin/main.rs"

[dependencies]
blevm-common = { path = "../common" }
sp1-sdk = { workspace=true }
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
serde = { version = "1.0.200", default-features = false, features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion script/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use sp1_helper::build_program_with_args;

fn main() {
build_program_with_args("../blevm", Default::default())
//build_program_with_args("../blevm", Default::default())
}
30 changes: 29 additions & 1 deletion script/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use tendermint_proto::{
Protobuf,
};

use blevm_common::{BlevmInput, BlevmOutput};
use celestia_rpc::{BlobClient, Client, HeaderClient};
use core::cmp::max;
use rsp_client_executor::{
Expand All @@ -27,7 +28,8 @@ use sp1_sdk::{include_elf, ProverClient, SP1Stdin};
use std::fs;

/// The ELF (executable and linkable format) file for the Succinct RISC-V zkVM.
pub const BLEVM_ELF: &[u8] = include_elf!("blevm");
//pub const BLEVM_ELF: &[u8] = include_elf!("blevm");
pub const BLEVM_ELF: &[u8] = include_bytes!("../../../target/elf-compilation/riscv32im-succinct-zkvm-elf/release/blevm");

#[tokio::main]
async fn main() {
Expand Down Expand Up @@ -187,6 +189,31 @@ async fn main() {
// Setup the logger.
sp1_sdk::utils::setup_logger();

let input = BlevmInput{
blob_commitment: blob_from_chain.commitment.0,
celestia_header_hash: header.hash().as_bytes().try_into().unwrap(),
state_root: input.current_block.state_root.0.try_into().unwrap(),
evm_header_hash: input.current_block.header.hash_slow().0,
prev_evm_header_hash: input.parent_header().hash_slow().0,
height: input.current_block.number,
gas_used: input.current_block.gas_used,
beneficiary: input.current_block.beneficiary.0.try_into().unwrap(),
input: input,
namespace: namespace,
data_hash: data_hash_from_tree.as_bytes().try_into().unwrap(),
proof_data_hash_to_celestia_hash: data_hash_proof,
row_root_multiproof: row_root_multiproof,
nmt_multiproofs: nmt_multiproofs,
row_roots: eds_row_roots[first_row_index as usize..(last_row_index + 1) as usize].to_vec(),
};

let client = ProverClient::new();
let mut stdin = SP1Stdin::new();
stdin.write(&input);
let (output, report) = client.execute(BLEVM_ELF, stdin).run().unwrap();

/*

// Setup the prover client.
let client = ProverClient::new();

Expand All @@ -213,4 +240,5 @@ async fn main() {

let proof_bytes = bincode::serialize(&proof).expect("Failed to serialize proof");
fs::write("proof.bin", proof_bytes).expect("Failed to write proof to file");
*/
}
Loading