use crate::pedersen::{PedersenCommitment, PedersenParams};
use curve25519_dalek::scalar::Scalar;
use rand::rngs::OsRng;
use rand::Rng;
#[derive(Debug, Clone)]
pub struct BindingVerifier {
pub attempts: usize,
}
impl BindingVerifier {
pub fn new(attempts: usize) -> Self {
Self { attempts }
}
pub fn test_binding(&self, params: &PedersenParams, value: u64) -> bool {
let scalar_val = Scalar::from(value);
let (commitment, original_opening) = PedersenCommitment::commit(params, &scalar_val);
for _ in 0..self.attempts {
let mut rng = OsRng;
let fake_value: u64 = rng.gen_range(0..u64::MAX);
if fake_value == value {
continue;
}
let fake_scalar = Scalar::from(fake_value);
let fake_randomness = Scalar::random(&mut OsRng);
let fake_opening = crate::pedersen::PedersenOpening {
value: fake_scalar,
randomness: fake_randomness,
};
if PedersenCommitment::verify(params, &fake_opening, &commitment) {
return false;
}
}
PedersenCommitment::verify(params, &original_opening, &commitment)
}
pub fn test_binding_batch(&self, params: &PedersenParams, values: &[u64]) -> bool {
values.iter().all(|&v| self.test_binding(params, v))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn binding_holds_single() {
let params = PedersenParams::default();
let verifier = BindingVerifier::new(100);
assert!(verifier.test_binding(¶ms, 42));
}
#[test]
fn binding_holds_batch() {
let params = PedersenParams::default();
let verifier = BindingVerifier::new(50);
assert!(verifier.test_binding_batch(¶ms, &[1, 100, 999, 0]));
}
#[test]
fn binding_holds_zero_value() {
let params = PedersenParams::default();
let verifier = BindingVerifier::new(50);
assert!(verifier.test_binding(¶ms, 0));
}
}