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
42 changes: 35 additions & 7 deletions crates/consensus/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ pub struct Header {
///
/// The beacon roots contract handles root storage, enhancing Ethereum's functionalities.
pub parent_beacon_block_root: Option<B256>,
/// The Keccak 256-bit hash of the root node of the trie structure populated with each
/// [EIP-7685] request in the block body.
///
/// [EIP-7685]: https://eips.ethereum.org/EIPS/eip-7685
pub requests_root: Option<B256>,
/// An arbitrary byte array containing data relevant to this block. This must be 32 bytes or
/// fewer; formally Hx.
pub extra_data: Bytes,
Expand Down Expand Up @@ -117,6 +122,7 @@ impl Default for Header {
blob_gas_used: None,
excess_blob_gas: None,
parent_beacon_block_root: None,
requests_root: None,
}
}
}
Expand Down Expand Up @@ -285,15 +291,22 @@ impl Header {
length += 1; // EMPTY LIST CODE
}

// Encode parent beacon block root length. If new fields are added, the above pattern will
// Encode parent beacon block root length.
if let Some(parent_beacon_block_root) = self.parent_beacon_block_root {
length += parent_beacon_block_root.length();
}

// Encode requests root length.
//
// If new fields are added, the above pattern will
// need to be repeated and placeholder length added. Otherwise, it's impossible to
// tell _which_ fields are missing. This is mainly relevant for contrived cases
// where a header is created at random, for example:
// * A header is created with a withdrawals root, but no base fee. Shanghai blocks are
// post-London, so this is technically not valid. However, a tool like proptest would
// generate a block like this.
if let Some(parent_beacon_block_root) = self.parent_beacon_block_root {
length += parent_beacon_block_root.length();
if let Some(requests_root) = self.requests_root {
length += requests_root.length();
Comment on lines +299 to +309
Copy link
Contributor

Choose a reason for hiding this comment

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

note: the hack in this comment is not needed in reth any more, the arbitrary impl was changed instead, we should copy it over so the encoding / decoding impl is more sensible

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will do

}

length
Expand Down Expand Up @@ -360,15 +373,22 @@ impl Encodable for Header {
out.put_u8(EMPTY_LIST_CODE);
}

// Encode parent beacon block root. If new fields are added, the above pattern will need to
// Encode parent beacon block root.
if let Some(ref parent_beacon_block_root) = self.parent_beacon_block_root {
parent_beacon_block_root.encode(out);
}

// Encode requests root.
//
// If new fields are added, the above pattern will need to
// be repeated and placeholders added. Otherwise, it's impossible to tell _which_
// fields are missing. This is mainly relevant for contrived cases where a header is
// created at random, for example:
// * A header is created with a withdrawals root, but no base fee. Shanghai blocks are
// post-London, so this is technically not valid. However, a tool like proptest would
// generate a block like this.
if let Some(ref parent_beacon_block_root) = self.parent_beacon_block_root {
parent_beacon_block_root.encode(out);
if let Some(ref requests_root) = self.requests_root {
requests_root.encode(out);
}
}

Expand Down Expand Up @@ -408,6 +428,7 @@ impl Decodable for Header {
blob_gas_used: None,
excess_blob_gas: None,
parent_beacon_block_root: None,
requests_root: None,
};

if started_len - buf.len() < rlp_head.payload_length {
Expand Down Expand Up @@ -444,7 +465,14 @@ impl Decodable for Header {
}
}

// Decode parent beacon block root. If new fields are added, the above pattern will need to
// Decode parent beacon block root.
if started_len - buf.len() < rlp_head.payload_length {
this.parent_beacon_block_root = Some(B256::decode(buf)?);
}

// Decode requests root.
//
// If new fields are added, the above pattern will need to
// be repeated and placeholders decoded. Otherwise, it's impossible to tell _which_
// fields are missing. This is mainly relevant for contrived cases where a header is
// created at random, for example:
Expand Down
8 changes: 7 additions & 1 deletion crates/rpc-types/src/eth/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,12 @@ pub struct Header {
with = "alloy_serde::num::u128_opt_via_ruint"
)]
pub excess_blob_gas: Option<u128>,
/// Parent beacon block root
/// EIP-4788 parent beacon block root
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_beacon_block_root: Option<B256>,
/// EIP-7685 requests root.
#[serde(skip_serializing_if = "Option::is_none")]
pub requests_root: Option<B256>,
}

impl Header {
Expand Down Expand Up @@ -620,6 +623,7 @@ mod tests {
blob_gas_used: None,
excess_blob_gas: None,
parent_beacon_block_root: None,
requests_root: None,
},
uncles: vec![B256::with_last_byte(17)],
transactions: vec![B256::with_last_byte(18)].into(),
Expand Down Expand Up @@ -662,6 +666,7 @@ mod tests {
blob_gas_used: None,
excess_blob_gas: None,
parent_beacon_block_root: None,
requests_root: None,
},
uncles: vec![],
transactions: BlockTransactions::Uncle,
Expand Down Expand Up @@ -704,6 +709,7 @@ mod tests {
blob_gas_used: None,
excess_blob_gas: None,
parent_beacon_block_root: None,
requests_root: None,
},
uncles: vec![B256::with_last_byte(17)],
transactions: vec![B256::with_last_byte(18)].into(),
Expand Down