mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-08 01:05:47 +00:00
Merge remote-tracking branch 'origin/unstable' into tree-states
This commit is contained in:
@@ -23,7 +23,7 @@ use lighthouse_network::PeerId;
|
||||
pub use reqwest;
|
||||
use reqwest::{IntoUrl, RequestBuilder, Response};
|
||||
pub use reqwest::{StatusCode, Url};
|
||||
use sensitive_url::SensitiveUrl;
|
||||
pub use sensitive_url::SensitiveUrl;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
@@ -110,7 +110,10 @@ pub struct Timeouts {
|
||||
pub liveness: Duration,
|
||||
pub proposal: Duration,
|
||||
pub proposer_duties: Duration,
|
||||
pub sync_committee_contribution: Duration,
|
||||
pub sync_duties: Duration,
|
||||
pub get_beacon_blocks_ssz: Duration,
|
||||
pub get_debug_beacon_states: Duration,
|
||||
}
|
||||
|
||||
impl Timeouts {
|
||||
@@ -121,7 +124,10 @@ impl Timeouts {
|
||||
liveness: timeout,
|
||||
proposal: timeout,
|
||||
proposer_duties: timeout,
|
||||
sync_committee_contribution: timeout,
|
||||
sync_duties: timeout,
|
||||
get_beacon_blocks_ssz: timeout,
|
||||
get_debug_beacon_states: timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,9 +243,10 @@ impl BeaconNodeHttpClient {
|
||||
&self,
|
||||
url: U,
|
||||
accept_header: Accept,
|
||||
timeout: Duration,
|
||||
) -> Result<Option<Vec<u8>>, Error> {
|
||||
let opt_response = self
|
||||
.get_response(url, |b| b.accept(accept_header))
|
||||
.get_response(url, |b| b.accept(accept_header).timeout(timeout))
|
||||
.await
|
||||
.optional()?;
|
||||
match opt_response {
|
||||
@@ -330,7 +337,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_states_root(
|
||||
&self,
|
||||
state_id: StateId,
|
||||
) -> Result<Option<GenericResponse<RootData>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticResponse<RootData>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -349,7 +356,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_states_fork(
|
||||
&self,
|
||||
state_id: StateId,
|
||||
) -> Result<Option<GenericResponse<Fork>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticResponse<Fork>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -368,7 +375,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_states_finality_checkpoints(
|
||||
&self,
|
||||
state_id: StateId,
|
||||
) -> Result<Option<GenericResponse<FinalityCheckpointsData>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticResponse<FinalityCheckpointsData>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -388,7 +395,7 @@ impl BeaconNodeHttpClient {
|
||||
&self,
|
||||
state_id: StateId,
|
||||
ids: Option<&[ValidatorId]>,
|
||||
) -> Result<Option<GenericResponse<Vec<ValidatorBalanceData>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticResponse<Vec<ValidatorBalanceData>>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -418,7 +425,7 @@ impl BeaconNodeHttpClient {
|
||||
state_id: StateId,
|
||||
ids: Option<&[ValidatorId]>,
|
||||
statuses: Option<&[ValidatorStatus]>,
|
||||
) -> Result<Option<GenericResponse<Vec<ValidatorData>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticResponse<Vec<ValidatorData>>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -458,7 +465,7 @@ impl BeaconNodeHttpClient {
|
||||
slot: Option<Slot>,
|
||||
index: Option<u64>,
|
||||
epoch: Option<Epoch>,
|
||||
) -> Result<Option<GenericResponse<Vec<CommitteeData>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticResponse<Vec<CommitteeData>>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -491,7 +498,7 @@ impl BeaconNodeHttpClient {
|
||||
&self,
|
||||
state_id: StateId,
|
||||
epoch: Option<Epoch>,
|
||||
) -> Result<GenericResponse<SyncCommitteeByValidatorIndices>, Error> {
|
||||
) -> Result<ExecutionOptimisticResponse<SyncCommitteeByValidatorIndices>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -516,7 +523,7 @@ impl BeaconNodeHttpClient {
|
||||
&self,
|
||||
state_id: StateId,
|
||||
validator_id: &ValidatorId,
|
||||
) -> Result<Option<GenericResponse<ValidatorData>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticResponse<ValidatorData>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -537,7 +544,7 @@ impl BeaconNodeHttpClient {
|
||||
&self,
|
||||
slot: Option<Slot>,
|
||||
parent_root: Option<Hash256>,
|
||||
) -> Result<Option<GenericResponse<Vec<BlockHeaderData>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticResponse<Vec<BlockHeaderData>>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -564,7 +571,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_headers_block_id(
|
||||
&self,
|
||||
block_id: BlockId,
|
||||
) -> Result<Option<GenericResponse<BlockHeaderData>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticResponse<BlockHeaderData>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -633,7 +640,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_blocks<T: EthSpec>(
|
||||
&self,
|
||||
block_id: BlockId,
|
||||
) -> Result<Option<ForkVersionedResponse<SignedBeaconBlock<T>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticForkVersionedResponse<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,
|
||||
@@ -642,20 +649,31 @@ impl BeaconNodeHttpClient {
|
||||
|
||||
// If present, use the fork provided in the headers to decode the block. Gracefully handle
|
||||
// missing and malformed fork names by falling back to regular deserialisation.
|
||||
let (block, version) = match response.fork_name_from_header() {
|
||||
let (block, version, execution_optimistic) = match response.fork_name_from_header() {
|
||||
Ok(Some(fork_name)) => {
|
||||
map_fork_name_with!(fork_name, SignedBeaconBlock, {
|
||||
let ForkVersionedResponse { version, data } = response.json().await?;
|
||||
(data, version)
|
||||
})
|
||||
let (data, (version, execution_optimistic)) =
|
||||
map_fork_name_with!(fork_name, SignedBeaconBlock, {
|
||||
let ExecutionOptimisticForkVersionedResponse {
|
||||
version,
|
||||
execution_optimistic,
|
||||
data,
|
||||
} = response.json().await?;
|
||||
(data, (version, execution_optimistic))
|
||||
});
|
||||
(data, version, execution_optimistic)
|
||||
}
|
||||
Ok(None) | Err(_) => {
|
||||
let ForkVersionedResponse { version, data } = response.json().await?;
|
||||
(data, version)
|
||||
let ExecutionOptimisticForkVersionedResponse {
|
||||
version,
|
||||
execution_optimistic,
|
||||
data,
|
||||
} = response.json().await?;
|
||||
(data, version, execution_optimistic)
|
||||
}
|
||||
};
|
||||
Ok(Some(ForkVersionedResponse {
|
||||
Ok(Some(ExecutionOptimisticForkVersionedResponse {
|
||||
version,
|
||||
execution_optimistic,
|
||||
data: block,
|
||||
}))
|
||||
}
|
||||
@@ -688,7 +706,7 @@ impl BeaconNodeHttpClient {
|
||||
) -> Result<Option<SignedBeaconBlock<T>>, Error> {
|
||||
let path = self.get_beacon_blocks_path(block_id)?;
|
||||
|
||||
self.get_bytes_opt_accept_header(path, Accept::Ssz)
|
||||
self.get_bytes_opt_accept_header(path, Accept::Ssz, self.timeouts.get_beacon_blocks_ssz)
|
||||
.await?
|
||||
.map(|bytes| SignedBeaconBlock::from_ssz_bytes(&bytes, spec).map_err(Error::InvalidSsz))
|
||||
.transpose()
|
||||
@@ -700,7 +718,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_blocks_root(
|
||||
&self,
|
||||
block_id: BlockId,
|
||||
) -> Result<Option<GenericResponse<RootData>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticResponse<RootData>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -719,7 +737,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_beacon_blocks_attestations<T: EthSpec>(
|
||||
&self,
|
||||
block_id: BlockId,
|
||||
) -> Result<Option<GenericResponse<Vec<Attestation<T>>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticResponse<Vec<Attestation<T>>>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -907,7 +925,12 @@ impl BeaconNodeHttpClient {
|
||||
.push("validator")
|
||||
.push("contribution_and_proofs");
|
||||
|
||||
self.post(path, &signed_contributions).await?;
|
||||
self.post_with_timeout(
|
||||
path,
|
||||
&signed_contributions,
|
||||
self.timeouts.sync_committee_contribution,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -929,6 +952,23 @@ impl BeaconNodeHttpClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `POST validator/register_validator`
|
||||
pub async fn post_validator_register_validator(
|
||||
&self,
|
||||
registration_data: &[SignedValidatorRegistrationData],
|
||||
) -> Result<(), Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("validator")
|
||||
.push("register_validator");
|
||||
|
||||
self.post(path, ®istration_data).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `GET config/fork_schedule`
|
||||
pub async fn get_config_fork_schedule(&self) -> Result<GenericResponse<Vec<Fork>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
@@ -942,7 +982,9 @@ impl BeaconNodeHttpClient {
|
||||
}
|
||||
|
||||
/// `GET config/spec`
|
||||
pub async fn get_config_spec(&self) -> Result<GenericResponse<ConfigAndPreset>, Error> {
|
||||
pub async fn get_config_spec<T: Serialize + DeserializeOwned>(
|
||||
&self,
|
||||
) -> Result<GenericResponse<T>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -1099,7 +1141,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_debug_beacon_states<T: EthSpec>(
|
||||
&self,
|
||||
state_id: StateId,
|
||||
) -> Result<Option<ForkVersionedResponse<BeaconState<T>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticForkVersionedResponse<BeaconState<T>>>, Error> {
|
||||
let path = self.get_debug_beacon_states_path(state_id)?;
|
||||
self.get_opt(path).await
|
||||
}
|
||||
@@ -1108,7 +1150,7 @@ impl BeaconNodeHttpClient {
|
||||
pub async fn get_debug_beacon_states_v1<T: EthSpec>(
|
||||
&self,
|
||||
state_id: StateId,
|
||||
) -> Result<Option<ForkVersionedResponse<BeaconState<T>>>, Error> {
|
||||
) -> Result<Option<ExecutionOptimisticForkVersionedResponse<BeaconState<T>>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -1130,15 +1172,30 @@ impl BeaconNodeHttpClient {
|
||||
) -> Result<Option<BeaconState<T>>, Error> {
|
||||
let path = self.get_debug_beacon_states_path(state_id)?;
|
||||
|
||||
self.get_bytes_opt_accept_header(path, Accept::Ssz)
|
||||
self.get_bytes_opt_accept_header(path, Accept::Ssz, self.timeouts.get_debug_beacon_states)
|
||||
.await?
|
||||
.map(|bytes| BeaconState::from_ssz_bytes(&bytes, spec).map_err(Error::InvalidSsz))
|
||||
.transpose()
|
||||
}
|
||||
|
||||
/// `GET debug/beacon/heads`
|
||||
/// `GET v2/debug/beacon/heads`
|
||||
pub async fn get_debug_beacon_heads(
|
||||
&self,
|
||||
) -> Result<GenericResponse<Vec<ChainHeadData>>, Error> {
|
||||
let mut path = self.eth_path(V2)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("debug")
|
||||
.push("beacon")
|
||||
.push("heads");
|
||||
|
||||
self.get(path).await
|
||||
}
|
||||
|
||||
/// `GET v1/debug/beacon/heads` (LEGACY)
|
||||
pub async fn get_debug_beacon_heads_v1(
|
||||
&self,
|
||||
) -> Result<GenericResponse<Vec<ChainHeadData>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
@@ -1230,7 +1287,7 @@ impl BeaconNodeHttpClient {
|
||||
.await
|
||||
}
|
||||
|
||||
/// `GET v2/validator/blocks/{slot}`
|
||||
/// `GET v1/validator/blinded_blocks/{slot}`
|
||||
pub async fn get_validator_blinded_blocks_with_verify_randao<
|
||||
T: EthSpec,
|
||||
Payload: ExecPayload<T>,
|
||||
@@ -1241,7 +1298,7 @@ impl BeaconNodeHttpClient {
|
||||
graffiti: Option<&Graffiti>,
|
||||
verify_randao: Option<bool>,
|
||||
) -> Result<ForkVersionedResponse<BeaconBlock<T, Payload>>, Error> {
|
||||
let mut path = self.eth_path(V2)?;
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
@@ -1470,7 +1527,7 @@ impl BeaconNodeHttpClient {
|
||||
&self,
|
||||
epoch: Epoch,
|
||||
indices: &[u64],
|
||||
) -> Result<GenericResponse<Vec<SyncDuty>>, Error> {
|
||||
) -> Result<ExecutionOptimisticResponse<Vec<SyncDuty>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -1491,7 +1548,7 @@ impl BeaconNodeHttpClient {
|
||||
|
||||
/// Returns `Ok(response)` if the response is a `200 OK` response. Otherwise, creates an
|
||||
/// appropriate error message.
|
||||
async fn ok_or_error(response: Response) -> Result<Response, Error> {
|
||||
pub async fn ok_or_error(response: Response) -> Result<Response, Error> {
|
||||
let status = response.status();
|
||||
|
||||
if status == StatusCode::OK {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use types::{Hash256, Slot};
|
||||
use types::{AttestationData, Hash256, Slot};
|
||||
|
||||
/// Details about the rewards paid to a block proposer for proposing a block.
|
||||
///
|
||||
@@ -42,6 +42,9 @@ pub struct AttestationRewards {
|
||||
///
|
||||
/// Each element of the vec is a map from validator index to reward.
|
||||
pub per_attestation_rewards: Vec<HashMap<u64, u64>>,
|
||||
/// The attestations themselves (optional).
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub attestations: Vec<AttestationData>,
|
||||
}
|
||||
|
||||
/// Query parameters for the `/lighthouse/block_rewards` endpoint.
|
||||
@@ -51,4 +54,7 @@ pub struct BlockRewardsQuery {
|
||||
pub start_slot: Slot,
|
||||
/// Upper slot limit for block rewards returned (inclusive).
|
||||
pub end_slot: Slot,
|
||||
/// Include the full attestations themselves?
|
||||
#[serde(default)]
|
||||
pub include_attestations: bool,
|
||||
}
|
||||
|
||||
@@ -303,11 +303,11 @@ impl ValidatorClientHttpClient {
|
||||
}
|
||||
|
||||
/// Perform a HTTP DELETE request.
|
||||
async fn delete_with_unsigned_response<T: Serialize, U: IntoUrl, V: DeserializeOwned>(
|
||||
async fn delete_with_raw_response<T: Serialize, U: IntoUrl>(
|
||||
&self,
|
||||
url: U,
|
||||
body: &T,
|
||||
) -> Result<V, Error> {
|
||||
) -> Result<Response, Error> {
|
||||
let response = self
|
||||
.client
|
||||
.delete(url)
|
||||
@@ -316,7 +316,16 @@ impl ValidatorClientHttpClient {
|
||||
.send()
|
||||
.await
|
||||
.map_err(Error::Reqwest)?;
|
||||
let response = ok_or_error(response).await?;
|
||||
ok_or_error(response).await
|
||||
}
|
||||
|
||||
/// Perform a HTTP DELETE request.
|
||||
async fn delete_with_unsigned_response<T: Serialize, U: IntoUrl, V: DeserializeOwned>(
|
||||
&self,
|
||||
url: U,
|
||||
body: &T,
|
||||
) -> Result<V, Error> {
|
||||
let response = self.delete_with_raw_response(url, body).await?;
|
||||
Ok(response.json().await?)
|
||||
}
|
||||
|
||||
@@ -345,7 +354,9 @@ impl ValidatorClientHttpClient {
|
||||
}
|
||||
|
||||
/// `GET lighthouse/spec`
|
||||
pub async fn get_lighthouse_spec(&self) -> Result<GenericResponse<ConfigAndPreset>, Error> {
|
||||
pub async fn get_lighthouse_spec<T: Serialize + DeserializeOwned>(
|
||||
&self,
|
||||
) -> Result<GenericResponse<T>, Error> {
|
||||
let mut path = self.server.full.clone();
|
||||
|
||||
path.path_segments_mut()
|
||||
@@ -453,7 +464,9 @@ impl ValidatorClientHttpClient {
|
||||
pub async fn patch_lighthouse_validators(
|
||||
&self,
|
||||
voting_pubkey: &PublicKeyBytes,
|
||||
enabled: bool,
|
||||
enabled: Option<bool>,
|
||||
gas_limit: Option<u64>,
|
||||
builder_proposals: Option<bool>,
|
||||
) -> Result<(), Error> {
|
||||
let mut path = self.server.full.clone();
|
||||
|
||||
@@ -463,7 +476,15 @@ impl ValidatorClientHttpClient {
|
||||
.push("validators")
|
||||
.push(&voting_pubkey.to_string());
|
||||
|
||||
self.patch(path, &ValidatorPatchRequest { enabled }).await
|
||||
self.patch(
|
||||
path,
|
||||
&ValidatorPatchRequest {
|
||||
enabled,
|
||||
gas_limit,
|
||||
builder_proposals,
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
fn make_keystores_url(&self) -> Result<Url, Error> {
|
||||
@@ -486,6 +507,30 @@ impl ValidatorClientHttpClient {
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
fn make_fee_recipient_url(&self, pubkey: &PublicKeyBytes) -> Result<Url, Error> {
|
||||
let mut url = self.server.full.clone();
|
||||
url.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("eth")
|
||||
.push("v1")
|
||||
.push("validator")
|
||||
.push(&pubkey.to_string())
|
||||
.push("feerecipient");
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
fn make_gas_limit_url(&self, pubkey: &PublicKeyBytes) -> Result<Url, Error> {
|
||||
let mut url = self.server.full.clone();
|
||||
url.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("eth")
|
||||
.push("v1")
|
||||
.push("validator")
|
||||
.push(&pubkey.to_string())
|
||||
.push("gas_limit");
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
/// `GET lighthouse/auth`
|
||||
pub async fn get_auth(&self) -> Result<AuthResponse, Error> {
|
||||
let mut url = self.server.full.clone();
|
||||
@@ -543,14 +588,71 @@ impl ValidatorClientHttpClient {
|
||||
let url = self.make_remotekeys_url()?;
|
||||
self.delete_with_unsigned_response(url, req).await
|
||||
}
|
||||
|
||||
/// `GET /eth/v1/validator/{pubkey}/feerecipient`
|
||||
pub async fn get_fee_recipient(
|
||||
&self,
|
||||
pubkey: &PublicKeyBytes,
|
||||
) -> Result<GetFeeRecipientResponse, Error> {
|
||||
let url = self.make_fee_recipient_url(pubkey)?;
|
||||
self.get(url)
|
||||
.await
|
||||
.map(|generic: GenericResponse<GetFeeRecipientResponse>| generic.data)
|
||||
}
|
||||
|
||||
/// `POST /eth/v1/validator/{pubkey}/feerecipient`
|
||||
pub async fn post_fee_recipient(
|
||||
&self,
|
||||
pubkey: &PublicKeyBytes,
|
||||
req: &UpdateFeeRecipientRequest,
|
||||
) -> Result<Response, Error> {
|
||||
let url = self.make_fee_recipient_url(pubkey)?;
|
||||
self.post_with_raw_response(url, req).await
|
||||
}
|
||||
|
||||
/// `DELETE /eth/v1/validator/{pubkey}/feerecipient`
|
||||
pub async fn delete_fee_recipient(&self, pubkey: &PublicKeyBytes) -> Result<Response, Error> {
|
||||
let url = self.make_fee_recipient_url(pubkey)?;
|
||||
self.delete_with_raw_response(url, &()).await
|
||||
}
|
||||
|
||||
/// `GET /eth/v1/validator/{pubkey}/gas_limit`
|
||||
pub async fn get_gas_limit(
|
||||
&self,
|
||||
pubkey: &PublicKeyBytes,
|
||||
) -> Result<GetGasLimitResponse, Error> {
|
||||
let url = self.make_gas_limit_url(pubkey)?;
|
||||
self.get(url)
|
||||
.await
|
||||
.map(|generic: GenericResponse<GetGasLimitResponse>| generic.data)
|
||||
}
|
||||
|
||||
/// `POST /eth/v1/validator/{pubkey}/gas_limit`
|
||||
pub async fn post_gas_limit(
|
||||
&self,
|
||||
pubkey: &PublicKeyBytes,
|
||||
req: &UpdateGasLimitRequest,
|
||||
) -> Result<Response, Error> {
|
||||
let url = self.make_gas_limit_url(pubkey)?;
|
||||
self.post_with_raw_response(url, req).await
|
||||
}
|
||||
|
||||
/// `DELETE /eth/v1/validator/{pubkey}/gas_limit`
|
||||
pub async fn delete_gas_limit(&self, pubkey: &PublicKeyBytes) -> Result<Response, Error> {
|
||||
let url = self.make_gas_limit_url(pubkey)?;
|
||||
self.delete_with_raw_response(url, &()).await
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `Ok(response)` if the response is a `200 OK` response. Otherwise, creates an
|
||||
/// appropriate error message.
|
||||
/// Returns `Ok(response)` if the response is a `200 OK` response or a
|
||||
/// `202 Accepted` response. Otherwise, creates an appropriate error message.
|
||||
async fn ok_or_error(response: Response) -> Result<Response, Error> {
|
||||
let status = response.status();
|
||||
|
||||
if status == StatusCode::OK {
|
||||
if status == StatusCode::OK
|
||||
|| status == StatusCode::ACCEPTED
|
||||
|| status == StatusCode::NO_CONTENT
|
||||
{
|
||||
Ok(response)
|
||||
} else if let Ok(message) = response.json().await {
|
||||
Err(Error::ServerMessage(message))
|
||||
|
||||
@@ -2,7 +2,20 @@ use account_utils::ZeroizeString;
|
||||
use eth2_keystore::Keystore;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use slashing_protection::interchange::Interchange;
|
||||
use types::PublicKeyBytes;
|
||||
use types::{Address, PublicKeyBytes};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub struct GetFeeRecipientResponse {
|
||||
pub pubkey: PublicKeyBytes,
|
||||
pub ethaddress: Address,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub struct GetGasLimitResponse {
|
||||
pub pubkey: PublicKeyBytes,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
pub gas_limit: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq)]
|
||||
pub struct AuthResponse {
|
||||
|
||||
@@ -26,6 +26,12 @@ pub struct ValidatorRequest {
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub suggested_fee_recipient: Option<Address>,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub gas_limit: Option<u64>,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub builder_proposals: Option<bool>,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
pub deposit_gwei: u64,
|
||||
}
|
||||
@@ -49,6 +55,12 @@ pub struct CreatedValidator {
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub suggested_fee_recipient: Option<Address>,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub gas_limit: Option<u64>,
|
||||
#[serde(default)]
|
||||
#[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")]
|
||||
pub deposit_gwei: u64,
|
||||
@@ -62,7 +74,15 @@ pub struct PostValidatorsResponseData {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ValidatorPatchRequest {
|
||||
pub enabled: bool,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub enabled: Option<bool>,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub gas_limit: Option<u64>,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub builder_proposals: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
@@ -70,8 +90,18 @@ pub struct KeystoreValidatorsPostRequest {
|
||||
pub password: ZeroizeString,
|
||||
pub enable: bool,
|
||||
pub keystore: Keystore,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub graffiti: Option<GraffitiString>,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub suggested_fee_recipient: Option<Address>,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub gas_limit: Option<u64>,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub builder_proposals: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
@@ -84,6 +114,12 @@ pub struct Web3SignerValidatorRequest {
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub suggested_fee_recipient: Option<Address>,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub gas_limit: Option<u64>,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub builder_proposals: Option<bool>,
|
||||
pub voting_public_key: PublicKey,
|
||||
pub url: String,
|
||||
#[serde(default)]
|
||||
@@ -97,3 +133,14 @@ pub struct Web3SignerValidatorRequest {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub client_identity_password: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct UpdateFeeRecipientRequest {
|
||||
pub ethaddress: Address,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct UpdateGasLimitRequest {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
pub gas_limit: u64,
|
||||
}
|
||||
|
||||
@@ -21,17 +21,17 @@ impl ResponseOptional for Result<Response, Error> {
|
||||
/// Trait for extracting the fork name from the headers of a response.
|
||||
pub trait ResponseForkName {
|
||||
#[allow(clippy::result_unit_err)]
|
||||
fn fork_name_from_header(&self) -> Result<Option<ForkName>, ()>;
|
||||
fn fork_name_from_header(&self) -> Result<Option<ForkName>, String>;
|
||||
}
|
||||
|
||||
impl ResponseForkName for Response {
|
||||
fn fork_name_from_header(&self) -> Result<Option<ForkName>, ()> {
|
||||
fn fork_name_from_header(&self) -> Result<Option<ForkName>, String> {
|
||||
self.headers()
|
||||
.get(CONSENSUS_VERSION_HEADER)
|
||||
.map(|fork_name| {
|
||||
fork_name
|
||||
.to_str()
|
||||
.map_err(|_| ())
|
||||
.map_err(|e| e.to_string())
|
||||
.and_then(ForkName::from_str)
|
||||
})
|
||||
.transpose()
|
||||
|
||||
@@ -189,6 +189,14 @@ impl fmt::Display for StateId {
|
||||
#[serde(bound = "T: Serialize + serde::de::DeserializeOwned")]
|
||||
pub struct DutiesResponse<T: Serialize + serde::de::DeserializeOwned> {
|
||||
pub dependent_root: Hash256,
|
||||
pub execution_optimistic: Option<bool>,
|
||||
pub data: T,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(bound = "T: Serialize + serde::de::DeserializeOwned")]
|
||||
pub struct ExecutionOptimisticResponse<T: Serialize + serde::de::DeserializeOwned> {
|
||||
pub execution_optimistic: Option<bool>,
|
||||
pub data: T,
|
||||
}
|
||||
|
||||
@@ -204,6 +212,18 @@ impl<T: Serialize + serde::de::DeserializeOwned> From<T> for GenericResponse<T>
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Serialize + serde::de::DeserializeOwned> GenericResponse<T> {
|
||||
pub fn add_execution_optimistic(
|
||||
self,
|
||||
execution_optimistic: bool,
|
||||
) -> ExecutionOptimisticResponse<T> {
|
||||
ExecutionOptimisticResponse {
|
||||
execution_optimistic: Some(execution_optimistic),
|
||||
data: self.data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize)]
|
||||
#[serde(bound = "T: Serialize")]
|
||||
pub struct GenericResponseRef<'a, T: Serialize> {
|
||||
@@ -216,6 +236,14 @@ impl<'a, T: Serialize> From<&'a T> for GenericResponseRef<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
pub struct ExecutionOptimisticForkVersionedResponse<T> {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub version: Option<ForkName>,
|
||||
pub execution_optimistic: Option<bool>,
|
||||
pub data: T,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
pub struct ForkVersionedResponse<T> {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
@@ -495,6 +523,8 @@ pub struct DepositContractData {
|
||||
pub struct ChainHeadData {
|
||||
pub slot: Slot,
|
||||
pub root: Hash256,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub execution_optimistic: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
@@ -522,6 +552,7 @@ pub struct VersionData {
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct SyncingData {
|
||||
pub is_syncing: bool,
|
||||
pub is_optimistic: Option<bool>,
|
||||
pub head_slot: Slot,
|
||||
pub sync_distance: Slot,
|
||||
}
|
||||
@@ -651,7 +682,7 @@ pub struct ValidatorAggregateAttestationQuery {
|
||||
pub slot: Slot,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
|
||||
pub struct BeaconCommitteeSubscription {
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
pub validator_index: u64,
|
||||
@@ -794,6 +825,7 @@ pub struct PeerCount {
|
||||
pub struct SseBlock {
|
||||
pub slot: Slot,
|
||||
pub block: Hash256,
|
||||
pub execution_optimistic: bool,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -801,6 +833,7 @@ pub struct SseFinalizedCheckpoint {
|
||||
pub block: Hash256,
|
||||
pub state: Hash256,
|
||||
pub epoch: Epoch,
|
||||
pub execution_optimistic: bool,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -811,6 +844,7 @@ pub struct SseHead {
|
||||
pub current_duty_dependent_root: Hash256,
|
||||
pub previous_duty_dependent_root: Hash256,
|
||||
pub epoch_transition: bool,
|
||||
pub execution_optimistic: bool,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -823,6 +857,7 @@ pub struct SseChainReorg {
|
||||
pub new_head_block: Hash256,
|
||||
pub new_head_state: Hash256,
|
||||
pub epoch: Epoch,
|
||||
pub execution_optimistic: bool,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -838,6 +873,7 @@ pub struct SseLateHead {
|
||||
pub attestable_delay: Option<Duration>,
|
||||
pub imported_delay: Option<Duration>,
|
||||
pub set_as_head_delay: Option<Duration>,
|
||||
pub execution_optimistic: bool,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Serialize, Clone)]
|
||||
|
||||
Reference in New Issue
Block a user