Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Str-727 Upgrade EL guest code to prove range of N blocks #533

Merged
merged 12 commits into from
Dec 20, 2024
Merged
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
4 changes: 3 additions & 1 deletion Cargo.lock

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

17 changes: 10 additions & 7 deletions bin/prover-client/src/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use strata_db::traits::ProofDatabase;
use strata_primitives::proof::{ProofContext, ProofKey, ProofZkVm};
use strata_proofimpl_evm_ee_stf::ELProofInput;
use strata_proofimpl_evm_ee_stf::EvmBlockStfInput;
use strata_rocksdb::{prover::db::ProofDb, DbOpsConfig};
use strata_state::l1::L1BlockId;
use strata_zkvm::{ProofReceipt, ProofType, ZkVmHost, ZkVmInputBuilder};
Expand All @@ -22,7 +22,6 @@
},
proving_ops::btc_ops::get_pm_rollup_params,
};

#[derive(Debug, Clone)]
#[allow(clippy::large_enum_variant)]
enum ProvingTaskState {
Expand Down Expand Up @@ -98,11 +97,15 @@
{
let (zkvm_input, proof_type) = match zkvm_input {
ZkVmInput::ElBlock(el_input) => {
let el_input: ELProofInput = bincode::deserialize(&el_input.data)?;
(
Vm::Input::new().write_serde(&el_input)?.build()?,
ProofType::Compressed,
)
let el_inputs: Vec<EvmBlockStfInput> = bincode::deserialize(&el_input.data)?;
let mut input_builder = Vm::Input::new();

input_builder.write_serde(&el_inputs.len())?;
for el_input in el_inputs {
input_builder.write_serde(&el_input)?;

Check warning on line 105 in bin/prover-client/src/prover.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/prover.rs#L100-L105

Added lines #L100 - L105 were not covered by tests
}

(input_builder.build()?, ProofType::Compressed)

Check warning on line 108 in bin/prover-client/src/prover.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/prover.rs#L108

Added line #L108 was not covered by tests
}

ZkVmInput::BtcBlock(block, rollup_params) => (
Expand Down
4 changes: 3 additions & 1 deletion bin/prover-client/src/proving_ops/cl_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@
task_tracker: Arc<TaskTracker>,
input: Self::Input,
) -> Result<Uuid, ProvingTaskError> {
let el_task_id = self.el_dispatcher.create_task(input.block_num).await?;
// Create proving task for the corresponding EL block
let el_block_range = (input.block_num, input.block_num);
MdTeach marked this conversation as resolved.
Show resolved Hide resolved
let el_task_id = self.el_dispatcher.create_task(el_block_range).await?;

Check warning on line 73 in bin/prover-client/src/proving_ops/cl_ops.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/proving_ops/cl_ops.rs#L72-L73

Added lines #L72 - L73 were not covered by tests

let prover_input = ZkVmInput::ClBlock(input);

Expand Down
47 changes: 27 additions & 20 deletions bin/prover-client/src/proving_ops/el_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use alloy_rpc_types::Block;
use async_trait::async_trait;
use jsonrpsee::{core::client::ClientT, http_client::HttpClient, rpc_params};
use strata_proofimpl_evm_ee_stf::ELProofInput;
use strata_proofimpl_evm_ee_stf::EvmBlockStfInput;
use tracing::debug;
use uuid::Uuid;

Expand All @@ -29,31 +29,38 @@

#[async_trait]
impl ProvingOperations for ElOperations {
/// Used serialized [`ELProofInput`] because [`ELProofInput::parent_state_trie`] contains
/// RefCell, which is not Sync or Send
/// Used serialized [`EvmBlockStfInput`] because [`EvmBlockStfInput::pre_state_trie`]
/// contains RefCell, which is not Sync or Send
type Input = Vec<u8>;
type Params = u64;
type Params = (u64, u64);

fn proving_task_type(&self) -> ProvingTaskType {
ProvingTaskType::EL
}

async fn fetch_input(&self, block_num: Self::Params) -> Result<Self::Input, anyhow::Error> {
debug!(%block_num, "Fetching EL block input");
let block: Block = self
.el_client
.request(
"eth_getBlockByNumber",
rpc_params![format!("0x{:x}", block_num), false],
)
.await?;
let block_hash = block.header.hash;
let witness: ELProofInput = self
.el_client
.request("strataee_getBlockWitness", rpc_params![block_hash, true])
.await?;
debug!("Fetched EL block witness for block {}", block_num);
Ok(bincode::serialize(&witness).unwrap())
async fn fetch_input(&self, block_range: Self::Params) -> Result<Self::Input, anyhow::Error> {
let (start_block_num, end_block_num) = block_range;
let mut el_proof_inputs: Vec<EvmBlockStfInput> = Vec::new();

Check warning on line 43 in bin/prover-client/src/proving_ops/el_ops.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/proving_ops/el_ops.rs#L41-L43

Added lines #L41 - L43 were not covered by tests

for block_num in start_block_num..=end_block_num {
let block: Block = self
.el_client
.request(
"eth_getBlockByNumber",
rpc_params![format!("0x{:x}", block_num), false],

Check warning on line 50 in bin/prover-client/src/proving_ops/el_ops.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/proving_ops/el_ops.rs#L45-L50

Added lines #L45 - L50 were not covered by tests
)
.await?;
let block_hash = block.header.hash;
let el_proof_input: EvmBlockStfInput = self
.el_client
.request("strataee_getBlockWitness", rpc_params![block_hash, true])
.await?;

Check warning on line 57 in bin/prover-client/src/proving_ops/el_ops.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/proving_ops/el_ops.rs#L52-L57

Added lines #L52 - L57 were not covered by tests

el_proof_inputs.push(el_proof_input);

Check warning on line 59 in bin/prover-client/src/proving_ops/el_ops.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/proving_ops/el_ops.rs#L59

Added line #L59 was not covered by tests
}

debug!("Fetched EL block witness for block {:?}", block_range);
Ok(bincode::serialize(&el_proof_inputs).unwrap())

Check warning on line 63 in bin/prover-client/src/proving_ops/el_ops.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/proving_ops/el_ops.rs#L62-L63

Added lines #L62 - L63 were not covered by tests
}

async fn append_task(
Expand Down
4 changes: 2 additions & 2 deletions bin/prover-client/src/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@
RpcResult::Ok(task_id)
}

async fn prove_el_block(&self, el_block_num: u64) -> RpcResult<Uuid> {
async fn prove_el_blocks(&self, block_range: (u64, u64)) -> RpcResult<Uuid> {

Check warning on line 117 in bin/prover-client/src/rpc_server.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/rpc_server.rs#L117

Added line #L117 was not covered by tests
let task_id = self
.context
.el_proving_task_dispatcher
.create_task(el_block_num)
.create_task(block_range)

Check warning on line 121 in bin/prover-client/src/rpc_server.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/rpc_server.rs#L121

Added line #L121 was not covered by tests
.await
.expect("failed to add proving task, el block");

Expand Down
1 change: 1 addition & 0 deletions bin/prover-client/src/zkvm/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use strata_proofimpl_cl_agg::process_cl_agg;
use strata_proofimpl_cl_stf::process_cl_stf;
use strata_proofimpl_evm_ee_stf::process_block_transaction_outer;
use strata_proofimpl_l1_batch::process_l1_batch_proof;
use strata_zkvm::ZkVmHost;

use crate::primitives::vms::ProofVm;

Expand Down
1 change: 1 addition & 0 deletions bin/prover-client/src/zkvm/risc0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use strata_risc0_guest_builder::{
GUEST_RISC0_BTC_BLOCKSPACE_ELF, GUEST_RISC0_CHECKPOINT_ELF, GUEST_RISC0_CL_AGG_ELF,
GUEST_RISC0_CL_STF_ELF, GUEST_RISC0_EVM_EE_STF_ELF, GUEST_RISC0_L1_BATCH_ELF,
};
use strata_zkvm::ZkVmHost;

use crate::primitives::vms::ProofVm;

Expand Down
55 changes: 18 additions & 37 deletions crates/proof-impl/cl-stf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
pub mod prover;

use borsh::{BorshDeserialize, BorshSerialize};
use strata_primitives::{buf::Buf32, evm_exec::create_evm_extra_payload, params::RollupParams};
use strata_proofimpl_evm_ee_stf::ELProofPublicParams;
use strata_primitives::{buf::Buf32, params::RollupParams};
use strata_state::{
block::ExecSegment,
block_validation::{check_block_credential, validate_block_segments},
exec_update::{ExecUpdate, UpdateInput, UpdateOutput},
id::L2BlockId,
tx::DepositInfo,
};
Expand Down Expand Up @@ -41,19 +39,15 @@
pub fn verify_and_transition(
prev_chstate: Chainstate,
new_l2_block: L2Block,
el_proof_pp: ELProofPublicParams,
exec_segment: &ExecSegment,
rollup_params: &RollupParams,
) -> Chainstate {
verify_l2_block(&new_l2_block, &el_proof_pp, rollup_params);
verify_l2_block(&new_l2_block, exec_segment, rollup_params);
apply_state_transition(prev_chstate, &new_l2_block, rollup_params)
}

/// Verifies the L2 block.
fn verify_l2_block(
block: &L2Block,
el_proof_pp: &ELProofPublicParams,
chain_params: &RollupParams,
) {
fn verify_l2_block(block: &L2Block, exec_segment: &ExecSegment, chain_params: &RollupParams) {
// Assert that the block has been signed by the designated signer
assert!(
check_block_credential(block.header(), chain_params),
Expand All @@ -67,25 +61,8 @@
);

// Verify proof public params matches the exec segment
let proof_exec_segment = reconstruct_exec_segment(el_proof_pp);
let block_exec_segment = block.body().exec_segment().clone();
assert_eq!(proof_exec_segment, block_exec_segment);
}

/// Generates an execution segment from the given ELProof public parameters.
pub fn reconstruct_exec_segment(el_proof_pp: &ELProofPublicParams) -> ExecSegment {
// create_evm_extra_payload
let update_input = UpdateInput::new(
el_proof_pp.block_idx,
Vec::new(),
Buf32(*el_proof_pp.txn_root),
create_evm_extra_payload(Buf32(*el_proof_pp.new_blockhash)),
);

let update_output = UpdateOutput::new_from_state(Buf32(*el_proof_pp.new_state_root));
let exec_update = ExecUpdate::new(update_input, update_output);

ExecSegment::new(exec_update)
let block_exec_segment = block.body().exec_segment();
assert_eq!(exec_segment, block_exec_segment);
}

/// Applies a state transition for a given L2 block.
Expand All @@ -110,17 +87,21 @@
pub fn process_cl_stf(zkvm: &impl ZkVmEnv, el_vkey: &[u32; 8]) {
let rollup_params: RollupParams = zkvm.read_serde();
let (prev_state, block): (Chainstate, L2Block) = zkvm.read_borsh();
let el_pp_deserialized: Vec<ExecSegment> = zkvm.read_verified_borsh(el_vkey);

// Read the EL proof output
let el_pp_deserialized: ELProofPublicParams = zkvm.read_verified_serde(el_vkey);

let new_state = verify_and_transition(
prev_state.clone(),
block,
el_pp_deserialized,
&rollup_params,
// The CL block currently includes only a single ExecSegment
assert_eq!(
el_pp_deserialized.len(),
1,
"execsegment: expected exactly one"

Check warning on line 96 in crates/proof-impl/cl-stf/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

crates/proof-impl/cl-stf/src/lib.rs#L96

Added line #L96 was not covered by tests
);

let exec_update = el_pp_deserialized
.first()
.expect("execsegment: failed to fetch the first");

let new_state = verify_and_transition(prev_state.clone(), block, exec_update, &rollup_params);

let initial_snapshot = ChainStateSnapshot {
hash: prev_state.compute_state_root(),
slot: prev_state.chain_tip_slot(),
Expand Down
2 changes: 2 additions & 0 deletions crates/proof-impl/evm-ee-stf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ name = "strata-proofimpl-evm-ee-stf"
version = "0.1.0"

[dependencies]
strata-primitives.workspace = true
strata-reth-evm.workspace = true
strata-reth-primitives.workspace = true
strata-state.workspace = true
strata-zkvm.workspace = true

alloy-consensus = { workspace = true, features = ["serde-bincode-compat"] }
Expand Down
14 changes: 7 additions & 7 deletions crates/proof-impl/evm-ee-stf/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ use revm::{

use crate::{
mpt::{keccak, StateAccount, KECCAK_EMPTY},
ELProofInput,
EvmBlockStfInput,
};

/// A helper trait to extend [`InMemoryDB`] with additional functionality.
pub trait InMemoryDBHelper {
/// Create an [`InMemoryDB`] from a given [`ELProofInput`].
fn initialize(input: &mut ELProofInput) -> Result<Self>
/// Create an [`InMemoryDB`] from a given [`EvmBlockStfInput`].
fn initialize(input: &mut EvmBlockStfInput) -> Result<Self>
where
Self: Sized;

Expand All @@ -53,7 +53,7 @@ pub trait InMemoryDBHelper {
}

impl InMemoryDBHelper for InMemoryDB {
fn initialize(input: &mut ELProofInput) -> Result<Self> {
fn initialize(input: &mut EvmBlockStfInput) -> Result<Self> {
// For each contract's byte code, hash it and store it in a map.
let contracts: HashMap<B256, Bytes> = input
.contracts
Expand All @@ -63,12 +63,12 @@ impl InMemoryDBHelper for InMemoryDB {

// For each account, load the information into the database.
let mut accounts = HashMap::with_capacity_and_hasher(
input.parent_storage.len(),
input.pre_state_storage.len(),
DefaultHashBuilder::default(),
);
for (address, (storage_trie, slots)) in &mut input.parent_storage {
for (address, (storage_trie, slots)) in &mut input.pre_state_storage {
let state_account = input
.parent_state_trie
.pre_state_trie
.get_rlp::<StateAccount>(&keccak(address))?
.unwrap_or_default();

Expand Down
Loading
Loading