diem_types/
epoch_state.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 crate::{
9    epoch_change::Verifier,
10    ledger_info::{LedgerInfo, LedgerInfoWithSignatures},
11    on_chain_config::OnChainConfig,
12    validator_verifier::ValidatorVerifier,
13};
14use anyhow::ensure;
15use once_cell::sync::OnceCell;
16#[cfg(any(test, feature = "fuzzing"))]
17use proptest_derive::Arbitrary;
18use serde::{Deserialize, Serialize};
19use std::{collections::BTreeMap, fmt};
20
21pub static HARDCODED_COMMITTEE_FOR_EPOCH: OnceCell<
22    BTreeMap<u64, ValidatorVerifier>,
23> = OnceCell::new();
24
25/// EpochState represents a trusted validator set to validate messages from the
26/// specific epoch, it could be updated with EpochChangeProof.
27#[derive(Clone, Deserialize, Eq, PartialEq, Serialize)]
28#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
29pub struct EpochState {
30    pub epoch: u64,
31
32    verifier: ValidatorVerifier,
33
34    pub vrf_seed: Vec<u8>,
35}
36
37impl EpochState {
38    pub fn empty() -> Self {
39        Self {
40            epoch: 0,
41            verifier: ValidatorVerifier::new(BTreeMap::new()),
42            vrf_seed: vec![],
43        }
44    }
45
46    pub fn new(
47        epoch: u64, verifier: ValidatorVerifier, vrf_seed: Vec<u8>,
48    ) -> Self {
49        Self {
50            epoch,
51            verifier,
52            vrf_seed,
53        }
54    }
55
56    pub fn verifier(&self) -> &ValidatorVerifier {
57        if let Some(verifier) = HARDCODED_COMMITTEE_FOR_EPOCH
58            .get()
59            .and_then(|m| m.get(&self.epoch))
60        {
61            verifier
62        } else {
63            &self.verifier
64        }
65    }
66}
67
68impl OnChainConfig for EpochState {
69    const IDENTIFIER: &'static str = "DiemSystem";
70}
71
72impl Verifier for EpochState {
73    fn verify(
74        &self, ledger_info: &LedgerInfoWithSignatures,
75    ) -> anyhow::Result<()> {
76        ensure!(
77            self.epoch == ledger_info.ledger_info().epoch(),
78            "LedgerInfo has unexpected epoch {}, expected {}",
79            ledger_info.ledger_info().epoch(),
80            self.epoch
81        );
82        ledger_info.verify_signatures(&self.verifier())?;
83        Ok(())
84    }
85
86    fn epoch_change_verification_required(&self, epoch: u64) -> bool {
87        self.epoch < epoch
88    }
89
90    fn is_ledger_info_stale(&self, ledger_info: &LedgerInfo) -> bool {
91        ledger_info.epoch() < self.epoch
92    }
93}
94
95// this is required by structured log
96impl fmt::Debug for EpochState {
97    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98        write!(f, "{}", self)
99    }
100}
101
102impl fmt::Display for EpochState {
103    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104        write!(
105            f,
106            "EpochState [epoch: {}, validator: {}]",
107            self.epoch,
108            self.verifier()
109        )
110    }
111}