sunscreen_runtime/
lib.rs

1#![deny(missing_docs)]
2#![deny(rustdoc::broken_intra_doc_links)]
3
4//! This crate contains the types and functions for executing a Sunscreen FHE or ZKP program.
5
6mod array;
7mod error;
8mod keys;
9mod metadata;
10mod run;
11mod runtime;
12mod serialization;
13
14use std::sync::Arc;
15
16pub use crate::error::*;
17pub use crate::keys::*;
18pub use crate::metadata::*;
19pub use run::*;
20pub use runtime::*;
21pub use serialization::WithContext;
22
23use seal_fhe::{Ciphertext as SealCiphertext, Plaintext as SealPlaintext};
24use serde::{Deserialize, Serialize};
25use sunscreen_zkp_backend::BigInt;
26
27#[derive(Debug, Clone, PartialEq, Hash, Serialize, Deserialize, Eq)]
28/**
29 * The underlying backend implementation of a plaintext (e.g. SEAL's [`Plaintext`](seal_fhe::Plaintext)).
30 */
31pub enum InnerPlaintext {
32    /**
33     * This plaintext wraps a SEAL [`Plaintext`](seal_fhe::Plaintext).
34     */
35    Seal(Vec<WithContext<SealPlaintext>>),
36}
37
38impl InnerPlaintext {
39    /**
40     * Returns how many plaintexts are inside this wrapper.
41     */
42    pub fn len(&self) -> usize {
43        match self {
44            Self::Seal(d) => d.len(),
45        }
46    }
47
48    /**
49     * Returns whether or not there are any plaintexts inside this wrapper.
50     */
51    pub fn is_empty(&self) -> bool {
52        self.len() == 0
53    }
54
55    /**
56     * Decompose the N plaintexts inside this wrapper into N wrappers
57     * with 1 plaintext each. Useful for creating plaintext constants
58     * in FHE programs.
59     */
60    pub fn scatter(&self) -> Vec<InnerPlaintext> {
61        match self {
62            Self::Seal(d) => d.iter().map(|p| Self::Seal(vec![p.clone()])).collect(),
63        }
64    }
65
66    /**
67     * Serialize this object into bytes.
68     *
69     * # Remarks
70     * This function internally uses bincode for serialization.
71     */
72    pub fn to_bytes(&self) -> Result<Vec<u8>> {
73        Ok(bincode::serialize(&self)?)
74    }
75
76    /**
77     * Deserialize an inner plaintext object from bytes.
78     *
79     * # Remarks
80     * This function internally uses bincode for serialization.
81     */
82    pub fn from_bytes(data: &[u8]) -> Result<Self> {
83        Ok(bincode::deserialize(data)?)
84    }
85
86    /**
87     * Unwraps the enum and returns the underlying seal plaintexts, or
88     * returns an error if this plaintext isn't a Seal plaintext.
89     */
90    pub fn as_seal_plaintext(&self) -> Result<&[WithContext<SealPlaintext>]> {
91        match self {
92            Self::Seal(d) => Ok(d),
93        }
94    }
95}
96
97#[derive(Clone)]
98/**
99 * A type that can be either a SEAL plaintext or a ciphertext.
100 */
101pub enum SealData {
102    /**
103     * The underlying ciphertext.
104     */
105    Ciphertext(SealCiphertext),
106
107    /**
108     * The underlying plaintext.
109     */
110    Plaintext(SealPlaintext),
111}
112
113impl From<SealCiphertext> for SealData {
114    fn from(val: SealCiphertext) -> Self {
115        Self::Ciphertext(val)
116    }
117}
118
119impl From<SealPlaintext> for SealData {
120    fn from(val: SealPlaintext) -> Self {
121        Self::Plaintext(val)
122    }
123}
124
125#[derive(Clone, Serialize, Deserialize)]
126/**
127 * Represents an encoded plaintext suitable for use in the underlying scheme.
128 */
129pub struct Plaintext {
130    /**
131     * The data type contained in this ciphertext. Note, this type metadata is stored in the clear.
132     */
133    pub data_type: Type,
134
135    /**
136     * The scheme and backend-specific plaintext.
137     */
138    pub inner: InnerPlaintext,
139}
140
141impl Plaintext {
142    /**
143     * Unwraps the inner plaintext as a Seal plaintext variant. Returns an
144     * error if the inner plaintext is not a Seal plaintext.
145     */
146    pub fn inner_as_seal_plaintext(&self) -> Result<&[WithContext<SealPlaintext>]> {
147        self.inner.as_seal_plaintext()
148    }
149}
150
151#[derive(Clone, Deserialize, Serialize)]
152/**
153 * The underlying backend implementation of a ciphertext (e.g SEAL's [`Ciphertext`](seal_fhe::Ciphertext)).
154 */
155pub enum InnerCiphertext {
156    /**
157     * A set of ciphertexts in SEAL's runtime.
158     */
159    Seal(Vec<WithContext<SealCiphertext>>),
160}
161
162#[derive(Clone, Deserialize, Serialize)]
163/**
164 * An encryption of the given data type. Note, the data type is
165 * stored in plaintext and is considered part of Sunscreen's runtime
166 * protocol.
167 */
168pub struct Ciphertext {
169    /**
170     * The data type contained in this ciphertext. Note, this type metadata is stored in the clear.
171     */
172    pub data_type: Type,
173
174    /**
175     * The scheme and backend-specific plaintext.
176     */
177    pub inner: InnerCiphertext,
178}
179
180/**
181 * A trait that denotes this type can be used as an
182 * argument to an FHE program.
183 */
184pub trait FheProgramInputTrait: TryIntoPlaintext + TypeNameInstance {}
185
186/**
187 * An input argument to an Fhe Program. See [`crate::Runtime::run`].
188 */
189pub enum FheProgramInput {
190    /**
191     * The argument is a ciphertext.
192     */
193    Ciphertext(Ciphertext),
194
195    /**
196     * The argument is a plaintext.
197     */
198    Plaintext(Box<dyn FheProgramInputTrait>),
199}
200
201/**
202 * Denotes this type can be used as an input to a ZKP
203 * program.
204 */
205pub trait ZkpProgramInputTrait: ToNativeFields + TypeNameInstance {}
206
207impl<T: ToNativeFields + TypeNameInstance> ZkpProgramInputTrait for T {}
208
209#[derive(Clone)]
210/**
211 * An input argument to a ZKP program.
212 */
213pub struct ZkpProgramInput(pub Arc<dyn ZkpProgramInputTrait>);
214
215impl<T> From<T> for ZkpProgramInput
216where
217    T: ZkpProgramInputTrait + 'static,
218{
219    fn from(val: T) -> Self {
220        Self(Arc::new(val))
221    }
222}
223
224impl TypeNameInstance for FheProgramInput {
225    fn type_name_instance(&self) -> Type {
226        match self {
227            Self::Ciphertext(c) => c.data_type.clone(),
228            Self::Plaintext(p) => p.type_name_instance(),
229        }
230    }
231}
232
233impl From<Ciphertext> for FheProgramInput {
234    fn from(val: Ciphertext) -> Self {
235        Self::Ciphertext(val)
236    }
237}
238
239impl<T> From<T> for FheProgramInput
240where
241    T: FheProgramInputTrait + 'static,
242{
243    fn from(val: T) -> Self {
244        Self::Plaintext(Box::new(val))
245    }
246}
247
248/**
249 * This trait denotes one may attempt to turn this type into a plaintext.
250 */
251pub trait TryIntoPlaintext {
252    /**
253     * Attempts to turn this type into a [`Plaintext`].
254     */
255    fn try_into_plaintext(&self, params: &Params) -> Result<Plaintext>;
256}
257
258/**
259 * A trait for converting values into fields used by ZKPs.
260 */
261pub trait ToNativeFields {
262    /**
263     * Converts the given value into [`BigInt`]s.
264     *
265     * # Remarks
266     * The length of the returned vector must equal NUM_NATIVE_FIELD_ELEMENTS.
267     */
268    fn to_native_fields(&self) -> Vec<BigInt>;
269}
270
271impl<T, const N: usize> ToNativeFields for [T; N]
272where
273    T: ToNativeFields,
274{
275    fn to_native_fields(&self) -> Vec<sunscreen_zkp_backend::BigInt> {
276        self.iter().flat_map(|x| x.to_native_fields()).collect()
277    }
278}
279
280/**
281 * This trait specifies one may attempt to convert a plaintext into this type.
282 */
283pub trait TryFromPlaintext
284where
285    Self: Sized,
286{
287    /**
288     * Attempts to turn a [`Plaintext`] into `Self`. On success, returns
289     */
290    fn try_from_plaintext(plaintext: &Plaintext, params: &Params) -> Result<Self>;
291}
292
293/**
294 * Declare how many ciphertexts an FheType decomposes into. The runtime needs this
295 * to correctly bundle return values from an Fhe Program.
296 */
297pub trait NumCiphertexts {
298    /**
299     * The number of ciphertexts this type decomposes into.
300     */
301    const NUM_CIPHERTEXTS: usize;
302}
303
304/**
305 * Denotes the given rust type is an encoding in an FHE scheme
306 */
307pub trait FheType:
308    TypeNameInstance + TryIntoPlaintext + TryFromPlaintext + FheProgramInputTrait + NumCiphertexts
309{
310}
311
312/**
313 * Denotes the given type is valid under the BFV scheme.
314 */
315pub trait BfvType: FheType {}
316
317/**
318 * A trait the gives a name an version to a given type
319 */
320pub trait TypeNameInstance {
321    /**
322     * Returns the [`Type`] of the `&self`. Lives only on the instance so you can be object-safe
323     * for use in `dyn TypeName`.
324     */
325    fn type_name_instance(&self) -> Type;
326}