mirror of
https://github.com/sigp/lighthouse.git
synced 2026-07-02 04:14:33 +00:00
Breakout from: - https://github.com/sigp/lighthouse/pull/9295 We currently do not handle the verification of payload attestations on non-canonical side chains, we always attempt to use the head. The included regression test demonstrates this, and there is _also_ a fork choice compliance test in #9295 that triggers it. This PR is a bit opinionated, but I'll explain my judgements: - We need a way to get the PTC for an arbitrary slot from an arbitrary state. This involves potential state advances, database lookups, etc. There is some fiddly logic required to check that states are in range/etc. - We _already have_ a cache with the exact same lifecycle as the PTCs, namely the attester shuffling cache. Therefore, we can de-duplicate a lot of the complexity by storing the PTCs for a given epoch (and decision block) in this cache. The other opinionated change is in the tests. The previous tests were set up kind of nicely to avoid instantiating a `BeaconChainHarness`. However they were not using mocking, which made testing the non-canonical chain case kind of infeasible. To remedy this, I've changed them to just use a beacon chain harness and create two chains using its relatively easy to use methods for doing this. The running time of the tests goes from something like 2.6s for 8 tests to 3.3s for 9 tests, which is only an increase of 0.04s/test. Negligible. Another plus to using the `BeaconChainHarness` is that it avoids a bunch of the cruft to create synthetic non-mocked beacon chain bits. At the same time, I've made some attempt to improve modularity (and fit with the `GossipVerificationContext`) by pulling out the guts of `with_committee_cache` into a new function (`with_cached_shuffling`) that clearly shows its dependency surface. Co-Authored-By: Michael Sproul <michael@sigmaprime.io> Co-Authored-By: dapplion <35266934+dapplion@users.noreply.github.com>
344 lines
12 KiB
Rust
344 lines
12 KiB
Rust
use crate::beacon_block_streamer::Error as BlockStreamerError;
|
|
use crate::beacon_chain::ForkChoiceError;
|
|
use crate::beacon_fork_choice_store::Error as ForkChoiceStoreError;
|
|
use crate::data_availability_checker::AvailabilityCheckError;
|
|
use crate::migrate::PruningError;
|
|
use crate::naive_aggregation_pool::Error as NaiveAggregationError;
|
|
use crate::observed_aggregates::Error as ObservedAttestationsError;
|
|
use crate::observed_attesters::Error as ObservedAttestersError;
|
|
use crate::observed_block_producers::Error as ObservedBlockProducersError;
|
|
use crate::observed_data_sidecars::Error as ObservedDataSidecarsError;
|
|
use crate::payload_envelope_streamer::Error as EnvelopeStreamerError;
|
|
use bls::PublicKeyBytes;
|
|
use execution_layer::PayloadStatus;
|
|
use fork_choice::ExecutionStatus;
|
|
use futures::channel::mpsc::TrySendError;
|
|
use milhouse::Error as MilhouseError;
|
|
use operation_pool::OpPoolError;
|
|
use safe_arith::ArithError;
|
|
use ssz_types::Error as SszTypesError;
|
|
use state_processing::envelope_processing::EnvelopeProcessingError;
|
|
use state_processing::{
|
|
BlockProcessingError, BlockReplayError, EpochProcessingError, SlotProcessingError,
|
|
block_signature_verifier::Error as BlockSignatureVerifierError,
|
|
per_block_processing::errors::{
|
|
AttestationValidationError, AttesterSlashingValidationError,
|
|
BlsExecutionChangeValidationError, ExitValidationError, ProposerSlashingValidationError,
|
|
SyncCommitteeMessageValidationError,
|
|
},
|
|
signature_sets::Error as SignatureSetError,
|
|
state_advance::Error as StateAdvanceError,
|
|
};
|
|
use task_executor::ShutdownReason;
|
|
use tokio::task::JoinError;
|
|
use types::*;
|
|
|
|
macro_rules! easy_from_to {
|
|
($from: ident, $to: ident) => {
|
|
impl From<$from> for $to {
|
|
fn from(e: $from) -> $to {
|
|
$to::$from(e)
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum BeaconChainError {
|
|
InsufficientValidators,
|
|
UnableToReadSlot,
|
|
UnableToComputeTimeAtSlot,
|
|
RevertedFinalizedEpoch {
|
|
old: Checkpoint,
|
|
new: Checkpoint,
|
|
},
|
|
SlotClockDidNotStart,
|
|
NoStateForSlot(Slot),
|
|
NoBlockForSlot(Slot),
|
|
BeaconStateError(BeaconStateError),
|
|
EpochCacheError(EpochCacheError),
|
|
DBInconsistent(String),
|
|
DBError(store::Error),
|
|
ForkChoiceError(ForkChoiceError),
|
|
ForkChoiceStoreError(ForkChoiceStoreError),
|
|
MissingBeaconBlock(Hash256),
|
|
MissingBeaconState(Hash256),
|
|
MissingExecutionPayloadEnvelope(Hash256),
|
|
MissingHotStateSummary(Hash256),
|
|
SlotProcessingError(SlotProcessingError),
|
|
EpochProcessingError(EpochProcessingError),
|
|
StateAdvanceError(StateAdvanceError),
|
|
UnableToAdvanceState(String),
|
|
NoStateForAttestation {
|
|
beacon_block_root: Hash256,
|
|
},
|
|
CannotAttestToFutureState,
|
|
AttestationValidationError(AttestationValidationError),
|
|
SyncCommitteeMessageValidationError(SyncCommitteeMessageValidationError),
|
|
ExitValidationError(ExitValidationError),
|
|
ProposerSlashingValidationError(ProposerSlashingValidationError),
|
|
AttesterSlashingValidationError(AttesterSlashingValidationError),
|
|
BlsExecutionChangeValidationError(BlsExecutionChangeValidationError),
|
|
MissingFinalizedStateRoot(Slot),
|
|
SszTypesError(SszTypesError),
|
|
NoProposerForSlot(Slot),
|
|
CanonicalHeadLockTimeout,
|
|
AttestationCacheLockTimeout,
|
|
ValidatorPubkeyCacheLockTimeout,
|
|
SnapshotCacheLockTimeout,
|
|
IncorrectStateForAttestation(RelativeEpochError),
|
|
InvalidValidatorPubkeyBytes(bls::Error),
|
|
ValidatorPubkeyCacheIncomplete(usize),
|
|
SignatureSetError(SignatureSetError),
|
|
BlockSignatureVerifierError(state_processing::block_signature_verifier::Error),
|
|
BlockReplayError(BlockReplayError),
|
|
DuplicateValidatorPublicKey,
|
|
ValidatorPubkeyCacheError(String),
|
|
ValidatorIndexUnknown(usize),
|
|
ValidatorPubkeyUnknown(PublicKeyBytes),
|
|
OpPoolError(OpPoolError),
|
|
NaiveAggregationError(NaiveAggregationError),
|
|
ObservedAttestationsError(ObservedAttestationsError),
|
|
ObservedAttestersError(ObservedAttestersError),
|
|
ObservedBlockProducersError(ObservedBlockProducersError),
|
|
ObservedDataSidecarsError(ObservedDataSidecarsError),
|
|
EarlyAttesterCacheError,
|
|
PruningError(PruningError),
|
|
ArithError(ArithError),
|
|
InvalidShufflingId {
|
|
shuffling_epoch: Epoch,
|
|
head_block_epoch: Epoch,
|
|
},
|
|
WeakSubjectivtyVerificationFailure,
|
|
WeakSubjectivtyShutdownError(TrySendError<ShutdownReason>),
|
|
AttestingToFinalizedSlot {
|
|
finalized_slot: Slot,
|
|
request_slot: Slot,
|
|
},
|
|
AttestingToAncientSlot {
|
|
lowest_permissible_slot: Slot,
|
|
request_slot: Slot,
|
|
},
|
|
BadPreState {
|
|
parent_root: Hash256,
|
|
parent_slot: Slot,
|
|
block_root: Hash256,
|
|
block_slot: Slot,
|
|
state_slot: Slot,
|
|
},
|
|
/// Block is not available (only returned when fetching historic blocks).
|
|
HistoricalBlockOutOfRange {
|
|
slot: Slot,
|
|
oldest_block_slot: Slot,
|
|
},
|
|
InvalidStateForShuffling {
|
|
state_epoch: Epoch,
|
|
shuffling_epoch: Epoch,
|
|
},
|
|
SyncDutiesError(BeaconStateError),
|
|
InconsistentForwardsIter {
|
|
request_slot: Slot,
|
|
slot: Slot,
|
|
},
|
|
InvalidReorgSlotIter {
|
|
old_slot: Slot,
|
|
new_slot: Slot,
|
|
},
|
|
AltairForkDisabled,
|
|
BuilderMissing,
|
|
ExecutionLayerMissing,
|
|
BlockVariantLacksExecutionPayload(Hash256),
|
|
ExecutionLayerErrorPayloadReconstruction(ExecutionBlockHash, Box<execution_layer::Error>),
|
|
EngineGetCapabilititesFailed(Box<execution_layer::Error>),
|
|
ExecutionLayerGetBlockByNumberFailed(Box<execution_layer::Error>),
|
|
ExecutionLayerGetBlockByHashFailed(Box<execution_layer::Error>),
|
|
BlockHashMissingFromExecutionLayer(ExecutionBlockHash),
|
|
InconsistentPayloadReconstructed {
|
|
slot: Slot,
|
|
exec_block_hash: ExecutionBlockHash,
|
|
canonical_transactions_root: Hash256,
|
|
reconstructed_transactions_root: Hash256,
|
|
},
|
|
BlockStreamerError(BlockStreamerError),
|
|
EnvelopeStreamerError(EnvelopeStreamerError),
|
|
AddPayloadLogicError,
|
|
ExecutionForkChoiceUpdateFailed(execution_layer::Error),
|
|
PrepareProposerFailed(BlockProcessingError),
|
|
ExecutionForkChoiceUpdateInvalid {
|
|
status: PayloadStatus,
|
|
},
|
|
BlockRewardError,
|
|
BlockRewardSlotError,
|
|
BlockRewardAttestationError,
|
|
BlockRewardSyncError,
|
|
SyncCommitteeRewardsSyncError,
|
|
AttestationRewardsError,
|
|
HeadMissingFromForkChoice(Hash256),
|
|
FinalizedBlockMissingFromForkChoice(Hash256),
|
|
HeadBlockMissingFromForkChoice(Hash256),
|
|
InvalidFinalizedPayload {
|
|
finalized_root: Hash256,
|
|
execution_block_hash: ExecutionBlockHash,
|
|
},
|
|
InvalidFinalizedPayloadShutdownError(TrySendError<ShutdownReason>),
|
|
JustifiedPayloadInvalid {
|
|
justified_root: Hash256,
|
|
execution_block_hash: Option<ExecutionBlockHash>,
|
|
},
|
|
ForkchoiceUpdate(execution_layer::Error),
|
|
InvalidCheckpoint {
|
|
state_root: Hash256,
|
|
checkpoint: Checkpoint,
|
|
},
|
|
InvalidSlot(Slot),
|
|
HeadBlockNotFullyVerified {
|
|
beacon_block_root: Hash256,
|
|
execution_status: ExecutionStatus,
|
|
},
|
|
CannotAttestToFinalizedBlock {
|
|
beacon_block_root: Hash256,
|
|
},
|
|
SyncContributionDataReferencesFinalizedBlock {
|
|
beacon_block_root: Hash256,
|
|
},
|
|
RuntimeShutdown,
|
|
TokioJoin(tokio::task::JoinError),
|
|
ProcessInvalidExecutionPayload(JoinError),
|
|
ForkChoiceSignalOutOfOrder {
|
|
current: Slot,
|
|
latest: Slot,
|
|
},
|
|
ForkchoiceUpdateParamsMissing,
|
|
HeadHasInvalidPayload {
|
|
block_root: Hash256,
|
|
execution_status: ExecutionStatus,
|
|
},
|
|
AttestationHeadNotInForkChoice(Hash256),
|
|
MissingPersistedForkChoice,
|
|
CommitteePromiseFailed(oneshot_broadcast::Error),
|
|
MaxCommitteePromises(usize),
|
|
BlsToExecutionPriorToCapella,
|
|
BlsToExecutionConflictsWithPool,
|
|
InconsistentFork(InconsistentFork),
|
|
ProposerHeadForkChoiceError(fork_choice::Error<proto_array::Error>),
|
|
UnableToPublish,
|
|
UnableToBuildColumnSidecar(String),
|
|
AvailabilityCheckError(AvailabilityCheckError),
|
|
LightClientError(LightClientError),
|
|
LightClientBootstrapError(String),
|
|
UnsupportedFork,
|
|
MilhouseError(MilhouseError),
|
|
EmptyRpcCustodyColumns,
|
|
AttestationError(AttestationError),
|
|
AttestationCommitteeIndexNotSet,
|
|
InsufficientColumnsToReconstructBlobs {
|
|
columns_found: usize,
|
|
},
|
|
FailedToReconstructBlobs(String),
|
|
ProposerCacheIncorrectState {
|
|
state_decision_block_root: Hash256,
|
|
requested_decision_block_root: Hash256,
|
|
},
|
|
ProposerCacheAccessorFailure {
|
|
decision_block_root: Hash256,
|
|
proposal_epoch: Epoch,
|
|
},
|
|
ProposerCacheOutOfBounds {
|
|
slot: Slot,
|
|
epoch: Epoch,
|
|
},
|
|
ProposerCacheWrongEpoch {
|
|
request_epoch: Epoch,
|
|
cache_epoch: Epoch,
|
|
},
|
|
AttesterCachePtcOutOfBounds {
|
|
slot: Slot,
|
|
epoch: Epoch,
|
|
},
|
|
AttesterCacheNoPtcPreGloas {
|
|
slot: Slot,
|
|
},
|
|
SkipProposerPreparation,
|
|
FailedColumnCustodyInfoUpdate,
|
|
}
|
|
|
|
easy_from_to!(SlotProcessingError, BeaconChainError);
|
|
easy_from_to!(EpochProcessingError, BeaconChainError);
|
|
easy_from_to!(AttestationValidationError, BeaconChainError);
|
|
easy_from_to!(SyncCommitteeMessageValidationError, BeaconChainError);
|
|
easy_from_to!(ExitValidationError, BeaconChainError);
|
|
easy_from_to!(ProposerSlashingValidationError, BeaconChainError);
|
|
easy_from_to!(AttesterSlashingValidationError, BeaconChainError);
|
|
easy_from_to!(BlsExecutionChangeValidationError, BeaconChainError);
|
|
easy_from_to!(SszTypesError, BeaconChainError);
|
|
easy_from_to!(OpPoolError, BeaconChainError);
|
|
easy_from_to!(NaiveAggregationError, BeaconChainError);
|
|
easy_from_to!(ObservedAttestationsError, BeaconChainError);
|
|
easy_from_to!(ObservedAttestersError, BeaconChainError);
|
|
easy_from_to!(ObservedBlockProducersError, BeaconChainError);
|
|
easy_from_to!(ObservedDataSidecarsError, BeaconChainError);
|
|
easy_from_to!(BlockSignatureVerifierError, BeaconChainError);
|
|
easy_from_to!(PruningError, BeaconChainError);
|
|
easy_from_to!(ArithError, BeaconChainError);
|
|
easy_from_to!(ForkChoiceStoreError, BeaconChainError);
|
|
easy_from_to!(StateAdvanceError, BeaconChainError);
|
|
easy_from_to!(BlockReplayError, BeaconChainError);
|
|
easy_from_to!(InconsistentFork, BeaconChainError);
|
|
easy_from_to!(AvailabilityCheckError, BeaconChainError);
|
|
easy_from_to!(EpochCacheError, BeaconChainError);
|
|
easy_from_to!(LightClientError, BeaconChainError);
|
|
easy_from_to!(MilhouseError, BeaconChainError);
|
|
easy_from_to!(AttestationError, BeaconChainError);
|
|
|
|
#[derive(Debug)]
|
|
pub enum BlockProductionError {
|
|
UnableToGetBlockRootFromState,
|
|
UnableToReadSlot,
|
|
UnableToProduceAtSlot(Slot),
|
|
SlotProcessingError(SlotProcessingError),
|
|
BlockProcessingError(BlockProcessingError),
|
|
EpochCacheError(EpochCacheError),
|
|
ForkChoiceError(ForkChoiceError),
|
|
BeaconStateError(BeaconStateError),
|
|
StateAdvanceError(StateAdvanceError),
|
|
OpPoolError(OpPoolError),
|
|
StateSlotTooHigh {
|
|
produce_at_slot: Slot,
|
|
state_slot: Slot,
|
|
},
|
|
ExecutionLayerMissing,
|
|
BlockingFailed(execution_layer::Error),
|
|
TerminalPoWBlockLookupFailed(execution_layer::Error),
|
|
GetPayloadFailed(execution_layer::Error),
|
|
FailedToReadFinalizedBlock(store::Error),
|
|
FailedToLoadState(store::Error),
|
|
MissingFinalizedBlock(Hash256),
|
|
BlockTooLarge(usize),
|
|
ShuttingDown,
|
|
MissingBlobs,
|
|
MissingSyncAggregate,
|
|
MissingExecutionPayload,
|
|
MissingKzgCommitment(String),
|
|
TokioJoin(JoinError),
|
|
BeaconChain(Box<BeaconChainError>),
|
|
InvalidPayloadFork,
|
|
InvalidBlockVariant(String),
|
|
KzgError(kzg::Error),
|
|
FailedToBuildBlobSidecars(String),
|
|
MissingExecutionRequests,
|
|
SszTypesError(ssz_types::Error),
|
|
EnvelopeProcessingError(EnvelopeProcessingError),
|
|
BlsError(bls::Error),
|
|
MissingParentExecutionPayload,
|
|
MissingExecutionPayloadEnvelope(Hash256),
|
|
// TODO(gloas): Remove this once Gloas is implemented
|
|
GloasNotImplemented(String),
|
|
}
|
|
|
|
easy_from_to!(BlockProcessingError, BlockProductionError);
|
|
easy_from_to!(BeaconStateError, BlockProductionError);
|
|
easy_from_to!(SlotProcessingError, BlockProductionError);
|
|
easy_from_to!(StateAdvanceError, BlockProductionError);
|
|
easy_from_to!(ForkChoiceError, BlockProductionError);
|
|
easy_from_to!(EpochCacheError, BlockProductionError);
|