diff --git a/Cargo.lock b/Cargo.lock index a08817c5..e490e736 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3700,7 +3700,9 @@ dependencies = [ "axum", "chrono", "clap 4.3.14", + "dotenvy", "ethers", + "hex", "hyper", "oz-api", "serde", diff --git a/Readme.md b/Readme.md index 2f2d4139..0ce1bde1 100644 --- a/Readme.md +++ b/Readme.md @@ -59,6 +59,22 @@ Fetch the [postgres](https://hub.docker.com/_/postgres) docker image before runn docker pull postgres ``` +## Micro OZ +Sequencer depends on Openzeppelin Defender. In order to run it locally we provide a mock version of this service under the `micro-oz` crate. + +To run it, execute the following command: +```shell +cargo run -p micro-oz +``` + +By default it'll run on port `9876` and start with default values compatible with anvil. +Check out +```shell +cargo run -p micro-oz -- --help +``` + +for more configuration options. + ### Worldcoin id contracts Worldcoin id contracts are ethereum smart contracts that are used by the sequencer diff --git a/crates/micro-oz/Cargo.toml b/crates/micro-oz/Cargo.toml index 5e0a1463..ce284bb8 100644 --- a/crates/micro-oz/Cargo.toml +++ b/crates/micro-oz/Cargo.toml @@ -11,7 +11,9 @@ async-trait = "0.1.71" axum = "0.6.19" chrono = "0.4.26" clap = { version = "4.3.14", features = ["env", "derive"] } +dotenvy = "0.15.0" ethers = { version = "1.0.0", features = ["openssl"] } +hex = "0.4.3" hyper = "0.14.27" oz-api = { path = "../oz-api" } serde = "1.0.171" diff --git a/crates/micro-oz/src/lib.rs b/crates/micro-oz/src/lib.rs index c83f7c6d..be35b7b1 100644 --- a/crates/micro-oz/src/lib.rs +++ b/crates/micro-oz/src/lib.rs @@ -17,7 +17,7 @@ pub mod server; const DEFAULT_GAS_LIMIT: u32 = 1_000_000; -pub use self::server::{spawn, ServerHandle}; +pub use self::server::{spawn, spawn_on_random_port, ServerHandle}; type PinheadSigner = SignerMiddleware<Provider<Http>, LocalWallet>; diff --git a/crates/micro-oz/src/main.rs b/crates/micro-oz/src/main.rs new file mode 100644 index 00000000..97e834c4 --- /dev/null +++ b/crates/micro-oz/src/main.rs @@ -0,0 +1,52 @@ +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + +use clap::Parser; +use ethers::prelude::k256::ecdsa::SigningKey; + +#[derive(Debug, Clone, Parser)] +#[clap(rename_all = "kebab-case")] +struct Args { + /// The port at which to serve + /// + /// Set to 0 to use a random port + #[clap(short, long, env, default_value = "9876")] + port: u16, + /// The RPC url to use + /// + /// Uses a default value compatible with anvil + #[clap(short, long, env, default_value = "http://127.0.0.1:8545")] + rpc_url: String, + /// A hex encoded private key + /// + /// By default uses a private key used by anvil + #[clap( + short, + long, + env, + default_value = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + )] + secret_key: String, +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + dotenvy::dotenv().ok(); + tracing_subscriber::fmt::init(); + + let args = Args::parse(); + + let private_key = args.secret_key.trim_start_matches("0x"); + let private_key = hex::decode(private_key)?; + + let signing_key = SigningKey::from_bytes(&private_key)?; + + let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), args.port); + + let handle = micro_oz::spawn(addr, args.rpc_url, signing_key).await?; + + tracing::info!("Micro OZ listening on {}", handle.endpoint()); + + handle.wait().await; + + Ok(()) +} diff --git a/crates/micro-oz/src/server.rs b/crates/micro-oz/src/server.rs index 76f2c9ef..db603a66 100644 --- a/crates/micro-oz/src/server.rs +++ b/crates/micro-oz/src/server.rs @@ -91,6 +91,12 @@ impl ServerHandle { format!("http://{}", self.addr) } + pub async fn wait(self) { + if let Err(e) = self.server_join_handle.await { + tracing::error!("Server error: {:?}", e); + } + } + pub async fn shutdown(self) { self.shutdown_notify.notify_waiters(); @@ -100,7 +106,11 @@ impl ServerHandle { } } -pub async fn spawn(rpc_url: String, secret_key: SigningKey) -> anyhow::Result<ServerHandle> { +pub async fn spawn( + addr: SocketAddr, + rpc_url: String, + secret_key: SigningKey, +) -> anyhow::Result<ServerHandle> { let pinhead = Pinhead::new(rpc_url, secret_key).await?; let router = Router::new() @@ -108,7 +118,6 @@ pub async fn spawn(rpc_url: String, secret_key: SigningKey) -> anyhow::Result<Se .route("/txs/:tx_id", get(query_transaction)) .with_state(pinhead.clone()); - let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0); let listener = TcpListener::bind(addr).context("Failed to bind random port")?; let local_addr = listener.local_addr()?; @@ -132,3 +141,12 @@ pub async fn spawn(rpc_url: String, secret_key: SigningKey) -> anyhow::Result<Se server_join_handle, }) } + +pub async fn spawn_on_random_port( + rpc_url: String, + secret_key: SigningKey, +) -> anyhow::Result<ServerHandle> { + let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0); + + spawn(addr, rpc_url, secret_key).await +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs index a530a014..a593a3e9 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -638,7 +638,7 @@ pub async fn spawn_deps( let chain = chain?; let signing_key = SigningKey::from_bytes(chain.private_key.as_bytes())?; - let micro_oz = micro_oz::spawn(chain.anvil.endpoint(), signing_key).await?; + let micro_oz = micro_oz::spawn_on_random_port(chain.anvil.endpoint(), signing_key).await?; let insertion_provers = insertion_provers .into_iter()