mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-15 02:42:38 +00:00
## Issue Addressed Closes https://github.com/sigp/lighthouse/issues/2371 ## Proposed Changes Backport some changes from `tree-states` that remove duplicated calculations of the `proposer_index`. With this change the proposer index should be calculated only once for each block, and then plumbed through to every place it is required. ## Additional Info In future I hope to add more data to the consensus context that is cached on a per-epoch basis, like the effective balances of validators and the base rewards. There are some other changes to remove indexing in tests that were also useful for `tree-states` (the `tree-states` types don't implement `Index`).
93 lines
2.5 KiB
Rust
93 lines
2.5 KiB
Rust
use std::marker::PhantomData;
|
|
use tree_hash::TreeHash;
|
|
use types::{
|
|
BeaconState, BeaconStateError, ChainSpec, EthSpec, ExecPayload, Hash256, SignedBeaconBlock,
|
|
Slot,
|
|
};
|
|
|
|
#[derive(Debug)]
|
|
pub struct ConsensusContext<T: EthSpec> {
|
|
/// Slot to act as an identifier/safeguard
|
|
slot: Slot,
|
|
/// Proposer index of the block at `slot`.
|
|
proposer_index: Option<u64>,
|
|
/// Block root of the block at `slot`.
|
|
current_block_root: Option<Hash256>,
|
|
_phantom: PhantomData<T>,
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
pub enum ContextError {
|
|
BeaconState(BeaconStateError),
|
|
SlotMismatch { slot: Slot, expected: Slot },
|
|
}
|
|
|
|
impl From<BeaconStateError> for ContextError {
|
|
fn from(e: BeaconStateError) -> Self {
|
|
Self::BeaconState(e)
|
|
}
|
|
}
|
|
|
|
impl<T: EthSpec> ConsensusContext<T> {
|
|
pub fn new(slot: Slot) -> Self {
|
|
Self {
|
|
slot,
|
|
proposer_index: None,
|
|
current_block_root: None,
|
|
_phantom: PhantomData,
|
|
}
|
|
}
|
|
|
|
pub fn set_proposer_index(mut self, proposer_index: u64) -> Self {
|
|
self.proposer_index = Some(proposer_index);
|
|
self
|
|
}
|
|
|
|
pub fn get_proposer_index(
|
|
&mut self,
|
|
state: &BeaconState<T>,
|
|
spec: &ChainSpec,
|
|
) -> Result<u64, ContextError> {
|
|
self.check_slot(state.slot())?;
|
|
|
|
if let Some(proposer_index) = self.proposer_index {
|
|
return Ok(proposer_index);
|
|
}
|
|
|
|
let proposer_index = state.get_beacon_proposer_index(self.slot, spec)? as u64;
|
|
self.proposer_index = Some(proposer_index);
|
|
Ok(proposer_index)
|
|
}
|
|
|
|
pub fn set_current_block_root(mut self, block_root: Hash256) -> Self {
|
|
self.current_block_root = Some(block_root);
|
|
self
|
|
}
|
|
|
|
pub fn get_current_block_root<Payload: ExecPayload<T>>(
|
|
&mut self,
|
|
block: &SignedBeaconBlock<T, Payload>,
|
|
) -> Result<Hash256, ContextError> {
|
|
self.check_slot(block.slot())?;
|
|
|
|
if let Some(current_block_root) = self.current_block_root {
|
|
return Ok(current_block_root);
|
|
}
|
|
|
|
let current_block_root = block.message().tree_hash_root();
|
|
self.current_block_root = Some(current_block_root);
|
|
Ok(current_block_root)
|
|
}
|
|
|
|
fn check_slot(&self, slot: Slot) -> Result<(), ContextError> {
|
|
if slot == self.slot {
|
|
Ok(())
|
|
} else {
|
|
Err(ContextError::SlotMismatch {
|
|
slot,
|
|
expected: self.slot,
|
|
})
|
|
}
|
|
}
|
|
}
|