espresso_types/v0/impls/
header.rs

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