subspace_gateway_rpc/
lib.rsuse jsonrpsee::core::async_trait;
use jsonrpsee::proc_macros::rpc;
use jsonrpsee::types::{ErrorObject, ErrorObjectOwned};
use std::fmt;
use std::ops::{Deref, DerefMut};
use subspace_core_primitives::objects::GlobalObjectMapping;
use subspace_data_retrieval::object_fetcher::{self, ObjectFetcher};
use subspace_data_retrieval::piece_getter::PieceGetter;
use tracing::{debug, error};
const SUBSPACE_ERROR: i32 = 9000;
const MAX_OBJECTS_PER_REQUEST: usize = 100;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Mapping count {count} exceeded request limit {MAX_OBJECTS_PER_REQUEST}")]
TooManyMappings {
count: usize,
},
#[error(transparent)]
ObjectFetcherError(#[from] object_fetcher::Error),
}
impl From<Error> for ErrorObjectOwned {
fn from(error: Error) -> Self {
ErrorObject::owned(SUBSPACE_ERROR + 1, format!("{error:?}"), None::<()>)
}
}
#[derive(Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(transparent)]
pub struct HexData {
#[serde(with = "hex")]
pub data: Vec<u8>,
}
impl fmt::Debug for HexData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "HexData({})", hex::encode(&self.data))
}
}
impl fmt::Display for HexData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode(&self.data))
}
}
impl From<Vec<u8>> for HexData {
fn from(data: Vec<u8>) -> Self {
Self { data }
}
}
impl Deref for HexData {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl DerefMut for HexData {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
#[rpc(client, server)]
pub trait SubspaceGatewayRpcApi {
#[method(name = "subspace_fetchObject")]
async fn fetch_object(&self, mappings: GlobalObjectMapping) -> Result<Vec<HexData>, Error>;
}
pub struct SubspaceGatewayRpcConfig<PG>
where
PG: PieceGetter + Send + Sync + 'static,
{
pub object_fetcher: ObjectFetcher<PG>,
}
pub struct SubspaceGatewayRpc<PG>
where
PG: PieceGetter + Send + Sync + 'static,
{
object_fetcher: ObjectFetcher<PG>,
}
impl<PG> SubspaceGatewayRpc<PG>
where
PG: PieceGetter + Send + Sync + 'static,
{
pub fn new(config: SubspaceGatewayRpcConfig<PG>) -> Self {
Self {
object_fetcher: config.object_fetcher,
}
}
}
#[async_trait]
impl<PG> SubspaceGatewayRpcApiServer for SubspaceGatewayRpc<PG>
where
PG: PieceGetter + Send + Sync + 'static,
{
async fn fetch_object(&self, mappings: GlobalObjectMapping) -> Result<Vec<HexData>, Error> {
let count = mappings.objects().len();
if count > MAX_OBJECTS_PER_REQUEST {
debug!(%count, %MAX_OBJECTS_PER_REQUEST, "Too many mappings in request");
return Err(Error::TooManyMappings { count });
}
let objects = self.object_fetcher.fetch_objects(mappings).await?;
let objects = objects.into_iter().map(HexData::from).collect();
Ok(objects)
}
}