nexus_sdk/legacy/nova/
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::nova::pp::{gen_vm_pp, load_pp, save_pp};
15use nexus_core_legacy::prover::nova::prove_seq;
16use nexus_core_legacy::prover::nova::types::IVCProof;
17
18use crate::error::{BuildError, ConfigurationError, IOError, PathError};
19use nexus_core_legacy::prover::nova::error::ProofError;
20
21pub use nexus_core_legacy::prover::nova::types::SeqPP as PP;
24
25use std::marker::PhantomData;
26
27const K: usize = 16;
29
30#[derive(Debug, Error)]
32pub enum Error {
33 #[error(transparent)]
35 ProofError(#[from] ProofError),
36
37 #[error(transparent)]
39 BuildError(#[from] BuildError),
40
41 #[error(transparent)]
43 HostIOError(#[from] std::io::Error),
44
45 #[error(transparent)]
47 PathError(#[from] PathError),
48
49 #[error(transparent)]
51 GuestIOError(#[from] IOError),
52
53 #[error(transparent)]
55 ConfigurationError(#[from] ConfigurationError),
56}
57
58pub struct Nova<'a, C: Compute = Local> {
60 vm: NexusVM<MerkleTrie>,
61 pp: Option<&'a PP>,
62 _compute: PhantomData<C>,
63}
64
65#[derive(Serialize, Deserialize)]
69pub struct Proof<'a> {
70 #[serde(serialize_with = "ark_se", deserialize_with = "ark_de")]
71 proof: IVCProof,
72 #[serde(skip)]
73 view: UncheckedView,
74 #[serde(skip)]
75 pp: Option<&'a PP>,
76}
77
78macro_rules! setup {
79 ($id:ty) => {
80 impl<'a> Setup<'a> for $id {
81 type Reference = ();
82 type Parameters = PP;
83 type Preprocessing = ();
84 type Error = Error;
85
86 fn setup_reference<'b: 'a>(
87 &mut self,
88 _reference: &'b Self::Reference,
89 ) -> Result<(), Self::Error> {
90 return Err(Error::from(ConfigurationError::NotApplicableOperation));
91 }
92
93 fn setup_parameters<'b: 'a>(
94 &mut self,
95 parameters: &'b Self::Parameters,
96 ) -> Result<(), Self::Error> {
97 self.pp = Some(parameters);
98 Ok(())
99 }
100
101 fn detach(&mut self) {
102 self.pp = None;
103 }
104
105 fn reference(&self) -> Result<&'a Self::Reference, Self::Error> {
106 Ok(&())
107 }
108
109 fn parameters(&self) -> Result<&'a Self::Parameters, Self::Error> {
110 if self.pp.is_none() {
111 return Err(Error::from(ConfigurationError::NotYetConfigured));
112 } else {
113 Ok(self.pp.unwrap())
114 }
115 }
116
117 fn preprocessing(&self) -> Result<Self::Preprocessing, Self::Error> {
118 Ok(())
119 }
120 }
121 };
122}
123
124setup!(Nova<'a, Local>);
125setup!(Proof<'a>);
126
127impl<'a> LegacyProver<'a> for Nova<'a, Local> {
128 type Proof = Proof<'a>;
129 type View = UncheckedView;
130
131 fn new(elf_bytes: &[u8]) -> Result<Self, Self::Error> {
132 Ok(Nova::<Local> {
133 vm: parse_elf::<MerkleTrie>(elf_bytes).map_err(ProofError::from)?,
134 pp: None,
135 _compute: PhantomData,
136 })
137 }
138
139 fn compile(opts: &compile::CompileOpts) -> Result<Self, Self::Error> {
140 let mut iopts = opts.to_owned();
141
142 if iopts.memlimit.is_none() {
144 iopts.set_memlimit(4);
145 }
146
147 let elf_path = iopts.build(&compile::ForProver::Default)?;
148
149 Self::new_from_file(&elf_path)
150 }
151
152 fn run_with_input<S>(mut self, private_input: &S) -> Result<Self::View, Self::Error>
153 where
154 S: Serialize + Sized,
155 {
156 self.vm.syscalls.set_input(
157 postcard::to_stdvec(private_input)
158 .map_err(IOError::from)?
159 .as_slice(),
160 );
161
162 eval(&mut self.vm, false, false).map_err(ProofError::from)?;
163
164 Ok(Self::View {
165 out: self.vm.syscalls.get_output(),
166 logs: self
167 .vm
168 .syscalls
169 .get_log_buffer()
170 .into_iter()
171 .map(String::from_utf8)
172 .collect::<Result<Vec<_>, _>>()
173 .map_err(IOError::from)?,
174 })
175 }
176
177 fn prove_with_input<S>(mut self, private_input: &S) -> Result<Self::Proof, Self::Error>
178 where
179 S: Serialize + Sized,
180 {
181 if self.pp.is_none() {
182 return Err(Error::from(ConfigurationError::NotYetConfigured));
183 }
184
185 self.vm.syscalls.set_input(
186 postcard::to_stdvec(private_input)
187 .map_err(IOError::from)?
188 .as_slice(),
189 );
190
191 let tr = trace(&mut self.vm, K, false).map_err(ProofError::from)?;
192
193 Ok(Self::Proof {
194 proof: prove_seq(self.pp.as_ref().unwrap(), tr)?,
195 pp: self.pp,
196 view: Self::View {
197 out: self.vm.syscalls.get_output(),
198 logs: self
199 .vm
200 .syscalls
201 .get_log_buffer()
202 .into_iter()
203 .map(String::from_utf8)
204 .collect::<Result<Vec<_>, _>>()
205 .map_err(IOError::from)?,
206 },
207 })
208 }
209}
210
211impl Parameters for PP {
212 type Ref = ();
213 type Error = Error;
214
215 fn generate(_reference: &Self::Ref) -> Result<Self, Self::Error> {
216 eprintln!("Using test parameter generation, not for production use!!!");
217 Ok(gen_vm_pp(K, &())?)
218 }
219
220 fn load(path: &Path) -> Result<Self, Self::Error> {
221 if let Some(path_str) = path.to_str() {
222 return Ok(load_pp(path_str)?);
223 }
224
225 Err(Self::Error::PathError(
226 crate::error::PathError::EncodingError,
227 ))
228 }
229
230 fn save(pp: &Self, path: &Path) -> Result<(), Self::Error> {
231 if let Some(path_str) = path.to_str() {
232 return Ok(save_pp(pp, path_str)?);
233 }
234
235 Err(Self::Error::PathError(
236 crate::error::PathError::EncodingError,
237 ))
238 }
239}
240
241impl<'a> LegacyVerifiable<'a> for Proof<'a> {
242 type View = UncheckedView;
243
244 fn output<U: DeserializeOwned>(&self) -> Result<U, Self::Error> {
245 Ok(Self::View::output::<U>(&self.view)?)
246 }
247
248 fn logs(&self) -> &Vec<String> {
249 Self::View::logs(&self.view)
250 }
251
252 fn detach(&mut self) {
253 self.pp = None;
254 }
255
256 fn verify(&self) -> Result<(), Self::Error> {
257 if self.pp.is_none() {
258 return Err(Error::from(ConfigurationError::NotYetConfigured));
259 }
260
261 Ok(self
262 .proof
263 .verify(self.pp.as_ref().unwrap())
264 .map_err(ProofError::from)?)
265 }
266}