Merge pull request #75 from poanetwork/afck-ord
Make several types Ord, PartialOrd.
This commit is contained in:
commit
9ef9c3d73e
|
@ -0,0 +1,10 @@
|
|||
use std::cmp::Ordering;
|
||||
|
||||
use pairing::{CurveAffine, CurveProjective};
|
||||
|
||||
/// Compares two curve elements and returns their `Ordering`.
|
||||
pub fn cmp_projective<G: CurveProjective>(x: &G, y: &G) -> Ordering {
|
||||
let xc = x.into_affine().into_compressed();
|
||||
let yc = y.into_affine().into_compressed();
|
||||
xc.as_ref().cmp(yc.as_ref())
|
||||
}
|
|
@ -3,6 +3,7 @@ use pairing::{Field, PrimeField};
|
|||
|
||||
/// A conversion into an element of the field `Fr`.
|
||||
pub trait IntoFr: Copy {
|
||||
/// Converts `self` to a field element.
|
||||
fn into_fr(self) -> Fr;
|
||||
}
|
||||
|
||||
|
|
82
src/lib.rs
82
src/lib.rs
|
@ -13,6 +13,7 @@
|
|||
|
||||
pub use pairing;
|
||||
|
||||
mod cmp_pairing;
|
||||
mod into_fr;
|
||||
mod secret;
|
||||
|
||||
|
@ -20,6 +21,7 @@ pub mod error;
|
|||
pub mod poly;
|
||||
pub mod serde_impl;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ptr::copy_nonoverlapping;
|
||||
|
@ -34,11 +36,13 @@ use rand_chacha::ChaChaRng;
|
|||
use serde_derive::{Deserialize, Serialize};
|
||||
use tiny_keccak::sha3_256;
|
||||
|
||||
use crate::cmp_pairing::cmp_projective;
|
||||
use crate::error::{Error, FromBytesError, FromBytesResult, Result};
|
||||
use crate::into_fr::IntoFr;
|
||||
use crate::poly::{Commitment, Poly};
|
||||
use crate::secret::{clear_fr, ContainsSecret, MemRange, FR_SIZE};
|
||||
|
||||
pub use crate::into_fr::IntoFr;
|
||||
|
||||
#[cfg(not(feature = "use-insecure-test-only-mock-crypto"))]
|
||||
pub use pairing::bls12_381::{Bls12 as PEngine, Fr, FrRepr, G1Affine, G2Affine, G1, G2};
|
||||
|
||||
|
@ -78,6 +82,18 @@ impl fmt::Debug for PublicKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for PublicKey {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(&other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for PublicKey {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
cmp_projective(&self.0, &other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl PublicKey {
|
||||
/// Returns `true` if the signature matches the element of `G2`.
|
||||
pub fn verify_g2<H: Into<G2Affine>>(&self, sig: &Signature, hash: H) -> bool {
|
||||
|
@ -129,7 +145,7 @@ impl PublicKey {
|
|||
}
|
||||
|
||||
/// A public key share.
|
||||
#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct PublicKeyShare(PublicKey);
|
||||
|
||||
impl fmt::Debug for PublicKeyShare {
|
||||
|
@ -175,6 +191,18 @@ impl PublicKeyShare {
|
|||
#[derive(Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||
pub struct Signature(#[serde(with = "serde_impl::projective")] G2);
|
||||
|
||||
impl PartialOrd for Signature {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(&other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Signature {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
cmp_projective(&self.0, &other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Distribution<Signature> for Standard {
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Signature {
|
||||
Signature(rng.gen04())
|
||||
|
@ -223,7 +251,7 @@ impl Signature {
|
|||
|
||||
/// A signature share.
|
||||
// Note: Random signature shares can be generated for testing.
|
||||
#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct SignatureShare(pub Signature);
|
||||
|
||||
impl Distribution<SignatureShare> for Standard {
|
||||
|
@ -455,6 +483,22 @@ impl Hash for Ciphertext {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Ciphertext {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(&other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Ciphertext {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
let Ciphertext(ref u0, ref v0, ref w0) = self;
|
||||
let Ciphertext(ref u1, ref v1, ref w1) = other;
|
||||
cmp_projective(u0, u1)
|
||||
.then(v0.cmp(v1))
|
||||
.then(cmp_projective(w0, w1))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ciphertext {
|
||||
/// Returns `true` if this is a valid ciphertext. This check is necessary to prevent
|
||||
/// chosen-ciphertext attacks.
|
||||
|
@ -520,6 +564,38 @@ impl PublicKeySet {
|
|||
}
|
||||
|
||||
/// Combines the shares into a signature that can be verified with the main public key.
|
||||
///
|
||||
/// The validity of the shares is not checked: If one of them is invalid, the resulting
|
||||
/// signature also is. Only returns an error if there is a duplicate index or too few shares.
|
||||
///
|
||||
/// Validity of signature shares should be checked beforehand, or validity of the result
|
||||
/// afterwards:
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate rand;
|
||||
/// #
|
||||
/// # use std::collections::BTreeMap;
|
||||
/// # use threshold_crypto::SecretKeySet;
|
||||
/// #
|
||||
/// let sk_set = SecretKeySet::random(3, &mut rand::thread_rng());
|
||||
/// let sk_shares: Vec<_> = (0..6).map(|i| sk_set.secret_key_share(i)).collect();
|
||||
/// let pk_set = sk_set.public_keys();
|
||||
/// let msg = "Happy birthday! If this is signed, at least four people remembered!";
|
||||
///
|
||||
/// // Create four signature shares for the message.
|
||||
/// let sig_shares: BTreeMap<_, _> = (0..4).map(|i| (i, sk_shares[i].sign(msg))).collect();
|
||||
///
|
||||
/// // Validate the signature shares.
|
||||
/// for (i, sig_share) in &sig_shares {
|
||||
/// assert!(pk_set.public_key_share(*i).verify(sig_share, msg));
|
||||
/// }
|
||||
///
|
||||
/// // Combine them to produce the main signature.
|
||||
/// let sig = pk_set.combine_signatures(&sig_shares).expect("not enough shares");
|
||||
///
|
||||
/// // Validate the main signature. If the shares were valid, this can't fail.
|
||||
/// assert!(pk_set.public_key().verify(&sig, msg));
|
||||
/// ```
|
||||
pub fn combine_signatures<'a, T, I>(&self, shares: I) -> Result<Signature>
|
||||
where
|
||||
I: IntoIterator<Item = (T, &'a SignatureShare)>,
|
||||
|
|
40
src/poly.rs
40
src/poly.rs
|
@ -17,6 +17,7 @@
|
|||
//! polynomials (in two variables) over a field `Fr`, as well as their _commitments_ in `G`.
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::mem::size_of_val;
|
||||
|
@ -27,6 +28,7 @@ use rand::Rng;
|
|||
use rand04_compat::RngExt;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
use crate::cmp_pairing::cmp_projective;
|
||||
use crate::error::{Error, Result};
|
||||
use crate::into_fr::IntoFr;
|
||||
use crate::secret::{clear_fr, ContainsSecret, MemRange, Safe};
|
||||
|
@ -436,6 +438,24 @@ pub struct Commitment {
|
|||
pub(super) coeff: Vec<G1>,
|
||||
}
|
||||
|
||||
impl PartialOrd for Commitment {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(&other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Commitment {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.coeff.len().cmp(&other.coeff.len()).then_with(|| {
|
||||
self.coeff
|
||||
.iter()
|
||||
.zip(&other.coeff)
|
||||
.find(|(x, y)| x != y)
|
||||
.map_or(Ordering::Equal, |(x, y)| cmp_projective(x, y))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Commitment {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.coeff.len().hash(state);
|
||||
|
@ -657,6 +677,24 @@ impl Hash for BivarCommitment {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for BivarCommitment {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(&other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for BivarCommitment {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.degree.cmp(&other.degree).then_with(|| {
|
||||
self.coeff
|
||||
.iter()
|
||||
.zip(&other.coeff)
|
||||
.find(|(x, y)| x != y)
|
||||
.map_or(Ordering::Equal, |(x, y)| cmp_projective(x, y))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl BivarCommitment {
|
||||
/// Returns the polynomial's degree: It is the same in both variables.
|
||||
pub fn degree(&self) -> usize {
|
||||
|
@ -760,7 +798,7 @@ mod tests {
|
|||
let x_pow_1 = Poly::monomial(1);
|
||||
let poly = x_pow_3 * 5 + x_pow_1 - 2;
|
||||
|
||||
let coeff: Vec<_> = [-2, 1, 0, 5].into_iter().map(IntoFr::into_fr).collect();
|
||||
let coeff: Vec<_> = [-2, 1, 0, 5].iter().map(IntoFr::into_fr).collect();
|
||||
assert_eq!(Poly { coeff }, poly);
|
||||
let samples = vec![(-1, -8), (2, 40), (3, 136), (5, 628)];
|
||||
for &(x, y) in &samples {
|
||||
|
|
|
@ -94,7 +94,7 @@ impl<'de> Deserialize<'de> for crate::SecretKey {
|
|||
return Err(de::Error::invalid_value(
|
||||
de::Unexpected::Other(&"Number outside of prime field."),
|
||||
&"Valid prime field element.",
|
||||
))
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue