use bellperson::{ groth16, util_cs::{metric_cs::MetricCS, test_cs::TestConstraintSystem}, Circuit, }; use filecoin_hashers::{poseidon::PoseidonHasher, Domain, HashFunction, Hasher}; use generic_array::typenum::{U0, U2, U4, U8}; use pretty_assertions::assert_eq; use rand::SeedableRng; use rand_xorshift::XorShiftRng; use storage_proofs_core::{ api_version::ApiVersion, compound_proof::{self, CompoundProof}, merkle::{generate_tree, get_base_tree_count, LCTree, MerkleTreeTrait}, multi_proof::MultiProof, util::NODE_SIZE, TEST_SEED, }; use storage_proofs_post::fallback::{ ChallengeRequirements, FallbackPoStCompound, PrivateInputs, PrivateSector, PublicInputs, PublicSector, SetupParams, }; use tempfile::tempdir; #[ignore] #[test] fn test_fallback_post_compound_poseidon_single_partition_base_8() { fallback_post::>(15, 15, 1, ApiVersion::V1_0_0); fallback_post::>(15, 15, 1, ApiVersion::V1_1_0); } #[ignore] #[test] fn test_fallback_post_compound_poseidon_single_partition_sub_8_4() { fallback_post::>(3, 3, 1, ApiVersion::V1_0_0); fallback_post::>(3, 3, 1, ApiVersion::V1_1_0); } #[ignore] #[test] fn test_fallback_post_compound_poseidon_single_partition_top_8_4_2() { fallback_post::>(3, 3, 1, ApiVersion::V1_0_0); fallback_post::>(3, 3, 1, ApiVersion::V1_1_0); } #[ignore] #[test] fn test_fallback_post_compound_poseidon_single_partition_smaller_base_8() { fallback_post::>(2, 3, 1, ApiVersion::V1_0_0); fallback_post::>(2, 3, 1, ApiVersion::V1_1_0); } #[ignore] #[test] fn test_fallback_post_compound_poseidon_two_partitions_base_8() { fallback_post::>(4, 2, 2, ApiVersion::V1_0_0); fallback_post::>(4, 2, 2, ApiVersion::V1_1_0); } #[ignore] #[test] fn test_fallback_post_compound_poseidon_two_partitions_smaller_base_8() { fallback_post::>(5, 3, 2, ApiVersion::V1_0_0); fallback_post::>(5, 3, 2, ApiVersion::V1_1_0); } fn fallback_post( total_sector_count: usize, sector_count: usize, partitions: usize, api_version: ApiVersion, ) where Tree::Store: 'static, { let rng = &mut XorShiftRng::from_seed(TEST_SEED); let leaves = 64 * get_base_tree_count::(); let sector_size = (leaves * NODE_SIZE) as u64; let randomness = ::Domain::random(rng); let prover_id = ::Domain::random(rng); let challenge_count = 2; let setup_params = compound_proof::SetupParams { vanilla_params: SetupParams { sector_size, challenge_count, sector_count, api_version, }, partitions: Some(partitions), priority: false, }; let temp_dir = tempdir().unwrap(); let temp_path = temp_dir.path(); let mut pub_sectors = Vec::new(); let mut priv_sectors = Vec::new(); let mut trees = Vec::new(); for _i in 0..total_sector_count { let (_data, tree) = generate_tree::(rng, leaves, Some(temp_path.to_path_buf())); trees.push(tree); } for (i, tree) in trees.iter().enumerate() { let comm_c = ::Domain::random(rng); let comm_r_last = tree.root(); priv_sectors.push(PrivateSector { tree, comm_c, comm_r_last, }); let comm_r = ::Function::hash2(&comm_c, &comm_r_last); pub_sectors.push(PublicSector { id: (i as u64).into(), comm_r, }); } let pub_params = FallbackPoStCompound::::setup(&setup_params).expect("setup failed"); let pub_inputs = PublicInputs { randomness, prover_id, sectors: pub_sectors, k: None, }; let priv_inputs = PrivateInputs:: { sectors: &priv_sectors, }; // Use this to debug differences between blank and regular circuit generation. { let circuits = FallbackPoStCompound::circuit_for_test_all(&pub_params, &pub_inputs, &priv_inputs) .unwrap(); let blank_circuit = FallbackPoStCompound::::blank_circuit(&pub_params.vanilla_params); let mut cs_blank = MetricCS::new(); blank_circuit .synthesize(&mut cs_blank) .expect("failed to synthesize"); let a = cs_blank.pretty_print_list(); for (circuit1, _inputs) in circuits.into_iter() { let mut cs1 = TestConstraintSystem::new(); circuit1.synthesize(&mut cs1).expect("failed to synthesize"); let b = cs1.pretty_print_list(); for (i, (a, b)) in a.chunks(100).zip(b.chunks(100)).enumerate() { assert_eq!(a, b, "failed at chunk {}", i); } } } { let circuits = FallbackPoStCompound::circuit_for_test_all(&pub_params, &pub_inputs, &priv_inputs) .unwrap(); for (circuit, inputs) in circuits.into_iter() { let mut cs = TestConstraintSystem::new(); circuit.synthesize(&mut cs).expect("failed to synthesize"); if !cs.is_satisfied() { panic!( "failed to satisfy: {:?}", cs.which_is_unsatisfied().unwrap() ); } assert!( cs.verify(&inputs), "verification failed with TestContraintSystem and generated inputs" ); } } let blank_groth_params = FallbackPoStCompound::::groth_params(Some(rng), &pub_params.vanilla_params) .expect("failed to generate groth params"); let proofs = FallbackPoStCompound::prove(&pub_params, &pub_inputs, &priv_inputs, &blank_groth_params) .expect("failed while proving"); // Don't try to generate the groth parameters, as they should already have been generated by // the `groth_params()` call above. let verifying_key = FallbackPoStCompound::::verifying_key::( None, &pub_params.vanilla_params, ) .expect("failed to get veriyfing key"); let prepared_verifying_key = groth16::prepare_verifying_key(&verifying_key); let multi_proof = MultiProof::new(proofs, &prepared_verifying_key); let verified = FallbackPoStCompound::verify( &pub_params, &pub_inputs, &multi_proof, &ChallengeRequirements { minimum_challenge_count: total_sector_count * challenge_count, }, ) .expect("failed while verifying"); assert!(verified); }