sui_analytics_indexer/handlers/
checkpoint_handler.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use fastcrypto::traits::EncodeDecodeBase64;
use std::sync::Arc;

use sui_types::effects::TransactionEffectsAPI;
use sui_types::full_checkpoint_content::CheckpointData;
use sui_types::messages_checkpoint::CheckpointSummary;
use sui_types::transaction::TransactionDataAPI;

use crate::handlers::AnalyticsHandler;
use crate::tables::CheckpointEntry;
use crate::FileType;

pub struct CheckpointHandler {}

impl CheckpointHandler {
    pub fn new() -> Self {
        CheckpointHandler {}
    }
}

#[async_trait::async_trait]
impl AnalyticsHandler<CheckpointEntry> for CheckpointHandler {
    async fn process_checkpoint(
        &self,
        checkpoint_data: &Arc<CheckpointData>,
    ) -> Result<Box<dyn Iterator<Item = CheckpointEntry> + Send + Sync>> {
        let checkpoint_entry = process_checkpoint_data(checkpoint_data);
        Ok(Box::new(std::iter::once(checkpoint_entry)))
    }

    fn file_type(&self) -> Result<FileType> {
        Ok(FileType::Checkpoint)
    }

    fn name(&self) -> &'static str {
        "checkpoint"
    }
}

fn process_checkpoint_data(checkpoint_data: &CheckpointData) -> CheckpointEntry {
    let CheckpointSummary {
        epoch,
        sequence_number,
        network_total_transactions,
        previous_digest,
        epoch_rolling_gas_cost_summary,
        timestamp_ms,
        end_of_epoch_data,
        ..
    } = checkpoint_data.checkpoint_summary.data();

    let total_gas_cost = epoch_rolling_gas_cost_summary.computation_cost as i64
        + epoch_rolling_gas_cost_summary.storage_cost as i64
        - epoch_rolling_gas_cost_summary.storage_rebate as i64;
    let total_transaction_blocks = checkpoint_data.transactions.len() as u64;
    let mut total_transactions: u64 = 0;
    let mut total_successful_transaction_blocks: u64 = 0;
    let mut total_successful_transactions: u64 = 0;
    for checkpoint_transaction in &checkpoint_data.transactions {
        let txn_data = checkpoint_transaction.transaction.transaction_data();
        let cmds = txn_data.kind().num_commands() as u64;
        total_transactions += cmds;
        if checkpoint_transaction.effects.status().is_ok() {
            total_successful_transaction_blocks += 1;
            total_successful_transactions += cmds;
        }
    }

    CheckpointEntry {
        sequence_number: *sequence_number,
        checkpoint_digest: checkpoint_data.checkpoint_summary.digest().base58_encode(),
        previous_checkpoint_digest: previous_digest.map(|d| d.base58_encode()),
        epoch: *epoch,
        end_of_epoch: end_of_epoch_data.is_some(),
        total_gas_cost,
        computation_cost: epoch_rolling_gas_cost_summary.computation_cost,
        storage_cost: epoch_rolling_gas_cost_summary.storage_cost,
        storage_rebate: epoch_rolling_gas_cost_summary.storage_rebate,
        non_refundable_storage_fee: epoch_rolling_gas_cost_summary.non_refundable_storage_fee,
        total_transaction_blocks,
        total_transactions,
        total_successful_transaction_blocks,
        total_successful_transactions,
        network_total_transaction: *network_total_transactions,
        timestamp_ms: *timestamp_ms,
        validator_signature: checkpoint_data
            .checkpoint_summary
            .auth_sig()
            .signature
            .encode_base64(),
    }
}