blake.rs 4.0 KB

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