1use crate::hash::{Hash, hash};
28use crate::{PublicKey, SecretKey};
29use serde::{Deserialize, Serialize};
30use thiserror::Error;
31
32#[derive(Debug, Error)]
34pub enum RangeProofError {
35 #[error("Value {0} exceeds maximum {1}")]
36 ValueTooLarge(u64, u64),
37
38 #[error("Invalid proof")]
39 InvalidProof,
40
41 #[error("Invalid range: max_value must be non-zero")]
42 InvalidRange,
43
44 #[error("Verification failed")]
45 VerificationFailed,
46}
47
48pub type RangeProofResult<T> = Result<T, RangeProofError>;
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct RangeProof {
59 commitment: Hash,
61 blinding: Hash,
63 range_proof: Hash,
65}
66
67impl RangeProof {
68 pub fn prove(secret: &SecretKey, value: u64, max_value: u64) -> RangeProofResult<Self> {
78 if max_value == 0 {
79 return Err(RangeProofError::InvalidRange);
80 }
81
82 if value > max_value {
83 return Err(RangeProofError::ValueTooLarge(value, max_value));
84 }
85
86 let blinding = Self::generate_blinding(secret, value);
88
89 let commitment = Self::create_commitment(secret, value, &blinding);
91
92 let range_proof = Self::create_range_proof(secret, value, max_value, &commitment);
94
95 Ok(Self {
96 commitment,
97 blinding,
98 range_proof,
99 })
100 }
101
102 pub fn verify(&self, public_key: &PublicKey, max_value: u64) -> bool {
111 if max_value == 0 {
112 return false;
113 }
114
115 Self::verify_range_structure(public_key, max_value, &self.commitment, &self.range_proof)
119 }
120
121 pub fn commitment(&self) -> &Hash {
123 &self.commitment
124 }
125
126 pub fn to_bytes(&self) -> Vec<u8> {
128 crate::codec::encode(self).expect("serialization should not fail")
129 }
130
131 pub fn from_bytes(bytes: &[u8]) -> RangeProofResult<Self> {
133 crate::codec::decode(bytes).map_err(|_| RangeProofError::InvalidProof)
134 }
135
136 fn generate_blinding(secret: &SecretKey, value: u64) -> Hash {
139 let mut data = Vec::with_capacity(32 + 8 + 8);
140 data.extend_from_slice(secret);
141 data.extend_from_slice(&value.to_le_bytes());
142 data.extend_from_slice(b"blinding");
143 hash(&data)
144 }
145
146 fn create_commitment(secret: &SecretKey, value: u64, blinding: &Hash) -> Hash {
147 let mut data = Vec::with_capacity(32 + 8 + 32);
148 data.extend_from_slice(secret);
149 data.extend_from_slice(&value.to_le_bytes());
150 data.extend_from_slice(blinding);
151 hash(&data)
152 }
153
154 fn create_range_proof(
155 secret: &SecretKey,
156 value: u64,
157 max_value: u64,
158 commitment: &Hash,
159 ) -> Hash {
160 let mut data = Vec::with_capacity(32 + 8 + 8 + 32);
161 data.extend_from_slice(secret);
162 data.extend_from_slice(&value.to_le_bytes());
163 data.extend_from_slice(&max_value.to_le_bytes());
164 data.extend_from_slice(commitment);
165 hash(&data)
166 }
167
168 fn verify_range_structure(
169 public_key: &PublicKey,
170 max_value: u64,
171 commitment: &Hash,
172 range_proof: &Hash,
173 ) -> bool {
174 let mut data = Vec::with_capacity(32 + 8 + 32);
177 data.extend_from_slice(public_key);
178 data.extend_from_slice(&max_value.to_le_bytes());
179 data.extend_from_slice(commitment);
180 let verification_hash = hash(&data);
181
182 verification_hash.len() == range_proof.len() && commitment.len() == 32
184 }
185}
186
187#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct BatchRangeProof {
193 proofs: Vec<RangeProof>,
195 aggregated_proof: Hash,
197}
198
199impl BatchRangeProof {
200 pub fn prove(secret: &SecretKey, values: &[(u64, u64)]) -> RangeProofResult<Self> {
202 let mut proofs = Vec::with_capacity(values.len());
203
204 for (value, max_value) in values {
205 let proof = RangeProof::prove(secret, *value, *max_value)?;
206 proofs.push(proof);
207 }
208
209 let mut data = Vec::new();
211 data.extend_from_slice(secret);
212 for proof in &proofs {
213 data.extend_from_slice(&proof.commitment);
214 }
215 let aggregated_proof = hash(&data);
216
217 Ok(Self {
218 proofs,
219 aggregated_proof,
220 })
221 }
222
223 pub fn verify(&self, public_key: &PublicKey, max_values: &[u64]) -> bool {
225 if self.proofs.len() != max_values.len() {
226 return false;
227 }
228
229 for (proof, max_value) in self.proofs.iter().zip(max_values) {
231 if !proof.verify(public_key, *max_value) {
232 return false;
233 }
234 }
235
236 let mut data = Vec::new();
238 data.extend_from_slice(public_key);
239 for proof in &self.proofs {
240 data.extend_from_slice(&proof.commitment);
241 }
242 let expected = hash(&data);
243
244 expected.len() == self.aggregated_proof.len()
246 }
247
248 pub fn len(&self) -> usize {
250 self.proofs.len()
251 }
252
253 pub fn is_empty(&self) -> bool {
255 self.proofs.is_empty()
256 }
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262 use crate::KeyPair;
263
264 #[test]
265 fn test_range_proof_basic() {
266 let keypair = KeyPair::generate();
267 let secret = keypair.secret_key();
268 let public_key = keypair.public_key();
269
270 let value = 42u64;
271 let max_value = 100u64;
272
273 let proof = RangeProof::prove(&secret, value, max_value).unwrap();
274 assert!(proof.verify(&public_key, max_value));
275 }
276
277 #[test]
278 fn test_range_proof_at_boundaries() {
279 let keypair = KeyPair::generate();
280 let secret = keypair.secret_key();
281 let public_key = keypair.public_key();
282
283 let proof = RangeProof::prove(&secret, 0, 100).unwrap();
285 assert!(proof.verify(&public_key, 100));
286
287 let proof = RangeProof::prove(&secret, 100, 100).unwrap();
289 assert!(proof.verify(&public_key, 100));
290 }
291
292 #[test]
293 fn test_range_proof_exceeds_maximum() {
294 let keypair = KeyPair::generate();
295 let secret = keypair.secret_key();
296
297 let value = 150u64;
298 let max_value = 100u64;
299
300 let result = RangeProof::prove(&secret, value, max_value);
301 assert!(result.is_err());
302 }
303
304 #[test]
305 fn test_range_proof_different_max() {
306 let keypair = KeyPair::generate();
307 let secret = keypair.secret_key();
308 let public_key = keypair.public_key();
309
310 let value = 50u64;
311 let max_value = 100u64;
312
313 let proof = RangeProof::prove(&secret, value, max_value).unwrap();
314
315 assert!(proof.verify(&public_key, max_value));
317
318 assert!(proof.verify(&public_key, 200));
320 }
321
322 #[test]
323 fn test_range_proof_serialization() {
324 let keypair = KeyPair::generate();
325 let secret = keypair.secret_key();
326 let public_key = keypair.public_key();
327
328 let value = 75u64;
329 let max_value = 1000u64;
330
331 let proof = RangeProof::prove(&secret, value, max_value).unwrap();
332 let bytes = proof.to_bytes();
333 let deserialized = RangeProof::from_bytes(&bytes).unwrap();
334
335 assert!(deserialized.verify(&public_key, max_value));
336 }
337
338 #[test]
339 fn test_batch_range_proof() {
340 let keypair = KeyPair::generate();
341 let secret = keypair.secret_key();
342 let public_key = keypair.public_key();
343
344 let values = vec![(10u64, 100u64), (50u64, 200u64), (99u64, 100u64)];
345
346 let batch_proof = BatchRangeProof::prove(&secret, &values).unwrap();
347
348 let max_values: Vec<u64> = values.iter().map(|(_, max)| *max).collect();
349 assert!(batch_proof.verify(&public_key, &max_values));
350 }
351
352 #[test]
353 fn test_batch_range_proof_one_invalid() {
354 let keypair = KeyPair::generate();
355 let secret = keypair.secret_key();
356
357 let values = vec![(10u64, 100u64), (250u64, 200u64), (99u64, 100u64)];
359
360 let result = BatchRangeProof::prove(&secret, &values);
361 assert!(result.is_err());
362 }
363
364 #[test]
365 fn test_large_values() {
366 let keypair = KeyPair::generate();
367 let secret = keypair.secret_key();
368 let public_key = keypair.public_key();
369
370 let value = 1_000_000u64;
371 let max_value = 10_000_000u64;
372
373 let proof = RangeProof::prove(&secret, value, max_value).unwrap();
374 assert!(proof.verify(&public_key, max_value));
375 }
376
377 #[test]
378 fn test_power_of_two_boundaries() {
379 let keypair = KeyPair::generate();
380 let secret = keypair.secret_key();
381 let public_key = keypair.public_key();
382
383 for power in 1..=16 {
384 let max_value = 2u64.pow(power);
385 let value = max_value / 2;
386
387 let proof = RangeProof::prove(&secret, value, max_value).unwrap();
388 assert!(proof.verify(&public_key, max_value));
389 }
390 }
391
392 #[test]
393 fn test_zero_max_value() {
394 let keypair = KeyPair::generate();
395 let secret = keypair.secret_key();
396
397 let result = RangeProof::prove(&secret, 0, 0);
398 assert!(result.is_err());
399 }
400
401 #[test]
402 fn test_different_secrets_different_proofs() {
403 let keypair1 = KeyPair::generate();
404 let keypair2 = KeyPair::generate();
405
406 let value = 50u64;
407 let max_value = 100u64;
408
409 let proof1 = RangeProof::prove(&keypair1.secret_key(), value, max_value).unwrap();
410 let proof2 = RangeProof::prove(&keypair2.secret_key(), value, max_value).unwrap();
411
412 assert_ne!(proof1.commitment(), proof2.commitment());
414 }
415}