cfx_executor/internal_contract/components/
contract_map.rs

1use std::collections::BTreeMap;
2
3use cfx_types::{Address, AddressWithSpace, Space};
4use cfx_vm_types::Spec;
5use primitives::BlockNumber;
6
7use super::{super::contracts::all_internal_contracts, InternalContractTrait};
8use crate::spec::CommonParams;
9
10#[derive(Default)]
11pub struct InternalContractMap {
12    builtin: BTreeMap<Address, Box<dyn InternalContractTrait>>,
13    activation_info: BTreeMap<BlockNumber, Vec<Address>>,
14}
15
16impl std::ops::Deref for InternalContractMap {
17    type Target = BTreeMap<Address, Box<dyn InternalContractTrait>>;
18
19    fn deref(&self) -> &Self::Target { &self.builtin }
20}
21
22impl InternalContractMap {
23    pub fn new(params: &CommonParams) -> Self {
24        let mut builtin = BTreeMap::new();
25        let mut activation_info = BTreeMap::new();
26        // We should initialize all the internal contracts here. Even if not all
27        // of them are activated at the genesis block. The activation of the
28        // internal contracts are controlled by the `CommonParams` and
29        // `vm::Spec`.
30        let mut internal_contracts = all_internal_contracts();
31
32        while let Some(contract) = internal_contracts.pop() {
33            let address = *contract.address();
34            let transition_block = if params.early_set_internal_contracts_states
35            {
36                0
37            } else {
38                contract.initialize_block(params)
39            };
40
41            builtin.insert(*contract.address(), contract);
42            activation_info
43                .entry(transition_block)
44                .or_insert(vec![])
45                .push(address);
46        }
47
48        Self {
49            builtin,
50            activation_info,
51        }
52    }
53
54    #[cfg(test)]
55    pub fn initialize_for_test() -> Vec<Address> {
56        all_internal_contracts()
57            .iter()
58            .map(|contract| *contract.address())
59            .collect()
60    }
61
62    pub fn initialized_at_genesis(&self) -> &[Address] {
63        self.initialized_at(0)
64    }
65
66    pub fn initialized_at(&self, number: BlockNumber) -> &[Address] {
67        self.activation_info
68            .get(&number)
69            .map_or(&[], |vec| vec.as_slice())
70    }
71
72    pub fn contract(
73        &self, address: &AddressWithSpace, spec: &Spec,
74    ) -> Option<&Box<dyn InternalContractTrait>> {
75        if address.space != Space::Native {
76            return None;
77        }
78        self.builtin
79            .get(&address.address)
80            .filter(|&contract| contract.is_active(spec))
81    }
82}