• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

input-output-hk / catalyst-libs / 16054905839

03 Jul 2025 03:45PM UTC coverage: 65.701% (+0.02%) from 65.683%
16054905839

Pull #405

github

web-flow
Merge 30c505c79 into 31f00a4a8
Pull Request #405: fix(rust/rbac-registration): Fix `validate_txn_inputs_hash` error message

0 of 1 new or added line in 1 file covered. (0.0%)

6 existing lines in 2 files now uncovered.

10972 of 16700 relevant lines covered (65.7%)

2614.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/rust/cardano-chain-follower/src/stats/rollback.rs
1
//! Rollback statistics.
2

3
use std::sync::{Arc, LazyLock, RwLock};
4

5
use cardano_blockchain_types::Network;
6
use dashmap::DashMap;
7
use serde::Serialize;
8
use strum::{EnumIter, IntoEnumIterator};
9
use tracing::error;
10

11
/// Statistics related to a single depth of rollback
12
#[derive(Debug, Default, Clone, Serialize)]
13
pub struct Rollback {
14
    /// How deep was the rollback from tip.
15
    pub depth: u64,
16
    /// How many times has a rollback been this deep.
17
    pub count: u64,
18
}
19

20
/// Statistics for all our known rollback types
21
/// Rollback Vec is sorted by depth, ascending.
22
#[derive(Debug, Default, Clone, Serialize)]
23
pub struct Rollbacks {
24
    /// These are the ACTUAL rollbacks we did on our live-chain in memory.
25
    pub live: Vec<Rollback>,
26
    /// These are the rollbacks reported by the Peer Node, which may not == an actual
27
    /// rollback on our internal live chain.
28
    pub peer: Vec<Rollback>,
29
    /// These are the rollbacks synthesized for followers, based on their reading of the
30
    /// chain tip.
31
    pub follower: Vec<Rollback>,
32
}
33

34
/// The types of rollbacks we track for a chain.
35
#[derive(EnumIter, Eq, Ord, PartialEq, PartialOrd, Copy, Clone, Hash)]
×
36
#[allow(clippy::module_name_repetitions)]
37
pub enum RollbackType {
38
    /// Rollback on the in-memory live chain.
39
    LiveChain,
40
    /// Rollback signaled by the peer.
41
    Peer,
42
    /// Rollback synthesized for the Follower.
43
    Follower,
44
}
45

46
/// Individual rollback records.
47
type RollbackRecords = DashMap<u64, Rollback>;
48
/// Rollback Records per rollback type.
49
type RollbackTypeMap = DashMap<RollbackType, Arc<RwLock<RollbackRecords>>>;
50
/// Record of rollbacks.
51
type RollbackMap = DashMap<Network, RollbackTypeMap>;
52

53
/// Statistics of rollbacks detected per chain.
54
static ROLLBACKS_MAP: LazyLock<RollbackMap> = LazyLock::new(|| {
×
55
    let map = RollbackMap::new();
×
56
    for network in Network::iter() {
×
57
        let type_map = RollbackTypeMap::new();
×
58
        for rollback in RollbackType::iter() {
×
59
            type_map.insert(rollback, Arc::new(RwLock::new(RollbackRecords::new())));
×
60
        }
×
61
        map.insert(network, type_map);
×
62
    }
63
    map
×
64
});
×
65

66
/// Get the actual rollback map for a chain.
67
fn lookup_rollback_map(
×
68
    chain: Network, rollback: RollbackType,
×
69
) -> Option<Arc<RwLock<RollbackRecords>>> {
×
70
    let Some(chain_rollback_map) = ROLLBACKS_MAP.get(&chain) else {
×
71
        error!("Rollback stats SHOULD BE exhaustively pre-allocated.");
×
72
        return None;
×
73
    };
74
    let chain_rollback_map = chain_rollback_map.value();
×
75

76
    let Some(rollback_map) = chain_rollback_map.get(&rollback) else {
×
77
        error!("Rollback stats SHOULD BE exhaustively pre-allocated.");
×
78
        return None;
×
79
    };
80
    let rollback_map = rollback_map.value();
×
81

×
82
    Some(rollback_map.clone())
×
83
}
×
84

85
/// Extract the current rollback stats as a vec.
86
pub(crate) fn rollbacks(chain: Network, rollback: RollbackType) -> Vec<Rollback> {
×
87
    let Some(rollback_map) = lookup_rollback_map(chain, rollback) else {
×
88
        return Vec::new();
×
89
    };
90

91
    let Ok(rollback_values) = rollback_map.read() else {
×
92
        error!("Rollback stats LOCK Poisoned, should not happen.");
×
93
        return vec![];
×
94
    };
95

96
    let mut rollbacks = Vec::new();
×
97

98
    // Get all the rollback stats.
99
    for stat in rollback_values.iter() {
×
100
        rollbacks.push(stat.value().clone());
×
101
    }
×
102

103
    rollbacks
×
104
}
×
105

106
/// Reset ALL the rollback stats for a given blockchain.
107
pub(crate) fn rollbacks_reset(chain: Network, rollback: RollbackType) -> Vec<Rollback> {
×
108
    let Some(rollback_map) = lookup_rollback_map(chain, rollback) else {
×
109
        return Vec::new();
×
110
    };
111

112
    let Ok(rollbacks) = rollback_map.write() else {
×
113
        error!("Rollback stats LOCK Poisoned, should not happen.");
×
114
        return vec![];
×
115
    };
116

117
    rollbacks.clear();
×
118

×
119
    Vec::new()
×
120
}
×
121

122
/// Count a rollback
123
pub(crate) fn rollback(chain: Network, rollback: RollbackType, depth: u64) {
×
124
    let Some(rollback_map) = lookup_rollback_map(chain, rollback) else {
×
125
        return;
×
126
    };
127

128
    let Ok(rollbacks) = rollback_map.write() else {
×
129
        error!("Rollback stats LOCK Poisoned, should not happen.");
×
130
        return;
×
131
    };
132

133
    let mut value = match rollbacks.get(&depth) {
×
134
        Some(value_entry) => (*value_entry.value()).clone(),
×
135
        None => Rollback { depth, count: 0 },
×
136
    };
137

138
    value.count = value.count.saturating_add(1);
×
139

×
140
    let _unused = rollbacks.insert(depth, value);
×
141
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc