nexus_sdk/legacy/hypernova/
seq.rs1use crate::legacy::compile;
2use crate::legacy::traits::*;
3use crate::legacy::views::UncheckedView;
4use crate::traits::*;
5
6use crate::legacy::ark_serialize_utils::{ark_de, ark_se};
7use serde::{de::DeserializeOwned, Deserialize, Serialize};
8use std::path::Path;
9use thiserror::Error;
10
11use nexus_core_legacy::nvm::interactive::{eval, parse_elf, trace};
12use nexus_core_legacy::nvm::memory::MerkleTrie;
13use nexus_core_legacy::nvm::NexusVM;
14use nexus_core_legacy::prover::hypernova::pp::{gen_vm_pp, load_pp, save_pp};
15use nexus_core_legacy::prover::hypernova::prove_seq;
16use nexus_core_legacy::prover::hypernova::types::IVCProof;
17use nexus_core_legacy::prover::nova::srs::{
18 get_min_srs_size, load_srs,
19 test_srs::{gen_test_srs, save_srs},
20};
21
22use crate::error::{BuildError, ConfigurationError, IOError, PathError};
23use nexus_core_legacy::prover::hypernova::error::{NovaProofError, ProofError};
24
25pub use nexus_core_legacy::prover::hypernova::types::PP;
28
29use nexus_core_legacy::prover::hypernova::types::SRS as SRSi;
30pub struct SRS(SRSi); use std::marker::PhantomData;
34
35const K: usize = 1;
37
38#[derive(Debug, Error)]
40pub enum Error {
41 #[error(transparent)]
43 ProofError(#[from] ProofError),
44
45 #[error(transparent)]
47 SRSError(#[from] NovaProofError), #[error(transparent)]
51 BuildError(#[from] BuildError),
52
53 #[error(transparent)]
55 HostIOError(#[from] std::io::Error),
56
57 #[error(transparent)]
59 PathError(#[from] PathError),
60
61 #[error(transparent)]
63 GuestIOError(#[from] IOError),
64
65 #[error(transparent)]
67 ConfigurationError(#[from] ConfigurationError),
68}
69
70pub struct HyperNova<'a, C: Compute = Local> {
72 vm: NexusVM<MerkleTrie>,
73 pp: Option<&'a PP>,
74 srs: Option<&'a SRS>,
75 _compute: PhantomData<C>,
76}
77
78#[derive(Serialize, Deserialize)]
82pub struct Proof<'a> {
83 #[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
84 proof: IVCProof,
85 #[serde(skip)]
86 view: UncheckedView,
87 #[serde(skip)]
88 srs: Option<&'a SRS>,
89 #[serde(skip)]
90 pp: Option<&'a PP>,
91}
92
93macro_rules! setup {
94 ($id:ty) => {
95 impl<'a> Setup<'a> for $id {
96 type Reference = SRS;
97 type Parameters = PP;
98 type Preprocessing = ();
99 type Error = Error;
100
101 fn setup_reference<'b: 'a>(
102 &mut self,
103 reference: &'b Self::Reference,
104 ) -> Result<(), Self::Error> {
105 self.srs = Some(reference);
106 Ok(())
107 }
108
109 fn setup_parameters<'b: 'a>(
110 &mut self,
111 parameters: &'b Self::Parameters,
112 ) -> Result<(), Self::Error> {
113 self.pp = Some(parameters);
114 Ok(())
115 }
116
117 fn detach(&mut self) {
118 self.srs = None;
119 self.pp = None;
120 }
121
122 fn reference(&self) -> Result<&'a Self::Reference, Self::Error> {
123 if self.srs.is_none() {
124 return Err(Error::from(ConfigurationError::NotYetConfigured));
125 } else {
126 Ok(self.srs.unwrap())
127 }
128 }
129
130 fn parameters(&self) -> Result<&'a Self::Parameters, Self::Error> {
131 if self.pp.is_none() {
132 return Err(Error::from(ConfigurationError::NotYetConfigured));
133 } else {
134 Ok(self.pp.unwrap())
135 }
136 }
137
138 fn preprocessing(&self) -> Result<Self::Preprocessing, Self::Error> {
139 Ok(())
140 }
141 }
142 };
143}
144
145setup!(HyperNova<'a, Local>);
146setup!(Proof<'a>);
147
148impl<'a> LegacyProver<'a> for HyperNova<'a, Local> {
149 type Proof = Proof<'a>;
150 type View = UncheckedView;
151
152 fn new(elf_bytes: &[u8]) -> Result<Self, Self::Error> {
153 Ok(HyperNova::<Local> {
154 vm: parse_elf::<MerkleTrie>(elf_bytes).map_err(ProofError::from)?,
155 srs: None,
156 pp: None,
157 _compute: PhantomData,
158 })
159 }
160
161 fn compile(opts: &compile::CompileOpts) -> Result<Self, Self::Error> {
162 let mut iopts = opts.to_owned();
163
164 if iopts.memlimit.is_none() {
166 iopts.set_memlimit(4);
167 }
168
169 let elf_path = iopts.build(&compile::ForProver::Default)?;
170
171 Self::new_from_file(&elf_path)
172 }
173
174 fn run_with_input<S>(mut self, private_input: &S) -> Result<Self::View, Self::Error>
175 where
176 S: Serialize + Sized,
177 {
178 self.vm.syscalls.set_input(
179 postcard::to_stdvec(private_input)
180 .map_err(IOError::from)?
181 .as_slice(),
182 );
183
184 eval(&mut self.vm, false, false).map_err(ProofError::from)?;
185
186 Ok(Self::View {
187 out: self.vm.syscalls.get_output(),
188 logs: self
189 .vm
190 .syscalls
191 .get_log_buffer()
192 .into_iter()
193 .map(String::from_utf8)
194 .collect::<Result<Vec<_>, _>>()
195 .map_err(IOError::from)?,
196 })
197 }
198
199 fn prove_with_input<S>(mut self, private_input: &S) -> Result<Self::Proof, Self::Error>
200 where
201 S: Serialize + Sized,
202 {
203 if self.pp.is_none() {
204 return Err(Error::from(ConfigurationError::NotYetConfigured));
205 }
206
207 self.vm.syscalls.set_input(
208 postcard::to_stdvec(private_input)
209 .map_err(IOError::from)?
210 .as_slice(),
211 );
212
213 let tr = trace(&mut self.vm, K, false).map_err(ProofError::from)?;
214
215 Ok(Self::Proof {
216 proof: prove_seq(self.pp.as_ref().unwrap(), tr)?,
217 srs: self.srs,
218 pp: self.pp,
219 view: Self::View {
220 out: self.vm.syscalls.get_output(),
221 logs: self
222 .vm
223 .syscalls
224 .get_log_buffer()
225 .into_iter()
226 .map(String::from_utf8)
227 .collect::<Result<Vec<_>, _>>()
228 .map_err(IOError::from)?,
229 },
230 })
231 }
232}
233
234impl Reference for SRS {
235 type Error = Error;
236
237 fn generate() -> Result<Self, Self::Error> {
238 eprintln!("Using test reference generation, not for production use!!!");
239 Ok(SRS(
240 gen_test_srs(get_min_srs_size(K)?).map_err(ProofError::from)?
241 ))
242 }
243
244 fn load(path: &Path) -> Result<Self, Self::Error> {
245 if let Some(path_str) = path.to_str() {
246 return Ok(SRS(load_srs(path_str).map_err(ProofError::from)?));
247 }
248
249 Err(Self::Error::PathError(
250 crate::error::PathError::EncodingError,
251 ))
252 }
253
254 fn save(reference: &Self, path: &Path) -> Result<(), Self::Error> {
255 if let Some(path_str) = path.to_str() {
256 let srs = &reference.0;
257 return Ok(save_srs(srs.clone(), path_str).map_err(ProofError::from)?);
258 }
259
260 Err(Self::Error::PathError(
261 crate::error::PathError::EncodingError,
262 ))
263 }
264}
265
266impl Parameters for PP {
267 type Ref = SRS;
268 type Error = Error;
269
270 fn generate(reference: &Self::Ref) -> Result<Self, Self::Error> {
271 eprintln!("Using test parameter generation, not for production use!!!");
272 let srs = &reference.0;
273 Ok(gen_vm_pp(K, srs, &())?)
274 }
275
276 fn load(path: &Path) -> Result<Self, Self::Error> {
277 if let Some(path_str) = path.to_str() {
278 return Ok(load_pp(path_str)?);
279 }
280
281 Err(Self::Error::PathError(
282 crate::error::PathError::EncodingError,
283 ))
284 }
285
286 fn save(pp: &Self, path: &Path) -> Result<(), Self::Error> {
287 if let Some(path_str) = path.to_str() {
288 return Ok(save_pp(pp, path_str)?);
289 }
290
291 Err(Self::Error::PathError(
292 crate::error::PathError::EncodingError,
293 ))
294 }
295}
296
297impl<'a> LegacyVerifiable<'a> for Proof<'a> {
298 type View = UncheckedView;
299
300 fn output<U: DeserializeOwned>(&self) -> Result<U, Self::Error> {
301 Ok(Self::View::output::<U>(&self.view)?)
302 }
303
304 fn logs(&self) -> &Vec<String> {
305 Self::View::logs(&self.view)
306 }
307
308 fn detach(&mut self) {
309 self.srs = None;
310 self.pp = None;
311 }
312
313 fn verify(&self) -> Result<(), Self::Error> {
314 if self.pp.is_none() {
315 return Err(Error::from(ConfigurationError::NotYetConfigured));
316 }
317
318 Ok(self
319 .proof
320 .verify(self.pp.as_ref().unwrap())
321 .map_err(ProofError::from)?)
322 }
323}