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