mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 12:47:05 +00:00
Merge branch 'unstable' into validator-manager
This commit is contained in:
@@ -11,7 +11,7 @@ clap = "2.33.3"
|
||||
hex = "0.4.2"
|
||||
dirs = "3.0.1"
|
||||
eth2_network_config = { path = "../eth2_network_config" }
|
||||
eth2_ssz = "0.4.1"
|
||||
ethereum_ssz = "0.5.0"
|
||||
ethereum-types = "0.14.1"
|
||||
serde = "1.0.116"
|
||||
serde_json = "1.0.59"
|
||||
|
||||
@@ -14,6 +14,6 @@ hex = "0.4.2"
|
||||
|
||||
[dependencies]
|
||||
types = { path = "../../consensus/types"}
|
||||
eth2_ssz = "0.4.1"
|
||||
tree_hash = "0.4.1"
|
||||
ethereum_ssz = "0.5.0"
|
||||
tree_hash = "0.5.0"
|
||||
ethabi = "16.0.0"
|
||||
|
||||
@@ -13,15 +13,15 @@ types = { path = "../../consensus/types" }
|
||||
reqwest = { version = "0.11.0", features = ["json","stream"] }
|
||||
lighthouse_network = { path = "../../beacon_node/lighthouse_network" }
|
||||
proto_array = { path = "../../consensus/proto_array", optional = true }
|
||||
eth2_serde_utils = "0.1.1"
|
||||
ethereum_serde_utils = "0.5.0"
|
||||
eth2_keystore = { path = "../../crypto/eth2_keystore" }
|
||||
libsecp256k1 = "0.7.0"
|
||||
ring = "0.16.19"
|
||||
bytes = "1.0.1"
|
||||
account_utils = { path = "../../common/account_utils" }
|
||||
sensitive_url = { path = "../../common/sensitive_url" }
|
||||
eth2_ssz = "0.4.1"
|
||||
eth2_ssz_derive = "0.3.1"
|
||||
ethereum_ssz = "0.5.0"
|
||||
ethereum_ssz_derive = "0.5.0"
|
||||
futures-util = "0.3.8"
|
||||
futures = "0.3.8"
|
||||
store = { path = "../../beacon_node/store", optional = true }
|
||||
|
||||
@@ -22,13 +22,14 @@ use lighthouse_network::PeerId;
|
||||
pub use reqwest;
|
||||
use reqwest::{IntoUrl, RequestBuilder, Response};
|
||||
pub use reqwest::{StatusCode, Url};
|
||||
pub use sensitive_url::SensitiveUrl;
|
||||
pub use sensitive_url::{SensitiveError, SensitiveUrl};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::iter::Iterator;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
use store::fork_versioned_response::ExecutionOptimisticFinalizedForkVersionedResponse;
|
||||
|
||||
pub const V1: EndpointVersion = EndpointVersion(1);
|
||||
pub const V2: EndpointVersion = EndpointVersion(2);
|
||||
@@ -338,7 +339,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_states_root(
|
||||
&self,
|
||||
state_id: StateId,
|
||||
) -> Result<Option<ExecutionOptimisticResponse<RootData>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<RootData>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -357,7 +358,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_states_fork(
|
||||
&self,
|
||||
state_id: StateId,
|
||||
) -> Result<Option<ExecutionOptimisticResponse<Fork>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<Fork>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -376,7 +377,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_states_finality_checkpoints(
|
||||
&self,
|
||||
state_id: StateId,
|
||||
) -> Result<Option<ExecutionOptimisticResponse<FinalityCheckpointsData>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<FinalityCheckpointsData>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -396,7 +397,8 @@ impl BeaconNodeHttpClient {
|
||||
&self,
|
||||
state_id: StateId,
|
||||
ids: Option<&[ValidatorId]>,
|
||||
) -> Result<Option<ExecutionOptimisticResponse<Vec<ValidatorBalanceData>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<Vec<ValidatorBalanceData>>>, Error>
|
||||
{
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -426,7 +428,7 @@ impl BeaconNodeHttpClient {
|
||||
state_id: StateId,
|
||||
ids: Option<&[ValidatorId]>,
|
||||
statuses: Option<&[ValidatorStatus]>,
|
||||
) -> Result<Option<ExecutionOptimisticResponse<Vec<ValidatorData>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<Vec<ValidatorData>>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -466,7 +468,7 @@ impl BeaconNodeHttpClient {
|
||||
slot: Option<Slot>,
|
||||
index: Option<u64>,
|
||||
epoch: Option<Epoch>,
|
||||
) -> Result<Option<ExecutionOptimisticResponse<Vec<CommitteeData>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<Vec<CommitteeData>>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -499,7 +501,7 @@ impl BeaconNodeHttpClient {
|
||||
&self,
|
||||
state_id: StateId,
|
||||
epoch: Option<Epoch>,
|
||||
) -> Result<ExecutionOptimisticResponse<SyncCommitteeByValidatorIndices>, Error> {
|
||||
) -> Result<ExecutionOptimisticFinalizedResponse<SyncCommitteeByValidatorIndices>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -522,7 +524,7 @@ impl BeaconNodeHttpClient {
|
||||
&self,
|
||||
state_id: StateId,
|
||||
epoch: Option<Epoch>,
|
||||
) -> Result<Option<ExecutionOptimisticResponse<RandaoMix>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<RandaoMix>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -547,7 +549,7 @@ impl BeaconNodeHttpClient {
|
||||
&self,
|
||||
state_id: StateId,
|
||||
validator_id: &ValidatorId,
|
||||
) -> Result<Option<ExecutionOptimisticResponse<ValidatorData>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<ValidatorData>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -568,7 +570,7 @@ impl BeaconNodeHttpClient {
|
||||
&self,
|
||||
slot: Option<Slot>,
|
||||
parent_root: Option<Hash256>,
|
||||
) -> Result<Option<ExecutionOptimisticResponse<Vec<BlockHeaderData>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<Vec<BlockHeaderData>>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -595,7 +597,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_headers_block_id(
|
||||
&self,
|
||||
block_id: BlockId,
|
||||
) -> Result<Option<ExecutionOptimisticResponse<BlockHeaderData>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<BlockHeaderData>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -675,7 +677,10 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_blocks<T: EthSpec>(
|
||||
&self,
|
||||
block_id: BlockId,
|
||||
) -> Result<Option<ExecutionOptimisticForkVersionedResponse<SignedBeaconBlock<T>>>, Error> {
|
||||
) -> Result<
|
||||
Option<ExecutionOptimisticFinalizedForkVersionedResponse<SignedBeaconBlock<T>>>,
|
||||
Error,
|
||||
> {
|
||||
let path = self.get_beacon_blocks_path(block_id)?;
|
||||
let response = match self.get_response(path, |b| b).await.optional()? {
|
||||
Some(res) => res,
|
||||
@@ -691,8 +696,10 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_blinded_blocks<T: EthSpec>(
|
||||
&self,
|
||||
block_id: BlockId,
|
||||
) -> Result<Option<ExecutionOptimisticForkVersionedResponse<SignedBlindedBeaconBlock<T>>>, Error>
|
||||
{
|
||||
) -> Result<
|
||||
Option<ExecutionOptimisticFinalizedForkVersionedResponse<SignedBlindedBeaconBlock<T>>>,
|
||||
Error,
|
||||
> {
|
||||
let path = self.get_beacon_blinded_blocks_path(block_id)?;
|
||||
let response = match self.get_response(path, |b| b).await.optional()? {
|
||||
Some(res) => res,
|
||||
@@ -760,7 +767,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_blocks_root(
|
||||
&self,
|
||||
block_id: BlockId,
|
||||
) -> Result<Option<ExecutionOptimisticResponse<RootData>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<RootData>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -779,7 +786,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_blocks_attestations<T: EthSpec>(
|
||||
&self,
|
||||
block_id: BlockId,
|
||||
) -> Result<Option<ExecutionOptimisticResponse<Vec<Attestation<T>>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<Vec<Attestation<T>>>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -1267,28 +1274,12 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_debug_beacon_states<T: EthSpec>(
|
||||
&self,
|
||||
state_id: StateId,
|
||||
) -> Result<Option<ExecutionOptimisticForkVersionedResponse<BeaconState<T>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedForkVersionedResponse<BeaconState<T>>>, Error>
|
||||
{
|
||||
let path = self.get_debug_beacon_states_path(state_id)?;
|
||||
self.get_opt(path).await
|
||||
}
|
||||
|
||||
/// `GET v1/debug/beacon/states/{state_id}` (LEGACY)
|
||||
pub async fn get_debug_beacon_states_v1<T: EthSpec>(
|
||||
&self,
|
||||
state_id: StateId,
|
||||
) -> Result<Option<ExecutionOptimisticForkVersionedResponse<BeaconState<T>>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("debug")
|
||||
.push("beacon")
|
||||
.push("states")
|
||||
.push(&state_id.to_string());
|
||||
|
||||
self.get_opt(path).await
|
||||
}
|
||||
|
||||
/// `GET debug/beacon/states/{state_id}`
|
||||
/// `-H "accept: application/octet-stream"`
|
||||
pub async fn get_debug_beacon_states_ssz<T: EthSpec>(
|
||||
@@ -1334,6 +1325,18 @@ impl BeaconNodeHttpClient {
|
||||
self.get(path).await
|
||||
}
|
||||
|
||||
/// `GET v1/debug/fork_choice`
|
||||
pub async fn get_debug_fork_choice(&self) -> Result<ForkChoice, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("debug")
|
||||
.push("fork_choice");
|
||||
|
||||
self.get(path).await
|
||||
}
|
||||
|
||||
/// `GET validator/duties/proposer/{epoch}`
|
||||
pub async fn get_validator_duties_proposer(
|
||||
&self,
|
||||
@@ -1649,7 +1652,7 @@ impl BeaconNodeHttpClient {
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
indices: &[u64],
|
||||
) -> Result<ExecutionOptimisticResponse<Vec<SyncDuty>>, Error> {
|
||||
) -> Result<ExecutionOptimisticFinalizedResponse<Vec<SyncDuty>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::{
|
||||
BeaconState, ChainSpec, DepositTreeSnapshot, Epoch, EthSpec, FinalizedExecutionBlock,
|
||||
GenericResponse, ValidatorId,
|
||||
},
|
||||
BeaconNodeHttpClient, DepositData, Error, Eth1Data, Hash256, StateId, StatusCode,
|
||||
BeaconNodeHttpClient, DepositData, Error, Eth1Data, Hash256, Slot, StateId, StatusCode,
|
||||
};
|
||||
use proto_array::core::ProtoArray;
|
||||
use reqwest::IntoUrl;
|
||||
@@ -566,4 +566,73 @@ impl BeaconNodeHttpClient {
|
||||
|
||||
self.post_with_response(path, &()).await
|
||||
}
|
||||
|
||||
///
|
||||
/// Analysis endpoints.
|
||||
///
|
||||
|
||||
/// `GET` lighthouse/analysis/block_rewards?start_slot,end_slot
|
||||
pub async fn get_lighthouse_analysis_block_rewards(
|
||||
&self,
|
||||
start_slot: Slot,
|
||||
end_slot: Slot,
|
||||
) -> Result<Vec<BlockReward>, Error> {
|
||||
let mut path = self.server.full.clone();
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("lighthouse")
|
||||
.push("analysis")
|
||||
.push("block_rewards");
|
||||
|
||||
path.query_pairs_mut()
|
||||
.append_pair("start_slot", &start_slot.to_string())
|
||||
.append_pair("end_slot", &end_slot.to_string());
|
||||
|
||||
self.get(path).await
|
||||
}
|
||||
|
||||
/// `GET` lighthouse/analysis/block_packing?start_epoch,end_epoch
|
||||
pub async fn get_lighthouse_analysis_block_packing(
|
||||
&self,
|
||||
start_epoch: Epoch,
|
||||
end_epoch: Epoch,
|
||||
) -> Result<Vec<BlockPackingEfficiency>, Error> {
|
||||
let mut path = self.server.full.clone();
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("lighthouse")
|
||||
.push("analysis")
|
||||
.push("block_packing_efficiency");
|
||||
|
||||
path.query_pairs_mut()
|
||||
.append_pair("start_epoch", &start_epoch.to_string())
|
||||
.append_pair("end_epoch", &end_epoch.to_string());
|
||||
|
||||
self.get(path).await
|
||||
}
|
||||
|
||||
/// `GET` lighthouse/analysis/attestation_performance/{index}?start_epoch,end_epoch
|
||||
pub async fn get_lighthouse_analysis_attestation_performance(
|
||||
&self,
|
||||
start_epoch: Epoch,
|
||||
end_epoch: Epoch,
|
||||
target: String,
|
||||
) -> Result<Vec<AttestationPerformance>, Error> {
|
||||
let mut path = self.server.full.clone();
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("lighthouse")
|
||||
.push("analysis")
|
||||
.push("attestation_performance")
|
||||
.push(&target);
|
||||
|
||||
path.query_pairs_mut()
|
||||
.append_pair("start_epoch", &start_epoch.to_string())
|
||||
.append_pair("end_epoch", &end_epoch.to_string());
|
||||
|
||||
self.get(path).await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,32 +6,32 @@ use serde::{Deserialize, Serialize};
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct IdealAttestationRewards {
|
||||
// Validator's effective balance in gwei
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub effective_balance: u64,
|
||||
// Ideal attester's reward for head vote in gwei
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub head: u64,
|
||||
// Ideal attester's reward for target vote in gwei
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub target: u64,
|
||||
// Ideal attester's reward for source vote in gwei
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub source: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||
pub struct TotalAttestationRewards {
|
||||
// one entry for every validator based on their attestations in the epoch
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub validator_index: u64,
|
||||
// attester's reward for head vote in gwei
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub head: u64,
|
||||
// attester's reward for target vote in gwei
|
||||
#[serde(with = "eth2_serde_utils::quoted_i64")]
|
||||
#[serde(with = "serde_utils::quoted_i64")]
|
||||
pub target: i64,
|
||||
// attester's reward for source vote in gwei
|
||||
#[serde(with = "eth2_serde_utils::quoted_i64")]
|
||||
#[serde(with = "serde_utils::quoted_i64")]
|
||||
pub source: i64,
|
||||
// TBD attester's inclusion_delay reward in gwei (phase0 only)
|
||||
// pub inclusion_delay: u64,
|
||||
|
||||
@@ -5,22 +5,22 @@ use serde::{Deserialize, Serialize};
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
pub struct StandardBlockReward {
|
||||
// proposer of the block, the proposer index who receives these rewards
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub proposer_index: u64,
|
||||
// total block reward in gwei,
|
||||
// equal to attestations + sync_aggregate + proposer_slashings + attester_slashings
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub total: u64,
|
||||
// block reward component due to included attestations in gwei
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub attestations: u64,
|
||||
// block reward component due to included sync_aggregate in gwei
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub sync_aggregate: u64,
|
||||
// block reward component due to included proposer_slashings in gwei
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub proposer_slashings: u64,
|
||||
// block reward component due to included attester_slashings in gwei
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub attester_slashings: u64,
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
pub struct SyncCommitteeReward {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub validator_index: u64,
|
||||
// sync committee reward in gwei for the validator
|
||||
#[serde(with = "eth2_serde_utils::quoted_i64")]
|
||||
#[serde(with = "serde_utils::quoted_i64")]
|
||||
pub reward: i64,
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ pub fn parse_pubkey(secret: &str) -> Result<Option<PublicKey>, Error> {
|
||||
&secret[SECRET_PREFIX.len()..]
|
||||
};
|
||||
|
||||
eth2_serde_utils::hex::decode(secret)
|
||||
serde_utils::hex::decode(secret)
|
||||
.map_err(|e| Error::InvalidSecret(format!("invalid hex: {:?}", e)))
|
||||
.and_then(|bytes| {
|
||||
if bytes.len() != PK_LEN {
|
||||
@@ -174,7 +174,7 @@ impl ValidatorClientHttpClient {
|
||||
let message =
|
||||
Message::parse_slice(digest(&SHA256, &body).as_ref()).expect("sha256 is 32 bytes");
|
||||
|
||||
eth2_serde_utils::hex::decode(&sig)
|
||||
serde_utils::hex::decode(&sig)
|
||||
.ok()
|
||||
.and_then(|bytes| {
|
||||
let sig = Signature::parse_der(&bytes).ok()?;
|
||||
@@ -657,6 +657,30 @@ impl ValidatorClientHttpClient {
|
||||
let url = self.make_gas_limit_url(pubkey)?;
|
||||
self.delete_with_raw_response(url, &()).await
|
||||
}
|
||||
|
||||
/// `POST /eth/v1/validator/{pubkey}/voluntary_exit`
|
||||
pub async fn post_validator_voluntary_exit(
|
||||
&self,
|
||||
pubkey: &PublicKeyBytes,
|
||||
epoch: Option<Epoch>,
|
||||
) -> Result<SignedVoluntaryExit, Error> {
|
||||
let mut path = self.server.full.clone();
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("eth")
|
||||
.push("v1")
|
||||
.push("validator")
|
||||
.push(&pubkey.to_string())
|
||||
.push("voluntary_exit");
|
||||
|
||||
if let Some(epoch) = epoch {
|
||||
path.query_pairs_mut()
|
||||
.append_pair("epoch", &epoch.to_string());
|
||||
}
|
||||
|
||||
self.post(path, &()).await
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `Ok(response)` if the response is a `200 OK` response or a
|
||||
|
||||
@@ -14,7 +14,7 @@ pub struct GetFeeRecipientResponse {
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub struct GetGasLimitResponse {
|
||||
pub pubkey: PublicKeyBytes,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub gas_limit: u64,
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ pub struct ImportKeystoresRequest {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct KeystoreJsonStr(#[serde(with = "eth2_serde_utils::json_str")] pub Keystore);
|
||||
pub struct KeystoreJsonStr(#[serde(with = "serde_utils::json_str")] pub Keystore);
|
||||
|
||||
impl std::ops::Deref for KeystoreJsonStr {
|
||||
type Target = Keystore;
|
||||
@@ -57,7 +57,7 @@ impl std::ops::Deref for KeystoreJsonStr {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct InterchangeJsonStr(#[serde(with = "eth2_serde_utils::json_str")] pub Interchange);
|
||||
pub struct InterchangeJsonStr(#[serde(with = "serde_utils::json_str")] pub Interchange);
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct ImportKeystoresResponse {
|
||||
@@ -104,7 +104,7 @@ pub struct DeleteKeystoresRequest {
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct DeleteKeystoresResponse {
|
||||
pub data: Vec<Status<DeleteKeystoreStatus>>,
|
||||
#[serde(with = "eth2_serde_utils::json_str")]
|
||||
#[serde(with = "serde_utils::json_str")]
|
||||
pub slashing_protection: Interchange,
|
||||
}
|
||||
|
||||
|
||||
@@ -32,14 +32,14 @@ pub struct ValidatorRequest {
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub builder_proposals: Option<bool>,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub deposit_gwei: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CreateValidatorsMnemonicRequest {
|
||||
pub mnemonic: ZeroizeString,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u32")]
|
||||
#[serde(with = "serde_utils::quoted_u32")]
|
||||
pub key_derivation_path_offset: u32,
|
||||
pub validators: Vec<ValidatorRequest>,
|
||||
}
|
||||
@@ -62,7 +62,7 @@ pub struct CreatedValidator {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub builder_proposals: Option<bool>,
|
||||
pub eth1_deposit_tx_data: String,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub deposit_gwei: u64,
|
||||
}
|
||||
|
||||
@@ -141,14 +141,19 @@ pub struct UpdateFeeRecipientRequest {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct UpdateGasLimitRequest {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub gas_limit: u64,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct VoluntaryExitQuery {
|
||||
pub epoch: Option<Epoch>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct ExportKeystoresResponse {
|
||||
pub data: Vec<SingleExportKeystoresResponse>,
|
||||
#[serde(with = "eth2_serde_utils::json_str")]
|
||||
#[serde(with = "serde_utils::json_str")]
|
||||
pub slashing_protection: Interchange,
|
||||
}
|
||||
|
||||
|
||||
@@ -82,10 +82,10 @@ impl std::fmt::Display for EndpointVersion {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct GenesisData {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub genesis_time: u64,
|
||||
pub genesis_validators_root: Hash256,
|
||||
#[serde(with = "eth2_serde_utils::bytes_4_hex")]
|
||||
#[serde(with = "serde_utils::bytes_4_hex")]
|
||||
pub genesis_fork_version: [u8; 4],
|
||||
}
|
||||
|
||||
@@ -200,6 +200,14 @@ pub struct ExecutionOptimisticResponse<T: Serialize + serde::de::DeserializeOwne
|
||||
pub data: T,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(bound = "T: Serialize + serde::de::DeserializeOwned")]
|
||||
pub struct ExecutionOptimisticFinalizedResponse<T: Serialize + serde::de::DeserializeOwned> {
|
||||
pub execution_optimistic: Option<bool>,
|
||||
pub finalized: Option<bool>,
|
||||
pub data: T,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(bound = "T: Serialize + serde::de::DeserializeOwned")]
|
||||
pub struct GenericResponse<T: Serialize + serde::de::DeserializeOwned> {
|
||||
@@ -222,6 +230,18 @@ impl<T: Serialize + serde::de::DeserializeOwned> GenericResponse<T> {
|
||||
data: self.data,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_execution_optimistic_finalized(
|
||||
self,
|
||||
execution_optimistic: bool,
|
||||
finalized: bool,
|
||||
) -> ExecutionOptimisticFinalizedResponse<T> {
|
||||
ExecutionOptimisticFinalizedResponse {
|
||||
execution_optimistic: Some(execution_optimistic),
|
||||
finalized: Some(finalized),
|
||||
data: self.data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize)]
|
||||
@@ -296,9 +316,9 @@ impl fmt::Display for ValidatorId {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ValidatorData {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub index: u64,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub balance: u64,
|
||||
pub status: ValidatorStatus,
|
||||
pub validator: Validator,
|
||||
@@ -306,9 +326,9 @@ pub struct ValidatorData {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ValidatorBalanceData {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub index: u64,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub balance: u64,
|
||||
}
|
||||
|
||||
@@ -471,16 +491,16 @@ pub struct ValidatorsQuery {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CommitteeData {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub index: u64,
|
||||
pub slot: Slot,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64_vec")]
|
||||
#[serde(with = "serde_utils::quoted_u64_vec")]
|
||||
pub validators: Vec<u64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct SyncCommitteeByValidatorIndices {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64_vec")]
|
||||
#[serde(with = "serde_utils::quoted_u64_vec")]
|
||||
pub validators: Vec<u64>,
|
||||
pub validator_aggregates: Vec<SyncSubcommittee>,
|
||||
}
|
||||
@@ -493,7 +513,7 @@ pub struct RandaoMix {
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct SyncSubcommittee {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64_vec")]
|
||||
#[serde(with = "serde_utils::quoted_u64_vec")]
|
||||
pub indices: Vec<u64>,
|
||||
}
|
||||
|
||||
@@ -518,7 +538,7 @@ pub struct BlockHeaderData {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct DepositContractData {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub chain_id: u64,
|
||||
pub address: Address,
|
||||
}
|
||||
@@ -542,7 +562,7 @@ pub struct IdentityData {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct MetaData {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub seq_number: u64,
|
||||
pub attnets: String,
|
||||
pub syncnets: String,
|
||||
@@ -629,27 +649,27 @@ pub struct ValidatorBalancesQuery {
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct ValidatorIndexData(#[serde(with = "eth2_serde_utils::quoted_u64_vec")] pub Vec<u64>);
|
||||
pub struct ValidatorIndexData(#[serde(with = "serde_utils::quoted_u64_vec")] pub Vec<u64>);
|
||||
|
||||
/// Borrowed variant of `ValidatorIndexData`, for serializing/sending.
|
||||
#[derive(Clone, Copy, Serialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct ValidatorIndexDataRef<'a>(
|
||||
#[serde(serialize_with = "eth2_serde_utils::quoted_u64_vec::serialize")] pub &'a [u64],
|
||||
#[serde(serialize_with = "serde_utils::quoted_u64_vec::serialize")] pub &'a [u64],
|
||||
);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct AttesterData {
|
||||
pub pubkey: PublicKeyBytes,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub validator_index: u64,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub committees_at_slot: u64,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub committee_index: CommitteeIndex,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub committee_length: u64,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub validator_committee_index: u64,
|
||||
pub slot: Slot,
|
||||
}
|
||||
@@ -657,7 +677,7 @@ pub struct AttesterData {
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ProposerData {
|
||||
pub pubkey: PublicKeyBytes,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub validator_index: u64,
|
||||
pub slot: Slot,
|
||||
}
|
||||
@@ -706,11 +726,11 @@ pub struct ValidatorAggregateAttestationQuery {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
|
||||
pub struct BeaconCommitteeSubscription {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub validator_index: u64,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub committee_index: u64,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub committees_at_slot: u64,
|
||||
pub slot: Slot,
|
||||
pub is_aggregator: bool,
|
||||
@@ -831,13 +851,13 @@ impl fmt::Display for PeerDirection {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PeerCount {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub connected: u64,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub connecting: u64,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub disconnected: u64,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub disconnecting: u64,
|
||||
}
|
||||
|
||||
@@ -872,7 +892,7 @@ pub struct SseHead {
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct SseChainReorg {
|
||||
pub slot: Slot,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub depth: u64,
|
||||
pub old_head_block: Hash256,
|
||||
pub old_head_state: Hash256,
|
||||
@@ -905,7 +925,7 @@ pub struct SseLateHead {
|
||||
#[serde(untagged)]
|
||||
pub struct SsePayloadAttributes {
|
||||
#[superstruct(getter(copy))]
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub timestamp: u64,
|
||||
#[superstruct(getter(copy))]
|
||||
pub prev_randao: Hash256,
|
||||
@@ -918,10 +938,10 @@ pub struct SsePayloadAttributes {
|
||||
#[derive(PartialEq, Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct SseExtendedPayloadAttributesGeneric<T> {
|
||||
pub proposal_slot: Slot,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub proposer_index: u64,
|
||||
pub parent_block_root: Hash256,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub parent_block_number: u64,
|
||||
pub parent_block_hash: ExecutionBlockHash,
|
||||
pub payload_attributes: T,
|
||||
@@ -1185,18 +1205,38 @@ fn parse_accept(accept: &str) -> Result<Vec<Mime>, String> {
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct LivenessRequestData {
|
||||
pub epoch: Epoch,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64_vec")]
|
||||
#[serde(with = "serde_utils::quoted_u64_vec")]
|
||||
pub indices: Vec<u64>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub struct LivenessResponseData {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub index: u64,
|
||||
pub epoch: Epoch,
|
||||
pub is_live: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ForkChoice {
|
||||
pub justified_checkpoint: Checkpoint,
|
||||
pub finalized_checkpoint: Checkpoint,
|
||||
pub fork_choice_nodes: Vec<ForkChoiceNode>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct ForkChoiceNode {
|
||||
pub slot: Slot,
|
||||
pub block_root: Hash256,
|
||||
pub parent_root: Option<Hash256>,
|
||||
pub justified_epoch: Epoch,
|
||||
pub finalized_epoch: Epoch,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
pub weight: u64,
|
||||
pub validity: Option<String>,
|
||||
pub execution_block_hash: Option<Hash256>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -9,7 +9,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
lazy_static = "1.4.0"
|
||||
num-bigint = "0.4.2"
|
||||
eth2_hashing = "0.3.0"
|
||||
ethereum_hashing = "1.0.0-beta.2"
|
||||
hex = "0.4.2"
|
||||
serde_yaml = "0.8.13"
|
||||
serde = "1.0.116"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
extern crate lazy_static;
|
||||
|
||||
use bls::{Keypair, PublicKey, SecretKey};
|
||||
use eth2_hashing::hash;
|
||||
use ethereum_hashing::hash;
|
||||
use num_bigint::BigUint;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::convert::TryInto;
|
||||
|
||||
@@ -16,6 +16,6 @@ tempfile = "3.1.0"
|
||||
[dependencies]
|
||||
serde_yaml = "0.8.13"
|
||||
types = { path = "../../consensus/types"}
|
||||
eth2_ssz = "0.4.1"
|
||||
ethereum_ssz = "0.5.0"
|
||||
eth2_config = { path = "../eth2_config"}
|
||||
discv5 = "0.2.2"
|
||||
|
||||
@@ -17,8 +17,8 @@ pub const VERSION: &str = git_version!(
|
||||
// NOTE: using --match instead of --exclude for compatibility with old Git
|
||||
"--match=thiswillnevermatchlol"
|
||||
],
|
||||
prefix = "Lighthouse/v4.0.1-rc.0-",
|
||||
fallback = "Lighthouse/v4.0.1-rc.0"
|
||||
prefix = "Lighthouse/v4.1.0-",
|
||||
fallback = "Lighthouse/v4.1.0"
|
||||
);
|
||||
|
||||
/// Returns `VERSION`, but with platform information appended to the end.
|
||||
|
||||
@@ -104,12 +104,23 @@ pub trait SlotClock: Send + Sync + Sized + Clone {
|
||||
self.slot_duration() * 2 / INTERVALS_PER_SLOT as u32
|
||||
}
|
||||
|
||||
/// Returns the `Duration` since the start of the current `Slot`. Useful in determining whether to apply proposer boosts.
|
||||
fn seconds_from_current_slot_start(&self, seconds_per_slot: u64) -> Option<Duration> {
|
||||
/// Returns the `Duration` since the start of the current `Slot` at seconds precision. Useful in determining whether to apply proposer boosts.
|
||||
fn seconds_from_current_slot_start(&self) -> Option<Duration> {
|
||||
self.now_duration()
|
||||
.and_then(|now| now.checked_sub(self.genesis_duration()))
|
||||
.map(|duration_into_slot| {
|
||||
Duration::from_secs(duration_into_slot.as_secs() % seconds_per_slot)
|
||||
Duration::from_secs(duration_into_slot.as_secs() % self.slot_duration().as_secs())
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the `Duration` since the start of the current `Slot` at milliseconds precision.
|
||||
fn millis_from_current_slot_start(&self) -> Option<Duration> {
|
||||
self.now_duration()
|
||||
.and_then(|now| now.checked_sub(self.genesis_duration()))
|
||||
.map(|duration_into_slot| {
|
||||
Duration::from_millis(
|
||||
(duration_into_slot.as_millis() % self.slot_duration().as_millis()) as u64,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -6,3 +6,6 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
lru_cache = { path = "../lru_cache" }
|
||||
lazy_static = "1.4.0"
|
||||
parking_lot = "0.12.0"
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
use std::net::{TcpListener, UdpSocket};
|
||||
use lazy_static::lazy_static;
|
||||
use lru_cache::LRUTimeCache;
|
||||
use parking_lot::Mutex;
|
||||
use std::net::{SocketAddr, TcpListener, UdpSocket};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Transport {
|
||||
@@ -12,6 +16,13 @@ pub enum IpVersion {
|
||||
Ipv6,
|
||||
}
|
||||
|
||||
pub const CACHED_PORTS_TTL: Duration = Duration::from_secs(300);
|
||||
|
||||
lazy_static! {
|
||||
static ref FOUND_PORTS_CACHE: Mutex<LRUTimeCache<u16>> =
|
||||
Mutex::new(LRUTimeCache::new(CACHED_PORTS_TTL));
|
||||
}
|
||||
|
||||
/// A convenience wrapper over [`zero_port`].
|
||||
pub fn unused_tcp4_port() -> Result<u16, String> {
|
||||
zero_port(Transport::Tcp, IpVersion::Ipv4)
|
||||
@@ -48,6 +59,20 @@ pub fn zero_port(transport: Transport, ipv: IpVersion) -> Result<u16, String> {
|
||||
IpVersion::Ipv6 => std::net::Ipv6Addr::LOCALHOST.into(),
|
||||
};
|
||||
let socket_addr = std::net::SocketAddr::new(localhost, 0);
|
||||
let mut unused_port: u16;
|
||||
loop {
|
||||
unused_port = find_unused_port(transport, socket_addr)?;
|
||||
let mut cache_lock = FOUND_PORTS_CACHE.lock();
|
||||
if !cache_lock.contains(&unused_port) {
|
||||
cache_lock.insert(unused_port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(unused_port)
|
||||
}
|
||||
|
||||
fn find_unused_port(transport: Transport, socket_addr: SocketAddr) -> Result<u16, String> {
|
||||
let local_addr = match transport {
|
||||
Transport::Tcp => {
|
||||
let listener = TcpListener::bind(socket_addr).map_err(|e| {
|
||||
|
||||
@@ -16,7 +16,7 @@ filesystem = { path = "../filesystem" }
|
||||
types = { path = "../../consensus/types" }
|
||||
rand = "0.8.5"
|
||||
deposit_contract = { path = "../deposit_contract" }
|
||||
tree_hash = "0.4.1"
|
||||
tree_hash = "0.5.0"
|
||||
hex = "0.4.2"
|
||||
derivative = "2.1.1"
|
||||
lockfile = { path = "../lockfile" }
|
||||
|
||||
Reference in New Issue
Block a user