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

L1-Scan guest code to prove range of N blocks #541

Merged
merged 6 commits into from
Jan 7, 2025
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
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.

2 changes: 1 addition & 1 deletion bin/prover-client/src/hosts/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
},
ProofContext::L1Batch(..) => NativeHost {
process_proof: Arc::new(Box::new(move |zkvm: &NativeMachine| {
process_l1_batch_proof(zkvm, &MOCK_VK);
process_l1_batch_proof(zkvm);

Check warning on line 33 in bin/prover-client/src/hosts/native.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/hosts/native.rs#L33

Added line #L33 was not covered by tests
Ok(())
})),
},
Expand Down
32 changes: 13 additions & 19 deletions bin/prover-client/src/operators/btc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
params::RollupParams,
proof::{ProofContext, ProofKey},
};
use strata_proofimpl_btc_blockspace::{logic::BlockspaceProofInput, prover::BtcBlockspaceProver};
use strata_proofimpl_btc_blockspace::{logic::BlockScanProofInput, prover::BtcBlockspaceProver};
use strata_rocksdb::prover::db::ProofDb;
use strata_state::l1::L1BlockId;
use tokio::sync::Mutex;
Expand All @@ -32,30 +32,19 @@
rollup_params,
}
}

/// Retrieves the [`L1BlockId`] for a given block number.
pub async fn get_id(&self, block_num: u64) -> Result<L1BlockId, ProvingTaskError> {
Ok(self
.btc_client
.get_block_hash(block_num)
.await
.inspect_err(|_| error!(%block_num, "Failed to fetch BTC BlockId"))
.map_err(|e| ProvingTaskError::RpcError(e.to_string()))?
.into())
}
}

