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(())
}