mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-20 22:38:34 +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:
@@ -73,8 +73,7 @@ impl<T: EthSpec> AggregateAndProof<T> {
|
||||
genesis_validators_root,
|
||||
);
|
||||
let message = self.aggregate.data.slot.signing_root(domain);
|
||||
self.selection_proof
|
||||
.verify(message.as_bytes(), validator_pubkey)
|
||||
self.selection_proof.verify(validator_pubkey, message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use super::{
|
||||
AggregateSignature, AttestationData, BitList, ChainSpec, Domain, EthSpec, Fork, SecretKey,
|
||||
Signature, SignedRoot,
|
||||
SignedRoot,
|
||||
};
|
||||
use crate::{test_utils::TestRandom, Hash256};
|
||||
use safe_arith::ArithError;
|
||||
@@ -44,7 +44,7 @@ impl<T: EthSpec> Attestation<T> {
|
||||
debug_assert!(self.signers_disjoint_from(other));
|
||||
|
||||
self.aggregation_bits = self.aggregation_bits.union(&other.aggregation_bits);
|
||||
self.signature.add_aggregate(&other.signature);
|
||||
self.signature.add_assign_aggregate(&other.signature);
|
||||
}
|
||||
|
||||
/// Signs `self`, setting the `committee_position`'th bit of `aggregation_bits` to `true`.
|
||||
@@ -77,8 +77,7 @@ impl<T: EthSpec> Attestation<T> {
|
||||
);
|
||||
let message = self.data.signing_root(domain);
|
||||
|
||||
self.signature
|
||||
.add(&Signature::new(message.as_bytes(), secret_key));
|
||||
self.signature.add_assign(&secret_key.sign(message));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ impl<T: EthSpec> BeaconBlock<T> {
|
||||
parent_root: Hash256::zero(),
|
||||
state_root: Hash256::zero(),
|
||||
body: BeaconBlockBody {
|
||||
randao_reveal: Signature::empty_signature(),
|
||||
randao_reveal: Signature::empty(),
|
||||
eth1_data: Eth1Data {
|
||||
deposit_root: Hash256::zero(),
|
||||
block_hash: Hash256::zero(),
|
||||
@@ -63,7 +63,7 @@ impl<T: EthSpec> BeaconBlock<T> {
|
||||
|
||||
let signed_header = SignedBeaconBlockHeader {
|
||||
message: header,
|
||||
signature: Signature::empty_signature(),
|
||||
signature: Signature::empty(),
|
||||
};
|
||||
let indexed_attestation: IndexedAttestation<T> = IndexedAttestation {
|
||||
attesting_indices: VariableList::new(vec![
|
||||
@@ -72,7 +72,7 @@ impl<T: EthSpec> BeaconBlock<T> {
|
||||
])
|
||||
.unwrap(),
|
||||
data: AttestationData::default(),
|
||||
signature: AggregateSignature::new(),
|
||||
signature: AggregateSignature::empty(),
|
||||
};
|
||||
|
||||
let deposit_data = DepositData {
|
||||
@@ -95,7 +95,7 @@ impl<T: EthSpec> BeaconBlock<T> {
|
||||
aggregation_bits: BitList::with_capacity(T::MaxValidatorsPerCommittee::to_usize())
|
||||
.unwrap(),
|
||||
data: AttestationData::default(),
|
||||
signature: AggregateSignature::new(),
|
||||
signature: AggregateSignature::empty(),
|
||||
};
|
||||
|
||||
let deposit = Deposit {
|
||||
@@ -110,7 +110,7 @@ impl<T: EthSpec> BeaconBlock<T> {
|
||||
|
||||
let signed_voluntary_exit = SignedVoluntaryExit {
|
||||
message: voluntary_exit,
|
||||
signature: Signature::empty_signature(),
|
||||
signature: Signature::empty(),
|
||||
};
|
||||
|
||||
let mut block: BeaconBlock<T> = BeaconBlock::empty(spec);
|
||||
@@ -200,7 +200,7 @@ impl<T: EthSpec> BeaconBlock<T> {
|
||||
genesis_validators_root,
|
||||
);
|
||||
let message = self.signing_root(domain);
|
||||
let signature = Signature::new(message.as_bytes(), secret_key);
|
||||
let signature = secret_key.sign(message);
|
||||
SignedBeaconBlock {
|
||||
message: self,
|
||||
signature,
|
||||
|
||||
@@ -54,7 +54,7 @@ impl BeaconBlockHeader {
|
||||
let epoch = self.slot.epoch(E::slots_per_epoch());
|
||||
let domain = spec.get_domain(epoch, Domain::BeaconProposer, fork, genesis_validators_root);
|
||||
let message = self.signing_root(domain);
|
||||
let signature = Signature::new(message.as_bytes(), secret_key);
|
||||
let signature = secret_key.sign(message);
|
||||
SignedBeaconBlockHeader {
|
||||
message: self,
|
||||
signature,
|
||||
|
||||
@@ -10,7 +10,7 @@ use int_to_bytes::{int_to_bytes4, int_to_bytes8};
|
||||
use pubkey_cache::PubkeyCache;
|
||||
use safe_arith::{ArithError, SafeArith};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use ssz::ssz_encode;
|
||||
use ssz::{ssz_encode, Encode};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use ssz_types::{typenum::Unsigned, BitVector, FixedVector};
|
||||
use std::convert::TryInto;
|
||||
@@ -501,7 +501,7 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
1,
|
||||
(committee.committee.len() as u64).safe_div(spec.target_aggregators_per_committee)?,
|
||||
);
|
||||
let signature_hash = hash(&slot_signature.as_bytes());
|
||||
let signature_hash = hash(&slot_signature.as_ssz_bytes());
|
||||
let signature_hash_int = u64::from_le_bytes(
|
||||
signature_hash[0..8]
|
||||
.try_into()
|
||||
|
||||
@@ -38,7 +38,7 @@ impl DepositData {
|
||||
let domain = spec.get_deposit_domain();
|
||||
let msg = self.as_deposit_message().signing_root(domain);
|
||||
|
||||
SignatureBytes::from(Signature::new(msg.as_bytes(), secret_key))
|
||||
SignatureBytes::from(secret_key.sign(msg))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,8 +96,7 @@ pub type Address = H160;
|
||||
pub type ForkVersion = [u8; 4];
|
||||
|
||||
pub use bls::{
|
||||
AggregatePublicKey, AggregateSignature, Keypair, PublicKey, PublicKeyBytes, SecretKey,
|
||||
Signature, SignatureBytes,
|
||||
AggregateSignature, Keypair, PublicKey, PublicKeyBytes, SecretKey, Signature, SignatureBytes,
|
||||
};
|
||||
pub use ssz_types::{typenum, typenum::Unsigned, BitList, BitVector, FixedVector, VariableList};
|
||||
pub use utils::{Graffiti, GRAFFITI_BYTES_LEN};
|
||||
|
||||
@@ -27,7 +27,7 @@ impl SelectionProof {
|
||||
);
|
||||
let message = slot.signing_root(domain);
|
||||
|
||||
Self(Signature::new(message.as_bytes(), secret_key))
|
||||
Self(secret_key.sign(message))
|
||||
}
|
||||
|
||||
/// Returns the "modulo" used for determining if a `SelectionProof` elects an aggregator.
|
||||
@@ -74,7 +74,7 @@ impl SelectionProof {
|
||||
);
|
||||
let message = slot.signing_root(domain);
|
||||
|
||||
self.0.verify(message.as_bytes(), pubkey)
|
||||
self.0.verify(pubkey, message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ impl<T: EthSpec> SignedAggregateAndProof<T> {
|
||||
|
||||
SignedAggregateAndProof {
|
||||
message,
|
||||
signature: Signature::new(signing_message.as_bytes(), &secret_key),
|
||||
signature: secret_key.sign(signing_message),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ impl<T: EthSpec> SignedAggregateAndProof<T> {
|
||||
genesis_validators_root,
|
||||
);
|
||||
let message = self.message.signing_root(domain);
|
||||
self.signature.verify(message.as_bytes(), validator_pubkey)
|
||||
self.signature.verify(validator_pubkey, message)
|
||||
}
|
||||
|
||||
/// Verifies the signature of the `AggregateAndProof` as well the underlying selection_proof in
|
||||
|
||||
@@ -78,7 +78,7 @@ impl<E: EthSpec> SignedBeaconBlock<E> {
|
||||
self.message.signing_root(domain)
|
||||
};
|
||||
|
||||
self.signature.verify(message.as_bytes(), pubkey)
|
||||
self.signature.verify(pubkey, message)
|
||||
}
|
||||
|
||||
/// Convenience accessor for the block's slot.
|
||||
|
||||
@@ -36,7 +36,7 @@ impl<T: EthSpec> TestingAttestationBuilder<T> {
|
||||
let attestation = Attestation {
|
||||
aggregation_bits,
|
||||
data: data_builder.build(),
|
||||
signature: AggregateSignature::new(),
|
||||
signature: AggregateSignature::empty(),
|
||||
};
|
||||
|
||||
Self {
|
||||
|
||||
@@ -64,7 +64,7 @@ impl TestingAttesterSlashingBuilder {
|
||||
validator_indices.to_vec().into()
|
||||
},
|
||||
data: data_1,
|
||||
signature: AggregateSignature::new(),
|
||||
signature: AggregateSignature::empty(),
|
||||
};
|
||||
|
||||
let mut attestation_2 = IndexedAttestation {
|
||||
@@ -76,7 +76,7 @@ impl TestingAttesterSlashingBuilder {
|
||||
validator_indices.to_vec().into()
|
||||
},
|
||||
data: data_2,
|
||||
signature: AggregateSignature::new(),
|
||||
signature: AggregateSignature::empty(),
|
||||
};
|
||||
|
||||
let add_signatures = |attestation: &mut IndexedAttestation<T>| {
|
||||
@@ -90,7 +90,7 @@ impl TestingAttesterSlashingBuilder {
|
||||
|
||||
for validator_index in validator_indices {
|
||||
let signature = signer(*validator_index, message.as_bytes());
|
||||
attestation.signature.add(&signature);
|
||||
attestation.signature.add_assign(&signature);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
|
||||
let epoch = self.block.slot.epoch(T::slots_per_epoch());
|
||||
let domain = spec.get_domain(epoch, Domain::Randao, fork, genesis_validators_root);
|
||||
let message = epoch.signing_root(domain);
|
||||
self.block.body.randao_reveal = Signature::new(message.as_bytes(), sk);
|
||||
self.block.body.randao_reveal = sk.sign(message);
|
||||
}
|
||||
|
||||
/// Has the randao reveal been set?
|
||||
@@ -368,7 +368,7 @@ impl<T: EthSpec> TestingBeaconBlockBuilder<T> {
|
||||
pub fn build_without_signing(self) -> SignedBeaconBlock<T> {
|
||||
SignedBeaconBlock {
|
||||
message: self.block,
|
||||
signature: Signature::empty_signature(),
|
||||
signature: Signature::empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -410,7 +410,7 @@ pub fn build_double_vote_attester_slashing<T: EthSpec>(
|
||||
.iter()
|
||||
.position(|&i| i == validator_index)
|
||||
.expect("Unable to find attester slashing key");
|
||||
Signature::new(message, secret_keys[key_index])
|
||||
secret_keys[key_index].sign(Hash256::from_slice(message))
|
||||
};
|
||||
|
||||
TestingAttesterSlashingBuilder::double_vote(
|
||||
|
||||
@@ -41,7 +41,7 @@ impl TestingDepositBuilder {
|
||||
// Creating invalid public key bytes
|
||||
let mut public_key_bytes: Vec<u8> = vec![0; 48];
|
||||
public_key_bytes[0] = 255;
|
||||
pubkeybytes = PublicKeyBytes::from_bytes(&public_key_bytes).unwrap();
|
||||
pubkeybytes = PublicKeyBytes::deserialize(&public_key_bytes).unwrap();
|
||||
}
|
||||
DepositTestTask::BadSig => secret_key = new_key.sk,
|
||||
_ => (),
|
||||
|
||||
@@ -37,7 +37,7 @@ impl TestingProposerSlashingBuilder {
|
||||
state_root: hash_1,
|
||||
body_root: hash_1,
|
||||
},
|
||||
signature: Signature::empty_signature(),
|
||||
signature: Signature::empty(),
|
||||
};
|
||||
|
||||
let slot_2 = if test_task == ProposerSlashingTestTask::ProposalEpochMismatch {
|
||||
@@ -52,7 +52,7 @@ impl TestingProposerSlashingBuilder {
|
||||
slot: slot_2,
|
||||
..signed_header_1.message
|
||||
},
|
||||
signature: Signature::empty_signature(),
|
||||
signature: Signature::empty(),
|
||||
};
|
||||
|
||||
if test_task != ProposerSlashingTestTask::BadProposal1Signature {
|
||||
|
||||
@@ -27,20 +27,10 @@ pub fn generate_deterministic_keypairs(validator_count: usize) -> Vec<Keypair> {
|
||||
///
|
||||
/// This is used for testing only, and not to be used in production!
|
||||
pub fn generate_deterministic_keypair(validator_index: usize) -> Keypair {
|
||||
let raw = keypair(validator_index);
|
||||
Keypair {
|
||||
pk: PublicKey::from_raw(raw.pk),
|
||||
sk: SecretKey::from_raw(raw.sk),
|
||||
}
|
||||
keypair(validator_index)
|
||||
}
|
||||
|
||||
/// Loads a list of keypairs from file.
|
||||
pub fn load_keypairs_from_yaml(path: PathBuf) -> Result<Vec<Keypair>, String> {
|
||||
Ok(keypairs_from_yaml_file(path)?
|
||||
.into_iter()
|
||||
.map(|raw| Keypair {
|
||||
pk: PublicKey::from_raw(raw.pk),
|
||||
sk: SecretKey::from_raw(raw.sk),
|
||||
})
|
||||
.collect())
|
||||
keypairs_from_yaml_file(path)
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ use bls::{AggregateSignature, Signature};
|
||||
impl TestRandom for AggregateSignature {
|
||||
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||
let signature = Signature::random_for_test(rng);
|
||||
let mut aggregate_signature = AggregateSignature::new();
|
||||
aggregate_signature.add(&signature);
|
||||
let mut aggregate_signature = AggregateSignature::infinity();
|
||||
aggregate_signature.add_assign(&signature);
|
||||
aggregate_signature
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ use bls::{PublicKey, SecretKey};
|
||||
|
||||
impl TestRandom for PublicKey {
|
||||
fn random_for_test(rng: &mut impl RngCore) -> Self {
|
||||
let secret_key = SecretKey::random_for_test(rng);
|
||||
PublicKey::from_secret_key(&secret_key)
|
||||
SecretKey::random_for_test(rng).public_key()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::convert::From;
|
||||
|
||||
use bls::{PublicKeyBytes, BLS_PUBLIC_KEY_BYTE_SIZE};
|
||||
use bls::{PublicKeyBytes, PUBLIC_KEY_BYTES_LEN};
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -12,7 +12,7 @@ impl TestRandom for PublicKeyBytes {
|
||||
PublicKeyBytes::from(PublicKey::random_for_test(rng))
|
||||
} else {
|
||||
//invalid signature, just random bytes
|
||||
PublicKeyBytes::from_bytes(&<[u8; BLS_PUBLIC_KEY_BYTE_SIZE]>::random_for_test(rng))
|
||||
PublicKeyBytes::deserialize(&<[u8; PUBLIC_KEY_BYTES_LEN]>::random_for_test(rng))
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@ impl TestRandom for Signature {
|
||||
let mut message = vec![0; 32];
|
||||
rng.fill_bytes(&mut message);
|
||||
|
||||
Signature::new(&message, &secret_key)
|
||||
secret_key.sign(Hash256::from_slice(&message))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use bls::{SignatureBytes, BLS_SIG_BYTE_SIZE};
|
||||
use bls::{SignatureBytes, SIGNATURE_BYTES_LEN};
|
||||
|
||||
use super::*;
|
||||
use std::convert::From;
|
||||
@@ -11,7 +11,7 @@ impl TestRandom for SignatureBytes {
|
||||
SignatureBytes::from(Signature::random_for_test(rng))
|
||||
} else {
|
||||
//invalid signature, just random bytes
|
||||
SignatureBytes::from_bytes(&<[u8; BLS_SIG_BYTE_SIZE]>::random_for_test(rng)).unwrap()
|
||||
SignatureBytes::deserialize(&<[u8; SIGNATURE_BYTES_LEN]>::random_for_test(rng)).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ fn process_pubkey_bytes_field(
|
||||
leaf: &mut Hash256,
|
||||
force_update: bool,
|
||||
) -> bool {
|
||||
let new_tree_hash = merkle_root(val.as_slice(), 0);
|
||||
let new_tree_hash = merkle_root(val.as_serialized(), 0);
|
||||
process_slice_field(new_tree_hash.as_bytes(), leaf, force_update)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
test_utils::TestRandom, ChainSpec, Domain, Epoch, Fork, Hash256, SecretKey, Signature,
|
||||
SignedRoot, SignedVoluntaryExit,
|
||||
test_utils::TestRandom, ChainSpec, Domain, Epoch, Fork, Hash256, SecretKey, SignedRoot,
|
||||
SignedVoluntaryExit,
|
||||
};
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
@@ -36,10 +36,9 @@ impl VoluntaryExit {
|
||||
genesis_validators_root,
|
||||
);
|
||||
let message = self.signing_root(domain);
|
||||
let signature = Signature::new(message.as_bytes(), &secret_key);
|
||||
SignedVoluntaryExit {
|
||||
message: self,
|
||||
signature,
|
||||
signature: secret_key.sign(message),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user