mirror of
https://github.com/Sunscreen-tech/Sunscreen.git
synced 2026-04-19 03:00:06 -04:00
Merge pull request #42 from Sunscreen-tech/rweber/plaintext
Remove Unsigned type; it doesn't support subtraction
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use sunscreen_compiler::{
|
||||
circuit,
|
||||
types::{bfv::Unsigned, Cipher},
|
||||
types::{bfv::Signed, Cipher},
|
||||
Compiler, PlainModulusConstraint,
|
||||
};
|
||||
use sunscreen_runtime::Runtime;
|
||||
@@ -11,17 +11,17 @@ use sunscreen_runtime::Runtime;
|
||||
* the result. Circuits may take any number of parameters and return either a single result
|
||||
* or a tuple of results.
|
||||
*
|
||||
* The [`Unsigned`] type refers to an unsigned integer modulo the plaintext
|
||||
* The [`Signed`] type refers to an unsigned integer modulo the plaintext
|
||||
* modulus (p). p is passed to the compiler via plain_modulus_constraint.
|
||||
*
|
||||
* A `Cipher` type indicates the type is encrypted. Thus, a `Cipher<Unsigned>`
|
||||
* refers to an encrypted [`Unsigned`] value.
|
||||
* A `Cipher` type indicates the type is encrypted. Thus, a `Cipher<Signed>`
|
||||
* refers to an encrypted [`Signed`] value.
|
||||
*
|
||||
* One takes a circuit and passes them to the compiler, which transforms it into a form
|
||||
* suitable for execution.
|
||||
*/
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn simple_multiply(a: Cipher<Unsigned>, b: Cipher<Unsigned>) -> Cipher<Unsigned> {
|
||||
fn simple_multiply(a: Cipher<Signed>, b: Cipher<Signed>) -> Cipher<Signed> {
|
||||
a * b
|
||||
}
|
||||
|
||||
@@ -66,8 +66,8 @@ fn main() {
|
||||
*/
|
||||
let (public, secret) = runtime.generate_keys().unwrap();
|
||||
|
||||
let a = runtime.encrypt(Unsigned::from(15), &public).unwrap();
|
||||
let b = runtime.encrypt(Unsigned::from(5), &public).unwrap();
|
||||
let a = runtime.encrypt(Signed::from(15), &public).unwrap();
|
||||
let b = runtime.encrypt(Signed::from(5), &public).unwrap();
|
||||
|
||||
/*
|
||||
* Run the circuit with our arguments. This produces a results
|
||||
@@ -76,9 +76,9 @@ fn main() {
|
||||
let results = runtime.run(&circuit, vec![a, b], &public).unwrap();
|
||||
|
||||
/*
|
||||
* Our circuit outputs a Unsigned single value as the result. Decrypt it.
|
||||
* Our circuit outputs a Signed single value as the result. Decrypt it.
|
||||
*/
|
||||
let c: Unsigned = runtime.decrypt(&results[0], &secret).unwrap();
|
||||
let c: Signed = runtime.decrypt(&results[0], &secret).unwrap();
|
||||
|
||||
/*
|
||||
* Yay, 5 * 15 indeed equals 75.
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
//! # Examples
|
||||
//! This example is further annotated in `examples/simple_multiply`.
|
||||
//! ```
|
||||
//! # use sunscreen_compiler::{circuit, Compiler, types::{bfv::Unsigned, Cipher}, PlainModulusConstraint, Params, Runtime, Context};
|
||||
//! # use sunscreen_compiler::{circuit, Compiler, types::{bfv::Signed, Cipher}, PlainModulusConstraint, Params, Runtime, Context};
|
||||
//!
|
||||
//! #[circuit(scheme = "bfv")]
|
||||
//! fn simple_multiply(a: Cipher<Unsigned>, b: Cipher<Unsigned>) -> Cipher<Unsigned> {
|
||||
//! fn simple_multiply(a: Cipher<Signed>, b: Cipher<Signed>) -> Cipher<Signed> {
|
||||
//! a * b
|
||||
//! }
|
||||
//!
|
||||
@@ -25,12 +25,12 @@
|
||||
//!
|
||||
//! let (public, secret) = runtime.generate_keys().unwrap();
|
||||
//!
|
||||
//! let a = runtime.encrypt(Unsigned::from(15), &public).unwrap();
|
||||
//! let b = runtime.encrypt(Unsigned::from(5), &public).unwrap();
|
||||
//! let a = runtime.encrypt(Signed::from(15), &public).unwrap();
|
||||
//! let b = runtime.encrypt(Signed::from(5), &public).unwrap();
|
||||
//!
|
||||
//! let results = runtime.run(&circuit, vec![a, b], &public).unwrap();
|
||||
//!
|
||||
//! let c: Unsigned = runtime.decrypt(&results[0], &secret).unwrap();
|
||||
//! let c: Signed = runtime.decrypt(&results[0], &secret).unwrap();
|
||||
//!
|
||||
//! assert_eq!(c, 75.into());
|
||||
//! }
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
mod fractional;
|
||||
mod rational;
|
||||
mod signed;
|
||||
mod unsigned;
|
||||
|
||||
pub use fractional::*;
|
||||
pub use rational::*;
|
||||
pub use signed::*;
|
||||
pub use unsigned::*;
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
use seal::Plaintext as SealPlaintext;
|
||||
|
||||
use crate::types::{ops::*, Cipher};
|
||||
use crate::{
|
||||
types::{intern::CircuitNode, BfvType, FheType, TypeNameInstance},
|
||||
with_ctx, CircuitInputTrait, Params, TypeName as DeriveTypeName, WithContext,
|
||||
};
|
||||
|
||||
use sunscreen_runtime::{
|
||||
InnerPlaintext, NumCiphertexts, Plaintext, TryFromPlaintext, TryIntoPlaintext,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, DeriveTypeName, PartialEq, Eq)]
|
||||
/**
|
||||
* A single unsigned integer.
|
||||
*/
|
||||
pub struct Unsigned {
|
||||
val: u64,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for Unsigned {
|
||||
type Target = u64;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.val
|
||||
}
|
||||
}
|
||||
|
||||
impl CircuitInputTrait for Unsigned {}
|
||||
impl FheType for Unsigned {}
|
||||
impl BfvType for Unsigned {}
|
||||
|
||||
impl Unsigned {}
|
||||
|
||||
impl GraphCipherAdd for Unsigned {
|
||||
type Left = Unsigned;
|
||||
type Right = Unsigned;
|
||||
|
||||
fn graph_cipher_add(
|
||||
a: CircuitNode<Cipher<Self::Left>>,
|
||||
b: CircuitNode<Cipher<Self::Right>>,
|
||||
) -> CircuitNode<Cipher<Self::Left>> {
|
||||
with_ctx(|ctx| {
|
||||
let n = ctx.add_addition(a.ids[0], b.ids[0]);
|
||||
|
||||
CircuitNode::new(&[n])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl GraphCipherPlainAdd for Unsigned {
|
||||
type Left = Unsigned;
|
||||
type Right = Unsigned;
|
||||
|
||||
fn graph_cipher_plain_add(
|
||||
a: CircuitNode<Cipher<Self::Left>>,
|
||||
b: CircuitNode<Self::Right>,
|
||||
) -> CircuitNode<Cipher<Self::Left>> {
|
||||
with_ctx(|ctx| {
|
||||
let n = ctx.add_addition_plaintext(a.ids[0], b.ids[0]);
|
||||
|
||||
CircuitNode::new(&[n])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl GraphCipherConstAdd for Unsigned {
|
||||
type Left = Self;
|
||||
type Right = u64;
|
||||
|
||||
fn graph_cipher_const_add(
|
||||
a: CircuitNode<Cipher<Self::Left>>,
|
||||
b: u64,
|
||||
) -> CircuitNode<Cipher<Self::Left>> {
|
||||
with_ctx(|ctx| {
|
||||
let b = Self::from(b).try_into_plaintext(&ctx.params).unwrap();
|
||||
|
||||
let lit = ctx.add_plaintext_literal(b.inner);
|
||||
let add = ctx.add_addition_plaintext(a.ids[0], lit);
|
||||
|
||||
CircuitNode::new(&[add])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl GraphCipherMul for Unsigned {
|
||||
type Left = Unsigned;
|
||||
type Right = Unsigned;
|
||||
|
||||
fn graph_cipher_mul(
|
||||
a: CircuitNode<Cipher<Self::Left>>,
|
||||
b: CircuitNode<Cipher<Self::Right>>,
|
||||
) -> CircuitNode<Cipher<Self::Left>> {
|
||||
with_ctx(|ctx| {
|
||||
let n = ctx.add_multiplication(a.ids[0], b.ids[0]);
|
||||
|
||||
CircuitNode::new(&[n])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl GraphCipherConstMul for Unsigned {
|
||||
type Left = Self;
|
||||
type Right = u64;
|
||||
|
||||
fn graph_cipher_const_mul(
|
||||
a: CircuitNode<Cipher<Self::Left>>,
|
||||
b: u64,
|
||||
) -> CircuitNode<Cipher<Self::Left>> {
|
||||
with_ctx(|ctx| {
|
||||
let b = Self::from(b).try_into_plaintext(&ctx.params).unwrap();
|
||||
|
||||
let lit = ctx.add_plaintext_literal(b.inner);
|
||||
let add = ctx.add_multiplication_plaintext(a.ids[0], lit);
|
||||
|
||||
CircuitNode::new(&[add])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl GraphCipherPlainMul for Unsigned {
|
||||
type Left = Unsigned;
|
||||
type Right = Unsigned;
|
||||
|
||||
fn graph_cipher_plain_mul(
|
||||
a: CircuitNode<Cipher<Self::Left>>,
|
||||
b: CircuitNode<Self::Right>,
|
||||
) -> CircuitNode<Cipher<Self::Left>> {
|
||||
with_ctx(|ctx| {
|
||||
let n = ctx.add_multiplication_plaintext(a.ids[0], b.ids[0]);
|
||||
|
||||
CircuitNode::new(&[n])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryIntoPlaintext for Unsigned {
|
||||
fn try_into_plaintext(
|
||||
&self,
|
||||
params: &Params,
|
||||
) -> std::result::Result<Plaintext, sunscreen_runtime::Error> {
|
||||
let mut seal_plaintext = SealPlaintext::new()?;
|
||||
|
||||
let bits = std::mem::size_of::<u64>() * 8;
|
||||
|
||||
seal_plaintext.resize(bits);
|
||||
|
||||
for i in 0..bits {
|
||||
let bit_value = (self.val & 0x1 << i) >> i;
|
||||
seal_plaintext.set_coefficient(i, bit_value);
|
||||
}
|
||||
|
||||
Ok(Plaintext {
|
||||
data_type: self.type_name_instance(),
|
||||
inner: InnerPlaintext::Seal(vec![WithContext {
|
||||
params: params.clone(),
|
||||
data: seal_plaintext,
|
||||
}]),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromPlaintext for Unsigned {
|
||||
fn try_from_plaintext(
|
||||
plaintext: &Plaintext,
|
||||
_params: &Params,
|
||||
) -> std::result::Result<Self, sunscreen_runtime::Error> {
|
||||
let val = match &plaintext.inner {
|
||||
InnerPlaintext::Seal(p) => {
|
||||
if p.len() != 1 {
|
||||
return Err(sunscreen_runtime::Error::IncorrectCiphertextCount);
|
||||
}
|
||||
|
||||
let mut val = 0u64;
|
||||
let bits = usize::min(std::mem::size_of::<u64>() * 8, p[0].len());
|
||||
|
||||
for i in 0..bits {
|
||||
val += p[0].get_coefficient(i) * (1 << i);
|
||||
}
|
||||
|
||||
Self { val }
|
||||
}
|
||||
};
|
||||
|
||||
Ok(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl NumCiphertexts for Unsigned {
|
||||
const NUM_CIPHERTEXTS: usize = 1;
|
||||
}
|
||||
|
||||
impl From<u64> for Unsigned {
|
||||
fn from(val: u64) -> Self {
|
||||
Self { val }
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<u64> for Unsigned {
|
||||
fn into(self) -> u64 {
|
||||
self.val
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn can_convert_u64_to_unsigned() {
|
||||
let foo: Unsigned = 64u64.into();
|
||||
|
||||
assert_eq!(foo.val, 64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_convert_unsigned_to_u64() {
|
||||
let foo = Unsigned { val: 64 };
|
||||
let converted: u64 = foo.into();
|
||||
|
||||
assert_eq!(converted, 64u64);
|
||||
}
|
||||
}
|
||||
@@ -20,13 +20,9 @@
|
||||
* allows for somewhat efficiently representing integers, but has unusual
|
||||
* overflow semantics developers need to understand. This type supports
|
||||
* addition, subtraction, multiplication, and negation.
|
||||
* * The [`Unsigned`](crate::types::bfv::Unsigned) type represents and unsigned
|
||||
* integer. This type has the same benefits and caveats as
|
||||
* [`Signed`](crate::types::bfv::Signed) types, but is unsigned.
|
||||
* * The [`Fractional`](crate::types::bfv::Fractional) type is a quasi fixed-point
|
||||
* value. It allows you to homomorphically compute decimal values as
|
||||
* efficiently as [`Signed`](crate::types::bfv::Signed) and
|
||||
* [`Unsigned`](crate::types::bfv::Unsigned) types. This type has complex overflow
|
||||
* efficiently as the [`Signed`](crate::types::bfv::Signed) type. This type has complex overflow
|
||||
* conditions. This type intrinsically supports homomorphic addition
|
||||
* multiplication, and negation. Dividing by an [`f64`] constant is supported.
|
||||
* Dividing by ciphertext is not possible.
|
||||
@@ -44,7 +40,6 @@
|
||||
* | Type | # ciphertexts | overflow conditions | values | ops/add | ops/mul | ops/sub | ops/neg | ops/div |
|
||||
* |------------|---------------|---------------------|-------------------|----------------|---------|----------------|---------|---------|
|
||||
* | Signed | 1 | moderate | signed integral | 1 add | 1 mul | 1 sub | 1 neg | - |
|
||||
* | Unsigned | 1 | moderate | unsigned integral | 1 add | 1 mul | 1 sub | 1 neg | - |
|
||||
* | Fractional | 1 | complex | signed decimal | 1 add | 1 mul | 1 sub | 1 neg | 1 mul* |
|
||||
* | Rational | 2 | moderate | signed decimal | 2 muls + 1 sub | 2 muls | 2 muls + 1 sub | 1 neg | 2 muls |
|
||||
*
|
||||
|
||||
@@ -1,231 +0,0 @@
|
||||
use sunscreen_compiler::{
|
||||
circuit,
|
||||
types::{bfv::Unsigned, Cipher},
|
||||
CircuitInput, Compiler, PlainModulusConstraint, Runtime,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn can_add_cipher_plain() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn add(a: Cipher<Unsigned>, b: Unsigned) -> Cipher<Unsigned> {
|
||||
a + b
|
||||
}
|
||||
|
||||
let circuit = Compiler::with_circuit(add)
|
||||
.noise_margin_bits(5)
|
||||
.plain_modulus_constraint(PlainModulusConstraint::Raw(500))
|
||||
.compile()
|
||||
.unwrap();
|
||||
|
||||
let runtime = Runtime::new(&circuit.metadata.params).unwrap();
|
||||
|
||||
let (public, secret) = runtime.generate_keys().unwrap();
|
||||
|
||||
let a = runtime.encrypt(Unsigned::from(15), &public).unwrap();
|
||||
let b = Unsigned::from(5);
|
||||
|
||||
let args: Vec<CircuitInput> = vec![a.into(), b.into()];
|
||||
|
||||
let result = runtime.run(&circuit, args, &public).unwrap();
|
||||
|
||||
let c: Unsigned = runtime.decrypt(&result[0], &secret).unwrap();
|
||||
|
||||
assert_eq!(c, 20.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_add_plain_cipher() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn add(a: Unsigned, b: Cipher<Unsigned>) -> Cipher<Unsigned> {
|
||||
b + a
|
||||
}
|
||||
|
||||
let circuit = Compiler::with_circuit(add)
|
||||
.noise_margin_bits(5)
|
||||
.plain_modulus_constraint(PlainModulusConstraint::Raw(500))
|
||||
.compile()
|
||||
.unwrap();
|
||||
|
||||
let runtime = Runtime::new(&circuit.metadata.params).unwrap();
|
||||
|
||||
let (public, secret) = runtime.generate_keys().unwrap();
|
||||
|
||||
let a = Unsigned::from(5);
|
||||
let b = runtime.encrypt(Unsigned::from(15), &public).unwrap();
|
||||
|
||||
let args: Vec<CircuitInput> = vec![a.into(), b.into()];
|
||||
|
||||
let result = runtime.run(&circuit, args, &public).unwrap();
|
||||
|
||||
let c: Unsigned = runtime.decrypt(&result[0], &secret).unwrap();
|
||||
|
||||
assert_eq!(c, 20.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_add_cipher_literal() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn add(a: Cipher<Unsigned>) -> Cipher<Unsigned> {
|
||||
a + 4
|
||||
}
|
||||
|
||||
let circuit = Compiler::with_circuit(add)
|
||||
.noise_margin_bits(5)
|
||||
.plain_modulus_constraint(PlainModulusConstraint::Raw(500))
|
||||
.compile()
|
||||
.unwrap();
|
||||
|
||||
let runtime = Runtime::new(&circuit.metadata.params).unwrap();
|
||||
|
||||
let (public, secret) = runtime.generate_keys().unwrap();
|
||||
|
||||
let a = runtime.encrypt(Unsigned::from(15), &public).unwrap();
|
||||
let args: Vec<CircuitInput> = vec![a.into()];
|
||||
|
||||
let result = runtime.run(&circuit, args, &public).unwrap();
|
||||
|
||||
let c: Unsigned = runtime.decrypt(&result[0], &secret).unwrap();
|
||||
|
||||
assert_eq!(c, 19.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_add_literal_cipher() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn add(a: Cipher<Unsigned>) -> Cipher<Unsigned> {
|
||||
4 + a
|
||||
}
|
||||
|
||||
let circuit = Compiler::with_circuit(add)
|
||||
.noise_margin_bits(5)
|
||||
.plain_modulus_constraint(PlainModulusConstraint::Raw(500))
|
||||
.compile()
|
||||
.unwrap();
|
||||
|
||||
let runtime = Runtime::new(&circuit.metadata.params).unwrap();
|
||||
|
||||
let (public, secret) = runtime.generate_keys().unwrap();
|
||||
|
||||
let a = runtime.encrypt(Unsigned::from(15), &public).unwrap();
|
||||
let args: Vec<CircuitInput> = vec![a.into()];
|
||||
|
||||
let result = runtime.run(&circuit, args, &public).unwrap();
|
||||
|
||||
let c: Unsigned = runtime.decrypt(&result[0], &secret).unwrap();
|
||||
|
||||
assert_eq!(c, 19.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_mul_cipher_plain() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn add(a: Cipher<Unsigned>, b: Unsigned) -> Cipher<Unsigned> {
|
||||
a * b
|
||||
}
|
||||
|
||||
let circuit = Compiler::with_circuit(add)
|
||||
.noise_margin_bits(5)
|
||||
.plain_modulus_constraint(PlainModulusConstraint::Raw(500))
|
||||
.compile()
|
||||
.unwrap();
|
||||
|
||||
let runtime = Runtime::new(&circuit.metadata.params).unwrap();
|
||||
|
||||
let (public, secret) = runtime.generate_keys().unwrap();
|
||||
|
||||
let a = runtime.encrypt(Unsigned::from(15), &public).unwrap();
|
||||
let b = Unsigned::from(3);
|
||||
|
||||
let args: Vec<CircuitInput> = vec![a.into(), b.into()];
|
||||
|
||||
let result = runtime.run(&circuit, args, &public).unwrap();
|
||||
|
||||
let c: Unsigned = runtime.decrypt(&result[0], &secret).unwrap();
|
||||
|
||||
assert_eq!(c, 45.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_mul_plain_cipher() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn add(a: Unsigned, b: Cipher<Unsigned>) -> Cipher<Unsigned> {
|
||||
a * b
|
||||
}
|
||||
|
||||
let circuit = Compiler::with_circuit(add)
|
||||
.noise_margin_bits(5)
|
||||
.plain_modulus_constraint(PlainModulusConstraint::Raw(500))
|
||||
.compile()
|
||||
.unwrap();
|
||||
|
||||
let runtime = Runtime::new(&circuit.metadata.params).unwrap();
|
||||
|
||||
let (public, secret) = runtime.generate_keys().unwrap();
|
||||
|
||||
let a = Unsigned::from(15);
|
||||
let b = runtime.encrypt(Unsigned::from(3), &public).unwrap();
|
||||
|
||||
let args: Vec<CircuitInput> = vec![a.into(), b.into()];
|
||||
|
||||
let result = runtime.run(&circuit, args, &public).unwrap();
|
||||
|
||||
let c: Unsigned = runtime.decrypt(&result[0], &secret).unwrap();
|
||||
|
||||
assert_eq!(c, 45.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_mul_cipher_literal() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn add(a: Cipher<Unsigned>) -> Cipher<Unsigned> {
|
||||
a * 3
|
||||
}
|
||||
|
||||
let circuit = Compiler::with_circuit(add)
|
||||
.noise_margin_bits(5)
|
||||
.plain_modulus_constraint(PlainModulusConstraint::Raw(500))
|
||||
.compile()
|
||||
.unwrap();
|
||||
|
||||
let runtime = Runtime::new(&circuit.metadata.params).unwrap();
|
||||
|
||||
let (public, secret) = runtime.generate_keys().unwrap();
|
||||
|
||||
let a = runtime.encrypt(Unsigned::from(15), &public).unwrap();
|
||||
|
||||
let args: Vec<CircuitInput> = vec![a.into()];
|
||||
|
||||
let result = runtime.run(&circuit, args, &public).unwrap();
|
||||
|
||||
let c: Unsigned = runtime.decrypt(&result[0], &secret).unwrap();
|
||||
|
||||
assert_eq!(c, 45.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_mul_literal_cipher() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn add(a: Cipher<Unsigned>) -> Cipher<Unsigned> {
|
||||
3 * a
|
||||
}
|
||||
|
||||
let circuit = Compiler::with_circuit(add)
|
||||
.noise_margin_bits(5)
|
||||
.plain_modulus_constraint(PlainModulusConstraint::Raw(500))
|
||||
.compile()
|
||||
.unwrap();
|
||||
|
||||
let runtime = Runtime::new(&circuit.metadata.params).unwrap();
|
||||
|
||||
let (public, secret) = runtime.generate_keys().unwrap();
|
||||
|
||||
let a = runtime.encrypt(Unsigned::from(15), &public).unwrap();
|
||||
|
||||
let args: Vec<CircuitInput> = vec![a.into()];
|
||||
|
||||
let result = runtime.run(&circuit, args, &public).unwrap();
|
||||
|
||||
let c: Unsigned = runtime.decrypt(&result[0], &secret).unwrap();
|
||||
|
||||
assert_eq!(c, 45.into());
|
||||
}
|
||||
@@ -33,27 +33,27 @@ pub fn derive_typename(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
||||
*
|
||||
* # Examples
|
||||
* ```rust
|
||||
* # use sunscreen_compiler::{circuit, types::{bfv::Unsigned, Cipher}, Params, Context};
|
||||
* # use sunscreen_compiler::{circuit, types::{bfv::Signed, Cipher}, Params, Context};
|
||||
*
|
||||
* #[circuit(scheme = "bfv")]
|
||||
* fn multiply_add(
|
||||
* a: Cipher<Unsigned>,
|
||||
* b: Cipher<Unsigned>,
|
||||
* c: Cipher<Unsigned>
|
||||
* ) -> Cipher<Unsigned> {
|
||||
* a: Cipher<Signed>,
|
||||
* b: Cipher<Signed>,
|
||||
* c: Cipher<Signed>
|
||||
* ) -> Cipher<Signed> {
|
||||
* a * b + c
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ```rust
|
||||
* # use sunscreen_compiler::{circuit, types::{bfv::Unsigned, Cipher}, Params, Context};
|
||||
* # use sunscreen_compiler::{circuit, types::{bfv::Signed, Cipher}, Params, Context};
|
||||
*
|
||||
* #[circuit(scheme = "bfv")]
|
||||
* fn multi_out(
|
||||
* a: Cipher<Unsigned>,
|
||||
* b: Cipher<Unsigned>,
|
||||
* c: Cipher<Unsigned>
|
||||
* ) -> (Cipher<Unsigned>, Cipher<Unsigned>) {
|
||||
* a: Cipher<Signed>,
|
||||
* b: Cipher<Signed>,
|
||||
* c: Cipher<Signed>
|
||||
* ) -> (Cipher<Signed>, Cipher<Signed>) {
|
||||
* (a + b, b + c)
|
||||
* }
|
||||
* ```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use sunscreen_compiler::{
|
||||
types::{bfv::Unsigned, Cipher, TypeName},
|
||||
types::{bfv::Signed, Cipher, TypeName},
|
||||
CallSignature, CircuitFn, FrontendCompilation, Params, SchemeType, SecurityLevel, CURRENT_CTX,
|
||||
};
|
||||
use sunscreen_compiler_macros::circuit;
|
||||
@@ -16,8 +16,6 @@ fn get_params() -> Params {
|
||||
}
|
||||
}
|
||||
|
||||
type CipherUnsigned = Cipher<Unsigned>;
|
||||
|
||||
#[test]
|
||||
fn circuit_gets_called() {
|
||||
static mut FOO: u32 = 0;
|
||||
@@ -89,11 +87,11 @@ fn compile_failures() {
|
||||
#[test]
|
||||
fn capture_circuit_input_args() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn circuit_with_args(_a: Unsigned, _b: Unsigned, _c: Unsigned, _d: Unsigned) {}
|
||||
fn circuit_with_args(_a: Signed, _b: Signed, _c: Signed, _d: Signed) {}
|
||||
|
||||
assert_eq!(circuit_with_args.scheme_type(), SchemeType::Bfv);
|
||||
|
||||
let type_name = Unsigned::type_name();
|
||||
let type_name = Signed::type_name();
|
||||
|
||||
let expected_signature = CallSignature {
|
||||
arguments: vec![
|
||||
@@ -116,11 +114,11 @@ fn capture_circuit_input_args() {
|
||||
#[test]
|
||||
fn can_add() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn circuit_with_args(a: CipherUnsigned, b: CipherUnsigned, c: CipherUnsigned) {
|
||||
fn circuit_with_args(a: Cipher<Signed>, b: Cipher<Signed>, c: Cipher<Signed>) {
|
||||
let _ = a + b + c;
|
||||
}
|
||||
|
||||
let type_name = Cipher::<Unsigned>::type_name();
|
||||
let type_name = Cipher::<Signed>::type_name();
|
||||
|
||||
let expected_signature = CallSignature {
|
||||
arguments: vec![type_name.clone(), type_name.clone(), type_name.clone()],
|
||||
@@ -178,12 +176,12 @@ fn can_add() {
|
||||
#[test]
|
||||
fn can_add_plaintext() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn circuit_with_args(a: Cipher<Unsigned>, b: Unsigned) {
|
||||
fn circuit_with_args(a: Cipher<Signed>, b: Signed) {
|
||||
let _ = a + b;
|
||||
}
|
||||
|
||||
let expected_signature = CallSignature {
|
||||
arguments: vec![Cipher::<Unsigned>::type_name(), Unsigned::type_name()],
|
||||
arguments: vec![Cipher::<Signed>::type_name(), Signed::type_name()],
|
||||
returns: vec![],
|
||||
num_ciphertexts: vec![],
|
||||
};
|
||||
@@ -226,11 +224,11 @@ fn can_add_plaintext() {
|
||||
#[test]
|
||||
fn can_mul() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn circuit_with_args(a: CipherUnsigned, b: CipherUnsigned, c: CipherUnsigned) {
|
||||
fn circuit_with_args(a: Cipher<Signed>, b: Cipher<Signed>, c: Cipher<Signed>) {
|
||||
let _ = a * b * c;
|
||||
}
|
||||
|
||||
let type_name = Cipher::<Unsigned>::type_name();
|
||||
let type_name = Cipher::<Signed>::type_name();
|
||||
|
||||
let expected_signature = CallSignature {
|
||||
arguments: vec![type_name.clone(), type_name.clone(), type_name.clone()],
|
||||
@@ -287,11 +285,11 @@ fn can_mul() {
|
||||
#[test]
|
||||
fn can_collect_output() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn circuit_with_args(a: Cipher<Unsigned>, b: CipherUnsigned) -> CipherUnsigned {
|
||||
fn circuit_with_args(a: Cipher<Signed>, b: Cipher<Signed>) -> Cipher<Signed> {
|
||||
a + b * a
|
||||
}
|
||||
|
||||
let type_name = Cipher::<Unsigned>::type_name();
|
||||
let type_name = Cipher::<Signed>::type_name();
|
||||
|
||||
let expected_signature = CallSignature {
|
||||
arguments: vec![type_name.clone(), type_name.clone()],
|
||||
@@ -354,13 +352,13 @@ fn can_collect_output() {
|
||||
fn can_collect_multiple_outputs() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn circuit_with_args(
|
||||
a: Cipher<Unsigned>,
|
||||
b: Cipher<Unsigned>,
|
||||
) -> (Cipher<Unsigned>, Cipher<Unsigned>) {
|
||||
a: Cipher<Signed>,
|
||||
b: Cipher<Signed>,
|
||||
) -> (Cipher<Signed>, Cipher<Signed>) {
|
||||
(a + b * a, a)
|
||||
}
|
||||
|
||||
let type_name = Cipher::<Unsigned>::type_name();
|
||||
let type_name = Cipher::<Signed>::type_name();
|
||||
|
||||
let expected_signature = CallSignature {
|
||||
arguments: vec![type_name.clone(), type_name.clone()],
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
use sunscreen_compiler::{types::bfv::Unsigned, types::Cipher, *};
|
||||
|
||||
type CipherUnsigned = Cipher<Unsigned>;
|
||||
use sunscreen_compiler::{types::bfv::Signed, types::Cipher, *};
|
||||
|
||||
#[test]
|
||||
fn can_encrypt_decrypt() {
|
||||
#[circuit(scheme = "bfv")]
|
||||
fn foo(a: CipherUnsigned, b: CipherUnsigned) -> CipherUnsigned {
|
||||
fn foo(a: Cipher<Signed>, b: Cipher<Signed>) -> Cipher<Signed> {
|
||||
a + b
|
||||
}
|
||||
|
||||
@@ -19,12 +17,12 @@ fn can_encrypt_decrypt() {
|
||||
|
||||
let (public, secret) = runtime.generate_keys().unwrap();
|
||||
|
||||
let a = runtime.encrypt(Unsigned::from(15), &public).unwrap();
|
||||
let b = runtime.encrypt(Unsigned::from(5), &public).unwrap();
|
||||
let a = runtime.encrypt(Signed::from(15), &public).unwrap();
|
||||
let b = runtime.encrypt(Signed::from(5), &public).unwrap();
|
||||
|
||||
let result = runtime.run(&circuit, vec![a, b], &public).unwrap();
|
||||
|
||||
let c: Unsigned = runtime.decrypt(&result[0], &secret).unwrap();
|
||||
let c: Signed = runtime.decrypt(&result[0], &secret).unwrap();
|
||||
|
||||
assert_eq!(c, 20.into());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user