mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-11 18:04:18 +00:00
Add lcli eth1-genesis command
This commit is contained in:
@@ -194,38 +194,8 @@ where
|
||||
"eth1_node" => &config.endpoint
|
||||
);
|
||||
|
||||
let genesis_service = Eth1GenesisService::new(
|
||||
// Some of the configuration options for `Eth1Config` are
|
||||
// hard-coded when listening for genesis from the deposit contract.
|
||||
//
|
||||
// The idea is that the `Eth1Config` supplied to this function
|
||||
// (`config`) is intended for block production duties (i.e.,
|
||||
// listening for deposit events and voting on eth1 data) and that
|
||||
// we can make listening for genesis more efficient if we modify
|
||||
// some params.
|
||||
Eth1Config {
|
||||
// Truncating the block cache makes searching for genesis more
|
||||
// complicated.
|
||||
block_cache_truncation: None,
|
||||
// Scan large ranges of blocks when awaiting genesis.
|
||||
blocks_per_log_query: 1_000,
|
||||
// Only perform a single log request each time the eth1 node is
|
||||
// polled.
|
||||
//
|
||||
// For small testnets this makes finding genesis much faster,
|
||||
// as it usually happens within 1,000 blocks.
|
||||
max_log_requests_per_update: Some(1),
|
||||
// Only perform a single block request each time the eth1 node
|
||||
// is polled.
|
||||
//
|
||||
// For small testnets, this is much faster as they do not have
|
||||
// a `MIN_GENESIS_SECONDS`, so after `MIN_GENESIS_VALIDATOR_COUNT`
|
||||
// has been reached only a single block needs to be read.
|
||||
max_blocks_per_update: Some(1),
|
||||
..config
|
||||
},
|
||||
context.log.clone(),
|
||||
);
|
||||
let genesis_service =
|
||||
Eth1GenesisService::new(config, context.log.clone());
|
||||
|
||||
let future = genesis_service
|
||||
.wait_for_genesis_state(
|
||||
|
||||
@@ -39,6 +39,7 @@ impl Default for ClientGenesis {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
pub data_dir: PathBuf,
|
||||
pub testnet_dir: PathBuf,
|
||||
pub db_type: String,
|
||||
pub db_name: String,
|
||||
pub freezer_db_path: Option<PathBuf>,
|
||||
@@ -63,6 +64,7 @@ impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
data_dir: PathBuf::from(".lighthouse"),
|
||||
testnet_dir: PathBuf::from("testnet"),
|
||||
log_file: PathBuf::from(""),
|
||||
db_type: "disk".to_string(),
|
||||
db_name: "chain_db".to_string(),
|
||||
|
||||
@@ -59,6 +59,11 @@ impl BlockCache {
|
||||
self.blocks.first().map(|block| block.timestamp)
|
||||
}
|
||||
|
||||
/// Returns the timestamp of the latest block in the cache (if any).
|
||||
pub fn latest_block_timestamp(&self) -> Option<u64> {
|
||||
self.blocks.last().map(|block| block.timestamp)
|
||||
}
|
||||
|
||||
/// Returns the lowest block number stored.
|
||||
pub fn lowest_block_number(&self) -> Option<u64> {
|
||||
self.blocks.first().map(|block| block.number)
|
||||
|
||||
@@ -173,6 +173,11 @@ impl Service {
|
||||
self.inner.block_cache.read().earliest_block_timestamp()
|
||||
}
|
||||
|
||||
/// Returns the timestamp of the latest block in the cache (if any).
|
||||
pub fn latest_block_timestamp(&self) -> Option<u64> {
|
||||
self.inner.block_cache.read().latest_block_timestamp()
|
||||
}
|
||||
|
||||
/// Returns the lowest block number stored.
|
||||
pub fn lowest_block_number(&self) -> Option<u64> {
|
||||
self.inner.block_cache.read().lowest_block_number()
|
||||
|
||||
@@ -37,7 +37,31 @@ pub struct Eth1GenesisService {
|
||||
|
||||
impl Eth1GenesisService {
|
||||
/// Creates a new service. Does not attempt to connect to the Eth1 node.
|
||||
///
|
||||
/// Modifies the given `config` to make it more suitable to the task of listening to genesis.
|
||||
pub fn new(config: Eth1Config, log: Logger) -> Self {
|
||||
let config = Eth1Config {
|
||||
// Truncating the block cache makes searching for genesis more
|
||||
// complicated.
|
||||
block_cache_truncation: None,
|
||||
// Scan large ranges of blocks when awaiting genesis.
|
||||
blocks_per_log_query: 1_000,
|
||||
// Only perform a single log request each time the eth1 node is
|
||||
// polled.
|
||||
//
|
||||
// For small testnets this makes finding genesis much faster,
|
||||
// as it usually happens within 1,000 blocks.
|
||||
max_log_requests_per_update: Some(5),
|
||||
// Only perform a single block request each time the eth1 node
|
||||
// is polled.
|
||||
//
|
||||
// For small testnets, this is much faster as they do not have
|
||||
// a `MIN_GENESIS_SECONDS`, so after `MIN_GENESIS_VALIDATOR_COUNT`
|
||||
// has been reached only a single block needs to be read.
|
||||
max_blocks_per_update: Some(5),
|
||||
..config
|
||||
};
|
||||
|
||||
Self {
|
||||
core: Service::new(config, log),
|
||||
highest_processed_block: Arc::new(Mutex::new(None)),
|
||||
@@ -81,6 +105,7 @@ impl Eth1GenesisService {
|
||||
let service_4 = service.clone();
|
||||
let log = service.core.log.clone();
|
||||
let min_genesis_active_validator_count = spec.min_genesis_active_validator_count;
|
||||
let min_genesis_time = spec.min_genesis_time;
|
||||
|
||||
Delay::new(Instant::now() + update_interval)
|
||||
.map_err(|e| format!("Delay between genesis deposit checks failed: {:?}", e))
|
||||
@@ -161,6 +186,9 @@ impl Eth1GenesisService {
|
||||
trace!(
|
||||
service_4.core.log,
|
||||
"No eth1 genesis block found";
|
||||
"latest_block_timestamp" => service_4.core.latest_block_timestamp(),
|
||||
"min_genesis_time" => min_genesis_time,
|
||||
"min_validator_count" => min_genesis_active_validator_count,
|
||||
"cached_blocks" => service_4.core.block_cache_len(),
|
||||
"cached_deposits" => service_4.core.deposit_cache_len(),
|
||||
"cache_head" => service_4.highest_known_block(),
|
||||
@@ -218,7 +246,7 @@ impl Eth1GenesisService {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.is_valid_genesis_eth1_block::<E>(block, &spec)
|
||||
self.is_valid_genesis_eth1_block::<E>(block, &spec, &self.core.log)
|
||||
.and_then(|val| {
|
||||
*highest_processed_block = Some(block.number);
|
||||
Ok(val)
|
||||
@@ -313,6 +341,7 @@ impl Eth1GenesisService {
|
||||
&self,
|
||||
target_block: &Eth1Block,
|
||||
spec: &ChainSpec,
|
||||
log: &Logger,
|
||||
) -> Result<bool, String> {
|
||||
if target_block.timestamp < spec.min_genesis_time {
|
||||
Ok(false)
|
||||
@@ -357,8 +386,16 @@ impl Eth1GenesisService {
|
||||
})?;
|
||||
|
||||
process_activations(&mut local_state, spec);
|
||||
let is_valid = is_valid_genesis_state(&local_state, spec);
|
||||
|
||||
Ok(is_valid_genesis_state(&local_state, spec))
|
||||
trace!(
|
||||
log,
|
||||
"Eth1 block inspected for genesis";
|
||||
"active_validators" => local_state.get_active_validator_indices(local_state.current_epoch()).len(),
|
||||
"validators" => local_state.validators.len()
|
||||
);
|
||||
|
||||
Ok(is_valid)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
Arg::with_name("network-dir")
|
||||
.long("network-dir")
|
||||
.value_name("DIR")
|
||||
.help("Data directory for network keys.")
|
||||
.help("Data directory for network keys. Defaults to network/ inside the beacon node \
|
||||
dir.")
|
||||
.takes_value(true)
|
||||
.global(true)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("freezer-dir")
|
||||
@@ -23,7 +23,14 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
.value_name("DIR")
|
||||
.help("Data directory for the freezer database.")
|
||||
.takes_value(true)
|
||||
.global(true)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("testnet-dir")
|
||||
.long("testnet-dir")
|
||||
.value_name("DIR")
|
||||
.help("Path to directory containing eth2_testnet specs. Defaults to \
|
||||
~/.lighthouse/testnet.")
|
||||
.takes_value(true)
|
||||
)
|
||||
/*
|
||||
* Network parameters.
|
||||
|
||||
@@ -9,12 +9,13 @@ use slog::{crit, info, Logger};
|
||||
use std::fs;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::path::PathBuf;
|
||||
use types::{Epoch, Fork};
|
||||
use types::{Epoch, EthSpec, Fork};
|
||||
|
||||
pub const CLIENT_CONFIG_FILENAME: &str = "beacon-node.toml";
|
||||
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";
|
||||
pub const ETH2_TESTNET_DIR: &str = "testnet";
|
||||
pub const BEACON_NODE_DIR: &str = "beacon";
|
||||
pub const NETWORK_DIR: &str = "network";
|
||||
|
||||
pub const SECONDS_PER_ETH1_BLOCK: u64 = 15;
|
||||
|
||||
@@ -28,7 +29,7 @@ type Config = (ClientConfig, Eth2Config, Logger);
|
||||
/// The output of this function depends primarily upon the given `cli_args`, however it's behaviour
|
||||
/// may be influenced by other external services like the contents of the file system or the
|
||||
/// response of some remote server.
|
||||
pub fn get_configs(
|
||||
pub fn get_configs<E: EthSpec>(
|
||||
cli_args: &ArgMatches,
|
||||
mut eth2_config: Eth2Config,
|
||||
core_log: Logger,
|
||||
@@ -41,16 +42,20 @@ pub fn get_configs(
|
||||
//
|
||||
// If it's not present, try and find the home directory (`~`) and push the default data
|
||||
// directory onto it.
|
||||
//
|
||||
// Note: the `config.data_dir` defines the _global_ lighthouse datadir, not just the beacon
|
||||
// node specific datadir.
|
||||
let data_dir: PathBuf = cli_args
|
||||
client_config.data_dir = cli_args
|
||||
.value_of("datadir")
|
||||
.map(PathBuf::from)
|
||||
.or_else(|| dirs::home_dir().map(|home| home.join(".lighthouse").join(BEACON_NODE_DIR)))
|
||||
.ok_or_else(|| "Unable to find a home directory for the datadir".to_string())?;
|
||||
|
||||
client_config.data_dir = data_dir;
|
||||
// Read the `--testnet-dir` flag.
|
||||
//
|
||||
// If it's not present, use the default dir.
|
||||
client_config.testnet_dir = cli_args
|
||||
.value_of("testnet-dir")
|
||||
.map(PathBuf::from)
|
||||
.or_else(|| dirs::home_dir().map(|home| home.join(".lighthouse").join(ETH2_TESTNET_DIR)))
|
||||
.ok_or_else(|| "Unable to find a home directory for the testnet-dir".to_string())?;
|
||||
|
||||
// When present, use an eth1 backend that generates deterministic junk.
|
||||
//
|
||||
@@ -79,6 +84,8 @@ pub fn get_configs(
|
||||
// If a network dir has been specified, override the `datadir` definition.
|
||||
if let Some(dir) = cli_args.value_of("network-dir") {
|
||||
client_config.network.network_dir = PathBuf::from(dir);
|
||||
} else {
|
||||
client_config.network.network_dir = client_config.data_dir.join(NETWORK_DIR);
|
||||
};
|
||||
|
||||
if let Some(listen_address_str) = cli_args.value_of("listen-address") {
|
||||
@@ -213,7 +220,7 @@ pub fn get_configs(
|
||||
// Whilst there is no large testnet or mainnet force the user to specify how they want
|
||||
// to start a new chain (e.g., from a genesis YAML file, another node, etc).
|
||||
if !client_config.data_dir.exists() {
|
||||
init_new_client(&mut client_config, &mut eth2_config)?
|
||||
init_new_client::<E>(&mut client_config, &mut eth2_config)?
|
||||
} else {
|
||||
// If the `testnet` command was not provided, attempt to load an existing datadir and
|
||||
// continue with an existing chain.
|
||||
@@ -288,21 +295,20 @@ fn load_from_datadir(client_config: &mut ClientConfig, eth2_config: &mut Eth2Con
|
||||
}
|
||||
|
||||
/// Create a new client with the default configuration.
|
||||
fn init_new_client(client_config: &mut ClientConfig, eth2_config: &mut Eth2Config) -> Result<()> {
|
||||
fn init_new_client<E: EthSpec>(
|
||||
client_config: &mut ClientConfig,
|
||||
eth2_config: &mut Eth2Config,
|
||||
) -> Result<()> {
|
||||
let spec = &mut eth2_config.spec;
|
||||
|
||||
spec.min_deposit_amount = 100;
|
||||
spec.max_effective_balance = 3_200_000_000;
|
||||
spec.ejection_balance = 1_600_000_000;
|
||||
spec.effective_balance_increment = 100_000_000;
|
||||
spec.genesis_fork = Fork {
|
||||
previous_version: [0; 4],
|
||||
current_version: [0, 0, 0, 42],
|
||||
epoch: Epoch::new(0),
|
||||
};
|
||||
|
||||
let eth2_testnet_dir = Eth2TestnetDir::load(client_config.data_dir.join(ETH2_TESTNET_DIR))
|
||||
.map_err(|e| format!("Unable to open testnet dir: {}", e))?;
|
||||
let testnet_dir = client_config.testnet_dir.clone();
|
||||
let eth2_testnet_dir: Eth2TestnetDir<E> = Eth2TestnetDir::load(testnet_dir.clone())
|
||||
.map_err(|e| format!("Unable to open testnet dir at {:?}: {}", testnet_dir, e))?;
|
||||
|
||||
client_config.eth1.deposit_contract_address =
|
||||
format!("{:?}", eth2_testnet_dir.deposit_contract_address()?);
|
||||
|
||||
@@ -60,7 +60,7 @@ impl<E: EthSpec> ProductionBeaconNode<E> {
|
||||
// TODO: the eth2 config in the env is being modified.
|
||||
//
|
||||
// See https://github.com/sigp/lighthouse/issues/602
|
||||
get_configs(&matches, context.eth2_config.clone(), log)
|
||||
get_configs::<E>(&matches, context.eth2_config.clone(), log)
|
||||
.into_future()
|
||||
.and_then(move |(client_config, eth2_config, _log)| {
|
||||
context.eth2_config = eth2_config;
|
||||
|
||||
Reference in New Issue
Block a user