-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(workspace):
kona-proof-interop
crate (#902)
- Loading branch information
Showing
9 changed files
with
554 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
[package] | ||
name = "kona-proof-interop" | ||
description = "OP Stack Proof SDK with Interop support" | ||
version = "0.1.0" | ||
edition.workspace = true | ||
authors.workspace = true | ||
license.workspace = true | ||
repository.workspace = true | ||
homepage.workspace = true | ||
|
||
[lints] | ||
workspace = true | ||
|
||
[dependencies] | ||
# Workspace | ||
kona-preimage.workspace = true | ||
kona-interop.workspace = true | ||
kona-proof.workspace = true | ||
|
||
# Maili | ||
maili-registry.workspace = true | ||
|
||
# Alloy | ||
alloy-rlp.workspace = true | ||
alloy-primitives.workspace = true | ||
|
||
# Op Alloy | ||
op-alloy-genesis = { workspace = true, features = ["serde"] } | ||
|
||
# General | ||
serde.workspace = true | ||
tracing.workspace = true | ||
serde_json.workspace = true | ||
|
||
# Arbitrary | ||
arbitrary = { version = "1.4", features = ["derive"], optional = true } | ||
|
||
[dev-dependencies] | ||
alloy-primitives = { workspace = true, features = ["rlp", "arbitrary"] } | ||
kona-interop = { workspace = true, features = ["arbitrary"] } | ||
arbitrary = { version = "1.4", features = ["derive"] } | ||
rand.workspace = true | ||
|
||
[features] | ||
arbitrary = ["dep:arbitrary", "alloy-primitives/arbitrary", "kona-interop/arbitrary"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# `kona-proof-interop` | ||
|
||
<a href="https://github.com/op-rs/kona/actions/workflows/rust_ci.yaml"><img src="https://github.com/op-rs/kona/actions/workflows/rust_ci.yaml/badge.svg?label=ci" alt="CI"></a> | ||
<a href="https://crates.io/crates/kona-proof-interop"><img src="https://img.shields.io/crates/v/kona-proof-interop.svg?label=kona-proof-interop&labelColor=2a2f35" alt="Kona Proof SDK"></a> | ||
<a href="https://github.com/op-rs/kona/blob/main/LICENSE.md"><img src="https://img.shields.io/badge/License-MIT-d1d1f6.svg?label=license&labelColor=2a2f35" alt="License"></a> | ||
<a href="https://img.shields.io/codecov/c/github/op-rs/kona"><img src="https://img.shields.io/codecov/c/github/op-rs/kona" alt="Codecov"></a> | ||
|
||
`kona-proof-interop` is an OP Stack state transition proof SDK, with interop support, built on top of [`kona-proof`](../proof/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
//! This module contains the prologue phase of the client program, pulling in the boot information | ||
//! through the `PreimageOracle` ABI as local keys. | ||
use alloy_primitives::{B256, U256}; | ||
use kona_preimage::{PreimageKey, PreimageOracleClient}; | ||
use kona_proof::errors::OracleProviderError; | ||
use maili_registry::ROLLUP_CONFIGS; | ||
use op_alloy_genesis::RollupConfig; | ||
use serde::{Deserialize, Serialize}; | ||
use tracing::warn; | ||
|
||
/// The local key ident for the L1 head hash. | ||
pub const L1_HEAD_KEY: U256 = U256::from_be_slice(&[1]); | ||
|
||
/// The local key ident for the agreed upon L2 pre-state claim. | ||
pub const L2_AGREED_PRE_STATE_KEY: U256 = U256::from_be_slice(&[2]); | ||
|
||
/// The local key ident for the L2 post-state claim. | ||
pub const L2_CLAIMED_POST_STATE_KEY: U256 = U256::from_be_slice(&[3]); | ||
|
||
/// The local key ident for the L2 claim timestamp. | ||
pub const L2_CLAIM_TIMESTAMP_KEY: U256 = U256::from_be_slice(&[4]); | ||
|
||
/// The local key ident for the L2 chain ID. | ||
pub const L2_CHAIN_ID_KEY: U256 = U256::from_be_slice(&[5]); | ||
|
||
/// The local key ident for the L2 rollup config. | ||
pub const L2_ROLLUP_CONFIG_KEY: U256 = U256::from_be_slice(&[6]); | ||
|
||
/// The boot information for the interop client program. | ||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] | ||
pub struct BootInfo { | ||
/// The L1 head hash containing the safe L2 chain data that may reproduce the post-state claim. | ||
pub l1_head: B256, | ||
/// The agreed upon superchain pre-state commitment. | ||
pub agreed_pre_state: B256, | ||
/// The claimed (disputed) superchain post-state commitment. | ||
pub claimed_post_state: B256, | ||
/// The L2 claim timestamp. | ||
pub claimed_l2_timestamp: u64, | ||
/// The L2 chain ID. | ||
pub chain_id: u64, | ||
/// The rollup config for the L2 chain. | ||
pub rollup_config: RollupConfig, | ||
} | ||
|
||
impl BootInfo { | ||
/// Load the boot information from the preimage oracle. | ||
/// | ||
/// ## Takes | ||
/// - `oracle`: The preimage oracle reader. | ||
/// | ||
/// ## Returns | ||
/// - `Ok(BootInfo)`: The boot information. | ||
/// - `Err(_)`: Failed to load the boot information. | ||
pub async fn load<O>(oracle: &O) -> Result<Self, OracleProviderError> | ||
where | ||
O: PreimageOracleClient + Send, | ||
{ | ||
let mut l1_head: B256 = B256::ZERO; | ||
oracle | ||
.get_exact(PreimageKey::new_local(L1_HEAD_KEY.to()), l1_head.as_mut()) | ||
.await | ||
.map_err(OracleProviderError::Preimage)?; | ||
|
||
let mut l2_pre: B256 = B256::ZERO; | ||
oracle | ||
.get_exact(PreimageKey::new_local(L2_AGREED_PRE_STATE_KEY.to()), l2_pre.as_mut()) | ||
.await | ||
.map_err(OracleProviderError::Preimage)?; | ||
|
||
let mut l2_post: B256 = B256::ZERO; | ||
oracle | ||
.get_exact(PreimageKey::new_local(L2_CLAIMED_POST_STATE_KEY.to()), l2_post.as_mut()) | ||
.await | ||
.map_err(OracleProviderError::Preimage)?; | ||
|
||
let l2_claim_block = u64::from_be_bytes( | ||
oracle | ||
.get(PreimageKey::new_local(L2_CLAIM_TIMESTAMP_KEY.to())) | ||
.await | ||
.map_err(OracleProviderError::Preimage)? | ||
.as_slice() | ||
.try_into() | ||
.map_err(OracleProviderError::SliceConversion)?, | ||
); | ||
let chain_id = u64::from_be_bytes( | ||
oracle | ||
.get(PreimageKey::new_local(L2_CHAIN_ID_KEY.to())) | ||
.await | ||
.map_err(OracleProviderError::Preimage)? | ||
.as_slice() | ||
.try_into() | ||
.map_err(OracleProviderError::SliceConversion)?, | ||
); | ||
|
||
// Attempt to load the rollup config from the chain ID. If there is no config for the chain, | ||
// fall back to loading the config from the preimage oracle. | ||
let rollup_config = if let Some(config) = ROLLUP_CONFIGS.get(&chain_id) { | ||
config.clone() | ||
} else { | ||
warn!( | ||
target: "boot-loader", | ||
"No rollup config found for chain ID {}, falling back to preimage oracle. This is insecure in production without additional validation!", | ||
chain_id | ||
); | ||
let ser_cfg = oracle | ||
.get(PreimageKey::new_local(L2_ROLLUP_CONFIG_KEY.to())) | ||
.await | ||
.map_err(OracleProviderError::Preimage)?; | ||
serde_json::from_slice(&ser_cfg).map_err(OracleProviderError::Serde)? | ||
}; | ||
|
||
Ok(Self { | ||
l1_head, | ||
agreed_pre_state: l2_pre, | ||
claimed_post_state: l2_post, | ||
claimed_l2_timestamp: l2_claim_block, | ||
chain_id, | ||
rollup_config, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
//! This module contains the [HintType] enum. | ||
use alloc::{ | ||
string::{String, ToString}, | ||
vec::Vec, | ||
}; | ||
use alloy_primitives::{hex, Bytes}; | ||
use core::fmt::Display; | ||
use kona_proof::errors::HintParsingError; | ||
|
||
/// 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 | ||
/// encoded as hex UTF-8). | ||
#[derive(Debug, Clone, PartialEq, Eq)] | ||
pub struct Hint { | ||
/// The type of hint. | ||
pub hint_type: HintType, | ||
/// The data associated with the hint. | ||
pub hint_data: Bytes, | ||
} | ||
|
||
impl Hint { | ||
/// Parses a hint from a string. | ||
pub fn parse(s: &str) -> Result<Self, HintParsingError> { | ||
let mut parts = s.split(' ').collect::<Vec<_>>(); | ||
|
||
if parts.len() != 2 { | ||
return Err(HintParsingError(alloc::format!("Invalid hint format: {}", s))); | ||
} | ||
|
||
let hint_type = HintType::try_from(parts.remove(0))?; | ||
let hint_data = | ||
hex::decode(parts.remove(0)).map_err(|e| HintParsingError(e.to_string()))?.into(); | ||
|
||
Ok(Self { hint_type, hint_data }) | ||
} | ||
|
||
/// Splits the [Hint] into its components. | ||
pub fn split(self) -> (HintType, Bytes) { | ||
(self.hint_type, self.hint_data) | ||
} | ||
} | ||
|
||
/// The [HintType] enum is used to specify the type of hint that was received. | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||
pub enum HintType { | ||
/// A hint that specifies the block header of a layer 1 block. | ||
L1BlockHeader, | ||
/// A hint that specifies the transactions of a layer 1 block. | ||
L1Transactions, | ||
/// A hint that specifies the state node of a layer 1 block. | ||
L1Receipts, | ||
/// A hint that specifies a blob in the layer 1 beacon chain. | ||
L1Blob, | ||
/// A hint that specifies a precompile call on layer 1. | ||
L1Precompile, | ||
/// A hint that specifies the block header of a layer 2 block. | ||
L2BlockHeader, | ||
/// A hint that specifies the transactions of a layer 2 block. | ||
L2Transactions, | ||
/// A hint that specifies the code of a contract on layer 2. | ||
L2Code, | ||
/// A hint that specifies the preimage of the agreed upon pre-state claim. | ||
AgreedPreState, | ||
/// A hint that specifies the preimage of an L2 output root within the agreed upon pre-state, | ||
/// by chain ID. | ||
L2OutputRoot, | ||
/// A hint that specifies the state node in the L2 state trie. | ||
L2StateNode, | ||
/// A hint that specifies the proof on the path to an account in the L2 state trie. | ||
L2AccountProof, | ||
/// A hint that specifies the proof on the path to a storage slot in an account within in the | ||
/// L2 state trie. | ||
L2AccountStorageProof, | ||
/// A hint that specifies bulk storage of all the code, state and keys generated by an | ||
/// execution witness. | ||
L2PayloadWitness, | ||
} | ||
|
||
impl HintType { | ||
/// Encodes the hint type as a string. | ||
pub fn encode_with(&self, data: &[&[u8]]) -> String { | ||
let concatenated = hex::encode(data.iter().copied().flatten().copied().collect::<Vec<_>>()); | ||
alloc::format!("{} {}", self, concatenated) | ||
} | ||
} | ||
|
||
impl TryFrom<&str> for HintType { | ||
type Error = HintParsingError; | ||
|
||
fn try_from(value: &str) -> Result<Self, Self::Error> { | ||
match value { | ||
"l1-block-header" => Ok(Self::L1BlockHeader), | ||
"l1-transactions" => Ok(Self::L1Transactions), | ||
"l1-receipts" => Ok(Self::L1Receipts), | ||
"l1-blob" => Ok(Self::L1Blob), | ||
"l1-precompile" => Ok(Self::L1Precompile), | ||
"l2-block-header" => Ok(Self::L2BlockHeader), | ||
"l2-transactions" => Ok(Self::L2Transactions), | ||
"l2-code" => Ok(Self::L2Code), | ||
"agreed-pre-state" => Ok(Self::AgreedPreState), | ||
"l2-output-root" => Ok(Self::L2OutputRoot), | ||
"l2-state-node" => Ok(Self::L2StateNode), | ||
"l2-account-proof" => Ok(Self::L2AccountProof), | ||
"l2-account-storage-proof" => Ok(Self::L2AccountStorageProof), | ||
"l2-payload-witness" => Ok(Self::L2PayloadWitness), | ||
_ => Err(HintParsingError(value.to_string())), | ||
} | ||
} | ||
} | ||
|
||
impl From<HintType> for &str { | ||
fn from(value: HintType) -> Self { | ||
match value { | ||
HintType::L1BlockHeader => "l1-block-header", | ||
HintType::L1Transactions => "l1-transactions", | ||
HintType::L1Receipts => "l1-receipts", | ||
HintType::L1Blob => "l1-blob", | ||
HintType::L1Precompile => "l1-precompile", | ||
HintType::L2BlockHeader => "l2-block-header", | ||
HintType::L2Transactions => "l2-transactions", | ||
HintType::L2Code => "l2-code", | ||
HintType::AgreedPreState => "agreed-pre-state", | ||
HintType::L2OutputRoot => "l2-output-root", | ||
HintType::L2StateNode => "l2-state-node", | ||
HintType::L2AccountProof => "l2-account-proof", | ||
HintType::L2AccountStorageProof => "l2-account-storage-proof", | ||
HintType::L2PayloadWitness => "l2-payload-witness", | ||
} | ||
} | ||
} | ||
|
||
impl Display for HintType { | ||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | ||
let s: &str = (*self).into(); | ||
write!(f, "{}", s) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#![doc = include_str!("../README.md")] | ||
#![warn(missing_debug_implementations, missing_docs, unreachable_pub, rustdoc::all)] | ||
#![deny(unused_must_use, rust_2018_idioms)] | ||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] | ||
#![cfg_attr(not(test), warn(unused_crate_dependencies))] | ||
#![cfg_attr(not(any(test, feature = "arbitrary")), no_std)] | ||
|
||
extern crate alloc; | ||
|
||
pub mod pre_state; | ||
|
||
mod hint; | ||
pub use hint::{Hint, HintType}; | ||
|
||
pub mod boot; | ||
pub use boot::BootInfo; |
Oops, something went wrong.