Skip to content

Commit 54f92cc

Browse files
committed
Use THC for state.inactivity_scores (#2504)
## Issue Addressed - Resolves #2502 ## Proposed Changes Adds tree-hash caching (THC 🍁) for `state.inactivity_scores`, as per #2502. Since the `inactivity_scores` field is introduced during Altair, the cache must be optional (i.e., not present pre-Altair). The mechanism for optional caches was already implemented via the `ParticipationTreeHashCache`, albeit not quite generically enough. To this end, I made the `ParticipationTreeHashCache` more generic and renamed it to `OptionalTreeHashCache`. This made the code a little more verbose around the previous/current epoch participation fields, but overall less verbose when the needs of `inactivity_scores` are considered. All changes to `ParticipationTreeHashCache` should be *non-substantial*. ## Additional Info NA
1 parent 7b46c4b commit 54f92cc

File tree

1 file changed

+52
-43
lines changed

1 file changed

+52
-43
lines changed

consensus/types/src/beacon_state/tree_hash_cache.rs

Lines changed: 52 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
#![allow(clippy::indexing_slicing)]
44

55
use super::Error;
6-
use crate::{
7-
BeaconState, EthSpec, Hash256, ParticipationFlags, ParticipationList, Slot, Unsigned, Validator,
8-
};
6+
use crate::{BeaconState, EthSpec, Hash256, ParticipationList, Slot, Unsigned, Validator};
97
use cached_tree_hash::{int_log, CacheArena, CachedTreeHash, TreeHashCache};
108
use rayon::prelude::*;
119
use ssz_derive::{Decode, Encode};
@@ -141,9 +139,10 @@ pub struct BeaconTreeHashCacheInner<T: EthSpec> {
141139
randao_mixes: TreeHashCache,
142140
slashings: TreeHashCache,
143141
eth1_data_votes: Eth1DataVotesTreeHashCache<T>,
142+
inactivity_scores: OptionalTreeHashCache,
144143
// Participation caches
145-
previous_epoch_participation: ParticipationTreeHashCache,
146-
current_epoch_participation: ParticipationTreeHashCache,
144+
previous_epoch_participation: OptionalTreeHashCache,
145+
current_epoch_participation: OptionalTreeHashCache,
147146
}
148147

149148
impl<T: EthSpec> BeaconTreeHashCacheInner<T> {
@@ -168,10 +167,22 @@ impl<T: EthSpec> BeaconTreeHashCacheInner<T> {
168167
let mut slashings_arena = CacheArena::default();
169168
let slashings = state.slashings().new_tree_hash_cache(&mut slashings_arena);
170169

171-
let previous_epoch_participation =
172-
ParticipationTreeHashCache::new(state, BeaconState::previous_epoch_participation);
173-
let current_epoch_participation =
174-
ParticipationTreeHashCache::new(state, BeaconState::current_epoch_participation);
170+
let inactivity_scores = OptionalTreeHashCache::new(state.inactivity_scores().ok());
171+
172+
let previous_epoch_participation = OptionalTreeHashCache::new(
173+
state
174+
.previous_epoch_participation()
175+
.ok()
176+
.map(ParticipationList::new)
177+
.as_ref(),
178+
);
179+
let current_epoch_participation = OptionalTreeHashCache::new(
180+
state
181+
.current_epoch_participation()
182+
.ok()
183+
.map(ParticipationList::new)
184+
.as_ref(),
185+
);
175186

176187
Self {
177188
previous_state: None,
@@ -185,6 +196,7 @@ impl<T: EthSpec> BeaconTreeHashCacheInner<T> {
185196
balances,
186197
randao_mixes,
187198
slashings,
199+
inactivity_scores,
188200
eth1_data_votes: Eth1DataVotesTreeHashCache::new(state),
189201
previous_epoch_participation,
190202
current_epoch_participation,
@@ -287,12 +299,16 @@ impl<T: EthSpec> BeaconTreeHashCacheInner<T> {
287299
} else {
288300
hasher.write(
289301
self.previous_epoch_participation
290-
.recalculate_tree_hash_root(state.previous_epoch_participation()?)?
302+
.recalculate_tree_hash_root(&ParticipationList::new(
303+
state.previous_epoch_participation()?,
304+
))?
291305
.as_bytes(),
292306
)?;
293307
hasher.write(
294308
self.current_epoch_participation
295-
.recalculate_tree_hash_root(state.current_epoch_participation()?)?
309+
.recalculate_tree_hash_root(&ParticipationList::new(
310+
state.current_epoch_participation()?,
311+
))?
296312
.as_bytes(),
297313
)?;
298314
}
@@ -314,8 +330,11 @@ impl<T: EthSpec> BeaconTreeHashCacheInner<T> {
314330

315331
// Inactivity & light-client sync committees
316332
if let BeaconState::Altair(ref state) = state {
317-
// FIXME(altair): add cache for this field
318-
hasher.write(state.inactivity_scores.tree_hash_root().as_bytes())?;
333+
hasher.write(
334+
self.inactivity_scores
335+
.recalculate_tree_hash_root(&state.inactivity_scores)?
336+
.as_bytes(),
337+
)?;
319338

320339
hasher.write(state.current_sync_committee.tree_hash_root().as_bytes())?;
321340
hasher.write(state.next_sync_committee.tree_hash_root().as_bytes())?;
@@ -513,53 +532,43 @@ impl ParallelValidatorTreeHash {
513532
}
514533

515534
#[derive(Debug, PartialEq, Clone)]
516-
pub struct ParticipationTreeHashCache {
517-
inner: Option<ParticipationTreeHashCacheInner>,
535+
pub struct OptionalTreeHashCache {
536+
inner: Option<OptionalTreeHashCacheInner>,
518537
}
519538

520539
#[derive(Debug, PartialEq, Clone)]
521-
pub struct ParticipationTreeHashCacheInner {
540+
pub struct OptionalTreeHashCacheInner {
522541
arena: CacheArena,
523542
tree_hash_cache: TreeHashCache,
524543
}
525544

526-
impl ParticipationTreeHashCache {
527-
/// Initialize a new cache for the participation list returned by `field` (if any).
528-
fn new<T: EthSpec>(
529-
state: &BeaconState<T>,
530-
field: impl FnOnce(
531-
&BeaconState<T>,
532-
) -> Result<
533-
&VariableList<ParticipationFlags, T::ValidatorRegistryLimit>,
534-
Error,
535-
>,
536-
) -> Self {
537-
let inner = field(state).map(ParticipationTreeHashCacheInner::new).ok();
545+
impl OptionalTreeHashCache {
546+
/// Initialize a new cache if `item.is_some()`.
547+
fn new<C: CachedTreeHash<TreeHashCache>>(item: Option<&C>) -> Self {
548+
let inner = item.map(OptionalTreeHashCacheInner::new);
538549
Self { inner }
539550
}
540551

541-
/// Compute the tree hash root for the given `epoch_participation`.
552+
/// Compute the tree hash root for the given `item`.
542553
///
543554
/// This function will initialize the inner cache if necessary (e.g. when crossing the fork).
544-
fn recalculate_tree_hash_root<N: Unsigned>(
555+
fn recalculate_tree_hash_root<C: CachedTreeHash<TreeHashCache>>(
545556
&mut self,
546-
epoch_participation: &VariableList<ParticipationFlags, N>,
557+
item: &C,
547558
) -> Result<Hash256, Error> {
548559
let cache = self
549560
.inner
550-
.get_or_insert_with(|| ParticipationTreeHashCacheInner::new(epoch_participation));
551-
ParticipationList::new(epoch_participation)
552-
.recalculate_tree_hash_root(&mut cache.arena, &mut cache.tree_hash_cache)
561+
.get_or_insert_with(|| OptionalTreeHashCacheInner::new(item));
562+
item.recalculate_tree_hash_root(&mut cache.arena, &mut cache.tree_hash_cache)
553563
.map_err(Into::into)
554564
}
555565
}
556566

557-
impl ParticipationTreeHashCacheInner {
558-
fn new<N: Unsigned>(epoch_participation: &VariableList<ParticipationFlags, N>) -> Self {
567+
impl OptionalTreeHashCacheInner {
568+
fn new<C: CachedTreeHash<TreeHashCache>>(item: &C) -> Self {
559569
let mut arena = CacheArena::default();
560-
let tree_hash_cache =
561-
ParticipationList::new(epoch_participation).new_tree_hash_cache(&mut arena);
562-
ParticipationTreeHashCacheInner {
570+
let tree_hash_cache = item.new_tree_hash_cache(&mut arena);
571+
OptionalTreeHashCacheInner {
563572
arena,
564573
tree_hash_cache,
565574
}
@@ -576,7 +585,7 @@ impl<T: EthSpec> arbitrary::Arbitrary for BeaconTreeHashCache<T> {
576585
#[cfg(test)]
577586
mod test {
578587
use super::*;
579-
use crate::MainnetEthSpec;
588+
use crate::{MainnetEthSpec, ParticipationFlags};
580589

581590
#[test]
582591
fn validator_node_count() {
@@ -594,13 +603,13 @@ mod test {
594603
test_flag.add_flag(0).unwrap();
595604
let epoch_participation = VariableList::<_, N>::new(vec![test_flag; len]).unwrap();
596605

597-
let mut cache = ParticipationTreeHashCache { inner: None };
606+
let mut cache = OptionalTreeHashCache { inner: None };
598607

599608
let cache_root = cache
600-
.recalculate_tree_hash_root(&epoch_participation)
609+
.recalculate_tree_hash_root(&ParticipationList::new(&epoch_participation))
601610
.unwrap();
602611
let recalc_root = cache
603-
.recalculate_tree_hash_root(&epoch_participation)
612+
.recalculate_tree_hash_root(&ParticipationList::new(&epoch_participation))
604613
.unwrap();
605614

606615
assert_eq!(cache_root, recalc_root, "recalculated root should match");

0 commit comments

Comments
 (0)