mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-26 04:09:28 +00:00
Support multiple BLS implementations (#1335)
## Issue Addressed NA ## Proposed Changes - Refactor the `bls` crate to support multiple BLS "backends" (e.g., milagro, blst, etc). - Removes some duplicate, unused code in `common/rest_types/src/validator.rs`. - Removes the old "upgrade legacy keypairs" functionality (these were unencrypted keys that haven't been supported for a few testnets, no one should be using them anymore). ## Additional Info Most of the files changed are just inconsequential changes to function names. ## TODO - [x] Optimization levels - [x] Infinity point: https://github.com/supranational/blst/issues/11 - [x] Ensure milagro *and* blst are tested via CI - [x] What to do with unsafe code? - [x] Test infinity point in signature sets
This commit is contained in:
@@ -1,84 +1,140 @@
|
||||
extern crate milagro_bls;
|
||||
extern crate ssz;
|
||||
//! This library provides a wrapper around several BLS implementations to provide
|
||||
//! Lighthouse-specific functionality.
|
||||
//!
|
||||
//! This crate should not perform direct cryptographic operations, instead it should do these via
|
||||
//! external libraries. However, seeing as it is an interface to a real cryptographic library, it
|
||||
//! may contain logic that affects the outcomes of cryptographic operations.
|
||||
//!
|
||||
//! A source of complexity in this crate is that *multiple* BLS implementations (a.k.a. "backends")
|
||||
//! are supported via compile-time flags. There are three backends supported via features:
|
||||
//!
|
||||
//! - `supranational`: the pure-assembly, highly optimized version from the `blst` crate.
|
||||
//! - `milagro`: the classic pure-Rust `milagro_bls` crate.
|
||||
//! - `fake_crypto`: an always-returns-valid implementation that is only useful for testing
|
||||
//! scenarios which intend to *ignore* real cryptography.
|
||||
//!
|
||||
//! This crate uses traits to reduce code-duplication between the two implementations. For example,
|
||||
//! the `GenericPublicKey` struct exported from this crate is generic across the `TPublicKey` trait
|
||||
//! (i.e., `PublicKey<TPublicKey>`). `TPublicKey` is implemented by all three backends (see the
|
||||
//! `impls.rs` module). When compiling with the `milagro` feature, we export
|
||||
//! `type PublicKey = GenericPublicKey<milagro::PublicKey>`.
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod keypair;
|
||||
mod public_key_bytes;
|
||||
mod secret_hash;
|
||||
mod secret_key;
|
||||
mod signature_bytes;
|
||||
mod signature_set;
|
||||
mod generic_aggregate_public_key;
|
||||
mod generic_aggregate_signature;
|
||||
mod generic_keypair;
|
||||
mod generic_public_key;
|
||||
mod generic_public_key_bytes;
|
||||
mod generic_secret_key;
|
||||
mod generic_signature;
|
||||
mod generic_signature_bytes;
|
||||
mod generic_signature_set;
|
||||
mod get_withdrawal_credentials;
|
||||
mod zeroize_hash;
|
||||
|
||||
pub use crate::keypair::Keypair;
|
||||
pub use crate::public_key_bytes::PublicKeyBytes;
|
||||
pub use crate::secret_key::SecretKey;
|
||||
pub use crate::signature_bytes::SignatureBytes;
|
||||
pub use secret_hash::SecretHash;
|
||||
pub use signature_set::{verify_signature_sets, SignatureSet};
|
||||
pub mod impls;
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
pub use arbitrary;
|
||||
pub use generic_public_key::{INFINITY_PUBLIC_KEY, PUBLIC_KEY_BYTES_LEN};
|
||||
pub use generic_secret_key::SECRET_KEY_BYTES_LEN;
|
||||
pub use generic_signature::{INFINITY_SIGNATURE, SIGNATURE_BYTES_LEN};
|
||||
pub use get_withdrawal_credentials::get_withdrawal_credentials;
|
||||
pub use zeroize_hash::ZeroizeHash;
|
||||
|
||||
#[cfg(feature = "fake_crypto")]
|
||||
mod fake_aggregate_public_key;
|
||||
#[cfg(feature = "fake_crypto")]
|
||||
mod fake_aggregate_signature;
|
||||
#[cfg(feature = "fake_crypto")]
|
||||
mod fake_public_key;
|
||||
#[cfg(feature = "fake_crypto")]
|
||||
mod fake_signature;
|
||||
use blst::BLST_ERROR as BlstError;
|
||||
use milagro_bls::AmclError;
|
||||
|
||||
#[cfg(not(feature = "fake_crypto"))]
|
||||
mod aggregate_public_key;
|
||||
#[cfg(not(feature = "fake_crypto"))]
|
||||
mod aggregate_signature;
|
||||
#[cfg(not(feature = "fake_crypto"))]
|
||||
mod public_key;
|
||||
#[cfg(not(feature = "fake_crypto"))]
|
||||
mod signature;
|
||||
pub type Hash256 = ethereum_types::H256;
|
||||
|
||||
#[cfg(feature = "fake_crypto")]
|
||||
pub use fakes::*;
|
||||
#[cfg(feature = "fake_crypto")]
|
||||
mod fakes {
|
||||
pub use crate::fake_aggregate_public_key::FakeAggregatePublicKey as AggregatePublicKey;
|
||||
pub use crate::fake_aggregate_signature::FakeAggregateSignature as AggregateSignature;
|
||||
pub use crate::fake_public_key::FakePublicKey as PublicKey;
|
||||
pub use crate::fake_signature::FakeSignature as Signature;
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Error {
|
||||
/// An error was raised from the Milagro BLS library.
|
||||
MilagroError(AmclError),
|
||||
/// An error was raised from the Supranational BLST BLS library.
|
||||
BlstError(BlstError),
|
||||
/// The provided bytes were an incorrect length.
|
||||
InvalidByteLength { got: usize, expected: usize },
|
||||
/// The provided secret key bytes were an incorrect length.
|
||||
InvalidSecretKeyLength { got: usize, expected: usize },
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "fake_crypto"))]
|
||||
pub use reals::*;
|
||||
#[cfg(not(feature = "fake_crypto"))]
|
||||
mod reals {
|
||||
pub use crate::aggregate_public_key::AggregatePublicKey;
|
||||
pub use crate::aggregate_signature::AggregateSignature;
|
||||
pub use crate::public_key::PublicKey;
|
||||
pub use crate::signature::Signature;
|
||||
impl From<AmclError> for Error {
|
||||
fn from(e: AmclError) -> Error {
|
||||
Error::MilagroError(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub const BLS_AGG_SIG_BYTE_SIZE: usize = 96;
|
||||
pub const BLS_SIG_BYTE_SIZE: usize = 96;
|
||||
pub const BLS_SECRET_KEY_BYTE_SIZE: usize = 32;
|
||||
pub const BLS_PUBLIC_KEY_BYTE_SIZE: usize = 48;
|
||||
|
||||
use eth2_hashing::hash;
|
||||
use ssz::ssz_encode;
|
||||
|
||||
/// Returns the withdrawal credentials for a given public key.
|
||||
pub fn get_withdrawal_credentials(pubkey: &PublicKey, prefix_byte: u8) -> Vec<u8> {
|
||||
let hashed = hash(&ssz_encode(pubkey));
|
||||
let mut prefixed = vec![prefix_byte];
|
||||
prefixed.extend_from_slice(&hashed[1..]);
|
||||
|
||||
prefixed
|
||||
impl From<BlstError> for Error {
|
||||
fn from(e: BlstError) -> Error {
|
||||
Error::BlstError(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bls_verify_aggregate(
|
||||
pubkey: &AggregatePublicKey,
|
||||
message: &[u8],
|
||||
signature: &AggregateSignature,
|
||||
) -> bool {
|
||||
signature.verify(message, pubkey)
|
||||
/// Generic implementations which are only generally useful for docs.
|
||||
pub mod generics {
|
||||
pub use crate::generic_aggregate_signature::GenericAggregateSignature;
|
||||
pub use crate::generic_keypair::GenericKeypair;
|
||||
pub use crate::generic_public_key::GenericPublicKey;
|
||||
pub use crate::generic_public_key_bytes::GenericPublicKeyBytes;
|
||||
pub use crate::generic_secret_key::GenericSecretKey;
|
||||
pub use crate::generic_signature::GenericSignature;
|
||||
pub use crate::generic_signature_bytes::GenericSignatureBytes;
|
||||
}
|
||||
|
||||
/// Defines all the fundamental BLS points which should be exported by this crate by making
|
||||
/// concrete the generic type parameters using the points from some external BLS library (e.g.,
|
||||
/// Milagro, BLST).
|
||||
macro_rules! define_mod {
|
||||
($name: ident, $mod: path) => {
|
||||
pub mod $name {
|
||||
use $mod as bls_variant;
|
||||
|
||||
use crate::generics::*;
|
||||
|
||||
pub use bls_variant::{verify_signature_sets, SignatureSet};
|
||||
|
||||
pub type PublicKey = GenericPublicKey<bls_variant::PublicKey>;
|
||||
pub type PublicKeyBytes = GenericPublicKeyBytes<bls_variant::PublicKey>;
|
||||
pub type Signature = GenericSignature<bls_variant::PublicKey, bls_variant::Signature>;
|
||||
pub type AggregateSignature = GenericAggregateSignature<
|
||||
bls_variant::PublicKey,
|
||||
bls_variant::AggregatePublicKey,
|
||||
bls_variant::Signature,
|
||||
bls_variant::AggregateSignature,
|
||||
>;
|
||||
pub type SignatureBytes =
|
||||
GenericSignatureBytes<bls_variant::PublicKey, bls_variant::Signature>;
|
||||
pub type SecretKey = GenericSecretKey<
|
||||
bls_variant::Signature,
|
||||
bls_variant::PublicKey,
|
||||
bls_variant::SecretKey,
|
||||
>;
|
||||
pub type Keypair = GenericKeypair<
|
||||
bls_variant::PublicKey,
|
||||
bls_variant::SecretKey,
|
||||
bls_variant::Signature,
|
||||
>;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
define_mod!(milagro_implementations, crate::impls::milagro::types);
|
||||
define_mod!(blst_implementations, crate::impls::blst::types);
|
||||
#[cfg(feature = "fake_crypto")]
|
||||
define_mod!(
|
||||
fake_crypto_implementations,
|
||||
crate::impls::fake_crypto::types
|
||||
);
|
||||
|
||||
#[cfg(all(feature = "milagro", not(feature = "fake_crypto"),))]
|
||||
pub use milagro_implementations::*;
|
||||
|
||||
#[cfg(all(
|
||||
feature = "supranational",
|
||||
not(feature = "fake_crypto"),
|
||||
not(feature = "milagro")
|
||||
))]
|
||||
pub use blst_implementations::*;
|
||||
|
||||
#[cfg(feature = "fake_crypto")]
|
||||
pub use fake_crypto_implementations::*;
|
||||
|
||||
Reference in New Issue
Block a user