sui_analytics_indexer/handlers/
checkpoint_handler.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use anyhow::Result;
5use fastcrypto::traits::EncodeDecodeBase64;
6use std::sync::Arc;
7
8use sui_types::effects::TransactionEffectsAPI;
9use sui_types::full_checkpoint_content::CheckpointData;
10use sui_types::messages_checkpoint::CheckpointSummary;
11use sui_types::transaction::TransactionDataAPI;
12
13use crate::FileType;
14use crate::handlers::AnalyticsHandler;
15use crate::tables::CheckpointEntry;
16
17pub struct CheckpointHandler {}
18
19impl CheckpointHandler {
20    pub fn new() -> Self {
21        CheckpointHandler {}
22    }
23}
24
25#[async_trait::async_trait]
26impl AnalyticsHandler<CheckpointEntry> for CheckpointHandler {
27    async fn process_checkpoint(
28        &self,
29        checkpoint_data: &Arc<CheckpointData>,
30    ) -> Result<Box<dyn Iterator<Item = CheckpointEntry> + Send + Sync>> {
31        let checkpoint_entry = process_checkpoint_data(checkpoint_data);
32        Ok(Box::new(std::iter::once(checkpoint_entry)))
33    }
34
35    fn file_type(&self) -> Result<FileType> {
36        Ok(FileType::Checkpoint)
37    }
38
39    fn name(&self) -> &'static str {
40        "checkpoint"
41    }
42}
43
44fn process_checkpoint_data(checkpoint_data: &CheckpointData) -> CheckpointEntry {
45    let CheckpointSummary {
46        epoch,
47        sequence_number,
48        network_total_transactions,
49        previous_digest,
50        epoch_rolling_gas_cost_summary,
51        timestamp_ms,
52        end_of_epoch_data,
53        ..
54    } = checkpoint_data.checkpoint_summary.data();
55
56    let total_gas_cost = epoch_rolling_gas_cost_summary.computation_cost as i64
57        + epoch_rolling_gas_cost_summary.storage_cost as i64
58        - epoch_rolling_gas_cost_summary.storage_rebate as i64;
59    let total_transaction_blocks = checkpoint_data.transactions.len() as u64;
60    let mut total_transactions: u64 = 0;
61    let mut total_successful_transaction_blocks: u64 = 0;
62    let mut total_successful_transactions: u64 = 0;
63    for checkpoint_transaction in &checkpoint_data.transactions {
64        let txn_data = checkpoint_transaction.transaction.transaction_data();
65        let cmds = txn_data.kind().num_commands() as u64;
66        total_transactions += cmds;
67        if checkpoint_transaction.effects.status().is_ok() {
68            total_successful_transaction_blocks += 1;
69            total_successful_transactions += cmds;
70        }
71    }
72
73    CheckpointEntry {
74        sequence_number: *sequence_number,
75        checkpoint_digest: checkpoint_data.checkpoint_summary.digest().base58_encode(),
76        previous_checkpoint_digest: previous_digest.map(|d| d.base58_encode()),
77        epoch: *epoch,
78        end_of_epoch: end_of_epoch_data.is_some(),
79        total_gas_cost,
80        computation_cost: epoch_rolling_gas_cost_summary.computation_cost,
81        storage_cost: epoch_rolling_gas_cost_summary.storage_cost,
82        storage_rebate: epoch_rolling_gas_cost_summary.storage_rebate,
83        non_refundable_storage_fee: epoch_rolling_gas_cost_summary.non_refundable_storage_fee,
84        total_transaction_blocks,
85        total_transactions,
86        total_successful_transaction_blocks,
87        total_successful_transactions,
88        network_total_transaction: *network_total_transactions,
89        timestamp_ms: *timestamp_ms,
90        validator_signature: checkpoint_data
91            .checkpoint_summary
92            .auth_sig()
93            .signature
94            .encode_base64(),
95    }
96}