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}