dpp/block/extended_epoch_info/
mod.rs1pub mod v0;
2
3use crate::block::epoch::EpochIndex;
4use crate::block::extended_epoch_info::v0::{ExtendedEpochInfoV0, ExtendedEpochInfoV0Getters};
5use crate::protocol_error::ProtocolError;
6#[cfg(feature = "json-conversion")]
7use crate::serialization::JsonConvertible;
8#[cfg(feature = "value-conversion")]
9use crate::serialization::ValueConvertible;
10use crate::util::deserializer::ProtocolVersion;
11use bincode::{Decode, Encode};
12use derive_more::From;
13use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize};
14use serde::{Deserialize, Serialize};
15
16#[cfg_attr(feature = "json-conversion", derive(JsonConvertible))]
18#[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
19#[derive(
20 Clone,
21 Debug,
22 PartialEq,
23 Serialize,
24 Deserialize,
25 Encode,
26 Decode,
27 PlatformSerialize,
28 PlatformDeserialize,
29 From,
30)]
31#[platform_serialize(unversioned)] #[serde(tag = "$formatVersion")]
33pub enum ExtendedEpochInfo {
34 #[serde(rename = "0")]
35 V0(ExtendedEpochInfoV0),
36}
37
38impl ExtendedEpochInfoV0Getters for ExtendedEpochInfo {
39 fn index(&self) -> EpochIndex {
40 match self {
41 ExtendedEpochInfo::V0(v0) => v0.index,
42 }
43 }
44
45 fn first_block_time(&self) -> u64 {
46 match self {
47 ExtendedEpochInfo::V0(v0) => v0.first_block_time,
48 }
49 }
50
51 fn first_block_height(&self) -> u64 {
52 match self {
53 ExtendedEpochInfo::V0(v0) => v0.first_block_height,
54 }
55 }
56
57 fn first_core_block_height(&self) -> u32 {
58 match self {
59 ExtendedEpochInfo::V0(v0) => v0.first_core_block_height,
60 }
61 }
62
63 fn fee_multiplier_permille(&self) -> u64 {
64 match self {
65 ExtendedEpochInfo::V0(v0) => v0.fee_multiplier_permille,
66 }
67 }
68
69 fn protocol_version(&self) -> ProtocolVersion {
70 match self {
71 ExtendedEpochInfo::V0(v0) => v0.protocol_version,
72 }
73 }
74}
75
76#[cfg(all(test, feature = "json-conversion"))]
77mod tests {
78 use super::*;
79 use crate::serialization::JsonConvertible;
80
81 #[test]
82 fn extended_epoch_info_json_round_trip() {
83 let info = ExtendedEpochInfo::V0(ExtendedEpochInfoV0 {
84 index: 5,
85 first_block_time: 1_700_000_000_000u64,
86 first_block_height: 500_000u64,
87 first_core_block_height: 800_000u32,
88 fee_multiplier_permille: 1_500u64,
89 protocol_version: 4,
90 });
91
92 let json = info.to_json().expect("to_json should succeed");
93 assert!(json["firstBlockTime"].is_number());
94 assert_eq!(json["firstBlockTime"].as_u64().unwrap(), 1700000000000);
95 assert!(json["firstBlockHeight"].is_number());
96 assert_eq!(json["firstBlockHeight"].as_u64().unwrap(), 500000);
97 assert!(json["feeMultiplierPermille"].is_number());
98 assert_eq!(json["feeMultiplierPermille"].as_u64().unwrap(), 1500);
99 assert!(json["firstCoreBlockHeight"].is_number());
100 assert_eq!(json["firstCoreBlockHeight"].as_u64().unwrap(), 800_000);
101 assert!(json["protocolVersion"].is_number());
102 assert_eq!(json["protocolVersion"].as_u64().unwrap(), 4);
103
104 let restored = ExtendedEpochInfo::from_json(json).expect("from_json should succeed");
105 assert_eq!(info, restored);
106 }
107
108 #[test]
109 fn extended_epoch_info_value_round_trip() {
110 let info = ExtendedEpochInfo::V0(ExtendedEpochInfoV0 {
111 index: 10,
112 first_block_time: u64::MAX,
113 first_block_height: 0,
114 first_core_block_height: u32::MAX,
115 fee_multiplier_permille: 1_000,
116 protocol_version: 1,
117 });
118
119 let obj = info.to_object().expect("to_object should succeed");
120 let restored = ExtendedEpochInfo::from_object(obj).expect("from_object should succeed");
121 assert_eq!(info, restored);
122 }
123}
124
125#[cfg(all(
128 test,
129 feature = "json-conversion",
130 feature = "value-conversion",
131 feature = "serde-conversion"
132))]
133mod json_convertible_tests_extendedepochinfo {
134 use super::*;
135 use crate::block::extended_epoch_info::v0::ExtendedEpochInfoV0;
136 use platform_value::platform_value;
137 use serde_json::json;
138
139 fn fixture() -> ExtendedEpochInfo {
140 ExtendedEpochInfo::V0(ExtendedEpochInfoV0 {
141 index: 7,
142 first_block_time: 1_700_000_000_000,
143 first_block_height: 100,
144 first_core_block_height: 50,
145 fee_multiplier_permille: 1500,
146 protocol_version: 9,
147 })
148 }
149
150 #[test]
151 fn json_round_trip_with_full_wire_shape() {
152 use crate::serialization::JsonConvertible;
153 let original = fixture();
154 let json = original.to_json().expect("to_json");
155 assert_eq!(
160 json,
161 json!({
162 "$formatVersion": "0",
163 "index": 7,
164 "firstBlockTime": 1_700_000_000_000_u64,
165 "firstBlockHeight": 100,
166 "firstCoreBlockHeight": 50,
167 "feeMultiplierPermille": 1500,
168 "protocolVersion": 9,
169 })
170 );
171 let recovered = ExtendedEpochInfo::from_json(json).expect("from_json");
172 assert_eq!(original, recovered);
173 }
174
175 #[test]
176 fn value_round_trip_with_full_wire_shape() {
177 use crate::serialization::ValueConvertible;
178 let original = fixture();
179 let value = original.to_object().expect("to_object");
180 assert_eq!(
183 value,
184 platform_value!({
185 "$formatVersion": "0",
186 "index": 7u16,
187 "firstBlockTime": 1_700_000_000_000_u64,
188 "firstBlockHeight": 100u64,
189 "firstCoreBlockHeight": 50u32,
190 "feeMultiplierPermille": 1500u64,
191 "protocolVersion": 9u32,
192 })
193 );
194 let recovered = ExtendedEpochInfo::from_object(value).expect("from_object");
195 assert_eq!(original, recovered);
196 }
197}