1use diesel::prelude::*;
5
6use sui_json_rpc_types::Checkpoint as RpcCheckpoint;
7use sui_types::base_types::TransactionDigest;
8use sui_types::digests::CheckpointDigest;
9use sui_types::gas::GasCostSummary;
10
11use crate::errors::IndexerError;
12use crate::schema::{chain_identifier, checkpoints, pruner_cp_watermark};
13use crate::types::IndexedCheckpoint;
14
15#[derive(Queryable, Insertable, Selectable, Debug, Clone, Default)]
16#[diesel(table_name = chain_identifier)]
17pub struct StoredChainIdentifier {
18 pub checkpoint_digest: Vec<u8>,
19}
20
21#[derive(Queryable, Insertable, Selectable, Debug, Clone, Default)]
22#[diesel(table_name = checkpoints)]
23pub struct StoredCheckpoint {
24 pub sequence_number: i64,
25 pub checkpoint_digest: Vec<u8>,
26 pub epoch: i64,
27 pub network_total_transactions: i64,
28 pub previous_checkpoint_digest: Option<Vec<u8>>,
29 pub end_of_epoch: bool,
30 pub tx_digests: Vec<Option<Vec<u8>>>,
31 pub timestamp_ms: i64,
32 pub total_gas_cost: i64,
33 pub computation_cost: i64,
34 pub storage_cost: i64,
35 pub storage_rebate: i64,
36 pub non_refundable_storage_fee: i64,
37 pub checkpoint_commitments: Vec<u8>,
38 pub validator_signature: Vec<u8>,
39 pub end_of_epoch_data: Option<Vec<u8>>,
40 pub min_tx_sequence_number: Option<i64>,
41 pub max_tx_sequence_number: Option<i64>,
42}
43
44impl From<&IndexedCheckpoint> for StoredCheckpoint {
45 fn from(c: &IndexedCheckpoint) -> Self {
46 Self {
47 sequence_number: c.sequence_number as i64,
48 checkpoint_digest: c.checkpoint_digest.into_inner().to_vec(),
49 epoch: c.epoch as i64,
50 tx_digests: c
51 .tx_digests
52 .iter()
53 .map(|tx| Some(tx.into_inner().to_vec()))
54 .collect(),
55 network_total_transactions: c.network_total_transactions as i64,
56 previous_checkpoint_digest: c
57 .previous_checkpoint_digest
58 .as_ref()
59 .map(|d| (*d).into_inner().to_vec()),
60 timestamp_ms: c.timestamp_ms as i64,
61 total_gas_cost: c.total_gas_cost,
62 computation_cost: c.computation_cost as i64,
63 storage_cost: c.storage_cost as i64,
64 storage_rebate: c.storage_rebate as i64,
65 non_refundable_storage_fee: c.non_refundable_storage_fee as i64,
66 checkpoint_commitments: bcs::to_bytes(&c.checkpoint_commitments).unwrap(),
67 validator_signature: bcs::to_bytes(&c.validator_signature).unwrap(),
68 end_of_epoch_data: c
69 .end_of_epoch_data
70 .as_ref()
71 .map(|d| bcs::to_bytes(d).unwrap()),
72 end_of_epoch: c.end_of_epoch_data.is_some(),
73 min_tx_sequence_number: Some(c.min_tx_sequence_number as i64),
74 max_tx_sequence_number: Some(c.max_tx_sequence_number as i64),
75 }
76 }
77}
78
79impl TryFrom<StoredCheckpoint> for RpcCheckpoint {
80 type Error = IndexerError;
81 fn try_from(checkpoint: StoredCheckpoint) -> Result<RpcCheckpoint, IndexerError> {
82 let parsed_digest = CheckpointDigest::try_from(checkpoint.checkpoint_digest.clone())
83 .map_err(|e| {
84 IndexerError::PersistentStorageDataCorruptionError(format!(
85 "Failed to decode checkpoint digest: {:?} with err: {:?}",
86 checkpoint.checkpoint_digest, e
87 ))
88 })?;
89
90 let parsed_previous_digest: Option<CheckpointDigest> = checkpoint
91 .previous_checkpoint_digest
92 .map(|digest| {
93 CheckpointDigest::try_from(digest.clone()).map_err(|e| {
94 IndexerError::PersistentStorageDataCorruptionError(format!(
95 "Failed to decode previous checkpoint digest: {:?} with err: {:?}",
96 digest, e
97 ))
98 })
99 })
100 .transpose()?;
101
102 let transactions: Vec<TransactionDigest> = {
103 checkpoint
104 .tx_digests
105 .into_iter()
106 .map(|tx_digest| match tx_digest {
107 None => Err(IndexerError::PersistentStorageDataCorruptionError(
108 "tx_digests should not contain null elements".to_string(),
109 )),
110 Some(tx_digest) => {
111 TransactionDigest::try_from(tx_digest.as_slice()).map_err(|e| {
112 IndexerError::PersistentStorageDataCorruptionError(format!(
113 "Failed to decode transaction digest: {:?} with err: {:?}",
114 tx_digest, e
115 ))
116 })
117 }
118 })
119 .collect::<Result<Vec<TransactionDigest>, IndexerError>>()?
120 };
121 let validator_signature =
122 bcs::from_bytes(&checkpoint.validator_signature).map_err(|e| {
123 IndexerError::PersistentStorageDataCorruptionError(format!(
124 "Failed to decode validator signature: {:?} with err: {:?}",
125 checkpoint.validator_signature, e
126 ))
127 })?;
128
129 let checkpoint_commitments =
130 bcs::from_bytes(&checkpoint.checkpoint_commitments).map_err(|e| {
131 IndexerError::PersistentStorageDataCorruptionError(format!(
132 "Failed to decode checkpoint commitments: {:?} with err: {:?}",
133 checkpoint.checkpoint_commitments, e
134 ))
135 })?;
136
137 let end_of_epoch_data = checkpoint
138 .end_of_epoch_data
139 .map(|data| {
140 bcs::from_bytes(&data).map_err(|e| {
141 IndexerError::PersistentStorageDataCorruptionError(format!(
142 "Failed to decode end of epoch data: {:?} with err: {:?}",
143 data, e
144 ))
145 })
146 })
147 .transpose()?;
148
149 Ok(RpcCheckpoint {
150 epoch: checkpoint.epoch as u64,
151 sequence_number: checkpoint.sequence_number as u64,
152 digest: parsed_digest,
153 previous_digest: parsed_previous_digest,
154 end_of_epoch_data,
155 epoch_rolling_gas_cost_summary: GasCostSummary {
156 computation_cost: checkpoint.computation_cost as u64,
157 storage_cost: checkpoint.storage_cost as u64,
158 storage_rebate: checkpoint.storage_rebate as u64,
159 non_refundable_storage_fee: checkpoint.non_refundable_storage_fee as u64,
160 },
161 network_total_transactions: checkpoint.network_total_transactions as u64,
162 timestamp_ms: checkpoint.timestamp_ms as u64,
163 transactions,
164 validator_signature,
165 checkpoint_commitments,
166 })
167 }
168}
169
170#[derive(Queryable, Insertable, Selectable, Debug, Clone, Default)]
171#[diesel(table_name = pruner_cp_watermark)]
172pub struct StoredCpTx {
173 pub checkpoint_sequence_number: i64,
174 pub min_tx_sequence_number: i64,
175 pub max_tx_sequence_number: i64,
176}
177
178impl From<&IndexedCheckpoint> for StoredCpTx {
179 fn from(c: &IndexedCheckpoint) -> Self {
180 Self {
181 checkpoint_sequence_number: c.sequence_number as i64,
182 min_tx_sequence_number: c.min_tx_sequence_number as i64,
183 max_tx_sequence_number: c.max_tx_sequence_number as i64,
184 }
185 }
186}