claim_narrowing.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #![allow(non_snake_case)]
  2. //! Term-free (public) equations are lowered one of two ways, and these
  3. //! tests pin down which: conjoined, they are evaluated by `compile()`
  4. //! and cost nothing on the wire; under a disjunction, they become claim
  5. //! leaves whose constant shape lets a false branch be simulated.
  6. use curve25519_dalek::ristretto::RistrettoPoint as G;
  7. use group::Group;
  8. use sha2::Sha512;
  9. use sigma_compiler::*;
  10. type Scalar = <G as Group>::Scalar;
  11. /// A conjoined term-free equation leaves no trace: `compile()` strips
  12. /// it, so the statement is the one written without it, down to the
  13. /// transcript. A proof of the stripped statement therefore verifies
  14. /// here -- which it cannot if the equation became a claim leaf, since
  15. /// that leaf is part of the composition the transcript binds.
  16. #[test]
  17. fn conjoined_claim_leaves_no_trace() -> Result<(), Box<dyn std::error::Error>> {
  18. sigma_compiler! { plain,
  19. (x),
  20. (C, const cind A),
  21. C = x*A,
  22. }
  23. sigma_compiler! { claimed,
  24. (x),
  25. (C, D, E, const cind A),
  26. C = x*A,
  27. D = E,
  28. }
  29. let mut rng = rand::thread_rng();
  30. let A = G::hash_from_bytes::<Sha512>(b"Generator A");
  31. let D = G::hash_from_bytes::<Sha512>(b"Element D");
  32. let x = Scalar::random(&mut rng);
  33. let C = x * A;
  34. let plain_proof = plain::prove(
  35. &plain::Instance { C, A },
  36. &plain::Witness { x },
  37. b"claim_narrowing",
  38. &mut rng,
  39. )?;
  40. // `D = E` holds, so the statement is exactly the one above.
  41. let instance = claimed::Instance { C, D, E: D, A };
  42. let claimed_proof = claimed::prove(
  43. &instance,
  44. &claimed::Witness { x },
  45. b"claim_narrowing",
  46. &mut rng,
  47. )?;
  48. claimed::verify(&instance, &claimed_proof, b"claim_narrowing")?;
  49. assert_eq!(claimed_proof.len(), plain_proof.len());
  50. Ok(claimed::verify(
  51. &instance,
  52. &plain_proof,
  53. b"claim_narrowing",
  54. )?)
  55. }
  56. /// A conjoined term-free equation that does not hold makes the instance
  57. /// invalid, for the prover and the verifier alike -- an error, not a
  58. /// panic and not a proof that fails to verify later.
  59. #[test]
  60. fn false_conjoined_claim_is_an_error() {
  61. sigma_compiler! { claimed,
  62. (x),
  63. (C, D, E, const cind A),
  64. C = x*A,
  65. D = E,
  66. }
  67. let mut rng = rand::thread_rng();
  68. let A = G::hash_from_bytes::<Sha512>(b"Generator A");
  69. let D = G::hash_from_bytes::<Sha512>(b"Element D");
  70. let E = G::hash_from_bytes::<Sha512>(b"Element E");
  71. let x = Scalar::random(&mut rng);
  72. let C = x * A;
  73. let instance = claimed::Instance { C, D, E, A };
  74. claimed::prove(
  75. &instance,
  76. &claimed::Witness { x },
  77. b"claim_narrowing",
  78. &mut rng,
  79. )
  80. .unwrap_err();
  81. claimed::verify(&instance, &[], b"claim_narrowing").unwrap_err();
  82. }
  83. /// Under a disjunction the claim leaf stays: the branch has to be
  84. /// simulatable when its claim is false, and the proof must look the
  85. /// same either way.
  86. #[test]
  87. fn disjunctive_claim_keeps_constant_shape() -> Result<(), Box<dyn std::error::Error>> {
  88. sigma_compiler! { proof,
  89. (x),
  90. (C, D, E, const cind A),
  91. OR (
  92. D = E,
  93. C = x*A,
  94. )
  95. }
  96. let mut rng = rand::thread_rng();
  97. let A = G::hash_from_bytes::<Sha512>(b"Generator A");
  98. let D = G::hash_from_bytes::<Sha512>(b"Element D");
  99. let E = G::hash_from_bytes::<Sha512>(b"Element E");
  100. let x = Scalar::random(&mut rng);
  101. let C = x * A;
  102. // The second disjunct is the real one in both runs; only the truth
  103. // of the first disjunct's claim differs.
  104. let mut sizes = Vec::new();
  105. for E in [D, E] {
  106. let instance = proof::Instance { C, D, E, A };
  107. let proof = proof::prove(
  108. &instance,
  109. &proof::Witness { x },
  110. b"claim_narrowing",
  111. &mut rng,
  112. )?;
  113. proof::verify(&instance, &proof, b"claim_narrowing")?;
  114. sizes.push(proof.len());
  115. }
  116. assert_eq!(sizes[0], sizes[1]);
  117. Ok(())
  118. }