near_primitives/
block_header.rs

1use crate::challenge::SlashedValidator;
2use crate::hash::{CryptoHash, hash};
3use crate::merkle::combine_hash;
4use crate::network::PeerId;
5use crate::stateless_validation::chunk_endorsements_bitmap::ChunkEndorsementsBitmap;
6use crate::types::validator_stake::{ValidatorStake, ValidatorStakeIter, ValidatorStakeV1};
7use crate::types::{AccountId, Balance, BlockHeight, EpochId, MerkleHash, NumBlocks};
8use crate::validator_signer::ValidatorSigner;
9use crate::version::ProtocolVersion;
10use borsh::{BorshDeserialize, BorshSerialize};
11use near_crypto::{KeyType, PublicKey, Signature};
12use near_schema_checker_lib::ProtocolSchema;
13use near_time::Utc;
14
15#[derive(
16    BorshSerialize,
17    BorshDeserialize,
18    serde::Serialize,
19    Debug,
20    Clone,
21    Eq,
22    PartialEq,
23    Default,
24    ProtocolSchema,
25)]
26pub struct BlockHeaderInnerLite {
27    /// Height of this block.
28    pub height: BlockHeight,
29    /// Epoch start hash of this block's epoch.
30    /// Used for retrieving validator information
31    pub epoch_id: EpochId,
32    pub next_epoch_id: EpochId,
33    /// Root hash of the state at the previous block.
34    pub prev_state_root: MerkleHash,
35    /// Root of the outcomes of transactions and receipts from the previous chunks.
36    pub prev_outcome_root: MerkleHash,
37    /// Timestamp at which the block was built (number of non-leap-nanoseconds since January 1, 1970 0:00:00 UTC).
38    pub timestamp: u64,
39    /// Hash of the next epoch block producers set
40    pub next_bp_hash: CryptoHash,
41    /// Merkle root of block hashes up to the current block.
42    pub block_merkle_root: CryptoHash,
43}
44
45#[derive(
46    BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, Eq, PartialEq, ProtocolSchema,
47)]
48pub struct BlockHeaderInnerRest {
49    /// Root hash of the previous chunks' outgoing receipts in the given block.
50    pub prev_chunk_outgoing_receipts_root: MerkleHash,
51    /// Root hash of the chunk headers in the given block.
52    pub chunk_headers_root: MerkleHash,
53    /// Root hash of the chunk transactions in the given block.
54    pub chunk_tx_root: MerkleHash,
55    /// Number of chunks included into the block.
56    pub chunks_included: u64,
57    /// Root hash of the challenges in the given block.
58    #[deprecated]
59    pub challenges_root: MerkleHash,
60    /// The output of the randomness beacon
61    pub random_value: CryptoHash,
62    /// Validator proposals from the previous chunks.
63    pub prev_validator_proposals: Vec<ValidatorStakeV1>,
64    /// Mask for new chunks included in the block
65    pub chunk_mask: Vec<bool>,
66    /// Gas price for chunks in the next block.
67    pub next_gas_price: Balance,
68    /// Total supply of tokens in the system
69    pub total_supply: Balance,
70    /// List of challenges result from previous block.
71    #[deprecated]
72    pub challenges_result: Vec<SlashedValidator>,
73
74    /// Last block that has full BFT finality
75    pub last_final_block: CryptoHash,
76    /// Last block that has doomslug finality
77    pub last_ds_final_block: CryptoHash,
78
79    /// All the approvals included in this block
80    pub approvals: Vec<Option<Box<Signature>>>,
81
82    /// Latest protocol version that this block producer has.
83    pub latest_protocol_version: ProtocolVersion,
84}
85
86/// Remove `chunks_included` from V1
87#[derive(
88    BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, Eq, PartialEq, ProtocolSchema,
89)]
90pub struct BlockHeaderInnerRestV2 {
91    /// Root hash of the previous chunks' outgoing receipts in the given block.
92    pub prev_chunk_outgoing_receipts_root: MerkleHash,
93    /// Root hash of the chunk headers in the given block.
94    pub chunk_headers_root: MerkleHash,
95    /// Root hash of the chunk transactions in the given block.
96    pub chunk_tx_root: MerkleHash,
97    /// Root hash of the challenges in the given block.
98    #[deprecated]
99    pub challenges_root: MerkleHash,
100    /// The output of the randomness beacon
101    pub random_value: CryptoHash,
102    /// Validator proposals from the previous chunks.
103    pub prev_validator_proposals: Vec<ValidatorStakeV1>,
104    /// Mask for new chunks included in the block
105    pub chunk_mask: Vec<bool>,
106    /// Gas price for chunks in the next block.
107    pub next_gas_price: Balance,
108    /// Total supply of tokens in the system
109    pub total_supply: Balance,
110    /// List of challenges result from previous block.
111    #[deprecated]
112    pub challenges_result: Vec<SlashedValidator>,
113
114    /// Last block that has full BFT finality
115    pub last_final_block: CryptoHash,
116    /// Last block that has doomslug finality
117    pub last_ds_final_block: CryptoHash,
118
119    /// All the approvals included in this block
120    pub approvals: Vec<Option<Box<Signature>>>,
121
122    /// Latest protocol version that this block producer has.
123    pub latest_protocol_version: ProtocolVersion,
124}
125
126/// Add `prev_height`
127/// Add `block_ordinal`
128/// Add `epoch_sync_data_hash`
129/// Use new `ValidatorStake` struct
130#[derive(
131    BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, Eq, PartialEq, ProtocolSchema,
132)]
133pub struct BlockHeaderInnerRestV3 {
134    /// Root hash of the previous chunks' outgoing receipts in the given block.
135    pub prev_chunk_outgoing_receipts_root: MerkleHash,
136    /// Root hash of the chunk headers in the given block.
137    pub chunk_headers_root: MerkleHash,
138    /// Root hash of the chunk transactions in the given block.
139    pub chunk_tx_root: MerkleHash,
140    /// Root hash of the challenges in the given block.
141    #[deprecated]
142    pub challenges_root: MerkleHash,
143    /// The output of the randomness beacon
144    pub random_value: CryptoHash,
145    /// Validator proposals from the previous chunks.
146    pub prev_validator_proposals: Vec<ValidatorStake>,
147    /// Mask for new chunks included in the block
148    pub chunk_mask: Vec<bool>,
149    /// Gas price for chunks in the next block.
150    pub next_gas_price: Balance,
151    /// Total supply of tokens in the system
152    pub total_supply: Balance,
153    /// List of challenges result from previous block.
154    #[deprecated]
155    pub challenges_result: Vec<SlashedValidator>,
156
157    /// Last block that has full BFT finality
158    pub last_final_block: CryptoHash,
159    /// Last block that has doomslug finality
160    pub last_ds_final_block: CryptoHash,
161
162    /// The ordinal of the Block on the Canonical Chain
163    pub block_ordinal: NumBlocks,
164
165    pub prev_height: BlockHeight,
166
167    pub epoch_sync_data_hash: Option<CryptoHash>,
168
169    /// All the approvals included in this block
170    pub approvals: Vec<Option<Box<Signature>>>,
171
172    /// Latest protocol version that this block producer has.
173    pub latest_protocol_version: ProtocolVersion,
174}
175
176/// Add `block_body_hash`
177#[derive(
178    BorshSerialize,
179    BorshDeserialize,
180    serde::Serialize,
181    Debug,
182    Clone,
183    Eq,
184    PartialEq,
185    Default,
186    ProtocolSchema,
187)]
188pub struct BlockHeaderInnerRestV4 {
189    /// Hash of block body
190    pub block_body_hash: CryptoHash,
191    /// Root hash of the previous chunks' outgoing receipts in the given block.
192    pub prev_chunk_outgoing_receipts_root: MerkleHash,
193    /// Root hash of the chunk headers in the given block.
194    pub chunk_headers_root: MerkleHash,
195    /// Root hash of the chunk transactions in the given block.
196    pub chunk_tx_root: MerkleHash,
197    /// Root hash of the challenges in the given block.
198    #[deprecated]
199    pub challenges_root: MerkleHash,
200    /// The output of the randomness beacon
201    pub random_value: CryptoHash,
202    /// Validator proposals from the previous chunks.
203    pub prev_validator_proposals: Vec<ValidatorStake>,
204    /// Mask for new chunks included in the block
205    pub chunk_mask: Vec<bool>,
206    /// Gas price for chunks in the next block.
207    pub next_gas_price: Balance,
208    /// Total supply of tokens in the system
209    pub total_supply: Balance,
210    /// List of challenges result from previous block.
211    #[deprecated]
212    pub challenges_result: Vec<SlashedValidator>,
213
214    /// Last block that has full BFT finality
215    pub last_final_block: CryptoHash,
216    /// Last block that has doomslug finality
217    pub last_ds_final_block: CryptoHash,
218
219    /// The ordinal of the Block on the Canonical Chain
220    pub block_ordinal: NumBlocks,
221
222    pub prev_height: BlockHeight,
223
224    pub epoch_sync_data_hash: Option<CryptoHash>,
225
226    /// All the approvals included in this block
227    pub approvals: Vec<Option<Box<Signature>>>,
228
229    /// Latest protocol version that this block producer has.
230    pub latest_protocol_version: ProtocolVersion,
231}
232
233/// Add `chunk_endorsements`
234#[derive(
235    BorshSerialize,
236    BorshDeserialize,
237    serde::Serialize,
238    Debug,
239    Clone,
240    Eq,
241    PartialEq,
242    Default,
243    ProtocolSchema,
244)]
245pub struct BlockHeaderInnerRestV5 {
246    /// Hash of block body
247    pub block_body_hash: CryptoHash,
248    /// Root hash of the previous chunks' outgoing receipts in the given block.
249    pub prev_chunk_outgoing_receipts_root: MerkleHash,
250    /// Root hash of the chunk headers in the given block.
251    pub chunk_headers_root: MerkleHash,
252    /// Root hash of the chunk transactions in the given block.
253    pub chunk_tx_root: MerkleHash,
254    /// Root hash of the challenges in the given block.
255    #[deprecated]
256    pub challenges_root: MerkleHash,
257    /// The output of the randomness beacon
258    pub random_value: CryptoHash,
259    /// Validator proposals from the previous chunks.
260    pub prev_validator_proposals: Vec<ValidatorStake>,
261    /// Mask for new chunks included in the block
262    pub chunk_mask: Vec<bool>,
263    /// Gas price for chunks in the next block.
264    pub next_gas_price: Balance,
265    /// Total supply of tokens in the system
266    pub total_supply: Balance,
267    /// List of challenges result from previous block.
268    #[deprecated]
269    pub challenges_result: Vec<SlashedValidator>,
270
271    /// Last block that has full BFT finality
272    pub last_final_block: CryptoHash,
273    /// Last block that has doomslug finality
274    pub last_ds_final_block: CryptoHash,
275
276    /// The ordinal of the Block on the Canonical Chain
277    pub block_ordinal: NumBlocks,
278
279    pub prev_height: BlockHeight,
280
281    pub epoch_sync_data_hash: Option<CryptoHash>,
282
283    /// All the approvals included in this block
284    pub approvals: Vec<Option<Box<Signature>>>,
285
286    /// Latest protocol version that this block producer has.
287    pub latest_protocol_version: ProtocolVersion,
288
289    pub chunk_endorsements: ChunkEndorsementsBitmap,
290}
291
292/// The part of the block approval that is different for endorsements and skips
293#[derive(
294    BorshSerialize,
295    BorshDeserialize,
296    serde::Serialize,
297    Debug,
298    Clone,
299    PartialEq,
300    Eq,
301    Hash,
302    ProtocolSchema,
303)]
304#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
305pub enum ApprovalInner {
306    Endorsement(CryptoHash),
307    Skip(BlockHeight),
308}
309
310/// Block approval by other block producers with a signature
311#[derive(
312    BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, PartialEq, Eq, ProtocolSchema,
313)]
314pub struct Approval {
315    pub inner: ApprovalInner,
316    pub target_height: BlockHeight,
317    pub signature: Signature,
318    pub account_id: AccountId,
319}
320
321/// The type of approvals. It is either approval from self or from a peer
322#[derive(PartialEq, Eq, Debug)]
323pub enum ApprovalType {
324    SelfApproval,
325    PeerApproval(PeerId),
326}
327
328/// Block approval by other block producers.
329#[derive(
330    BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, PartialEq, Eq, ProtocolSchema,
331)]
332pub struct ApprovalMessage {
333    pub approval: Approval,
334    pub target: AccountId,
335}
336
337impl ApprovalInner {
338    pub fn new(
339        parent_hash: &CryptoHash,
340        parent_height: BlockHeight,
341        target_height: BlockHeight,
342    ) -> Self {
343        if target_height == parent_height + 1 {
344            ApprovalInner::Endorsement(*parent_hash)
345        } else {
346            ApprovalInner::Skip(parent_height)
347        }
348    }
349}
350
351impl Approval {
352    pub fn new(
353        parent_hash: CryptoHash,
354        parent_height: BlockHeight,
355        target_height: BlockHeight,
356        signer: &ValidatorSigner,
357    ) -> Self {
358        let inner = ApprovalInner::new(&parent_hash, parent_height, target_height);
359
360        let signature = signer.sign_bytes(&Approval::get_data_for_sig(&inner, target_height));
361        Approval { inner, target_height, signature, account_id: signer.validator_id().clone() }
362    }
363
364    pub fn get_data_for_sig(inner: &ApprovalInner, target_height: BlockHeight) -> Vec<u8> {
365        [borsh::to_vec(&inner).unwrap().as_ref(), target_height.to_le_bytes().as_ref()].concat()
366    }
367}
368
369impl ApprovalMessage {
370    pub fn new(approval: Approval, target: AccountId) -> Self {
371        ApprovalMessage { approval, target }
372    }
373}
374
375#[derive(
376    BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, Eq, PartialEq, ProtocolSchema,
377)]
378#[borsh(init=init)]
379pub struct BlockHeaderV1 {
380    pub prev_hash: CryptoHash,
381
382    /// Inner part of the block header that gets hashed, split into two parts, one that is sent
383    ///    to light clients, and the rest
384    pub inner_lite: BlockHeaderInnerLite,
385    pub inner_rest: BlockHeaderInnerRest,
386
387    /// Signature of the block producer.
388    pub signature: Signature,
389
390    /// Cached value of hash for this block.
391    #[borsh(skip)]
392    pub hash: CryptoHash,
393}
394
395impl BlockHeaderV1 {
396    pub fn init(&mut self) {
397        self.hash = BlockHeader::compute_hash(
398            self.prev_hash,
399            &borsh::to_vec(&self.inner_lite).expect("Failed to serialize"),
400            &borsh::to_vec(&self.inner_rest).expect("Failed to serialize"),
401        );
402    }
403}
404
405/// V1 -> V2: Remove `chunks_included` from `inner_reset`
406#[derive(
407    BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, Eq, PartialEq, ProtocolSchema,
408)]
409#[borsh(init=init)]
410pub struct BlockHeaderV2 {
411    pub prev_hash: CryptoHash,
412
413    /// Inner part of the block header that gets hashed, split into two parts, one that is sent
414    ///    to light clients, and the rest
415    pub inner_lite: BlockHeaderInnerLite,
416    pub inner_rest: BlockHeaderInnerRestV2,
417
418    /// Signature of the block producer.
419    pub signature: Signature,
420
421    /// Cached value of hash for this block.
422    #[borsh(skip)]
423    pub hash: CryptoHash,
424}
425
426/// V2 -> V3: Add `prev_height` to `inner_rest` and use new `ValidatorStake`
427// Add `block_ordinal` to `inner_rest`
428#[derive(
429    BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, Eq, PartialEq, ProtocolSchema,
430)]
431#[borsh(init=init)]
432pub struct BlockHeaderV3 {
433    pub prev_hash: CryptoHash,
434
435    /// Inner part of the block header that gets hashed, split into two parts, one that is sent
436    ///    to light clients, and the rest
437    pub inner_lite: BlockHeaderInnerLite,
438    pub inner_rest: BlockHeaderInnerRestV3,
439
440    /// Signature of the block producer.
441    pub signature: Signature,
442
443    /// Cached value of hash for this block.
444    #[borsh(skip)]
445    pub hash: CryptoHash,
446}
447
448/// V3 -> V4: Add hash of block body to inner_rest
449#[derive(
450    BorshSerialize,
451    BorshDeserialize,
452    serde::Serialize,
453    Debug,
454    Clone,
455    Eq,
456    PartialEq,
457    Default,
458    ProtocolSchema,
459)]
460#[borsh(init=init)]
461pub struct BlockHeaderV4 {
462    pub prev_hash: CryptoHash,
463
464    /// Inner part of the block header that gets hashed, split into two parts, one that is sent
465    ///    to light clients, and the rest
466    pub inner_lite: BlockHeaderInnerLite,
467    pub inner_rest: BlockHeaderInnerRestV4,
468
469    /// Signature of the block producer.
470    pub signature: Signature,
471
472    /// Cached value of hash for this block.
473    #[borsh(skip)]
474    pub hash: CryptoHash,
475}
476
477/// V4 -> V5: Add chunk_endorsements to inner_rest
478#[derive(
479    BorshSerialize,
480    BorshDeserialize,
481    serde::Serialize,
482    Debug,
483    Clone,
484    Eq,
485    PartialEq,
486    Default,
487    ProtocolSchema,
488)]
489#[borsh(init=init)]
490pub struct BlockHeaderV5 {
491    pub prev_hash: CryptoHash,
492
493    /// Inner part of the block header that gets hashed, split into two parts, one that is sent
494    ///    to light clients, and the rest
495    pub inner_lite: BlockHeaderInnerLite,
496    pub inner_rest: BlockHeaderInnerRestV5,
497
498    /// Signature of the block producer.
499    pub signature: Signature,
500
501    /// Cached value of hash for this block.
502    #[borsh(skip)]
503    pub hash: CryptoHash,
504}
505
506impl BlockHeaderV2 {
507    pub fn init(&mut self) {
508        self.hash = BlockHeader::compute_hash(
509            self.prev_hash,
510            &borsh::to_vec(&self.inner_lite).expect("Failed to serialize"),
511            &borsh::to_vec(&self.inner_rest).expect("Failed to serialize"),
512        );
513    }
514}
515
516impl BlockHeaderV3 {
517    pub fn init(&mut self) {
518        self.hash = BlockHeader::compute_hash(
519            self.prev_hash,
520            &borsh::to_vec(&self.inner_lite).expect("Failed to serialize"),
521            &borsh::to_vec(&self.inner_rest).expect("Failed to serialize"),
522        );
523    }
524}
525
526impl BlockHeaderV4 {
527    pub fn init(&mut self) {
528        self.hash = BlockHeader::compute_hash(
529            self.prev_hash,
530            &borsh::to_vec(&self.inner_lite).expect("Failed to serialize"),
531            &borsh::to_vec(&self.inner_rest).expect("Failed to serialize"),
532        );
533    }
534}
535
536impl BlockHeaderV5 {
537    pub fn init(&mut self) {
538        self.hash = BlockHeader::compute_hash(
539            self.prev_hash,
540            &borsh::to_vec(&self.inner_lite).expect("Failed to serialize"),
541            &borsh::to_vec(&self.inner_rest).expect("Failed to serialize"),
542        );
543    }
544}
545
546/// Used in the BlockHeader::new_impl to specify the source of the block header signature.
547enum SignatureSource<'a> {
548    /// Use the given signer to sign a new block header.
549    /// This variant is used only when some features are enabled. There is a warning
550    /// because it's unused in the default configuration, where the features are disabled.
551    #[allow(dead_code)]
552    Signer(&'a ValidatorSigner),
553    /// Use a previously-computed signature (for reconstructing an already-produced block header).
554    Signature(Signature),
555}
556
557/// Versioned BlockHeader data structure.
558/// For each next version, document what are the changes between versions.
559#[derive(
560    BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, Eq, PartialEq, ProtocolSchema,
561)]
562pub enum BlockHeader {
563    BlockHeaderV1(BlockHeaderV1),
564    BlockHeaderV2(BlockHeaderV2),
565    BlockHeaderV3(BlockHeaderV3),
566    BlockHeaderV4(BlockHeaderV4),
567    BlockHeaderV5(BlockHeaderV5),
568}
569
570impl BlockHeader {
571    pub fn compute_inner_hash(inner_lite: &[u8], inner_rest: &[u8]) -> CryptoHash {
572        let hash_lite = hash(inner_lite);
573        let hash_rest = hash(inner_rest);
574        combine_hash(&hash_lite, &hash_rest)
575    }
576
577    pub fn compute_hash(prev_hash: CryptoHash, inner_lite: &[u8], inner_rest: &[u8]) -> CryptoHash {
578        let hash_inner = BlockHeader::compute_inner_hash(inner_lite, inner_rest);
579
580        combine_hash(&hash_inner, &prev_hash)
581    }
582
583    /// Creates BlockHeader for a newly produced block.
584    pub fn new(
585        latest_protocol_version: ProtocolVersion,
586        height: BlockHeight,
587        prev_hash: CryptoHash,
588        block_body_hash: CryptoHash,
589        prev_state_root: MerkleHash,
590        prev_chunk_outgoing_receipts_root: MerkleHash,
591        chunk_headers_root: MerkleHash,
592        chunk_tx_root: MerkleHash,
593        outcome_root: MerkleHash,
594        timestamp: u64,
595        random_value: CryptoHash,
596        prev_validator_proposals: Vec<ValidatorStake>,
597        chunk_mask: Vec<bool>,
598        block_ordinal: NumBlocks,
599        epoch_id: EpochId,
600        next_epoch_id: EpochId,
601        next_gas_price: Balance,
602        total_supply: Balance,
603        signer: &ValidatorSigner,
604        last_final_block: CryptoHash,
605        last_ds_final_block: CryptoHash,
606        epoch_sync_data_hash: Option<CryptoHash>,
607        approvals: Vec<Option<Box<Signature>>>,
608        next_bp_hash: CryptoHash,
609        block_merkle_root: CryptoHash,
610        prev_height: BlockHeight,
611        chunk_endorsements: Option<ChunkEndorsementsBitmap>,
612    ) -> Self {
613        Self::new_impl(
614            latest_protocol_version,
615            height,
616            prev_hash,
617            block_body_hash,
618            prev_state_root,
619            prev_chunk_outgoing_receipts_root,
620            chunk_headers_root,
621            chunk_tx_root,
622            outcome_root,
623            timestamp,
624            random_value,
625            prev_validator_proposals,
626            chunk_mask,
627            block_ordinal,
628            epoch_id,
629            next_epoch_id,
630            next_gas_price,
631            total_supply,
632            SignatureSource::Signer(signer),
633            last_final_block,
634            last_ds_final_block,
635            epoch_sync_data_hash,
636            approvals,
637            next_bp_hash,
638            block_merkle_root,
639            prev_height,
640            chunk_endorsements,
641        )
642    }
643
644    /// Creates a new BlockHeader from information in the view of an existing block.
645    pub fn from_view(
646        expected_hash: &CryptoHash,
647        epoch_protocol_version: ProtocolVersion,
648        height: BlockHeight,
649        prev_hash: CryptoHash,
650        block_body_hash: CryptoHash,
651        prev_state_root: MerkleHash,
652        prev_chunk_outgoing_receipts_root: MerkleHash,
653        chunk_headers_root: MerkleHash,
654        chunk_tx_root: MerkleHash,
655        outcome_root: MerkleHash,
656        timestamp: u64,
657        random_value: CryptoHash,
658        prev_validator_proposals: Vec<ValidatorStake>,
659        chunk_mask: Vec<bool>,
660        block_ordinal: NumBlocks,
661        epoch_id: EpochId,
662        next_epoch_id: EpochId,
663        next_gas_price: Balance,
664        total_supply: Balance,
665        signature: Signature,
666        last_final_block: CryptoHash,
667        last_ds_final_block: CryptoHash,
668        epoch_sync_data_hash: Option<CryptoHash>,
669        approvals: Vec<Option<Box<Signature>>>,
670        next_bp_hash: CryptoHash,
671        block_merkle_root: CryptoHash,
672        prev_height: BlockHeight,
673        chunk_endorsements: Option<ChunkEndorsementsBitmap>,
674    ) -> Self {
675        let header = Self::new_impl(
676            epoch_protocol_version,
677            height,
678            prev_hash,
679            block_body_hash,
680            prev_state_root,
681            prev_chunk_outgoing_receipts_root,
682            chunk_headers_root,
683            chunk_tx_root,
684            outcome_root,
685            timestamp,
686            random_value,
687            prev_validator_proposals,
688            chunk_mask,
689            block_ordinal,
690            epoch_id,
691            next_epoch_id,
692            next_gas_price,
693            total_supply,
694            SignatureSource::Signature(signature),
695            last_final_block,
696            last_ds_final_block,
697            epoch_sync_data_hash,
698            approvals,
699            next_bp_hash,
700            block_merkle_root,
701            prev_height,
702            chunk_endorsements,
703        );
704        // Note: We do not panic but only log if the hash of the created header does not match the expected hash (From the view)
705        // because there are tests that check if we can downgrade a BlockHeader's view a previous version, in which case the hash
706        // of the header changes.
707        if header.hash() != expected_hash {
708            tracing::debug!(height, header_hash=?header.hash(), ?expected_hash, "Hash of the created header does not match expected hash");
709        }
710        header
711    }
712
713    /// Common logic for generating BlockHeader for different purposes, including new blocks, from views, and for genesis block
714    fn new_impl(
715        latest_protocol_version: ProtocolVersion,
716        height: BlockHeight,
717        prev_hash: CryptoHash,
718        block_body_hash: CryptoHash,
719        prev_state_root: MerkleHash,
720        prev_chunk_outgoing_receipts_root: MerkleHash,
721        chunk_headers_root: MerkleHash,
722        chunk_tx_root: MerkleHash,
723        outcome_root: MerkleHash,
724        timestamp: u64,
725        random_value: CryptoHash,
726        prev_validator_proposals: Vec<ValidatorStake>,
727        chunk_mask: Vec<bool>,
728        block_ordinal: NumBlocks,
729        epoch_id: EpochId,
730        next_epoch_id: EpochId,
731        next_gas_price: Balance,
732        total_supply: Balance,
733        signature_source: SignatureSource,
734        last_final_block: CryptoHash,
735        last_ds_final_block: CryptoHash,
736        epoch_sync_data_hash: Option<CryptoHash>,
737        approvals: Vec<Option<Box<Signature>>>,
738        next_bp_hash: CryptoHash,
739        block_merkle_root: CryptoHash,
740        prev_height: BlockHeight,
741        chunk_endorsements: Option<ChunkEndorsementsBitmap>,
742    ) -> Self {
743        let inner_lite = BlockHeaderInnerLite {
744            height,
745            epoch_id,
746            next_epoch_id,
747            prev_state_root,
748            prev_outcome_root: outcome_root,
749            timestamp,
750            next_bp_hash,
751            block_merkle_root,
752        };
753
754        let chunk_endorsements = chunk_endorsements.unwrap_or_else(|| {
755            panic!("BlockHeaderV5 is enabled but chunk endorsement bitmap is not provided")
756        });
757        #[allow(deprecated)]
758        let inner_rest = BlockHeaderInnerRestV5 {
759            block_body_hash,
760            prev_chunk_outgoing_receipts_root,
761            chunk_headers_root,
762            chunk_tx_root,
763            challenges_root: CryptoHash::default(),
764            random_value,
765            prev_validator_proposals,
766            chunk_mask,
767            next_gas_price,
768            block_ordinal,
769            total_supply,
770            challenges_result: vec![],
771            last_final_block,
772            last_ds_final_block,
773            prev_height,
774            epoch_sync_data_hash,
775            approvals,
776            latest_protocol_version,
777            chunk_endorsements,
778        };
779        let (hash, signature) =
780            Self::compute_hash_and_sign(signature_source, prev_hash, &inner_lite, &inner_rest);
781        Self::BlockHeaderV5(BlockHeaderV5 { prev_hash, inner_lite, inner_rest, signature, hash })
782    }
783
784    /// Helper function for `new_impl` and `old_impl` to compute the hash and signature of the hash from the block header parts.
785    /// Exactly one of the `signer` and `signature` must be provided.
786    /// If `signer` is given signs the header with given `prev_hash`, `inner_lite`, and `inner_rest` and returns the hash and signature of the header.
787    /// If `signature` is given, uses the signature as is and only computes the hash.
788    fn compute_hash_and_sign<T>(
789        signature_source: SignatureSource,
790        prev_hash: CryptoHash,
791        inner_lite: &BlockHeaderInnerLite,
792        inner_rest: &T,
793    ) -> (CryptoHash, Signature)
794    where
795        T: BorshSerialize + ?Sized,
796    {
797        let hash = BlockHeader::compute_hash(
798            prev_hash,
799            &borsh::to_vec(&inner_lite).expect("Failed to serialize"),
800            &borsh::to_vec(&inner_rest).expect("Failed to serialize"),
801        );
802        match signature_source {
803            SignatureSource::Signer(signer) => (hash, signer.sign_bytes(hash.as_ref())),
804            SignatureSource::Signature(signature) => (hash, signature),
805        }
806    }
807
808    pub fn genesis(
809        genesis_protocol_version: ProtocolVersion,
810        height: BlockHeight,
811        state_root: MerkleHash,
812        block_body_hash: CryptoHash,
813        prev_chunk_outgoing_receipts_root: MerkleHash,
814        chunk_headers_root: MerkleHash,
815        chunk_tx_root: MerkleHash,
816        num_shards: u64,
817        timestamp: Utc,
818        initial_gas_price: Balance,
819        initial_total_supply: Balance,
820        next_bp_hash: CryptoHash,
821    ) -> Self {
822        let chunks_included = if height == 0 { num_shards } else { 0 };
823        Self::new_impl(
824            genesis_protocol_version,
825            height,
826            CryptoHash::default(), // prev_hash
827            block_body_hash,
828            state_root,
829            prev_chunk_outgoing_receipts_root,
830            chunk_headers_root,
831            chunk_tx_root,
832            CryptoHash::default(), // prev_outcome_root
833            timestamp.unix_timestamp_nanos() as u64,
834            CryptoHash::default(),                // random_value
835            vec![],                               // prev_validator_proposals
836            vec![true; chunks_included as usize], // chunk_mask
837            1, // block_ordinal. It is guaranteed that Chain has the only Block which is Genesis
838            EpochId::default(), // epoch_id
839            EpochId::default(), // next_epoch_id
840            initial_gas_price,
841            initial_total_supply,
842            SignatureSource::Signature(Signature::empty(KeyType::ED25519)),
843            CryptoHash::default(), // last_final_block
844            CryptoHash::default(), // last_ds_final_block
845            None,   // epoch_sync_data_hash. Epoch Sync cannot be executed up to Genesis
846            vec![], // approvals
847            next_bp_hash,
848            CryptoHash::default(), // block_merkle_root,
849            0,                     // prev_height
850            Some(ChunkEndorsementsBitmap::genesis()),
851        )
852    }
853
854    #[inline]
855    pub fn is_genesis(&self) -> bool {
856        self.prev_hash() == &CryptoHash::default()
857    }
858
859    #[inline]
860    pub fn hash(&self) -> &CryptoHash {
861        match self {
862            BlockHeader::BlockHeaderV1(header) => &header.hash,
863            BlockHeader::BlockHeaderV2(header) => &header.hash,
864            BlockHeader::BlockHeaderV3(header) => &header.hash,
865            BlockHeader::BlockHeaderV4(header) => &header.hash,
866            BlockHeader::BlockHeaderV5(header) => &header.hash,
867        }
868    }
869
870    #[inline]
871    pub fn prev_hash(&self) -> &CryptoHash {
872        match self {
873            BlockHeader::BlockHeaderV1(header) => &header.prev_hash,
874            BlockHeader::BlockHeaderV2(header) => &header.prev_hash,
875            BlockHeader::BlockHeaderV3(header) => &header.prev_hash,
876            BlockHeader::BlockHeaderV4(header) => &header.prev_hash,
877            BlockHeader::BlockHeaderV5(header) => &header.prev_hash,
878        }
879    }
880
881    #[inline]
882    pub fn signature(&self) -> &Signature {
883        match self {
884            BlockHeader::BlockHeaderV1(header) => &header.signature,
885            BlockHeader::BlockHeaderV2(header) => &header.signature,
886            BlockHeader::BlockHeaderV3(header) => &header.signature,
887            BlockHeader::BlockHeaderV4(header) => &header.signature,
888            BlockHeader::BlockHeaderV5(header) => &header.signature,
889        }
890    }
891
892    #[inline]
893    pub fn height(&self) -> BlockHeight {
894        match self {
895            BlockHeader::BlockHeaderV1(header) => header.inner_lite.height,
896            BlockHeader::BlockHeaderV2(header) => header.inner_lite.height,
897            BlockHeader::BlockHeaderV3(header) => header.inner_lite.height,
898            BlockHeader::BlockHeaderV4(header) => header.inner_lite.height,
899            BlockHeader::BlockHeaderV5(header) => header.inner_lite.height,
900        }
901    }
902
903    #[inline]
904    pub fn prev_height(&self) -> Option<BlockHeight> {
905        match self {
906            BlockHeader::BlockHeaderV1(_) => None,
907            BlockHeader::BlockHeaderV2(_) => None,
908            BlockHeader::BlockHeaderV3(header) => Some(header.inner_rest.prev_height),
909            BlockHeader::BlockHeaderV4(header) => Some(header.inner_rest.prev_height),
910            BlockHeader::BlockHeaderV5(header) => Some(header.inner_rest.prev_height),
911        }
912    }
913
914    #[inline]
915    pub fn epoch_id(&self) -> &EpochId {
916        match self {
917            BlockHeader::BlockHeaderV1(header) => &header.inner_lite.epoch_id,
918            BlockHeader::BlockHeaderV2(header) => &header.inner_lite.epoch_id,
919            BlockHeader::BlockHeaderV3(header) => &header.inner_lite.epoch_id,
920            BlockHeader::BlockHeaderV4(header) => &header.inner_lite.epoch_id,
921            BlockHeader::BlockHeaderV5(header) => &header.inner_lite.epoch_id,
922        }
923    }
924
925    #[inline]
926    pub fn next_epoch_id(&self) -> &EpochId {
927        match self {
928            BlockHeader::BlockHeaderV1(header) => &header.inner_lite.next_epoch_id,
929            BlockHeader::BlockHeaderV2(header) => &header.inner_lite.next_epoch_id,
930            BlockHeader::BlockHeaderV3(header) => &header.inner_lite.next_epoch_id,
931            BlockHeader::BlockHeaderV4(header) => &header.inner_lite.next_epoch_id,
932            BlockHeader::BlockHeaderV5(header) => &header.inner_lite.next_epoch_id,
933        }
934    }
935
936    #[inline]
937    pub fn prev_state_root(&self) -> &MerkleHash {
938        match self {
939            BlockHeader::BlockHeaderV1(header) => &header.inner_lite.prev_state_root,
940            BlockHeader::BlockHeaderV2(header) => &header.inner_lite.prev_state_root,
941            BlockHeader::BlockHeaderV3(header) => &header.inner_lite.prev_state_root,
942            BlockHeader::BlockHeaderV4(header) => &header.inner_lite.prev_state_root,
943            BlockHeader::BlockHeaderV5(header) => &header.inner_lite.prev_state_root,
944        }
945    }
946
947    #[inline]
948    pub fn prev_chunk_outgoing_receipts_root(&self) -> &MerkleHash {
949        match self {
950            BlockHeader::BlockHeaderV1(header) => {
951                &header.inner_rest.prev_chunk_outgoing_receipts_root
952            }
953            BlockHeader::BlockHeaderV2(header) => {
954                &header.inner_rest.prev_chunk_outgoing_receipts_root
955            }
956            BlockHeader::BlockHeaderV3(header) => {
957                &header.inner_rest.prev_chunk_outgoing_receipts_root
958            }
959            BlockHeader::BlockHeaderV4(header) => {
960                &header.inner_rest.prev_chunk_outgoing_receipts_root
961            }
962            BlockHeader::BlockHeaderV5(header) => {
963                &header.inner_rest.prev_chunk_outgoing_receipts_root
964            }
965        }
966    }
967
968    #[inline]
969    pub fn chunk_headers_root(&self) -> &MerkleHash {
970        match self {
971            BlockHeader::BlockHeaderV1(header) => &header.inner_rest.chunk_headers_root,
972            BlockHeader::BlockHeaderV2(header) => &header.inner_rest.chunk_headers_root,
973            BlockHeader::BlockHeaderV3(header) => &header.inner_rest.chunk_headers_root,
974            BlockHeader::BlockHeaderV4(header) => &header.inner_rest.chunk_headers_root,
975            BlockHeader::BlockHeaderV5(header) => &header.inner_rest.chunk_headers_root,
976        }
977    }
978
979    #[inline]
980    pub fn chunk_tx_root(&self) -> &MerkleHash {
981        match self {
982            BlockHeader::BlockHeaderV1(header) => &header.inner_rest.chunk_tx_root,
983            BlockHeader::BlockHeaderV2(header) => &header.inner_rest.chunk_tx_root,
984            BlockHeader::BlockHeaderV3(header) => &header.inner_rest.chunk_tx_root,
985            BlockHeader::BlockHeaderV4(header) => &header.inner_rest.chunk_tx_root,
986            BlockHeader::BlockHeaderV5(header) => &header.inner_rest.chunk_tx_root,
987        }
988    }
989
990    pub fn chunks_included(&self) -> u64 {
991        let mask = match self {
992            BlockHeader::BlockHeaderV1(header) => return header.inner_rest.chunks_included,
993            BlockHeader::BlockHeaderV2(header) => &header.inner_rest.chunk_mask,
994            BlockHeader::BlockHeaderV3(header) => &header.inner_rest.chunk_mask,
995            BlockHeader::BlockHeaderV4(header) => &header.inner_rest.chunk_mask,
996            BlockHeader::BlockHeaderV5(header) => &header.inner_rest.chunk_mask,
997        };
998        mask.iter().map(|&x| u64::from(x)).sum::<u64>()
999    }
1000
1001    #[inline]
1002    pub fn outcome_root(&self) -> &MerkleHash {
1003        match self {
1004            BlockHeader::BlockHeaderV1(header) => &header.inner_lite.prev_outcome_root,
1005            BlockHeader::BlockHeaderV2(header) => &header.inner_lite.prev_outcome_root,
1006            BlockHeader::BlockHeaderV3(header) => &header.inner_lite.prev_outcome_root,
1007            BlockHeader::BlockHeaderV4(header) => &header.inner_lite.prev_outcome_root,
1008            BlockHeader::BlockHeaderV5(header) => &header.inner_lite.prev_outcome_root,
1009        }
1010    }
1011
1012    #[inline]
1013    pub fn block_body_hash(&self) -> Option<CryptoHash> {
1014        match self {
1015            BlockHeader::BlockHeaderV1(_) => None,
1016            BlockHeader::BlockHeaderV2(_) => None,
1017            BlockHeader::BlockHeaderV3(_) => None,
1018            BlockHeader::BlockHeaderV4(header) => Some(header.inner_rest.block_body_hash),
1019            BlockHeader::BlockHeaderV5(header) => Some(header.inner_rest.block_body_hash),
1020        }
1021    }
1022
1023    #[inline]
1024    pub fn raw_timestamp(&self) -> u64 {
1025        match self {
1026            BlockHeader::BlockHeaderV1(header) => header.inner_lite.timestamp,
1027            BlockHeader::BlockHeaderV2(header) => header.inner_lite.timestamp,
1028            BlockHeader::BlockHeaderV3(header) => header.inner_lite.timestamp,
1029            BlockHeader::BlockHeaderV4(header) => header.inner_lite.timestamp,
1030            BlockHeader::BlockHeaderV5(header) => header.inner_lite.timestamp,
1031        }
1032    }
1033
1034    #[inline]
1035    pub fn prev_validator_proposals(&self) -> ValidatorStakeIter {
1036        match self {
1037            BlockHeader::BlockHeaderV1(header) => {
1038                ValidatorStakeIter::v1(&header.inner_rest.prev_validator_proposals)
1039            }
1040            BlockHeader::BlockHeaderV2(header) => {
1041                ValidatorStakeIter::v1(&header.inner_rest.prev_validator_proposals)
1042            }
1043            BlockHeader::BlockHeaderV3(header) => {
1044                ValidatorStakeIter::new(&header.inner_rest.prev_validator_proposals)
1045            }
1046            BlockHeader::BlockHeaderV4(header) => {
1047                ValidatorStakeIter::new(&header.inner_rest.prev_validator_proposals)
1048            }
1049            BlockHeader::BlockHeaderV5(header) => {
1050                ValidatorStakeIter::new(&header.inner_rest.prev_validator_proposals)
1051            }
1052        }
1053    }
1054
1055    #[inline]
1056    pub fn chunk_mask(&self) -> &[bool] {
1057        match self {
1058            BlockHeader::BlockHeaderV1(header) => &header.inner_rest.chunk_mask,
1059            BlockHeader::BlockHeaderV2(header) => &header.inner_rest.chunk_mask,
1060            BlockHeader::BlockHeaderV3(header) => &header.inner_rest.chunk_mask,
1061            BlockHeader::BlockHeaderV4(header) => &header.inner_rest.chunk_mask,
1062            BlockHeader::BlockHeaderV5(header) => &header.inner_rest.chunk_mask,
1063        }
1064    }
1065
1066    #[inline]
1067    pub fn block_ordinal(&self) -> NumBlocks {
1068        match self {
1069            BlockHeader::BlockHeaderV1(_) => 0, // not applicable
1070            BlockHeader::BlockHeaderV2(_) => 0, // not applicable
1071            BlockHeader::BlockHeaderV3(header) => header.inner_rest.block_ordinal,
1072            BlockHeader::BlockHeaderV4(header) => header.inner_rest.block_ordinal,
1073            BlockHeader::BlockHeaderV5(header) => header.inner_rest.block_ordinal,
1074        }
1075    }
1076
1077    #[inline]
1078    pub fn next_gas_price(&self) -> Balance {
1079        match self {
1080            BlockHeader::BlockHeaderV1(header) => header.inner_rest.next_gas_price,
1081            BlockHeader::BlockHeaderV2(header) => header.inner_rest.next_gas_price,
1082            BlockHeader::BlockHeaderV3(header) => header.inner_rest.next_gas_price,
1083            BlockHeader::BlockHeaderV4(header) => header.inner_rest.next_gas_price,
1084            BlockHeader::BlockHeaderV5(header) => header.inner_rest.next_gas_price,
1085        }
1086    }
1087
1088    #[inline]
1089    pub fn total_supply(&self) -> Balance {
1090        match self {
1091            BlockHeader::BlockHeaderV1(header) => header.inner_rest.total_supply,
1092            BlockHeader::BlockHeaderV2(header) => header.inner_rest.total_supply,
1093            BlockHeader::BlockHeaderV3(header) => header.inner_rest.total_supply,
1094            BlockHeader::BlockHeaderV4(header) => header.inner_rest.total_supply,
1095            BlockHeader::BlockHeaderV5(header) => header.inner_rest.total_supply,
1096        }
1097    }
1098
1099    #[inline]
1100    pub fn random_value(&self) -> &CryptoHash {
1101        match self {
1102            BlockHeader::BlockHeaderV1(header) => &header.inner_rest.random_value,
1103            BlockHeader::BlockHeaderV2(header) => &header.inner_rest.random_value,
1104            BlockHeader::BlockHeaderV3(header) => &header.inner_rest.random_value,
1105            BlockHeader::BlockHeaderV4(header) => &header.inner_rest.random_value,
1106            BlockHeader::BlockHeaderV5(header) => &header.inner_rest.random_value,
1107        }
1108    }
1109
1110    #[inline]
1111    pub fn last_final_block(&self) -> &CryptoHash {
1112        match self {
1113            BlockHeader::BlockHeaderV1(header) => &header.inner_rest.last_final_block,
1114            BlockHeader::BlockHeaderV2(header) => &header.inner_rest.last_final_block,
1115            BlockHeader::BlockHeaderV3(header) => &header.inner_rest.last_final_block,
1116            BlockHeader::BlockHeaderV4(header) => &header.inner_rest.last_final_block,
1117            BlockHeader::BlockHeaderV5(header) => &header.inner_rest.last_final_block,
1118        }
1119    }
1120
1121    #[inline]
1122    pub fn last_ds_final_block(&self) -> &CryptoHash {
1123        match self {
1124            BlockHeader::BlockHeaderV1(header) => &header.inner_rest.last_ds_final_block,
1125            BlockHeader::BlockHeaderV2(header) => &header.inner_rest.last_ds_final_block,
1126            BlockHeader::BlockHeaderV3(header) => &header.inner_rest.last_ds_final_block,
1127            BlockHeader::BlockHeaderV4(header) => &header.inner_rest.last_ds_final_block,
1128            BlockHeader::BlockHeaderV5(header) => &header.inner_rest.last_ds_final_block,
1129        }
1130    }
1131
1132    #[inline]
1133    pub fn next_bp_hash(&self) -> &CryptoHash {
1134        match self {
1135            BlockHeader::BlockHeaderV1(header) => &header.inner_lite.next_bp_hash,
1136            BlockHeader::BlockHeaderV2(header) => &header.inner_lite.next_bp_hash,
1137            BlockHeader::BlockHeaderV3(header) => &header.inner_lite.next_bp_hash,
1138            BlockHeader::BlockHeaderV4(header) => &header.inner_lite.next_bp_hash,
1139            BlockHeader::BlockHeaderV5(header) => &header.inner_lite.next_bp_hash,
1140        }
1141    }
1142
1143    #[inline]
1144    pub fn block_merkle_root(&self) -> &CryptoHash {
1145        match self {
1146            BlockHeader::BlockHeaderV1(header) => &header.inner_lite.block_merkle_root,
1147            BlockHeader::BlockHeaderV2(header) => &header.inner_lite.block_merkle_root,
1148            BlockHeader::BlockHeaderV3(header) => &header.inner_lite.block_merkle_root,
1149            BlockHeader::BlockHeaderV4(header) => &header.inner_lite.block_merkle_root,
1150            BlockHeader::BlockHeaderV5(header) => &header.inner_lite.block_merkle_root,
1151        }
1152    }
1153
1154    #[inline]
1155    pub fn epoch_sync_data_hash(&self) -> Option<CryptoHash> {
1156        match self {
1157            BlockHeader::BlockHeaderV1(_) => None,
1158            BlockHeader::BlockHeaderV2(_) => None,
1159            BlockHeader::BlockHeaderV3(header) => header.inner_rest.epoch_sync_data_hash,
1160            BlockHeader::BlockHeaderV4(header) => header.inner_rest.epoch_sync_data_hash,
1161            BlockHeader::BlockHeaderV5(header) => header.inner_rest.epoch_sync_data_hash,
1162        }
1163    }
1164
1165    #[inline]
1166    pub fn approvals(&self) -> &[Option<Box<Signature>>] {
1167        match self {
1168            BlockHeader::BlockHeaderV1(header) => &header.inner_rest.approvals,
1169            BlockHeader::BlockHeaderV2(header) => &header.inner_rest.approvals,
1170            BlockHeader::BlockHeaderV3(header) => &header.inner_rest.approvals,
1171            BlockHeader::BlockHeaderV4(header) => &header.inner_rest.approvals,
1172            BlockHeader::BlockHeaderV5(header) => &header.inner_rest.approvals,
1173        }
1174    }
1175
1176    /// Verifies that given public key produced the block.
1177    pub fn verify_block_producer(&self, public_key: &PublicKey) -> bool {
1178        self.signature().verify(self.hash().as_ref(), public_key)
1179    }
1180
1181    pub fn timestamp(&self) -> Utc {
1182        Utc::from_unix_timestamp_nanos(self.raw_timestamp() as i128).unwrap()
1183    }
1184
1185    pub fn num_approvals(&self) -> u64 {
1186        self.approvals().iter().filter(|x| x.is_some()).count() as u64
1187    }
1188
1189    pub fn verify_chunks_included(&self) -> bool {
1190        match self {
1191            BlockHeader::BlockHeaderV1(header) => {
1192                header.inner_rest.chunk_mask.iter().map(|&x| u64::from(x)).sum::<u64>()
1193                    == header.inner_rest.chunks_included
1194            }
1195            BlockHeader::BlockHeaderV2(_header) => true,
1196            BlockHeader::BlockHeaderV3(_header) => true,
1197            BlockHeader::BlockHeaderV4(_header) => true,
1198            BlockHeader::BlockHeaderV5(_header) => true,
1199        }
1200    }
1201
1202    #[inline]
1203    pub fn latest_protocol_version(&self) -> u32 {
1204        match self {
1205            BlockHeader::BlockHeaderV1(header) => header.inner_rest.latest_protocol_version,
1206            BlockHeader::BlockHeaderV2(header) => header.inner_rest.latest_protocol_version,
1207            BlockHeader::BlockHeaderV3(header) => header.inner_rest.latest_protocol_version,
1208            BlockHeader::BlockHeaderV4(header) => header.inner_rest.latest_protocol_version,
1209            BlockHeader::BlockHeaderV5(header) => header.inner_rest.latest_protocol_version,
1210        }
1211    }
1212
1213    pub fn inner_lite_bytes(&self) -> Vec<u8> {
1214        match self {
1215            BlockHeader::BlockHeaderV1(header) => {
1216                borsh::to_vec(&header.inner_lite).expect("Failed to serialize")
1217            }
1218            BlockHeader::BlockHeaderV2(header) => {
1219                borsh::to_vec(&header.inner_lite).expect("Failed to serialize")
1220            }
1221            BlockHeader::BlockHeaderV3(header) => {
1222                borsh::to_vec(&header.inner_lite).expect("Failed to serialize")
1223            }
1224            BlockHeader::BlockHeaderV4(header) => {
1225                borsh::to_vec(&header.inner_lite).expect("Failed to serialize")
1226            }
1227            BlockHeader::BlockHeaderV5(header) => {
1228                borsh::to_vec(&header.inner_lite).expect("Failed to serialize")
1229            }
1230        }
1231    }
1232
1233    pub fn inner_rest_bytes(&self) -> Vec<u8> {
1234        match self {
1235            BlockHeader::BlockHeaderV1(header) => {
1236                borsh::to_vec(&header.inner_rest).expect("Failed to serialize")
1237            }
1238            BlockHeader::BlockHeaderV2(header) => {
1239                borsh::to_vec(&header.inner_rest).expect("Failed to serialize")
1240            }
1241            BlockHeader::BlockHeaderV3(header) => {
1242                borsh::to_vec(&header.inner_rest).expect("Failed to serialize")
1243            }
1244            BlockHeader::BlockHeaderV4(header) => {
1245                borsh::to_vec(&header.inner_rest).expect("Failed to serialize")
1246            }
1247            BlockHeader::BlockHeaderV5(header) => {
1248                borsh::to_vec(&header.inner_rest).expect("Failed to serialize")
1249            }
1250        }
1251    }
1252
1253    #[inline]
1254    pub fn chunk_endorsements(&self) -> Option<&ChunkEndorsementsBitmap> {
1255        match self {
1256            BlockHeader::BlockHeaderV1(_) => None,
1257            BlockHeader::BlockHeaderV2(_) => None,
1258            BlockHeader::BlockHeaderV3(_) => None,
1259            BlockHeader::BlockHeaderV4(_) => None,
1260            BlockHeader::BlockHeaderV5(header) => Some(&header.inner_rest.chunk_endorsements),
1261        }
1262    }
1263
1264    #[inline]
1265    pub fn inner_lite(&self) -> &BlockHeaderInnerLite {
1266        match self {
1267            BlockHeader::BlockHeaderV1(header) => &header.inner_lite,
1268            BlockHeader::BlockHeaderV2(header) => &header.inner_lite,
1269            BlockHeader::BlockHeaderV3(header) => &header.inner_lite,
1270            BlockHeader::BlockHeaderV4(header) => &header.inner_lite,
1271            BlockHeader::BlockHeaderV5(header) => &header.inner_lite,
1272        }
1273    }
1274
1275    /// As challenges are now deprecated and not supported, a valid block should
1276    /// not have challenges.
1277    pub fn challenges_present(&self) -> bool {
1278        #[allow(deprecated)]
1279        let (challenges_root, challenges_result) = match self {
1280            Self::BlockHeaderV1(header) => {
1281                (&header.inner_rest.challenges_root, &header.inner_rest.challenges_result)
1282            }
1283            Self::BlockHeaderV2(header) => {
1284                (&header.inner_rest.challenges_root, &header.inner_rest.challenges_result)
1285            }
1286            Self::BlockHeaderV3(header) => {
1287                (&header.inner_rest.challenges_root, &header.inner_rest.challenges_result)
1288            }
1289            Self::BlockHeaderV4(header) => {
1290                (&header.inner_rest.challenges_root, &header.inner_rest.challenges_result)
1291            }
1292            Self::BlockHeaderV5(header) => {
1293                (&header.inner_rest.challenges_root, &header.inner_rest.challenges_result)
1294            }
1295        };
1296
1297        !challenges_result.is_empty() || challenges_root != &MerkleHash::default()
1298    }
1299}
1300
1301pub fn compute_bp_hash_from_validator_stakes(
1302    validator_stakes: &Vec<ValidatorStake>,
1303    use_versioned_bp_hash_format: bool,
1304) -> CryptoHash {
1305    if use_versioned_bp_hash_format {
1306        CryptoHash::hash_borsh_iter(validator_stakes)
1307    } else {
1308        let stakes = validator_stakes.into_iter().map(|stake| stake.clone().into_v1());
1309        CryptoHash::hash_borsh_iter(stakes)
1310    }
1311}