Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support ssz devnet #418

Draft
wants to merge 4 commits into
base: pectra
Choose a base branch
from
Draft
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
261 changes: 118 additions & 143 deletions Cargo.lock

Large diffs are not rendered by default.

9 changes: 7 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ default-members = ["cli"]
[workspace.dependencies]
# consensus
ssz_types = "0.7.0"
ethereum_ssz_derive = "0.6.0"
ethereum_ssz = "0.6.0"
ethereum_ssz_derive = "0.5.4"
ethereum_ssz = "0.5.4"
tree_hash_derive = "0.7.0"
tree_hash = "0.7.0"
sha2 = "0.9"
Expand Down Expand Up @@ -111,6 +111,11 @@ rand = "0.8.5"

[patch.crates-io]
ethereum_hashing = { git = "https://github.com/ncitron/ethereum_hashing", rev = "7ee70944ed4fabe301551da8c447e4f4ae5e6c35" }
ssz_types = { git = "https://github.com/ncitron/ssz_types", branch = "stable-container" }
ethereum_ssz = { git = "https://github.com/ncitron/ethereum_ssz", branch = "stable-container" }
ethereum_ssz_derive = { git = "https://github.com/ncitron/ethereum_ssz", branch = "stable-container" }
tree_hash = { git = "https://github.com/ncitron/tree_hash", branch = "stable-container" }
tree_hash_derive = { git = "https://github.com/ncitron/tree_hash", branch = "stable-container" }

######################################
# Profiles
Expand Down
1 change: 1 addition & 0 deletions ethereum/consensus-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ superstruct.workspace = true
thiserror.workspace = true
tracing.workspace = true
zduny-wasm-timer.workspace = true
serde_json.workspace = true

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2", features = ["js"] }
Expand Down
13 changes: 10 additions & 3 deletions ethereum/consensus-core/src/consensus_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,9 @@ fn has_sync_update<S: ConsensusSpec>(update: &GenericUpdate<S>) -> bool {
}

fn has_finality_update<S: ConsensusSpec>(update: &GenericUpdate<S>) -> bool {
update.finalized_header.is_some() && update.finality_branch.is_some()
let normal = update.finalized_header.is_some() && update.finality_branch.is_some();
let genesis = update.finalized_header.is_none() && update.finality_branch.is_some();
normal || genesis
}

fn verify_sync_committee_signture(
Expand Down Expand Up @@ -504,8 +506,13 @@ fn is_valid_header<S: ConsensusSpec>(header: &LightClientHeader, forks: &Forks)
}
};

let proof_valid =
is_execution_payload_proof_valid(header.beacon(), execution, execution_branch);
let proof_valid = is_execution_payload_proof_valid(
header.beacon(),
execution,
execution_branch,
epoch,
forks,
);

