diff --git a/bootstrap/src/cli.rs b/bootstrap/src/cli.rs index 30d7b22d4..8ae3138f8 100644 --- a/bootstrap/src/cli.rs +++ b/bootstrap/src/cli.rs @@ -1,4 +1,4 @@ -use clap::{command, ArgAction, Parser}; +use clap::{ArgAction, Parser}; use tracing::Level; #[derive(Parser)] diff --git a/client/src/cli.rs b/client/src/cli.rs index ee61a7a18..29fa32feb 100644 --- a/client/src/cli.rs +++ b/client/src/cli.rs @@ -2,7 +2,7 @@ use avail_light_core::{ network::{AutoNatMode, Network}, types::{KademliaMode, NetworkMode}, }; -use clap::{command, ArgAction, Parser}; +use clap::{ArgAction, Parser}; use tracing::Level; #[derive(Parser)] diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index e93227fe3..065b6b07f 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -2,6 +2,7 @@ ## [1.2.13] +- Added verified cell count query API on light client - Added put record duration histogram - Added event source and name to event count metric - Trigger maintenance on empty blocks diff --git a/core/src/api/types.rs b/core/src/api/types.rs index 23f540596..5e701acb8 100644 --- a/core/src/api/types.rs +++ b/core/src/api/types.rs @@ -58,6 +58,19 @@ impl Reply for Version { } } +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct CellCountResponse { + pub block_number: u32, + pub cell_count: u32, +} + +#[cfg(not(target_arch = "wasm32"))] +impl Reply for CellCountResponse { + fn into_response(self) -> warp::reply::Response { + warp::reply::json(&self).into_response() + } +} + #[derive(Serialize, Deserialize)] pub struct BlockRange { pub first: u32, diff --git a/core/src/api/v2/README.md b/core/src/api/v2/README.md index 84f716e58..75ed9b1e8 100644 --- a/core/src/api/v2/README.md +++ b/core/src/api/v2/README.md @@ -199,12 +199,42 @@ Content-Type: application/json ``` If **block_status** is **incomplete**, data will be empty. -If **block_status** is not **“finished”**, or **app** mode is not enabled, data is not available and the response is: +If **block_status** is not **"finished"**, or **app** mode is not enabled, data is not available and the response is: ```yaml HTTP/1.1 400 Bad Request ``` +## **GET** `/v2/blocks/{block_number}/cell-count` + +Gets the verified cell count for a specified block number. This endpoint returns the number of cells that have been successfully sampled and verified for data availability. + +If the verified cell count is available (greater than zero), the response is: + +```yaml +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "block_number": {block-number}, + "cell_count": {cell-count} +} +``` + +- **block_number** - the block number for which the cell count is requested +- **cell_count** - the number of cells that have been successfully sampled and verified for this block + +If the verified cell count is zero or not available (sampling has not completed for this block), the response is: + +```yaml +HTTP/1.1 400 Bad Request +Content-Type: application/json + +{ + "error": "Verified cell count is not available; sampling has not completed for this block" +} +``` + ## POST `/v2/submit` Submits application data to the avail network.\ diff --git a/core/src/api/v2/handlers.rs b/core/src/api/v2/handlers.rs index 3775cdb71..d2b5600e8 100644 --- a/core/src/api/v2/handlers.rs +++ b/core/src/api/v2/handlers.rs @@ -9,9 +9,9 @@ use crate::{ api::{ configuration::SharedConfig, types::{ - block_status, filter_fields, Block, BlockStatus, DataQuery, DataResponse, - DataTransaction, Error, FieldsQueryParameter, Header, Status, SubmitResponse, - Subscription, SubscriptionId, Transaction, Version, WsClients, + block_status, filter_fields, Block, BlockStatus, CellCountResponse, DataQuery, + DataResponse, DataTransaction, Error, FieldsQueryParameter, Header, Status, + SubmitResponse, Subscription, SubscriptionId, Transaction, Version, WsClients, }, }, data::{ @@ -172,3 +172,18 @@ pub async fn block_data( data_transactions, }) } + +pub async fn cell_count(block_number: u32, db: impl Database + Clone) -> Result { + if let Some(count) = db.get(VerifiedCellCountKey(block_number)) { + if count > 0 { + return Ok(CellCountResponse { + block_number, + cell_count: count, + }); + } + } + + Err(Error::bad_request_unknown( + "Verified cell count is not available; sampling has not completed for this block", + )) +} diff --git a/core/src/api/v2/mod.rs b/core/src/api/v2/mod.rs index 42b683dbf..b549047a8 100644 --- a/core/src/api/v2/mod.rs +++ b/core/src/api/v2/mod.rs @@ -96,6 +96,7 @@ pub fn routes( .or(block_route(config.clone(), db.clone())) .or(block_header_route(config.clone(), db.clone())) .or(block_data_route(config.clone(), db.clone())) + .or(cell_count_route(db.clone())) .or(subscriptions_route(ws_clients.clone())) .or(submit_route(submitter.clone())) .or(ws_route(ws_clients, version, config, submitter, db.clone())) diff --git a/core/src/api/v2/routes.rs b/core/src/api/v2/routes.rs index 0b1131599..8c30292d6 100644 --- a/core/src/api/v2/routes.rs +++ b/core/src/api/v2/routes.rs @@ -88,6 +88,16 @@ pub fn block_data_route( .map(log_internal_server_error_v2) } +pub fn cell_count_route( + db: impl Database + Clone + Send, +) -> impl Filter + Clone { + warp::path!("v2" / "blocks" / u32 / "cell-count") + .and(warp::get()) + .and(with_db(db)) + .then(handlers::cell_count) + .map(log_internal_server_error_v2) +} + pub fn submit_route( submitter: Option>, ) -> impl Filter + Clone { diff --git a/core/src/network/rpc/client.rs b/core/src/network/rpc/client.rs index 150199963..40a752aeb 100644 --- a/core/src/network/rpc/client.rs +++ b/core/src/network/rpc/client.rs @@ -44,7 +44,7 @@ use tokio_retry::Retry; #[cfg(not(target_arch = "wasm32"))] use tokio_stream::Elapsed; use tokio_stream::{StreamExt, StreamMap}; -use tracing::{error, info, warn}; +use tracing::{info, warn}; use super::{configuration::RetryConfig, Node, Nodes, Subscription, WrappedProof}; use crate::{ @@ -88,7 +88,7 @@ enum ClientCreationError { #[error("Failed to connect to any RPC node")] AllNodesFailed { #[source] - last_error: Report, + _last_error: Report, }, #[error("RPC function execution failed for host {host}: {error}")] @@ -274,7 +274,7 @@ impl Client { } Err(Report::msg(ClientCreationError::AllNodesFailed { - last_error: last_error.unwrap_or_else(|| eyre!("No error recorded")), + _last_error: last_error.unwrap_or_else(|| eyre!("No error recorded")), })) } diff --git a/crawler/src/config.rs b/crawler/src/config.rs index 76c02eef8..c6ee58833 100644 --- a/crawler/src/config.rs +++ b/crawler/src/config.rs @@ -10,7 +10,7 @@ use avail_light_core::{ telemetry::otlp::OtelConfig, types::{block_matrix_partition_format, tracing_level_format, Origin, PeerAddress}, }; -use clap::{command, Parser}; +use clap::Parser; use color_eyre::{eyre::eyre, Result}; use kate_recovery::matrix::Partition; use serde::{Deserialize, Serialize}; diff --git a/fat/src/config.rs b/fat/src/config.rs index 738a9b009..429dacf49 100644 --- a/fat/src/config.rs +++ b/fat/src/config.rs @@ -14,7 +14,7 @@ use avail_light_core::{ PeerAddress, SecretKey, }, }; -use clap::{command, Parser}; +use clap::Parser; use color_eyre::{eyre::eyre, Result}; use kate_recovery::matrix::Partition; use serde::{Deserialize, Serialize};