mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 16:55:46 +00:00
Merge unstable 20230911 into deneb-free-blobs.
This commit is contained in:
@@ -37,14 +37,8 @@ tokio = { version = "1.14.0", features = ["full"] }
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
psutil = { version = "3.2.2", optional = true }
|
||||
procinfo = { version = "0.4.2", optional = true }
|
||||
procfs = { version = "0.15.1", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["lighthouse"]
|
||||
lighthouse = [
|
||||
"proto_array",
|
||||
"psutil",
|
||||
"procinfo",
|
||||
"store",
|
||||
"slashing_protection",
|
||||
]
|
||||
lighthouse = ["proto_array", "psutil", "procfs", "store", "slashing_protection"]
|
||||
|
||||
@@ -707,7 +707,7 @@ impl BeaconNodeHttpClient {
|
||||
/// Returns `Ok(None)` on a 404 error.
|
||||
pub async fn post_beacon_blocks_ssz<T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
&self,
|
||||
block: &SignedBlockContents<T, Payload>,
|
||||
block_contents: &SignedBlockContents<T, Payload>,
|
||||
) -> Result<(), Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
@@ -716,8 +716,12 @@ impl BeaconNodeHttpClient {
|
||||
.push("beacon")
|
||||
.push("blocks");
|
||||
|
||||
self.post_generic_with_ssz_body(path, block.as_ssz_bytes(), Some(self.timeouts.proposal))
|
||||
.await?;
|
||||
self.post_generic_with_ssz_body(
|
||||
path,
|
||||
block_contents.as_ssz_bytes(),
|
||||
Some(self.timeouts.proposal),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -747,7 +751,7 @@ impl BeaconNodeHttpClient {
|
||||
/// Returns `Ok(None)` on a 404 error.
|
||||
pub async fn post_beacon_blinded_blocks_ssz<T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
&self,
|
||||
block: &SignedBeaconBlock<T, Payload>,
|
||||
block: &SignedBlindedBlockContents<T>,
|
||||
) -> Result<(), Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
@@ -818,14 +822,14 @@ impl BeaconNodeHttpClient {
|
||||
/// `POST v2/beacon/blocks`
|
||||
pub async fn post_beacon_blocks_v2_ssz<T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
&self,
|
||||
block: &SignedBeaconBlock<T, Payload>,
|
||||
block_contents: &SignedBlockContents<T, Payload>,
|
||||
validation_level: Option<BroadcastValidation>,
|
||||
) -> Result<(), Error> {
|
||||
self.post_generic_with_consensus_version_and_ssz_body(
|
||||
self.post_beacon_blocks_v2_path(validation_level)?,
|
||||
block.as_ssz_bytes(),
|
||||
block_contents.as_ssz_bytes(),
|
||||
Some(self.timeouts.proposal),
|
||||
block.message().body().fork_name(),
|
||||
block_contents.signed_block().message().body().fork_name(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -852,14 +856,14 @@ impl BeaconNodeHttpClient {
|
||||
/// `POST v2/beacon/blinded_blocks`
|
||||
pub async fn post_beacon_blinded_blocks_v2_ssz<T: EthSpec>(
|
||||
&self,
|
||||
block: &SignedBlindedBeaconBlock<T>,
|
||||
block_contents: &SignedBlindedBlockContents<T>,
|
||||
validation_level: Option<BroadcastValidation>,
|
||||
) -> Result<(), Error> {
|
||||
self.post_generic_with_consensus_version_and_ssz_body(
|
||||
self.post_beacon_blinded_blocks_v2_path(validation_level)?,
|
||||
block.as_ssz_bytes(),
|
||||
block_contents.as_ssz_bytes(),
|
||||
Some(self.timeouts.proposal),
|
||||
block.message().body().fork_name(),
|
||||
block_contents.signed_block().message().body().fork_name(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -95,8 +95,8 @@ pub struct ValidatorInclusionData {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use {
|
||||
procinfo::pid, psutil::cpu::os::linux::CpuTimesExt,
|
||||
psutil::memory::os::linux::VirtualMemoryExt, psutil::process::Process,
|
||||
psutil::cpu::os::linux::CpuTimesExt, psutil::memory::os::linux::VirtualMemoryExt,
|
||||
psutil::process::Process,
|
||||
};
|
||||
|
||||
/// Reports on the health of the Lighthouse instance.
|
||||
@@ -238,7 +238,7 @@ pub struct ProcessHealth {
|
||||
/// The pid of this process.
|
||||
pub pid: u32,
|
||||
/// The number of threads used by this pid.
|
||||
pub pid_num_threads: i32,
|
||||
pub pid_num_threads: i64,
|
||||
/// The total resident memory used by this pid.
|
||||
pub pid_mem_resident_set_size: u64,
|
||||
/// The total virtual memory used by this pid.
|
||||
@@ -262,7 +262,12 @@ impl ProcessHealth {
|
||||
.memory_info()
|
||||
.map_err(|e| format!("Unable to get process memory info: {:?}", e))?;
|
||||
|
||||
let stat = pid::stat_self().map_err(|e| format!("Unable to get stat: {:?}", e))?;
|
||||
let me = procfs::process::Process::myself()
|
||||
.map_err(|e| format!("Unable to get process: {:?}", e))?;
|
||||
let stat = me
|
||||
.stat()
|
||||
.map_err(|e| format!("Unable to get stat: {:?}", e))?;
|
||||
|
||||
let process_times = process
|
||||
.cpu_times()
|
||||
.map_err(|e| format!("Unable to get process cpu times : {:?}", e))?;
|
||||
|
||||
@@ -1333,6 +1333,26 @@ pub struct BroadcastValidationQuery {
|
||||
pub broadcast_validation: BroadcastValidation,
|
||||
}
|
||||
|
||||
pub mod serde_status_code {
|
||||
use crate::StatusCode;
|
||||
use serde::{de::Error, Deserialize, Serialize};
|
||||
|
||||
pub fn serialize<S>(status_code: &StatusCode, ser: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
status_code.as_u16().serialize(ser)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(de: D) -> Result<StatusCode, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
let status_code = u16::deserialize(de)?;
|
||||
StatusCode::try_from(status_code).map_err(D::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -1465,6 +1485,8 @@ pub type SignedBlockContentsTuple<T, Payload> = (
|
||||
Option<SignedSidecarList<T, <Payload as AbstractExecPayload<T>>::Sidecar>>,
|
||||
);
|
||||
|
||||
pub type SignedBlindedBlockContents<E> = SignedBlockContents<E, BlindedPayload<E>>;
|
||||
|
||||
/// A wrapper over a [`SignedBeaconBlock`] or a [`SignedBeaconBlockAndBlobSidecars`].
|
||||
#[derive(Clone, Debug, Encode, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
@@ -1593,6 +1615,19 @@ impl<T: EthSpec> SignedBlockContents<T, BlindedPayload<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec> SignedBlockContents<T> {
|
||||
pub fn clone_as_blinded(&self) -> SignedBlindedBlockContents<T> {
|
||||
let blinded_blobs = self.blobs_cloned().map(|blob_sidecars| {
|
||||
blob_sidecars
|
||||
.into_iter()
|
||||
.map(|blob| blob.into())
|
||||
.collect::<Vec<_>>()
|
||||
.into()
|
||||
});
|
||||
SignedBlockContents::new(self.signed_block().clone_as_blinded(), blinded_blobs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec, Payload: AbstractExecPayload<T>> TryFrom<SignedBeaconBlock<T, Payload>>
|
||||
for SignedBlockContents<T, Payload>
|
||||
{
|
||||
|
||||
@@ -23,6 +23,23 @@ pub const PREDEFINED_NETWORKS_DIR: &str = predefined_networks_dir!();
|
||||
pub const GENESIS_FILE_NAME: &str = "genesis.ssz";
|
||||
pub const GENESIS_ZIP_FILE_NAME: &str = "genesis.ssz.zip";
|
||||
|
||||
const HOLESKY_GENESIS_STATE_SOURCE: GenesisStateSource = GenesisStateSource::Url {
|
||||
urls: &[
|
||||
// This is an AWS S3 bucket hosted by Sigma Prime. See Paul Hauner for
|
||||
// more details.
|
||||
"https://sigp-public-genesis-states.s3.ap-southeast-2.amazonaws.com/holesky/",
|
||||
],
|
||||
checksum: "0x76631cd0b9ddc5b2c766b496e23f16759ce1181446a4efb40e5540cd15b78a07",
|
||||
genesis_validators_root: "0x9143aa7c615a7f7115e2b6aac319c03529df8242ae705fba9df39b79c59fa8b1",
|
||||
};
|
||||
|
||||
const CHIADO_GENESIS_STATE_SOURCE: GenesisStateSource = GenesisStateSource::Url {
|
||||
// No default checkpoint sources are provided.
|
||||
urls: &[],
|
||||
checksum: "0xd4a039454c7429f1dfaa7e11e397ef3d0f50d2d5e4c0e4dc04919d153aa13af1",
|
||||
genesis_validators_root: "0x9d642dac73058fbf39c0ae41ab1e34e4d889043cb199851ded7095bc99eb4c1e",
|
||||
};
|
||||
|
||||
/// The core configuration of a Lighthouse beacon node.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Eth2Config {
|
||||
@@ -62,6 +79,32 @@ impl Eth2Config {
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes how a genesis state may be obtained.
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum GenesisStateSource {
|
||||
/// The genesis state for this network is not yet known.
|
||||
Unknown,
|
||||
/// The genesis state for this network is included in the binary via
|
||||
/// `include_bytes!` or by loading from a testnet dir.
|
||||
IncludedBytes,
|
||||
/// The genesis state for this network should be downloaded from a URL.
|
||||
Url {
|
||||
/// URLs to try to download the file from, in order.
|
||||
urls: &'static [&'static str],
|
||||
/// The SHA256 of the genesis state bytes. This is *not* a hash tree
|
||||
/// root to simplify the types (i.e., to avoid getting EthSpec
|
||||
/// involved).
|
||||
///
|
||||
/// The format should be 0x-prefixed ASCII bytes.
|
||||
checksum: &'static str,
|
||||
/// The `genesis_validators_root` of the genesis state. Used to avoid
|
||||
/// downloading the state for simple signing operations.
|
||||
///
|
||||
/// The format should be 0x-prefixed ASCII bytes.
|
||||
genesis_validators_root: &'static str,
|
||||
},
|
||||
}
|
||||
|
||||
/// A directory that can be built by downloading files via HTTP.
|
||||
///
|
||||
/// Used by the `eth2_network_config` crate to initialize the network directories during build and
|
||||
@@ -70,7 +113,7 @@ impl Eth2Config {
|
||||
pub struct Eth2NetArchiveAndDirectory<'a> {
|
||||
pub name: &'a str,
|
||||
pub config_dir: &'a str,
|
||||
pub genesis_is_known: bool,
|
||||
pub genesis_state_source: GenesisStateSource,
|
||||
}
|
||||
|
||||
impl<'a> Eth2NetArchiveAndDirectory<'a> {
|
||||
@@ -89,15 +132,11 @@ impl<'a> Eth2NetArchiveAndDirectory<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates that the `genesis.ssz.zip` file is present on the filesystem. This means that the
|
||||
/// deposit ceremony has concluded and the final genesis `BeaconState` is known.
|
||||
const GENESIS_STATE_IS_KNOWN: bool = true;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct HardcodedNet {
|
||||
pub name: &'static str,
|
||||
pub config_dir: &'static str,
|
||||
pub genesis_is_known: bool,
|
||||
pub genesis_state_source: GenesisStateSource,
|
||||
pub config: &'static [u8],
|
||||
pub deploy_block: &'static [u8],
|
||||
pub boot_enr: &'static [u8],
|
||||
@@ -109,7 +148,7 @@ pub struct HardcodedNet {
|
||||
/// It also defines a `include_<title>_file!` macro which provides a wrapper around
|
||||
/// `std::include_bytes`, allowing the inclusion of bytes from the specific testnet directory.
|
||||
macro_rules! define_archive {
|
||||
($name_ident: ident, $config_dir: tt, $genesis_is_known: ident) => {
|
||||
($name_ident: ident, $config_dir: tt, $genesis_state_source: path) => {
|
||||
paste! {
|
||||
#[macro_use]
|
||||
pub mod $name_ident {
|
||||
@@ -118,7 +157,7 @@ macro_rules! define_archive {
|
||||
pub const ETH2_NET_DIR: Eth2NetArchiveAndDirectory = Eth2NetArchiveAndDirectory {
|
||||
name: stringify!($name_ident),
|
||||
config_dir: $config_dir,
|
||||
genesis_is_known: $genesis_is_known,
|
||||
genesis_state_source: $genesis_state_source,
|
||||
};
|
||||
|
||||
/// A wrapper around `std::include_bytes` which includes a file from a specific network
|
||||
@@ -151,7 +190,7 @@ macro_rules! define_net {
|
||||
$this_crate::HardcodedNet {
|
||||
name: ETH2_NET_DIR.name,
|
||||
config_dir: ETH2_NET_DIR.config_dir,
|
||||
genesis_is_known: ETH2_NET_DIR.genesis_is_known,
|
||||
genesis_state_source: ETH2_NET_DIR.genesis_state_source,
|
||||
config: $this_crate::$include_file!($this_crate, "../", "config.yaml"),
|
||||
deploy_block: $this_crate::$include_file!($this_crate, "../", "deploy_block.txt"),
|
||||
boot_enr: $this_crate::$include_file!($this_crate, "../", "boot_enr.yaml"),
|
||||
@@ -199,9 +238,9 @@ macro_rules! define_nets {
|
||||
/// `build.rs` which will unzip the genesis states. Then, that `eth2_network_configs` crate can
|
||||
/// perform the final step of using `std::include_bytes` to bake the files (bytes) into the binary.
|
||||
macro_rules! define_hardcoded_nets {
|
||||
($(($name_ident: ident, $config_dir: tt, $genesis_is_known: ident)),+) => {
|
||||
($(($name_ident: ident, $config_dir: tt, $genesis_state_source: path)),+) => {
|
||||
$(
|
||||
define_archive!($name_ident, $config_dir, $genesis_is_known);
|
||||
define_archive!($name_ident, $config_dir, $genesis_state_source);
|
||||
)+
|
||||
|
||||
pub const ETH2_NET_DIRS: &[Eth2NetArchiveAndDirectory<'static>] = &[$($name_ident::ETH2_NET_DIR,)+];
|
||||
@@ -242,9 +281,8 @@ define_hardcoded_nets!(
|
||||
// The name of the directory in the `eth2_network_config/built_in_network_configs`
|
||||
// directory where the configuration files are located for this network.
|
||||
"mainnet",
|
||||
// Set to `true` if the genesis state can be found in the `built_in_network_configs`
|
||||
// directory.
|
||||
GENESIS_STATE_IS_KNOWN
|
||||
// Describes how the genesis state can be obtained.
|
||||
GenesisStateSource::IncludedBytes
|
||||
),
|
||||
(
|
||||
// Network name (must be unique among all networks).
|
||||
@@ -252,9 +290,8 @@ define_hardcoded_nets!(
|
||||
// The name of the directory in the `eth2_network_config/built_in_network_configs`
|
||||
// directory where the configuration files are located for this network.
|
||||
"prater",
|
||||
// Set to `true` if the genesis state can be found in the `built_in_network_configs`
|
||||
// directory.
|
||||
GENESIS_STATE_IS_KNOWN
|
||||
// Describes how the genesis state can be obtained.
|
||||
GenesisStateSource::IncludedBytes
|
||||
),
|
||||
(
|
||||
// Network name (must be unique among all networks).
|
||||
@@ -264,9 +301,8 @@ define_hardcoded_nets!(
|
||||
//
|
||||
// The Goerli network is effectively an alias to Prater.
|
||||
"prater",
|
||||
// Set to `true` if the genesis state can be found in the `built_in_network_configs`
|
||||
// directory.
|
||||
GENESIS_STATE_IS_KNOWN
|
||||
// Describes how the genesis state can be obtained.
|
||||
GenesisStateSource::IncludedBytes
|
||||
),
|
||||
(
|
||||
// Network name (must be unique among all networks).
|
||||
@@ -274,9 +310,18 @@ define_hardcoded_nets!(
|
||||
// The name of the directory in the `eth2_network_config/built_in_network_configs`
|
||||
// directory where the configuration files are located for this network.
|
||||
"gnosis",
|
||||
// Describes how the genesis state can be obtained.
|
||||
GenesisStateSource::IncludedBytes
|
||||
),
|
||||
(
|
||||
// Network name (must be unique among all networks).
|
||||
chiado,
|
||||
// The name of the directory in the `eth2_network_config/built_in_network_configs`
|
||||
// directory where the configuration files are located for this network.
|
||||
"chiado",
|
||||
// Set to `true` if the genesis state can be found in the `built_in_network_configs`
|
||||
// directory.
|
||||
GENESIS_STATE_IS_KNOWN
|
||||
CHIADO_GENESIS_STATE_SOURCE
|
||||
),
|
||||
(
|
||||
// Network name (must be unique among all networks).
|
||||
@@ -284,8 +329,16 @@ define_hardcoded_nets!(
|
||||
// The name of the directory in the `eth2_network_config/built_in_network_configs`
|
||||
// directory where the configuration files are located for this network.
|
||||
"sepolia",
|
||||
// Set to `true` if the genesis state can be found in the `built_in_network_configs`
|
||||
// directory.
|
||||
GENESIS_STATE_IS_KNOWN
|
||||
// Describes how the genesis state can be obtained.
|
||||
GenesisStateSource::IncludedBytes
|
||||
),
|
||||
(
|
||||
// Network name (must be unique among all networks).
|
||||
holesky,
|
||||
// The name of the directory in the `eth2_network_config/built_in_network_configs`
|
||||
// directory where the configuration files are located for this network.
|
||||
"holesky",
|
||||
// Describes how the genesis state can be obtained.
|
||||
HOLESKY_GENESIS_STATE_SOURCE
|
||||
)
|
||||
);
|
||||
|
||||
@@ -7,8 +7,8 @@ edition = "2021"
|
||||
build = "build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
zip = "0.5.8"
|
||||
eth2_config = { path = "../eth2_config"}
|
||||
zip = "0.6"
|
||||
eth2_config = { path = "../eth2_config" }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.1.0"
|
||||
@@ -16,8 +16,15 @@ tempfile = "3.1.0"
|
||||
[dependencies]
|
||||
serde_yaml = "0.8.13"
|
||||
serde_json = "1.0.58"
|
||||
types = { path = "../../consensus/types"}
|
||||
types = { path = "../../consensus/types" }
|
||||
kzg = { path = "../../crypto/kzg" }
|
||||
ethereum_ssz = "0.5.0"
|
||||
eth2_config = { path = "../eth2_config"}
|
||||
discv5 = "0.3.1"
|
||||
eth2_config = { path = "../eth2_config" }
|
||||
discv5 = "0.3.1"
|
||||
reqwest = { version = "0.11.0", features = ["blocking"] }
|
||||
pretty_reqwest_error = { path = "../pretty_reqwest_error" }
|
||||
sha2 = "0.10"
|
||||
url = "2.2.2"
|
||||
sensitive_url = { path = "../sensitive_url" }
|
||||
slog = "2.5.2"
|
||||
logging = { path = "../logging" }
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//! Extracts zipped genesis states on first run.
|
||||
use eth2_config::{Eth2NetArchiveAndDirectory, ETH2_NET_DIRS, GENESIS_FILE_NAME};
|
||||
use eth2_config::{
|
||||
Eth2NetArchiveAndDirectory, GenesisStateSource, ETH2_NET_DIRS, GENESIS_FILE_NAME,
|
||||
};
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use zip::ZipArchive;
|
||||
@@ -26,7 +28,7 @@ fn uncompress_state(network: &Eth2NetArchiveAndDirectory<'static>) -> Result<(),
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if network.genesis_is_known {
|
||||
if network.genesis_state_source == GenesisStateSource::IncludedBytes {
|
||||
// Extract genesis state from genesis.ssz.zip
|
||||
let archive_path = network.genesis_state_archive();
|
||||
let archive_file = File::open(&archive_path)
|
||||
@@ -46,7 +48,8 @@ fn uncompress_state(network: &Eth2NetArchiveAndDirectory<'static>) -> Result<(),
|
||||
io::copy(&mut file, &mut outfile)
|
||||
.map_err(|e| format!("Error writing file {:?}: {}", genesis_ssz_path, e))?;
|
||||
} else {
|
||||
// Create empty genesis.ssz if genesis is unknown
|
||||
// Create empty genesis.ssz if genesis is unknown or to be downloaded via URL.
|
||||
// This is a bit of a hack to make `include_bytes!` easier to deal with.
|
||||
File::create(genesis_ssz_path)
|
||||
.map_err(|e| format!("Failed to create {}: {}", GENESIS_FILE_NAME, e))?;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# chiado-teku-0
|
||||
- "enr:-Ly4QLYLNqrjvSxD3lpAPBUNlxa6cIbe79JqLZLFcZZjWoCjZcw-85agLUErHiygG2weRSCLnd5V460qTbLbwJQsfZkoh2F0dG5ldHOI__________-EZXRoMpAxNnBDAgAAb___________gmlkgnY0gmlwhKq7mu-Jc2VjcDI1NmsxoQP900YAYa9kdvzlSKGjVo-F3XVzATjOYp3BsjLjSophO4hzeW5jbmV0cw-DdGNwgiMog3VkcIIjKA"
|
||||
# chiado-teku-1
|
||||
- "enr:-Ly4QCGeYvTCNOGKi0mKRUd45rLj96b4pH98qG7B9TCUGXGpHZALtaL2-XfjASQyhbCqENccI4PGXVqYTIehNT9KJMQgh2F0dG5ldHOI__________-EZXRoMpAxNnBDAgAAb___________gmlkgnY0gmlwhIuQrVSJc2VjcDI1NmsxoQP9iDchx2PGl3JyJ29B9fhLCvVMN6n23pPAIIeFV-sHOIhzeW5jbmV0cw-DdGNwgiMog3VkcIIjKA"
|
||||
#GnosisDAO Bootnode: 3.71.132.231
|
||||
- "enr:-Ly4QAtr21x5Ps7HYhdZkIBRBgcBkvlIfEel1YNjtFWf4cV3au2LgBGICz9PtEs9-p2HUl_eME8m1WImxTxSB3AkCMwBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAxNnBDAgAAb___________gmlkgnY0gmlwhANHhOeJc2VjcDI1NmsxoQNLp1QPV8-pyMCohOtj6xGtSBM_GtVTqzlbvNsCF4ezkYhzeW5jbmV0cwCDdGNwgiMog3VkcIIjKA"
|
||||
#GnosisDAO Bootnode: 3.69.35.13
|
||||
- "enr:-Ly4QLgn8Bx6faigkKUGZQvd1HDToV2FAxZIiENK-lczruzQb90qJK-4E65ADly0s4__dQOW7IkLMW7ZAyJy2vtiLy8Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpAxNnBDAgAAb___________gmlkgnY0gmlwhANFIw2Jc2VjcDI1NmsxoQMa-fWEy9UJHfOl_lix3wdY5qust78sHAqZnWwEiyqKgYhzeW5jbmV0cwCDdGNwgiMog3VkcIIjKA"
|
||||
@@ -0,0 +1,154 @@
|
||||
# Extends the mainnet preset
|
||||
PRESET_BASE: gnosis
|
||||
# needs to exist because of Prysm. Otherwise it conflicts with mainnet genesis
|
||||
CONFIG_NAME: chiado
|
||||
|
||||
# Genesis
|
||||
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 6000
|
||||
# 10 October 2022 10:00:00 GMT+0000
|
||||
MIN_GENESIS_TIME: 1665396000
|
||||
GENESIS_DELAY: 300
|
||||
|
||||
# Projected time: 2022-11-04T15:00:00.000Z, block: 680928
|
||||
TERMINAL_TOTAL_DIFFICULTY: 231707791542740786049188744689299064356246512
|
||||
|
||||
# Deposit contract
|
||||
# ---------------------------------------------------------------
|
||||
# NOTE: Don't use a value too high, or Teku rejects it (4294906129 NOK)
|
||||
DEPOSIT_CHAIN_ID: 10200
|
||||
DEPOSIT_NETWORK_ID: 10200
|
||||
DEPOSIT_CONTRACT_ADDRESS: 0xb97036A26259B7147018913bD58a774cf91acf25
|
||||
|
||||
# Misc
|
||||
# ---------------------------------------------------------------
|
||||
# 2**6 (= 64)
|
||||
MAX_COMMITTEES_PER_SLOT: 64
|
||||
# 2**7 (= 128)
|
||||
TARGET_COMMITTEE_SIZE: 128
|
||||
# 2**11 (= 2,048)
|
||||
MAX_VALIDATORS_PER_COMMITTEE: 2048
|
||||
# 2**2 (= 4)
|
||||
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
||||
# 2**12 (= 4096)
|
||||
CHURN_LIMIT_QUOTIENT: 4096
|
||||
# See issue 563
|
||||
SHUFFLE_ROUND_COUNT: 90
|
||||
# 4
|
||||
HYSTERESIS_QUOTIENT: 4
|
||||
# 1 (minus 0.25)
|
||||
HYSTERESIS_DOWNWARD_MULTIPLIER: 1
|
||||
# 5 (plus 1.25)
|
||||
HYSTERESIS_UPWARD_MULTIPLIER: 5
|
||||
# Validator
|
||||
# ---------------------------------------------------------------
|
||||
# 2**10 (= 1024) ~1.4 hour
|
||||
ETH1_FOLLOW_DISTANCE: 1024
|
||||
# 2**4 (= 16)
|
||||
TARGET_AGGREGATORS_PER_COMMITTEE: 16
|
||||
# 2**0 (= 1)
|
||||
RANDOM_SUBNETS_PER_VALIDATOR: 1
|
||||
# 2**8 (= 256)
|
||||
EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION: 256
|
||||
# 6 (estimate from xDai mainnet)
|
||||
SECONDS_PER_ETH1_BLOCK: 6
|
||||
|
||||
# Gwei values
|
||||
# ---------------------------------------------------------------
|
||||
# 2**0 * 10**9 (= 1,000,000,000) Gwei
|
||||
MIN_DEPOSIT_AMOUNT: 1000000000
|
||||
# 2**5 * 10**9 (= 32,000,000,000) Gwei
|
||||
MAX_EFFECTIVE_BALANCE: 32000000000
|
||||
# 2**4 * 10**9 (= 16,000,000,000) Gwei
|
||||
EJECTION_BALANCE: 16000000000
|
||||
# 2**0 * 10**9 (= 1,000,000,000) Gwei
|
||||
EFFECTIVE_BALANCE_INCREMENT: 1000000000
|
||||
# Initial values
|
||||
# ---------------------------------------------------------------
|
||||
# GBC area code
|
||||
GENESIS_FORK_VERSION: 0x0000006f
|
||||
BLS_WITHDRAWAL_PREFIX: 0x00
|
||||
# Time parameters
|
||||
# ---------------------------------------------------------------
|
||||
# 5 seconds
|
||||
SECONDS_PER_SLOT: 5
|
||||
# 2**0 (= 1) slots 12 seconds
|
||||
MIN_ATTESTATION_INCLUSION_DELAY: 1
|
||||
# 2**4 (= 16) slots 1.87 minutes
|
||||
SLOTS_PER_EPOCH: 16
|
||||
# 2**0 (= 1) epochs 1.87 minutes
|
||||
MIN_SEED_LOOKAHEAD: 1
|
||||
# 2**2 (= 4) epochs 7.47 minutes
|
||||
MAX_SEED_LOOKAHEAD: 4
|
||||
# 2**6 (= 64) epochs ~2 hours
|
||||
EPOCHS_PER_ETH1_VOTING_PERIOD: 64
|
||||
# 2**13 (= 8,192) slots ~15.9 hours
|
||||
SLOTS_PER_HISTORICAL_ROOT: 8192
|
||||
# 2**8 (= 256) epochs ~8 hours
|
||||
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
|
||||
# 2**8 (= 256) epochs ~8 hours
|
||||
SHARD_COMMITTEE_PERIOD: 256
|
||||
# 2**2 (= 4) epochs 7.47 minutes
|
||||
MIN_EPOCHS_TO_INACTIVITY_PENALTY: 4
|
||||
|
||||
# State vector lengths
|
||||
# ---------------------------------------------------------------
|
||||
# 2**16 (= 65,536) epochs ~85 days
|
||||
EPOCHS_PER_HISTORICAL_VECTOR: 65536
|
||||
# 2**13 (= 8,192) epochs ~10.6 days
|
||||
EPOCHS_PER_SLASHINGS_VECTOR: 8192
|
||||
# 2**24 (= 16,777,216) historical roots, ~15,243 years
|
||||
HISTORICAL_ROOTS_LIMIT: 16777216
|
||||
# 2**40 (= 1,099,511,627,776) validator spots
|
||||
VALIDATOR_REGISTRY_LIMIT: 1099511627776
|
||||
# Reward and penalty quotients
|
||||
# ---------------------------------------------------------------
|
||||
# 25
|
||||
BASE_REWARD_FACTOR: 25
|
||||
# 2**9 (= 512)
|
||||
WHISTLEBLOWER_REWARD_QUOTIENT: 512
|
||||
# 2**3 (= 8)
|
||||
PROPOSER_REWARD_QUOTIENT: 8
|
||||
# 2**26 (= 67,108,864)
|
||||
INACTIVITY_PENALTY_QUOTIENT: 67108864
|
||||
# 2**7 (= 128) (lower safety margin at Phase 0 genesis)
|
||||
MIN_SLASHING_PENALTY_QUOTIENT: 128
|
||||
# 1 (lower safety margin at Phase 0 genesis)
|
||||
PROPORTIONAL_SLASHING_MULTIPLIER: 1
|
||||
# Max operations per block
|
||||
# ---------------------------------------------------------------
|
||||
# 2**4 (= 16)
|
||||
MAX_PROPOSER_SLASHINGS: 16
|
||||
# 2**1 (= 2)
|
||||
MAX_ATTESTER_SLASHINGS: 2
|
||||
# 2**7 (= 128)
|
||||
MAX_ATTESTATIONS: 128
|
||||
# 2**4 (= 16)
|
||||
MAX_DEPOSITS: 16
|
||||
# 2**4 (= 16)
|
||||
MAX_VOLUNTARY_EXITS: 16
|
||||
# Signature domains
|
||||
# ---------------------------------------------------------------
|
||||
DOMAIN_BEACON_PROPOSER: 0x00000000
|
||||
DOMAIN_BEACON_ATTESTER: 0x01000000
|
||||
DOMAIN_RANDAO: 0x02000000
|
||||
DOMAIN_DEPOSIT: 0x03000000
|
||||
DOMAIN_VOLUNTARY_EXIT: 0x04000000
|
||||
DOMAIN_SELECTION_PROOF: 0x05000000
|
||||
DOMAIN_AGGREGATE_AND_PROOF: 0x06000000
|
||||
DOMAIN_SYNC_COMMITTEE: 0x07000000
|
||||
DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF: 0x08000000
|
||||
DOMAIN_CONTRIBUTION_AND_PROOF: 0x09000000
|
||||
|
||||
# Altair
|
||||
ALTAIR_FORK_VERSION: 0x0100006f
|
||||
ALTAIR_FORK_EPOCH: 90 # Mon Oct 10 2022 12:00:00 GMT+0000
|
||||
# Bellatrix
|
||||
BELLATRIX_FORK_VERSION: 0x0200006f
|
||||
BELLATRIX_FORK_EPOCH: 180 # Mon Oct 10 2022 14:00:00 GMT+0000
|
||||
# Capella
|
||||
CAPELLA_FORK_VERSION: 0x0300006f
|
||||
CAPELLA_FORK_EPOCH: 244224 # Wed May 24 2023 13:12:00 GMT+0000
|
||||
|
||||
INACTIVITY_SCORE_BIAS: 4
|
||||
# 2**4 (= 16)
|
||||
INACTIVITY_SCORE_RECOVERY_RATE: 16
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1,8 @@
|
||||
# EF
|
||||
- enr:-Iq4QJk4WqRkjsX5c2CXtOra6HnxN-BMXnWhmhEQO9Bn9iABTJGdjUOurM7Btj1ouKaFkvTRoju5vz2GPmVON2dffQKGAX53x8JigmlkgnY0gmlwhLKAlv6Jc2VjcDI1NmsxoQK6S-Cii_KmfFdUJL2TANL3ksaKUnNXvTCv1tLwXs0QgIN1ZHCCIyk
|
||||
- enr:-KG4QF6d6vMSboSujAXTI4vYqArccm0eIlXfcxf2Lx_VE1q6IkQo_2D5LAO3ZSBVUs0w5rrVDmABJZuMzISe_pZundADhGV0aDKQqX6DZjABcAAAAQAAAAAAAIJpZIJ2NIJpcISygIjpiXNlY3AyNTZrMaEDF3aSa7QSCvdqLpANNd8GML4PLEZVg45fKQwMWhDZjd2DdGNwgiMog3VkcIIjKA
|
||||
- enr:-Ly4QJLXSSAj3ggPBIcodvBU6IyfpU_yW7E9J-5syoJorBuvcYj_Fokcjr303bQoTdWXADf8po0ssh75Mr5wVGzZZsMBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpCpfoNmMAFwAAABAAAAAAAAgmlkgnY0gmlwhJK-DYCJc2VjcDI1NmsxoQJrIlXIQDvQ6t9yDySqJYDXgZgLXzTvq8W7OI51jfmxJohzeW5jbmV0cwCDdGNwgiMog3VkcIIjKA
|
||||
# Teku
|
||||
- enr:-LK4QMlzEff6d-M0A1pSFG5lJ2c56i_I-ZftdojZbW3ehkGNM4pkQuHQqzVvF1BG9aDjIakjnmO23mCBFFZ2w5zOsugEh2F0dG5ldHOIAAAAAAYAAACEZXRoMpCpfoNmMAFwAAABAAAAAAAAgmlkgnY0gmlwhKyuI_mJc2VjcDI1NmsxoQIH1kQRCZW-4AIVyAeXj5o49m_IqNFKRHp6tSpfXMUrSYN0Y3CCIyiDdWRwgiMo
|
||||
# Sigma Prime
|
||||
- enr:-Le4QI88slOwzz66Ksq8Vnz324DPb1BzSiY-WYPvnoJIl-lceW9bmSJnwDzgNbCjp5wsBigg76x4tValvGgQPxxSjrMBhGV0aDKQqX6DZjABcAAAAQAAAAAAAIJpZIJ2NIJpcIQ5gR6Wg2lwNpAgAUHQBwEQAAAAAAAAADR-iXNlY3AyNTZrMaEDPMSNdcL92uNIyCsS177Z6KTXlbZakQqxv3aQcWawNXeDdWRwgiMohHVkcDaCI4I
|
||||
@@ -0,0 +1,117 @@
|
||||
# Extends the mainnet preset
|
||||
PRESET_BASE: 'mainnet'
|
||||
CONFIG_NAME: holesky
|
||||
|
||||
# Genesis
|
||||
# ---------------------------------------------------------------
|
||||
# `2**14` (= 16,384)
|
||||
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 16384
|
||||
# Sep-15-2023 13:55:00 +UTC
|
||||
MIN_GENESIS_TIME: 1694786100
|
||||
GENESIS_FORK_VERSION: 0x00017000
|
||||
# Genesis delay 5 mins
|
||||
GENESIS_DELAY: 300
|
||||
|
||||
|
||||
# Forking
|
||||
# ---------------------------------------------------------------
|
||||
# Some forks are disabled for now:
|
||||
# - These may be re-assigned to another fork-version later
|
||||
# - Temporarily set to max uint64 value: 2**64 - 1
|
||||
|
||||
# Altair
|
||||
ALTAIR_FORK_VERSION: 0x10017000
|
||||
ALTAIR_FORK_EPOCH: 0
|
||||
# Merge
|
||||
BELLATRIX_FORK_VERSION: 0x20017000
|
||||
BELLATRIX_FORK_EPOCH: 0
|
||||
TERMINAL_TOTAL_DIFFICULTY: 0
|
||||
TERMINAL_BLOCK_HASH: 0x0000000000000000000000000000000000000000000000000000000000000000
|
||||
TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: 18446744073709551615
|
||||
|
||||
# Capella
|
||||
CAPELLA_FORK_VERSION: 0x30017000
|
||||
CAPELLA_FORK_EPOCH: 256
|
||||
|
||||
# DENEB
|
||||
DENEB_FORK_VERSION: 0x40017000
|
||||
DENEB_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
# Time parameters
|
||||
# ---------------------------------------------------------------
|
||||
# 12 seconds
|
||||
SECONDS_PER_SLOT: 12
|
||||
# 14 (estimate from Eth1 mainnet)
|
||||
SECONDS_PER_ETH1_BLOCK: 14
|
||||
# 2**8 (= 256) epochs ~27 hours
|
||||
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
|
||||
# 2**8 (= 256) epochs ~27 hours
|
||||
SHARD_COMMITTEE_PERIOD: 256
|
||||
# 2**11 (= 2,048) Eth1 blocks ~8 hours
|
||||
ETH1_FOLLOW_DISTANCE: 2048
|
||||
|
||||
|
||||
# Validator cycle
|
||||
# ---------------------------------------------------------------
|
||||
# 2**2 (= 4)
|
||||
INACTIVITY_SCORE_BIAS: 4
|
||||
# 2**4 (= 16)
|
||||
INACTIVITY_SCORE_RECOVERY_RATE: 16
|
||||
# 28,000,000,000 Gwei to ensure quicker ejection
|
||||
EJECTION_BALANCE: 28000000000
|
||||
# 2**2 (= 4)
|
||||
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
||||
# 2**16 (= 65,536)
|
||||
CHURN_LIMIT_QUOTIENT: 65536
|
||||
|
||||
# Fork choice
|
||||
# ---------------------------------------------------------------
|
||||
# 40%
|
||||
PROPOSER_SCORE_BOOST: 40
|
||||
|
||||
# Deposit contract
|
||||
# ---------------------------------------------------------------
|
||||
DEPOSIT_CHAIN_ID: 17000
|
||||
DEPOSIT_NETWORK_ID: 17000
|
||||
DEPOSIT_CONTRACT_ADDRESS: 0x4242424242424242424242424242424242424242
|
||||
|
||||
# Networking
|
||||
# ---------------------------------------------------------------
|
||||
# `10 * 2**20` (= 10485760, 10 MiB)
|
||||
GOSSIP_MAX_SIZE: 10485760
|
||||
# `2**10` (= 1024)
|
||||
MAX_REQUEST_BLOCKS: 1024
|
||||
# `2**8` (= 256)
|
||||
EPOCHS_PER_SUBNET_SUBSCRIPTION: 256
|
||||
# `MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2` (= 33024, ~5 months)
|
||||
MIN_EPOCHS_FOR_BLOCK_REQUESTS: 33024
|
||||
# `10 * 2**20` (=10485760, 10 MiB)
|
||||
MAX_CHUNK_SIZE: 10485760
|
||||
# 5s
|
||||
TTFB_TIMEOUT: 5
|
||||
# 10s
|
||||
RESP_TIMEOUT: 10
|
||||
ATTESTATION_PROPAGATION_SLOT_RANGE: 32
|
||||
# 500ms
|
||||
MAXIMUM_GOSSIP_CLOCK_DISPARITY: 500
|
||||
MESSAGE_DOMAIN_INVALID_SNAPPY: 0x00000000
|
||||
MESSAGE_DOMAIN_VALID_SNAPPY: 0x01000000
|
||||
# 2 subnets per node
|
||||
SUBNETS_PER_NODE: 2
|
||||
# 2**8 (= 64)
|
||||
ATTESTATION_SUBNET_COUNT: 64
|
||||
ATTESTATION_SUBNET_EXTRA_BITS: 0
|
||||
# ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS
|
||||
ATTESTATION_SUBNET_PREFIX_BITS: 6
|
||||
|
||||
# Deneb
|
||||
# `2**7` (=128)
|
||||
MAX_REQUEST_BLOCKS_DENEB: 128
|
||||
# MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK
|
||||
MAX_REQUEST_BLOB_SIDECARS: 768
|
||||
# `2**12` (= 4096 epochs, ~18 days)
|
||||
MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: 4096
|
||||
# `6`
|
||||
BLOB_SIDECAR_SUBNET_COUNT: 6
|
||||
# `uint64(6)`
|
||||
MAX_BLOBS_PER_BLOCK: 6
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -14,11 +14,20 @@
|
||||
use discv5::enr::{CombinedKey, Enr};
|
||||
use eth2_config::{instantiate_hardcoded_nets, HardcodedNet};
|
||||
use kzg::{KzgPreset, KzgPresetId, TrustedSetup};
|
||||
use pretty_reqwest_error::PrettyReqwestError;
|
||||
use reqwest::blocking::Client;
|
||||
use sensitive_url::SensitiveUrl;
|
||||
use sha2::{Digest, Sha256};
|
||||
use slog::{info, warn, Logger};
|
||||
use std::fs::{create_dir_all, File};
|
||||
use std::io::{Read, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use types::{BeaconState, ChainSpec, Config, Epoch, EthSpec, EthSpecId};
|
||||
use std::time::Duration;
|
||||
use types::{BeaconState, ChainSpec, Config, Epoch, EthSpec, EthSpecId, Hash256};
|
||||
use url::Url;
|
||||
|
||||
pub use eth2_config::GenesisStateSource;
|
||||
|
||||
pub const DEPLOY_BLOCK_FILE: &str = "deploy_block.txt";
|
||||
pub const BOOT_ENR_FILE: &str = "boot_enr.yaml";
|
||||
@@ -70,6 +79,35 @@ fn get_trusted_setup_from_config(config: &Config) -> Result<Option<TrustedSetup>
|
||||
.transpose()
|
||||
}
|
||||
|
||||
/// A simple slice-or-vec enum to avoid cloning the beacon state bytes in the
|
||||
/// binary whilst also supporting loading them from a file at runtime.
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum GenesisStateBytes {
|
||||
Slice(&'static [u8]),
|
||||
Vec(Vec<u8>),
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for GenesisStateBytes {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
match self {
|
||||
GenesisStateBytes::Slice(slice) => slice,
|
||||
GenesisStateBytes::Vec(vec) => vec.as_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&'static [u8]> for GenesisStateBytes {
|
||||
fn from(slice: &'static [u8]) -> Self {
|
||||
GenesisStateBytes::Slice(slice)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for GenesisStateBytes {
|
||||
fn from(vec: Vec<u8>) -> Self {
|
||||
GenesisStateBytes::Vec(vec)
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies an Eth2 network.
|
||||
///
|
||||
/// See the crate-level documentation for more details.
|
||||
@@ -79,7 +117,8 @@ pub struct Eth2NetworkConfig {
|
||||
/// value to be the block number where the first deposit occurs.
|
||||
pub deposit_contract_deploy_block: u64,
|
||||
pub boot_enr: Option<Vec<Enr<CombinedKey>>>,
|
||||
pub genesis_state_bytes: Option<Vec<u8>>,
|
||||
pub genesis_state_source: GenesisStateSource,
|
||||
pub genesis_state_bytes: Option<GenesisStateBytes>,
|
||||
pub config: Config,
|
||||
pub kzg_trusted_setup: Option<TrustedSetup>,
|
||||
}
|
||||
@@ -107,8 +146,10 @@ impl Eth2NetworkConfig {
|
||||
serde_yaml::from_reader(net.boot_enr)
|
||||
.map_err(|e| format!("Unable to parse boot enr: {:?}", e))?,
|
||||
),
|
||||
genesis_state_bytes: Some(net.genesis_state_bytes.to_vec())
|
||||
.filter(|bytes| !bytes.is_empty()),
|
||||
genesis_state_source: net.genesis_state_source,
|
||||
genesis_state_bytes: Some(net.genesis_state_bytes)
|
||||
.filter(|bytes| !bytes.is_empty())
|
||||
.map(Into::into),
|
||||
config,
|
||||
kzg_trusted_setup,
|
||||
})
|
||||
@@ -123,8 +164,37 @@ impl Eth2NetworkConfig {
|
||||
}
|
||||
|
||||
/// Returns `true` if this configuration contains a `BeaconState`.
|
||||
pub fn beacon_state_is_known(&self) -> bool {
|
||||
self.genesis_state_bytes.is_some()
|
||||
pub fn genesis_state_is_known(&self) -> bool {
|
||||
self.genesis_state_source != GenesisStateSource::Unknown
|
||||
}
|
||||
|
||||
/// The `genesis_validators_root` of the genesis state. May download the
|
||||
/// genesis state if the value is not already available.
|
||||
pub fn genesis_validators_root<E: EthSpec>(
|
||||
&self,
|
||||
genesis_state_url: Option<&str>,
|
||||
timeout: Duration,
|
||||
log: &Logger,
|
||||
) -> Result<Option<Hash256>, String> {
|
||||
if let GenesisStateSource::Url {
|
||||
genesis_validators_root,
|
||||
..
|
||||
} = self.genesis_state_source
|
||||
{
|
||||
Hash256::from_str(genesis_validators_root)
|
||||
.map(Option::Some)
|
||||
.map_err(|e| {
|
||||
format!(
|
||||
"Unable to parse genesis state genesis_validators_root: {:?}",
|
||||
e
|
||||
)
|
||||
})
|
||||
} else {
|
||||
self.genesis_state::<E>(genesis_state_url, timeout, log)?
|
||||
.map(|state| state.genesis_validators_root())
|
||||
.map(Result::Ok)
|
||||
.transpose()
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a consolidated `ChainSpec` from the YAML config.
|
||||
@@ -138,15 +208,65 @@ impl Eth2NetworkConfig {
|
||||
}
|
||||
|
||||
/// Attempts to deserialize `self.beacon_state`, returning an error if it's missing or invalid.
|
||||
pub fn beacon_state<E: EthSpec>(&self) -> Result<BeaconState<E>, String> {
|
||||
///
|
||||
/// If the genesis state is configured to be downloaded from a URL, then the
|
||||
/// `genesis_state_url` will override the built-in list of download URLs.
|
||||
pub fn genesis_state<E: EthSpec>(
|
||||
&self,
|
||||
genesis_state_url: Option<&str>,
|
||||
timeout: Duration,
|
||||
log: &Logger,
|
||||
) -> Result<Option<BeaconState<E>>, String> {
|
||||
let spec = self.chain_spec::<E>()?;
|
||||
let genesis_state_bytes = self
|
||||
.genesis_state_bytes
|
||||
.as_ref()
|
||||
.ok_or("Genesis state is unknown")?;
|
||||
match &self.genesis_state_source {
|
||||
GenesisStateSource::Unknown => Ok(None),
|
||||
GenesisStateSource::IncludedBytes => {
|
||||
let state = self
|
||||
.genesis_state_bytes
|
||||
.as_ref()
|
||||
.map(|bytes| {
|
||||
BeaconState::from_ssz_bytes(bytes.as_ref(), &spec).map_err(|e| {
|
||||
format!("Built-in genesis state SSZ bytes are invalid: {:?}", e)
|
||||
})
|
||||
})
|
||||
.ok_or("Genesis state bytes missing from Eth2NetworkConfig")??;
|
||||
Ok(Some(state))
|
||||
}
|
||||
GenesisStateSource::Url {
|
||||
urls: built_in_urls,
|
||||
checksum,
|
||||
genesis_validators_root,
|
||||
} => {
|
||||
let checksum = Hash256::from_str(checksum).map_err(|e| {
|
||||
format!("Unable to parse genesis state bytes checksum: {:?}", e)
|
||||
})?;
|
||||
let bytes = if let Some(specified_url) = genesis_state_url {
|
||||
download_genesis_state(&[specified_url], timeout, checksum, log)
|
||||
} else {
|
||||
download_genesis_state(built_in_urls, timeout, checksum, log)
|
||||
}?;
|
||||
let state = BeaconState::from_ssz_bytes(bytes.as_ref(), &spec).map_err(|e| {
|
||||
format!("Downloaded genesis state SSZ bytes are invalid: {:?}", e)
|
||||
})?;
|
||||
|
||||
BeaconState::from_ssz_bytes(genesis_state_bytes, &spec)
|
||||
.map_err(|e| format!("Genesis state SSZ bytes are invalid: {:?}", e))
|
||||
let genesis_validators_root =
|
||||
Hash256::from_str(genesis_validators_root).map_err(|e| {
|
||||
format!(
|
||||
"Unable to parse genesis state genesis_validators_root: {:?}",
|
||||
e
|
||||
)
|
||||
})?;
|
||||
if state.genesis_validators_root() != genesis_validators_root {
|
||||
return Err(format!(
|
||||
"Downloaded genesis validators root {:?} does not match expected {:?}",
|
||||
state.genesis_validators_root(),
|
||||
genesis_validators_root
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Some(state))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Write the files to the directory.
|
||||
@@ -204,7 +324,7 @@ impl Eth2NetworkConfig {
|
||||
File::create(&file)
|
||||
.map_err(|e| format!("Unable to create {:?}: {:?}", file, e))
|
||||
.and_then(|mut file| {
|
||||
file.write_all(genesis_state_bytes)
|
||||
file.write_all(genesis_state_bytes.as_ref())
|
||||
.map_err(|e| format!("Unable to write {:?}: {:?}", file, e))
|
||||
})?;
|
||||
}
|
||||
@@ -240,7 +360,7 @@ impl Eth2NetworkConfig {
|
||||
|
||||
// The genesis state is a special case because it uses SSZ, not YAML.
|
||||
let genesis_file_path = base_dir.join(GENESIS_STATE_FILE);
|
||||
let genesis_state_bytes = if genesis_file_path.exists() {
|
||||
let (genesis_state_bytes, genesis_state_source) = if genesis_file_path.exists() {
|
||||
let mut bytes = vec![];
|
||||
File::open(&genesis_file_path)
|
||||
.map_err(|e| format!("Unable to open {:?}: {:?}", genesis_file_path, e))
|
||||
@@ -249,9 +369,15 @@ impl Eth2NetworkConfig {
|
||||
.map_err(|e| format!("Unable to read {:?}: {:?}", file, e))
|
||||
})?;
|
||||
|
||||
Some(bytes).filter(|bytes| !bytes.is_empty())
|
||||
let state = Some(bytes).filter(|bytes| !bytes.is_empty());
|
||||
let genesis_state_source = if state.is_some() {
|
||||
GenesisStateSource::IncludedBytes
|
||||
} else {
|
||||
GenesisStateSource::Unknown
|
||||
};
|
||||
(state, genesis_state_source)
|
||||
} else {
|
||||
None
|
||||
(None, GenesisStateSource::Unknown)
|
||||
};
|
||||
|
||||
let kzg_trusted_setup = get_trusted_setup_from_config(&config)?;
|
||||
@@ -259,13 +385,92 @@ impl Eth2NetworkConfig {
|
||||
Ok(Self {
|
||||
deposit_contract_deploy_block,
|
||||
boot_enr,
|
||||
genesis_state_bytes,
|
||||
genesis_state_source,
|
||||
genesis_state_bytes: genesis_state_bytes.map(Into::into),
|
||||
config,
|
||||
kzg_trusted_setup,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to download a genesis state from each of the `urls` in the order they
|
||||
/// are defined. Return `Ok` if any url returns a response that matches the
|
||||
/// given `checksum`.
|
||||
fn download_genesis_state(
|
||||
urls: &[&str],
|
||||
timeout: Duration,
|
||||
checksum: Hash256,
|
||||
log: &Logger,
|
||||
) -> Result<Vec<u8>, String> {
|
||||
if urls.is_empty() {
|
||||
return Err(
|
||||
"The genesis state is not present in the binary and there are no known download URLs. \
|
||||
Please use --checkpoint-sync-url or --genesis-state-url."
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
let mut errors = vec![];
|
||||
for url in urls {
|
||||
// URLs are always expected to be the base URL of a server that supports
|
||||
// the beacon-API.
|
||||
let url = parse_state_download_url(url)?;
|
||||
let redacted_url = SensitiveUrl::new(url.clone())
|
||||
.map(|url| url.to_string())
|
||||
.unwrap_or_else(|_| "<REDACTED>".to_string());
|
||||
|
||||
info!(
|
||||
log,
|
||||
"Downloading genesis state";
|
||||
"server" => &redacted_url,
|
||||
"timeout" => ?timeout,
|
||||
"info" => "this may take some time on testnets with large validator counts"
|
||||
);
|
||||
|
||||
let client = Client::new();
|
||||
let response = client
|
||||
.get(url)
|
||||
.header("Accept", "application/octet-stream")
|
||||
.timeout(timeout)
|
||||
.send()
|
||||
.and_then(|r| r.error_for_status().and_then(|r| r.bytes()));
|
||||
|
||||
match response {
|
||||
Ok(bytes) => {
|
||||
// Check the server response against our local checksum.
|
||||
if Sha256::digest(bytes.as_ref())[..] == checksum[..] {
|
||||
return Ok(bytes.into());
|
||||
} else {
|
||||
warn!(
|
||||
log,
|
||||
"Genesis state download failed";
|
||||
"server" => &redacted_url,
|
||||
"timeout" => ?timeout,
|
||||
);
|
||||
errors.push(format!(
|
||||
"Response from {} did not match local checksum",
|
||||
redacted_url
|
||||
))
|
||||
}
|
||||
}
|
||||
Err(e) => errors.push(PrettyReqwestError::from(e).to_string()),
|
||||
}
|
||||
}
|
||||
Err(format!(
|
||||
"Unable to download a genesis state from {} source(s): {}",
|
||||
errors.len(),
|
||||
errors.join(",")
|
||||
))
|
||||
}
|
||||
|
||||
/// Parses the `url` and joins the necessary state download path.
|
||||
fn parse_state_download_url(url: &str) -> Result<Url, String> {
|
||||
Url::parse(url)
|
||||
.map_err(|e| format!("Invalid genesis state URL: {:?}", e))?
|
||||
.join("eth/v2/debug/beacon/states/genesis")
|
||||
.map_err(|e| format!("Failed to append genesis state path to URL: {:?}", e))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -305,7 +510,9 @@ mod tests {
|
||||
#[test]
|
||||
fn mainnet_genesis_state() {
|
||||
let config = Eth2NetworkConfig::from_hardcoded_net(&MAINNET).unwrap();
|
||||
config.beacon_state::<E>().expect("beacon state can decode");
|
||||
config
|
||||
.genesis_state::<E>(None, Duration::from_secs(1), &logging::test_logger())
|
||||
.expect("beacon state can decode");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -319,10 +526,10 @@ mod tests {
|
||||
fn hard_coded_nets_work() {
|
||||
for net in HARDCODED_NETS {
|
||||
let config = Eth2NetworkConfig::from_hardcoded_net(net)
|
||||
.unwrap_or_else(|_| panic!("{:?}", net.name));
|
||||
.unwrap_or_else(|e| panic!("{:?}: {:?}", net.name, e));
|
||||
|
||||
// Ensure we can parse the YAML config to a chain spec.
|
||||
if net.name == types::GNOSIS {
|
||||
if config.config.preset_base == types::GNOSIS {
|
||||
config.chain_spec::<GnosisEthSpec>().unwrap();
|
||||
} else {
|
||||
config.chain_spec::<MainnetEthSpec>().unwrap();
|
||||
@@ -330,10 +537,25 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
config.genesis_state_bytes.is_some(),
|
||||
net.genesis_is_known,
|
||||
net.genesis_state_source == GenesisStateSource::IncludedBytes,
|
||||
"{:?}",
|
||||
net.name
|
||||
);
|
||||
|
||||
if let GenesisStateSource::Url {
|
||||
urls,
|
||||
checksum,
|
||||
genesis_validators_root,
|
||||
} = net.genesis_state_source
|
||||
{
|
||||
Hash256::from_str(checksum).expect("the checksum must be a valid 32-byte value");
|
||||
Hash256::from_str(genesis_validators_root)
|
||||
.expect("the GVR must be a valid 32-byte value");
|
||||
for url in urls {
|
||||
parse_state_download_url(url).expect("url must be valid");
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(config.config.config_name, Some(net.config_dir.to_string()));
|
||||
}
|
||||
}
|
||||
@@ -369,10 +591,20 @@ mod tests {
|
||||
let base_dir = temp_dir.path().join("my_testnet");
|
||||
let deposit_contract_deploy_block = 42;
|
||||
|
||||
let genesis_state_source = if genesis_state.is_some() {
|
||||
GenesisStateSource::IncludedBytes
|
||||
} else {
|
||||
GenesisStateSource::Unknown
|
||||
};
|
||||
|
||||
let testnet = Eth2NetworkConfig {
|
||||
deposit_contract_deploy_block,
|
||||
boot_enr,
|
||||
genesis_state_bytes: genesis_state.as_ref().map(Encode::as_ssz_bytes),
|
||||
genesis_state_source,
|
||||
genesis_state_bytes: genesis_state
|
||||
.as_ref()
|
||||
.map(Encode::as_ssz_bytes)
|
||||
.map(Into::into),
|
||||
config,
|
||||
kzg_trusted_setup: None,
|
||||
};
|
||||
|
||||
@@ -17,8 +17,8 @@ pub const VERSION: &str = git_version!(
|
||||
// NOTE: using --match instead of --exclude for compatibility with old Git
|
||||
"--match=thiswillnevermatchlol"
|
||||
],
|
||||
prefix = "Lighthouse/v4.3.0-",
|
||||
fallback = "Lighthouse/v4.3.0"
|
||||
prefix = "Lighthouse/v4.4.1-",
|
||||
fallback = "Lighthouse/v4.4.1"
|
||||
);
|
||||
|
||||
/// Returns `VERSION`, but with platform information appended to the end.
|
||||
|
||||
@@ -17,6 +17,6 @@ sloggers = { version = "2.1.1", features = ["json"] }
|
||||
slog-async = "2.7.0"
|
||||
take_mut = "0.2.2"
|
||||
parking_lot = "0.12.1"
|
||||
serde = "1.0.153"
|
||||
serde = "1.0.153"
|
||||
serde_json = "1.0.94"
|
||||
chrono = "0.4.23"
|
||||
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
|
||||
|
||||
@@ -55,6 +55,12 @@ impl fmt::Debug for PrettyReqwestError {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PrettyReqwestError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<reqwest::Error> for PrettyReqwestError {
|
||||
fn from(inner: reqwest::Error) -> Self {
|
||||
Self(inner)
|
||||
|
||||
@@ -10,10 +10,14 @@ pub fn set_builder_origins(
|
||||
default_origin: (IpAddr, u16),
|
||||
) -> Result<Builder, String> {
|
||||
if let Some(allow_origin) = allow_origin {
|
||||
let origins = allow_origin
|
||||
.split(',')
|
||||
.map(|s| verify_cors_origin_str(s).map(|_| s))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let mut origins = vec![];
|
||||
for origin in allow_origin.split(',') {
|
||||
verify_cors_origin_str(origin)?;
|
||||
if origin == "*" {
|
||||
return Ok(builder.allow_any_origin());
|
||||
}
|
||||
origins.push(origin)
|
||||
}
|
||||
Ok(builder.allow_origins(origins))
|
||||
} else {
|
||||
let origin = match default_origin.0 {
|
||||
|
||||
@@ -87,7 +87,7 @@ pub fn scrape_process_health_metrics() {
|
||||
// This will silently fail if we are unable to observe the health. This is desired behaviour
|
||||
// since we don't support `Health` for all platforms.
|
||||
if let Ok(health) = ProcessHealth::observe() {
|
||||
set_gauge(&PROCESS_NUM_THREADS, health.pid_num_threads as i64);
|
||||
set_gauge(&PROCESS_NUM_THREADS, health.pid_num_threads);
|
||||
set_gauge(&PROCESS_RES_MEM, health.pid_mem_resident_set_size as i64);
|
||||
set_gauge(&PROCESS_VIRT_MEM, health.pid_mem_virtual_memory_size as i64);
|
||||
set_gauge(&PROCESS_SECONDS, health.pid_process_seconds_total as i64);
|
||||
|
||||
Reference in New Issue
Block a user