Merge branch 'unstable' into merge-unstable-to-deneb-20231005
This commit is contained in:
commit
3692622339
@ -3,6 +3,8 @@ use crate::{
|
|||||||
BlockProcessingError, BlockSignatureStrategy, ConsensusContext, SlotProcessingError,
|
BlockProcessingError, BlockSignatureStrategy, ConsensusContext, SlotProcessingError,
|
||||||
VerifyBlockRoot,
|
VerifyBlockRoot,
|
||||||
};
|
};
|
||||||
|
use itertools::Itertools;
|
||||||
|
use std::iter::Peekable;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use types::{BeaconState, BlindedPayload, ChainSpec, EthSpec, Hash256, SignedBeaconBlock, Slot};
|
use types::{BeaconState, BlindedPayload, ChainSpec, EthSpec, Hash256, SignedBeaconBlock, Slot};
|
||||||
|
|
||||||
@ -25,7 +27,7 @@ pub struct BlockReplayer<
|
|||||||
'a,
|
'a,
|
||||||
Spec: EthSpec,
|
Spec: EthSpec,
|
||||||
Error = BlockReplayError,
|
Error = BlockReplayError,
|
||||||
StateRootIter = StateRootIterDefault<Error>,
|
StateRootIter: Iterator<Item = Result<(Hash256, Slot), Error>> = StateRootIterDefault<Error>,
|
||||||
> {
|
> {
|
||||||
state: BeaconState<Spec>,
|
state: BeaconState<Spec>,
|
||||||
spec: &'a ChainSpec,
|
spec: &'a ChainSpec,
|
||||||
@ -36,7 +38,7 @@ pub struct BlockReplayer<
|
|||||||
post_block_hook: Option<PostBlockHook<'a, Spec, Error>>,
|
post_block_hook: Option<PostBlockHook<'a, Spec, Error>>,
|
||||||
pre_slot_hook: Option<PreSlotHook<'a, Spec, Error>>,
|
pre_slot_hook: Option<PreSlotHook<'a, Spec, Error>>,
|
||||||
post_slot_hook: Option<PostSlotHook<'a, Spec, Error>>,
|
post_slot_hook: Option<PostSlotHook<'a, Spec, Error>>,
|
||||||
state_root_iter: Option<StateRootIter>,
|
pub(crate) state_root_iter: Option<Peekable<StateRootIter>>,
|
||||||
state_root_miss: bool,
|
state_root_miss: bool,
|
||||||
_phantom: PhantomData<Error>,
|
_phantom: PhantomData<Error>,
|
||||||
}
|
}
|
||||||
@ -138,7 +140,7 @@ where
|
|||||||
/// `self.state.slot` to the `target_slot` supplied to `apply_blocks` (inclusive of both
|
/// `self.state.slot` to the `target_slot` supplied to `apply_blocks` (inclusive of both
|
||||||
/// endpoints).
|
/// endpoints).
|
||||||
pub fn state_root_iter(mut self, iter: StateRootIter) -> Self {
|
pub fn state_root_iter(mut self, iter: StateRootIter) -> Self {
|
||||||
self.state_root_iter = Some(iter);
|
self.state_root_iter = Some(iter.peekable());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +194,7 @@ where
|
|||||||
// If a state root iterator is configured, use it to find the root.
|
// If a state root iterator is configured, use it to find the root.
|
||||||
if let Some(ref mut state_root_iter) = self.state_root_iter {
|
if let Some(ref mut state_root_iter) = self.state_root_iter {
|
||||||
let opt_root = state_root_iter
|
let opt_root = state_root_iter
|
||||||
.take_while(|res| res.as_ref().map_or(true, |(_, s)| *s <= slot))
|
.peeking_take_while(|res| res.as_ref().map_or(true, |(_, s)| *s <= slot))
|
||||||
.find(|res| res.as_ref().map_or(true, |(_, s)| *s == slot))
|
.find(|res| res.as_ref().map_or(true, |(_, s)| *s == slot))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use crate::per_block_processing::errors::{
|
|||||||
DepositInvalid, HeaderInvalid, IndexedAttestationInvalid, IntoWithIndex,
|
DepositInvalid, HeaderInvalid, IndexedAttestationInvalid, IntoWithIndex,
|
||||||
ProposerSlashingInvalid,
|
ProposerSlashingInvalid,
|
||||||
};
|
};
|
||||||
use crate::{per_block_processing, StateProcessingStrategy};
|
use crate::{per_block_processing, BlockReplayError, BlockReplayer, StateProcessingStrategy};
|
||||||
use crate::{
|
use crate::{
|
||||||
per_block_processing::{process_operations, verify_exit::verify_exit},
|
per_block_processing::{process_operations, verify_exit::verify_exit},
|
||||||
BlockSignatureStrategy, ConsensusContext, VerifyBlockRoot, VerifySignatures,
|
BlockSignatureStrategy, ConsensusContext, VerifyBlockRoot, VerifySignatures,
|
||||||
@ -1035,3 +1035,51 @@ async fn fork_spanning_exit() {
|
|||||||
)
|
)
|
||||||
.expect_err("phase0 exit does not verify against bellatrix state");
|
.expect_err("phase0 exit does not verify against bellatrix state");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check that the block replayer does not consume state roots unnecessarily.
|
||||||
|
#[tokio::test]
|
||||||
|
async fn block_replayer_peeking_state_roots() {
|
||||||
|
let harness = get_harness::<MainnetEthSpec>(EPOCH_OFFSET, VALIDATOR_COUNT).await;
|
||||||
|
|
||||||
|
let target_state = harness.get_current_state();
|
||||||
|
let target_block_root = harness.head_block_root();
|
||||||
|
let target_block = harness
|
||||||
|
.chain
|
||||||
|
.get_blinded_block(&target_block_root)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let parent_block_root = target_block.parent_root();
|
||||||
|
let parent_block = harness
|
||||||
|
.chain
|
||||||
|
.get_blinded_block(&parent_block_root)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
let parent_state = harness
|
||||||
|
.chain
|
||||||
|
.get_state(&parent_block.state_root(), Some(parent_block.slot()))
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Omit the state root for `target_state` but provide a dummy state root at the *next* slot.
|
||||||
|
// If the block replayer is peeking at the state roots rather than consuming them, then the
|
||||||
|
// dummy state should still be there after block replay completes.
|
||||||
|
let dummy_state_root = Hash256::repeat_byte(0xff);
|
||||||
|
let dummy_slot = target_state.slot() + 1;
|
||||||
|
let state_root_iter = vec![Ok::<_, BlockReplayError>((dummy_state_root, dummy_slot))];
|
||||||
|
let block_replayer = BlockReplayer::new(parent_state, &harness.chain.spec)
|
||||||
|
.state_root_iter(state_root_iter.into_iter())
|
||||||
|
.no_signature_verification()
|
||||||
|
.apply_blocks(vec![target_block], None)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
block_replayer
|
||||||
|
.state_root_iter
|
||||||
|
.unwrap()
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.unwrap(),
|
||||||
|
(dummy_state_root, dummy_slot)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -491,6 +491,14 @@ impl<T: SlotClock + 'static, E: EthSpec> AttestationService<T, E> {
|
|||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let log = self.context.log();
|
let log = self.context.log();
|
||||||
|
|
||||||
|
if !validator_duties
|
||||||
|
.iter()
|
||||||
|
.any(|duty_and_proof| duty_and_proof.selection_proof.is_some())
|
||||||
|
{
|
||||||
|
// Exit early if no validator is aggregator
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let aggregated_attestation = &self
|
let aggregated_attestation = &self
|
||||||
.beacon_nodes
|
.beacon_nodes
|
||||||
.first_success(
|
.first_success(
|
||||||
|
Loading…
Reference in New Issue
Block a user