cargo_openvm/commands/
keygen.rs1use std::{
2 fs::{copy, create_dir_all},
3 path::{Path, PathBuf},
4};
5
6use clap::Parser;
7use eyre::Result;
8use openvm_sdk::{fs::write_object_to_file, Sdk};
9
10use crate::{
11 default::{DEFAULT_APP_PK_NAME, DEFAULT_APP_VK_NAME},
12 util::{
13 get_app_pk_path, get_app_vk_path, get_manifest_path_and_dir, get_target_dir,
14 read_config_toml_or_default,
15 },
16};
17
18#[derive(Parser)]
19#[command(name = "keygen", about = "Generate an application proving key")]
20pub struct KeygenCmd {
21 #[arg(
22 long,
23 help = "Path to the OpenVM config .toml file that specifies the VM extensions, by default will search for the file at ${manifest_dir}/openvm.toml",
24 help_heading = "OpenVM Options"
25 )]
26 config: Option<PathBuf>,
27
28 #[arg(
29 long,
30 help = "Output directory that OpenVM proving artifacts will be copied to",
31 help_heading = "OpenVM Options"
32 )]
33 output_dir: Option<PathBuf>,
34
35 #[command(flatten)]
36 cargo_args: KeygenCargoArgs,
37}
38
39#[derive(Parser)]
40pub struct KeygenCargoArgs {
41 #[arg(
42 long,
43 value_name = "DIR",
44 help = "Directory for all Cargo-generated artifacts and intermediate files",
45 help_heading = "Cargo Options"
46 )]
47 pub(crate) target_dir: Option<PathBuf>,
48
49 #[arg(
50 long,
51 value_name = "PATH",
52 help = "Path to the Cargo.toml file, by default searches for the file in the current or any parent directory",
53 help_heading = "Cargo Options"
54 )]
55 pub(crate) manifest_path: Option<PathBuf>,
56}
57
58impl KeygenCmd {
59 pub fn run(&self) -> Result<()> {
60 let (manifest_path, manifest_dir) =
61 get_manifest_path_and_dir(&self.cargo_args.manifest_path)?;
62 let target_dir = get_target_dir(&self.cargo_args.target_dir, &manifest_path);
63 let app_pk_path = get_app_pk_path(&target_dir);
64 let app_vk_path = get_app_vk_path(&target_dir);
65
66 keygen(
67 self.config
68 .to_owned()
69 .unwrap_or_else(|| manifest_dir.join("openvm.toml")),
70 &app_pk_path,
71 &app_vk_path,
72 self.output_dir.as_ref(),
73 )?;
74 println!(
75 "Successfully generated app pk and vk in {}",
76 if let Some(output_dir) = self.output_dir.as_ref() {
77 output_dir.display()
78 } else {
79 app_pk_path.parent().unwrap().display()
80 }
81 );
82 Ok(())
83 }
84}
85
86pub(crate) fn keygen(
87 config: impl AsRef<Path>,
88 app_pk_path: impl AsRef<Path>,
89 app_vk_path: impl AsRef<Path>,
90 output_dir: Option<impl AsRef<Path>>,
91) -> Result<()> {
92 let app_config = read_config_toml_or_default(config)?;
93 let (app_pk, app_vk) = Sdk::new(app_config)?.app_keygen();
94 write_object_to_file(&app_vk_path, app_vk)?;
95 write_object_to_file(&app_pk_path, app_pk)?;
96
97 if let Some(output_dir) = output_dir {
98 let output_dir = output_dir.as_ref();
99 create_dir_all(output_dir)?;
100 copy(&app_pk_path, output_dir.join(DEFAULT_APP_PK_NAME))?;
101 copy(&app_vk_path, output_dir.join(DEFAULT_APP_VK_NAME))?;
102 }
103
104 Ok(())
105}