proof_valid && valid_execution_type
} else {
Expand Down
22 changes: 18 additions & 4 deletions ethereum/consensus-core/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn is_finality_proof_valid(
forks: &Forks,
) -> bool {
let (index, depth) = if current_epoch >= forks.electra.epoch {
(41, 7)
(41, 9)
} else {
(41, 6)
};
Expand All @@ -37,7 +37,7 @@ pub fn is_next_committee_proof_valid<S: ConsensusSpec>(
forks: &Forks,
) -> bool {
let (index, depth) = if current_epoch >= forks.electra.epoch {
(23, 6)
(23, 8)
} else {
(23, 5)
};
Expand All @@ -59,7 +59,7 @@ pub fn is_current_committee_proof_valid<S: ConsensusSpec>(
forks: &Forks,
) -> bool {
let (index, depth) = if current_epoch >= forks.electra.epoch {
(22, 6)
(22, 8)
} else {
(22, 5)
};
Expand All @@ -77,8 +77,22 @@ pub fn is_execution_payload_proof_valid(
attested_header: &BeaconBlockHeader,
execution: &ExecutionPayloadHeader,
execution_branch: &[B256],
current_epoch: u64,
forks: &Forks,
) -> bool {
is_proof_valid(attested_header.body_root, execution, execution_branch, 4, 9)
let (index, depth) = if current_epoch >= forks.electra.epoch {
(9, 7)
} else {
(9, 4)
};

is_proof_valid(
attested_header.body_root,
execution,
execution_branch,
depth,
index,
)
}

fn is_proof_valid<T: TreeHash>(
Expand Down
54 changes: 41 additions & 13 deletions ethereum/consensus-core/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,23 @@ use ssz_derive::{Decode, Encode};
use ssz_types::{serde_utils::quoted_u64_var_list, BitList, BitVector, FixedVector, VariableList};
use superstruct::superstruct;
use tree_hash_derive::TreeHash;
use typenum::Unsigned;

use crate::consensus_spec::ConsensusSpec;

use self::{
bls::{PublicKey, Signature},
bytes::{ByteList, ByteVector},
transaction::Transaction,
};

pub mod bls;
pub mod bytes;
mod serde_utils;
pub mod transaction;

pub type LogsBloom = ByteVector<typenum::U256>;
pub type KZGCommitment = ByteVector<typenum::U48>;
pub type Transaction = ByteList<typenum::U1073741824>;

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct LightClientStore<S: ConsensusSpec> {
Expand Down Expand Up @@ -53,13 +55,17 @@ pub struct BeaconBlock<S: ConsensusSpec> {
derive(Deserialize, Clone, Debug, Encode, TreeHash, Default),
serde(deny_unknown_fields),
serde(bound = "S: ConsensusSpec"),
)
),
specific_variant_attributes(Electra(tree_hash(
struct_behaviour = "profile",
max_fields = "typenum::U64"
)))
)]
#[derive(Encode, TreeHash, Deserialize, Debug, Clone)]
#[serde(untagged)]
#[serde(bound = "S: ConsensusSpec")]
#[ssz(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent_stable")]
pub struct BeaconBlockBody<S: ConsensusSpec> {
randao_reveal: Signature,
eth1_data: Eth1Data,
Expand Down Expand Up @@ -120,13 +126,17 @@ pub struct BlsToExecutionChange {
derive(Default, Debug, Deserialize, Encode, TreeHash, Clone),
serde(deny_unknown_fields),
serde(bound = "S: ConsensusSpec"),
)
),
specific_variant_attributes(Electra(tree_hash(
struct_behaviour = "profile",
max_fields = "typenum::U64"
)))
)]
#[derive(Debug, Deserialize, Clone, Encode, TreeHash)]
#[serde(untagged)]
#[serde(bound = "S: ConsensusSpec")]
#[ssz(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent_stable")]
pub struct ExecutionPayload<S: ConsensusSpec> {
pub parent_hash: B256,
pub fee_recipient: Address,
Expand Down Expand Up @@ -155,6 +165,8 @@ pub struct ExecutionPayload<S: ConsensusSpec> {
#[superstruct(only(Deneb, Electra))]
#[serde(with = "serde_utils::u64")]
pub excess_blob_gas: u64,
#[superstruct(only(Electra))]
pub system_logs_root: B256,
#[ssz(skip_serializing, skip_deserializing)]
#[tree_hash(skip_hashing)]
#[serde(skip)]
Expand Down Expand Up @@ -182,12 +194,16 @@ impl<S: ConsensusSpec> Default for ExecutionPayload<S> {
PartialEq
),
serde(deny_unknown_fields),
)
),
specific_variant_attributes(Electra(tree_hash(
struct_behaviour = "profile",
max_fields = "typenum::U64"
)))
)]
#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, PartialEq)]
#[serde(untagged)]
#[ssz(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent_stable")]
pub struct ExecutionPayloadHeader {
pub parent_hash: B256,
pub fee_recipient: Address,
Expand Down Expand Up @@ -216,6 +232,8 @@ pub struct ExecutionPayloadHeader {
#[superstruct(only(Deneb, Electra))]
#[serde(with = "serde_utils::u64")]
pub excess_blob_gas: u64,
#[superstruct(only(Electra))]
pub system_logs_root: B256,
}

impl Default for ExecutionPayloadHeader {
Expand Down Expand Up @@ -270,13 +288,17 @@ pub struct AttesterSlashing<S: ConsensusSpec> {
variant_attributes(
derive(Deserialize, Debug, Default, Encode, TreeHash, Clone,),
serde(deny_unknown_fields),
)
),
specific_variant_attributes(Electra(tree_hash(
struct_behaviour = "profile",
max_fields = "typenum::U8"
)))
)]
#[derive(Deserialize, Debug, Encode, TreeHash, Clone)]
#[serde(bound = "S: ConsensusSpec")]
#[serde(untagged)]
#[ssz(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent_stable")]
struct IndexedAttestation<S: ConsensusSpec> {
#[serde(with = "quoted_u64_var_list")]
#[superstruct(only(Base), partial_getter(rename = "attesting_indices_base"))]
Expand All @@ -299,13 +321,18 @@ impl<S: ConsensusSpec> Default for IndexedAttestation<S> {
variant_attributes(
derive(Deserialize, Debug, Encode, TreeHash, Clone,),
serde(deny_unknown_fields),
)
),
specific_variant_attributes(Electra(tree_hash(
struct_behaviour = "profile",
max_fields = "typenum::U8"
))),
//ref_attributes(derive(TreeHash), tree_hash(enum_behaviour = "transparent")),
)]
#[derive(Deserialize, Debug, Encode, TreeHash, Clone)]
#[serde(bound = "S: ConsensusSpec")]
#[serde(untagged)]
#[ssz(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent_stable")]
pub struct Attestation<S: ConsensusSpec> {
#[superstruct(only(Base), partial_getter(rename = "aggregation_bits_base"))]
aggregation_bits: BitList<S::MaxValidatorsPerCommitee>,
Expand Down Expand Up @@ -373,6 +400,7 @@ pub struct Eth1Data {
}

#[derive(Deserialize, Debug, Default, Encode, TreeHash, Clone)]
#[tree_hash(struct_behaviour = "profile", max_fields = "typenum::U16")]
pub struct ExecutionRequests<S: ConsensusSpec> {
deposits: VariableList<DepositRequest, S::MaxDepositRequests>,
withdrawals: VariableList<WithdrawalRequest, S::MaxWithdrawalRequests>,
Expand Down Expand Up @@ -429,7 +457,7 @@ pub struct Bootstrap<S: ConsensusSpec> {
only(Electra),
partial_getter(rename = "current_sync_committee_branch_electra")
)]
pub current_sync_committee_branch: FixedVector<B256, typenum::U6>,
pub current_sync_committee_branch: FixedVector<B256, typenum::U8>,
}

