Skip to content

Commit

Permalink
STR-799: Upgrade CL guest code to prove range of N blocks (#563)
Browse files Browse the repository at this point in the history
* refactor ol range changes

* feat make the cl range on block_ids

* cl blocks batching tests fix

* rpc updates

* cl range fix functional test

* invalid witness error

* add util for blkidx_to_blkid in functional test

* review fix
  • Loading branch information
MdTeach authored Jan 5, 2025
1 parent ef1097b commit 207944a
Show file tree
Hide file tree
Showing 32 changed files with 468 additions and 269 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

8 changes: 8 additions & 0 deletions bin/prover-client/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ pub enum ProvingTaskError {
#[error("Witness not found")]
WitnessNotFound,

/// Occurs when a newly created proving task is expected but none is found.
#[error("No tasks found after creation; at least one was expected")]
NoTasksFound,

/// Occurs when the witness data provided is invalid.
#[error("{0}")]
InvalidWitness(String),

/// Represents a generic database error.
#[error("Database error: {0:?}")]
DatabaseError(DbError),
Expand Down
16 changes: 8 additions & 8 deletions bin/prover-client/src/hosts/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use strata_primitives::proof::ProofContext;
use strata_proofimpl_btc_blockspace::logic::process_blockspace_proof_outer;
use strata_proofimpl_checkpoint::process_checkpoint_proof_outer;
use strata_proofimpl_cl_agg::process_cl_agg;
use strata_proofimpl_cl_stf::process_cl_stf;
use strata_proofimpl_cl_stf::batch_process_cl_stf;
use strata_proofimpl_evm_ee_stf::process_block_transaction_outer;
use strata_proofimpl_l1_batch::process_l1_batch_proof;

Expand All @@ -22,37 +22,37 @@ const MOCK_VK: [u32; 8] = [0u32; 8];
/// allowing for efficient host selection for different proof types.
pub fn get_host(id: &ProofContext) -> NativeHost {
match id {
ProofContext::BtcBlockspace(_) => NativeHost {
ProofContext::BtcBlockspace(..) => NativeHost {
process_proof: Arc::new(Box::new(move |zkvm: &NativeMachine| {
process_blockspace_proof_outer(zkvm);
Ok(())
})),
},
ProofContext::L1Batch(_, _) => NativeHost {
ProofContext::L1Batch(..) => NativeHost {
process_proof: Arc::new(Box::new(move |zkvm: &NativeMachine| {
process_l1_batch_proof(zkvm, &MOCK_VK);
Ok(())
})),
},
ProofContext::EvmEeStf(_, _) => NativeHost {
ProofContext::EvmEeStf(..) => NativeHost {
process_proof: Arc::new(Box::new(move |zkvm: &NativeMachine| {
process_block_transaction_outer(zkvm);
Ok(())
})),
},
ProofContext::ClStf(_) => NativeHost {
ProofContext::ClStf(..) => NativeHost {
process_proof: Arc::new(Box::new(move |zkvm: &NativeMachine| {
process_cl_stf(zkvm, &MOCK_VK);
batch_process_cl_stf(zkvm, &MOCK_VK);
Ok(())
})),
},
ProofContext::ClAgg(_, _) => NativeHost {
ProofContext::ClAgg(..) => NativeHost {
process_proof: Arc::new(Box::new(move |zkvm: &NativeMachine| {
process_cl_agg(zkvm, &MOCK_VK);
Ok(())
})),
},
ProofContext::Checkpoint(_) => NativeHost {
ProofContext::Checkpoint(..) => NativeHost {
process_proof: Arc::new(Box::new(move |zkvm: &NativeMachine| {
process_checkpoint_proof_outer(zkvm, &MOCK_VK, &MOCK_VK);
Ok(())
Expand Down
12 changes: 6 additions & 6 deletions bin/prover-client/src/hosts/risc0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ static CHECKPOINT_HOST: LazyLock<Risc0Host> =
/// instance, allowing for efficient host selection for different proof types.
pub fn get_host(id: &ProofContext) -> &'static Risc0Host {
match id {
ProofContext::BtcBlockspace(_) => &BTC_BLOCKSPACE_HOST,
ProofContext::L1Batch(_, _) => &L1_BATCH_HOST,
ProofContext::EvmEeStf(_, _) => &EVM_EE_STF_HOST,
ProofContext::ClStf(_) => &CL_STF_HOST,
ProofContext::ClAgg(_, _) => &CL_AGG_HOST,
ProofContext::Checkpoint(_) => &CHECKPOINT_HOST,
ProofContext::BtcBlockspace(..) => &BTC_BLOCKSPACE_HOST,
ProofContext::L1Batch(..) => &L1_BATCH_HOST,
ProofContext::EvmEeStf(..) => &EVM_EE_STF_HOST,
ProofContext::ClStf(..) => &CL_STF_HOST,
ProofContext::ClAgg(..) => &CL_AGG_HOST,
ProofContext::Checkpoint(..) => &CHECKPOINT_HOST,
}
}
12 changes: 6 additions & 6 deletions bin/prover-client/src/hosts/sp1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ pub static CHECKPOINT_HOST: LazyLock<SP1Host> = std::sync::LazyLock::new(|| {
/// instance, allowing for efficient host selection for different proof types.
pub fn get_host(id: &ProofContext) -> &'static SP1Host {
match id {
ProofContext::BtcBlockspace(_) => &BTC_BLOCKSPACE_HOST,
ProofContext::L1Batch(_, _) => &L1_BATCH_HOST,
ProofContext::EvmEeStf(_, _) => &EVM_EE_STF_HOST,
ProofContext::ClStf(_) => &CL_STF_HOST,
ProofContext::ClAgg(_, _) => &CL_AGG_HOST,
ProofContext::Checkpoint(_) => &CHECKPOINT_HOST,
ProofContext::BtcBlockspace(..) => &BTC_BLOCKSPACE_HOST,
ProofContext::L1Batch(..) => &L1_BATCH_HOST,
ProofContext::EvmEeStf(..) => &EVM_EE_STF_HOST,
ProofContext::ClStf(..) => &CL_STF_HOST,
ProofContext::ClAgg(..) => &CL_AGG_HOST,
ProofContext::Checkpoint(..) => &CHECKPOINT_HOST,
}
}
47 changes: 44 additions & 3 deletions bin/prover-client/src/operators/checkpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ use std::sync::Arc;
use jsonrpsee::http_client::HttpClient;
use strata_db::traits::ProofDatabase;
use strata_primitives::{
buf::Buf32,
params::RollupParams,
proof::{ProofContext, ProofKey},
};
use strata_proofimpl_checkpoint::prover::{CheckpointProver, CheckpointProverInput};
use strata_rocksdb::prover::db::ProofDb;
use strata_rpc_api::StrataApiClient;
use strata_rpc_types::RpcCheckpointInfo;
use strata_state::id::L2BlockId;
use strata_zkvm::AggregationInput;
use tokio::sync::Mutex;
use tracing::error;
Expand Down Expand Up @@ -59,6 +61,31 @@ impl CheckpointOperator {
.ok_or(ProvingTaskError::WitnessNotFound)
}

/// Retrieves the [`L2BlockId`] for the given `block_num`
pub async fn get_l2id(&self, block_num: u64) -> Result<L2BlockId, ProvingTaskError> {
let l2_headers = self
.cl_client
.get_headers_at_idx(block_num)
.await
.inspect_err(|_| error!(%block_num, "Failed to fetch l2_headers"))
.map_err(|e| ProvingTaskError::RpcError(e.to_string()))?;

let headers = l2_headers.ok_or_else(|| {
error!(%block_num, "Failed to fetch L2 block");
ProvingTaskError::InvalidWitness(format!("Invalid L2 block height {}", block_num))
})?;

let first_header: Buf32 = headers
.first()
.ok_or_else(|| {
ProvingTaskError::InvalidWitness(format!("Invalid L2 block height {}", block_num))
})?
.block_id
.into();

Ok(first_header.into())
}

/// Retrieves the latest checkpoint index
pub async fn fetch_latest_ckp_idx(&self) -> Result<u64, ProvingTaskError> {
self.cl_client
Expand Down Expand Up @@ -88,13 +115,27 @@ impl ProvingOp for CheckpointOperator {
.l1_batch_operator
.create_task(checkpoint_info.l1_range, task_tracker.clone(), db)
.await?;
let l1_batch_id = l1_batch_keys.first().expect("at least one").context();
let l1_batch_id = l1_batch_keys
.first()
.ok_or_else(|| ProvingTaskError::NoTasksFound)?
.context();

// Doing the manual block idx to id transformation. Will be removed once checkpoint_info
// include the range in terms of block_id.
// https://alpenlabs.atlassian.net/browse/STR-756
let start_l2_idx = self.get_l2id(checkpoint_info.l2_range.0).await?;
let end_l2_idx = self.get_l2id(checkpoint_info.l2_range.1).await?;
let l2_range = vec![(start_l2_idx, end_l2_idx)];

let l2_batch_keys = self
.l2_batch_operator
.create_task(checkpoint_info.l2_range, task_tracker.clone(), db)
.create_task(l2_range, task_tracker.clone(), db)
.await?;
let l2_batch_id = l2_batch_keys.first().expect("at least one").context();

let l2_batch_id = l2_batch_keys
.first()
.ok_or_else(|| ProvingTaskError::NoTasksFound)?
.context();

let deps = vec![*l1_batch_id, *l2_batch_id];

Expand Down
33 changes: 20 additions & 13 deletions bin/prover-client/src/operators/cl_agg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use strata_db::traits::ProofDatabase;
use strata_primitives::proof::{ProofContext, ProofKey};
use strata_proofimpl_cl_agg::{ClAggInput, ClAggProver};
use strata_rocksdb::prover::db::ProofDb;
use strata_state::id::L2BlockId;
use tokio::sync::Mutex;
use tracing::error;

use super::{cl_stf::ClStfOperator, ProvingOp};
use crate::{errors::ProvingTaskError, hosts, task_tracker::TaskTracker};
Expand All @@ -29,28 +31,33 @@ impl ClAggOperator {

impl ProvingOp for ClAggOperator {
type Prover = ClAggProver;
type Params = (u64, u64);
type Params = Vec<(L2BlockId, L2BlockId)>;

async fn create_task(
&self,
params: (u64, u64),
batches: Self::Params,
task_tracker: Arc<Mutex<TaskTracker>>,
db: &ProofDb,
) -> Result<Vec<ProofKey>, ProvingTaskError> {
let (start_height, end_height) = params;
let mut cl_stf_deps = Vec::with_capacity(batches.len());

let len = (end_height - start_height) as usize + 1;
let mut cl_stf_deps = Vec::with_capacity(len);
// Extract first and last block IDs from batches, error if empty
let (start_blkid, end_blkid) = match (batches.first(), batches.last()) {
(Some(first), Some(last)) => (first.0, last.1),
_ => {
error!("Aggregation task with empty batch");
return Err(ProvingTaskError::InvalidInput(
"Aggregation task with empty batch".into(),
));
}
};

let start_blkid = self.cl_stf_operator.get_id(start_height).await?;
let end_blkid = self.cl_stf_operator.get_id(end_height).await?;
let cl_agg_proof_id = ProofContext::ClAgg(start_blkid, end_blkid);

for height in start_height..=end_height {
let blkid = self.cl_stf_operator.get_id(height).await?;
let proof_id = ProofContext::ClStf(blkid);
for (start_blkid, end_blkid) in batches {
let proof_id = ProofContext::ClStf(start_blkid, end_blkid);
self.cl_stf_operator
.create_task(height, task_tracker.clone(), db)
.create_task((start_blkid, end_blkid), task_tracker.clone(), db)
.await?;
cl_stf_deps.push(proof_id);
}
Expand All @@ -67,7 +74,7 @@ impl ProvingOp for ClAggOperator {
task_id: &ProofKey,
db: &ProofDb,
) -> Result<ClAggInput, ProvingTaskError> {
let (start_blkid, _) = match task_id.context() {
let (start_blkid, end_blkid) = match task_id.context() {
ProofContext::ClAgg(start, end) => (start, end),
_ => return Err(ProvingTaskError::InvalidInput("ClAgg".to_string())),
};
Expand All @@ -88,7 +95,7 @@ impl ProvingOp for ClAggOperator {
}

let cl_stf_vk = hosts::get_verification_key(&ProofKey::new(
ProofContext::ClStf(*start_blkid),
ProofContext::ClStf(*start_blkid, *end_blkid),
*task_id.host(),
));
Ok(ClAggInput { batch, cl_stf_vk })
Expand Down
Loading

0 comments on commit 207944a

Please sign in to comment.