arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/crypto-primitives/src/commitment/blake2s/constraints.rs
crypto-primitives/src/commitment/blake2s/constraints.rsRaw
  1use r1cs_core::{Namespace, SynthesisError};
  2
  3use crate::{
  4    commitment::blake2s,
  5    commitment::CommitmentGadget,
  6    prf::blake2s::constraints::{evaluate_blake2s, OutputVar},
  7    Vec,
  8};
  9use algebra_core::{Field, PrimeField};
 10use r1cs_std::prelude::*;
 11
 12use core::borrow::Borrow;
 13
 14#[derive(Clone)]
 15pub struct ParametersVar;
 16
 17#[derive(Clone)]
 18pub struct RandomnessVar<F: Field>(pub Vec<UInt8<F>>);
 19
 20pub struct CommGadget;
 21
 22impl<F: PrimeField> CommitmentGadget<blake2s::Commitment, F> for CommGadget {
 23    type OutputVar = OutputVar<F>;
 24    type ParametersVar = ParametersVar;
 25    type RandomnessVar = RandomnessVar<F>;
 26
 27    fn commit(
 28        _: &Self::ParametersVar,
 29        input: &[UInt8<F>],
 30        r: &Self::RandomnessVar,
 31    ) -> Result<Self::OutputVar, SynthesisError> {
 32        let mut input_bits = Vec::with_capacity(512);
 33        for byte in input.iter().chain(r.0.iter()) {
 34            input_bits.extend_from_slice(&byte.to_bits_le()?);
 35        }
 36        let mut result = Vec::new();
 37        for int in evaluate_blake2s(&input_bits)?.into_iter() {
 38            let chunk = int.to_bytes()?;
 39            result.extend_from_slice(&chunk);
 40        }
 41        Ok(OutputVar(result))
 42    }
 43}
 44
 45impl<ConstraintF: Field> AllocVar<(), ConstraintF> for ParametersVar {
 46    fn new_variable<T: Borrow<()>>(
 47        _cs: impl Into<Namespace<ConstraintF>>,
 48        _f: impl FnOnce() -> Result<T, SynthesisError>,
 49        _mode: AllocationMode,
 50    ) -> Result<Self, SynthesisError> {
 51        Ok(ParametersVar)
 52    }
 53}
 54
 55impl<ConstraintF: PrimeField> AllocVar<[u8; 32], ConstraintF> for RandomnessVar<ConstraintF> {
 56    fn new_variable<T: Borrow<[u8; 32]>>(
 57        cs: impl Into<Namespace<ConstraintF>>,
 58        f: impl FnOnce() -> Result<T, SynthesisError>,
 59        mode: AllocationMode,
 60    ) -> Result<Self, SynthesisError> {
 61        let bytes = f().map(|b| *b.borrow()).unwrap_or([0u8; 32]);
 62        match mode {
 63            AllocationMode::Constant => Ok(Self(UInt8::constant_vec(&bytes))),
 64            AllocationMode::Input => UInt8::new_input_vec(cs, &bytes).map(Self),
 65            AllocationMode::Witness => UInt8::new_witness_vec(cs, &bytes).map(Self),
 66        }
 67    }
 68}
 69
 70#[cfg(test)]
 71mod test {
 72    use crate::{
 73        commitment::blake2s::{
 74            constraints::{CommGadget, RandomnessVar},
 75            Commitment,
 76        },
 77        commitment::{CommitmentGadget, CommitmentScheme},
 78    };
 79    use algebra::{ed_on_bls12_381::Fq as Fr, test_rng};
 80    use r1cs_core::ConstraintSystem;
 81    use r1cs_std::prelude::*;
 82    use rand::Rng;
 83
 84    #[test]
 85    fn commitment_gadget_test() {
 86        let cs = ConstraintSystem::<Fr>::new_ref();
 87
 88        let input = [1u8; 32];
 89
 90        let rng = &mut test_rng();
 91
 92        type TestCOMM = Commitment;
 93        type TestCOMMGadget = CommGadget;
 94
 95        let mut randomness = [0u8; 32];
 96        rng.fill(&mut randomness);
 97
 98        let parameters = ();
 99        let primitive_result = Commitment::commit(&parameters, &input, &randomness).unwrap();
100
101        let mut input_var = vec![];
102        for byte in &input {
103            input_var.push(UInt8::new_witness(cs.clone(), || Ok(*byte)).unwrap());
104        }
105
106        let mut randomness_var = vec![];
107        for r_byte in randomness.iter() {
108            randomness_var.push(UInt8::new_witness(cs.clone(), || Ok(r_byte)).unwrap());
109        }
110        let randomness_var = RandomnessVar(randomness_var);
111
112        let parameters_var =
113            <TestCOMMGadget as CommitmentGadget<TestCOMM, Fr>>::ParametersVar::new_witness(
114                cs.ns("gadget_parameters"),
115                || Ok(&parameters),
116            )
117            .unwrap();
118        let result_var = <TestCOMMGadget as CommitmentGadget<TestCOMM, Fr>>::commit(
119            &parameters_var,
120            &input_var,
121            &randomness_var,
122        )
123        .unwrap();
124
125        for i in 0..32 {
126            assert_eq!(primitive_result[i], result_var.0[i].value().unwrap());
127        }
128        assert!(cs.is_satisfied().unwrap());
129    }
130}