mirror of
https://github.com/serai-dex/serai.git
synced 2025-03-09 10:14:50 +00:00
Document multiexp
Bumps the crate version to enable publishing.
This commit is contained in:
parent
be61bff074
commit
d714f2202d
4 changed files with 20 additions and 5 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -4695,7 +4695,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "multiexp"
|
name = "multiexp"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dalek-ff-group",
|
"dalek-ff-group",
|
||||||
"ff",
|
"ff",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "multiexp"
|
name = "multiexp"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
description = "Multiexponentation algorithms for ff/group"
|
description = "Multiexponentation algorithms for ff/group"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/serai-dex/serai/tree/develop/crypto/multiexp"
|
repository = "https://github.com/serai-dex/serai/tree/develop/crypto/multiexp"
|
||||||
|
|
|
@ -7,19 +7,21 @@ use group::Group;
|
||||||
|
|
||||||
use crate::{multiexp, multiexp_vartime};
|
use crate::{multiexp, multiexp_vartime};
|
||||||
|
|
||||||
#[cfg(feature = "batch")]
|
/// A batch verifier intended to verify a series of statements are each equivalent to zero.
|
||||||
#[derive(Clone, Zeroize)]
|
#[derive(Clone, Zeroize)]
|
||||||
pub struct BatchVerifier<Id: Copy + Zeroize, G: Group + Zeroize>(Vec<(Id, Vec<(G::Scalar, G)>)>);
|
pub struct BatchVerifier<Id: Copy + Zeroize, G: Group + Zeroize>(Vec<(Id, Vec<(G::Scalar, G)>)>);
|
||||||
|
|
||||||
#[cfg(feature = "batch")]
|
|
||||||
impl<Id: Copy + Zeroize, G: Group + Zeroize> BatchVerifier<Id, G>
|
impl<Id: Copy + Zeroize, G: Group + Zeroize> BatchVerifier<Id, G>
|
||||||
where
|
where
|
||||||
<G as Group>::Scalar: PrimeFieldBits + Zeroize,
|
<G as Group>::Scalar: PrimeFieldBits + Zeroize,
|
||||||
{
|
{
|
||||||
|
/// Create a new batch verifier, expected to verify the following amount of statements.
|
||||||
|
/// This is a size hint and is not required to be accurate.
|
||||||
pub fn new(capacity: usize) -> BatchVerifier<Id, G> {
|
pub fn new(capacity: usize) -> BatchVerifier<Id, G> {
|
||||||
BatchVerifier(Vec::with_capacity(capacity))
|
BatchVerifier(Vec::with_capacity(capacity))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Queue a statement for batch verification.
|
||||||
pub fn queue<R: RngCore + CryptoRng, I: IntoIterator<Item = (G::Scalar, G)>>(
|
pub fn queue<R: RngCore + CryptoRng, I: IntoIterator<Item = (G::Scalar, G)>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
|
@ -71,6 +73,7 @@ where
|
||||||
self.0.push((id, pairs.into_iter().map(|(scalar, point)| (scalar * u, point)).collect()));
|
self.0.push((id, pairs.into_iter().map(|(scalar, point)| (scalar * u, point)).collect()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Perform batch verification, returning a boolean of if the statements equaled zero.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn verify_core(&self) -> bool {
|
pub fn verify_core(&self) -> bool {
|
||||||
let mut flat = self.0.iter().flat_map(|pairs| pairs.1.iter()).cloned().collect::<Vec<_>>();
|
let mut flat = self.0.iter().flat_map(|pairs| pairs.1.iter()).cloned().collect::<Vec<_>>();
|
||||||
|
@ -79,12 +82,14 @@ where
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Perform batch verification, zeroizing the statements verified.
|
||||||
pub fn verify(mut self) -> bool {
|
pub fn verify(mut self) -> bool {
|
||||||
let res = self.verify_core();
|
let res = self.verify_core();
|
||||||
self.zeroize();
|
self.zeroize();
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Perform batch verification in variable time.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn verify_vartime(&self) -> bool {
|
pub fn verify_vartime(&self) -> bool {
|
||||||
multiexp_vartime(&self.0.iter().flat_map(|pairs| pairs.1.iter()).cloned().collect::<Vec<_>>())
|
multiexp_vartime(&self.0.iter().flat_map(|pairs| pairs.1.iter()).cloned().collect::<Vec<_>>())
|
||||||
|
@ -92,6 +97,9 @@ where
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Perform a binary search to identify which statement does not equal 0, returning None if all
|
||||||
|
/// statements do. This function will only return the ID of one invalid statement, even if
|
||||||
|
/// multiple are invalid.
|
||||||
// A constant time variant may be beneficial for robust protocols
|
// A constant time variant may be beneficial for robust protocols
|
||||||
pub fn blame_vartime(&self) -> Option<Id> {
|
pub fn blame_vartime(&self) -> Option<Id> {
|
||||||
let mut slice = self.0.as_slice();
|
let mut slice = self.0.as_slice();
|
||||||
|
@ -115,12 +123,16 @@ where
|
||||||
.map(|(id, _)| *id)
|
.map(|(id, _)| *id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Perform constant time batch verification, and if verification fails, identify one faulty
|
||||||
|
/// statement in variable time.
|
||||||
pub fn verify_with_vartime_blame(mut self) -> Result<(), Id> {
|
pub fn verify_with_vartime_blame(mut self) -> Result<(), Id> {
|
||||||
let res = if self.verify_core() { Ok(()) } else { Err(self.blame_vartime().unwrap()) };
|
let res = if self.verify_core() { Ok(()) } else { Err(self.blame_vartime().unwrap()) };
|
||||||
self.zeroize();
|
self.zeroize();
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Perform variable time batch verification, and if verification fails, identify one faulty
|
||||||
|
/// statement in variable time.
|
||||||
pub fn verify_vartime_with_vartime_blame(&self) -> Result<(), Id> {
|
pub fn verify_vartime_with_vartime_blame(&self) -> Result<(), Id> {
|
||||||
if self.verify_vartime() {
|
if self.verify_vartime() {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -160,7 +160,8 @@ fn algorithm(len: usize) -> Algorithm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Performs a multiexp, automatically selecting the optimal algorithm based on amount of pairs
|
/// Performs a multiexponentation, automatically selecting the optimal algorithm based on the
|
||||||
|
/// amount of pairs.
|
||||||
pub fn multiexp<G: Group>(pairs: &[(G::Scalar, G)]) -> G
|
pub fn multiexp<G: Group>(pairs: &[(G::Scalar, G)]) -> G
|
||||||
where
|
where
|
||||||
G::Scalar: PrimeFieldBits + Zeroize,
|
G::Scalar: PrimeFieldBits + Zeroize,
|
||||||
|
@ -173,6 +174,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs a multiexponentation in variable time, automatically selecting the optimal algorithm
|
||||||
|
/// based on the amount of pairs.
|
||||||
pub fn multiexp_vartime<G: Group>(pairs: &[(G::Scalar, G)]) -> G
|
pub fn multiexp_vartime<G: Group>(pairs: &[(G::Scalar, G)]) -> G
|
||||||
where
|
where
|
||||||
G::Scalar: PrimeFieldBits,
|
G::Scalar: PrimeFieldBits,
|
||||||
|
|
Loading…
Reference in a new issue