mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-08 01:05:47 +00:00
Optimization: reduce BLS decompression (#766)
* Add RwLock-style caching for BLS pubkeys * Tidy docker ignore * Remove RwLocks * Merge in master
This commit is contained in:
@@ -248,10 +248,14 @@ fn validator_pubkey<'a, T: EthSpec>(
|
||||
.ok_or_else(|| Error::ValidatorUnknown(validator_index as u64))?
|
||||
.pubkey;
|
||||
|
||||
pubkey_bytes
|
||||
.try_into()
|
||||
.map(|pubkey: PublicKey| Cow::Owned(pubkey.as_raw().point.clone()))
|
||||
.map_err(|_| Error::BadBlsBytes {
|
||||
validator_index: validator_index as u64,
|
||||
})
|
||||
if let Some(pubkey) = pubkey_bytes.decompressed() {
|
||||
Ok(Cow::Borrowed(&pubkey.as_raw().point))
|
||||
} else {
|
||||
pubkey_bytes
|
||||
.try_into()
|
||||
.map(|pubkey: PublicKey| Cow::Owned(pubkey.as_raw().point.clone()))
|
||||
.map_err(|_| Error::BadBlsBytes {
|
||||
validator_index: validator_index as u64,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ pub enum Error {
|
||||
CommitteeCacheUninitialized(Option<RelativeEpoch>),
|
||||
SszTypesError(ssz_types::Error),
|
||||
CachedTreeHashError(cached_tree_hash::Error),
|
||||
InvalidValidatorPubkey(ssz::DecodeError),
|
||||
}
|
||||
|
||||
/// Control whether an epoch-indexed field can be indexed at the next epoch or not.
|
||||
@@ -784,6 +785,7 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
self.update_pubkey_cache()?;
|
||||
self.build_tree_hash_cache()?;
|
||||
self.exit_cache.build(&self.validators, spec)?;
|
||||
self.decompress_validator_pubkeys()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -945,6 +947,23 @@ impl<T: EthSpec> BeaconState<T> {
|
||||
self.tree_hash_cache = BeaconTreeHashCache::default();
|
||||
}
|
||||
|
||||
/// Iterate through all validators and decompress their public key, unless it has already been
|
||||
/// decompressed.
|
||||
///
|
||||
/// Does not check the validity of already decompressed keys.
|
||||
pub fn decompress_validator_pubkeys(&mut self) -> Result<(), Error> {
|
||||
self.validators.iter_mut().try_for_each(|validator| {
|
||||
if validator.pubkey.decompressed().is_none() {
|
||||
validator
|
||||
.pubkey
|
||||
.decompress()
|
||||
.map_err(|e| Error::InvalidValidatorPubkey(e))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn clone_without_caches(&self) -> Self {
|
||||
BeaconState {
|
||||
genesis_time: self.genesis_time,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use crate::{test_utils::TestRandom, Epoch, Hash256, PublicKeyBytes};
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
|
||||
@@ -83,7 +83,10 @@ macro_rules! bytes_struct {
|
||||
#[doc = $small_name]
|
||||
#[doc = " (e.g., from the deposit contract)."]
|
||||
#[derive(Clone)]
|
||||
pub struct $name([u8; $byte_size]);
|
||||
pub struct $name {
|
||||
bytes: [u8; $byte_size],
|
||||
decompressed: Option<$type>
|
||||
}
|
||||
};
|
||||
($name: ident, $type: ty, $byte_size: expr, $small_name: expr) => {
|
||||
bytes_struct!($name, $type, $byte_size, $small_name, stringify!($type),
|
||||
@@ -91,15 +94,21 @@ macro_rules! bytes_struct {
|
||||
|
||||
impl $name {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
|
||||
Ok(Self(Self::get_bytes(bytes)?))
|
||||
Ok(Self {
|
||||
bytes: Self::get_bytes(bytes)?,
|
||||
decompressed: None
|
||||
})
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
Self([0; $byte_size])
|
||||
Self {
|
||||
bytes: [0; $byte_size],
|
||||
decompressed: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> Vec<u8> {
|
||||
self.0.to_vec()
|
||||
self.bytes.to_vec()
|
||||
}
|
||||
|
||||
fn get_bytes(bytes: &[u8]) -> Result<[u8; $byte_size], ssz::DecodeError> {
|
||||
@@ -114,23 +123,32 @@ macro_rules! bytes_struct {
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decompress(&mut self) -> Result<(), ssz::DecodeError> {
|
||||
self.decompressed = Some(<&Self as std::convert::TryInto<$type>>::try_into(self)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decompressed(&self) -> &Option<$type> {
|
||||
&self.decompressed
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for $name {
|
||||
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
self.0[..].fmt(formatter)
|
||||
self.bytes[..].fmt(formatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for $name {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
&self.0[..] == &other.0[..]
|
||||
&self.bytes[..] == &other.bytes[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl std::hash::Hash for $name {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state)
|
||||
self.bytes.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +158,7 @@ macro_rules! bytes_struct {
|
||||
type Error = ssz::DecodeError;
|
||||
|
||||
fn try_into(self) -> Result<$type, Self::Error> {
|
||||
<$type>::from_bytes(&self.0[..])
|
||||
<$type>::from_bytes(&self.bytes[..])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use super::*;
|
||||
pub mod impls;
|
||||
|
||||
/// Returned when SSZ decoding fails.
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum DecodeError {
|
||||
/// The bytes supplied were too short to be decoded into the specified type.
|
||||
InvalidByteLength { len: usize, expected: usize },
|
||||
|
||||
Reference in New Issue
Block a user