Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a84b69b
Misc doc fixes
samtay Jun 26, 2023
a91e07b
Fix sunscreen zkp exports
samtay Jun 26, 2023
ff8e3be
Fix broken api doc reference
samtay Jun 27, 2023
e60ee45
Add starter zkp example
samtay Jun 27, 2023
523a611
Use ZkpRuntime::new in sudoku example
samtay Jun 27, 2023
7cbadbd
Use ? over unwrap in zkp examples
samtay Jun 27, 2023
c99f1e9
Refactor pattern matching
samtay Jun 28, 2023
a6ddd6f
Disallow `mut` args in fhe/zkp programs
samtay Jun 28, 2023
2def1ed
Play around with allowing cipher|plain values
samtay Jun 29, 2023
b06c848
Allow user-declared plain|cipher values
samtay Jun 29, 2023
b02dc8e
Refactor array::output()
samtay Jun 29, 2023
a7358fd
More targeted compiler error messages on invalid return values
samtay Jun 29, 2023
1c179ed
Add option for var.into() rather than fhe_out(var)
samtay Jun 29, 2023
ee1455d
Fix incorrect macro invocation
samtay Jun 29, 2023
b48f870
Add trait for inserting const as plaintext
samtay Jun 29, 2023
5966444
Impl all arithmetic operations for indeterminate nodes
samtay Jun 29, 2023
2c0f69d
Offer an `fhe_var!` macro
samtay Jun 30, 2023
bfa6e47
Offer a zkp_var! macro
samtay Jun 30, 2023
bd70632
Offer a (safe) debug impl for zkp program nodes
samtay Jun 30, 2023
1d7e374
Fix tests
samtay Jun 30, 2023
f0cdf89
Add test for fhe_var!
samtay Jun 30, 2023
ae7cb9e
Simplify tf out of sudoku
samtay Jun 30, 2023
1656ec8
Simplify fhe input() codegen
samtay Jun 30, 2023
77c1980
Marginally better compiler error messages on invalid fhe program arg …
samtay Jun 30, 2023
c593f74
Fix error for fhe program argument attributes
samtay Jun 30, 2023
6cb0de3
Throw appropriate compiler error on generics
samtay Jun 30, 2023
c201db8
Silence clippy warnings in generated code
samtay Jun 30, 2023
33a24e8
Fixup quote_spanned invocations
samtay Jun 30, 2023
b0f3caf
Automatically call `.into()` on fhe prog return values
samtay Jun 30, 2023
b49b4d4
Factor fhe_program_impl
samtay Jun 30, 2023
3410197
Further factor fhe_program_impl
samtay Jun 30, 2023
72797be
Fix doctests
samtay Jun 30, 2023
13f9a34
Fix clippy warnings
samtay Jun 30, 2023
883c771
Merge remote-tracking branch 'origin/main' into samtay/hackathon
samtay Jun 30, 2023
e749c3e
Remove TODOs
samtay Jun 30, 2023
a5e3670
Add missing example runs to CI
samtay Jun 30, 2023
ca31c91
Oops: fix 232 > 64
samtay Jun 30, 2023
e63c44a
Allow arbitrary expressions in fhe_var!
samtay Jun 30, 2023
3be1f39
Use custom "into" to support impls on []
samtay Jul 2, 2023
16a6277
Support explicit #[private] params
samtay Jul 3, 2023
2e6a081
Remove `backend = "bulletproofs"` attribute
samtay Jul 3, 2023
863e052
Address PR reveiw
samtay Jul 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,22 @@ jobs:
# Run our non-interactive examples and assert the complete without error
- name: Verify examples (amm)
run: cargo run --release --bin amm
- name: Verify examples (bigint)
run: cargo run --release --bin bigint
- name: Verify examples (chi_sq)
run: cargo run --release --bin chi_sq
- name: Verify examples (simple_multiply)
run: cargo run --release --bin simple_multiply
- name: Verify examples (dot_prod)
run: cargo run --release --bin dot_prod
- name: Verify examples (mean_variance)
run: cargo run --release --bin mean_variance
- name: Verify examples (ordering_zkp)
run: cargo run --release --bin ordering_zkp
- name: Verify examples (pir)
run: cargo run --release --bin pir
- name: Verify examples (simple_multiply)
run: cargo run --release --bin simple_multiply
- name: Verify examples (sudoku_zkp)
run: cargo run --release --bin sudoku_zkp
- name: Build sunscreen and bincode
run: cargo build --release --package sunscreen --package bincode
- name: Build mdBook
Expand Down
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion benchmarks/bfv_zkp/src/bfv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ fn div_round_bigint<const N: usize>(a: BigInt<N>, b: BigInt<N>) -> BigInt<N> {

type BfvPoly<F> = RnsRingPolynomial<F, POLY_DEGREE, 1>;

#[zkp_program(backend = "bulletproofs")]
#[zkp_program]
fn prove_enc<F: BackendField>(
m: BfvPoly<F>,
e_1: BfvPoly<F>,
Expand Down
7 changes: 7 additions & 0 deletions examples/ordering_zkp/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "ordering_zkp"
version = "0.1.0"
edition = "2021"

[dependencies]
sunscreen = { path = "../../sunscreen", features = ["bulletproofs"] }
79 changes: 79 additions & 0 deletions examples/ordering_zkp/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use sunscreen::{
types::zkp::{ConstrainCmp, NativeField},
zkp_program, BackendField, BulletproofsBackend, Compiler, Error, ZkpBackend, ZkpRuntime,
};

#[zkp_program]
fn greater_than<F: BackendField>(a: NativeField<F>, #[constant] b: NativeField<F>) {
a.constrain_gt_bounded(b, 32)
}

type BPField = NativeField<<BulletproofsBackend as ZkpBackend>::Field>;

fn main() -> Result<(), Error> {
let app = Compiler::new()
.zkp_backend::<BulletproofsBackend>()
.zkp_program(greater_than)
.compile()?;

let greater_than_zkp = app.get_zkp_program(greater_than).unwrap();

let runtime = ZkpRuntime::new(&BulletproofsBackend::new())?;

let amount = BPField::from(232);
let threshold = BPField::from(64);

// Prove that amount > threshold

let proof = runtime.prove(greater_than_zkp, vec![threshold], vec![], vec![amount])?;

runtime.verify(greater_than_zkp, &proof, vec![threshold], vec![])?;

Ok(())
}

#[cfg(test)]
mod tests {
use super::*;

fn run_test(amount: BPField, threshold: BPField, should_succeed: bool) {
let app = Compiler::new()
.zkp_backend::<BulletproofsBackend>()
.zkp_program(greater_than)
.compile()
.unwrap();
let gt_zkp = app.get_zkp_program(greater_than).unwrap();
let runtime = ZkpRuntime::new(&BulletproofsBackend::new()).unwrap();
let proof = runtime.prove(gt_zkp, vec![threshold], vec![], vec![amount]);
if !should_succeed {
assert!(proof.is_err());
} else {
assert!(runtime
.verify(gt_zkp, &proof.unwrap(), vec![threshold], vec![])
.is_ok())
}
}

#[test]
fn test_gt() {
run_test(1.into(), 0.into(), true);
run_test(100.into(), 0.into(), true);
run_test(100.into(), 99.into(), true);
run_test(u32::MAX.into(), 0.into(), true);
}

#[test]
fn test_le() {
run_test(0.into(), 1.into(), false);
}

#[test]
fn test_eq() {
run_test(1.into(), 1.into(), false);
}

#[test]
fn test_bounded_failure() {
run_test(u64::MAX.into(), 0.into(), false);
}
}
47 changes: 24 additions & 23 deletions examples/sudoku_zkp/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
use sunscreen::{
types::zkp::NativeField, zkp_program, BackendField, BulletproofsBackend, Compiler, Runtime,
ZkpBackend, ZkpProgramInput,
types::zkp::NativeField, zkp_program, zkp_var, BackendField, BulletproofsBackend, Compiler,
Error, ZkpBackend, ZkpProgramInput, ZkpRuntime,
};

type BPField = NativeField<<BulletproofsBackend as ZkpBackend>::Field>;

fn main() {
fn main() -> Result<(), Error> {
let app = Compiler::new()
.zkp_backend::<BulletproofsBackend>()
.zkp_program(sudoku_proof)
.compile()
.unwrap();
.compile()?;

let prog = app.get_zkp_program(sudoku_proof).unwrap();

let runtime = Runtime::new_zkp(&BulletproofsBackend::new()).unwrap();
let runtime = ZkpRuntime::new(&BulletproofsBackend::new())?;

let ex_puzzle = [
[0, 7, 0, 0, 2, 0, 0, 4, 6],
Expand Down Expand Up @@ -44,34 +43,36 @@ fn main() {

let cons: Vec<ZkpProgramInput> = vec![ex_puzzle.map(|a| a.map(BPField::from)).into()];

let proof = runtime.prove(prog, cons.clone(), vec![], board).unwrap();
let proof = runtime.prove(prog, cons.clone(), vec![], board)?;

let verify = runtime.verify(prog, &proof, cons, vec![]);
runtime.verify(prog, &proof, cons, vec![])?;

assert!(verify.is_ok());
Ok(())
}

#[zkp_program(backend = "bulletproofs")]
#[zkp_program]
fn sudoku_proof<F: BackendField>(
#[constant] constraints: [[NativeField<F>; 9]; 9],
board: [[NativeField<F>; 9]; 9],
) {
fn assert_unique_numbers<F: BackendField>(arr: [ProgramNode<NativeField<F>>; 9]) {
let zero = zkp_var!(0);

let assert_unique_numbers = |squares| {
for i in 1..=9 {
let mut circuit = NativeField::<F>::from(1).into_program_node();
for a in arr {
circuit = circuit * (NativeField::<F>::from(i).into_program_node() - a);
let mut circuit = zkp_var!(1);
for s in squares {
circuit = circuit * (zkp_var!(i) - s);
}
circuit.constrain_eq(NativeField::<F>::from(0));
circuit.constrain_eq(zero);
}
}
};

// Proves that the board matches up with the puzzle where applicable
let zero = NativeField::<F>::from(0).into_program_node();

for i in 0..9 {
for j in 0..9 {
let square = board[i][j].into_program_node();
let constraint = constraints[i][j].into_program_node();
let square = board[i][j];
let constraint = constraints[i][j];
(constraint * (constraint - square)).constrain_eq(zero);
}
}
Expand All @@ -94,7 +95,7 @@ fn sudoku_proof<F: BackendField>(

let square = rows.iter().map(|s| &s[(j * 3)..(j * 3 + 3)]);

let flattened_sq: [ProgramNode<NativeField<F>>; 9] = square
let flattened_sq = square
.flatten()
.copied()
.collect::<Vec<_>>()
Expand All @@ -120,7 +121,7 @@ mod tests {

let prog = app.get_zkp_program(sudoku_proof).unwrap();

let runtime = Runtime::new_zkp(&BulletproofsBackend::new()).unwrap();
let runtime = ZkpRuntime::new(&BulletproofsBackend::new()).unwrap();

let ex_puzzle = [
[0, 7, 0, 0, 2, 0, 0, 4, 6],
Expand Down Expand Up @@ -167,7 +168,7 @@ mod tests {

let prog = app.get_zkp_program(sudoku_proof).unwrap();

let runtime = Runtime::new_zkp(&BulletproofsBackend::new()).unwrap();
let runtime = ZkpRuntime::new(&BulletproofsBackend::new()).unwrap();

let ex_puzzle = [
[0, 7, 0, 0, 2, 0, 0, 4, 6],
Expand Down Expand Up @@ -212,7 +213,7 @@ mod tests {

let prog = app.get_zkp_program(sudoku_proof).unwrap();

let runtime = Runtime::new_zkp(&BulletproofsBackend::new()).unwrap();
let runtime = ZkpRuntime::new(&BulletproofsBackend::new()).unwrap();

let ex_puzzle = [[0; 9]; 9];

Expand Down
4 changes: 3 additions & 1 deletion sunscreen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ env_logger = "0.10.0"
float-cmp = "0.9.0"
lazy_static = "1.4.0"
proptest = "1.1.0"
sunscreen_zkp_backend = { path = "../sunscreen_zkp_backend", features = ["bulletproofs"] }
sunscreen_zkp_backend = { path = "../sunscreen_zkp_backend", features = [
"bulletproofs",
] }
sunscreen_compiler_common = { path = "../sunscreen_compiler_common" }
serde_json = "1.0.74"

Expand Down
8 changes: 4 additions & 4 deletions sunscreen/benches/fractional_range_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ fn make_fractional_value(bits: &[i8]) -> [[BPField; 8]; 64] {
/// the number of decimal places in the fractional amount. This is
/// basically free, so we don't need to time it here.
fn unshield_tx_fractional_range_proof(_c: &mut Criterion) {
#[zkp_program(backend = "bulletproofs")]
#[zkp_program]
/**
* Proves the 0 < a <= b and a == c
*/
Expand Down Expand Up @@ -153,7 +153,7 @@ fn unshield_tx_fractional_range_proof(_c: &mut Criterion) {
/// in the SDLP, which reduces the number of circuit inputs. However, this proof is
/// orders of magnitude faster than the SDLP so 🤷‍♀️.
fn private_tx_fractional_range_proof(_c: &mut Criterion) {
#[zkp_program(backend = "bulletproofs")]
#[zkp_program]
/**
* Proves the 0 < a <= b and a == c
*/
Expand Down Expand Up @@ -228,7 +228,7 @@ fn private_tx_fractional_range_proof(_c: &mut Criterion) {
/// * a is the submitted value under a given user's key.
/// * b is the maximum value encrypted under the same user's key.
fn mean_variance_fractional_range_proof(_c: &mut Criterion) {
#[zkp_program(backend = "bulletproofs")]
#[zkp_program]
/**
* Proves the 0 < a <= b and a == c
*/
Expand Down Expand Up @@ -291,7 +291,7 @@ fn mean_variance_fractional_range_proof(_c: &mut Criterion) {
///
/// * a_0, a_1, a_2 are submitted value under a given user's key.
fn chi_sq_fractional_range_proof(_c: &mut Criterion) {
#[zkp_program(backend = "bulletproofs")]
#[zkp_program]
/**
* Proves the 0 < a <= b and a == c
*/
Expand Down
6 changes: 3 additions & 3 deletions sunscreen/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ mod tests {

#[test]
fn fhe_zkp_program_yields_fhezkp_compiler() {
#[zkp_program(backend = "bulletproofs")]
#[zkp_program]
fn kitty<F: BackendField>() {}

#[fhe_program(scheme = "bfv")]
Expand Down Expand Up @@ -619,7 +619,7 @@ mod tests {

#[test]
fn compiling_zkp_program_yields_zkp_application() {
#[zkp_program(backend = "bulletproofs")]
#[zkp_program]
fn kitty<F: BackendField>() {}

let app = GenericCompiler::new()
Expand All @@ -633,7 +633,7 @@ mod tests {

#[test]
fn compiling_fhe_and_zkp_program_yields_fhezkp_application() {
#[zkp_program(backend = "bulletproofs")]
#[zkp_program]
fn kitty<F: BackendField>(_a: NativeField<F>) {}

#[fhe_program(scheme = "bfv")]
Expand Down
14 changes: 14 additions & 0 deletions sunscreen/src/types/bfv/batched.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,20 @@ impl<const LANES: usize> GraphCipherMul for Batched<LANES> {
}
}

impl<const LANES: usize> GraphCipherInsert for Batched<LANES> {
type Lit = i64;
type Val = Self;

fn graph_cipher_insert(lit: Self::Lit) -> FheProgramNode<Self::Val> {
with_fhe_ctx(|ctx| {
let lit = Self::from(lit).try_into_plaintext(&ctx.data).unwrap();
let l = ctx.add_plaintext_literal(lit.inner);

FheProgramNode::new(&[l])
})
}
}

impl<const LANES: usize> GraphCipherConstMul for Batched<LANES> {
type Left = Self;
type Right = i64;
Expand Down
20 changes: 17 additions & 3 deletions sunscreen/src/types/bfv/fractional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use crate::{
types::{
ops::{
GraphCipherAdd, GraphCipherConstAdd, GraphCipherConstDiv, GraphCipherConstMul,
GraphCipherConstSub, GraphCipherMul, GraphCipherNeg, GraphCipherPlainAdd,
GraphCipherPlainMul, GraphCipherPlainSub, GraphCipherSub, GraphConstCipherSub,
GraphPlainCipherSub,
GraphCipherConstSub, GraphCipherInsert, GraphCipherMul, GraphCipherNeg,
GraphCipherPlainAdd, GraphCipherPlainMul, GraphCipherPlainSub, GraphCipherSub,
GraphConstCipherSub, GraphPlainCipherSub,
},
Cipher,
},
Expand Down Expand Up @@ -236,6 +236,20 @@ impl<const INT_BITS: usize> GraphCipherPlainAdd for Fractional<INT_BITS> {
}
}

impl<const INT_BITS: usize> GraphCipherInsert for Fractional<INT_BITS> {
type Lit = f64;
type Val = Self;

fn graph_cipher_insert(lit: Self::Lit) -> FheProgramNode<Self::Val> {
with_fhe_ctx(|ctx| {
let lit = Self::from(lit).try_into_plaintext(&ctx.data).unwrap();
let lit = ctx.add_plaintext_literal(lit.inner);

FheProgramNode::new(&[lit])
})
}
}

impl<const INT_BITS: usize> GraphCipherConstAdd for Fractional<INT_BITS> {
type Left = Fractional<INT_BITS>;
type Right = f64;
Expand Down
Loading