You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.8 KiB

  1. use ark_ec::{AffineRepr, CurveGroup};
  2. use ark_ff::PrimeField;
  3. use std::marker::PhantomData;
  4. use ark_r1cs_std::fields::fp::FpVar;
  5. use ark_crypto_primitives::sponge::poseidon::{
  6. constraints::PoseidonSpongeVar, PoseidonConfig, PoseidonSponge,
  7. };
  8. use ark_crypto_primitives::sponge::{
  9. constraints::CryptographicSpongeVar, Absorb, CryptographicSponge,
  10. };
  11. use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
  12. pub struct Transcript<F: PrimeField + Absorb, C: CurveGroup>
  13. where
  14. <C as CurveGroup>::BaseField: Absorb,
  15. {
  16. // where F is the Constraint Field (eq. C::ScalarField)
  17. sponge: PoseidonSponge<F>,
  18. _c: PhantomData<C>,
  19. }
  20. impl<F: PrimeField + Absorb, C: CurveGroup> Transcript<F, C>
  21. where
  22. <C as CurveGroup>::BaseField: Absorb,
  23. {
  24. pub fn new(poseidon_config: &PoseidonConfig<F>) -> Self {
  25. let sponge = PoseidonSponge::<F>::new(poseidon_config);
  26. Transcript {
  27. sponge,
  28. _c: PhantomData,
  29. }
  30. }
  31. pub fn add(&mut self, v: &F) {
  32. self.sponge.absorb(&v);
  33. }
  34. pub fn add_vec(&mut self, v: &[F]) {
  35. self.sponge.absorb(&v);
  36. }
  37. pub fn add_point(&mut self, v: &C) {
  38. let v_affine = v.into_affine();
  39. let xy = v_affine.xy().unwrap(); // WIP
  40. self.sponge.absorb(&vec![xy.0, xy.1]);
  41. }
  42. pub fn get_challenge(&mut self) -> F {
  43. let c = self.sponge.squeeze_field_elements(1);
  44. self.add(&c[0]);
  45. c[0]
  46. }
  47. pub fn get_challenge_vec(&mut self, n: usize) -> Vec<F> {
  48. let c = self.sponge.squeeze_field_elements(n);
  49. self.sponge.absorb(&c);
  50. c
  51. }
  52. }
  53. pub struct TranscriptVar<F: PrimeField> {
  54. // where F is the Constraint Field
  55. sponge: PoseidonSpongeVar<F>,
  56. }
  57. impl<F: PrimeField> TranscriptVar<F> {
  58. pub fn new(cs: ConstraintSystemRef<F>, poseidon_config: &PoseidonConfig<F>) -> Self {
  59. let sponge = PoseidonSpongeVar::<F>::new(cs, poseidon_config);
  60. Self { sponge }
  61. }
  62. pub fn add(&mut self, v: FpVar<F>) -> Result<(), SynthesisError> {
  63. self.sponge.absorb(&v)
  64. }
  65. pub fn get_challenge(&mut self) -> Result<FpVar<F>, SynthesisError> {
  66. let c = self.sponge.squeeze_field_elements(1)?;
  67. self.sponge.absorb(&c[0])?;
  68. Ok(c[0].clone())
  69. }
  70. pub fn get_challenge_vec(&mut self, n: usize) -> Result<Vec<FpVar<F>>, SynthesisError> {
  71. let c = self.sponge.squeeze_field_elements(n)?;
  72. self.sponge.absorb(&c)?;
  73. Ok(c)
  74. }
  75. }
  76. use ark_crypto_primitives::sponge::poseidon::find_poseidon_ark_and_mds;
  77. // WARNING this is for test only
  78. pub fn poseidon_test_config<F: PrimeField>() -> PoseidonConfig<F> {
  79. let full_rounds = 8;
  80. let partial_rounds = 31;
  81. let alpha = 5;
  82. let rate = 2;
  83. let (ark, mds) = find_poseidon_ark_and_mds::<F>(
  84. F::MODULUS_BIT_SIZE as u64,
  85. rate,
  86. full_rounds,
  87. partial_rounds,
  88. 0,
  89. );
  90. PoseidonConfig::new(
  91. full_rounds as usize,
  92. partial_rounds as usize,
  93. alpha,
  94. mds,
  95. ark,
  96. rate,
  97. 1,
  98. )
  99. }
  100. #[cfg(test)]
  101. mod tests {
  102. use super::*;
  103. use ark_mnt4_298::{Fr, G1Projective}; // scalar field
  104. use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, R1CSVar};
  105. use ark_relations::r1cs::ConstraintSystem;
  106. #[test]
  107. fn test_transcript_and_transcriptvar() {
  108. let config = poseidon_test_config::<Fr>();
  109. let mut tr = Transcript::<Fr, G1Projective>::new(&config);
  110. tr.add(&Fr::from(42_u32));
  111. let c = tr.get_challenge();
  112. let cs = ConstraintSystem::<Fr>::new_ref();
  113. let mut tr_var = TranscriptVar::<Fr>::new(cs.clone(), &config);
  114. let v = FpVar::<Fr>::new_witness(cs.clone(), || Ok(Fr::from(42_u32))).unwrap();
  115. tr_var.add(v).unwrap();
  116. let c_var = tr_var.get_challenge().unwrap();
  117. assert_eq!(c, c_var.value().unwrap());
  118. }
  119. }