parent
c6f042b94f
commit
ad47dcf228
|
@ -12,6 +12,7 @@ nomos-storage = { path = "../../nomos-services/storage", features = ["sled"] }
|
||||||
nomos-api = { path = "../../nomos-services/api" }
|
nomos-api = { path = "../../nomos-services/api" }
|
||||||
nomos-node = { path = "../nomos-node" }
|
nomos-node = { path = "../nomos-node" }
|
||||||
nomos-core = { path = "../../nomos-core" }
|
nomos-core = { path = "../../nomos-core" }
|
||||||
|
full-replication = { path = "../../nomos-da/full-replication" }
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
async-trait = "0.1.73"
|
async-trait = "0.1.73"
|
||||||
|
@ -19,8 +20,9 @@ axum = "0.6"
|
||||||
hyper = "0.14.27"
|
hyper = "0.14.27"
|
||||||
tower-http = "0.4"
|
tower-http = "0.4"
|
||||||
utoipa = "4.0"
|
utoipa = "4.0"
|
||||||
utoipa-swagger-ui = "4.0"
|
utoipa-swagger-ui = "6.0"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
serde_yaml = "0.9.25"
|
serde_yaml = "0.9.25"
|
||||||
clap = { version = "4.4.6", features = ["derive"] }
|
clap = { version = "4.4.6", features = ["derive"] }
|
||||||
eyre = "0.6"
|
eyre = "0.6"
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,12 @@ where
|
||||||
)
|
)
|
||||||
.layer(TraceLayer::new_for_http())
|
.layer(TraceLayer::new_for_http())
|
||||||
// .merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi()))
|
// .merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi()))
|
||||||
.route("/blocks", routing::get(store::store_blocks::<T, S>))
|
.route("/store/blocks", routing::get(store::store_blocks::<T, S>))
|
||||||
|
.route("/explorer/blocks", routing::get(store::blocks::<T, S>))
|
||||||
|
.route(
|
||||||
|
"/explorer/blocks/depth",
|
||||||
|
routing::get(store::block_depth::<T, S>),
|
||||||
|
)
|
||||||
.with_state(handle);
|
.with_state(handle);
|
||||||
|
|
||||||
Server::bind(&self.settings.address)
|
Server::bind(&self.settings.address)
|
||||||
|
|
|
@ -4,12 +4,14 @@ use std::hash::Hash;
|
||||||
|
|
||||||
// crates
|
// crates
|
||||||
use axum::extract::{Query, State};
|
use axum::extract::{Query, State};
|
||||||
use axum::response::Response;
|
use axum::response::{IntoResponse, Response};
|
||||||
|
use hyper::StatusCode;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
// internal
|
// internal
|
||||||
|
use full_replication::Certificate;
|
||||||
use nomos_api::http::storage;
|
use nomos_api::http::storage;
|
||||||
use nomos_core::block::BlockId;
|
use nomos_core::block::{Block, BlockId};
|
||||||
use nomos_core::tx::Transaction;
|
use nomos_core::tx::Transaction;
|
||||||
use nomos_node::make_request_and_return_response;
|
use nomos_node::make_request_and_return_response;
|
||||||
use nomos_storage::backends::StorageSerde;
|
use nomos_storage::backends::StorageSerde;
|
||||||
|
@ -44,3 +46,182 @@ where
|
||||||
.collect();
|
.collect();
|
||||||
make_request_and_return_response!(futures::future::try_join_all(results))
|
make_request_and_return_response!(futures::future::try_join_all(results))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct BlocksByIdQueryParams {
|
||||||
|
from: BlockId,
|
||||||
|
to: Option<BlockId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn blocks<Tx, S>(
|
||||||
|
State(store): State<OverwatchHandle>,
|
||||||
|
Query(query): Query<BlocksByIdQueryParams>,
|
||||||
|
) -> Response
|
||||||
|
where
|
||||||
|
Tx: Transaction
|
||||||
|
+ Clone
|
||||||
|
+ Debug
|
||||||
|
+ Eq
|
||||||
|
+ Hash
|
||||||
|
+ Serialize
|
||||||
|
+ DeserializeOwned
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
<Tx as Transaction>::Hash: std::cmp::Ord + Debug + Send + Sync + 'static,
|
||||||
|
S: StorageSerde + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
let BlocksByIdQueryParams { from, to } = query;
|
||||||
|
// get the from block
|
||||||
|
let from = match storage::block_req::<S, Tx>(&store, from).await {
|
||||||
|
Ok(from) => match from {
|
||||||
|
Some(from) => from,
|
||||||
|
None => {
|
||||||
|
return IntoResponse::into_response((StatusCode::NOT_FOUND, "from block not found"))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
return IntoResponse::into_response((StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// check if to is valid
|
||||||
|
match to {
|
||||||
|
Some(to) => match storage::block_req::<S, Tx>(&store, to).await {
|
||||||
|
Ok(to) => match to {
|
||||||
|
Some(to) => handle_to::<S, Tx>(store, from, Some(to)).await,
|
||||||
|
None => IntoResponse::into_response((StatusCode::NOT_FOUND, "to block not found")),
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
IntoResponse::into_response((StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => handle_to::<S, Tx>(store, from, None).await,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_to<S, Tx>(
|
||||||
|
store: OverwatchHandle,
|
||||||
|
from: Block<Tx, Certificate>,
|
||||||
|
to: Option<Block<Tx, Certificate>>,
|
||||||
|
) -> Response
|
||||||
|
where
|
||||||
|
Tx: Transaction
|
||||||
|
+ Clone
|
||||||
|
+ Debug
|
||||||
|
+ Eq
|
||||||
|
+ Hash
|
||||||
|
+ Serialize
|
||||||
|
+ DeserializeOwned
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
<Tx as Transaction>::Hash: std::cmp::Ord + Debug + Send + Sync + 'static,
|
||||||
|
S: StorageSerde + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
let mut current = Some(from.header().parent());
|
||||||
|
let mut blocks = Vec::new();
|
||||||
|
while let Some(id) = current {
|
||||||
|
if let Some(to) = &to {
|
||||||
|
if id == to.header().id {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let block = match storage::block_req::<S, Tx>(&store, id).await {
|
||||||
|
Ok(block) => block,
|
||||||
|
Err(e) => {
|
||||||
|
return IntoResponse::into_response((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
e.to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match block {
|
||||||
|
Some(block) => {
|
||||||
|
current = Some(block.header().parent());
|
||||||
|
blocks.push(block);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
current = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IntoResponse::into_response((StatusCode::OK, ::axum::Json(blocks)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub(crate) struct BlocksByDepthQueryParams {
|
||||||
|
from: BlockId,
|
||||||
|
#[serde(default = "default_depth")]
|
||||||
|
depth: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_depth() -> usize {
|
||||||
|
500
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn block_depth<Tx, S>(
|
||||||
|
State(store): State<OverwatchHandle>,
|
||||||
|
Query(query): Query<BlocksByDepthQueryParams>,
|
||||||
|
) -> Response
|
||||||
|
where
|
||||||
|
Tx: Transaction
|
||||||
|
+ Clone
|
||||||
|
+ Debug
|
||||||
|
+ Eq
|
||||||
|
+ Hash
|
||||||
|
+ Serialize
|
||||||
|
+ DeserializeOwned
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
<Tx as Transaction>::Hash: std::cmp::Ord + Debug + Send + Sync + 'static,
|
||||||
|
S: StorageSerde + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
let BlocksByDepthQueryParams { from, depth } = query;
|
||||||
|
// get the from block
|
||||||
|
let from = match storage::block_req::<S, Tx>(&store, from).await {
|
||||||
|
Ok(from) => match from {
|
||||||
|
Some(from) => from,
|
||||||
|
None => {
|
||||||
|
return IntoResponse::into_response((StatusCode::NOT_FOUND, "from block not found"))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
return IntoResponse::into_response((StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut current = Some(from.header().parent());
|
||||||
|
let mut blocks = Vec::new();
|
||||||
|
while blocks.len() < depth {
|
||||||
|
if let Some(id) = current {
|
||||||
|
let block = match storage::block_req::<S, Tx>(&store, id).await {
|
||||||
|
Ok(block) => block,
|
||||||
|
Err(e) => {
|
||||||
|
return IntoResponse::into_response((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
e.to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match block {
|
||||||
|
Some(block) => {
|
||||||
|
current = Some(block.header().parent());
|
||||||
|
blocks.push(block);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
current = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IntoResponse::into_response((StatusCode::OK, ::axum::Json(blocks)))
|
||||||
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@ impl StorageTransaction for SledTransaction {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sled storage backend
|
/// Sled storage backend
|
||||||
|
|
||||||
pub struct SledBackend<SerdeOp> {
|
pub struct SledBackend<SerdeOp> {
|
||||||
sled: sled::Db,
|
sled: sled::Db,
|
||||||
_serde_op: PhantomData<SerdeOp>,
|
_serde_op: PhantomData<SerdeOp>,
|
||||||
|
|
|
@ -136,16 +136,16 @@ impl<Backend: StorageBackend> StorageMsg<Backend> {
|
||||||
impl<Backend: StorageBackend> Debug for StorageMsg<Backend> {
|
impl<Backend: StorageBackend> Debug for StorageMsg<Backend> {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
StorageMsg::Load { key, .. } => {
|
Self::Load { key, .. } => {
|
||||||
write!(f, "Load {{ {key:?} }}")
|
write!(f, "Load {{ {key:?} }}")
|
||||||
}
|
}
|
||||||
StorageMsg::Store { key, value } => {
|
Self::Store { key, value } => {
|
||||||
write!(f, "Store {{ {key:?}, {value:?}}}")
|
write!(f, "Store {{ {key:?}, {value:?}}}")
|
||||||
}
|
}
|
||||||
StorageMsg::Remove { key, .. } => {
|
Self::Remove { key, .. } => {
|
||||||
write!(f, "Remove {{ {key:?} }}")
|
write!(f, "Remove {{ {key:?} }}")
|
||||||
}
|
}
|
||||||
StorageMsg::Execute { .. } => write!(f, "Execute transaction"),
|
Self::Execute { .. } => write!(f, "Execute transaction"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue