Skip to content

Commit

Permalink
feat(client): Remove anyhow (#779)
Browse files Browse the repository at this point in the history
  • Loading branch information
clabby authored Nov 5, 2024
1 parent ba87a80 commit a6ef5ab
Show file tree
Hide file tree
Showing 14 changed files with 210 additions and 74 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

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

1 change: 0 additions & 1 deletion bin/client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ lru.workspace = true
spin.workspace = true
serde.workspace = true
cfg-if.workspace = true
anyhow.workspace = true
tracing.workspace = true
serde_json.workspace = true
async-trait.workspace = true
Expand Down
37 changes: 25 additions & 12 deletions bin/client/src/boot.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! This module contains the prologue phase of the client program, pulling in the boot information
//! through the `PreimageOracle` ABI as local keys.
use crate::errors::OracleProviderError;
use alloy_primitives::{B256, U256};
use anyhow::{anyhow, Result};
use kona_preimage::{PreimageKey, PreimageOracleClient};
use op_alloy_genesis::RollupConfig;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -62,34 +62,45 @@ impl BootInfo {
/// ## Returns
/// - `Ok(BootInfo)`: The boot information.
/// - `Err(_)`: Failed to load the boot information.
pub async fn load<O>(oracle: &O) -> Result<Self>
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?;
oracle
.get_exact(PreimageKey::new_local(L1_HEAD_KEY.to()), l1_head.as_mut())
.await
.map_err(OracleProviderError::Preimage)?;

let mut l2_output_root: B256 = B256::ZERO;
oracle
.get_exact(PreimageKey::new_local(L2_OUTPUT_ROOT_KEY.to()), l2_output_root.as_mut())
.await?;
.await
.map_err(OracleProviderError::Preimage)?;

let mut l2_claim: B256 = B256::ZERO;
oracle.get_exact(PreimageKey::new_local(L2_CLAIM_KEY.to()), l2_claim.as_mut()).await?;
oracle
.get_exact(PreimageKey::new_local(L2_CLAIM_KEY.to()), l2_claim.as_mut())
.await
.map_err(OracleProviderError::Preimage)?;

let l2_claim_block = u64::from_be_bytes(
oracle
.get(PreimageKey::new_local(L2_CLAIM_BLOCK_NUMBER_KEY.to()))
.await?
.await
.map_err(OracleProviderError::Preimage)?
.as_slice()
.try_into()
.map_err(|_| anyhow!("Failed to convert L2 claim block number to u64"))?,
.map_err(OracleProviderError::SliceConversion)?,
);
let chain_id = u64::from_be_bytes(
oracle
.get(PreimageKey::new_local(L2_CHAIN_ID_KEY.to()))
.await?
.await
.map_err(OracleProviderError::Preimage)?
.as_slice()
.try_into()
.map_err(|_| anyhow!("Failed to convert L2 chain ID to u64"))?,
.map_err(OracleProviderError::SliceConversion)?,
);

// Attempt to load the rollup config from the chain ID. If there is no config for the chain,
Expand All @@ -102,9 +113,11 @@ impl BootInfo {
"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?;
serde_json::from_slice(&ser_cfg)
.map_err(|e| anyhow!("Failed to deserialize rollup config: {}", e))?
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 {
Expand Down
68 changes: 67 additions & 1 deletion bin/client/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//! Error types for the client program.
use alloc::string::ToString;
use alloc::string::{String, ToString};
use derive_more::derive::Display;
use kona_derive::errors::{PipelineError, PipelineErrorKind};
use kona_executor::ExecutorError;
use kona_mpt::OrderedListWalkerError;
use kona_preimage::errors::PreimageOracleError;
use op_alloy_protocol::{FromBlockError, OpBlockConversionError};
Expand Down Expand Up @@ -31,6 +32,9 @@ pub enum OracleProviderError {
/// Slice conversion error.
#[display("Slice conversion error: {_0}")]
SliceConversion(core::array::TryFromSliceError),
/// Serde error.
#[display("Serde error: {_0}")]
Serde(serde_json::Error),
}

impl core::error::Error for OracleProviderError {}
Expand All @@ -43,3 +47,65 @@ impl From<OracleProviderError> for PipelineErrorKind {
}
}
}

/// Driver error.
#[derive(Display, Debug)]
pub enum DriverError {
/// Pipeline error.
#[display("Pipeline error: {_0}")]
Pipeline(PipelineErrorKind),
/// Execution error.
#[display("Execution error: {_0}")]
Execution(ExecutorError),
/// Error from the oracle provider.
#[display("Oracle provider error: {_0}")]
Oracle(OracleProviderError),
/// Error parsing a hint.
#[display("Hint parsing error: {_0}")]
HintParsing(HintParsingError),
/// Error decoding or encoding RLP.
#[display("RLP error: {_0}")]
Rlp(alloy_rlp::Error),
}

impl core::error::Error for DriverError {}

impl From<OracleProviderError> for DriverError {
fn from(val: OracleProviderError) -> Self {
DriverError::Oracle(val)
}
}

impl From<PipelineErrorKind> for DriverError {
fn from(val: PipelineErrorKind) -> Self {
DriverError::Pipeline(val)
}
}

impl From<ExecutorError> for DriverError {
fn from(val: ExecutorError) -> Self {
DriverError::Execution(val)
}
}

impl From<HintParsingError> for DriverError {
fn from(val: HintParsingError) -> Self {
DriverError::HintParsing(val)
}
}

impl From<alloy_rlp::Error> for DriverError {
fn from(val: alloy_rlp::Error) -> Self {
DriverError::Rlp(val)
}
}

/// A [Result] type for the [DriverError].
pub type DriverResult<T> = Result<T, DriverError>;

/// Error parsing a hint.
#[derive(Display, Debug)]
#[display("Hint parsing error: {_0}")]
pub struct HintParsingError(pub String);

impl core::error::Error for HintParsingError {}
31 changes: 23 additions & 8 deletions bin/client/src/fault/handler/bn128_pair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
use crate::fault::{HINT_WRITER, ORACLE_READER};
use alloc::{string::ToString, vec::Vec};
use alloy_primitives::{keccak256, Address, Bytes};
use anyhow::ensure;
use kona_client::HintType;
use kona_preimage::{HintWriterClient, PreimageKey, PreimageKeyType, PreimageOracleClient};
use kona_client::{errors::OracleProviderError, HintType};
use kona_preimage::{
errors::PreimageOracleError, HintWriterClient, PreimageKey, PreimageKeyType,
PreimageOracleClient,
};
use revm::{
precompile::{
bn128::pair::{ISTANBUL_PAIR_BASE, ISTANBUL_PAIR_PER_POINT},
Expand Down Expand Up @@ -39,21 +41,34 @@ fn fpvm_ecpairing(input: &Bytes, gas_limit: u64) -> PrecompileResult {
let result_data = kona_common::block_on(async move {
// Write the hint for the ecrecover precompile run.
let hint_data = &[ECPAIRING_ADDRESS.as_ref(), input.as_ref()];
HINT_WRITER.write(&HintType::L1Precompile.encode_with(hint_data)).await?;
HINT_WRITER
.write(&HintType::L1Precompile.encode_with(hint_data))
.await
.map_err(OracleProviderError::Preimage)?;

// Construct the key hash for the ecrecover precompile run.
let raw_key_data = hint_data.iter().copied().flatten().copied().collect::<Vec<u8>>();
let key_hash = keccak256(&raw_key_data);

// Fetch the result of the ecrecover precompile run from the host.
let result_data =
ORACLE_READER.get(PreimageKey::new(*key_hash, PreimageKeyType::Precompile)).await?;
let result_data = ORACLE_READER
.get(PreimageKey::new(*key_hash, PreimageKeyType::Precompile))
.await
.map_err(OracleProviderError::Preimage)?;

// Ensure we've received valid result data.
ensure!(!result_data.is_empty(), "Invalid result data");
if result_data.is_empty() {
return Err(OracleProviderError::Preimage(PreimageOracleError::Other(
"Invalid result data".to_string(),
)));
}

// Ensure we've not received an error from the host.
ensure!(result_data[0] != 0, "Error executing ecrecover precompile in host");
if result_data[0] == 0 {
return Err(OracleProviderError::Preimage(PreimageOracleError::Other(
"Error executing ecrecover precompile in host".to_string(),
)));
}

// Return the result data.
Ok(result_data[1..].to_vec())
Expand Down
31 changes: 23 additions & 8 deletions bin/client/src/fault/handler/ecrecover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
use crate::fault::{HINT_WRITER, ORACLE_READER};
use alloc::{string::ToString, vec::Vec};
use alloy_primitives::{keccak256, Address, Bytes};
use anyhow::ensure;
use kona_client::HintType;
use kona_preimage::{HintWriterClient, PreimageKey, PreimageKeyType, PreimageOracleClient};
use kona_client::{errors::OracleProviderError, HintType};
use kona_preimage::{
errors::PreimageOracleError, HintWriterClient, PreimageKey, PreimageKeyType,
PreimageOracleClient,
};
use revm::{
precompile::{u64_to_address, Error as PrecompileError, PrecompileWithAddress},
primitives::{Precompile, PrecompileOutput, PrecompileResult},
Expand All @@ -27,21 +29,34 @@ fn fpvm_ecrecover(input: &Bytes, gas_limit: u64) -> PrecompileResult {
let result_data = kona_common::block_on(async move {
// Write the hint for the ecrecover precompile run.
let hint_data = &[ECRECOVER_ADDRESS.as_ref(), input.as_ref()];
HINT_WRITER.write(&HintType::L1Precompile.encode_with(hint_data)).await?;
HINT_WRITER
.write(&HintType::L1Precompile.encode_with(hint_data))
.await
.map_err(OracleProviderError::Preimage)?;

// Construct the key hash for the ecrecover precompile run.
let raw_key_data = hint_data.iter().copied().flatten().copied().collect::<Vec<u8>>();
let key_hash = keccak256(&raw_key_data);

// Fetch the result of the ecrecover precompile run from the host.
let result_data =
ORACLE_READER.get(PreimageKey::new(*key_hash, PreimageKeyType::Precompile)).await?;
let result_data = ORACLE_READER
.get(PreimageKey::new(*key_hash, PreimageKeyType::Precompile))
.await
.map_err(OracleProviderError::Preimage)?;

// Ensure we've received valid result data.
ensure!(!result_data.is_empty(), "Invalid result data");
if result_data.is_empty() {
return Err(OracleProviderError::Preimage(PreimageOracleError::Other(
"Invalid result data".to_string(),
)));
}

// Ensure we've not received an error from the host.
ensure!(result_data[0] != 0, "Error executing ecrecover precompile in host");
if result_data[0] == 0 {
return Err(OracleProviderError::Preimage(PreimageOracleError::Other(
"Error executing ecrecover precompile in host".to_string(),
)));
}

// Return the result data.
Ok(result_data[1..].to_vec())
Expand Down
31 changes: 23 additions & 8 deletions bin/client/src/fault/handler/kzg_point_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
use crate::fault::{HINT_WRITER, ORACLE_READER};
use alloc::{string::ToString, vec::Vec};
use alloy_primitives::{keccak256, Address, Bytes};
use anyhow::ensure;
use kona_client::HintType;
use kona_preimage::{HintWriterClient, PreimageKey, PreimageKeyType, PreimageOracleClient};
use kona_client::{errors::OracleProviderError, HintType};
use kona_preimage::{
errors::PreimageOracleError, HintWriterClient, PreimageKey, PreimageKeyType,
PreimageOracleClient,
};
use revm::{
precompile::{u64_to_address, Error as PrecompileError, PrecompileWithAddress},
primitives::{Precompile, PrecompileOutput, PrecompileResult},
Expand All @@ -31,21 +33,34 @@ fn fpvm_kzg_point_eval(input: &Bytes, gas_limit: u64) -> PrecompileResult {
let result_data = kona_common::block_on(async move {
// Write the hint for the ecrecover precompile run.
let hint_data = &[POINT_EVAL_ADDRESS.as_ref(), input.as_ref()];
HINT_WRITER.write(&HintType::L1Precompile.encode_with(hint_data)).await?;
HINT_WRITER
.write(&HintType::L1Precompile.encode_with(hint_data))
.await
.map_err(OracleProviderError::Preimage)?;

// Construct the key hash for the ecrecover precompile run.
let raw_key_data = hint_data.iter().copied().flatten().copied().collect::<Vec<u8>>();
let key_hash = keccak256(&raw_key_data);

// Fetch the result of the ecrecover precompile run from the host.
let result_data =
ORACLE_READER.get(PreimageKey::new(*key_hash, PreimageKeyType::Precompile)).await?;
let result_data = ORACLE_READER
.get(PreimageKey::new(*key_hash, PreimageKeyType::Precompile))
.await
.map_err(OracleProviderError::Preimage)?;

// Ensure we've received valid result data.
ensure!(!result_data.is_empty(), "Invalid result data");
if result_data.is_empty() {
return Err(OracleProviderError::Preimage(PreimageOracleError::Other(
"Invalid result data".to_string(),
)));
}

// Ensure we've not received an error from the host.
ensure!(result_data[0] != 0, "Error executing ecrecover precompile in host");
if result_data[0] == 0 {
return Err(OracleProviderError::Preimage(PreimageOracleError::Other(
"Error executing ecrecover precompile in host".to_string(),
)));
}

// Return the result data.
Ok(result_data[1..].to_vec())
Expand Down
11 changes: 8 additions & 3 deletions bin/client/src/hint.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
//! This module contains the [HintType] enum.
use alloc::{string::String, vec::Vec};
use alloc::{
string::{String, ToString},
vec::Vec,
};
use alloy_primitives::hex;
use core::fmt::Display;

use crate::errors::HintParsingError;

/// 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 {
Expand Down Expand Up @@ -43,7 +48,7 @@ impl HintType {
}

impl TryFrom<&str> for HintType {
type Error = anyhow::Error;
type Error = HintParsingError;

fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
Expand All @@ -59,7 +64,7 @@ impl TryFrom<&str> for HintType {
"l2-state-node" => Ok(HintType::L2StateNode),
"l2-account-proof" => Ok(HintType::L2AccountProof),
"l2-account-storage-proof" => Ok(HintType::L2AccountStorageProof),
_ => anyhow::bail!("Invalid hint type: {value}"),
_ => Err(HintParsingError(value.to_string())),
}
}
}
Expand Down
Loading

0 comments on commit a6ef5ab

Please sign in to comment.