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