Serialization
Serializing works just like unlinked proofs, but for the sake of completeness, below is an example of serialization and deserialization of a linked proof:
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<(), Box<dyn std::error::Error>> { let app = Compiler::new() .fhe_program(increase_by_factor) .zkp_backend::<BulletproofsBackend>() .zkp_program(is_greater_than_one) .compile()?; let runtime = FheZkpRuntime::new(app.params(), &BulletproofsBackend::new())?; let (public_key, private_key) = runtime.generate_keys()?; let mut builder = runtime.linkedproof_builder(); let (ct, link) = builder.encrypt_returning_link(&Signed::from(2), &public_key)?; let proof = builder .zkp_program(app.get_zkp_program(is_greater_than_one).unwrap())? .linked_input(link) .build()?; let serialized_proof = bincode::serialize(&proof)?; let deserialized_proof: LinkedProof = bincode::deserialize(&serialized_proof)?; Ok(()) }