dpp/block/finalized_epoch_info/
mod.rs1mod getters;
2pub mod v0;
3
4use crate::block::finalized_epoch_info::v0::FinalizedEpochInfoV0;
5use crate::protocol_error::ProtocolError;
6#[cfg(feature = "json-conversion")]
7use crate::serialization::JsonConvertible;
8#[cfg(feature = "value-conversion")]
9use crate::serialization::ValueConvertible;
10use bincode::{Decode, Encode};
11use derive_more::From;
12use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize};
13use serde::{Deserialize, Serialize};
14
15#[cfg_attr(feature = "json-conversion", derive(JsonConvertible))]
17#[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
18#[derive(
19 Clone,
20 Debug,
21 PartialEq,
22 Serialize,
23 Deserialize,
24 Encode,
25 Decode,
26 PlatformSerialize,
27 PlatformDeserialize,
28 From,
29)]
30#[platform_serialize(unversioned)] #[serde(tag = "$formatVersion")]
32pub enum FinalizedEpochInfo {
33 #[serde(rename = "0")]
34 V0(FinalizedEpochInfoV0),
35}
36
37#[cfg(all(test, feature = "json-conversion"))]
38mod tests {
39 use super::*;
40 use crate::serialization::JsonConvertible;
41 use platform_value::Identifier;
42 use std::collections::BTreeMap;
43
44 #[test]
45 fn finalized_epoch_info_json_round_trip() {
46 let proposer_id = Identifier::from([1u8; 32]);
47 let mut block_proposers = BTreeMap::new();
48 block_proposers.insert(proposer_id, 42u64);
49
50 let info = FinalizedEpochInfo::V0(FinalizedEpochInfoV0 {
51 first_block_time: 1_700_000_000_000u64,
52 first_block_height: 100_000u64,
53 total_blocks_in_epoch: 2_000u64,
54 first_core_block_height: 500_000u32,
55 next_epoch_start_core_block_height: 500_200u32,
56 total_processing_fees: 1_000_000u64,
57 total_distributed_storage_fees: 500_000u64,
58 total_created_storage_fees: 600_000u64,
59 core_block_rewards: 10_000_000u64,
60 block_proposers,
61 fee_multiplier_permille: 1_000u64,
62 protocol_version: 3,
63 });
64
65 let json = info.to_json().expect("to_json should succeed");
66 assert!(json["firstBlockTime"].is_number());
67 assert!(json["firstBlockHeight"].is_number());
68 assert!(json["totalBlocksInEpoch"].is_number());
69 assert!(json["totalProcessingFees"].is_number());
70 assert!(json["feeMultiplierPermille"].is_number());
71 assert!(json["firstCoreBlockHeight"].is_number());
72 assert!(json["nextEpochStartCoreBlockHeight"].is_number());
73
74 let proposers = json["blockProposers"]
75 .as_object()
76 .expect("blockProposers should be an object");
77 assert_eq!(proposers.len(), 1);
78
79 let expected_base58 =
80 proposer_id.to_string(platform_value::string_encoding::Encoding::Base58);
81 assert!(
82 proposers.contains_key(&expected_base58),
83 "Expected key {} in blockProposers, got keys: {:?}",
84 expected_base58,
85 proposers.keys().collect::<Vec<_>>()
86 );
87
88 let value = &proposers[&expected_base58];
89 assert!(value.is_number());
90 assert_eq!(value.as_u64().unwrap(), 42);
91
92 let restored = FinalizedEpochInfo::from_json(json).expect("from_json should succeed");
93 assert_eq!(info, restored);
94 }
95
96 #[test]
97 fn finalized_epoch_info_value_round_trip_empty_proposers() {
98 let info = FinalizedEpochInfo::V0(FinalizedEpochInfoV0 {
99 first_block_time: 1_000_000u64,
100 first_block_height: 10_000u64,
101 total_blocks_in_epoch: 500u64,
102 first_core_block_height: 50_000u32,
103 next_epoch_start_core_block_height: 50_200u32,
104 total_processing_fees: 100u64,
105 total_distributed_storage_fees: 50u64,
106 total_created_storage_fees: 60u64,
107 core_block_rewards: 1_000u64,
108 block_proposers: BTreeMap::new(),
109 fee_multiplier_permille: 1_000u64,
110 protocol_version: 2,
111 });
112
113 let obj = info.to_object().expect("to_object should succeed");
114 let restored = FinalizedEpochInfo::from_object(obj).expect("from_object should succeed");
115 assert_eq!(info, restored);
116 }
117}