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(¶meters, &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(¶meters),
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}