Integrate Witti testnet (#1193)
* Update for latest master * Shift delay inside loop * Clean up genesis service * Tidy * Tidy logs * Address Michael's comments * Add pre-genesis logging * Remove est time till genesis * Fix time formatting * Tidy * Update docs for Witti * Update JS for Witti * Ensure deposit data is 0x-prefixed hex * Hard code witti testnet dir * Add --auto-register warning * Integrate local sigp testnet source * Reword warning
This commit is contained in:
parent
9718c5db07
commit
ad4e5adabc
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -5409,6 +5409,7 @@ dependencies = [
|
|||||||
"deposit_contract",
|
"deposit_contract",
|
||||||
"eth2_keystore",
|
"eth2_keystore",
|
||||||
"eth2_wallet",
|
"eth2_wallet",
|
||||||
|
"hex 0.4.2",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"rayon",
|
"rayon",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
@ -1,20 +1,10 @@
|
|||||||
# Become an Ethereum 2.0 Testnet Validator
|
# Become an Ethereum 2.0 Testnet Validator on Witti
|
||||||
|
|
||||||
---
|
Running a Lighthouse validator on the [Witti](https://github.com/goerli/witti)
|
||||||
|
multi-client testnet is easy if you're familiar with the terminal.
|
||||||
|
|
||||||
**The Schlesi testnet is currently down.**
|
Lighthouse runs on Linux, MacOS and Windows and has a Docker work-flow to make
|
||||||
|
things as simple as possible.
|
||||||
Please do not submit any deposits. For updates, see:
|
|
||||||
|
|
||||||
- The Lighthouse ["announcements"](https://discord.gg/cE3GEy) Discord channel.
|
|
||||||
- The Eth R&D ["Schlesi"](https://discord.gg/GQwzr7) Discord channel.
|
|
||||||
- [goerli/witti](https://github.com/goerli/witti) for technical information.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Running a Lighthouse validator is easy if you're familiar with the terminal.
|
|
||||||
|
|
||||||
Lighthouse runs on Linux, MacOS and Windows and has a Docker work-flow to make things as simple as possible.
|
|
||||||
|
|
||||||
|
|
||||||
## 0. Acquire Goerli ETH
|
## 0. Acquire Goerli ETH
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const NETWORK = "5";
|
const NETWORK = "5";
|
||||||
const NETWORK_NAME = "Goerli Test Network";
|
const NETWORK_NAME = "Goerli Test Network";
|
||||||
const DEPOSIT_CONTRACT = "0xA15554BF93a052669B511ae29EA21f3581677ac5";
|
const DEPOSIT_CONTRACT = "0x42cc0FcEB02015F145105Cf6f19F90e9BEa76558";
|
||||||
const DEPOSIT_AMOUNT_ETH = "32";
|
const DEPOSIT_AMOUNT_ETH = "32";
|
||||||
const GAS_LIMIT = "4000000";
|
const GAS_LIMIT = "4000000";
|
||||||
const DEPOSIT_DATA_BYTES = 420;
|
const DEPOSIT_DATA_BYTES = 420;
|
||||||
|
1
common/eth2_testnet_config/.gitignore
vendored
1
common/eth2_testnet_config/.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
testnet*
|
testnet*
|
||||||
schlesi-*
|
schlesi-*
|
||||||
|
witti-*
|
||||||
|
@ -6,7 +6,7 @@ use std::fs::File;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
const TESTNET_ID: &str = "schlesi-v0-11";
|
const TESTNET_ID: &str = "witti-v0-11-3";
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
if !base_dir().exists() {
|
if !base_dir().exists() {
|
||||||
@ -38,7 +38,7 @@ pub fn get_all_files() -> Result<(), String> {
|
|||||||
|
|
||||||
pub fn get_file(filename: &str) -> Result<(), String> {
|
pub fn get_file(filename: &str) -> Result<(), String> {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"https://raw.githubusercontent.com/goerli/schlesi/839866fe29a1b4df3a87bfe2ff1257c8a58671c9/light/{}",
|
"https://raw.githubusercontent.com/sigp/witti/6d079b0f10f6bed75cd003e5f0ea5ecbe2044455/lighthouse/{}",
|
||||||
filename
|
filename
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -20,14 +20,14 @@ pub const BOOT_ENR_FILE: &str = "boot_enr.yaml";
|
|||||||
pub const GENESIS_STATE_FILE: &str = "genesis.ssz";
|
pub const GENESIS_STATE_FILE: &str = "genesis.ssz";
|
||||||
pub const YAML_CONFIG_FILE: &str = "config.yaml";
|
pub const YAML_CONFIG_FILE: &str = "config.yaml";
|
||||||
|
|
||||||
pub const HARDCODED_TESTNET: &str = "schlesi-v0-11";
|
pub const HARDCODED_TESTNET: &str = "witti-v0-11-3";
|
||||||
|
|
||||||
pub const HARDCODED_YAML_CONFIG: &[u8] = include_bytes!("../schlesi-v0-11/config.yaml");
|
pub const HARDCODED_YAML_CONFIG: &[u8] = include_bytes!("../witti-v0-11-3/config.yaml");
|
||||||
pub const HARDCODED_DEPLOY_BLOCK: &[u8] = include_bytes!("../schlesi-v0-11/deploy_block.txt");
|
pub const HARDCODED_DEPLOY_BLOCK: &[u8] = include_bytes!("../witti-v0-11-3/deploy_block.txt");
|
||||||
pub const HARDCODED_DEPOSIT_CONTRACT: &[u8] =
|
pub const HARDCODED_DEPOSIT_CONTRACT: &[u8] =
|
||||||
include_bytes!("../schlesi-v0-11/deposit_contract.txt");
|
include_bytes!("../witti-v0-11-3/deposit_contract.txt");
|
||||||
pub const HARDCODED_GENESIS_STATE: &[u8] = include_bytes!("../schlesi-v0-11/genesis.ssz");
|
pub const HARDCODED_GENESIS_STATE: &[u8] = include_bytes!("../witti-v0-11-3/genesis.ssz");
|
||||||
pub const HARDCODED_BOOT_ENR: &[u8] = include_bytes!("../schlesi-v0-11/boot_enr.yaml");
|
pub const HARDCODED_BOOT_ENR: &[u8] = include_bytes!("../witti-v0-11-3/boot_enr.yaml");
|
||||||
|
|
||||||
/// Specifies an Eth2 testnet.
|
/// Specifies an Eth2 testnet.
|
||||||
///
|
///
|
||||||
|
@ -19,6 +19,7 @@ rand = "0.7.2"
|
|||||||
deposit_contract = { path = "../deposit_contract" }
|
deposit_contract = { path = "../deposit_contract" }
|
||||||
rayon = "1.3.0"
|
rayon = "1.3.0"
|
||||||
tree_hash = { path = "../../consensus/tree_hash" }
|
tree_hash = { path = "../../consensus/tree_hash" }
|
||||||
|
hex = "0.4.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
@ -175,13 +175,14 @@ impl<'a> Builder<'a> {
|
|||||||
if path.exists() {
|
if path.exists() {
|
||||||
return Err(Error::DepositDataAlreadyExists(path));
|
return Err(Error::DepositDataAlreadyExists(path));
|
||||||
} else {
|
} else {
|
||||||
|
let hex = format!("0x{}", hex::encode(&deposit_data));
|
||||||
OpenOptions::new()
|
OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.read(true)
|
.read(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
.open(path.clone())
|
.open(path.clone())
|
||||||
.map_err(Error::UnableToSaveDepositData)?
|
.map_err(Error::UnableToSaveDepositData)?
|
||||||
.write_all(&deposit_data)
|
.write_all(hex.as_bytes())
|
||||||
.map_err(Error::UnableToSaveDepositData)?
|
.map_err(Error::UnableToSaveDepositData)?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,9 @@ pub enum Error {
|
|||||||
UnableToReadPassword(PathBuf),
|
UnableToReadPassword(PathBuf),
|
||||||
UnableToDecryptKeypair(KeystoreError),
|
UnableToDecryptKeypair(KeystoreError),
|
||||||
UnableToReadDepositData(io::Error),
|
UnableToReadDepositData(io::Error),
|
||||||
|
DepositDataMissing0xPrefix,
|
||||||
|
DepositDataNotUtf8,
|
||||||
|
DepositDataInvalidHex(hex::FromHexError),
|
||||||
DepositAmountDoesNotExist(PathBuf),
|
DepositAmountDoesNotExist(PathBuf),
|
||||||
UnableToReadDepositAmount(io::Error),
|
UnableToReadDepositAmount(io::Error),
|
||||||
UnableToParseDepositAmount(std::num::ParseIntError),
|
UnableToParseDepositAmount(std::num::ParseIntError),
|
||||||
@ -160,7 +163,16 @@ impl ValidatorDir {
|
|||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
let deposit_data_rlp = read(path).map_err(Error::UnableToReadDepositData)?;
|
let deposit_data_rlp = read(path)
|
||||||
|
.map_err(Error::UnableToReadDepositData)
|
||||||
|
.and_then(|hex_bytes| {
|
||||||
|
let hex = std::str::from_utf8(&hex_bytes).map_err(|_| Error::DepositDataNotUtf8)?;
|
||||||
|
if hex.starts_with("0x") {
|
||||||
|
hex::decode(&hex[2..]).map_err(Error::DepositDataInvalidHex)
|
||||||
|
} else {
|
||||||
|
Err(Error::DepositDataMissing0xPrefix)
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
// Read and parse `ETH1_DEPOSIT_AMOUNT_FILE`.
|
// Read and parse `ETH1_DEPOSIT_AMOUNT_FILE`.
|
||||||
let path = self.dir.join(ETH1_DEPOSIT_AMOUNT_FILE);
|
let path = self.dir.join(ETH1_DEPOSIT_AMOUNT_FILE);
|
||||||
|
@ -6,7 +6,7 @@ use std::path::Path;
|
|||||||
use tempfile::{tempdir, TempDir};
|
use tempfile::{tempdir, TempDir};
|
||||||
use types::{test_utils::generate_deterministic_keypair, EthSpec, Keypair, MainnetEthSpec};
|
use types::{test_utils::generate_deterministic_keypair, EthSpec, Keypair, MainnetEthSpec};
|
||||||
use validator_dir::{
|
use validator_dir::{
|
||||||
Builder, ValidatorDir, ETH1_DEPOSIT_TX_HASH_FILE, VOTING_KEYSTORE_FILE,
|
Builder, ValidatorDir, ETH1_DEPOSIT_DATA_FILE, ETH1_DEPOSIT_TX_HASH_FILE, VOTING_KEYSTORE_FILE,
|
||||||
WITHDRAWAL_KEYSTORE_FILE,
|
WITHDRAWAL_KEYSTORE_FILE,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -145,6 +145,13 @@ impl Harness {
|
|||||||
|
|
||||||
// Ensure the amount is consistent.
|
// Ensure the amount is consistent.
|
||||||
assert_eq!(data.deposit_data.amount, amount);
|
assert_eq!(data.deposit_data.amount, amount);
|
||||||
|
|
||||||
|
// Check that the eth1 deposit data file is a valid format.
|
||||||
|
let hex =
|
||||||
|
String::from_utf8(fs::read(validator.dir().join(ETH1_DEPOSIT_DATA_FILE)).unwrap())
|
||||||
|
.unwrap();
|
||||||
|
assert!(hex.starts_with("0x"), "deposit data should have 0x prefix");
|
||||||
|
hex::decode(&hex[2..]).unwrap();
|
||||||
} else {
|
} else {
|
||||||
// If there was no deposit then we should return `Ok(None)`.
|
// If there was no deposit then we should return `Ok(None)`.
|
||||||
assert!(validator.eth1_deposit_data().unwrap().is_none());
|
assert!(validator.eth1_deposit_data().unwrap().is_none());
|
||||||
|
@ -14,13 +14,14 @@ pub use config::Config;
|
|||||||
use attestation_service::{AttestationService, AttestationServiceBuilder};
|
use attestation_service::{AttestationService, AttestationServiceBuilder};
|
||||||
use block_service::{BlockService, BlockServiceBuilder};
|
use block_service::{BlockService, BlockServiceBuilder};
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
|
use config::SLASHING_PROTECTION_FILENAME;
|
||||||
use duties_service::{DutiesService, DutiesServiceBuilder};
|
use duties_service::{DutiesService, DutiesServiceBuilder};
|
||||||
use environment::RuntimeContext;
|
use environment::RuntimeContext;
|
||||||
use exit_future::Signal;
|
use exit_future::Signal;
|
||||||
use fork_service::{ForkService, ForkServiceBuilder};
|
use fork_service::{ForkService, ForkServiceBuilder};
|
||||||
use notifier::spawn_notifier;
|
use notifier::spawn_notifier;
|
||||||
use remote_beacon_node::RemoteBeaconNode;
|
use remote_beacon_node::RemoteBeaconNode;
|
||||||
use slog::{error, info, Logger};
|
use slog::{error, info, warn, Logger};
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use slot_clock::SystemTimeSlotClock;
|
use slot_clock::SystemTimeSlotClock;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
@ -71,6 +72,14 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
|||||||
"datadir" => format!("{:?}", config.data_dir),
|
"datadir" => format!("{:?}", config.data_dir),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if !config.data_dir.join(SLASHING_PROTECTION_FILENAME).exists() && !config.auto_register {
|
||||||
|
warn!(
|
||||||
|
log_1,
|
||||||
|
"Will not register any validators";
|
||||||
|
"msg" => "strongly consider using --auto-register on the first use",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let beacon_node =
|
let beacon_node =
|
||||||
RemoteBeaconNode::new_with_timeout(config.http_server.clone(), HTTP_TIMEOUT)
|
RemoteBeaconNode::new_with_timeout(config.http_server.clone(), HTTP_TIMEOUT)
|
||||||
.map_err(|e| format!("Unable to init beacon node http client: {}", e))?;
|
.map_err(|e| format!("Unable to init beacon node http client: {}", e))?;
|
||||||
|
Loading…
Reference in New Issue
Block a user