zebra_rpc/
indexer.rs

1//! A tonic RPC server for Zebra's indexer API.
2
3use std::sync::Arc;
4
5use zebra_chain::{
6    block,
7    serialization::{ZcashDeserializeInto, ZcashSerialize},
8};
9
10#[cfg(test)]
11mod tests;
12
13pub mod methods;
14pub mod server;
15
16// The generated indexer proto
17tonic::include_proto!("zebra.indexer.rpc");
18
19pub(crate) const FILE_DESCRIPTOR_SET: &[u8] =
20    tonic::include_file_descriptor_set!("indexer_descriptor");
21
22impl BlockHashAndHeight {
23    /// Create a new [`BlockHashAndHeight`] from a [`block::Hash`] and [`block::Height`].
24    pub fn new(hash: block::Hash, block::Height(height): block::Height) -> Self {
25        let hash = hash.bytes_in_display_order().to_vec();
26        BlockHashAndHeight { hash, height }
27    }
28
29    /// Try to convert a [`BlockHashAndHeight`] into a tuple of a block hash and height.
30    pub fn try_into_hash_and_height(self) -> Option<(block::Hash, block::Height)> {
31        self.hash
32            .try_into()
33            .map(|bytes| block::Hash::from_bytes_in_display_order(&bytes))
34            .map_err(|bytes: Vec<_>| {
35                tracing::warn!(
36                    "failed to convert BlockHash to Hash, unexpected len: {}",
37                    bytes.len()
38                )
39            })
40            .ok()
41            .and_then(|hash| self.height.try_into().ok().map(|height| (hash, height)))
42    }
43}
44
45impl BlockAndHash {
46    /// Creates a new [`BlockAndHash`] from a [`block::Hash`] and [`block::Height`].
47    ///
48    /// # Panics
49    ///
50    /// This function will panic if the block serialization fails (if the header version is invalid).
51    pub fn new(hash: block::Hash, block: Arc<block::Block>) -> Self {
52        BlockAndHash {
53            hash: hash.bytes_in_display_order().to_vec(),
54            data: block
55                .zcash_serialize_to_vec()
56                .expect("block serialization should not fail"),
57        }
58    }
59
60    /// Try to convert a [`BlockAndHash`] into a tuple of a decoded block and hash.
61    pub fn decode(self) -> Option<(block::Block, block::Hash)> {
62        self.hash
63            .try_into()
64            .map(|bytes| block::Hash::from_bytes_in_display_order(&bytes))
65            .map_err(|bytes: Vec<_>| {
66                tracing::warn!(
67                    "failed to convert BlockHash to Hash, unexpected len: {}",
68                    bytes.len()
69                )
70            })
71            .ok()
72            .and_then(|hash| {
73                self.data
74                    .zcash_deserialize_into()
75                    .map_err(|err| tracing::warn!(?err, "failed to deserialize block",))
76                    .ok()
77                    .map(|block| (block, hash))
78            })
79    }
80}