mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-24 07:14:46 +00:00
Merge remote-tracking branch 'origin/unstable' into tree-states
This commit is contained in:
@@ -21,10 +21,14 @@ use futures_util::StreamExt;
|
||||
use lighthouse_network::PeerId;
|
||||
use pretty_reqwest_error::PrettyReqwestError;
|
||||
pub use reqwest;
|
||||
use reqwest::{IntoUrl, RequestBuilder, Response};
|
||||
use reqwest::{
|
||||
header::{HeaderMap, HeaderValue},
|
||||
Body, IntoUrl, RequestBuilder, Response,
|
||||
};
|
||||
pub use reqwest::{StatusCode, Url};
|
||||
pub use sensitive_url::{SensitiveError, SensitiveUrl};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use ssz::Encode;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::iter::Iterator;
|
||||
@@ -322,6 +326,25 @@ impl BeaconNodeHttpClient {
|
||||
ok_or_error(response).await
|
||||
}
|
||||
|
||||
/// Generic POST function supporting arbitrary responses and timeouts.
|
||||
async fn post_generic_with_ssz_body<T: Into<Body>, U: IntoUrl>(
|
||||
&self,
|
||||
url: U,
|
||||
body: T,
|
||||
timeout: Option<Duration>,
|
||||
) -> Result<Response, Error> {
|
||||
let mut builder = self.client.post(url);
|
||||
if let Some(timeout) = timeout {
|
||||
builder = builder.timeout(timeout);
|
||||
}
|
||||
let response = builder
|
||||
.header("Content-Type", "application/octet-stream")
|
||||
.body(body)
|
||||
.send()
|
||||
.await?;
|
||||
ok_or_error(response).await
|
||||
}
|
||||
|
||||
/// Generic POST function supporting arbitrary responses and timeouts.
|
||||
async fn post_generic_with_consensus_version<T: Serialize, U: IntoUrl>(
|
||||
&self,
|
||||
@@ -342,6 +365,31 @@ impl BeaconNodeHttpClient {
|
||||
ok_or_error(response).await
|
||||
}
|
||||
|
||||
/// Generic POST function supporting arbitrary responses and timeouts.
|
||||
async fn post_generic_with_consensus_version_and_ssz_body<T: Into<Body>, U: IntoUrl>(
|
||||
&self,
|
||||
url: U,
|
||||
body: T,
|
||||
timeout: Option<Duration>,
|
||||
fork: ForkName,
|
||||
) -> Result<Response, Error> {
|
||||
let mut builder = self.client.post(url);
|
||||
if let Some(timeout) = timeout {
|
||||
builder = builder.timeout(timeout);
|
||||
}
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(
|
||||
CONSENSUS_VERSION_HEADER,
|
||||
HeaderValue::from_str(&fork.to_string()).expect("Failed to create header value"),
|
||||
);
|
||||
headers.insert(
|
||||
"Content-Type",
|
||||
HeaderValue::from_static("application/octet-stream"),
|
||||
);
|
||||
let response = builder.headers(headers).body(body).send().await?;
|
||||
ok_or_error(response).await
|
||||
}
|
||||
|
||||
/// `GET beacon/genesis`
|
||||
///
|
||||
/// ## Errors
|
||||
@@ -654,6 +702,26 @@ impl BeaconNodeHttpClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `POST beacon/blocks`
|
||||
///
|
||||
/// Returns `Ok(None)` on a 404 error.
|
||||
pub async fn post_beacon_blocks_ssz<T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
&self,
|
||||
block: &SignedBeaconBlock<T, Payload>,
|
||||
) -> Result<(), Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("beacon")
|
||||
.push("blocks");
|
||||
|
||||
self.post_generic_with_ssz_body(path, block.as_ssz_bytes(), Some(self.timeouts.proposal))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `POST beacon/blinded_blocks`
|
||||
///
|
||||
/// Returns `Ok(None)` on a 404 error.
|
||||
@@ -674,6 +742,26 @@ impl BeaconNodeHttpClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `POST beacon/blinded_blocks`
|
||||
///
|
||||
/// Returns `Ok(None)` on a 404 error.
|
||||
pub async fn post_beacon_blinded_blocks_ssz<T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
&self,
|
||||
block: &SignedBeaconBlock<T, Payload>,
|
||||
) -> Result<(), Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("beacon")
|
||||
.push("blinded_blocks");
|
||||
|
||||
self.post_generic_with_ssz_body(path, block.as_ssz_bytes(), Some(self.timeouts.proposal))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn post_beacon_blocks_v2_path(
|
||||
&self,
|
||||
validation_level: Option<BroadcastValidation>,
|
||||
@@ -727,6 +815,23 @@ impl BeaconNodeHttpClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `POST v2/beacon/blocks`
|
||||
pub async fn post_beacon_blocks_v2_ssz<T: EthSpec, Payload: AbstractExecPayload<T>>(
|
||||
&self,
|
||||
block: &SignedBeaconBlock<T, Payload>,
|
||||
validation_level: Option<BroadcastValidation>,
|
||||
) -> Result<(), Error> {
|
||||
self.post_generic_with_consensus_version_and_ssz_body(
|
||||
self.post_beacon_blocks_v2_path(validation_level)?,
|
||||
block.as_ssz_bytes(),
|
||||
Some(self.timeouts.proposal),
|
||||
block.message().body().fork_name(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `POST v2/beacon/blinded_blocks`
|
||||
pub async fn post_beacon_blinded_blocks_v2<T: EthSpec>(
|
||||
&self,
|
||||
@@ -744,6 +849,23 @@ impl BeaconNodeHttpClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `POST v2/beacon/blinded_blocks`
|
||||
pub async fn post_beacon_blinded_blocks_v2_ssz<T: EthSpec>(
|
||||
&self,
|
||||
block: &SignedBlindedBeaconBlock<T>,
|
||||
validation_level: Option<BroadcastValidation>,
|
||||
) -> Result<(), Error> {
|
||||
self.post_generic_with_consensus_version_and_ssz_body(
|
||||
self.post_beacon_blinded_blocks_v2_path(validation_level)?,
|
||||
block.as_ssz_bytes(),
|
||||
Some(self.timeouts.proposal),
|
||||
block.message().body().fork_name(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Path for `v2/beacon/blocks`
|
||||
pub fn get_beacon_blocks_path(&self, block_id: BlockId) -> Result<Url, Error> {
|
||||
let mut path = self.eth_path(V2)?;
|
||||
@@ -1139,6 +1261,23 @@ impl BeaconNodeHttpClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// GET builder/states/{state_id}/expected_withdrawals
|
||||
pub async fn get_expected_withdrawals(
|
||||
&self,
|
||||
state_id: &StateId,
|
||||
) -> Result<ExecutionOptimisticFinalizedResponse<Vec<Withdrawal>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("builder")
|
||||
.push("states")
|
||||
.push(&state_id.to_string())
|
||||
.push("expected_withdrawals");
|
||||
|
||||
self.get(path).await
|
||||
}
|
||||
|
||||
/// `POST validator/contribution_and_proofs`
|
||||
pub async fn post_validator_contribution_and_proofs<T: EthSpec>(
|
||||
&self,
|
||||
@@ -1636,6 +1775,24 @@ impl BeaconNodeHttpClient {
|
||||
.await
|
||||
}
|
||||
|
||||
/// `POST validator/liveness/{epoch}`
|
||||
pub async fn post_validator_liveness_epoch(
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
indices: Vec<u64>,
|
||||
) -> Result<GenericResponse<Vec<StandardLivenessResponseData>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("validator")
|
||||
.push("liveness")
|
||||
.push(&epoch.to_string());
|
||||
|
||||
self.post_with_timeout_and_response(path, &indices, self.timeouts.liveness)
|
||||
.await
|
||||
}
|
||||
|
||||
/// `POST validator/duties/attester/{epoch}`
|
||||
pub async fn post_validator_duties_attester(
|
||||
&self,
|
||||
|
||||
@@ -95,8 +95,8 @@ pub struct ValidatorInclusionData {
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use {
|
||||
procinfo::pid, psutil::cpu::os::linux::CpuTimesExt,
|
||||
psutil::memory::os::linux::VirtualMemoryExt, psutil::process::Process,
|
||||
psutil::cpu::os::linux::CpuTimesExt, psutil::memory::os::linux::VirtualMemoryExt,
|
||||
psutil::process::Process,
|
||||
};
|
||||
|
||||
/// Reports on the health of the Lighthouse instance.
|
||||
@@ -238,7 +238,7 @@ pub struct ProcessHealth {
|
||||
/// The pid of this process.
|
||||
pub pid: u32,
|
||||
/// The number of threads used by this pid.
|
||||
pub pid_num_threads: i32,
|
||||
pub pid_num_threads: i64,
|
||||
/// The total resident memory used by this pid.
|
||||
pub pid_mem_resident_set_size: u64,
|
||||
/// The total virtual memory used by this pid.
|
||||
@@ -262,7 +262,12 @@ impl ProcessHealth {
|
||||
.memory_info()
|
||||
.map_err(|e| format!("Unable to get process memory info: {:?}", e))?;
|
||||
|
||||
let stat = pid::stat_self().map_err(|e| format!("Unable to get stat: {:?}", e))?;
|
||||
let me = procfs::process::Process::myself()
|
||||
.map_err(|e| format!("Unable to get process: {:?}", e))?;
|
||||
let stat = me
|
||||
.stat()
|
||||
.map_err(|e| format!("Unable to get stat: {:?}", e))?;
|
||||
|
||||
let process_times = process
|
||||
.cpu_times()
|
||||
.map_err(|e| format!("Unable to get process cpu times : {:?}", e))?;
|
||||
|
||||
@@ -490,6 +490,21 @@ impl ValidatorClientHttpClient {
|
||||
.await
|
||||
}
|
||||
|
||||
/// `DELETE eth/v1/keystores`
|
||||
pub async fn delete_lighthouse_keystores(
|
||||
&self,
|
||||
req: &DeleteKeystoresRequest,
|
||||
) -> Result<ExportKeystoresResponse, Error> {
|
||||
let mut path = self.server.full.clone();
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("lighthouse")
|
||||
.push("keystores");
|
||||
|
||||
self.delete_with_unsigned_response(path, req).await
|
||||
}
|
||||
|
||||
fn make_keystores_url(&self) -> Result<Url, Error> {
|
||||
let mut url = self.server.full.clone();
|
||||
url.path_segments_mut()
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use account_utils::ZeroizeString;
|
||||
use eth2_keystore::Keystore;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use slashing_protection::interchange::Interchange;
|
||||
use types::{Address, PublicKeyBytes};
|
||||
|
||||
pub use slashing_protection::interchange::Interchange;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub struct GetFeeRecipientResponse {
|
||||
pub pubkey: PublicKeyBytes,
|
||||
@@ -27,7 +28,7 @@ pub struct ListKeystoresResponse {
|
||||
pub data: Vec<SingleKeystoreResponse>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
|
||||
pub struct SingleKeystoreResponse {
|
||||
pub validating_pubkey: PublicKeyBytes,
|
||||
pub derivation_path: Option<String>,
|
||||
|
||||
@@ -152,3 +152,19 @@ pub struct UpdateGasLimitRequest {
|
||||
pub struct VoluntaryExitQuery {
|
||||
pub epoch: Option<Epoch>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct ExportKeystoresResponse {
|
||||
pub data: Vec<SingleExportKeystoresResponse>,
|
||||
#[serde(with = "serde_utils::json_str")]
|
||||
pub slashing_protection: Interchange,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct SingleExportKeystoresResponse {
|
||||
pub status: Status<DeleteKeystoreStatus>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub validating_keystore: Option<KeystoreJsonStr>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub validating_keystore_password: Option<ZeroizeString>,
|
||||
}
|
||||
|
||||
@@ -581,6 +581,11 @@ pub struct SyncingData {
|
||||
pub sync_distance: Slot,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ExpectedWithdrawalsQuery {
|
||||
pub proposal_slot: Option<Slot>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Deserialize)]
|
||||
#[serde(try_from = "String", bound = "T: FromStr")]
|
||||
pub struct QueryVec<T: FromStr> {
|
||||
@@ -1226,6 +1231,13 @@ impl FromStr for Accept {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct StandardLivenessResponseData {
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub index: u64,
|
||||
pub is_live: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct LivenessRequestData {
|
||||
pub epoch: Epoch,
|
||||
@@ -1305,6 +1317,26 @@ pub struct BroadcastValidationQuery {
|
||||
pub broadcast_validation: BroadcastValidation,
|
||||
}
|
||||
|
||||
pub mod serde_status_code {
|
||||
use crate::StatusCode;
|
||||
use serde::{de::Error, Deserialize, Serialize};
|
||||
|
||||
pub fn serialize<S>(status_code: &StatusCode, ser: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
status_code.as_u16().serialize(ser)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(de: D) -> Result<StatusCode, D::Error>
|
||||
where
|
||||
D: serde::de::Deserializer<'de>,
|
||||
{
|
||||
let status_code = u16::deserialize(de)?;
|
||||
StatusCode::try_from(status_code).map_err(D::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user