Skip to content

Commit

Permalink
Merge pull request zcash#87 from filecoin-project/feat/por-compound-v…
Browse files Browse the repository at this point in the history
…erify

Make PoRCompound prove/verify work.
  • Loading branch information
porcuquine authored Jul 17, 2018
2 parents da2697d + 02593d9 commit 077bad9
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 49 deletions.
8 changes: 4 additions & 4 deletions src/circuit/drgporep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ mod tests {
}

assert!(cs.is_satisfied(), "constraints not satisfied");
assert_eq!(cs.num_inputs(), 27, "wrong number of inputs");
assert_eq!(cs.num_constraints(), 58126, "wrong number of constraints");
assert_eq!(cs.num_inputs(), 19, "wrong number of inputs");
assert_eq!(cs.num_constraints(), 58118, "wrong number of constraints");

assert_eq!(cs.get_input(0, "ONE"), Fr::one());

Expand Down Expand Up @@ -322,7 +322,7 @@ mod tests {
m,
).expect("failed to synthesize circuit");

assert_eq!(cs.num_inputs(), 27, "wrong number of inputs");
assert_eq!(cs.num_constraints(), 290302, "wrong number of constraints");
assert_eq!(cs.num_inputs(), 19, "wrong number of inputs");
assert_eq!(cs.num_constraints(), 290294, "wrong number of constraints");
}
}
98 changes: 79 additions & 19 deletions src/circuit/por.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ pub struct PoR<'a, E: JubjubEngine> {

pub struct PoRCompound {}

fn challenge_into_auth_path_bits(challenge: usize, leaves: usize) -> Vec<bool> {
let height = (leaves as f64).log2().ceil() as usize;
let mut bits = Vec::new();
let mut n = challenge;
for _ in 0..height {
bits.push(n & 1 == 1);
n >>= 1;
}
bits
}

// can only implment for Bls12 because merklepor is not generic over the engine.
impl<'a> CompoundProof<'a, Bls12, MerklePoR, PoR<'a, Bls12>> for PoRCompound {
fn make_circuit<'b>(
Expand All @@ -41,8 +52,18 @@ impl<'a> CompoundProof<'a, Bls12, MerklePoR, PoR<'a, Bls12>> for PoRCompound {
}
}

fn inputize(pub_inputs: &<MerklePoR as ProofScheme>::PublicInputs) -> Vec<Fr> {
vec![pub_inputs.commitment.into()]
fn inputize(
pub_inputs: &<MerklePoR as ProofScheme>::PublicInputs,
pub_params: &<MerklePoR as ProofScheme>::PublicParams,
) -> Vec<Fr> {
let auth_path_bits = challenge_into_auth_path_bits(pub_inputs.challenge, pub_params.leaves);
let packed_auth_path = multipack::compute_multipacking::<Bls12>(&auth_path_bits);

let mut inputs = Vec::new();
inputs.extend(packed_auth_path);
inputs.push(pub_inputs.commitment.into());

inputs
}
}

Expand All @@ -51,9 +72,11 @@ impl<'a, E: JubjubEngine> Circuit<E> for PoR<'a, E> {
///
/// This circuit expects the following public inputs.
///
/// * [0] - packed version of `value` as bits. (might be more than one Fr)
/// * [1] - packed version of the `is_right` components of the auth_path.
/// * [2] - the merkle root of the tree.
/// * [0] - packed version of the `is_right` components of the auth_path.
/// * [1] - the merkle root of the tree.
///
/// This circuit derives the following private inputs from its fields:
/// * value_num - packed version of `value` as bits. (might be more than one Fr)
///
/// Note: All public inputs must be provided as `E::Fr`.
fn synthesize<CS: ConstraintSystem<E>>(self, cs: &mut CS) -> Result<(), SynthesisError>
Expand All @@ -69,8 +92,6 @@ impl<'a, E: JubjubEngine> Circuit<E> for PoR<'a, E> {
Ok(value.ok_or_else(|| SynthesisError::AssignmentMissing)?)
})?;

value_num.inputize(cs.namespace(|| "value num"))?;

let mut value_bits = value_num.into_bits_le(cs.namespace(|| "value bits"))?;

