cfxcore/pos/consensus/
metrics_safety_rules.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4// Copyright 2021 Conflux Foundation. All rights reserved.
5// Conflux is free software and distributed under GNU General Public License.
6// See http://www.gnu.org/licenses/
7
8use super::persistent_liveness_storage::PersistentLivenessStorage;
9use consensus_types::{
10    block::Block, block_data::BlockData, timeout::Timeout, vote::Vote,
11    vote_proposal::MaybeSignedVoteProposal,
12};
13use diem_metrics::monitor;
14use diem_types::{
15    epoch_change::EpochChangeProof, validator_config::ConsensusSignature,
16};
17use safety_rules::{ConsensusState, Error, TSafetyRules};
18use std::sync::Arc;
19
20/// Wrap safety rules with counters.
21pub struct MetricsSafetyRules {
22    inner: Box<dyn TSafetyRules + Send + Sync>,
23    storage: Arc<dyn PersistentLivenessStorage>,
24}
25
26impl MetricsSafetyRules {
27    pub fn new(
28        inner: Box<dyn TSafetyRules + Send + Sync>,
29        storage: Arc<dyn PersistentLivenessStorage>,
30    ) -> Self {
31        Self { inner, storage }
32    }
33
34    pub fn perform_initialize(&mut self) -> Result<(), Error> {
35        let consensus_state = self.consensus_state()?;
36        let sr_waypoint = consensus_state.waypoint();
37        let proofs = self
38            .storage
39            .retrieve_epoch_change_proof(sr_waypoint.version())
40            .map_err(|e| {
41                Error::InternalError(format!(
42                    "Unable to retrieve Waypoint state from storage, encountered Error:{}",
43                    e
44                ))
45            })?;
46        self.initialize(&proofs)
47    }
48}
49
50impl TSafetyRules for MetricsSafetyRules {
51    fn consensus_state(&mut self) -> Result<ConsensusState, Error> {
52        monitor!("safety_rules", self.inner.consensus_state())
53    }
54
55    fn initialize(&mut self, proof: &EpochChangeProof) -> Result<(), Error> {
56        monitor!("safety_rules", self.inner.initialize(proof))
57    }
58
59    fn construct_and_sign_vote(
60        &mut self, vote_proposal: &MaybeSignedVoteProposal,
61    ) -> Result<Vote, Error> {
62        let mut result = monitor!(
63            "safety_rules",
64            self.inner.construct_and_sign_vote(vote_proposal)
65        );
66
67        if let Err(Error::NotInitialized(_res)) = result {
68            self.perform_initialize()?;
69            result = monitor!(
70                "safety_rules",
71                self.inner.construct_and_sign_vote(vote_proposal)
72            );
73        }
74        result
75    }
76
77    fn sign_proposal(&mut self, block_data: BlockData) -> Result<Block, Error> {
78        let mut result = monitor!(
79            "safety_rules",
80            self.inner.sign_proposal(block_data.clone())
81        );
82        if let Err(Error::NotInitialized(_res)) = result {
83            self.perform_initialize()?;
84            result =
85                monitor!("safety_rules", self.inner.sign_proposal(block_data));
86        }
87        result
88    }
89
90    fn sign_timeout(
91        &mut self, timeout: &Timeout,
92    ) -> Result<ConsensusSignature, Error> {
93        let mut result =
94            monitor!("safety_rules", self.inner.sign_timeout(timeout));
95        if let Err(Error::NotInitialized(_res)) = result {
96            self.perform_initialize()?;
97            result = monitor!("safety_rules", self.inner.sign_timeout(timeout));
98        }
99        result
100    }
101
102    fn start_voting(&mut self, initialize: bool) -> Result<(), Error> {
103        monitor!("safety_rules", self.inner.start_voting(initialize))
104    }
105
106    fn stop_voting(&mut self) -> Result<(), Error> {
107        monitor!("safety_rules", self.inner.stop_voting())
108    }
109}