mirror of
https://github.com/sigp/lighthouse.git
synced 2026-06-16 02:08:29 +00:00
Merge branch 'unstable' into superstruct-features
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
use crate::engines::ForkchoiceState;
|
||||
use crate::http::{
|
||||
ENGINE_FORKCHOICE_UPDATED_V1, ENGINE_FORKCHOICE_UPDATED_V2, ENGINE_FORKCHOICE_UPDATED_V3,
|
||||
ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V1, ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1,
|
||||
ENGINE_GET_PAYLOAD_V1, ENGINE_GET_PAYLOAD_V2, ENGINE_GET_PAYLOAD_V3, ENGINE_NEW_PAYLOAD_V1,
|
||||
ENGINE_NEW_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_V3,
|
||||
ENGINE_GET_CLIENT_VERSION_V1, ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V1,
|
||||
ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1, ENGINE_GET_PAYLOAD_V1, ENGINE_GET_PAYLOAD_V2,
|
||||
ENGINE_GET_PAYLOAD_V3, ENGINE_NEW_PAYLOAD_V1, ENGINE_NEW_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_V3,
|
||||
};
|
||||
use eth2::types::{
|
||||
BlobsBundle, SsePayloadAttributes, SsePayloadAttributesV1, SsePayloadAttributesV2,
|
||||
@@ -24,11 +24,11 @@ pub use types::{
|
||||
ExecutionPayloadRef, FixedVector, ForkName, Hash256, Transactions, Uint256, VariableList,
|
||||
Withdrawal, Withdrawals,
|
||||
};
|
||||
|
||||
use types::{
|
||||
ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadElectra, ExecutionPayloadMerge,
|
||||
ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadElectra, ExecutionPayloadBellatrix,
|
||||
FeatureName, KzgProofs,
|
||||
};
|
||||
use types::{Graffiti, GRAFFITI_BYTES_LEN};
|
||||
|
||||
pub mod auth;
|
||||
pub mod http;
|
||||
@@ -36,8 +36,8 @@ pub mod json_structures;
|
||||
mod new_payload_request;
|
||||
|
||||
pub use new_payload_request::{
|
||||
NewPayloadRequest, NewPayloadRequestCapella, NewPayloadRequestDeneb, NewPayloadRequestElectra,
|
||||
NewPayloadRequestMerge,
|
||||
NewPayloadRequest, NewPayloadRequestBellatrix, NewPayloadRequestCapella,
|
||||
NewPayloadRequestDeneb, NewPayloadRequestElectra,
|
||||
};
|
||||
|
||||
pub const LATEST_TAG: &str = "latest";
|
||||
@@ -61,13 +61,13 @@ pub enum Error {
|
||||
ParentHashEqualsBlockHash(ExecutionBlockHash),
|
||||
PayloadIdUnavailable,
|
||||
TransitionConfigurationMismatch,
|
||||
PayloadConversionLogicFlaw,
|
||||
SszError(ssz_types::Error),
|
||||
DeserializeWithdrawals(ssz_types::Error),
|
||||
BuilderApi(builder_client::Error),
|
||||
IncorrectStateVariant,
|
||||
RequiredMethodUnsupported(&'static str),
|
||||
UnsupportedForkVariant(String),
|
||||
InvalidClientVersion(String),
|
||||
RlpDecoderError(rlp::DecoderError),
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ pub struct ExecutionBlock {
|
||||
|
||||
/// Representation of an execution block with enough detail to reconstruct a payload.
|
||||
#[superstruct(
|
||||
feature(Merge),
|
||||
feature(Bellatrix),
|
||||
variants_and_features_from = "FORK_ORDER",
|
||||
feature_dependencies = "FEATURE_DEPENDENCIES",
|
||||
variant_type(name = "ForkName", getter = "fork_name"),
|
||||
@@ -212,26 +212,28 @@ impl<E: EthSpec> TryFrom<ExecutionPayload<E>> for ExecutionBlockWithTransactions
|
||||
|
||||
fn try_from(payload: ExecutionPayload<E>) -> Result<Self, Error> {
|
||||
let json_payload = match payload {
|
||||
ExecutionPayload::Merge(block) => Self::Merge(ExecutionBlockWithTransactionsMerge {
|
||||
parent_hash: block.parent_hash,
|
||||
fee_recipient: block.fee_recipient,
|
||||
state_root: block.state_root,
|
||||
receipts_root: block.receipts_root,
|
||||
logs_bloom: block.logs_bloom,
|
||||
prev_randao: block.prev_randao,
|
||||
block_number: block.block_number,
|
||||
gas_limit: block.gas_limit,
|
||||
gas_used: block.gas_used,
|
||||
timestamp: block.timestamp,
|
||||
extra_data: block.extra_data,
|
||||
base_fee_per_gas: block.base_fee_per_gas,
|
||||
block_hash: block.block_hash,
|
||||
transactions: block
|
||||
.transactions
|
||||
.iter()
|
||||
.map(|tx| Transaction::decode(&Rlp::new(tx)))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
}),
|
||||
ExecutionPayload::Bellatrix(block) => {
|
||||
Self::Bellatrix(ExecutionBlockWithTransactionsBellatrix {
|
||||
parent_hash: block.parent_hash,
|
||||
fee_recipient: block.fee_recipient,
|
||||
state_root: block.state_root,
|
||||
receipts_root: block.receipts_root,
|
||||
logs_bloom: block.logs_bloom,
|
||||
prev_randao: block.prev_randao,
|
||||
block_number: block.block_number,
|
||||
gas_limit: block.gas_limit,
|
||||
gas_used: block.gas_used,
|
||||
timestamp: block.timestamp,
|
||||
extra_data: block.extra_data,
|
||||
base_fee_per_gas: block.base_fee_per_gas,
|
||||
block_hash: block.block_hash,
|
||||
transactions: block
|
||||
.transactions
|
||||
.iter()
|
||||
.map(|tx| Transaction::decode(&Rlp::new(tx)))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
})
|
||||
}
|
||||
ExecutionPayload::Capella(block) => {
|
||||
Self::Capella(ExecutionBlockWithTransactionsCapella {
|
||||
parent_hash: block.parent_hash,
|
||||
@@ -431,7 +433,7 @@ pub struct ProposeBlindedBlockResponse {
|
||||
}
|
||||
|
||||
#[superstruct(
|
||||
feature(Merge),
|
||||
feature(Bellatrix),
|
||||
variants_and_features_from = "FORK_ORDER",
|
||||
feature_dependencies = "FEATURE_DEPENDENCIES",
|
||||
variant_type(name = "ForkName", getter = "fork_name"),
|
||||
@@ -448,8 +450,11 @@ pub struct ProposeBlindedBlockResponse {
|
||||
)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct GetPayloadResponse<E: EthSpec> {
|
||||
#[superstruct(only(Merge), partial_getter(rename = "execution_payload_merge"))]
|
||||
pub execution_payload: ExecutionPayloadMerge<E>,
|
||||
#[superstruct(
|
||||
only(Bellatrix),
|
||||
partial_getter(rename = "execution_payload_bellatrix")
|
||||
)]
|
||||
pub execution_payload: ExecutionPayloadBellatrix<E>,
|
||||
#[superstruct(only(Capella), partial_getter(rename = "execution_payload_capella"))]
|
||||
pub execution_payload: ExecutionPayloadCapella<E>,
|
||||
#[superstruct(only(Deneb), partial_getter(rename = "execution_payload_deneb"))]
|
||||
@@ -498,8 +503,8 @@ impl<E: EthSpec> From<GetPayloadResponse<E>>
|
||||
{
|
||||
fn from(response: GetPayloadResponse<E>) -> Self {
|
||||
match response {
|
||||
GetPayloadResponse::Merge(inner) => (
|
||||
ExecutionPayload::Merge(inner.execution_payload),
|
||||
GetPayloadResponse::Bellatrix(inner) => (
|
||||
ExecutionPayload::Bellatrix(inner.execution_payload),
|
||||
inner.block_value,
|
||||
None,
|
||||
),
|
||||
@@ -545,14 +550,14 @@ impl<E: EthSpec> ExecutionPayloadBodyV1<E> {
|
||||
header: ExecutionPayloadHeader<E>,
|
||||
) -> Result<ExecutionPayload<E>, String> {
|
||||
match header {
|
||||
ExecutionPayloadHeader::Merge(header) => {
|
||||
ExecutionPayloadHeader::Bellatrix(header) => {
|
||||
if self.withdrawals.is_some() {
|
||||
return Err(format!(
|
||||
"block {} is merge but payload body has withdrawals",
|
||||
header.block_hash
|
||||
));
|
||||
}
|
||||
Ok(ExecutionPayload::Merge(ExecutionPayloadMerge {
|
||||
Ok(ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix {
|
||||
parent_hash: header.parent_hash,
|
||||
fee_recipient: header.fee_recipient,
|
||||
state_root: header.state_root,
|
||||
@@ -643,6 +648,9 @@ impl<E: EthSpec> ExecutionPayloadBodyV1<E> {
|
||||
withdrawals,
|
||||
blob_gas_used: header.blob_gas_used,
|
||||
excess_blob_gas: header.excess_blob_gas,
|
||||
// TODO(electra)
|
||||
deposit_receipts: <_>::default(),
|
||||
withdrawal_requests: <_>::default(),
|
||||
}))
|
||||
} else {
|
||||
Err(format!(
|
||||
@@ -668,6 +676,7 @@ pub struct EngineCapabilities {
|
||||
pub get_payload_v1: bool,
|
||||
pub get_payload_v2: bool,
|
||||
pub get_payload_v3: bool,
|
||||
pub get_client_version_v1: bool,
|
||||
}
|
||||
|
||||
impl EngineCapabilities {
|
||||
@@ -706,7 +715,141 @@ impl EngineCapabilities {
|
||||
if self.get_payload_v3 {
|
||||
response.push(ENGINE_GET_PAYLOAD_V3);
|
||||
}
|
||||
if self.get_client_version_v1 {
|
||||
response.push(ENGINE_GET_CLIENT_VERSION_V1);
|
||||
}
|
||||
|
||||
response
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum ClientCode {
|
||||
Besu,
|
||||
EtherumJS,
|
||||
Erigon,
|
||||
GoEthereum,
|
||||
Grandine,
|
||||
Lighthouse,
|
||||
Lodestar,
|
||||
Nethermind,
|
||||
Nimbus,
|
||||
Teku,
|
||||
Prysm,
|
||||
Reth,
|
||||
Unknown(String),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ClientCode {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let s = match self {
|
||||
ClientCode::Besu => "BU",
|
||||
ClientCode::EtherumJS => "EJ",
|
||||
ClientCode::Erigon => "EG",
|
||||
ClientCode::GoEthereum => "GE",
|
||||
ClientCode::Grandine => "GR",
|
||||
ClientCode::Lighthouse => "LH",
|
||||
ClientCode::Lodestar => "LS",
|
||||
ClientCode::Nethermind => "NM",
|
||||
ClientCode::Nimbus => "NB",
|
||||
ClientCode::Teku => "TK",
|
||||
ClientCode::Prysm => "PM",
|
||||
ClientCode::Reth => "RH",
|
||||
ClientCode::Unknown(code) => code,
|
||||
};
|
||||
write!(f, "{}", s)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for ClientCode {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(code: String) -> Result<Self, Self::Error> {
|
||||
match code.as_str() {
|
||||
"BU" => Ok(Self::Besu),
|
||||
"EJ" => Ok(Self::EtherumJS),
|
||||
"EG" => Ok(Self::Erigon),
|
||||
"GE" => Ok(Self::GoEthereum),
|
||||
"GR" => Ok(Self::Grandine),
|
||||
"LH" => Ok(Self::Lighthouse),
|
||||
"LS" => Ok(Self::Lodestar),
|
||||
"NM" => Ok(Self::Nethermind),
|
||||
"NB" => Ok(Self::Nimbus),
|
||||
"TK" => Ok(Self::Teku),
|
||||
"PM" => Ok(Self::Prysm),
|
||||
"RH" => Ok(Self::Reth),
|
||||
string => {
|
||||
if string.len() == 2 {
|
||||
Ok(Self::Unknown(code))
|
||||
} else {
|
||||
Err(format!("Invalid client code: {}", code))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CommitPrefix(pub String);
|
||||
|
||||
impl TryFrom<String> for CommitPrefix {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
// Check if the input starts with '0x' and strip it if it does
|
||||
let commit_prefix = value.strip_prefix("0x").unwrap_or(&value);
|
||||
|
||||
// Ensure length is exactly 8 characters after '0x' removal
|
||||
if commit_prefix.len() != 8 {
|
||||
return Err(
|
||||
"Input must be exactly 8 characters long (excluding any '0x' prefix)".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
// Ensure all characters are valid hex digits
|
||||
if commit_prefix.chars().all(|c| c.is_ascii_hexdigit()) {
|
||||
Ok(CommitPrefix(commit_prefix.to_lowercase()))
|
||||
} else {
|
||||
Err("Input must contain only hexadecimal characters".to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for CommitPrefix {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ClientVersionV1 {
|
||||
pub code: ClientCode,
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub commit: CommitPrefix,
|
||||
}
|
||||
|
||||
impl ClientVersionV1 {
|
||||
pub fn calculate_graffiti(&self, lighthouse_commit_prefix: CommitPrefix) -> Graffiti {
|
||||
let graffiti_string = format!(
|
||||
"{}{}LH{}",
|
||||
self.code,
|
||||
self.commit
|
||||
.0
|
||||
.get(..4)
|
||||
.map_or_else(|| self.commit.0.as_str(), |s| s)
|
||||
.to_lowercase(),
|
||||
lighthouse_commit_prefix
|
||||
.0
|
||||
.get(..4)
|
||||
.unwrap_or("0000")
|
||||
.to_lowercase(),
|
||||
);
|
||||
let mut graffiti_bytes = [0u8; GRAFFITI_BYTES_LEN];
|
||||
let bytes_to_copy = std::cmp::min(graffiti_string.len(), GRAFFITI_BYTES_LEN);
|
||||
graffiti_bytes[..bytes_to_copy]
|
||||
.copy_from_slice(&graffiti_string.as_bytes()[..bytes_to_copy]);
|
||||
|
||||
Graffiti::from(graffiti_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user