// sad face, need to pad to make all algorithms the same
Expand Down Expand Up @@ -194,6 +215,7 @@ where
mod tests {
use super::*;
use circuit::test::*;
use compound_proof;
use drgraph::{BucketGraph, Graph};
use fr32::{bytes_into_fr, fr_into_bytes};
use merklepor;
Expand All @@ -204,6 +226,50 @@ mod tests {
use sapling_crypto::jubjub::JubjubBls12;
use util::data_at_node;

#[test]
fn test_compound() {
let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let leaves = 6;
let lambda = 32;
let data: Vec<u8> = (0..leaves)
.flat_map(|_| fr_into_bytes::<Bls12>(&rng.gen()))
.collect();
let graph = BucketGraph::new(leaves, 16);
let tree = graph.merkle_tree(data.as_slice(), lambda).unwrap();

for i in 0..3 {
let public_inputs = merklepor::PublicInputs {
challenge: i,
commitment: tree.root(),
};

let setup_params = compound_proof::SetupParams {
vanilla_params: &merklepor::SetupParams { lambda, leaves },
engine_params: &JubjubBls12::new(),
};
let public_params = PoRCompound::setup(&setup_params).expect("setup failed");

let private_inputs = merklepor::PrivateInputs {
tree: &tree,
leaf: bytes_into_fr::<Bls12>(
data_at_node(
data.as_slice(),
public_inputs.challenge,
public_params.vanilla_params.lambda,
).unwrap(),
).expect("failed to create Fr from node data"),
};

let proof = PoRCompound::prove(&public_params, &public_inputs, &private_inputs)
.expect("failed while proving");

let verified =
PoRCompound::verify(&public_inputs, &public_params.vanilla_params, proof)
.expect("failed while verifying");
assert!(verified);
}
}

#[test]
fn test_por_input_circuit_with_bls12_381() {
let params = &JubjubBls12::new();
Expand Down Expand Up @@ -260,8 +326,8 @@ mod tests {

por.synthesize(&mut cs).unwrap();

assert_eq!(cs.num_inputs(), 4, "wrong number of inputs");
assert_eq!(cs.num_constraints(), 4847, "wrong number of constraints");
assert_eq!(cs.num_inputs(), 3, "wrong number of inputs");
assert_eq!(cs.num_constraints(), 4846, "wrong number of constraints");

let auth_path_bits: Vec<bool> = proof
.proof
Expand All @@ -271,27 +337,21 @@ mod tests {
.collect();
let packed_auth_path = multipack::compute_multipacking::<Bls12>(&auth_path_bits);

let mut expected_inputs = vec![proof.data];
let mut expected_inputs = Vec::new();
expected_inputs.extend(packed_auth_path);
expected_inputs.push(pub_inputs.commitment.into());

assert_eq!(cs.get_input(0, "ONE"), Fr::one(), "wrong input 0");

assert_eq!(
cs.get_input(1, "value num/input variable"),
cs.get_input(1, "packed auth_path/input 0"),
expected_inputs[0],
"wrong data"
);

assert_eq!(
cs.get_input(2, "packed auth_path/input 0"),
expected_inputs[1],
"wrong packed_auth_path"
);

assert_eq!(
cs.get_input(3, "root/input variable"),
expected_inputs[2],
cs.get_input(2, "root/input variable"),
expected_inputs[1],
"wrong root input"
);

Expand Down
46 changes: 24 additions & 22 deletions src/compound_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,48 +9,52 @@ pub struct SetupParams<'a, 'b: 'a, E: JubjubEngine, S: ProofScheme<'a>>
where
<S as ProofScheme<'a>>::SetupParams: 'b,
{
vanilla_params: &'b <S as ProofScheme<'a>>::SetupParams,
pub vanilla_params: &'b <S as ProofScheme<'a>>::SetupParams,
// TODO: would be nice to use a reference, but that requires E::Params to impl Clone or Copy I think
engine_params: E::Params,
pub engine_params: &'a E::Params,
}

pub struct PublicParams<'a, E: JubjubEngine, S: ProofScheme<'a>> {
vanilla_params: S::PublicParams,
engine_params: E::Params,
pub vanilla_params: S::PublicParams,
pub engine_params: &'a E::Params,
}

pub struct Proof<E: JubjubEngine> {
circuit_proof: groth16::Proof<E>,
engine_params: groth16::Parameters<E>,
pub circuit_proof: groth16::Proof<E>,
pub groth_params: groth16::Parameters<E>,
}

pub trait CompoundProof<'a, E: JubjubEngine, S: ProofScheme<'a>, C: Circuit<E>> {
fn setup<'b>(sp: SetupParams<'a, 'b, E, S>) -> Result<PublicParams<'a, E, S>> {
fn setup<'b>(sp: &SetupParams<'a, 'b, E, S>) -> Result<PublicParams<'a, E, S>> {
Ok(PublicParams {
vanilla_params: S::setup(sp.vanilla_params)?,
engine_params: sp.engine_params,
})
}

fn prove(
pub_params: &'a PublicParams<'a, E, S>,
pub_in: S::PublicInputs,
priv_in: S::PrivateInputs,
fn prove<'b>(
pub_params: &'b PublicParams<'a, E, S>,
pub_in: &'b S::PublicInputs,
priv_in: &'b S::PrivateInputs,
) -> Result<Proof<E>> {
let vanilla_proof = S::prove(&pub_params.vanilla_params, &pub_in, &priv_in)?;
let vanilla_proof = S::prove(&pub_params.vanilla_params, pub_in, priv_in)?;

let (groth_proof, groth_params) =
Self::circuit_proof(pub_in, &vanilla_proof, &pub_params.engine_params)?;

Ok(Proof {
circuit_proof: groth_proof,
engine_params: groth_params,
groth_params,
})
}

fn verify(public_inputs: &S::PublicInputs, proof: Proof<E>) -> Result<bool> {
let pvk = groth16::prepare_verifying_key(&proof.engine_params.vk);
let inputs = Self::inputize(public_inputs);
fn verify(
public_inputs: &S::PublicInputs,
public_params: &S::PublicParams,
proof: Proof<E>,
) -> Result<bool> {
let pvk = groth16::prepare_verifying_key(&proof.groth_params.vk);
let inputs = Self::inputize(public_inputs, public_params);

Ok(groth16::verify_proof(
&pvk,
Expand All @@ -60,7 +64,7 @@ pub trait CompoundProof<'a, E: JubjubEngine, S: ProofScheme<'a>, C: Circuit<E>>
}

fn circuit_proof(
pub_in: S::PublicInputs,
pub_in: &S::PublicInputs,
vanilla_proof: &S::Proof,
params: &'a E::Params,
) -> Result<(groth16::Proof<E>, groth16::Parameters<E>)> {
Expand All @@ -69,23 +73,21 @@ pub trait CompoundProof<'a, E: JubjubEngine, S: ProofScheme<'a>, C: Circuit<E>>

// TODO: don't do this, we should store the circuit
let vp = vanilla_proof;
let circuit = Self::make_circuit(&pub_in, &vp, params);

let circuit = Self::make_circuit(&pub_in, &vp, params);
let groth_params = groth16::generate_random_parameters::<E, _, _>(circuit, rng)?;

// FIXME: Don't do this -- either Circuit must implement Copy,
// or generate_random_parameters/generate_parameters must borrow circuit.
let circuit = Self::make_circuit(&pub_in, &vp, params);

let groth_proof = groth16::create_random_proof(circuit, &groth_params, rng)?;

let mut proof_vec = vec![];
groth_proof.write(&mut proof_vec)?;
let gp = groth16::Proof::<E>::read(&proof_vec[..])?;

Ok((gp, groth_params))
}

fn inputize(pub_in: &S::PublicInputs) -> Vec<E::Fr>;
fn inputize(pub_in: &S::PublicInputs, pub_params: &S::PublicParams) -> Vec<E::Fr>;

fn make_circuit(
public_inputs: &S::PublicInputs,
Expand Down
11 changes: 7 additions & 4 deletions src/merklepor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ pub struct PrivateInputs<'a> {
pub type Proof = DataProof;

#[derive(Debug)]
pub struct SetupParams {}
pub struct SetupParams {
pub lambda: usize,
pub leaves: usize,
}

/// Merkle tree based proof of retrievability.
#[derive(Debug, Default)]
Expand All @@ -51,10 +54,10 @@ impl<'a> ProofScheme<'a> for MerklePoR {
type PrivateInputs = PrivateInputs<'a>;
type Proof = Proof;

fn setup(_sp: &SetupParams) -> Result<PublicParams> {
fn setup(sp: &SetupParams) -> Result<PublicParams> {
Ok(PublicParams {
lambda: LAMBDA,
leaves: LEAVES,
lambda: sp.lambda,
leaves: sp.leaves,
})
}

Expand Down

0 comments on commit 077bad9

Please sign in to comment.