Reorg events (#2090)

## Issue Addressed

Resolves #2088

## Proposed Changes

Add the `chain_reorg` SSE event topic

## Additional Info


Co-authored-by: realbigsean <seananderson33@gmail.com>
Co-authored-by: Paul Hauner <paul@paulhauner.com>
This commit is contained in:
realbigsean
2021-06-17 02:10:46 +00:00
parent 3261eff0bf
commit b1657a60e9
10 changed files with 412 additions and 9 deletions

View File

@@ -23,12 +23,14 @@ use tree_hash_derive::TreeHash;
pub use self::committee_cache::CommitteeCache;
pub use clone_config::CloneConfig;
pub use eth_spec::*;
pub use iter::BlockRootsIter;
pub use tree_hash_cache::BeaconTreeHashCache;
#[macro_use]
mod committee_cache;
mod clone_config;
mod exit_cache;
mod iter;
mod pubkey_cache;
mod tests;
mod tree_hash_cache;
@@ -640,6 +642,13 @@ impl<T: EthSpec> BeaconState<T> {
}
}
/// Returns an iterator across the past block roots of `state` in descending slot-order.
///
/// See the docs for `BlockRootsIter` for more detail.
pub fn rev_iter_block_roots<'a>(&'a self, spec: &ChainSpec) -> BlockRootsIter<'a, T> {
BlockRootsIter::new(self, spec.genesis_slot)
}
/// Return the block root at a recent `slot`.
///
/// Spec v0.12.1

View File

@@ -0,0 +1,151 @@
use crate::*;
/// Returns an iterator across the past block roots of `state` in descending slot-order.
///
/// The iterator has the following characteristics:
///
/// - Will only return *at most* `state.block_roots.len()` entries.
/// - Will not return slots prior to the genesis_slot.
/// - Each call to next will result in a slot one less than the prior one (or `None`).
/// - Skipped slots will contain the block root from the prior non-skipped slot.
pub struct BlockRootsIter<'a, T: EthSpec> {
state: &'a BeaconState<T>,
genesis_slot: Slot,
prev: Slot,
}
impl<'a, T: EthSpec> BlockRootsIter<'a, T> {
/// Instantiates a new iterator, returning roots for slots earlier that `state.slot`.
///
/// See the struct-level documentation for more details.
pub fn new(state: &'a BeaconState<T>, genesis_slot: Slot) -> Self {
Self {
state,
genesis_slot,
prev: state.slot,
}
}
}
impl<'a, T: EthSpec> Iterator for BlockRootsIter<'a, T> {
type Item = Result<(Slot, Hash256), Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.prev > self.genesis_slot
&& self.prev
> self
.state
.slot
.saturating_sub(self.state.block_roots.len() as u64)
{
self.prev = self.prev.saturating_sub(1_u64);
Some(
self.state
.get_block_root(self.prev)
.map(|root| (self.prev, *root)),
)
} else {
None
}
}
}
#[cfg(test)]
mod test {
use crate::*;
type E = MinimalEthSpec;
fn root_slot(i: usize) -> (Slot, Hash256) {
(Slot::from(i), Hash256::from_low_u64_be(i as u64))
}
fn all_roots(state: &BeaconState<E>, spec: &ChainSpec) -> Vec<(Slot, Hash256)> {
state
.rev_iter_block_roots(spec)
.collect::<Result<_, _>>()
.unwrap()
}
#[test]
fn block_roots_iter() {
let spec = E::default_spec();
let mut state: BeaconState<E> = BeaconState::new(0, <_>::default(), &spec);
for i in 0..state.block_roots.len() {
state.block_roots[i] = root_slot(i).1;
}
assert_eq!(
state.slot, spec.genesis_slot,
"test assume a genesis slot state"
);
assert_eq!(
all_roots(&state, &spec),
vec![],
"state at genesis slot has no history"
);
state.slot = Slot::new(1);
assert_eq!(
all_roots(&state, &spec),
vec![root_slot(0)],
"first slot after genesis has one slot history"
);
state.slot = Slot::new(2);
assert_eq!(
all_roots(&state, &spec),
vec![root_slot(1), root_slot(0)],
"second slot after genesis has two slot history"
);
state.slot = Slot::from(state.block_roots.len() + 2);
let expected = (2..state.block_roots.len() + 2)
.rev()
.map(|i| (Slot::from(i), *state.get_block_root(Slot::from(i)).unwrap()))
.collect::<Vec<_>>();
assert_eq!(
all_roots(&state, &spec),
expected,
"slot higher than the block roots history"
);
}
#[test]
fn block_roots_iter_non_zero_genesis() {
let mut spec = E::default_spec();
spec.genesis_slot = Slot::new(4);
let mut state: BeaconState<E> = BeaconState::new(0, <_>::default(), &spec);
for i in 0..state.block_roots.len() {
state.block_roots[i] = root_slot(i).1;
}
assert_eq!(
state.slot, spec.genesis_slot,
"test assume a genesis slot state"
);
assert_eq!(
all_roots(&state, &spec),
vec![],
"state at genesis slot has no history"
);
state.slot = Slot::new(5);
assert_eq!(
all_roots(&state, &spec),
vec![root_slot(4)],
"first slot after genesis has one slot history"
);
state.slot = Slot::new(6);
assert_eq!(
all_roots(&state, &spec),
vec![root_slot(5), root_slot(4)],
"second slot after genesis has two slot history"
);
}
}