|
| 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