diem_types/on_chain_config/
mod.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::{account_address::AccountAddress, event::EventKey};
9use anyhow::{format_err, Result};
10use serde::de::DeserializeOwned;
11use std::{collections::HashMap, fmt, sync::Arc};
12
13mod validator_set;
14
15pub use self::validator_set::ValidatorSet;
16
17#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
18pub struct ConfigID(&'static str, &'static str);
19
20impl fmt::Display for ConfigID {
21    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22        write!(
23            f,
24            "OnChain config ID [address: {}, identifier: {}]",
25            self.0, self.1
26        )
27    }
28}
29
30/// State sync will panic if the value of any config in this registry is
31/// uninitialized
32pub const ON_CHAIN_CONFIG_REGISTRY: &[ConfigID] = &[ValidatorSet::CONFIG_ID];
33
34#[derive(Clone, Debug, PartialEq)]
35pub struct OnChainConfigPayload {
36    epoch: u64,
37    configs: Arc<HashMap<ConfigID, Vec<u8>>>,
38}
39
40impl OnChainConfigPayload {
41    pub fn new(epoch: u64, configs: Arc<HashMap<ConfigID, Vec<u8>>>) -> Self {
42        Self { epoch, configs }
43    }
44
45    pub fn epoch(&self) -> u64 { self.epoch }
46
47    pub fn get<T: OnChainConfig>(&self) -> Result<T> {
48        let bytes = self.configs.get(&T::CONFIG_ID).ok_or_else(|| {
49            format_err!("[on-chain cfg] config not in payload")
50        })?;
51        T::deserialize_into_config(bytes)
52    }
53
54    pub fn configs(&self) -> &HashMap<ConfigID, Vec<u8>> { &self.configs }
55}
56
57impl fmt::Display for OnChainConfigPayload {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        let mut config_ids = "".to_string();
60        for id in self.configs.keys() {
61            config_ids += &id.to_string();
62        }
63        write!(
64            f,
65            "OnChainConfigPayload [epoch: {}, configs: {}]",
66            self.epoch, config_ids
67        )
68    }
69}
70
71/// Trait to be implemented by a Rust struct representation of an on-chain
72/// config that is stored in storage as a serialized byte array
73pub trait OnChainConfig: Send + Sync + DeserializeOwned {
74    const ADDRESS: &'static str = "0xA550C18";
75    const IDENTIFIER: &'static str;
76    const CONFIG_ID: ConfigID = ConfigID(Self::ADDRESS, Self::IDENTIFIER);
77
78    fn deserialize_default_impl(bytes: &[u8]) -> Result<Self> {
79        bcs::from_bytes::<Self>(&bytes).map_err(|e| {
80            format_err!(
81                "[on-chain config] Failed to deserialize into config: {}",
82                e
83            )
84        })
85    }
86
87    fn deserialize_into_config(bytes: &[u8]) -> Result<Self> {
88        Self::deserialize_default_impl(bytes)
89    }
90}
91
92pub fn config_address() -> AccountAddress {
93    AccountAddress::from_hex_literal("0xA550C18")
94        .expect("failed to get address")
95}
96
97pub fn new_epoch_event_key() -> EventKey {
98    EventKey::new_from_address(&config_address(), 4)
99}