mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-10 20:22:02 +00:00
* Renamed fork_choice::process_attestation_from_block * Processing attestation in fork choice * Retrieving state from store and checking signature * Looser check on beacon state validity. * Cleaned up get_attestation_state * Expanded fork choice api to provide latest validator message. * Checking if the an attestation contains a latest message * Correct process_attestation error handling. * Copy paste error in comment fixed. * Tidy ancestor iterators * Getting attestation slot via helper method * Refactored attestation creation in test utils * Revert "Refactored attestation creation in test utils" This reverts commit 4d277fe4239a7194758b18fb5c00dfe0b8231306. * Integration tests for free attestation processing * Implicit conflicts resolved. * formatting * Do first pass on Grants code * Add another attestation processing test * Tidy attestation processing * Remove old code fragment * Add non-compiling half finished changes * Simplify, fix bugs, add tests for chain iters * Remove attestation processing from op pool * Fix bug with fork choice, tidy * Fix overly restrictive check in fork choice. * Ensure committee cache is build during attn proc * Ignore unknown blocks at fork choice * Various minor fixes * Make fork choice write lock in to read lock * Remove unused method * Tidy comments * Fix attestation prod. target roots change * Fix compile error in store iters * Reject any attestation prior to finalization * Begin metrics refactor * Move beacon_chain to new metrics structure. * Make metrics not panic if already defined * Use global prometheus gather at rest api * Unify common metric fns into a crate * Add heavy metering to block processing * Remove hypen from prometheus metric name * Add more beacon chain metrics * Add beacon chain persistence metric * Prune op pool on finalization * Add extra prom beacon chain metrics * Prefix BeaconChain metrics with "beacon_" * Add more store metrics * Add basic metrics to libp2p * Add metrics to HTTP server * Remove old `http_server` crate * Update metrics names to be more like standard * Fix broken beacon chain metrics, add slot clock metrics * Add lighthouse_metrics gather fn * Remove http args * Fix wrong state given to op pool prune * Make prom metric names more consistent * Add more metrics, tidy existing metrics * Fix store block read metrics * Tidy attestation metrics * Fix minor PR comments * Fix minor PR comments * Remove duplicated attestation finalization check * Remove awkward `let` statement * Add first attempts at HTTP bootstrap * Add beacon_block methods to rest api * Fix serde for block.body.grafitti * Allow travis failures on beta (see desc) There's a non-backward compatible change in `cargo fmt`. Stable and beta do not agree. * Add network routes to API * Fix rustc warnings * Add best_slot method * Add --bootstrap arg to beacon node * Get bootstrapper working for ENR address * Store intermediate states during block processing * Allow bootstrapper to scrape libp2p address * Update bootstrapper libp2p address finding * Add comments * Tidy API to be more consistent with recent decisions * Address some review comments * Make BeaconChainTypes Send + Sync + 'static * Add `/network/listen_port` API endpoint * Abandon starting the node if libp2p doesn't start * Update bootstrapper for API changes * Remove unnecessary trait bounds
211 lines
6.4 KiB
Rust
211 lines
6.4 KiB
Rust
use eth2_libp2p::{
|
|
multiaddr::{Multiaddr, Protocol},
|
|
Enr,
|
|
};
|
|
use reqwest::{Error as HttpError, Url};
|
|
use serde::Deserialize;
|
|
use std::borrow::Cow;
|
|
use std::net::Ipv4Addr;
|
|
use types::{BeaconBlock, BeaconState, Checkpoint, EthSpec, Hash256, Slot};
|
|
use url::Host;
|
|
|
|
#[derive(Debug)]
|
|
enum Error {
|
|
InvalidUrl,
|
|
HttpError(HttpError),
|
|
}
|
|
|
|
impl From<HttpError> for Error {
|
|
fn from(e: HttpError) -> Error {
|
|
Error::HttpError(e)
|
|
}
|
|
}
|
|
|
|
/// Used to load "bootstrap" information from the HTTP API of another Lighthouse beacon node.
|
|
///
|
|
/// Bootstrapping information includes things like genesis and finalized states and blocks, and
|
|
/// libp2p connection details.
|
|
pub struct Bootstrapper {
|
|
url: Url,
|
|
}
|
|
|
|
impl Bootstrapper {
|
|
/// Parses the given `server` as a URL, instantiating `Self`.
|
|
pub fn from_server_string(server: String) -> Result<Self, String> {
|
|
Ok(Self {
|
|
url: Url::parse(&server).map_err(|e| format!("Invalid bootstrap server url: {}", e))?,
|
|
})
|
|
}
|
|
|
|
/// Build a multiaddr using the HTTP server URL that is not guaranteed to be correct.
|
|
///
|
|
/// The address is created by querying the HTTP server for its listening libp2p addresses.
|
|
/// Then, we find the first TCP port in those addresses and combine the port with the URL of
|
|
/// the server.
|
|
///
|
|
/// For example, the server `http://192.168.0.1` might end up with a `best_effort_multiaddr` of
|
|
/// `/ipv4/192.168.0.1/tcp/9000` if the server advertises a listening address of
|
|
/// `/ipv4/172.0.0.1/tcp/9000`.
|
|
pub fn best_effort_multiaddr(&self) -> Option<Multiaddr> {
|
|
let tcp_port = self.listen_port().ok()?;
|
|
|
|
let mut multiaddr = Multiaddr::with_capacity(2);
|
|
|
|
match self.url.host()? {
|
|
Host::Ipv4(addr) => multiaddr.push(Protocol::Ip4(addr)),
|
|
Host::Domain(s) => multiaddr.push(Protocol::Dns4(Cow::Borrowed(s))),
|
|
_ => return None,
|
|
};
|
|
|
|
multiaddr.push(Protocol::Tcp(tcp_port));
|
|
|
|
Some(multiaddr)
|
|
}
|
|
|
|
/// Returns the IPv4 address of the server URL, unless it contains a FQDN.
|
|
pub fn server_ipv4_addr(&self) -> Option<Ipv4Addr> {
|
|
match self.url.host()? {
|
|
Host::Ipv4(addr) => Some(addr),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
/// Returns the servers ENR address.
|
|
pub fn enr(&self) -> Result<Enr, String> {
|
|
get_enr(self.url.clone()).map_err(|e| format!("Unable to get ENR: {:?}", e))
|
|
}
|
|
|
|
/// Returns the servers listening libp2p addresses.
|
|
pub fn listen_port(&self) -> Result<u16, String> {
|
|
get_listen_port(self.url.clone()).map_err(|e| format!("Unable to get listen port: {:?}", e))
|
|
}
|
|
|
|
/// Returns the genesis block and state.
|
|
pub fn genesis<T: EthSpec>(&self) -> Result<(BeaconState<T>, BeaconBlock<T>), String> {
|
|
let genesis_slot = Slot::new(0);
|
|
|
|
let block = get_block(self.url.clone(), genesis_slot)
|
|
.map_err(|e| format!("Unable to get genesis block: {:?}", e))?
|
|
.beacon_block;
|
|
let state = get_state(self.url.clone(), genesis_slot)
|
|
.map_err(|e| format!("Unable to get genesis state: {:?}", e))?
|
|
.beacon_state;
|
|
|
|
Ok((state, block))
|
|
}
|
|
|
|
/// Returns the most recent finalized state and block.
|
|
pub fn finalized<T: EthSpec>(&self) -> Result<(BeaconState<T>, BeaconBlock<T>), String> {
|
|
let slots_per_epoch = get_slots_per_epoch(self.url.clone())
|
|
.map_err(|e| format!("Unable to get slots per epoch: {:?}", e))?;
|
|
let finalized_slot = get_finalized_slot(self.url.clone(), slots_per_epoch.as_u64())
|
|
.map_err(|e| format!("Unable to get finalized slot: {:?}", e))?;
|
|
|
|
let block = get_block(self.url.clone(), finalized_slot)
|
|
.map_err(|e| format!("Unable to get finalized block: {:?}", e))?
|
|
.beacon_block;
|
|
let state = get_state(self.url.clone(), finalized_slot)
|
|
.map_err(|e| format!("Unable to get finalized state: {:?}", e))?
|
|
.beacon_state;
|
|
|
|
Ok((state, block))
|
|
}
|
|
}
|
|
|
|
fn get_slots_per_epoch(mut url: Url) -> Result<Slot, Error> {
|
|
url.path_segments_mut()
|
|
.map(|mut url| {
|
|
url.push("spec").push("slots_per_epoch");
|
|
})
|
|
.map_err(|_| Error::InvalidUrl)?;
|
|
|
|
reqwest::get(url)?
|
|
.error_for_status()?
|
|
.json()
|
|
.map_err(Into::into)
|
|
}
|
|
|
|
fn get_finalized_slot(mut url: Url, slots_per_epoch: u64) -> Result<Slot, Error> {
|
|
url.path_segments_mut()
|
|
.map(|mut url| {
|
|
url.push("beacon").push("latest_finalized_checkpoint");
|
|
})
|
|
.map_err(|_| Error::InvalidUrl)?;
|
|
|
|
let checkpoint: Checkpoint = reqwest::get(url)?.error_for_status()?.json()?;
|
|
|
|
Ok(checkpoint.epoch.start_slot(slots_per_epoch))
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
#[serde(bound = "T: EthSpec")]
|
|
pub struct StateResponse<T: EthSpec> {
|
|
pub root: Hash256,
|
|
pub beacon_state: BeaconState<T>,
|
|
}
|
|
|
|
fn get_state<T: EthSpec>(mut url: Url, slot: Slot) -> Result<StateResponse<T>, Error> {
|
|
url.path_segments_mut()
|
|
.map(|mut url| {
|
|
url.push("beacon").push("state");
|
|
})
|
|
.map_err(|_| Error::InvalidUrl)?;
|
|
|
|
url.query_pairs_mut()
|
|
.append_pair("slot", &format!("{}", slot.as_u64()));
|
|
|
|
reqwest::get(url)?
|
|
.error_for_status()?
|
|
.json()
|
|
.map_err(Into::into)
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
#[serde(bound = "T: EthSpec")]
|
|
pub struct BlockResponse<T: EthSpec> {
|
|
pub root: Hash256,
|
|
pub beacon_block: BeaconBlock<T>,
|
|
}
|
|
|
|
fn get_block<T: EthSpec>(mut url: Url, slot: Slot) -> Result<BlockResponse<T>, Error> {
|
|
url.path_segments_mut()
|
|
.map(|mut url| {
|
|
url.push("beacon").push("block");
|
|
})
|
|
.map_err(|_| Error::InvalidUrl)?;
|
|
|
|
url.query_pairs_mut()
|
|
.append_pair("slot", &format!("{}", slot.as_u64()));
|
|
|
|
reqwest::get(url)?
|
|
.error_for_status()?
|
|
.json()
|
|
.map_err(Into::into)
|
|
}
|
|
|
|
fn get_enr(mut url: Url) -> Result<Enr, Error> {
|
|
url.path_segments_mut()
|
|
.map(|mut url| {
|
|
url.push("network").push("enr");
|
|
})
|
|
.map_err(|_| Error::InvalidUrl)?;
|
|
|
|
reqwest::get(url)?
|
|
.error_for_status()?
|
|
.json()
|
|
.map_err(Into::into)
|
|
}
|
|
|
|
fn get_listen_port(mut url: Url) -> Result<u16, Error> {
|
|
url.path_segments_mut()
|
|
.map(|mut url| {
|
|
url.push("network").push("listen_port");
|
|
})
|
|
.map_err(|_| Error::InvalidUrl)?;
|
|
|
|
reqwest::get(url)?
|
|
.error_for_status()?
|
|
.json()
|
|
.map_err(Into::into)
|
|
}
|