ark-r1cs-std/crypto-primitives/src/commitment/blake2s/constraints.rs
crypto-primitives/src/commitment/blake2s/constraints.rsRaw
1use r1cs_core::{Namespace, SynthesisError};
2
3use crate::{
4 commitment::blake2s,
5 commitment::CommitmentGadget,
6 prf::blake2s::constraints::{evaluate_blake2s, OutputVar},
7 Vec,
8};
9use algebra_core::{Field, PrimeField};
10use r1cs_std::prelude::*;
11
12use core::borrow::Borrow;
13
14#[derive(Clone)]
15pub struct ParametersVar;
16
17#[derive(Clone)]
18pub struct RandomnessVar<F: Field>(pub Vec<UInt8<F>>);
19
20pub struct CommGadget;
21
22impl<F: PrimeField> CommitmentGadget<blake2s::Commitment, F> for CommGadget {
23 type OutputVar = OutputVar<F>;
24 type ParametersVar = ParametersVar;
25 type RandomnessVar = RandomnessVar<F>;
26
27 fn commit(
28 _: &Self::ParametersVar,
29 input: &[UInt8<F>],
30 r: &Self::RandomnessVar,
31 ) -> Result<Self::OutputVar, SynthesisError> {
32 let mut input_bits = Vec::with_capacity(512);
33 for byte in input.iter().chain(r.0.iter()) {
34 input_bits.extend_from_slice(&byte.into_bits_le());
35 }
36 let mut result = Vec::new();
37 for int in evaluate_blake2s(&input_bits)?.into_iter() {
38 let chunk = int.to_bytes()?;
39 result.extend_from_slice(&chunk);
40 }
41 Ok(OutputVar(result))
42 }
43}
44
45impl<ConstraintF: Field> AllocVar<(), ConstraintF> for ParametersVar {
46 fn new_variable<T: Borrow<()>>(
47 _cs: impl Into<Namespace<ConstraintF>>,
48 _f: impl FnOnce() -> Result<T, SynthesisError>,
49 _mode: AllocationMode,
50 ) -> Result<Self, SynthesisError> {
51 Ok(ParametersVar)
52 }
53}
54
55impl<ConstraintF: PrimeField> AllocVar<[u8; 32], ConstraintF> for RandomnessVar<ConstraintF> {
56 fn new_variable<T: Borrow<[u8; 32]>>(
57 cs: impl Into<Namespace<ConstraintF>>,
58 f: impl FnOnce() -> Result<T, SynthesisError>,
59 mode: AllocationMode,
60 ) -> Result<Self, SynthesisError> {
61 let bytes = f().map(|b| *b.borrow()).unwrap_or([0u8; 32]);
62 match mode {
63 AllocationMode::Constant => Ok(Self(UInt8::constant_vec(&bytes))),
64 AllocationMode::Input => UInt8::new_input_vec(cs, &bytes).map(Self),
65 AllocationMode::Witness => UInt8::new_witness_vec(cs, &bytes).map(Self),
66 }
67 }
68}
69
70#[cfg(test)]
71mod test {
72 use crate::{
73 commitment::blake2s::{
74 constraints::{CommGadget, RandomnessVar},
75 Commitment,
76 },
77 commitment::{CommitmentGadget, CommitmentScheme},
78 };
79 use algebra::{ed_on_bls12_381::Fq as Fr, test_rng};
80 use r1cs_core::ConstraintSystem;
81 use r1cs_std::prelude::*;
82 use rand::Rng;
83
84 #[test]
85 fn commitment_gadget_test() {
86 let cs = ConstraintSystem::<Fr>::new_ref();
87
88 let input = [1u8; 32];
89
90 let rng = &mut test_rng();
91
92 type TestCOMM = Commitment;
93 type TestCOMMGadget = CommGadget;
94
95 let mut randomness = [0u8; 32];
96 rng.fill(&mut randomness);
97
98 let parameters = ();
99 let primitive_result = Commitment::commit(¶meters, &input, &randomness).unwrap();
100
101 let mut input_var = vec![];
102 for byte in &input {
103 input_var.push(UInt8::new_witness(cs.clone(), || Ok(*byte)).unwrap());
104 }
105
106 let mut randomness_var = vec![];
107 for r_byte in randomness.iter() {
108 randomness_var.push(UInt8::new_witness(cs.clone(), || Ok(r_byte)).unwrap());
109 }
110 let randomness_var = RandomnessVar(randomness_var);
111
112 let parameters_var =
113 <TestCOMMGadget as CommitmentGadget<TestCOMM, Fr>>::ParametersVar::new_witness(
114 cs.ns("gadget_parameters"),
115 || Ok(¶meters),
116 )
117 .unwrap();
118 let result_var = <TestCOMMGadget as CommitmentGadget<TestCOMM, Fr>>::commit(
119 ¶meters_var,
120 &input_var,
121 &randomness_var,
122 )
123 .unwrap();
124
125 for i in 0..32 {
126 assert_eq!(primitive_result[i], result_var.0[i].value().unwrap());
127 }
128 assert!(cs.is_satisfied().unwrap());
129 }
130}