Skip to main content

espresso_types/v0/v0_7/
header.rs

1use ark_serialize::CanonicalSerialize;
2use committable::{Commitment, Committable, RawCommitmentBuilder};
3use hotshot_types::data::VidCommitment;
4use serde::{Deserialize, Serialize};
5
6use super::{
7    BlockMerkleCommitment, BuilderSignature, FeeInfo, FeeMerkleCommitment, L1BlockInfo,
8    ResolvableChainConfig,
9};
10use crate::{
11    NsTable, TimestampMillis,
12    v0::impls::StakeTableHash,
13    v0_3::RewardAmount,
14    v0_4::RewardMerkleCommitmentV2,
15    v0_5::{LeaderCounts, leader_counts_serde},
16};
17
18/// The V5 header without `builder_commitment`.
19///
20/// That field was a SHA-256 over the whole payload which every leader computed
21/// and no validator checked: the fee signature covers the fee amount, the
22/// metadata and, from 0.3, the VID commitment, and nothing recomputed the value
23/// from the payload. From 0.7 the header no longer carries it, so the leader no
24/// longer pays for it on the proposal path.
25#[derive(Clone, Debug, Deserialize, Serialize, Hash, PartialEq, Eq)]
26pub struct Header {
27    /// A commitment to a ChainConfig or a full ChainConfig.
28    pub(crate) chain_config: ResolvableChainConfig,
29    pub(crate) height: u64,
30    pub(crate) timestamp: u64,
31    pub(crate) timestamp_millis: TimestampMillis,
32    pub(crate) l1_head: u64,
33    pub(crate) l1_finalized: Option<L1BlockInfo>,
34    pub(crate) payload_commitment: VidCommitment,
35    pub(crate) ns_table: NsTable,
36    pub(crate) block_merkle_tree_root: BlockMerkleCommitment,
37    pub(crate) fee_merkle_tree_root: FeeMerkleCommitment,
38    pub(crate) fee_info: FeeInfo,
39    pub(crate) builder_signature: Option<BuilderSignature>,
40    pub(crate) reward_merkle_tree_root: RewardMerkleCommitmentV2,
41    pub(crate) total_reward_distributed: RewardAmount,
42    pub(crate) next_stake_table_hash: Option<StakeTableHash>,
43    /// leader counts for the current epoch, indexed by validator position
44    /// in the stake table. Fixed to [`MAX_VALIDATORS`](crate::v0_5::MAX_VALIDATORS)
45    /// as the active validator set is capped at 100 validators.
46    #[serde(with = "leader_counts_serde")]
47    pub(crate) leader_counts: LeaderCounts,
48}
49
50impl Committable for Header {
51    fn commit(&self) -> Commitment<Self> {
52        let mut bmt_bytes = vec![];
53        self.block_merkle_tree_root
54            .serialize_with_mode(&mut bmt_bytes, ark_serialize::Compress::Yes)
55            .unwrap();
56        let mut fmt_bytes = vec![];
57        self.fee_merkle_tree_root
58            .serialize_with_mode(&mut fmt_bytes, ark_serialize::Compress::Yes)
59            .unwrap();
60
61        let mut rwd_bytes = vec![];
62        self.reward_merkle_tree_root
63            .serialize_with_mode(&mut rwd_bytes, ark_serialize::Compress::Yes)
64            .unwrap();
65
66        let leader_counts_bytes: Vec<u8> = self
67            .leader_counts
68            .iter()
69            .flat_map(|&count| count.to_le_bytes())
70            .collect();
71
72        let mut cb = RawCommitmentBuilder::new(&Self::tag())
73            .field("chain_config", self.chain_config.commit())
74            .u64_field("height", self.height)
75            .u64_field("timestamp", self.timestamp)
76            .u64_field("timestamp_millis", self.timestamp_millis.u64())
77            .u64_field("l1_head", self.l1_head)
78            .optional("l1_finalized", &self.l1_finalized)
79            .constant_str("payload_commitment")
80            .fixed_size_bytes(self.payload_commitment.as_ref())
81            .field("ns_table", self.ns_table.commit())
82            .var_size_field("block_merkle_tree_root", &bmt_bytes)
83            .var_size_field("fee_merkle_tree_root", &fmt_bytes)
84            .field("fee_info", self.fee_info.commit())
85            .var_size_field("reward_merkle_tree_root", &rwd_bytes)
86            .var_size_field(
87                "total_reward_distributed",
88                &self.total_reward_distributed.to_fixed_bytes(),
89            )
90            .var_size_field("leader_counts", &leader_counts_bytes);
91
92        if let Some(next_stake_table_hash) = self.next_stake_table_hash {
93            cb = cb.field("next_stake_table_hash", next_stake_table_hash);
94        }
95
96        cb.finalize()
97    }
98
99    fn tag() -> String {
100        crate::v0_1::Header::tag()
101    }
102}