merge with unstable

This commit is contained in:
realbigsean
2022-11-01 13:18:00 -04:00
143 changed files with 4773 additions and 1876 deletions

View File

@@ -6,6 +6,7 @@ use types::ForkName;
mod bls_aggregate_sigs;
mod bls_aggregate_verify;
mod bls_batch_verify;
mod bls_eth_aggregate_pubkeys;
mod bls_eth_fast_aggregate_verify;
mod bls_fast_aggregate_verify;
@@ -29,6 +30,7 @@ mod transition;
pub use self::fork_choice::*;
pub use bls_aggregate_sigs::*;
pub use bls_aggregate_verify::*;
pub use bls_batch_verify::*;
pub use bls_eth_aggregate_pubkeys::*;
pub use bls_eth_fast_aggregate_verify::*;
pub use bls_fast_aggregate_verify::*;

View File

@@ -1,22 +1,18 @@
use super::*;
use crate::case_result::compare_result;
use crate::cases::common::BlsCase;
use crate::impl_bls_load_case;
use bls::{AggregateSignature, Signature};
use serde_derive::Deserialize;
#[derive(Debug, Clone, Deserialize)]
pub struct BlsAggregateSigs {
pub input: Vec<String>,
pub output: String,
pub output: Option<String>,
}
impl BlsCase for BlsAggregateSigs {}
impl_bls_load_case!(BlsAggregateSigs);
impl Case for BlsAggregateSigs {
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
fork_name == ForkName::Base
}
fn result(&self, _case_index: usize, _fork_name: ForkName) -> Result<(), Error> {
let mut aggregate_signature = AggregateSignature::infinity();
@@ -29,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());

View File

@@ -1,6 +1,6 @@
use super::*;
use crate::case_result::compare_result;
use crate::cases::common::BlsCase;
use crate::impl_bls_load_case;
use bls::{AggregateSignature, PublicKeyBytes};
use serde_derive::Deserialize;
use types::Hash256;
@@ -18,13 +18,9 @@ pub struct BlsAggregateVerify {
pub output: bool,
}
impl BlsCase for BlsAggregateVerify {}
impl_bls_load_case!(BlsAggregateVerify);
impl Case for BlsAggregateVerify {
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
fork_name == ForkName::Base
}
fn result(&self, _case_index: usize, _fork_name: ForkName) -> Result<(), Error> {
let messages = self
.input

View File

@@ -0,0 +1,67 @@
use super::*;
use crate::case_result::compare_result;
use crate::impl_bls_load_case;
use bls::{verify_signature_sets, BlsWrappedSignature, PublicKeyBytes, Signature, SignatureSet};
use serde_derive::Deserialize;
use std::borrow::Cow;
use std::str::FromStr;
use types::Hash256;
#[derive(Debug, Clone, Deserialize)]
pub struct BlsBatchVerifyInput {
pubkeys: Vec<PublicKeyBytes>,
messages: Vec<String>,
signatures: Vec<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct BlsBatchVerify {
pub input: BlsBatchVerifyInput,
pub output: bool,
}
impl_bls_load_case!(BlsBatchVerify);
impl Case for BlsBatchVerify {
fn result(&self, _case_index: usize, _fork_name: ForkName) -> Result<(), Error> {
let messages = self
.input
.messages
.iter()
.map(|s| Hash256::from_str(s).map_err(|e| Error::FailedToParseTest(format!("{:?}", e))))
.collect::<Result<Vec<_>, _>>()?;
let pubkeys = self
.input
.pubkeys
.iter()
.map(|pkb| {
pkb.decompress()
.map_err(|_| Error::FailedToParseTest("pubkeys parse error".to_string()))
})
.collect::<Result<Vec<_>, _>>()?;
let signatures = self
.input
.signatures
.iter()
.map(|s| {
Signature::from_str(s).map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))
})
.collect::<Result<Vec<_>, _>>()?;
let signature_set = messages
.iter()
.zip(pubkeys.iter())
.zip(signatures.iter())
.map(|((&message, pubkey), signature)| {
let wraped_signature = BlsWrappedSignature::from(signature);
SignatureSet::single_pubkey(wraped_signature, Cow::Borrowed(pubkey), message)
})
.collect::<Vec<_>>();
let signature_valid = verify_signature_sets(signature_set.iter());
compare_result::<bool, ()>(&Ok(signature_valid), &Some(self.output))
}
}

View File

