casper_client/types/
block.rs

1pub mod v1;
2pub mod v2;
3
4use std::fmt::{self, Display, Formatter};
5
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8
9use casper_hashing::Digest;
10use casper_types::{
11    bytesrepr::{self, ToBytes},
12    crypto::PublicKey,
13    EraId, ProtocolVersion,
14};
15
16#[cfg(doc)]
17use crate::types::{validate_block_hashes_v1, validate_block_hashes_v2};
18use crate::types::{DeployHash, EraEnd, Proof, Timestamp};
19
20/// A cryptographic hash uniquely identifying a [`Block`].
21///
22/// # Note
23///
24/// The type of this field is currently the same for all versions of blocks, and furthermore it is
25/// always a hash over the block's header.  However, *how* the hash is calculated can be different.
26///
27/// There are two separate functions to allow for validation of the block given the different
28/// hash mechanisms: [`validate_block_hashes_v1`] and [`validate_block_hashes_v2`].
29#[derive(
30    Copy,
31    Clone,
32    Default,
33    PartialOrd,
34    Ord,
35    PartialEq,
36    Eq,
37    Hash,
38    Serialize,
39    Deserialize,
40    Debug,
41    JsonSchema,
42)]
43#[serde(deny_unknown_fields)]
44pub struct BlockHash(Digest);
45
46impl BlockHash {
47    /// Returns a new `BlockHash`.
48    pub fn new(digest: Digest) -> Self {
49        BlockHash(digest)
50    }
51
52    /// Returns a copy of the wrapped `Digest`.
53    pub fn inner(&self) -> Digest {
54        self.0
55    }
56}
57
58impl Display for BlockHash {
59    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
60        write!(formatter, "{}", self.0)
61    }
62}
63
64impl ToBytes for BlockHash {
65    fn write_bytes(&self, buffer: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
66        self.0.write_bytes(buffer)
67    }
68
69    fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
70        self.0.to_bytes()
71    }
72
73    fn serialized_length(&self) -> usize {
74        self.0.serialized_length()
75    }
76}
77
78/// The header portion of a [`Block`].
79#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)]
80#[serde(deny_unknown_fields)]
81pub struct BlockHeader {
82    parent_hash: BlockHash,
83    state_root_hash: Digest,
84    body_hash: Digest,
85    random_bit: bool,
86    accumulated_seed: Digest,
87    era_end: Option<EraEnd>,
88    timestamp: Timestamp,
89    era_id: EraId,
90    height: u64,
91    protocol_version: ProtocolVersion,
92}
93
94impl BlockHeader {
95    /// Returns the parent block's hash.
96    pub fn parent_hash(&self) -> BlockHash {
97        self.parent_hash
98    }
99
100    /// Returns the root hash of global state after executing the deploys in this block.
101    pub fn state_root_hash(&self) -> Digest {
102        self.state_root_hash
103    }
104
105    /// Returns the hash of the body of this block.
106    ///
107    /// # Note
108    ///
109    /// See [`validate_block_hashes_v1`] and [`validate_block_hashes_v2`] for further details on the
110    /// different ways in which this hash can be calculated.
111    pub fn body_hash(&self) -> Digest {
112        self.body_hash
113    }
114
115    /// Returns the random bit held in this block.
116    pub fn random_bit(&self) -> bool {
117        self.random_bit
118    }
119
120    /// Returns the accumulated seed held in this block.
121    pub fn accumulated_seed(&self) -> Digest {
122        self.accumulated_seed
123    }
124
125    /// Returns the `EraEnd`, where `Some` means this is a "switch block", i.e. the final block of
126    /// the specified era.
127    pub fn era_end(&self) -> Option<&EraEnd> {
128        self.era_end.as_ref()
129    }
130
131    /// Returns the creation timestamp of this block.
132    pub fn timestamp(&self) -> Timestamp {
133        self.timestamp
134    }
135
136    /// Returns the ID of the era in which this block belongs.
137    pub fn era_id(&self) -> EraId {
138        self.era_id
139    }
140
141    /// Returns the height of the block in the blockchain.
142    pub fn height(&self) -> u64 {
143        self.height
144    }
145
146    /// Returns the protocol version of the network at the time this block was created.
147    pub fn protocol_version(&self) -> ProtocolVersion {
148        self.protocol_version
149    }
150}
151
152impl Display for BlockHeader {
153    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
154        write!(
155            formatter,
156            "block header {{ parent hash {}, post-state hash {}, body hash {}, \
157            random bit {}, accumulated seed {}, timestamp {} }}",
158            self.parent_hash.0,
159            self.state_root_hash,
160            self.body_hash,
161            self.random_bit,
162            self.accumulated_seed,
163            self.timestamp,
164        )?;
165        if let Some(era_end) = &self.era_end {
166            write!(formatter, ", era_end {}", era_end)?;
167        }
168        Ok(())
169    }
170}
171
172impl ToBytes for BlockHeader {
173    fn write_bytes(&self, buffer: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
174        self.parent_hash.write_bytes(buffer)?;
175        self.state_root_hash.write_bytes(buffer)?;
176        self.body_hash.write_bytes(buffer)?;
177        self.random_bit.write_bytes(buffer)?;
178        self.accumulated_seed.write_bytes(buffer)?;
179        self.era_end.write_bytes(buffer)?;
180        self.timestamp.write_bytes(buffer)?;
181        self.era_id.write_bytes(buffer)?;
182        self.height.write_bytes(buffer)?;
183        self.protocol_version.write_bytes(buffer)
184    }
185
186    fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
187        let mut buffer = vec![];
188        self.write_bytes(&mut buffer)?;
189        Ok(buffer)
190    }
191
192    fn serialized_length(&self) -> usize {
193        self.parent_hash.serialized_length()
194            + self.state_root_hash.serialized_length()
195            + self.body_hash.serialized_length()
196            + self.random_bit.serialized_length()
197            + self.accumulated_seed.serialized_length()
198            + self.era_end.serialized_length()
199            + self.timestamp.serialized_length()
200            + self.era_id.serialized_length()
201            + self.height.serialized_length()
202            + self.protocol_version.serialized_length()
203    }
204}
205
206/// The body portion of a block.
207#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)]
208#[serde(deny_unknown_fields)]
209pub struct BlockBody {
210    proposer: PublicKey,
211    deploy_hashes: Vec<DeployHash>,
212    transfer_hashes: Vec<DeployHash>,
213}
214
215impl BlockBody {
216    /// Returns the public key of the validator which proposed this block.
217    pub fn proposer(&self) -> &PublicKey {
218        &self.proposer
219    }
220
221    /// Returns the hashes of all non-transfer deploys included in this block.
222    pub fn deploy_hashes(&self) -> impl Iterator<Item = &DeployHash> {
223        self.deploy_hashes.iter()
224    }
225
226    /// Returns the hashes of all transfers included in this block.
227    pub fn transfer_hashes(&self) -> impl Iterator<Item = &DeployHash> {
228        self.transfer_hashes.iter()
229    }
230}
231
232impl Display for BlockBody {
233    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
234        write!(formatter, "{:?}", self)
235    }
236}
237
238impl ToBytes for BlockBody {
239    fn write_bytes(&self, buffer: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
240        self.proposer.write_bytes(buffer)?;
241        self.deploy_hashes.write_bytes(buffer)?;
242        self.transfer_hashes.write_bytes(buffer)
243    }
244
245    fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
246        let mut buffer = vec![];
247        self.write_bytes(&mut buffer)?;
248        Ok(buffer)
249    }
250
251    fn serialized_length(&self) -> usize {
252        self.proposer.serialized_length()
253            + self.deploy_hashes.serialized_length()
254            + self.transfer_hashes.serialized_length()
255    }
256}
257
258/// A block; the core component of the Casper linear blockchain.
259#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)]
260#[serde(deny_unknown_fields)]
261pub struct Block {
262    hash: BlockHash,
263    header: BlockHeader,
264    body: BlockBody,
265    proofs: Vec<Proof>,
266}
267
268impl Block {
269    /// Returns the hash uniquely identifying this block.
270    ///
271    /// # Note
272    ///
273    /// See [`validate_block_hashes_v1`] and [`validate_block_hashes_v2`] for further details on the
274    /// different ways in which this hash can be calculated.
275    pub fn hash(&self) -> &BlockHash {
276        &self.hash
277    }
278
279    /// Returns the header portion of the block.
280    pub fn header(&self) -> &BlockHeader {
281        &self.header
282    }
283
284    /// Returns the body portion of the block.
285    pub fn body(&self) -> &BlockBody {
286        &self.body
287    }
288
289    /// Returns the proofs; the public keys and signatures of the validators which signed the block.
290    pub fn proofs(&self) -> impl Iterator<Item = &Proof> {
291        self.proofs.iter()
292    }
293}
294
295impl Display for Block {
296    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
297        write!(
298            formatter,
299            "block {{ {}, parent hash {}, post-state hash {}, body hash {}, \
300             random bit {}, timestamp {}, {}, height {}, protocol version: {} }}",
301            self.hash,
302            self.header.parent_hash,
303            self.header.state_root_hash,
304            self.header.body_hash,
305            self.header.random_bit,
306            self.header.timestamp,
307            self.header.era_id,
308            self.header.height,
309            self.header.protocol_version
310        )?;
311        if let Some(era_end) = &self.header.era_end {
312            write!(formatter, ", era-end: {}", era_end)?;
313        }
314        Ok(())
315    }
316}
317
318impl ToBytes for Block {
319    fn write_bytes(&self, buffer: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
320        // Note: the proofs are deliberately not part of the bytesrepr serialized block.
321        self.hash.write_bytes(buffer)?;
322        self.header.write_bytes(buffer)?;
323        self.body.write_bytes(buffer)
324    }
325
326    fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
327        let mut buffer = vec![];
328        self.write_bytes(&mut buffer)?;
329        Ok(buffer)
330    }
331
332    fn serialized_length(&self) -> usize {
333        self.hash.serialized_length()
334            + self.header.serialized_length()
335            + self.body.serialized_length()
336    }
337}
338
339/// Describes a block's hash and height.
340#[derive(Clone, Copy, Default, Eq, JsonSchema, Serialize, Deserialize, Debug, PartialEq)]
341pub struct BlockHashAndHeight {
342    /// The hash of the block.
343    #[schemars(description = "The hash of this deploy's block.")]
344    pub block_hash: BlockHash,
345    /// The height of the block.
346    #[schemars(description = "The height of this deploy's block.")]
347    pub block_height: u64,
348}