|
7 | 7 | //! ```rust |
8 | 8 | //! # use fastcrypto::bulletproofs::*; |
9 | 9 | //! use rand::{thread_rng, RngCore}; |
| 10 | +//! use fastcrypto::bulletproofs::Range::Bits16; |
10 | 11 | //! # use fastcrypto::groups::ristretto255::RistrettoScalar; |
11 | 12 | //! # use fastcrypto::groups::Scalar; |
12 | 13 | //! let value = 300; |
13 | | -//! let bits = 16; |
| 14 | +//! let range = Bits16; |
14 | 15 | //! let output = |
15 | | -//! RangeProof::prove(value, bits, b"MY_DOMAIN", &mut thread_rng()).unwrap(); |
16 | | -//! assert!(output.proof.verify(&output.commitment, &output.blinding, bits, b"MY_DOMAIN").is_ok()); |
| 16 | +//! RangeProof::prove(value, &range, b"MY_DOMAIN", &mut thread_rng()).unwrap(); |
| 17 | +//! assert!(output.proof.verify(&output.commitment, &output.blinding, &range, b"MY_DOMAIN").is_ok()); |
17 | 18 | //! ``` |
18 | 19 |
|
19 | 20 | use crate::error::FastCryptoError::{GeneralOpaqueError, InvalidInput, InvalidProof}; |
@@ -55,15 +56,25 @@ pub struct AggregateRangeProofOutput { |
55 | 56 | } |
56 | 57 |
|
57 | 58 | pub enum Range { |
| 59 | + /// The range [0,...,2^8). |
58 | 60 | Bits8, |
| 61 | + |
| 62 | + /// The range [0,...,2^16). |
59 | 63 | Bits16, |
| 64 | + |
| 65 | + /// The range [0,...,2^32). |
60 | 66 | Bits32, |
| 67 | + |
| 68 | + /// The range [0,...,2^64). |
61 | 69 | Bits64, |
62 | 70 | } |
63 | 71 |
|
64 | 72 | impl Range { |
65 | | - pub fn is_in_range(&self, value: &u64) -> bool { |
66 | | - value.ilog2() <= self.upper_bound_in_bits() |
| 73 | + pub fn is_in_range(&self, value: u64) -> bool { |
| 74 | + if value == 0 { |
| 75 | + return true; |
| 76 | + } |
| 77 | + value.ilog2() < self.upper_bound_in_bits() |
67 | 78 | } |
68 | 79 |
|
69 | 80 | fn upper_bound_in_bits(&self) -> u32 { |
@@ -159,7 +170,7 @@ impl RangeProof { |
159 | 170 | domain: &'static [u8], |
160 | 171 | rng: &mut impl AllowedRng, |
161 | 172 | ) -> FastCryptoResult<AggregateRangeProofOutput> { |
162 | | - if values.iter().any(|v| !range.is_in_range(v)) |
| 173 | + if values.iter().any(|&v| !range.is_in_range(v)) |
163 | 174 | || blindings.len() != values.len() |
164 | 175 | || !values.len().is_power_of_two() |
165 | 176 | { |
@@ -227,3 +238,29 @@ impl RangeProof { |
227 | 238 | .map_err(|_| InvalidProof) |
228 | 239 | } |
229 | 240 | } |
| 241 | + |
| 242 | +#[test] |
| 243 | +fn test_is_in_range() { |
| 244 | + assert!(Range::Bits8.is_in_range(0)); |
| 245 | + assert!(Range::Bits8.is_in_range(255)); |
| 246 | + assert!(!Range::Bits8.is_in_range(256)); |
| 247 | + assert!(Range::Bits16.is_in_range(0)); |
| 248 | + assert!(Range::Bits16.is_in_range(65535)); |
| 249 | + assert!(!Range::Bits16.is_in_range(65536)); |
| 250 | + assert!(Range::Bits32.is_in_range(0)); |
| 251 | + assert!(Range::Bits32.is_in_range(4294967295)); |
| 252 | + assert!(!Range::Bits32.is_in_range(4294967296)); |
| 253 | + assert!(Range::Bits64.is_in_range(0)); |
| 254 | + assert!(Range::Bits64.is_in_range(u64::MAX)); |
| 255 | +} |
| 256 | + |
| 257 | +#[test] |
| 258 | +fn test_range_proof_valid() { |
| 259 | + use rand::thread_rng; |
| 260 | + let range = Range::Bits32; |
| 261 | + let output = RangeProof::prove(1u64, &range, b"NARWHAL", &mut thread_rng()).unwrap(); |
| 262 | + assert!(output |
| 263 | + .proof |
| 264 | + .verify(&output.commitment, &output.blinding, &range, b"NARWHAL") |
| 265 | + .is_ok()); |
| 266 | +} |
0 commit comments