espresso_types/v0/impls/
header.rs

1use std::fmt;
2
3use alloy::primitives::{Keccak256, B256};
4use anyhow::{ensure, Context};
5use ark_serialize::CanonicalSerialize;
6use committable::{Commitment, Committable, RawCommitmentBuilder};
7use either::Either;
8use hotshot_query_service::{availability::QueryableHeader, explorer::ExplorerHeader};
9use hotshot_types::{
10    data::{vid_commitment, EpochNumber, VidCommitment, ViewNumber},
11    light_client::LightClientState,
12    traits::{
13        block_contents::{BlockHeader, BuilderFee, GENESIS_VID_NUM_STORAGE_NODES},
14        node_implementation::{ConsensusTime, NodeType, Versions},
15        signature_key::BuilderSignatureKey,
16        BlockPayload, EncodeBytes, ValidatedState as _,
17    },
18    utils::{epoch_from_block_number, is_ge_epoch_root, BuilderCommitment},
19};
20use jf_merkle_tree_compat::{AppendableMerkleTreeScheme, MerkleCommitment, MerkleTreeScheme};
21use serde::{
22    de::{self, MapAccess, SeqAccess, Visitor},
23    Deserialize, Deserializer, Serialize, Serializer,
24};
25use serde_json::{Map, Value};
26use thiserror::Error;
27use time::OffsetDateTime;
28use vbs::version::{StaticVersionType, Version};
29
30use super::{
31    instance_state::NodeState, state::ValidatedState, v0_1::IterableFeeInfo, v0_3::ChainConfig,
32};
33use crate::{
34    eth_signature_key::BuilderSignature,
35    v0::{
36        header::{EitherOrVersion, VersionedHeader},
37        impls::{distribute_block_reward, reward::RewardDistributor, StakeTableHash},
38    },
39    v0_1::{self},
40    v0_2,
41    v0_3::{
42        self, RewardAmount, RewardMerkleCommitmentV1, RewardMerkleTreeV1,
43        REWARD_MERKLE_TREE_V1_HEIGHT,
44    },
45    v0_4::{self, RewardMerkleCommitmentV2},
46    v0_5, BlockMerkleCommitment, DrbAndHeaderUpgradeVersion, EpochVersion, FeeAccount, FeeAmount,
47    FeeInfo, FeeMerkleCommitment, Header, L1BlockInfo, L1Snapshot, Leaf2, NamespaceId, NsIndex,
48    NsTable, PayloadByteLen, SeqTypes, TimestampMillis, UpgradeType,
49};
50
51impl v0_1::Header {
52    pub(crate) fn commit(&self) -> Commitment<Header> {
53        let mut bmt_bytes = vec![];
54        self.block_merkle_tree_root
55            .serialize_with_mode(&mut bmt_bytes, ark_serialize::Compress::Yes)
56            .unwrap();
57        let mut fmt_bytes = vec![];
58        self.fee_merkle_tree_root
59            .serialize_with_mode(&mut fmt_bytes, ark_serialize::Compress::Yes)
60            .unwrap();
61
62        RawCommitmentBuilder::new(&Self::tag())
63            .field("chain_config", self.chain_config.commit())
64            .u64_field("height", self.height)
65            .u64_field("timestamp", self.timestamp)
66            .u64_field("l1_head", self.l1_head)
67            .optional("l1_finalized", &self.l1_finalized)
68            .constant_str("payload_commitment")
69            .fixed_size_bytes(self.payload_commitment.as_ref())
70            .constant_str("builder_commitment")
71            .fixed_size_bytes(self.builder_commitment.as_ref())
72            .field("ns_table", self.ns_table.commit())
73            .var_size_field("block_merkle_tree_root", &bmt_bytes)
74            .var_size_field("fee_merkle_tree_root", &fmt_bytes)
75            .field("fee_info", self.fee_info.commit())
76            .finalize()
77    }
78}
79
80impl Committable for Header {
81    fn commit(&self) -> Commitment<Self> {
82        match self {
83            Self::V1(header) => header.commit(),
84            Self::V2(fields) => RawCommitmentBuilder::new(&Self::tag())
85                .u64_field("version_major", 0)
86                .u64_field("version_minor", 2)
87                .field("fields", fields.commit())
88                .finalize(),
89            Self::V3(fields) => RawCommitmentBuilder::new(&Self::tag())
90                .u64_field("version_major", 0)
91                .u64_field("version_minor", 3)
92                .field("fields", fields.commit())
93                .finalize(),
94            Self::V4(fields) => RawCommitmentBuilder::new(&Self::tag())
95                .u64_field("version_major", 0)
96                .u64_field("version_minor", 4)
97                .field("fields", fields.commit())
98                .finalize(),
99            Self::V5(fields) => RawCommitmentBuilder::new(&Self::tag())
100                .u64_field("version_major", 0)
101                .u64_field("version_minor", 5)
102                .field("fields", fields.commit())
103                .finalize(),
104        }
105    }
106
107    fn tag() -> String {
108        // We use the tag "BLOCK" since blocks are identified by the hash of their header. This will
109        // thus be more intuitive to users than "HEADER".
110        "BLOCK".into()
111    }
112}
113
114impl Serialize for Header {
115    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
116    where
117        S: Serializer,
118    {
119        match self {
120            Self::V1(header) => header.serialize(serializer),
121            Self::V2(fields) => VersionedHeader {
122                version: EitherOrVersion::Version(Version { major: 0, minor: 2 }),
123                fields: fields.clone(),
124            }
125            .serialize(serializer),
126            Self::V3(fields) => VersionedHeader {
127                version: EitherOrVersion::Version(Version { major: 0, minor: 3 }),
128                fields: fields.clone(),
129            }
130            .serialize(serializer),
131            Self::V4(fields) => VersionedHeader {
132                version: EitherOrVersion::Version(Version { major: 0, minor: 4 }),
133                fields: fields.clone(),
134            }
135            .serialize(serializer),
136            Self::V5(fields) => VersionedHeader {
137                version: EitherOrVersion::Version(Version { major: 0, minor: 5 }),
138                fields: fields.clone(),
139            }
140            .serialize(serializer),
141        }
142    }
143}
144
145impl<'de> Deserialize<'de> for Header {
146    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
147    where
148        D: Deserializer<'de>,
149    {
150        struct HeaderVisitor;
151
152        impl<'de> Visitor<'de> for HeaderVisitor {
153            type Value = Header;
154
155            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
156                formatter.write_str("Header")
157            }
158
159            fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
160            where
161                V: SeqAccess<'de>,
162            {
163                let chain_config_or_version: EitherOrVersion = seq
164                    .next_element()?
165                    .ok_or_else(|| de::Error::missing_field("chain_config"))?;
166
167                match chain_config_or_version {
168                    // For v0.1, the first field in the sequence of fields is the first field of the struct, so we call a function to get the rest of
169                    // the fields from the sequence and pack them into the struct.
170                    EitherOrVersion::Left(cfg) => Ok(Header::V1(
171                        v0_1::Header::deserialize_with_chain_config(cfg.into(), seq)?,
172                    )),
173                    EitherOrVersion::Right(commit) => Ok(Header::V1(
174                        v0_1::Header::deserialize_with_chain_config(commit.into(), seq)?,
175                    )),
176                    // For all versions > 0.1, the first "field" is not actually part of the `Header` struct.
177                    // We just delegate directly to the derived deserialization impl for the appropriate version.
178                    EitherOrVersion::Version(Version { major: 0, minor: 2 }) => Ok(Header::V2(
179                        seq.next_element()?
180                            .ok_or_else(|| de::Error::missing_field("fields"))?,
181                    )),
182                    EitherOrVersion::Version(Version { major: 0, minor: 3 }) => Ok(Header::V3(
183                        seq.next_element()?
184                            .ok_or_else(|| de::Error::missing_field("fields"))?,
185                    )),
186                    EitherOrVersion::Version(Version { major: 0, minor: 4 }) => Ok(Header::V4(
187                        seq.next_element()?
188                            .ok_or_else(|| de::Error::missing_field("fields"))?,
189                    )),
190                    EitherOrVersion::Version(Version { major: 0, minor: 5 }) => Ok(Header::V5(
191                        seq.next_element()?
192                            .ok_or_else(|| de::Error::missing_field("fields"))?,
193                    )),
194                    EitherOrVersion::Version(v) => {
195                        Err(serde::de::Error::custom(format!("invalid version {v:?}")))
196                    },
197                }
198            }
199
200            fn visit_map<V>(self, mut map: V) -> Result<Header, V::Error>
201            where
202                V: MapAccess<'de>,
203            {
204                // insert all the fields in the serde_map as the map may have out of order fields.
205                let mut serde_map: Map<String, Value> = Map::new();
206
207                while let Some(key) = map.next_key::<String>()? {
208                    serde_map.insert(key.trim().to_owned(), map.next_value()?);
209                }
210
211                if let Some(v) = serde_map.get("version") {
212                    let fields = serde_map
213                        .get("fields")
214                        .ok_or_else(|| de::Error::missing_field("fields"))?;
215
216                    let version = serde_json::from_value::<EitherOrVersion>(v.clone())
217                        .map_err(de::Error::custom)?;
218                    let result = match version {
219                        EitherOrVersion::Version(Version { major: 0, minor: 2 }) => Ok(Header::V2(
220                            serde_json::from_value(fields.clone()).map_err(de::Error::custom)?,
221                        )),
222                        EitherOrVersion::Version(Version { major: 0, minor: 3 }) => Ok(Header::V3(
223                            serde_json::from_value(fields.clone()).map_err(de::Error::custom)?,
224                        )),
225                        EitherOrVersion::Version(Version { major: 0, minor: 4 }) => Ok(Header::V4(
226                            serde_json::from_value(fields.clone()).map_err(de::Error::custom)?,
227                        )),
228                        EitherOrVersion::Version(Version { major: 0, minor: 5 }) => Ok(Header::V5(
229                            serde_json::from_value(fields.clone()).map_err(de::Error::custom)?,
230                        )),
231                        EitherOrVersion::Version(v) => {
232                            Err(de::Error::custom(format!("invalid version {v:?}")))
233                        },
234                        chain_config => Err(de::Error::custom(format!(
235                            "expected version, found chain_config {chain_config:?}"
236                        ))),
237                    };
238                    return result;
239                }
240
241                Ok(Header::V1(
242                    serde_json::from_value(serde_map.into()).map_err(de::Error::custom)?,
243                ))
244            }
245        }
246
247        // List of all possible fields of all versions of the `Header`.
248        // serde's `deserialize_struct` works by deserializing to a struct with a specific list of fields.
249        // The length of the fields list we provide is always going to be greater than the length of the target struct.
250        // In our case, we are deserializing to either a V1 Header or a VersionedHeader for versions > 0.1.
251        // We use serde_json and bincode serialization in the sequencer.
252        // Fortunately, serde_json ignores fields parameter and only cares about our Visitor implementation.
253        // -  https://docs.rs/serde_json/1.0.120/serde_json/struct.Deserializer.html#method.deserialize_struct
254        // Bincode uses the length of the fields list, but the bincode deserialization only cares that the length of the fields
255        // is an upper bound of the target struct's fields length.
256        // -  https://docs.rs/bincode/1.3.3/src/bincode/de/mod.rs.html#313
257        // This works because the bincode deserializer only consumes the next field when `next_element` is called,
258        // and our visitor calls it the correct number of times.
259        // This would, however, break if the bincode deserializer implementation required an exact match of the field's length,
260        // consuming one element for each field.
261        let fields: &[&str] = &[
262            "fields",
263            "chain_config",
264            "version",
265            "height",
266            "timestamp",
267            "l1_head",
268            "l1_finalized",
269            "payload_commitment",
270            "builder_commitment",
271            "ns_table",
272            "block_merkle_tree_root",
273            "fee_merkle_tree_root",
274            "fee_info",
275            "builder_signature",
276        ];
277
278        deserializer.deserialize_struct("Header", fields, HeaderVisitor)
279    }
280}
281
282impl Header {
283    pub fn version(&self) -> Version {
284        match self {
285            Self::V1(_) => Version { major: 0, minor: 1 },
286            Self::V2(_) => Version { major: 0, minor: 2 },
287            Self::V3(_) => Version { major: 0, minor: 3 },
288            Self::V4(_) => Version { major: 0, minor: 4 },
289            Self::V5(_) => Version { major: 0, minor: 5 },
290        }
291    }
292    #[allow(clippy::too_many_arguments)]
293    pub(crate) fn create(
294        chain_config: ChainConfig,
295        height: u64,
296        timestamp: u64,
297        timestamp_millis: u64,
298        l1_head: u64,
299        l1_finalized: Option<L1BlockInfo>,
300        payload_commitment: VidCommitment,
301        builder_commitment: BuilderCommitment,
302        ns_table: NsTable,
303        fee_merkle_tree_root: FeeMerkleCommitment,
304        block_merkle_tree_root: BlockMerkleCommitment,
305        reward_merkle_tree_root_v1: RewardMerkleCommitmentV1,
306        reward_merkle_tree_root_v2: RewardMerkleCommitmentV2,
307        fee_info: Vec<FeeInfo>,
308        builder_signature: Vec<BuilderSignature>,
309        total_reward_distributed: Option<RewardAmount>,
310        version: Version,
311        next_stake_table_hash: Option<StakeTableHash>,
312    ) -> Self {
313        // Ensure FeeInfo contains at least 1 element
314        assert!(!fee_info.is_empty(), "Invalid fee_info length: 0");
315
316        match (version.major, version.minor) {
317            (0, 1) => Self::V1(v0_1::Header {
318                chain_config: v0_1::ResolvableChainConfig::from(v0_1::ChainConfig::from(
319                    chain_config,
320                )),
321                height,
322                timestamp,
323                l1_head,
324                l1_finalized,
325                payload_commitment,
326                builder_commitment,
327                ns_table,
328                block_merkle_tree_root,
329                fee_merkle_tree_root,
330                fee_info: fee_info[0], // NOTE this is asserted to exist above
331                builder_signature: builder_signature.first().copied(),
332            }),
333            (0, 2) => Self::V2(v0_2::Header {
334                chain_config: v0_1::ResolvableChainConfig::from(v0_1::ChainConfig::from(
335                    chain_config,
336                )),
337                height,
338                timestamp,
339                l1_head,
340                l1_finalized,
341                payload_commitment,
342                builder_commitment,
343                ns_table,
344                block_merkle_tree_root,
345                fee_merkle_tree_root,
346                fee_info: fee_info[0], // NOTE this is asserted to exist above
347                builder_signature: builder_signature.first().copied(),
348            }),
349            (0, 3) => Self::V3(v0_3::Header {
350                chain_config: chain_config.into(),
351                height,
352                timestamp,
353                l1_head,
354                l1_finalized,
355                payload_commitment,
356                builder_commitment,
357                ns_table,
358                block_merkle_tree_root,
359                fee_merkle_tree_root,
360                fee_info: fee_info[0], // NOTE this is asserted to exist above
361                builder_signature: builder_signature.first().copied(),
362                reward_merkle_tree_root: reward_merkle_tree_root_v1,
363            }),
364            (0, 4) => Self::V4(v0_4::Header {
365                chain_config: chain_config.into(),
366                height,
367                timestamp,
368                timestamp_millis: TimestampMillis::from_millis(timestamp_millis),
369                l1_head,
370                l1_finalized,
371                payload_commitment,
372                builder_commitment,
373                ns_table,
374                block_merkle_tree_root,
375                fee_merkle_tree_root,
376                fee_info: fee_info[0], // NOTE this is asserted to exist above
377                builder_signature: builder_signature.first().copied(),
378                reward_merkle_tree_root: reward_merkle_tree_root_v2,
379                total_reward_distributed: total_reward_distributed.unwrap_or_default(),
380                next_stake_table_hash,
381            }),
382            (0, 5) => Self::V5(v0_5::Header {
383                chain_config: chain_config.into(),
384                height,
385                timestamp,
386                timestamp_millis: TimestampMillis::from_millis(timestamp_millis),
387                l1_head,
388                l1_finalized,
389                payload_commitment,
390                builder_commitment,
391                ns_table,
392                block_merkle_tree_root,
393                fee_merkle_tree_root,
394                fee_info: fee_info[0], // NOTE this is asserted to exist above
395                builder_signature: builder_signature.first().copied(),
396                reward_merkle_tree_root: reward_merkle_tree_root_v2,
397                total_reward_distributed: total_reward_distributed.unwrap_or_default(),
398                next_stake_table_hash,
399            }),
400            // This case should never occur
401            // but if it does, we must panic
402            // because we don't have the versioned types for this version
403            _ => panic!("invalid version: {version}"),
404        }
405    }
406
407    pub fn next_stake_table_hash(&self) -> Option<StakeTableHash> {
408        match self {
409            Self::V4(fields) | Self::V5(fields) => fields.next_stake_table_hash,
410            _ => None,
411        }
412    }
413
414    pub fn set_next_stake_table_hash(&mut self, hash: StakeTableHash) -> bool {
415        match self {
416            Self::V4(fields) | Self::V5(fields) => {
417                fields.next_stake_table_hash = Some(hash);
418                true
419            },
420            _ => false,
421        }
422    }
423}
424
425// Getter for a field which is the same across all versions.
426macro_rules! field {
427    ($obj:ident.$name:ident) => {
428        match $obj {
429            Self::V1(data) => &data.$name,
430            Self::V2(data) => &data.$name,
431            Self::V3(data) => &data.$name,
432            Self::V4(data) => &data.$name,
433            Self::V5(data) => &data.$name,
434        }
435    };
436}
437
438macro_rules! field_mut {
439    ($obj:ident.$name:ident) => {
440        match $obj {
441            Self::V1(data) => &mut data.$name,
442            Self::V2(data) => &mut data.$name,
443            Self::V3(data) => &mut data.$name,
444            Self::V4(data) => &mut data.$name,
445            Self::V5(data) => &mut data.$name,
446        }
447    };
448}
449
450impl Header {
451    #[allow(clippy::too_many_arguments)]
452    fn from_info(
453        payload_commitment: VidCommitment,
454        builder_commitment: BuilderCommitment,
455        ns_table: NsTable,
456        parent_leaf: &Leaf2,
457        mut l1: L1Snapshot,
458        l1_deposits: &[FeeInfo],
459        builder_fee: Vec<BuilderFee<SeqTypes>>,
460        mut timestamp: u64,
461        mut timestamp_millis: u64,
462        mut state: ValidatedState,
463        chain_config: ChainConfig,
464        version: Version,
465        reward_distributor: Option<RewardDistributor>,
466        next_stake_table_hash: Option<StakeTableHash>,
467    ) -> anyhow::Result<Self> {
468        ensure!(
469            version.major == 0,
470            "Invalid major version {}",
471            version.major
472        );
473
474        // Increment height.
475        let parent_header = parent_leaf.block_header();
476        let height = parent_header.height() + 1;
477
478        // Ensure the timestamp does not decrease. We can trust `parent.timestamp` because `parent`
479        // has already been voted on by consensus. If our timestamp is behind, either f + 1 nodes
480        // are lying about the current time, or our clock is just lagging.
481        if timestamp < parent_header.timestamp() {
482            tracing::warn!(
483                "Espresso timestamp {timestamp} behind parent {}, local clock may be out of sync",
484                parent_header.timestamp()
485            );
486            timestamp = parent_header.timestamp();
487        }
488
489        if timestamp_millis < parent_header.timestamp_millis() {
490            tracing::warn!(
491                "Espresso timestamp {timestamp} behind parent {}, local clock may be out of sync",
492                parent_header.timestamp_millis()
493            );
494            timestamp_millis = parent_header.timestamp_millis();
495        }
496
497        // Ensure the L1 block references don't decrease. Again, we can trust `parent.l1_*` are
498        // accurate.
499        if l1.head < parent_header.l1_head() {
500            tracing::warn!(
501                "L1 head {} behind parent {}, L1 client may be lagging",
502                l1.head,
503                parent_header.l1_head()
504            );
505            l1.head = parent_header.l1_head();
506        }
507        if l1.finalized < parent_header.l1_finalized() {
508            tracing::warn!(
509                "L1 finalized {:?} behind parent {:?}, L1 client may be lagging",
510                l1.finalized,
511                parent_header.l1_finalized()
512            );
513            l1.finalized = parent_header.l1_finalized();
514        }
515
516        // Enforce that the sequencer block timestamp is not behind the L1 block timestamp. This can
517        // only happen if our clock is badly out of sync with L1.
518        if let Some(l1_block) = &l1.finalized {
519            let l1_timestamp = l1_block.timestamp.to::<u64>();
520            if timestamp < l1_timestamp {
521                tracing::warn!(
522                    "Espresso timestamp {timestamp} behind L1 timestamp {l1_timestamp}, local \
523                     clock may be out of sync"
524                );
525                timestamp = l1_timestamp;
526            }
527
528            let l1_timestamp_millis = l1_timestamp * 1_000;
529
530            if timestamp_millis < l1_timestamp_millis {
531                tracing::warn!(
532                    "Espresso timestamp_millis {timestamp_millis} behind L1 timestamp \
533                     {l1_timestamp_millis}, local clock may be out of sync"
534                );
535                timestamp_millis = l1_timestamp_millis;
536            }
537        }
538
539        state
540            .block_merkle_tree
541            .push(parent_header.commit())
542            .context("missing blocks frontier")?;
543        let block_merkle_tree_root = state.block_merkle_tree.commitment();
544
545        // Insert the new L1 deposits
546        for fee_info in l1_deposits {
547            state
548                .insert_fee_deposit(*fee_info)
549                .context(format!("missing fee account {}", fee_info.account()))?;
550        }
551
552        // Validate and charge the builder fee.
553        for BuilderFee {
554            fee_account,
555            fee_signature,
556            fee_amount,
557        } in &builder_fee
558        {
559            ensure!(
560                fee_account.validate_fee_signature(fee_signature, *fee_amount, &ns_table)
561                    || fee_account.validate_fee_signature_with_vid_commitment(
562                        fee_signature,
563                        *fee_amount,
564                        &ns_table,
565                        &payload_commitment
566                    ),
567                "invalid builder signature"
568            );
569
570            let fee_info = FeeInfo::new(*fee_account, *fee_amount);
571            state
572                .charge_fee(fee_info, chain_config.fee_recipient)
573                .context(format!("invalid builder fee {fee_info:?}"))?;
574        }
575
576        let fee_info = FeeInfo::from_builder_fees(builder_fee.clone());
577
578        let builder_signature: Vec<BuilderSignature> =
579            builder_fee.iter().map(|e| e.fee_signature).collect();
580
581        let fee_merkle_tree_root = state.fee_merkle_tree.commitment();
582
583        let header = match (version.major, version.minor) {
584            (0, 1) => Self::V1(v0_1::Header {
585                chain_config: v0_1::ResolvableChainConfig::from(v0_1::ChainConfig::from(
586                    chain_config,
587                )),
588                height,
589                timestamp,
590                l1_head: l1.head,
591                l1_finalized: l1.finalized,
592                payload_commitment,
593                builder_commitment,
594                ns_table,
595                block_merkle_tree_root,
596                fee_merkle_tree_root,
597                fee_info: fee_info[0],
598                builder_signature: builder_signature.first().copied(),
599            }),
600            (0, 2) => Self::V2(v0_2::Header {
601                chain_config: v0_1::ResolvableChainConfig::from(v0_1::ChainConfig::from(
602                    chain_config,
603                )),
604                height,
605                timestamp,
606                l1_head: l1.head,
607                l1_finalized: l1.finalized,
608                payload_commitment,
609                builder_commitment,
610                ns_table,
611                block_merkle_tree_root,
612                fee_merkle_tree_root,
613                fee_info: fee_info[0],
614                builder_signature: builder_signature.first().copied(),
615            }),
616            (0, 3) => Self::V3(v0_3::Header {
617                chain_config: chain_config.into(),
618                height,
619                timestamp,
620                l1_head: l1.head,
621                l1_finalized: l1.finalized,
622                payload_commitment,
623                builder_commitment,
624                ns_table,
625                block_merkle_tree_root,
626                fee_merkle_tree_root,
627                reward_merkle_tree_root: state.reward_merkle_tree_v1.commitment(),
628                fee_info: fee_info[0],
629                builder_signature: builder_signature.first().copied(),
630            }),
631            (0, 4) => Self::V4(v0_4::Header {
632                chain_config: chain_config.into(),
633                height,
634                timestamp,
635                timestamp_millis: TimestampMillis::from_millis(timestamp_millis),
636                l1_head: l1.head,
637                l1_finalized: l1.finalized,
638                payload_commitment,
639                builder_commitment,
640                ns_table,
641                block_merkle_tree_root,
642                fee_merkle_tree_root,
643                reward_merkle_tree_root: state.reward_merkle_tree_v2.commitment(),
644                fee_info: fee_info[0],
645                builder_signature: builder_signature.first().copied(),
646                total_reward_distributed: reward_distributor
647                    .map(|r| r.total_distributed())
648                    .unwrap_or_default(),
649                next_stake_table_hash,
650            }),
651            (0, 5) => Self::V5(v0_5::Header {
652                chain_config: chain_config.into(),
653                height,
654                timestamp,
655                timestamp_millis: TimestampMillis::from_millis(timestamp_millis),
656                l1_head: l1.head,
657                l1_finalized: l1.finalized,
658                payload_commitment,
659                builder_commitment,
660                ns_table,
661                block_merkle_tree_root,
662                fee_merkle_tree_root,
663                reward_merkle_tree_root: state.reward_merkle_tree_v2.commitment(),
664                fee_info: fee_info[0],
665                builder_signature: builder_signature.first().copied(),
666                total_reward_distributed: reward_distributor
667                    .map(|r| r.total_distributed())
668                    .unwrap_or_default(),
669                next_stake_table_hash,
670            }),
671            // This case should never occur
672            // but if it does, we must panic
673            // because we don't have the versioned types for this version
674            _ => panic!("invalid version: {version}"),
675        };
676        Ok(header)
677    }
678
679    async fn get_chain_config(
680        validated_state: &ValidatedState,
681        instance_state: &NodeState,
682    ) -> anyhow::Result<ChainConfig> {
683        let validated_cf = validated_state.chain_config;
684        let instance_cf = instance_state.chain_config;
685
686        if validated_cf.commit() == instance_cf.commit() {
687            return Ok(instance_cf);
688        }
689
690        match validated_cf.resolve() {
691            Some(cf) => Ok(cf),
692            None => {
693                tracing::info!("fetching chain config {} from peers", validated_cf.commit());
694
695                instance_state
696                    .state_catchup
697                    .as_ref()
698                    .fetch_chain_config(validated_cf.commit())
699                    .await
700            },
701        }
702    }
703}
704
705impl Header {
706    /// A commitment to a ChainConfig or a full ChainConfig.
707    pub fn chain_config(&self) -> v0_3::ResolvableChainConfig {
708        match self {
709            Self::V1(fields) => v0_3::ResolvableChainConfig::from(&fields.chain_config),
710            Self::V2(fields) => v0_3::ResolvableChainConfig::from(&fields.chain_config),
711            Self::V3(fields) => fields.chain_config,
712            Self::V4(fields) => fields.chain_config,
713            Self::V5(fields) => fields.chain_config,
714        }
715    }
716
717    pub fn height(&self) -> u64 {
718        *field!(self.height)
719    }
720
721    pub fn height_mut(&mut self) -> &mut u64 {
722        &mut *field_mut!(self.height)
723    }
724
725    pub fn timestamp_internal(&self) -> u64 {
726        match self {
727            Self::V1(fields) => fields.timestamp,
728            Self::V2(fields) => fields.timestamp,
729            Self::V3(fields) => fields.timestamp,
730            Self::V4(fields) => fields.timestamp,
731            Self::V5(fields) => fields.timestamp,
732        }
733    }
734
735    pub fn timestamp_millis_internal(&self) -> u64 {
736        match self {
737            Self::V1(fields) => fields.timestamp * 1_000,
738            Self::V2(fields) => fields.timestamp * 1_000,
739            Self::V3(fields) => fields.timestamp * 1_000,
740            Self::V4(fields) => fields.timestamp_millis.u64(),
741            Self::V5(fields) => fields.timestamp_millis.u64(),
742        }
743    }
744
745    pub fn set_timestamp(&mut self, timestamp: u64, timestamp_millis: u64) {
746        match self {
747            Self::V1(fields) => {
748                fields.timestamp = timestamp;
749            },
750            Self::V2(fields) => {
751                fields.timestamp = timestamp;
752            },
753            Self::V3(fields) => {
754                fields.timestamp = timestamp;
755            },
756            Self::V4(fields) => {
757                fields.timestamp = timestamp;
758                fields.timestamp_millis = TimestampMillis::from_millis(timestamp_millis);
759            },
760            Self::V5(fields) => {
761                fields.timestamp = timestamp;
762                fields.timestamp_millis = TimestampMillis::from_millis(timestamp_millis);
763            },
764        };
765    }
766
767    /// The Espresso block header includes a reference to the current head of the L1 chain.
768    ///
769    /// Rollups can use this to facilitate bridging between the L1 and L2 in a deterministic way.
770    /// This field deterministically associates an L2 block with a recent L1 block the instant the
771    /// L2 block is sequenced. Rollups can then define the L2 state after this block as the state
772    /// obtained by executing all the transactions in this block _plus_ all the L1 deposits up to
773    /// the given L1 block number. Since there is no need to wait for the L2 block to be reflected
774    /// on the L1, this bridge design retains the low confirmation latency of HotShot.
775    ///
776    /// This block number indicates the unsafe head of the L1 chain, so it is subject to reorgs. For
777    /// this reason, the Espresso header does not include any information that might change in a
778    /// reorg, such as the L1 block timestamp or hash. It includes only the L1 block number, which
779    /// will always refer to _some_ block after a reorg: if the L1 head at the time this block was
780    /// sequenced gets reorged out, the L1 chain will eventually (and probably quickly) grow to the
781    /// same height once again, and a different block will exist with the same height. In this way,
782    /// Espresso does not have to handle L1 reorgs, and the Espresso blockchain will always be
783    /// reflective of the current state of the L1 blockchain. Rollups that use this block number
784    /// _do_ have to handle L1 reorgs, but each rollup and each rollup client can decide how many
785    /// confirmations they want to wait for on top of this `l1_head` before they consider an L2
786    /// block finalized. This offers a tradeoff between low-latency L1-L2 bridges and finality.
787    ///
788    /// Rollups that want a stronger guarantee of finality, or that want Espresso to attest to data
789    /// from the L1 block that might change in reorgs, can instead use the latest L1 _finalized_
790    /// block at the time this L2 block was sequenced: [`Self::l1_finalized`].
791    pub fn l1_head(&self) -> u64 {
792        *field!(self.l1_head)
793    }
794
795    pub fn l1_head_mut(&mut self) -> &mut u64 {
796        &mut *field_mut!(self.l1_head)
797    }
798
799    /// The Espresso block header includes information about the latest finalized L1 block.
800    ///
801    /// Similar to [`l1_head`](Self::l1_head), rollups can use this information to implement a
802    /// bridge between the L1 and L2 while retaining the finality of low-latency block confirmations
803    /// from HotShot. Since this information describes the finalized L1 block, a bridge using this
804    /// L1 block will have much higher latency than a bridge using [`l1_head`](Self::l1_head). In
805    /// exchange, rollups that use the finalized block do not have to worry about L1 reorgs, and can
806    /// inject verifiable attestations to the L1 block metadata (such as its timestamp or hash) into
807    /// their execution layers, since Espresso replicas will sign this information for the finalized
808    /// L1 block.
809    ///
810    /// This block may be `None` in the rare case where Espresso has started shortly after the
811    /// genesis of the L1, and the L1 has yet to finalize a block. In all other cases it will be
812    /// `Some`.
813    pub fn l1_finalized(&self) -> Option<L1BlockInfo> {
814        *field!(self.l1_finalized)
815    }
816
817    pub fn l1_finalized_mut(&mut self) -> &mut Option<L1BlockInfo> {
818        &mut *field_mut!(self.l1_finalized)
819    }
820
821    pub fn payload_commitment(&self) -> VidCommitment {
822        *field!(self.payload_commitment)
823    }
824
825    pub fn payload_commitment_mut(&mut self) -> &mut VidCommitment {
826        &mut *field_mut!(self.payload_commitment)
827    }
828
829    pub fn builder_commitment(&self) -> &BuilderCommitment {
830        field!(self.builder_commitment)
831    }
832
833    pub fn builder_commitment_mut(&mut self) -> &mut BuilderCommitment {
834        &mut *field_mut!(self.builder_commitment)
835    }
836
837    pub fn ns_table(&self) -> &NsTable {
838        field!(self.ns_table)
839    }
840
841    pub fn ns_table_mut(&mut self) -> &mut NsTable {
842        &mut *field_mut!(self.ns_table)
843    }
844
845    /// Root Commitment of Block Merkle Tree
846    pub fn block_merkle_tree_root(&self) -> BlockMerkleCommitment {
847        *field!(self.block_merkle_tree_root)
848    }
849
850    pub fn block_merkle_tree_root_mut(&mut self) -> &mut BlockMerkleCommitment {
851        &mut *field_mut!(self.block_merkle_tree_root)
852    }
853
854    /// Root Commitment of `FeeMerkleTree`
855    pub fn fee_merkle_tree_root(&self) -> FeeMerkleCommitment {
856        *field!(self.fee_merkle_tree_root)
857    }
858
859    pub fn fee_merkle_tree_root_mut(&mut self) -> &mut FeeMerkleCommitment {
860        &mut *field_mut!(self.fee_merkle_tree_root)
861    }
862
863    /// Fee paid by the block builder
864    pub fn fee_info(&self) -> Vec<FeeInfo> {
865        match self {
866            Self::V1(fields) => vec![fields.fee_info],
867            Self::V2(fields) => vec![fields.fee_info],
868            Self::V3(fields) => vec![fields.fee_info],
869            Self::V4(fields) => vec![fields.fee_info],
870            Self::V5(fields) => vec![fields.fee_info],
871        }
872    }
873
874    pub fn reward_merkle_tree_root(
875        &self,
876    ) -> Either<RewardMerkleCommitmentV1, RewardMerkleCommitmentV2> {
877        let empty_reward_merkle_tree = RewardMerkleTreeV1::new(REWARD_MERKLE_TREE_V1_HEIGHT);
878        match self {
879            Self::V1(_) => Either::Left(empty_reward_merkle_tree.commitment()),
880            Self::V2(_) => Either::Left(empty_reward_merkle_tree.commitment()),
881            Self::V3(fields) => Either::Left(fields.reward_merkle_tree_root),
882            Self::V4(fields) => Either::Right(fields.reward_merkle_tree_root),
883            Self::V5(fields) => Either::Right(fields.reward_merkle_tree_root),
884        }
885    }
886
887    /// Account (etheruem address) of builder
888    ///
889    /// This signature is not considered formally part of the header; it is just evidence proving
890    /// that other parts of the header ([`fee_info`](Self::fee_info)) are correct. It exists in the
891    /// header so that it is available to all nodes to be used during validation. But since it is
892    /// checked during consensus, any downstream client who has a proof of consensus finality of a
893    /// header can trust that [`fee_info`](Self::fee_info) is correct without relying on the
894    /// signature. Thus, this signature is not included in the header commitment.
895    pub fn builder_signature(&self) -> Vec<BuilderSignature> {
896        match self {
897            // Previously we used `Option<BuilderSignature>` to
898            // represent presence/absence of signature.  The simplest
899            // way to represent the same now that we have a `Vec` is
900            // empty/non-empty
901            Self::V1(fields) => fields.builder_signature.as_slice().to_vec(),
902            Self::V2(fields) => fields.builder_signature.as_slice().to_vec(),
903            Self::V3(fields) => fields.builder_signature.as_slice().to_vec(),
904            Self::V4(fields) => fields.builder_signature.as_slice().to_vec(),
905            Self::V5(fields) => fields.builder_signature.as_slice().to_vec(),
906        }
907    }
908
909    pub fn total_reward_distributed(&self) -> Option<RewardAmount> {
910        match self {
911            Self::V1(_) | Self::V2(_) | Self::V3(_) => None,
912            Self::V4(fields) | Self::V5(fields) => Some(fields.total_reward_distributed),
913        }
914    }
915}
916
917#[derive(Debug, Error)]
918#[error("Invalid Block Header {msg}")]
919pub struct InvalidBlockHeader {
920    msg: String,
921}
922impl InvalidBlockHeader {
923    fn new(msg: String) -> Self {
924        Self { msg }
925    }
926}
927
928impl From<anyhow::Error> for InvalidBlockHeader {
929    fn from(err: anyhow::Error) -> Self {
930        Self::new(format!("{err:#}"))
931    }
932}
933
934impl BlockHeader<SeqTypes> for Header {
935    type Error = InvalidBlockHeader;
936
937    #[tracing::instrument(
938        skip_all,
939        fields(
940            node_id = instance_state.node_id,
941            view = ?parent_leaf.view_number(),
942            height = parent_leaf.block_header().height(),
943        ),
944    )]
945    #[tracing::instrument(
946        skip_all,
947        fields(
948            height = parent_leaf.block_header().block_number() + 1,
949            parent_view = ?parent_leaf.view_number(),
950            payload_commitment,
951            version,
952        )
953    )]
954    async fn new(
955        parent_state: &ValidatedState,
956        instance_state: &NodeState,
957        parent_leaf: &Leaf2,
958        payload_commitment: VidCommitment,
959        builder_commitment: BuilderCommitment,
960        metadata: <<SeqTypes as NodeType>::BlockPayload as BlockPayload<SeqTypes>>::Metadata,
961        builder_fee: BuilderFee<SeqTypes>,
962        version: Version,
963        view_number: u64,
964    ) -> Result<Self, Self::Error> {
965        tracing::info!("preparing to propose legacy header");
966
967        let height = parent_leaf.height();
968        let view = parent_leaf.view_number();
969
970        let mut validated_state = parent_state.clone();
971
972        let chain_config = if version > instance_state.current_version {
973            match instance_state.upgrades.get(&version) {
974                Some(upgrade) => match upgrade.upgrade_type {
975                    UpgradeType::Fee { chain_config } => chain_config,
976                    UpgradeType::Epoch { chain_config } => chain_config,
977                    UpgradeType::DrbAndHeader { chain_config } => chain_config,
978                    UpgradeType::Da { chain_config } => chain_config,
979                },
980                None => Header::get_chain_config(&validated_state, instance_state).await?,
981            }
982        } else {
983            Header::get_chain_config(&validated_state, instance_state).await?
984        };
985
986        validated_state.chain_config = chain_config.into();
987
988        // Fetch the latest L1 snapshot.
989        let l1_snapshot = instance_state.l1_client.snapshot().await;
990        // Fetch the new L1 deposits between parent and current finalized L1 block.
991        let l1_deposits = if let (Some(addr), Some(block_info)) =
992            (chain_config.fee_contract, l1_snapshot.finalized)
993        {
994            instance_state
995                .l1_client
996                .get_finalized_deposits(
997                    addr,
998                    parent_leaf
999                        .block_header()
1000                        .l1_finalized()
1001                        .map(|block_info| block_info.number),
1002                    block_info.number,
1003                )
1004                .await
1005        } else {
1006            vec![]
1007        };
1008        // Find missing fee state entries. We will need to use the builder account which is paying a
1009        // fee and the recipient account which is receiving it, plus any counts receiving deposits
1010        // in this block.
1011        let missing_accounts = parent_state.forgotten_accounts(
1012            [builder_fee.fee_account, chain_config.fee_recipient]
1013                .into_iter()
1014                .chain(l1_deposits.iter().map(|info| info.account())),
1015        );
1016        if !missing_accounts.is_empty() {
1017            tracing::warn!(
1018                height,
1019                ?view,
1020                ?missing_accounts,
1021                "fetching missing accounts from peers"
1022            );
1023
1024            // Fetch missing fee state entries
1025            let missing_account_proofs = instance_state
1026                .state_catchup
1027                .as_ref()
1028                .fetch_accounts(
1029                    instance_state,
1030                    height,
1031                    view,
1032                    parent_state.fee_merkle_tree.commitment(),
1033                    missing_accounts,
1034                )
1035                .await?;
1036
1037            // Insert missing fee state entries
1038            for proof in missing_account_proofs.iter() {
1039                proof
1040                    .remember(&mut validated_state.fee_merkle_tree)
1041                    .context("remembering fee account")?;
1042            }
1043        }
1044
1045        // Ensure merkle tree has frontier
1046        if validated_state.need_to_fetch_blocks_mt_frontier() {
1047            tracing::warn!(height, ?view, "fetching block frontier from peers");
1048            instance_state
1049                .state_catchup
1050                .as_ref()
1051                .remember_blocks_merkle_tree(
1052                    instance_state,
1053                    height,
1054                    view,
1055                    &mut validated_state.block_merkle_tree,
1056                )
1057                .await
1058                .context("remembering block proof")?;
1059        }
1060
1061        let mut rewards = None;
1062        if version >= EpochVersion::version() {
1063            rewards = distribute_block_reward(
1064                instance_state,
1065                &mut validated_state,
1066                parent_leaf,
1067                ViewNumber::new(view_number),
1068                version,
1069            )
1070            .await?;
1071        };
1072
1073        let mut next_stake_table_hash = None;
1074
1075        if version >= DrbAndHeaderUpgradeVersion::version() {
1076            let epoch_height = instance_state
1077                .epoch_height
1078                .context("epoch height not in instance state")?;
1079            if is_ge_epoch_root(height + 1, epoch_height) {
1080                let coordinator = instance_state.coordinator.clone();
1081                let first_epoch = {
1082                    coordinator
1083                        .membership()
1084                        .read()
1085                        .await
1086                        .first_epoch()
1087                        .context("The first epoch was not set.")?
1088                };
1089
1090                let epoch = EpochNumber::new(epoch_from_block_number(height + 1, epoch_height));
1091
1092                // first 2 epochs don't have a stake table hash because they are configured.
1093                if epoch > first_epoch {
1094                    let epoch_membership = coordinator
1095                        .stake_table_for_epoch(Some(epoch + 1))
1096                        .await
1097                        .map_err(|e| anyhow::anyhow!("failed to get epoch membership: {e}"))?;
1098                    next_stake_table_hash = Some(
1099                        epoch_membership
1100                            .stake_table_hash()
1101                            .await
1102                            .context("failed to get next stake table hash")?,
1103                    );
1104                }
1105            }
1106        }
1107
1108        let now = OffsetDateTime::now_utc();
1109
1110        let timestamp = now.unix_timestamp() as u64;
1111        let timestamp_millis = TimestampMillis::from_time(&now).u64();
1112
1113        Ok(Self::from_info(
1114            payload_commitment,
1115            builder_commitment,
1116            metadata,
1117            parent_leaf,
1118            l1_snapshot,
1119            &l1_deposits,
1120            vec![builder_fee],
1121            timestamp,
1122            timestamp_millis,
1123            validated_state,
1124            chain_config,
1125            version,
1126            rewards,
1127            next_stake_table_hash,
1128        )?)
1129    }
1130
1131    fn genesis<V: Versions>(
1132        instance_state: &NodeState,
1133        payload: <SeqTypes as NodeType>::BlockPayload,
1134        metadata: &<<SeqTypes as NodeType>::BlockPayload as BlockPayload<SeqTypes>>::Metadata,
1135    ) -> Self {
1136        let payload_bytes = payload.encode();
1137        let builder_commitment = payload.builder_commitment(metadata);
1138
1139        let vid_commitment_version = instance_state.genesis_version;
1140
1141        let payload_commitment = vid_commitment::<V>(
1142            &payload_bytes,
1143            &metadata.encode(),
1144            GENESIS_VID_NUM_STORAGE_NODES,
1145            vid_commitment_version,
1146        );
1147
1148        let ValidatedState {
1149            fee_merkle_tree,
1150            block_merkle_tree,
1151            reward_merkle_tree_v1,
1152            reward_merkle_tree_v2,
1153            ..
1154        } = ValidatedState::genesis(instance_state).0;
1155        let block_merkle_tree_root = block_merkle_tree.commitment();
1156        let fee_merkle_tree_root = fee_merkle_tree.commitment();
1157        let reward_merkle_tree_root = reward_merkle_tree_v2.commitment();
1158
1159        let time = instance_state.genesis_header.timestamp;
1160
1161        let timestamp = time.unix_timestamp();
1162        let timestamp_millis = time.unix_timestamp_millis();
1163
1164        //  The Header is versioned,
1165        //  so we create the genesis header for the current version of the sequencer.
1166        Self::create(
1167            instance_state.genesis_header.chain_config,
1168            0,
1169            timestamp,
1170            timestamp_millis,
1171            instance_state
1172                .l1_genesis
1173                .map(|block| block.number)
1174                .unwrap_or_default(),
1175            instance_state.l1_genesis,
1176            payload_commitment,
1177            builder_commitment.clone(),
1178            metadata.clone(),
1179            fee_merkle_tree_root,
1180            block_merkle_tree_root,
1181            reward_merkle_tree_v1.commitment(),
1182            reward_merkle_tree_root,
1183            vec![FeeInfo::genesis()],
1184            vec![],
1185            None,
1186            instance_state.genesis_version,
1187            None,
1188        )
1189    }
1190
1191    fn timestamp(&self) -> u64 {
1192        self.timestamp_internal()
1193    }
1194
1195    fn timestamp_millis(&self) -> u64 {
1196        self.timestamp_millis_internal()
1197    }
1198
1199    fn block_number(&self) -> u64 {
1200        self.height()
1201    }
1202
1203    fn version(&self) -> Version {
1204        self.version()
1205    }
1206
1207    fn payload_commitment(&self) -> VidCommitment {
1208        self.payload_commitment()
1209    }
1210
1211    fn metadata(
1212        &self,
1213    ) -> &<<SeqTypes as NodeType>::BlockPayload as BlockPayload<SeqTypes>>::Metadata {
1214        self.ns_table()
1215    }
1216
1217    /// Commit over fee_amount, payload_commitment and metadata
1218    fn builder_commitment(&self) -> BuilderCommitment {
1219        self.builder_commitment().clone()
1220    }
1221
1222    fn get_light_client_state(
1223        &self,
1224        view: <SeqTypes as NodeType>::View,
1225    ) -> anyhow::Result<LightClientState> {
1226        let mut block_comm_root_bytes = vec![];
1227        self.block_merkle_tree_root()
1228            .serialize_compressed(&mut block_comm_root_bytes)?;
1229
1230        Ok(LightClientState {
1231            view_number: view.u64(),
1232            block_height: self.height(),
1233            block_comm_root: hotshot_types::light_client::hash_bytes_to_field(
1234                &block_comm_root_bytes,
1235            )?,
1236        })
1237    }
1238
1239    fn auth_root(&self) -> anyhow::Result<B256> {
1240        match self {
1241            Header::V1(_) | Header::V2(_) | Header::V3(_) => Ok(B256::ZERO),
1242            Header::V4(header) | Header::V5(header) => {
1243                // Temporary placeholder values for future fields
1244                let placeholder_1 = B256::ZERO;
1245                let placeholder_2 = B256::ZERO;
1246                let placeholder_3 = B256::ZERO;
1247                let placeholder_4 = B256::ZERO;
1248                let placeholder_5 = B256::ZERO;
1249                let placeholder_6 = B256::ZERO;
1250                let placeholder_7 = B256::ZERO;
1251
1252                let mut hasher = Keccak256::new();
1253
1254                // Start with the reward Merkle tree root digest as the base input
1255                let digest = header.reward_merkle_tree_root.digest();
1256                hasher.update(digest.0);
1257                hasher.update(placeholder_1);
1258                hasher.update(placeholder_2);
1259                hasher.update(placeholder_3);
1260                hasher.update(placeholder_4);
1261                hasher.update(placeholder_5);
1262                hasher.update(placeholder_6);
1263                hasher.update(placeholder_7);
1264
1265                Ok(hasher.finalize())
1266            },
1267        }
1268    }
1269}
1270
1271impl QueryableHeader<SeqTypes> for Header {
1272    type NamespaceId = NamespaceId;
1273    type NamespaceIndex = NsIndex;
1274
1275    fn namespace_id(&self, i: &NsIndex) -> Option<NamespaceId> {
1276        self.ns_table().read_ns_id(i)
1277    }
1278
1279    fn namespace_size(&self, i: &NsIndex, payload_size: usize) -> u64 {
1280        self.ns_table()
1281            .ns_range(i, &PayloadByteLen(payload_size))
1282            .byte_len()
1283            .0 as u64
1284    }
1285}
1286
1287impl ExplorerHeader<SeqTypes> for Header {
1288    type BalanceAmount = FeeAmount;
1289    type WalletAddress = Vec<FeeAccount>;
1290    type ProposerId = Vec<FeeAccount>;
1291
1292    // TODO what are these expected values w/ multiple Fees
1293    fn proposer_id(&self) -> Self::ProposerId {
1294        self.fee_info().accounts()
1295    }
1296
1297    fn fee_info_account(&self) -> Self::WalletAddress {
1298        self.fee_info().accounts()
1299    }
1300
1301    fn fee_info_balance(&self) -> Self::BalanceAmount {
1302        // TODO this will panic if some amount or total does not fit in a u64
1303        self.fee_info().amount().unwrap()
1304    }
1305
1306    /// reward_balance at the moment is only implemented as a stub, as block
1307    /// rewards have not yet been implemented.
1308    ///
1309    /// TODO: update implementation when rewards have been created / supported.
1310    ///       Issue: https://github.com/EspressoSystems/espresso-sequencer/issues/1453
1311    fn reward_balance(&self) -> Self::BalanceAmount {
1312        FeeAmount::from(0)
1313    }
1314
1315    fn namespace_ids(&self) -> Vec<NamespaceId> {
1316        self.ns_table()
1317            .iter()
1318            .map(|i| self.ns_table().read_ns_id_unchecked(&i))
1319            .collect()
1320    }
1321}
1322
1323#[cfg(test)]
1324mod test_headers {
1325    use std::sync::Arc;
1326
1327    use alloy::{
1328        node_bindings::Anvil,
1329        primitives::{Address, U256},
1330    };
1331    use hotshot_query_service::testing::mocks::MockVersions;
1332    use hotshot_types::traits::signature_key::BuilderSignatureKey;
1333    use v0_1::{BlockMerkleTree, FeeMerkleTree, L1Client};
1334    use vbs::{bincode_serializer::BincodeSerializer, version::StaticVersion, BinarySerializer};
1335
1336    use super::*;
1337    use crate::{
1338        eth_signature_key::EthKeyPair,
1339        mock::MockStateCatchup,
1340        v0_3::{RewardAccountV1, RewardAmount, REWARD_MERKLE_TREE_V1_HEIGHT},
1341        v0_4::{RewardAccountV2, RewardMerkleTreeV2, REWARD_MERKLE_TREE_V2_HEIGHT},
1342        Leaf,
1343    };
1344
1345    #[derive(Debug, Default)]
1346    #[must_use]
1347    struct TestCase {
1348        // Parent header info.
1349        parent_timestamp: u64,
1350        parent_timestamp_millis: u64,
1351        parent_l1_head: u64,
1352        parent_l1_finalized: Option<L1BlockInfo>,
1353
1354        // Environment at the time the new header is created.
1355        l1_head: u64,
1356        l1_finalized: Option<L1BlockInfo>,
1357        timestamp: u64,
1358        timestamp_millis: u64,
1359        l1_deposits: Vec<FeeInfo>,
1360
1361        // Expected new header info.
1362        expected_timestamp: u64,
1363        expected_timestamp_millis: u64,
1364        expected_l1_head: u64,
1365        expected_l1_finalized: Option<L1BlockInfo>,
1366    }
1367
1368    impl TestCase {
1369        async fn run(self) {
1370            // Check test case validity.
1371            assert!(self.expected_timestamp >= self.parent_timestamp);
1372            assert!(self.expected_timestamp_millis >= self.parent_timestamp_millis);
1373            assert!(self.expected_l1_head >= self.parent_l1_head);
1374            assert!(self.expected_l1_finalized >= self.parent_l1_finalized);
1375
1376            let genesis = GenesisForTest::default().await;
1377            let mut parent = genesis.header.clone();
1378            parent.set_timestamp(self.parent_timestamp, self.parent_timestamp_millis);
1379            *parent.l1_head_mut() = self.parent_l1_head;
1380            *parent.l1_finalized_mut() = self.parent_l1_finalized;
1381
1382            let mut parent_leaf = genesis.leaf.clone();
1383            *parent_leaf.block_header_mut() = parent.clone();
1384
1385            let block_merkle_tree =
1386                BlockMerkleTree::from_elems(Some(32), Vec::<Commitment<Header>>::new()).unwrap();
1387
1388            let fee_info = FeeInfo::genesis();
1389            let fee_merkle_tree = FeeMerkleTree::from_kv_set(
1390                20,
1391                Vec::from([(fee_info.account(), fee_info.amount())]),
1392            )
1393            .unwrap();
1394
1395            let reward_account_v1 = RewardAccountV1::default();
1396            let reward_account = RewardAccountV2::default();
1397            let reward_amount = RewardAmount::default();
1398            let reward_merkle_tree_v2 =
1399                RewardMerkleTreeV2::from_kv_set(20, Vec::from([(reward_account, reward_amount)]))
1400                    .unwrap();
1401
1402            let reward_merkle_tree_v1 = RewardMerkleTreeV1::from_kv_set(
1403                20,
1404                Vec::from([(reward_account_v1, reward_amount)]),
1405            )
1406            .unwrap();
1407
1408            let mut validated_state = ValidatedState {
1409                block_merkle_tree: block_merkle_tree.clone(),
1410                fee_merkle_tree,
1411                reward_merkle_tree_v2,
1412                reward_merkle_tree_v1,
1413                chain_config: genesis.instance_state.chain_config.into(),
1414            };
1415
1416            let (fee_account, fee_key) = FeeAccount::generated_from_seed_indexed([0; 32], 0);
1417            let fee_amount = 0;
1418            let fee_signature =
1419                FeeAccount::sign_fee(&fee_key, fee_amount, &genesis.ns_table).unwrap();
1420
1421            let header = Header::from_info(
1422                genesis.header.payload_commitment(),
1423                genesis.header.builder_commitment().clone(),
1424                genesis.ns_table,
1425                &parent_leaf,
1426                L1Snapshot {
1427                    head: self.l1_head,
1428                    finalized: self.l1_finalized,
1429                },
1430                &self.l1_deposits,
1431                vec![BuilderFee {
1432                    fee_account,
1433                    fee_amount,
1434                    fee_signature,
1435                }],
1436                self.timestamp,
1437                self.timestamp_millis,
1438                validated_state.clone(),
1439                genesis.instance_state.chain_config,
1440                Version { major: 0, minor: 1 },
1441                None,
1442                None,
1443            )
1444            .unwrap();
1445            assert_eq!(header.height(), parent.height() + 1);
1446            assert_eq!(header.timestamp(), self.expected_timestamp);
1447            assert_eq!(header.timestamp_millis(), self.expected_timestamp_millis);
1448            assert_eq!(header.l1_head(), self.expected_l1_head);
1449            assert_eq!(header.l1_finalized(), self.expected_l1_finalized);
1450
1451            // Check deposits were inserted before computing the fee merkle tree root.
1452            for fee_info in self.l1_deposits {
1453                validated_state.insert_fee_deposit(fee_info).unwrap();
1454            }
1455            assert_eq!(
1456                validated_state.fee_merkle_tree.commitment(),
1457                header.fee_merkle_tree_root(),
1458            );
1459
1460            assert_eq!(
1461                block_merkle_tree,
1462                BlockMerkleTree::from_elems(Some(32), Vec::<Commitment<Header>>::new()).unwrap()
1463            );
1464        }
1465    }
1466
1467    fn l1_block(number: u64) -> L1BlockInfo {
1468        L1BlockInfo {
1469            number,
1470            ..Default::default()
1471        }
1472    }
1473
1474    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1475    async fn test_new_header() {
1476        // Simplest case: building on genesis, L1 info and timestamp unchanged.
1477        TestCase::default().run().await
1478    }
1479
1480    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1481    async fn test_new_header_advance_timestamp() {
1482        TestCase {
1483            timestamp: 1,
1484            timestamp_millis: 1_000,
1485            expected_timestamp: 1,
1486            expected_timestamp_millis: 1_000,
1487            ..Default::default()
1488        }
1489        .run()
1490        .await
1491    }
1492
1493    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1494    async fn test_new_header_advance_l1_block() {
1495        TestCase {
1496            parent_l1_head: 0,
1497            parent_l1_finalized: Some(l1_block(0)),
1498
1499            l1_head: 1,
1500            l1_finalized: Some(l1_block(1)),
1501
1502            expected_l1_head: 1,
1503            expected_l1_finalized: Some(l1_block(1)),
1504
1505            ..Default::default()
1506        }
1507        .run()
1508        .await
1509    }
1510
1511    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1512    async fn test_new_header_advance_l1_finalized_from_none() {
1513        TestCase {
1514            l1_finalized: Some(l1_block(1)),
1515            expected_l1_finalized: Some(l1_block(1)),
1516            ..Default::default()
1517        }
1518        .run()
1519        .await
1520    }
1521
1522    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1523    async fn test_new_header_timestamp_behind_finalized_l1_block() {
1524        let l1_finalized = Some(L1BlockInfo {
1525            number: 1,
1526            timestamp: U256::from(1),
1527            ..Default::default()
1528        });
1529        TestCase {
1530            l1_head: 1,
1531            l1_finalized,
1532            timestamp: 0,
1533            timestamp_millis: 0,
1534
1535            expected_l1_head: 1,
1536            expected_l1_finalized: l1_finalized,
1537            expected_timestamp: 1,
1538            expected_timestamp_millis: 1_000,
1539
1540            ..Default::default()
1541        }
1542        .run()
1543        .await
1544    }
1545
1546    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1547    async fn test_new_header_timestamp_behind() {
1548        TestCase {
1549            parent_timestamp: 1,
1550            parent_timestamp_millis: 1_000,
1551            timestamp: 0,
1552            timestamp_millis: 0,
1553            expected_timestamp: 1,
1554            expected_timestamp_millis: 1_000,
1555
1556            ..Default::default()
1557        }
1558        .run()
1559        .await
1560    }
1561
1562    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1563    async fn test_new_header_l1_head_behind() {
1564        TestCase {
1565            parent_l1_head: 1,
1566            l1_head: 0,
1567            expected_l1_head: 1,
1568
1569            ..Default::default()
1570        }
1571        .run()
1572        .await
1573    }
1574
1575    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1576    async fn test_new_header_l1_finalized_behind_some() {
1577        TestCase {
1578            parent_l1_finalized: Some(l1_block(1)),
1579            l1_finalized: Some(l1_block(0)),
1580            expected_l1_finalized: Some(l1_block(1)),
1581
1582            ..Default::default()
1583        }
1584        .run()
1585        .await
1586    }
1587
1588    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1589    async fn test_new_header_l1_finalized_behind_none() {
1590        TestCase {
1591            parent_l1_finalized: Some(l1_block(0)),
1592            l1_finalized: None,
1593            expected_l1_finalized: Some(l1_block(0)),
1594
1595            ..Default::default()
1596        }
1597        .run()
1598        .await
1599    }
1600
1601    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1602    async fn test_new_header_deposits_one() {
1603        TestCase {
1604            l1_deposits: vec![FeeInfo::new(Address::default(), 1)],
1605            ..Default::default()
1606        }
1607        .run()
1608        .await
1609    }
1610
1611    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1612    async fn test_new_header_deposits_many() {
1613        TestCase {
1614            l1_deposits: [
1615                (Address::default(), 1),
1616                (Address::default(), 2),
1617                (Address::random(), 3),
1618            ]
1619            .iter()
1620            .map(|(address, amount)| FeeInfo::new(*address, *amount))
1621            .collect(),
1622            ..Default::default()
1623        }
1624        .run()
1625        .await
1626    }
1627
1628    struct GenesisForTest {
1629        pub instance_state: NodeState,
1630        pub validated_state: ValidatedState,
1631        pub leaf: Leaf2,
1632        pub header: Header,
1633        pub ns_table: NsTable,
1634    }
1635
1636    impl GenesisForTest {
1637        async fn default() -> Self {
1638            let instance_state = NodeState::mock();
1639            let validated_state = ValidatedState::genesis(&instance_state).0;
1640            let leaf: Leaf2 = Leaf::genesis::<MockVersions>(&validated_state, &instance_state)
1641                .await
1642                .into();
1643            let header = leaf.block_header().clone();
1644            let ns_table = leaf.block_payload().unwrap().ns_table().clone();
1645            Self {
1646                instance_state,
1647                validated_state,
1648                leaf,
1649                header,
1650                ns_table,
1651            }
1652        }
1653    }
1654
1655    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1656    async fn test_proposal_validation_success() {
1657        let anvil = Anvil::new().block_time(1u64).spawn();
1658        let mut genesis_state = NodeState::mock()
1659            .with_l1(L1Client::new(vec![anvil.endpoint_url()]).expect("Failed to create L1 client"))
1660            .with_current_version(StaticVersion::<0, 1>::version());
1661
1662        let genesis = GenesisForTest::default().await;
1663
1664        let mut parent_state = genesis.validated_state.clone();
1665
1666        let mut block_merkle_tree = parent_state.block_merkle_tree.clone();
1667        let fee_merkle_tree = parent_state.fee_merkle_tree.clone();
1668
1669        // Populate the tree with an initial `push`.
1670        block_merkle_tree.push(genesis.header.commit()).unwrap();
1671        let block_merkle_tree_root = block_merkle_tree.commitment();
1672        let fee_merkle_tree_root = fee_merkle_tree.commitment();
1673        parent_state.block_merkle_tree = block_merkle_tree.clone();
1674        parent_state.fee_merkle_tree = fee_merkle_tree.clone();
1675
1676        let mut parent_header = genesis.header.clone();
1677        *parent_header.block_merkle_tree_root_mut() = block_merkle_tree_root;
1678        *parent_header.fee_merkle_tree_root_mut() = fee_merkle_tree_root;
1679
1680        let mut parent_leaf = genesis.leaf.clone();
1681        *parent_leaf.block_header_mut() = parent_header.clone();
1682
1683        // Forget the state to trigger lookups in Header::new
1684        let forgotten_state = parent_state.forget();
1685        genesis_state.state_catchup = Arc::new(MockStateCatchup::from_iter([(
1686            parent_leaf.view_number(),
1687            Arc::new(parent_state.clone()),
1688        )]));
1689        // Get a proposal from a parent
1690
1691        // TODO this currently fails because after fetching the blocks frontier
1692        // the element (header commitment) does not match the one in the proof.
1693        let key_pair = EthKeyPair::for_test();
1694        let fee_amount = 0u64;
1695        let payload_commitment = parent_header.payload_commitment();
1696        let builder_commitment = parent_header.builder_commitment();
1697        let ns_table = genesis.ns_table;
1698        let fee_signature = FeeAccount::sign_fee(&key_pair, fee_amount, &ns_table).unwrap();
1699        let builder_fee = BuilderFee {
1700            fee_amount,
1701            fee_account: key_pair.fee_account(),
1702            fee_signature,
1703        };
1704        let proposal = Header::new(
1705            &forgotten_state,
1706            &genesis_state,
1707            &parent_leaf,
1708            payload_commitment,
1709            builder_commitment.clone(),
1710            ns_table,
1711            builder_fee,
1712            StaticVersion::<0, 1>::version(),
1713            *parent_leaf.view_number() + 1,
1714        )
1715        .await
1716        .unwrap();
1717
1718        let mut proposal_state = parent_state.clone();
1719        for fee_info in genesis_state
1720            .l1_client
1721            .get_finalized_deposits(Address::default(), None, 0)
1722            .await
1723        {
1724            proposal_state.insert_fee_deposit(fee_info).unwrap();
1725        }
1726
1727        let mut block_merkle_tree = proposal_state.block_merkle_tree.clone();
1728        block_merkle_tree.push(proposal.commit()).unwrap();
1729
1730        let _proposal_state = proposal_state
1731            .apply_header(
1732                &genesis_state,
1733                &genesis_state.state_catchup,
1734                &parent_leaf,
1735                &proposal,
1736                StaticVersion::<0, 1>::version(),
1737                parent_leaf.view_number() + 1,
1738            )
1739            .await
1740            .unwrap()
1741            .0;
1742
1743        // ValidatedTransition::new(
1744        //     proposal_state.clone(),
1745        //     &parent_leaf.block_header(),
1746        //     Proposal::new(&proposal, ADVZScheme::get_payload_byte_len(&vid_common)),
1747        // )
1748        // .validate()
1749        // .unwrap();
1750
1751        // assert_eq!(
1752        //     proposal_state.block_merkle_tree.commitment(),
1753        //     proposal.block_merkle_tree_root()
1754        // );
1755    }
1756
1757    #[test_log::test]
1758    fn verify_builder_signature() {
1759        // simulate a fixed size hash by padding our message
1760        let message = ";)";
1761        let mut commitment = [0u8; 32];
1762        commitment[..message.len()].copy_from_slice(message.as_bytes());
1763
1764        let key = FeeAccount::generated_from_seed_indexed([0; 32], 0).1;
1765        let signature = FeeAccount::sign_builder_message(&key, &commitment).unwrap();
1766        assert!(key
1767            .fee_account()
1768            .validate_builder_signature(&signature, &commitment));
1769    }
1770
1771    #[test_log::test(tokio::test(flavor = "multi_thread"))]
1772    async fn test_versioned_header_serialization() {
1773        let genesis = GenesisForTest::default().await;
1774        let header = genesis.header.clone();
1775        let ns_table = genesis.ns_table;
1776
1777        let (fee_account, _) = FeeAccount::generated_from_seed_indexed([0; 32], 0);
1778
1779        let v1_header = Header::create(
1780            genesis.instance_state.chain_config,
1781            1,
1782            2,
1783            2_000_000_000,
1784            3,
1785            Default::default(),
1786            header.payload_commitment(),
1787            header.builder_commitment().clone(),
1788            ns_table.clone(),
1789            header.fee_merkle_tree_root(),
1790            header.block_merkle_tree_root(),
1791            header.reward_merkle_tree_root().left().unwrap_or_else(|| {
1792                RewardMerkleTreeV1::new(REWARD_MERKLE_TREE_V1_HEIGHT).commitment()
1793            }),
1794            header.reward_merkle_tree_root().right().unwrap_or_else(|| {
1795                RewardMerkleTreeV2::new(REWARD_MERKLE_TREE_V2_HEIGHT).commitment()
1796            }),
1797            vec![FeeInfo {
1798                amount: 0.into(),
1799                account: fee_account,
1800            }],
1801            Default::default(),
1802            None,
1803            Version { major: 0, minor: 1 },
1804            None,
1805        );
1806
1807        let serialized = serde_json::to_string(&v1_header).unwrap();
1808        let deserialized: Header = serde_json::from_str(&serialized).unwrap();
1809        assert_eq!(v1_header, deserialized);
1810
1811        let v2_header = Header::create(
1812            genesis.instance_state.chain_config,
1813            1,
1814            2,
1815            2_000_000_000,
1816            3,
1817            Default::default(),
1818            header.payload_commitment(),
1819            header.builder_commitment().clone(),
1820            ns_table.clone(),
1821            header.fee_merkle_tree_root(),
1822            header.block_merkle_tree_root(),
1823            header.reward_merkle_tree_root().left().unwrap_or_else(|| {
1824                RewardMerkleTreeV1::new(REWARD_MERKLE_TREE_V1_HEIGHT).commitment()
1825            }),
1826            header.reward_merkle_tree_root().right().unwrap_or_else(|| {
1827                RewardMerkleTreeV2::new(REWARD_MERKLE_TREE_V2_HEIGHT).commitment()
1828            }),
1829            vec![FeeInfo {
1830                amount: 0.into(),
1831                account: fee_account,
1832            }],
1833            Default::default(),
1834            None,
1835            Version { major: 0, minor: 2 },
1836            None,
1837        );
1838
1839        let serialized = serde_json::to_string(&v2_header).unwrap();
1840        let deserialized: Header = serde_json::from_str(&serialized).unwrap();
1841        assert_eq!(v2_header, deserialized);
1842
1843        let v3_header = Header::create(
1844            genesis.instance_state.chain_config,
1845            1,
1846            2,
1847            2_000_000_000,
1848            3,
1849            Default::default(),
1850            header.payload_commitment(),
1851            header.builder_commitment().clone(),
1852            ns_table.clone(),
1853            header.fee_merkle_tree_root(),
1854            header.block_merkle_tree_root(),
1855            header.reward_merkle_tree_root().left().unwrap_or_else(|| {
1856                RewardMerkleTreeV1::new(REWARD_MERKLE_TREE_V1_HEIGHT).commitment()
1857            }),
1858            header.reward_merkle_tree_root().right().unwrap_or_else(|| {
1859                RewardMerkleTreeV2::new(REWARD_MERKLE_TREE_V2_HEIGHT).commitment()
1860            }),
1861            vec![FeeInfo {
1862                amount: 0.into(),
1863                account: fee_account,
1864            }],
1865            Default::default(),
1866            None,
1867            Version { major: 0, minor: 3 },
1868            None,
1869        );
1870
1871        let serialized = serde_json::to_string(&v3_header).unwrap();
1872        let deserialized: Header = serde_json::from_str(&serialized).unwrap();
1873        assert_eq!(v3_header, deserialized);
1874
1875        let v1_bytes = BincodeSerializer::<StaticVersion<0, 1>>::serialize(&v1_header).unwrap();
1876        let deserialized: Header =
1877            BincodeSerializer::<StaticVersion<0, 1>>::deserialize(&v1_bytes).unwrap();
1878        assert_eq!(v1_header, deserialized);
1879
1880        let v2_bytes = BincodeSerializer::<StaticVersion<0, 2>>::serialize(&v2_header).unwrap();
1881        let deserialized: Header =
1882            BincodeSerializer::<StaticVersion<0, 2>>::deserialize(&v2_bytes).unwrap();
1883        assert_eq!(v2_header, deserialized);
1884
1885        let v3_bytes = BincodeSerializer::<StaticVersion<0, 3>>::serialize(&v3_header).unwrap();
1886        let deserialized: Header =
1887            BincodeSerializer::<StaticVersion<0, 3>>::deserialize(&v3_bytes).unwrap();
1888        assert_eq!(v3_header, deserialized);
1889    }
1890}