dpp/block/extended_block_info/
mod.rs1use crate::block::block_info::BlockInfo;
2use crate::block::extended_block_info::v0::{
3 ExtendedBlockInfoV0, ExtendedBlockInfoV0Getters, ExtendedBlockInfoV0Setters,
4};
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::version::FeatureVersion;
11use bincode::{Decode, DecodeUntrusted, Encode};
12use derive_more::From;
13use platform_serialization_derive::{
14 PlatformDeserializeTrusted, PlatformDeserializeUntrusted, PlatformSerialize,
15};
16use serde::{Deserialize, Serialize};
17
18pub mod v0;
19
20#[cfg_attr(feature = "json-conversion", derive(JsonConvertible))]
22#[cfg_attr(feature = "value-conversion", derive(ValueConvertible))]
23#[derive(
24 Clone,
25 Debug,
26 PartialEq,
27 Eq,
28 Serialize,
29 Deserialize,
30 Encode,
31 Decode,
32 PlatformSerialize,
33 PlatformDeserializeTrusted,
34 PlatformDeserializeUntrusted,
35 From,
36 DecodeUntrusted,
37)]
38#[platform_serialize(unversioned)] #[serde(tag = "$formatVersion")]
40pub enum ExtendedBlockInfo {
41 #[serde(rename = "0")]
42 V0(ExtendedBlockInfoV0),
43}
44
45impl ExtendedBlockInfo {
46 pub fn version(&self) -> FeatureVersion {
49 match self {
50 ExtendedBlockInfo::V0(_) => 0,
51 }
52 }
53}
54
55impl ExtendedBlockInfoV0Getters for ExtendedBlockInfo {
56 fn basic_info(&self) -> &BlockInfo {
57 match self {
58 ExtendedBlockInfo::V0(v0) => &v0.basic_info,
59 }
60 }
61
62 fn basic_info_mut(&mut self) -> &mut BlockInfo {
63 match self {
64 ExtendedBlockInfo::V0(v0) => &mut v0.basic_info,
65 }
66 }
67
68 fn basic_info_owned(self) -> BlockInfo {
69 match self {
70 ExtendedBlockInfo::V0(v0) => v0.basic_info,
71 }
72 }
73
74 fn app_hash(&self) -> &[u8; 32] {
75 match self {
76 ExtendedBlockInfo::V0(v0) => &v0.app_hash,
77 }
78 }
79
80 fn quorum_hash(&self) -> &[u8; 32] {
81 match self {
82 ExtendedBlockInfo::V0(v0) => &v0.quorum_hash,
83 }
84 }
85
86 fn proposer_pro_tx_hash(&self) -> &[u8; 32] {
87 match self {
88 ExtendedBlockInfo::V0(v0) => &v0.proposer_pro_tx_hash,
89 }
90 }
91
92 fn block_id_hash(&self) -> &[u8; 32] {
93 match self {
94 ExtendedBlockInfo::V0(v0) => &v0.block_id_hash,
95 }
96 }
97
98 fn signature(&self) -> &[u8; 96] {
99 match self {
100 ExtendedBlockInfo::V0(v0) => &v0.signature,
101 }
102 }
103
104 fn round(&self) -> u32 {
105 match self {
106 ExtendedBlockInfo::V0(v0) => v0.round,
107 }
108 }
109}
110
111impl ExtendedBlockInfoV0Setters for ExtendedBlockInfo {
112 fn set_basic_info(&mut self, info: BlockInfo) {
113 match self {
114 ExtendedBlockInfo::V0(v0) => {
115 v0.set_basic_info(info);
116 }
117 }
118 }
119
120 fn set_app_hash(&mut self, hash: [u8; 32]) {
121 match self {
122 ExtendedBlockInfo::V0(v0) => {
123 v0.set_app_hash(hash);
124 }
125 }
126 }
127
128 fn set_quorum_hash(&mut self, hash: [u8; 32]) {
129 match self {
130 ExtendedBlockInfo::V0(v0) => {
131 v0.set_quorum_hash(hash);
132 }
133 }
134 }
135
136 fn set_signature(&mut self, signature: [u8; 96]) {
137 match self {
138 ExtendedBlockInfo::V0(v0) => {
139 v0.set_signature(signature);
140 }
141 }
142 }
143
144 fn set_round(&mut self, round: u32) {
145 match self {
146 ExtendedBlockInfo::V0(v0) => {
147 v0.set_round(round);
148 }
149 }
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156 use crate::block::block_info::BlockInfo;
157 use crate::serialization::{PlatformDeserializableUntrusted, PlatformSerializable};
158
159 #[test]
160 fn test_extended_block_info_bincode() {
161 let block_info: ExtendedBlockInfo = ExtendedBlockInfoV0 {
162 basic_info: BlockInfo::default(),
163 app_hash: [1; 32],
164 quorum_hash: [2; 32],
165 block_id_hash: [3; 32],
166 proposer_pro_tx_hash: [4; 32],
167 signature: [3; 96],
168 round: 1,
169 }
170 .into();
171
172 let encoded =
174 PlatformSerializable::serialize_to_bytes(&block_info).expect("expected to serialize");
175
176 let decoded: ExtendedBlockInfo =
178 PlatformDeserializableUntrusted::deserialize_from_bytes_untrusted(&encoded)
179 .expect("expected to deserialize");
180
181 assert_eq!(block_info, decoded);
182 }
183}
184
185#[cfg(all(
188 test,
189 feature = "json-conversion",
190 feature = "value-conversion",
191 feature = "serde-conversion"
192))]
193mod json_convertible_tests_extendedblockinfo {
194 use super::*;
195 use crate::block::block_info::BlockInfo;
196 use crate::block::extended_block_info::v0::ExtendedBlockInfoV0;
197 use platform_value::platform_value;
198 use serde_json::json;
199
200 fn fixture() -> ExtendedBlockInfo {
201 ExtendedBlockInfo::V0(ExtendedBlockInfoV0 {
202 basic_info: BlockInfo::default(),
203 app_hash: [0x11; 32],
204 quorum_hash: [0x22; 32],
205 block_id_hash: [0x33; 32],
206 proposer_pro_tx_hash: [0x44; 32],
207 signature: [0x55; 96],
208 round: 3,
209 })
210 }
211
212 #[test]
213 fn json_round_trip_with_full_wire_shape() {
214 use crate::serialization::JsonConvertible;
215 let original = fixture();
216 let json = original.to_json().expect("to_json");
217 assert_eq!(
223 json,
224 json!({
225 "$formatVersion": "0",
226 "basicInfo": {
227 "timeMs": 0,
228 "height": 0,
229 "coreHeight": 0,
230 "epoch": {"index": 0},
231 },
232 "appHash": "ERERERERERERERERERERERERERERERERERERERERERE=",
233 "quorumHash": "IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI=",
234 "blockIdHash": "MzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM=",
235 "proposerProTxHash": "REREREREREREREREREREREREREREREREREREREREREQ=",
236 "signature": "VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
237 "round": 3,
238 })
239 );
240 let recovered = ExtendedBlockInfo::from_json(json).expect("from_json");
241 assert_eq!(original, recovered);
242 }
243
244 #[test]
245 fn value_round_trip_with_full_wire_shape() {
246 use crate::serialization::ValueConvertible;
247 use platform_value::Value;
248 let original = fixture();
249 let value = original.to_object().expect("to_object");
250 assert_eq!(
254 value,
255 platform_value!({
256 "$formatVersion": "0",
257 "basicInfo": {
258 "timeMs": 0u64,
259 "height": 0u64,
260 "coreHeight": 0u32,
261 "epoch": {"index": 0u16},
262 },
263 "appHash": Value::Bytes32([0x11; 32]),
264 "quorumHash": Value::Bytes32([0x22; 32]),
265 "blockIdHash": Value::Bytes32([0x33; 32]),
266 "proposerProTxHash": Value::Bytes32([0x44; 32]),
267 "signature": Value::Bytes(vec![0x55; 96]),
268 "round": 3u32,
269 })
270 );
271 let recovered = ExtendedBlockInfo::from_object(value).expect("from_object");
272 assert_eq!(original, recovered);
273 }
274}