Ssz state (#1749)
## Issue Addressed NA ## Proposed Changes Adds a `lighthouse/beacon/states/:state_id/ssz` endpoint to allow us to pull the genesis state from the API. ## Additional Info NA
This commit is contained in:
parent
7f73dccebc
commit
b829257cca
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1574,6 +1574,7 @@ dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"eth2_keystore",
|
||||
"eth2_libp2p",
|
||||
"eth2_ssz",
|
||||
"hex 0.4.2",
|
||||
"libsecp256k1",
|
||||
"procinfo",
|
||||
@ -2461,6 +2462,7 @@ dependencies = [
|
||||
"eth1",
|
||||
"eth2",
|
||||
"eth2_libp2p",
|
||||
"eth2_ssz",
|
||||
"fork_choice",
|
||||
"hex 0.4.2",
|
||||
"lazy_static",
|
||||
|
@ -24,6 +24,7 @@ lighthouse_metrics = { path = "../../common/lighthouse_metrics" }
|
||||
lazy_static = "1.4.0"
|
||||
warp_utils = { path = "../../common/warp_utils" }
|
||||
slot_clock = { path = "../../common/slot_clock" }
|
||||
eth2_ssz = { path = "../../consensus/ssz" }
|
||||
bs58 = "0.3.1"
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -28,6 +28,7 @@ use parking_lot::Mutex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use slog::{crit, error, info, trace, warn, Logger};
|
||||
use slot_clock::SlotClock;
|
||||
use ssz::Encode;
|
||||
use state_id::StateId;
|
||||
use state_processing::per_slot_processing;
|
||||
use std::borrow::Cow;
|
||||
@ -41,7 +42,7 @@ use types::{
|
||||
Hash256, ProposerSlashing, PublicKey, RelativeEpoch, SignedAggregateAndProof,
|
||||
SignedBeaconBlock, SignedVoluntaryExit, Slot, YamlConfig,
|
||||
};
|
||||
use warp::Filter;
|
||||
use warp::{http::Response, Filter};
|
||||
use warp_utils::task::{blocking_json_task, blocking_task};
|
||||
|
||||
const API_PREFIX: &str = "eth";
|
||||
@ -1768,7 +1769,7 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.and(warp::path::param::<Epoch>())
|
||||
.and(warp::path("global"))
|
||||
.and(warp::path::end())
|
||||
.and(chain_filter)
|
||||
.and(chain_filter.clone())
|
||||
.and_then(|epoch: Epoch, chain: Arc<BeaconChain<T>>| {
|
||||
blocking_json_task(move || {
|
||||
validator_inclusion::global_validator_inclusion_data(epoch, &chain)
|
||||
@ -1776,6 +1777,30 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
})
|
||||
});
|
||||
|
||||
// GET lighthouse/beacon/states/{state_id}/ssz
|
||||
let get_lighthouse_beacon_states_ssz = warp::path("lighthouse")
|
||||
.and(warp::path("beacon"))
|
||||
.and(warp::path("states"))
|
||||
.and(warp::path::param::<StateId>())
|
||||
.and(warp::path("ssz"))
|
||||
.and(warp::path::end())
|
||||
.and(chain_filter)
|
||||
.and_then(|state_id: StateId, chain: Arc<BeaconChain<T>>| {
|
||||
blocking_task(move || {
|
||||
let state = state_id.state(&chain)?;
|
||||
Response::builder()
|
||||
.status(200)
|
||||
.header("Content-Type", "application/ssz")
|
||||
.body(state.as_ssz_bytes())
|
||||
.map_err(|e| {
|
||||
warp_utils::reject::custom_server_error(format!(
|
||||
"failed to create response: {}",
|
||||
e
|
||||
))
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
// Define the ultimate set of routes that will be provided to the server.
|
||||
let routes = warp::get()
|
||||
.and(
|
||||
@ -1818,6 +1843,7 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.or(get_lighthouse_proto_array.boxed())
|
||||
.or(get_lighthouse_validator_inclusion_global.boxed())
|
||||
.or(get_lighthouse_validator_inclusion.boxed())
|
||||
.or(get_lighthouse_beacon_states_ssz.boxed())
|
||||
.boxed(),
|
||||
)
|
||||
.or(warp::post()
|
||||
|
@ -1571,6 +1571,23 @@ impl ApiTester {
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn test_get_lighthouse_beacon_states_ssz(self) -> Self {
|
||||
for state_id in self.interesting_state_ids() {
|
||||
let result = self
|
||||
.client
|
||||
.get_lighthouse_beacon_states_ssz(&state_id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let mut expected = self.get_state(state_id);
|
||||
expected.as_mut().map(|state| state.drop_all_caches());
|
||||
|
||||
assert_eq!(result, expected, "{:?}", state_id);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test(core_threads = 2)]
|
||||
@ -1871,5 +1888,7 @@ async fn lighthouse_endpoints() {
|
||||
.test_get_lighthouse_validator_inclusion()
|
||||
.await
|
||||
.test_get_lighthouse_validator_inclusion_global()
|
||||
.await
|
||||
.test_get_lighthouse_beacon_states_ssz()
|
||||
.await;
|
||||
}
|
||||
|
@ -177,3 +177,17 @@ See [Validator Inclusion APIs](./validator-inclusion.md).
|
||||
### `/lighthouse/validator_inclusion/{epoch}/global`
|
||||
|
||||
See [Validator Inclusion APIs](./validator-inclusion.md).
|
||||
|
||||
### `/lighthouse/beacon/states/{state_id}/ssz`
|
||||
|
||||
Obtains a `BeaconState` in SSZ bytes. Useful for obtaining a genesis state.
|
||||
|
||||
The `state_id` parameter is identical to that used in the [Standard Eth2.0 API
|
||||
`beacon/state`
|
||||
routes](https://ethereum.github.io/eth2.0-APIs/#/Beacon/getStateRoot).
|
||||
|
||||
```bash
|
||||
curl -X GET "http://localhost:5052/lighthouse/beacon/states/0/ssz" | jq
|
||||
```
|
||||
|
||||
*Example omitted for brevity, the body simply contains SSZ bytes.*
|
||||
|
@ -21,6 +21,7 @@ libsecp256k1 = "0.3.5"
|
||||
ring = "0.16.12"
|
||||
bytes = "0.5.6"
|
||||
account_utils = { path = "../../common/account_utils" }
|
||||
eth2_ssz = { path = "../../consensus/ssz" }
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
psutil = { version = "3.2.0", optional = true }
|
||||
|
@ -40,6 +40,8 @@ pub enum Error {
|
||||
MissingSignatureHeader,
|
||||
/// The server returned an invalid JSON response.
|
||||
InvalidJson(serde_json::Error),
|
||||
/// The server returned an invalid SSZ response.
|
||||
InvalidSsz(ssz::DecodeError),
|
||||
}
|
||||
|
||||
impl Error {
|
||||
@ -54,6 +56,7 @@ impl Error {
|
||||
Error::InvalidSignatureHeader => None,
|
||||
Error::MissingSignatureHeader => None,
|
||||
Error::InvalidJson(_) => None,
|
||||
Error::InvalidSsz(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
//! This module contains endpoints that are non-standard and only available on Lighthouse servers.
|
||||
|
||||
use crate::{
|
||||
types::{Epoch, EthSpec, GenericResponse, ValidatorId},
|
||||
BeaconNodeHttpClient, Error,
|
||||
ok_or_error,
|
||||
types::{BeaconState, Epoch, EthSpec, GenericResponse, ValidatorId},
|
||||
BeaconNodeHttpClient, Error, StateId, StatusCode,
|
||||
};
|
||||
use proto_array::core::ProtoArray;
|
||||
use reqwest::IntoUrl;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ssz::Decode;
|
||||
|
||||
pub use eth2_libp2p::{types::SyncState, PeerInfo};
|
||||
|
||||
@ -143,6 +146,27 @@ impl Health {
|
||||
}
|
||||
|
||||
impl BeaconNodeHttpClient {
|
||||
/// Perform a HTTP GET request, returning `None` on a 404 error.
|
||||
async fn get_bytes_opt<U: IntoUrl>(&self, url: U) -> Result<Option<Vec<u8>>, Error> {
|
||||
let response = self.client.get(url).send().await.map_err(Error::Reqwest)?;
|
||||
match ok_or_error(response).await {
|
||||
Ok(resp) => Ok(Some(
|
||||
resp.bytes()
|
||||
.await
|
||||
.map_err(Error::Reqwest)?
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>(),
|
||||
)),
|
||||
Err(err) => {
|
||||
if err.status() == Some(StatusCode::NOT_FOUND) {
|
||||
Ok(None)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `GET lighthouse/health`
|
||||
pub async fn get_lighthouse_health(&self) -> Result<GenericResponse<Health>, Error> {
|
||||
let mut path = self.server.clone();
|
||||
@ -221,4 +245,25 @@ impl BeaconNodeHttpClient {
|
||||
|
||||
self.get(path).await
|
||||
}
|
||||
|
||||
/// `GET lighthouse/beacon/states/{state_id}/ssz`
|
||||
pub async fn get_lighthouse_beacon_states_ssz<E: EthSpec>(
|
||||
&self,
|
||||
state_id: &StateId,
|
||||
) -> Result<Option<BeaconState<E>>, Error> {
|
||||
let mut path = self.server.clone();
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("lighthouse")
|
||||
.push("beacon")
|
||||
.push("states")
|
||||
.push(&state_id.to_string())
|
||||
.push("ssz");
|
||||
|
||||
self.get_bytes_opt(path)
|
||||
.await?
|
||||
.map(|bytes| BeaconState::from_ssz_bytes(&bytes).map_err(Error::InvalidSsz))
|
||||
.transpose()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user