use super::group::{GroupElement, VartimeMultiscalarMul, GROUP_BASEPOINT_COMPRESSED}; use super::scalar::Scalar; use digest::{ExtendableOutput, Input, XofReader}; use sha3::Shake256; #[derive(Debug)] pub struct MultiCommitGens { pub n: usize, pub G: Vec, pub h: GroupElement, } impl MultiCommitGens { pub fn new(n: usize, label: &[u8]) -> Self { let mut shake = Shake256::default(); shake.input(label); shake.input(GROUP_BASEPOINT_COMPRESSED.as_bytes()); let mut reader = shake.xof_result(); let mut gens: Vec = Vec::new(); let mut uniform_bytes = [0u8; 64]; for _ in 0..n + 1 { reader.read(&mut uniform_bytes); gens.push(GroupElement::from_uniform_bytes(&uniform_bytes)); } MultiCommitGens { n, G: gens[0..n].to_vec(), h: gens[n], } } pub fn clone(&self) -> MultiCommitGens { MultiCommitGens { n: self.n, h: self.h, G: self.G.clone(), } } pub fn split_at_mut(&mut self, mid: usize) -> (MultiCommitGens, MultiCommitGens) { let (G1, G2) = self.G.split_at_mut(mid); ( MultiCommitGens { n: G1.len(), G: G1.to_vec(), h: self.h, }, MultiCommitGens { n: G2.len(), G: G2.to_vec(), h: self.h, }, ) } } pub trait Commitments { fn commit(&self, blind: &Scalar, gens_n: &MultiCommitGens) -> GroupElement; } impl Commitments for Scalar { fn commit(&self, blind: &Scalar, gens_n: &MultiCommitGens) -> GroupElement { assert!(gens_n.n == 1); GroupElement::vartime_multiscalar_mul(&[*self, *blind], &[gens_n.G[0], gens_n.h]) } } impl Commitments for Vec { fn commit(&self, blind: &Scalar, gens_n: &MultiCommitGens) -> GroupElement { assert!(gens_n.n == self.len()); GroupElement::vartime_multiscalar_mul(self, &gens_n.G) + blind * &gens_n.h } } impl Commitments for [Scalar] { fn commit(&self, blind: &Scalar, gens_n: &MultiCommitGens) -> GroupElement { assert_eq!(gens_n.n, self.len()); GroupElement::vartime_multiscalar_mul(self, &gens_n.G) + blind * &gens_n.h } } impl Commitments for Vec { fn commit(&self, blind: &Scalar, gens_n: &MultiCommitGens) -> GroupElement { assert!(gens_n.n == self.len()); let mut comm = blind * &gens_n.h; for i in 0..self.len() { if self[i] { comm = comm + gens_n.G[i]; } } comm } } impl Commitments for [bool] { fn commit(&self, blind: &Scalar, gens_n: &MultiCommitGens) -> GroupElement { assert!(gens_n.n == self.len()); let mut comm = blind * &gens_n.h; for i in 0..self.len() { if self[i] { comm = comm + gens_n.G[i]; } } comm } }