Skip to content

Commit

Permalink
Replace bls12_381
Browse files Browse the repository at this point in the history
  • Loading branch information
moshababo committed Oct 23, 2023
1 parent 5c7c527 commit cae1291
Show file tree
Hide file tree
Showing 16 changed files with 103 additions and 47 deletions.
4 changes: 2 additions & 2 deletions node/actors/consensus/src/leader/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ pub(crate) enum Error {
current_view: validator::ViewNumber,
},
#[error("received replica commit message with invalid signature")]
ReplicaCommitInvalidSignature(#[source] crypto::bls12_381::Error),
ReplicaCommitInvalidSignature(#[source] crypto::bn254::Error),
#[error("received replica prepare message with invalid signature")]
ReplicaPrepareInvalidSignature(#[source] crypto::bls12_381::Error),
ReplicaPrepareInvalidSignature(#[source] crypto::bn254::Error),
#[error("received replica prepare message with invalid high QC")]
ReplicaPrepareInvalidHighQC(#[source] anyhow::Error),
}
Expand Down
4 changes: 2 additions & 2 deletions node/actors/consensus/src/replica/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ pub(crate) enum Error {
current_phase: validator::Phase,
},
#[error("received leader commit message with invalid signature")]
LeaderCommitInvalidSignature(#[source] crypto::bls12_381::Error),
LeaderCommitInvalidSignature(#[source] crypto::bn254::Error),
#[error("received leader prepare message with invalid signature")]
LeaderPrepareInvalidSignature(#[source] crypto::bls12_381::Error),
LeaderPrepareInvalidSignature(#[source] crypto::bn254::Error),
#[error("received leader commit message with invalid justification")]
LeaderCommitInvalidJustification(#[source] anyhow::Error),
#[error("received leader prepare message with empty map in the justification")]
Expand Down
4 changes: 2 additions & 2 deletions node/actors/network/src/consensus/handshake/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{frame, noise};
use anyhow::Context as _;
use concurrency::{ctx, time};
use crypto::{bls12_381, ByteFmt};
use crypto::{bn254, ByteFmt};
use roles::{node, validator};
use schema::{proto::network::consensus as proto, read_required, ProtoFmt};

Expand Down Expand Up @@ -43,7 +43,7 @@ pub(super) enum Error {
#[error("unexpected peer")]
PeerMismatch,
#[error("validator signature {0}")]
Signature(#[from] bls12_381::Error),
Signature(#[from] bn254::Error),
#[error("stream {0}")]
Stream(#[source] anyhow::Error),
}
Expand Down
3 changes: 0 additions & 3 deletions node/libs/crypto/src/bn254/error.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#[derive(Debug, thiserror::Error)]
pub enum Error {
/// Signature verification failure
#[error("Failed to decode secret key: TODO(moshababo)")]
DecodeFailure,
/// Signature verification failure
#[error("Signature verification failure: {0:?}")]
SignatureVerification(bn254::Error),
Expand Down
32 changes: 28 additions & 4 deletions node/libs/crypto/src/bn254/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
use std::collections::BTreeMap;

use anyhow::anyhow;
use bn254::{ECDSA, PrivateKey};
use bn254::{PrivateKey, ECDSA};
use rand::Rng;

use crate::bn254::error::Error;
pub use crate::bn254::error::Error;
use crate::ByteFmt;

mod error;

mod testonly;
#[cfg(test)]
mod tests;

Expand All @@ -36,7 +37,6 @@ impl SecretKey {
}
}


impl ByteFmt for SecretKey {
fn decode(bytes: &[u8]) -> anyhow::Result<Self> {
bn254::PrivateKey::try_from(bytes)
Expand Down Expand Up @@ -119,7 +119,8 @@ impl ByteFmt for Signature {
.map_err(|err| anyhow!("Error decoding signature: {err:?}"))
}
fn encode(&self) -> Vec<u8> {
self.0.to_compressed().unwrap() }
self.0.to_compressed().unwrap()
}
}

impl PartialOrd for Signature {
Expand Down Expand Up @@ -174,3 +175,26 @@ impl AggregateSignature {
Ok(())
}
}

impl ByteFmt for AggregateSignature {
fn decode(bytes: &[u8]) -> anyhow::Result<Self> {
let signature = Signature::decode(bytes)?;
Ok(AggregateSignature(signature))
}

fn encode(&self) -> Vec<u8> {
Signature::encode(&self.0)
}
}

impl PartialOrd for AggregateSignature {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for AggregateSignature {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
ByteFmt::encode(self).cmp(&ByteFmt::encode(other))
}
}
35 changes: 35 additions & 0 deletions node/libs/crypto/src/bn254/testonly.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//! Random key generation, intended for use in testing

use super::{AggregateSignature, ByteFmt, PublicKey, SecretKey, Signature};
use rand::{distributions::Standard, prelude::Distribution, Rng};

/// Generates a random SecretKey. This is meant for testing purposes.
impl Distribution<SecretKey> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> SecretKey {
SecretKey::decode(&rng.gen::<[u8; 32]>()).unwrap()
}
}

/// Generates a random Signature. This is meant for testing purposes.
impl Distribution<Signature> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Signature {
let key = rng.gen::<SecretKey>();
let msg = rng.gen::<[u8; 4]>();
key.sign(&msg)
}
}

/// Generates a random AggregateSignature. This is meant for testing purposes.
impl Distribution<AggregateSignature> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> AggregateSignature {
let sig: Signature = self.sample(rng);
AggregateSignature(sig)
}
}

/// Generates a random PublicKey. This is meant for testing purposes.
impl Distribution<PublicKey> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> PublicKey {
rng.gen::<SecretKey>().public()
}
}
5 changes: 2 additions & 3 deletions node/libs/crypto/src/bn254/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::bn254::{AggregateSignature, PublicKey, SecretKey, Signature, ByteFmt};
use crate::bn254::{AggregateSignature, ByteFmt, PublicKey, SecretKey, Signature};
use rand::{rngs::StdRng, Rng, SeedableRng};
use std::iter::repeat_with;

Expand Down Expand Up @@ -63,11 +63,10 @@ fn aggregate_signature_failure_smoke() {
assert!(agg_sig.verify(pks.iter().map(|pk| (&msg[..], pk))).is_err())
}


#[test]
fn aggregate_signature_distinct_messages() {
let mut rng = StdRng::seed_from_u64(29483920);
let num_keys = 6;
let num_keys = 5;
let num_distinct = 2;

// Use an arbitrary 5 keys for the smoke test
Expand Down
1 change: 0 additions & 1 deletion node/libs/crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

pub use fmt::*;

pub mod bls12_381;
pub mod bn254;
pub mod ed25519;
mod fmt;
Expand Down
23 changes: 12 additions & 11 deletions node/libs/roles/src/validator/keys/aggregate_signature.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
use super::{Error, PublicKey, Signature};
use crate::validator::messages::{Msg, MsgHash};
use crypto::{bls12_381, ByteFmt, Text, TextFmt};
use std::fmt;

use crypto::{bn254, ByteFmt, Text, TextFmt};
use utils::enum_util::Variant;

use crate::validator::messages::{Msg, MsgHash};

use super::{Error, PublicKey, Signature};

/// An aggregate signature from a validator.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct AggregateSignature(pub(crate) bls12_381::AggregateSignature);
pub struct AggregateSignature(pub(crate) bn254::AggregateSignature);

impl AggregateSignature {
/// Generate a new aggregate signature from a list of signatures.
pub fn aggregate<'a>(sigs: impl IntoIterator<Item = &'a Signature>) -> anyhow::Result<Self> {
Ok(AggregateSignature(
bls12_381::AggregateSignature::aggregate(
sigs.into_iter().map(|sig| &sig.0).collect::<Vec<_>>(),
)?,
pub fn aggregate<'a>(sigs: impl IntoIterator<Item = &'a Signature>) -> Self {
AggregateSignature(bn254::AggregateSignature::aggregate(
sigs.into_iter().map(|sig| &sig.0).collect::<Vec<_>>(),
))
}

Expand Down Expand Up @@ -55,12 +56,12 @@ impl ByteFmt for AggregateSignature {
impl TextFmt for AggregateSignature {
fn encode(&self) -> String {
format!(
"validator:aggregate_signature:bls12_381:{}",
"validator:aggregate_signature:bn254:{}",
hex::encode(ByteFmt::encode(&self.0))
)
}
fn decode(text: Text) -> anyhow::Result<Self> {
text.strip("validator:aggregate_signature:bls12_381:")?
text.strip("validator:aggregate_signature:bn254:")?
.decode_hex()
.map(Self)
}
Expand Down
2 changes: 1 addition & 1 deletion node/libs/roles/src/validator/keys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ pub use secret_key::SecretKey;
pub use signature::Signature;

/// Error type returned by validator key operations.
pub type Error = crypto::bls12_381::Error;
pub type Error = crypto::bn254::Error;
8 changes: 4 additions & 4 deletions node/libs/roles/src/validator/keys/public_key.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crypto::{bls12_381, ByteFmt, Text, TextFmt};
use crypto::{bn254, ByteFmt, Text, TextFmt};
use std::fmt;

/// A public key for a validator.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PublicKey(pub(crate) bls12_381::PublicKey);
pub struct PublicKey(pub(crate) bn254::PublicKey);

impl ByteFmt for PublicKey {
fn encode(&self) -> Vec<u8> {
Expand All @@ -17,12 +17,12 @@ impl ByteFmt for PublicKey {
impl TextFmt for PublicKey {
fn encode(&self) -> String {
format!(
"validator:public:bls12_381:{}",
"validator:public:bn254:{}",
hex::encode(ByteFmt::encode(&self.0))
)
}
fn decode(text: Text) -> anyhow::Result<Self> {
text.strip("validator:public:bls12_381:")?
text.strip("validator:public:bn254:")?
.decode_hex()
.map(Self)
}
Expand Down
13 changes: 7 additions & 6 deletions node/libs/roles/src/validator/keys/secret_key.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
use super::{PublicKey, Signature};
use crate::validator::messages::{Msg, MsgHash, Signed};
use crypto::{bls12_381, ByteFmt, Text, TextFmt};
use crypto::{bn254, ByteFmt, Text, TextFmt};
use rand::Rng;
use std::{fmt, sync::Arc};
use utils::enum_util::Variant;

/// A secret key for the validator role.
/// SecretKey is put into an Arc, so that we can clone it,
/// without copying the secret all over the RAM.
#[derive(Clone)]
pub struct SecretKey(pub(crate) Arc<bls12_381::SecretKey>);
pub struct SecretKey(pub(crate) Arc<bn254::SecretKey>);

impl SecretKey {
/// Generate a new secret key.
pub fn generate(ikm: [u8; 32]) -> Self {
Self(Arc::new(bls12_381::SecretKey::generate(ikm)))
pub fn generate<R: Rng>(rng: &mut R) -> Self {
Self(Arc::new(bn254::SecretKey::random(rng)))
}

/// Public key corresponding to this secret key.
Expand Down Expand Up @@ -50,13 +51,13 @@ impl ByteFmt for SecretKey {
impl TextFmt for SecretKey {
fn encode(&self) -> String {
format!(
"validator:secret:bls12_381:{}",
"validator:secret:bn254:{}",
hex::encode(ByteFmt::encode(&*self.0))
)
}

fn decode(text: Text) -> anyhow::Result<Self> {
text.strip("validator:secret:bls12_381:")?
text.strip("validator:secret:bn254:")?
.decode_hex()
.map(Arc::new)
.map(Self)
Expand Down
8 changes: 4 additions & 4 deletions node/libs/roles/src/validator/keys/signature.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use super::{Error, PublicKey};
use crate::validator::messages::{Msg, MsgHash};
use crypto::{bls12_381, ByteFmt, Text, TextFmt};
use crypto::{bn254, ByteFmt, Text, TextFmt};
use std::fmt;

/// A signature from a validator.
#[derive(Clone, PartialEq, Eq)]
pub struct Signature(pub(crate) bls12_381::Signature);
pub struct Signature(pub(crate) bn254::Signature);

impl Signature {
/// Verify a message against a public key.
Expand All @@ -31,12 +31,12 @@ impl ByteFmt for Signature {
impl TextFmt for Signature {
fn encode(&self) -> String {
format!(
"validator:signature:bls12_381:{}",
"validator:signature:bn254:{}",
hex::encode(ByteFmt::encode(&self.0))
)
}
fn decode(text: Text) -> anyhow::Result<Self> {
text.strip("validator:signature:bls12_381:")?
text.strip("validator:signature:bn254:")?
.decode_hex()
.map(Self)
}
Expand Down
4 changes: 2 additions & 2 deletions node/libs/roles/src/validator/messages/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ impl PrepareQC {

// Aggregate the signatures.
let signature =
validator::AggregateSignature::aggregate(signed_messages.iter().map(|v| &v.sig))?;
validator::AggregateSignature::aggregate(signed_messages.iter().map(|v| &v.sig));

Ok(Self { map, signature })
}
Expand Down Expand Up @@ -297,7 +297,7 @@ impl CommitQC {
.collect();

// Aggregate the signatures.
let signature = validator::AggregateSignature::aggregate(msg_map.values().copied())?;
let signature = validator::AggregateSignature::aggregate(msg_map.values().copied());
Ok(Self {
message,
signers: Signers(bit_vec),
Expand Down
2 changes: 1 addition & 1 deletion node/libs/roles/src/validator/messages/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use super::{ConsensusMsg, NetAddress};
use crate::{node::SessionId, validator};
use crypto::{bls12_381::Error, sha256, ByteFmt, Text, TextFmt};
use crypto::{bn254::Error, sha256, ByteFmt, Text, TextFmt};
use std::fmt;
use utils::enum_util::{ErrBadVariant, Variant};

Expand Down
2 changes: 1 addition & 1 deletion node/tools/src/bin/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use roles::validator;

/// This tool generates a validator key pair and prints it to stdout.
fn main() {
let key = validator::SecretKey::generate(rand::rngs::OsRng.gen());
let key = validator::SecretKey::generate(&mut rand::rngs::OsRng);
let encoded_pk = crypto::TextFmt::encode(&key.public());
let encoded_sk = crypto::TextFmt::encode(&key);
println!("Generating keypair:");
Expand Down

0 comments on commit cae1291

Please sign in to comment.