@@ -1,6 +1,6 @@
use super::*;
use crate::case_result::compare_result;
use crate::cases::common::BlsCase;
use crate::impl_bls_load_case;
use bls::{AggregatePublicKey, PublicKeyBytes};
use serde_derive::Deserialize;
@@ -10,7 +10,7 @@ pub struct BlsEthAggregatePubkeys {
pub output: Option<PublicKeyBytes>,
}
impl BlsCase for BlsEthAggregatePubkeys {}
impl_bls_load_case!(BlsEthAggregatePubkeys, "data.yaml");
impl Case for BlsEthAggregatePubkeys {
fn is_enabled_for_fork(fork_name: ForkName) -> bool {

View File

@@ -1,6 +1,6 @@
use super::*;
use crate::case_result::compare_result;
use crate::cases::common::BlsCase;
use crate::impl_bls_load_case;
use bls::{AggregateSignature, PublicKeyBytes};
use serde_derive::Deserialize;
use std::convert::TryInto;
@@ -20,7 +20,7 @@ pub struct BlsEthFastAggregateVerify {
pub output: bool,
}
impl BlsCase for BlsEthFastAggregateVerify {}
impl_bls_load_case!(BlsEthFastAggregateVerify, "data.yaml");
impl Case for BlsEthFastAggregateVerify {
fn is_enabled_for_fork(fork_name: ForkName) -> bool {

View File

@@ -1,6 +1,6 @@
use super::*;
use crate::case_result::compare_result;
use crate::cases::common::BlsCase;
use crate::impl_bls_load_case;
use bls::{AggregateSignature, PublicKeyBytes};
use serde_derive::Deserialize;
use std::convert::TryInto;
@@ -20,13 +20,9 @@ pub struct BlsFastAggregateVerify {
pub output: bool,
}
impl BlsCase for BlsFastAggregateVerify {}
impl_bls_load_case!(BlsFastAggregateVerify);
impl Case for BlsFastAggregateVerify {
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
fork_name == ForkName::Base
}
fn result(&self, _case_index: usize, _fork_name: ForkName) -> Result<(), Error> {
let message = Hash256::from_slice(
&hex::decode(&self.input.message[2..])

View File

@@ -1,6 +1,6 @@
use super::*;
use crate::case_result::compare_result;
use crate::cases::common::BlsCase;
use crate::impl_bls_load_case;
use bls::SecretKey;
use serde_derive::Deserialize;
use types::Hash256;
@@ -17,13 +17,9 @@ pub struct BlsSign {
pub output: Option<String>,
}
impl BlsCase for BlsSign {}
impl_bls_load_case!(BlsSign);
impl Case for BlsSign {
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
fork_name == ForkName::Base
}
fn result(&self, _case_index: usize, _fork_name: ForkName) -> Result<(), Error> {
// Convert private_key and message to required types
let sk = hex::decode(&self.input.privkey[2..])

View File

@@ -1,6 +1,6 @@
use super::*;
use crate::case_result::compare_result;
use crate::cases::common::BlsCase;
use crate::impl_bls_load_case;
use bls::{PublicKeyBytes, Signature, SignatureBytes};
use serde_derive::Deserialize;
use std::convert::TryInto;
@@ -19,13 +19,9 @@ pub struct BlsVerify {
pub output: bool,
}
impl BlsCase for BlsVerify {}
impl_bls_load_case!(BlsVerify);
impl Case for BlsVerify {
fn is_enabled_for_fork(fork_name: ForkName) -> bool {
fork_name == ForkName::Base
}
fn result(&self, _case_index: usize, _fork_name: ForkName) -> Result<(), Error> {
let message = hex::decode(&self.input.message[2..])
.map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?;

View File

@@ -1,24 +1,11 @@
use crate::cases::LoadCase;
use crate::decode::yaml_decode_file;
use crate::error::Error;
use serde_derive::Deserialize;
use ssz::Encode;
use ssz_derive::{Decode, Encode};
use std::convert::TryFrom;
use std::fmt::Debug;
use std::path::Path;
use tree_hash::TreeHash;
use types::ForkName;
/// Trait for all BLS cases to eliminate some boilerplate.
pub trait BlsCase: serde::de::DeserializeOwned {}
impl<T: BlsCase> LoadCase for T {
fn load_from_dir(path: &Path, _fork_name: ForkName) -> Result<Self, Error> {
yaml_decode_file(&path.join("data.yaml"))
}
}
/// Macro to wrap U128 and U256 so they deserialize correctly.
macro_rules! uint_wrapper {
($wrapper_name:ident, $wrapped_type:ty) => {
@@ -82,3 +69,24 @@ pub fn previous_fork(fork_name: ForkName) -> ForkName {
ForkName::Eip4844 => ForkName::Capella, // TODO: Check this when tests are released..
}
}
#[macro_export]
macro_rules! impl_bls_load_case {
($case_name:ident) => {
use $crate::decode::yaml_decode_file;
impl LoadCase for $case_name {
fn load_from_dir(path: &Path, _fork_name: ForkName) -> Result<Self, Error> {
yaml_decode_file(&path)
}
}
};
($case_name:ident, $sub_path_name:expr) => {
use $crate::decode::yaml_decode_file;
impl LoadCase for $case_name {
fn load_from_dir(path: &Path, _fork_name: ForkName) -> Result<Self, Error> {
yaml_decode_file(&path.join($sub_path_name))
}
}
};
}

View File

@@ -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,

View File

@@ -5,15 +5,17 @@ use crate::decode::{ssz_decode_file, ssz_decode_file_with, ssz_decode_state, yam
use crate::testing_spec;
use crate::type_name::TypeName;
use serde_derive::Deserialize;
use ssz::Decode;
use state_processing::per_block_processing::{
errors::BlockProcessingError,
process_block_header, process_execution_payload,
process_operations::{
altair, base, process_attester_slashings, process_deposits, process_exits,
process_proposer_slashings,
use state_processing::{
per_block_processing::{
errors::BlockProcessingError,
process_block_header, process_execution_payload,
process_operations::{
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::path::Path;
@@ -77,16 +79,20 @@ impl<E: EthSpec> Operation<E> for Attestation<E> {
spec: &ChainSpec,
_: &Operations<E, Self>,
) -> 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 {
BeaconState::Base(_) => {
base::process_attestations(state, &[self.clone()], VerifySignatures::True, spec)
}
BeaconState::Base(_) => base::process_attestations(
state,
&[self.clone()],
VerifySignatures::True,
&mut ctxt,
spec,
),
BeaconState::Altair(_)
| BeaconState::Merge(_)
| BeaconState::Capella(_)
| BeaconState::Eip4844(_) => altair::process_attestation(
state,
| BeaconState::Eip4844(_) => altair::process_attestation( state,
self,
0,
proposer_index,
@@ -112,7 +118,14 @@ impl<E: EthSpec> Operation<E> for AttesterSlashing<E> {
spec: &ChainSpec,
_: &Operations<E, Self>,
) -> 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,
)
}
}
@@ -121,6 +134,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>,
@@ -146,7 +164,14 @@ impl<E: EthSpec> Operation<E> for ProposerSlashing {
spec: &ChainSpec,
_: &Operations<E, Self>,
) -> 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,
)
}
}
@@ -188,10 +213,12 @@ impl<E: EthSpec> Operation<E> for BeaconBlock<E> {
spec: &ChainSpec,
_: &Operations<E, Self>,
) -> Result<(), BlockProcessingError> {
let mut ctxt = ConsensusContext::new(state.slot());
process_block_header(
state,
self.to_ref().temporary_block_header(),
VerifyBlockRoot::True,
&mut ctxt,
spec,
)?;
Ok(())

View File

@@ -5,7 +5,7 @@ use crate::decode::{ssz_decode_file_with, ssz_decode_state, yaml_decode_file};
use serde_derive::Deserialize;
use state_processing::{
per_block_processing, per_slot_processing, BlockProcessingError, BlockSignatureStrategy,
VerifyBlockRoot,
ConsensusContext, VerifyBlockRoot,
};
use types::{BeaconState, EthSpec, ForkName, RelativeEpoch, SignedBeaconBlock};
@@ -91,26 +91,28 @@ impl<E: EthSpec> Case for SanityBlocks<E> {
.build_committee_cache(RelativeEpoch::Current, spec)
.unwrap();
let mut ctxt = ConsensusContext::new(indiv_state.slot());
per_block_processing(
&mut indiv_state,
signed_block,
None,
BlockSignatureStrategy::VerifyIndividual,
VerifyBlockRoot::True,
&mut ctxt,
spec,
)?;
let mut ctxt = ConsensusContext::new(indiv_state.slot());
per_block_processing(
&mut bulk_state,
signed_block,
None,
BlockSignatureStrategy::VerifyBulk,
VerifyBlockRoot::True,
&mut ctxt,
spec,
)?;
if block.state_root() == bulk_state.canonical_root()
&& block.state_root() == indiv_state.canonical_root()
if block.state_root() == bulk_state.update_tree_hash_cache().unwrap()
&& block.state_root() == indiv_state.update_tree_hash_cache().unwrap()
{
Ok(())
} else {

View File

@@ -4,7 +4,7 @@ use crate::decode::{ssz_decode_file_with, ssz_decode_state, yaml_decode_file};
use serde_derive::Deserialize;
use state_processing::{
per_block_processing, state_advance::complete_state_advance, BlockSignatureStrategy,
VerifyBlockRoot,
ConsensusContext, VerifyBlockRoot,
};
use std::str::FromStr;
use types::{BeaconState, Epoch, ForkName, SignedBeaconBlock};
@@ -99,12 +99,13 @@ impl<E: EthSpec> Case for TransitionTest<E> {
.map_err(|e| format!("Failed to advance: {:?}", e))?;
// Apply block.
let mut ctxt = ConsensusContext::new(state.slot());
per_block_processing(
&mut state,
block,
None,
BlockSignatureStrategy::VerifyBulk,
VerifyBlockRoot::True,
&mut ctxt,
spec,
)
.map_err(|e| format!("Block processing failed: {:?}", e))?;

View File

@@ -49,8 +49,9 @@ pub trait Handler {
let as_directory = |entry: Result<DirEntry, std::io::Error>| -> Option<DirEntry> {
entry
.ok()
.filter(|e| e.file_type().map(|ty| ty.is_dir()).unwrap_or(false))
.filter(|e| e.file_type().map(|ty| ty.is_dir()).unwrap())
};
let test_cases = fs::read_dir(&handler_path)
.unwrap_or_else(|e| panic!("handler dir {} exists: {:?}", handler_path.display(), e))
.filter_map(as_directory)
@@ -58,6 +59,7 @@ pub trait Handler {
.filter_map(as_directory)
.map(|test_case_dir| {
let path = test_case_dir.path();
let case = Self::Case::load_from_dir(&path, fork_name).expect("test should load");
(path, case)
})
@@ -75,7 +77,7 @@ pub trait Handler {
}
}
macro_rules! bls_handler {
macro_rules! bls_eth_handler {
($runner_name: ident, $case_name:ident, $handler_name:expr) => {
#[derive(Derivative)]
#[derivative(Default(bound = ""))]
@@ -95,8 +97,69 @@ macro_rules! bls_handler {
};
}
macro_rules! bls_handler {
($runner_name: ident, $case_name:ident, $handler_name:expr) => {
#[derive(Derivative)]
#[derivative(Default(bound = ""))]
pub struct $runner_name;
impl Handler for $runner_name {
type Case = cases::$case_name;
fn runner_name() -> &'static str {
"bls"
}
fn config_name() -> &'static str {
"bls12-381-tests"
}
fn handler_name(&self) -> String {
$handler_name.into()
}
fn run(&self) {
let fork_name = ForkName::Base;
let fork_name_str = fork_name.to_string();
let handler_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("consensus-spec-tests")
.join(Self::config_name())
.join(self.handler_name());
let as_file = |entry: Result<DirEntry, std::io::Error>| -> Option<DirEntry> {
entry
.ok()
.filter(|e| e.file_type().map(|ty| ty.is_file()).unwrap_or(false))
};
let test_cases: Vec<(PathBuf, Self::Case)> = fs::read_dir(&handler_path)
.expect("handler dir exists")
.filter_map(as_file)
.map(|test_case_path| {
let path = test_case_path.path();
let case =
Self::Case::load_from_dir(&path, fork_name).expect("test should load");
(path, case)
})
.collect();
let results = Cases { test_cases }.test_results(fork_name, Self::use_rayon());
let name = format!(
"{}/{}/{}",
fork_name_str,
Self::runner_name(),
self.handler_name()
);
crate::results::assert_tests_pass(&name, &handler_path, &results);
}
}
};
}
bls_handler!(BlsAggregateSigsHandler, BlsAggregateSigs, "aggregate");
bls_handler!(BlsSignMsgHandler, BlsSign, "sign");
bls_handler!(BlsBatchVerifyHandler, BlsBatchVerify, "batch_verify");
bls_handler!(BlsVerifyMsgHandler, BlsVerify, "verify");
bls_handler!(
BlsAggregateVerifyHandler,
@@ -108,12 +171,12 @@ bls_handler!(
BlsFastAggregateVerify,
"fast_aggregate_verify"
);
bls_handler!(
bls_eth_handler!(
BlsEthAggregatePubkeysHandler,
BlsEthAggregatePubkeys,
"eth_aggregate_pubkeys"
);
bls_handler!(
bls_eth_handler!(
BlsEthFastAggregateVerifyHandler,
BlsEthFastAggregateVerify,
"eth_fast_aggregate_verify"
@@ -483,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>);