1#![allow(deprecated)]
2
3use crypto::digest::{Digest, OutputSizeUser};
4use crypto_common::generic_array::{ArrayLength, GenericArray};
5use nexus_common::constants::WORD_SIZE;
6use serde::{de::DeserializeOwned, Serialize};
7use std::path::Path;
8
9use nexus_core::nvm::internals::*;
10
11use crate::compile::*;
12use crate::error::*;
13
14pub trait Compute {}
16
17pub enum Local {}
19impl Compute for Local {}
20
21pub trait CheckedView {
23 fn new_from_expected(
25 memory_layout: &LinearMemoryLayout,
26 expected_public_input: &[u8],
27 expected_exit_code: &[u8],
28 expected_public_output: &[u8],
29 expected_elf: &nexus_core::nvm::ElfFile,
30 expected_ad: &[u8],
31 ) -> Self;
32}
33
34impl CheckedView for nexus_core::nvm::View {
35 fn new_from_expected(
36 memory_layout: &LinearMemoryLayout,
37 expected_public_input: &[u8],
38 expected_exit_code: &[u8],
39 expected_public_output: &[u8],
40 expected_elf: &nexus_core::nvm::ElfFile,
41 expected_ad: &[u8],
42 ) -> Self {
43 let emulator = LinearEmulator::default();
44
45 let instructions = expected_elf
47 .instructions
48 .iter()
49 .map(|instr| convert_instruction(&emulator.executor.instruction_executor, instr))
50 .collect();
51
52 let converted_elf = nexus_core::nvm::ElfFile {
53 instructions,
54 ..expected_elf.clone()
55 };
56
57 let program_memory = elf_into_program_info(&converted_elf, memory_layout);
58
59 let input_memory = slice_into_io_entries::<MemoryInitializationEntry>(
60 memory_layout.public_input_start(),
61 &[
62 &(expected_public_input.len() as u32).to_le_bytes(),
63 expected_public_input,
64 ]
65 .concat(),
66 );
67
68 let ro_initial_memory = slice_into_io_entries::<MemoryInitializationEntry>(
69 memory_layout.public_input_address_location(),
70 &[
71 memory_layout.public_input_start().to_le_bytes(),
72 memory_layout.exit_code().to_le_bytes(), ]
74 .concat(),
75 )
76 .iter()
77 .chain(map_into_io_entries::<MemoryInitializationEntry>(&expected_elf.rom_image).iter())
78 .copied()
79 .collect();
80
81 let rw_initial_memory =
82 map_into_io_entries::<MemoryInitializationEntry>(&expected_elf.ram_image);
83
84 let exit_code = slice_into_io_entries::<PublicOutputEntry>(
85 memory_layout.exit_code(),
86 expected_exit_code,
87 );
88
89 let output_memory = slice_into_io_entries::<PublicOutputEntry>(
90 memory_layout.public_output_start(),
91 expected_public_output,
92 );
93
94 let static_memory_size =
95 (expected_elf.rom_image.len_bytes() + expected_elf.ram_image.len_bytes()) * WORD_SIZE;
96
97 Self::new(
98 &Some(*memory_layout),
99 &Vec::new(),
100 &program_memory,
101 &ro_initial_memory,
102 &rw_initial_memory,
103 &input_memory,
104 memory_layout.tracked_ram_size(static_memory_size),
105 &exit_code,
106 &output_memory,
107 &expected_ad.to_vec(),
108 )
109 }
110}
111
112pub trait Viewable {
114 fn public_input<T: Serialize + DeserializeOwned + Sized>(&self) -> Result<T, IOError>;
116
117 fn public_input_digest<T: Serialize + DeserializeOwned + Sized, H: Digest>(
119 &self,
120 ) -> Result<GenericArray<u8, H::OutputSize>, IOError>
121 where
122 <H as OutputSizeUser>::OutputSize: ArrayLength<u8>,
123 {
124 Ok(H::digest(
125 postcard::to_stdvec_cobs::<T>(&Self::public_input::<T>(self)?)
126 .map_err(IOError::from)?
127 .as_slice(),
128 ))
129 }
130
131 fn exit_code(&self) -> Result<u32, IOError>;
133
134 fn exit_code_digest<H: Digest>(&self) -> Result<GenericArray<u8, H::OutputSize>, IOError>
136 where
137 <H as OutputSizeUser>::OutputSize: ArrayLength<u8>,
138 {
139 Ok(H::digest(Self::exit_code(self)?.to_le_bytes()))
140 }
141
142 fn public_output<U: Serialize + DeserializeOwned + Sized>(&self) -> Result<U, IOError>;
144
145 fn public_output_digest<U: Serialize + DeserializeOwned + Sized, H: Digest>(
147 &self,
148 ) -> Result<GenericArray<u8, H::OutputSize>, IOError>
149 where
150 <H as OutputSizeUser>::OutputSize: ArrayLength<u8>,
151 {
152 Ok(H::digest(
153 postcard::to_stdvec_cobs::<U>(&Self::public_output::<U>(self)?)
154 .map_err(IOError::from)?
155 .as_slice(),
156 ))
157 }
158
159 fn associated_data(&self) -> Result<Vec<u8>, IOError>;
161
162 fn associated_data_digest<H: Digest>(&self) -> Result<GenericArray<u8, H::OutputSize>, IOError>
164 where
165 <H as OutputSizeUser>::OutputSize: ArrayLength<u8>,
166 {
167 Ok(H::digest(Self::associated_data(self)?.as_slice()))
168 }
169
170 fn logs(&self) -> Result<Vec<String>, IOError>;
172}
173
174impl Viewable for nexus_core::nvm::View {
175 fn public_input<T: Serialize + DeserializeOwned + Sized>(&self) -> Result<T, IOError> {
177 if let Some(mut bytes) = self.view_public_input() {
178 Ok(postcard::from_bytes_cobs::<T>(&mut bytes).map_err(IOError::from)?)
179 } else {
180 Err(IOError::NotYetAvailableError)
181 }
182 }
183
184 fn exit_code(&self) -> Result<u32, IOError> {
186 if let Some(bytes) = self.view_exit_code() {
187 Ok(postcard::from_bytes::<u32>(&bytes).map_err(IOError::from)?)
188 } else {
189 Err(IOError::NotYetAvailableError)
190 }
191 }
192
193 fn public_output<U: Serialize + DeserializeOwned + Sized>(&self) -> Result<U, IOError> {
195 if let Some(mut bytes) = self.view_public_output() {
196 Ok(postcard::from_bytes_cobs::<U>(&mut bytes).map_err(IOError::from)?)
197 } else {
198 Err(IOError::NotYetAvailableError)
199 }
200 }
201
202 fn associated_data(&self) -> Result<Vec<u8>, IOError> {
204 if let Some(bytes) = self.view_associated_data() {
205 Ok(bytes)
206 } else {
207 Err(IOError::NotYetAvailableError)
208 }
209 }
210
211 fn logs(&self) -> Result<Vec<String>, IOError> {
213 if let Some(bytes_vecs) = self.view_debug_logs() {
214 Ok(bytes_vecs
215 .iter()
216 .map(|raw_log: &Vec<u8>| String::from_utf8_lossy(raw_log).to_string())
217 .collect())
218 } else {
219 Err(IOError::NotYetAvailableError)
220 }
221 }
222}
223
224pub trait ByGuestCompilation: Prover {
226 fn compile(compiler: &mut impl Compile) -> Result<Self, Self::Error>;
228}
229
230pub trait Prover: Sized {
232 type Proof: Verifiable;
233 type View: CheckedView;
234 type Error: From<nexus_core::nvm::VMError>;
235
236 fn new(elf: &nexus_core::nvm::ElfFile) -> Result<Self, <Self as Prover>::Error>;
238
239 fn new_from_bytes(elf_bytes: &[u8]) -> Result<Self, <Self as Prover>::Error> {
241 Self::new(&nexus_core::nvm::ElfFile::from_bytes(elf_bytes)?)
242 }
243
244 fn new_from_file<P: AsRef<Path> + ?Sized>(path: &P) -> Result<Self, <Self as Prover>::Error> {
246 Self::new(&nexus_core::nvm::ElfFile::from_path(&path)?)
247 }
248
249 fn set_associated_data(&mut self, ad: &[u8]) -> Result<(), <Self as Prover>::Error>;
251
252 fn run(&self) -> Result<Self::View, <Self as Prover>::Error> {
254 Self::run_with_input::<(), ()>(self, &(), &())
255 }
256
257 fn run_with_input<S: Serialize + Sized, T: Serialize + DeserializeOwned + Sized>(
259 &self,
260 private_input: &S,
261 public_input: &T,
262 ) -> Result<Self::View, <Self as Prover>::Error>;
263
264 fn prove(self) -> Result<(Self::View, Self::Proof), <Self as Prover>::Error> {
266 Self::prove_with_input::<(), ()>(self, &(), &())
267 }
268
269 fn prove_with_input<S: Serialize + Sized, T: Serialize + DeserializeOwned + Sized>(
271 self,
272 private_input: &S,
273 public_input: &T,
274 ) -> Result<(Self::View, Self::Proof), <Self as Prover>::Error>;
275
276 fn encode_input<T: Serialize>(input: &T) -> Result<Vec<u8>, IOError> {
279 let mut encoded = postcard::to_stdvec(input).map_err(IOError::from)?;
280 if !encoded.is_empty() {
281 encoded = postcard::to_stdvec_cobs(input).map_err(IOError::from)?;
282 let padded_len = (encoded.len() + 3) & !3;
283
284 assert!(padded_len >= encoded.len());
285 encoded.resize(padded_len, 0x00); }
287 Ok(encoded)
288 }
289}
290
291pub trait Setup<'a> {
295 type Reference;
297 type Parameters;
299 type Preprocessing;
301 type Error;
302
303 fn setup_reference<'b: 'a>(
305 &mut self,
306 reference: &'b Self::Reference,
307 ) -> Result<(), Self::Error>;
308
309 fn setup_parameters<'b: 'a>(
311 &mut self,
312 parameters: &'b Self::Parameters,
313 ) -> Result<(), Self::Error>;
314
315 fn detach(&mut self);
317
318 fn reference(&self) -> Result<&'a Self::Reference, Self::Error>;
320
321 fn parameters(&self) -> Result<&'a Self::Parameters, Self::Error>;
325
326 fn preprocessing(&self) -> Result<Self::Preprocessing, Self::Error>;
330
331 }
333
334pub trait Reference {
338 type Error;
339
340 fn generate() -> Result<Self, Self::Error>
342 where
343 Self: Sized;
344
345 fn load(path: &Path) -> Result<Self, Self::Error>
347 where
348 Self: Sized;
349
350 fn save(reference: &Self, path: &Path) -> Result<(), Self::Error>;
352}
353
354impl Reference for () {
355 type Error = ConfigurationError;
356
357 fn generate() -> Result<Self, Self::Error> {
358 Err(ConfigurationError::NotApplicableOperation)
359 }
360
361 fn load(_path: &Path) -> Result<Self, Self::Error> {
362 Err(ConfigurationError::NotApplicableOperation)
363 }
364
365 fn save(_reference: &Self, _path: &Path) -> Result<(), Self::Error> {
366 Err(ConfigurationError::NotApplicableOperation)
367 }
368}
369
370pub trait Parameters {
374 type Ref: Reference;
375 type Error;
376
377 fn generate(reference: &Self::Ref) -> Result<Self, Self::Error>
379 where
380 Self: Sized;
381
382 fn load(path: &Path) -> Result<Self, Self::Error>
384 where
385 Self: Sized;
386
387 fn save(parameters: &Self, path: &Path) -> Result<(), Self::Error>;
389}
390
391impl Parameters for () {
392 type Ref = ();
393 type Error = ConfigurationError;
394
395 fn generate(_reference: &Self::Ref) -> Result<Self, Self::Error> {
396 Err(ConfigurationError::NotApplicableOperation)
397 }
398
399 fn load(_path: &Path) -> Result<Self, Self::Error> {
400 Err(ConfigurationError::NotApplicableOperation)
401 }
402
403 fn save(_parameters: &Self, _path: &Path) -> Result<(), Self::Error> {
404 Err(ConfigurationError::NotApplicableOperation)
405 }
406}
407
408pub trait Preprocessing {
412 type Ref: Reference;
413 type Params: Parameters;
414 type Error;
415
416 fn load(path: &Path) -> Result<Self, Self::Error>
418 where
419 Self: Sized;
420
421 fn save(preprocessing: &Self, path: &Path) -> Result<(), Self::Error>;
423}
424
425impl Preprocessing for () {
426 type Ref = ();
427 type Params = ();
428 type Error = ConfigurationError;
429
430 fn load(_path: &Path) -> Result<Self, Self::Error> {
431 Err(ConfigurationError::NotApplicableOperation)
432 }
433
434 fn save(_preprocessing: &Self, _path: &Path) -> Result<(), Self::Error> {
435 Err(ConfigurationError::NotApplicableOperation)
436 }
437}
438
439pub trait Verifiable: Serialize + DeserializeOwned {
441 type View: CheckedView;
442 type Error: From<nexus_core::nvm::VMError> + From<IOError>;
443
444 fn get_memory_layout(&self) -> &LinearMemoryLayout;
446
447 fn verify(&self, expected_view: &Self::View) -> Result<(), <Self as Verifiable>::Error>;
449
450 fn verify_expected<
452 T: Serialize + DeserializeOwned + Sized,
453 U: Serialize + DeserializeOwned + Sized,
454 >(
455 &self,
456 expected_public_input: &T,
457 expected_exit_code: u32,
458 expected_public_output: &U,
459 expected_elf: &nexus_core::nvm::ElfFile,
460 expected_ad: &[u8],
461 ) -> Result<(), <Self as Verifiable>::Error> {
462 let mut input_encoded =
463 postcard::to_stdvec(&expected_public_input).map_err(IOError::from)?;
464 if !input_encoded.is_empty() {
465 input_encoded =
466 postcard::to_stdvec_cobs(&expected_public_input).map_err(IOError::from)?;
467 let input_padded_len = (input_encoded.len() + 3) & !3;
468
469 assert!(input_padded_len >= input_encoded.len());
470 input_encoded.resize(input_padded_len, 0x00); }
472
473 let mut output_encoded =
474 postcard::to_stdvec(&expected_public_output).map_err(IOError::from)?;
475 if !output_encoded.is_empty() {
476 output_encoded =
477 postcard::to_stdvec_cobs(&expected_public_output).map_err(IOError::from)?;
478 let output_padded_len = (output_encoded.len() + 3) & !3;
479
480 assert!(output_padded_len >= output_encoded.len());
481 output_encoded.resize(output_padded_len, 0x00); }
483
484 let view = Self::View::new_from_expected(
485 self.get_memory_layout(),
486 input_encoded.as_slice(),
487 &expected_exit_code.to_le_bytes(),
488 output_encoded.as_slice(),
489 expected_elf,
490 expected_ad,
491 );
492
493 self.verify(&view)
494 }
495
496 fn verify_expected_from_program_bytes<
498 T: Serialize + DeserializeOwned + Sized,
499 U: Serialize + DeserializeOwned + Sized,
500 >(
501 &self,
502 expected_public_input: &T,
503 expected_exit_code: u32,
504 expected_public_output: &U,
505 expected_elf_bytes: &[u8],
506 expected_ad: &[u8],
507 ) -> Result<(), <Self as Verifiable>::Error> {
508 self.verify_expected(
509 expected_public_input,
510 expected_exit_code,
511 expected_public_output,
512 &nexus_core::nvm::ElfFile::from_bytes(expected_elf_bytes)?,
513 expected_ad,
514 )
515 }
516
517 fn verify_expected_from_program_path<
519 P: AsRef<Path> + ?Sized,
520 T: Serialize + DeserializeOwned + Sized,
521 U: Serialize + DeserializeOwned + Sized,
522 >(
523 &self,
524 expected_public_input: &T,
525 expected_exit_code: u32,
526 expected_public_output: &U,
527 expected_elf_path: &P,
528 expected_ad: &[u8],
529 ) -> Result<(), <Self as Verifiable>::Error> {
530 self.verify_expected(
531 expected_public_input,
532 expected_exit_code,
533 expected_public_output,
534 &nexus_core::nvm::ElfFile::from_path(expected_elf_path)?,
535 expected_ad,
536 )
537 }
538
539 fn size_estimate(&self) -> usize;
541}