subspace_gateway_rpc/
lib.rs1use jsonrpsee::core::async_trait;
4use jsonrpsee::proc_macros::rpc;
5use jsonrpsee::types::{ErrorObject, ErrorObjectOwned};
6use std::fmt;
7use std::ops::{Deref, DerefMut};
8use subspace_core_primitives::objects::GlobalObjectMapping;
9use subspace_data_retrieval::object_fetcher::{self, ObjectFetcher};
10use subspace_data_retrieval::piece_getter::PieceGetter;
11use tracing::{debug, error};
12
13const SUBSPACE_ERROR: i32 = 9000;
14
15const MAX_OBJECTS_PER_REQUEST: usize = 100;
21
22#[derive(Debug, thiserror::Error)]
24pub enum Error {
25 #[error("Mapping count {count} exceeded request limit {MAX_OBJECTS_PER_REQUEST}")]
27 TooManyMappings {
28 count: usize,
30 },
31
32 #[error(transparent)]
34 ObjectFetcherError(#[from] object_fetcher::Error),
35}
36
37impl From<Error> for ErrorObjectOwned {
38 fn from(error: Error) -> Self {
39 ErrorObject::owned(SUBSPACE_ERROR + 1, format!("{error:?}"), None::<()>)
40 }
41}
42
43#[derive(Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
45#[serde(transparent)]
46pub struct HexData {
47 #[serde(with = "hex")]
48 pub data: Vec<u8>,
49}
50
51impl fmt::Debug for HexData {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(f, "HexData({})", hex::encode(&self.data))
54 }
55}
56
57impl fmt::Display for HexData {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 write!(f, "{}", hex::encode(&self.data))
60 }
61}
62
63impl From<Vec<u8>> for HexData {
64 fn from(data: Vec<u8>) -> Self {
65 Self { data }
66 }
67}
68
69impl Deref for HexData {
70 type Target = Vec<u8>;
71
72 fn deref(&self) -> &Self::Target {
73 &self.data
74 }
75}
76
77impl DerefMut for HexData {
78 fn deref_mut(&mut self) -> &mut Self::Target {
79 &mut self.data
80 }
81}
82
83#[rpc(client, server)]
85pub trait SubspaceGatewayRpcApi {
86 #[method(name = "subspace_fetchObject")]
96 async fn fetch_object(&self, mappings: GlobalObjectMapping) -> Result<Vec<HexData>, Error>;
97}
98
99pub struct SubspaceGatewayRpcConfig<PG>
101where
102 PG: PieceGetter + Send + Sync + 'static,
103{
104 pub object_fetcher: ObjectFetcher<PG>,
106}
107
108pub struct SubspaceGatewayRpc<PG>
110where
111 PG: PieceGetter + Send + Sync + 'static,
112{
113 object_fetcher: ObjectFetcher<PG>,
115}
116
117impl<PG> SubspaceGatewayRpc<PG>
119where
120 PG: PieceGetter + Send + Sync + 'static,
121{
122 pub fn new(config: SubspaceGatewayRpcConfig<PG>) -> Self {
124 Self {
125 object_fetcher: config.object_fetcher,
126 }
127 }
128}
129
130#[async_trait]
131impl<PG> SubspaceGatewayRpcApiServer for SubspaceGatewayRpc<PG>
132where
133 PG: PieceGetter + Send + Sync + 'static,
134{
135 async fn fetch_object(&self, mappings: GlobalObjectMapping) -> Result<Vec<HexData>, Error> {
136 let count = mappings.objects().len();
137 if count > MAX_OBJECTS_PER_REQUEST {
138 debug!(%count, %MAX_OBJECTS_PER_REQUEST, "Too many mappings in request");
139 return Err(Error::TooManyMappings { count });
140 }
141
142 let objects = self.object_fetcher.fetch_objects(mappings).await?;
143 let objects = objects.into_iter().map(HexData::from).collect();
144
145 Ok(objects)
146 }
147}