sc_rpc_spec_v2/bitswap/
bitswap.rs1use crate::bitswap::{api::BitswapApiServer, error::Error};
24use cid::Cid;
25use jsonrpsee::core::RpcResult;
26use multihash_codetable::Code;
27use sc_client_api::BlockBackend;
28use sp_core::H256;
29use sp_runtime::traits::Block as BlockT;
30use std::sync::Arc;
31
32const LOG_TARGET: &str = "rpc-spec-v2";
34
35pub struct Bitswap<Block, Client> {
37 client: Arc<Client>,
38 sync_oracle: Arc<dyn sp_consensus::SyncOracle + Send + Sync>,
39 _phantom: std::marker::PhantomData<Block>,
40}
41
42impl<Block, Client> Bitswap<Block, Client> {
43 pub fn new(
45 client: Arc<Client>,
46 sync_oracle: Arc<dyn sp_consensus::SyncOracle + Send + Sync>,
47 ) -> Self {
48 Self { client, sync_oracle, _phantom: std::marker::PhantomData }
49 }
50}
51
52impl<Block, Client> BitswapApiServer for Bitswap<Block, Client>
53where
54 Block: BlockT,
55 Client: BlockBackend<Block> + Send + Sync + 'static,
56{
57 fn bitswap_v1_get(&self, cid_str: String) -> RpcResult<String> {
58 let cid = Cid::try_from(cid_str.as_str()).map_err(|e| Error::InvalidCid(format!("{e}")))?;
59
60 if cid.version() != cid::Version::V1 {
62 return Err(Error::InvalidCid("Only CIDv1 is supported".into()).into());
63 }
64
65 let hash = cid.hash();
66
67 if hash.code() != u64::from(Code::Sha2_256) &&
70 hash.code() != u64::from(Code::Blake2b256) &&
71 hash.code() != u64::from(Code::Keccak256)
72 {
73 return Err(Error::InvalidCid(
74 "Only sha2-256, blake2b-256 & keccak-256 hash functions are supported".into(),
75 )
76 .into());
77 }
78
79 if hash.size() != 32 {
82 return Err(Error::InvalidCid("Only 256-bit hash digests are supported".into()).into());
83 }
84
85 let digest = H256::from_slice(hash.digest());
86
87 match self.client.indexed_transaction(digest) {
88 Ok(Some(data)) => Ok(crate::hex_string(&data)),
89 Ok(None) => {
90 if self.sync_oracle.is_major_syncing() {
91 Err(Error::MajorSyncing.into())
92 } else {
93 Err(Error::NotFound.into())
94 }
95 },
96 Err(err) => {
97 log::warn!(target: LOG_TARGET, "Indexed transaction fetch failed: {err:?}");
101
102 Err(Error::Internal(err).into())
103 },
104 }
105 }
106}