Skip to content

Commit 0c0fdbf

Browse files
michaelsproulpaulhauner
authored andcommitted
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
1 parent 8b56004 commit 0c0fdbf

File tree

21 files changed

+282
-186
lines changed

21 files changed

+282
-186
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use crate::FixedVector;
2+
use eth2_serde_utils::hex::{self, PrefixedHexVisitor};
3+
use serde::{Deserializer, Serializer};
4+
use typenum::Unsigned;
5+
6+
pub fn serialize<S, U>(bytes: &FixedVector<u8, U>, serializer: S) -> Result<S::Ok, S::Error>
7+
where
8+
S: Serializer,
9+
U: Unsigned,
10+
{
11+
let mut hex_string: String = "0x".to_string();
12+
hex_string.push_str(&hex::encode(&bytes[..]));
13+
14+
serializer.serialize_str(&hex_string)
15+
}
16+
17+
pub fn deserialize<'de, D, U>(deserializer: D) -> Result<FixedVector<u8, U>, D::Error>
18+
where
19+
D: Deserializer<'de>,
20+
U: Unsigned,
21+
{
22+
let vec = deserializer.deserialize_string(PrefixedHexVisitor)?;
23+
FixedVector::new(vec)
24+
.map_err(|e| serde::de::Error::custom(format!("invalid fixed vector: {:?}", e)))
25+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! Serialize `VariableList<u8, N>` as 0x-prefixed hex string.
2+
use crate::VariableList;
3+
use eth2_serde_utils::hex::{self, PrefixedHexVisitor};
4+
use serde::{Deserializer, Serializer};
5+
use typenum::Unsigned;
6+
7+
pub fn serialize<S, N>(bytes: &VariableList<u8, N>, serializer: S) -> Result<S::Ok, S::Error>
8+
where
9+
S: Serializer,
10+
N: Unsigned,
11+
{
12+
let mut hex_string: String = "0x".to_string();
13+
hex_string.push_str(&hex::encode(&**bytes));
14+
15+
serializer.serialize_str(&hex_string)
16+
}
17+
18+
pub fn deserialize<'de, D, N>(deserializer: D) -> Result<VariableList<u8, N>, D::Error>
19+
where
20+
D: Deserializer<'de>,
21+
N: Unsigned,
22+
{
23+
let bytes = deserializer.deserialize_str(PrefixedHexVisitor)?;
24+
VariableList::new(bytes)
25+
.map_err(|e| serde::de::Error::custom(format!("invalid variable list: {:?}", e)))
26+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
pub mod hex_fixed_vec;
2+
pub mod hex_var_list;
13
pub mod quoted_u64_fixed_vec;
24
pub mod quoted_u64_var_list;

consensus/state_processing/src/per_block_processing.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,18 +139,22 @@ pub fn per_block_processing<T: EthSpec>(
139139
process_eth1_data(state, block.body().eth1_data())?;
140140
process_operations(state, block.body(), proposer_index, verify_signatures, spec)?;
141141

142-
if let BeaconBlockRef::Altair(inner) = block {
142+
if let Some(sync_aggregate) = block.body().sync_aggregate() {
143143
process_sync_aggregate(
144144
state,
145-
&inner.body.sync_aggregate,
145+
sync_aggregate,
146146
proposer_index,
147147
verify_signatures,
148148
spec,
149149
)?;
150150
}
151151

152152
if is_execution_enabled(state, block.body()) {
153-
process_execution_payload(state, block.body().execution_payload().unwrap(), spec)?
153+
let payload = block
154+
.body()
155+
.execution_payload()
156+
.ok_or(BlockProcessingError::IncorrectStateType)?;
157+
process_execution_payload(state, payload, spec)?;
154158
}
155159

156160
Ok(())

consensus/state_processing/src/per_block_processing/errors.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub enum BlockProcessingError {
7777
expected: u64,
7878
found: u64,
7979
},
80+
ExecutionInvalid,
8081
}
8182

8283
impl From<BeaconStateError> for BlockProcessingError {

consensus/state_processing/src/per_block_processing/process_operations.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -353,15 +353,15 @@ pub fn process_deposit<T: EthSpec>(
353353
state.validators_mut().push(validator)?;
354354
state.balances_mut().push(deposit.data.amount)?;
355355

356-
// Altair-specific initializations.
357-
if let BeaconState::Altair(altair_state) = state {
358-
altair_state
359-
.previous_epoch_participation
360-
.push(ParticipationFlags::default())?;
361-
altair_state
362-
.current_epoch_participation
363-
.push(ParticipationFlags::default())?;
364-
altair_state.inactivity_scores.push(0)?;
356+
// Altair or later initializations.
357+
if let Ok(previous_epoch_participation) = state.previous_epoch_participation_mut() {
358+
previous_epoch_participation.push(ParticipationFlags::default())?;
359+
}
360+
if let Ok(current_epoch_participation) = state.current_epoch_participation_mut() {
361+
current_epoch_participation.push(ParticipationFlags::default())?;
362+
}
363+
if let Ok(inactivity_scores) = state.inactivity_scores_mut() {
364+
inactivity_scores.push(0)?;
365365
}
366366
}
367367

consensus/types/src/beacon_block.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,13 @@ impl<T: EthSpec> BeaconBlock<T> {
101101
/// Usually it's better to prefer `from_ssz_bytes` which will decode the correct variant based
102102
/// on the fork slot.
103103
pub fn any_from_ssz_bytes(bytes: &[u8]) -> Result<Self, ssz::DecodeError> {
104-
BeaconBlockAltair::from_ssz_bytes(bytes)
105-
.map(BeaconBlock::Altair)
106-
.or_else(|_| BeaconBlockBase::from_ssz_bytes(bytes).map(BeaconBlock::Base))
104+
BeaconBlockMerge::from_ssz_bytes(bytes)
105+
.map(BeaconBlock::Merge)
106+
.or_else(|_| {
107+
BeaconBlockAltair::from_ssz_bytes(bytes)
108+
.map(BeaconBlock::Altair)
109+
.or_else(|_| BeaconBlockBase::from_ssz_bytes(bytes).map(BeaconBlock::Base))
110+
})
107111
}
108112

109113
/// Convenience accessor for the `body` as a `BeaconBlockBodyRef`.

consensus/types/src/beacon_state.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1684,7 +1684,8 @@ impl<T: EthSpec> CompareFields for BeaconState<T> {
16841684
match (self, other) {
16851685
(BeaconState::Base(x), BeaconState::Base(y)) => x.compare_fields(y),
16861686
(BeaconState::Altair(x), BeaconState::Altair(y)) => x.compare_fields(y),
1687-
_ => panic!("compare_fields: mismatched state variants"),
1687+
(BeaconState::Merge(x), BeaconState::Merge(y)) => x.compare_fields(y),
1688+
_ => panic!("compare_fields: mismatched state variants",),
16881689
}
16891690
}
16901691
}

consensus/types/src/beacon_state/tree_hash_cache.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -341,16 +341,26 @@ impl<T: EthSpec> BeaconTreeHashCacheInner<T> {
341341
)?;
342342
hasher.write(state.finalized_checkpoint().tree_hash_root().as_bytes())?;
343343

344-
// Inactivity & light-client sync committees
345-
if let BeaconState::Altair(ref state) = state {
344+
// Inactivity & light-client sync committees (Altair and later).
345+
if let Ok(inactivity_scores) = state.inactivity_scores() {
346346
hasher.write(
347347
self.inactivity_scores
348-
.recalculate_tree_hash_root(&state.inactivity_scores)?
348+
.recalculate_tree_hash_root(inactivity_scores)?
349349
.as_bytes(),
350350
)?;
351+
}
352+
353+
if let Ok(current_sync_committee) = state.current_sync_committee() {
354+
hasher.write(current_sync_committee.tree_hash_root().as_bytes())?;
355+
}
356+
357+
if let Ok(next_sync_committee) = state.next_sync_committee() {
358+
hasher.write(next_sync_committee.tree_hash_root().as_bytes())?;
359+
}
351360

352-
hasher.write(state.current_sync_committee.tree_hash_root().as_bytes())?;
353-
hasher.write(state.next_sync_committee.tree_hash_root().as_bytes())?;
361+
// Execution payload (merge and later).
362+
if let Ok(payload_header) = state.latest_execution_payload_header() {
363+
hasher.write(payload_header.tree_hash_root().as_bytes())?;
354364
}
355365

356366
let root = hasher.finish()?;

consensus/types/src/execution_payload.rs

Lines changed: 10 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,15 @@ use tree_hash_derive::TreeHash;
88
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash)]
99
#[ssz(enum_behaviour = "union")]
1010
#[tree_hash(enum_behaviour = "union")]
11+
#[serde(tag = "selector", content = "value")]
12+
#[serde(bound = "T: EthSpec")]
1113
pub enum Transaction<T: EthSpec> {
12-
OpaqueTransaction(VariableList<u8, T::MaxBytesPerOpaqueTransaction>),
14+
// FIXME(merge): renaming this enum variant to 0 is a bit of a hack...
15+
#[serde(rename = "0")]
16+
OpaqueTransaction(
17+
#[serde(with = "ssz_types::serde_utils::hex_var_list")]
18+
VariableList<u8, T::MaxBytesPerOpaqueTransaction>,
19+
),
1320
}
1421

1522
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
3340
#[derive(
3441
Default, Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
3542
)]
43+
#[serde(bound = "T: EthSpec")]
3644
pub struct ExecutionPayload<T: EthSpec> {
3745
pub parent_hash: Hash256,
3846
pub coinbase: Address,
3947
pub state_root: Hash256,
4048
pub receipt_root: Hash256,
41-
#[serde(with = "serde_logs_bloom")]
49+
#[serde(with = "ssz_types::serde_utils::hex_fixed_vec")]
4250
pub logs_bloom: FixedVector<u8, T::BytesPerLogsBloom>,
4351
pub random: Hash256,
4452
#[serde(with = "eth2_serde_utils::quoted_u64")]
@@ -51,7 +59,6 @@ pub struct ExecutionPayload<T: EthSpec> {
5159
pub timestamp: u64,
5260
pub base_fee_per_gas: Hash256,
5361
pub block_hash: Hash256,
54-
#[serde(with = "serde_transactions")]
5562
#[test_random(default)]
5663
pub transactions: VariableList<Transaction<T>, T::MaxTransactionsPerPayload>,
5764
}
@@ -76,99 +83,3 @@ impl<T: EthSpec> ExecutionPayload<T> {
7683
}
7784
}
7885
}
79-
80-
/// Serializes the `logs_bloom` field.
81-
pub mod serde_logs_bloom {
82-
use super::*;
83-
use eth2_serde_utils::hex::PrefixedHexVisitor;
84-
use serde::{Deserializer, Serializer};
85-
86-
pub fn serialize<S, U>(bytes: &FixedVector<u8, U>, serializer: S) -> Result<S::Ok, S::Error>
87-
where
88-
S: Serializer,
89-
U: Unsigned,
90-
{
91-
let mut hex_string: String = "0x".to_string();
92-
hex_string.push_str(&hex::encode(&bytes[..]));
93-
94-
serializer.serialize_str(&hex_string)
95-
}
96-
97-
pub fn deserialize<'de, D, U>(deserializer: D) -> Result<FixedVector<u8, U>, D::Error>
98-
where
99-
D: Deserializer<'de>,
100-
U: Unsigned,
101-
{
102-
let vec = deserializer.deserialize_string(PrefixedHexVisitor)?;
103-
104-
FixedVector::new(vec)
105-
.map_err(|e| serde::de::Error::custom(format!("invalid logs bloom: {:?}", e)))
106-
}
107-
}
108-
109-
/// Serializes the `transactions` field.
110-
pub mod serde_transactions {
111-
use super::*;
112-
use eth2_serde_utils::hex;
113-
use serde::ser::SerializeSeq;
114-
use serde::{de, Deserializer, Serializer};
115-
use std::marker::PhantomData;
116-
117-
pub struct ListOfBytesListVisitor<T: EthSpec> {
118-
_t: PhantomData<T>,
119-
}
120-
impl<'a, T> serde::de::Visitor<'a> for ListOfBytesListVisitor<T>
121-
where
122-
T: EthSpec,
123-
{
124-
type Value = VariableList<Transaction<T>, T::MaxTransactionsPerPayload>;
125-
126-
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
127-
write!(formatter, "a list of 0x-prefixed byte lists")
128-
}
129-
130-
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
131-
where
132-
A: serde::de::SeqAccess<'a>,
133-
{
134-
let mut outer = VariableList::default();
135-
136-
while let Some(val) = seq.next_element::<String>()? {
137-
let inner_vec = hex::decode(&val).map_err(de::Error::custom)?;
138-
let inner = VariableList::new(inner_vec).map_err(|e| {
139-
serde::de::Error::custom(format!("invalid transaction: {:?}", e))
140-
})?;
141-
outer.push(inner.into()).map_err(|e| {
142-
serde::de::Error::custom(format!("too many transactions: {:?}", e))
143-
})?;
144-
}
145-
146-
Ok(outer)
147-
}
148-
}
149-
150-
pub fn serialize<S, T>(
151-
value: &VariableList<Transaction<T>, T::MaxTransactionsPerPayload>,
152-
serializer: S,
153-
) -> Result<S::Ok, S::Error>
154-
where
155-
S: Serializer,
156-
T: EthSpec,
157-
{
158-
let mut seq = serializer.serialize_seq(Some(value.len()))?;
159-
for val in value {
160-
seq.serialize_element(&hex::encode(&val[..]))?;
161-
}
162-
seq.end()
163-
}
164-
165-
pub fn deserialize<'de, D, T>(
166-
deserializer: D,
167-
) -> Result<VariableList<Transaction<T>, T::MaxTransactionsPerPayload>, D::Error>
168-
where
169-
D: Deserializer<'de>,
170-
T: EthSpec,
171-
{
172-
deserializer.deserialize_any(ListOfBytesListVisitor { _t: PhantomData })
173-
}
174-
}

0 commit comments

Comments
 (0)