1use byteorder::BigEndian;
2use serde::{Deserialize, Serialize};
3use sled::{Db, Tree};
4use std::fmt;
5use std::hash::Hash;
6use subxt::utils::H256;
7use tokio::sync::mpsc::UnboundedSender;
8use tokio_tungstenite::tungstenite;
9use zerocopy::{
10 AsBytes,
11 byteorder::{U16, U32},
12};
13use zerocopy_derive::*;
14
15#[derive(thiserror::Error, Debug)]
17pub enum IndexError {
18 #[error("database error")]
19 Sled(#[from] sled::Error),
20 #[error("connection error")]
21 Subxt(#[from] subxt::Error),
22 #[error("connection error")]
23 Tungstenite(#[from] tungstenite::Error),
24 #[error("parse error")]
25 Hex(#[from] hex::FromHexError),
26 #[error("parse error")]
27 ParseError,
28 #[error("connection error")]
29 BlockNotFound(u32),
30 #[error("RPC error")]
31 RpcError(#[from] subxt::ext::subxt_rpcs::Error),
32 #[error("codec error")]
33 CodecError(#[from] subxt::ext::codec::Error),
34 #[error("metadata error")]
35 MetadataError(#[from] subxt::error::MetadataTryFromError),
36}
37
38pub trait RuntimeIndexer {
40 type RuntimeConfig: subxt::Config;
41 type ChainKey: IndexKey
42 + Serialize
43 + for<'a> Deserialize<'a>
44 + Clone
45 + Eq
46 + PartialEq
47 + Hash
48 + Send;
49
50 fn get_name() -> &'static str;
51
52 fn get_genesis_hash() -> H256;
53
54 fn get_versions() -> &'static [u32];
55
56 fn get_default_url() -> &'static str;
57
58 fn process_event(
59 indexer: &crate::Indexer<Self>,
60 block_number: u32,
61 event_index: u16,
62 event: subxt::events::EventDetails<Self::RuntimeConfig>,
63 ) -> Result<u32, IndexError>;
64}
65
66pub trait IndexTrees {
67 fn open(db: &Db) -> Result<Self, sled::Error>
68 where
69 Self: Sized;
70 fn flush(&self) -> Result<(), sled::Error>;
71}
72
73#[derive(Clone)]
75pub struct SubstrateTrees {
76 pub account_id: Tree,
77 pub account_index: Tree,
78 pub bounty_index: Tree,
79 pub era_index: Tree,
80 pub message_id: Tree,
81 pub pool_id: Tree,
82 pub preimage_hash: Tree,
83 pub proposal_hash: Tree,
84 pub proposal_index: Tree,
85 pub ref_index: Tree,
86 pub registrar_index: Tree,
87 pub session_index: Tree,
88 pub tip_hash: Tree,
89 pub spend_index: Tree,
90}
91
92impl SubstrateTrees {
93 pub fn open(db: &Db) -> Result<Self, sled::Error> {
94 Ok(SubstrateTrees {
95 account_id: db.open_tree(b"account_id")?,
96 account_index: db.open_tree(b"account_index")?,
97 bounty_index: db.open_tree(b"bounty_index")?,
98 era_index: db.open_tree(b"era_index")?,
99 message_id: db.open_tree(b"message_id")?,
100 pool_id: db.open_tree(b"pool_id")?,
101 preimage_hash: db.open_tree(b"preimage_hash")?,
102 proposal_hash: db.open_tree(b"proposal_hash")?,
103 proposal_index: db.open_tree(b"proposal_index")?,
104 ref_index: db.open_tree(b"ref_index")?,
105 registrar_index: db.open_tree(b"registrar_index")?,
106 session_index: db.open_tree(b"session_index")?,
107 tip_hash: db.open_tree(b"tip_hash")?,
108 spend_index: db.open_tree(b"spend_index")?,
109 })
110 }
111
112 pub fn flush(&self) -> Result<(), sled::Error> {
113 self.account_id.flush()?;
114 self.account_index.flush()?;
115 self.bounty_index.flush()?;
116 self.era_index.flush()?;
117 self.message_id.flush()?;
118 self.pool_id.flush()?;
119 self.preimage_hash.flush()?;
120 self.proposal_hash.flush()?;
121 self.proposal_index.flush()?;
122 self.ref_index.flush()?;
123 self.registrar_index.flush()?;
124 self.session_index.flush()?;
125 self.tip_hash.flush()?;
126 self.spend_index.flush()?;
127 Ok(())
128 }
129}
130
131#[derive(Clone)]
133pub struct Trees<CT> {
134 pub root: sled::Db,
135 pub span: Tree,
136 pub variant: Tree,
137 pub substrate: SubstrateTrees,
138 pub chain: CT,
139 pub block_events: Tree,
140}
141
142#[derive(FromZeroes, FromBytes, AsBytes, Unaligned, PartialEq, Debug)]
144#[repr(C)]
145pub struct VariantKey {
146 pub pallet_index: u8,
147 pub variant_index: u8,
148 pub block_number: U32<BigEndian>,
149 pub event_index: U16<BigEndian>,
150}
151
152#[derive(FromZeroes, FromBytes, AsBytes, Unaligned, PartialEq, Debug)]
154#[repr(C)]
155pub struct Bytes32Key {
156 pub key: [u8; 32],
157 pub block_number: U32<BigEndian>,
158 pub event_index: U16<BigEndian>,
159}
160
161#[derive(FromZeroes, FromBytes, AsBytes, Unaligned, PartialEq, Debug)]
163#[repr(C)]
164pub struct U32Key {
165 pub key: U32<BigEndian>,
166 pub block_number: U32<BigEndian>,
167 pub event_index: U16<BigEndian>,
168}
169
170#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
172pub struct Bytes32(pub [u8; 32]);
173
174impl AsRef<[u8; 32]> for Bytes32 {
175 fn as_ref(&self) -> &[u8; 32] {
176 &self.0
177 }
178}
179
180impl From<[u8; 32]> for Bytes32 {
181 fn from(x: [u8; 32]) -> Self {
182 Bytes32(x)
183 }
184}
185
186impl AsRef<[u8]> for Bytes32 {
187 fn as_ref(&self) -> &[u8] {
188 &self.0[..]
189 }
190}
191
192impl Serialize for Bytes32 {
193 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
194 where
195 S: serde::Serializer,
196 {
197 let mut hex_string = "0x".to_owned();
198 hex_string.push_str(&hex::encode(self.0));
199 serializer.serialize_str(&hex_string)
200 }
201}
202
203impl<'de> Deserialize<'de> for Bytes32 {
204 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
205 where
206 D: serde::Deserializer<'de>,
207 {
208 match String::deserialize(deserializer)?.get(2..66) {
209 Some(message_id) => match hex::decode(message_id) {
210 Ok(message_id) => Ok(Bytes32(message_id.try_into().unwrap())),
211 Err(_error) => Err(serde::de::Error::custom("error")),
212 },
213 None => Err(serde::de::Error::custom("error")),
214 }
215 }
216}
217
218impl std::str::FromStr for Bytes32 {
219 type Err = IndexError;
220
221 fn from_str(s: &str) -> Result<Self, Self::Err> {
222 Ok(Bytes32(
223 hex::decode(s)?
224 .try_into()
225 .map_err(|_| IndexError::ParseError)?,
226 ))
227 }
228}
229
230#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Hash)]
232#[serde(tag = "type", content = "value")]
233pub enum SubstrateKey {
234 AccountId(Bytes32),
235 AccountIndex(u32),
236 BountyIndex(u32),
237 EraIndex(u32),
238 MessageId(Bytes32),
239 PoolId(u32),
240 PreimageHash(Bytes32),
241 ProposalHash(Bytes32),
242 ProposalIndex(u32),
243 RefIndex(u32),
244 RegistrarIndex(u32),
245 SessionIndex(u32),
246 TipHash(Bytes32),
247 SpendIndex(u32),
248}
249
250impl SubstrateKey {
251 pub fn write_db_key(
252 &self,
253 trees: &SubstrateTrees,
254 block_number: u32,
255 event_index: u16,
256 ) -> Result<(), sled::Error> {
257 let block_number = block_number.into();
258 let event_index = event_index.into();
259 match self {
260 SubstrateKey::AccountId(account_id) => {
261 let key = Bytes32Key {
262 key: account_id.0,
263 block_number,
264 event_index,
265 };
266 trees.account_id.insert(key.as_bytes(), &[])?
267 }
268 SubstrateKey::AccountIndex(account_index) => {
269 let key = U32Key {
270 key: (*account_index).into(),
271 block_number,
272 event_index,
273 };
274 trees.account_index.insert(key.as_bytes(), &[])?
275 }
276 SubstrateKey::BountyIndex(bounty_index) => {
277 let key = U32Key {
278 key: (*bounty_index).into(),
279 block_number,
280 event_index,
281 };
282 trees.bounty_index.insert(key.as_bytes(), &[])?
283 }
284 SubstrateKey::EraIndex(era_index) => {
285 let key = U32Key {
286 key: (*era_index).into(),
287 block_number,
288 event_index,
289 };
290 trees.era_index.insert(key.as_bytes(), &[])?
291 }
292 SubstrateKey::MessageId(message_id) => {
293 let key = Bytes32Key {
294 key: message_id.0,
295 block_number,
296 event_index,
297 };
298 trees.message_id.insert(key.as_bytes(), &[])?
299 }
300 SubstrateKey::PoolId(pool_id) => {
301 let key = U32Key {
302 key: (*pool_id).into(),
303 block_number,
304 event_index,
305 };
306 trees.pool_id.insert(key.as_bytes(), &[])?
307 }
308 SubstrateKey::PreimageHash(preimage_hash) => {
309 let key = Bytes32Key {
310 key: preimage_hash.0,
311 block_number,
312 event_index,
313 };
314 trees.preimage_hash.insert(key.as_bytes(), &[])?
315 }
316 SubstrateKey::ProposalHash(proposal_hash) => {
317 let key = Bytes32Key {
318 key: proposal_hash.0,
319 block_number,
320 event_index,
321 };
322 trees.proposal_hash.insert(key.as_bytes(), &[])?
323 }
324 SubstrateKey::ProposalIndex(proposal_index) => {
325 let key = U32Key {
326 key: (*proposal_index).into(),
327 block_number,
328 event_index,
329 };
330 trees.proposal_index.insert(key.as_bytes(), &[])?
331 }
332 SubstrateKey::RefIndex(ref_index) => {
333 let key = U32Key {
334 key: (*ref_index).into(),
335 block_number,
336 event_index,
337 };
338 trees.ref_index.insert(key.as_bytes(), &[])?
339 }
340 SubstrateKey::RegistrarIndex(registrar_index) => {
341 let key = U32Key {
342 key: (*registrar_index).into(),
343 block_number,
344 event_index,
345 };
346 trees.registrar_index.insert(key.as_bytes(), &[])?
347 }
348 SubstrateKey::SessionIndex(session_index) => {
349 let key = U32Key {
350 key: (*session_index).into(),
351 block_number,
352 event_index,
353 };
354 trees.session_index.insert(key.as_bytes(), &[])?
355 }
356 SubstrateKey::TipHash(tip_hash) => {
357 let key = Bytes32Key {
358 key: tip_hash.0,
359 block_number,
360 event_index,
361 };
362 trees.tip_hash.insert(key.as_bytes(), &[])?
363 }
364 SubstrateKey::SpendIndex(spend_index) => {
365 let key = U32Key {
366 key: (*spend_index).into(),
367 block_number,
368 event_index,
369 };
370 trees.spend_index.insert(key.as_bytes(), &[])?
371 }
372 };
373 Ok(())
374 }
375}
376
377pub trait IndexKey {
378 type ChainTrees: IndexTrees + Send + Sync + Clone;
379
380 fn write_db_key(
381 &self,
382 trees: &Self::ChainTrees,
383 block_number: u32,
384 event_index: u16,
385 ) -> Result<(), sled::Error>;
386
387 fn get_key_events(&self, trees: &Self::ChainTrees) -> Vec<Event>;
388}
389
390#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Hash)]
392#[serde(tag = "type", content = "value")]
393pub enum Key<CK: IndexKey> {
394 Variant(u8, u8),
395 Substrate(SubstrateKey),
396 Chain(CK),
397}
398
399impl<CK: IndexKey> Key<CK> {
400 pub fn write_db_key(
401 &self,
402 trees: &Trees<CK::ChainTrees>,
403 block_number: u32,
404 event_index: u16,
405 ) -> Result<(), sled::Error> {
406 match self {
407 Key::Variant(pallet_index, variant_index) => {
408 let key = VariantKey {
409 pallet_index: *pallet_index,
410 variant_index: *variant_index,
411 block_number: block_number.into(),
412 event_index: event_index.into(),
413 };
414 trees.variant.insert(key.as_bytes(), &[])?;
415 }
416 Key::Substrate(substrate_key) => {
417 substrate_key.write_db_key(&trees.substrate, block_number, event_index)?;
418 }
419 Key::Chain(chain_key) => {
420 chain_key.write_db_key(&trees.chain, block_number, event_index)?;
421 }
422 };
423 Ok(())
424 }
425}
426
427#[derive(Deserialize, Debug, Clone)]
429#[serde(tag = "type")]
430pub enum RequestMessage<CK: IndexKey> {
431 Status,
432 SubscribeStatus,
433 UnsubscribeStatus,
434 Variants,
435 GetEvents { key: Key<CK> },
436 SubscribeEvents { key: Key<CK> },
437 UnsubscribeEvents { key: Key<CK> },
438 SizeOnDisk,
439}
440
441#[derive(Serialize, Debug, Clone, Deserialize, PartialEq)]
443#[serde(rename_all = "camelCase")]
444pub struct Event {
445 pub block_number: u32,
446 pub event_index: u16,
447}
448
449#[derive(Serialize, Debug, Clone, Deserialize, PartialEq)]
450#[serde(rename_all = "camelCase")]
451pub struct Block {
452 pub block_number: u32,
453 pub bytes: Vec<u8>,
454}
455
456impl fmt::Display for Event {
457 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
458 write!(
459 f,
460 "block number: {}, event index: {}",
461 self.block_number, self.event_index
462 )
463 }
464}
465
466#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
468pub struct EventMeta {
469 pub index: u8,
470 pub name: String,
471}
472
473#[derive(Serialize, Debug, Clone, Deserialize, PartialEq)]
475pub struct PalletMeta {
476 pub index: u8,
477 pub name: String,
478 pub events: Vec<EventMeta>,
479}
480
481#[derive(FromZeroes, FromBytes, AsBytes, Unaligned, PartialEq, Debug)]
483#[repr(C)]
484pub struct SpanDbValue {
485 pub start: U32<BigEndian>,
486 pub version: U16<BigEndian>,
487 pub index_variant: u8,
488 pub store_events: u8,
489}
490
491#[derive(Serialize, Debug, Clone, PartialEq, Deserialize)]
493pub struct Span {
494 pub start: u32,
495 pub end: u32,
496}
497
498impl fmt::Display for Span {
499 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
500 write!(f, "start: {}, end: {}", self.start, self.end)
501 }
502}
503
504#[derive(Serialize, Debug, Clone)]
506#[serde(tag = "type", content = "data")]
507#[serde(rename_all = "camelCase")]
508pub enum ResponseMessage<CK: IndexKey> {
509 Status(Vec<Span>),
510 Variants(Vec<PalletMeta>),
511 Events {
512 key: Key<CK>,
513 events: Vec<Event>,
514 block_events: Vec<Block>,
515 },
516 Subscribed,
517 Unsubscribed,
518 SizeOnDisk(u64),
519 }
521
522#[derive(Debug)]
524pub enum SubscriptionMessage<CK: IndexKey> {
525 SubscribeStatus {
526 sub_response_tx: UnboundedSender<ResponseMessage<CK>>,
527 },
528 UnsubscribeStatus {
529 sub_response_tx: UnboundedSender<ResponseMessage<CK>>,
530 },
531 SubscribeEvents {
532 key: Key<CK>,
533 sub_response_tx: UnboundedSender<ResponseMessage<CK>>,
534 },
535 UnsubscribeEvents {
536 key: Key<CK>,
537 sub_response_tx: UnboundedSender<ResponseMessage<CK>>,
538 },
539}