Replace ganache-cli with anvil (#3555)

## Issue Addressed

N/A

## Proposed Changes

Replace ganache-cli with anvil https://github.com/foundry-rs/foundry/blob/master/anvil/README.md
We can lose all js dependencies in CI as a consequence.

## Additional info
Also changes the ethers-rs version used in the execution layer (for the transaction reconstruction) to a newer one. This was necessary to get use the ethers utils for anvil. The fixed execution engine integration tests should catch any potential issues with the payload reconstruction after #3592 


Co-authored-by: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
Pawan Dhananjay 2023-05-15 07:22:02 +00:00
parent 3c029d48bf
commit 8a3eb4df9c
24 changed files with 465 additions and 506 deletions

View File

@ -25,8 +25,8 @@ jobs:
uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612 uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install ganache - name: Install anvil
run: npm install ganache@latest --global run: cargo install --git https://github.com/foundry-rs/foundry --locked anvil
# https://github.com/actions/cache/blob/main/examples.md#rust---cargo # https://github.com/actions/cache/blob/main/examples.md#rust---cargo
- uses: actions/cache@v3 - uses: actions/cache@v3

View File

@ -58,8 +58,8 @@ jobs:
uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612 uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install ganache - name: Install anvil
run: sudo npm install -g ganache run: cargo install --git https://github.com/foundry-rs/foundry --locked anvil
- name: Run tests in release - name: Run tests in release
run: make test-release run: make test-release
release-tests-windows: release-tests-windows:
@ -78,8 +78,8 @@ jobs:
run: | run: |
choco install python protoc visualstudio2019-workload-vctools -y choco install python protoc visualstudio2019-workload-vctools -y
npm config set msvs_version 2019 npm config set msvs_version 2019
- name: Install ganache - name: Install anvil
run: npm install -g ganache --loglevel verbose run: cargo install --git https://github.com/foundry-rs/foundry --locked anvil
- name: Install make - name: Install make
run: choco install -y make run: choco install -y make
- uses: KyleMayes/install-llvm-action@v1 - uses: KyleMayes/install-llvm-action@v1
@ -140,8 +140,8 @@ jobs:
uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612 uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install ganache - name: Install anvil
run: sudo npm install -g ganache run: cargo install --git https://github.com/foundry-rs/foundry --locked anvil
- name: Run tests in debug - name: Run tests in debug
run: make test-debug run: make test-debug
state-transition-vectors-ubuntu: state-transition-vectors-ubuntu:
@ -196,8 +196,8 @@ jobs:
uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612 uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install ganache - name: Install anvil
run: sudo npm install -g ganache run: cargo install --git https://github.com/foundry-rs/foundry --locked anvil
- name: Run the beacon chain sim that starts from an eth1 contract - name: Run the beacon chain sim that starts from an eth1 contract
run: cargo run --release --bin simulator eth1-sim run: cargo run --release --bin simulator eth1-sim
merge-transition-ubuntu: merge-transition-ubuntu:
@ -212,8 +212,8 @@ jobs:
uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612 uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install ganache - name: Install anvil
run: sudo npm install -g ganache run: cargo install --git https://github.com/foundry-rs/foundry --locked anvil
- name: Run the beacon chain sim and go through the merge transition - name: Run the beacon chain sim and go through the merge transition
run: cargo run --release --bin simulator eth1-sim --post-merge run: cargo run --release --bin simulator eth1-sim --post-merge
no-eth1-simulator-ubuntu: no-eth1-simulator-ubuntu:
@ -228,8 +228,8 @@ jobs:
uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612 uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install ganache - name: Install anvil
run: sudo npm install -g ganache run: cargo install --git https://github.com/foundry-rs/foundry --locked anvil
- name: Run the beacon chain sim without an eth1 connection - name: Run the beacon chain sim without an eth1 connection
run: cargo run --release --bin simulator no-eth1-sim run: cargo run --release --bin simulator no-eth1-sim
syncing-simulator-ubuntu: syncing-simulator-ubuntu:
@ -244,8 +244,8 @@ jobs:
uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612 uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install ganache - name: Install anvil
run: sudo npm install -g ganache run: cargo install --git https://github.com/foundry-rs/foundry --locked anvil
- name: Run the syncing simulator - name: Run the syncing simulator
run: cargo run --release --bin simulator syncing-sim run: cargo run --release --bin simulator syncing-sim
doppelganger-protection-test: doppelganger-protection-test:
@ -260,8 +260,8 @@ jobs:
uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612 uses: arduino/setup-protoc@e52d9eb8f7b63115df1ac544a1376fdbf5a39612
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install ganache - name: Install anvil
run: sudo npm install -g ganache run: cargo install --git https://github.com/foundry-rs/foundry --locked anvil
- name: Install lighthouse and lcli - name: Install lighthouse and lcli
run: | run: |
make make

235
Cargo.lock generated
View File

@ -2,6 +2,16 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "Inflector"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
dependencies = [
"lazy_static",
"regex",
]
[[package]] [[package]]
name = "account_manager" name = "account_manager"
version = "0.3.5" version = "0.3.5"
@ -934,6 +944,38 @@ dependencies = [
"tree_hash", "tree_hash",
] ]
[[package]]
name = "camino"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2"
dependencies = [
"serde",
]
[[package]]
name = "cargo-platform"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27"
dependencies = [
"serde",
]
[[package]]
name = "cargo_metadata"
version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07"
dependencies = [
"camino",
"cargo-platform",
"semver 1.0.17",
"serde",
"serde_json",
"thiserror",
]
[[package]] [[package]]
name = "cast" name = "cast"
version = "0.3.0" version = "0.3.0"
@ -1429,9 +1471,9 @@ dependencies = [
[[package]] [[package]]
name = "curve25519-dalek" name = "curve25519-dalek"
version = "4.0.0-rc.2" version = "4.0.0-rc.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03d928d978dbec61a1167414f5ec534f24bea0d7a0d24dd9b6233d3d8223e585" checksum = "8d4ba9852b42210c7538b75484f9daa0655e9a3ac04f693747bb0f02cf3cfe16"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"fiat-crypto", "fiat-crypto",
@ -1911,6 +1953,12 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65d09067bfacaa79114679b279d7f5885b53295b1e2cfb4e79c8e4bd3d633169" checksum = "65d09067bfacaa79114679b279d7f5885b53295b1e2cfb4e79c8e4bd3d633169"
[[package]]
name = "dunce"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c"
[[package]] [[package]]
name = "ecdsa" name = "ecdsa"
version = "0.14.8" version = "0.14.8"
@ -2170,7 +2218,6 @@ dependencies = [
"tokio", "tokio",
"tree_hash", "tree_hash",
"types", "types",
"web3",
] ]
[[package]] [[package]]
@ -2178,11 +2225,14 @@ name = "eth1_test_rig"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"deposit_contract", "deposit_contract",
"ethers-contract",
"ethers-core",
"ethers-providers",
"hex",
"serde_json", "serde_json",
"tokio", "tokio",
"types", "types",
"unused_port", "unused_port",
"web3",
] ]
[[package]] [[package]]
@ -2469,6 +2519,65 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "ethers-contract"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9c3c3e119a89f0a9a1e539e7faecea815f74ddcf7c90d0b00d1f524db2fdc9c"
dependencies = [
"ethers-contract-abigen",
"ethers-contract-derive",
"ethers-core",
"ethers-providers",
"futures-util",
"hex",
"once_cell",
"pin-project",
"serde",
"serde_json",
"thiserror",
]
[[package]]
name = "ethers-contract-abigen"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d4e5ad46aede34901f71afdb7bb555710ed9613d88d644245c657dc371aa228"
dependencies = [
"Inflector",
"cfg-if",
"dunce",
"ethers-core",
"eyre",
"getrandom 0.2.8",
"hex",
"proc-macro2",
"quote",
"regex",
"reqwest",
"serde",
"serde_json",
"syn 1.0.109",
"toml",
"url",
"walkdir",
]
[[package]]
name = "ethers-contract-derive"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f192e8e4cf2b038318aae01e94e7644e0659a76219e94bcd3203df744341d61f"
dependencies = [
"ethers-contract-abigen",
"ethers-core",
"hex",
"proc-macro2",
"quote",
"serde_json",
"syn 1.0.109",
]
[[package]] [[package]]
name = "ethers-core" name = "ethers-core"
version = "1.0.2" version = "1.0.2"
@ -2477,12 +2586,14 @@ checksum = "ade3e9c97727343984e1ceada4fdab11142d2ee3472d2c67027d56b1251d4f15"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"bytes", "bytes",
"cargo_metadata",
"chrono", "chrono",
"elliptic-curve", "elliptic-curve",
"ethabi 18.0.0", "ethabi 18.0.0",
"generic-array", "generic-array",
"hex", "hex",
"k256", "k256",
"once_cell",
"open-fastrlp", "open-fastrlp",
"rand 0.8.5", "rand 0.8.5",
"rlp", "rlp",
@ -2490,6 +2601,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"strum", "strum",
"syn 1.0.109",
"thiserror", "thiserror",
"tiny-keccak", "tiny-keccak",
"unicode-xid", "unicode-xid",
@ -2621,6 +2733,16 @@ dependencies = [
"futures", "futures",
] ]
[[package]]
name = "eyre"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb"
dependencies = [
"indenter",
"once_cell",
]
[[package]] [[package]]
name = "fallible-iterator" name = "fallible-iterator"
version = "0.2.0" version = "0.2.0"
@ -3589,6 +3711,12 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "indenter"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.9.3" version = "1.9.3"
@ -3741,21 +3869,6 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "jsonrpc-core"
version = "18.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb"
dependencies = [
"futures",
"futures-executor",
"futures-util",
"log",
"serde",
"serde_derive",
"serde_json",
]
[[package]] [[package]]
name = "jsonwebtoken" name = "jsonwebtoken"
version = "8.3.0" version = "8.3.0"
@ -3851,7 +3964,6 @@ dependencies = [
"tree_hash", "tree_hash",
"types", "types",
"validator_dir", "validator_dir",
"web3",
] ]
[[package]] [[package]]
@ -6949,24 +7061,6 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "secp256k1"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c42e6f1735c5f00f51e43e28d6634141f2bcad10931b2609ddd74a86d751260"
dependencies = [
"secp256k1-sys",
]
[[package]]
name = "secp256k1-sys"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957da2573cde917463ece3570eab4a0b3f19de6f1646cde62e6fd3868f566036"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "2.8.2" version = "2.8.2"
@ -7004,6 +7098,9 @@ name = "semver"
version = "1.0.17" version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "semver-parser" name = "semver-parser"
@ -7485,14 +7582,14 @@ checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831"
[[package]] [[package]]
name = "snow" name = "snow"
version = "0.9.0" version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "774d05a3edae07ce6d68ea6984f3c05e9bba8927e3dd591e3b479e5b03213d0d" checksum = "5ccba027ba85743e09d15c03296797cad56395089b832b48b5a5217880f57733"
dependencies = [ dependencies = [
"aes-gcm 0.9.4", "aes-gcm 0.9.4",
"blake2", "blake2",
"chacha20poly1305", "chacha20poly1305",
"curve25519-dalek 4.0.0-rc.2", "curve25519-dalek 4.0.0-rc.1",
"rand_core 0.6.4", "rand_core 0.6.4",
"ring", "ring",
"rustc_version 0.4.0", "rustc_version 0.4.0",
@ -9142,53 +9239,6 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "web3"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44f258e254752d210b84fe117b31f1e3cc9cbf04c0d747eb7f8cf7cf5e370f6d"
dependencies = [
"arrayvec",
"base64 0.13.1",
"bytes",
"derive_more",
"ethabi 16.0.0",
"ethereum-types 0.12.1",
"futures",
"futures-timer",
"headers",
"hex",
"idna 0.2.3",
"jsonrpc-core",
"log",
"once_cell",
"parking_lot 0.12.1",
"pin-project",
"reqwest",
"rlp",
"secp256k1",
"serde",
"serde_json",
"soketto",
"tiny-keccak",
"tokio",
"tokio-util 0.6.10",
"url",
"web3-async-native-tls",
]
[[package]]
name = "web3-async-native-tls"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f6d8d1636b2627fe63518d5a9b38a569405d9c9bc665c43c9c341de57227ebb"
dependencies = [
"native-tls",
"thiserror",
"tokio",
"url",
]
[[package]] [[package]]
name = "web3signer_tests" name = "web3signer_tests"
version = "0.1.0" version = "0.1.0"
@ -9338,7 +9388,7 @@ dependencies = [
"tokio", "tokio",
"webpki 0.21.4", "webpki 0.21.4",
"webrtc-util", "webrtc-util",
"x25519-dalek 2.0.0-rc.2", "x25519-dalek 2.0.0-pre.1",
"x509-parser 0.13.2", "x509-parser 0.13.2",
] ]
@ -9718,13 +9768,12 @@ dependencies = [
[[package]] [[package]]
name = "x25519-dalek" name = "x25519-dalek"
version = "2.0.0-rc.2" version = "2.0.0-pre.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fabd6e16dd08033932fc3265ad4510cc2eab24656058a6dcb107ffe274abcc95" checksum = "e5da623d8af10a62342bcbbb230e33e58a63255a58012f8653c578e54bab48df"
dependencies = [ dependencies = [
"curve25519-dalek 4.0.0-rc.2", "curve25519-dalek 3.2.0",
"rand_core 0.6.4", "rand_core 0.6.4",
"serde",
"zeroize", "zeroize",
] ]

View File

@ -7,7 +7,6 @@ edition = "2021"
[dev-dependencies] [dev-dependencies]
eth1_test_rig = { path = "../../testing/eth1_test_rig" } eth1_test_rig = { path = "../../testing/eth1_test_rig" }
serde_yaml = "0.8.13" serde_yaml = "0.8.13"
web3 = { version = "0.18.0", default-features = false, features = ["http-tls", "signing", "ws-tls-tokio"] }
sloggers = { version = "2.1.1", features = ["json"] } sloggers = { version = "2.1.1", features = ["json"] }
environment = { path = "../../lighthouse/environment" } environment = { path = "../../lighthouse/environment" }

View File

@ -2,7 +2,7 @@
use environment::{Environment, EnvironmentBuilder}; use environment::{Environment, EnvironmentBuilder};
use eth1::{Config, Eth1Endpoint, Service}; use eth1::{Config, Eth1Endpoint, Service};
use eth1::{DepositCache, DEFAULT_CHAIN_ID}; use eth1::{DepositCache, DEFAULT_CHAIN_ID};
use eth1_test_rig::GanacheEth1Instance; use eth1_test_rig::{AnvilEth1Instance, Http, Middleware, Provider};
use execution_layer::http::{deposit_methods::*, HttpJsonRpc, Log}; use execution_layer::http::{deposit_methods::*, HttpJsonRpc, Log};
use merkle_proof::verify_merkle_proof; use merkle_proof::verify_merkle_proof;
use sensitive_url::SensitiveUrl; use sensitive_url::SensitiveUrl;
@ -12,7 +12,6 @@ use std::ops::Range;
use std::time::Duration; use std::time::Duration;
use tree_hash::TreeHash; use tree_hash::TreeHash;
use types::{DepositData, EthSpec, Hash256, Keypair, MainnetEthSpec, MinimalEthSpec, Signature}; use types::{DepositData, EthSpec, Hash256, Keypair, MainnetEthSpec, MinimalEthSpec, Signature};
use web3::{transports::Http, Web3};
const DEPOSIT_CONTRACT_TREE_DEPTH: usize = 32; const DEPOSIT_CONTRACT_TREE_DEPTH: usize = 32;
@ -53,7 +52,7 @@ fn random_deposit_data() -> DepositData {
/// Blocking operation to get the deposit logs from the `deposit_contract`. /// Blocking operation to get the deposit logs from the `deposit_contract`.
async fn blocking_deposit_logs( async fn blocking_deposit_logs(
client: &HttpJsonRpc, client: &HttpJsonRpc,
eth1: &GanacheEth1Instance, eth1: &AnvilEth1Instance,
range: Range<u64>, range: Range<u64>,
) -> Vec<Log> { ) -> Vec<Log> {
client client
@ -65,7 +64,7 @@ async fn blocking_deposit_logs(
/// Blocking operation to get the deposit root from the `deposit_contract`. /// Blocking operation to get the deposit root from the `deposit_contract`.
async fn blocking_deposit_root( async fn blocking_deposit_root(
client: &HttpJsonRpc, client: &HttpJsonRpc,
eth1: &GanacheEth1Instance, eth1: &AnvilEth1Instance,
block_number: u64, block_number: u64,
) -> Option<Hash256> { ) -> Option<Hash256> {
client client
@ -77,7 +76,7 @@ async fn blocking_deposit_root(
/// Blocking operation to get the deposit count from the `deposit_contract`. /// Blocking operation to get the deposit count from the `deposit_contract`.
async fn blocking_deposit_count( async fn blocking_deposit_count(
client: &HttpJsonRpc, client: &HttpJsonRpc,
eth1: &GanacheEth1Instance, eth1: &AnvilEth1Instance,
block_number: u64, block_number: u64,
) -> Option<u64> { ) -> Option<u64> {
client client
@ -86,16 +85,16 @@ async fn blocking_deposit_count(
.expect("should get deposit count") .expect("should get deposit count")
} }
async fn get_block_number(web3: &Web3<Http>) -> u64 { async fn get_block_number(client: &Provider<Http>) -> u64 {
web3.eth() client
.block_number() .get_block_number()
.await .await
.map(|v| v.as_u64()) .map(|v| v.as_u64())
.expect("should get block number") .expect("should get block number")
} }
async fn new_ganache_instance() -> Result<GanacheEth1Instance, String> { async fn new_anvil_instance() -> Result<AnvilEth1Instance, String> {
GanacheEth1Instance::new(DEFAULT_CHAIN_ID.into()).await AnvilEth1Instance::new(DEFAULT_CHAIN_ID.into()).await
} }
mod eth1_cache { mod eth1_cache {
@ -108,13 +107,13 @@ mod eth1_cache {
let log = null_logger(); let log = null_logger();
for follow_distance in 0..3 { for follow_distance in 0..3 {
let eth1 = new_ganache_instance() let eth1 = new_anvil_instance()
.await .await
.expect("should start eth1 environment"); .expect("should start eth1 environment");
let deposit_contract = &eth1.deposit_contract; let deposit_contract = &eth1.deposit_contract;
let web3 = eth1.web3(); let anvil_client = eth1.json_rpc_client();
let initial_block_number = get_block_number(&web3).await; let initial_block_number = get_block_number(&anvil_client).await;
let config = Config { let config = Config {
endpoint: Eth1Endpoint::NoAuth( endpoint: Eth1Endpoint::NoAuth(
@ -146,7 +145,7 @@ mod eth1_cache {
}; };
for _ in 0..blocks { for _ in 0..blocks {
eth1.ganache.evm_mine().await.expect("should mine block"); eth1.anvil.evm_mine().await.expect("should mine block");
} }
service service
@ -189,11 +188,11 @@ mod eth1_cache {
async { async {
let log = null_logger(); let log = null_logger();
let eth1 = new_ganache_instance() let eth1 = new_anvil_instance()
.await .await
.expect("should start eth1 environment"); .expect("should start eth1 environment");
let deposit_contract = &eth1.deposit_contract; let deposit_contract = &eth1.deposit_contract;
let web3 = eth1.web3(); let anvil_client = eth1.json_rpc_client();
let cache_len = 4; let cache_len = 4;
@ -203,7 +202,7 @@ mod eth1_cache {
SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap(), SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap(),
), ),
deposit_contract_address: deposit_contract.address(), deposit_contract_address: deposit_contract.address(),
lowest_cached_block_number: get_block_number(&web3).await, lowest_cached_block_number: get_block_number(&anvil_client).await,
follow_distance: 0, follow_distance: 0,
block_cache_truncation: Some(cache_len), block_cache_truncation: Some(cache_len),
..Config::default() ..Config::default()
@ -216,7 +215,7 @@ mod eth1_cache {
let blocks = cache_len * 2; let blocks = cache_len * 2;
for _ in 0..blocks { for _ in 0..blocks {
eth1.ganache.evm_mine().await.expect("should mine block") eth1.anvil.evm_mine().await.expect("should mine block")
} }
service service
@ -244,11 +243,11 @@ mod eth1_cache {
async { async {
let log = null_logger(); let log = null_logger();
let eth1 = new_ganache_instance() let eth1 = new_anvil_instance()
.await .await
.expect("should start eth1 environment"); .expect("should start eth1 environment");
let deposit_contract = &eth1.deposit_contract; let deposit_contract = &eth1.deposit_contract;
let web3 = eth1.web3(); let anvil_client = eth1.json_rpc_client();
let cache_len = 4; let cache_len = 4;
@ -258,7 +257,7 @@ mod eth1_cache {
SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap(), SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap(),
), ),
deposit_contract_address: deposit_contract.address(), deposit_contract_address: deposit_contract.address(),
lowest_cached_block_number: get_block_number(&web3).await, lowest_cached_block_number: get_block_number(&anvil_client).await,
follow_distance: 0, follow_distance: 0,
block_cache_truncation: Some(cache_len), block_cache_truncation: Some(cache_len),
..Config::default() ..Config::default()
@ -270,7 +269,7 @@ mod eth1_cache {
for _ in 0..4u8 { for _ in 0..4u8 {
for _ in 0..cache_len / 2 { for _ in 0..cache_len / 2 {
eth1.ganache.evm_mine().await.expect("should mine block") eth1.anvil.evm_mine().await.expect("should mine block")
} }
service service
.update_deposit_cache(None) .update_deposit_cache(None)
@ -298,11 +297,11 @@ mod eth1_cache {
let n = 16; let n = 16;
let eth1 = new_ganache_instance() let eth1 = new_anvil_instance()
.await .await
.expect("should start eth1 environment"); .expect("should start eth1 environment");
let deposit_contract = &eth1.deposit_contract; let deposit_contract = &eth1.deposit_contract;
let web3 = eth1.web3(); let anvil_client = eth1.json_rpc_client();
let service = Service::new( let service = Service::new(
Config { Config {
@ -310,7 +309,7 @@ mod eth1_cache {
SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap(), SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap(),
), ),
deposit_contract_address: deposit_contract.address(), deposit_contract_address: deposit_contract.address(),
lowest_cached_block_number: get_block_number(&web3).await, lowest_cached_block_number: get_block_number(&anvil_client).await,
follow_distance: 0, follow_distance: 0,
..Config::default() ..Config::default()
}, },
@ -320,7 +319,7 @@ mod eth1_cache {
.unwrap(); .unwrap();
for _ in 0..n { for _ in 0..n {
eth1.ganache.evm_mine().await.expect("should mine block") eth1.anvil.evm_mine().await.expect("should mine block")
} }
futures::try_join!( futures::try_join!(
@ -341,6 +340,7 @@ mod eth1_cache {
} }
mod deposit_tree { mod deposit_tree {
use super::*; use super::*;
#[tokio::test] #[tokio::test]
@ -350,13 +350,13 @@ mod deposit_tree {
let n = 4; let n = 4;
let eth1 = new_ganache_instance() let eth1 = new_anvil_instance()
.await .await
.expect("should start eth1 environment"); .expect("should start eth1 environment");
let deposit_contract = &eth1.deposit_contract; let deposit_contract = &eth1.deposit_contract;
let web3 = eth1.web3(); let anvil_client = eth1.json_rpc_client();
let start_block = get_block_number(&web3).await; let start_block = get_block_number(&anvil_client).await;
let service = Service::new( let service = Service::new(
Config { Config {
@ -431,13 +431,13 @@ mod deposit_tree {
let n = 8; let n = 8;
let eth1 = new_ganache_instance() let eth1 = new_anvil_instance()
.await .await
.expect("should start eth1 environment"); .expect("should start eth1 environment");
let deposit_contract = &eth1.deposit_contract; let deposit_contract = &eth1.deposit_contract;
let web3 = eth1.web3(); let anvil_client = eth1.json_rpc_client();
let start_block = get_block_number(&web3).await; let start_block = get_block_number(&anvil_client).await;
let service = Service::new( let service = Service::new(
Config { Config {
@ -484,11 +484,12 @@ mod deposit_tree {
let deposits: Vec<_> = (0..n).map(|_| random_deposit_data()).collect(); let deposits: Vec<_> = (0..n).map(|_| random_deposit_data()).collect();
let eth1 = new_ganache_instance() let eth1 = new_anvil_instance()
.await .await
.expect("should start eth1 environment"); .expect("should start eth1 environment");
let deposit_contract = &eth1.deposit_contract; let deposit_contract = &eth1.deposit_contract;
let web3 = eth1.web3(); let anvil_client = eth1.json_rpc_client();
let mut deposit_roots = vec![]; let mut deposit_roots = vec![];
let mut deposit_counts = vec![]; let mut deposit_counts = vec![];
@ -502,7 +503,7 @@ mod deposit_tree {
.deposit(deposit.clone()) .deposit(deposit.clone())
.await .await
.expect("should perform a deposit"); .expect("should perform a deposit");
let block_number = get_block_number(&web3).await; let block_number = get_block_number(&anvil_client).await;
deposit_roots.push( deposit_roots.push(
blocking_deposit_root(&client, &eth1, block_number) blocking_deposit_root(&client, &eth1, block_number)
.await .await
@ -518,7 +519,7 @@ mod deposit_tree {
let mut tree = DepositCache::default(); let mut tree = DepositCache::default();
// Pull all the deposit logs from the contract. // Pull all the deposit logs from the contract.
let block_number = get_block_number(&web3).await; let block_number = get_block_number(&anvil_client).await;
let logs: Vec<_> = blocking_deposit_logs(&client, &eth1, 0..block_number) let logs: Vec<_> = blocking_deposit_logs(&client, &eth1, 0..block_number)
.await .await
.iter() .iter()
@ -593,15 +594,15 @@ mod http {
#[tokio::test] #[tokio::test]
async fn incrementing_deposits() { async fn incrementing_deposits() {
async { async {
let eth1 = new_ganache_instance() let eth1 = new_anvil_instance()
.await .await
.expect("should start eth1 environment"); .expect("should start eth1 environment");
let deposit_contract = &eth1.deposit_contract; let deposit_contract = &eth1.deposit_contract;
let web3 = eth1.web3(); let anvil_client = eth1.json_rpc_client();
let client = let client =
HttpJsonRpc::new(SensitiveUrl::parse(&eth1.endpoint()).unwrap(), None).unwrap(); HttpJsonRpc::new(SensitiveUrl::parse(&eth1.endpoint()).unwrap(), None).unwrap();
let block_number = get_block_number(&web3).await; let block_number = get_block_number(&anvil_client).await;
let logs = blocking_deposit_logs(&client, &eth1, 0..block_number).await; let logs = blocking_deposit_logs(&client, &eth1, 0..block_number).await;
assert_eq!(logs.len(), 0); assert_eq!(logs.len(), 0);
@ -616,10 +617,10 @@ mod http {
); );
for i in 1..=8 { for i in 1..=8 {
eth1.ganache eth1.anvil
.increase_time(1) .increase_time(1)
.await .await
.expect("should be able to increase time on ganache"); .expect("should be able to increase time on anvil");
deposit_contract deposit_contract
.deposit(random_deposit_data()) .deposit(random_deposit_data())
@ -627,7 +628,7 @@ mod http {
.expect("should perform a deposit"); .expect("should perform a deposit");
// Check the logs. // Check the logs.
let block_number = get_block_number(&web3).await; let block_number = get_block_number(&anvil_client).await;
let logs = blocking_deposit_logs(&client, &eth1, 0..block_number).await; let logs = blocking_deposit_logs(&client, &eth1, 0..block_number).await;
assert_eq!(logs.len(), i, "the number of logs should be as expected"); assert_eq!(logs.len(), i, "the number of logs should be as expected");
@ -690,13 +691,13 @@ mod fast {
async { async {
let log = null_logger(); let log = null_logger();
let eth1 = new_ganache_instance() let eth1 = new_anvil_instance()
.await .await
.expect("should start eth1 environment"); .expect("should start eth1 environment");
let deposit_contract = &eth1.deposit_contract; let deposit_contract = &eth1.deposit_contract;
let web3 = eth1.web3(); let anvil_client = eth1.json_rpc_client();
let now = get_block_number(&web3).await; let now = get_block_number(&anvil_client).await;
let spec = MainnetEthSpec::default_spec(); let spec = MainnetEthSpec::default_spec();
let service = Service::new( let service = Service::new(
Config { Config {
@ -724,7 +725,7 @@ mod fast {
.await .await
.expect("should perform a deposit"); .expect("should perform a deposit");
// Mine an extra block between deposits to test for corner cases // Mine an extra block between deposits to test for corner cases
eth1.ganache.evm_mine().await.expect("should mine block"); eth1.anvil.evm_mine().await.expect("should mine block");
} }
service service
@ -737,7 +738,7 @@ mod fast {
"should have imported n deposits" "should have imported n deposits"
); );
for block_num in 0..=get_block_number(&web3).await { for block_num in 0..=get_block_number(&anvil_client).await {
let expected_deposit_count = let expected_deposit_count =
blocking_deposit_count(&client, &eth1, block_num).await; blocking_deposit_count(&client, &eth1, block_num).await;
let expected_deposit_root = blocking_deposit_root(&client, &eth1, block_num).await; let expected_deposit_root = blocking_deposit_root(&client, &eth1, block_num).await;
@ -773,13 +774,13 @@ mod persist {
async { async {
let log = null_logger(); let log = null_logger();
let eth1 = new_ganache_instance() let eth1 = new_anvil_instance()
.await .await
.expect("should start eth1 environment"); .expect("should start eth1 environment");
let deposit_contract = &eth1.deposit_contract; let deposit_contract = &eth1.deposit_contract;
let web3 = eth1.web3(); let anvil_client = eth1.json_rpc_client();
let now = get_block_number(&web3).await; let now = get_block_number(&anvil_client).await;
let config = Config { let config = Config {
endpoint: Eth1Endpoint::NoAuth( endpoint: Eth1Endpoint::NoAuth(
SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap(), SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap(),

View File

@ -1,11 +1,11 @@
//! NOTE: These tests will not pass unless ganache is running on `ENDPOINT` (see below). //! NOTE: These tests will not pass unless an anvil is running on `ENDPOINT` (see below).
//! //!
//! You can start a suitable instance using the `ganache_test_node.sh` script in the `scripts` //! You can start a suitable instance using the `anvil_test_node.sh` script in the `scripts`
//! dir in the root of the `lighthouse` repo. //! dir in the root of the `lighthouse` repo.
#![cfg(test)] #![cfg(test)]
use environment::{Environment, EnvironmentBuilder}; use environment::{Environment, EnvironmentBuilder};
use eth1::{Eth1Endpoint, DEFAULT_CHAIN_ID}; use eth1::{Eth1Endpoint, DEFAULT_CHAIN_ID};
use eth1_test_rig::{DelayThenDeposit, GanacheEth1Instance}; use eth1_test_rig::{AnvilEth1Instance, DelayThenDeposit, Middleware};
use genesis::{Eth1Config, Eth1GenesisService}; use genesis::{Eth1Config, Eth1GenesisService};
use sensitive_url::SensitiveUrl; use sensitive_url::SensitiveUrl;
use state_processing::is_valid_genesis_state; use state_processing::is_valid_genesis_state;
@ -29,15 +29,14 @@ fn basic() {
let mut spec = env.eth2_config().spec.clone(); let mut spec = env.eth2_config().spec.clone();
env.runtime().block_on(async { env.runtime().block_on(async {
let eth1 = GanacheEth1Instance::new(DEFAULT_CHAIN_ID.into()) let eth1 = AnvilEth1Instance::new(DEFAULT_CHAIN_ID.into())
.await .await
.expect("should start eth1 environment"); .expect("should start eth1 environment");
let deposit_contract = &eth1.deposit_contract; let deposit_contract = &eth1.deposit_contract;
let web3 = eth1.web3(); let client = eth1.json_rpc_client();
let now = web3 let now = client
.eth() .get_block_number()
.block_number()
.await .await
.map(|v| v.as_u64()) .map(|v| v.as_u64())
.expect("should get block number"); .expect("should get block number");
@ -89,7 +88,7 @@ fn basic() {
.map(|(_, state)| state) .map(|(_, state)| state)
.expect("should finish waiting for genesis"); .expect("should finish waiting for genesis");
// Note: using ganache these deposits are 1-per-block, therefore we know there should only be // Note: using anvil these deposits are 1-per-block, therefore we know there should only be
// the minimum number of validators. // the minimum number of validators.
assert_eq!( assert_eq!(
state.validators().len(), state.validators().len(),

View File

@ -9,9 +9,9 @@ particularly useful for development but still a good way to ensure you have the
base dependencies. base dependencies.
The additional requirements for developers are: The additional requirements for developers are:
- [`ganache v7`](https://github.com/trufflesuite/ganache). This is used to - [`anvil`](https://github.com/foundry-rs/foundry/tree/master/anvil). This is used to
simulate the execution chain during tests. You'll get failures during tests if you simulate the execution chain during tests. You'll get failures during tests if you
don't have `ganache` available on your `PATH` or if ganache is older than v7. don't have `anvil` available on your `PATH`.
- [`cmake`](https://cmake.org/cmake/help/latest/command/install.html). Used by - [`cmake`](https://cmake.org/cmake/help/latest/command/install.html). Used by
some dependencies. See [`Installation Guide`](./installation.md) for more info. some dependencies. See [`Installation Guide`](./installation.md) for more info.
- [`protoc`](https://github.com/protocolbuffers/protobuf/releases) required for - [`protoc`](https://github.com/protocolbuffers/protobuf/releases) required for

View File

@ -34,7 +34,6 @@ lighthouse_version = { path = "../common/lighthouse_version" }
directory = { path = "../common/directory" } directory = { path = "../common/directory" }
account_utils = { path = "../common/account_utils" } account_utils = { path = "../common/account_utils" }
eth2_wallet = { path = "../crypto/eth2_wallet" } eth2_wallet = { path = "../crypto/eth2_wallet" }
web3 = { version = "0.18.0", default-features = false, features = ["http-tls", "signing", "ws-tls-tokio"] }
eth1_test_rig = { path = "../testing/eth1_test_rig" } eth1_test_rig = { path = "../testing/eth1_test_rig" }
sensitive_url = { path = "../common/sensitive_url" } sensitive_url = { path = "../common/sensitive_url" }
eth2 = { path = "../common/eth2" } eth2 = { path = "../common/eth2" }

View File

@ -2,19 +2,18 @@ use clap::ArgMatches;
use environment::Environment; use environment::Environment;
use types::EthSpec; use types::EthSpec;
use web3::{transports::Http, Web3}; use eth1_test_rig::{Http, Provider};
pub fn run<T: EthSpec>(env: Environment<T>, matches: &ArgMatches<'_>) -> Result<(), String> { pub fn run<T: EthSpec>(env: Environment<T>, matches: &ArgMatches<'_>) -> Result<(), String> {
let eth1_http: String = clap_utils::parse_required(matches, "eth1-http")?; let eth1_http: String = clap_utils::parse_required(matches, "eth1-http")?;
let confirmations: usize = clap_utils::parse_required(matches, "confirmations")?; let confirmations: usize = clap_utils::parse_required(matches, "confirmations")?;
let validator_count: Option<usize> = clap_utils::parse_optional(matches, "validator-count")?; let validator_count: Option<usize> = clap_utils::parse_optional(matches, "validator-count")?;
let transport = let client = Provider::<Http>::try_from(&eth1_http)
Http::new(&eth1_http).map_err(|e| format!("Unable to connect to eth1 HTTP: {:?}", e))?; .map_err(|e| format!("Unable to connect to eth1 HTTP: {:?}", e))?;
let web3 = Web3::new(transport);
env.runtime().block_on(async { env.runtime().block_on(async {
let contract = eth1_test_rig::DepositContract::deploy(web3, confirmations, None) let contract = eth1_test_rig::DepositContract::deploy(client, confirmations, None)
.await .await
.map_err(|e| format!("Failed to deploy deposit contract: {:?}", e))?; .map_err(|e| format!("Failed to deploy deposit contract: {:?}", e))?;

View File

@ -28,10 +28,6 @@ use tempfile::{tempdir, TempDir};
use types::{Keypair, PublicKey}; use types::{Keypair, PublicKey};
use validator_dir::ValidatorDir; use validator_dir::ValidatorDir;
// TODO: create tests for the `lighthouse account validator deposit` command. This involves getting
// access to an IPC endpoint during testing or adding support for deposit submission via HTTP and
// using ganache.
/// Returns the `lighthouse account` command. /// Returns the `lighthouse account` command.
fn account_cmd() -> Command { fn account_cmd() -> Command {
let lighthouse_bin = env!("CARGO_BIN_EXE_lighthouse"); let lighthouse_bin = env!("CARGO_BIN_EXE_lighthouse");

View File

@ -17,7 +17,7 @@ make install-lcli
Modify `vars.env` as desired. Modify `vars.env` as desired.
Start a local eth1 ganache server plus boot node along with `BN_COUNT` Start a local eth1 anvil server plus boot node along with `BN_COUNT`
number of beacon nodes and `VC_COUNT` validator clients. number of beacon nodes and `VC_COUNT` validator clients.
The `start_local_testnet.sh` script takes four options `-v VC_COUNT`, `-d DEBUG_LEVEL`, `-p` to enable builder proposals and `-h` for help. The `start_local_testnet.sh` script takes four options `-v VC_COUNT`, `-d DEBUG_LEVEL`, `-p` to enable builder proposals and `-h` for help.
@ -41,9 +41,9 @@ This is not necessary before `start_local_testnet.sh` as it invokes `stop_local_
These scripts are used by ./start_local_testnet.sh and may be used to manually These scripts are used by ./start_local_testnet.sh and may be used to manually
Start a local eth1 ganache server Start a local eth1 anvil server
```bash ```bash
./ganache_test_node.sh ./anvil_test_node.sh
``` ```
Assuming you are happy with the configuration in `vars.env`, deploy the deposit contract, make deposits, Assuming you are happy with the configuration in `vars.env`, deploy the deposit contract, make deposits,

View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -Eeuo pipefail
source ./vars.env
exec anvil \
--balance 1000000000 \
--gas-limit 1000000000 \
--accounts 10 \
--mnemonic "$ETH1_NETWORK_MNEMONIC" \
--block-time $SECONDS_PER_ETH1_BLOCK \
--port 8545 \
--chain-id "$CHAIN_ID"

View File

@ -1,14 +0,0 @@
#!/usr/bin/env bash
set -Eeuo pipefail
source ./vars.env
exec ganache \
--defaultBalanceEther 1000000000 \
--gasLimit 1000000000 \
--accounts 10 \
--mnemonic "$ETH1_NETWORK_MNEMONIC" \
--port 8545 \
--blockTime $SECONDS_PER_ETH1_BLOCK \
--chain.chainId "$CHAIN_ID"

View File

@ -92,11 +92,11 @@ execute_command_add_PID() {
echo "$!" >> $PID_FILE echo "$!" >> $PID_FILE
} }
# Start ganache, setup things up and start the bootnode. # Start anvil, setup things up and start the bootnode.
# The delays are necessary, hopefully there is a better way :( # The delays are necessary, hopefully there is a better way :(
# Delay to let ganache to get started # Delay to let anvil to get started
execute_command_add_PID ganache_test_node.log ./ganache_test_node.sh execute_command_add_PID anvil_test_node.log ./anvil_test_node.sh
sleeping 10 sleeping 10
# Setup data # Setup data

View File

@ -4,7 +4,7 @@ DATADIR=~/.lighthouse/local-testnet
# Directory for the eth2 config # Directory for the eth2 config
TESTNET_DIR=$DATADIR/testnet TESTNET_DIR=$DATADIR/testnet
# Mnemonic for the ganache test network # Mnemonic for the anvil test network
ETH1_NETWORK_MNEMONIC="vast thought differ pull jewel broom cook wrist tribe word before omit" ETH1_NETWORK_MNEMONIC="vast thought differ pull jewel broom cook wrist tribe word before omit"
# Hardcoded deposit contract based on ETH1_NETWORK_MNEMONIC # Hardcoded deposit contract based on ETH1_NETWORK_MNEMONIC

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Requires `lighthouse`, ``lcli`, `ganache`, `curl`, `jq` # Requires `lighthouse`, ``lcli`, `anvil`, `curl`, `jq`
BEHAVIOR=$1 BEHAVIOR=$1
@ -23,12 +23,12 @@ source ./vars.env
exit_if_fails ../local_testnet/clean.sh exit_if_fails ../local_testnet/clean.sh
echo "Starting ganache" echo "Starting anvil"
exit_if_fails ../local_testnet/ganache_test_node.sh &> /dev/null & exit_if_fails ../local_testnet/anvil_test_node.sh &> /dev/null &
GANACHE_PID=$! ANVIL_PID=$!
# Wait for ganache to start # Wait for anvil to start
sleep 5 sleep 5
echo "Setting up local testnet" echo "Setting up local testnet"
@ -79,7 +79,7 @@ if [[ "$BEHAVIOR" == "failure" ]]; then
echo "Shutting down" echo "Shutting down"
# Cleanup # Cleanup
kill $BOOT_PID $BEACON_PID $BEACON_PID2 $BEACON_PID3 $GANACHE_PID $VALIDATOR_1_PID $VALIDATOR_2_PID $VALIDATOR_3_PID kill $BOOT_PID $BEACON_PID $BEACON_PID2 $BEACON_PID3 $ANVIL_PID $VALIDATOR_1_PID $VALIDATOR_2_PID $VALIDATOR_3_PID
echo "Done" echo "Done"
@ -144,7 +144,7 @@ if [[ "$BEHAVIOR" == "success" ]]; then
# Cleanup # Cleanup
cd $PREVIOUS_DIR cd $PREVIOUS_DIR
kill $BOOT_PID $BEACON_PID $BEACON_PID2 $BEACON_PID3 $GANACHE_PID $VALIDATOR_1_PID $VALIDATOR_2_PID $VALIDATOR_3_PID $VALIDATOR_4_PID kill $BOOT_PID $BEACON_PID $BEACON_PID2 $BEACON_PID3 $ANVIL_PID $VALIDATOR_1_PID $VALIDATOR_2_PID $VALIDATOR_3_PID $VALIDATOR_4_PID
echo "Done" echo "Done"

View File

@ -4,7 +4,7 @@ DATADIR=~/.lighthouse/local-testnet
# Directory for the eth2 config # Directory for the eth2 config
TESTNET_DIR=$DATADIR/testnet TESTNET_DIR=$DATADIR/testnet
# Mnemonic for the ganache test network # Mnemonic for the anvil test network
ETH1_NETWORK_MNEMONIC="vast thought differ pull jewel broom cook wrist tribe word before omit" ETH1_NETWORK_MNEMONIC="vast thought differ pull jewel broom cook wrist tribe word before omit"
# Hardcoded deposit contract based on ETH1_NETWORK_MNEMONIC # Hardcoded deposit contract based on ETH1_NETWORK_MNEMONIC

View File

@ -6,8 +6,11 @@ edition = "2021"
[dependencies] [dependencies]
tokio = { version = "1.14.0", features = ["time"] } tokio = { version = "1.14.0", features = ["time"] }
web3 = { version = "0.18.0", default-features = false, features = ["http-tls", "signing", "ws-tls-tokio"] } ethers-core = "1.0.2"
ethers-providers = "1.0.2"
ethers-contract = "1.0.2"
types = { path = "../../consensus/types"} types = { path = "../../consensus/types"}
serde_json = "1.0.58" serde_json = "1.0.58"
deposit_contract = { path = "../../common/deposit_contract"} deposit_contract = { path = "../../common/deposit_contract"}
unused_port = { path = "../../common/unused_port" } unused_port = { path = "../../common/unused_port" }
hex = "0.4.2"

View File

@ -0,0 +1,101 @@
use ethers_core::utils::{Anvil, AnvilInstance};
use ethers_providers::{Http, Middleware, Provider};
use serde_json::json;
use std::convert::TryFrom;
use unused_port::unused_tcp4_port;
/// Provides a dedicated `anvil` instance.
///
/// Requires that `anvil` is installed and available on `PATH`.
pub struct AnvilCliInstance {
pub port: u16,
pub anvil: AnvilInstance,
pub client: Provider<Http>,
chain_id: u64,
}
impl AnvilCliInstance {
fn new_from_child(anvil_instance: Anvil, chain_id: u64, port: u16) -> Result<Self, String> {
let client = Provider::<Http>::try_from(&endpoint(port))
.map_err(|e| format!("Failed to start HTTP transport connected to anvil: {:?}", e))?;
Ok(Self {
port,
anvil: anvil_instance.spawn(),
client,
chain_id,
})
}
pub fn new(chain_id: u64) -> Result<Self, String> {
let port = unused_tcp4_port()?;
let anvil = Anvil::new()
.port(port)
.mnemonic("vast thought differ pull jewel broom cook wrist tribe word before omit")
.arg("--balance")
.arg("1000000000")
.arg("--gas-limit")
.arg("1000000000")
.arg("--accounts")
.arg("10")
.arg("--chain-id")
.arg(format!("{}", chain_id));
Self::new_from_child(anvil, chain_id, port)
}
pub fn fork(&self) -> Result<Self, String> {
let port = unused_tcp4_port()?;
let anvil = Anvil::new()
.port(port)
.arg("--chain-id")
.arg(format!("{}", self.chain_id()))
.fork(self.endpoint());
Self::new_from_child(anvil, self.chain_id, port)
}
/// Returns the endpoint that this instance is listening on.
pub fn endpoint(&self) -> String {
endpoint(self.port)
}
/// Returns the chain id of the anvil instance
pub fn chain_id(&self) -> u64 {
self.chain_id
}
/// Increase the timestamp on future blocks by `increase_by` seconds.
pub async fn increase_time(&self, increase_by: u64) -> Result<(), String> {
self.client
.request("evm_increaseTime", vec![json!(increase_by)])
.await
.map(|_json_value: u64| ())
.map_err(|e| format!("Failed to increase time on EVM (is this anvil?): {:?}", e))
}
/// Returns the current block number, as u64
pub async fn block_number(&self) -> Result<u64, String> {
self.client
.get_block_number()
.await
.map(|v| v.as_u64())
.map_err(|e| format!("Failed to get block number: {:?}", e))
}
/// Mines a single block.
pub async fn evm_mine(&self) -> Result<(), String> {
self.client
.request("evm_mine", ())
.await
.map(|_: String| ())
.map_err(|_| {
"utils should mine new block with evm_mine (only works with anvil/ganache!)"
.to_string()
})
}
}
fn endpoint(port: u16) -> String {
format!("http://127.0.0.1:{}", port)
}

View File

@ -1,193 +0,0 @@
use serde_json::json;
use std::io::prelude::*;
use std::io::BufReader;
use std::process::{Child, Command, Stdio};
use std::time::{Duration, Instant};
use unused_port::unused_tcp4_port;
use web3::{transports::Http, Transport, Web3};
/// How long we will wait for ganache to indicate that it is ready.
const GANACHE_STARTUP_TIMEOUT_MILLIS: u64 = 10_000;
/// Provides a dedicated `ganachi-cli` instance with a connected `Web3` instance.
///
/// Requires that `ganachi-cli` is installed and available on `PATH`.
pub struct GanacheInstance {
pub port: u16,
child: Child,
pub web3: Web3<Http>,
chain_id: u64,
}
impl GanacheInstance {
fn new_from_child(mut child: Child, port: u16, chain_id: u64) -> Result<Self, String> {
let stdout = child
.stdout
.ok_or("Unable to get stdout for ganache child process")?;
let start = Instant::now();
let mut reader = BufReader::new(stdout);
loop {
if start + Duration::from_millis(GANACHE_STARTUP_TIMEOUT_MILLIS) <= Instant::now() {
break Err(
"Timed out waiting for ganache to start. Is ganache installed?".to_string(),
);
}
let mut line = String::new();
if let Err(e) = reader.read_line(&mut line) {
break Err(format!("Failed to read line from ganache process: {:?}", e));
} else if line.starts_with("RPC Listening on") {
break Ok(());
} else {
continue;
}
}?;
let transport = Http::new(&endpoint(port)).map_err(|e| {
format!(
"Failed to start HTTP transport connected to ganache: {:?}",
e
)
})?;
let web3 = Web3::new(transport);
child.stdout = Some(reader.into_inner());
Ok(Self {
port,
child,
web3,
chain_id,
})
}
/// Start a new `ganache` process, waiting until it indicates that it is ready to accept
/// RPC connections.
pub fn new(chain_id: u64) -> Result<Self, String> {
let port = unused_tcp4_port()?;
let binary = match cfg!(windows) {
true => "ganache.cmd",
false => "ganache",
};
let child = Command::new(binary)
.stdout(Stdio::piped())
.arg("--defaultBalanceEther")
.arg("1000000000")
.arg("--gasLimit")
.arg("1000000000")
.arg("--accounts")
.arg("10")
.arg("--port")
.arg(format!("{}", port))
.arg("--mnemonic")
.arg("\"vast thought differ pull jewel broom cook wrist tribe word before omit\"")
.arg("--chain.chainId")
.arg(format!("{}", chain_id))
.spawn()
.map_err(|e| {
format!(
"Failed to start {}. \
Is it installed and available on $PATH? Error: {:?}",
binary, e
)
})?;
Self::new_from_child(child, port, chain_id)
}
pub fn fork(&self) -> Result<Self, String> {
let port = unused_tcp4_port()?;
let binary = match cfg!(windows) {
true => "ganache.cmd",
false => "ganache",
};
let child = Command::new(binary)
.stdout(Stdio::piped())
.arg("--fork")
.arg(self.endpoint())
.arg("--port")
.arg(format!("{}", port))
.arg("--chain.chainId")
.arg(format!("{}", self.chain_id))
.spawn()
.map_err(|e| {
format!(
"Failed to start {}. \
Is it installed and available on $PATH? Error: {:?}",
binary, e
)
})?;
Self::new_from_child(child, port, self.chain_id)
}
/// Returns the endpoint that this instance is listening on.
pub fn endpoint(&self) -> String {
endpoint(self.port)
}
/// Returns the chain id of the ganache instance
pub fn chain_id(&self) -> u64 {
self.chain_id
}
/// Increase the timestamp on future blocks by `increase_by` seconds.
pub async fn increase_time(&self, increase_by: u64) -> Result<(), String> {
self.web3
.transport()
.execute("evm_increaseTime", vec![json!(increase_by)])
.await
.map(|_json_value| ())
.map_err(|e| format!("Failed to increase time on EVM (is this ganache?): {:?}", e))
}
/// Returns the current block number, as u64
pub async fn block_number(&self) -> Result<u64, String> {
self.web3
.eth()
.block_number()
.await
.map(|v| v.as_u64())
.map_err(|e| format!("Failed to get block number: {:?}", e))
}
/// Mines a single block.
pub async fn evm_mine(&self) -> Result<(), String> {
self.web3
.transport()
.execute("evm_mine", vec![])
.await
.map(|_| ())
.map_err(|_| {
"utils should mine new block with evm_mine (only works with ganache!)".to_string()
})
}
}
fn endpoint(port: u16) -> String {
format!("http://127.0.0.1:{}", port)
}
impl Drop for GanacheInstance {
fn drop(&mut self) {
if cfg!(windows) {
// Calling child.kill() in Windows will only kill the process
// that spawned ganache, leaving the actual ganache process
// intact. You have to kill the whole process tree. What's more,
// if you don't spawn ganache with --keepAliveTimeout=0, Windows
// will STILL keep the server running even after you've ended
// the process tree and it's disappeared from the task manager.
// Unbelievable...
Command::new("taskkill")
.arg("/pid")
.arg(self.child.id().to_string())
.arg("/T")
.arg("/F")
.output()
.expect("failed to execute taskkill");
} else {
let _ = self.child.kill();
}
}
}

View File

@ -1,77 +1,79 @@
//! Provides utilities for deploying and manipulating the eth2 deposit contract on the eth1 chain. //! Provides utilities for deploying and manipulating the eth2 deposit contract on the eth1 chain.
//! //!
//! Presently used with [`ganache`](https://github.com/trufflesuite/ganache) to simulate //! Presently used with [`anvil`](https://github.com/foundry-rs/foundry/tree/master/anvil) to simulate
//! the deposit contract for testing beacon node eth1 integration. //! the deposit contract for testing beacon node eth1 integration.
//! //!
//! Not tested to work with actual clients (e.g., geth). It should work fine, however there may be //! Not tested to work with actual clients (e.g., geth). It should work fine, however there may be
//! some initial issues. //! some initial issues.
mod ganache; mod anvil;
use anvil::AnvilCliInstance;
use deposit_contract::{ use deposit_contract::{
encode_eth1_tx_data, testnet, ABI, BYTECODE, CONTRACT_DEPLOY_GAS, DEPOSIT_GAS, encode_eth1_tx_data, testnet, ABI, BYTECODE, CONTRACT_DEPLOY_GAS, DEPOSIT_GAS,
}; };
use ganache::GanacheInstance; use ethers_contract::Contract;
use ethers_core::{
abi::Abi,
types::{transaction::eip2718::TypedTransaction, Address, Bytes, TransactionRequest, U256},
};
pub use ethers_providers::{Http, Middleware, Provider};
use std::time::Duration; use std::time::Duration;
use tokio::time::sleep; use tokio::time::sleep;
use types::DepositData; use types::DepositData;
use types::{test_utils::generate_deterministic_keypair, EthSpec, Hash256, Keypair, Signature}; use types::{test_utils::generate_deterministic_keypair, EthSpec, Hash256, Keypair, Signature};
use web3::contract::{Contract, Options};
use web3::transports::Http;
use web3::types::{Address, TransactionRequest, U256};
use web3::Web3;
pub const DEPLOYER_ACCOUNTS_INDEX: usize = 0; pub const DEPLOYER_ACCOUNTS_INDEX: usize = 0;
pub const DEPOSIT_ACCOUNTS_INDEX: usize = 0; pub const DEPOSIT_ACCOUNTS_INDEX: usize = 0;
/// Provides a dedicated ganache instance with the deposit contract already deployed. /// Provides a dedicated anvil instance with the deposit contract already deployed.
pub struct GanacheEth1Instance { pub struct AnvilEth1Instance {
pub ganache: GanacheInstance, pub anvil: AnvilCliInstance,
pub deposit_contract: DepositContract, pub deposit_contract: DepositContract,
} }
impl GanacheEth1Instance { impl AnvilEth1Instance {
pub async fn new(chain_id: u64) -> Result<Self, String> { pub async fn new(chain_id: u64) -> Result<Self, String> {
let ganache = GanacheInstance::new(chain_id)?; let anvil = AnvilCliInstance::new(chain_id)?;
DepositContract::deploy(ganache.web3.clone(), 0, None) DepositContract::deploy(anvil.client.clone(), 0, None)
.await .await
.map(|deposit_contract| Self { .map(|deposit_contract| Self {
ganache, anvil,
deposit_contract, deposit_contract,
}) })
} }
pub fn endpoint(&self) -> String { pub fn endpoint(&self) -> String {
self.ganache.endpoint() self.anvil.endpoint()
} }
pub fn web3(&self) -> Web3<Http> { pub fn json_rpc_client(&self) -> Provider<Http> {
self.ganache.web3.clone() self.anvil.client.clone()
} }
} }
/// Deploys and provides functions for the eth2 deposit contract, deployed on the eth1 chain. /// Deploys and provides functions for the eth2 deposit contract, deployed on the eth1 chain.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct DepositContract { pub struct DepositContract {
web3: Web3<Http>, client: Provider<Http>,
contract: Contract<Http>, contract: Contract<Provider<Http>>,
} }
impl DepositContract { impl DepositContract {
pub async fn deploy( pub async fn deploy(
web3: Web3<Http>, client: Provider<Http>,
confirmations: usize, confirmations: usize,
password: Option<String>, password: Option<String>,
) -> Result<Self, String> { ) -> Result<Self, String> {
Self::deploy_bytecode(web3, confirmations, BYTECODE, ABI, password).await Self::deploy_bytecode(client, confirmations, BYTECODE, ABI, password).await
} }
pub async fn deploy_testnet( pub async fn deploy_testnet(
web3: Web3<Http>, client: Provider<Http>,
confirmations: usize, confirmations: usize,
password: Option<String>, password: Option<String>,
) -> Result<Self, String> { ) -> Result<Self, String> {
Self::deploy_bytecode( Self::deploy_bytecode(
web3, client,
confirmations, confirmations,
testnet::BYTECODE, testnet::BYTECODE,
testnet::ABI, testnet::ABI,
@ -81,29 +83,25 @@ impl DepositContract {
} }
async fn deploy_bytecode( async fn deploy_bytecode(
web3: Web3<Http>, client: Provider<Http>,
confirmations: usize, confirmations: usize,
bytecode: &[u8], bytecode: &[u8],
abi: &[u8], abi: &[u8],
password: Option<String>, password: Option<String>,
) -> Result<Self, String> { ) -> Result<Self, String> {
let address = deploy_deposit_contract( let abi = Abi::load(abi).map_err(|e| format!("Invalid deposit contract abi: {:?}", e))?;
web3.clone(), let address =
confirmations, deploy_deposit_contract(client.clone(), confirmations, bytecode.to_vec(), password)
bytecode.to_vec(), .await
abi.to_vec(), .map_err(|e| {
password, format!(
) "Failed to deploy contract: {}. Is scripts/anvil_tests_node.sh running?.",
.await e
.map_err(|e| { )
format!( })?;
"Failed to deploy contract: {}. Is scripts/ganache_tests_node.sh running?.",
e let contract = Contract::new(address, abi, client.clone());
) Ok(Self { client, contract })
})?;
Contract::from_json(web3.clone().eth(), address, ABI)
.map_err(|e| format!("Failed to init contract: {:?}", e))
.map(move |contract| Self { web3, contract })
} }
/// The deposit contract's address in `0x00ab...` format. /// The deposit contract's address in `0x00ab...` format.
@ -178,9 +176,8 @@ impl DepositContract {
/// Performs a non-blocking deposit. /// Performs a non-blocking deposit.
pub async fn deposit_async(&self, deposit_data: DepositData) -> Result<(), String> { pub async fn deposit_async(&self, deposit_data: DepositData) -> Result<(), String> {
let from = self let from = self
.web3 .client
.eth() .get_accounts()
.accounts()
.await .await
.map_err(|e| format!("Failed to get accounts: {:?}", e)) .map_err(|e| format!("Failed to get accounts: {:?}", e))
.and_then(|accounts| { .and_then(|accounts| {
@ -189,32 +186,33 @@ impl DepositContract {
.cloned() .cloned()
.ok_or_else(|| "Insufficient accounts for deposit".to_string()) .ok_or_else(|| "Insufficient accounts for deposit".to_string())
})?; })?;
let tx_request = TransactionRequest { // Note: the reason we use this `TransactionRequest` instead of just using the
from, // function in `self.contract` is so that the `eth1_tx_data` function gets used
to: Some(self.contract.address()), // during testing.
gas: Some(U256::from(DEPOSIT_GAS)), //
gas_price: None, // It's important that `eth1_tx_data` stays correct and does not suffer from
max_fee_per_gas: None, // code-rot.
max_priority_fee_per_gas: None, let tx_request = TransactionRequest::new()
value: Some(from_gwei(deposit_data.amount)), .from(from)
// Note: the reason we use this `TransactionRequest` instead of just using the .to(self.contract.address())
// function in `self.contract` is so that the `eth1_tx_data` function gets used .gas(DEPOSIT_GAS)
// during testing. .value(from_gwei(deposit_data.amount))
// .data(Bytes::from(encode_eth1_tx_data(&deposit_data).map_err(
// It's important that `eth1_tx_data` stays correct and does not suffer from |e| format!("Failed to encode deposit data: {:?}", e),
// code-rot. )?));
data: encode_eth1_tx_data(&deposit_data).map(Into::into).ok(),
nonce: None,
condition: None,
transaction_type: None,
access_list: None,
};
self.web3 let pending_tx = self
.eth() .client
.send_transaction(tx_request) .send_transaction(tx_request, None)
.await .await
.map_err(|e| format!("Failed to call deposit fn: {:?}", e))?; .map_err(|e| format!("Failed to call deposit fn: {:?}", e))?;
pending_tx
.interval(Duration::from_millis(10))
.confirmations(0)
.await
.map_err(|e| format!("Transaction failed to resolve: {:?}", e))?
.ok_or_else(|| "Transaction dropped from mempool".to_string())?;
Ok(()) Ok(())
} }
@ -245,17 +243,13 @@ fn from_gwei(gwei: u64) -> U256 {
/// Deploys the deposit contract to the given web3 instance using the account with index /// Deploys the deposit contract to the given web3 instance using the account with index
/// `DEPLOYER_ACCOUNTS_INDEX`. /// `DEPLOYER_ACCOUNTS_INDEX`.
async fn deploy_deposit_contract( async fn deploy_deposit_contract(
web3: Web3<Http>, client: Provider<Http>,
confirmations: usize, confirmations: usize,
bytecode: Vec<u8>, bytecode: Vec<u8>,
abi: Vec<u8>,
password_opt: Option<String>, password_opt: Option<String>,
) -> Result<Address, String> { ) -> Result<Address, String> {
let bytecode = String::from_utf8(bytecode).expect("bytecode must be valid utf8"); let from_address = client
.get_accounts()
let from_address = web3
.eth()
.accounts()
.await .await
.map_err(|e| format!("Failed to get accounts: {:?}", e)) .map_err(|e| format!("Failed to get accounts: {:?}", e))
.and_then(|accounts| { .and_then(|accounts| {
@ -266,30 +260,42 @@ async fn deploy_deposit_contract(
})?; })?;
let deploy_address = if let Some(password) = password_opt { let deploy_address = if let Some(password) = password_opt {
let result = web3 let result = client
.personal() .request(
.unlock_account(from_address, &password, None) "personal_unlockAccount",
vec![from_address.to_string(), password],
)
.await; .await;
match result { match result {
Ok(true) => return Ok(from_address), Ok(true) => from_address,
Ok(false) => return Err("Eth1 node refused to unlock account".to_string()), Ok(false) => return Err("Eth1 node refused to unlock account".to_string()),
Err(e) => return Err(format!("Eth1 unlock request failed: {:?}", e)), Err(e) => return Err(format!("Eth1 unlock request failed: {:?}", e)),
}; }
} else { } else {
from_address from_address
}; };
let pending_contract = Contract::deploy(web3.eth(), &abi) let mut bytecode = String::from_utf8(bytecode).unwrap();
.map_err(|e| format!("Unable to build contract deployer: {:?}", e))? bytecode.retain(|c| c.is_ascii_hexdigit());
.confirmations(confirmations) let bytecode = hex::decode(&bytecode[1..]).unwrap();
.options(Options {
gas: Some(U256::from(CONTRACT_DEPLOY_GAS)),
..Options::default()
})
.execute(bytecode, (), deploy_address);
pending_contract let deploy_tx: TypedTransaction = TransactionRequest::new()
.from(deploy_address)
.data(Bytes::from(bytecode))
.gas(CONTRACT_DEPLOY_GAS)
.into();
let pending_tx = client
.send_transaction(deploy_tx, None)
.await .await
.map(|contract| contract.address()) .map_err(|e| format!("Failed to send tx: {:?}", e))?;
.map_err(|e| format!("Unable to resolve pending contract: {:?}", e))
let tx = pending_tx
.interval(Duration::from_millis(500))
.confirmations(confirmations)
.await
.map_err(|e| format!("Failed to fetch tx receipt: {:?}", e))?;
tx.and_then(|tx| tx.contract_address)
.ok_or_else(|| "Deposit contract not deployed successfully".to_string())
} }

View File

@ -10,7 +10,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.about( .about(
"Lighthouse Beacon Chain Simulator creates `n` beacon node and validator clients, \ "Lighthouse Beacon Chain Simulator creates `n` beacon node and validator clients, \
each with `v` validators. A deposit contract is deployed at the start of the \ each with `v` validators. A deposit contract is deployed at the start of the \
simulation using a local `ganache` instance (you must have `ganache` \ simulation using a local `anvil` instance (you must have `anvil` \
installed and avaliable on your path). All beacon nodes independently listen \ installed and avaliable on your path). All beacon nodes independently listen \
for genesis from the deposit contract, then start operating. \ for genesis from the deposit contract, then start operating. \
\ \

View File

@ -2,7 +2,7 @@ use crate::local_network::{EXECUTION_PORT, TERMINAL_BLOCK, TERMINAL_DIFFICULTY};
use crate::{checks, LocalNetwork, E}; use crate::{checks, LocalNetwork, E};
use clap::ArgMatches; use clap::ArgMatches;
use eth1::{Eth1Endpoint, DEFAULT_CHAIN_ID}; use eth1::{Eth1Endpoint, DEFAULT_CHAIN_ID};
use eth1_test_rig::GanacheEth1Instance; use eth1_test_rig::AnvilEth1Instance;
use execution_layer::http::deposit_methods::Eth1Id; use execution_layer::http::deposit_methods::Eth1Id;
use futures::prelude::*; use futures::prelude::*;
@ -110,12 +110,12 @@ pub fn run_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
* Deploy the deposit contract, spawn tasks to keep creating new blocks and deposit * Deploy the deposit contract, spawn tasks to keep creating new blocks and deposit
* validators. * validators.
*/ */
let ganache_eth1_instance = GanacheEth1Instance::new(DEFAULT_CHAIN_ID.into()).await?; let anvil_eth1_instance = AnvilEth1Instance::new(DEFAULT_CHAIN_ID.into()).await?;
let deposit_contract = ganache_eth1_instance.deposit_contract; let deposit_contract = anvil_eth1_instance.deposit_contract;
let chain_id = ganache_eth1_instance.ganache.chain_id(); let chain_id = anvil_eth1_instance.anvil.chain_id();
let ganache = ganache_eth1_instance.ganache; let anvil = anvil_eth1_instance.anvil;
let eth1_endpoint = SensitiveUrl::parse(ganache.endpoint().as_str()) let eth1_endpoint = SensitiveUrl::parse(anvil.endpoint().as_str())
.expect("Unable to parse ganache endpoint."); .expect("Unable to parse anvil endpoint.");
let deposit_contract_address = deposit_contract.address(); let deposit_contract_address = deposit_contract.address();
// Start a timer that produces eth1 blocks on an interval. // Start a timer that produces eth1 blocks on an interval.
@ -123,7 +123,7 @@ pub fn run_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
let mut interval = tokio::time::interval(eth1_block_time); let mut interval = tokio::time::interval(eth1_block_time);
loop { loop {
interval.tick().await; interval.tick().await;
let _ = ganache.evm_mine().await; let _ = anvil.evm_mine().await;
} }
}); });

View File

@ -1,6 +1,6 @@
//! This crate provides a simluation that creates `n` beacon node and validator clients, each with //! This crate provides a simluation that creates `n` beacon node and validator clients, each with
//! `v` validators. A deposit contract is deployed at the start of the simulation using a local //! `v` validators. A deposit contract is deployed at the start of the simulation using a local
//! `ganache` instance (you must have `ganache` installed and avaliable on your path). All //! `anvil` instance (you must have `anvil` installed and avaliable on your path). All
//! beacon nodes independently listen for genesis from the deposit contract, then start operating. //! beacon nodes independently listen for genesis from the deposit contract, then start operating.
//! //!
//! As the simulation runs, there are checks made to ensure that all components are running //! As the simulation runs, there are checks made to ensure that all components are running