use crate::constants::BASEPOINT;
use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
use curve25519_dalek::scalar::Scalar;
use sha2::Sha512;
use std::collections::HashSet;
#[derive(Debug, Clone)]
pub struct PublicSet(pub Vec<RistrettoPoint>);
impl PublicSet {
pub fn len(&self) -> usize {
self.0.len()
}
pub fn duplicates_exist(&self) -> bool {
let compressed_points: Vec<CompressedRistretto> =
self.0.iter().map(|point| point.compress()).collect();
let hashable_slice: Vec<&[u8; 32]> =
compressed_points.iter().map(|cp| cp.as_bytes()).collect();
let uniques: HashSet<_> = hashable_slice.iter().collect();
self.0.len() != uniques.len()
}
pub fn hashed_pubkey(&self) -> RistrettoPoint {
let first_pubkey = &self.0[0].compress();
RistrettoPoint::hash_from_bytes::<Sha512>(first_pubkey.as_bytes())
}
pub fn to_bytes(&self) -> Vec<u8> {
self.0
.iter()
.map(|point| point.compress().to_bytes().to_vec())
.flatten()
.collect()
}
pub fn to_keys(&self) -> Vec<CompressedRistretto> {
self.0.iter().map(|key| key.compress()).collect()
}
}
#[derive(Debug, Clone)]
pub struct PrivateSet(pub(crate) Vec<Scalar>);
impl PrivateSet {
pub fn new(scalars: Vec<Scalar>) -> Self {
PrivateSet(scalars)
}
pub fn to_public_set(&self) -> PublicSet {
let public_keys = self
.0
.iter()
.map(|&x| x * BASEPOINT)
.collect::<Vec<RistrettoPoint>>();
PublicSet(public_keys)
}
pub fn compute_key_images(
&self,
signers_basepoint: &RistrettoPoint,
) -> Vec<CompressedRistretto> {
self.0
.iter()
.map(|priv_key| (priv_key * signers_basepoint).compress())
.collect()
}
pub fn len(&self) -> usize {
self.0.len()
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::tests_helper::*;
#[test]
fn private_set_to_public_set() {
let private_set = generate_private_set(10);
let public_set = private_set.to_public_set();
assert_eq!(private_set.len(), public_set.len());
for i in 0..private_set.len() {
match (private_set.0.get(i), public_set.0.get(i)) {
(Some(private_key), Some(expected_public_key)) => {
let public_key = private_key * &BASEPOINT;
assert_eq!(public_key, *expected_public_key);
}
_ => panic!("could not get the private/public key at index {} ", i),
}
}
}
#[test]
fn check_duplicates_exist() {
let private_set = generate_private_set(10);
let mut public_set = private_set.to_public_set();
let dup_exists = public_set.duplicates_exist();
assert!(!dup_exists);
let last_element = public_set.0.last().unwrap().clone();
public_set.0[0] = last_element;
let dup_exists = public_set.duplicates_exist();
assert!(dup_exists);
}
}