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.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(¶meters, &input, &randomness).unwrap();
142
143 let mut input_bytes = vec![];
144 for (byte_i, input_byte) in input.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.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(¶meters),
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}