unc_primitives/
block_header.rs

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