diff --git a/crates/axvm-sdk/src/fs.rs b/crates/axvm-sdk/src/fs.rs index da88d86a9d..2d54b3aaad 100644 --- a/crates/axvm-sdk/src/fs.rs +++ b/crates/axvm-sdk/src/fs.rs @@ -1,5 +1,6 @@ use std::{ fs::{create_dir_all, write, File}, + io::Write, path::Path, }; @@ -15,11 +16,15 @@ use crate::{ }; pub fn read_exe_from_file>(path: P) -> Result> { - read_from_file_bson(path) + let data = std::fs::read(path)?; + let exe = bincode::serde::decode_from_slice(&data, bincode::config::standard())?.0; + Ok(exe) } pub fn write_exe_to_file>(exe: AxVmExe, path: P) -> Result<()> { - write_to_file_bson(path, exe) + let data = bincode::serde::encode_to_vec(&exe, bincode::config::standard())?; + File::create(path)?.write_all(&data)?; + Ok(()) } pub fn read_app_pk_from_file, P: AsRef>( diff --git a/crates/cargo-axiom/src/commands/build.rs b/crates/cargo-axiom/src/commands/build.rs index da2cd44cd2..3cb1277d80 100644 --- a/crates/cargo-axiom/src/commands/build.rs +++ b/crates/cargo-axiom/src/commands/build.rs @@ -7,11 +7,17 @@ use axvm_build::{ build_guest_package, find_unique_executable, get_package, GuestOptions, TargetFilter, }; use axvm_rv32im_transpiler::{Rv32ITranspilerExtension, Rv32MTranspilerExtension}; -use axvm_sdk::{fs::write_exe_to_file, Sdk}; +use axvm_sdk::{ + config::{AppConfig, SdkVmConfig}, + fs::write_exe_to_file, + Sdk, +}; use axvm_transpiler::{axvm_platform::memory::MEM_SIZE, elf::Elf, transpiler::Transpiler}; use clap::Parser; use eyre::Result; +use crate::util::read_to_struct_toml; + #[derive(Parser)] #[command(name = "build", about = "Compile an axVM program")] pub struct BuildCmd { @@ -49,9 +55,13 @@ pub struct BuildArgs { #[arg(long, default_value = "false")] pub transpile: bool, + /// Path to the SDK config .toml file that specifies the transpiler extensions + #[arg(long)] + pub transpiler_config: Option, + /// Output path for the transpiled program (default: .axvmexe) #[arg(long)] - pub transpile_path: Option, + pub transpile_to: Option, /// Build profile #[arg(long, default_value = "release")] @@ -60,7 +70,7 @@ pub struct BuildArgs { impl BuildArgs { pub fn exe_path(&self, elf_path: &Path) -> PathBuf { - self.transpile_path + self.transpile_to .clone() .unwrap_or_else(|| elf_path.with_extension("axvmexe")) } @@ -116,7 +126,20 @@ pub(crate) fn build(build_args: &BuildArgs) -> Result> { let elf_path = elf_path?; println!("[axiom] Transpiling the package..."); let output_path = build_args.exe_path(&elf_path); - transpile(elf_path.clone(), output_path.clone())?; + let transpiler = if let Some(transpiler_config) = build_args.transpiler_config.clone() { + let app_config: AppConfig = read_to_struct_toml(&transpiler_config)?; + app_config.app_vm_config.transpiler() + } else { + Transpiler::default() + .with_extension(Rv32ITranspilerExtension) + .with_extension(Rv32MTranspilerExtension) + }; + + let data = read(elf_path.clone())?; + let elf = Elf::decode(&data, MEM_SIZE as u32)?; + let exe = Sdk.transpile(elf, transpiler)?; + write_exe_to_file(exe, &output_path)?; + println!( "[axiom] Successfully transpiled to {}", output_path.display() @@ -133,17 +156,3 @@ pub(crate) fn build(build_args: &BuildArgs) -> Result> { Ok(None) } } - -fn transpile(elf_path: PathBuf, output_path: PathBuf) -> Result<()> { - let data = read(elf_path.clone())?; - let elf = Elf::decode(&data, MEM_SIZE as u32)?; - let exe = Sdk.transpile( - elf, - Transpiler::default() - .with_extension(Rv32ITranspilerExtension) - .with_extension(Rv32MTranspilerExtension), - )?; - write_exe_to_file(exe, &output_path)?; - eprintln!("Successfully transpiled to {}", output_path.display()); - Ok(()) -} diff --git a/crates/cargo-axiom/src/lib.rs b/crates/cargo-axiom/src/lib.rs index a4c5666ab6..a465ac3531 100644 --- a/crates/cargo-axiom/src/lib.rs +++ b/crates/cargo-axiom/src/lib.rs @@ -52,3 +52,6 @@ pub fn is_supported_target() -> bool { pub fn get_target() -> String { target_lexicon::HOST.to_string() } + +#[cfg(test)] +mod tests; diff --git a/crates/cargo-axiom/src/tests.rs b/crates/cargo-axiom/src/tests.rs new file mode 100644 index 0000000000..9f2dafeb70 --- /dev/null +++ b/crates/cargo-axiom/src/tests.rs @@ -0,0 +1,99 @@ +use std::{env, process::Command}; + +use eyre::Result; +use tempfile::tempdir; + +#[test] +fn test_cli_e2e() -> Result<()> { + let temp_dir = tempdir()?; + let package_dir = env::current_dir()?; + let prefix = "[test cli e2e]"; + let run_cmd = |program: &str, args: &[&str]| { + println!("{prefix} Running command: {} {} ...", program, args[0]); + let mut cmd = Command::new(program); + cmd.args(args); + cmd.current_dir(&package_dir); + let output = cmd.output().unwrap(); + println!("{prefix} Finished!"); + println!("{prefix} stdout:"); + println!("{}", std::str::from_utf8(&output.stdout).unwrap()); + println!("{prefix} stderr:"); + println!("{}", std::str::from_utf8(&output.stderr).unwrap()); + }; + run_cmd("cargo", &["install", "--path", ".", "--force"]); + let temp_exe = temp_dir.path().join("example.axvmexe"); + let temp_pk = temp_dir.path().join("example.pk"); + let temp_vk = temp_dir.path().join("example.vk"); + let temp_proof = temp_dir.path().join("example.apppf"); + + run_cmd( + "cargo", + &[ + "axiom", + "build", + "--manifest-dir", + "../axvm-sdk/example", + "--transpile", + "--transpiler-config", + "example/app_config.toml", + "--transpile-to", + temp_exe.to_str().unwrap(), + ], + ); + + run_cmd( + "cargo", + &[ + "axiom", + "keygen", + "--config", + "example/app_config.toml", + "--output", + temp_pk.to_str().unwrap(), + "--vk-output", + temp_vk.to_str().unwrap(), + ], + ); + + run_cmd( + "cargo", + &[ + "axiom", + "run", + "--exe", + temp_exe.to_str().unwrap(), + "--config", + "example/app_config.toml", + ], + ); + + run_cmd( + "cargo", + &[ + "axiom", + "prove", + "app", + "--app-pk", + temp_pk.to_str().unwrap(), + "--exe", + temp_exe.to_str().unwrap(), + "--output", + temp_proof.to_str().unwrap(), + ], + ); + + run_cmd( + "cargo", + &[ + "axiom", + "verify", + "app", + "--app-vk", + temp_vk.to_str().unwrap(), + "--proof", + temp_proof.to_str().unwrap(), + ], + ); + + Ok(()) +}