massa_grpc/
lib.rs

1// Copyright (c) 2023 MASSA LABS <info@massa.net>
2//
3//! ## **Overview**
4//!
5//! This Rust module is a gRPC API for providing services for the Massa blockchain.
6//! It implements gRPC services defined in the [massa_proto_rs] crate.
7//!
8//! ## **Structure**
9//!
10//! * `api.rs`: implements gRPC service methods without streams.
11//! * `handler.rs`: defines the logic for handling incoming gRPC requests.
12//! * `server`: initializes the gRPC service and serve It.
13//! * `stream/`: contains the gRPC streaming methods implementations files.
14
15#![warn(missing_docs)]
16#![warn(unused_crate_dependencies)]
17
18use error::GrpcError;
19use massa_models::slot::Slot;
20use massa_proto_rs::massa::model::v1 as grpc_model;
21use std::hash::Hash;
22use tonic_health as _;
23use tonic_reflection as _;
24use tonic_web as _;
25
26#[cfg(feature = "execution-trace")]
27use serde_json as _;
28
29/// gRPC configuration
30pub mod config;
31/// models error
32pub mod error;
33/// gRPC API implementation
34pub mod handler;
35/// business code for node management methods
36pub mod private;
37/// business code for non stream methods
38pub mod public;
39/// gRPC service initialization and serve
40pub mod server;
41/// business code for stream methods
42pub mod stream;
43
44#[cfg(test)]
45/// gRPC tests
46pub mod tests;
47
48/// Slot range type
49#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
50pub struct SlotRange {
51    // Start lot
52    start_slot: Option<Slot>,
53    // End slot
54    end_slot: Option<Slot>,
55}
56
57impl SlotRange {
58    /// Check if the slot range is valid
59    pub fn check(&self) -> Result<(), GrpcError> {
60        match (self.start_slot, self.end_slot) {
61            (None, None) => Err(GrpcError::InvalidArgument(
62                "Invalid slot range: both start slot and end slot are empty".to_string(),
63            )),
64            (Some(s_slot), Some(e_slot)) if s_slot > e_slot => {
65                Err(GrpcError::InvalidArgument(format!(
66                    "Invalid slot range: start slot {} is greater than end slot {}",
67                    s_slot, e_slot
68                )))
69            }
70            (Some(s_slot), Some(e_slot)) if e_slot < s_slot => {
71                Err(GrpcError::InvalidArgument(format!(
72                    "Invalid slot range: end slot {} is lower to start slot {}",
73                    s_slot, e_slot
74                )))
75            }
76            (Some(s_slot), Some(e_slot)) if s_slot == e_slot => {
77                Err(GrpcError::InvalidArgument(format!(
78                    "Invalid slot range: start slot {} is equal to end slot {}",
79                    s_slot, e_slot
80                )))
81            }
82            _ => Ok(()),
83        }
84    }
85}
86
87// Slot draw
88#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
89struct SlotDraw {
90    /// Slot
91    slot: Option<Slot>,
92    /// Block producer address (Optional)
93    block_producer: Option<String>,
94    /// Endorsement draws
95    endorsement_draws: Vec<EndorsementDraw>,
96}
97
98// Endorsement draw
99#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
100struct EndorsementDraw {
101    /// Endorsement index
102    index: u64,
103    /// Producer address
104    producer: String,
105}
106
107impl From<SlotDraw> for grpc_model::SlotDraw {
108    fn from(value: SlotDraw) -> Self {
109        grpc_model::SlotDraw {
110            slot: value.slot.map(Into::into),
111            block_producer: value.block_producer,
112            endorsement_draws: value
113                .endorsement_draws
114                .into_iter()
115                .map(Into::into)
116                .collect(),
117        }
118    }
119}
120
121impl From<EndorsementDraw> for grpc_model::EndorsementDraw {
122    fn from(value: EndorsementDraw) -> Self {
123        grpc_model::EndorsementDraw {
124            index: value.index,
125            producer: value.producer,
126        }
127    }
128}