cargo_openvm/commands/
prove.rs

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(&params_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}