consensus_types/
block.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::{
5    fmt,
6    hash::{Hash, Hasher},
7};
8
9use consensus_config::{AuthorityIndex, DIGEST_LENGTH};
10use fastcrypto::hash::Digest;
11use serde::{Deserialize, Serialize};
12
13/// Round number of a block.
14pub type Round = u32;
15
16/// Block proposal timestamp in milliseconds.
17pub type BlockTimestampMs = u64;
18
19/// Index of a transaction in a block.
20pub type TransactionIndex = u16;
21
22/// The number of reserved transaction indices.
23pub const NUM_RESERVED_TRANSACTION_INDICES: TransactionIndex = 8;
24
25/// The index of the ping transaction. This is a special type of transaction that is used in order to ping consensus and perform ping requests.
26/// We reserve the max index for this transaction.
27pub const PING_TRANSACTION_INDEX: TransactionIndex = TransactionIndex::MAX;
28
29/// `BlockRef` uniquely identifies a `VerifiedBlock` via `digest`. It also contains the slot
30/// info (round and author) so it can be used in logic such as aggregating stakes for a round.
31#[derive(Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq, PartialOrd, Ord)]
32pub struct BlockRef {
33    pub round: Round,
34    pub author: AuthorityIndex,
35    pub digest: BlockDigest,
36}
37
38impl BlockRef {
39    pub const MIN: Self = Self {
40        round: 0,
41        author: AuthorityIndex::MIN,
42        digest: BlockDigest::MIN,
43    };
44
45    pub const MAX: Self = Self {
46        round: u32::MAX,
47        author: AuthorityIndex::MAX,
48        digest: BlockDigest::MAX,
49    };
50
51    pub fn new(round: Round, author: AuthorityIndex, digest: BlockDigest) -> Self {
52        Self {
53            round,
54            author,
55            digest,
56        }
57    }
58}
59
60impl fmt::Display for BlockRef {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
62        write!(f, "B{}({},{})", self.round, self.author, self.digest)
63    }
64}
65
66impl fmt::Debug for BlockRef {
67    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
68        write!(f, "B{}({},{:?})", self.round, self.author, self.digest)
69    }
70}
71
72impl Hash for BlockRef {
73    fn hash<H: Hasher>(&self, state: &mut H) {
74        state.write(&self.digest.0[..8]);
75    }
76}
77
78/// Digest of a `VerifiedBlock` or verified `SignedBlock`, which covers the `Block` and its
79/// signature.
80///
81/// Note: the signature algorithm is assumed to be non-malleable, so it is impossible for another
82/// party to create an altered but valid signature, producing an equivocating `BlockDigest`.
83#[derive(Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq, PartialOrd, Ord)]
84pub struct BlockDigest(pub [u8; consensus_config::DIGEST_LENGTH]);
85
86impl BlockDigest {
87    /// Lexicographic min & max digest.
88    pub const MIN: Self = Self([u8::MIN; consensus_config::DIGEST_LENGTH]);
89    pub const MAX: Self = Self([u8::MAX; consensus_config::DIGEST_LENGTH]);
90}
91
92impl Hash for BlockDigest {
93    fn hash<H: Hasher>(&self, state: &mut H) {
94        state.write(&self.0[..8]);
95    }
96}
97
98impl From<BlockDigest> for Digest<{ DIGEST_LENGTH }> {
99    fn from(hd: BlockDigest) -> Self {
100        Digest::new(hd.0)
101    }
102}
103
104impl fmt::Display for BlockDigest {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
106        write!(
107            f,
108            "{}",
109            base64::Engine::encode(&base64::engine::general_purpose::STANDARD, self.0)
110                .get(0..4)
111                .ok_or(fmt::Error)?
112        )
113    }
114}
115
116impl fmt::Debug for BlockDigest {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
118        write!(
119            f,
120            "{}",
121            base64::Engine::encode(&base64::engine::general_purpose::STANDARD, self.0)
122        )
123    }
124}
125
126impl AsRef<[u8]> for BlockDigest {
127    fn as_ref(&self) -> &[u8] {
128        &self.0
129    }
130}