mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-18 21:38:31 +00:00
Merge remote-tracking branch 'origin/unstable' into tree-states
This commit is contained in:
1
testing/ef_tests/.gitignore
vendored
1
testing/ef_tests/.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
/consensus-spec-tests
|
||||
.accessed_file_log.txt
|
||||
/bls12-381-tests
|
||||
|
||||
@@ -37,3 +37,4 @@ store = { path = "../../beacon_node/store" }
|
||||
fork_choice = { path = "../../consensus/fork_choice" }
|
||||
malloc_utils = { path = "../../common/malloc_utils" }
|
||||
logging = { path = "../../common/logging" }
|
||||
execution_layer = { path = "../../beacon_node/execution_layer" }
|
||||
|
||||
@@ -1,26 +1,41 @@
|
||||
TESTS_TAG := v1.2.0-rc.3
|
||||
TESTS_TAG := v1.2.0
|
||||
TESTS = general minimal mainnet
|
||||
TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS))
|
||||
|
||||
REPO_NAME := consensus-spec-tests
|
||||
OUTPUT_DIR := ./$(REPO_NAME)
|
||||
|
||||
BASE_URL := https://github.com/ethereum/$(REPO_NAME)/releases/download/$(TESTS_TAG)
|
||||
|
||||
BLS_TEST_REPO_NAME := bls12-381-tests
|
||||
BLS_TEST_TAG := v0.1.1
|
||||
BLS_TEST = bls_tests_yaml
|
||||
BLS_TARBALL = $(patsubst %,%-$(BLS_TEST_TAG).tar.gz,$(BLS_TEST))
|
||||
BLS_OUTPUT_DIR := $(OUTPUT_DIR)/$(BLS_TEST_REPO_NAME)
|
||||
BLS_BASE_URL := https://github.com/ethereum/$(BLS_TEST_REPO_NAME)/releases/download/$(BLS_TEST_TAG)
|
||||
|
||||
all:
|
||||
make $(OUTPUT_DIR)
|
||||
make $(BLS_OUTPUT_DIR)
|
||||
|
||||
$(OUTPUT_DIR): $(TARBALLS)
|
||||
mkdir $(OUTPUT_DIR)
|
||||
for test_tarball in $^; do \
|
||||
tar -xzf $$test_tarball -C $(OUTPUT_DIR);\
|
||||
done
|
||||
|
||||
$(BLS_OUTPUT_DIR):
|
||||
mkdir $(BLS_OUTPUT_DIR)
|
||||
wget $(BLS_BASE_URL)/$(BLS_TEST).tar.gz -O $(BLS_TARBALL)
|
||||
tar -xzf $(BLS_TARBALL) -C $(BLS_OUTPUT_DIR)
|
||||
|
||||
%-$(TESTS_TAG).tar.gz:
|
||||
wget $(BASE_URL)/$*.tar.gz -O $@
|
||||
|
||||
clean-test-files:
|
||||
rm -rf $(OUTPUT_DIR)
|
||||
rm -rf $(OUTPUT_DIR) $(BLS_OUTPUT_DIR)
|
||||
|
||||
clean-archives:
|
||||
rm -f $(TARBALLS)
|
||||
rm -f $(TARBALLS) $(BLS_TARBALL)
|
||||
|
||||
clean: clean-test-files clean-archives
|
||||
|
||||
|
||||
@@ -46,7 +46,13 @@ excluded_paths = [
|
||||
# One of the EF researchers likes to pack the tarballs on a Mac
|
||||
".*\.DS_Store.*",
|
||||
# More Mac weirdness.
|
||||
"tests/mainnet/bellatrix/operations/deposit/pyspec_tests/deposit_with_previous_fork_version__valid_ineffective/._meta.yaml"
|
||||
"tests/mainnet/bellatrix/operations/deposit/pyspec_tests/deposit_with_previous_fork_version__valid_ineffective/._meta.yaml",
|
||||
# bls tests are moved to bls12-381-tests directory
|
||||
"tests/general/phase0/bls",
|
||||
# some bls tests are not included now
|
||||
"bls12-381-tests/deserialization_G1",
|
||||
"bls12-381-tests/deserialization_G2",
|
||||
"bls12-381-tests/hash_to_G2"
|
||||
]
|
||||
|
||||
def normalize_path(path):
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
67
testing/ef_tests/src/cases/bls_batch_verify.rs
Normal file
67
testing/ef_tests/src/cases/bls_batch_verify.rs
Normal 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))
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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..])
|
||||
|
||||
@@ -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..])
|
||||
|
||||
@@ -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)))?;
|
||||
|
||||
@@ -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) => {
|
||||
@@ -80,3 +67,24 @@ pub fn previous_fork(fork_name: ForkName) -> ForkName {
|
||||
ForkName::Merge => ForkName::Altair, // 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))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -331,11 +384,11 @@ impl<E: EthSpec> Tester<E> {
|
||||
pub fn process_block(&self, block: SignedBeaconBlock<E>, valid: bool) -> Result<(), Error> {
|
||||
let block_root = block.canonical_root();
|
||||
let block = Arc::new(block);
|
||||
let result = self.block_on_dangerous(
|
||||
self.harness
|
||||
.chain
|
||||
.process_block(block.clone(), CountUnrealized::False),
|
||||
)?;
|
||||
let result = self.block_on_dangerous(self.harness.chain.process_block(
|
||||
block_root,
|
||||
block.clone(),
|
||||
CountUnrealized::False,
|
||||
))?;
|
||||
if result.is_ok() != valid {
|
||||
return Err(Error::DidntFail(format!(
|
||||
"block with root {} was valid={} whilst test expects valid={}. result: {:?}",
|
||||
|
||||
@@ -79,11 +79,16 @@ 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(_) => altair::process_attestation(
|
||||
state,
|
||||
self,
|
||||
@@ -111,7 +116,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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +132,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>,
|
||||
@@ -145,7 +162,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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>);
|
||||
|
||||
@@ -118,6 +118,12 @@ fn bls_verify() {
|
||||
BlsVerifyMsgHandler::default().run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "fake_crypto"))]
|
||||
fn bls_batch_verify() {
|
||||
BlsBatchVerifyHandler::default().run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(feature = "fake_crypto"))]
|
||||
fn bls_aggregate_verify() {
|
||||
@@ -444,6 +450,12 @@ fn fork_choice_ex_ante() {
|
||||
ForkChoiceHandler::<MainnetEthSpec>::new("ex_ante").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn optimistic_sync() {
|
||||
OptimisticSyncHandler::<MinimalEthSpec>::default().run();
|
||||
OptimisticSyncHandler::<MainnetEthSpec>::default().run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn genesis_initialization() {
|
||||
GenesisInitializationHandler::<MinimalEthSpec>::default().run();
|
||||
|
||||
@@ -239,13 +239,16 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
||||
|
||||
// Submit transactions before getting payload
|
||||
let txs = transactions::<MainnetEthSpec>(account1, account2);
|
||||
let mut pending_txs = Vec::new();
|
||||
for tx in txs.clone().into_iter() {
|
||||
self.ee_a
|
||||
let pending_tx = self
|
||||
.ee_a
|
||||
.execution_engine
|
||||
.provider
|
||||
.send_transaction(tx, None)
|
||||
.await
|
||||
.unwrap();
|
||||
pending_txs.push(pending_tx);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -328,8 +331,6 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
||||
.unwrap()
|
||||
.execution_payload;
|
||||
|
||||
assert_eq!(valid_payload.transactions.len(), txs.len());
|
||||
|
||||
/*
|
||||
* Execution Engine A:
|
||||
*
|
||||
@@ -393,6 +394,18 @@ impl<E: GenericExecutionEngine> TestRig<E> {
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(status, PayloadStatus::Valid);
|
||||
assert_eq!(valid_payload.transactions.len(), pending_txs.len());
|
||||
|
||||
// Verify that all submitted txs were successful
|
||||
for pending_tx in pending_txs {
|
||||
let tx_receipt = pending_tx.await.unwrap().unwrap();
|
||||
assert_eq!(
|
||||
tx_receipt.status,
|
||||
Some(1.into()),
|
||||
"Tx index {} has invalid status ",
|
||||
tx_receipt.transaction_index
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execution Engine A:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use deposit_contract::{encode_eth1_tx_data, BYTECODE, CONTRACT_DEPLOY_GAS, DEPOSIT_GAS};
|
||||
use ethers_core::types::{
|
||||
transaction::{eip2718::TypedTransaction, eip2930::AccessList},
|
||||
Address, Bytes, Eip1559TransactionRequest, TransactionRequest,
|
||||
Address, Bytes, Eip1559TransactionRequest, TransactionRequest, U256,
|
||||
};
|
||||
use types::{DepositData, EthSpec, Hash256, Keypair, Signature};
|
||||
|
||||
@@ -56,30 +56,36 @@ impl Transaction {
|
||||
.value(1)
|
||||
.with_access_list(AccessList::default())
|
||||
.into(),
|
||||
Self::DeployDepositContract(addr) => TransactionRequest::new()
|
||||
.from(*addr)
|
||||
.data(Bytes::from(BYTECODE.to_vec()))
|
||||
.gas(CONTRACT_DEPLOY_GAS)
|
||||
.into(),
|
||||
Self::DeployDepositContract(addr) => {
|
||||
let mut bytecode = String::from_utf8(BYTECODE.to_vec()).unwrap();
|
||||
bytecode.retain(|c| c.is_ascii_hexdigit());
|
||||
let bytecode = hex::decode(&bytecode[1..]).unwrap();
|
||||
TransactionRequest::new()
|
||||
.from(*addr)
|
||||
.data(Bytes::from(bytecode))
|
||||
.gas(CONTRACT_DEPLOY_GAS)
|
||||
.into()
|
||||
}
|
||||
Self::DepositDepositContract {
|
||||
sender,
|
||||
deposit_contract_address,
|
||||
} => {
|
||||
let keypair = Keypair::random();
|
||||
|
||||
let amount: u64 = 32_000_000_000;
|
||||
let mut deposit = DepositData {
|
||||
pubkey: keypair.pk.into(),
|
||||
withdrawal_credentials: Hash256::zero(),
|
||||
amount: 32_000_000_000,
|
||||
amount,
|
||||
signature: Signature::empty().into(),
|
||||
};
|
||||
|
||||
deposit.signature = deposit.create_signature(&keypair.sk, &E::default_spec());
|
||||
TransactionRequest::new()
|
||||
.from(*sender)
|
||||
.to(*deposit_contract_address)
|
||||
.data(Bytes::from(encode_eth1_tx_data(&deposit).unwrap()))
|
||||
.gas(DEPOSIT_GAS)
|
||||
.value(U256::from(amount) * U256::exp10(9))
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::local_network::{EXECUTION_PORT, INVALID_ADDRESS, TERMINAL_BLOCK, TERMINAL_DIFFICULTY};
|
||||
use crate::local_network::{EXECUTION_PORT, TERMINAL_BLOCK, TERMINAL_DIFFICULTY};
|
||||
use crate::{checks, LocalNetwork, E};
|
||||
use clap::ArgMatches;
|
||||
use eth1::{Eth1Endpoint, DEFAULT_CHAIN_ID};
|
||||
@@ -56,16 +56,14 @@ pub fn run_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let log_level = "debug";
|
||||
let log_format = None;
|
||||
|
||||
let mut env = EnvironmentBuilder::minimal()
|
||||
.initialize_logger(LoggerConfig {
|
||||
path: None,
|
||||
debug_level: log_level,
|
||||
logfile_debug_level: "debug",
|
||||
log_format,
|
||||
debug_level: String::from("debug"),
|
||||
logfile_debug_level: String::from("debug"),
|
||||
log_format: None,
|
||||
log_color: false,
|
||||
disable_log_timestamp: false,
|
||||
max_log_size: 0,
|
||||
max_log_number: 0,
|
||||
compression: false,
|
||||
@@ -137,7 +135,7 @@ pub fn run_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
|
||||
let mut beacon_config = testing_client_config();
|
||||
|
||||
beacon_config.genesis = ClientGenesis::DepositContract;
|
||||
beacon_config.eth1.endpoints = Eth1Endpoint::NoAuth(vec![eth1_endpoint]);
|
||||
beacon_config.eth1.endpoint = Eth1Endpoint::NoAuth(eth1_endpoint);
|
||||
beacon_config.eth1.deposit_contract_address = deposit_contract_address;
|
||||
beacon_config.eth1.deposit_contract_deploy_block = 0;
|
||||
beacon_config.eth1.lowest_cached_block_number = 0;
|
||||
@@ -172,18 +170,8 @@ pub fn run_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
|
||||
/*
|
||||
* One by one, add beacon nodes to the network.
|
||||
*/
|
||||
for i in 0..node_count - 1 {
|
||||
let mut config = beacon_config.clone();
|
||||
if i % 2 == 0 {
|
||||
if let Eth1Endpoint::NoAuth(endpoints) = &mut config.eth1.endpoints {
|
||||
endpoints.insert(
|
||||
0,
|
||||
SensitiveUrl::parse(INVALID_ADDRESS)
|
||||
.expect("Unable to parse invalid address"),
|
||||
)
|
||||
}
|
||||
}
|
||||
network.add_beacon_node(config).await?;
|
||||
for _ in 0..node_count - 1 {
|
||||
network.add_beacon_node(beacon_config.clone()).await?;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -41,16 +41,14 @@ pub fn run_no_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let log_level = "debug";
|
||||
let log_format = None;
|
||||
|
||||
let mut env = EnvironmentBuilder::mainnet()
|
||||
.initialize_logger(LoggerConfig {
|
||||
path: None,
|
||||
debug_level: log_level,
|
||||
logfile_debug_level: "debug",
|
||||
log_format,
|
||||
debug_level: String::from("debug"),
|
||||
logfile_debug_level: String::from("debug"),
|
||||
log_format: None,
|
||||
log_color: false,
|
||||
disable_log_timestamp: false,
|
||||
max_log_size: 0,
|
||||
max_log_number: 0,
|
||||
compression: false,
|
||||
|
||||
@@ -48,10 +48,11 @@ fn syncing_sim(
|
||||
let mut env = EnvironmentBuilder::minimal()
|
||||
.initialize_logger(LoggerConfig {
|
||||
path: None,
|
||||
debug_level: log_level,
|
||||
logfile_debug_level: "debug",
|
||||
log_format,
|
||||
debug_level: String::from(log_level),
|
||||
logfile_debug_level: String::from("debug"),
|
||||
log_format: log_format.map(String::from),
|
||||
log_color: false,
|
||||
disable_log_timestamp: false,
|
||||
max_log_size: 0,
|
||||
max_log_number: 0,
|
||||
compression: false,
|
||||
|
||||
Reference in New Issue
Block a user