1use iota_protocol_config::ProtocolVersion;
6use iota_sdk_types::gas::GasCostSummary;
7use iota_types::{
8 base_types::{AuthorityName, TransactionDigest},
9 committee::{EpochId, StakeUnit},
10 crypto::AggregateAuthoritySignature,
11 digests::{CheckpointDigest, Digest},
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 #[serde_as(as = "Base58Schema")]
46 #[schemars(with = "Base58Schema")]
47 pub digest: CheckpointDigest,
48 #[schemars(with = "String")]
51 #[serde_as(as = "DisplayFromStr")]
52 pub network_total_transactions: u64,
53 #[serde(skip_serializing_if = "Option::is_none")]
55 #[serde_as(as = "Option<Base58Schema>")]
56 #[schemars(with = "Option<Base58Schema>")]
57 pub previous_digest: Option<CheckpointDigest>,
58 #[schemars(with = "IotaGasCostSummary")]
61 #[serde_as(as = "IotaGasCostSummary")]
62 pub epoch_rolling_gas_cost_summary: GasCostSummary,
63 #[schemars(with = "String")]
68 #[serde_as(as = "DisplayFromStr")]
69 pub timestamp_ms: CheckpointTimestamp,
70 #[serde(skip_serializing_if = "Option::is_none")]
72 #[schemars(with = "Option<EndOfEpochDataSchema>")]
73 #[serde_as(as = "Option<EndOfEpochDataSchema>")]
74 pub end_of_epoch_data: Option<EndOfEpochData>,
75 #[serde_as(as = "Vec<Base58Schema>")]
77 #[schemars(with = "Vec<Base58Schema>")]
78 pub transactions: Vec<TransactionDigest>,
79
80 #[schemars(with = "Vec<CheckpointCommitmentSchema>")]
82 #[serde_as(as = "Vec<CheckpointCommitmentSchema>")]
83 pub checkpoint_commitments: Vec<CheckpointCommitment>,
84 #[schemars(with = "Base64Schema")]
86 pub validator_signature: AggregateAuthoritySignature,
87}
88
89impl
90 From<(
91 CheckpointSummary,
92 CheckpointContents,
93 AggregateAuthoritySignature,
94 )> for Checkpoint
95{
96 fn from(
97 (summary, contents, signature): (
98 CheckpointSummary,
99 CheckpointContents,
100 AggregateAuthoritySignature,
101 ),
102 ) -> Self {
103 let digest = summary.digest();
104 let CheckpointSummary {
105 epoch,
106 sequence_number,
107 network_total_transactions,
108 previous_digest,
109 epoch_rolling_gas_cost_summary,
110 timestamp_ms,
111 end_of_epoch_data,
112 ..
113 } = summary;
114
115 Checkpoint {
116 epoch,
117 sequence_number,
118 digest,
119 network_total_transactions,
120 previous_digest,
121 epoch_rolling_gas_cost_summary,
122 timestamp_ms,
123 end_of_epoch_data,
124 transactions: contents.iter().map(|digest| digest.transaction).collect(),
125 checkpoint_commitments: Default::default(),
129 validator_signature: signature,
130 }
131 }
132}
133
134#[serde_as]
135#[derive(Serialize, Deserialize, JsonSchema)]
136#[serde(rename_all = "camelCase", rename = "EndOfEpochData")]
137pub struct EndOfEpochDataSchema {
138 #[schemars(with = "Vec<(IotaAuthorityPublicKeyBytes, String)>")]
147 #[serde_as(as = "Vec<(_, DisplayFromStr)>")]
148 pub next_epoch_committee: Vec<(AuthorityName, StakeUnit)>,
149
150 #[schemars(with = "ProtocolVersionSchema")]
153 #[serde_as(as = "ProtocolVersionSchema")]
154 pub next_epoch_protocol_version: ProtocolVersion,
155
156 pub epoch_commitments: Vec<CheckpointCommitmentSchema>,
158
159 pub epoch_supply_change: i64,
162}
163
164impl SerializeAs<EndOfEpochData> for EndOfEpochDataSchema {
165 fn serialize_as<S>(source: &EndOfEpochData, serializer: S) -> Result<S::Ok, S::Error>
166 where
167 S: serde::Serializer,
168 {
169 let iota_data = EndOfEpochDataSchema::from(source.clone());
170 iota_data.serialize(serializer)
171 }
172}
173
174impl<'de> DeserializeAs<'de, EndOfEpochData> for EndOfEpochDataSchema {
175 fn deserialize_as<D>(deserializer: D) -> Result<EndOfEpochData, D::Error>
176 where
177 D: serde::Deserializer<'de>,
178 {
179 let iota_data = EndOfEpochDataSchema::deserialize(deserializer)?;
180 Ok(iota_data.into())
181 }
182}
183
184impl From<EndOfEpochDataSchema> for EndOfEpochData {
185 fn from(iota_data: EndOfEpochDataSchema) -> Self {
186 let EndOfEpochDataSchema {
187 next_epoch_committee,
188 next_epoch_protocol_version,
189 epoch_commitments,
190 epoch_supply_change,
191 } = iota_data;
192 EndOfEpochData {
193 next_epoch_committee: next_epoch_committee.into_iter().collect(),
194 next_epoch_protocol_version,
195 epoch_commitments: epoch_commitments.into_iter().map(Into::into).collect(),
196 epoch_supply_change,
197 }
198 }
199}
200
201impl From<EndOfEpochData> for EndOfEpochDataSchema {
202 fn from(data: EndOfEpochData) -> Self {
203 let EndOfEpochData {
204 next_epoch_committee,
205 next_epoch_protocol_version,
206 epoch_commitments,
207 epoch_supply_change,
208 } = data;
209 EndOfEpochDataSchema {
210 next_epoch_committee: next_epoch_committee.into_iter().collect(),
211 next_epoch_protocol_version,
212 epoch_commitments: epoch_commitments.into_iter().map(Into::into).collect(),
213 epoch_supply_change,
214 }
215 }
216}
217
218#[serde_as]
219#[derive(Serialize, Deserialize, JsonSchema)]
220#[schemars(rename = "CheckpointCommitment")]
221pub enum CheckpointCommitmentSchema {
222 ECMHLiveObjectSetDigest(
223 #[schemars(with = "ECMHLiveObjectSetDigestSchema")]
224 #[serde_as(as = "ECMHLiveObjectSetDigestSchema")]
225 ECMHLiveObjectSetDigest,
226 ),
227}
228
229impl SerializeAs<CheckpointCommitment> for CheckpointCommitmentSchema {
230 fn serialize_as<S>(source: &CheckpointCommitment, serializer: S) -> Result<S::Ok, S::Error>
231 where
232 S: serde::Serializer,
233 {
234 let iota_commitment = CheckpointCommitmentSchema::from(source.clone());
235 iota_commitment.serialize(serializer)
236 }
237}
238
239impl<'de> DeserializeAs<'de, CheckpointCommitment> for CheckpointCommitmentSchema {
240 fn deserialize_as<D>(deserializer: D) -> Result<CheckpointCommitment, D::Error>
241 where
242 D: serde::Deserializer<'de>,
243 {
244 let iota_commitment = CheckpointCommitmentSchema::deserialize(deserializer)?;
245 Ok(iota_commitment.into())
246 }
247}
248
249impl From<CheckpointCommitmentSchema> for CheckpointCommitment {
250 fn from(iota_commitment: CheckpointCommitmentSchema) -> Self {
251 match iota_commitment {
252 CheckpointCommitmentSchema::ECMHLiveObjectSetDigest(digest) => {
253 CheckpointCommitment::ECMHLiveObjectSetDigest(digest)
254 }
255 }
256 }
257}
258
259impl From<CheckpointCommitment> for CheckpointCommitmentSchema {
260 fn from(commitment: CheckpointCommitment) -> Self {
261 match commitment {
262 CheckpointCommitment::ECMHLiveObjectSetDigest(digest) => {
263 CheckpointCommitmentSchema::ECMHLiveObjectSetDigest(digest)
264 }
265 }
266 }
267}
268
269#[derive(Serialize, Deserialize, JsonSchema)]
272#[serde(rename = "ECMHLiveObjectSetDigest")]
273pub struct ECMHLiveObjectSetDigestSchema {
274 #[schemars(with = "[u8; 32]")]
275 pub digest: Digest,
276}
277
278impl SerializeAs<ECMHLiveObjectSetDigest> for ECMHLiveObjectSetDigestSchema {
279 fn serialize_as<S>(source: &ECMHLiveObjectSetDigest, serializer: S) -> Result<S::Ok, S::Error>
280 where
281 S: serde::Serializer,
282 {
283 let iota_digest = ECMHLiveObjectSetDigestSchema::from(source.clone());
284 iota_digest.serialize(serializer)
285 }
286}
287
288impl<'de> DeserializeAs<'de, ECMHLiveObjectSetDigest> for ECMHLiveObjectSetDigestSchema {
289 fn deserialize_as<D>(deserializer: D) -> Result<ECMHLiveObjectSetDigest, D::Error>
290 where
291 D: serde::Deserializer<'de>,
292 {
293 let iota_digest = ECMHLiveObjectSetDigestSchema::deserialize(deserializer)?;
294 Ok(iota_digest.into())
295 }
296}
297
298impl From<ECMHLiveObjectSetDigestSchema> for ECMHLiveObjectSetDigest {
299 fn from(iota_digest: ECMHLiveObjectSetDigestSchema) -> Self {
300 Self {
301 digest: iota_digest.digest,
302 }
303 }
304}
305
306impl From<ECMHLiveObjectSetDigest> for ECMHLiveObjectSetDigestSchema {
307 fn from(digest: ECMHLiveObjectSetDigest) -> Self {
308 Self {
309 digest: digest.digest,
310 }
311 }
312}
313
314#[serde_as]
315#[derive(Clone, Copy, Debug, JsonSchema, Serialize, Deserialize)]
316#[serde(untagged)]
317pub enum CheckpointId {
318 SequenceNumber(
319 #[schemars(with = "String")]
320 #[serde_as(as = "DisplayFromStr")]
321 CheckpointSequenceNumber,
322 ),
323 Digest(
324 #[serde_as(as = "Base58Schema")]
325 #[schemars(with = "Base58Schema")]
326 CheckpointDigest,
327 ),
328}
329
330impl From<CheckpointSequenceNumber> for CheckpointId {
331 fn from(seq: CheckpointSequenceNumber) -> Self {
332 Self::SequenceNumber(seq)
333 }
334}
335
336impl From<CheckpointDigest> for CheckpointId {
337 fn from(digest: CheckpointDigest) -> Self {
338 Self::Digest(digest)
339 }
340}