decouple eth2 from store and lighthouse_network (#6680)

- #6452 (partially)


  Remove dependencies on `store` and `lighthouse_network`  from `eth2`. This was achieved as follows:

- depend on `enr` and `multiaddr` directly instead of using `lighthouse_network`'s reexports.
- make `lighthouse_network` responsible for converting between API and internal types.
- in two cases, remove complex internal types and use the generic `serde_json::Value` instead - this is not ideal, but should be fine for now, as this affects two internal non-spec endpoints which are meant for debugging, unstable, and subject to change without notice anyway. Inspired by #6679. The alternative is to move all relevant types to `eth2` or `types` instead - what do you think?
This commit is contained in:
Daniel Knopik
2025-03-14 17:44:48 +01:00
committed by GitHub
parent a6bdc474db
commit 574b204bdb
26 changed files with 190 additions and 246 deletions

9
Cargo.lock generated
View File

@@ -2518,14 +2518,16 @@ version = "0.1.0"
dependencies = [ dependencies = [
"derivative", "derivative",
"either", "either",
"enr",
"eth2_keystore", "eth2_keystore",
"ethereum_serde_utils", "ethereum_serde_utils",
"ethereum_ssz", "ethereum_ssz",
"ethereum_ssz_derive", "ethereum_ssz_derive",
"futures", "futures",
"futures-util", "futures-util",
"lighthouse_network", "libp2p-identity",
"mediatype", "mediatype",
"multiaddr",
"pretty_reqwest_error", "pretty_reqwest_error",
"proto_array", "proto_array",
"reqwest", "reqwest",
@@ -2535,7 +2537,6 @@ dependencies = [
"serde_json", "serde_json",
"slashing_protection", "slashing_protection",
"ssz_types", "ssz_types",
"store",
"tokio", "tokio",
"types", "types",
"zeroize", "zeroize",
@@ -2980,7 +2981,6 @@ dependencies = [
"builder_client", "builder_client",
"bytes", "bytes",
"eth2", "eth2",
"eth2_network_config",
"ethereum_serde_utils", "ethereum_serde_utils",
"ethereum_ssz", "ethereum_ssz",
"ethers-core", "ethers-core",
@@ -5309,6 +5309,7 @@ dependencies = [
"dirs", "dirs",
"discv5", "discv5",
"either", "either",
"eth2",
"ethereum_ssz", "ethereum_ssz",
"ethereum_ssz_derive", "ethereum_ssz_derive",
"fnv", "fnv",
@@ -9486,7 +9487,6 @@ name = "validator_test_rig"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"eth2", "eth2",
"logging",
"mockito", "mockito",
"regex", "regex",
"sensitive_url", "sensitive_url",
@@ -9583,7 +9583,6 @@ dependencies = [
"bytes", "bytes",
"eth2", "eth2",
"headers", "headers",
"metrics",
"safe_arith", "safe_arith",
"serde", "serde",
"serde_array_query", "serde_array_query",

View File

@@ -1,7 +1,7 @@
use crate::{BeaconChain, BeaconChainError, BeaconChainTypes}; use crate::{BeaconChain, BeaconChainError, BeaconChainTypes};
use eth2::lighthouse::attestation_rewards::{IdealAttestationRewards, TotalAttestationRewards}; use eth2::types::{
use eth2::lighthouse::StandardAttestationRewards; IdealAttestationRewards, StandardAttestationRewards, TotalAttestationRewards, ValidatorId,
use eth2::types::ValidatorId; };
use safe_arith::SafeArith; use safe_arith::SafeArith;
use serde_utils::quoted_u64::Quoted; use serde_utils::quoted_u64::Quoted;
use state_processing::common::base::{self, SqrtTotalActiveBalance}; use state_processing::common::base::{self, SqrtTotalActiveBalance};

View File

@@ -1,6 +1,6 @@
use crate::{BeaconChain, BeaconChainError, BeaconChainTypes, StateSkipConfig}; use crate::{BeaconChain, BeaconChainError, BeaconChainTypes, StateSkipConfig};
use attesting_indices_base::get_attesting_indices; use attesting_indices_base::get_attesting_indices;
use eth2::lighthouse::StandardBlockReward; use eth2::types::StandardBlockReward;
use safe_arith::SafeArith; use safe_arith::SafeArith;
use state_processing::common::attesting_indices_base; use state_processing::common::attesting_indices_base;
use state_processing::{ use state_processing::{

View File

@@ -1,6 +1,6 @@
use crate::{BeaconChain, BeaconChainError, BeaconChainTypes}; use crate::{BeaconChain, BeaconChainError, BeaconChainTypes};
use eth2::lighthouse::SyncCommitteeReward; use eth2::types::SyncCommitteeReward;
use safe_arith::SafeArith; use safe_arith::SafeArith;
use state_processing::per_block_processing::altair::sync_committee::compute_sync_aggregate_rewards; use state_processing::per_block_processing::altair::sync_committee::compute_sync_aggregate_rewards;
use std::collections::HashMap; use std::collections::HashMap;

View File

@@ -9,9 +9,7 @@ use beacon_chain::{
types::{Epoch, EthSpec, Keypair, MinimalEthSpec}, types::{Epoch, EthSpec, Keypair, MinimalEthSpec},
BlockError, ChainConfig, StateSkipConfig, WhenSlotSkipped, BlockError, ChainConfig, StateSkipConfig, WhenSlotSkipped,
}; };
use eth2::lighthouse::attestation_rewards::TotalAttestationRewards; use eth2::types::{StandardAttestationRewards, TotalAttestationRewards, ValidatorId};
use eth2::lighthouse::StandardAttestationRewards;
use eth2::types::ValidatorId;
use state_processing::{BlockReplayError, BlockReplayer}; use state_processing::{BlockReplayError, BlockReplayer};
use std::array::IntoIter; use std::array::IntoIter;
use std::collections::HashMap; use std::collections::HashMap;

View File

@@ -12,7 +12,6 @@ arc-swap = "1.6.0"
builder_client = { path = "../builder_client" } builder_client = { path = "../builder_client" }
bytes = { workspace = true } bytes = { workspace = true }
eth2 = { workspace = true } eth2 = { workspace = true }
eth2_network_config = { workspace = true }
ethereum_serde_utils = { workspace = true } ethereum_serde_utils = { workspace = true }
ethereum_ssz = { workspace = true } ethereum_ssz = { workspace = true }
ethers-core = { workspace = true } ethers-core = { workspace = true }

View File

@@ -50,7 +50,6 @@ warp_utils = { workspace = true }
[dev-dependencies] [dev-dependencies]
genesis = { workspace = true } genesis = { workspace = true }
proto_array = { workspace = true } proto_array = { workspace = true }
serde_json = { workspace = true }
[[test]] [[test]]
name = "bn_http_api_tests" name = "bn_http_api_tests"

View File

@@ -1,7 +1,17 @@
use beacon_chain::store::metadata::CURRENT_SCHEMA_VERSION; use beacon_chain::store::metadata::CURRENT_SCHEMA_VERSION;
use beacon_chain::{BeaconChain, BeaconChainTypes}; use beacon_chain::{BeaconChain, BeaconChainTypes};
use eth2::lighthouse::DatabaseInfo; use serde::Serialize;
use std::sync::Arc; use std::sync::Arc;
use store::{AnchorInfo, BlobInfo, Split, StoreConfig};
#[derive(Debug, Serialize)]
pub struct DatabaseInfo {
pub schema_version: u64,
pub config: StoreConfig,
pub split: Split,
pub anchor: AnchorInfo,
pub blob_info: BlobInfo,
}
pub fn info<T: BeaconChainTypes>( pub fn info<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>, chain: Arc<BeaconChain<T>>,

View File

@@ -16,6 +16,7 @@ mod builder_states;
mod database; mod database;
mod light_client; mod light_client;
mod metrics; mod metrics;
mod peer;
mod produce_block; mod produce_block;
mod proposer_duties; mod proposer_duties;
mod publish_attestations; mod publish_attestations;
@@ -3022,15 +3023,13 @@ pub fn serve<T: BeaconChainTypes>(
}; };
// the eth2 API spec implies only peers we have been connected to at some point should be included. // the eth2 API spec implies only peers we have been connected to at some point should be included.
if let Some(dir) = peer_info.connection_direction().as_ref() { if let Some(&dir) = peer_info.connection_direction() {
return Ok(api_types::GenericResponse::from(api_types::PeerData { return Ok(api_types::GenericResponse::from(api_types::PeerData {
peer_id: peer_id.to_string(), peer_id: peer_id.to_string(),
enr: peer_info.enr().map(|enr| enr.to_base64()), enr: peer_info.enr().map(|enr| enr.to_base64()),
last_seen_p2p_address: address, last_seen_p2p_address: address,
direction: api_types::PeerDirection::from_connection_direction(dir), direction: dir.into(),
state: api_types::PeerState::from_peer_connection_status( state: peer_info.connection_status().clone().into(),
peer_info.connection_status(),
),
})); }));
} }
} }
@@ -3071,12 +3070,9 @@ pub fn serve<T: BeaconChainTypes>(
}; };
// the eth2 API spec implies only peers we have been connected to at some point should be included. // the eth2 API spec implies only peers we have been connected to at some point should be included.
if let Some(dir) = peer_info.connection_direction() { if let Some(&dir) = peer_info.connection_direction() {
let direction = let direction = dir.into();
api_types::PeerDirection::from_connection_direction(dir); let state = peer_info.connection_status().clone().into();
let state = api_types::PeerState::from_peer_connection_status(
peer_info.connection_status(),
);
let state_matches = query.state.as_ref().is_none_or(|states| { let state_matches = query.state.as_ref().is_none_or(|states| {
states.iter().any(|state_param| *state_param == state) states.iter().any(|state_param| *state_param == state)
@@ -3128,9 +3124,8 @@ pub fn serve<T: BeaconChainTypes>(
.read() .read()
.peers() .peers()
.for_each(|(_, peer_info)| { .for_each(|(_, peer_info)| {
let state = api_types::PeerState::from_peer_connection_status( let state =
peer_info.connection_status(), api_types::PeerState::from(peer_info.connection_status().clone());
);
match state { match state {
api_types::PeerState::Connected => connected += 1, api_types::PeerState::Connected => connected += 1,
api_types::PeerState::Connecting => connecting += 1, api_types::PeerState::Connecting => connecting += 1,
@@ -4089,7 +4084,7 @@ pub fn serve<T: BeaconChainTypes>(
.peers .peers
.read() .read()
.peers() .peers()
.map(|(peer_id, peer_info)| eth2::lighthouse::Peer { .map(|(peer_id, peer_info)| peer::Peer {
peer_id: peer_id.to_string(), peer_id: peer_id.to_string(),
peer_info: peer_info.clone(), peer_info: peer_info.clone(),
}) })
@@ -4109,15 +4104,14 @@ pub fn serve<T: BeaconChainTypes>(
|task_spawner: TaskSpawner<T::EthSpec>, |task_spawner: TaskSpawner<T::EthSpec>,
network_globals: Arc<NetworkGlobals<T::EthSpec>>| { network_globals: Arc<NetworkGlobals<T::EthSpec>>| {
task_spawner.blocking_json_task(Priority::P1, move || { task_spawner.blocking_json_task(Priority::P1, move || {
Ok(network_globals let mut peers = vec![];
.peers for (peer_id, peer_info) in network_globals.peers.read().connected_peers() {
.read() peers.push(peer::Peer {
.connected_peers()
.map(|(peer_id, peer_info)| eth2::lighthouse::Peer {
peer_id: peer_id.to_string(), peer_id: peer_id.to_string(),
peer_info: peer_info.clone(), peer_info: peer_info.clone(),
}) });
.collect::<Vec<_>>()) }
Ok(peers)
}) })
}, },
); );

View File

@@ -0,0 +1,13 @@
use lighthouse_network::PeerInfo;
use serde::Serialize;
use types::EthSpec;
/// Information returned by `peers` and `connected_peers`.
#[derive(Debug, Clone, Serialize)]
#[serde(bound = "E: EthSpec")]
pub(crate) struct Peer<E: EthSpec> {
/// The Peer's ID
pub peer_id: String,
/// The PeerInfo associated with the peer.
pub peer_info: PeerInfo<E>,
}

View File

@@ -2,7 +2,7 @@ use crate::sync_committee_rewards::get_state_before_applying_block;
use crate::BlockId; use crate::BlockId;
use crate::ExecutionOptimistic; use crate::ExecutionOptimistic;
use beacon_chain::{BeaconChain, BeaconChainTypes}; use beacon_chain::{BeaconChain, BeaconChainTypes};
use eth2::lighthouse::StandardBlockReward; use eth2::types::StandardBlockReward;
use std::sync::Arc; use std::sync::Arc;
use warp_utils::reject::unhandled_error; use warp_utils::reject::unhandled_error;
/// The difference between block_rewards and beacon_block_rewards is the later returns block /// The difference between block_rewards and beacon_block_rewards is the later returns block

View File

@@ -1,7 +1,6 @@
use crate::{BlockId, ExecutionOptimistic}; use crate::{BlockId, ExecutionOptimistic};
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes}; use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes};
use eth2::lighthouse::SyncCommitteeReward; use eth2::types::{SyncCommitteeReward, ValidatorId};
use eth2::types::ValidatorId;
use state_processing::BlockReplayer; use state_processing::BlockReplayer;
use std::sync::Arc; use std::sync::Arc;
use tracing::debug; use tracing::debug;

View File

@@ -5686,19 +5686,6 @@ impl ApiTester {
self self
} }
pub async fn test_get_lighthouse_database_info(self) -> Self {
let info = self.client.get_lighthouse_database_info().await.unwrap();
assert_eq!(info.anchor, self.chain.store.get_anchor_info());
assert_eq!(info.split, self.chain.store.get_split_info());
assert_eq!(
info.schema_version,
store::metadata::CURRENT_SCHEMA_VERSION.as_u64()
);
self
}
pub async fn test_post_lighthouse_database_reconstruct(self) -> Self { pub async fn test_post_lighthouse_database_reconstruct(self) -> Self {
let response = self let response = self
.client .client
@@ -7254,8 +7241,6 @@ async fn lighthouse_endpoints() {
.await .await
.test_get_lighthouse_staking() .test_get_lighthouse_staking()
.await .await
.test_get_lighthouse_database_info()
.await
.test_post_lighthouse_database_reconstruct() .test_post_lighthouse_database_reconstruct()
.await .await
.test_post_lighthouse_liveness() .test_post_lighthouse_liveness()

View File

@@ -13,6 +13,7 @@ directory = { workspace = true }
dirs = { workspace = true } dirs = { workspace = true }
discv5 = { workspace = true } discv5 = { workspace = true }
either = { workspace = true } either = { workspace = true }
eth2 = { workspace = true }
ethereum_ssz = { workspace = true } ethereum_ssz = { workspace = true }
ethereum_ssz_derive = { workspace = true } ethereum_ssz_derive = { workspace = true }
fnv = { workspace = true } fnv = { workspace = true }

View File

@@ -4,6 +4,7 @@ use super::sync_status::SyncStatus;
use crate::discovery::Eth2Enr; use crate::discovery::Eth2Enr;
use crate::{rpc::MetaData, types::Subnet}; use crate::{rpc::MetaData, types::Subnet};
use discv5::Enr; use discv5::Enr;
use eth2::types::{PeerDirection, PeerState};
use libp2p::core::multiaddr::{Multiaddr, Protocol}; use libp2p::core::multiaddr::{Multiaddr, Protocol};
use serde::{ use serde::{
ser::{SerializeStruct, Serializer}, ser::{SerializeStruct, Serializer},
@@ -522,7 +523,7 @@ impl<E: EthSpec> PeerInfo<E> {
} }
/// Connection Direction of connection. /// Connection Direction of connection.
#[derive(Debug, Clone, Serialize, AsRefStr)] #[derive(Debug, Clone, Copy, Serialize, AsRefStr)]
#[strum(serialize_all = "snake_case")] #[strum(serialize_all = "snake_case")]
pub enum ConnectionDirection { pub enum ConnectionDirection {
/// The connection was established by a peer dialing us. /// The connection was established by a peer dialing us.
@@ -531,6 +532,15 @@ pub enum ConnectionDirection {
Outgoing, Outgoing,
} }
impl From<ConnectionDirection> for PeerDirection {
fn from(direction: ConnectionDirection) -> Self {
match direction {
ConnectionDirection::Incoming => PeerDirection::Inbound,
ConnectionDirection::Outgoing => PeerDirection::Outbound,
}
}
}
/// Connection Status of the peer. /// Connection Status of the peer.
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub enum PeerConnectionStatus { pub enum PeerConnectionStatus {
@@ -624,3 +634,14 @@ impl Serialize for PeerConnectionStatus {
} }
} }
} }
impl From<PeerConnectionStatus> for PeerState {
fn from(status: PeerConnectionStatus) -> Self {
match status {
Connected { .. } => PeerState::Connected,
Dialing { .. } => PeerState::Connecting,
Disconnecting { .. } => PeerState::Disconnecting,
Disconnected { .. } | Banned { .. } | Unknown => PeerState::Disconnected,
}
}
}

View File

@@ -1,7 +1,6 @@
mod globals; mod globals;
mod pubsub; mod pubsub;
mod subnet; mod subnet;
mod sync_state;
mod topics; mod topics;
use types::{BitVector, EthSpec}; use types::{BitVector, EthSpec};
@@ -11,10 +10,10 @@ pub type EnrSyncCommitteeBitfield<E> = BitVector<<E as EthSpec>::SyncCommitteeSu
pub type Enr = discv5::enr::Enr<discv5::enr::CombinedKey>; pub type Enr = discv5::enr::Enr<discv5::enr::CombinedKey>;
pub use eth2::lighthouse::sync_state::{BackFillState, SyncState};
pub use globals::NetworkGlobals; pub use globals::NetworkGlobals;
pub use pubsub::{PubsubMessage, SnappyTransform}; pub use pubsub::{PubsubMessage, SnappyTransform};
pub use subnet::{Subnet, SubnetDiscovery}; pub use subnet::{Subnet, SubnetDiscovery};
pub use sync_state::{BackFillState, SyncState};
pub use topics::{ pub use topics::{
all_topics_at_fork, core_topics_to_subscribe, is_fork_non_core_topic, subnet_from_topic_hash, all_topics_at_fork, core_topics_to_subscribe, is_fork_non_core_topic, subnet_from_topic_hash,
GossipEncoding, GossipKind, GossipTopic, TopicConfig, GossipEncoding, GossipKind, GossipTopic, TopicConfig,

View File

@@ -3,19 +3,20 @@ name = "eth2"
version = "0.1.0" version = "0.1.0"
authors = ["Paul Hauner <paul@paulhauner.com>"] authors = ["Paul Hauner <paul@paulhauner.com>"]
edition = { workspace = true } edition = { workspace = true }
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
derivative = { workspace = true } derivative = { workspace = true }
either = { workspace = true } either = { workspace = true }
enr = { version = "0.13.0", features = ["ed25519"] }
eth2_keystore = { workspace = true } eth2_keystore = { workspace = true }
ethereum_serde_utils = { workspace = true } ethereum_serde_utils = { workspace = true }
ethereum_ssz = { workspace = true } ethereum_ssz = { workspace = true }
ethereum_ssz_derive = { workspace = true } ethereum_ssz_derive = { workspace = true }
futures = { workspace = true } futures = { workspace = true }
futures-util = "0.3.8" futures-util = "0.3.8"
lighthouse_network = { workspace = true } libp2p-identity = { version = "0.2", features = ["peerid"] }
mediatype = "0.19.13" mediatype = "0.19.13"
multiaddr = "0.18.2"
pretty_reqwest_error = { workspace = true } pretty_reqwest_error = { workspace = true }
proto_array = { workspace = true } proto_array = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }
@@ -25,7 +26,6 @@ serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
slashing_protection = { workspace = true } slashing_protection = { workspace = true }
ssz_types = { workspace = true } ssz_types = { workspace = true }
store = { workspace = true }
types = { workspace = true } types = { workspace = true }
zeroize = { workspace = true } zeroize = { workspace = true }

View File

@@ -16,11 +16,12 @@ pub mod types;
use self::mixin::{RequestAccept, ResponseOptional}; use self::mixin::{RequestAccept, ResponseOptional};
use self::types::{Error as ResponseError, *}; use self::types::{Error as ResponseError, *};
use ::types::fork_versioned_response::ExecutionOptimisticFinalizedForkVersionedResponse;
use derivative::Derivative; use derivative::Derivative;
use either::Either; use either::Either;
use futures::Stream; use futures::Stream;
use futures_util::StreamExt; use futures_util::StreamExt;
use lighthouse_network::PeerId; use libp2p_identity::PeerId;
use pretty_reqwest_error::PrettyReqwestError; use pretty_reqwest_error::PrettyReqwestError;
pub use reqwest; pub use reqwest;
use reqwest::{ use reqwest::{
@@ -36,7 +37,6 @@ use std::fmt;
use std::future::Future; use std::future::Future;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
use store::fork_versioned_response::ExecutionOptimisticFinalizedForkVersionedResponse;
pub const V1: EndpointVersion = EndpointVersion(1); pub const V1: EndpointVersion = EndpointVersion(1);
pub const V2: EndpointVersion = EndpointVersion(2); pub const V2: EndpointVersion = EndpointVersion(2);
@@ -329,7 +329,6 @@ impl BeaconNodeHttpClient {
} }
/// Perform a HTTP POST request, returning a JSON response. /// Perform a HTTP POST request, returning a JSON response.
#[cfg(feature = "lighthouse")]
async fn post_with_response<T: Serialize, U: IntoUrl, R: DeserializeOwned>( async fn post_with_response<T: Serialize, U: IntoUrl, R: DeserializeOwned>(
&self, &self,
url: U, url: U,
@@ -1602,33 +1601,34 @@ impl BeaconNodeHttpClient {
/// `POST beacon/rewards/sync_committee` /// `POST beacon/rewards/sync_committee`
pub async fn post_beacon_rewards_sync_committee( pub async fn post_beacon_rewards_sync_committee(
&self, &self,
rewards: &[Option<Vec<lighthouse::SyncCommitteeReward>>], block_id: BlockId,
) -> Result<(), Error> { validators: &[ValidatorId],
) -> Result<GenericResponse<Vec<SyncCommitteeReward>>, Error> {
let mut path = self.eth_path(V1)?; let mut path = self.eth_path(V1)?;
path.path_segments_mut() path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))? .map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("beacon") .push("beacon")
.push("rewards") .push("rewards")
.push("sync_committee"); .push("sync_committee")
.push(&block_id.to_string());
self.post(path, &rewards).await?; self.post_with_response(path, &validators).await
Ok(())
} }
/// `GET beacon/rewards/blocks` /// `GET beacon/rewards/blocks`
pub async fn get_beacon_rewards_blocks(&self, epoch: Epoch) -> Result<(), Error> { pub async fn get_beacon_rewards_blocks(
&self,
block_id: BlockId,
) -> Result<GenericResponse<StandardBlockReward>, Error> {
let mut path = self.eth_path(V1)?; let mut path = self.eth_path(V1)?;
path.path_segments_mut() path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))? .map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("beacon") .push("beacon")
.push("rewards") .push("rewards")
.push("blocks"); .push("blocks")
.push(&block_id.to_string());
path.query_pairs_mut()
.append_pair("epoch", &epoch.to_string());
self.get(path).await self.get(path).await
} }
@@ -1636,19 +1636,19 @@ impl BeaconNodeHttpClient {
/// `POST beacon/rewards/attestations` /// `POST beacon/rewards/attestations`
pub async fn post_beacon_rewards_attestations( pub async fn post_beacon_rewards_attestations(
&self, &self,
attestations: &[ValidatorId], epoch: Epoch,
) -> Result<(), Error> { validators: &[ValidatorId],
) -> Result<StandardAttestationRewards, Error> {
let mut path = self.eth_path(V1)?; let mut path = self.eth_path(V1)?;
path.path_segments_mut() path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))? .map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("beacon") .push("beacon")
.push("rewards") .push("rewards")
.push("attestations"); .push("attestations")
.push(&epoch.to_string());
self.post(path, &attestations).await?; self.post_with_response(path, &validators).await
Ok(())
} }
// GET builder/states/{state_id}/expected_withdrawals // GET builder/states/{state_id}/expected_withdrawals

View File

@@ -1,52 +1,33 @@
//! This module contains endpoints that are non-standard and only available on Lighthouse servers. //! This module contains endpoints that are non-standard and only available on Lighthouse servers.
mod attestation_performance; mod attestation_performance;
pub mod attestation_rewards;
mod block_packing_efficiency; mod block_packing_efficiency;
mod block_rewards; mod block_rewards;
mod standard_block_rewards; pub mod sync_state;
mod sync_committee_rewards;
use crate::{ use crate::{
types::{ lighthouse::sync_state::SyncState,
DepositTreeSnapshot, Epoch, EthSpec, FinalizedExecutionBlock, GenericResponse, ValidatorId, types::{DepositTreeSnapshot, Epoch, FinalizedExecutionBlock, GenericResponse, ValidatorId},
},
BeaconNodeHttpClient, DepositData, Error, Eth1Data, Hash256, Slot, BeaconNodeHttpClient, DepositData, Error, Eth1Data, Hash256, Slot,
}; };
use proto_array::core::ProtoArray; use proto_array::core::ProtoArray;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ssz::four_byte_option_impl; use ssz::four_byte_option_impl;
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use store::{AnchorInfo, BlobInfo, Split, StoreConfig};
pub use attestation_performance::{ pub use attestation_performance::{
AttestationPerformance, AttestationPerformanceQuery, AttestationPerformanceStatistics, AttestationPerformance, AttestationPerformanceQuery, AttestationPerformanceStatistics,
}; };
pub use attestation_rewards::StandardAttestationRewards;
pub use block_packing_efficiency::{ pub use block_packing_efficiency::{
BlockPackingEfficiency, BlockPackingEfficiencyQuery, ProposerInfo, UniqueAttestation, BlockPackingEfficiency, BlockPackingEfficiencyQuery, ProposerInfo, UniqueAttestation,
}; };
pub use block_rewards::{AttestationRewards, BlockReward, BlockRewardMeta, BlockRewardsQuery}; pub use block_rewards::{AttestationRewards, BlockReward, BlockRewardMeta, BlockRewardsQuery};
pub use lighthouse_network::{types::SyncState, PeerInfo};
pub use standard_block_rewards::StandardBlockReward;
pub use sync_committee_rewards::SyncCommitteeReward;
// Define "legacy" implementations of `Option<T>` which use four bytes for encoding the union // Define "legacy" implementations of `Option<T>` which use four bytes for encoding the union
// selector. // selector.
four_byte_option_impl!(four_byte_option_u64, u64); four_byte_option_impl!(four_byte_option_u64, u64);
four_byte_option_impl!(four_byte_option_hash256, Hash256); four_byte_option_impl!(four_byte_option_hash256, Hash256);
/// Information returned by `peers` and `connected_peers`.
// TODO: this should be deserializable..
#[derive(Debug, Clone, Serialize)]
#[serde(bound = "E: EthSpec")]
pub struct Peer<E: EthSpec> {
/// The Peer's ID
pub peer_id: String,
/// The PeerInfo associated with the peer.
pub peer_info: PeerInfo<E>,
}
/// The results of validators voting during an epoch. /// The results of validators voting during an epoch.
/// ///
/// Provides information about the current and previous epochs. /// Provides information about the current and previous epochs.
@@ -234,15 +215,6 @@ impl From<Eth1Block> for FinalizedExecutionBlock {
} }
} }
#[derive(Debug, Serialize, Deserialize)]
pub struct DatabaseInfo {
pub schema_version: u64,
pub config: StoreConfig,
pub split: Split,
pub anchor: AnchorInfo,
pub blob_info: BlobInfo,
}
impl BeaconNodeHttpClient { impl BeaconNodeHttpClient {
/// `GET lighthouse/health` /// `GET lighthouse/health`
pub async fn get_lighthouse_health(&self) -> Result<GenericResponse<Health>, Error> { pub async fn get_lighthouse_health(&self) -> Result<GenericResponse<Health>, Error> {
@@ -380,19 +352,6 @@ impl BeaconNodeHttpClient {
self.get_opt::<(), _>(path).await.map(|opt| opt.is_some()) self.get_opt::<(), _>(path).await.map(|opt| opt.is_some())
} }
/// `GET lighthouse/database/info`
pub async fn get_lighthouse_database_info(&self) -> Result<DatabaseInfo, Error> {
let mut path = self.server.full.clone();
path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("lighthouse")
.push("database")
.push("info");
self.get(path).await
}
/// `POST lighthouse/database/reconstruct` /// `POST lighthouse/database/reconstruct`
pub async fn post_lighthouse_database_reconstruct(&self) -> Result<String, Error> { pub async fn post_lighthouse_database_reconstruct(&self) -> Result<String, Error> {
let mut path = self.server.full.clone(); let mut path = self.server.full.clone();

View File

@@ -1,55 +0,0 @@
use serde::{Deserialize, Serialize};
use serde_utils::quoted_u64::Quoted;
// Details about the rewards paid for attestations
// All rewards in GWei
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct IdealAttestationRewards {
// Validator's effective balance in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub effective_balance: u64,
// Ideal attester's reward for head vote in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub head: u64,
// Ideal attester's reward for target vote in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub target: u64,
// Ideal attester's reward for source vote in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub source: u64,
// Ideal attester's inclusion_delay reward in gwei (phase0 only)
#[serde(skip_serializing_if = "Option::is_none")]
pub inclusion_delay: Option<Quoted<u64>>,
// Ideal attester's inactivity penalty in gwei
#[serde(with = "serde_utils::quoted_i64")]
pub inactivity: i64,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct TotalAttestationRewards {
// one entry for every validator based on their attestations in the epoch
#[serde(with = "serde_utils::quoted_u64")]
pub validator_index: u64,
// attester's reward for head vote in gwei
#[serde(with = "serde_utils::quoted_i64")]
pub head: i64,
// attester's reward for target vote in gwei
#[serde(with = "serde_utils::quoted_i64")]
pub target: i64,
// attester's reward for source vote in gwei
#[serde(with = "serde_utils::quoted_i64")]
pub source: i64,
// attester's inclusion_delay reward in gwei (phase0 only)
#[serde(skip_serializing_if = "Option::is_none")]
pub inclusion_delay: Option<Quoted<u64>>,
// attester's inactivity penalty in gwei
#[serde(with = "serde_utils::quoted_i64")]
pub inactivity: i64,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct StandardAttestationRewards {
pub ideal_rewards: Vec<IdealAttestationRewards>,
pub total_rewards: Vec<TotalAttestationRewards>,
}

View File

@@ -1,26 +0,0 @@
use serde::{Deserialize, Serialize};
// Details about the rewards for a single block
// All rewards in GWei
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct StandardBlockReward {
// proposer of the block, the proposer index who receives these rewards
#[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 = "serde_utils::quoted_u64")]
pub total: u64,
// block reward component due to included attestations in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub attestations: u64,
// block reward component due to included sync_aggregate in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub sync_aggregate: u64,
// block reward component due to included proposer_slashings in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub proposer_slashings: u64,
// block reward component due to included attester_slashings in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub attester_slashings: u64,
}

View File

@@ -1,13 +0,0 @@
use serde::{Deserialize, Serialize};
// Details about the rewards paid to sync committee members for attesting headers
// All rewards in GWei
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct SyncCommitteeReward {
#[serde(with = "serde_utils::quoted_u64")]
pub validator_index: u64,
// sync committee reward in gwei for the validator
#[serde(with = "serde_utils::quoted_i64")]
pub reward: i64,
}

View File

@@ -5,11 +5,13 @@ use crate::{
Error as ServerError, CONSENSUS_BLOCK_VALUE_HEADER, CONSENSUS_VERSION_HEADER, Error as ServerError, CONSENSUS_BLOCK_VALUE_HEADER, CONSENSUS_VERSION_HEADER,
EXECUTION_PAYLOAD_BLINDED_HEADER, EXECUTION_PAYLOAD_VALUE_HEADER, EXECUTION_PAYLOAD_BLINDED_HEADER, EXECUTION_PAYLOAD_VALUE_HEADER,
}; };
use lighthouse_network::{ConnectionDirection, Enr, Multiaddr, PeerConnectionStatus}; use enr::{CombinedKey, Enr};
use mediatype::{names, MediaType, MediaTypeList}; use mediatype::{names, MediaType, MediaTypeList};
use multiaddr::Multiaddr;
use reqwest::header::HeaderMap; use reqwest::header::HeaderMap;
use serde::{Deserialize, Deserializer, Serialize}; use serde::{Deserialize, Deserializer, Serialize};
use serde_json::Value; use serde_json::Value;
use serde_utils::quoted_u64::Quoted;
use ssz::{Decode, DecodeError}; use ssz::{Decode, DecodeError};
use ssz_derive::{Decode, Encode}; use ssz_derive::{Decode, Encode};
use std::fmt::{self, Display}; use std::fmt::{self, Display};
@@ -578,7 +580,7 @@ pub struct ChainHeadData {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct IdentityData { pub struct IdentityData {
pub peer_id: String, pub peer_id: String,
pub enr: Enr, pub enr: Enr<CombinedKey>,
pub p2p_addresses: Vec<Multiaddr>, pub p2p_addresses: Vec<Multiaddr>,
pub discovery_addresses: Vec<Multiaddr>, pub discovery_addresses: Vec<Multiaddr>,
pub metadata: MetaData, pub metadata: MetaData,
@@ -861,19 +863,6 @@ pub enum PeerState {
Disconnecting, Disconnecting,
} }
impl PeerState {
pub fn from_peer_connection_status(status: &PeerConnectionStatus) -> Self {
match status {
PeerConnectionStatus::Connected { .. } => PeerState::Connected,
PeerConnectionStatus::Dialing { .. } => PeerState::Connecting,
PeerConnectionStatus::Disconnecting { .. } => PeerState::Disconnecting,
PeerConnectionStatus::Disconnected { .. }
| PeerConnectionStatus::Banned { .. }
| PeerConnectionStatus::Unknown => PeerState::Disconnected,
}
}
}
impl FromStr for PeerState { impl FromStr for PeerState {
type Err = String; type Err = String;
@@ -906,15 +895,6 @@ pub enum PeerDirection {
Outbound, Outbound,
} }
impl PeerDirection {
pub fn from_connection_direction(direction: &ConnectionDirection) -> Self {
match direction {
ConnectionDirection::Incoming => PeerDirection::Inbound,
ConnectionDirection::Outgoing => PeerDirection::Outbound,
}
}
}
impl FromStr for PeerDirection { impl FromStr for PeerDirection {
type Err = String; type Err = String;
@@ -2066,6 +2046,90 @@ pub struct BlobsBundle<E: EthSpec> {
pub blobs: BlobsList<E>, pub blobs: BlobsList<E>,
} }
/// Details about the rewards paid to sync committee members for attesting headers
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct SyncCommitteeReward {
#[serde(with = "serde_utils::quoted_u64")]
pub validator_index: u64,
/// sync committee reward in gwei for the validator
#[serde(with = "serde_utils::quoted_i64")]
pub reward: i64,
}
/// Details about the rewards for a single block
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct StandardBlockReward {
/// proposer of the block, the proposer index who receives these rewards
#[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 = "serde_utils::quoted_u64")]
pub total: u64,
/// block reward component due to included attestations in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub attestations: u64,
/// block reward component due to included sync_aggregate in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub sync_aggregate: u64,
/// block reward component due to included proposer_slashings in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub proposer_slashings: u64,
/// block reward component due to included attester_slashings in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub attester_slashings: u64,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct IdealAttestationRewards {
/// Validator's effective balance in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub effective_balance: u64,
/// Ideal attester's reward for head vote in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub head: u64,
/// Ideal attester's reward for target vote in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub target: u64,
/// Ideal attester's reward for source vote in gwei
#[serde(with = "serde_utils::quoted_u64")]
pub source: u64,
/// Ideal attester's inclusion_delay reward in gwei (phase0 only)
#[serde(skip_serializing_if = "Option::is_none")]
pub inclusion_delay: Option<Quoted<u64>>,
/// Ideal attester's inactivity penalty in gwei
#[serde(with = "serde_utils::quoted_i64")]
pub inactivity: i64,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct TotalAttestationRewards {
/// one entry for every validator based on their attestations in the epoch
#[serde(with = "serde_utils::quoted_u64")]
pub validator_index: u64,
/// attester's reward for head vote in gwei
#[serde(with = "serde_utils::quoted_i64")]
pub head: i64,
/// attester's reward for target vote in gwei
#[serde(with = "serde_utils::quoted_i64")]
pub target: i64,
/// attester's reward for source vote in gwei
#[serde(with = "serde_utils::quoted_i64")]
pub source: i64,
/// attester's inclusion_delay reward in gwei (phase0 only)
#[serde(skip_serializing_if = "Option::is_none")]
pub inclusion_delay: Option<Quoted<u64>>,
/// attester's inactivity penalty in gwei
#[serde(with = "serde_utils::quoted_i64")]
pub inactivity: i64,
}
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct StandardAttestationRewards {
pub ideal_rewards: Vec<IdealAttestationRewards>,
pub total_rewards: Vec<TotalAttestationRewards>,
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

View File

@@ -9,7 +9,6 @@ edition = { workspace = true }
bytes = { workspace = true } bytes = { workspace = true }
eth2 = { workspace = true } eth2 = { workspace = true }
headers = "0.3.2" headers = "0.3.2"
metrics = { workspace = true }
safe_arith = { workspace = true } safe_arith = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
serde_array_query = "0.1.0" serde_array_query = "0.1.0"

View File

@@ -5,7 +5,6 @@ edition = { workspace = true }
[dependencies] [dependencies]
eth2 = { workspace = true } eth2 = { workspace = true }
logging = { workspace = true }
mockito = { workspace = true } mockito = { workspace = true }
regex = { workspace = true } regex = { workspace = true }
sensitive_url = { workspace = true } sensitive_url = { workspace = true }