Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions consensus/types/presets/minimal/electra.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ MAX_ATTESTATIONS_ELECTRA: 8

# Execution
# ---------------------------------------------------------------
# [customized] 2**2 (= 4) deposit requests
MAX_DEPOSIT_REQUESTS_PER_PAYLOAD: 4
# [customized] 2**1 (= 2) withdrawal requests
MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD: 2
# 2**13 (= 8,192) deposit requests
MAX_DEPOSIT_REQUESTS_PER_PAYLOAD: 8192
# 2**4 (= 16) withdrawal requests
MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD: 16
# 2**1 (= 2) consolidation requests
MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: 2

Expand Down
59 changes: 42 additions & 17 deletions consensus/types/src/data_column_sidecar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ use crate::{
SignedBeaconBlockHeader, Slot,
};
use bls::Signature;
use context_deserialize::ContextDeserialize;
use derivative::Derivative;
use kzg::Error as KzgError;
use kzg::{KzgCommitment, KzgProof};
use merkle_proof::verify_merkle_proof;
use safe_arith::ArithError;
use serde::{Deserialize, Serialize};
use serde::de::Error;
use serde::{Deserialize, Deserializer, Serialize};
use ssz::{DecodeError, Encode};
use ssz_derive::{Decode, Encode};
use ssz_types::Error as SszError;
Expand All @@ -26,12 +28,49 @@ pub type Cell<E> = FixedVector<u8, <E as EthSpec>::BytesPerCell>;
pub type DataColumn<E> = VariableList<Cell<E>, <E as EthSpec>::MaxBlobCommitmentsPerBlock>;

/// Identifies a set of data columns associated with a specific beacon block.
#[derive(Encode, Clone, Debug, PartialEq)]
#[derive(Encode, Clone, Debug, PartialEq, TreeHash)]
pub struct DataColumnsByRootIdentifier {
pub block_root: Hash256,
pub columns: RuntimeVariableList<ColumnIndex>,
}

impl<'de> ContextDeserialize<'de, (ForkName, usize)> for DataColumnsByRootIdentifier {
fn context_deserialize<D>(deserializer: D, context: (ForkName, usize)) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct Helper {
block_root: Hash256,
columns: serde_json::Value,
}

let helper = Helper::deserialize(deserializer)?;
Ok(Self {
block_root: helper.block_root,
columns: RuntimeVariableList::context_deserialize(helper.columns, context)
.map_err(Error::custom)?,
})
}
}

impl DataColumnsByRootIdentifier {
pub fn from_ssz_bytes(bytes: &[u8], num_columns: usize) -> Result<Self, DecodeError> {
let mut builder = ssz::SszDecoderBuilder::new(bytes);
builder.register_type::<Hash256>()?;
builder.register_anonymous_variable_length_item()?;

let mut decoder = builder.build()?;
let block_root = decoder.decode_next()?;
let columns = decoder
.decode_next_with(|bytes| RuntimeVariableList::from_ssz_bytes(bytes, num_columns))?;
Ok(DataColumnsByRootIdentifier {
block_root,
columns,
})
}
}

