snarkvm_ledger_block/header/metadata/
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 bytes;
17mod genesis;
18mod serialize;
19mod string;
20mod to_bits;
21mod to_hash;
22mod verify;
23
24use console::{network::prelude::*, types::Field};
25
26use core::marker::PhantomData;
27
28#[derive(Copy, Clone, PartialEq, Eq, Hash)]
29pub struct Metadata<N: Network> {
30    /// The network ID of the block.
31    network: u16,
32    /// The round that produced this block - 8 bytes.
33    round: u64,
34    /// The height of this block - 4 bytes.
35    height: u32,
36    /// The cumulative weight for this block - 16 bytes.
37    cumulative_weight: u128,
38    /// The cumulative proof target for this block - 16 bytes.
39    cumulative_proof_target: u128,
40    /// The coinbase target for this block - 8 bytes.
41    coinbase_target: u64,
42    /// The proof target for this block - 8 bytes.
43    proof_target: u64,
44    /// The coinbase target for the last coinbase - 8 bytes.
45    last_coinbase_target: u64,
46    /// The Unix timestamp (UTC) for the last coinbase - 8 bytes.
47    last_coinbase_timestamp: i64,
48    /// The Unix timestamp (UTC) for this block - 8 bytes.
49    timestamp: i64,
50    /// PhantomData.
51    _phantom: PhantomData<N>,
52}
53
54impl<N: Network> Metadata<N> {
55    /// Initializes a new metadata with the given inputs.
56    #[allow(clippy::too_many_arguments)]
57    pub fn new(
58        network: u16,
59        round: u64,
60        height: u32,
61        cumulative_weight: u128,
62        cumulative_proof_target: u128,
63        coinbase_target: u64,
64        proof_target: u64,
65        last_coinbase_target: u64,
66        last_coinbase_timestamp: i64,
67        timestamp: i64,
68    ) -> Result<Self> {
69        // Construct a new metadata.
70        let metadata = Self {
71            network,
72            round,
73            height,
74            cumulative_weight,
75            cumulative_proof_target,
76            coinbase_target,
77            proof_target,
78            last_coinbase_target,
79            last_coinbase_timestamp,
80            timestamp,
81            _phantom: PhantomData,
82        };
83        // Ensure the header is valid.
84        match metadata.is_valid() {
85            true => Ok(metadata),
86            false => bail!("Invalid block metadata: {:?}", metadata),
87        }
88    }
89
90    /// Returns `true` if the block metadata is well-formed.
91    pub fn is_valid(&self) -> bool {
92        match self.height == 0u32 {
93            true => self.is_genesis(),
94            false => {
95                // Ensure the network ID is correct.
96                self.network == N::ID
97                    // Ensure the round is nonzero.
98                    && self.round != 0u64
99                    // Ensure the height is nonzero.
100                    && self.height != 0u32
101                    // Ensure the round is at least as large as the height.
102                    && self.round >= self.height as u64
103                    // Ensure the coinbase target is at or above the minimum.
104                    && self.coinbase_target >= N::GENESIS_COINBASE_TARGET
105                    // Ensure the proof target is at or above the minimum.
106                    && self.proof_target >= N::GENESIS_PROOF_TARGET
107                    // Ensure the coinbase target is larger than the proof target.
108                    && self.coinbase_target > self.proof_target
109                    // Ensure the last coinbase target is at or above the minimum.
110                    && self.last_coinbase_target >= N::GENESIS_COINBASE_TARGET
111                    // Ensure the last coinbase timestamp is after the genesis timestamp.
112                    && self.last_coinbase_timestamp >= N::GENESIS_TIMESTAMP
113                    // Ensure the timestamp in the block is after the genesis timestamp.
114                    && self.timestamp > N::GENESIS_TIMESTAMP
115            }
116        }
117    }
118}
119
120impl<N: Network> Metadata<N> {
121    /// Returns the network ID of the block.
122    pub const fn network(&self) -> u16 {
123        self.network
124    }
125
126    /// Returns the round number of the block.
127    pub const fn round(&self) -> u64 {
128        self.round
129    }
130
131    /// Returns the height of the block.
132    pub const fn height(&self) -> u32 {
133        self.height
134    }
135
136    /// Returns the cumulative weight for this block.
137    pub const fn cumulative_weight(&self) -> u128 {
138        self.cumulative_weight
139    }
140
141    /// Returns the cumulative proof target for this block.
142    pub const fn cumulative_proof_target(&self) -> u128 {
143        self.cumulative_proof_target
144    }
145
146    /// Returns the coinbase target for this block.
147    pub const fn coinbase_target(&self) -> u64 {
148        self.coinbase_target
149    }
150
151    /// Returns the proof target for this block.
152    pub const fn proof_target(&self) -> u64 {
153        self.proof_target
154    }
155
156    /// Returns the coinbase target of the last coinbase.
157    pub const fn last_coinbase_target(&self) -> u64 {
158        self.last_coinbase_target
159    }
160
161    /// Returns the block timestamp of the last coinbase.
162    pub const fn last_coinbase_timestamp(&self) -> i64 {
163        self.last_coinbase_timestamp
164    }
165
166    /// Returns the Unix timestamp (UTC) for this block.
167    pub const fn timestamp(&self) -> i64 {
168        self.timestamp
169    }
170}
171
172#[cfg(test)]
173pub mod test_helpers {
174    use super::*;
175
176    type CurrentNetwork = console::network::MainnetV0;
177
178    /// Samples a block metadata.
179    pub(crate) fn sample_block_metadata(rng: &mut TestRng) -> Metadata<CurrentNetwork> {
180        *crate::test_helpers::sample_genesis_block(rng).metadata()
181    }
182}