diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 93711f95..f111ea1e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -9,6 +9,7 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v4 + - uses: taiki-e/install-action@just - name: Install Rust stable toolchain uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 @@ -16,7 +17,7 @@ jobs: cache-on-failure: true - uses: taiki-e/install-action@nextest - name: cargo test - run: cargo nextest run --release --workspace --all --locked + run: just test --locked cargo-lint: runs-on: ubuntu-latest timeout-minutes: 20 diff --git a/Cargo.lock b/Cargo.lock index 22cee150..1591ef23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,22 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "alloy-primitives" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef197eb250c64962003cb08b90b17f0882c192f4a6f2f544809d424fd7cb0e7d" +dependencies = [ + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal", + "itoa", + "ruint", + "tiny-keccak", +] + [[package]] name = "anyhow" version = "1.0.79" @@ -74,6 +90,53 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "const-hex" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d59688ad0945eaf6b84cb44fedbe93484c81b48970e98f09db8a22832d7961" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + [[package]] name = "errno" version = "0.3.8" @@ -102,6 +165,34 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "kona-client" +version = "0.0.1" +dependencies = [ + "alloy-primitives", + "anyhow", + "kona-common", + "kona-preimage", +] + [[package]] name = "kona-common" version = "0.0.1" @@ -128,6 +219,12 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "linked_list_allocator" version = "0.10.5" @@ -179,6 +276,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", + "libm", +] + [[package]] name = "num_cpus" version = "1.16.0" @@ -227,6 +334,12 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro2" version = "1.0.78" @@ -236,6 +349,20 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proptest" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +dependencies = [ + "bitflags 2.4.2", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "unarray", +] + [[package]] name = "quote" version = "1.0.35" @@ -245,6 +372,40 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -254,12 +415,41 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "ruint" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608a5726529f2f0ef81b8fde9873c4bb829d6b5b5ca6be4d97345ddf0749c825" +dependencies = [ + "proptest", + "rand", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e666a5496a0b2186dbcd0ff6106e29e093c15591bde62c20d3842007c6978a09" + [[package]] name = "rustc-demangle" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.31" @@ -279,6 +469,32 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "semver" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" + +[[package]] +name = "serde" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -313,6 +529,17 @@ dependencies = [ "lock_api", ] +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.48" @@ -336,6 +563,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tokio" version = "1.36.0" @@ -363,15 +599,27 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.48", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -509,3 +757,9 @@ name = "windows_x86_64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/Cargo.toml b/Cargo.toml index 7ccd2d7d..aec4b63b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["crates/*"] +members = ["bin/client", "crates/*"] exclude = ["examples/minimal", "examples/simple-revm", "fpvm-tests/cannon-rs-tests"] resolver = "2" @@ -20,6 +20,12 @@ cfg-if = "1.0.0" [profile.dev] opt-level = 1 overflow-checks = false +panic = "abort" + +[profile.release] +panic = "abort" +codegen-units = 1 +lto = "fat" [profile.bench] debug = true diff --git a/bin/client/.gitkeep b/bin/client/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/bin/client/Cargo.toml b/bin/client/Cargo.toml new file mode 100644 index 00000000..9de0a638 --- /dev/null +++ b/bin/client/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "kona-client" +version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true +exclude.workspace = true + +[dependencies] +# Workspace +anyhow.workspace = true + +# Local +kona-common = { path = "../../crates/common" } +kona-preimage = { path = "../../crates/preimage" } + +# External +alloy-primitives = { version = "0.6.3", default-features = false } diff --git a/bin/client/README.md b/bin/client/README.md new file mode 100644 index 00000000..8c926a11 --- /dev/null +++ b/bin/client/README.md @@ -0,0 +1,3 @@ +# `kona-client` + +The `client` binary for `kona`. diff --git a/bin/client/src/boot.rs b/bin/client/src/boot.rs new file mode 100644 index 00000000..b49f738f --- /dev/null +++ b/bin/client/src/boot.rs @@ -0,0 +1,95 @@ +//! This module contains the [BootInfo] struct, which contains bootstrap information for the `client` program. + +use alloy_primitives::B256; +use anyhow::{anyhow, Result}; +use kona_preimage::{OracleReader, PreimageKey, PreimageOracleClient}; + +/// The [BootInfo] struct contains bootstrap information for the `client` program. This information is used to +/// initialize chain derivation as well as verify the integrity of the L2 claim versus the produced L2 output root. +#[derive(Debug, Clone, Copy)] +#[allow(dead_code)] +pub(crate) struct BootInfo { + /// The L1 head hash containing all data necessary to derive the `l2_claim` state. + pub(crate) l1_head: B256, + /// The starting L2 output root hash. + pub(crate) starting_l2_output_root: B256, + /// The claimed L2 output root hash. + pub(crate) claimed_l2_output_root: B256, + /// The claimed L2 output root block number. + pub(crate) claimed_l2_output_root_block_number: u64, + /// The L2 chain ID. + pub(crate) l2_chain_id: u64, + // /// The L2 chain configuration. + // pub(crate) l2_chain_config: L2ChainConfig, + // /// The rollup configuration. + // pub(crate) rollup_config: RollupConfig, +} + +/// A [LocalKeyIndex] is a unique identifier for a local preimage key in the `PreimageOracle`. These keys are used to +/// store and retrieve bootstrap information for the `client` program. +#[repr(u8)] +pub(crate) enum LocalKeyIndex { + L1Head = 1, + StartingL2OutputRoot = 2, + ClaimedL2OutputRoot = 3, + ClaimedL2OutputRootBlockNumber = 4, + L2ChainId = 5, + // L2ChainConfig = 6, + // RollupConfig = 7, +} + +impl BootInfo { + /// Attempts to boot the client program by reading the necessary bootstrap information from the [OracleReader] + /// passed. If any of the required keys are missing or malformatted, an error is returned. + pub(crate) fn try_boot(oracle: &OracleReader) -> Result { + let l1_head: B256 = oracle + .get(PreimageKey::new_local(LocalKeyIndex::L1Head as u64))? + .as_slice() + .try_into() + .map_err(|_| anyhow!("Failed to convert L1 head hash slice to `B256`"))?; + let starting_l2_output_root: B256 = oracle + .get(PreimageKey::new_local( + LocalKeyIndex::StartingL2OutputRoot as u64, + ))? + .as_slice() + .try_into() + .map_err(|_| { + anyhow!("Failed to convert starting L2 output root hash slice to `B256`") + })?; + let claimed_l2_output_root: B256 = oracle + .get(PreimageKey::new_local( + LocalKeyIndex::ClaimedL2OutputRoot as u64, + ))? + .as_slice() + .try_into() + .map_err(|_| { + anyhow!("Failed to convert claimed L2 output root hash slice to `B256`") + })?; + let claimed_l2_output_root_block_number: u64 = u64::from_be_bytes( + oracle + .get(PreimageKey::new_local( + LocalKeyIndex::ClaimedL2OutputRootBlockNumber as u64, + ))? + .as_slice() + .try_into() + .map_err(|_| { + anyhow!("Failed to convert claimed L2 output root block number slice to `u64`") + })?, + ); + let l2_chain_id: u64 = u64::from_be_bytes( + oracle + .get(PreimageKey::new_local(LocalKeyIndex::L2ChainId as u64))? + .as_slice() + .try_into() + .map_err(|_| anyhow!("Failed to convert L2 chain ID slice to `u64`"))?, + ); + + Ok(Self { + l1_head, + starting_l2_output_root, + claimed_l2_output_root, + claimed_l2_output_root_block_number, + l2_chain_id, + }) + } +} diff --git a/bin/client/src/constants.rs b/bin/client/src/constants.rs new file mode 100644 index 00000000..3fc0cc58 --- /dev/null +++ b/bin/client/src/constants.rs @@ -0,0 +1,12 @@ +//! This module contains constant values used throughout the client program. + +use kona_common::FileDescriptor; +use kona_preimage::PipeHandle; + +/// The size of the heap to allocate, in bytes (1GB). +#[cfg(any(target_arch = "mips", target_arch = "riscv64"))] +pub(crate) const HEAP_SIZE: usize = 0x3B9ACA00; + +/// The pipe handle used to communicate with the preimage oracle from the client program. +pub(crate) const CLIENT_PREIMAGE_PIPE: PipeHandle = + PipeHandle::new(FileDescriptor::PreimageRead, FileDescriptor::PreimageWrite); diff --git a/bin/client/src/main.rs b/bin/client/src/main.rs new file mode 100644 index 00000000..dee255c3 --- /dev/null +++ b/bin/client/src/main.rs @@ -0,0 +1,56 @@ +#![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(target_arch = "mips", feature(asm_experimental_arch))] +#![no_std] +#![no_main] + +#[cfg(any(target_arch = "mips", target_arch = "riscv64"))] +extern crate alloc; + +use boot::BootInfo; +use kona_common::io; +use kona_preimage::OracleReader; + +mod boot; +mod constants; +mod types; + +/// The entry point for the client program. +fn boot() { + kona_common::alloc_heap!(constants::HEAP_SIZE); + + let oracle = OracleReader::new(constants::CLIENT_PREIMAGE_PIPE); + let _ = BootInfo::try_boot(&oracle).expect("Failed to boot client program"); + + // Exit the program with a success code. + io::exit(0); +} + +/// The entry point for the client program when ran on a bare-metal target. Aliases `boot`. +#[cfg(any(target_arch = "mips", target_arch = "riscv64"))] +#[no_mangle] +pub extern "C" fn _start() { + boot(); +} + +/// The entry point for the client program when ran natively. Aliases `boot`. +#[cfg(not(any(target_arch = "mips", target_arch = "riscv64")))] +#[no_mangle] +pub fn main() { + boot(); +} + +#[cfg(any(target_arch = "mips", target_arch = "riscv64"))] +#[panic_handler] +fn panic(info: &core::panic::PanicInfo<'_>) -> ! { + let msg = alloc::format!("Panic: {}", info); + io::print_err(msg.as_ref()); + io::exit(2) +} diff --git a/bin/client/src/types.rs b/bin/client/src/types.rs new file mode 100644 index 00000000..c3aac75d --- /dev/null +++ b/bin/client/src/types.rs @@ -0,0 +1,7 @@ +//! This module contains types used throughout the client program. + +#[allow(dead_code)] +pub(crate) struct ChainConfig { + pub(crate) preset: i64, + pub(crate) l1_starting_height: u64, +} diff --git a/crates/preimage/src/hint.rs b/crates/preimage/src/hint.rs index ff634287..42137fd3 100644 --- a/crates/preimage/src/hint.rs +++ b/crates/preimage/src/hint.rs @@ -1,3 +1,5 @@ +//! Contains the [HintWriter] type, which is a high-level interface to the hint writer pipe. + use crate::{traits::HintWriterClient, PipeHandle}; use alloc::vec; use anyhow::Result; @@ -35,3 +37,74 @@ impl HintWriterClient for HintWriter { Ok(()) } } + +#[cfg(test)] +mod test { + extern crate std; + + use super::*; + use kona_common::FileDescriptor; + use std::{fs::File, os::fd::AsRawFd}; + use tempfile::tempfile; + + /// Test struct containing the [HintWriter] and a [PipeHandle] for the host, plus the open [File]s. The [File]s + /// are stored in this struct so that they are not dropped until the end of the test. + /// + /// TODO: Swap host pipe handle to hint router once it exists. + #[derive(Debug)] + struct ClientAndHost { + hint_writer: HintWriter, + host_handle: PipeHandle, + _read_file: File, + _write_file: File, + } + + /// Helper for creating a new [HintWriter] and [PipeHandle] for testing. The file channel is over two temporary + /// files. + /// + /// TODO: Swap host pipe handle to hint router once it exists. + fn client_and_host() -> ClientAndHost { + let (read_file, write_file) = (tempfile().unwrap(), tempfile().unwrap()); + let (read_fd, write_fd) = ( + FileDescriptor::Wildcard(read_file.as_raw_fd().try_into().unwrap()), + FileDescriptor::Wildcard(write_file.as_raw_fd().try_into().unwrap()), + ); + let client_handle = PipeHandle::new(read_fd, write_fd); + let host_handle = PipeHandle::new(write_fd, read_fd); + + let hint_writer = HintWriter::new(client_handle); + + ClientAndHost { + hint_writer, + host_handle, + _read_file: read_file, + _write_file: write_file, + } + } + + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_hint_writer() { + const MOCK_DATA: &str = "dummy-hint facade"; + let sys = client_and_host(); + let (hint_writer, host_handle) = (sys.hint_writer, sys.host_handle); + + let client = tokio::task::spawn(async move { + hint_writer.write(MOCK_DATA).unwrap(); + }); + let host = tokio::task::spawn(async move { + let mut hint_bytes = vec![0u8; MOCK_DATA.len() + 4]; + host_handle.read_exact(hint_bytes.as_mut_slice()).unwrap(); + + let len = u32::from_be_bytes(hint_bytes[..4].try_into().unwrap()); + assert_eq!(len, MOCK_DATA.len() as u32); + assert_eq!(&hint_bytes[4..], MOCK_DATA.as_bytes()); + + let ack = [1u8; 1]; + host_handle.write(&ack).unwrap(); + }); + + let (r, w) = tokio::join!(client, host); + r.unwrap(); + w.unwrap(); + } +} diff --git a/crates/preimage/src/oracle.rs b/crates/preimage/src/oracle.rs index e319825a..1e33479d 100644 --- a/crates/preimage/src/oracle.rs +++ b/crates/preimage/src/oracle.rs @@ -1,3 +1,5 @@ +//! Contains the [OracleReader] struct, which is a high-level interface to the preimage oracle pipe. + use crate::{traits::PreimageOracleClient, PipeHandle, PreimageKey}; use alloc::vec::Vec; use anyhow::{bail, Result}; @@ -16,7 +18,7 @@ impl OracleReader { /// Set the preimage key for the global oracle reader. This will overwrite any existing key, and block until the /// host has prepared the preimage and responded with the length of the preimage. - fn write_key(&mut self, key: PreimageKey) -> Result { + fn write_key(&self, key: PreimageKey) -> Result { // Write the key to the host so that it can prepare the preimage. let key_bytes: [u8; 32] = key.into(); self.pipe_handle.write(&key_bytes)?; @@ -31,7 +33,7 @@ impl OracleReader { impl PreimageOracleClient for OracleReader { /// Get the data corresponding to the currently set key from the host. Return the data in a new heap allocated /// `Vec` - fn get(&mut self, key: PreimageKey) -> Result> { + fn get(&self, key: PreimageKey) -> Result> { let length = self.write_key(key)?; let mut data_buffer = alloc::vec![0; length]; @@ -42,7 +44,7 @@ impl PreimageOracleClient for OracleReader { } /// Get the data corresponding to the currently set key from the host. Write the data into the provided buffer - fn get_exact(&mut self, key: PreimageKey, buf: &mut [u8]) -> Result<()> { + fn get_exact(&self, key: PreimageKey, buf: &mut [u8]) -> Result<()> { // Write the key to the host and read the length of the preimage. let length = self.write_key(key)?; @@ -110,7 +112,7 @@ mod test { async fn test_oracle_reader() { const MOCK_DATA: &[u8] = b"1234567890"; let sys = client_and_host(); - let (mut oracle_reader, host_handle) = (sys.oracle_reader, sys.host_handle); + let (oracle_reader, host_handle) = (sys.oracle_reader, sys.host_handle); let client = tokio::task::spawn(async move { oracle_reader @@ -124,7 +126,8 @@ mod test { host_handle.write(&length_and_data).unwrap(); }); - let (r, _) = tokio::join!(client, host); + let (r, w) = tokio::join!(client, host); assert_eq!(r.unwrap(), MOCK_DATA); + w.unwrap(); } } diff --git a/crates/preimage/src/pipe.rs b/crates/preimage/src/pipe.rs index 42194a69..1218d0b9 100644 --- a/crates/preimage/src/pipe.rs +++ b/crates/preimage/src/pipe.rs @@ -1,10 +1,10 @@ -//! This module contains a rudamentary pipe between two file descriptors, using [kona_common::io] for -//! reading and writing from the file descriptors. +//! Contains a rudamentary pipe between two file descriptors, using [kona_common::io] for reading and writing from +//! the file descriptors. use anyhow::{bail, Result}; use kona_common::{io, FileDescriptor, RegisterSize}; -/// [PipeHandle] is a handle for one end of a bidirectional pipe. +/// A [PipeHandle] is a handle for one end of a bidirectional pipe. #[derive(Debug, Clone, Copy)] pub struct PipeHandle { /// File descriptor to read from diff --git a/crates/preimage/src/traits.rs b/crates/preimage/src/traits.rs index e7676c3d..d5f9ceaf 100644 --- a/crates/preimage/src/traits.rs +++ b/crates/preimage/src/traits.rs @@ -1,3 +1,5 @@ +//! Contains the traits that define the high-level interfaces to the preimage oracle and hint writer. + use crate::PreimageKey; use alloc::vec::Vec; use anyhow::Result; @@ -10,14 +12,14 @@ pub trait PreimageOracleClient { /// # Returns /// - `Ok(Vec)` if the data was successfully fetched from the host. /// - `Err(_)` if the data could not be fetched from the host. - fn get(&mut self, key: PreimageKey) -> Result>; + fn get(&self, key: PreimageKey) -> Result>; /// Get the data corresponding to the currently set key from the host. Writes the data into the provided buffer. /// /// # Returns /// - `Ok(())` if the data was successfully written into the buffer. /// - `Err(_)` if the data could not be written into the buffer. - fn get_exact(&mut self, key: PreimageKey, buf: &mut [u8]) -> Result<()>; + fn get_exact(&self, key: PreimageKey, buf: &mut [u8]) -> Result<()>; } /// A [HintWriterClient] is a high-level interface to the hint pipe. It provides a way to write hints to the host. diff --git a/examples/simple-revm/src/main.rs b/examples/simple-revm/src/main.rs index d56dc975..54eaecc3 100644 --- a/examples/simple-revm/src/main.rs +++ b/examples/simple-revm/src/main.rs @@ -36,13 +36,13 @@ static CLIENT_HINT_PIPE: PipeHandle = pub extern "C" fn _start() { kona_common::alloc_heap!(HEAP_SIZE); - let mut oracle = OracleReader::new(CLIENT_PREIMAGE_PIPE); + let oracle = OracleReader::new(CLIENT_PREIMAGE_PIPE); let hint_writer = HintWriter::new(CLIENT_HINT_PIPE); io::print("Booting EVM and checking hash...\n"); - let (digest, code) = boot(&mut oracle).expect("Failed to boot"); + let (digest, code) = boot(&oracle).expect("Failed to boot"); - match run_evm(&mut oracle, &hint_writer, digest, code) { + match run_evm(&oracle, &hint_writer, digest, code) { Ok(_) => io::print("Success, hashes matched!\n"), Err(e) => { let _ = io::print_err(alloc::format!("Error: {}\n", e).as_ref()); @@ -55,7 +55,7 @@ pub extern "C" fn _start() { /// Boot the program and load bootstrap information. #[inline] -fn boot(oracle: &mut OracleReader) -> Result<([u8; 32], Vec)> { +fn boot(oracle: &OracleReader) -> Result<([u8; 32], Vec)> { let digest = oracle .get(PreimageKey::new_local(DIGEST_IDENT))? .try_into() @@ -68,7 +68,7 @@ fn boot(oracle: &mut OracleReader) -> Result<([u8; 32], Vec)> { /// Call the SHA-256 precompile and assert that the input and output match the expected values #[inline] fn run_evm( - oracle: &mut OracleReader, + oracle: &OracleReader, hint_writer: &HintWriter, digest: [u8; 32], code: Vec, diff --git a/justfile b/justfile index b41e6a1b..5f350dfd 100644 --- a/justfile +++ b/justfile @@ -6,7 +6,7 @@ default: # Test for the native target test *args='': - cargo nextest run --workspace --all $@ + cargo nextest run --workspace --exclude kona-client $@ # Lint the workspace for all available targets lint: lint-native lint-cannon lint-asterisc lint-docs