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`
|
# Binaries will most likely be found in `./target/release`
|
||||||
install:
|
install:
|
||||||
ifeq ($(PORTABLE), true)
|
ifeq ($(PORTABLE), true)
|
||||||
cargo install --path lighthouse --force --locked --features portable
|
cargo install --path lighthouse --force --locked --features portable,spec-minimal
|
||||||
else
|
else
|
||||||
cargo install --path lighthouse --force --locked
|
cargo install --path lighthouse --force --locked --features spec-minimal
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Builds the lcli binary in release (optimized).
|
# Builds the lcli binary in release (optimized).
|
||||||
|
@ -919,7 +919,9 @@ fn descriptive_db_error(item: &str, error: &StoreError) -> String {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use eth2_hashing::hash;
|
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 sloggers::{null::NullLoggerBuilder, Build};
|
||||||
use ssz::Encode;
|
use ssz::Encode;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -951,6 +953,7 @@ mod test {
|
|||||||
let genesis_state = interop_genesis_state(
|
let genesis_state = interop_genesis_state(
|
||||||
&generate_deterministic_keypairs(validator_count),
|
&generate_deterministic_keypairs(validator_count),
|
||||||
genesis_time,
|
genesis_time,
|
||||||
|
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||||
&spec,
|
&spec,
|
||||||
)
|
)
|
||||||
.expect("should create interop genesis state");
|
.expect("should create interop genesis state");
|
||||||
@ -1016,8 +1019,13 @@ mod test {
|
|||||||
|
|
||||||
let keypairs = generate_deterministic_keypairs(validator_count);
|
let keypairs = generate_deterministic_keypairs(validator_count);
|
||||||
|
|
||||||
let state = interop_genesis_state::<TestEthSpec>(&keypairs, genesis_time, spec)
|
let state = interop_genesis_state::<TestEthSpec>(
|
||||||
.expect("should build state");
|
&keypairs,
|
||||||
|
genesis_time,
|
||||||
|
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||||
|
spec,
|
||||||
|
)
|
||||||
|
.expect("should build state");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
state.eth1_data().block_hash,
|
state.eth1_data().block_hash,
|
||||||
|
@ -18,7 +18,7 @@ use execution_layer::{
|
|||||||
ExecutionLayer,
|
ExecutionLayer,
|
||||||
};
|
};
|
||||||
use futures::channel::mpsc::Receiver;
|
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 int_to_bytes::int_to_bytes32;
|
||||||
use logging::test_logger;
|
use logging::test_logger;
|
||||||
use merkle_proof::MerkleTree;
|
use merkle_proof::MerkleTree;
|
||||||
@ -181,6 +181,7 @@ impl<E: EthSpec> Builder<EphemeralHarnessType<E>> {
|
|||||||
let genesis_state = interop_genesis_state::<E>(
|
let genesis_state = interop_genesis_state::<E>(
|
||||||
&validator_keypairs,
|
&validator_keypairs,
|
||||||
HARNESS_GENESIS_TIME,
|
HARNESS_GENESIS_TIME,
|
||||||
|
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||||
builder.get_spec(),
|
builder.get_spec(),
|
||||||
)
|
)
|
||||||
.expect("should generate interop state");
|
.expect("should generate interop state");
|
||||||
@ -226,6 +227,7 @@ impl<E: EthSpec> Builder<DiskHarnessType<E>> {
|
|||||||
let genesis_state = interop_genesis_state::<E>(
|
let genesis_state = interop_genesis_state::<E>(
|
||||||
&validator_keypairs,
|
&validator_keypairs,
|
||||||
HARNESS_GENESIS_TIME,
|
HARNESS_GENESIS_TIME,
|
||||||
|
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||||
builder.get_spec(),
|
builder.get_spec(),
|
||||||
)
|
)
|
||||||
.expect("should generate interop state");
|
.expect("should generate interop state");
|
||||||
|
@ -17,7 +17,7 @@ use eth2::{
|
|||||||
BeaconNodeHttpClient, Error as ApiError, Timeouts,
|
BeaconNodeHttpClient, Error as ApiError, Timeouts,
|
||||||
};
|
};
|
||||||
use execution_layer::ExecutionLayer;
|
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 lighthouse_network::NetworkGlobals;
|
||||||
use monitoring_api::{MonitoringHttpClient, ProcessType};
|
use monitoring_api::{MonitoringHttpClient, ProcessType};
|
||||||
use network::{NetworkConfig, NetworkMessage, NetworkService};
|
use network::{NetworkConfig, NetworkMessage, NetworkService};
|
||||||
@ -31,7 +31,8 @@ use std::time::Duration;
|
|||||||
use timer::spawn_timer;
|
use timer::spawn_timer;
|
||||||
use tokio::sync::{mpsc::UnboundedSender, oneshot};
|
use tokio::sync::{mpsc::UnboundedSender, oneshot};
|
||||||
use types::{
|
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.
|
/// Interval between polling the eth1 node for genesis information.
|
||||||
@ -229,7 +230,12 @@ where
|
|||||||
genesis_time,
|
genesis_time,
|
||||||
} => {
|
} => {
|
||||||
let keypairs = generate_deterministic_keypairs(validator_count);
|
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))?
|
builder.genesis_state(genesis_state).map(|v| (v, None))?
|
||||||
}
|
}
|
||||||
ClientGenesis::SszBytes {
|
ClientGenesis::SszBytes {
|
||||||
|
@ -8,7 +8,7 @@ use engine_api::{Error as ApiError, *};
|
|||||||
use engines::{Engine, EngineError, Engines};
|
use engines::{Engine, EngineError, Engines};
|
||||||
use lru::LruCache;
|
use lru::LruCache;
|
||||||
use sensitive_url::SensitiveUrl;
|
use sensitive_url::SensitiveUrl;
|
||||||
use slog::{crit, Logger};
|
use slog::{crit, info, Logger};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use task_executor::TaskExecutor;
|
use task_executor::TaskExecutor;
|
||||||
@ -177,6 +177,14 @@ impl ExecutionLayer {
|
|||||||
random: Hash256,
|
random: Hash256,
|
||||||
) -> Result<PayloadId, Error> {
|
) -> Result<PayloadId, Error> {
|
||||||
let fee_recipient = self.fee_recipient()?;
|
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()
|
self.engines()
|
||||||
.first_success(|engine| {
|
.first_success(|engine| {
|
||||||
// TODO(merge): make a cache for these IDs, so we don't always have to perform this
|
// 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,
|
random: Hash256,
|
||||||
) -> Result<ExecutionPayload<T>, Error> {
|
) -> Result<ExecutionPayload<T>, Error> {
|
||||||
let fee_recipient = self.fee_recipient()?;
|
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()
|
self.engines()
|
||||||
.first_success(|engine| async move {
|
.first_success(|engine| async move {
|
||||||
// TODO(merge): make a cache for these IDs, so we don't always have to perform this
|
// TODO(merge): make a cache for these IDs, so we don't always have to perform this
|
||||||
@ -236,6 +252,14 @@ impl ExecutionLayer {
|
|||||||
&self,
|
&self,
|
||||||
execution_payload: &ExecutionPayload<T>,
|
execution_payload: &ExecutionPayload<T>,
|
||||||
) -> Result<(ExecutePayloadResponse, ExecutePayloadHandle), Error> {
|
) -> 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
|
let broadcast_results = self
|
||||||
.engines()
|
.engines()
|
||||||
.broadcast(|engine| engine.api.execute_payload(execution_payload.clone()))
|
.broadcast(|engine| engine.api.execute_payload(execution_payload.clone()))
|
||||||
@ -296,6 +320,12 @@ impl ExecutionLayer {
|
|||||||
block_hash: Hash256,
|
block_hash: Hash256,
|
||||||
status: ConsensusStatus,
|
status: ConsensusStatus,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
info!(
|
||||||
|
self.log(),
|
||||||
|
"Issuing engine_consensusValidated";
|
||||||
|
"status" => ?status,
|
||||||
|
"block_hash" => ?block_hash,
|
||||||
|
);
|
||||||
let broadcast_results = self
|
let broadcast_results = self
|
||||||
.engines()
|
.engines()
|
||||||
.broadcast(|engine| engine.api.consensus_validated(block_hash, status))
|
.broadcast(|engine| engine.api.consensus_validated(block_hash, status))
|
||||||
@ -328,6 +358,12 @@ impl ExecutionLayer {
|
|||||||
head_block_hash: Hash256,
|
head_block_hash: Hash256,
|
||||||
finalized_block_hash: Hash256,
|
finalized_block_hash: Hash256,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
info!(
|
||||||
|
self.log(),
|
||||||
|
"Issuing engine_forkchoiceUpdated";
|
||||||
|
"finalized_block_hash" => ?finalized_block_hash,
|
||||||
|
"head_block_hash" => ?head_block_hash,
|
||||||
|
);
|
||||||
let broadcast_results = self
|
let broadcast_results = self
|
||||||
.engines()
|
.engines()
|
||||||
.broadcast(|engine| {
|
.broadcast(|engine| {
|
||||||
@ -357,7 +393,8 @@ impl ExecutionLayer {
|
|||||||
///
|
///
|
||||||
/// https://github.com/ethereum/consensus-specs/blob/v1.1.0/specs/merge/validator.md
|
/// 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> {
|
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 {
|
.first_success(|engine| async move {
|
||||||
if self.terminal_block_hash() != Hash256::zero() {
|
if self.terminal_block_hash() != Hash256::zero() {
|
||||||
// Note: the specification is written such that if there are multiple blocks in
|
// Note: the specification is written such that if there are multiple blocks in
|
||||||
@ -376,7 +413,19 @@ impl ExecutionLayer {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await
|
.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
|
/// 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 state_processing::initialize_beacon_state_from_eth1;
|
||||||
use types::{BeaconState, ChainSpec, DepositData, EthSpec, Hash256, Keypair, PublicKey, Signature};
|
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).
|
/// Builds a genesis state as defined by the Eth2 interop procedure (see below).
|
||||||
///
|
///
|
||||||
/// Reference:
|
/// Reference:
|
||||||
@ -12,9 +14,10 @@ use types::{BeaconState, ChainSpec, DepositData, EthSpec, Hash256, Keypair, Publ
|
|||||||
pub fn interop_genesis_state<T: EthSpec>(
|
pub fn interop_genesis_state<T: EthSpec>(
|
||||||
keypairs: &[Keypair],
|
keypairs: &[Keypair],
|
||||||
genesis_time: u64,
|
genesis_time: u64,
|
||||||
|
eth1_block_hash: Hash256,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Result<BeaconState<T>, String> {
|
) -> 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 eth1_timestamp = 2_u64.pow(40);
|
||||||
let amount = spec.max_effective_balance;
|
let amount = spec.max_effective_balance;
|
||||||
|
|
||||||
@ -73,8 +76,13 @@ mod test {
|
|||||||
|
|
||||||
let keypairs = generate_deterministic_keypairs(validator_count);
|
let keypairs = generate_deterministic_keypairs(validator_count);
|
||||||
|
|
||||||
let state = interop_genesis_state::<TestEthSpec>(&keypairs, genesis_time, spec)
|
let state = interop_genesis_state::<TestEthSpec>(
|
||||||
.expect("should build state");
|
&keypairs,
|
||||||
|
genesis_time,
|
||||||
|
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||||
|
spec,
|
||||||
|
)
|
||||||
|
.expect("should build state");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
state.eth1_data().block_hash,
|
state.eth1_data().block_hash,
|
||||||
|
@ -4,5 +4,5 @@ mod interop;
|
|||||||
|
|
||||||
pub use eth1::Config as Eth1Config;
|
pub use eth1::Config as Eth1Config;
|
||||||
pub use eth1_genesis_service::{Eth1GenesisService, Statistics};
|
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;
|
pub use types::test_utils::generate_deterministic_keypairs;
|
||||||
|
@ -97,6 +97,7 @@ pub struct Config {
|
|||||||
pub allow_origin: Option<String>,
|
pub allow_origin: Option<String>,
|
||||||
pub serve_legacy_spec: bool,
|
pub serve_legacy_spec: bool,
|
||||||
pub tls_config: Option<TlsConfig>,
|
pub tls_config: Option<TlsConfig>,
|
||||||
|
pub allow_sync_stalled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
@ -108,6 +109,7 @@ impl Default for Config {
|
|||||||
allow_origin: None,
|
allow_origin: None,
|
||||||
serve_legacy_spec: true,
|
serve_legacy_spec: true,
|
||||||
tls_config: None,
|
tls_config: None,
|
||||||
|
allow_sync_stalled: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,6 +239,7 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
shutdown: impl Future<Output = ()> + Send + Sync + 'static,
|
shutdown: impl Future<Output = ()> + Send + Sync + 'static,
|
||||||
) -> Result<HttpServer, Error> {
|
) -> Result<HttpServer, Error> {
|
||||||
let config = ctx.config.clone();
|
let config = ctx.config.clone();
|
||||||
|
let allow_sync_stalled = config.allow_sync_stalled;
|
||||||
let log = ctx.log.clone();
|
let log = ctx.log.clone();
|
||||||
|
|
||||||
// Configure CORS.
|
// Configure CORS.
|
||||||
@ -338,44 +341,49 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Create a `warp` filter that rejects request whilst the node is syncing.
|
// Create a `warp` filter that rejects request whilst the node is syncing.
|
||||||
let not_while_syncing_filter = warp::any()
|
let not_while_syncing_filter =
|
||||||
.and(network_globals.clone())
|
warp::any()
|
||||||
.and(chain_filter.clone())
|
.and(network_globals.clone())
|
||||||
.and_then(
|
.and(chain_filter.clone())
|
||||||
|network_globals: Arc<NetworkGlobals<T::EthSpec>>, chain: Arc<BeaconChain<T>>| async move {
|
.and_then(
|
||||||
match *network_globals.sync_state.read() {
|
move |network_globals: Arc<NetworkGlobals<T::EthSpec>>,
|
||||||
SyncState::SyncingFinalized { .. } => {
|
chain: Arc<BeaconChain<T>>| async move {
|
||||||
let head_slot = chain.best_slot().map_err(warp_utils::reject::beacon_chain_error)?;
|
match *network_globals.sync_state.read() {
|
||||||
|
SyncState::SyncingFinalized { .. } => {
|
||||||
|
let head_slot = chain
|
||||||
|
.best_slot()
|
||||||
|
.map_err(warp_utils::reject::beacon_chain_error)?;
|
||||||
|
|
||||||
let current_slot = chain
|
let current_slot =
|
||||||
.slot_clock
|
chain.slot_clock.now_or_genesis().ok_or_else(|| {
|
||||||
.now_or_genesis()
|
warp_utils::reject::custom_server_error(
|
||||||
.ok_or_else(|| {
|
"unable to read slot clock".to_string(),
|
||||||
warp_utils::reject::custom_server_error(
|
)
|
||||||
"unable to read slot clock".to_string(),
|
})?;
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let tolerance = SYNC_TOLERANCE_EPOCHS * T::EthSpec::slots_per_epoch();
|
let tolerance = SYNC_TOLERANCE_EPOCHS * T::EthSpec::slots_per_epoch();
|
||||||
|
|
||||||
if head_slot + tolerance >= current_slot {
|
if head_slot + tolerance >= current_slot {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(warp_utils::reject::not_synced(format!(
|
Err(warp_utils::reject::not_synced(format!(
|
||||||
"head slot is {}, current slot is {}",
|
"head slot is {}, current slot is {}",
|
||||||
head_slot, current_slot
|
head_slot, current_slot
|
||||||
)))
|
)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
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(),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
SyncState::SyncingHead { .. } | SyncState::SyncTransition | SyncState::BackFillSyncing { .. } => Ok(()),
|
},
|
||||||
SyncState::Synced => Ok(()),
|
)
|
||||||
SyncState::Stalled => Err(warp_utils::reject::not_synced(
|
.untuple_one();
|
||||||
"sync is stalled".to_string(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.untuple_one();
|
|
||||||
|
|
||||||
// Create a `warp` filter that provides access to the logger.
|
// Create a `warp` filter that provides access to the logger.
|
||||||
let inner_ctx = ctx.clone();
|
let inner_ctx = ctx.clone();
|
||||||
|
@ -133,6 +133,7 @@ pub async fn create_api_server<T: BeaconChainTypes>(
|
|||||||
allow_origin: None,
|
allow_origin: None,
|
||||||
serve_legacy_spec: true,
|
serve_legacy_spec: true,
|
||||||
tls_config: None,
|
tls_config: None,
|
||||||
|
allow_sync_stalled: false,
|
||||||
},
|
},
|
||||||
chain: Some(chain.clone()),
|
chain: Some(chain.clone()),
|
||||||
network_tx: Some(network_tx),
|
network_tx: Some(network_tx),
|
||||||
|
@ -5,7 +5,7 @@ use beacon_chain::{
|
|||||||
BeaconChain,
|
BeaconChain,
|
||||||
};
|
};
|
||||||
use futures::prelude::*;
|
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 lazy_static::lazy_static;
|
||||||
use lighthouse_network::NetworkConfig;
|
use lighthouse_network::NetworkConfig;
|
||||||
use slog::Logger;
|
use slog::Logger;
|
||||||
@ -16,8 +16,8 @@ use std::time::{Duration, SystemTime};
|
|||||||
use store::config::StoreConfig;
|
use store::config::StoreConfig;
|
||||||
use store::{HotColdDB, MemoryStore};
|
use store::{HotColdDB, MemoryStore};
|
||||||
use types::{
|
use types::{
|
||||||
CommitteeIndex, Epoch, EthSpec, MainnetEthSpec, Slot, SubnetId, SyncCommitteeSubscription,
|
CommitteeIndex, Epoch, EthSpec, Hash256, MainnetEthSpec, Slot, SubnetId,
|
||||||
SyncSubnetId, ValidatorSubscription,
|
SyncCommitteeSubscription, SyncSubnetId, ValidatorSubscription,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SLOT_DURATION_MILLIS: u64 = 400;
|
const SLOT_DURATION_MILLIS: u64 = 400;
|
||||||
@ -52,8 +52,13 @@ impl TestBeaconChain {
|
|||||||
.custom_spec(spec.clone())
|
.custom_spec(spec.clone())
|
||||||
.store(Arc::new(store))
|
.store(Arc::new(store))
|
||||||
.genesis_state(
|
.genesis_state(
|
||||||
interop_genesis_state::<MainnetEthSpec>(&keypairs, 0, &spec)
|
interop_genesis_state::<MainnetEthSpec>(
|
||||||
.expect("should generate interop state"),
|
&keypairs,
|
||||||
|
0,
|
||||||
|
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||||
|
&spec,
|
||||||
|
)
|
||||||
|
.expect("should generate interop state"),
|
||||||
)
|
)
|
||||||
.expect("should build state using recent genesis")
|
.expect("should build state using recent genesis")
|
||||||
.dummy_eth1_backend()
|
.dummy_eth1_backend()
|
||||||
|
@ -240,6 +240,13 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
|||||||
over TLS. Must not be password-protected.")
|
over TLS. Must not be password-protected.")
|
||||||
.takes_value(true)
|
.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 */
|
/* Prometheus metrics HTTP server related arguments */
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("metrics")
|
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
|
* Prometheus metrics HTTP server
|
||||||
*/
|
*/
|
||||||
|
@ -3,6 +3,7 @@ use crate::test_utils::*;
|
|||||||
use crate::test_utils::{SeedableRng, XorShiftRng};
|
use crate::test_utils::{SeedableRng, XorShiftRng};
|
||||||
use beacon_chain::test_utils::{
|
use beacon_chain::test_utils::{
|
||||||
interop_genesis_state, test_spec, BeaconChainHarness, EphemeralHarnessType,
|
interop_genesis_state, test_spec, BeaconChainHarness, EphemeralHarnessType,
|
||||||
|
DEFAULT_ETH1_BLOCK_HASH,
|
||||||
};
|
};
|
||||||
use beacon_chain::types::{
|
use beacon_chain::types::{
|
||||||
test_utils::TestRandom, BeaconState, BeaconStateAltair, BeaconStateBase, BeaconStateError,
|
test_utils::TestRandom, BeaconState, BeaconStateAltair, BeaconStateBase, BeaconStateError,
|
||||||
@ -557,7 +558,13 @@ fn tree_hash_cache_linear_history_long_skip() {
|
|||||||
let spec = &test_spec::<MinimalEthSpec>();
|
let spec = &test_spec::<MinimalEthSpec>();
|
||||||
|
|
||||||
// This state has a cache that advances normally each slot.
|
// 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();
|
state.update_tree_hash_cache().unwrap();
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use clap_utils::parse_ssz_optional;
|
use clap_utils::parse_ssz_optional;
|
||||||
use eth2_network_config::Eth2NetworkConfig;
|
use eth2_network_config::Eth2NetworkConfig;
|
||||||
use genesis::interop_genesis_state;
|
use genesis::{interop_genesis_state, DEFAULT_ETH1_BLOCK_HASH};
|
||||||
use ssz::Encode;
|
use ssz::Encode;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
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> {
|
pub fn run<T: EthSpec>(testnet_dir: PathBuf, matches: &ArgMatches) -> Result<(), String> {
|
||||||
let validator_count = matches
|
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 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.genesis_state_bytes = Some(genesis_state.as_ssz_bytes());
|
||||||
eth2_network_config.force_write_to_file(testnet_dir)?;
|
eth2_network_config.force_write_to_file(testnet_dir)?;
|
||||||
|
@ -284,6 +284,14 @@ fn main() {
|
|||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Overwrites any previous testnet configurations"),
|
.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(
|
||||||
Arg::with_name("min-genesis-time")
|
Arg::with_name("min-genesis-time")
|
||||||
.long("min-genesis-time")
|
.long("min-genesis-time")
|
||||||
@ -402,6 +410,36 @@ fn main() {
|
|||||||
"The epoch at which to enable the Altair hard fork",
|
"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(
|
||||||
SubCommand::with_name("check-deposit-data")
|
SubCommand::with_name("check-deposit-data")
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use clap_utils::{parse_optional, parse_required, parse_ssz_optional};
|
use clap_utils::{parse_optional, parse_required, parse_ssz_optional};
|
||||||
use eth2_network_config::Eth2NetworkConfig;
|
use eth2_network_config::Eth2NetworkConfig;
|
||||||
|
use genesis::interop_genesis_state;
|
||||||
|
use ssz::Encode;
|
||||||
use std::path::PathBuf;
|
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> {
|
pub fn run<T: EthSpec>(testnet_dir_path: PathBuf, matches: &ArgMatches) -> Result<(), String> {
|
||||||
let deposit_contract_address: Address = parse_required(matches, "deposit-contract-address")?;
|
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);
|
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 {
|
let testnet = Eth2NetworkConfig {
|
||||||
deposit_contract_deploy_block,
|
deposit_contract_deploy_block,
|
||||||
boot_enr: Some(vec![]),
|
boot_enr: Some(vec![]),
|
||||||
genesis_state_bytes: None,
|
genesis_state_bytes,
|
||||||
config: Config::from_chain_spec::<T>(&spec),
|
config: Config::from_chain_spec::<T>(&spec),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user