1use crypto::digest::{Digest, OutputSizeUser};
2use crypto_common::generic_array::{ArrayLength, GenericArray};
3use nexus_common::constants::WORD_SIZE;
4use serde::{de::DeserializeOwned, Serialize};
5use std::path::Path;
6
7use nexus_core::nvm::internals::*;
8
9use crate::compile::*;
10use crate::error::*;
11
12pub trait Compute {}
14
15pub enum Local {}
17impl Compute for Local {}
18
19pub trait CheckedView {
21 fn new_from_expected(
23 memory_layout: &LinearMemoryLayout,
24 expected_public_input: &[u8],
25 expected_exit_code: &[u8],
26 expected_public_output: &[u8],
27 expected_elf: &nexus_core::nvm::ElfFile,
28 expected_ad: &[u8],
29 ) -> Self;
30}
31
32impl CheckedView for nexus_core::nvm::View {
33 fn new_from_expected(
34 memory_layout: &LinearMemoryLayout,
35 expected_public_input: &[u8],
36 expected_exit_code: &[u8],
37 expected_public_output: &[u8],
38 expected_elf: &nexus_core::nvm::ElfFile,
39 expected_ad: &[u8],
40 ) -> Self {
41 let emulator = LinearEmulator::default();
42
43 let instructions = expected_elf
45 .instructions
46 .iter()
47 .map(|instr| convert_instruction(&emulator.executor.instruction_executor, instr))
48 .collect();
49
50 let converted_elf = nexus_core::nvm::ElfFile {
51 instructions,
52 ..expected_elf.clone()
53 };
54
55 let program_memory = elf_into_program_info(&converted_elf, memory_layout);
56
57 let initial_memory = slice_into_io_entries::<MemoryInitializationEntry>(
58 memory_layout.public_input_address_location(),
59 &[
60 memory_layout.public_input_start().to_le_bytes(),
61 memory_layout.exit_code().to_le_bytes(), ]
63 .concat(),
64 )
65 .iter()
66 .chain(map_into_io_entries::<MemoryInitializationEntry>(&expected_elf.rom_image).iter())
67 .chain(map_into_io_entries::<MemoryInitializationEntry>(&expected_elf.ram_image).iter())
68 .chain(
69 slice_into_io_entries::<MemoryInitializationEntry>(
70 memory_layout.public_input_start(),
71 &[
72 &(expected_public_input.len() as u32).to_le_bytes(),
73 expected_public_input,
74 ]
75 .concat(),
76 )
77 .iter(),
78 )
79 .copied()
80 .collect();
81
82 let exit_code = slice_into_io_entries::<PublicOutputEntry>(
83 memory_layout.exit_code(),
84 expected_exit_code,
85 );
86
87 let output_memory = slice_into_io_entries::<PublicOutputEntry>(
88 memory_layout.public_output_start(),
89 expected_public_output,
90 );
91
92 let static_memory_size =
93 (&expected_elf.rom_image.len_bytes() + &expected_elf.ram_image.len_bytes()) * WORD_SIZE;
94
95 Self::new(
96 &Some(*memory_layout),
97 &Vec::new(),
98 &program_memory,
99 &initial_memory,
100 memory_layout.tracked_ram_size(static_memory_size),
101 &exit_code,
102 &output_memory,
103 &expected_ad.to_vec(),
104 )
105 }
106}
107
108pub trait Viewable {
110 fn public_input<T: Serialize + DeserializeOwned + Sized>(&self) -> Result<T, IOError>;
112
113 fn public_input_digest<T: Serialize + DeserializeOwned + Sized, H: Digest>(
115 &self,
116 ) -> Result<GenericArray<u8, H::OutputSize>, IOError>
117 where
118 <H as OutputSizeUser>::OutputSize: ArrayLength<u8>,
119 {
120 Ok(H::digest(
121 postcard::to_stdvec_cobs::<T>(&Self::public_input::<T>(self)?)
122 .map_err(IOError::from)?
123 .as_slice(),
124 ))
125 }
126
127 fn exit_code(&self) -> Result<u32, IOError>;
129
130 fn exit_code_digest<H: Digest>(&self) -> Result<GenericArray<u8, H::OutputSize>, IOError>
132 where
133 <H as OutputSizeUser>::OutputSize: ArrayLength<u8>,
134 {
135 Ok(H::digest(Self::exit_code(self)?.to_le_bytes()))
136 }
137
138 fn public_output<U: Serialize + DeserializeOwned + Sized>(&self) -> Result<U, IOError>;
140
141 fn public_output_digest<U: Serialize + DeserializeOwned + Sized, H: Digest>(
143 &self,
144 ) -> Result<GenericArray<u8, H::OutputSize>, IOError>
145 where
146 <H as OutputSizeUser>::OutputSize: ArrayLength<u8>,
147 {
148 Ok(H::digest(
149 postcard::to_stdvec_cobs::<U>(&Self::public_output::<U>(self)?)
150 .map_err(IOError::from)?
151 .as_slice(),
152 ))
153 }
154
155 fn associated_data(&self) -> Result<Vec<u8>, IOError>;
157
158 fn associated_data_digest<H: Digest>(&self) -> Result<GenericArray<u8, H::OutputSize>, IOError>
160 where
161 <H as OutputSizeUser>::OutputSize: ArrayLength<u8>,
162 {
163 Ok(H::digest(Self::associated_data(self)?.as_slice()))
164 }
165
166 fn logs(&self) -> Result<Vec<String>, IOError>;
168}
169
170impl Viewable for nexus_core::nvm::View {
171 fn public_input<T: Serialize + DeserializeOwned + Sized>(&self) -> Result<T, IOError> {
173 if let Some(mut bytes) = self.view_public_input() {
174 Ok(postcard::from_bytes_cobs::<T>(&mut bytes).map_err(IOError::from)?)
175 } else {
176 Err(IOError::NotYetAvailableError)
177 }
178 }
179
180 fn exit_code(&self) -> Result<u32, IOError> {
182 if let Some(bytes) = self.view_exit_code() {
183 Ok(postcard::from_bytes::<u32>(&bytes).map_err(IOError::from)?)
184 } else {
185 Err(IOError::NotYetAvailableError)
186 }
187 }
188
189 fn public_output<U: Serialize + DeserializeOwned + Sized>(&self) -> Result<U, IOError> {
191 if let Some(mut bytes) = self.view_public_output() {
192 Ok(postcard::from_bytes_cobs::<U>(&mut bytes).map_err(IOError::from)?)
193 } else {
194 Err(IOError::NotYetAvailableError)
195 }
196 }
197
198 fn associated_data(&self) -> Result<Vec<u8>, IOError> {
200 if let Some(bytes) = self.view_associated_data() {
201 Ok(bytes)
202 } else {
203 Err(IOError::NotYetAvailableError)
204 }
205 }
206
207 fn logs(&self) -> Result<Vec<String>, IOError> {
209 if let Some(bytes_vecs) = self.view_debug_logs() {
210 Ok(bytes_vecs
211 .iter()
212 .map(|raw_log: &Vec<u8>| String::from_utf8_lossy(raw_log).to_string())
213 .collect())
214 } else {
215 Err(IOError::NotYetAvailableError)
216 }
217 }
218}
219
220pub trait ByGuestCompilation: Prover {
222 fn compile(compiler: &mut impl Compile) -> Result<Self, Self::Error>;
224}
225
226pub trait Prover: Sized {
228 type Proof: Verifiable;
229 type View: CheckedView;
230 type Error: From<nexus_core::nvm::VMError>;
231
232 fn new(elf: &nexus_core::nvm::ElfFile) -> Result<Self, <Self as Prover>::Error>;
234
235 fn new_from_bytes(elf_bytes: &[u8]) -> Result<Self, <Self as Prover>::Error> {
237 Self::new(&nexus_core::nvm::ElfFile::from_bytes(elf_bytes)?)
238 }
239
240 fn new_from_file<P: AsRef<Path> + ?Sized>(path: &P) -> Result<Self, <Self as Prover>::Error> {
242 Self::new(&nexus_core::nvm::ElfFile::from_path(&path)?)
243 }
244
245 fn set_associated_data(&mut self, ad: &[u8]) -> Result<(), <Self as Prover>::Error>;
247
248 fn run(&self) -> Result<Self::View, <Self as Prover>::Error> {
250 Self::run_with_input::<(), ()>(self, &(), &())
251 }
252
253 fn run_with_input<S: Serialize + Sized, T: Serialize + DeserializeOwned + Sized>(
255 &self,
256 private_input: &S,
257 public_input: &T,
258 ) -> Result<Self::View, <Self as Prover>::Error>;
259
260 fn prove(self) -> Result<(Self::View, Self::Proof), <Self as Prover>::Error>
262 where
263 Self: Sized,
264 {
265 Self::prove_with_input::<(), ()>(self, &(), &())
266 }
267
268 fn prove_with_input<S: Serialize + Sized, T: Serialize + DeserializeOwned + Sized>(
270 self,
271 private_input: &S,
272 public_input: &T,
273 ) -> Result<(Self::View, Self::Proof), <Self as Prover>::Error>;
274}
275
276pub trait Setup<'a> {
280 type Reference;
282 type Parameters;
284 type Preprocessing;
286 type Error;
287
288 fn setup_reference<'b: 'a>(
290 &mut self,
291 reference: &'b Self::Reference,
292 ) -> Result<(), Self::Error>;
293
294 fn setup_parameters<'b: 'a>(
296 &mut self,
297 parameters: &'b Self::Parameters,
298 ) -> Result<(), Self::Error>;
299
300 fn detach(&mut self);
302
303 fn reference(&self) -> Result<&'a Self::Reference, Self::Error>;
305
306 fn parameters(&self) -> Result<&'a Self::Parameters, Self::Error>;
310
311 fn preprocessing(&self) -> Result<Self::Preprocessing, Self::Error>;
315
316 }
318
319pub trait Reference {
323 type Error;
324
325 fn generate() -> Result<Self, Self::Error>
327 where
328 Self: Sized;
329
330 fn load(path: &Path) -> Result<Self, Self::Error>
332 where
333 Self: Sized;
334
335 fn save(reference: &Self, path: &Path) -> Result<(), Self::Error>;
337}
338
339impl Reference for () {
340 type Error = ConfigurationError;
341
342 fn generate() -> Result<Self, Self::Error> {
343 Err(ConfigurationError::NotApplicableOperation)
344 }
345
346 fn load(_path: &Path) -> Result<Self, Self::Error> {
347 Err(ConfigurationError::NotApplicableOperation)
348 }
349
350 fn save(_reference: &Self, _path: &Path) -> Result<(), Self::Error> {
351 Err(ConfigurationError::NotApplicableOperation)
352 }
353}
354
355pub trait Parameters {
359 type Ref: Reference;
360 type Error;
361
362 fn generate(reference: &Self::Ref) -> Result<Self, Self::Error>
364 where
365 Self: Sized;
366
367 fn load(path: &Path) -> Result<Self, Self::Error>
369 where
370 Self: Sized;
371
372 fn save(parameters: &Self, path: &Path) -> Result<(), Self::Error>;
374}
375
376impl Parameters for () {
377 type Ref = ();
378 type Error = ConfigurationError;
379
380 fn generate(_reference: &Self::Ref) -> Result<Self, Self::Error> {
381 Err(ConfigurationError::NotApplicableOperation)
382 }
383
384 fn load(_path: &Path) -> Result<Self, Self::Error> {
385 Err(ConfigurationError::NotApplicableOperation)
386 }
387
388 fn save(_parameters: &Self, _path: &Path) -> Result<(), Self::Error> {
389 Err(ConfigurationError::NotApplicableOperation)
390 }
391}
392
393pub trait Preprocessing {
397 type Ref: Reference;
398 type Params: Parameters;
399 type Error;
400
401 fn load(path: &Path) -> Result<Self, Self::Error>
403 where
404 Self: Sized;
405
406 fn save(preprocessing: &Self, path: &Path) -> Result<(), Self::Error>;
408}
409
410impl Preprocessing for () {
411 type Ref = ();
412 type Params = ();
413 type Error = ConfigurationError;
414
415 fn load(_path: &Path) -> Result<Self, Self::Error> {
416 Err(ConfigurationError::NotApplicableOperation)
417 }
418
419 fn save(_preprocessing: &Self, _path: &Path) -> Result<(), Self::Error> {
420 Err(ConfigurationError::NotApplicableOperation)
421 }
422}
423
424pub trait Verifiable: Serialize + DeserializeOwned {
426 type View: CheckedView;
427 type Error: From<nexus_core::nvm::VMError> + From<IOError>;
428
429 fn get_memory_layout(&self) -> &LinearMemoryLayout;
431
432 fn verify(&self, expected_view: &Self::View) -> Result<(), <Self as Verifiable>::Error>;
434
435 fn verify_expected<
437 T: Serialize + DeserializeOwned + Sized,
438 U: Serialize + DeserializeOwned + Sized,
439 >(
440 &self,
441 expected_public_input: &T,
442 expected_exit_code: u32,
443 expected_public_output: &U,
444 expected_elf: &nexus_core::nvm::ElfFile,
445 expected_ad: &[u8],
446 ) -> Result<(), <Self as Verifiable>::Error> {
447 let mut input_encoded =
448 postcard::to_stdvec(&expected_public_input).map_err(IOError::from)?;
449 if !input_encoded.is_empty() {
450 let input = expected_public_input.to_owned();
451
452 input_encoded = postcard::to_stdvec_cobs(&input).map_err(IOError::from)?;
453 let input_padded_len = (input_encoded.len() + 3) & !3;
454
455 assert!(input_padded_len >= input_encoded.len());
456 input_encoded.resize(input_padded_len, 0x00); }
458
459 let mut output_encoded =
460 postcard::to_stdvec(&expected_public_output).map_err(IOError::from)?;
461 if !output_encoded.is_empty() {
462 let output = expected_public_output.to_owned();
463
464 output_encoded = postcard::to_stdvec_cobs(&output).map_err(IOError::from)?;
465 let output_padded_len = (output_encoded.len() + 3) & !3;
466
467 assert!(output_padded_len >= output_encoded.len());
468 output_encoded.resize(output_padded_len, 0x00); }
470
471 let view = Self::View::new_from_expected(
472 self.get_memory_layout(),
473 input_encoded.as_slice(),
474 &expected_exit_code.to_le_bytes(),
475 output_encoded.as_slice(),
476 expected_elf,
477 expected_ad,
478 );
479
480 self.verify(&view)
481 }
482
483 fn verify_expected_from_program_bytes<
485 T: Serialize + DeserializeOwned + Sized,
486 U: Serialize + DeserializeOwned + Sized,
487 >(
488 &self,
489 expected_public_input: &T,
490 expected_exit_code: u32,
491 expected_public_output: &U,
492 expected_elf_bytes: &[u8],
493 expected_ad: &[u8],
494 ) -> Result<(), <Self as Verifiable>::Error> {
495 self.verify_expected(
496 expected_public_input,
497 expected_exit_code,
498 expected_public_output,
499 &nexus_core::nvm::ElfFile::from_bytes(expected_elf_bytes)?,
500 expected_ad,
501 )
502 }
503
504 fn verify_expected_from_program_path<
506 P: AsRef<Path> + ?Sized,
507 T: Serialize + DeserializeOwned + Sized,
508 U: Serialize + DeserializeOwned + Sized,
509 >(
510 &self,
511 expected_public_input: &T,
512 expected_exit_code: u32,
513 expected_public_output: &U,
514 expected_elf_path: &P,
515 expected_ad: &[u8],
516 ) -> Result<(), <Self as Verifiable>::Error> {
517 self.verify_expected(
518 expected_public_input,
519 expected_exit_code,
520 expected_public_output,
521 &nexus_core::nvm::ElfFile::from_path(expected_elf_path)?,
522 expected_ad,
523 )
524 }
525
526 fn size_estimate(&self) -> usize;
528}