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