mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 00:42:42 +00:00
Merge remote-tracking branch 'origin/unstable' into tree-states
This commit is contained in:
@@ -19,19 +19,16 @@ pub fn compare_fields_derive(input: TokenStream) -> TokenStream {
|
||||
let name = &item.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = &item.generics.split_for_impl();
|
||||
|
||||
let struct_data = match &item.data {
|
||||
syn::Data::Struct(s) => s,
|
||||
_ => panic!("compare_fields_derive only supports structs."),
|
||||
let syn::Data::Struct(struct_data) = &item.data else {
|
||||
panic!("compare_fields_derive only supports structs.");
|
||||
};
|
||||
|
||||
let mut quotes = vec![];
|
||||
|
||||
for field in struct_data.fields.iter() {
|
||||
let ident_a = match &field.ident {
|
||||
Some(ref ident) => ident,
|
||||
_ => panic!("compare_fields_derive only supports named struct fields."),
|
||||
let Some(ident_a) = &field.ident else {
|
||||
panic!("compare_fields_derive only supports named struct fields.");
|
||||
};
|
||||
|
||||
let field_name = ident_a.to_string();
|
||||
let ident_b = ident_a.clone();
|
||||
|
||||
|
||||
@@ -38,8 +38,12 @@ use store::fork_versioned_response::ExecutionOptimisticFinalizedForkVersionedRes
|
||||
|
||||
pub const V1: EndpointVersion = EndpointVersion(1);
|
||||
pub const V2: EndpointVersion = EndpointVersion(2);
|
||||
pub const V3: EndpointVersion = EndpointVersion(3);
|
||||
|
||||
pub const CONSENSUS_VERSION_HEADER: &str = "Eth-Consensus-Version";
|
||||
pub const EXECUTION_PAYLOAD_BLINDED_HEADER: &str = "Eth-Execution-Payload-Blinded";
|
||||
pub const EXECUTION_PAYLOAD_VALUE_HEADER: &str = "Eth-Execution-Payload-Value";
|
||||
pub const CONSENSUS_BLOCK_VALUE_HEADER: &str = "Eth-Consensus-Block-Value";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
@@ -268,6 +272,31 @@ impl BeaconNodeHttpClient {
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform a HTTP GET request using an 'accept' header, returning `None` on a 404 error.
|
||||
pub async fn get_bytes_response_with_response_headers<U: IntoUrl>(
|
||||
&self,
|
||||
url: U,
|
||||
accept_header: Accept,
|
||||
timeout: Duration,
|
||||
) -> Result<(Option<Vec<u8>>, Option<HeaderMap>), Error> {
|
||||
let opt_response = self
|
||||
.get_response(url, |b| b.accept(accept_header).timeout(timeout))
|
||||
.await
|
||||
.optional()?;
|
||||
|
||||
// let headers = opt_response.headers();
|
||||
match opt_response {
|
||||
Some(resp) => {
|
||||
let response_headers = resp.headers().clone();
|
||||
Ok((
|
||||
Some(resp.bytes().await?.into_iter().collect::<Vec<_>>()),
|
||||
Some(response_headers),
|
||||
))
|
||||
}
|
||||
None => Ok((None, None)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform a HTTP POST request.
|
||||
async fn post<T: Serialize, U: IntoUrl>(&self, url: U, body: &T) -> Result<(), Error> {
|
||||
self.post_generic(url, body, None).await?;
|
||||
@@ -916,9 +945,8 @@ impl BeaconNodeHttpClient {
|
||||
Error,
|
||||
> {
|
||||
let path = self.get_beacon_blocks_path(block_id)?;
|
||||
let response = match self.get_response(path, |b| b).await.optional()? {
|
||||
Some(res) => res,
|
||||
None => return Ok(None),
|
||||
let Some(response) = self.get_response(path, |b| b).await.optional()? else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
Ok(Some(response.json().await?))
|
||||
@@ -932,9 +960,8 @@ impl BeaconNodeHttpClient {
|
||||
block_id: BlockId,
|
||||
) -> Result<Option<GenericResponse<BlobSidecarList<T>>>, Error> {
|
||||
let path = self.get_blobs_path(block_id)?;
|
||||
let response = match self.get_response(path, |b| b).await.optional()? {
|
||||
Some(res) => res,
|
||||
None => return Ok(None),
|
||||
let Some(response) = self.get_response(path, |b| b).await.optional()? else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
Ok(Some(response.json().await?))
|
||||
@@ -951,9 +978,8 @@ impl BeaconNodeHttpClient {
|
||||
Error,
|
||||
> {
|
||||
let path = self.get_beacon_blinded_blocks_path(block_id)?;
|
||||
let response = match self.get_response(path, |b| b).await.optional()? {
|
||||
Some(res) => res,
|
||||
None => return Ok(None),
|
||||
let Some(response) = self.get_response(path, |b| b).await.optional()? else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
Ok(Some(response.json().await?))
|
||||
@@ -1631,6 +1657,26 @@ impl BeaconNodeHttpClient {
|
||||
.await
|
||||
}
|
||||
|
||||
/// `GET v2/validator/blocks/{slot}`
|
||||
pub async fn get_validator_blocks_modular<T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
&self,
|
||||
slot: Slot,
|
||||
randao_reveal: &SignatureBytes,
|
||||
graffiti: Option<&Graffiti>,
|
||||
skip_randao_verification: SkipRandaoVerification,
|
||||
) -> Result<ForkVersionedResponse<BlockContents<T, Payload>>, Error> {
|
||||
let path = self
|
||||
.get_validator_blocks_path::<T, Payload>(
|
||||
slot,
|
||||
randao_reveal,
|
||||
graffiti,
|
||||
skip_randao_verification,
|
||||
)
|
||||
.await?;
|
||||
|
||||
self.get(path).await
|
||||
}
|
||||
|
||||
/// returns `GET v2/validator/blocks/{slot}` URL path
|
||||
pub async fn get_validator_blocks_path<T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
&self,
|
||||
@@ -1663,16 +1709,64 @@ impl BeaconNodeHttpClient {
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
/// `GET v2/validator/blocks/{slot}`
|
||||
pub async fn get_validator_blocks_modular<T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
/// returns `GET v3/validator/blocks/{slot}` URL path
|
||||
pub async fn get_validator_blocks_v3_path<T: EthSpec>(
|
||||
&self,
|
||||
slot: Slot,
|
||||
randao_reveal: &SignatureBytes,
|
||||
graffiti: Option<&Graffiti>,
|
||||
skip_randao_verification: SkipRandaoVerification,
|
||||
) -> Result<ForkVersionedResponse<BlockContents<T, Payload>>, Error> {
|
||||
) -> Result<Url, Error> {
|
||||
let mut path = self.eth_path(V3)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("validator")
|
||||
.push("blocks")
|
||||
.push(&slot.to_string());
|
||||
|
||||
path.query_pairs_mut()
|
||||
.append_pair("randao_reveal", &randao_reveal.to_string());
|
||||
|
||||
if let Some(graffiti) = graffiti {
|
||||
path.query_pairs_mut()
|
||||
.append_pair("graffiti", &graffiti.to_string());
|
||||
}
|
||||
|
||||
if skip_randao_verification == SkipRandaoVerification::Yes {
|
||||
path.query_pairs_mut()
|
||||
.append_pair("skip_randao_verification", "");
|
||||
}
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
/// `GET v3/validator/blocks/{slot}`
|
||||
pub async fn get_validator_blocks_v3<T: EthSpec>(
|
||||
&self,
|
||||
slot: Slot,
|
||||
randao_reveal: &SignatureBytes,
|
||||
graffiti: Option<&Graffiti>,
|
||||
) -> Result<ForkVersionedBeaconBlockType<T>, Error> {
|
||||
self.get_validator_blocks_v3_modular(
|
||||
slot,
|
||||
randao_reveal,
|
||||
graffiti,
|
||||
SkipRandaoVerification::No,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// `GET v3/validator/blocks/{slot}`
|
||||
pub async fn get_validator_blocks_v3_modular<T: EthSpec>(
|
||||
&self,
|
||||
slot: Slot,
|
||||
randao_reveal: &SignatureBytes,
|
||||
graffiti: Option<&Graffiti>,
|
||||
skip_randao_verification: SkipRandaoVerification,
|
||||
) -> Result<ForkVersionedBeaconBlockType<T>, Error> {
|
||||
let path = self
|
||||
.get_validator_blocks_path::<T, Payload>(
|
||||
.get_validator_blocks_v3_path::<T>(
|
||||
slot,
|
||||
randao_reveal,
|
||||
graffiti,
|
||||
@@ -1680,7 +1774,77 @@ impl BeaconNodeHttpClient {
|
||||
)
|
||||
.await?;
|
||||
|
||||
self.get(path).await
|
||||
let response = self.get_response(path, |b| b).await?;
|
||||
|
||||
let is_blinded_payload = response
|
||||
.headers()
|
||||
.get(EXECUTION_PAYLOAD_BLINDED_HEADER)
|
||||
.map(|value| value.to_str().unwrap_or_default().to_lowercase() == "true")
|
||||
.unwrap_or(false);
|
||||
|
||||
if is_blinded_payload {
|
||||
let blinded_payload = response
|
||||
.json::<ForkVersionedResponse<BlockContents<T, BlindedPayload<T>>>>()
|
||||
.await?;
|
||||
Ok(ForkVersionedBeaconBlockType::Blinded(blinded_payload))
|
||||
} else {
|
||||
let full_payload = response
|
||||
.json::<ForkVersionedResponse<BlockContents<T, FullPayload<T>>>>()
|
||||
.await?;
|
||||
Ok(ForkVersionedBeaconBlockType::Full(full_payload))
|
||||
}
|
||||
}
|
||||
|
||||
/// `GET v3/validator/blocks/{slot}` in ssz format
|
||||
pub async fn get_validator_blocks_v3_ssz<T: EthSpec>(
|
||||
&self,
|
||||
slot: Slot,
|
||||
randao_reveal: &SignatureBytes,
|
||||
graffiti: Option<&Graffiti>,
|
||||
) -> Result<(Option<Vec<u8>>, bool), Error> {
|
||||
self.get_validator_blocks_v3_modular_ssz::<T>(
|
||||
slot,
|
||||
randao_reveal,
|
||||
graffiti,
|
||||
SkipRandaoVerification::No,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// `GET v3/validator/blocks/{slot}` in ssz format
|
||||
pub async fn get_validator_blocks_v3_modular_ssz<T: EthSpec>(
|
||||
&self,
|
||||
slot: Slot,
|
||||
randao_reveal: &SignatureBytes,
|
||||
graffiti: Option<&Graffiti>,
|
||||
skip_randao_verification: SkipRandaoVerification,
|
||||
) -> Result<(Option<Vec<u8>>, bool), Error> {
|
||||
let path = self
|
||||
.get_validator_blocks_v3_path::<T>(
|
||||
slot,
|
||||
randao_reveal,
|
||||
graffiti,
|
||||
skip_randao_verification,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let (response_content, response_headers) = self
|
||||
.get_bytes_response_with_response_headers(
|
||||
path,
|
||||
Accept::Ssz,
|
||||
self.timeouts.get_validator_block_ssz,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let is_blinded_payload = match response_headers {
|
||||
Some(headers) => headers
|
||||
.get(EXECUTION_PAYLOAD_BLINDED_HEADER)
|
||||
.map(|value| value.to_str().unwrap_or_default().to_lowercase() == "true")
|
||||
.unwrap_or(false),
|
||||
None => false,
|
||||
};
|
||||
|
||||
Ok((response_content, is_blinded_payload))
|
||||
}
|
||||
|
||||
/// `GET v2/validator/blocks/{slot}` in ssz format
|
||||
|
||||
@@ -1385,6 +1385,11 @@ pub mod serde_status_code {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ForkVersionedBeaconBlockType<T: EthSpec> {
|
||||
Full(ForkVersionedResponse<BlockContents<T, FullPayload<T>>>),
|
||||
Blinded(ForkVersionedResponse<BlockContents<T, BlindedPayload<T>>>),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -18,7 +18,6 @@ tokio = { workspace = true }
|
||||
serde_yaml = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
types = { workspace = true }
|
||||
kzg = { workspace = true }
|
||||
ethereum_ssz = { workspace = true }
|
||||
eth2_config = { workspace = true }
|
||||
discv5 = { workspace = true }
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -14,7 +14,6 @@
|
||||
use bytes::Bytes;
|
||||
use discv5::enr::{CombinedKey, Enr};
|
||||
use eth2_config::{instantiate_hardcoded_nets, HardcodedNet};
|
||||
use kzg::{KzgPreset, KzgPresetId, TrustedSetup};
|
||||
use pretty_reqwest_error::PrettyReqwestError;
|
||||
use reqwest::{Client, Error};
|
||||
use sensitive_url::SensitiveUrl;
|
||||
@@ -49,35 +48,19 @@ pub const DEFAULT_HARDCODED_NETWORK: &str = "mainnet";
|
||||
///
|
||||
/// This is done to ensure that testnets also inherit the high security and
|
||||
/// randomness of the mainnet kzg trusted setup ceremony.
|
||||
const TRUSTED_SETUP: &[u8] =
|
||||
include_bytes!("../built_in_network_configs/testing_trusted_setups.json");
|
||||
///
|
||||
/// Note: The trusted setup for both mainnet and minimal presets are the same.
|
||||
pub const TRUSTED_SETUP_BYTES: &[u8] =
|
||||
include_bytes!("../built_in_network_configs/trusted_setup.json");
|
||||
|
||||
const TRUSTED_SETUP_MINIMAL: &[u8] =
|
||||
include_bytes!("../built_in_network_configs/minimal_testing_trusted_setups.json");
|
||||
|
||||
pub fn get_trusted_setup<P: KzgPreset>() -> &'static [u8] {
|
||||
get_trusted_setup_from_id(P::spec_name())
|
||||
}
|
||||
|
||||
pub fn get_trusted_setup_from_id(id: KzgPresetId) -> &'static [u8] {
|
||||
match id {
|
||||
KzgPresetId::Mainnet => TRUSTED_SETUP,
|
||||
KzgPresetId::Minimal => TRUSTED_SETUP_MINIMAL,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_trusted_setup_from_config(config: &Config) -> Result<Option<TrustedSetup>, String> {
|
||||
/// Returns `Some(TrustedSetup)` if the deneb fork epoch is set and `None` otherwise.
|
||||
///
|
||||
/// Returns an error if the trusted setup parsing failed.
|
||||
fn get_trusted_setup_from_config(config: &Config) -> Option<Vec<u8>> {
|
||||
config
|
||||
.deneb_fork_epoch
|
||||
.filter(|epoch| epoch.value != Epoch::max_value())
|
||||
.map(|_| {
|
||||
let id = KzgPresetId::from_str(&config.preset_base)
|
||||
.map_err(|e| format!("Unable to parse preset_base as KZG preset: {:?}", e))?;
|
||||
let trusted_setup_bytes = get_trusted_setup_from_id(id);
|
||||
serde_json::from_reader(trusted_setup_bytes)
|
||||
.map_err(|e| format!("Unable to read trusted setup file: {}", e))
|
||||
})
|
||||
.transpose()
|
||||
.map(|_| TRUSTED_SETUP_BYTES.to_vec())
|
||||
}
|
||||
|
||||
/// A simple slice-or-vec enum to avoid cloning the beacon state bytes in the
|
||||
@@ -121,7 +104,7 @@ pub struct Eth2NetworkConfig {
|
||||
pub genesis_state_source: GenesisStateSource,
|
||||
pub genesis_state_bytes: Option<GenesisStateBytes>,
|
||||
pub config: Config,
|
||||
pub kzg_trusted_setup: Option<TrustedSetup>,
|
||||
pub kzg_trusted_setup: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl Eth2NetworkConfig {
|
||||
@@ -139,7 +122,7 @@ impl Eth2NetworkConfig {
|
||||
fn from_hardcoded_net(net: &HardcodedNet) -> Result<Self, String> {
|
||||
let config: Config = serde_yaml::from_reader(net.config)
|
||||
.map_err(|e| format!("Unable to parse yaml config: {:?}", e))?;
|
||||
let kzg_trusted_setup = get_trusted_setup_from_config(&config)?;
|
||||
let kzg_trusted_setup = get_trusted_setup_from_config(&config);
|
||||
Ok(Self {
|
||||
deposit_contract_deploy_block: serde_yaml::from_reader(net.deploy_block)
|
||||
.map_err(|e| format!("Unable to parse deploy block: {:?}", e))?,
|
||||
@@ -376,7 +359,7 @@ impl Eth2NetworkConfig {
|
||||
(None, GenesisStateSource::Unknown)
|
||||
};
|
||||
|
||||
let kzg_trusted_setup = get_trusted_setup_from_config(&config)?;
|
||||
let kzg_trusted_setup = get_trusted_setup_from_config(&config);
|
||||
|
||||
Ok(Self {
|
||||
deposit_contract_deploy_block,
|
||||
|
||||
@@ -20,9 +20,8 @@ pub fn test_random_derive(input: TokenStream) -> TokenStream {
|
||||
let name = &derived_input.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = &derived_input.generics.split_for_impl();
|
||||
|
||||
let struct_data = match &derived_input.data {
|
||||
syn::Data::Struct(s) => s,
|
||||
_ => panic!("test_random_derive only supports structs."),
|
||||
let syn::Data::Struct(struct_data) = &derived_input.data else {
|
||||
panic!("test_random_derive only supports structs.");
|
||||
};
|
||||
|
||||
// Build quotes for fields that should be generated and those that should be built from
|
||||
|
||||
Reference in New Issue
Block a user