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::{ConstraintSystem, SynthesisError};
  2
  3use crate::{
  4    commitment::blake2s::Blake2sCommitment,
  5    prf::blake2s::constraints::{blake2s_gadget, Blake2sOutputGadget},
  6    CommitmentGadget,
  7};
  8use algebra::{PrimeField, Field};
  9use r1cs_std::prelude::*;
 10
 11use std::borrow::Borrow;
 12
 13#[derive(Clone)]
 14pub struct Blake2sParametersGadget;
 15
 16#[derive(Clone)]
 17pub struct Blake2sRandomnessGadget(pub Vec<UInt8>);
 18
 19pub struct Blake2sCommitmentGadget;
 20
 21impl<ConstraintF: PrimeField> CommitmentGadget<Blake2sCommitment, ConstraintF> for Blake2sCommitmentGadget {
 22    type OutputGadget = Blake2sOutputGadget;
 23    type ParametersGadget = Blake2sParametersGadget;
 24    type RandomnessGadget = Blake2sRandomnessGadget;
 25
 26    fn check_commitment_gadget<CS: ConstraintSystem<ConstraintF>>(
 27        mut cs: CS,
 28        _: &Self::ParametersGadget,
 29        input: &[UInt8],
 30        r: &Self::RandomnessGadget,
 31    ) -> Result<Self::OutputGadget, SynthesisError> {
 32        let mut input_bits = Vec::with_capacity(512);
 33        for byte in input.into_iter().chain(r.0.iter()) {
 34            input_bits.extend_from_slice(&byte.into_bits_le());
 35        }
 36        let mut result = Vec::new();
 37        for (i, int) in blake2s_gadget(cs.ns(|| "Blake2s Eval"), &input_bits)?
 38            .into_iter()
 39            .enumerate()
 40        {
 41            let chunk = int.to_bytes(&mut cs.ns(|| format!("Result ToBytes {}", i)))?;
 42            result.extend_from_slice(&chunk);
 43        }
 44        Ok(Blake2sOutputGadget(result))
 45    }
 46}
 47
 48impl<ConstraintF: Field> AllocGadget<(), ConstraintF> for Blake2sParametersGadget {
 49    fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(_: CS, _: F) -> Result<Self, SynthesisError>
 50    where
 51        F: FnOnce() -> Result<T, SynthesisError>,
 52        T: Borrow<()>,
 53    {
 54        Ok(Blake2sParametersGadget)
 55    }
 56
 57    fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(_: CS, _: F) -> Result<Self, SynthesisError>
 58    where
 59        F: FnOnce() -> Result<T, SynthesisError>,
 60        T: Borrow<()>,
 61    {
 62        Ok(Blake2sParametersGadget)
 63    }
 64}
 65
 66impl<ConstraintF: PrimeField> AllocGadget<[u8; 32], ConstraintF> for Blake2sRandomnessGadget {
 67    #[inline]
 68    fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, value_gen: F) -> Result<Self, SynthesisError>
 69    where
 70        F: FnOnce() -> Result<T, SynthesisError>,
 71        T: Borrow<[u8; 32]>,
 72    {
 73        let zeros = [0u8; 32];
 74        let value = match value_gen() {
 75            Ok(val) => *(val.borrow()),
 76            Err(_) => zeros,
 77        };
 78        let bytes = <UInt8>::alloc_vec(cs, &value)?;
 79
 80        Ok(Blake2sRandomnessGadget(bytes))
 81    }
 82
 83    #[inline]
 84    fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
 85        cs: CS,
 86        value_gen: F,
 87    ) -> Result<Self, SynthesisError>
 88    where
 89        F: FnOnce() -> Result<T, SynthesisError>,
 90        T: Borrow<[u8; 32]>,
 91    {
 92        let zeros = [0u8; 32];
 93        let value = match value_gen() {
 94            Ok(val) => *(val.borrow()),
 95            Err(_) => zeros,
 96        };
 97        let bytes = <UInt8>::alloc_input_vec(cs, &value)?;
 98
 99        Ok(Blake2sRandomnessGadget(bytes))
100    }
101}
102
103#[cfg(test)]
104mod test {
105    use algebra::fields::bls12_381::Fr;
106    use rand::{thread_rng, Rng};
107
108    use crate::*;
109    use crate::{
110        commitment::blake2s::Blake2sCommitment,
111        commitment::blake2s::constraints::{Blake2sCommitmentGadget, Blake2sRandomnessGadget},
112    };
113    use r1cs_core::ConstraintSystem;
114    use r1cs_std::prelude::*;
115    use r1cs_std::test_constraint_system::TestConstraintSystem;
116
117    #[test]
118    fn commitment_gadget_test() {
119        let mut cs = TestConstraintSystem::<Fr>::new();
120
121        let input = [1u8; 32];
122
123        let rng = &mut thread_rng();
124
125        type TestCOMM = Blake2sCommitment;
126        type TestCOMMGadget = Blake2sCommitmentGadget;
127
128        let mut randomness = [0u8; 32];
129        rng.fill(&mut randomness);
130
131        let parameters = ();
132        let primitive_result = Blake2sCommitment::commit(&parameters, &input, &randomness).unwrap();
133
134        let mut input_bytes = vec![];
135        for (byte_i, input_byte) in input.into_iter().enumerate() {
136            let cs = cs.ns(|| format!("input_byte_gadget_{}", byte_i));
137            input_bytes.push(UInt8::alloc(cs, || Ok(*input_byte)).unwrap());
138        }
139
140        let mut randomness_bytes = vec![];
141        for (byte_i, random_byte) in randomness.into_iter().enumerate() {
142            let cs = cs.ns(|| format!("randomness_byte_gadget_{}", byte_i));
143            randomness_bytes.push(UInt8::alloc(cs, || Ok(*random_byte)).unwrap());
144        }
145        let randomness_bytes = Blake2sRandomnessGadget(randomness_bytes);
146
147        let gadget_parameters =
148            <TestCOMMGadget as CommitmentGadget<TestCOMM, Fr>>::ParametersGadget::alloc(
149                &mut cs.ns(|| "gadget_parameters"),
150                || Ok(&parameters),
151            )
152            .unwrap();
153        let gadget_result =
154            <TestCOMMGadget as CommitmentGadget<TestCOMM, Fr>>::check_commitment_gadget(
155                &mut cs.ns(|| "gadget_evaluation"),
156                &gadget_parameters,
157                &input_bytes,
158                &randomness_bytes,
159            )
160            .unwrap();
161
162        for i in 0..32 {
163            assert_eq!(primitive_result[i], gadget_result.0[i].get_value().unwrap());
164        }
165        assert!(cs.is_satisfied());
166    }
167}