1use crate::compile::Compile;
2use crate::traits::*;
3
4use serde::{de::DeserializeOwned, Deserialize, Serialize};
5use std::marker::PhantomData;
6use thiserror::Error;
7
8use crate::error::{BuildError, ConfigurationError, IOError, PathError};
9
10#[derive(Debug, Error)]
12pub enum Error {
13 #[error(transparent)]
15 ProvingError(#[from] nexus_core::stwo::ProvingError),
16
17 #[error(transparent)]
19 VerificationError(#[from] nexus_core::stwo::VerificationError),
20
21 #[error(transparent)]
23 BuildError(#[from] BuildError),
24
25 #[error(transparent)]
27 HostIOError(#[from] std::io::Error),
28
29 #[error(transparent)]
31 PathError(#[from] PathError),
32
33 #[error(transparent)]
35 GuestIOError(#[from] IOError),
36
37 #[error(transparent)]
39 VMError(#[from] nexus_core::nvm::VMError),
40
41 #[error(transparent)]
43 ElfError(#[from] nexus_core::nvm::ElfError),
44
45 #[error(transparent)]
47 ConfigurationError(#[from] ConfigurationError),
48}
49
50pub struct Stwo<C: Compute = Local> {
52 pub elf: nexus_core::nvm::ElfFile,
54 pub ad: Vec<u8>,
56 _compute: PhantomData<C>,
57}
58
59#[derive(Serialize, Deserialize)]
61pub struct Proof {
62 proof: nexus_core::stwo::Proof,
63 memory_layout: nexus_core::nvm::internals::LinearMemoryLayout,
64}
65
66impl<C: Compute> ByGuestCompilation for Stwo<C>
67where
68 Stwo<C>: Prover,
69 <Stwo<C> as Prover>::Error: From<BuildError>,
70{
71 fn compile(compiler: &mut impl Compile) -> Result<Self, <Self as Prover>::Error> {
73 let elf_path = compiler.build()?;
74
75 Self::new_from_file(&elf_path.to_string_lossy().to_string())
76 }
77}
78
79impl Prover for Stwo<Local> {
80 type Proof = Proof;
81 type View = nexus_core::nvm::View;
82 type Error = Error;
83
84 fn new(elf: &nexus_core::nvm::ElfFile) -> Result<Self, <Self as Prover>::Error> {
86 Ok(Self {
87 elf: elf.clone(),
88 ad: Vec::new(),
89 _compute: PhantomData,
90 })
91 }
92
93 fn set_associated_data(&mut self, ad: &[u8]) -> Result<(), <Self as Prover>::Error> {
95 self.ad = ad.to_vec();
96 Ok(())
97 }
98
99 fn run_with_input<S: Serialize + Sized, T: Serialize + DeserializeOwned + Sized>(
101 &self,
102 private_input: &S,
103 public_input: &T,
104 ) -> Result<Self::View, <Self as Prover>::Error> {
105 let mut private_encoded = postcard::to_stdvec(&private_input).map_err(IOError::from)?;
106 if !private_encoded.is_empty() {
107 let private = private_input.to_owned();
108
109 private_encoded = postcard::to_stdvec_cobs(&private).map_err(IOError::from)?;
110 let private_padded_len = (private_encoded.len() + 3) & !3;
111
112 assert!(private_padded_len >= private_encoded.len());
113 private_encoded.resize(private_padded_len, 0x00); }
115
116 let mut public_encoded = postcard::to_stdvec(&public_input).map_err(IOError::from)?;
117 if !public_encoded.is_empty() {
118 let public = public_input.to_owned();
119
120 public_encoded = postcard::to_stdvec_cobs(&public).map_err(IOError::from)?;
121 let public_padded_len = (public_encoded.len() + 3) & !3;
122
123 assert!(public_padded_len >= public_encoded.len());
124 public_encoded.resize(public_padded_len, 0x00); }
126
127 let (view, _) = nexus_core::nvm::k_trace(
128 self.elf.clone(),
129 self.ad.as_slice(),
130 public_encoded.as_slice(),
131 private_encoded.as_slice(),
132 1,
133 )?; Ok(view)
136 }
137
138 fn prove_with_input<S: Serialize + Sized, T: Serialize + DeserializeOwned + Sized>(
140 self,
141 private_input: &S,
142 public_input: &T,
143 ) -> Result<(Self::View, Self::Proof), <Self as Prover>::Error> {
144 let mut private_encoded = postcard::to_stdvec(&private_input).map_err(IOError::from)?;
145 if !private_encoded.is_empty() {
146 let private = private_input.to_owned();
147
148 private_encoded = postcard::to_stdvec_cobs(&private).map_err(IOError::from)?;
149 let private_padded_len = (private_encoded.len() + 3) & !3;
150
151 assert!(private_padded_len >= private_encoded.len());
152 private_encoded.resize(private_padded_len, 0x00); }
154
155 let mut public_encoded = postcard::to_stdvec(&public_input).map_err(IOError::from)?;
156 if !public_encoded.is_empty() {
157 let public = public_input.to_owned();
158
159 public_encoded = postcard::to_stdvec_cobs(&public).map_err(IOError::from)?;
160 let public_padded_len = (public_encoded.len() + 3) & !3;
161
162 assert!(public_padded_len >= public_encoded.len());
163 public_encoded.resize(public_padded_len, 0x00); }
165
166 let (view, trace) = nexus_core::nvm::k_trace(
167 self.elf.clone(),
168 self.ad.as_slice(),
169 public_encoded.as_slice(),
170 private_encoded.as_slice(),
171 1,
172 )?;
173 let proof = nexus_core::stwo::prove(&trace, &view)?;
174
175 Ok((
176 view,
177 Proof {
178 proof,
179 memory_layout: trace.memory_layout,
180 },
181 ))
182 }
183}
184
185impl Verifiable for Proof {
186 type View = nexus_core::nvm::View;
187 type Error = Error;
188
189 fn get_memory_layout(&self) -> &nexus_core::nvm::internals::LinearMemoryLayout {
190 &self.memory_layout
191 }
192
193 fn verify(&self, view: &Self::View) -> Result<(), <Self as Verifiable>::Error> {
194 nexus_core::stwo::verify(self.proof.clone(), view)?;
195 Ok(())
196 }
197
198 fn size_estimate(&self) -> usize {
199 self.proof.size_estimate()
200 }
201}