pedersen_hash.rs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. use bellman::{
  2. gadgets::{
  3. boolean::{AllocatedBit, Boolean},
  4. multipack,
  5. },
  6. groth16, Circuit, ConstraintSystem, SynthesisError,
  7. };
  8. use bls12_381::Bls12;
  9. use group::Curve;
  10. use rand::rngs::OsRng;
  11. pub const CRH_IVK_PERSONALIZATION: &[u8; 8] = b"Zcashivk";
  12. struct MyCircuit {
  13. /// The input to SHA-256d we are proving that we know. Set to `None` when we
  14. /// are verifying a proof (and do not have the witness data).
  15. preimage: Option<[u8; 80]>,
  16. }
  17. impl Circuit<bls12_381::Scalar> for MyCircuit {
  18. fn synthesize<CS: ConstraintSystem<bls12_381::Scalar>>(
  19. self,
  20. cs: &mut CS,
  21. ) -> Result<(), SynthesisError> {
  22. // Compute the values for the bits of the preimage. If we are verifying a proof,
  23. // we still need to create the same constraints, so we return an equivalent-size
  24. // Vec of None (indicating that the value of each bit is unknown).
  25. let bit_values = if let Some(preimage) = self.preimage {
  26. preimage
  27. .iter()
  28. .map(|byte| (0..8).map(move |i| (byte >> i) & 1u8 == 1u8))
  29. .flatten()
  30. .map(|b| Some(b))
  31. .collect()
  32. } else {
  33. vec![None; 80 * 8]
  34. };
  35. assert_eq!(bit_values.len(), 80 * 8);
  36. // Witness the bits of the preimage.
  37. let preimage_bits = bit_values
  38. .into_iter()
  39. .enumerate()
  40. // Allocate each bit.
  41. .map(|(i, b)| AllocatedBit::alloc(cs.namespace(|| format!("preimage bit {}", i)), b))
  42. // Convert the AllocatedBits into Booleans (required for the sha256 gadget).
  43. .map(|b| b.map(Boolean::from))
  44. .collect::<Result<Vec<_>, _>>()?;
  45. let hash = zcash_proofs::circuit::pedersen_hash::pedersen_hash(
  46. cs.namespace(|| "computation of ivk"),
  47. zcash_primitives::pedersen_hash::Personalization::MerkleTree(0),
  48. &preimage_bits,
  49. )?;
  50. hash.get_u().inputize(cs.namespace(|| "commitment"))?;
  51. Ok(())
  52. }
  53. }
  54. fn main() {
  55. use std::time::Instant;
  56. let start = Instant::now();
  57. println!("Starting...");
  58. // Create parameters for our circuit. In a production deployment these would
  59. // be generated securely using a multiparty computation.
  60. let params = {
  61. let c = MyCircuit { preimage: None };
  62. groth16::generate_random_parameters::<Bls12, _, _>(c, &mut OsRng).unwrap()
  63. };
  64. println!("Generated random params. [{:?}]", start.elapsed());
  65. let start = Instant::now();
  66. // Prepare the verification key (for proof verification).
  67. let pvk = groth16::prepare_verifying_key(&params.vk);
  68. println!("Prepared verify key [{:?}]", start.elapsed());
  69. let start = Instant::now();
  70. // Pick a preimage and compute its hash.
  71. let preimage = [42; 80];
  72. //let hash = Sha256::digest(&Sha256::digest(&preimage));
  73. println!(
  74. "Computed pedersen_hash(preimage) witness data [{:?}]",
  75. start.elapsed()
  76. );
  77. // Create an instance of our circuit (with the preimage as a witness).
  78. let test_c = MyCircuit {
  79. preimage: Some(preimage.clone()),
  80. };
  81. let mut cs = bellman::gadgets::test::TestConstraintSystem::new();
  82. test_c.synthesize(&mut cs).unwrap();
  83. assert!(cs.is_satisfied());
  84. println!("Constraints: {}", cs.num_constraints());
  85. let c = MyCircuit {
  86. preimage: Some(preimage),
  87. };
  88. let start = Instant::now();
  89. // Create a Groth16 proof with our parameters.
  90. let proof = groth16::create_random_proof(c, &params, &mut OsRng).unwrap();
  91. println!("Generated random proof [{:?}]", start.elapsed());
  92. let start = Instant::now();
  93. let input_bools: Vec<bool> = preimage
  94. .iter()
  95. .map(|byte| (0..8).map(move |i| (byte >> i) & 1u8 == 1u8))
  96. .flatten()
  97. .collect();
  98. let hash_result = jubjub::ExtendedPoint::from(zcash_primitives::pedersen_hash::pedersen_hash(
  99. zcash_primitives::pedersen_hash::Personalization::MerkleTree(0),
  100. input_bools.into_iter(),
  101. ));
  102. let mut public_input = [bls12_381::Scalar::zero(); 1];
  103. {
  104. let affine = hash_result.to_affine();
  105. //let (u, v) = (affine.get_u(), affine.get_v());
  106. let u = affine.get_u();
  107. public_input[0] = u;
  108. }
  109. // Pack the hash as inputs for proof verification.
  110. println!("Packed data and verifying proof... [{:?}]", start.elapsed());
  111. let start = Instant::now();
  112. // Check the proof!
  113. assert!(groth16::verify_proof(&pvk, &proof, &public_input).is_ok());
  114. println!("Done! [{:?}]", start.elapsed());
  115. }