1use std::{path::PathBuf, sync::Arc};
2
3use clap::Parser;
4use eyre::Result;
5use openvm_native_recursion::halo2::utils::CacheHalo2ParamsReader;
6use openvm_sdk::{
7 commit::AppExecutionCommit,
8 config::SdkVmConfig,
9 fs::{
10 read_agg_pk_from_file, read_app_pk_from_file, read_exe_from_file, write_app_proof_to_file,
11 write_evm_proof_to_file,
12 },
13 keygen::AppProvingKey,
14 NonRootCommittedExe, Sdk, StdIn,
15};
16
17use crate::{
18 default::{
19 DEFAULT_AGG_PK_PATH, DEFAULT_APP_EXE_PATH, DEFAULT_APP_PK_PATH, DEFAULT_APP_PROOF_PATH,
20 DEFAULT_EVM_PROOF_PATH, DEFAULT_PARAMS_DIR,
21 },
22 input::{read_to_stdin, Input},
23};
24
25#[derive(Parser)]
26#[command(name = "prove", about = "Generate a program proof")]
27pub struct ProveCmd {
28 #[command(subcommand)]
29 command: ProveSubCommand,
30}
31
32#[derive(Parser)]
33enum ProveSubCommand {
34 App {
35 #[arg(long, action, help = "Path to app proving key", default_value = DEFAULT_APP_PK_PATH)]
36 app_pk: PathBuf,
37
38 #[arg(long, action, help = "Path to OpenVM executable", default_value = DEFAULT_APP_EXE_PATH)]
39 exe: PathBuf,
40
41 #[arg(long, value_parser, help = "Input to OpenVM program")]
42 input: Option<Input>,
43
44 #[arg(long, action, help = "Path to output proof", default_value = DEFAULT_APP_PROOF_PATH)]
45 output: PathBuf,
46 },
47 Evm {
48 #[arg(long, action, help = "Path to app proving key", default_value = DEFAULT_APP_PK_PATH)]
49 app_pk: PathBuf,
50
51 #[arg(long, action, help = "Path to OpenVM executable", default_value = DEFAULT_APP_EXE_PATH)]
52 exe: PathBuf,
53
54 #[arg(long, value_parser, help = "Input to OpenVM program")]
55 input: Option<Input>,
56
57 #[arg(long, action, help = "Path to output proof", default_value = DEFAULT_EVM_PROOF_PATH)]
58 output: PathBuf,
59 },
60}
61
62impl ProveCmd {
63 pub fn run(&self) -> Result<()> {
64 let sdk = Sdk::new();
65 match &self.command {
66 ProveSubCommand::App {
67 app_pk,
68 exe,
69 input,
70 output,
71 } => {
72 let (app_pk, committed_exe, input) =
73 Self::prepare_execution(&sdk, app_pk, exe, input)?;
74 let app_proof = sdk.generate_app_proof(app_pk, committed_exe, input)?;
75 write_app_proof_to_file(app_proof, output)?;
76 }
77 ProveSubCommand::Evm {
78 app_pk,
79 exe,
80 input,
81 output,
82 } => {
83 let params_reader = CacheHalo2ParamsReader::new(DEFAULT_PARAMS_DIR);
84 let (app_pk, committed_exe, input) =
85 Self::prepare_execution(&sdk, app_pk, exe, input)?;
86 println!("Generating EVM proof, this may take a lot of compute and memory...");
87 let agg_pk = read_agg_pk_from_file(DEFAULT_AGG_PK_PATH).map_err(|e| {
88 eyre::eyre!("Failed to read aggregation proving key: {}\nPlease run 'cargo openvm setup' first", e)
89 })?;
90 let evm_proof =
91 sdk.generate_evm_proof(¶ms_reader, app_pk, committed_exe, agg_pk, input)?;
92 write_evm_proof_to_file(evm_proof, output)?;
93 }
94 }
95 Ok(())
96 }
97
98 fn prepare_execution(
99 sdk: &Sdk,
100 app_pk: &PathBuf,
101 exe: &PathBuf,
102 input: &Option<Input>,
103 ) -> Result<(
104 Arc<AppProvingKey<SdkVmConfig>>,
105 Arc<NonRootCommittedExe>,
106 StdIn,
107 )> {
108 let app_pk: Arc<AppProvingKey<SdkVmConfig>> = Arc::new(read_app_pk_from_file(app_pk)?);
109 let app_exe = read_exe_from_file(exe)?;
110 let committed_exe = sdk.commit_app_exe(app_pk.app_fri_params(), app_exe)?;
111
112 let commits = AppExecutionCommit::compute(
113 &app_pk.app_vm_pk.vm_config,
114 &committed_exe,
115 &app_pk.leaf_committed_exe,
116 );
117 println!("app_pk commit: {:?}", commits.app_config_commit_to_bn254());
118 println!("exe commit: {:?}", commits.exe_commit_to_bn254());
119
120 let input = read_to_stdin(input)?;
121 Ok((app_pk, committed_exe, input))
122 }
123}