cargo_openvm/commands/
prove.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::{path::PathBuf, sync::Arc};

use clap::Parser;
use eyre::Result;
use openvm_native_recursion::halo2::utils::CacheHalo2ParamsReader;
use openvm_sdk::{
    commit::AppExecutionCommit,
    config::SdkVmConfig,
    fs::{
        read_agg_pk_from_file, read_app_pk_from_file, read_exe_from_file, write_app_proof_to_file,
        write_evm_proof_to_file,
    },
    keygen::AppProvingKey,
    NonRootCommittedExe, Sdk, StdIn,
};

use crate::{
    default::{
        DEFAULT_AGG_PK_PATH, DEFAULT_APP_EXE_PATH, DEFAULT_APP_PK_PATH, DEFAULT_APP_PROOF_PATH,
        DEFAULT_EVM_PROOF_PATH, DEFAULT_PARAMS_DIR,
    },
    util::{read_to_stdin, Input},
};

#[derive(Parser)]
#[command(name = "prove", about = "Generate a program proof")]
pub struct ProveCmd {
    #[clap(subcommand)]
    command: ProveSubCommand,
}

#[derive(Parser)]
enum ProveSubCommand {
    App {
        #[clap(long, action, help = "Path to app proving key", default_value = DEFAULT_APP_PK_PATH)]
        app_pk: PathBuf,

        #[clap(long, action, help = "Path to OpenVM executable", default_value = DEFAULT_APP_EXE_PATH)]
        exe: PathBuf,

        #[clap(long, value_parser, help = "Input to OpenVM program")]
        input: Option<Input>,

        #[clap(long, action, help = "Path to output proof", default_value = DEFAULT_APP_PROOF_PATH)]
        output: PathBuf,
    },
    Evm {
        #[clap(long, action, help = "Path to app proving key", default_value = DEFAULT_APP_PK_PATH)]
        app_pk: PathBuf,

        #[clap(long, action, help = "Path to OpenVM executable", default_value = DEFAULT_APP_EXE_PATH)]
        exe: PathBuf,

        #[clap(long, value_parser, help = "Input to OpenVM program")]
        input: Option<Input>,

        #[clap(long, action, help = "Path to output proof", default_value = DEFAULT_EVM_PROOF_PATH)]
        output: PathBuf,
    },
}

impl ProveCmd {
    pub fn run(&self) -> Result<()> {
        match &self.command {
            ProveSubCommand::App {
                app_pk,
                exe,
                input,
                output,
            } => {
                let (app_pk, committed_exe, input) = Self::prepare_execution(app_pk, exe, input)?;
                let app_proof = Sdk.generate_app_proof(app_pk, committed_exe, input)?;
                write_app_proof_to_file(app_proof, output)?;
            }
            ProveSubCommand::Evm {
                app_pk,
                exe,
                input,
                output,
            } => {
                let params_reader = CacheHalo2ParamsReader::new(DEFAULT_PARAMS_DIR);
                let (app_pk, committed_exe, input) = Self::prepare_execution(app_pk, exe, input)?;
                println!("Generating EVM proof, this may take a lot of compute and memory...");
                let agg_pk = read_agg_pk_from_file(DEFAULT_AGG_PK_PATH).map_err(|e| {
                    eyre::eyre!("Failed to read aggregation proving key: {}\nPlease run 'cargo openvm setup' first", e)
                })?;
                let evm_proof =
                    Sdk.generate_evm_proof(&params_reader, app_pk, committed_exe, agg_pk, input)?;
                write_evm_proof_to_file(evm_proof, output)?;
            }
        }
        Ok(())
    }

    fn prepare_execution(
        app_pk: &PathBuf,
        exe: &PathBuf,
        input: &Option<Input>,
    ) -> Result<(
        Arc<AppProvingKey<SdkVmConfig>>,
        Arc<NonRootCommittedExe>,
        StdIn,
    )> {
        let app_pk: Arc<AppProvingKey<SdkVmConfig>> = Arc::new(read_app_pk_from_file(app_pk)?);
        let app_exe = read_exe_from_file(exe)?;
        let committed_exe = Sdk.commit_app_exe(app_pk.app_fri_params(), app_exe)?;

        let commits = AppExecutionCommit::compute(
            &app_pk.app_vm_pk.vm_config,
            &committed_exe,
            &app_pk.leaf_committed_exe,
        );
        println!("app_pk commit: {:?}", commits.app_config_commit_to_bn254());
        println!("exe commit: {:?}", commits.exe_commit_to_bn254());

        let input = read_to_stdin(input)?;
        Ok((app_pk, committed_exe, input))
    }
}