1use crate::block_header::BlockHeader;
2use crate::stateless_validation::chunk_endorsements_bitmap::ChunkEndorsementsBitmap;
3use crate::types::validator_stake::{ValidatorStake, ValidatorStakeIter};
4use crate::types::{AccountId, EpochId, ValidatorStakeV1};
5use borsh::{BorshDeserialize, BorshSerialize};
6use near_primitives_core::hash::CryptoHash;
7use near_primitives_core::types::{Balance, BlockHeight, ProtocolVersion};
8use near_schema_checker_lib::ProtocolSchema;
9use std::collections::HashMap;
10
11#[derive(
13 BorshSerialize, BorshDeserialize, Eq, PartialEq, Clone, Debug, serde::Serialize, ProtocolSchema,
14)]
15pub enum BlockInfo {
16 V1(BlockInfoV1),
17 V2(BlockInfoV2),
18 V3(BlockInfoV3),
19}
20
21impl Default for BlockInfo {
22 fn default() -> Self {
23 Self::V3(BlockInfoV3::default())
24 }
25}
26
27impl BlockInfo {
28 #[allow(deprecated)]
29 pub fn new(
30 hash: CryptoHash,
31 height: BlockHeight,
32 last_finalized_height: BlockHeight,
33 last_final_block_hash: CryptoHash,
34 prev_hash: CryptoHash,
35 proposals: Vec<ValidatorStake>,
36 validator_mask: Vec<bool>,
37 total_supply: Balance,
38 latest_protocol_version: ProtocolVersion,
39 timestamp_nanosec: u64,
40 chunk_endorsements: Option<ChunkEndorsementsBitmap>,
41 ) -> Self {
42 if let Some(chunk_endorsements) = chunk_endorsements {
43 Self::V3(BlockInfoV3 {
44 hash,
45 height,
46 last_finalized_height,
47 last_final_block_hash,
48 prev_hash,
49 proposals,
50 chunk_mask: validator_mask,
51 latest_protocol_version,
52 slashed: HashMap::new(),
53 total_supply,
54 epoch_first_block: Default::default(),
55 epoch_id: Default::default(),
56 timestamp_nanosec,
57 chunk_endorsements,
58 })
59 } else {
60 Self::V2(BlockInfoV2 {
61 hash,
62 height,
63 last_finalized_height,
64 last_final_block_hash,
65 prev_hash,
66 proposals,
67 chunk_mask: validator_mask,
68 latest_protocol_version,
69 slashed: HashMap::new(),
70 total_supply,
71 epoch_first_block: Default::default(),
72 epoch_id: Default::default(),
73 timestamp_nanosec,
74 })
75 }
76 }
77
78 pub fn from_header(header: &BlockHeader, last_finalized_height: BlockHeight) -> Self {
79 BlockInfo::new(
80 *header.hash(),
81 header.height(),
82 last_finalized_height,
83 *header.last_final_block(),
84 *header.prev_hash(),
85 header.prev_validator_proposals().collect(),
86 header.chunk_mask().to_vec(),
87 header.total_supply(),
88 header.latest_protocol_version(),
89 header.raw_timestamp(),
90 header.chunk_endorsements().cloned(),
91 )
92 }
93
94 pub fn from_header_and_endorsements(
96 header: &BlockHeader,
97 last_finalized_height: BlockHeight,
98 chunk_endorsements: Option<ChunkEndorsementsBitmap>,
99 ) -> Self {
100 BlockInfo::new(
101 *header.hash(),
102 header.height(),
103 last_finalized_height,
104 *header.last_final_block(),
105 *header.prev_hash(),
106 header.prev_validator_proposals().collect(),
107 header.chunk_mask().to_vec(),
108 header.total_supply(),
109 header.latest_protocol_version(),
110 header.raw_timestamp(),
111 header.chunk_endorsements().cloned().or(chunk_endorsements),
112 )
113 }
114
115 #[inline]
116 pub fn proposals_iter(&self) -> ValidatorStakeIter {
117 match self {
118 Self::V1(info) => ValidatorStakeIter::v1(&info.proposals),
119 Self::V2(info) => ValidatorStakeIter::new(&info.proposals),
120 Self::V3(info) => ValidatorStakeIter::new(&info.proposals),
121 }
122 }
123
124 #[inline]
125 pub fn hash(&self) -> &CryptoHash {
126 match self {
127 Self::V1(info) => &info.hash,
128 Self::V2(info) => &info.hash,
129 Self::V3(info) => &info.hash,
130 }
131 }
132
133 #[inline]
134 pub fn height(&self) -> BlockHeight {
135 match self {
136 Self::V1(info) => info.height,
137 Self::V2(info) => info.height,
138 Self::V3(info) => info.height,
139 }
140 }
141
142 #[inline]
143 pub fn last_finalized_height(&self) -> BlockHeight {
144 match self {
145 Self::V1(info) => info.last_finalized_height,
146 Self::V2(info) => info.last_finalized_height,
147 Self::V3(info) => info.last_finalized_height,
148 }
149 }
150
151 #[inline]
152 pub fn last_final_block_hash(&self) -> &CryptoHash {
153 match self {
154 Self::V1(info) => &info.last_final_block_hash,
155 Self::V2(info) => &info.last_final_block_hash,
156 Self::V3(info) => &info.last_final_block_hash,
157 }
158 }
159
160 #[inline]
161 pub fn prev_hash(&self) -> &CryptoHash {
162 match self {
163 Self::V1(info) => &info.prev_hash,
164 Self::V2(info) => &info.prev_hash,
165 Self::V3(info) => &info.prev_hash,
166 }
167 }
168
169 #[inline]
170 pub fn is_genesis(&self) -> bool {
171 self.prev_hash() == &CryptoHash::default()
172 }
173
174 #[inline]
175 pub fn epoch_first_block(&self) -> &CryptoHash {
176 match self {
177 Self::V1(info) => &info.epoch_first_block,
178 Self::V2(info) => &info.epoch_first_block,
179 Self::V3(info) => &info.epoch_first_block,
180 }
181 }
182
183 #[inline]
184 pub fn epoch_first_block_mut(&mut self) -> &mut CryptoHash {
185 match self {
186 Self::V1(info) => &mut info.epoch_first_block,
187 Self::V2(info) => &mut info.epoch_first_block,
188 Self::V3(info) => &mut info.epoch_first_block,
189 }
190 }
191
192 #[inline]
193 pub fn epoch_id(&self) -> &EpochId {
194 match self {
195 Self::V1(info) => &info.epoch_id,
196 Self::V2(info) => &info.epoch_id,
197 Self::V3(info) => &info.epoch_id,
198 }
199 }
200
201 #[inline]
202 pub fn epoch_id_mut(&mut self) -> &mut EpochId {
203 match self {
204 Self::V1(info) => &mut info.epoch_id,
205 Self::V2(info) => &mut info.epoch_id,
206 Self::V3(info) => &mut info.epoch_id,
207 }
208 }
209
210 #[inline]
211 pub fn chunk_mask(&self) -> &[bool] {
212 match self {
213 Self::V1(info) => &info.chunk_mask,
214 Self::V2(info) => &info.chunk_mask,
215 Self::V3(info) => &info.chunk_mask,
216 }
217 }
218
219 #[inline]
220 pub fn latest_protocol_version(&self) -> &ProtocolVersion {
221 match self {
222 Self::V1(info) => &info.latest_protocol_version,
223 Self::V2(info) => &info.latest_protocol_version,
224 Self::V3(info) => &info.latest_protocol_version,
225 }
226 }
227
228 #[inline]
229 pub fn total_supply(&self) -> &Balance {
230 match self {
231 Self::V1(info) => &info.total_supply,
232 Self::V2(info) => &info.total_supply,
233 Self::V3(info) => &info.total_supply,
234 }
235 }
236
237 #[inline]
238 pub fn timestamp_nanosec(&self) -> &u64 {
239 match self {
240 Self::V1(info) => &info.timestamp_nanosec,
241 Self::V2(info) => &info.timestamp_nanosec,
242 Self::V3(info) => &info.timestamp_nanosec,
243 }
244 }
245
246 #[inline]
247 pub fn chunk_endorsements(&self) -> Option<&ChunkEndorsementsBitmap> {
248 match self {
249 Self::V1(_) => None,
250 Self::V2(_) => None,
251 Self::V3(info) => Some(&info.chunk_endorsements),
252 }
253 }
254}
255
256#[derive(
258 Default,
259 BorshSerialize,
260 BorshDeserialize,
261 Eq,
262 PartialEq,
263 Clone,
264 Debug,
265 serde::Serialize,
266 ProtocolSchema,
267)]
268pub struct BlockInfoV3 {
269 pub hash: CryptoHash,
270 pub height: BlockHeight,
271 pub last_finalized_height: BlockHeight,
272 pub last_final_block_hash: CryptoHash,
273 pub prev_hash: CryptoHash,
274 pub epoch_first_block: CryptoHash,
275 pub epoch_id: EpochId,
276 pub proposals: Vec<ValidatorStake>,
277 pub chunk_mask: Vec<bool>,
278 pub latest_protocol_version: ProtocolVersion,
280 #[deprecated]
282 pub slashed: HashMap<AccountId, SlashState>,
283 pub total_supply: Balance,
285 pub timestamp_nanosec: u64,
286 pub chunk_endorsements: ChunkEndorsementsBitmap,
287}
288
289#[derive(
291 Default,
292 BorshSerialize,
293 BorshDeserialize,
294 Eq,
295 PartialEq,
296 Clone,
297 Debug,
298 serde::Serialize,
299 ProtocolSchema,
300)]
301pub struct BlockInfoV2 {
302 pub hash: CryptoHash,
303 pub height: BlockHeight,
304 pub last_finalized_height: BlockHeight,
305 pub last_final_block_hash: CryptoHash,
306 pub prev_hash: CryptoHash,
307 pub epoch_first_block: CryptoHash,
308 pub epoch_id: EpochId,
309 pub proposals: Vec<ValidatorStake>,
310 pub chunk_mask: Vec<bool>,
311 pub latest_protocol_version: ProtocolVersion,
313 #[deprecated]
315 pub slashed: HashMap<AccountId, SlashState>,
316 pub total_supply: Balance,
318 pub timestamp_nanosec: u64,
319}
320
321#[derive(
323 Default,
324 BorshSerialize,
325 BorshDeserialize,
326 Eq,
327 PartialEq,
328 Clone,
329 Debug,
330 serde::Serialize,
331 ProtocolSchema,
332)]
333pub struct BlockInfoV1 {
334 pub hash: CryptoHash,
335 pub height: BlockHeight,
336 pub last_finalized_height: BlockHeight,
337 pub last_final_block_hash: CryptoHash,
338 pub prev_hash: CryptoHash,
339 pub epoch_first_block: CryptoHash,
340 pub epoch_id: EpochId,
341 pub proposals: Vec<ValidatorStakeV1>,
342 pub chunk_mask: Vec<bool>,
343 pub latest_protocol_version: ProtocolVersion,
345 #[deprecated]
347 pub slashed: HashMap<AccountId, SlashState>,
348 pub total_supply: Balance,
350 pub timestamp_nanosec: u64,
351}
352
353impl BlockInfoV1 {
354 #[allow(deprecated)]
355 pub fn new(
356 hash: CryptoHash,
357 height: BlockHeight,
358 last_finalized_height: BlockHeight,
359 last_final_block_hash: CryptoHash,
360 prev_hash: CryptoHash,
361 proposals: Vec<ValidatorStakeV1>,
362 validator_mask: Vec<bool>,
363 total_supply: Balance,
364 latest_protocol_version: ProtocolVersion,
365 timestamp_nanosec: u64,
366 ) -> Self {
367 Self {
368 hash,
369 height,
370 last_finalized_height,
371 last_final_block_hash,
372 prev_hash,
373 proposals,
374 chunk_mask: validator_mask,
375 latest_protocol_version,
376 slashed: HashMap::new(),
377 total_supply,
378 epoch_first_block: Default::default(),
379 epoch_id: Default::default(),
380 timestamp_nanosec,
381 }
382 }
383}
384
385#[derive(
387 BorshSerialize, BorshDeserialize, serde::Serialize, Debug, Clone, PartialEq, Eq, ProtocolSchema,
388)]
389pub enum SlashState {
390 DoubleSign,
392 AlreadySlashed,
394 Other,
396}