impl RuntimeVariableList<DataColumnsByRootIdentifier> {
pub fn from_ssz_bytes_with_nested(
bytes: &[u8],
Expand All @@ -47,21 +86,7 @@ impl RuntimeVariableList<DataColumnsByRootIdentifier> {
Some(max_len),
)?
.into_iter()
.map(|bytes| {
let mut builder = ssz::SszDecoderBuilder::new(&bytes);
builder.register_type::<Hash256>()?;
builder.register_anonymous_variable_length_item()?;

let mut decoder = builder.build()?;
let block_root = decoder.decode_next()?;
let columns = decoder.decode_next_with(|bytes| {
RuntimeVariableList::from_ssz_bytes(bytes, num_columns)
})?;
Ok(DataColumnsByRootIdentifier {
block_root,
columns,
})
})
.map(|bytes| DataColumnsByRootIdentifier::from_ssz_bytes(&bytes, num_columns))
.collect::<Result<Vec<_>, _>>()?;

Ok(RuntimeVariableList::from_vec(vec, max_len))
Expand Down
6 changes: 3 additions & 3 deletions consensus/types/src/eth_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,6 @@ impl EthSpec for MinimalEthSpec {
type KzgCommitmentInclusionProofDepth = U10;
type PendingPartialWithdrawalsLimit = U64;
type PendingConsolidationsLimit = U64;
type MaxDepositRequestsPerPayload = U4;
type MaxWithdrawalRequestsPerPayload = U2;
type FieldElementsPerCell = U64;
type FieldElementsPerExtBlob = U8192;
type MaxCellsPerBlock = U33554432;
Expand Down Expand Up @@ -509,7 +507,9 @@ impl EthSpec for MinimalEthSpec {
MaxPendingDepositsPerEpoch,
MaxConsolidationRequestsPerPayload,
MaxAttesterSlashingsElectra,
MaxAttestationsElectra
MaxAttestationsElectra,
MaxDepositRequestsPerPayload,
MaxWithdrawalRequestsPerPayload
});

fn default_spec() -> ChainSpec {
Expand Down
57 changes: 57 additions & 0 deletions consensus/types/src/runtime_var_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use ssz::Decode;
use ssz_types::Error;
use std::ops::{Deref, Index, IndexMut};
use std::slice::SliceIndex;
use tree_hash::{Hash256, MerkleHasher, PackedEncoding, TreeHash, TreeHashType};

/// Emulates a SSZ `List`.
///
Expand Down Expand Up @@ -241,6 +242,62 @@ where
}
}

impl<T: TreeHash> TreeHash for RuntimeVariableList<T> {
fn tree_hash_type() -> tree_hash::TreeHashType {
tree_hash::TreeHashType::List
}

fn tree_hash_packed_encoding(&self) -> PackedEncoding {
unreachable!("List should never be packed.")
}

fn tree_hash_packing_factor() -> usize {
unreachable!("List should never be packed.")
}

fn tree_hash_root(&self) -> Hash256 {
let root = runtime_vec_tree_hash_root::<T>(&self.vec, self.max_len);

tree_hash::mix_in_length(&root, self.len())
}
}

// We can delete this once the upstream `vec_tree_hash_root` is modified to use a runtime max len.
pub fn runtime_vec_tree_hash_root<T>(vec: &[T], max_len: usize) -> Hash256
where
T: TreeHash,
{
match T::tree_hash_type() {
TreeHashType::Basic => {
let mut hasher =
MerkleHasher::with_leaves(max_len.div_ceil(T::tree_hash_packing_factor()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is covered by the spec tests in LH - but we should add a unit test if we move this into the ssz library.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah agreed. I'll work on a PR for that


for item in vec {
hasher
.write(&item.tree_hash_packed_encoding())
.expect("ssz_types variable vec should not contain more elements than max");
}

hasher
.finish()
.expect("ssz_types variable vec should not have a remaining buffer")
}
TreeHashType::Container | TreeHashType::List | TreeHashType::Vector => {
let mut hasher = MerkleHasher::with_leaves(max_len);

for item in vec {
hasher
.write(item.tree_hash_root().as_slice())
.expect("ssz_types vec should not contain more elements than max");
}

hasher
.finish()
.expect("ssz_types vec should not have a remaining buffer")
}
}
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
3 changes: 3 additions & 0 deletions testing/ef_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = { workspace = true }
[features]
# `ef_tests` feature must be enabled to actually run the tests
ef_tests = []
disable_rayon = []
fake_crypto = ["bls/fake_crypto"]
portable = ["beacon_chain/portable"]

Expand All @@ -16,6 +17,8 @@ beacon_chain = { workspace = true }
bls = { workspace = true }
compare_fields = { workspace = true }
compare_fields_derive = { workspace = true }
context_deserialize = { workspace = true }
context_deserialize_derive = { workspace = true }
derivative = { workspace = true }
eth2_network_config = { workspace = true }
ethereum_ssz = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion testing/ef_tests/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
TESTS_TAG := v1.5.0-beta.4
TESTS_TAG := v1.6.0-alpha.0
TESTS = general minimal mainnet
TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS))

Expand Down
10 changes: 10 additions & 0 deletions testing/ef_tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ $ cargo test --features ef_tests
The tests won't run without the `ef_tests` feature enabled (this is to ensure that a top-level
`cargo test --all` won't fail on missing files).

The following is sometimes necessary to avoid stack overflow issues when running on MacOS:
```
$ export RUST_MIN_STACK=8388608
```

When debugging failing tests, it's often useful to disable parallization and output suppression:
```
$ cargo test --features ef_tests,disable_rayon -- --nocapture
```

## Saving Space

When you download the tests, the downloaded archives will be kept in addition to the extracted
Expand Down
12 changes: 6 additions & 6 deletions testing/ef_tests/check_all_files_accessed.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@
"bls12-381-tests/deserialization_G1",
"bls12-381-tests/deserialization_G2",
"bls12-381-tests/hash_to_G2",
"tests/.*/eip6110",
"tests/.*/whisk",
# TODO(das): Fulu tests are ignored for now
"tests/.*/fulu",
"tests/.*/fulu/ssz_static/MatrixEntry",
"tests/.*/eip7441",
"tests/.*/eip7732",
"tests/.*/eip7805",
# Ignore MatrixEntry SSZ tests for now.
"tests/.*/fulu/ssz_static/MatrixEntry/.*",
# Ignore full epoch tests for now (just test the sub-transitions).
"tests/.*/.*/epoch_processing/.*/pre_epoch.ssz_snappy",
"tests/.*/.*/epoch_processing/.*/post_epoch.ssz_snappy",
]


Expand Down
20 changes: 11 additions & 9 deletions testing/ef_tests/src/cases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ mod genesis_validity;
mod get_custody_groups;
mod kzg_blob_to_kzg_commitment;
mod kzg_compute_blob_kzg_proof;
mod kzg_compute_cells;
mod kzg_compute_cells_and_kzg_proofs;
mod kzg_compute_kzg_proof;
mod kzg_recover_cells_and_kzg_proofs;
Expand Down Expand Up @@ -49,7 +50,7 @@ pub use bls_eth_fast_aggregate_verify::*;
pub use bls_fast_aggregate_verify::*;
pub use bls_sign_msg::*;
pub use bls_verify_msg::*;
pub use common::SszStaticType;
pub use common::{DataColumnsByRootIdentifierWrapper, SszStaticType};
pub use compute_columns_for_custody_groups::*;
pub use epoch_processing::*;
pub use fork::ForkTest;
Expand All @@ -58,6 +59,7 @@ pub use genesis_validity::*;
pub use get_custody_groups::*;
pub use kzg_blob_to_kzg_commitment::*;
pub use kzg_compute_blob_kzg_proof::*;
pub use kzg_compute_cells::*;
pub use kzg_compute_cells_and_kzg_proofs::*;
pub use kzg_compute_kzg_proof::*;
pub use kzg_recover_cells_and_kzg_proofs::*;
Expand Down Expand Up @@ -91,29 +93,29 @@ pub use transition::TransitionTest;
/// to return `true` for the feature in order for the feature test vector to be tested.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum FeatureName {
// TODO(fulu): to be removed once we start using Fulu types for test vectors.
// Existing SSZ types for PeerDAS (Fulu) are the same as Electra, so the test vectors get
// loaded as Electra types (default serde behaviour for untagged enums).
Fulu,
// Placeholder for future feature-gated forks
// Add new feature-gated forks here before they are incorporated into a main fork
#[doc(hidden)]
__Placeholder,
}

impl FeatureName {
pub fn list_all() -> Vec<FeatureName> {
vec![FeatureName::Fulu]
vec![]
}

/// `ForkName` to use when running the feature tests.
pub fn fork_name(&self) -> ForkName {
match self {
FeatureName::Fulu => ForkName::Electra,
FeatureName::__Placeholder => unreachable!("Placeholder variant should never be used"),
}
}
}

impl Display for FeatureName {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
FeatureName::Fulu => f.write_str("fulu"),
FeatureName::__Placeholder => unreachable!("Placeholder variant should never be used"),
}
}
}
Expand Down
Loading