mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-19 22:08:30 +00:00
Fix consensus, SSZ, tree hash & run merge EF tests (#2622)
* Update to v1.1.0-beta.4 (squash of #2548) * SSZ, cached tree hash, EF tests
This commit is contained in:
committed by
Paul Hauner
parent
5687c56d51
commit
cce855f9ea
@@ -101,9 +101,13 @@ impl<T: EthSpec> BeaconBlock<T> {
|
||||
/// Usually it's better to prefer `from_ssz_bytes` which will decode the correct variant based
|
||||
/// on the fork slot.
|
||||
pub fn any_from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
|
||||
BeaconBlockAltair::from_ssz_bytes(bytes)
|
||||
.map(BeaconBlock::Altair)
|
||||
.or_else(|_| BeaconBlockBase::from_ssz_bytes(bytes).map(BeaconBlock::Base))
|
||||
BeaconBlockMerge::from_ssz_bytes(bytes)
|
||||
.map(BeaconBlock::Merge)
|
||||
.or_else(|_| {
|
||||
BeaconBlockAltair::from_ssz_bytes(bytes)
|
||||
.map(BeaconBlock::Altair)
|
||||
.or_else(|_| BeaconBlockBase::from_ssz_bytes(bytes).map(BeaconBlock::Base))
|
||||
})
|
||||
}
|
||||
|
||||
/// Convenience accessor for the `body` as a `BeaconBlockBodyRef`.
|
||||
|
||||
@@ -1684,7 +1684,8 @@ impl<T: EthSpec> CompareFields for BeaconState<T> {
|
||||
match (self, other) {
|
||||
(BeaconState::Base(x), BeaconState::Base(y)) => x.compare_fields(y),
|
||||
(BeaconState::Altair(x), BeaconState::Altair(y)) => x.compare_fields(y),
|
||||
_ => panic!("compare_fields: mismatched state variants"),
|
||||
(BeaconState::Merge(x), BeaconState::Merge(y)) => x.compare_fields(y),
|
||||
_ => panic!("compare_fields: mismatched state variants",),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,16 +341,26 @@ impl<T: EthSpec> BeaconTreeHashCacheInner<T> {
|
||||
)?;
|
||||
hasher.write(state.finalized_checkpoint().tree_hash_root().as_bytes())?;
|
||||
|
||||
// Inactivity & light-client sync committees
|
||||
if let BeaconState::Altair(ref state) = state {
|
||||
// Inactivity & light-client sync committees (Altair and later).
|
||||
if let Ok(inactivity_scores) = state.inactivity_scores() {
|
||||
hasher.write(
|
||||
self.inactivity_scores
|
||||
.recalculate_tree_hash_root(&state.inactivity_scores)?
|
||||
.recalculate_tree_hash_root(inactivity_scores)?
|
||||
.as_bytes(),
|
||||
)?;
|
||||
}
|
||||
|
||||
hasher.write(state.current_sync_committee.tree_hash_root().as_bytes())?;
|
||||
hasher.write(state.next_sync_committee.tree_hash_root().as_bytes())?;
|
||||
if let Ok(current_sync_committee) = state.current_sync_committee() {
|
||||
hasher.write(current_sync_committee.tree_hash_root().as_bytes())?;
|
||||
}
|
||||
|
||||
if let Ok(next_sync_committee) = state.next_sync_committee() {
|
||||
hasher.write(next_sync_committee.tree_hash_root().as_bytes())?;
|
||||
}
|
||||
|
||||
// Execution payload (merge and later).
|
||||
if let Ok(payload_header) = state.latest_execution_payload_header() {
|
||||
hasher.write(payload_header.tree_hash_root().as_bytes())?;
|
||||
}
|
||||
|
||||
let root = hasher.finish()?;
|
||||
|
||||
@@ -8,8 +8,15 @@ use tree_hash_derive::TreeHash;
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash)]
|
||||
#[ssz(enum_behaviour = "union")]
|
||||
#[tree_hash(enum_behaviour = "union")]
|
||||
#[serde(tag = "selector", content = "value")]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
pub enum Transaction<T: EthSpec> {
|
||||
OpaqueTransaction(VariableList<u8, T::MaxBytesPerOpaqueTransaction>),
|
||||
// FIXME(merge): renaming this enum variant to 0 is a bit of a hack...
|
||||
#[serde(rename = "0")]
|
||||
OpaqueTransaction(
|
||||
#[serde(with = "ssz_types::serde_utils::hex_var_list")]
|
||||
VariableList<u8, T::MaxBytesPerOpaqueTransaction>,
|
||||
),
|
||||
}
|
||||
|
||||
impl<T: EthSpec, I: SliceIndex<[u8]>> Index<I> for Transaction<T> {
|
||||
@@ -33,12 +40,13 @@ impl<T: EthSpec> From<VariableList<u8, T::MaxBytesPerOpaqueTransaction>> for Tra
|
||||
#[derive(
|
||||
Default, Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
|
||||
)]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
pub struct ExecutionPayload<T: EthSpec> {
|
||||
pub parent_hash: Hash256,
|
||||
pub coinbase: Address,
|
||||
pub state_root: Hash256,
|
||||
pub receipt_root: Hash256,
|
||||
#[serde(with = "serde_logs_bloom")]
|
||||
#[serde(with = "ssz_types::serde_utils::hex_fixed_vec")]
|
||||
pub logs_bloom: FixedVector<u8, T::BytesPerLogsBloom>,
|
||||
pub random: Hash256,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
@@ -51,7 +59,6 @@ pub struct ExecutionPayload<T: EthSpec> {
|
||||
pub timestamp: u64,
|
||||
pub base_fee_per_gas: Hash256,
|
||||
pub block_hash: Hash256,
|
||||
#[serde(with = "serde_transactions")]
|
||||
#[test_random(default)]
|
||||
pub transactions: VariableList<Transaction<T>, T::MaxTransactionsPerPayload>,
|
||||
}
|
||||
@@ -76,99 +83,3 @@ impl<T: EthSpec> ExecutionPayload<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes the `logs_bloom` field.
|
||||
pub mod serde_logs_bloom {
|
||||
use super::*;
|
||||
use eth2_serde_utils::hex::PrefixedHexVisitor;
|
||||
use serde::{Deserializer, Serializer};
|
||||
|
||||
pub fn serialize<S, U>(bytes: &FixedVector<u8, U>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
U: Unsigned,
|
||||
{
|
||||
let mut hex_string: String = "0x".to_string();
|
||||
hex_string.push_str(&hex::encode(&bytes[..]));
|
||||
|
||||
serializer.serialize_str(&hex_string)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D, U>(deserializer: D) -> Result<FixedVector<u8, U>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
U: Unsigned,
|
||||
{
|
||||
let vec = deserializer.deserialize_string(PrefixedHexVisitor)?;
|
||||
|
||||
FixedVector::new(vec)
|
||||
.map_err(|e| serde::de::Error::custom(format!("invalid logs bloom: {:?}", e)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes the `transactions` field.
|
||||
pub mod serde_transactions {
|
||||
use super::*;
|
||||
use eth2_serde_utils::hex;
|
||||
use serde::ser::SerializeSeq;
|
||||
use serde::{de, Deserializer, Serializer};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct ListOfBytesListVisitor<T: EthSpec> {
|
||||
_t: PhantomData<T>,
|
||||
}
|
||||
impl<'a, T> serde::de::Visitor<'a> for ListOfBytesListVisitor<T>
|
||||
where
|
||||
T: EthSpec,
|
||||
{
|
||||
type Value = VariableList<Transaction<T>, T::MaxTransactionsPerPayload>;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(formatter, "a list of 0x-prefixed byte lists")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: serde::de::SeqAccess<'a>,
|
||||
{
|
||||
let mut outer = VariableList::default();
|
||||
|
||||
while let Some(val) = seq.next_element::<String>()? {
|
||||
let inner_vec = hex::decode(&val).map_err(de::Error::custom)?;
|
||||
let inner = VariableList::new(inner_vec).map_err(|e| {
|
||||
serde::de::Error::custom(format!("invalid transaction: {:?}", e))
|
||||
})?;
|
||||
outer.push(inner.into()).map_err(|e| {
|
||||
serde::de::Error::custom(format!("too many transactions: {:?}", e))
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(outer)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize<S, T>(
|
||||
value: &VariableList<Transaction<T>, T::MaxTransactionsPerPayload>,
|
||||
serializer: S,
|
||||
) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
T: EthSpec,
|
||||
{
|
||||
let mut seq = serializer.serialize_seq(Some(value.len()))?;
|
||||
for val in value {
|
||||
seq.serialize_element(&hex::encode(&val[..]))?;
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D, T>(
|
||||
deserializer: D,
|
||||
) -> Result<VariableList<Transaction<T>, T::MaxTransactionsPerPayload>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
T: EthSpec,
|
||||
{
|
||||
deserializer.deserialize_any(ListOfBytesListVisitor { _t: PhantomData })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{execution_payload::serde_logs_bloom, test_utils::TestRandom, *};
|
||||
use crate::{test_utils::TestRandom, *};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -13,7 +13,7 @@ pub struct ExecutionPayloadHeader<T: EthSpec> {
|
||||
pub coinbase: Address,
|
||||
pub state_root: Hash256,
|
||||
pub receipt_root: Hash256,
|
||||
#[serde(with = "serde_logs_bloom")]
|
||||
#[serde(with = "ssz_types::serde_utils::hex_fixed_vec")]
|
||||
pub logs_bloom: FixedVector<u8, T::BytesPerLogsBloom>,
|
||||
pub random: Hash256,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
|
||||
@@ -15,7 +15,7 @@ pub enum ForkName {
|
||||
|
||||
impl ForkName {
|
||||
pub fn list_all() -> Vec<ForkName> {
|
||||
vec![ForkName::Base, ForkName::Altair]
|
||||
vec![ForkName::Base, ForkName::Altair, ForkName::Merge]
|
||||
}
|
||||
|
||||
/// Set the activation slots in the given `ChainSpec` so that the fork named by `self`
|
||||
|
||||
Reference in New Issue
Block a user