impl ProvingOp for BtcBlockspaceOperator {
type Prover = BtcBlockspaceProver;
type Params = u64;
type Params = L1BlockId;

async fn create_task(
&self,
block_num: u64,
block_id: Self::Params,

Check warning on line 43 in bin/prover-client/src/operators/btc.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/btc.rs#L43

Added line #L43 was not covered by tests
task_tracker: Arc<Mutex<TaskTracker>>,
_db: &ProofDb,
) -> Result<Vec<ProofKey>, ProvingTaskError> {
let context = ProofContext::BtcBlockspace(self.get_id(block_num).await?);
let context = ProofContext::BtcBlockspace(block_id);

Check warning on line 47 in bin/prover-client/src/operators/btc.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/btc.rs#L47

Added line #L47 was not covered by tests
let mut task_tracker = task_tracker.lock().await;
task_tracker.create_tasks(context, vec![])
}
Expand All @@ -64,15 +53,20 @@
&self,
task_id: &ProofKey,
_db: &ProofDb,
) -> Result<BlockspaceProofInput, ProvingTaskError> {
let blkid = match task_id.context() {
) -> Result<BlockScanProofInput, ProvingTaskError> {
let block_id = match task_id.context() {

Check warning on line 57 in bin/prover-client/src/operators/btc.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/btc.rs#L56-L57

Added lines #L56 - L57 were not covered by tests
ProofContext::BtcBlockspace(id) => *id,
_ => return Err(ProvingTaskError::InvalidInput("BtcBlockspace".to_string())),
};

let block = self.btc_client.get_block(&blkid.into()).await.unwrap();
let block = self
.btc_client
.get_block(&block_id.into())
.await
.inspect_err(|_| error!(%block_id, "Failed to fetch BTC BlockId"))
.map_err(|e| ProvingTaskError::RpcError(e.to_string()))?;

Check warning on line 67 in bin/prover-client/src/operators/btc.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/btc.rs#L62-L67

Added lines #L62 - L67 were not covered by tests

Ok(BlockspaceProofInput {
Ok(BlockScanProofInput {

Check warning on line 69 in bin/prover-client/src/operators/btc.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/btc.rs#L69

Added line #L69 was not covered by tests
rollup_params: self.rollup_params.as_ref().clone(),
block,
})
Expand Down
18 changes: 17 additions & 1 deletion bin/prover-client/src/operators/checkpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,25 @@

let ckp_proof_id = ProofContext::Checkpoint(ckp_idx);

// 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_l1_block_id = self
.l1_batch_operator
.get_block_at(checkpoint_info.l1_range.0)
.await?;
let end_l1_block_id = self
.l1_batch_operator
.get_block_at(checkpoint_info.l1_range.1)
.await?;

Check warning on line 124 in bin/prover-client/src/operators/checkpoint.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/checkpoint.rs#L117-L124

Added lines #L117 - L124 were not covered by tests

let l1_batch_keys = self
.l1_batch_operator
.create_task(checkpoint_info.l1_range, task_tracker.clone(), db)
.create_task(
(start_l1_block_id, end_l1_block_id),
task_tracker.clone(),
db,
)

Check warning on line 132 in bin/prover-client/src/operators/checkpoint.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/checkpoint.rs#L128-L132

Added lines #L128 - L132 were not covered by tests
.await?;
let l1_batch_id = l1_batch_keys
.first()
Expand Down
162 changes: 81 additions & 81 deletions bin/prover-client/src/operators/l1_batch.rs
Original file line number Diff line number Diff line change
@@ -1,128 +1,133 @@
use std::sync::Arc;

use bitcoin::params::MAINNET;
use bitcoin::{params::MAINNET, Block};
use strata_btcio::{
reader::query::get_verification_state,
rpc::{
traits::{Reader, Wallet},
BitcoinClient,
},
};
use strata_db::traits::ProofDatabase;
use strata_primitives::proof::{ProofContext, ProofKey};
use strata_primitives::{
params::RollupParams,
proof::{ProofContext, ProofKey},
};
use strata_proofimpl_l1_batch::{L1BatchProofInput, L1BatchProver};
use strata_rocksdb::prover::db::ProofDb;
use strata_state::l1::L1BlockId;
use tokio::sync::Mutex;
use tracing::error;

use super::{btc::BtcBlockspaceOperator, ProvingOp};
use crate::{errors::ProvingTaskError, hosts, task_tracker::TaskTracker};
use super::ProvingOp;
use crate::{errors::ProvingTaskError, task_tracker::TaskTracker};

/// A struct that implements the [`ProvingOp`] trait for L1 Batch Proof generation.
///
/// It is responsible for managing the data and tasks required to generate proofs for L1 Batch. It
/// It is responsible for managing the data to generate proofs for L1 Batch. It
/// fetches the necessary inputs for the [`L1BatchProver`] by:
///
/// - Utilizing the [`BtcBlockspaceOperator`] to create and manage proving tasks for BTC Blockspace.
/// The resulting BTC Blockspace proofs are incorporated as part of the input for the CL STF
/// proof.
/// - Fetching the Bitcoin blocks and verification state for the given block range.
/// - Interfacing with the Bitcoin Client to fetch additional required information for batch proofs.
#[derive(Debug, Clone)]
pub struct L1BatchOperator {
btc_client: Arc<BitcoinClient>,
btc_blockspace_operator: Arc<BtcBlockspaceOperator>,
rollup_params: Arc<RollupParams>,
}

impl L1BatchOperator {
pub fn new(
btc_client: Arc<BitcoinClient>,
btc_blockspace_operator: Arc<BtcBlockspaceOperator>,
) -> Self {
pub fn new(btc_client: Arc<BitcoinClient>, rollup_params: Arc<RollupParams>) -> Self {

Check warning on line 37 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L37

Added line #L37 was not covered by tests
Self {
btc_client,
btc_blockspace_operator,
rollup_params,

Check warning on line 40 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L40

Added line #L40 was not covered by tests
}
}

async fn get_block(&self, block_id: L1BlockId) -> Result<bitcoin::Block, ProvingTaskError> {
self.btc_client
.get_block(&block_id.into())
.await
.inspect_err(|_| error!(%block_id, "Failed to fetch BTC block"))
.map_err(|e| ProvingTaskError::RpcError(e.to_string()))
}

Check warning on line 50 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L44-L50

Added lines #L44 - L50 were not covered by tests

async fn get_block_height(&self, block_id: L1BlockId) -> Result<u64, ProvingTaskError> {
let block = self.get_block(block_id).await?;

Check warning on line 53 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L52-L53

Added lines #L52 - L53 were not covered by tests

let block_height = self
.btc_client
.get_transaction(&block.coinbase().expect("expect coinbase tx").compute_txid())
.await
.map_err(|e| ProvingTaskError::RpcError(e.to_string()))?
.block_height();

Ok(block_height)
}

Check warning on line 63 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L55-L63

Added lines #L55 - L63 were not covered by tests

/// Retrieves the specified number of ancestor block IDs for the given block ID.
async fn get_block_ancestors(
&self,
block_id: L1BlockId,
n_ancestors: u64,
) -> Result<Vec<Block>, ProvingTaskError> {
let mut ancestors = Vec::with_capacity(n_ancestors as usize);
let mut block_id = block_id;
for _ in 0..=n_ancestors {
let block = self.get_block(block_id).await?;
block_id = block.header.prev_blockhash.into();
ancestors.push(block);

Check warning on line 76 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L66-L76

Added lines #L66 - L76 were not covered by tests
}

Ok(ancestors)
}

Check warning on line 80 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L79-L80

Added lines #L79 - L80 were not covered by tests

/// Retrieves the block ID at the specified height.
///
/// Note: This function will be removed once checkpoint_info includes the block ID range.
/// Currently, it requires a manual L1 block index-to-ID conversion by the checkpoint operator.
// https://alpenlabs.atlassian.net/browse/STR-756
pub async fn get_block_at(&self, height: u64) -> Result<L1BlockId, ProvingTaskError> {
let block_hash = self
.btc_client
.get_block_hash(height)
.await
.map_err(|e| ProvingTaskError::RpcError(e.to_string()))?;
Ok(block_hash.into())
}

Check warning on line 94 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L87-L94

Added lines #L87 - L94 were not covered by tests
}

impl ProvingOp for L1BatchOperator {
type Prover = L1BatchProver;
type Params = (u64, u64);
type Params = (L1BlockId, L1BlockId);

async fn create_task(
&self,
params: (u64, u64),
params: Self::Params,

Check warning on line 103 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L103

Added line #L103 was not covered by tests
task_tracker: Arc<Mutex<TaskTracker>>,
db: &ProofDb,
_db: &ProofDb,

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

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L105

Added line #L105 was not covered by tests
) -> Result<Vec<ProofKey>, ProvingTaskError> {
let (start_height, end_height) = params;

let len = (end_height - start_height) as usize + 1;
let mut btc_deps = Vec::with_capacity(len);

let start_blkid = self.btc_blockspace_operator.get_id(start_height).await?;
let end_blkid = self.btc_blockspace_operator.get_id(end_height).await?;
let (start_blkid, end_blkid) = params;

Check warning on line 107 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L107

Added line #L107 was not covered by tests
let l1_batch_proof_id = ProofContext::L1Batch(start_blkid, end_blkid);

for height in start_height..=end_height {
let blkid = self.btc_blockspace_operator.get_id(height).await?;
let proof_id = ProofContext::BtcBlockspace(blkid);
self.btc_blockspace_operator
.create_task(height, task_tracker.clone(), db)
.await?;
btc_deps.push(proof_id);
}

db.put_proof_deps(l1_batch_proof_id, btc_deps.clone())
.map_err(ProvingTaskError::DatabaseError)?;

let mut task_tracker = task_tracker.lock().await;
task_tracker.create_tasks(l1_batch_proof_id, btc_deps)
task_tracker.create_tasks(l1_batch_proof_id, vec![])

Check warning on line 111 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L111

Added line #L111 was not covered by tests
}

async fn fetch_input(
&self,
task_id: &ProofKey,
db: &ProofDb,
_db: &ProofDb,

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

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L117

Added line #L117 was not covered by tests
) -> Result<L1BatchProofInput, ProvingTaskError> {
let (start_blkid, _) = match task_id.context() {
ProofContext::L1Batch(start, end) => (*start, end),
let (start_block_id, end_block_id) = match task_id.context() {
ProofContext::L1Batch(start, end) => (*start, *end),

Check warning on line 120 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L119-L120

Added lines #L119 - L120 were not covered by tests
_ => return Err(ProvingTaskError::InvalidInput("L1Batch".to_string())),
};

let deps = db
.get_proof_deps(*task_id.context())
.map_err(ProvingTaskError::DatabaseError)?
.ok_or(ProvingTaskError::DependencyNotFound(*task_id))?;

let mut batch = Vec::new();
for proof_id in deps {
let proof_key = ProofKey::new(proof_id, *task_id.host());
let proof = db
.get_proof(proof_key)
.map_err(ProvingTaskError::DatabaseError)?
.ok_or(ProvingTaskError::ProofNotFound(proof_key))?;
batch.push(proof);
}
let start_height = self.get_block_height(start_block_id).await?;
let end_height = self.get_block_height(end_block_id).await?;
let num_blocks = end_height - start_height;

Check warning on line 126 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L124-L126

Added lines #L124 - L126 were not covered by tests

let start_block = self
.btc_client
.get_block(&start_blkid.into())
.await
.inspect_err(|_| error!(%start_blkid, "Failed to fetch BTC block"))
.map_err(|e| ProvingTaskError::RpcError(e.to_string()))?;

let start_height = self
.btc_client
.get_transaction(
&start_block
.coinbase()
.expect("expect coinbase tx")
.compute_txid(),
)
.await
.map_err(|e| ProvingTaskError::RpcError(e.to_string()))?
.block_height();
// Get ancestor blocks and reverse to oldest-first order
let mut blocks = self.get_block_ancestors(end_block_id, num_blocks).await?;
blocks.reverse();

Check warning on line 130 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L129-L130

Added lines #L129 - L130 were not covered by tests

let state = get_verification_state(
self.btc_client.as_ref(),
Expand All @@ -132,15 +137,10 @@
.await
.map_err(|e| ProvingTaskError::RpcError(e.to_string()))?;

let blockspace_vk = hosts::get_verification_key(&ProofKey::new(
ProofContext::BtcBlockspace(start_blkid),
*task_id.host(),
));

Ok(L1BatchProofInput {
batch,
blocks,

Check warning on line 141 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L141

Added line #L141 was not covered by tests
state,
blockspace_vk,
rollup_params: self.rollup_params.as_ref().clone(),

Check warning on line 143 in bin/prover-client/src/operators/l1_batch.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/l1_batch.rs#L143

Added line #L143 was not covered by tests
})
}
}
5 changes: 1 addition & 4 deletions bin/prover-client/src/operators/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,7 @@
// Create each operator using the respective clients.
let btc_blockspace_operator =
BtcBlockspaceOperator::new(btc_client.clone(), rollup_params.clone());
let l1_batch_operator = L1BatchOperator::new(
btc_client.clone(),
Arc::new(btc_blockspace_operator.clone()),
);
let l1_batch_operator = L1BatchOperator::new(btc_client.clone(), rollup_params.clone());

Check warning on line 67 in bin/prover-client/src/operators/operator.rs

View check run for this annotation

Codecov / codecov/patch

bin/prover-client/src/operators/operator.rs#L67

Added line #L67 was not covered by tests
let evm_ee_operator = EvmEeOperator::new(evm_ee_client.clone());
let cl_stf_operator = ClStfOperator::new(
cl_client.clone(),
Expand Down
8 changes: 4 additions & 4 deletions bin/prover-client/src/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use strata_prover_client_rpc_api::StrataProverClientApiServer;
use strata_rocksdb::prover::db::ProofDb;
use strata_rpc_types::ProofKey;
use strata_state::id::L2BlockId;
use strata_state::{id::L2BlockId, l1::L1BlockId};
use tokio::sync::{oneshot, Mutex};
use tracing::{info, warn};

Expand Down Expand Up @@ -80,11 +80,11 @@

#[async_trait]
impl StrataProverClientApiServer for ProverClientRpc {
async fn prove_btc_block(&self, btc_block_num: u64) -> RpcResult<Vec<ProofKey>> {
async fn prove_btc_block(&self, block_id: L1BlockId) -> RpcResult<Vec<ProofKey>> {

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

View check run for this annotation

Codecov / codecov/patch

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

Added line #L83 was not covered by tests
Ok(self
.operator
.btc_operator()
.create_task(btc_block_num, self.task_tracker.clone(), &self.db)
.create_task(block_id, self.task_tracker.clone(), &self.db)

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

View check run for this annotation

Codecov / codecov/patch

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

Added line #L87 was not covered by tests
.await
.expect("failed to create task"))
}
Expand All @@ -110,7 +110,7 @@
.expect("failed to create task"))
}

async fn prove_l1_batch(&self, l1_range: (u64, u64)) -> RpcResult<Vec<ProofKey>> {
async fn prove_l1_batch(&self, l1_range: (L1BlockId, L1BlockId)) -> RpcResult<Vec<ProofKey>> {

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

View check run for this annotation

Codecov / codecov/patch

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

Added line #L113 was not covered by tests
Ok(self
.operator
.l1_batch_operator()
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub enum RollupVerifyingKey {
Deserialize,
)]
pub enum ProofContext {
/// Identifier for the L1 block height used in a Bitcoin blockspace proof.
/// Identifier representing a Bitcoin L1 block for blockscan proof
BtcBlockspace(L1BlockId),

/// Identifier for a batch of L1 blocks being proven.
Expand Down
1 change: 1 addition & 0 deletions crates/proof-impl/btc-blockspace/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ pub mod filter;
pub mod logic;
pub mod merkle;
pub mod prover;
pub mod scan;
pub mod tx;
Loading
Loading