cargo_openvm/commands/
setup.rs1use std::{
2 fs::{create_dir_all, write},
3 path::PathBuf,
4};
5
6use aws_config::{defaults, BehaviorVersion, Region};
7use aws_sdk_s3::Client;
8use clap::Parser;
9use eyre::{eyre, Result};
10use openvm_sdk::{
11 config::DEFAULT_HALO2_VERIFIER_K,
12 fs::{
13 read_object_from_file, write_evm_halo2_verifier_to_folder, write_object_to_file,
14 EVM_HALO2_VERIFIER_BASE_NAME, EVM_HALO2_VERIFIER_INTERFACE_NAME,
15 EVM_HALO2_VERIFIER_PARENT_NAME,
16 },
17 Sdk,
18};
19use static_assertions::const_assert;
20
21use crate::{
22 default::{
23 default_agg_halo2_pk_path, default_agg_stark_pk_path, default_agg_stark_vk_path,
24 default_asm_path, default_evm_halo2_verifier_path, default_params_dir,
25 },
26 util::read_default_agg_and_halo2_pk,
27};
28
29const MAX_HALO2_VERIFIER_K_FOR_DOWNLOAD: usize = 24;
32
33#[derive(Parser)]
34#[command(
35 name = "setup",
36 about = "Set up for generating EVM proofs. ATTENTION: this requires large amounts of computation and memory. "
37)]
38pub struct SetupCmd {
39 #[arg(
40 long,
41 default_value = "false",
42 help = "use --evm to also generate proving keys for EVM verifier"
43 )]
44 pub evm: bool,
45 #[arg(
46 long,
47 default_value = "false",
48 help = "force keygen even if the proving keys already exist"
49 )]
50 pub force_agg_keygen: bool,
51}
52
53impl SetupCmd {
54 pub async fn run(&self) -> Result<()> {
55 let default_agg_stark_pk_path = default_agg_stark_pk_path();
56 let default_agg_stark_vk_path = default_agg_stark_vk_path();
57 let default_evm_halo2_verifier_path = default_evm_halo2_verifier_path();
58 let default_asm_path = default_asm_path();
59 if !self.evm {
60 if PathBuf::from(&default_agg_stark_pk_path).exists() && !self.force_agg_keygen {
61 println!("Aggregation stark proving key already exists");
62 return Ok(());
63 }
64 let sdk = Sdk::standard();
66 let (agg_pk, agg_vk) = sdk.agg_keygen()?;
67
68 println!(
69 "Writing STARK aggregation proving key to {}",
70 &default_agg_stark_pk_path
71 );
72 write_object_to_file(default_agg_stark_pk_path, agg_pk)?;
73 println!(
74 "Writing STARK aggregation verifying key to {}",
75 &default_agg_stark_vk_path
76 );
77 write_object_to_file(default_agg_stark_vk_path, agg_vk)?;
78
79 println!("Generating root verifier ASM...");
80 let root_verifier_asm = sdk.generate_root_verifier_asm();
81
82 println!("Writing root verifier ASM to {}", &default_asm_path);
83 write(&default_asm_path, root_verifier_asm)?;
84 } else {
85 let default_agg_halo2_pk_path = default_agg_halo2_pk_path();
86 if PathBuf::from(&default_agg_stark_pk_path).exists()
87 && PathBuf::from(&default_agg_halo2_pk_path).exists()
88 && PathBuf::from(&default_evm_halo2_verifier_path)
89 .join(EVM_HALO2_VERIFIER_PARENT_NAME)
90 .exists()
91 && PathBuf::from(&default_evm_halo2_verifier_path)
92 .join(EVM_HALO2_VERIFIER_BASE_NAME)
93 .exists()
94 && PathBuf::from(&default_evm_halo2_verifier_path)
95 .join("interfaces")
96 .join(EVM_HALO2_VERIFIER_INTERFACE_NAME)
97 .exists()
98 {
99 println!("Aggregation proving key and verifier contract already exist");
100 return Ok(());
101 } else if !Self::check_solc_installed() {
102 return Err(eyre!(
103 "solc is not installed, please install solc to continue"
104 ));
105 }
106
107 const_assert!(DEFAULT_HALO2_VERIFIER_K <= MAX_HALO2_VERIFIER_K_FOR_DOWNLOAD);
108 Self::download_params(10, MAX_HALO2_VERIFIER_K_FOR_DOWNLOAD as u32).await?;
109 let sdk = Sdk::standard();
111
112 let agg_vk = if !self.force_agg_keygen
113 && PathBuf::from(&default_agg_stark_pk_path).exists()
114 && PathBuf::from(&default_agg_stark_vk_path).exists()
115 && PathBuf::from(&default_agg_halo2_pk_path).exists()
116 {
117 let (agg_pk, halo2_pk) = read_default_agg_and_halo2_pk()?;
118 sdk.set_agg_pk(agg_pk)
119 .map_err(|_| eyre!("agg_pk already existed"))?;
120 sdk.set_halo2_pk(halo2_pk)
121 .map_err(|_| eyre!("halo2_pk already existed"))?;
122 read_object_from_file(&default_agg_stark_vk_path)?
123 } else {
124 println!("Generating proving key...");
125 let (_agg_pk, agg_vk) = sdk.agg_keygen()?;
126 let _halo2_pk = sdk.halo2_pk();
127 agg_vk
128 };
129
130 println!("Generating root verifier ASM...");
131 let root_verifier_asm = sdk.generate_root_verifier_asm();
132
133 println!("Generating verifier contract...");
134 let verifier = sdk.generate_halo2_verifier_solidity()?;
135
136 println!("Writing stark proving key to file...");
137 write_object_to_file(&default_agg_stark_pk_path, sdk.agg_pk())?;
138
139 println!("Writing stark verifying key to file...");
140 write_object_to_file(&default_agg_stark_vk_path, agg_vk)?;
141
142 println!("Writing halo2 proving key to file...");
143 write_object_to_file(&default_agg_halo2_pk_path, sdk.halo2_pk())?;
144
145 println!("Writing root verifier ASM to file...");
146 write(&default_asm_path, root_verifier_asm)?;
147
148 println!("Writing verifier contract to file...");
149 write_evm_halo2_verifier_to_folder(verifier, &default_evm_halo2_verifier_path)?;
150 }
151 Ok(())
152 }
153
154 fn check_solc_installed() -> bool {
155 std::process::Command::new("solc")
156 .arg("--version")
157 .output()
158 .is_ok()
159 }
160
161 async fn download_params(min_k: u32, max_k: u32) -> Result<()> {
162 let default_params_dir = default_params_dir();
163 create_dir_all(&default_params_dir)?;
164
165 let config = defaults(BehaviorVersion::latest())
166 .region(Region::new("us-east-1"))
167 .no_credentials()
168 .load()
169 .await;
170 let client = Client::new(&config);
171
172 for k in min_k..=max_k {
173 let file_name = format!("kzg_bn254_{k}.srs");
174 let local_file_path = PathBuf::from(&default_params_dir).join(&file_name);
175 if !local_file_path.exists() {
176 println!("Downloading {file_name}");
177 let key = format!("challenge_0085/{file_name}");
178 let resp = client
179 .get_object()
180 .bucket("axiom-crypto")
181 .key(&key)
182 .send()
183 .await?;
184 let data = resp.body.collect().await?;
185 write(local_file_path, data.into_bytes())?;
186 }
187 }
188
189 Ok(())
190 }
191}