Short discrete log proof
If you only have to prove that ciphertexts are well formed and within certain
noise bounds, and you don't have any arbitrary properties to prove about the
encrypted values, you can also use an Sdlp on its own, rather than a full
LinkedProof and ZKP program.
use sunscreen::{ bulletproofs::BulletproofsBackend, fhe_program, linked::{LinkedProof, LinkedProofBuilder}, types::{ bfv::Signed, zkp::{ AsFieldElement, BfvSigned, BulletproofsField, ConstrainCmp, ConstrainFresh, Field, FieldSpec, }, Cipher, }, zkp_program, zkp_var, Ciphertext, CompiledFheProgram, CompiledZkpProgram, Compiler, Error, FheProgramInput, FheRuntime, FheZkpApplication, FheZkpRuntime, Params, PrivateKey, PublicKey, Result, ZkpProgramInput, }; #[fhe_program(scheme = "bfv")] fn increase_by_factor(x: Signed, scale: Cipher<Signed>) -> Cipher<Signed> { x * scale } #[zkp_program] fn is_greater_than_one<F: FieldSpec>(#[linked] scale: BfvSigned<F>) { scale .into_field_elem() .constrain_gt_bounded(zkp_var!(1), 64); } fn main() -> Result<(), Error> { let app = Compiler::new() .fhe_program(increase_by_factor) .compile()?; let runtime = FheRuntime::new(app.params())?; let (public_key, private_key) = runtime.generate_keys()?; let mut proof_builder = runtime.sdlp_builder(); let ct = proof_builder.encrypt(&Signed::from(2), &public_key)?; let proof = proof_builder.build()?; let mut verify_builder = runtime.sdlp_verification_builder(); verify_builder.encrypt(&ct, &public_key)?; verify_builder.proof(proof).verify()?; Ok(()) }