1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use std::fmt::{Debug, Formatter};
4
5use crate::entities::{
6 Epoch, ProtocolMessage, ProtocolMessagePartKey, ProtocolParameters, ProtocolVersion,
7 SignedEntityType,
8};
9
10pub type CertificateListMessage = Vec<CertificateListItemMessage>;
12
13#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
15pub struct CertificateListItemMessageMetadata {
16 pub network: String,
19
20 #[serde(rename = "version")]
24 pub protocol_version: ProtocolVersion,
25
26 #[serde(rename = "parameters")]
29 pub protocol_parameters: ProtocolParameters,
30
31 pub initiated_at: DateTime<Utc>,
35
36 pub sealed_at: DateTime<Utc>,
40
41 pub total_signers: usize,
44}
45
46#[derive(Clone, PartialEq, Serialize, Deserialize)]
48pub struct CertificateListItemMessage {
49 pub hash: String,
53
54 pub previous_hash: String,
59
60 pub epoch: Epoch,
62
63 pub signed_entity_type: SignedEntityType,
66
67 pub metadata: CertificateListItemMessageMetadata,
70
71 pub protocol_message: ProtocolMessage,
74
75 pub signed_message: String,
78
79 pub aggregate_verification_key: String,
83}
84
85impl CertificateListItemMessage {
86 pub fn dummy() -> Self {
88 let mut protocol_message = ProtocolMessage::new();
89 protocol_message.set_message_part(
90 ProtocolMessagePartKey::SnapshotDigest,
91 "snapshot-digest-123".to_string(),
92 );
93 protocol_message.set_message_part(
94 ProtocolMessagePartKey::NextAggregateVerificationKey,
95 "next-avk-123".to_string(),
96 );
97 let epoch = Epoch(10);
98
99 Self {
100 hash: "hash".to_string(),
101 previous_hash: "previous_hash".to_string(),
102 epoch,
103 signed_entity_type: SignedEntityType::MithrilStakeDistribution(epoch),
104 metadata: CertificateListItemMessageMetadata {
105 network: "testnet".to_string(),
106 protocol_version: "0.1.0".to_string(),
107 protocol_parameters: ProtocolParameters::new(1000, 100, 0.123),
108 initiated_at: DateTime::parse_from_rfc3339("2024-02-12T13:11:47Z")
109 .unwrap()
110 .with_timezone(&Utc),
111 sealed_at: DateTime::parse_from_rfc3339("2024-02-12T13:12:57Z")
112 .unwrap()
113 .with_timezone(&Utc),
114 total_signers: 2,
115 },
116 protocol_message: protocol_message.clone(),
117 signed_message: "signed_message".to_string(),
118 aggregate_verification_key: "aggregate_verification_key".to_string(),
119 }
120 }
121}
122
123impl Debug for CertificateListItemMessage {
124 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
125 let should_be_exhaustive = f.alternate();
126 let mut debug = f.debug_struct("Certificate");
127 debug
128 .field("hash", &self.hash)
129 .field("previous_hash", &self.previous_hash)
130 .field("epoch", &format_args!("{:?}", self.epoch))
131 .field(
132 "signed_entity_type",
133 &format_args!("{:?}", self.signed_entity_type),
134 )
135 .field("metadata", &format_args!("{:?}", self.metadata))
136 .field(
137 "protocol_message",
138 &format_args!("{:?}", self.protocol_message),
139 )
140 .field("signed_message", &self.signed_message);
141
142 match should_be_exhaustive {
143 true => debug
144 .field(
145 "aggregate_verification_key",
146 &self.aggregate_verification_key,
147 )
148 .finish(),
149 false => debug.finish_non_exhaustive(),
150 }
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use crate::entities::CardanoDbBeacon;
157
158 use super::*;
159
160 const CURRENT_JSON: &str = r#"[{
161 "hash": "hash",
162 "previous_hash": "previous_hash",
163 "epoch": 10,
164 "signed_entity_type": {
165 "CardanoImmutableFilesFull": {
166 "epoch": 10,
167 "immutable_file_number": 1728
168 }
169 },
170 "metadata": {
171 "network": "testnet",
172 "version": "0.1.0",
173 "parameters": {
174 "k": 1000,
175 "m": 100,
176 "phi_f": 0.123
177 },
178 "initiated_at": "2024-02-12T13:11:47Z",
179 "sealed_at": "2024-02-12T13:12:57Z",
180 "total_signers": 2
181 },
182 "protocol_message": {
183 "message_parts": {
184 "snapshot_digest": "snapshot-digest-123",
185 "next_aggregate_verification_key": "next-avk-123"
186 }
187 },
188 "signed_message": "signed_message",
189 "aggregate_verification_key": "aggregate_verification_key"
190 }]"#;
191
192 fn golden_current_message() -> CertificateListItemMessage {
193 let mut protocol_message = ProtocolMessage::new();
194 protocol_message.set_message_part(
195 ProtocolMessagePartKey::SnapshotDigest,
196 "snapshot-digest-123".to_string(),
197 );
198 protocol_message.set_message_part(
199 ProtocolMessagePartKey::NextAggregateVerificationKey,
200 "next-avk-123".to_string(),
201 );
202 let epoch = Epoch(10);
203
204 CertificateListItemMessage {
205 hash: "hash".to_string(),
206 previous_hash: "previous_hash".to_string(),
207 epoch,
208 signed_entity_type: SignedEntityType::CardanoImmutableFilesFull(CardanoDbBeacon::new(
209 *epoch, 1728,
210 )),
211 metadata: CertificateListItemMessageMetadata {
212 network: "testnet".to_string(),
213 protocol_version: "0.1.0".to_string(),
214 protocol_parameters: ProtocolParameters::new(1000, 100, 0.123),
215 initiated_at: DateTime::parse_from_rfc3339("2024-02-12T13:11:47Z")
216 .unwrap()
217 .with_timezone(&Utc),
218 sealed_at: DateTime::parse_from_rfc3339("2024-02-12T13:12:57Z")
219 .unwrap()
220 .with_timezone(&Utc),
221 total_signers: 2,
222 },
223 protocol_message: protocol_message.clone(),
224 signed_message: "signed_message".to_string(),
225 aggregate_verification_key: "aggregate_verification_key".to_string(),
226 }
227 }
228
229 #[test]
230 fn test_current_json_deserialized_into_current_message() {
231 let json = CURRENT_JSON;
232 let message: CertificateListMessage = serde_json::from_str(json).unwrap();
233
234 assert_eq!(vec![golden_current_message()], message);
235 }
236}