diff --git a/Cargo.lock b/Cargo.lock index 64285ab6..8e11da1e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5541,9 +5541,14 @@ dependencies = [ name = "server" version = "0.1.0" dependencies = [ + "anyhow", "axum", "cairo-vm", "dry_hint_processor", + "fetcher", + "hints", + "serde", + "sound_hint_processor", "tokio", "tower-http", "tracing-subscriber", diff --git a/Cargo.toml b/Cargo.toml index ee9aa0b2..6946ebc6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ members = [ [workspace.dependencies] alloy = { version = "0.7.2", features = ["full"] } alloy-rlp = { version = "0.3.5", features = ["derive"] } +anyhow = "1.0.95" axum = { version = "0.8", features = ["tracing"] } bincode = { version = "2.0.0-rc.3", default-features = false, features = ["serde"]} cairo-lang-casm = { version = "2.10.0-rc.1", default-features = false } diff --git a/crates/fetcher/src/lib.rs b/crates/fetcher/src/lib.rs index ffda729c..ffa294db 100644 --- a/crates/fetcher/src/lib.rs +++ b/crates/fetcher/src/lib.rs @@ -373,8 +373,7 @@ where .collect() } -pub fn parse_syscall_handler(input_file: &[u8]) -> Result { - let syscall_handler = serde_json::from_slice::(input_file)?; +pub fn parse_syscall_handler(syscall_handler: SyscallHandler) -> Result { let mut proof_keys = ProofKeys::default(); // Process EVM keys diff --git a/crates/fetcher/src/main.rs b/crates/fetcher/src/main.rs index 401b713a..cf2255fe 100644 --- a/crates/fetcher/src/main.rs +++ b/crates/fetcher/src/main.rs @@ -1,6 +1,7 @@ use std::{fs, path::PathBuf}; use clap::{Parser, ValueHint}; +use dry_hint_processor::syscall_handler::SyscallHandler; use fetcher::{parse_syscall_handler, Fetcher}; use types::ChainProofs; @@ -17,7 +18,9 @@ struct Args { async fn main() -> Result<(), fetcher::FetcherError> { let args = Args::try_parse_from(std::env::args()).map_err(fetcher::FetcherError::Args)?; let input_file = fs::read(&args.filename)?; - let proof_keys = parse_syscall_handler(&input_file)?; + + let syscall_handler: SyscallHandler = serde_json::from_slice(&input_file)?; + let proof_keys = parse_syscall_handler(syscall_handler)?; let fetcher = Fetcher::new(&proof_keys); let (evm_proofs, starknet_proofs) = tokio::try_join!(fetcher.collect_evm_proofs(), fetcher.collect_starknet_proofs())?; diff --git a/crates/server/Cargo.toml b/crates/server/Cargo.toml index f926f9ea..349806da 100644 --- a/crates/server/Cargo.toml +++ b/crates/server/Cargo.toml @@ -4,10 +4,15 @@ version = "0.1.0" edition = "2024" [dependencies] +anyhow.workspace = true axum.workspace = true +fetcher.workspace = true cairo-vm.workspace = true dry_hint_processor.workspace = true +sound_hint_processor.workspace = true +serde.workspace = true tokio.workspace = true tower-http.workspace = true tracing-subscriber.workspace = true -types.workspace = true \ No newline at end of file +types.workspace = true +hints.workspace = true \ No newline at end of file diff --git a/crates/server/src/dry_run.rs b/crates/server/src/dry_run.rs index 1885d230..ce553431 100644 --- a/crates/server/src/dry_run.rs +++ b/crates/server/src/dry_run.rs @@ -1,7 +1,58 @@ +use std::{env, path::PathBuf}; + use axum::Json; -use dry_hint_processor::syscall_handler::SyscallHandler; -use types::HDPDryRunInput; +use cairo_vm::{ + cairo_run::{self, cairo_run_program}, + types::{layout::CairoLayoutParams, layout_name::LayoutName, program::Program}, +}; +use dry_hint_processor::{ + CustomHintProcessor, + syscall_handler::{SyscallHandler, SyscallHandlerWrapper}, +}; +use hints::vars; +use serde::Deserialize; +use types::{HDPDryRunInput, error::Error}; + +use crate::error::AppError; + +#[derive(Debug, Deserialize)] +pub struct DryRunRequest { + params: Option, + layout: LayoutName, + input: HDPDryRunInput, +} + +pub async fn root(Json(value): Json) -> Result, AppError> { + // Init CairoRunConfig + let cairo_run_config = cairo_run::CairoRunConfig { + trace_enabled: false, + relocate_mem: false, + layout: value.layout, + proof_mode: false, + secure_run: Some(true), + allow_missing_builtins: Some(true), + dynamic_layout_params: value.params, + ..Default::default() + }; + + // Locate the compiled program file in the `OUT_DIR` folder. + let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR is not set")); + let program_file_path = out_dir.join("cairo").join("compiled.json"); + + let program_file = std::fs::read(program_file_path).map_err(Error::IO)?; + + // Load the Program + let program = Program::from_bytes(&program_file, Some(cairo_run_config.entrypoint))?; + + let mut hint_processor = CustomHintProcessor::new(value.input); + let cairo_runner = cairo_run_program(&program, &cairo_run_config, &mut hint_processor).unwrap(); -pub async fn root(Json(value): Json) -> Json { - todo!() + Ok(Json( + cairo_runner + .exec_scopes + .get::(vars::scopes::SYSCALL_HANDLER)? + .syscall_handler + .try_read()? + .clone(), + )) } diff --git a/crates/server/src/error.rs b/crates/server/src/error.rs new file mode 100644 index 00000000..c12289cd --- /dev/null +++ b/crates/server/src/error.rs @@ -0,0 +1,25 @@ +use axum::{ + http::StatusCode, + response::{IntoResponse, Response}, +}; + +// Make our own error that wraps `anyhow::Error`. +pub struct AppError(anyhow::Error); + +// Tell axum how to convert `AppError` into a response. +impl IntoResponse for AppError { + fn into_response(self) -> Response { + (StatusCode::INTERNAL_SERVER_ERROR, format!("Something went wrong: {}", self.0)).into_response() + } +} + +// This enables using `?` on functions that return `Result<_, anyhow::Error>` to turn them into +// `Result<_, AppError>`. That way you don't need to do that manually. +impl From for AppError +where + E: Into, +{ + fn from(err: E) -> Self { + Self(err.into()) + } +} diff --git a/crates/server/src/fetch_proofs.rs b/crates/server/src/fetch_proofs.rs index a58fd34e..1be761e2 100644 --- a/crates/server/src/fetch_proofs.rs +++ b/crates/server/src/fetch_proofs.rs @@ -1,7 +1,19 @@ use axum::Json; use dry_hint_processor::syscall_handler::SyscallHandler; +use fetcher::{Fetcher, parse_syscall_handler}; use types::ChainProofs; -pub async fn root(Json(value): Json) -> Json> { - todo!() +use crate::error::AppError; + +pub async fn root(Json(value): Json) -> Result>, AppError> { + let proof_keys = parse_syscall_handler(value)?; + + let fetcher = Fetcher::new(&proof_keys); + let (evm_proofs, starknet_proofs) = tokio::try_join!(fetcher.collect_evm_proofs(), fetcher.collect_starknet_proofs())?; + let chain_proofs = vec![ + ChainProofs::EthereumSepolia(evm_proofs), + ChainProofs::StarknetSepolia(starknet_proofs), + ]; + + Ok(Json(chain_proofs)) } diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index 28337db4..15187847 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs @@ -12,6 +12,7 @@ use tower_http::{timeout::TimeoutLayer, trace::TraceLayer}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; pub mod dry_run; +pub mod error; pub mod fetch_proofs; pub mod sound_run; diff --git a/crates/server/src/sound_run.rs b/crates/server/src/sound_run.rs index 2827c722..cbf91d01 100644 --- a/crates/server/src/sound_run.rs +++ b/crates/server/src/sound_run.rs @@ -1,7 +1,48 @@ +use std::{env, path::PathBuf}; + use axum::Json; -use cairo_vm::vm::runners::cairo_pie::CairoPie; -use types::HDPInput; +use cairo_vm::{ + cairo_run::{self, cairo_run_program}, + types::{layout::CairoLayoutParams, layout_name::LayoutName, program::Program}, + vm::runners::cairo_pie::CairoPie, +}; +use serde::Deserialize; +use sound_hint_processor::CustomHintProcessor; +use types::{HDPInput, error::Error}; + +use crate::error::AppError; + +#[derive(Debug, Deserialize)] +pub struct SoundRunRequest { + params: Option, + layout: LayoutName, + input: HDPInput, +} + +pub async fn root(Json(value): Json) -> Result, AppError> { + // Init CairoRunConfig + let cairo_run_config = cairo_run::CairoRunConfig { + trace_enabled: false, + relocate_mem: false, + layout: value.layout, + proof_mode: false, + secure_run: Some(true), + allow_missing_builtins: Some(true), + dynamic_layout_params: value.params, + ..Default::default() + }; + + // Locate the compiled program file in the `OUT_DIR` folder. + let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR is not set")); + let program_file_path = out_dir.join("cairo").join("compiled.json"); + + let program_file = std::fs::read(program_file_path).map_err(Error::IO)?; + + // Load the Program + let program = Program::from_bytes(&program_file, Some(cairo_run_config.entrypoint))?; + + let mut hint_processor = CustomHintProcessor::new(value.input); + let cairo_runner = cairo_run_program(&program, &cairo_run_config, &mut hint_processor).unwrap(); -pub async fn root(Json(value): Json) -> Json { - todo!() + Ok(Json(cairo_runner.get_cairo_pie()?)) }