snarkvm_ledger_block/header/
mod.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16mod metadata;
17pub use metadata::*;
18
19mod bytes;
20mod genesis;
21mod merkle;
22mod serialize;
23mod string;
24mod verify;
25
26use crate::{Ratifications, Transactions};
27use console::{
28    network::prelude::*,
29    program::{HEADER_DEPTH, HeaderLeaf, HeaderPath, HeaderTree},
30    types::Field,
31};
32use snarkvm_synthesizer_program::FinalizeOperation;
33
34/// The header for the block contains metadata that uniquely identifies the block.
35#[derive(Copy, Clone, PartialEq, Eq, Hash)]
36pub struct Header<N: Network> {
37    /// The Merkle root representing the blocks in the ledger up to the previous block.
38    previous_state_root: N::StateRoot,
39    /// The Merkle root representing the transactions in the block.
40    transactions_root: Field<N>,
41    /// The Merkle root representing the on-chain finalize including the current block.
42    finalize_root: Field<N>,
43    /// The Merkle root representing the ratifications in the block.
44    ratifications_root: Field<N>,
45    /// The solutions root of the puzzle.
46    solutions_root: Field<N>,
47    /// The subdag Merkle root of the authority.
48    subdag_root: Field<N>,
49    /// The metadata of the block.
50    metadata: Metadata<N>,
51}
52
53impl<N: Network> Header<N> {
54    /// Initializes a new block header with the given inputs.
55    pub fn from(
56        previous_state_root: N::StateRoot,
57        transactions_root: Field<N>,
58        finalize_root: Field<N>,
59        ratifications_root: Field<N>,
60        solutions_root: Field<N>,
61        subdag_root: Field<N>,
62        metadata: Metadata<N>,
63    ) -> Result<Self> {
64        // Construct a new block header.
65        let header = Self {
66            previous_state_root,
67            transactions_root,
68            finalize_root,
69            ratifications_root,
70            solutions_root,
71            subdag_root,
72            metadata,
73        };
74        // Ensure the header is valid.
75        match header.is_valid() {
76            true => Ok(header),
77            false => bail!("Invalid block header: {:?}", header),
78        }
79    }
80
81    /// Returns `true` if the block header is well-formed.
82    pub fn is_valid(&self) -> bool {
83        match self.height() == 0u32 {
84            true => self.is_genesis(),
85            false => {
86                // Ensure the previous ledger root is nonzero.
87                *self.previous_state_root != Field::zero()
88                    // Ensure the transactions root is nonzero.
89                    && self.transactions_root != Field::zero()
90                    // Ensure the finalize root is nonzero.
91                    && self.finalize_root != Field::zero()
92                    // Ensure the ratifications root is nonzero.
93                    && self.ratifications_root != Field::zero()
94                    // Ensure the metadata is valid.
95                    && self.metadata.is_valid()
96            }
97        }
98    }
99
100    /// Returns the previous state root from the block header.
101    pub const fn previous_state_root(&self) -> N::StateRoot {
102        self.previous_state_root
103    }
104
105    /// Returns the transactions root in the block header.
106    pub const fn transactions_root(&self) -> Field<N> {
107        self.transactions_root
108    }
109
110    /// Returns the finalize root in the block header.
111    pub const fn finalize_root(&self) -> Field<N> {
112        self.finalize_root
113    }
114
115    /// Returns the ratifications root in the block header.
116    pub const fn ratifications_root(&self) -> Field<N> {
117        self.ratifications_root
118    }
119
120    /// Returns the solutions root in the block header.
121    pub const fn solutions_root(&self) -> Field<N> {
122        self.solutions_root
123    }
124
125    /// Returns the subdag root in the block header.
126    pub const fn subdag_root(&self) -> Field<N> {
127        self.subdag_root
128    }
129
130    /// Returns the metadata in the block header.
131    pub const fn metadata(&self) -> &Metadata<N> {
132        &self.metadata
133    }
134
135    /// Returns the network ID of the block.
136    pub const fn network(&self) -> u16 {
137        self.metadata.network()
138    }
139
140    /// Returns the round number of the block.
141    pub const fn round(&self) -> u64 {
142        self.metadata.round()
143    }
144
145    /// Returns the height of the block.
146    pub const fn height(&self) -> u32 {
147        self.metadata.height()
148    }
149
150    /// Returns the cumulative weight for this block.
151    pub const fn cumulative_weight(&self) -> u128 {
152        self.metadata.cumulative_weight()
153    }
154
155    /// Returns the cumulative proof target for this block.
156    pub const fn cumulative_proof_target(&self) -> u128 {
157        self.metadata.cumulative_proof_target()
158    }
159
160    /// Returns the coinbase target for this block.
161    pub const fn coinbase_target(&self) -> u64 {
162        self.metadata.coinbase_target()
163    }
164
165    /// Returns the proof target for this block.
166    pub const fn proof_target(&self) -> u64 {
167        self.metadata.proof_target()
168    }
169
170    /// Returns the coinbase target of the last coinbase.
171    pub const fn last_coinbase_target(&self) -> u64 {
172        self.metadata.last_coinbase_target()
173    }
174
175    /// Returns the Unix timestamp (UTC) of the last coinbase.
176    pub const fn last_coinbase_timestamp(&self) -> i64 {
177        self.metadata.last_coinbase_timestamp()
178    }
179
180    /// Returns the Unix timestamp (UTC) for this block.
181    pub const fn timestamp(&self) -> i64 {
182        self.metadata.timestamp()
183    }
184}
185
186#[cfg(test)]
187pub mod test_helpers {
188    use super::*;
189
190    type CurrentNetwork = console::network::MainnetV0;
191
192    /// Samples a block header.
193    pub(crate) fn sample_block_header(rng: &mut TestRng) -> Header<CurrentNetwork> {
194        *crate::test_helpers::sample_genesis_block(rng).header()
195    }
196}