1use std::{
2 fs::{create_dir_all, read, write, File},
3 path::Path,
4};
5
6use eyre::{Report, Result};
7#[cfg(feature = "evm-prove")]
8use openvm_native_recursion::halo2::wrapper::EvmVerifierByteCode;
9use serde::{de::DeserializeOwned, Serialize};
10
11use crate::codec::{Decode, Encode};
12#[cfg(feature = "evm-prove")]
13use crate::{types::EvmHalo2Verifier, OPENVM_VERSION};
14
15pub const EVM_HALO2_VERIFIER_INTERFACE_NAME: &str = "IOpenVmHalo2Verifier.sol";
16pub const EVM_HALO2_VERIFIER_PARENT_NAME: &str = "Halo2Verifier.sol";
17pub const EVM_HALO2_VERIFIER_BASE_NAME: &str = "OpenVmHalo2Verifier.sol";
18pub const EVM_VERIFIER_ARTIFACT_FILENAME: &str = "verifier.bytecode.json";
19
20#[cfg(feature = "evm-prove")]
21pub fn read_evm_halo2_verifier_from_folder<P: AsRef<Path>>(folder: P) -> Result<EvmHalo2Verifier> {
22 use std::fs::read_to_string;
23
24 let folder = folder
25 .as_ref()
26 .join("src")
27 .join(format!("v{}", OPENVM_VERSION));
28 let halo2_verifier_code_path = folder.join(EVM_HALO2_VERIFIER_PARENT_NAME);
29 let openvm_verifier_code_path = folder.join(EVM_HALO2_VERIFIER_BASE_NAME);
30 let interface_path = folder
31 .join("interfaces")
32 .join(EVM_HALO2_VERIFIER_INTERFACE_NAME);
33 let halo2_verifier_code = read_to_string(halo2_verifier_code_path)?;
34 let openvm_verifier_code = read_to_string(openvm_verifier_code_path)?;
35 let interface = read_to_string(interface_path)?;
36
37 let artifact_path = folder.join(EVM_VERIFIER_ARTIFACT_FILENAME);
38 let artifact: EvmVerifierByteCode = serde_json::from_reader(File::open(artifact_path)?)?;
39
40 Ok(EvmHalo2Verifier {
41 halo2_verifier_code,
42 openvm_verifier_code,
43 openvm_verifier_interface: interface,
44 artifact,
45 })
46}
47
48#[cfg(feature = "evm-prove")]
62pub fn write_evm_halo2_verifier_to_folder<P: AsRef<Path>>(
63 verifier: EvmHalo2Verifier,
64 folder: P,
65) -> Result<()> {
66 let folder = folder
67 .as_ref()
68 .join("src")
69 .join(format!("v{}", OPENVM_VERSION));
70 if !folder.exists() {
71 create_dir_all(&folder)?; }
73
74 let halo2_verifier_code_path = folder.join(EVM_HALO2_VERIFIER_PARENT_NAME);
75 let openvm_verifier_code_path = folder.join(EVM_HALO2_VERIFIER_BASE_NAME);
76 let interface_path = folder
77 .join("interfaces")
78 .join(EVM_HALO2_VERIFIER_INTERFACE_NAME);
79
80 if let Some(parent) = interface_path.parent() {
81 create_dir_all(parent)?;
82 }
83
84 write(halo2_verifier_code_path, verifier.halo2_verifier_code)
85 .expect("Failed to write halo2 verifier code");
86 write(openvm_verifier_code_path, verifier.openvm_verifier_code)
87 .expect("Failed to write openvm halo2 verifier code");
88 write(interface_path, verifier.openvm_verifier_interface)
89 .expect("Failed to write openvm halo2 verifier interface");
90
91 let artifact_path = folder.join(EVM_VERIFIER_ARTIFACT_FILENAME);
92 serde_json::to_writer(File::create(artifact_path)?, &verifier.artifact)?;
93
94 Ok(())
95}
96
97pub fn read_object_from_file<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> Result<T> {
98 read_from_file_bitcode(path)
99}
100
101pub fn write_object_to_file<T: Serialize, P: AsRef<Path>>(path: P, data: T) -> Result<()> {
102 write_to_file_bitcode(path, data)
103}
104
105fn read_from_file_bitcode<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> Result<T> {
106 let ret = read(&path)
107 .map_err(|e| read_error(&path, e.into()))
108 .and_then(|data| {
109 bitcode::deserialize(&data).map_err(|e: bitcode::Error| read_error(&path, e.into()))
110 })?;
111 Ok(ret)
112}
113
114fn write_to_file_bitcode<T: Serialize, P: AsRef<Path>>(path: P, data: T) -> Result<()> {
115 if let Some(parent) = path.as_ref().parent() {
116 create_dir_all(parent).map_err(|e| write_error(&path, e.into()))?;
117 }
118 bitcode::serialize(&data)
119 .map_err(|e| write_error(&path, e.into()))
120 .and_then(|bytes| write(&path, bytes).map_err(|e| write_error(&path, e.into())))?;
121 Ok(())
122}
123
124pub fn read_from_file_json<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> Result<T> {
125 let ret: T = File::open(&path)
126 .and_then(|file| serde_json::from_reader(file).map_err(|e| e.into()))
127 .map_err(|e| read_error(&path, e.into()))?;
128 Ok(ret)
129}
130
131pub fn write_to_file_json<T: Serialize, P: AsRef<Path>>(path: P, data: T) -> Result<()> {
132 if let Some(parent) = path.as_ref().parent() {
133 create_dir_all(parent).map_err(|e| write_error(&path, e.into()))?;
134 }
135 File::create(&path)
136 .and_then(|file| serde_json::to_writer_pretty(file, &data).map_err(|e| e.into()))
137 .map_err(|e| write_error(&path, e.into()))?;
138 Ok(())
139}
140
141pub fn read_from_file_bytes<T: From<Vec<u8>>, P: AsRef<Path>>(path: P) -> Result<T> {
142 let bytes = read(path)?;
143 Ok(T::from(bytes))
144}
145
146pub fn write_to_file_bytes<T: Into<Vec<u8>>, P: AsRef<Path>>(path: P, data: T) -> Result<()> {
147 if let Some(parent) = path.as_ref().parent() {
148 create_dir_all(parent)?;
149 }
150 write(path, data.into())?;
151 Ok(())
152}
153
154pub fn decode_from_file<T: Decode, P: AsRef<Path>>(path: P) -> Result<T> {
155 let reader = &mut File::open(path)?;
156 let ret = T::decode(reader)?;
157 Ok(ret)
158}
159
160pub fn encode_to_file<T: Encode, P: AsRef<Path>>(path: P, data: T) -> Result<()> {
161 if let Some(parent) = path.as_ref().parent() {
162 create_dir_all(parent)?;
163 }
164 let writer = &mut File::create(path)?;
165 data.encode(writer)?;
166 Ok(())
167}
168
169fn read_error<P: AsRef<Path>>(path: P, error: Report) -> Report {
170 eyre::eyre!(
171 "reading from {} failed with the following error:\n {}",
172 path.as_ref().display(),
173 error,
174 )
175}
176
177fn write_error<P: AsRef<Path>>(path: P, error: Report) -> Report {
178 eyre::eyre!(
179 "writing to {} failed with the following error:\n {}",
180 path.as_ref().display(),
181 error,
182 )
183}