1use crate::{crhf::FixedLengthRescueCRHF, RescueError, RescueParameter};
10use ark_std::{borrow::Borrow, marker::PhantomData, string::ToString};
11use jf_commitment::CommitmentScheme;
12use jf_crhf::CRHF;
13
14type VerificationResult = Result<(), ()>;
16
17#[derive(Debug, Default, Clone, PartialEq, Eq)]
18pub struct FixedLengthRescueCommitment<
27 F: RescueParameter,
28 const INPUT_LEN: usize,
29 const INPUT_LEN_PLUS_ONE: usize,
30>(PhantomData<F>);
31
32impl<F: RescueParameter, const INPUT_LEN: usize, const INPUT_LEN_PLUS_ONE: usize> CommitmentScheme
33 for FixedLengthRescueCommitment<F, INPUT_LEN, INPUT_LEN_PLUS_ONE>
34{
35 type Input = [F; INPUT_LEN];
36 type Output = F;
37 type Randomness = F;
38 type Error = RescueError;
39
40 fn commit<T: Borrow<Self::Input>>(
41 input: T,
42 r: Option<&Self::Randomness>,
43 ) -> Result<Self::Output, Self::Error> {
44 let mut msg = [F::zero(); INPUT_LEN_PLUS_ONE];
45 msg[0] = *r.ok_or_else(|| {
46 RescueError::ParameterError("Expecting a blinding factor".to_string())
47 })?;
48 msg[1..INPUT_LEN_PLUS_ONE].copy_from_slice(&input.borrow()[..(INPUT_LEN)]);
49
50 Ok(FixedLengthRescueCRHF::<F, INPUT_LEN_PLUS_ONE, 1>::evaluate(&msg)?[0])
51 }
52
53 fn verify<T: Borrow<Self::Input>>(
54 input: T,
55 r: Option<&Self::Randomness>,
56 comm: &Self::Output,
57 ) -> Result<VerificationResult, Self::Error> {
58 if <Self as CommitmentScheme>::commit(input, r)? == *comm {
59 Ok(Ok(()))
60 } else {
61 Ok(Err(()))
62 }
63 }
64}
65
66#[cfg(test)]
67mod test {
68 use crate::{
69 commitment::{CommitmentScheme, FixedLengthRescueCommitment},
70 crhf::RescueCRHF,
71 CRHF_RATE,
72 };
73 use ark_bls12_377::Fq as Fq377;
74 use ark_bn254::Fq as Fq254;
75 use ark_ed_on_bls12_377::Fq as FqEd377;
76 use ark_ed_on_bls12_381::Fq as FqEd381;
77 use ark_ed_on_bls12_381_bandersnatch::Fq as FqEd381b;
78 use ark_ed_on_bn254::Fq as FqEd254;
79 use ark_ff::UniformRand;
80 use ark_std::vec;
81
82 macro_rules! test_commit {
83 ($tr:tt) => {
84 let mut prng = jf_utils::test_rng();
85
86 let input = [$tr::from(1u64), $tr::from(2u64), $tr::from(3u64)];
87 let blind = $tr::rand(&mut prng);
88
89 let c = FixedLengthRescueCommitment::<$tr, 3, 4>::commit(&input, Some(&blind)).unwrap();
90 assert!(
91 FixedLengthRescueCommitment::<$tr, 3, 4>::verify(&input, Some(&blind), &c)
92 .unwrap()
93 .is_ok()
94 );
95 let mut msg = vec![blind];
97 msg.extend_from_slice(&input);
98 if (input.len() + 1) % CRHF_RATE == 0 {
99 assert_eq!(c, RescueCRHF::sponge_no_padding(&msg, 1).unwrap()[0])
100 } else {
101 assert_eq!(c, RescueCRHF::sponge_with_zero_padding(&msg, 1)[0])
102 }
103
104 let bad_input = [input[0], input[1]];
106 assert!(
107 FixedLengthRescueCommitment::<$tr, 2, 3>::verify(&bad_input, Some(&blind), &c)
108 .unwrap()
109 .is_err()
110 );
111 let bad_blind = blind + $tr::from(1u8);
113 assert!(
114 FixedLengthRescueCommitment::<$tr, 3, 4>::verify(&input, Some(&bad_blind), &c)
115 .unwrap()
116 .is_err()
117 );
118 let bad_input = [$tr::from(2u64), $tr::from(1u64), $tr::from(3u64)];
120 assert!(
121 FixedLengthRescueCommitment::<$tr, 3, 4>::verify(&bad_input, Some(&blind), &c)
122 .unwrap()
123 .is_err()
124 );
125 };
126 }
127
128 #[test]
129 fn test_commit() {
130 test_commit!(FqEd254);
131 test_commit!(FqEd377);
132 test_commit!(FqEd381);
133 test_commit!(FqEd381b);
134 test_commit!(Fq377);
135 test_commit!(Fq254);
136 }
137}