From 7d136ce9d78a420e7283a8f7a35fb87098a52eaa Mon Sep 17 00:00:00 2001 From: clabby Date: Thu, 21 Sep 2023 23:23:44 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A7=20Start=20`preimage-oracle`=20crat?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 192 +++++++++++++++++++++++++++++++++- crates/preimage/Cargo.toml | 21 ++++ crates/preimage/README.md | 11 ++ crates/preimage/src/lib.rs | 13 +++ crates/preimage/src/oracle.rs | 65 ++++++++++++ crates/preimage/src/traits.rs | 35 +++++++ crates/preimage/src/types.rs | 79 ++++++++++++++ 7 files changed, 414 insertions(+), 2 deletions(-) create mode 100644 crates/preimage/Cargo.toml create mode 100644 crates/preimage/README.md create mode 100644 crates/preimage/src/lib.rs create mode 100644 crates/preimage/src/oracle.rs create mode 100644 crates/preimage/src/traits.rs create mode 100644 crates/preimage/src/types.rs diff --git a/Cargo.lock b/Cargo.lock index 2672551..48344ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "ahash" version = "0.8.3" @@ -245,6 +260,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base16ct" version = "0.2.0" @@ -668,6 +698,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + [[package]] name = "group" version = "0.13.0" @@ -700,6 +736,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + [[package]] name = "hex" version = "0.4.3" @@ -814,6 +856,16 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.17" @@ -829,6 +881,26 @@ version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -916,6 +988,25 @@ dependencies = [ "libm", ] +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -954,6 +1045,29 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + [[package]] name = "paste" version = "1.0.14" @@ -973,9 +1087,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "ppv-lite86" @@ -983,6 +1097,19 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "preimage-oracle" +version = "0.1.0" +dependencies = [ + "alloy-primitives", + "anyhow", + "once_cell", + "serde", + "serde_json", + "tokio", + "tracing", +] + [[package]] name = "primitive-types" version = "0.12.1" @@ -1251,6 +1378,12 @@ 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-hex" version = "2.1.0" @@ -1306,6 +1439,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "sec1" version = "0.7.3" @@ -1422,6 +1561,15 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "signature" version = "2.1.0" @@ -1447,6 +1595,16 @@ dependencies = [ "serde", ] +[[package]] +name = "socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "spin" version = "0.5.2" @@ -1564,6 +1722,36 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tokio" +version = "1.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + [[package]] name = "toml_datetime" version = "0.6.3" diff --git a/crates/preimage/Cargo.toml b/crates/preimage/Cargo.toml new file mode 100644 index 0000000..d5052f4 --- /dev/null +++ b/crates/preimage/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "preimage-oracle" +description = "Bindings for interacting as a client or server over the Pre-image Oracle ABI" +edition = "2021" + +version.workspace = true +authors.workspace = true + +[dependencies] +alloy-primitives = "0.3.3" +once_cell = "1.18.0" +serde = { version = "1.0.188", features = ["derive"] } +serde_json = "1.0.106" +tokio = { version = "1.32.0", features = ["full"] } + +# misc +anyhow = "1.0.75" +tracing = "0.1.37" + +[features] +tracing = [] diff --git a/crates/preimage/README.md b/crates/preimage/README.md new file mode 100644 index 0000000..9ad17f4 --- /dev/null +++ b/crates/preimage/README.md @@ -0,0 +1,11 @@ +# `preimage-oracle` + +The `preimage-oracle` crate offers bindings to interact as client or sever over the Pre-image Oracle ABI. + +Read more about the Preimage Oracle in the OP Stack [specs][specs]. + +See the OP Stack's [op-program][op-program] and [Cannon client examples](../../example) for client-side usage. +See [`mipsevm`](../mipsevm) for server-side usage. + +[specs]: https://github.com/ethereum-optimism/optimism/blob/6c7f366a55febbb119aa0b02d73f008c1c909900/specs/fault-proof.md +[op-program]: https://github.com/ethereum-optimism/optimism/tree/develop/op-program diff --git a/crates/preimage/src/lib.rs b/crates/preimage/src/lib.rs new file mode 100644 index 0000000..2d7c611 --- /dev/null +++ b/crates/preimage/src/lib.rs @@ -0,0 +1,13 @@ +#![doc = include_str!("../README.md")] +#![allow(dead_code, unused_variables)] + +mod oracle; +// pub use oracle::{OracleClient, OracleServer}; + +mod traits; +pub use traits::{Hint, Hinter, Key, Oracle}; + +mod types; +pub use types::{ + HinterFn, Keccak256Key, KeyType, LocalIndexKey, OracleFn, PreimageGetter, ReadWriterPair, +}; diff --git a/crates/preimage/src/oracle.rs b/crates/preimage/src/oracle.rs new file mode 100644 index 0000000..78a91ad --- /dev/null +++ b/crates/preimage/src/oracle.rs @@ -0,0 +1,65 @@ +// //! This module contains the [Client] struct and its implementation. +// +// use crate::{Oracle, PreimageGetter}; +// use alloy_primitives::B256; +// use anyhow::Result; +// use std::io::{Read, Write}; +// +// pub struct OracleClient { +// rw: RW, +// } +// +// impl OracleClient { +// fn new(rw: RW) -> Self { +// Self { rw } +// } +// } +// +// impl Oracle for OracleClient { +// fn get(&mut self, key: impl crate::Key) -> Result> { +// let hash = key.preimage_key(); +// self.rw.write(hash.as_ref())?; +// +// let length = 0u64; +// self.rw.read(&mut length.to_be_bytes())?; +// +// let mut payload = vec![0u8; length as usize]; +// self.rw.read_to_end(&mut payload)?; +// +// Ok(payload) +// } +// } +// +// pub struct OracleServer { +// rw: RW, +// } +// +// impl OracleServer { +// fn new(rw: RW) -> Self { +// Self { rw } +// } +// } +// +// impl OracleServer { +// pub fn new_preimage_request(&mut self, getter: PreimageGetter) -> Result<()> { +// let mut key = B256::ZERO; +// +// // TODO(clabby): Dunno if this is right. +// self.rw.read_exact(key.as_mut())?; +// +// let value = getter(key)?; +// +// self.rw.write(&(value.len() as u64).to_be_bytes())?; +// +// if value.is_empty() { +// return Ok(()); +// } +// +// self.rw.write(value.as_ref())?; +// +// Ok(()) +// } +// } +// +// #[cfg(test)] +// mod test {} diff --git a/crates/preimage/src/traits.rs b/crates/preimage/src/traits.rs new file mode 100644 index 0000000..f2053a0 --- /dev/null +++ b/crates/preimage/src/traits.rs @@ -0,0 +1,35 @@ +//! This module contains the traits for the preimage-oracle crate. + +use alloy_primitives::B256; +use anyhow::Result; + +/// The [Key] trait describes the behavior of a pre-image key that may be wrapped +/// into a 32-byte type-prefixed key. +pub trait Key { + /// Changes the [Key] commitment into a 32-byte type-prefixed preimage key. + fn preimage_key(self) -> B256; +} + +/// The [Oracle] trait describes the behavior of a read-only pre-image oracle. +pub trait Oracle { + /// Get the full pre-image of a given pre-image key. + fn get(&mut self, key: impl Key) -> Result>; +} + +// [Hint] is an trait to enable any program type to function as a hint, +// When passed to the Hinter interface, returning a string representation +// of what data the host should prepare pre-images for. +pub trait Hint { + /// Returns a string representation of the data the host should prepare + /// pre-images for. + fn hint() -> String; +} + +// [Hinter] is an trait describing behavior for writing hints to the host. +// This may be implemented as a no-op or logging hinter if the program is executing +// in a read-only environment where the host is expected to have all pre-images ready. +pub trait Hinter { + /// Returns a string representation of the data the host should prepare + /// pre-images for. + fn hint(&self) -> String; +} diff --git a/crates/preimage/src/types.rs b/crates/preimage/src/types.rs new file mode 100644 index 0000000..a85d8f9 --- /dev/null +++ b/crates/preimage/src/types.rs @@ -0,0 +1,79 @@ +//! This module contains the types for the preimage-oracle crate. + +use crate::{traits::Hint, Key}; +use alloy_primitives::B256; +use anyhow::Result; +use std::{fmt::Write, io::Read}; + +#[repr(u8)] +pub enum KeyType { + /// The zero key type is illegal to use. + _Illegal = 0, + /// The local key type is used to index a local variable, specific to the program instance. + Local = 1, + /// The global key type is used to index a global keccak256 preimage. + GlobalKeccak = 2, +} + +/// A [LocalIndexKey] is a key local to the program, indexing a special program input. +pub type LocalIndexKey = u64; + +impl Key for LocalIndexKey { + fn preimage_key(self) -> B256 { + let mut out = B256::ZERO; + out[0] = KeyType::Local as u8; + out[24..].copy_from_slice(&self.to_be_bytes()); + out + } +} + +/// A [Keccak256Key] wraps a keccak256 hash to use it as a typed pre-image key. +pub type Keccak256Key = B256; + +impl Key for Keccak256Key { + fn preimage_key(mut self) -> B256 { + self[0] = KeyType::GlobalKeccak as u8; + self + } +} + +/// An [OracleFn] is a function that can be used to fetch pre-images. +pub type OracleFn = fn(key: dyn Key) -> Vec; + +/// A [HinterFn] is a function that can be used to write a hint to the host. +pub type HinterFn = fn(hint: dyn Hint); + +/// A [ReadWriterPair] is a wrapper around two types, implementing [Read] and [Write]. +pub struct ReadWriterPair { + reader: R, + writer: W, +} + +impl ReadWriterPair { + pub fn new(reader: R, writer: W) -> Self { + Self { reader, writer } + } +} + +impl Read for ReadWriterPair +where + R: Read, + W: Write, +{ + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + self.reader.read(buf) + } +} + +impl Write for ReadWriterPair +where + R: Read, + W: Write, +{ + fn write_str(&mut self, s: &str) -> std::fmt::Result { + self.writer.write_str(s) + } +} + +/// A [PreimageGetter] is a function that can be used to fetch pre-images. +pub type PreimageGetter = fn(key: B256) -> Result>;