Merge pull request #75 from poanetwork/afck-ord

Make several types Ord, PartialOrd.
This commit is contained in:
Vladimir Komendantskiy 2019-02-04 10:13:45 +00:00 committed by GitHub
commit 9ef9c3d73e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 130 additions and 5 deletions

10
src/cmp_pairing.rs Normal file
View File

@ -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())
}

View File

@ -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;
}

View File

@ -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)>,

View File

@ -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 {

View File

@ -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.",
))
));
}
};