Misc changes for merge testnets (#2667)
* Thread eth1_block_hash into interop genesis state * Add merge-fork-epoch flag * Build LH with minimal spec by default * Add verbose logs to execution_layer * Add --http-allow-sync-stalled flag * Update lcli new-testnet to create genesis state * Fix http test * Fix compile errors in tests
This commit is contained in:
parent
a1033a9247
commit
b162b067de
4
Makefile
4
Makefile
@ -23,9 +23,9 @@ FORKS=phase0 altair
|
||||
# Binaries will most likely be found in `./target/release`
|
||||
install:
|
||||
ifeq ($(PORTABLE), true)
|
||||
cargo install --path lighthouse --force --locked --features portable
|
||||
cargo install --path lighthouse --force --locked --features portable,spec-minimal
|
||||
else
|
||||
cargo install --path lighthouse --force --locked
|
||||
cargo install --path lighthouse --force --locked --features spec-minimal
|
||||
endif
|
||||
|
||||
# Builds the lcli binary in release (optimized).
|
||||
|
@ -919,7 +919,9 @@ fn descriptive_db_error(item: &str, error: &StoreError) -> String {
|
||||
mod test {
|
||||
use super::*;
|
||||
use eth2_hashing::hash;
|
||||
use genesis::{generate_deterministic_keypairs, interop_genesis_state};
|
||||
use genesis::{
|
||||
generate_deterministic_keypairs, interop_genesis_state, DEFAULT_ETH1_BLOCK_HASH,
|
||||
};
|
||||
use sloggers::{null::NullLoggerBuilder, Build};
|
||||
use ssz::Encode;
|
||||
use std::time::Duration;
|
||||
@ -951,6 +953,7 @@ mod test {
|
||||
let genesis_state = interop_genesis_state(
|
||||
&generate_deterministic_keypairs(validator_count),
|
||||
genesis_time,
|
||||
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||
&spec,
|
||||
)
|
||||
.expect("should create interop genesis state");
|
||||
@ -1016,7 +1019,12 @@ mod test {
|
||||
|
||||
let keypairs = generate_deterministic_keypairs(validator_count);
|
||||
|
||||
let state = interop_genesis_state::<TestEthSpec>(&keypairs, genesis_time, spec)
|
||||
let state = interop_genesis_state::<TestEthSpec>(
|
||||
&keypairs,
|
||||
genesis_time,
|
||||
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||
spec,
|
||||
)
|
||||
.expect("should build state");
|
||||
|
||||
assert_eq!(
|
||||
|
@ -18,7 +18,7 @@ use execution_layer::{
|
||||
ExecutionLayer,
|
||||
};
|
||||
use futures::channel::mpsc::Receiver;
|
||||
pub use genesis::interop_genesis_state;
|
||||
pub use genesis::{interop_genesis_state, DEFAULT_ETH1_BLOCK_HASH};
|
||||
use int_to_bytes::int_to_bytes32;
|
||||
use logging::test_logger;
|
||||
use merkle_proof::MerkleTree;
|
||||
@ -181,6 +181,7 @@ impl<E: EthSpec> Builder<EphemeralHarnessType<E>> {
|
||||
let genesis_state = interop_genesis_state::<E>(
|
||||
&validator_keypairs,
|
||||
HARNESS_GENESIS_TIME,
|
||||
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||
builder.get_spec(),
|
||||
)
|
||||
.expect("should generate interop state");
|
||||
@ -226,6 +227,7 @@ impl<E: EthSpec> Builder<DiskHarnessType<E>> {
|
||||
let genesis_state = interop_genesis_state::<E>(
|
||||
&validator_keypairs,
|
||||
HARNESS_GENESIS_TIME,
|
||||
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||
builder.get_spec(),
|
||||
)
|
||||
.expect("should generate interop state");
|
||||
|
@ -17,7 +17,7 @@ use eth2::{
|
||||
BeaconNodeHttpClient, Error as ApiError, Timeouts,
|
||||
};
|
||||
use execution_layer::ExecutionLayer;
|
||||
use genesis::{interop_genesis_state, Eth1GenesisService};
|
||||
use genesis::{interop_genesis_state, Eth1GenesisService, DEFAULT_ETH1_BLOCK_HASH};
|
||||
use lighthouse_network::NetworkGlobals;
|
||||
use monitoring_api::{MonitoringHttpClient, ProcessType};
|
||||
use network::{NetworkConfig, NetworkMessage, NetworkService};
|
||||
@ -31,7 +31,8 @@ use std::time::Duration;
|
||||
use timer::spawn_timer;
|
||||
use tokio::sync::{mpsc::UnboundedSender, oneshot};
|
||||
use types::{
|
||||
test_utils::generate_deterministic_keypairs, BeaconState, ChainSpec, EthSpec, SignedBeaconBlock,
|
||||
test_utils::generate_deterministic_keypairs, BeaconState, ChainSpec, EthSpec, Hash256,
|
||||
SignedBeaconBlock,
|
||||
};
|
||||
|
||||
/// Interval between polling the eth1 node for genesis information.
|
||||
@ -229,7 +230,12 @@ where
|
||||
genesis_time,
|
||||
} => {
|
||||
let keypairs = generate_deterministic_keypairs(validator_count);
|
||||
let genesis_state = interop_genesis_state(&keypairs, genesis_time, &spec)?;
|
||||
let genesis_state = interop_genesis_state(
|
||||
&keypairs,
|
||||
genesis_time,
|
||||
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||
&spec,
|
||||
)?;
|
||||
builder.genesis_state(genesis_state).map(|v| (v, None))?
|
||||
}
|
||||
ClientGenesis::SszBytes {
|
||||
|
@ -8,7 +8,7 @@ use engine_api::{Error as ApiError, *};
|
||||
use engines::{Engine, EngineError, Engines};
|
||||
use lru::LruCache;
|
||||
use sensitive_url::SensitiveUrl;
|
||||
use slog::{crit, Logger};
|
||||
use slog::{crit, info, Logger};
|
||||
use std::future::Future;
|
||||
use std::sync::Arc;
|
||||
use task_executor::TaskExecutor;
|
||||
@ -177,6 +177,14 @@ impl ExecutionLayer {
|
||||
random: Hash256,
|
||||
) -> Result<PayloadId, Error> {
|
||||
let fee_recipient = self.fee_recipient()?;
|
||||
info!(
|
||||
self.log(),
|
||||
"Issuing engine_preparePayload";
|
||||
"fee_recipient" => ?fee_recipient,
|
||||
"random" => ?random,
|
||||
"timestamp" => timestamp,
|
||||
"parent_hash" => ?parent_hash,
|
||||
);
|
||||
self.engines()
|
||||
.first_success(|engine| {
|
||||
// TODO(merge): make a cache for these IDs, so we don't always have to perform this
|
||||
@ -205,6 +213,14 @@ impl ExecutionLayer {
|
||||
random: Hash256,
|
||||
) -> Result<ExecutionPayload<T>, Error> {
|
||||
let fee_recipient = self.fee_recipient()?;
|
||||
info!(
|
||||
self.log(),
|
||||
"Issuing engine_getPayload";
|
||||
"fee_recipient" => ?fee_recipient,
|
||||
"random" => ?random,
|
||||
"timestamp" => timestamp,
|
||||
"parent_hash" => ?parent_hash,
|
||||
);
|
||||
self.engines()
|
||||
.first_success(|engine| async move {
|
||||
// TODO(merge): make a cache for these IDs, so we don't always have to perform this
|
||||
@ -236,6 +252,14 @@ impl ExecutionLayer {
|
||||
&self,
|
||||
execution_payload: &ExecutionPayload<T>,
|
||||
) -> Result<(ExecutePayloadResponse, ExecutePayloadHandle), Error> {
|
||||
info!(
|
||||
self.log(),
|
||||
"Issuing engine_executePayload";
|
||||
"parent_hash" => ?execution_payload.parent_hash,
|
||||
"block_hash" => ?execution_payload.block_hash,
|
||||
"block_number" => execution_payload.block_number,
|
||||
);
|
||||
|
||||
let broadcast_results = self
|
||||
.engines()
|
||||
.broadcast(|engine| engine.api.execute_payload(execution_payload.clone()))
|
||||
@ -296,6 +320,12 @@ impl ExecutionLayer {
|
||||
block_hash: Hash256,
|
||||
status: ConsensusStatus,
|
||||
) -> Result<(), Error> {
|
||||
info!(
|
||||
self.log(),
|
||||
"Issuing engine_consensusValidated";
|
||||
"status" => ?status,
|
||||
"block_hash" => ?block_hash,
|
||||
);
|
||||
let broadcast_results = self
|
||||
.engines()
|
||||
.broadcast(|engine| engine.api.consensus_validated(block_hash, status))
|
||||
@ -328,6 +358,12 @@ impl ExecutionLayer {
|
||||
head_block_hash: Hash256,
|
||||
finalized_block_hash: Hash256,
|
||||
) -> Result<(), Error> {
|
||||
info!(
|
||||
self.log(),
|
||||
"Issuing engine_forkchoiceUpdated";
|
||||
"finalized_block_hash" => ?finalized_block_hash,
|
||||
"head_block_hash" => ?head_block_hash,
|
||||
);
|
||||
let broadcast_results = self
|
||||
.engines()
|
||||
.broadcast(|engine| {
|
||||
@ -357,7 +393,8 @@ impl ExecutionLayer {
|
||||
///
|
||||
/// https://github.com/ethereum/consensus-specs/blob/v1.1.0/specs/merge/validator.md
|
||||
pub async fn get_terminal_pow_block_hash(&self) -> Result<Option<Hash256>, Error> {
|
||||
self.engines()
|
||||
let hash_opt = self
|
||||
.engines()
|
||||
.first_success(|engine| async move {
|
||||
if self.terminal_block_hash() != Hash256::zero() {
|
||||
// Note: the specification is written such that if there are multiple blocks in
|
||||
@ -376,7 +413,19 @@ impl ExecutionLayer {
|
||||
}
|
||||
})
|
||||
.await
|
||||
.map_err(Error::EngineErrors)
|
||||
.map_err(Error::EngineErrors)?;
|
||||
|
||||
if let Some(hash) = &hash_opt {
|
||||
info!(
|
||||
self.log(),
|
||||
"Found terminal block hash";
|
||||
"terminal_block_hash_override" => ?self.terminal_block_hash(),
|
||||
"terminal_total_difficulty" => ?self.terminal_total_difficulty(),
|
||||
"block_hash" => ?hash,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(hash_opt)
|
||||
}
|
||||
|
||||
/// This function should remain internal. External users should use
|
||||
|
@ -5,6 +5,8 @@ use ssz::Encode;
|
||||
use state_processing::initialize_beacon_state_from_eth1;
|
||||
use types::{BeaconState, ChainSpec, DepositData, EthSpec, Hash256, Keypair, PublicKey, Signature};
|
||||
|
||||
pub const DEFAULT_ETH1_BLOCK_HASH: &[u8] = &[0x42; 32];
|
||||
|
||||
/// Builds a genesis state as defined by the Eth2 interop procedure (see below).
|
||||
///
|
||||
/// Reference:
|
||||
@ -12,9 +14,10 @@ use types::{BeaconState, ChainSpec, DepositData, EthSpec, Hash256, Keypair, Publ
|
||||
pub fn interop_genesis_state<T: EthSpec>(
|
||||
keypairs: &[Keypair],
|
||||
genesis_time: u64,
|
||||
eth1_block_hash: Hash256,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<BeaconState<T>, String> {
|
||||
let eth1_block_hash = Hash256::from_slice(&[0x42; 32]);
|
||||
let eth1_block_hash = eth1_block_hash;
|
||||
let eth1_timestamp = 2_u64.pow(40);
|
||||
let amount = spec.max_effective_balance;
|
||||
|
||||
@ -73,7 +76,12 @@ mod test {
|
||||
|
||||
let keypairs = generate_deterministic_keypairs(validator_count);
|
||||
|
||||
let state = interop_genesis_state::<TestEthSpec>(&keypairs, genesis_time, spec)
|
||||
let state = interop_genesis_state::<TestEthSpec>(
|
||||
&keypairs,
|
||||
genesis_time,
|
||||
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||
spec,
|
||||
)
|
||||
.expect("should build state");
|
||||
|
||||
assert_eq!(
|
||||
|
@ -4,5 +4,5 @@ mod interop;
|
||||
|
||||
pub use eth1::Config as Eth1Config;
|
||||
pub use eth1_genesis_service::{Eth1GenesisService, Statistics};
|
||||
pub use interop::interop_genesis_state;
|
||||
pub use interop::{interop_genesis_state, DEFAULT_ETH1_BLOCK_HASH};
|
||||
pub use types::test_utils::generate_deterministic_keypairs;
|
||||
|
@ -97,6 +97,7 @@ pub struct Config {
|
||||
pub allow_origin: Option<String>,
|
||||
pub serve_legacy_spec: bool,
|
||||
pub tls_config: Option<TlsConfig>,
|
||||
pub allow_sync_stalled: bool,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@ -108,6 +109,7 @@ impl Default for Config {
|
||||
allow_origin: None,
|
||||
serve_legacy_spec: true,
|
||||
tls_config: None,
|
||||
allow_sync_stalled: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -237,6 +239,7 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
shutdown: impl Future<Output = ()> + Send + Sync + 'static,
|
||||
) -> Result<HttpServer, Error> {
|
||||
let config = ctx.config.clone();
|
||||
let allow_sync_stalled = config.allow_sync_stalled;
|
||||
let log = ctx.log.clone();
|
||||
|
||||
// Configure CORS.
|
||||
@ -338,19 +341,21 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
});
|
||||
|
||||
// Create a `warp` filter that rejects request whilst the node is syncing.
|
||||
let not_while_syncing_filter = warp::any()
|
||||
let not_while_syncing_filter =
|
||||
warp::any()
|
||||
.and(network_globals.clone())
|
||||
.and(chain_filter.clone())
|
||||
.and_then(
|
||||
|network_globals: Arc<NetworkGlobals<T::EthSpec>>, chain: Arc<BeaconChain<T>>| async move {
|
||||
move |network_globals: Arc<NetworkGlobals<T::EthSpec>>,
|
||||
chain: Arc<BeaconChain<T>>| async move {
|
||||
match *network_globals.sync_state.read() {
|
||||
SyncState::SyncingFinalized { .. } => {
|
||||
let head_slot = chain.best_slot().map_err(warp_utils::reject::beacon_chain_error)?;
|
||||
let head_slot = chain
|
||||
.best_slot()
|
||||
.map_err(warp_utils::reject::beacon_chain_error)?;
|
||||
|
||||
let current_slot = chain
|
||||
.slot_clock
|
||||
.now_or_genesis()
|
||||
.ok_or_else(|| {
|
||||
let current_slot =
|
||||
chain.slot_clock.now_or_genesis().ok_or_else(|| {
|
||||
warp_utils::reject::custom_server_error(
|
||||
"unable to read slot clock".to_string(),
|
||||
)
|
||||
@ -367,8 +372,11 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
)))
|
||||
}
|
||||
}
|
||||
SyncState::SyncingHead { .. } | SyncState::SyncTransition | SyncState::BackFillSyncing { .. } => Ok(()),
|
||||
SyncState::SyncingHead { .. }
|
||||
| SyncState::SyncTransition
|
||||
| SyncState::BackFillSyncing { .. } => Ok(()),
|
||||
SyncState::Synced => Ok(()),
|
||||
SyncState::Stalled if allow_sync_stalled => Ok(()),
|
||||
SyncState::Stalled => Err(warp_utils::reject::not_synced(
|
||||
"sync is stalled".to_string(),
|
||||
)),
|
||||
|
@ -133,6 +133,7 @@ pub async fn create_api_server<T: BeaconChainTypes>(
|
||||
allow_origin: None,
|
||||
serve_legacy_spec: true,
|
||||
tls_config: None,
|
||||
allow_sync_stalled: false,
|
||||
},
|
||||
chain: Some(chain.clone()),
|
||||
network_tx: Some(network_tx),
|
||||
|
@ -5,7 +5,7 @@ use beacon_chain::{
|
||||
BeaconChain,
|
||||
};
|
||||
use futures::prelude::*;
|
||||
use genesis::{generate_deterministic_keypairs, interop_genesis_state};
|
||||
use genesis::{generate_deterministic_keypairs, interop_genesis_state, DEFAULT_ETH1_BLOCK_HASH};
|
||||
use lazy_static::lazy_static;
|
||||
use lighthouse_network::NetworkConfig;
|
||||
use slog::Logger;
|
||||
@ -16,8 +16,8 @@ use std::time::{Duration, SystemTime};
|
||||
use store::config::StoreConfig;
|
||||
use store::{HotColdDB, MemoryStore};
|
||||
use types::{
|
||||
CommitteeIndex, Epoch, EthSpec, MainnetEthSpec, Slot, SubnetId, SyncCommitteeSubscription,
|
||||
SyncSubnetId, ValidatorSubscription,
|
||||
CommitteeIndex, Epoch, EthSpec, Hash256, MainnetEthSpec, Slot, SubnetId,
|
||||
SyncCommitteeSubscription, SyncSubnetId, ValidatorSubscription,
|
||||
};
|
||||
|
||||
const SLOT_DURATION_MILLIS: u64 = 400;
|
||||
@ -52,7 +52,12 @@ impl TestBeaconChain {
|
||||
.custom_spec(spec.clone())
|
||||
.store(Arc::new(store))
|
||||
.genesis_state(
|
||||
interop_genesis_state::<MainnetEthSpec>(&keypairs, 0, &spec)
|
||||
interop_genesis_state::<MainnetEthSpec>(
|
||||
&keypairs,
|
||||
0,
|
||||
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||
&spec,
|
||||
)
|
||||
.expect("should generate interop state"),
|
||||
)
|
||||
.expect("should build state using recent genesis")
|
||||
|
@ -240,6 +240,13 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
over TLS. Must not be password-protected.")
|
||||
.takes_value(true)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("http-allow-sync-stalled")
|
||||
.long("http-allow-sync-stalled")
|
||||
.help("Forces the HTTP to indicate that the node is synced when sync is actually \
|
||||
stalled. This is useful for very small testnets. TESTING ONLY. DO NOT USE ON \
|
||||
MAINNET.")
|
||||
)
|
||||
/* Prometheus metrics HTTP server related arguments */
|
||||
.arg(
|
||||
Arg::with_name("metrics")
|
||||
|
@ -131,6 +131,10 @@ pub fn get_config<E: EthSpec>(
|
||||
});
|
||||
}
|
||||
|
||||
if cli_args.is_present("http-allow-sync-stalled") {
|
||||
client_config.http_api.allow_sync_stalled = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prometheus metrics HTTP server
|
||||
*/
|
||||
|
@ -3,6 +3,7 @@ use crate::test_utils::*;
|
||||
use crate::test_utils::{SeedableRng, XorShiftRng};
|
||||
use beacon_chain::test_utils::{
|
||||
interop_genesis_state, test_spec, BeaconChainHarness, EphemeralHarnessType,
|
||||
DEFAULT_ETH1_BLOCK_HASH,
|
||||
};
|
||||
use beacon_chain::types::{
|
||||
test_utils::TestRandom, BeaconState, BeaconStateAltair, BeaconStateBase, BeaconStateError,
|
||||
@ -557,7 +558,13 @@ fn tree_hash_cache_linear_history_long_skip() {
|
||||
let spec = &test_spec::<MinimalEthSpec>();
|
||||
|
||||
// This state has a cache that advances normally each slot.
|
||||
let mut state: BeaconState<MinimalEthSpec> = interop_genesis_state(&keypairs, 0, spec).unwrap();
|
||||
let mut state: BeaconState<MinimalEthSpec> = interop_genesis_state(
|
||||
&keypairs,
|
||||
0,
|
||||
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||
spec,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
state.update_tree_hash_cache().unwrap();
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
use clap::ArgMatches;
|
||||
use clap_utils::parse_ssz_optional;
|
||||
use eth2_network_config::Eth2NetworkConfig;
|
||||
use genesis::interop_genesis_state;
|
||||
use genesis::{interop_genesis_state, DEFAULT_ETH1_BLOCK_HASH};
|
||||
use ssz::Encode;
|
||||
use std::path::PathBuf;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use types::{test_utils::generate_deterministic_keypairs, EthSpec};
|
||||
use types::{test_utils::generate_deterministic_keypairs, EthSpec, Hash256};
|
||||
|
||||
pub fn run<T: EthSpec>(testnet_dir: PathBuf, matches: &ArgMatches) -> Result<(), String> {
|
||||
let validator_count = matches
|
||||
@ -34,7 +34,12 @@ pub fn run<T: EthSpec>(testnet_dir: PathBuf, matches: &ArgMatches) -> Result<(),
|
||||
}
|
||||
|
||||
let keypairs = generate_deterministic_keypairs(validator_count);
|
||||
let genesis_state = interop_genesis_state::<T>(&keypairs, genesis_time, &spec)?;
|
||||
let genesis_state = interop_genesis_state::<T>(
|
||||
&keypairs,
|
||||
genesis_time,
|
||||
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||
&spec,
|
||||
)?;
|
||||
|
||||
eth2_network_config.genesis_state_bytes = Some(genesis_state.as_ssz_bytes());
|
||||
eth2_network_config.force_write_to_file(testnet_dir)?;
|
||||
|
@ -284,6 +284,14 @@ fn main() {
|
||||
.takes_value(false)
|
||||
.help("Overwrites any previous testnet configurations"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("interop-genesis-state")
|
||||
.long("interop-genesis-state")
|
||||
.takes_value(false)
|
||||
.help(
|
||||
"If present, a interop-style genesis.ssz file will be generated.",
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("min-genesis-time")
|
||||
.long("min-genesis-time")
|
||||
@ -402,6 +410,36 @@ fn main() {
|
||||
"The epoch at which to enable the Altair hard fork",
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("merge-fork-epoch")
|
||||
.long("merge-fork-epoch")
|
||||
.value_name("EPOCH")
|
||||
.takes_value(true)
|
||||
.help(
|
||||
"The epoch at which to enable the Merge hard fork",
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("eth1-block-hash")
|
||||
.long("eth1-block-hash")
|
||||
.value_name("BLOCK_HASH")
|
||||
.takes_value(true)
|
||||
.help("The eth1 block hash used when generating a genesis state."),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("validator-count")
|
||||
.long("validator-count")
|
||||
.value_name("INTEGER")
|
||||
.takes_value(true)
|
||||
.help("The number of validators when generating a genesis state."),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("genesis-time")
|
||||
.long("genesis-time")
|
||||
.value_name("INTEGER")
|
||||
.takes_value(true)
|
||||
.help("The genesis time when generating a genesis state."),
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("check-deposit-data")
|
||||
|
@ -1,8 +1,11 @@
|
||||
use clap::ArgMatches;
|
||||
use clap_utils::{parse_optional, parse_required, parse_ssz_optional};
|
||||
use eth2_network_config::Eth2NetworkConfig;
|
||||
use genesis::interop_genesis_state;
|
||||
use ssz::Encode;
|
||||
use std::path::PathBuf;
|
||||
use types::{Address, Config, EthSpec};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use types::{test_utils::generate_deterministic_keypairs, Address, Config, EthSpec};
|
||||
|
||||
pub fn run<T: EthSpec>(testnet_dir_path: PathBuf, matches: &ArgMatches) -> Result<(), String> {
|
||||
let deposit_contract_address: Address = parse_required(matches, "deposit-contract-address")?;
|
||||
@ -54,10 +57,35 @@ pub fn run<T: EthSpec>(testnet_dir_path: PathBuf, matches: &ArgMatches) -> Resul
|
||||
spec.altair_fork_epoch = Some(fork_epoch);
|
||||
}
|
||||
|
||||
if let Some(fork_epoch) = parse_optional(matches, "merge-fork-epoch")? {
|
||||
spec.merge_fork_epoch = Some(fork_epoch);
|
||||
}
|
||||
|
||||
let genesis_state_bytes = if matches.is_present("interop-genesis-state") {
|
||||
let eth1_block_hash = parse_required(matches, "eth1-block-hash")?;
|
||||
let validator_count = parse_required(matches, "validator-count")?;
|
||||
let genesis_time = if let Some(time) = parse_optional(matches, "genesis-time")? {
|
||||
time
|
||||
} else {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map_err(|e| format!("Unable to get time: {:?}", e))?
|
||||
.as_secs()
|
||||
};
|
||||
|
||||
let keypairs = generate_deterministic_keypairs(validator_count);
|
||||
let genesis_state =
|
||||
interop_genesis_state::<T>(&keypairs, genesis_time, eth1_block_hash, &spec)?;
|
||||
|
||||
Some(genesis_state.as_ssz_bytes())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let testnet = Eth2NetworkConfig {
|
||||
deposit_contract_deploy_block,
|
||||
boot_enr: Some(vec![]),
|
||||
genesis_state_bytes: None,
|
||||
genesis_state_bytes,
|
||||
config: Config::from_chain_spec::<T>(&spec),
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user