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}