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.

47 lines
1.7 KiB

  1. use ark_ff::PrimeField;
  2. use ark_poly::{EvaluationDomain, GeneralEvaluationDomain};
  3. use ark_serialize::CanonicalSerialize;
  4. use merlin::Transcript as FSTranscript; // FS stands for Fiat-Shamir
  5. use std::marker::PhantomData;
  6. // This Transcript approach is a modified version from https://github.com/caulk-crypto/caulk ,
  7. // using Merlin transcript (https://merlin.cool/).
  8. pub struct Transcript<F: PrimeField> {
  9. phantom: PhantomData<F>,
  10. transcript: FSTranscript,
  11. }
  12. impl<F: PrimeField> Transcript<F> {
  13. pub fn new() -> Self {
  14. Self {
  15. phantom: PhantomData::default(),
  16. transcript: FSTranscript::new(b"FRI transcript"),
  17. }
  18. }
  19. pub fn add<T: CanonicalSerialize>(&mut self, label: &'static [u8], r: &T) {
  20. let mut buf = vec![];
  21. r.serialize_uncompressed(&mut buf).unwrap();
  22. self.transcript.append_message(label, buf.as_ref());
  23. }
  24. pub fn get_challenge(&mut self, label: &'static [u8]) -> F {
  25. let mut bytes = [0u8; 64];
  26. self.transcript.challenge_bytes(label, &mut bytes);
  27. let challenge = F::from_le_bytes_mod_order(bytes.as_ref());
  28. self.add(b"new challenge", &challenge);
  29. challenge
  30. }
  31. pub fn get_challenge_in_eval_domain(
  32. &mut self,
  33. eval_domain: GeneralEvaluationDomain<F>,
  34. label: &'static [u8],
  35. ) -> (usize, F) {
  36. let mut bytes = [0u8; 8];
  37. self.transcript.challenge_bytes(label, &mut bytes);
  38. let c: usize = usize::from_le_bytes(bytes);
  39. let size = eval_domain.size();
  40. let pos = c % size;
  41. let challenge = eval_domain.element(pos);
  42. self.add(b"new challenge", &challenge);
  43. (pos, challenge)
  44. }
  45. }