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