solana/zk-token-sdk/src/range_proof/generators.rs

157 lines
4.0 KiB
Rust

use {
curve25519_dalek::{
digest::{ExtendableOutput, Update, XofReader},
ristretto::RistrettoPoint,
},
sha3::{Sha3XofReader, Shake256},
};
/// Generators for Pedersen vector commitments.
///
/// The code is copied from https://github.com/dalek-cryptography/bulletproofs for now...
struct GeneratorsChain {
reader: Sha3XofReader,
}
impl GeneratorsChain {
/// Creates a chain of generators, determined by the hash of `label`.
fn new(label: &[u8]) -> Self {
let mut shake = Shake256::default();
shake.update(b"GeneratorsChain");
shake.update(label);
GeneratorsChain {
reader: shake.finalize_xof(),
}
}
/// Advances the reader n times, squeezing and discarding
/// the result.
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 {
/// The maximum number of usable generators.
pub gens_capacity: usize,
/// Precomputed \\(\mathbf G\\) generators.
G_vec: Vec<RistrettoPoint>,
/// Precomputed \\(\mathbf H\\) generators.
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 new_aggregate(gens_capacities: Vec<usize>) -> Vec<BulletproofGens> {
// let mut gens_vector = Vec::new();
// for (capacity, i) in gens_capacities.iter().enumerate() {
// gens_vector.push(BulletproofGens::new(capacity, &i.to_le_bytes()));
// }
// gens_vector
// }
/// Increases the generators' capacity to the amount specified.
/// If less than or equal to the current capacity, does nothing.
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))
}
}