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::{Field, PrimeField};
  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>
 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.into_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<F, T, CS: ConstraintSystem<ConstraintF>>(_: CS, _: F) -> Result<Self, SynthesisError>
 52    where
 53        F: FnOnce() -> Result<T, SynthesisError>,
 54        T: Borrow<()>,
 55    {
 56        Ok(Blake2sParametersGadget)
 57    }
 58
 59    fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
 60        _: CS,
 61        _: F,
 62    ) -> Result<Self, SynthesisError>
 63    where
 64        F: FnOnce() -> Result<T, SynthesisError>,
 65        T: Borrow<()>,
 66    {
 67        Ok(Blake2sParametersGadget)
 68    }
 69}
 70
 71impl<ConstraintF: PrimeField> AllocGadget<[u8; 32], ConstraintF> for Blake2sRandomnessGadget {
 72    #[inline]
 73    fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
 74        cs: CS,
 75        value_gen: F,
 76    ) -> Result<Self, SynthesisError>
 77    where
 78        F: FnOnce() -> Result<T, SynthesisError>,
 79        T: Borrow<[u8; 32]>,
 80    {
 81        let zeros = [0u8; 32];
 82        let value = match value_gen() {
 83            Ok(val) => *(val.borrow()),
 84            Err(_) => zeros,
 85        };
 86        let bytes = <UInt8>::alloc_vec(cs, &value)?;
 87
 88        Ok(Blake2sRandomnessGadget(bytes))
 89    }
 90
 91    #[inline]
 92    fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
 93        cs: CS,
 94        value_gen: F,
 95    ) -> Result<Self, SynthesisError>
 96    where
 97        F: FnOnce() -> Result<T, SynthesisError>,
 98        T: Borrow<[u8; 32]>,
 99    {
100        let zeros = [0u8; 32];
101        let value = match value_gen() {
102            Ok(val) => *(val.borrow()),
103            Err(_) => zeros,
104        };
105        let bytes = <UInt8>::alloc_input_vec(cs, &value)?;
106
107        Ok(Blake2sRandomnessGadget(bytes))
108    }
109}
110
111#[cfg(test)]
112mod test {
113    use algebra::fields::bls12_381::Fr;
114    use rand::{thread_rng, Rng};
115
116    use crate::{
117        commitment::blake2s::{
118            constraints::{Blake2sCommitmentGadget, Blake2sRandomnessGadget},
119            Blake2sCommitment,
120        },
121        *,
122    };
123    use r1cs_core::ConstraintSystem;
124    use r1cs_std::{prelude::*, test_constraint_system::TestConstraintSystem};
125
126    #[test]
127    fn commitment_gadget_test() {
128        let mut cs = TestConstraintSystem::<Fr>::new();
129
130        let input = [1u8; 32];
131
132        let rng = &mut thread_rng();
133
134        type TestCOMM = Blake2sCommitment;
135        type TestCOMMGadget = Blake2sCommitmentGadget;
136
137        let mut randomness = [0u8; 32];
138        rng.fill(&mut randomness);
139
140        let parameters = ();
141        let primitive_result = Blake2sCommitment::commit(&parameters, &input, &randomness).unwrap();
142
143        let mut input_bytes = vec![];
144        for (byte_i, input_byte) in input.into_iter().enumerate() {
145            let cs = cs.ns(|| format!("input_byte_gadget_{}", byte_i));
146            input_bytes.push(UInt8::alloc(cs, || Ok(*input_byte)).unwrap());
147        }
148
149        let mut randomness_bytes = vec![];
150        for (byte_i, random_byte) in randomness.into_iter().enumerate() {
151            let cs = cs.ns(|| format!("randomness_byte_gadget_{}", byte_i));
152            randomness_bytes.push(UInt8::alloc(cs, || Ok(*random_byte)).unwrap());
153        }
154        let randomness_bytes = Blake2sRandomnessGadget(randomness_bytes);
155
156        let gadget_parameters =
157            <TestCOMMGadget as CommitmentGadget<TestCOMM, Fr>>::ParametersGadget::alloc(
158                &mut cs.ns(|| "gadget_parameters"),
159                || Ok(&parameters),
160            )
161            .unwrap();
162        let gadget_result =
163            <TestCOMMGadget as CommitmentGadget<TestCOMM, Fr>>::check_commitment_gadget(
164                &mut cs.ns(|| "gadget_evaluation"),
165                &gadget_parameters,
166                &input_bytes,
167                &randomness_bytes,
168            )
169            .unwrap();
170
171        for i in 0..32 {
172            assert_eq!(primitive_result[i], gadget_result.0[i].get_value().unwrap());
173        }
174        assert!(cs.is_satisfied());
175    }
176}