nexus_sdk/stwo/
seq.rs

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/// Errors that occur while proving using Stwo.
11#[derive(Debug, Error)]
12pub enum Error {
13    /// An error occurred during proving a zkVM execution.
14    #[error(transparent)]
15    ProvingError(#[from] nexus_core::stwo::ProvingError),
16
17    /// An error occurred verifying a claimed proof of a zkVM execution.
18    #[error(transparent)]
19    VerificationError(#[from] nexus_core::stwo::VerificationError),
20
21    /// An error occurred building the guest program dynamically.
22    #[error(transparent)]
23    BuildError(#[from] BuildError),
24
25    /// An error occurred reading or writing to the filesystem.
26    #[error(transparent)]
27    HostIOError(#[from] std::io::Error),
28
29    /// An error occurred trying to parse a path for use with the filesystem.
30    #[error(transparent)]
31    PathError(#[from] PathError),
32
33    /// An error occurred reading or writing to the zkVM input/output segments.
34    #[error(transparent)]
35    GuestIOError(#[from] IOError),
36
37    /// An error occured executing the zkVM.
38    #[error(transparent)]
39    VMError(#[from] nexus_core::nvm::VMError),
40
41    /// An error occured loading or parsing the ELF.
42    #[error(transparent)]
43    ElfError(#[from] nexus_core::nvm::ElfError),
44
45    /// An error occured configuring the prover.
46    #[error(transparent)]
47    ConfigurationError(#[from] ConfigurationError),
48}
49
50/// Prover for the Nexus zkVM, when using Stwo.
51pub struct Stwo<C: Compute = Local> {
52    /// The program to be proven.
53    pub elf: nexus_core::nvm::ElfFile,
54    /// The associated data to prove with.
55    pub ad: Vec<u8>,
56    _compute: PhantomData<C>,
57}
58
59/// The Stwo proof, alongside machine configuration information needed for verification.
60#[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    /// Construct a new proving instance through dynamic compilation (see [`compile`](crate::compile)).
72    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)
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    /// Construct a new proving instance.
85    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    /// Set the associated data bytes to be bound into the proof.
94    fn set_associated_data(&mut self, ad: &[u8]) -> Result<(), <Self as Prover>::Error> {
95        self.ad = ad.to_vec();
96        Ok(())
97    }
98
99    /// Run the zkVM on private input of type `S` and public input of type `T` and return a view of the execution output.
100    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 private_encoded =
106            <Self as Prover>::encode_input(private_input).map_err(Error::GuestIOError)?;
107        let public_encoded =
108            <Self as Prover>::encode_input(public_input).map_err(Error::GuestIOError)?;
109
110        let (view, _) = nexus_core::nvm::k_trace(
111            self.elf.clone(),
112            self.ad.as_slice(),
113            public_encoded.as_slice(),
114            private_encoded.as_slice(),
115            1,
116        )?; // todo: run without tracing?
117
118        Ok(view)
119    }
120
121    /// Run the zkVM on private input of type `S` and public input of type `T` and return a verifiable proof, along with a view of the execution output.
122    fn prove_with_input<S: Serialize + Sized, T: Serialize + DeserializeOwned + Sized>(
123        self,
124        private_input: &S,
125        public_input: &T,
126    ) -> Result<(Self::View, Self::Proof), <Self as Prover>::Error> {
127        let private_encoded =
128            <Self as Prover>::encode_input(private_input).map_err(Error::GuestIOError)?;
129        let public_encoded =
130            <Self as Prover>::encode_input(public_input).map_err(Error::GuestIOError)?;
131
132        let (view, trace) = nexus_core::nvm::k_trace(
133            self.elf.clone(),
134            self.ad.as_slice(),
135            public_encoded.as_slice(),
136            private_encoded.as_slice(),
137            1,
138        )?;
139        let proof = nexus_core::stwo::prove(&trace, &view)?;
140
141        Ok((
142            view,
143            Proof {
144                proof,
145                memory_layout: trace.memory_layout,
146            },
147        ))
148    }
149}
150
151impl Verifiable for Proof {
152    type View = nexus_core::nvm::View;
153    type Error = Error;
154
155    fn get_memory_layout(&self) -> &nexus_core::nvm::internals::LinearMemoryLayout {
156        &self.memory_layout
157    }
158
159    fn verify(&self, view: &Self::View) -> Result<(), <Self as Verifiable>::Error> {
160        nexus_core::stwo::verify(self.proof.clone(), view)?;
161        Ok(())
162    }
163
164    fn size_estimate(&self) -> usize {
165        self.proof.size_estimate()
166    }
167}