From 43f4deceb0bb346eab8c81abb89832a489060f4c Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Tue, 31 Oct 2023 13:05:10 +0100 Subject: [PATCH] <4s --- node/Cargo.lock | 1 + node/actors/consensus/src/replica/tests.rs | 1 + .../network/src/consensus/handshake/mod.rs | 2 +- node/libs/crypto/Cargo.toml | 3 +- node/libs/crypto/src/bn254/hash.rs | 2 + node/libs/crypto/src/bn254/mod.rs | 65 ++++++++----------- node/libs/crypto/src/bn254/testonly.rs | 9 ++- .../src/validator/keys/aggregate_signature.rs | 9 +-- node/libs/roles/src/validator/messages/msg.rs | 2 +- 9 files changed, 41 insertions(+), 53 deletions(-) diff --git a/node/Cargo.lock b/node/Cargo.lock index 400544aa..fedbc7d4 100644 --- a/node/Cargo.lock +++ b/node/Cargo.lock @@ -696,6 +696,7 @@ dependencies = [ "rand", "sha2", "thiserror", + "tracing", ] [[package]] diff --git a/node/actors/consensus/src/replica/tests.rs b/node/actors/consensus/src/replica/tests.rs index 775929e8..09fd17b7 100644 --- a/node/actors/consensus/src/replica/tests.rs +++ b/node/actors/consensus/src/replica/tests.rs @@ -6,6 +6,7 @@ use roles::validator::{self, ViewNumber}; #[tokio::test] async fn start_new_view_not_leader() { + concurrency::testonly::abort_on_panic(); let ctx = &ctx::test_root(&ctx::ManualClock::new()); let rng = &mut ctx.rng(); diff --git a/node/actors/network/src/consensus/handshake/mod.rs b/node/actors/network/src/consensus/handshake/mod.rs index ccf8254f..5d6d309f 100644 --- a/node/actors/network/src/consensus/handshake/mod.rs +++ b/node/actors/network/src/consensus/handshake/mod.rs @@ -1,7 +1,7 @@ use crate::{frame, noise}; use anyhow::Context as _; use concurrency::{ctx, time}; -use crypto::{ByteFmt}; +use crypto::ByteFmt; use roles::{node, validator}; use schema::{proto::network::consensus as proto, read_required, ProtoFmt}; diff --git a/node/libs/crypto/Cargo.toml b/node/libs/crypto/Cargo.toml index 6a827f90..4b8f96f3 100644 --- a/node/libs/crypto/Cargo.toml +++ b/node/libs/crypto/Cargo.toml @@ -18,10 +18,11 @@ hex.workspace = true rand.workspace = true sha2.workspace = true thiserror.workspace = true +tracing.workspace = true [dev-dependencies] criterion = "0.5.1" [[bench]] name = "bench" -harness = false \ No newline at end of file +harness = false diff --git a/node/libs/crypto/src/bn254/hash.rs b/node/libs/crypto/src/bn254/hash.rs index 8540ee58..8d8aaa69 100644 --- a/node/libs/crypto/src/bn254/hash.rs +++ b/node/libs/crypto/src/bn254/hash.rs @@ -3,8 +3,10 @@ use ark_bn254::{G1Affine, G1Projective}; use ark_ec::AffineRepr as _; use sha2::Digest as _; +use tracing::instrument; /// Hashes an arbitrary message and maps it to an elliptic curve point in G1. +#[instrument(level = "trace", skip_all)] pub(crate) fn hash_to_g1(msg: &[u8]) -> G1Projective { for i in 0..100 { // Hash the message with the index as suffix. diff --git a/node/libs/crypto/src/bn254/mod.rs b/node/libs/crypto/src/bn254/mod.rs index 0aff49fe..f0c7b551 100644 --- a/node/libs/crypto/src/bn254/mod.rs +++ b/node/libs/crypto/src/bn254/mod.rs @@ -1,20 +1,16 @@ //! BLS signature scheme for the BN254 curve. -use std::collections::BTreeMap; -use std::fmt::Debug; -use std::hash::Hasher; - +use crate::ByteFmt; use anyhow::anyhow; use ark_bn254::{Bn254, Fr, G1Projective as G1, G2Projective as G2}; -use ark_ec::pairing::Pairing as _; -use ark_ec::pairing::PairingOutput; -use ark_ec::Group as _; +use ark_ec::{ + pairing::{Pairing as _, PairingOutput}, + Group as _, +}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; -use num_traits::Zero as _; - pub use error::Error; - -use crate::ByteFmt; +use num_traits::Zero as _; +use std::{collections::HashMap, fmt::Debug, hash::Hasher}; #[doc(hidden)] pub mod error; @@ -99,6 +95,7 @@ pub struct Signature(pub G1); impl Signature { /// Verifies a signature against the provided public key + #[inline(never)] pub fn verify(&self, msg: &[u8], pk: &PublicKey) -> Result<(), Error> { let hash_point = hash::hash_to_g1(msg); @@ -154,23 +151,21 @@ impl AggregateSignature { AggregateSignature(agg) } - /// Verifies an aggregated signature for multiple messages against the provided list of public keys. - /// This method expects one public key per message, otherwise it will fail. Note however that - /// If there are any duplicate messages, the public keys will be aggregated before verification. - pub fn verify<'a>( - &self, - msgs_and_pks: impl Iterator, - ) -> Result<(), Error> { - let msgs_and_pks = Self::aggregate_pk(msgs_and_pks); - + #[inline(never)] + fn verify_raw(&self, msgs_and_pks: &[(&[u8], &PublicKey)]) -> Result<(), Error> { + // Aggregate public keys if they are signing the same hash. Each public key aggregated + // is one fewer pairing to calculate. + let mut pairs: HashMap<&[u8], G2> = HashMap::new(); + for (msg, pk) in msgs_and_pks { + *pairs.entry(msg).or_default() += pk.0; + } // First pair: e(sig: G1, generator: G2) let a = Bn254::pairing(self.0, G2::generator()); - // Second pair: e(H(m1): G1, pk1: G2) * ... * (H(m1000): G1, pk1000: G2) + // Second pair: e(H(m1): G1, pk1: G2) * ... * e(H(m1000): G1, pk1000: G2) let mut b = PairingOutput::zero(); - for (msg, pk) in msgs_and_pks { - let hash_point = hash::hash_to_g1(msg); - b += Bn254::pairing(hash_point, pk.0); + for (msg, pk) in pairs { + b += Bn254::pairing(hash::hash_to_g1(msg), pk); } if a == b { @@ -180,22 +175,14 @@ impl AggregateSignature { } } - fn aggregate_pk<'a>( + /// Verifies an aggregated signature for multiple messages against the provided list of public keys. + /// This method expects one public key per message, otherwise it will fail. Note however that + /// If there are any duplicate messages, the public keys will be aggregated before verification. + pub fn verify<'a>( + &self, msgs_and_pks: impl Iterator, - ) -> impl Iterator { - // Aggregate public keys if they are signing the same hash. Each public key aggregated - // is one fewer pairing to calculate. - let mut tree_map: BTreeMap<&[u8], PublicKey> = BTreeMap::new(); - - for (msg, pk) in msgs_and_pks { - if let Some(existing_pk) = tree_map.get_mut(msg) { - existing_pk.0 += pk.0; - } else { - tree_map.insert(msg, pk.clone()); - } - } - - tree_map.into_iter() + ) -> Result<(), Error> { + self.verify_raw(&msgs_and_pks.collect::>()[..]) } } diff --git a/node/libs/crypto/src/bn254/testonly.rs b/node/libs/crypto/src/bn254/testonly.rs index 9304b530..a4af1c1d 100644 --- a/node/libs/crypto/src/bn254/testonly.rs +++ b/node/libs/crypto/src/bn254/testonly.rs @@ -1,8 +1,7 @@ //! Random key generation, intended for use in testing -use rand::{distributions::Standard, prelude::Distribution, Rng}; - use super::{AggregateSignature, PublicKey, SecretKey, Signature}; +use rand::{distributions::Standard, prelude::Distribution, Rng}; /// Generates a random SecretKey. This is meant for testing purposes. impl Distribution for Standard { @@ -15,20 +14,20 @@ impl Distribution for Standard { /// Generates a random PublicKey. This is meant for testing purposes. impl Distribution for Standard { fn sample(&self, rng: &mut R) -> PublicKey { - rng.gen() + PublicKey(rng.gen()) } } /// Generates a random Signature. This is meant for testing purposes. impl Distribution for Standard { fn sample(&self, rng: &mut R) -> Signature { - rng.gen() + Signature(rng.gen()) } } /// Generates a random AggregateSignature. This is meant for testing purposes. impl Distribution for Standard { fn sample(&self, rng: &mut R) -> AggregateSignature { - rng.gen() + AggregateSignature(rng.gen()) } } diff --git a/node/libs/roles/src/validator/keys/aggregate_signature.rs b/node/libs/roles/src/validator/keys/aggregate_signature.rs index a19d84be..7f1d6ee8 100644 --- a/node/libs/roles/src/validator/keys/aggregate_signature.rs +++ b/node/libs/roles/src/validator/keys/aggregate_signature.rs @@ -1,12 +1,9 @@ -use std::fmt; - +use super::{Error, PublicKey, Signature}; +use crate::validator::messages::{Msg, MsgHash}; use crypto::{bn254, ByteFmt, Text, TextFmt}; +use std::fmt; 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) bn254::AggregateSignature); diff --git a/node/libs/roles/src/validator/messages/msg.rs b/node/libs/roles/src/validator/messages/msg.rs index d4f66d05..ac0e3bf8 100644 --- a/node/libs/roles/src/validator/messages/msg.rs +++ b/node/libs/roles/src/validator/messages/msg.rs @@ -1,7 +1,7 @@ //! Generic message types. use super::{ConsensusMsg, NetAddress}; -use crate::{validator::Error, node::SessionId, validator}; +use crate::{node::SessionId, validator, validator::Error}; use crypto::{sha256, ByteFmt, Text, TextFmt}; use std::fmt; use utils::enum_util::{BadVariantError, Variant};