massa_consensus_exports/
block_status.rs

1use massa_models::{
2    active_block::ActiveBlock,
3    address::Address,
4    block::{Block, SecureShareBlock},
5    block_header::SecuredHeader,
6    block_id::BlockId,
7    prehash::PreHashSet,
8    slot::Slot,
9};
10use massa_storage::Storage;
11use serde::{Deserialize, Serialize};
12
13#[derive(Debug, Clone)]
14#[allow(clippy::large_enum_variant)]
15pub enum HeaderOrBlock {
16    Header(SecuredHeader),
17    Block {
18        id: BlockId,
19        slot: Slot,
20        storage: Storage,
21    },
22}
23
24impl HeaderOrBlock {
25    /// Gets slot for that header or block
26    pub fn get_slot(&self) -> Slot {
27        match self {
28            HeaderOrBlock::Header(header) => header.content.slot,
29            HeaderOrBlock::Block { slot, .. } => *slot,
30        }
31    }
32}
33
34/// Something can be discarded
35#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
36pub enum DiscardReason {
37    /// Block is invalid, either structurally, or because of some incompatibility. The String contains the reason for info or debugging.
38    Invalid(String),
39    /// Block is incompatible with a final block.
40    Stale,
41    /// Block has enough fitness.
42    Final,
43}
44
45#[derive(Debug, Clone, PartialEq, Eq)]
46pub enum BlockStatusId {
47    Incoming = 0,
48    WaitingForSlot = 1,
49    WaitingForDependencies = 2,
50    Active = 3,
51    Discarded = 4,
52}
53
54impl From<&BlockStatus> for BlockStatusId {
55    fn from(status: &BlockStatus) -> Self {
56        match status {
57            BlockStatus::Incoming(_) => BlockStatusId::Incoming,
58            BlockStatus::WaitingForSlot(_) => BlockStatusId::WaitingForSlot,
59            BlockStatus::WaitingForDependencies { .. } => BlockStatusId::WaitingForDependencies,
60            BlockStatus::Active { .. } => BlockStatusId::Active,
61            BlockStatus::Discarded { .. } => BlockStatusId::Discarded,
62        }
63    }
64}
65
66/// A structure defining whether we keep a full block with operations in storage
67/// or just the raw signed block without operations
68#[derive(Debug, Clone)]
69pub enum StorageOrBlock {
70    /// Keep a full storage with operations
71    Storage(Storage),
72    /// Keep only the block header and list of ops (but not the ops)
73    Block(Box<SecureShareBlock>),
74}
75
76impl StorageOrBlock {
77    /// Return a clone of the underlying block.
78    /// This is used when we want to get a copy of the block that is referenced by a block status
79    /// (and not a copy of the block status itself)
80    pub fn clone_block(&self, block_id: &BlockId) -> SecureShareBlock {
81        match self {
82            StorageOrBlock::Storage(storage) => storage
83                .read_blocks()
84                .get(block_id)
85                .expect("block absent from its own storage")
86                .clone(),
87            StorageOrBlock::Block(block) => *block.clone(),
88        }
89    }
90
91    /// Convert any StorageOrBlock variant into a StorageOrBlock::Block variant.
92    /// This effectively drops the operations of the block.
93    pub fn strip_to_block(&mut self, block_id: &BlockId) {
94        let block = if let StorageOrBlock::Storage(storage) = self {
95            storage
96                .read_blocks()
97                .get(block_id)
98                .expect("block absent from its own storage")
99                .clone()
100        } else {
101            return;
102        };
103        *self = StorageOrBlock::Block(Box::new(block));
104    }
105}
106
107/// Enum used in `BlockGraph`'s state machine
108#[derive(Debug, Clone)]
109pub enum BlockStatus {
110    /// The block/header has reached consensus but no consensus-level check has been performed.
111    /// It will be processed during the next iteration
112    Incoming(HeaderOrBlock),
113    /// The block's or header's slot is too much in the future.
114    /// It will be processed at the block/header slot
115    WaitingForSlot(HeaderOrBlock),
116    /// The block references an unknown Block id
117    WaitingForDependencies {
118        /// Given header/block
119        header_or_block: HeaderOrBlock,
120        /// includes self if it's only a header
121        unsatisfied_dependencies: PreHashSet<BlockId>,
122        /// Used to limit and sort the number of blocks/headers waiting for dependencies
123        sequence_number: u64,
124    },
125    /// The block was checked and included in the blockgraph
126    Active {
127        a_block: Box<ActiveBlock>,
128        storage_or_block: StorageOrBlock,
129    },
130    /// The block was discarded and is kept to avoid reprocessing it
131    Discarded {
132        /// Just the slot of that block
133        slot: Slot,
134        /// Address of the creator of the block
135        creator: Address,
136        /// Ids of parents blocks
137        parents: Vec<BlockId>,
138        /// why it was discarded
139        reason: DiscardReason,
140        /// Used to limit and sort the number of blocks/headers waiting for dependencies
141        sequence_number: u64,
142    },
143}
144
145/// Block status in the graph that can be exported.
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub enum ExportBlockStatus {
148    /// received but not yet graph processed
149    Incoming,
150    /// waiting for its slot
151    WaitingForSlot,
152    /// waiting for a missing dependency
153    WaitingForDependencies,
154    /// valid and not yet final
155    Active(Block),
156    /// immutable
157    Final(Block),
158    /// not part of the graph
159    Discarded(DiscardReason),
160}
161
162/// The block version that can be exported.
163/// Note that the detailed list of operation is not exported
164#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct ExportCompiledBlock {
166    /// Header of the corresponding block.
167    pub header: SecuredHeader,
168    /// For (i, set) in children,
169    /// set contains the headers' hashes
170    /// of blocks referencing exported block as a parent,
171    /// in thread i.
172    pub children: Vec<PreHashSet<BlockId>>,
173    /// Active or final
174    pub is_final: bool,
175}
176
177/// Status
178#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
179pub enum Status {
180    /// without enough fitness to be part of immutable history
181    Active,
182    /// with enough fitness to be part of immutable history
183    Final,
184}