impl<S: ConsensusSpec> Bootstrap<S> {
Expand Down Expand Up @@ -546,7 +574,7 @@ pub struct LightClientHeader {
#[superstruct(only(Capella, Deneb, Electra))]
pub execution: ExecutionPayloadHeader,
#[superstruct(only(Capella, Deneb, Electra))]
pub execution_branch: FixedVector<B256, typenum::U4>,
pub execution_branch: FixedVector<B256, typenum::U7>,
}

impl Default for LightClientHeader {
Expand Down
82 changes: 82 additions & 0 deletions ethereum/consensus-core/src/types/serde_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,60 @@ pub mod u64 {
}
}

pub mod u64_opt {
use serde::{de::Error, Deserializer, Serializer};

pub fn serialize<S>(value: &Option<u64>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if let Some(value) = value {
serializer.serialize_str(&value.to_string())
} else {
serializer.serialize_none()
}
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
where
D: Deserializer<'de>,
{
let val: Option<String> = serde::Deserialize::deserialize(deserializer)?;
if let Some(n) = val {
Ok(Some(n.parse().map_err(D::Error::custom)?))
} else {
Ok(None)
}
}
}

pub mod u8_opt {
use serde::{de::Error, Deserializer, Serializer};

pub fn serialize<S>(value: &Option<u8>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if let Some(value) = value {
serializer.serialize_str(&value.to_string())
} else {
serializer.serialize_none()
}
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<u8>, D::Error>
where
D: Deserializer<'de>,
{
let val: Option<String> = serde::Deserialize::deserialize(deserializer)?;
if let Some(n) = val {
Ok(Some(n.parse().map_err(D::Error::custom)?))
} else {
Ok(None)
}
}
}

pub mod u256 {
use alloy::primitives::U256;
use serde::{de::Error, Deserializer, Serializer};
Expand All @@ -36,3 +90,31 @@ pub mod u256 {
val.parse().map_err(D::Error::custom)
}
}

pub mod u256_opt {
use alloy::primitives::U256;
use serde::{de::Error, Deserializer, Serializer};

pub fn serialize<S>(value: &Option<U256>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if let Some(value) = value {
serializer.serialize_str(&value.to_string())
} else {
serializer.serialize_none()
}
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<U256>, D::Error>
where
D: Deserializer<'de>,
{
let val: Option<String> = serde::Deserialize::deserialize(deserializer)?;
if let Some(n) = val {
Ok(Some(n.parse().map_err(D::Error::custom)?))
} else {
Ok(None)
}
}
}
Loading