diff --git a/Cargo.toml b/Cargo.toml index a1b38a4..3f49cf4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,9 @@ anyhow = "1.0.86" hex = "0.4.3" tokio = "1.38.0" +# Jolt +jolt = { package = "jolt-sdk", git = "https://github.com/a16z/jolt", features = ["host"] } + # Sp1 sp1-sdk = { git = "https://github.com/succinctlabs/sp1.git", tag = "v1.0.8-testnet" } diff --git a/Makefile b/Makefile index c90bc67..74cfa0e 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,12 @@ install_sp1: @cargo prove --version @echo "Sp1 Toolchain Installed" +install_jolt: + @curl -L https://sp1.succinct.xyz | bash + @sp1up + @cargo prove --version + @echo "Jolt Toolchain Installed" + # Default target all: instal diff --git a/src/jolt.rs b/src/jolt.rs new file mode 100644 index 0000000..08e02b1 --- /dev/null +++ b/src/jolt.rs @@ -0,0 +1,52 @@ +use std::{fs, io::{self, Write}, process::Command}; + +use crate::utils; + +pub const JOLT_PROOF_PATH: &str = "./jolt.proof"; +pub const JOLT_ELF_PATH: &str = "./jolt.elf"; +pub const JOLT_WORKSPACE_DIR: &str = "./workspaces/jolt"; +pub const JOLT_SRC_DIR: &str = "./workspaces/jolt/guest/src"; +pub const JOLT_GUEST_MAIN: &str = "./workspaces/jolt/guest/src/main.rs"; + +pub const JOLT_GUEST_CARGO_TOML: &str = "./workspaces/jolt/guest/Cargo.toml"; +pub const JOLT_BASE_CARGO_TOML: &str = "./workspaces/base_files/jolt"; + +pub const JOLT_GUEST_PROGRAM_HEADER_STD: &str = "#![no_main]\n"; +pub const JOLT_GUEST_PROC_MACRO: &str = "\n#[jolt::provable]\n"; + +//pub const JOLT_GUEST_DEPS: &str = +// "\njolt = { package = \"jolt-sdk\", git = \"https://github.com/a16z/jolt\", features = [\"guest-std\"] }"; + +pub fn prepare_jolt_guest() -> io::Result<()> { + /* + #![no_main] + */ + utils::prepend_to_file(JOLT_GUEST_MAIN, JOLT_GUEST_PROGRAM_HEADER_STD)?; + + // Find and replace function name + let content = fs::read_to_string(JOLT_GUEST_MAIN).unwrap(); + + let modified_content = content.replace("main()", "method()"); + + /* + #[jolt::provable] + */ + let modified_content = + utils::add_before_substring(&modified_content, "fn method()", JOLT_GUEST_PROC_MACRO); + + let mut file = fs::File::create(JOLT_GUEST_MAIN).unwrap(); + file.write_all(modified_content.as_bytes()).unwrap(); + Ok(()) +} + +pub fn generate_jolt_proof() -> io::Result<()> { + let guest_path = fs::canonicalize(JOLT_WORKSPACE_DIR)?; + + Command::new("cargo") + .arg("run") + .arg("--release") + .current_dir(guest_path) + .status() + .unwrap(); + Ok(()) +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index d6f52e8..82c9ba9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ use ethers::types::Address; pub mod risc0; pub mod sp1; +pub mod jolt; pub mod utils; const BATCHER_URL: &str = "wss://batcher.alignedlayer.com"; diff --git a/src/main.rs b/src/main.rs index 2867ccd..c085842 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ use std::io; use std::path::PathBuf; use zkRust::risc0; use zkRust::sp1; +use zkRust::jolt; use zkRust::submit_proof_to_aligned; use zkRust::utils; @@ -22,6 +23,7 @@ enum Commands { /// Adds files to myapp ProveSp1(ProofArgs), ProveRisc0(ProofArgs), + ProveJolt(ProofArgs), } #[derive(Args, Debug)] @@ -96,6 +98,37 @@ fn main() -> io::Result<()> { println!("Proof submitted and verified on aligned"); } + Ok(()) + } + Commands::ProveJolt(args) => { + println!("Proving with Jolt, program in: {}", args.guest_path); + + utils::prepare_workspace( + &args.guest_path, + jolt::JOLT_SRC_DIR, + jolt::JOLT_GUEST_CARGO_TOML, + jolt::JOLT_BASE_CARGO_TOML, + )?; + + jolt::prepare_jolt_guest()?; + jolt::generate_jolt_proof()?; + + println!("Proof and Proof Image generated!"); + + // Submit to aligned + if let Some(keystore_path) = args.submit_to_aligned_with_keystore.clone() { + submit_proof_to_aligned( + keystore_path, + jolt::JOLT_PROOF_PATH, + jolt::JOLT_ELF_PATH, + //TODO: Change this to Jolt when upstream change is made + ProvingSystemId::Risc0, + ) + .unwrap(); + + println!("Proof submitted and verified on aligned"); + } + Ok(()) } } diff --git a/src/utils.rs b/src/utils.rs index 07d01ad..123f219 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -4,6 +4,18 @@ use std::{ path::Path, }; +pub fn add_before_substring(original_string: &str, substring: &str, text_to_add: &str) -> String { + if let Some(index) = original_string.find(substring) { + let mut modified_string = String::with_capacity(original_string.len() + text_to_add.len()); + modified_string.push_str(&original_string[..index]); + modified_string.push_str(text_to_add); + modified_string.push_str(&original_string[index..]); + modified_string + } else { + original_string.to_string() + } +} + pub fn prepend_to_file(file_path: &str, text_to_prepend: &str) -> io::Result<()> { // Open the file in read mode to read its existing content let mut file = OpenOptions::new().read(true).write(true).open(file_path)?; diff --git a/workspaces/base_files/jolt b/workspaces/base_files/jolt new file mode 100644 index 0000000..0b94c74 --- /dev/null +++ b/workspaces/base_files/jolt @@ -0,0 +1,14 @@ +[package] +name = "guest" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "guest" +path = "./src/lib.rs" + +[features] +guest = [] + +[dependencies] +jolt = { package = "jolt-sdk", git = "https://github.com/a16z/jolt", features = ["guest-std"] } diff --git a/workspaces/jolt/.gitignore b/workspaces/jolt/.gitignore new file mode 100644 index 0000000..1de5659 --- /dev/null +++ b/workspaces/jolt/.gitignore @@ -0,0 +1 @@ +target \ No newline at end of file diff --git a/workspaces/jolt/Cargo.toml b/workspaces/jolt/Cargo.toml new file mode 100644 index 0000000..a573451 --- /dev/null +++ b/workspaces/jolt/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "jolt" +version = "0.1.0" +edition = "2021" + +[workspace] +members = ["guest"] + +[profile.release] +debug = 1 +codegen-units = 1 +lto = "fat" + +[dependencies] +jolt = { package = "jolt-sdk", git = "https://github.com/a16z/jolt", features = ["host"] } +guest = { path = "./guest" } + +[patch.crates-io] +ark-ff = { git = "https://github.com/a16z/arkworks-algebra", branch = "optimize/field-from-u64" } +ark-ec = { git = "https://github.com/a16z/arkworks-algebra", branch = "optimize/field-from-u64" } +ark-serialize = { git = "https://github.com/a16z/arkworks-algebra", branch = "optimize/field-from-u64" } diff --git a/workspaces/jolt/guest/Cargo.toml b/workspaces/jolt/guest/Cargo.toml new file mode 100644 index 0000000..9da2c65 --- /dev/null +++ b/workspaces/jolt/guest/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "guest" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "guest" +path = "./src/lib.rs" + +[features] +guest = [] + +[dependencies] +jolt = { package = "jolt-sdk", git = "https://github.com/a16z/jolt" } diff --git a/workspaces/jolt/rust-toolchain.toml b/workspaces/jolt/rust-toolchain.toml new file mode 100644 index 0000000..2b8f238 --- /dev/null +++ b/workspaces/jolt/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2024-04-20" +targets = ["riscv32i-unknown-none-elf"] + diff --git a/workspaces/jolt/src/main.rs b/workspaces/jolt/src/main.rs new file mode 100644 index 0000000..14d860b --- /dev/null +++ b/workspaces/jolt/src/main.rs @@ -0,0 +1,9 @@ +pub fn main() { + let (prove_fib, verify_fib) = guest::build_method(); + + let (output, proof) = prove_method(50); + let is_valid = verify_method(proof); + + println!("output: {}", output); + println!("valid: {}", is_valid); +}