arnaucube
arnaucube/NovaPublic Self-hosted repository
Nova/src/provider/poseidon_transcript.rs
src/provider/poseidon_transcript.rsRaw
  1#![allow(unused)]
  2
  3use crate::errors::NovaError;
  4use crate::traits::PrimeFieldExt;
  5use crate::traits::{Group, TranscriptEngineTrait, TranscriptReprTrait};
  6use core::marker::PhantomData;
  7use ff::{PrimeField, PrimeFieldBits};
  8use generic_array::typenum::U24;
  9use neptune::{
 10  circuit2::Elt,
 11  poseidon::PoseidonConstants,
 12  sponge::{
 13    api::{IOPattern, SpongeAPI, SpongeOp},
 14    circuit::SpongeCircuit,
 15    vanilla::{Mode, Sponge, SpongeTrait},
 16  },
 17  Strength,
 18};
 19
 20use bellperson::{
 21  gadgets::{
 22    boolean::{AllocatedBit, Boolean},
 23    num::AllocatedNum,
 24  },
 25  ConstraintSystem, SynthesisError,
 26};
 27
 28// WARNING: all this is WIP. Current version is just to have something to use in SumCheck & Spartan
 29// that fullfills Nova's TranscriptEngineTrait with Poseidon.
 30/// Implements the Poseidon Transcript.
 31pub struct PoseidonTranscript<'a, G: Group> {
 32  sponge: Sponge<'a, G::Scalar, U24>,
 33}
 34impl<'a, G: Group> TranscriptEngineTrait<G> for PoseidonTranscript<'a, G> {
 35  fn new(label: &'static [u8]) -> Self {
 36    let constants: &'a PoseidonConstants<G::Scalar, U24> =
 37      &Sponge::<'a, G::Scalar, U24>::duplex_constants();
 38    let mut sponge: Sponge<'a, G::Scalar, U24> =
 39      Sponge::<'a, G::Scalar, U24>::new_with_constants(&constants, Mode::Duplex);
 40    Self { sponge }
 41  }
 42  fn squeeze(&mut self, label: &'static [u8]) -> Result<G::Scalar, NovaError> {
 43    let acc = &mut ();
 44    let hash = SpongeAPI::squeeze(&mut self.sponge, 1, acc);
 45    Ok(hash[0])
 46  }
 47  fn absorb<T: TranscriptReprTrait<G>>(&mut self, label: &'static [u8], o: &T) {
 48    let mut elements: Vec<G::Scalar> = Vec::with_capacity(1);
 49    elements.push(G::Scalar::from_uniform(&o.to_transcript_bytes()));
 50    let acc = &mut ();
 51    // self.sponge.absorb(o, acc);
 52    SpongeAPI::absorb(&mut self.sponge, 32, &elements, acc);
 53  }
 54  fn dom_sep(&mut self, bytes: &'static [u8]) {
 55    unimplemented!();
 56  }
 57}
 58
 59// WIP version
 60/// Implements Poseidon Transcript in Bellperson gadget system
 61pub struct PoseidonTranscriptCircuit<'a, G: Group, CS: ConstraintSystem<G::Scalar>> {
 62  sponge: SpongeCircuit<'a, G::Scalar, U24, CS>,
 63}
 64impl<'a, G: Group, CS: 'a + ConstraintSystem<G::Scalar, Root = CS>>
 65  PoseidonTranscriptCircuit<'a, G, CS>
 66{
 67  // for the TranscriptCircuit, since there is no trait already defined in Nova's codebase, we can
 68  // initiate it by passing the PoseidonConstants.
 69  fn new(constants: &'a PoseidonConstants<G::Scalar, U24>) -> Self {
 70    let sponge = SpongeCircuit::new_with_constants(&constants, Mode::Duplex);
 71    Self { sponge }
 72  }
 73  fn squeeze(&mut self, mut cs: &'a mut CS) -> AllocatedNum<G::Scalar> {
 74    let mut ns = cs.namespace(|| "ns");
 75    let hash = neptune::sponge::api::SpongeAPI::squeeze(&mut self.sponge, 1, &mut ns);
 76    let hash =
 77      Elt::ensure_allocated(&hash[0], &mut ns.namespace(|| "ensure allocated"), true).unwrap();
 78    hash
 79  }
 80  fn absorb(&mut self, mut cs: &'a mut CS, element: G::Scalar) {
 81    let mut ns = cs.namespace(|| "ns");
 82
 83    let mut allocated_elements = Vec::with_capacity(1);
 84    allocated_elements.push(Elt::Allocated(
 85      AllocatedNum::alloc(&mut ns.namespace(|| format!("elt{}", 1)), || Ok(element)).unwrap(),
 86    ));
 87
 88    neptune::sponge::api::SpongeAPI::absorb(
 89      &mut self.sponge,
 90      32,
 91      allocated_elements.as_slice(),
 92      &mut ns,
 93    );
 94  }
 95}
 96
 97#[cfg(test)]
 98mod tests {
 99  use super::*;
100  use crate::provider::bn256_grumpkin::bn256;
101  use crate::{
102    bellperson::solver::SatisfyingAssignment, constants::NUM_CHALLENGE_BITS,
103    gadgets::utils::le_bits_to_num, traits::Group,
104  };
105  use ff::Field;
106  use rand::rngs::OsRng;
107
108  /*
109  fn test_poseidon_transcript_with<G: Group>()
110  where
111    // we can print the field elements we get from G's Base & Scalar fields,
112    // and compare their byte representations
113    <<G as Group>::Base as PrimeField>::Repr: std::fmt::Debug,
114    <<G as Group>::Scalar as PrimeField>::Repr: std::fmt::Debug,
115    <<G as Group>::Base as PrimeField>::Repr: PartialEq<<<G as Group>::Scalar as PrimeField>::Repr>,
116  {
117    // Check that the value computed inside the circuit is equal to the value computed outside the circuit
118    let mut csprng: OsRng = OsRng;
119    let constants: PoseidonConstants<G::Scalar, U24> = Sponge::<G::Scalar, U24>::duplex_constants();
120    let constants2: PoseidonConstants<G::Scalar, U24> =
121      Sponge::<G::Scalar, U24>::duplex_constants();
122    let num_absorbs = 32;
123    let mut transcript: PoseidonTranscript<'_, G> = PoseidonTranscript::new(b"poseidontranscript");
124    let mut transcript_gadget: PoseidonTranscriptCircuit<'_, G, SatisfyingAssignment<G>> =
125      PoseidonTranscriptCircuit::new(&constants2);
126
127    let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new();
128    for i in 0..num_absorbs {
129      let num = G::Scalar::random(&mut csprng);
130      transcript.absorb(b"test", &num);
131      // let num_gadget =
132      //   AllocatedNum::alloc(cs.namespace(|| format!("data {i}")), || Ok(num)).unwrap();
133      // num_gadget
134      //   .inputize(&mut cs.namespace(|| format!("input {i}")))
135      //   .unwrap();
136      transcript_gadget.absorb(&mut cs, num);
137    }
138    let num = transcript.squeeze(b"test");
139    let num2: AllocatedNum<G::Scalar> = transcript_gadget.squeeze(&mut cs);
140    assert_eq!(num.unwrap(), num2.get_value().unwrap());
141    // let num2_bits = transcript_gadget.squeeze(&mut cs).unwrap();
142    // let num2 = le_bits_to_num(&mut cs, &num2_bits).unwrap();
143    // assert_eq!(num.to_repr(), num2.get_value().unwrap().to_repr());
144  }
145
146  #[test]
147  fn test_poseidon_ro() {
148    test_poseidon_transcript_with::<pasta_curves::pallas::Point>();
149    // test_poseidon_ro_with::<bn256::Point>();
150  }
151  */
152}