mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-11 18:04:18 +00:00
Optimistic sync spec tests (v1.2.0) (#3564)
## Issue Addressed Implements new optimistic sync test format from https://github.com/ethereum/consensus-specs/pull/2982. ## Proposed Changes - Add parsing and runner support for the new test format. - Extend the mock EL with a set of canned responses keyed by block hash. Although this doubles up on some of the existing functionality I think it's really nice to use compared to the `preloaded_responses` or static responses. I think we could write novel new opt sync tests using these primtives much more easily than the previous ones. Forks are natively supported, and different responses to `forkchoiceUpdated` and `newPayload` are also straight-forward. ## Additional Info Blocked on merge of the spec PR and release of new test vectors.
This commit is contained in:
@@ -7,7 +7,7 @@ use serde_derive::Deserialize;
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct BlsAggregateSigs {
|
||||
pub input: Vec<String>,
|
||||
pub output: String,
|
||||
pub output: Option<String>,
|
||||
}
|
||||
|
||||
impl_bls_load_case!(BlsAggregateSigs);
|
||||
@@ -25,14 +25,13 @@ impl Case for BlsAggregateSigs {
|
||||
aggregate_signature.add_assign(&sig);
|
||||
}
|
||||
|
||||
// Check for YAML null value, indicating invalid input. This is a bit of a hack,
|
||||
// as our mutating `aggregate_signature.add` API doesn't play nicely with aggregating 0
|
||||
// inputs.
|
||||
let output_bytes = if self.output == "~" {
|
||||
AggregateSignature::infinity().serialize().to_vec()
|
||||
} else {
|
||||
hex::decode(&self.output[2..])
|
||||
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?
|
||||
let output_bytes = match self.output.as_deref() {
|
||||
// Check for YAML null value, indicating invalid input. This is a bit of a hack,
|
||||
// as our mutating `aggregate_signature.add` API doesn't play nicely with aggregating 0
|
||||
// inputs.
|
||||
Some("~") | None => AggregateSignature::infinity().serialize().to_vec(),
|
||||
Some(output) => hex::decode(&output[2..])
|
||||
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?,
|
||||
};
|
||||
let aggregate_signature = Ok(aggregate_signature.serialize().to_vec());
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ use beacon_chain::{
|
||||
test_utils::{BeaconChainHarness, EphemeralHarnessType},
|
||||
BeaconChainTypes, CachedHead, CountUnrealized,
|
||||
};
|
||||
use serde_derive::Deserialize;
|
||||
use execution_layer::{json_structures::JsonPayloadStatusV1Status, PayloadStatusV1};
|
||||
use serde::Deserialize;
|
||||
use ssz_derive::Decode;
|
||||
use state_processing::state_advance::complete_state_advance;
|
||||
use std::future::Future;
|
||||
@@ -50,16 +51,53 @@ pub struct Checks {
|
||||
proposer_boost_root: Option<Hash256>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct PayloadStatus {
|
||||
status: JsonPayloadStatusV1Status,
|
||||
latest_valid_hash: Option<ExecutionBlockHash>,
|
||||
validation_error: Option<String>,
|
||||
}
|
||||
|
||||
impl From<PayloadStatus> for PayloadStatusV1 {
|
||||
fn from(status: PayloadStatus) -> Self {
|
||||
PayloadStatusV1 {
|
||||
status: status.status.into(),
|
||||
latest_valid_hash: status.latest_valid_hash,
|
||||
validation_error: status.validation_error,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(untagged, deny_unknown_fields)]
|
||||
pub enum Step<B, A, AS, P> {
|
||||
Tick { tick: u64 },
|
||||
ValidBlock { block: B },
|
||||
MaybeValidBlock { block: B, valid: bool },
|
||||
Attestation { attestation: A },
|
||||
AttesterSlashing { attester_slashing: AS },
|
||||
PowBlock { pow_block: P },
|
||||
Checks { checks: Box<Checks> },
|
||||
Tick {
|
||||
tick: u64,
|
||||
},
|
||||
ValidBlock {
|
||||
block: B,
|
||||
},
|
||||
MaybeValidBlock {
|
||||
block: B,
|
||||
valid: bool,
|
||||
},
|
||||
Attestation {
|
||||
attestation: A,
|
||||
},
|
||||
AttesterSlashing {
|
||||
attester_slashing: AS,
|
||||
},
|
||||
PowBlock {
|
||||
pow_block: P,
|
||||
},
|
||||
OnPayloadInfo {
|
||||
block_hash: ExecutionBlockHash,
|
||||
payload_status: PayloadStatus,
|
||||
},
|
||||
Checks {
|
||||
checks: Box<Checks>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
@@ -119,6 +157,13 @@ impl<E: EthSpec> LoadCase for ForkChoiceTest<E> {
|
||||
ssz_decode_file(&path.join(format!("{}.ssz_snappy", pow_block)))
|
||||
.map(|pow_block| Step::PowBlock { pow_block })
|
||||
}
|
||||
Step::OnPayloadInfo {
|
||||
block_hash,
|
||||
payload_status,
|
||||
} => Ok(Step::OnPayloadInfo {
|
||||
block_hash,
|
||||
payload_status,
|
||||
}),
|
||||
Step::Checks { checks } => Ok(Step::Checks { checks }),
|
||||
})
|
||||
.collect::<Result<_, _>>()?;
|
||||
@@ -168,6 +213,14 @@ impl<E: EthSpec> Case for ForkChoiceTest<E> {
|
||||
tester.process_attester_slashing(attester_slashing)
|
||||
}
|
||||
Step::PowBlock { pow_block } => tester.process_pow_block(pow_block),
|
||||
Step::OnPayloadInfo {
|
||||
block_hash,
|
||||
payload_status,
|
||||
} => {
|
||||
let el = tester.harness.mock_execution_layer.as_ref().unwrap();
|
||||
el.server
|
||||
.set_payload_statuses(*block_hash, payload_status.clone().into());
|
||||
}
|
||||
Step::Checks { checks } => {
|
||||
let Checks {
|
||||
head,
|
||||
|
||||
@@ -117,6 +117,11 @@ impl<E: EthSpec> Operation<E> for Deposit {
|
||||
ssz_decode_file(path)
|
||||
}
|
||||
|
||||
fn is_enabled_for_fork(_: ForkName) -> bool {
|
||||
// Some deposit tests require signature verification but are not marked as such.
|
||||
cfg!(not(feature = "fake_crypto"))
|
||||
}
|
||||
|
||||
fn apply_to(
|
||||
&self,
|
||||
state: &mut BeaconState<E>,
|
||||
|
||||
@@ -546,6 +546,37 @@ impl<E: EthSpec + TypeName> Handler for ForkChoiceHandler<E> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Default(bound = ""))]
|
||||
pub struct OptimisticSyncHandler<E>(PhantomData<E>);
|
||||
|
||||
impl<E: EthSpec + TypeName> Handler for OptimisticSyncHandler<E> {
|
||||
type Case = cases::ForkChoiceTest<E>;
|
||||
|
||||
fn config_name() -> &'static str {
|
||||
E::name()
|
||||
}
|
||||
|
||||
fn runner_name() -> &'static str {
|
||||
"sync"
|
||||
}
|
||||
|
||||
fn handler_name(&self) -> String {
|
||||
"optimistic".into()
|
||||
}
|
||||
|
||||
fn use_rayon() -> bool {
|
||||
// The opt sync tests use `block_on` which can cause panics with rayon.
|
||||
false
|
||||
}
|
||||
|
||||
fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool {
|
||||
fork_name != ForkName::Base
|
||||
&& fork_name != ForkName::Altair
|
||||
&& cfg!(not(feature = "fake_crypto"))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Default(bound = ""))]
|
||||
pub struct GenesisValidityHandler<E>(PhantomData<E>);
|
||||
|
||||
Reference in New Issue
Block a user