fuel_core_chain_config/config/
consensus.rs

1use alloc::collections::BTreeMap;
2use fuel_core_types::{
3    fuel_tx::Input,
4    fuel_types::{
5        Address,
6        BlockHeight,
7    },
8};
9use serde::{
10    Deserialize,
11    Serialize,
12};
13
14use crate as fuel_core_chain_config;
15use fuel_core_chain_config::default_consensus_dev_key;
16
17#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
18pub enum ConsensusConfig {
19    PoA { signing_key: Address },
20    PoAV2(PoAV2),
21}
22
23impl ConsensusConfig {
24    pub fn default_poa() -> Self {
25        ConsensusConfig::PoAV2(PoAV2 {
26            genesis_signing_key: Input::owner(&default_consensus_dev_key().public_key()),
27            signing_key_overrides: Default::default(),
28        })
29    }
30}
31
32#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
33pub struct PoAV2 {
34    genesis_signing_key: Address,
35    signing_key_overrides: BTreeMap<BlockHeight, Address>,
36}
37
38impl PoAV2 {
39    pub fn new(
40        genesis_signing_key: Address,
41        signing_key_overrides: BTreeMap<BlockHeight, Address>,
42    ) -> Self {
43        PoAV2 {
44            genesis_signing_key,
45            signing_key_overrides,
46        }
47    }
48
49    /// Returns the signing key for the given block height.
50    pub fn signing_key_at(&self, height: BlockHeight) -> Address {
51        if self.signing_key_overrides.is_empty() {
52            self.genesis_signing_key
53        } else {
54            self.signing_key_overrides
55                .range(..=height)
56                .last()
57                .map(|(_, key)| key)
58                .cloned()
59                .unwrap_or(self.genesis_signing_key)
60        }
61    }
62
63    /// Returns overrides for all the signing keys.
64    pub fn get_all_overrides(&self) -> &BTreeMap<BlockHeight, Address> {
65        &self.signing_key_overrides
66    }
67
68    #[cfg(feature = "test-helpers")]
69    pub fn set_genesis_signing_key(&mut self, key: Address) {
70        self.genesis_signing_key = key;
71    }
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn signing_key_at_works() {
80        // Given
81        let genesis_signing_key = Address::from([1; 32]);
82        let signing_key_after_10 = Address::from([2; 32]);
83        let signing_key_after_20 = Address::from([3; 32]);
84        let signing_key_after_30 = Address::from([4; 32]);
85        let signing_key_overrides = vec![
86            (10u32.into(), signing_key_after_10),
87            (20u32.into(), signing_key_after_20),
88            (30u32.into(), signing_key_after_30),
89        ]
90        .into_iter()
91        .collect();
92        let poa = PoAV2 {
93            genesis_signing_key,
94            signing_key_overrides,
95        };
96
97        // When/Then
98        assert_eq!(poa.signing_key_at(0u32.into()), genesis_signing_key);
99        assert_eq!(poa.signing_key_at(9u32.into()), genesis_signing_key);
100        assert_eq!(poa.signing_key_at(10u32.into()), signing_key_after_10);
101        assert_eq!(poa.signing_key_at(19u32.into()), signing_key_after_10);
102        assert_eq!(poa.signing_key_at(20u32.into()), signing_key_after_20);
103        assert_eq!(poa.signing_key_at(29u32.into()), signing_key_after_20);
104        assert_eq!(poa.signing_key_at(30u32.into()), signing_key_after_30);
105        assert_eq!(poa.signing_key_at(40u32.into()), signing_key_after_30);
106        assert_eq!(
107            poa.signing_key_at(4_000_000u32.into()),
108            signing_key_after_30
109        );
110    }
111}