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

feat(driver): Multi-block derivation #888

Merged
merged 8 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from 3 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.

43 changes: 6 additions & 37 deletions bin/client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,18 @@
extern crate alloc;

use alloc::sync::Arc;
use alloy_consensus::{Header, Sealed};
use alloy_primitives::B256;
use core::fmt::Debug;
use kona_driver::{Driver, DriverError};
use kona_executor::{ExecutorError, KonaHandleRegister, TrieDBProvider};
use kona_preimage::{
CommsClient, HintWriterClient, PreimageKey, PreimageKeyType, PreimageOracleClient,
};
use kona_executor::{ExecutorError, KonaHandleRegister};
use kona_preimage::{HintWriterClient, PreimageOracleClient};
use kona_proof::{
errors::OracleProviderError,
executor::KonaExecutor,
l1::{OracleBlobProvider, OracleL1ChainProvider, OraclePipeline},
l2::OracleL2ChainProvider,
sync::new_pipeline_cursor,
BootInfo, CachingOracle, HintType,
BootInfo, CachingOracle,
};
use thiserror::Error;
use tracing::{error, info, warn};
Expand Down Expand Up @@ -77,7 +74,7 @@ where

// If the claimed L2 block number is less than the safe head of the L2 chain, the claim is
// invalid.
let safe_head = fetch_safe_head(oracle.as_ref(), boot.as_ref(), &mut l2_provider).await?;
let safe_head = l2_provider.agreed_l2_block_header().await?;
if boot.claimed_l2_block_number < safe_head.number {
error!(
target: "client",
Expand Down Expand Up @@ -107,6 +104,8 @@ where

// Create a new derivation driver with the given boot information and oracle.
let cursor = new_pipeline_cursor(&boot, safe_head, &mut l1_provider, &mut l2_provider).await?;
l2_provider.set_cursor(cursor.clone());

let cfg = Arc::new(boot.rollup_config.clone());
let pipeline = OraclePipeline::new(
cfg.clone(),
Expand Down Expand Up @@ -147,33 +146,3 @@ where

Ok(())
}

/// Fetches the safe head of the L2 chain based on the agreed upon L2 output root in the
/// [BootInfo].
async fn fetch_safe_head<O>(
caching_oracle: &O,
boot_info: &BootInfo,
l2_chain_provider: &mut OracleL2ChainProvider<O>,
) -> Result<Sealed<Header>, OracleProviderError>
where
O: CommsClient,
{
caching_oracle
.write(&HintType::StartingL2Output.encode_with(&[boot_info.agreed_l2_output_root.as_ref()]))
.await
.map_err(OracleProviderError::Preimage)?;
let mut output_preimage = [0u8; 128];
caching_oracle
.get_exact(
PreimageKey::new(*boot_info.agreed_l2_output_root, PreimageKeyType::Keccak256),
&mut output_preimage,
)
.await
.map_err(OracleProviderError::Preimage)?;

let safe_hash =
output_preimage[96..128].try_into().map_err(OracleProviderError::SliceConversion)?;
l2_chain_provider
.header_by_hash(safe_hash)
.map(|header| Sealed::new_unchecked(header, safe_hash))
}
refcell marked this conversation as resolved.
Show resolved Hide resolved
5 changes: 3 additions & 2 deletions crates/driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ op-alloy-consensus.workspace = true
op-alloy-rpc-types-engine.workspace = true

# Misc
tracing.workspace = true
thiserror .workspace = true
async-trait.workspace = true
spin.workspace = true
thiserror .workspace = true
tracing.workspace = true
32 changes: 18 additions & 14 deletions crates/driver/src/core.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! The driver of the kona derivation pipeline.

use alloc::vec::Vec;
use crate::{DriverError, DriverPipeline, DriverResult, Executor, PipelineCursor, TipCursor};
use alloc::{sync::Arc, vec::Vec};
use alloy_consensus::{BlockBody, Sealable};
use alloy_primitives::B256;
use alloy_rlp::Decodable;
Expand All @@ -14,8 +15,7 @@ use op_alloy_consensus::{OpBlock, OpTxEnvelope, OpTxType};
use op_alloy_genesis::RollupConfig;
use op_alloy_protocol::L2BlockInfo;
use op_alloy_rpc_types_engine::OpAttributesWithParent;

use crate::{DriverError, DriverPipeline, DriverResult, Executor, PipelineCursor, TipCursor};
use spin::RwLock;

/// The Rollup Driver entrypoint.
#[derive(Debug)]
Expand All @@ -32,7 +32,7 @@ where
/// A pipeline abstraction.
pub pipeline: DP,
/// Cursor to keep track of the L2 tip
pub cursor: PipelineCursor,
pub cursor: Arc<RwLock<PipelineCursor>>,
/// The Executor.
pub executor: E,
}
Expand All @@ -44,7 +44,7 @@ where
P: Pipeline + SignalReceiver + Send + Sync + Debug,
{
/// Creates a new [Driver].
pub const fn new(cursor: PipelineCursor, executor: E, pipeline: DP) -> Self {
pub const fn new(cursor: Arc<RwLock<PipelineCursor>>, executor: E, pipeline: DP) -> Self {
Self {
_marker: core::marker::PhantomData,
_marker2: core::marker::PhantomData,
Expand Down Expand Up @@ -76,19 +76,20 @@ where
) -> DriverResult<(u64, B256), E::Error> {
loop {
// Check if we have reached the target block number.
let cursor = self.cursor.read();
if let Some(tb) = target {
if self.cursor.l2_safe_head().block_info.number >= tb {
if cursor.l2_safe_head().block_info.number >= tb {
info!(target: "client", "Derivation complete, reached L2 safe head.");
return Ok((
self.cursor.l2_safe_head().block_info.number,
*self.cursor.l2_safe_head_output_root(),
cursor.l2_safe_head().block_info.number,
*cursor.l2_safe_head_output_root(),
));
}
}

let OpAttributesWithParent { mut attributes, .. } = match self
.pipeline
.produce_payload(*self.cursor.l2_safe_head())
.produce_payload(*cursor.l2_safe_head())
.await
{
Ok(attrs) => attrs,
Expand All @@ -98,7 +99,7 @@ where
// Adjust the target block number to the current safe head, as no more blocks
// can be produced.
if target.is_some() {
target = Some(self.cursor.l2_safe_head().block_info.number);
target = Some(cursor.l2_safe_head().block_info.number);
};
continue;
}
Expand All @@ -108,7 +109,7 @@ where
}
};

self.executor.update_safe_head(self.cursor.l2_safe_head_header().clone());
self.executor.update_safe_head(cursor.l2_safe_head_header().clone());
let header = match self.executor.execute_payload(attributes.clone()).await {
Ok(header) => header,
Err(e) => {
Expand All @@ -132,7 +133,7 @@ where
});

// Retry the execution.
self.executor.update_safe_head(self.cursor.l2_safe_head_header().clone());
self.executor.update_safe_head(cursor.l2_safe_head_header().clone());
match self.executor.execute_payload(attributes.clone()).await {
Ok(header) => header,
Err(e) => {
Expand Down Expand Up @@ -171,12 +172,15 @@ where
&block,
&self.pipeline.rollup_config().genesis,
)?;
let cursor = TipCursor::new(
let tip_cursor = TipCursor::new(
l2_info,
header.clone().seal_slow(),
self.executor.compute_output_root().map_err(DriverError::Executor)?,
);
self.cursor.advance(origin, cursor);

// Advance the derivation pipeline cursor
drop(cursor);
self.cursor.write().advance(origin, tip_cursor);
}
}
}
38 changes: 36 additions & 2 deletions crates/proof-sdk/proof/src/hint.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//! This module contains the [HintType] enum.

use crate::errors::HintParsingError;
use crate::errors::{HintParsingError, OracleProviderError};
use alloc::{
string::{String, ToString},
vec::Vec,
};
use alloy_primitives::{hex, Bytes};
use alloy_primitives::{hex, Bytes, B256};
use core::fmt::Display;
use kona_preimage::{CommsClient, PreimageKey, PreimageKeyType};

/// A [Hint] is parsed in the format `<hint_type> <hint_data>`, where `<hint_type>` is a string that
/// represents the type of hint, and `<hint_data>` is the data associated with the hint (bytes
Expand Down Expand Up @@ -80,6 +81,39 @@ impl HintType {
let concatenated = hex::encode(data.iter().copied().flatten().copied().collect::<Vec<_>>());
alloc::format!("{} {}", self, concatenated)
}
/// Retrieves a preimage through an oracle
pub async fn get_preimage<T: CommsClient>(
&self,
oracle: &T,
preimage: B256,
preimage_key_type: PreimageKeyType,
) -> Result<Vec<u8>, OracleProviderError> {
oracle
.write(&self.encode_with(&[preimage.as_ref()]))
.await
.map_err(OracleProviderError::Preimage)?;
oracle
.get(PreimageKey::new(*preimage, preimage_key_type))
.await
.map_err(OracleProviderError::Preimage)
}
/// Retrieves a preimage through an oracle
pub async fn get_exact_preimage<T: CommsClient>(
&self,
oracle: &T,
preimage: B256,
preimage_key_type: PreimageKeyType,
buf: &mut [u8],
) -> Result<(), OracleProviderError> {
oracle
.write(&self.encode_with(&[preimage.as_ref()]))
.await
.map_err(OracleProviderError::Preimage)?;
oracle
.get_exact(PreimageKey::new(*preimage, preimage_key_type), buf)
.await
.map_err(OracleProviderError::Preimage)
}
}

impl TryFrom<&str> for HintType {
Expand Down
14 changes: 3 additions & 11 deletions crates/proof-sdk/proof/src/l1/chain_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,10 @@ impl<T: CommsClient + Sync + Send> ChainProvider for OracleL1ChainProvider<T> {
type Error = OracleProviderError;

async fn header_by_hash(&mut self, hash: B256) -> Result<Header, Self::Error> {
// Send a hint for the block header.
self.oracle
.write(&HintType::L1BlockHeader.encode_with(&[hash.as_ref()]))
.await
.map_err(OracleProviderError::Preimage)?;

// Fetch the header RLP from the oracle.
let header_rlp = self
.oracle
.get(PreimageKey::new(*hash, PreimageKeyType::Keccak256))
.await
.map_err(OracleProviderError::Preimage)?;
let header_rlp = HintType::L1BlockHeader
.get_preimage(self.oracle.as_ref(), hash, PreimageKeyType::Keccak256)
.await?;

// Decode the header RLP into a Header.
Header::decode(&mut header_rlp.as_slice()).map_err(OracleProviderError::Rlp)
Expand Down
5 changes: 3 additions & 2 deletions crates/proof-sdk/proof/src/l1/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use kona_preimage::CommsClient;
use op_alloy_genesis::{RollupConfig, SystemConfig};
use op_alloy_protocol::{BlockInfo, L2BlockInfo};
use op_alloy_rpc_types_engine::OpAttributesWithParent;
use spin::RwLock;

/// An oracle-backed derivation pipeline.
pub type OracleDerivationPipeline<O, B> = DerivationPipeline<
Expand Down Expand Up @@ -73,7 +74,7 @@ where
/// Constructs a new oracle-backed derivation pipeline.
pub fn new(
cfg: Arc<RollupConfig>,
sync_start: PipelineCursor,
sync_start: Arc<RwLock<PipelineCursor>>,
caching_oracle: Arc<O>,
blob_provider: B,
chain_provider: OracleL1ChainProvider<O>,
Expand All @@ -92,7 +93,7 @@ where
.l2_chain_provider(l2_chain_provider)
.chain_provider(chain_provider)
.builder(attributes)
.origin(sync_start.origin())
.origin(sync_start.read().origin())
.build();
Self { pipeline, caching_oracle }
}
Expand Down
Loading
Loading