diff --git a/.github/workflows/ethshadow.yml b/.github/workflows/lighthouse-geth.yaml similarity index 78% rename from .github/workflows/ethshadow.yml rename to .github/workflows/lighthouse-geth.yaml index 8c87621..895b6d3 100644 --- a/.github/workflows/ethshadow.yml +++ b/.github/workflows/lighthouse-geth.yaml @@ -1,4 +1,4 @@ -name: Ethshadow +name: Lighthouse and Geth on: push: @@ -66,7 +66,7 @@ jobs: cargo install --path . - name: Run Ethshadow run: | - ethshadow ci/config.yaml + ethshadow ci/lighthouse-geth.yaml - name: Check Ethshadow run: | block_received_lines=$(cat ./data/shadow/hosts/node*/lighthouse.*.stderr | grep "New block received" | wc -l) @@ -75,3 +75,9 @@ jobs: block_published_lines=$(cat ./data/shadow/hosts/node*/lighthouse.*.stderr | grep "Signed block published" | wc -l) echo "block_published_lines=$block_published_lines" test $block_published_lines -eq 24 + attestation_published_lines=$(cat ./data/shadow/hosts/node*/lighthouse.*.stderr | grep "Successfully published attestations" | wc -l) + echo "attestation_published_lines=$attestation_published_lines" + test $attestation_published_lines -gt 22 + chain_segment_imported_lines=$(cat ./data/shadow/hosts/node*/geth.*.stderr | grep "Imported new potential chain segment" | wc -l) + echo "chain_segment_imported_lines=$chain_segment_imported_lines" + test $chain_segment_imported_lines -gt 200 diff --git a/.github/workflows/prysm-geth.yaml b/.github/workflows/prysm-geth.yaml new file mode 100644 index 0000000..76db210 --- /dev/null +++ b/.github/workflows/prysm-geth.yaml @@ -0,0 +1,87 @@ +name: Prysm and Geth + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + schedule: + - cron: '0 0 * * *' + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Shadow's dependencies + run : | + # required dependencies + sudo apt-get install -y \ + cmake \ + findutils \ + libclang-dev \ + libc-dbg \ + libglib2.0-0 \ + libglib2.0-dev \ + make \ + netbase \ + python3 \ + python3-networkx \ + xz-utils \ + util-linux \ + gcc \ + g++ + - name: Install Shadow + run: | + git clone https://github.com/shadow/shadow.git + cd shadow + ./setup build --clean + ./setup install + cd .. + - name: Install Lighthouse's dependencies + run : | + sudo apt update + sudo apt install -y git gcc g++ make cmake pkg-config llvm-dev libclang-dev clang + - name: Install Lighthouse + run: | + git clone https://github.com/sigp/lighthouse.git + cd lighthouse + git checkout v5.3.0 + make + make install-lcli + lighthouse -V + cd .. + - name: Install Prysm + run: | + curl -L https://github.com/prysmaticlabs/prysm/releases/download/v5.3.0/beacon-chain-v5.3.0-linux-amd64 -o prysm + chmod +x prysm + - name: Install Geth + run: | + git clone https://github.com/ethereum/go-ethereum.git + cd go-ethereum + git checkout v1.14.11 + make all + sudo cp build/bin/geth /usr/local/bin/geth + sudo cp build/bin/bootnode /usr/local/bin/bootnode + geth -v + cd .. + - name: Install Ethshadow + run: | + cargo install --path . + - name: Run Ethshadow + run: | + ethshadow ci/prysm-geth.yaml + - name: Check Ethshadow + run: | + block_received_lines=$(cat ./data/shadow/hosts/node*/prysm.*.stderr | grep "Synced new block" | wc -l) + echo "block_received_lines=$block_received_lines" + test $block_received_lines -gt 200 + block_published_lines=$(cat ./data/shadow/hosts/node*/prysm.*.stderr | grep "Finished building block" | wc -l) + echo "block_published_lines=$block_published_lines" + test $block_published_lines -eq 24 + attestation_published_lines=$(cat ./data/shadow/hosts/node*/lighthouse.*.stderr | grep "Successfully published attestations" | wc -l) + echo "attestation_published_lines=$attestation_published_lines" + test $attestation_published_lines -gt 22 + chain_segment_imported_lines=$(cat ./data/shadow/hosts/node*/geth.*.stderr | grep "Imported new potential chain segment" | wc -l) + echo "chain_segment_imported_lines=$chain_segment_imported_lines" + test $chain_segment_imported_lines -gt 200 diff --git a/ci/config.yaml b/ci/lighthouse-geth.yaml similarity index 100% rename from ci/config.yaml rename to ci/lighthouse-geth.yaml diff --git a/ci/prysm-geth.yaml b/ci/prysm-geth.yaml new file mode 100644 index 0000000..bc31192 --- /dev/null +++ b/ci/prysm-geth.yaml @@ -0,0 +1,28 @@ +general: + # How much time should we simulate? + stop_time: 10 min + # Display a progress indicator? + progress: true + +ethereum: + # Distribute this many validators evenly across all nodes + validators: 30 + nodes: + - location: europe + reliability: reliable + tag: boot + clients: + el: geth_bootnode + cl: lighthouse_bootnode + - location: europe + reliability: reliable + clients: + el: geth + cl: prysm + vc: lighthouse_vc + count: + per_combination: 10 + clients: + prysm: + type: prysm + executable: ./prysm diff --git a/lib/src/clients/mod.rs b/lib/src/clients/mod.rs index 751c7f5..23cc1a6 100644 --- a/lib/src/clients/mod.rs +++ b/lib/src/clients/mod.rs @@ -18,6 +18,7 @@ pub mod lighthouse; pub mod lighthouse_bootnode; pub mod lighthouse_vc; pub mod prometheus; +pub mod prysm; pub mod reth; pub enum ValidatorDemand { diff --git a/lib/src/clients/prysm.rs b/lib/src/clients/prysm.rs new file mode 100644 index 0000000..077b056 --- /dev/null +++ b/lib/src/clients/prysm.rs @@ -0,0 +1,85 @@ +use crate::clients::Client; +use crate::clients::CommonParams; +use crate::clients::{BEACON_API_PORT, ENGINE_API_PORT}; +use crate::config::shadow::Process; +use crate::node::{NodeInfo, SimulationContext}; +use crate::validators::Validator; +use crate::Error; +use serde::Deserialize; +use std::collections::HashMap; + +const PORT: &str = "31000"; + +#[derive(Deserialize, Debug, Clone)] +#[serde(default)] +pub struct Prysm { + #[serde(flatten)] + pub common: CommonParams, + pub lower_target_peers: bool, +} + +impl Default for Prysm { + fn default() -> Self { + Self { + common: CommonParams::default(), + lower_target_peers: true, + } + } +} + +#[typetag::deserialize(name = "prysm")] +impl Client for Prysm { + fn add_to_node<'a>( + &self, + node: &NodeInfo<'a>, + ctx: &mut SimulationContext<'a>, + _validators: &[Validator], + ) -> Result { + if self.common.executable.is_empty() { + return Err(Error::MissingExecutable(String::from("prysm"))); + } + let dir = node.dir().join("prysm"); + let dir = dir.to_str().ok_or(Error::NonUTF8Path)?; + + let ip = node.ip(); + + ctx.add_cl_http_endpoint(format!("{ip}:{BEACON_API_PORT}")); + + let meta_dir = ctx.metadata_path().to_str().ok_or(Error::NonUTF8Path)?; + + let mut args = format!( + "--chain-config-file \"{meta_dir}/config.yaml\" \ + --accept-terms-of-use \ + --contract-deployment-block 0 \ + --deposit-contract 0x4242424242424242424242424242424242424242 \ + --genesis-state \"{meta_dir}/genesis.ssz\" + --datadir \"{dir}\" \ + --execution-endpoint http://localhost:{ENGINE_API_PORT} \ + --jwt-secret \"{}\" \ + --bootstrap-node {} \ + --p2p-tcp-port {PORT} \ + --p2p-udp-port {PORT} \ + --p2p-host-ip {ip} \ + --http-port {BEACON_API_PORT} \ + {} ", + ctx.jwt_path().to_str().ok_or(Error::NonUTF8Path)?, + ctx.cl_bootnode_enrs().join(" --bootstrap-node "), + self.common.extra_args, + ); + if self.lower_target_peers && ctx.num_cl_clients() <= 100 { + args.push_str(&format!("--p2p-max-peers {}", ctx.num_cl_clients() - 1)); + } + + Ok(Process { + path: self.common.executable.clone().into(), + args, + environment: HashMap::new(), + expected_final_state: "running".into(), + start_time: "5s".into(), + }) + } + + fn is_cl_client(&self) -> bool { + true + } +} diff --git a/lib/src/config/ethshadow.rs b/lib/src/config/ethshadow.rs index 6e2db00..72951a0 100644 --- a/lib/src/config/ethshadow.rs +++ b/lib/src/config/ethshadow.rs @@ -4,6 +4,7 @@ use crate::clients::lighthouse::Lighthouse; use crate::clients::lighthouse_bootnode::LighthouseBootnode; use crate::clients::lighthouse_vc::LighthouseValidatorClient; use crate::clients::prometheus::Prometheus; +use crate::clients::prysm::Prysm; use crate::clients::reth::Reth; use crate::clients::Client; use crate::config::one_or_many::OneOrMany; @@ -142,6 +143,7 @@ pub struct Genesis { pub capella_epoch: Option, pub deneb_epoch: Option, pub electra_epoch: Option, + pub fulu_epoch: Option, pub eip7594_epoch: Option, pub withdrawal_address: Option, pub delay: Option, @@ -346,6 +348,7 @@ impl EthShadowConfig { self.add_builtin_client("lighthouse_bootnode", LighthouseBootnode::default()); self.add_builtin_client("geth", Geth::default()); self.add_builtin_client("reth", Reth::default()); + self.add_builtin_client("prysm", Prysm::default()); self.add_builtin_client("lighthouse", Lighthouse::default()); self.add_builtin_client("lighthouse_vc", LighthouseValidatorClient::default()); self.add_builtin_client("prometheus", Prometheus::default()); @@ -445,7 +448,7 @@ pub struct Node<'a> { pub tag: Option<&'a str>, } -pub const DEFAULT_GENESIS_GEN_IMAGE: &str = "ethpandaops/ethereum-genesis-generator:3.3.7"; +pub const DEFAULT_GENESIS_GEN_IMAGE: &str = "ethpandaops/ethereum-genesis-generator:3.7.0"; pub const DEFAULT_MNEMONIC: &str = "\ iron oxygen will win \ iron oxygen will win \ diff --git a/lib/src/error.rs b/lib/src/error.rs index 0562ff9..cdcc4ee 100644 --- a/lib/src/error.rs +++ b/lib/src/error.rs @@ -17,6 +17,8 @@ pub enum Error { NonUTF8Path, #[error("Child process \"{0}\" returned failure")] ChildProcessFailure(String), + #[error("Custom executable path is required for client \"{0}\"")] + MissingExecutable(String), #[error("Missing info about the link from {0} to {1}")] MissingInfoForDestination(String, String), #[error( diff --git a/lib/src/genesis.rs b/lib/src/genesis.rs index b5246a4..28398a0 100644 --- a/lib/src/genesis.rs +++ b/lib/src/genesis.rs @@ -63,17 +63,26 @@ pub fn write_config( "ELECTRA_FORK_EPOCH", genesis.electra_epoch.unwrap_or(9_999_999), )?; - export(file, "EIP7594_FORK_VERSION", "0x70000000")?; + export(file, "FULU_FORK_VERSION", "0x70000000")?; + export( + file, + "FULU_FORK_EPOCH", + genesis.fulu_epoch.unwrap_or(9_999_999), + )?; + export(file, "EIP7594_FORK_VERSION", "0x80000000")?; export( file, "EIP7594_FORK_EPOCH", genesis.eip7594_epoch.unwrap_or(99_999_999), )?; - export(file, "WITHDRAWAL_TYPE", "0x01")?; + export(file, "WITHDRAWAL_TYPE", "0x00")?; export( file, "WITHDRAWAL_ADDRESS", - genesis.withdrawal_address.as_deref().unwrap_or(""), + genesis + .withdrawal_address + .as_deref() + .unwrap_or("0xf97e180c050e5Ab072211Ad2C213Eb5AEE4DF134"), )?; export(file, "GENESIS_TIMESTAMP", "946684800")?; export(file, "GENESIS_DELAY", genesis.delay.unwrap_or(300))?;