use {
curve25519_dalek::{
digest::{ExtendableOutput, Update, XofReader},
ristretto::RistrettoPoint,
},
sha3::{Sha3XofReader, Shake256},
};
struct GeneratorsChain {
reader: Sha3XofReader,
}
impl GeneratorsChain {
fn new(label: &[u8]) -> Self {
let mut shake = Shake256::default();
shake.update(b"GeneratorsChain");
shake.update(label);
GeneratorsChain {
reader: shake.finalize_xof(),
}
}
fn fast_forward(mut self, n: usize) -> Self {
for _ in 0..n {
let mut buf = [0u8; 64];
self.reader.read(&mut buf);
}
self
}
}
impl Default for GeneratorsChain {
fn default() -> Self {
Self::new(&[])
}
}
impl Iterator for GeneratorsChain {
type Item = RistrettoPoint;
fn next(&mut self) -> Option<Self::Item> {
let mut uniform_bytes = [0u8; 64];
self.reader.read(&mut uniform_bytes);
Some(RistrettoPoint::from_uniform_bytes(&uniform_bytes))
}
fn size_hint(&self) -> (usize, Option<usize>) {
(usize::max_value(), None)
}
}
#[allow(non_snake_case)]
#[derive(Clone)]
pub struct BulletproofGens {
pub gens_capacity: usize,
G_vec: Vec<RistrettoPoint>,
H_vec: Vec<RistrettoPoint>,
}
impl BulletproofGens {
pub fn new(gens_capacity: usize) -> Self {
let mut gens = BulletproofGens {
gens_capacity: 0,
G_vec: Vec::new(),
H_vec: Vec::new(),
};
gens.increase_capacity(gens_capacity);
gens
}
pub fn increase_capacity(&mut self, new_capacity: usize) {
if self.gens_capacity >= new_capacity {
return;
}
let label = [b'G'];
self.G_vec.extend(
&mut GeneratorsChain::new(&[label, [b'G']].concat())
.fast_forward(self.gens_capacity)
.take(new_capacity - self.gens_capacity),
);
self.H_vec.extend(
&mut GeneratorsChain::new(&[label, [b'H']].concat())
.fast_forward(self.gens_capacity)
.take(new_capacity - self.gens_capacity),
);
self.gens_capacity = new_capacity;
}
#[allow(non_snake_case)]
pub(crate) fn G(&self, n: usize) -> impl Iterator<Item = &RistrettoPoint> {
GensIter {
array: &self.G_vec,
n,
gen_idx: 0,
}
}
#[allow(non_snake_case)]
pub(crate) fn H(&self, n: usize) -> impl Iterator<Item = &RistrettoPoint> {
GensIter {
array: &self.H_vec,
n,
gen_idx: 0,
}
}
}
struct GensIter<'a> {
array: &'a Vec<RistrettoPoint>,
n: usize,
gen_idx: usize,
}
impl<'a> Iterator for GensIter<'a> {
type Item = &'a RistrettoPoint;
fn next(&mut self) -> Option<Self::Item> {
if self.gen_idx >= self.n {
None
} else {
let cur_gen = self.gen_idx;
self.gen_idx += 1;
Some(&self.array[cur_gen])
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.n - self.gen_idx;
(size, Some(size))
}
}