Consensus context with proposer index caching (#3604)
## 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`).
This commit is contained in:
parent
e4cbdc1c77
commit
59ec6b71b8
@ -80,7 +80,7 @@ use state_processing::{
|
|||||||
},
|
},
|
||||||
per_slot_processing,
|
per_slot_processing,
|
||||||
state_advance::{complete_state_advance, partial_state_advance},
|
state_advance::{complete_state_advance, partial_state_advance},
|
||||||
BlockSignatureStrategy, SigVerifiedOp, VerifyBlockRoot, VerifyOperation,
|
BlockSignatureStrategy, ConsensusContext, SigVerifiedOp, VerifyBlockRoot, VerifyOperation,
|
||||||
};
|
};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -3498,7 +3498,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let slot = state.slot();
|
let slot = state.slot();
|
||||||
let proposer_index = state.get_beacon_proposer_index(state.slot(), &self.spec)? as u64;
|
|
||||||
|
|
||||||
let sync_aggregate = if matches!(&state, BeaconState::Base(_)) {
|
let sync_aggregate = if matches!(&state, BeaconState::Base(_)) {
|
||||||
None
|
None
|
||||||
@ -3645,12 +3644,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
ProduceBlockVerification::VerifyRandao => BlockSignatureStrategy::VerifyRandao,
|
ProduceBlockVerification::VerifyRandao => BlockSignatureStrategy::VerifyRandao,
|
||||||
ProduceBlockVerification::NoVerification => BlockSignatureStrategy::NoVerification,
|
ProduceBlockVerification::NoVerification => BlockSignatureStrategy::NoVerification,
|
||||||
};
|
};
|
||||||
|
// Use a context without block root or proposer index so that both are checked.
|
||||||
|
let mut ctxt = ConsensusContext::new(block.slot());
|
||||||
per_block_processing(
|
per_block_processing(
|
||||||
&mut state,
|
&mut state,
|
||||||
&block,
|
&block,
|
||||||
None,
|
|
||||||
signature_strategy,
|
signature_strategy,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
&self.spec,
|
&self.spec,
|
||||||
)?;
|
)?;
|
||||||
drop(process_timer);
|
drop(process_timer);
|
||||||
|
@ -71,7 +71,8 @@ use state_processing::{
|
|||||||
block_signature_verifier::{BlockSignatureVerifier, Error as BlockSignatureVerifierError},
|
block_signature_verifier::{BlockSignatureVerifier, Error as BlockSignatureVerifierError},
|
||||||
per_block_processing, per_slot_processing,
|
per_block_processing, per_slot_processing,
|
||||||
state_advance::partial_state_advance,
|
state_advance::partial_state_advance,
|
||||||
BlockProcessingError, BlockSignatureStrategy, SlotProcessingError, VerifyBlockRoot,
|
BlockProcessingError, BlockSignatureStrategy, ConsensusContext, SlotProcessingError,
|
||||||
|
VerifyBlockRoot,
|
||||||
};
|
};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -549,7 +550,7 @@ pub fn signature_verify_chain_segment<T: BeaconChainTypes>(
|
|||||||
let mut signature_verifier = get_signature_verifier(&state, &pubkey_cache, &chain.spec);
|
let mut signature_verifier = get_signature_verifier(&state, &pubkey_cache, &chain.spec);
|
||||||
|
|
||||||
for (block_root, block) in &chain_segment {
|
for (block_root, block) in &chain_segment {
|
||||||
signature_verifier.include_all_signatures(block, Some(*block_root))?;
|
signature_verifier.include_all_signatures(block, Some(*block_root), None)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if signature_verifier.verify().is_err() {
|
if signature_verifier.verify().is_err() {
|
||||||
@ -560,10 +561,17 @@ pub fn signature_verify_chain_segment<T: BeaconChainTypes>(
|
|||||||
|
|
||||||
let mut signature_verified_blocks = chain_segment
|
let mut signature_verified_blocks = chain_segment
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(block_root, block)| SignatureVerifiedBlock {
|
.map(|(block_root, block)| {
|
||||||
block,
|
// Proposer index has already been verified above during signature verification.
|
||||||
block_root,
|
let consensus_context = ConsensusContext::new(block.slot())
|
||||||
parent: None,
|
.set_current_block_root(block_root)
|
||||||
|
.set_proposer_index(block.message().proposer_index());
|
||||||
|
SignatureVerifiedBlock {
|
||||||
|
block,
|
||||||
|
block_root,
|
||||||
|
parent: None,
|
||||||
|
consensus_context,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
@ -582,6 +590,7 @@ pub struct GossipVerifiedBlock<T: BeaconChainTypes> {
|
|||||||
pub block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
pub block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||||
pub block_root: Hash256,
|
pub block_root: Hash256,
|
||||||
parent: Option<PreProcessingSnapshot<T::EthSpec>>,
|
parent: Option<PreProcessingSnapshot<T::EthSpec>>,
|
||||||
|
consensus_context: ConsensusContext<T::EthSpec>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper around a `SignedBeaconBlock` that indicates that all signatures (except the deposit
|
/// A wrapper around a `SignedBeaconBlock` that indicates that all signatures (except the deposit
|
||||||
@ -590,6 +599,7 @@ pub struct SignatureVerifiedBlock<T: BeaconChainTypes> {
|
|||||||
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||||
block_root: Hash256,
|
block_root: Hash256,
|
||||||
parent: Option<PreProcessingSnapshot<T::EthSpec>>,
|
parent: Option<PreProcessingSnapshot<T::EthSpec>>,
|
||||||
|
consensus_context: ConsensusContext<T::EthSpec>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used to await the result of executing payload with a remote EE.
|
/// Used to await the result of executing payload with a remote EE.
|
||||||
@ -863,10 +873,16 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
|
|||||||
// Validate the block's execution_payload (if any).
|
// Validate the block's execution_payload (if any).
|
||||||
validate_execution_payload_for_gossip(&parent_block, block.message(), chain)?;
|
validate_execution_payload_for_gossip(&parent_block, block.message(), chain)?;
|
||||||
|
|
||||||
|
// Having checked the proposer index and the block root we can cache them.
|
||||||
|
let consensus_context = ConsensusContext::new(block.slot())
|
||||||
|
.set_current_block_root(block_root)
|
||||||
|
.set_proposer_index(block.message().proposer_index());
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
block,
|
block,
|
||||||
block_root,
|
block_root,
|
||||||
parent,
|
parent,
|
||||||
|
consensus_context,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -926,10 +942,13 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
|
|||||||
|
|
||||||
let mut signature_verifier = get_signature_verifier(&state, &pubkey_cache, &chain.spec);
|
let mut signature_verifier = get_signature_verifier(&state, &pubkey_cache, &chain.spec);
|
||||||
|
|
||||||
signature_verifier.include_all_signatures(&block, Some(block_root))?;
|
signature_verifier.include_all_signatures(&block, Some(block_root), None)?;
|
||||||
|
|
||||||
if signature_verifier.verify().is_ok() {
|
if signature_verifier.verify().is_ok() {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
consensus_context: ConsensusContext::new(block.slot())
|
||||||
|
.set_current_block_root(block_root)
|
||||||
|
.set_proposer_index(block.message().proposer_index()),
|
||||||
block,
|
block,
|
||||||
block_root,
|
block_root,
|
||||||
parent: Some(parent),
|
parent: Some(parent),
|
||||||
@ -972,13 +991,18 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
|
|||||||
|
|
||||||
let mut signature_verifier = get_signature_verifier(&state, &pubkey_cache, &chain.spec);
|
let mut signature_verifier = get_signature_verifier(&state, &pubkey_cache, &chain.spec);
|
||||||
|
|
||||||
signature_verifier.include_all_signatures_except_proposal(&block)?;
|
// Gossip verification has already checked the proposer index. Use it to check the RANDAO
|
||||||
|
// signature.
|
||||||
|
let verified_proposer_index = Some(block.message().proposer_index());
|
||||||
|
signature_verifier
|
||||||
|
.include_all_signatures_except_proposal(&block, verified_proposer_index)?;
|
||||||
|
|
||||||
if signature_verifier.verify().is_ok() {
|
if signature_verifier.verify().is_ok() {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
block,
|
block,
|
||||||
block_root: from.block_root,
|
block_root: from.block_root,
|
||||||
parent: Some(parent),
|
parent: Some(parent),
|
||||||
|
consensus_context: from.consensus_context,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(BlockError::InvalidSignature)
|
Err(BlockError::InvalidSignature)
|
||||||
@ -1015,8 +1039,14 @@ impl<T: BeaconChainTypes> IntoExecutionPendingBlock<T> for SignatureVerifiedBloc
|
|||||||
.map_err(|e| BlockSlashInfo::SignatureValid(header.clone(), e))?
|
.map_err(|e| BlockSlashInfo::SignatureValid(header.clone(), e))?
|
||||||
};
|
};
|
||||||
|
|
||||||
ExecutionPendingBlock::from_signature_verified_components(block, block_root, parent, chain)
|
ExecutionPendingBlock::from_signature_verified_components(
|
||||||
.map_err(|e| BlockSlashInfo::SignatureValid(header, e))
|
block,
|
||||||
|
block_root,
|
||||||
|
parent,
|
||||||
|
self.consensus_context,
|
||||||
|
chain,
|
||||||
|
)
|
||||||
|
.map_err(|e| BlockSlashInfo::SignatureValid(header, e))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block(&self) -> &SignedBeaconBlock<T::EthSpec> {
|
fn block(&self) -> &SignedBeaconBlock<T::EthSpec> {
|
||||||
@ -1057,6 +1087,7 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
|||||||
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||||
block_root: Hash256,
|
block_root: Hash256,
|
||||||
parent: PreProcessingSnapshot<T::EthSpec>,
|
parent: PreProcessingSnapshot<T::EthSpec>,
|
||||||
|
mut consensus_context: ConsensusContext<T::EthSpec>,
|
||||||
chain: &Arc<BeaconChain<T>>,
|
chain: &Arc<BeaconChain<T>>,
|
||||||
) -> Result<Self, BlockError<T::EthSpec>> {
|
) -> Result<Self, BlockError<T::EthSpec>> {
|
||||||
if let Some(parent) = chain
|
if let Some(parent) = chain
|
||||||
@ -1340,10 +1371,10 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
|||||||
if let Err(err) = per_block_processing(
|
if let Err(err) = per_block_processing(
|
||||||
&mut state,
|
&mut state,
|
||||||
&block,
|
&block,
|
||||||
Some(block_root),
|
|
||||||
// Signatures were verified earlier in this function.
|
// Signatures were verified earlier in this function.
|
||||||
BlockSignatureStrategy::NoVerification,
|
BlockSignatureStrategy::NoVerification,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut consensus_context,
|
||||||
&chain.spec,
|
&chain.spec,
|
||||||
) {
|
) {
|
||||||
match err {
|
match err {
|
||||||
|
@ -5,7 +5,8 @@ use proto_array::CountUnrealizedFull;
|
|||||||
use slog::{info, warn, Logger};
|
use slog::{info, warn, Logger};
|
||||||
use state_processing::state_advance::complete_state_advance;
|
use state_processing::state_advance::complete_state_advance;
|
||||||
use state_processing::{
|
use state_processing::{
|
||||||
per_block_processing, per_block_processing::BlockSignatureStrategy, VerifyBlockRoot,
|
per_block_processing, per_block_processing::BlockSignatureStrategy, ConsensusContext,
|
||||||
|
VerifyBlockRoot,
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -172,12 +173,14 @@ pub fn reset_fork_choice_to_finalization<E: EthSpec, Hot: ItemStore<E>, Cold: It
|
|||||||
complete_state_advance(&mut state, None, block.slot(), spec)
|
complete_state_advance(&mut state, None, block.slot(), spec)
|
||||||
.map_err(|e| format!("State advance failed: {:?}", e))?;
|
.map_err(|e| format!("State advance failed: {:?}", e))?;
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(block.slot())
|
||||||
|
.set_proposer_index(block.message().proposer_index());
|
||||||
per_block_processing(
|
per_block_processing(
|
||||||
&mut state,
|
&mut state,
|
||||||
&block,
|
&block,
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::NoVerification,
|
BlockSignatureStrategy::NoVerification,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
spec,
|
spec,
|
||||||
)
|
)
|
||||||
.map_err(|e| format!("Error replaying block: {:?}", e))?;
|
.map_err(|e| format!("Error replaying block: {:?}", e))?;
|
||||||
|
@ -11,7 +11,7 @@ use slasher::{Config as SlasherConfig, Slasher};
|
|||||||
use state_processing::{
|
use state_processing::{
|
||||||
common::get_indexed_attestation,
|
common::get_indexed_attestation,
|
||||||
per_block_processing::{per_block_processing, BlockSignatureStrategy},
|
per_block_processing::{per_block_processing, BlockSignatureStrategy},
|
||||||
per_slot_processing, BlockProcessingError, VerifyBlockRoot,
|
per_slot_processing, BlockProcessingError, ConsensusContext, VerifyBlockRoot,
|
||||||
};
|
};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -1139,14 +1139,15 @@ async fn add_base_block_to_altair_chain() {
|
|||||||
// Ensure that it would be impossible to apply this block to `per_block_processing`.
|
// Ensure that it would be impossible to apply this block to `per_block_processing`.
|
||||||
{
|
{
|
||||||
let mut state = state;
|
let mut state = state;
|
||||||
|
let mut ctxt = ConsensusContext::new(base_block.slot());
|
||||||
per_slot_processing(&mut state, None, &harness.chain.spec).unwrap();
|
per_slot_processing(&mut state, None, &harness.chain.spec).unwrap();
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
per_block_processing(
|
per_block_processing(
|
||||||
&mut state,
|
&mut state,
|
||||||
&base_block,
|
&base_block,
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::NoVerification,
|
BlockSignatureStrategy::NoVerification,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
&harness.chain.spec,
|
&harness.chain.spec,
|
||||||
),
|
),
|
||||||
Err(BlockProcessingError::InconsistentBlockFork(
|
Err(BlockProcessingError::InconsistentBlockFork(
|
||||||
@ -1271,14 +1272,15 @@ async fn add_altair_block_to_base_chain() {
|
|||||||
// Ensure that it would be impossible to apply this block to `per_block_processing`.
|
// Ensure that it would be impossible to apply this block to `per_block_processing`.
|
||||||
{
|
{
|
||||||
let mut state = state;
|
let mut state = state;
|
||||||
|
let mut ctxt = ConsensusContext::new(altair_block.slot());
|
||||||
per_slot_processing(&mut state, None, &harness.chain.spec).unwrap();
|
per_slot_processing(&mut state, None, &harness.chain.spec).unwrap();
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
per_block_processing(
|
per_block_processing(
|
||||||
&mut state,
|
&mut state,
|
||||||
&altair_block,
|
&altair_block,
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::NoVerification,
|
BlockSignatureStrategy::NoVerification,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
&harness.chain.spec,
|
&harness.chain.spec,
|
||||||
),
|
),
|
||||||
Err(BlockProcessingError::InconsistentBlockFork(
|
Err(BlockProcessingError::InconsistentBlockFork(
|
||||||
|
@ -4,7 +4,8 @@ use crate::{Error, ItemStore, KeyValueStore};
|
|||||||
use itertools::{process_results, Itertools};
|
use itertools::{process_results, Itertools};
|
||||||
use slog::info;
|
use slog::info;
|
||||||
use state_processing::{
|
use state_processing::{
|
||||||
per_block_processing, per_slot_processing, BlockSignatureStrategy, VerifyBlockRoot,
|
per_block_processing, per_slot_processing, BlockSignatureStrategy, ConsensusContext,
|
||||||
|
VerifyBlockRoot,
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{EthSpec, Hash256};
|
use types::{EthSpec, Hash256};
|
||||||
@ -87,12 +88,16 @@ where
|
|||||||
|
|
||||||
// Apply block.
|
// Apply block.
|
||||||
if let Some(block) = block {
|
if let Some(block) = block {
|
||||||
|
let mut ctxt = ConsensusContext::new(block.slot())
|
||||||
|
.set_current_block_root(block_root)
|
||||||
|
.set_proposer_index(block.message().proposer_index());
|
||||||
|
|
||||||
per_block_processing(
|
per_block_processing(
|
||||||
&mut state,
|
&mut state,
|
||||||
&block,
|
&block,
|
||||||
Some(block_root),
|
|
||||||
BlockSignatureStrategy::NoVerification,
|
BlockSignatureStrategy::NoVerification,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
&self.spec,
|
&self.spec,
|
||||||
)
|
)
|
||||||
.map_err(HotColdDBError::BlockReplayBlockError)?;
|
.map_err(HotColdDBError::BlockReplayBlockError)?;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
per_block_processing, per_epoch_processing::EpochProcessingSummary, per_slot_processing,
|
per_block_processing, per_epoch_processing::EpochProcessingSummary, per_slot_processing,
|
||||||
BlockProcessingError, BlockSignatureStrategy, SlotProcessingError, VerifyBlockRoot,
|
BlockProcessingError, BlockSignatureStrategy, ConsensusContext, SlotProcessingError,
|
||||||
|
VerifyBlockRoot,
|
||||||
};
|
};
|
||||||
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};
|
||||||
@ -254,12 +255,16 @@ where
|
|||||||
VerifyBlockRoot::False
|
VerifyBlockRoot::False
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// Proposer index was already checked when this block was originally processed, we
|
||||||
|
// can omit recomputing it during replay.
|
||||||
|
let mut ctxt = ConsensusContext::new(block.slot())
|
||||||
|
.set_proposer_index(block.message().proposer_index());
|
||||||
per_block_processing(
|
per_block_processing(
|
||||||
&mut self.state,
|
&mut self.state,
|
||||||
block,
|
block,
|
||||||
None,
|
|
||||||
self.block_sig_strategy,
|
self.block_sig_strategy,
|
||||||
verify_block_root,
|
verify_block_root,
|
||||||
|
&mut ctxt,
|
||||||
self.spec,
|
self.spec,
|
||||||
)
|
)
|
||||||
.map_err(BlockReplayError::from)?;
|
.map_err(BlockReplayError::from)?;
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
use crate::common::{decrease_balance, increase_balance, initiate_validator_exit};
|
use crate::{
|
||||||
|
common::{decrease_balance, increase_balance, initiate_validator_exit},
|
||||||
|
per_block_processing::errors::BlockProcessingError,
|
||||||
|
ConsensusContext,
|
||||||
|
};
|
||||||
use safe_arith::SafeArith;
|
use safe_arith::SafeArith;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use types::{
|
use types::{
|
||||||
consts::altair::{PROPOSER_WEIGHT, WEIGHT_DENOMINATOR},
|
consts::altair::{PROPOSER_WEIGHT, WEIGHT_DENOMINATOR},
|
||||||
BeaconStateError as Error, *,
|
*,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Slash the validator with index `slashed_index`.
|
/// Slash the validator with index `slashed_index`.
|
||||||
@ -11,8 +15,9 @@ pub fn slash_validator<T: EthSpec>(
|
|||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
slashed_index: usize,
|
slashed_index: usize,
|
||||||
opt_whistleblower_index: Option<usize>,
|
opt_whistleblower_index: Option<usize>,
|
||||||
|
ctxt: &mut ConsensusContext<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
let epoch = state.current_epoch();
|
let epoch = state.current_epoch();
|
||||||
|
|
||||||
initiate_validator_exit(state, slashed_index, spec)?;
|
initiate_validator_exit(state, slashed_index, spec)?;
|
||||||
@ -39,7 +44,7 @@ pub fn slash_validator<T: EthSpec>(
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Apply proposer and whistleblower rewards
|
// Apply proposer and whistleblower rewards
|
||||||
let proposer_index = state.get_beacon_proposer_index(state.slot(), spec)?;
|
let proposer_index = ctxt.get_proposer_index(state, spec)? as usize;
|
||||||
let whistleblower_index = opt_whistleblower_index.unwrap_or(proposer_index);
|
let whistleblower_index = opt_whistleblower_index.unwrap_or(proposer_index);
|
||||||
let whistleblower_reward =
|
let whistleblower_reward =
|
||||||
validator_effective_balance.safe_div(spec.whistleblower_reward_quotient)?;
|
validator_effective_balance.safe_div(spec.whistleblower_reward_quotient)?;
|
||||||
@ -52,7 +57,7 @@ pub fn slash_validator<T: EthSpec>(
|
|||||||
|
|
||||||
// Ensure the whistleblower index is in the validator registry.
|
// Ensure the whistleblower index is in the validator registry.
|
||||||
if state.validators().get(whistleblower_index).is_none() {
|
if state.validators().get(whistleblower_index).is_none() {
|
||||||
return Err(BeaconStateError::UnknownValidator(whistleblower_index));
|
return Err(BeaconStateError::UnknownValidator(whistleblower_index).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
increase_balance(state, proposer_index, proposer_reward)?;
|
increase_balance(state, proposer_index, proposer_reward)?;
|
||||||
|
92
consensus/state_processing/src/consensus_context.rs
Normal file
92
consensus/state_processing/src/consensus_context.rs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
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,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,7 @@ mod metrics;
|
|||||||
|
|
||||||
pub mod block_replayer;
|
pub mod block_replayer;
|
||||||
pub mod common;
|
pub mod common;
|
||||||
|
pub mod consensus_context;
|
||||||
pub mod genesis;
|
pub mod genesis;
|
||||||
pub mod per_block_processing;
|
pub mod per_block_processing;
|
||||||
pub mod per_epoch_processing;
|
pub mod per_epoch_processing;
|
||||||
@ -27,6 +28,7 @@ pub mod upgrade;
|
|||||||
pub mod verify_operation;
|
pub mod verify_operation;
|
||||||
|
|
||||||
pub use block_replayer::{BlockReplayError, BlockReplayer, StateRootStrategy};
|
pub use block_replayer::{BlockReplayError, BlockReplayer, StateRootStrategy};
|
||||||
|
pub use consensus_context::{ConsensusContext, ContextError};
|
||||||
pub use genesis::{
|
pub use genesis::{
|
||||||
eth2_genesis_time, initialize_beacon_state_from_eth1, is_valid_genesis_state,
|
eth2_genesis_time, initialize_beacon_state_from_eth1, is_valid_genesis_state,
|
||||||
process_activations,
|
process_activations,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::consensus_context::ConsensusContext;
|
||||||
use errors::{BlockOperationError, BlockProcessingError, HeaderInvalid};
|
use errors::{BlockOperationError, BlockProcessingError, HeaderInvalid};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use safe_arith::{ArithError, SafeArith};
|
use safe_arith::{ArithError, SafeArith};
|
||||||
@ -90,9 +91,9 @@ pub enum VerifyBlockRoot {
|
|||||||
pub fn per_block_processing<T: EthSpec, Payload: ExecPayload<T>>(
|
pub fn per_block_processing<T: EthSpec, Payload: ExecPayload<T>>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
signed_block: &SignedBeaconBlock<T, Payload>,
|
signed_block: &SignedBeaconBlock<T, Payload>,
|
||||||
block_root: Option<Hash256>,
|
|
||||||
block_signature_strategy: BlockSignatureStrategy,
|
block_signature_strategy: BlockSignatureStrategy,
|
||||||
verify_block_root: VerifyBlockRoot,
|
verify_block_root: VerifyBlockRoot,
|
||||||
|
ctxt: &mut ConsensusContext<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
let block = signed_block.message();
|
let block = signed_block.message();
|
||||||
@ -110,6 +111,8 @@ pub fn per_block_processing<T: EthSpec, Payload: ExecPayload<T>>(
|
|||||||
let verify_signatures = match block_signature_strategy {
|
let verify_signatures = match block_signature_strategy {
|
||||||
BlockSignatureStrategy::VerifyBulk => {
|
BlockSignatureStrategy::VerifyBulk => {
|
||||||
// Verify all signatures in the block at once.
|
// Verify all signatures in the block at once.
|
||||||
|
let block_root = Some(ctxt.get_current_block_root(signed_block)?);
|
||||||
|
let proposer_index = Some(ctxt.get_proposer_index(state, spec)?);
|
||||||
block_verify!(
|
block_verify!(
|
||||||
BlockSignatureVerifier::verify_entire_block(
|
BlockSignatureVerifier::verify_entire_block(
|
||||||
state,
|
state,
|
||||||
@ -117,6 +120,7 @@ pub fn per_block_processing<T: EthSpec, Payload: ExecPayload<T>>(
|
|||||||
|pk_bytes| pk_bytes.decompress().ok().map(Cow::Owned),
|
|pk_bytes| pk_bytes.decompress().ok().map(Cow::Owned),
|
||||||
signed_block,
|
signed_block,
|
||||||
block_root,
|
block_root,
|
||||||
|
proposer_index,
|
||||||
spec
|
spec
|
||||||
)
|
)
|
||||||
.is_ok(),
|
.is_ok(),
|
||||||
@ -133,11 +137,12 @@ pub fn per_block_processing<T: EthSpec, Payload: ExecPayload<T>>(
|
|||||||
state,
|
state,
|
||||||
block.temporary_block_header(),
|
block.temporary_block_header(),
|
||||||
verify_block_root,
|
verify_block_root,
|
||||||
|
ctxt,
|
||||||
spec,
|
spec,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if verify_signatures.is_true() {
|
if verify_signatures.is_true() {
|
||||||
verify_block_signature(state, signed_block, block_root, spec)?;
|
verify_block_signature(state, signed_block, ctxt, spec)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let verify_randao = if let BlockSignatureStrategy::VerifyRandao = block_signature_strategy {
|
let verify_randao = if let BlockSignatureStrategy::VerifyRandao = block_signature_strategy {
|
||||||
@ -157,9 +162,9 @@ pub fn per_block_processing<T: EthSpec, Payload: ExecPayload<T>>(
|
|||||||
process_execution_payload(state, payload, spec)?;
|
process_execution_payload(state, payload, spec)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_randao(state, block, verify_randao, spec)?;
|
process_randao(state, block, verify_randao, ctxt, spec)?;
|
||||||
process_eth1_data(state, block.body().eth1_data())?;
|
process_eth1_data(state, block.body().eth1_data())?;
|
||||||
process_operations(state, block.body(), proposer_index, verify_signatures, spec)?;
|
process_operations(state, block.body(), verify_signatures, ctxt, spec)?;
|
||||||
|
|
||||||
if let Ok(sync_aggregate) = block.body().sync_aggregate() {
|
if let Ok(sync_aggregate) = block.body().sync_aggregate() {
|
||||||
process_sync_aggregate(
|
process_sync_aggregate(
|
||||||
@ -179,6 +184,7 @@ pub fn process_block_header<T: EthSpec>(
|
|||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
block_header: BeaconBlockHeader,
|
block_header: BeaconBlockHeader,
|
||||||
verify_block_root: VerifyBlockRoot,
|
verify_block_root: VerifyBlockRoot,
|
||||||
|
ctxt: &mut ConsensusContext<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<u64, BlockOperationError<HeaderInvalid>> {
|
) -> Result<u64, BlockOperationError<HeaderInvalid>> {
|
||||||
// Verify that the slots match
|
// Verify that the slots match
|
||||||
@ -197,8 +203,8 @@ pub fn process_block_header<T: EthSpec>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Verify that proposer index is the correct index
|
// Verify that proposer index is the correct index
|
||||||
let proposer_index = block_header.proposer_index as usize;
|
let proposer_index = block_header.proposer_index;
|
||||||
let state_proposer_index = state.get_beacon_proposer_index(block_header.slot, spec)?;
|
let state_proposer_index = ctxt.get_proposer_index(state, spec)?;
|
||||||
verify!(
|
verify!(
|
||||||
proposer_index == state_proposer_index,
|
proposer_index == state_proposer_index,
|
||||||
HeaderInvalid::ProposerIndexMismatch {
|
HeaderInvalid::ProposerIndexMismatch {
|
||||||
@ -222,11 +228,11 @@ pub fn process_block_header<T: EthSpec>(
|
|||||||
|
|
||||||
// Verify proposer is not slashed
|
// Verify proposer is not slashed
|
||||||
verify!(
|
verify!(
|
||||||
!state.get_validator(proposer_index)?.slashed,
|
!state.get_validator(proposer_index as usize)?.slashed,
|
||||||
HeaderInvalid::ProposerSlashed(proposer_index)
|
HeaderInvalid::ProposerSlashed(proposer_index)
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(proposer_index as u64)
|
Ok(proposer_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verifies the signature of a block.
|
/// Verifies the signature of a block.
|
||||||
@ -235,15 +241,18 @@ pub fn process_block_header<T: EthSpec>(
|
|||||||
pub fn verify_block_signature<T: EthSpec, Payload: ExecPayload<T>>(
|
pub fn verify_block_signature<T: EthSpec, Payload: ExecPayload<T>>(
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
block: &SignedBeaconBlock<T, Payload>,
|
block: &SignedBeaconBlock<T, Payload>,
|
||||||
block_root: Option<Hash256>,
|
ctxt: &mut ConsensusContext<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), BlockOperationError<HeaderInvalid>> {
|
) -> Result<(), BlockOperationError<HeaderInvalid>> {
|
||||||
|
let block_root = Some(ctxt.get_current_block_root(block)?);
|
||||||
|
let proposer_index = Some(ctxt.get_proposer_index(state, spec)?);
|
||||||
verify!(
|
verify!(
|
||||||
block_proposal_signature_set(
|
block_proposal_signature_set(
|
||||||
state,
|
state,
|
||||||
|i| get_pubkey_from_state(state, i),
|
|i| get_pubkey_from_state(state, i),
|
||||||
block,
|
block,
|
||||||
block_root,
|
block_root,
|
||||||
|
proposer_index,
|
||||||
spec
|
spec
|
||||||
)?
|
)?
|
||||||
.verify(),
|
.verify(),
|
||||||
@ -259,12 +268,21 @@ pub fn process_randao<T: EthSpec, Payload: ExecPayload<T>>(
|
|||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
block: BeaconBlockRef<'_, T, Payload>,
|
block: BeaconBlockRef<'_, T, Payload>,
|
||||||
verify_signatures: VerifySignatures,
|
verify_signatures: VerifySignatures,
|
||||||
|
ctxt: &mut ConsensusContext<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
if verify_signatures.is_true() {
|
if verify_signatures.is_true() {
|
||||||
// Verify RANDAO reveal signature.
|
// Verify RANDAO reveal signature.
|
||||||
|
let proposer_index = ctxt.get_proposer_index(state, spec)?;
|
||||||
block_verify!(
|
block_verify!(
|
||||||
randao_signature_set(state, |i| get_pubkey_from_state(state, i), block, spec)?.verify(),
|
randao_signature_set(
|
||||||
|
state,
|
||||||
|
|i| get_pubkey_from_state(state, i),
|
||||||
|
block,
|
||||||
|
Some(proposer_index),
|
||||||
|
spec
|
||||||
|
)?
|
||||||
|
.verify(),
|
||||||
BlockProcessingError::RandaoSignatureInvalid
|
BlockProcessingError::RandaoSignatureInvalid
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -123,10 +123,11 @@ where
|
|||||||
decompressor: D,
|
decompressor: D,
|
||||||
block: &'a SignedBeaconBlock<T, Payload>,
|
block: &'a SignedBeaconBlock<T, Payload>,
|
||||||
block_root: Option<Hash256>,
|
block_root: Option<Hash256>,
|
||||||
|
verified_proposer_index: Option<u64>,
|
||||||
spec: &'a ChainSpec,
|
spec: &'a ChainSpec,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut verifier = Self::new(state, get_pubkey, decompressor, spec);
|
let mut verifier = Self::new(state, get_pubkey, decompressor, spec);
|
||||||
verifier.include_all_signatures(block, block_root)?;
|
verifier.include_all_signatures(block, block_root, verified_proposer_index)?;
|
||||||
verifier.verify()
|
verifier.verify()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,9 +136,10 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
block: &'a SignedBeaconBlock<T, Payload>,
|
block: &'a SignedBeaconBlock<T, Payload>,
|
||||||
block_root: Option<Hash256>,
|
block_root: Option<Hash256>,
|
||||||
|
verified_proposer_index: Option<u64>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.include_block_proposal(block, block_root)?;
|
self.include_block_proposal(block, block_root, verified_proposer_index)?;
|
||||||
self.include_all_signatures_except_proposal(block)?;
|
self.include_all_signatures_except_proposal(block, verified_proposer_index)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -147,8 +149,9 @@ where
|
|||||||
pub fn include_all_signatures_except_proposal<Payload: ExecPayload<T>>(
|
pub fn include_all_signatures_except_proposal<Payload: ExecPayload<T>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
block: &'a SignedBeaconBlock<T, Payload>,
|
block: &'a SignedBeaconBlock<T, Payload>,
|
||||||
|
verified_proposer_index: Option<u64>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.include_randao_reveal(block)?;
|
self.include_randao_reveal(block, verified_proposer_index)?;
|
||||||
self.include_proposer_slashings(block)?;
|
self.include_proposer_slashings(block)?;
|
||||||
self.include_attester_slashings(block)?;
|
self.include_attester_slashings(block)?;
|
||||||
self.include_attestations(block)?;
|
self.include_attestations(block)?;
|
||||||
@ -164,12 +167,14 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
block: &'a SignedBeaconBlock<T, Payload>,
|
block: &'a SignedBeaconBlock<T, Payload>,
|
||||||
block_root: Option<Hash256>,
|
block_root: Option<Hash256>,
|
||||||
|
verified_proposer_index: Option<u64>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let set = block_proposal_signature_set(
|
let set = block_proposal_signature_set(
|
||||||
self.state,
|
self.state,
|
||||||
self.get_pubkey.clone(),
|
self.get_pubkey.clone(),
|
||||||
block,
|
block,
|
||||||
block_root,
|
block_root,
|
||||||
|
verified_proposer_index,
|
||||||
self.spec,
|
self.spec,
|
||||||
)?;
|
)?;
|
||||||
self.sets.push(set);
|
self.sets.push(set);
|
||||||
@ -180,11 +185,13 @@ where
|
|||||||
pub fn include_randao_reveal<Payload: ExecPayload<T>>(
|
pub fn include_randao_reveal<Payload: ExecPayload<T>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
block: &'a SignedBeaconBlock<T, Payload>,
|
block: &'a SignedBeaconBlock<T, Payload>,
|
||||||
|
verified_proposer_index: Option<u64>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let set = randao_signature_set(
|
let set = randao_signature_set(
|
||||||
self.state,
|
self.state,
|
||||||
self.get_pubkey.clone(),
|
self.get_pubkey.clone(),
|
||||||
block.message(),
|
block.message(),
|
||||||
|
verified_proposer_index,
|
||||||
self.spec,
|
self.spec,
|
||||||
)?;
|
)?;
|
||||||
self.sets.push(set);
|
self.sets.push(set);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use super::signature_sets::Error as SignatureSetError;
|
use super::signature_sets::Error as SignatureSetError;
|
||||||
|
use crate::ContextError;
|
||||||
use merkle_proof::MerkleTreeError;
|
use merkle_proof::MerkleTreeError;
|
||||||
use safe_arith::ArithError;
|
use safe_arith::ArithError;
|
||||||
use types::*;
|
use types::*;
|
||||||
@ -70,6 +71,7 @@ pub enum BlockProcessingError {
|
|||||||
found: u64,
|
found: u64,
|
||||||
},
|
},
|
||||||
ExecutionInvalid,
|
ExecutionInvalid,
|
||||||
|
ConsensusContext(ContextError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BeaconStateError> for BlockProcessingError {
|
impl From<BeaconStateError> for BlockProcessingError {
|
||||||
@ -102,6 +104,12 @@ impl From<SyncAggregateInvalid> for BlockProcessingError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ContextError> for BlockProcessingError {
|
||||||
|
fn from(e: ContextError) -> Self {
|
||||||
|
BlockProcessingError::ConsensusContext(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<BlockOperationError<HeaderInvalid>> for BlockProcessingError {
|
impl From<BlockOperationError<HeaderInvalid>> for BlockProcessingError {
|
||||||
fn from(e: BlockOperationError<HeaderInvalid>) -> BlockProcessingError {
|
fn from(e: BlockOperationError<HeaderInvalid>) -> BlockProcessingError {
|
||||||
match e {
|
match e {
|
||||||
@ -109,6 +117,7 @@ impl From<BlockOperationError<HeaderInvalid>> for BlockProcessingError {
|
|||||||
BlockOperationError::BeaconStateError(e) => BlockProcessingError::BeaconStateError(e),
|
BlockOperationError::BeaconStateError(e) => BlockProcessingError::BeaconStateError(e),
|
||||||
BlockOperationError::SignatureSetError(e) => BlockProcessingError::SignatureSetError(e),
|
BlockOperationError::SignatureSetError(e) => BlockProcessingError::SignatureSetError(e),
|
||||||
BlockOperationError::SszTypesError(e) => BlockProcessingError::SszTypesError(e),
|
BlockOperationError::SszTypesError(e) => BlockProcessingError::SszTypesError(e),
|
||||||
|
BlockOperationError::ConsensusContext(e) => BlockProcessingError::ConsensusContext(e),
|
||||||
BlockOperationError::ArithError(e) => BlockProcessingError::ArithError(e),
|
BlockOperationError::ArithError(e) => BlockProcessingError::ArithError(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,6 +145,7 @@ macro_rules! impl_into_block_processing_error_with_index {
|
|||||||
BlockOperationError::BeaconStateError(e) => BlockProcessingError::BeaconStateError(e),
|
BlockOperationError::BeaconStateError(e) => BlockProcessingError::BeaconStateError(e),
|
||||||
BlockOperationError::SignatureSetError(e) => BlockProcessingError::SignatureSetError(e),
|
BlockOperationError::SignatureSetError(e) => BlockProcessingError::SignatureSetError(e),
|
||||||
BlockOperationError::SszTypesError(e) => BlockProcessingError::SszTypesError(e),
|
BlockOperationError::SszTypesError(e) => BlockProcessingError::SszTypesError(e),
|
||||||
|
BlockOperationError::ConsensusContext(e) => BlockProcessingError::ConsensusContext(e),
|
||||||
BlockOperationError::ArithError(e) => BlockProcessingError::ArithError(e),
|
BlockOperationError::ArithError(e) => BlockProcessingError::ArithError(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,6 +177,7 @@ pub enum BlockOperationError<T> {
|
|||||||
BeaconStateError(BeaconStateError),
|
BeaconStateError(BeaconStateError),
|
||||||
SignatureSetError(SignatureSetError),
|
SignatureSetError(SignatureSetError),
|
||||||
SszTypesError(ssz_types::Error),
|
SszTypesError(ssz_types::Error),
|
||||||
|
ConsensusContext(ContextError),
|
||||||
ArithError(ArithError),
|
ArithError(ArithError),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,6 +210,12 @@ impl<T> From<ArithError> for BlockOperationError<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> From<ContextError> for BlockOperationError<T> {
|
||||||
|
fn from(e: ContextError) -> Self {
|
||||||
|
BlockOperationError::ConsensusContext(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum HeaderInvalid {
|
pub enum HeaderInvalid {
|
||||||
ProposalSignatureInvalid,
|
ProposalSignatureInvalid,
|
||||||
@ -208,14 +225,14 @@ pub enum HeaderInvalid {
|
|||||||
block_slot: Slot,
|
block_slot: Slot,
|
||||||
},
|
},
|
||||||
ProposerIndexMismatch {
|
ProposerIndexMismatch {
|
||||||
block_proposer_index: usize,
|
block_proposer_index: u64,
|
||||||
state_proposer_index: usize,
|
state_proposer_index: u64,
|
||||||
},
|
},
|
||||||
ParentBlockRootMismatch {
|
ParentBlockRootMismatch {
|
||||||
state: Hash256,
|
state: Hash256,
|
||||||
block: Hash256,
|
block: Hash256,
|
||||||
},
|
},
|
||||||
ProposerSlashed(usize),
|
ProposerSlashed(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
@ -310,6 +327,7 @@ impl From<BlockOperationError<IndexedAttestationInvalid>>
|
|||||||
BlockOperationError::BeaconStateError(e) => BlockOperationError::BeaconStateError(e),
|
BlockOperationError::BeaconStateError(e) => BlockOperationError::BeaconStateError(e),
|
||||||
BlockOperationError::SignatureSetError(e) => BlockOperationError::SignatureSetError(e),
|
BlockOperationError::SignatureSetError(e) => BlockOperationError::SignatureSetError(e),
|
||||||
BlockOperationError::SszTypesError(e) => BlockOperationError::SszTypesError(e),
|
BlockOperationError::SszTypesError(e) => BlockOperationError::SszTypesError(e),
|
||||||
|
BlockOperationError::ConsensusContext(e) => BlockOperationError::ConsensusContext(e),
|
||||||
BlockOperationError::ArithError(e) => BlockOperationError::ArithError(e),
|
BlockOperationError::ArithError(e) => BlockOperationError::ArithError(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,23 +12,25 @@ use types::consts::altair::{PARTICIPATION_FLAG_WEIGHTS, PROPOSER_WEIGHT, WEIGHT_
|
|||||||
pub fn process_operations<'a, T: EthSpec, Payload: ExecPayload<T>>(
|
pub fn process_operations<'a, T: EthSpec, Payload: ExecPayload<T>>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
block_body: BeaconBlockBodyRef<'a, T, Payload>,
|
block_body: BeaconBlockBodyRef<'a, T, Payload>,
|
||||||
proposer_index: u64,
|
|
||||||
verify_signatures: VerifySignatures,
|
verify_signatures: VerifySignatures,
|
||||||
|
ctxt: &mut ConsensusContext<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
process_proposer_slashings(
|
process_proposer_slashings(
|
||||||
state,
|
state,
|
||||||
block_body.proposer_slashings(),
|
block_body.proposer_slashings(),
|
||||||
verify_signatures,
|
verify_signatures,
|
||||||
|
ctxt,
|
||||||
spec,
|
spec,
|
||||||
)?;
|
)?;
|
||||||
process_attester_slashings(
|
process_attester_slashings(
|
||||||
state,
|
state,
|
||||||
block_body.attester_slashings(),
|
block_body.attester_slashings(),
|
||||||
verify_signatures,
|
verify_signatures,
|
||||||
|
ctxt,
|
||||||
spec,
|
spec,
|
||||||
)?;
|
)?;
|
||||||
process_attestations(state, block_body, proposer_index, verify_signatures, spec)?;
|
process_attestations(state, block_body, verify_signatures, ctxt, spec)?;
|
||||||
process_deposits(state, block_body.deposits(), spec)?;
|
process_deposits(state, block_body.deposits(), spec)?;
|
||||||
process_exits(state, block_body.voluntary_exits(), verify_signatures, spec)?;
|
process_exits(state, block_body.voluntary_exits(), verify_signatures, spec)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -45,12 +47,13 @@ pub mod base {
|
|||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
attestations: &[Attestation<T>],
|
attestations: &[Attestation<T>],
|
||||||
verify_signatures: VerifySignatures,
|
verify_signatures: VerifySignatures,
|
||||||
|
ctxt: &mut ConsensusContext<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
// Ensure the previous epoch cache exists.
|
// Ensure the previous epoch cache exists.
|
||||||
state.build_committee_cache(RelativeEpoch::Previous, spec)?;
|
state.build_committee_cache(RelativeEpoch::Previous, spec)?;
|
||||||
|
|
||||||
let proposer_index = state.get_beacon_proposer_index(state.slot(), spec)? as u64;
|
let proposer_index = ctxt.get_proposer_index(state, spec)?;
|
||||||
|
|
||||||
// Verify and apply each attestation.
|
// Verify and apply each attestation.
|
||||||
for (i, attestation) in attestations.iter().enumerate() {
|
for (i, attestation) in attestations.iter().enumerate() {
|
||||||
@ -87,10 +90,11 @@ pub mod altair {
|
|||||||
pub fn process_attestations<T: EthSpec>(
|
pub fn process_attestations<T: EthSpec>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
attestations: &[Attestation<T>],
|
attestations: &[Attestation<T>],
|
||||||
proposer_index: u64,
|
|
||||||
verify_signatures: VerifySignatures,
|
verify_signatures: VerifySignatures,
|
||||||
|
ctxt: &mut ConsensusContext<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
|
let proposer_index = ctxt.get_proposer_index(state, spec)?;
|
||||||
attestations
|
attestations
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@ -170,6 +174,7 @@ pub fn process_proposer_slashings<T: EthSpec>(
|
|||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
proposer_slashings: &[ProposerSlashing],
|
proposer_slashings: &[ProposerSlashing],
|
||||||
verify_signatures: VerifySignatures,
|
verify_signatures: VerifySignatures,
|
||||||
|
ctxt: &mut ConsensusContext<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
// Verify and apply proposer slashings in series.
|
// Verify and apply proposer slashings in series.
|
||||||
@ -186,6 +191,7 @@ pub fn process_proposer_slashings<T: EthSpec>(
|
|||||||
state,
|
state,
|
||||||
proposer_slashing.signed_header_1.message.proposer_index as usize,
|
proposer_slashing.signed_header_1.message.proposer_index as usize,
|
||||||
None,
|
None,
|
||||||
|
ctxt,
|
||||||
spec,
|
spec,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -201,6 +207,7 @@ pub fn process_attester_slashings<T: EthSpec>(
|
|||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
attester_slashings: &[AttesterSlashing<T>],
|
attester_slashings: &[AttesterSlashing<T>],
|
||||||
verify_signatures: VerifySignatures,
|
verify_signatures: VerifySignatures,
|
||||||
|
ctxt: &mut ConsensusContext<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
for (i, attester_slashing) in attester_slashings.iter().enumerate() {
|
for (i, attester_slashing) in attester_slashings.iter().enumerate() {
|
||||||
@ -211,7 +218,7 @@ pub fn process_attester_slashings<T: EthSpec>(
|
|||||||
get_slashable_indices(state, attester_slashing).map_err(|e| e.into_with_index(i))?;
|
get_slashable_indices(state, attester_slashing).map_err(|e| e.into_with_index(i))?;
|
||||||
|
|
||||||
for i in slashable_indices {
|
for i in slashable_indices {
|
||||||
slash_validator(state, i as usize, None, spec)?;
|
slash_validator(state, i as usize, None, ctxt, spec)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,20 +229,26 @@ pub fn process_attester_slashings<T: EthSpec>(
|
|||||||
pub fn process_attestations<'a, T: EthSpec, Payload: ExecPayload<T>>(
|
pub fn process_attestations<'a, T: EthSpec, Payload: ExecPayload<T>>(
|
||||||
state: &mut BeaconState<T>,
|
state: &mut BeaconState<T>,
|
||||||
block_body: BeaconBlockBodyRef<'a, T, Payload>,
|
block_body: BeaconBlockBodyRef<'a, T, Payload>,
|
||||||
proposer_index: u64,
|
|
||||||
verify_signatures: VerifySignatures,
|
verify_signatures: VerifySignatures,
|
||||||
|
ctxt: &mut ConsensusContext<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
match block_body {
|
match block_body {
|
||||||
BeaconBlockBodyRef::Base(_) => {
|
BeaconBlockBodyRef::Base(_) => {
|
||||||
base::process_attestations(state, block_body.attestations(), verify_signatures, spec)?;
|
base::process_attestations(
|
||||||
|
state,
|
||||||
|
block_body.attestations(),
|
||||||
|
verify_signatures,
|
||||||
|
ctxt,
|
||||||
|
spec,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
BeaconBlockBodyRef::Altair(_) | BeaconBlockBodyRef::Merge(_) => {
|
BeaconBlockBodyRef::Altair(_) | BeaconBlockBodyRef::Merge(_) => {
|
||||||
altair::process_attestations(
|
altair::process_attestations(
|
||||||
state,
|
state,
|
||||||
block_body.attestations(),
|
block_body.attestations(),
|
||||||
proposer_index,
|
|
||||||
verify_signatures,
|
verify_signatures,
|
||||||
|
ctxt,
|
||||||
spec,
|
spec,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ pub fn block_proposal_signature_set<'a, T, F, Payload: ExecPayload<T>>(
|
|||||||
get_pubkey: F,
|
get_pubkey: F,
|
||||||
signed_block: &'a SignedBeaconBlock<T, Payload>,
|
signed_block: &'a SignedBeaconBlock<T, Payload>,
|
||||||
block_root: Option<Hash256>,
|
block_root: Option<Hash256>,
|
||||||
|
verified_proposer_index: Option<u64>,
|
||||||
spec: &'a ChainSpec,
|
spec: &'a ChainSpec,
|
||||||
) -> Result<SignatureSet<'a>>
|
) -> Result<SignatureSet<'a>>
|
||||||
where
|
where
|
||||||
@ -83,8 +84,12 @@ where
|
|||||||
F: Fn(usize) -> Option<Cow<'a, PublicKey>>,
|
F: Fn(usize) -> Option<Cow<'a, PublicKey>>,
|
||||||
{
|
{
|
||||||
let block = signed_block.message();
|
let block = signed_block.message();
|
||||||
let proposer_index = state.get_beacon_proposer_index(block.slot(), spec)? as u64;
|
|
||||||
|
|
||||||
|
let proposer_index = if let Some(proposer_index) = verified_proposer_index {
|
||||||
|
proposer_index
|
||||||
|
} else {
|
||||||
|
state.get_beacon_proposer_index(block.slot(), spec)? as u64
|
||||||
|
};
|
||||||
if proposer_index != block.proposer_index() {
|
if proposer_index != block.proposer_index() {
|
||||||
return Err(Error::IncorrectBlockProposer {
|
return Err(Error::IncorrectBlockProposer {
|
||||||
block: block.proposer_index(),
|
block: block.proposer_index(),
|
||||||
@ -156,13 +161,18 @@ pub fn randao_signature_set<'a, T, F, Payload: ExecPayload<T>>(
|
|||||||
state: &'a BeaconState<T>,
|
state: &'a BeaconState<T>,
|
||||||
get_pubkey: F,
|
get_pubkey: F,
|
||||||
block: BeaconBlockRef<'a, T, Payload>,
|
block: BeaconBlockRef<'a, T, Payload>,
|
||||||
|
verified_proposer_index: Option<u64>,
|
||||||
spec: &'a ChainSpec,
|
spec: &'a ChainSpec,
|
||||||
) -> Result<SignatureSet<'a>>
|
) -> Result<SignatureSet<'a>>
|
||||||
where
|
where
|
||||||
T: EthSpec,
|
T: EthSpec,
|
||||||
F: Fn(usize) -> Option<Cow<'a, PublicKey>>,
|
F: Fn(usize) -> Option<Cow<'a, PublicKey>>,
|
||||||
{
|
{
|
||||||
let proposer_index = state.get_beacon_proposer_index(block.slot(), spec)?;
|
let proposer_index = if let Some(proposer_index) = verified_proposer_index {
|
||||||
|
proposer_index
|
||||||
|
} else {
|
||||||
|
state.get_beacon_proposer_index(block.slot(), spec)? as u64
|
||||||
|
};
|
||||||
|
|
||||||
let domain = spec.get_domain(
|
let domain = spec.get_domain(
|
||||||
block.slot().epoch(T::slots_per_epoch()),
|
block.slot().epoch(T::slots_per_epoch()),
|
||||||
@ -178,7 +188,7 @@ where
|
|||||||
|
|
||||||
Ok(SignatureSet::single_pubkey(
|
Ok(SignatureSet::single_pubkey(
|
||||||
block.body().randao_reveal(),
|
block.body().randao_reveal(),
|
||||||
get_pubkey(proposer_index).ok_or(Error::ValidatorUnknown(proposer_index as u64))?,
|
get_pubkey(proposer_index as usize).ok_or(Error::ValidatorUnknown(proposer_index))?,
|
||||||
message,
|
message,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use crate::per_block_processing::errors::{
|
|||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
per_block_processing::{process_operations, verify_exit::verify_exit},
|
per_block_processing::{process_operations, verify_exit::verify_exit},
|
||||||
BlockSignatureStrategy, VerifyBlockRoot, VerifySignatures,
|
BlockSignatureStrategy, ConsensusContext, VerifyBlockRoot, VerifySignatures,
|
||||||
};
|
};
|
||||||
use beacon_chain::test_utils::{BeaconChainHarness, EphemeralHarnessType};
|
use beacon_chain::test_utils::{BeaconChainHarness, EphemeralHarnessType};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
@ -67,12 +67,13 @@ async fn valid_block_ok() {
|
|||||||
.make_block_return_pre_state(state, slot + Slot::new(1))
|
.make_block_return_pre_state(state, slot + Slot::new(1))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(block.slot());
|
||||||
let result = per_block_processing(
|
let result = per_block_processing(
|
||||||
&mut state,
|
&mut state,
|
||||||
&block,
|
&block,
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::VerifyIndividual,
|
BlockSignatureStrategy::VerifyIndividual,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -91,12 +92,13 @@ async fn invalid_block_header_state_slot() {
|
|||||||
let (mut block, signature) = signed_block.deconstruct();
|
let (mut block, signature) = signed_block.deconstruct();
|
||||||
*block.slot_mut() = slot + Slot::new(1);
|
*block.slot_mut() = slot + Slot::new(1);
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(block.slot());
|
||||||
let result = per_block_processing(
|
let result = per_block_processing(
|
||||||
&mut state,
|
&mut state,
|
||||||
&SignedBeaconBlock::from_block(block, signature),
|
&SignedBeaconBlock::from_block(block, signature),
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::VerifyIndividual,
|
BlockSignatureStrategy::VerifyIndividual,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -122,12 +124,13 @@ async fn invalid_parent_block_root() {
|
|||||||
let (mut block, signature) = signed_block.deconstruct();
|
let (mut block, signature) = signed_block.deconstruct();
|
||||||
*block.parent_root_mut() = Hash256::from([0xAA; 32]);
|
*block.parent_root_mut() = Hash256::from([0xAA; 32]);
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(block.slot());
|
||||||
let result = per_block_processing(
|
let result = per_block_processing(
|
||||||
&mut state,
|
&mut state,
|
||||||
&SignedBeaconBlock::from_block(block, signature),
|
&SignedBeaconBlock::from_block(block, signature),
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::VerifyIndividual,
|
BlockSignatureStrategy::VerifyIndividual,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -154,12 +157,13 @@ async fn invalid_block_signature() {
|
|||||||
.await;
|
.await;
|
||||||
let (block, _) = signed_block.deconstruct();
|
let (block, _) = signed_block.deconstruct();
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(block.slot());
|
||||||
let result = per_block_processing(
|
let result = per_block_processing(
|
||||||
&mut state,
|
&mut state,
|
||||||
&SignedBeaconBlock::from_block(block, Signature::empty()),
|
&SignedBeaconBlock::from_block(block, Signature::empty()),
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::VerifyIndividual,
|
BlockSignatureStrategy::VerifyIndividual,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -186,12 +190,13 @@ async fn invalid_randao_reveal_signature() {
|
|||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(signed_block.slot());
|
||||||
let result = per_block_processing(
|
let result = per_block_processing(
|
||||||
&mut state,
|
&mut state,
|
||||||
&signed_block,
|
&signed_block,
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::VerifyIndividual,
|
BlockSignatureStrategy::VerifyIndividual,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -386,11 +391,12 @@ async fn invalid_attestation_no_committee_for_index() {
|
|||||||
head_block.to_mut().body_mut().attestations_mut()[0]
|
head_block.to_mut().body_mut().attestations_mut()[0]
|
||||||
.data
|
.data
|
||||||
.index += 1;
|
.index += 1;
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_attestations(
|
let result = process_operations::process_attestations(
|
||||||
&mut state,
|
&mut state,
|
||||||
head_block.body(),
|
head_block.body(),
|
||||||
head_block.proposer_index(),
|
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -424,11 +430,12 @@ async fn invalid_attestation_wrong_justified_checkpoint() {
|
|||||||
.data
|
.data
|
||||||
.source = new_justified_checkpoint;
|
.source = new_justified_checkpoint;
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_attestations(
|
let result = process_operations::process_attestations(
|
||||||
&mut state,
|
&mut state,
|
||||||
head_block.body(),
|
head_block.body(),
|
||||||
head_block.proposer_index(),
|
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -463,11 +470,12 @@ async fn invalid_attestation_bad_aggregation_bitfield_len() {
|
|||||||
head_block.to_mut().body_mut().attestations_mut()[0].aggregation_bits =
|
head_block.to_mut().body_mut().attestations_mut()[0].aggregation_bits =
|
||||||
Bitfield::with_capacity(spec.target_committee_size).unwrap();
|
Bitfield::with_capacity(spec.target_committee_size).unwrap();
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_attestations(
|
let result = process_operations::process_attestations(
|
||||||
&mut state,
|
&mut state,
|
||||||
head_block.body(),
|
head_block.body(),
|
||||||
head_block.proposer_index(),
|
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -495,11 +503,12 @@ async fn invalid_attestation_bad_signature() {
|
|||||||
.0;
|
.0;
|
||||||
head_block.to_mut().body_mut().attestations_mut()[0].signature = AggregateSignature::empty();
|
head_block.to_mut().body_mut().attestations_mut()[0].signature = AggregateSignature::empty();
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_attestations(
|
let result = process_operations::process_attestations(
|
||||||
&mut state,
|
&mut state,
|
||||||
head_block.body(),
|
head_block.body(),
|
||||||
head_block.proposer_index(),
|
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
// Expecting BadSignature because we're signing with invalid secret_keys
|
// Expecting BadSignature because we're signing with invalid secret_keys
|
||||||
@ -533,11 +542,12 @@ async fn invalid_attestation_included_too_early() {
|
|||||||
.data
|
.data
|
||||||
.slot = new_attesation_slot;
|
.slot = new_attesation_slot;
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_attestations(
|
let result = process_operations::process_attestations(
|
||||||
&mut state,
|
&mut state,
|
||||||
head_block.body(),
|
head_block.body(),
|
||||||
head_block.proposer_index(),
|
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -575,11 +585,12 @@ async fn invalid_attestation_included_too_late() {
|
|||||||
.data
|
.data
|
||||||
.slot = new_attesation_slot;
|
.slot = new_attesation_slot;
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_attestations(
|
let result = process_operations::process_attestations(
|
||||||
&mut state,
|
&mut state,
|
||||||
head_block.body(),
|
head_block.body(),
|
||||||
head_block.proposer_index(),
|
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -613,11 +624,12 @@ async fn invalid_attestation_target_epoch_slot_mismatch() {
|
|||||||
.target
|
.target
|
||||||
.epoch += Epoch::new(1);
|
.epoch += Epoch::new(1);
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_attestations(
|
let result = process_operations::process_attestations(
|
||||||
&mut state,
|
&mut state,
|
||||||
head_block.body(),
|
head_block.body(),
|
||||||
head_block.proposer_index(),
|
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -640,10 +652,12 @@ async fn valid_insert_attester_slashing() {
|
|||||||
let attester_slashing = harness.make_attester_slashing(vec![1, 2]);
|
let attester_slashing = harness.make_attester_slashing(vec![1, 2]);
|
||||||
|
|
||||||
let mut state = harness.get_current_state();
|
let mut state = harness.get_current_state();
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_attester_slashings(
|
let result = process_operations::process_attester_slashings(
|
||||||
&mut state,
|
&mut state,
|
||||||
&[attester_slashing],
|
&[attester_slashing],
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -660,10 +674,12 @@ async fn invalid_attester_slashing_not_slashable() {
|
|||||||
attester_slashing.attestation_1 = attester_slashing.attestation_2.clone();
|
attester_slashing.attestation_1 = attester_slashing.attestation_2.clone();
|
||||||
|
|
||||||
let mut state = harness.get_current_state();
|
let mut state = harness.get_current_state();
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_attester_slashings(
|
let result = process_operations::process_attester_slashings(
|
||||||
&mut state,
|
&mut state,
|
||||||
&[attester_slashing],
|
&[attester_slashing],
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -686,10 +702,12 @@ async fn invalid_attester_slashing_1_invalid() {
|
|||||||
attester_slashing.attestation_1.attesting_indices = VariableList::from(vec![2, 1]);
|
attester_slashing.attestation_1.attesting_indices = VariableList::from(vec![2, 1]);
|
||||||
|
|
||||||
let mut state = harness.get_current_state();
|
let mut state = harness.get_current_state();
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_attester_slashings(
|
let result = process_operations::process_attester_slashings(
|
||||||
&mut state,
|
&mut state,
|
||||||
&[attester_slashing],
|
&[attester_slashing],
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -715,10 +733,12 @@ async fn invalid_attester_slashing_2_invalid() {
|
|||||||
attester_slashing.attestation_2.attesting_indices = VariableList::from(vec![2, 1]);
|
attester_slashing.attestation_2.attesting_indices = VariableList::from(vec![2, 1]);
|
||||||
|
|
||||||
let mut state = harness.get_current_state();
|
let mut state = harness.get_current_state();
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_attester_slashings(
|
let result = process_operations::process_attester_slashings(
|
||||||
&mut state,
|
&mut state,
|
||||||
&[attester_slashing],
|
&[attester_slashing],
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -741,10 +761,12 @@ async fn valid_insert_proposer_slashing() {
|
|||||||
let harness = get_harness::<MainnetEthSpec>(EPOCH_OFFSET, VALIDATOR_COUNT).await;
|
let harness = get_harness::<MainnetEthSpec>(EPOCH_OFFSET, VALIDATOR_COUNT).await;
|
||||||
let proposer_slashing = harness.make_proposer_slashing(1);
|
let proposer_slashing = harness.make_proposer_slashing(1);
|
||||||
let mut state = harness.get_current_state();
|
let mut state = harness.get_current_state();
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_proposer_slashings(
|
let result = process_operations::process_proposer_slashings(
|
||||||
&mut state,
|
&mut state,
|
||||||
&[proposer_slashing],
|
&[proposer_slashing],
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
// Expecting Ok(_) because we inserted a valid proposer slashing
|
// Expecting Ok(_) because we inserted a valid proposer slashing
|
||||||
@ -760,10 +782,12 @@ async fn invalid_proposer_slashing_proposals_identical() {
|
|||||||
proposer_slashing.signed_header_1.message = proposer_slashing.signed_header_2.message.clone();
|
proposer_slashing.signed_header_1.message = proposer_slashing.signed_header_2.message.clone();
|
||||||
|
|
||||||
let mut state = harness.get_current_state();
|
let mut state = harness.get_current_state();
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_proposer_slashings(
|
let result = process_operations::process_proposer_slashings(
|
||||||
&mut state,
|
&mut state,
|
||||||
&[proposer_slashing],
|
&[proposer_slashing],
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -787,10 +811,12 @@ async fn invalid_proposer_slashing_proposer_unknown() {
|
|||||||
proposer_slashing.signed_header_2.message.proposer_index = 3_141_592;
|
proposer_slashing.signed_header_2.message.proposer_index = 3_141_592;
|
||||||
|
|
||||||
let mut state = harness.get_current_state();
|
let mut state = harness.get_current_state();
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_proposer_slashings(
|
let result = process_operations::process_proposer_slashings(
|
||||||
&mut state,
|
&mut state,
|
||||||
&[proposer_slashing],
|
&[proposer_slashing],
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -811,10 +837,12 @@ async fn invalid_proposer_slashing_duplicate_slashing() {
|
|||||||
|
|
||||||
let proposer_slashing = harness.make_proposer_slashing(1);
|
let proposer_slashing = harness.make_proposer_slashing(1);
|
||||||
let mut state = harness.get_current_state();
|
let mut state = harness.get_current_state();
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result_1 = process_operations::process_proposer_slashings(
|
let result_1 = process_operations::process_proposer_slashings(
|
||||||
&mut state,
|
&mut state,
|
||||||
&[proposer_slashing.clone()],
|
&[proposer_slashing.clone()],
|
||||||
VerifySignatures::False,
|
VerifySignatures::False,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
assert!(result_1.is_ok());
|
assert!(result_1.is_ok());
|
||||||
@ -823,6 +851,7 @@ async fn invalid_proposer_slashing_duplicate_slashing() {
|
|||||||
&mut state,
|
&mut state,
|
||||||
&[proposer_slashing],
|
&[proposer_slashing],
|
||||||
VerifySignatures::False,
|
VerifySignatures::False,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
// Expecting ProposerNotSlashable because we've already slashed the validator
|
// Expecting ProposerNotSlashable because we've already slashed the validator
|
||||||
@ -842,10 +871,12 @@ async fn invalid_bad_proposal_1_signature() {
|
|||||||
let mut proposer_slashing = harness.make_proposer_slashing(1);
|
let mut proposer_slashing = harness.make_proposer_slashing(1);
|
||||||
proposer_slashing.signed_header_1.signature = Signature::empty();
|
proposer_slashing.signed_header_1.signature = Signature::empty();
|
||||||
let mut state = harness.get_current_state();
|
let mut state = harness.get_current_state();
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_proposer_slashings(
|
let result = process_operations::process_proposer_slashings(
|
||||||
&mut state,
|
&mut state,
|
||||||
&[proposer_slashing],
|
&[proposer_slashing],
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -866,10 +897,12 @@ async fn invalid_bad_proposal_2_signature() {
|
|||||||
let mut proposer_slashing = harness.make_proposer_slashing(1);
|
let mut proposer_slashing = harness.make_proposer_slashing(1);
|
||||||
proposer_slashing.signed_header_2.signature = Signature::empty();
|
proposer_slashing.signed_header_2.signature = Signature::empty();
|
||||||
let mut state = harness.get_current_state();
|
let mut state = harness.get_current_state();
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_proposer_slashings(
|
let result = process_operations::process_proposer_slashings(
|
||||||
&mut state,
|
&mut state,
|
||||||
&[proposer_slashing],
|
&[proposer_slashing],
|
||||||
VerifySignatures::True,
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -891,10 +924,12 @@ async fn invalid_proposer_slashing_proposal_epoch_mismatch() {
|
|||||||
proposer_slashing.signed_header_1.message.slot = Slot::new(0);
|
proposer_slashing.signed_header_1.message.slot = Slot::new(0);
|
||||||
proposer_slashing.signed_header_2.message.slot = Slot::new(128);
|
proposer_slashing.signed_header_2.message.slot = Slot::new(128);
|
||||||
let mut state = harness.get_current_state();
|
let mut state = harness.get_current_state();
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
let result = process_operations::process_proposer_slashings(
|
let result = process_operations::process_proposer_slashings(
|
||||||
&mut state,
|
&mut state,
|
||||||
&[proposer_slashing],
|
&[proposer_slashing],
|
||||||
VerifySignatures::False,
|
VerifySignatures::False,
|
||||||
|
&mut ctxt,
|
||||||
&spec,
|
&spec,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches) -> Result<
|
|||||||
};
|
};
|
||||||
|
|
||||||
for i in 0..runs {
|
for i in 0..runs {
|
||||||
let mut state = state.clone_with(CloneConfig::committee_caches_only());
|
let mut state = state.clone_with(CloneConfig::all());
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ use eth2::{
|
|||||||
use ssz::Encode;
|
use ssz::Encode;
|
||||||
use state_processing::{
|
use state_processing::{
|
||||||
block_signature_verifier::BlockSignatureVerifier, per_block_processing, per_slot_processing,
|
block_signature_verifier::BlockSignatureVerifier, per_block_processing, per_slot_processing,
|
||||||
BlockSignatureStrategy, VerifyBlockRoot,
|
BlockSignatureStrategy, ConsensusContext, VerifyBlockRoot,
|
||||||
};
|
};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@ -360,6 +360,7 @@ fn do_transition<T: EthSpec>(
|
|||||||
decompressor,
|
decompressor,
|
||||||
&block,
|
&block,
|
||||||
Some(block_root),
|
Some(block_root),
|
||||||
|
Some(block.message().proposer_index()),
|
||||||
spec,
|
spec,
|
||||||
)
|
)
|
||||||
.map_err(|e| format!("Invalid block signature: {:?}", e))?;
|
.map_err(|e| format!("Invalid block signature: {:?}", e))?;
|
||||||
@ -367,12 +368,15 @@ fn do_transition<T: EthSpec>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let t = Instant::now();
|
let t = Instant::now();
|
||||||
|
let mut ctxt = ConsensusContext::new(pre_state.slot())
|
||||||
|
.set_current_block_root(block_root)
|
||||||
|
.set_proposer_index(block.message().proposer_index());
|
||||||
per_block_processing(
|
per_block_processing(
|
||||||
&mut pre_state,
|
&mut pre_state,
|
||||||
&block,
|
&block,
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::NoVerification,
|
BlockSignatureStrategy::NoVerification,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
spec,
|
spec,
|
||||||
)
|
)
|
||||||
.map_err(|e| format!("State transition failed: {:?}", e))?;
|
.map_err(|e| format!("State transition failed: {:?}", e))?;
|
||||||
|
@ -5,14 +5,17 @@ use crate::decode::{ssz_decode_file, ssz_decode_file_with, ssz_decode_state, yam
|
|||||||
use crate::testing_spec;
|
use crate::testing_spec;
|
||||||
use crate::type_name::TypeName;
|
use crate::type_name::TypeName;
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
use state_processing::per_block_processing::{
|
use state_processing::{
|
||||||
errors::BlockProcessingError,
|
per_block_processing::{
|
||||||
process_block_header, process_execution_payload,
|
errors::BlockProcessingError,
|
||||||
process_operations::{
|
process_block_header, process_execution_payload,
|
||||||
altair, base, process_attester_slashings, process_deposits, process_exits,
|
process_operations::{
|
||||||
process_proposer_slashings,
|
altair, base, process_attester_slashings, process_deposits, process_exits,
|
||||||
|
process_proposer_slashings,
|
||||||
|
},
|
||||||
|
process_sync_aggregate, VerifyBlockRoot, VerifySignatures,
|
||||||
},
|
},
|
||||||
process_sync_aggregate, VerifyBlockRoot, VerifySignatures,
|
ConsensusContext,
|
||||||
};
|
};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@ -76,11 +79,16 @@ impl<E: EthSpec> Operation<E> for Attestation<E> {
|
|||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
_: &Operations<E, Self>,
|
_: &Operations<E, Self>,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
let proposer_index = state.get_beacon_proposer_index(state.slot(), spec)? as u64;
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
|
let proposer_index = ctxt.get_proposer_index(state, spec)?;
|
||||||
match state {
|
match state {
|
||||||
BeaconState::Base(_) => {
|
BeaconState::Base(_) => base::process_attestations(
|
||||||
base::process_attestations(state, &[self.clone()], VerifySignatures::True, spec)
|
state,
|
||||||
}
|
&[self.clone()],
|
||||||
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
|
spec,
|
||||||
|
),
|
||||||
BeaconState::Altair(_) | BeaconState::Merge(_) => altair::process_attestation(
|
BeaconState::Altair(_) | BeaconState::Merge(_) => altair::process_attestation(
|
||||||
state,
|
state,
|
||||||
self,
|
self,
|
||||||
@ -108,7 +116,14 @@ impl<E: EthSpec> Operation<E> for AttesterSlashing<E> {
|
|||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
_: &Operations<E, Self>,
|
_: &Operations<E, Self>,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
process_attester_slashings(state, &[self.clone()], VerifySignatures::True, spec)
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
|
process_attester_slashings(
|
||||||
|
state,
|
||||||
|
&[self.clone()],
|
||||||
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
|
spec,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +162,14 @@ impl<E: EthSpec> Operation<E> for ProposerSlashing {
|
|||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
_: &Operations<E, Self>,
|
_: &Operations<E, Self>,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
process_proposer_slashings(state, &[self.clone()], VerifySignatures::True, spec)
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
|
process_proposer_slashings(
|
||||||
|
state,
|
||||||
|
&[self.clone()],
|
||||||
|
VerifySignatures::True,
|
||||||
|
&mut ctxt,
|
||||||
|
spec,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,10 +211,12 @@ impl<E: EthSpec> Operation<E> for BeaconBlock<E> {
|
|||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
_: &Operations<E, Self>,
|
_: &Operations<E, Self>,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
process_block_header(
|
process_block_header(
|
||||||
state,
|
state,
|
||||||
self.to_ref().temporary_block_header(),
|
self.to_ref().temporary_block_header(),
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
spec,
|
spec,
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -5,7 +5,7 @@ use crate::decode::{ssz_decode_file_with, ssz_decode_state, yaml_decode_file};
|
|||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
use state_processing::{
|
use state_processing::{
|
||||||
per_block_processing, per_slot_processing, BlockProcessingError, BlockSignatureStrategy,
|
per_block_processing, per_slot_processing, BlockProcessingError, BlockSignatureStrategy,
|
||||||
VerifyBlockRoot,
|
ConsensusContext, VerifyBlockRoot,
|
||||||
};
|
};
|
||||||
use types::{BeaconState, EthSpec, ForkName, RelativeEpoch, SignedBeaconBlock};
|
use types::{BeaconState, EthSpec, ForkName, RelativeEpoch, SignedBeaconBlock};
|
||||||
|
|
||||||
@ -91,26 +91,28 @@ impl<E: EthSpec> Case for SanityBlocks<E> {
|
|||||||
.build_committee_cache(RelativeEpoch::Current, spec)
|
.build_committee_cache(RelativeEpoch::Current, spec)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(indiv_state.slot());
|
||||||
per_block_processing(
|
per_block_processing(
|
||||||
&mut indiv_state,
|
&mut indiv_state,
|
||||||
signed_block,
|
signed_block,
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::VerifyIndividual,
|
BlockSignatureStrategy::VerifyIndividual,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
spec,
|
spec,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
let mut ctxt = ConsensusContext::new(indiv_state.slot());
|
||||||
per_block_processing(
|
per_block_processing(
|
||||||
&mut bulk_state,
|
&mut bulk_state,
|
||||||
signed_block,
|
signed_block,
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::VerifyBulk,
|
BlockSignatureStrategy::VerifyBulk,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
spec,
|
spec,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if block.state_root() == bulk_state.canonical_root()
|
if block.state_root() == bulk_state.update_tree_hash_cache().unwrap()
|
||||||
&& block.state_root() == indiv_state.canonical_root()
|
&& block.state_root() == indiv_state.update_tree_hash_cache().unwrap()
|
||||||
{
|
{
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
@ -4,7 +4,7 @@ use crate::decode::{ssz_decode_file_with, ssz_decode_state, yaml_decode_file};
|
|||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
use state_processing::{
|
use state_processing::{
|
||||||
per_block_processing, state_advance::complete_state_advance, BlockSignatureStrategy,
|
per_block_processing, state_advance::complete_state_advance, BlockSignatureStrategy,
|
||||||
VerifyBlockRoot,
|
ConsensusContext, VerifyBlockRoot,
|
||||||
};
|
};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use types::{BeaconState, Epoch, ForkName, SignedBeaconBlock};
|
use types::{BeaconState, Epoch, ForkName, SignedBeaconBlock};
|
||||||
@ -91,12 +91,13 @@ impl<E: EthSpec> Case for TransitionTest<E> {
|
|||||||
.map_err(|e| format!("Failed to advance: {:?}", e))?;
|
.map_err(|e| format!("Failed to advance: {:?}", e))?;
|
||||||
|
|
||||||
// Apply block.
|
// Apply block.
|
||||||
|
let mut ctxt = ConsensusContext::new(state.slot());
|
||||||
per_block_processing(
|
per_block_processing(
|
||||||
&mut state,
|
&mut state,
|
||||||
block,
|
block,
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::VerifyBulk,
|
BlockSignatureStrategy::VerifyBulk,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
spec,
|
spec,
|
||||||
)
|
)
|
||||||
.map_err(|e| format!("Block processing failed: {:?}", e))?;
|
.map_err(|e| format!("Block processing failed: {:?}", e))?;
|
||||||
|
@ -2,7 +2,7 @@ use super::*;
|
|||||||
use beacon_chain::test_utils::{BeaconChainHarness, EphemeralHarnessType};
|
use beacon_chain::test_utils::{BeaconChainHarness, EphemeralHarnessType};
|
||||||
use state_processing::{
|
use state_processing::{
|
||||||
per_block_processing, per_block_processing::errors::ExitInvalid, BlockProcessingError,
|
per_block_processing, per_block_processing::errors::ExitInvalid, BlockProcessingError,
|
||||||
BlockSignatureStrategy, VerifyBlockRoot,
|
BlockSignatureStrategy, ConsensusContext, VerifyBlockRoot,
|
||||||
};
|
};
|
||||||
use types::{BeaconBlock, BeaconState, Epoch, EthSpec, SignedBeaconBlock};
|
use types::{BeaconBlock, BeaconState, Epoch, EthSpec, SignedBeaconBlock};
|
||||||
|
|
||||||
@ -64,12 +64,13 @@ impl ExitTest {
|
|||||||
block: &SignedBeaconBlock<E>,
|
block: &SignedBeaconBlock<E>,
|
||||||
state: &mut BeaconState<E>,
|
state: &mut BeaconState<E>,
|
||||||
) -> Result<(), BlockProcessingError> {
|
) -> Result<(), BlockProcessingError> {
|
||||||
|
let mut ctxt = ConsensusContext::new(block.slot());
|
||||||
per_block_processing(
|
per_block_processing(
|
||||||
state,
|
state,
|
||||||
block,
|
block,
|
||||||
None,
|
|
||||||
BlockSignatureStrategy::VerifyIndividual,
|
BlockSignatureStrategy::VerifyIndividual,
|
||||||
VerifyBlockRoot::True,
|
VerifyBlockRoot::True,
|
||||||
|
&mut ctxt,
|
||||||
&E::default_spec(),
|
&E::default_spec(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -125,7 +126,7 @@ vectors_and_tests!(
|
|||||||
ExitTest {
|
ExitTest {
|
||||||
block_modifier: Box::new(|_, block| {
|
block_modifier: Box::new(|_, block| {
|
||||||
// Duplicate the exit
|
// Duplicate the exit
|
||||||
let exit = block.body().voluntary_exits()[0].clone();
|
let exit = block.body().voluntary_exits().get(0).unwrap().clone();
|
||||||
block.body_mut().voluntary_exits_mut().push(exit).unwrap();
|
block.body_mut().voluntary_exits_mut().push(exit).unwrap();
|
||||||
}),
|
}),
|
||||||
expected: Err(BlockProcessingError::ExitInvalid {
|
expected: Err(BlockProcessingError::ExitInvalid {
|
||||||
@ -144,7 +145,11 @@ vectors_and_tests!(
|
|||||||
invalid_validator_unknown,
|
invalid_validator_unknown,
|
||||||
ExitTest {
|
ExitTest {
|
||||||
block_modifier: Box::new(|_, block| {
|
block_modifier: Box::new(|_, block| {
|
||||||
block.body_mut().voluntary_exits_mut()[0]
|
block
|
||||||
|
.body_mut()
|
||||||
|
.voluntary_exits_mut()
|
||||||
|
.get_mut(0)
|
||||||
|
.unwrap()
|
||||||
.message
|
.message
|
||||||
.validator_index = VALIDATOR_COUNT as u64;
|
.validator_index = VALIDATOR_COUNT as u64;
|
||||||
}),
|
}),
|
||||||
@ -165,7 +170,7 @@ vectors_and_tests!(
|
|||||||
invalid_exit_already_initiated,
|
invalid_exit_already_initiated,
|
||||||
ExitTest {
|
ExitTest {
|
||||||
state_modifier: Box::new(|state| {
|
state_modifier: Box::new(|state| {
|
||||||
state.validators_mut()[0].exit_epoch = STATE_EPOCH + 1;
|
state.validators_mut().get_mut(0).unwrap().exit_epoch = STATE_EPOCH + 1;
|
||||||
}),
|
}),
|
||||||
expected: Err(BlockProcessingError::ExitInvalid {
|
expected: Err(BlockProcessingError::ExitInvalid {
|
||||||
index: 0,
|
index: 0,
|
||||||
@ -184,7 +189,8 @@ vectors_and_tests!(
|
|||||||
invalid_not_active_before_activation_epoch,
|
invalid_not_active_before_activation_epoch,
|
||||||
ExitTest {
|
ExitTest {
|
||||||
state_modifier: Box::new(|state| {
|
state_modifier: Box::new(|state| {
|
||||||
state.validators_mut()[0].activation_epoch = E::default_spec().far_future_epoch;
|
state.validators_mut().get_mut(0).unwrap().activation_epoch =
|
||||||
|
E::default_spec().far_future_epoch;
|
||||||
}),
|
}),
|
||||||
expected: Err(BlockProcessingError::ExitInvalid {
|
expected: Err(BlockProcessingError::ExitInvalid {
|
||||||
index: 0,
|
index: 0,
|
||||||
@ -203,7 +209,7 @@ vectors_and_tests!(
|
|||||||
invalid_not_active_after_exit_epoch,
|
invalid_not_active_after_exit_epoch,
|
||||||
ExitTest {
|
ExitTest {
|
||||||
state_modifier: Box::new(|state| {
|
state_modifier: Box::new(|state| {
|
||||||
state.validators_mut()[0].exit_epoch = STATE_EPOCH;
|
state.validators_mut().get_mut(0).unwrap().exit_epoch = STATE_EPOCH;
|
||||||
}),
|
}),
|
||||||
expected: Err(BlockProcessingError::ExitInvalid {
|
expected: Err(BlockProcessingError::ExitInvalid {
|
||||||
index: 0,
|
index: 0,
|
||||||
@ -303,7 +309,11 @@ vectors_and_tests!(
|
|||||||
block_modifier: Box::new(|_, block| {
|
block_modifier: Box::new(|_, block| {
|
||||||
// Shift the validator index by 1 so that it's mismatched from the key that was
|
// Shift the validator index by 1 so that it's mismatched from the key that was
|
||||||
// used to sign.
|
// used to sign.
|
||||||
block.body_mut().voluntary_exits_mut()[0]
|
block
|
||||||
|
.body_mut()
|
||||||
|
.voluntary_exits_mut()
|
||||||
|
.get_mut(0)
|
||||||
|
.unwrap()
|
||||||
.message
|
.message
|
||||||
.validator_index = VALIDATOR_INDEX + 1;
|
.validator_index = VALIDATOR_INDEX + 1;
|
||||||
}),
|
}),
|
||||||
|
Loading…
Reference in New Issue
Block a user