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 crate::crypto_primitives::commitment::blake2s::Blake2sCommitment;
  2use r1cs_core::{ConstraintSystem, SynthesisError};
  3
  4use crate::gadgets::{
  5    prf::blake2s::{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        crypto_primitives::commitment::{blake2s::Blake2sCommitment, CommitmentScheme},
110        gadgets::commitment::{
111            blake2s::{Blake2sCommitmentGadget, Blake2sRandomnessGadget},
112            CommitmentGadget,
113        },
114    };
115    use r1cs_core::ConstraintSystem;
116    use r1cs_std::prelude::*;
117    use r1cs_std::test_constraint_system::TestConstraintSystem;
118
119    #[test]
120    fn commitment_gadget_test() {
121        let mut cs = TestConstraintSystem::<Fr>::new();
122
123        let input = [1u8; 32];
124
125        let rng = &mut thread_rng();
126
127        type TestCOMM = Blake2sCommitment;
128        type TestCOMMGadget = Blake2sCommitmentGadget;
129
130        let mut randomness = [0u8; 32];
131        rng.fill(&mut randomness);
132
133        let parameters = ();
134        let primitive_result = Blake2sCommitment::commit(&parameters, &input, &randomness).unwrap();
135
136        let mut input_bytes = vec![];
137        for (byte_i, input_byte) in input.into_iter().enumerate() {
138            let cs = cs.ns(|| format!("input_byte_gadget_{}", byte_i));
139            input_bytes.push(UInt8::alloc(cs, || Ok(*input_byte)).unwrap());
140        }
141
142        let mut randomness_bytes = vec![];
143        for (byte_i, random_byte) in randomness.into_iter().enumerate() {
144            let cs = cs.ns(|| format!("randomness_byte_gadget_{}", byte_i));
145            randomness_bytes.push(UInt8::alloc(cs, || Ok(*random_byte)).unwrap());
146        }
147        let randomness_bytes = Blake2sRandomnessGadget(randomness_bytes);
148
149        let gadget_parameters =
150            <TestCOMMGadget as CommitmentGadget<TestCOMM, Fr>>::ParametersGadget::alloc(
151                &mut cs.ns(|| "gadget_parameters"),
152                || Ok(&parameters),
153            )
154            .unwrap();
155        let gadget_result =
156            <TestCOMMGadget as CommitmentGadget<TestCOMM, Fr>>::check_commitment_gadget(
157                &mut cs.ns(|| "gadget_evaluation"),
158                &gadget_parameters,
159                &input_bytes,
160                &randomness_bytes,
161            )
162            .unwrap();
163
164        for i in 0..32 {
165            assert_eq!(primitive_result[i], gadget_result.0[i].get_value().unwrap());
166        }
167        assert!(cs.is_satisfied());
168    }
169}