mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-17 04:48:21 +00:00
Merge branch 'interop' into api-alignment
This commit is contained in:
@@ -8,8 +8,8 @@ use crate::persisted_beacon_chain::{PersistedBeaconChain, BEACON_CHAIN_DB_KEY};
|
||||
use lmd_ghost::LmdGhost;
|
||||
use operation_pool::DepositInsertStatus;
|
||||
use operation_pool::{OperationPool, PersistedOperationPool};
|
||||
use parking_lot::{RwLock, RwLockReadGuard};
|
||||
use slog::{error, info, warn, Logger};
|
||||
use parking_lot::RwLock;
|
||||
use slog::{error, info, trace, warn, Logger};
|
||||
use slot_clock::SlotClock;
|
||||
use ssz::Encode;
|
||||
use state_processing::per_block_processing::{
|
||||
@@ -37,6 +37,12 @@ use types::*;
|
||||
// |-------must be this long------|
|
||||
pub const GRAFFITI: &str = "sigp/lighthouse-0.0.0-prerelease";
|
||||
|
||||
/// If true, everytime a block is processed the pre-state, post-state and block are written to SSZ
|
||||
/// files in the temp directory.
|
||||
///
|
||||
/// Only useful for testing.
|
||||
const WRITE_BLOCK_PROCESSING_SSZ: bool = true;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum BlockProcessingOutcome {
|
||||
/// Block was valid and imported into the block graph.
|
||||
@@ -83,35 +89,6 @@ pub enum AttestationProcessingOutcome {
|
||||
Invalid(AttestationValidationError),
|
||||
}
|
||||
|
||||
/// Effectively a `Cow<BeaconState>`, however when it is `Borrowed` it holds a `RwLockReadGuard` (a
|
||||
/// read-lock on some read/write-locked state).
|
||||
///
|
||||
/// Only has a small subset of the functionality of a `std::borrow::Cow`.
|
||||
pub enum BeaconStateCow<'a, T: EthSpec> {
|
||||
Borrowed(RwLockReadGuard<'a, CheckPoint<T>>),
|
||||
Owned(BeaconState<T>),
|
||||
}
|
||||
|
||||
impl<'a, T: EthSpec> BeaconStateCow<'a, T> {
|
||||
pub fn maybe_as_mut_ref(&mut self) -> Option<&mut BeaconState<T>> {
|
||||
match self {
|
||||
BeaconStateCow::Borrowed(_) => None,
|
||||
BeaconStateCow::Owned(ref mut state) => Some(state),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: EthSpec> std::ops::Deref for BeaconStateCow<'a, T> {
|
||||
type Target = BeaconState<T>;
|
||||
|
||||
fn deref(&self) -> &BeaconState<T> {
|
||||
match self {
|
||||
BeaconStateCow::Borrowed(checkpoint) => &checkpoint.beacon_state,
|
||||
BeaconStateCow::Owned(state) => &state,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BeaconChainTypes: Send + Sync + 'static {
|
||||
type Store: store::Store;
|
||||
type SlotClock: slot_clock::SlotClock;
|
||||
@@ -332,13 +309,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
/// - As this iterator starts at the `head` of the chain (viz., the best block), the first slot
|
||||
/// returned may be earlier than the wall-clock slot.
|
||||
pub fn rev_iter_block_roots(&self) -> ReverseBlockRootIterator<T::EthSpec, T::Store> {
|
||||
let state = &self.head().beacon_state;
|
||||
let block_root = self.head().beacon_block_root;
|
||||
let block_slot = state.slot;
|
||||
let head = self.head();
|
||||
|
||||
let iter = BlockRootsIterator::owned(self.store.clone(), state.clone());
|
||||
let iter = BlockRootsIterator::owned(self.store.clone(), head.beacon_state);
|
||||
|
||||
ReverseBlockRootIterator::new((block_root, block_slot), iter)
|
||||
ReverseBlockRootIterator::new((head.beacon_block_root, head.beacon_block.slot), iter)
|
||||
}
|
||||
|
||||
/// Iterates across all `(state_root, slot)` pairs from the head of the chain (inclusive) to
|
||||
@@ -351,13 +326,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
/// - As this iterator starts at the `head` of the chain (viz., the best block), the first slot
|
||||
/// returned may be earlier than the wall-clock slot.
|
||||
pub fn rev_iter_state_roots(&self) -> ReverseStateRootIterator<T::EthSpec, T::Store> {
|
||||
let state = &self.head().beacon_state;
|
||||
let state_root = self.head().beacon_state_root;
|
||||
let state_slot = state.slot;
|
||||
let head = self.head();
|
||||
let slot = head.beacon_state.slot;
|
||||
|
||||
let iter = StateRootsIterator::owned(self.store.clone(), state.clone());
|
||||
let iter = StateRootsIterator::owned(self.store.clone(), head.beacon_state);
|
||||
|
||||
ReverseStateRootIterator::new((state_root, state_slot), iter)
|
||||
ReverseStateRootIterator::new((head.beacon_state_root, slot), iter)
|
||||
}
|
||||
|
||||
/// Returns the block at the given root, if any.
|
||||
@@ -372,32 +346,25 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
Ok(self.store.get(block_root)?)
|
||||
}
|
||||
|
||||
/// Returns a read-lock guarded `CheckPoint` struct for reading the head (as chosen by the
|
||||
/// fork-choice rule).
|
||||
/// Returns a `Checkpoint` representing the head block and state. Contains the "best block";
|
||||
/// the head of the canonical `BeaconChain`.
|
||||
///
|
||||
/// It is important to note that the `beacon_state` returned may not match the present slot. It
|
||||
/// is the state as it was when the head block was received, which could be some slots prior to
|
||||
/// now.
|
||||
pub fn head<'a>(&'a self) -> RwLockReadGuard<'a, CheckPoint<T::EthSpec>> {
|
||||
self.canonical_head.read()
|
||||
pub fn head(&self) -> CheckPoint<T::EthSpec> {
|
||||
self.canonical_head.read().clone()
|
||||
}
|
||||
|
||||
/// Returns the `BeaconState` at the given slot.
|
||||
///
|
||||
/// May return:
|
||||
///
|
||||
/// - A new state loaded from the database (for states prior to the head)
|
||||
/// - A reference to the head state (note: this keeps a read lock on the head, try to use
|
||||
/// sparingly).
|
||||
/// - The head state, but with skipped slots (for states later than the head).
|
||||
///
|
||||
/// Returns `None` when the state is not found in the database or there is an error skipping
|
||||
/// to a future state.
|
||||
pub fn state_at_slot(&self, slot: Slot) -> Result<BeaconStateCow<T::EthSpec>, Error> {
|
||||
let head_state = &self.head().beacon_state;
|
||||
pub fn state_at_slot(&self, slot: Slot) -> Result<BeaconState<T::EthSpec>, Error> {
|
||||
let head_state = self.head().beacon_state;
|
||||
|
||||
if slot == head_state.slot {
|
||||
Ok(BeaconStateCow::Borrowed(self.head()))
|
||||
Ok(head_state)
|
||||
} else if slot > head_state.slot {
|
||||
let head_state_slot = head_state.slot;
|
||||
let mut state = head_state.clone();
|
||||
@@ -417,7 +384,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
}
|
||||
};
|
||||
}
|
||||
Ok(BeaconStateCow::Owned(state))
|
||||
Ok(state)
|
||||
} else {
|
||||
let state_root = self
|
||||
.rev_iter_state_roots()
|
||||
@@ -425,11 +392,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
.map(|(root, _slot)| root)
|
||||
.ok_or_else(|| Error::NoStateForSlot(slot))?;
|
||||
|
||||
Ok(BeaconStateCow::Owned(
|
||||
self.store
|
||||
.get(&state_root)?
|
||||
.ok_or_else(|| Error::NoStateForSlot(slot))?,
|
||||
))
|
||||
Ok(self
|
||||
.store
|
||||
.get(&state_root)?
|
||||
.ok_or_else(|| Error::NoStateForSlot(slot))?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,7 +407,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
///
|
||||
/// Returns `None` when there is an error skipping to a future state or the slot clock cannot
|
||||
/// be read.
|
||||
pub fn state_now(&self) -> Result<BeaconStateCow<T::EthSpec>, Error> {
|
||||
pub fn wall_clock_state(&self) -> Result<BeaconState<T::EthSpec>, Error> {
|
||||
self.state_at_slot(self.slot()?)
|
||||
}
|
||||
|
||||
@@ -493,14 +459,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
let head_state = &self.head().beacon_state;
|
||||
|
||||
let mut state = if epoch(slot) == epoch(head_state.slot) {
|
||||
BeaconStateCow::Borrowed(self.head())
|
||||
self.head().beacon_state.clone()
|
||||
} else {
|
||||
self.state_at_slot(slot)?
|
||||
};
|
||||
|
||||
if let Some(state) = state.maybe_as_mut_ref() {
|
||||
state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
|
||||
}
|
||||
state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
|
||||
|
||||
if epoch(state.slot) != epoch(slot) {
|
||||
return Err(Error::InvariantViolated(format!(
|
||||
@@ -528,14 +492,12 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
let head_state = &self.head().beacon_state;
|
||||
|
||||
let mut state = if epoch == as_epoch(head_state.slot) {
|
||||
BeaconStateCow::Borrowed(self.head())
|
||||
self.head().beacon_state.clone()
|
||||
} else {
|
||||
self.state_at_slot(epoch.start_slot(T::EthSpec::slots_per_epoch()))?
|
||||
};
|
||||
|
||||
if let Some(state) = state.maybe_as_mut_ref() {
|
||||
state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
|
||||
}
|
||||
state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
|
||||
|
||||
if as_epoch(state.slot) != epoch {
|
||||
return Err(Error::InvariantViolated(format!(
|
||||
@@ -563,11 +525,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
slot: Slot,
|
||||
) -> Result<AttestationData, Error> {
|
||||
let state = self.state_at_slot(slot)?;
|
||||
let head = self.head();
|
||||
|
||||
let head_block_root = self.head().beacon_block_root;
|
||||
let head_block_slot = self.head().beacon_block.slot;
|
||||
|
||||
self.produce_attestation_data_for_block(shard, head_block_root, head_block_slot, &*state)
|
||||
self.produce_attestation_data_for_block(
|
||||
shard,
|
||||
head.beacon_block_root,
|
||||
head.beacon_block.slot,
|
||||
&state,
|
||||
)
|
||||
}
|
||||
|
||||
/// Produce an `AttestationData` that attests to the chain denoted by `block_root` and `state`.
|
||||
@@ -633,6 +598,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
metrics::inc_counter(&metrics::ATTESTATION_PRODUCTION_SUCCESSES);
|
||||
metrics::stop_timer(timer);
|
||||
|
||||
trace!(
|
||||
self.log,
|
||||
"Produced beacon attestation data";
|
||||
"beacon_block_root" => format!("{}", head_block_root),
|
||||
"shard" => shard,
|
||||
"slot" => state.slot
|
||||
);
|
||||
|
||||
Ok(AttestationData {
|
||||
beacon_block_root: head_block_root,
|
||||
source: state.current_justified_checkpoint.clone(),
|
||||
@@ -745,7 +718,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
// has a higher slot than the attestation.
|
||||
//
|
||||
// Permitting this would allow for attesters to vote on _future_ slots.
|
||||
if attestation_slot > state.slot {
|
||||
if state.slot > attestation_slot {
|
||||
Ok(AttestationProcessingOutcome::AttestsToFutureState {
|
||||
state: state.slot,
|
||||
attestation: attestation_slot,
|
||||
@@ -886,10 +859,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
|
||||
/// Accept some exit and queue it for inclusion in an appropriate block.
|
||||
pub fn process_voluntary_exit(&self, exit: VoluntaryExit) -> Result<(), ExitValidationError> {
|
||||
match self.state_now() {
|
||||
Ok(state) => self
|
||||
.op_pool
|
||||
.insert_voluntary_exit(exit, &*state, &self.spec),
|
||||
match self.wall_clock_state() {
|
||||
Ok(state) => self.op_pool.insert_voluntary_exit(exit, &state, &self.spec),
|
||||
Err(e) => {
|
||||
error!(
|
||||
&self.log,
|
||||
@@ -904,8 +875,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
|
||||
/// Accept some transfer and queue it for inclusion in an appropriate block.
|
||||
pub fn process_transfer(&self, transfer: Transfer) -> Result<(), TransferValidationError> {
|
||||
match self.state_now() {
|
||||
Ok(state) => self.op_pool.insert_transfer(transfer, &*state, &self.spec),
|
||||
match self.wall_clock_state() {
|
||||
Ok(state) => self.op_pool.insert_transfer(transfer, &state, &self.spec),
|
||||
Err(e) => {
|
||||
error!(
|
||||
&self.log,
|
||||
@@ -923,10 +894,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
&self,
|
||||
proposer_slashing: ProposerSlashing,
|
||||
) -> Result<(), ProposerSlashingValidationError> {
|
||||
match self.state_now() {
|
||||
match self.wall_clock_state() {
|
||||
Ok(state) => {
|
||||
self.op_pool
|
||||
.insert_proposer_slashing(proposer_slashing, &*state, &self.spec)
|
||||
.insert_proposer_slashing(proposer_slashing, &state, &self.spec)
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
@@ -945,10 +916,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
&self,
|
||||
attester_slashing: AttesterSlashing<T::EthSpec>,
|
||||
) -> Result<(), AttesterSlashingValidationError> {
|
||||
match self.state_now() {
|
||||
match self.wall_clock_state() {
|
||||
Ok(state) => {
|
||||
self.op_pool
|
||||
.insert_attester_slashing(attester_slashing, &*state, &self.spec)
|
||||
.insert_attester_slashing(attester_slashing, &state, &self.spec)
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
@@ -1264,6 +1235,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
metrics::inc_counter(&metrics::BLOCK_PRODUCTION_SUCCESSES);
|
||||
metrics::stop_timer(timer);
|
||||
|
||||
trace!(
|
||||
self.log,
|
||||
"Produced beacon block";
|
||||
"parent" => format!("{}", block.parent_root),
|
||||
"attestations" => block.body.attestations.len(),
|
||||
"slot" => block.slot
|
||||
);
|
||||
|
||||
Ok((block, state))
|
||||
}
|
||||
|
||||
@@ -1301,15 +1280,20 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
warn!(
|
||||
self.log,
|
||||
"Beacon chain re-org";
|
||||
"previous_head" => format!("{}", self.head().beacon_block_root),
|
||||
"previous_slot" => previous_slot,
|
||||
"new_head_parent" => format!("{}", beacon_block.parent_root),
|
||||
"new_head" => format!("{}", beacon_block_root),
|
||||
"new_slot" => new_slot
|
||||
);
|
||||
} else {
|
||||
info!(
|
||||
self.log,
|
||||
"new head block";
|
||||
"New head beacon block";
|
||||
"justified_root" => format!("{}", beacon_state.current_justified_checkpoint.root),
|
||||
"justified_epoch" => beacon_state.current_justified_checkpoint.epoch,
|
||||
"finalized_root" => format!("{}", beacon_state.finalized_checkpoint.root),
|
||||
"finalized_epoch" => beacon_state.finalized_checkpoint.epoch,
|
||||
"root" => format!("{}", beacon_block_root),
|
||||
"slot" => new_slot,
|
||||
);
|
||||
@@ -1359,10 +1343,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
|
||||
new_head.beacon_state.build_all_caches(&self.spec)?;
|
||||
|
||||
trace!(self.log, "Taking write lock on head");
|
||||
|
||||
// Update the checkpoint that stores the head of the chain at the time it received the
|
||||
// block.
|
||||
*self.canonical_head.write() = new_head;
|
||||
|
||||
trace!(self.log, "Dropping write lock on head");
|
||||
|
||||
// Save `self` to `self.store`.
|
||||
self.persist()?;
|
||||
|
||||
@@ -1463,41 +1451,45 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
}
|
||||
|
||||
fn write_state<T: EthSpec>(prefix: &str, state: &BeaconState<T>, log: &Logger) {
|
||||
let root = Hash256::from_slice(&state.tree_hash_root());
|
||||
let filename = format!("{}_slot_{}_root_{}.ssz", prefix, state.slot, root);
|
||||
let mut path = std::env::temp_dir().join("lighthouse");
|
||||
let _ = fs::create_dir_all(path.clone());
|
||||
path = path.join(filename);
|
||||
if WRITE_BLOCK_PROCESSING_SSZ {
|
||||
let root = Hash256::from_slice(&state.tree_hash_root());
|
||||
let filename = format!("{}_slot_{}_root_{}.ssz", prefix, state.slot, root);
|
||||
let mut path = std::env::temp_dir().join("lighthouse");
|
||||
let _ = fs::create_dir_all(path.clone());
|
||||
path = path.join(filename);
|
||||
|
||||
match fs::File::create(path.clone()) {
|
||||
Ok(mut file) => {
|
||||
let _ = file.write_all(&state.as_ssz_bytes());
|
||||
match fs::File::create(path.clone()) {
|
||||
Ok(mut file) => {
|
||||
let _ = file.write_all(&state.as_ssz_bytes());
|
||||
}
|
||||
Err(e) => error!(
|
||||
log,
|
||||
"Failed to log state";
|
||||
"path" => format!("{:?}", path),
|
||||
"error" => format!("{:?}", e)
|
||||
),
|
||||
}
|
||||
Err(e) => error!(
|
||||
log,
|
||||
"Failed to log state";
|
||||
"path" => format!("{:?}", path),
|
||||
"error" => format!("{:?}", e)
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_block<T: EthSpec>(block: &BeaconBlock<T>, root: Hash256, log: &Logger) {
|
||||
let filename = format!("block_slot_{}_root{}.ssz", block.slot, root);
|
||||
let mut path = std::env::temp_dir().join("lighthouse");
|
||||
let _ = fs::create_dir_all(path.clone());
|
||||
path = path.join(filename);
|
||||
if WRITE_BLOCK_PROCESSING_SSZ {
|
||||
let filename = format!("block_slot_{}_root{}.ssz", block.slot, root);
|
||||
let mut path = std::env::temp_dir().join("lighthouse");
|
||||
let _ = fs::create_dir_all(path.clone());
|
||||
path = path.join(filename);
|
||||
|
||||
match fs::File::create(path.clone()) {
|
||||
Ok(mut file) => {
|
||||
let _ = file.write_all(&block.as_ssz_bytes());
|
||||
match fs::File::create(path.clone()) {
|
||||
Ok(mut file) => {
|
||||
let _ = file.write_all(&block.as_ssz_bytes());
|
||||
}
|
||||
Err(e) => error!(
|
||||
log,
|
||||
"Failed to log block";
|
||||
"path" => format!("{:?}", path),
|
||||
"error" => format!("{:?}", e)
|
||||
),
|
||||
}
|
||||
Err(e) => error!(
|
||||
log,
|
||||
"Failed to log block";
|
||||
"path" => format!("{:?}", path),
|
||||
"error" => format!("{:?}", e)
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.32.0"
|
||||
hex = "0.3"
|
||||
#SigP repository
|
||||
libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "76f7475e4b7063e663ad03c7524cf091f9961968" }
|
||||
enr = { git = "https://github.com/SigP/rust-libp2p/", rev = "76f7475e4b7063e663ad03c7524cf091f9961968", features = ["serde"] }
|
||||
libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "8ac9c744197faaadc0e2b64fed7470ac4e2a41ca" }
|
||||
enr = { git = "https://github.com/SigP/rust-libp2p/", rev = "8ac9c744197faaadc0e2b64fed7470ac4e2a41ca", features = ["serde"] }
|
||||
types = { path = "../../eth2/types" }
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
|
||||
@@ -40,6 +40,12 @@ pub struct Config {
|
||||
/// Target number of connected peers.
|
||||
pub max_peers: usize,
|
||||
|
||||
/// A secp256k1 secret key, as bytes in ASCII-encoded hex.
|
||||
///
|
||||
/// With or without `0x` prefix.
|
||||
#[serde(skip)]
|
||||
pub secret_key_hex: Option<String>,
|
||||
|
||||
/// Gossipsub configuration parameters.
|
||||
#[serde(skip)]
|
||||
pub gs_config: GossipsubConfig,
|
||||
@@ -70,6 +76,7 @@ impl Default for Config {
|
||||
discovery_address: "127.0.0.1".parse().expect("valid ip address"),
|
||||
discovery_port: 9000,
|
||||
max_peers: 10,
|
||||
secret_key_hex: None,
|
||||
// Note: The topics by default are sent as plain strings. Hashes are an optional
|
||||
// parameter.
|
||||
gs_config: GossipsubConfigBuilder::new()
|
||||
@@ -158,6 +165,10 @@ impl Config {
|
||||
.map_err(|_| format!("Invalid discovery port: {}", disc_port_str))?;
|
||||
}
|
||||
|
||||
if let Some(p2p_priv_key) = args.value_of("p2p-priv-key") {
|
||||
self.secret_key_hex = Some(p2p_priv_key.to_string());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,16 +42,22 @@ impl Service {
|
||||
pub fn new(config: NetworkConfig, log: slog::Logger) -> error::Result<Self> {
|
||||
trace!(log, "Libp2p Service starting");
|
||||
|
||||
let local_keypair = if let Some(hex_bytes) = &config.secret_key_hex {
|
||||
keypair_from_hex(hex_bytes)?
|
||||
} else {
|
||||
load_private_key(&config, &log)
|
||||
};
|
||||
|
||||
// load the private key from CLI flag, disk or generate a new one
|
||||
let local_private_key = load_private_key(&config, &log);
|
||||
let local_peer_id = PeerId::from(local_private_key.public());
|
||||
// let local_private_key = load_private_key(&config, &log);
|
||||
let local_peer_id = PeerId::from(local_keypair.public());
|
||||
info!(log, "Libp2p Service"; "peer_id" => format!("{:?}", local_peer_id));
|
||||
|
||||
let mut swarm = {
|
||||
// Set up the transport - tcp/ws with secio and mplex/yamux
|
||||
let transport = build_transport(local_private_key.clone());
|
||||
let transport = build_transport(local_keypair.clone());
|
||||
// Lighthouse network behaviour
|
||||
let behaviour = Behaviour::new(&local_private_key, &config, &log)?;
|
||||
let behaviour = Behaviour::new(&local_keypair, &config, &log)?;
|
||||
Swarm::new(transport, behaviour, local_peer_id.clone())
|
||||
};
|
||||
|
||||
@@ -246,6 +252,27 @@ pub enum Libp2pEvent {
|
||||
},
|
||||
}
|
||||
|
||||
fn keypair_from_hex(hex_bytes: &str) -> error::Result<Keypair> {
|
||||
let hex_bytes = if hex_bytes.starts_with("0x") {
|
||||
hex_bytes[2..].to_string()
|
||||
} else {
|
||||
hex_bytes.to_string()
|
||||
};
|
||||
|
||||
hex::decode(&hex_bytes)
|
||||
.map_err(|e| format!("Failed to parse p2p secret key bytes: {:?}", e).into())
|
||||
.and_then(keypair_from_bytes)
|
||||
}
|
||||
|
||||
fn keypair_from_bytes(mut bytes: Vec<u8>) -> error::Result<Keypair> {
|
||||
libp2p::core::identity::secp256k1::SecretKey::from_bytes(&mut bytes)
|
||||
.map(|secret| {
|
||||
let keypair: libp2p::core::identity::secp256k1::Keypair = secret.into();
|
||||
Keypair::Secp256k1(keypair)
|
||||
})
|
||||
.map_err(|e| format!("Unable to parse p2p secret key: {:?}", e).into())
|
||||
}
|
||||
|
||||
/// Loads a private key from disk. If this fails, a new key is
|
||||
/// generated and is then saved to disk.
|
||||
///
|
||||
|
||||
@@ -25,8 +25,8 @@ impl<T: BeaconChainTypes> ValidatorService for ValidatorServiceInstance<T> {
|
||||
req: GetDutiesRequest,
|
||||
sink: UnarySink<GetDutiesResponse>,
|
||||
) {
|
||||
let validators = req.get_validators();
|
||||
trace!(self.log, "RPC request"; "endpoint" => "GetValidatorDuties", "epoch" => req.get_epoch());
|
||||
let validators = req.get_validators();
|
||||
|
||||
let epoch = Epoch::from(req.get_epoch());
|
||||
let slot = epoch.start_slot(T::EthSpec::slots_per_epoch());
|
||||
|
||||
@@ -13,7 +13,7 @@ pub const CLIENT_CONFIG_FILENAME: &str = "beacon-node.toml";
|
||||
pub const ETH2_CONFIG_FILENAME: &str = "eth2-spec.toml";
|
||||
|
||||
type Result<T> = std::result::Result<T, String>;
|
||||
type Config = (ClientConfig, Eth2Config);
|
||||
type Config = (ClientConfig, Eth2Config, Logger);
|
||||
|
||||
/// Gets the fully-initialized global client and eth2 configuration objects.
|
||||
///
|
||||
@@ -22,8 +22,10 @@ type Config = (ClientConfig, Eth2Config);
|
||||
/// 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(cli_args: &ArgMatches, log: &Logger) -> Result<Config> {
|
||||
let mut builder = ConfigBuilder::new(cli_args, log)?;
|
||||
pub fn get_configs(cli_args: &ArgMatches, core_log: Logger) -> Result<Config> {
|
||||
let log = core_log.clone();
|
||||
|
||||
let mut builder = ConfigBuilder::new(cli_args, core_log)?;
|
||||
|
||||
if let Some(server) = cli_args.value_of("eth1-server") {
|
||||
builder.set_eth1_backend_method(Eth1BackendMethod::Web3 {
|
||||
@@ -35,7 +37,7 @@ pub fn get_configs(cli_args: &ArgMatches, log: &Logger) -> Result<Config> {
|
||||
|
||||
match cli_args.subcommand() {
|
||||
("testnet", Some(sub_cmd_args)) => {
|
||||
process_testnet_subcommand(&mut builder, sub_cmd_args, log)?
|
||||
process_testnet_subcommand(&mut builder, sub_cmd_args, &log)?
|
||||
}
|
||||
// No sub-command assumes a resume operation.
|
||||
_ => {
|
||||
@@ -216,15 +218,15 @@ fn process_testnet_subcommand(
|
||||
}
|
||||
|
||||
/// Allows for building a set of configurations based upon `clap` arguments.
|
||||
struct ConfigBuilder<'a> {
|
||||
log: &'a Logger,
|
||||
struct ConfigBuilder {
|
||||
log: Logger,
|
||||
eth2_config: Eth2Config,
|
||||
client_config: ClientConfig,
|
||||
}
|
||||
|
||||
impl<'a> ConfigBuilder<'a> {
|
||||
impl ConfigBuilder {
|
||||
/// Create a new builder with default settings.
|
||||
pub fn new(cli_args: &'a ArgMatches, log: &'a Logger) -> Result<Self> {
|
||||
pub fn new(cli_args: &ArgMatches, log: Logger) -> Result<Self> {
|
||||
// Read the `--datadir` flag.
|
||||
//
|
||||
// If it's not present, try and find the home directory (`~`) and push the default data
|
||||
@@ -539,8 +541,7 @@ impl<'a> ConfigBuilder<'a> {
|
||||
/// cli_args).
|
||||
pub fn build(mut self, cli_args: &ArgMatches) -> Result<Config> {
|
||||
self.eth2_config.apply_cli_args(cli_args)?;
|
||||
self.client_config
|
||||
.apply_cli_args(cli_args, &mut self.log.clone())?;
|
||||
self.client_config.apply_cli_args(cli_args, &mut self.log)?;
|
||||
|
||||
if let Some(bump) = cli_args.value_of("port-bump") {
|
||||
let bump = bump
|
||||
@@ -561,7 +562,7 @@ impl<'a> ConfigBuilder<'a> {
|
||||
return Err("Specification constant mismatch".into());
|
||||
}
|
||||
|
||||
Ok((self.client_config, self.eth2_config))
|
||||
Ok((self.client_config, self.eth2_config, self.log))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,6 +116,13 @@ fn main() {
|
||||
.help("One or more comma-delimited multiaddrs to manually connect to a libp2p peer without an ENR.")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("p2p-priv-key")
|
||||
.long("p2p-priv-key")
|
||||
.value_name("HEX")
|
||||
.help("A secp256k1 secret key, represented as ASCII-encoded hex bytes (with or without 0x prefix).")
|
||||
.takes_value(true),
|
||||
)
|
||||
/*
|
||||
* gRPC parameters.
|
||||
*/
|
||||
@@ -355,13 +362,15 @@ fn main() {
|
||||
"Ethereum 2.0 is pre-release. This software is experimental."
|
||||
);
|
||||
|
||||
let log_clone = log.clone();
|
||||
|
||||
// Load the process-wide configuration.
|
||||
//
|
||||
// May load this from disk or create a new configuration, depending on the CLI flags supplied.
|
||||
let (client_config, eth2_config) = match get_configs(&matches, &log) {
|
||||
let (client_config, eth2_config, log) = match get_configs(&matches, log) {
|
||||
Ok(configs) => configs,
|
||||
Err(e) => {
|
||||
crit!(log, "Failed to load configuration"; "error" => e);
|
||||
crit!(log_clone, "Failed to load configuration. Exiting"; "error" => e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user