Skip to content

Commit 194e6eb

Browse files
authored
Merge pull request #367 from filecoin-project/feat/post-circuit
[WIP] PoSt Circuits
2 parents 838c2de + 4810589 commit 194e6eb

File tree

6 files changed

+820
-3
lines changed

6 files changed

+820
-3
lines changed

storage-proofs/src/bacon_post.rs

+19
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,31 @@ pub struct PrivateInputs<'a, H: 'a + Hasher> {
3535
_h: PhantomData<H>,
3636
}
3737

38+
impl<'a, H: 'a + Hasher> PrivateInputs<'a, H> {
39+
pub fn new(
40+
replicas: &'a [&'a [u8]],
41+
trees: &'a [&'a MerkleTree<H::Domain, H::Function>],
42+
) -> Self {
43+
PrivateInputs {
44+
replicas,
45+
trees,
46+
_h: PhantomData,
47+
}
48+
}
49+
}
50+
3851
/// Bacon-PoSt
3952
/// This is one construction of a Proof-of-Spacetime.
4053
/// It currently only supports proving over a single sector.
4154
#[derive(Clone, Debug)]
4255
pub struct Proof<'a, H: Hasher + 'a, V: Vdf<H::Domain>>(Vec<hvh_post::Proof<'a, H, V>>);
4356

57+
impl<'a, H: Hasher + 'a, V: Vdf<H::Domain>> Proof<'a, H, V> {
58+
pub fn proofs(&self) -> &[hvh_post::Proof<'a, H, V>] {
59+
&self.0
60+
}
61+
}
62+
4463
#[derive(Clone, Debug)]
4564
pub struct BaconPost<H: Hasher, V: Vdf<H::Domain>> {
4665
_t: PhantomData<H>,
+329
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
use bellman::{Circuit, ConstraintSystem, SynthesisError};
2+
// use sapling_crypto::circuit::boolean::Boolean;
3+
// use sapling_crypto::circuit::{num, uint32};
4+
use sapling_crypto::jubjub::JubjubEngine;
5+
6+
use crate::circuit::hvh_post;
7+
// use crate::circuit::pedersen::pedersen_compression_num;
8+
9+
/// This is an instance of the `BACON-PoSt` circuit.
10+
pub struct BaconPost<'a, E: JubjubEngine> {
11+
/// Paramters for the engine.
12+
pub params: &'a E::Params,
13+
14+
// Beacon
15+
// TODO:
16+
// pub beacon_randomness_vec: Vec<Option<E::Fr>>,
17+
// pub challenges_vec: Vec<Vec<Option<E::Fr>>>,
18+
19+
// HVH-PoSt
20+
pub vdf_key: Option<E::Fr>,
21+
pub vdf_ys_vec: Vec<Vec<Option<E::Fr>>>,
22+
pub vdf_xs_vec: Vec<Vec<Option<E::Fr>>>,
23+
pub vdf_sloth_rounds: usize,
24+
pub challenged_leafs_vec_vec: Vec<Vec<Vec<Option<E::Fr>>>>,
25+
pub commitments_vec_vec: Vec<Vec<Vec<Option<E::Fr>>>>,
26+
pub paths_vec_vec: Vec<Vec<Vec<Vec<Option<(E::Fr, bool)>>>>>,
27+
}
28+
29+
// fn extract_post_input<E: JubjubEngine, CS: ConstraintSystem<E>>(
30+
// _cs: &mut CS,
31+
// _params: &E::Params,
32+
// ) -> Result<num::AllocatedNum<E>, SynthesisError> {
33+
// unimplemented!()
34+
// }
35+
36+
// fn derive_challenges<E: JubjubEngine, CS: ConstraintSystem<E>>(
37+
// cs: &mut CS,
38+
// params: &E::Params,
39+
// count: usize,
40+
// t: usize,
41+
// x: Option<&num::AllocatedNum<E>>,
42+
// r: &num::AllocatedNum<E>,
43+
// ) -> Result<Vec<num::AllocatedNum<E>>, SynthesisError> {
44+
// let t_u32 = uint32::UInt32::alloc(cs.namespace(|| "t_u32"), Some(t as u32))?;
45+
// let t_bits = t_u32.into_bits();
46+
// let x_bits = x.map(|x| x.into_bits_le(cs.namespace(|| "x_bits")));
47+
48+
// let mut res = Vec::new();
49+
// for i in 0..count {
50+
// let mut cs = cs.namespace(|| format!("count_{}", i));
51+
// let i_u32 = uint32::UInt32::alloc(cs.namespace(|| "i_u32"), Some(i as u32))?;
52+
53+
// let mut bits: Vec<Boolean> = Vec::new();
54+
55+
// if let Some(x_bits) = x_bits {
56+
// bits.extend(x_bits.as_ref()?);
57+
// }
58+
59+
// bits.extend(r.into_bits_le(cs.namespace(|| "r_bits"))?);
60+
// bits.extend(&t_bits);
61+
// bits.extend(i_u32.into_bits());
62+
63+
// let h =
64+
// pedersen_compression_num(cs.namespace(|| format!("hash_{}", i)), params, &bits[..])?;
65+
// res.push(h);
66+
// }
67+
68+
// Ok(res)
69+
// }
70+
71+
impl<'a, E: JubjubEngine> Circuit<E> for BaconPost<'a, E> {
72+
fn synthesize<CS: ConstraintSystem<E>>(self, cs: &mut CS) -> Result<(), SynthesisError> {
73+
let post_periods_count = self.vdf_ys_vec.len();
74+
75+
assert_eq!(self.vdf_xs_vec.len(), post_periods_count);
76+
assert_eq!(self.challenged_leafs_vec_vec.len(), post_periods_count);
77+
assert_eq!(self.commitments_vec_vec.len(), post_periods_count);
78+
assert_eq!(self.paths_vec_vec.len(), post_periods_count);
79+
// assert_eq!(self.beacon_randomness_vec.len(), post_periods_count);
80+
// assert_eq!(self.challenges_vec.len(), post_periods_count);
81+
82+
// t = 0
83+
{
84+
// let mut cs = cs.namespace(|| "t_0");
85+
// let r = num::AllocatedNum::alloc(cs.namespace(|| "r"), || {
86+
// self.beacon_randomness_vec[0].ok_or_else(|| SynthesisError::AssignmentMissing)
87+
// })?;
88+
89+
// let challenges = derive_challenges(
90+
// cs.namespace(|| "derive_challenge"),
91+
// self.params,
92+
// 0,
93+
// None,
94+
// &r,
95+
// )?;
96+
// for (actual, expected) in challenges.iter().zip(self.challenges_vec[0].iter()) {
97+
// let mut cs = cs.namespace(|| format!("challenge_check_{}", i));
98+
99+
// let expected_num = num::AllocatedNum::alloc(cs.namespace(|| "expected"), || {
100+
// expected.ok_or_else(|| SynthesisError::AssignmentMissing)
101+
// })?;
102+
103+
// constraint::equal(&mut cs, || "challenge_equality", actual, expected_num);
104+
// }
105+
106+
hvh_post::hvh_post(
107+
&mut cs.namespace(|| "hvh_post"),
108+
self.params,
109+
self.vdf_key,
110+
&self.vdf_ys_vec[0],
111+
&self.vdf_xs_vec[0],
112+
self.vdf_sloth_rounds,
113+
&self.challenged_leafs_vec_vec[0],
114+
&self.commitments_vec_vec[0],
115+
&self.paths_vec_vec[0],
116+
)?;
117+
}
118+
119+
// t = 1..periods_count
120+
for t in 1..post_periods_count {
121+
let mut cs = cs.namespace(|| format!("t_{}", t));
122+
123+
// let r = num::AllocatedNum::alloc(cs.namespace(|| "r"), || {
124+
// self.beacon_randomness_vec[t].ok_or_else(|| SynthesisError::AssignmentMissing)
125+
// })?;
126+
127+
// let x = extract_post_input(cs.namespace(|| "extract_post_input"), self.params)?;
128+
129+
// let challenges = derive_challenges(
130+
// cs.namespace(|| "derive_challenge"),
131+
// self.params,
132+
// t,
133+
// Some(&x),
134+
// &r,
135+
// )?;
136+
// for (actual, expected) in challenges.iter().zip(self.challenges_vec[t].iter()) {
137+
// let mut cs = cs.namespace(|| format!("challenge_check_{}", i));
138+
139+
// let expected_num = num::AllocatedNum::alloc(cs.namespace(|| "expected"), || {
140+
// expected.ok_or_else(|| SynthesisError::AssignmentMissing)
141+
// })?;
142+
143+
// constraint::equal(&mut cs, || "challenge_equality", actual, expected_num);
144+
// }
145+
146+
hvh_post::hvh_post(
147+
&mut cs.namespace(|| "hvh_post"),
148+
self.params,
149+
self.vdf_key,
150+
&self.vdf_ys_vec[t],
151+
&self.vdf_xs_vec[t],
152+
self.vdf_sloth_rounds,
153+
&self.challenged_leafs_vec_vec[t],
154+
&self.commitments_vec_vec[t],
155+
&self.paths_vec_vec[t],
156+
)?;
157+
}
158+
159+
Ok(())
160+
}
161+
}
162+
163+
#[cfg(test)]
164+
mod tests {
165+
use super::*;
166+
167+
use pairing::bls12_381::*;
168+
use pairing::Field;
169+
use rand::{Rng, SeedableRng, XorShiftRng};
170+
use sapling_crypto::jubjub::JubjubBls12;
171+
172+
use crate::bacon_post;
173+
use crate::circuit::test::*;
174+
use crate::drgraph::{new_seed, BucketGraph, Graph};
175+
use crate::fr32::fr_into_bytes;
176+
use crate::hasher::pedersen::*;
177+
use crate::hvh_post;
178+
//use crate::proof::ProofScheme;
179+
use crate::vdf_sloth;
180+
181+
#[test]
182+
fn test_bacon_post_circuit_with_bls12_381() {
183+
let params = &JubjubBls12::new();
184+
let rng = &mut XorShiftRng::from_seed([0x3dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
185+
186+
let lambda = 32;
187+
188+
let sp = bacon_post::SetupParams::<PedersenDomain, vdf_sloth::Sloth> {
189+
setup_params_hvh_post: hvh_post::SetupParams::<PedersenDomain, vdf_sloth::Sloth> {
190+
challenge_count: 4,
191+
sector_size: 256 * lambda,
192+
post_epochs: 3,
193+
setup_params_vdf: vdf_sloth::SetupParams {
194+
key: rng.gen(),
195+
rounds: 1,
196+
},
197+
sectors_count: 2,
198+
},
199+
post_periods_count: 3,
200+
};
201+
202+
let mut bacon_post = bacon_post::BaconPost::<PedersenHasher, vdf_sloth::Sloth>::default();
203+
204+
let pub_params = bacon_post.setup(&sp).unwrap();
205+
206+
let data0: Vec<u8> = (0..256)
207+
.flat_map(|_| fr_into_bytes::<Bls12>(&rng.gen()))
208+
.collect();
209+
let data1: Vec<u8> = (0..256)
210+
.flat_map(|_| fr_into_bytes::<Bls12>(&rng.gen()))
211+
.collect();
212+
213+
let graph0 = BucketGraph::<PedersenHasher>::new(256, 5, 0, new_seed());
214+
let tree0 = graph0.merkle_tree(data0.as_slice()).unwrap();
215+
let graph1 = BucketGraph::<PedersenHasher>::new(256, 5, 0, new_seed());
216+
let tree1 = graph1.merkle_tree(data1.as_slice()).unwrap();
217+
218+
let pub_inputs = bacon_post::PublicInputs {
219+
commitments: vec![tree0.root(), tree1.root()],
220+
};
221+
let replicas = [&data0[..], &data1[..]];
222+
let trees = [&tree0, &tree1];
223+
let priv_inputs = bacon_post::PrivateInputs::new(&replicas[..], &trees[..]);
224+
225+
let proof = bacon_post
226+
.prove(&pub_params, &pub_inputs, &priv_inputs)
227+
.unwrap();
228+
229+
assert!(bacon_post.verify(&pub_params, &pub_inputs, &proof).unwrap());
230+
231+
// actual circuit test
232+
233+
let vdf_ys_vec = proof
234+
.proofs()
235+
.iter()
236+
.map(|proof| {
237+
proof
238+
.ys
239+
.iter()
240+
.map(|y| Some(y.clone().into()))
241+
.collect::<Vec<_>>()
242+
})
243+
.collect::<Vec<_>>();
244+
let vdf_xs_vec = proof
245+
.proofs()
246+
.iter()
247+
.map(|proof| {
248+
proof
249+
.proofs_porep
250+
.iter()
251+
.take(vdf_ys_vec[0].len())
252+
.map(|p| Some(hvh_post::extract_vdf_input::<PedersenHasher>(p).into()))
253+
.collect()
254+
})
255+
.collect::<Vec<_>>();
256+
257+
let mut paths_vec_vec = Vec::new();
258+
let mut challenged_leafs_vec_vec = Vec::new();
259+
let mut commitments_vec_vec = Vec::new();
260+
261+
for p in proof.proofs() {
262+
let mut paths_vec = Vec::new();
263+
let mut challenged_leafs_vec = Vec::new();
264+
let mut commitments_vec = Vec::new();
265+
266+
for proof_porep in &p.proofs_porep {
267+
// -- paths
268+
paths_vec.push(
269+
proof_porep
270+
.paths()
271+
.iter()
272+
.map(|p| {
273+
p.iter()
274+
.map(|v| Some((v.0.into(), v.1)))
275+
.collect::<Vec<_>>()
276+
})
277+
.collect::<Vec<_>>(),
278+
);
279+
280+
// -- challenged leafs
281+
challenged_leafs_vec.push(
282+
proof_porep
283+
.leafs()
284+
.iter()
285+
.map(|l| Some((**l).into()))
286+
.collect::<Vec<_>>(),
287+
);
288+
289+
// -- commitments
290+
commitments_vec.push(
291+
proof_porep
292+
.commitments()
293+
.iter()
294+
.map(|c| Some((**c).into()))
295+
.collect::<Vec<_>>(),
296+
);
297+
}
298+
299+
paths_vec_vec.push(paths_vec);
300+
challenged_leafs_vec_vec.push(challenged_leafs_vec);
301+
commitments_vec_vec.push(commitments_vec);
302+
}
303+
304+
let mut cs = TestConstraintSystem::<Bls12>::new();
305+
306+
let instance = BaconPost {
307+
params,
308+
// beacon_randomness_vec,
309+
// challenges_vec,
310+
vdf_key: Some(pub_params.pub_params_hvh_post.pub_params_vdf.key.into()),
311+
vdf_xs_vec,
312+
vdf_ys_vec,
313+
vdf_sloth_rounds: pub_params.pub_params_hvh_post.pub_params_vdf.rounds,
314+
challenged_leafs_vec_vec,
315+
paths_vec_vec,
316+
commitments_vec_vec,
317+
};
318+
319+
instance
320+
.synthesize(&mut cs)
321+
.expect("failed to synthesize circuit");
322+
323+
assert!(cs.is_satisfied(), "constraints not satisfied");
324+
325+
assert_eq!(cs.num_inputs(), 115, "wrong number of inputs");
326+
assert_eq!(cs.num_constraints(), 398196, "wrong number of constraints");
327+
assert_eq!(cs.get_input(0, "ONE"), Fr::one());
328+
}
329+
}

0 commit comments

Comments
 (0)