1use iota_protocol_config::ProtocolVersion;
6use iota_types::{
7 base_types::{AuthorityName, TransactionDigest},
8 committee::{EpochId, StakeUnit},
9 crypto::AggregateAuthoritySignature,
10 digests::{CheckpointDigest, Digest},
11 gas::GasCostSummary,
12 iota_serde::BigInt,
13 message_envelope::Message,
14 messages_checkpoint::{
15 CheckpointCommitment, CheckpointContents, CheckpointSequenceNumber, CheckpointSummary,
16 CheckpointTimestamp, ECMHLiveObjectSetDigest, EndOfEpochData,
17 },
18};
19use schemars::JsonSchema;
20use serde::{Deserialize, Serialize};
21use serde_with::{DeserializeAs, DisplayFromStr, SerializeAs, serde_as};
22
23use crate::{
24 IotaAuthorityPublicKeyBytes, Page,
25 iota_gas_cost_summary::IotaGasCostSummary,
26 iota_primitives::{
27 Base58 as Base58Schema, Base64 as Base64Schema, ProtocolVersion as ProtocolVersionSchema,
28 },
29};
30pub type CheckpointPage = Page<Checkpoint, BigInt<u64>>;
31
32#[serde_as]
33#[derive(Clone, Debug, JsonSchema, Serialize, Deserialize, PartialEq, Eq)]
34#[serde(rename_all = "camelCase")]
35pub struct Checkpoint {
36 #[schemars(with = "String")]
38 #[serde_as(as = "DisplayFromStr")]
39 pub epoch: EpochId,
40 #[schemars(with = "String")]
42 #[serde_as(as = "DisplayFromStr")]
43 pub sequence_number: CheckpointSequenceNumber,
44 #[schemars(with = "Base58Schema")]
46 pub digest: CheckpointDigest,
47 #[schemars(with = "String")]
50 #[serde_as(as = "DisplayFromStr")]
51 pub network_total_transactions: u64,
52 #[serde(skip_serializing_if = "Option::is_none")]
54 #[schemars(with = "Option<Base58Schema>")]
55 pub previous_digest: Option<CheckpointDigest>,
56 #[schemars(with = "IotaGasCostSummary")]
59 #[serde_as(as = "IotaGasCostSummary")]
60 pub epoch_rolling_gas_cost_summary: GasCostSummary,
61 #[schemars(with = "String")]
66 #[serde_as(as = "DisplayFromStr")]
67 pub timestamp_ms: CheckpointTimestamp,
68 #[serde(skip_serializing_if = "Option::is_none")]
70 #[schemars(with = "Option<EndOfEpochDataSchema>")]
71 #[serde_as(as = "Option<EndOfEpochDataSchema>")]
72 pub end_of_epoch_data: Option<EndOfEpochData>,
73 #[schemars(with = "Vec<Base58Schema>")]
75 pub transactions: Vec<TransactionDigest>,
76
77 #[schemars(with = "Vec<CheckpointCommitmentSchema>")]
79 #[serde_as(as = "Vec<CheckpointCommitmentSchema>")]
80 pub checkpoint_commitments: Vec<CheckpointCommitment>,
81 #[schemars(with = "Base64Schema")]
83 pub validator_signature: AggregateAuthoritySignature,
84}
85
86impl
87 From<(
88 CheckpointSummary,
89 CheckpointContents,
90 AggregateAuthoritySignature,
91 )> for Checkpoint
92{
93 fn from(
94 (summary, contents, signature): (
95 CheckpointSummary,
96 CheckpointContents,
97 AggregateAuthoritySignature,
98 ),
99 ) -> Self {
100 let digest = summary.digest();
101 let CheckpointSummary {
102 epoch,
103 sequence_number,
104 network_total_transactions,
105 previous_digest,
106 epoch_rolling_gas_cost_summary,
107 timestamp_ms,
108 end_of_epoch_data,
109 ..
110 } = summary;
111
112 Checkpoint {
113 epoch,
114 sequence_number,
115 digest,
116 network_total_transactions,
117 previous_digest,
118 epoch_rolling_gas_cost_summary,
119 timestamp_ms,
120 end_of_epoch_data,
121 transactions: contents.iter().map(|digest| digest.transaction).collect(),
122 checkpoint_commitments: Default::default(),
126 validator_signature: signature,
127 }
128 }
129}
130
131#[serde_as]
132#[derive(Serialize, Deserialize, JsonSchema)]
133#[serde(rename_all = "camelCase", rename = "EndOfEpochData")]
134pub struct EndOfEpochDataSchema {
135 #[schemars(with = "Vec<(IotaAuthorityPublicKeyBytes, String)>")]
144 #[serde_as(as = "Vec<(_, DisplayFromStr)>")]
145 pub next_epoch_committee: Vec<(AuthorityName, StakeUnit)>,
146
147 #[schemars(with = "ProtocolVersionSchema")]
150 #[serde_as(as = "ProtocolVersionSchema")]
151 pub next_epoch_protocol_version: ProtocolVersion,
152
153 pub epoch_commitments: Vec<CheckpointCommitmentSchema>,
155
156 pub epoch_supply_change: i64,
159}
160
161impl SerializeAs<EndOfEpochData> for EndOfEpochDataSchema {
162 fn serialize_as<S>(source: &EndOfEpochData, serializer: S) -> Result<S::Ok, S::Error>
163 where
164 S: serde::Serializer,
165 {
166 let iota_data = EndOfEpochDataSchema::from(source.clone());
167 iota_data.serialize(serializer)
168 }
169}
170
171impl<'de> DeserializeAs<'de, EndOfEpochData> for EndOfEpochDataSchema {
172 fn deserialize_as<D>(deserializer: D) -> Result<EndOfEpochData, D::Error>
173 where
174 D: serde::Deserializer<'de>,
175 {
176 let iota_data = EndOfEpochDataSchema::deserialize(deserializer)?;
177 Ok(iota_data.into())
178 }
179}
180
181impl From<EndOfEpochDataSchema> for EndOfEpochData {
182 fn from(iota_data: EndOfEpochDataSchema) -> Self {
183 let EndOfEpochDataSchema {
184 next_epoch_committee,
185 next_epoch_protocol_version,
186 epoch_commitments,
187 epoch_supply_change,
188 } = iota_data;
189 EndOfEpochData {
190 next_epoch_committee: next_epoch_committee.into_iter().collect(),
191 next_epoch_protocol_version,
192 epoch_commitments: epoch_commitments.into_iter().map(Into::into).collect(),
193 epoch_supply_change,
194 }
195 }
196}
197
198impl From<EndOfEpochData> for EndOfEpochDataSchema {
199 fn from(data: EndOfEpochData) -> Self {
200 let EndOfEpochData {
201 next_epoch_committee,
202 next_epoch_protocol_version,
203 epoch_commitments,
204 epoch_supply_change,
205 } = data;
206 EndOfEpochDataSchema {
207 next_epoch_committee: next_epoch_committee.into_iter().collect(),
208 next_epoch_protocol_version,
209 epoch_commitments: epoch_commitments.into_iter().map(Into::into).collect(),
210 epoch_supply_change,
211 }
212 }
213}
214
215#[serde_as]
216#[derive(Serialize, Deserialize, JsonSchema)]
217#[schemars(rename = "CheckpointCommitment")]
218pub enum CheckpointCommitmentSchema {
219 ECMHLiveObjectSetDigest(
220 #[schemars(with = "ECMHLiveObjectSetDigestSchema")]
221 #[serde_as(as = "ECMHLiveObjectSetDigestSchema")]
222 ECMHLiveObjectSetDigest,
223 ),
224}
225
226impl SerializeAs<CheckpointCommitment> for CheckpointCommitmentSchema {
227 fn serialize_as<S>(source: &CheckpointCommitment, serializer: S) -> Result<S::Ok, S::Error>
228 where
229 S: serde::Serializer,
230 {
231 let iota_commitment = CheckpointCommitmentSchema::from(source.clone());
232 iota_commitment.serialize(serializer)
233 }
234}
235
236impl<'de> DeserializeAs<'de, CheckpointCommitment> for CheckpointCommitmentSchema {
237 fn deserialize_as<D>(deserializer: D) -> Result<CheckpointCommitment, D::Error>
238 where
239 D: serde::Deserializer<'de>,
240 {
241 let iota_commitment = CheckpointCommitmentSchema::deserialize(deserializer)?;
242 Ok(iota_commitment.into())
243 }
244}
245
246impl From<CheckpointCommitmentSchema> for CheckpointCommitment {
247 fn from(iota_commitment: CheckpointCommitmentSchema) -> Self {
248 match iota_commitment {
249 CheckpointCommitmentSchema::ECMHLiveObjectSetDigest(digest) => {
250 CheckpointCommitment::ECMHLiveObjectSetDigest(digest)
251 }
252 }
253 }
254}
255
256impl From<CheckpointCommitment> for CheckpointCommitmentSchema {
257 fn from(commitment: CheckpointCommitment) -> Self {
258 match commitment {
259 CheckpointCommitment::ECMHLiveObjectSetDigest(digest) => {
260 CheckpointCommitmentSchema::ECMHLiveObjectSetDigest(digest)
261 }
262 }
263 }
264}
265
266#[derive(Serialize, Deserialize, JsonSchema)]
269#[serde(rename = "ECMHLiveObjectSetDigest")]
270pub struct ECMHLiveObjectSetDigestSchema {
271 #[schemars(with = "[u8; 32]")]
272 pub digest: Digest,
273}
274
275impl SerializeAs<ECMHLiveObjectSetDigest> for ECMHLiveObjectSetDigestSchema {
276 fn serialize_as<S>(source: &ECMHLiveObjectSetDigest, serializer: S) -> Result<S::Ok, S::Error>
277 where
278 S: serde::Serializer,
279 {
280 let iota_digest = ECMHLiveObjectSetDigestSchema::from(source.clone());
281 iota_digest.serialize(serializer)
282 }
283}
284
285impl<'de> DeserializeAs<'de, ECMHLiveObjectSetDigest> for ECMHLiveObjectSetDigestSchema {
286 fn deserialize_as<D>(deserializer: D) -> Result<ECMHLiveObjectSetDigest, D::Error>
287 where
288 D: serde::Deserializer<'de>,
289 {
290 let iota_digest = ECMHLiveObjectSetDigestSchema::deserialize(deserializer)?;
291 Ok(iota_digest.into())
292 }
293}
294
295impl From<ECMHLiveObjectSetDigestSchema> for ECMHLiveObjectSetDigest {
296 fn from(iota_digest: ECMHLiveObjectSetDigestSchema) -> Self {
297 Self {
298 digest: iota_digest.digest,
299 }
300 }
301}
302
303impl From<ECMHLiveObjectSetDigest> for ECMHLiveObjectSetDigestSchema {
304 fn from(digest: ECMHLiveObjectSetDigest) -> Self {
305 Self {
306 digest: digest.digest,
307 }
308 }
309}
310
311#[serde_as]
312#[derive(Clone, Copy, Debug, JsonSchema, Serialize, Deserialize)]
313#[serde(untagged)]
314pub enum CheckpointId {
315 SequenceNumber(
316 #[schemars(with = "String")]
317 #[serde_as(as = "DisplayFromStr")]
318 CheckpointSequenceNumber,
319 ),
320 Digest(#[schemars(with = "Base58Schema")] CheckpointDigest),
321}
322
323impl From<CheckpointSequenceNumber> for CheckpointId {
324 fn from(seq: CheckpointSequenceNumber) -> Self {
325 Self::SequenceNumber(seq)
326 }
327}
328
329impl From<CheckpointDigest> for CheckpointId {
330 fn from(digest: CheckpointDigest) -> Self {
331 Self::Digest(digest)
332 }
333}