1use super::{Mode, ParamType};
2use ark_ff::{PrimeField, UniformRand as _};
3use ark_serialize::CanonicalSerialize as _;
4use mina_curves::pasta::Fp;
5use mina_poseidon::{
6 constants::{self, SpongeConstants},
7 pasta,
8 poseidon::{ArithmeticSponge as Poseidon, ArithmeticSpongeParams, Sponge as _},
9};
10use num_bigint::BigUint;
11use rand::Rng;
12use serde::Serialize;
13
14#[derive(Debug, Serialize)]
23pub struct TestVectors {
24 name: String,
25 test_vectors: Vec<TestVector>,
26}
27
28#[derive(Debug, Serialize)]
29pub struct TestVector {
30 input: Vec<String>,
31 output: String,
32}
33
34fn poseidon<SC: SpongeConstants>(input: &[Fp], params: &'static ArithmeticSpongeParams<Fp>) -> Fp {
41 let mut s = Poseidon::<Fp, SC>::new(params);
42 s.absorb(input);
43 s.squeeze()
44}
45
46fn rand_fields(rng: &mut impl Rng, length: u8) -> Vec<Fp> {
48 let mut fields = vec![];
49 for _ in 0..length {
50 let fe = Fp::rand(rng);
51 fields.push(fe)
52 }
53 fields
54}
55
56pub fn generate(mode: Mode, param_type: ParamType) -> TestVectors {
58 let rng = &mut o1_utils::tests::make_test_rng(Some([0u8; 32]));
59 let mut test_vectors = vec![];
60
61 for length in 0..6 {
63 let input = rand_fields(rng, length);
65 let output = match param_type {
66 ParamType::Legacy => poseidon::<constants::PlonkSpongeConstantsLegacy>(
67 &input,
68 pasta::fp_legacy::static_params(),
69 ),
70 ParamType::Kimchi => poseidon::<constants::PlonkSpongeConstantsKimchi>(
71 &input,
72 pasta::fp_kimchi::static_params(),
73 ),
74 };
75
76 let input = input
78 .into_iter()
79 .map(|elem| {
80 let mut input_bytes = vec![];
81 elem.into_bigint()
82 .serialize_uncompressed(&mut input_bytes)
83 .expect("canonical serialiation should work");
84
85 match mode {
86 Mode::Hex => hex::encode(&input_bytes),
87 Mode::B10 => BigUint::from_bytes_le(&input_bytes).to_string(),
88 }
89 })
90 .collect();
91 let mut output_bytes = vec![];
92 output
93 .into_bigint()
94 .serialize_uncompressed(&mut output_bytes)
95 .expect("canonical serialization should work");
96
97 test_vectors.push(TestVector {
99 input,
100 output: match mode {
101 Mode::Hex => hex::encode(&output_bytes),
102 Mode::B10 => BigUint::from_bytes_le(&output_bytes).to_string(),
103 },
104 })
105 }
106
107 let name = match param_type {
108 ParamType::Legacy => "legacy",
109 ParamType::Kimchi => "kimchi",
110 }
111 .into();
112
113 TestVectors { name, test_vectors }
114}
115
116#[cfg(test)]
117mod tests {
118
119 use super::*;
120
121 #[test]
122 fn poseidon_test_vectors_regression() {
123 use mina_poseidon::pasta;
124 let rng = &mut o1_utils::tests::make_test_rng(Some([0u8; 32]));
125
126 let expected_output_bytes_legacy = [
131 [
132 27, 50, 81, 182, 145, 45, 130, 237, 199, 139, 187, 10, 92, 136, 240, 198, 253, 225,
133 120, 27, 195, 230, 84, 18, 63, 166, 134, 42, 76, 99, 230, 23,
134 ],
135 [
136 233, 146, 98, 4, 142, 113, 119, 69, 253, 205, 96, 42, 59, 82, 126, 158, 124, 46,
137 91, 165, 137, 65, 88, 8, 78, 47, 46, 44, 177, 66, 100, 61,
138 ],
139 [
140 31, 143, 157, 47, 185, 84, 125, 2, 84, 161, 192, 39, 31, 244, 0, 66, 165, 153, 39,
141 232, 47, 208, 151, 215, 250, 114, 63, 133, 81, 232, 194, 58,
142 ],
143 [
144 153, 120, 16, 250, 143, 51, 135, 158, 104, 156, 128, 128, 33, 215, 241, 207, 48,
145 47, 48, 240, 7, 87, 84, 228, 61, 194, 247, 93, 118, 187, 57, 32,
146 ],
147 [
148 249, 48, 174, 91, 239, 32, 152, 227, 183, 25, 73, 233, 135, 140, 175, 86, 89, 137,
149 127, 59, 158, 177, 113, 31, 41, 106, 153, 207, 183, 64, 236, 63,
150 ],
151 [
152 70, 27, 110, 192, 143, 211, 169, 195, 112, 51, 239, 212, 9, 207, 84, 132, 147, 176,
153 3, 178, 245, 0, 219, 132, 93, 93, 31, 210, 255, 206, 27, 2,
154 ],
155 ];
156
157 let expected_output_bytes_kimchi = [
158 [
159 168, 235, 158, 224, 243, 0, 70, 48, 138, 187, 250, 93, 32, 175, 115, 200, 27, 189,
160 171, 194, 91, 69, 151, 133, 2, 77, 4, 82, 40, 190, 173, 47,
161 ],
162 [
163 194, 127, 92, 204, 27, 156, 169, 110, 191, 207, 34, 111, 254, 28, 202, 241, 89,
164 145, 245, 226, 223, 247, 32, 48, 223, 109, 141, 29, 230, 181, 28, 13,
165 ],
166 [
167 238, 26, 57, 207, 87, 2, 255, 206, 108, 78, 212, 92, 105, 193, 255, 227, 103, 185,
168 123, 134, 79, 154, 104, 138, 78, 128, 170, 185, 149, 74, 14, 10,
169 ],
170 [
171 252, 66, 64, 58, 146, 197, 79, 63, 196, 10, 116, 66, 72, 177, 170, 234, 252, 154,
172 82, 137, 234, 3, 117, 226, 73, 211, 32, 4, 150, 196, 133, 33,
173 ],
174 [
175 42, 33, 199, 187, 104, 139, 231, 56, 52, 166, 8, 70, 141, 53, 158, 96, 175, 246,
176 75, 186, 160, 9, 17, 203, 83, 113, 240, 208, 235, 33, 111, 41,
177 ],
178 [
179 133, 233, 196, 82, 62, 17, 13, 12, 173, 230, 192, 216, 56, 126, 197, 152, 164, 155,
180 205, 238, 73, 116, 220, 196, 21, 134, 120, 39, 171, 177, 119, 25,
181 ],
182 ];
183
184 let expected_output_0_hex_legacy =
185 "1b3251b6912d82edc78bbb0a5c88f0c6fde1781bc3e654123fa6862a4c63e617";
186 let expected_output_0_hex_kimchi =
187 "a8eb9ee0f30046308abbfa5d20af73c81bbdabc25b459785024d045228bead2f";
188
189 for param_type in [ParamType::Legacy, ParamType::Kimchi] {
190 let expected_output_bytes = match param_type {
191 ParamType::Legacy => &expected_output_bytes_legacy,
192 ParamType::Kimchi => &expected_output_bytes_kimchi,
193 };
194
195 for length in 0..6 {
196 let input = rand_fields(rng, length);
198 let output = match param_type {
199 ParamType::Legacy => poseidon::<constants::PlonkSpongeConstantsLegacy>(
200 &input,
201 pasta::fp_legacy::static_params(),
202 ),
203 ParamType::Kimchi => poseidon::<constants::PlonkSpongeConstantsKimchi>(
204 &input,
205 pasta::fp_kimchi::static_params(),
206 ),
207 };
208
209 let mut output_bytes = vec![];
210 output
211 .into_bigint()
212 .serialize_uncompressed(&mut output_bytes)
213 .expect("canonical serialization should work");
214
215 assert!(output_bytes == expected_output_bytes[length as usize]);
216 }
217
218 let expected_output_0_hex = match param_type {
219 ParamType::Legacy => expected_output_0_hex_legacy,
220 ParamType::Kimchi => expected_output_0_hex_kimchi,
221 };
222
223 let test_vectors_hex = generate(Mode::Hex, param_type);
224 assert!(test_vectors_hex.test_vectors[0].output == expected_output_0_hex);
225 }
226 }
227}