odra_core/
contract_register.rs

1use crate::call_def::CallDef;
2use crate::prelude::*;
3use crate::ContractContainer;
4use crate::{casper_types::bytesrepr::Bytes, VmError};
5
6pub type ContractVersion = u32;
7
8/// A struct representing a contract register that maps an address to a contract.
9///
10/// A register is a central place where all contracts are stored. It is used by the
11/// host side to manage and/or call contracts.
12#[derive(Default)]
13pub struct ContractRegister {
14    contracts: BTreeMap<(Address, ContractVersion), ContractContainer>,
15    versions_count: BTreeMap<Address, ContractVersion>
16}
17
18impl ContractRegister {
19    /// Adds a contract to the register.
20    pub fn add(&mut self, addr: Address, container: ContractContainer) {
21        let new_version = match self.versions_count.get(&addr) {
22            Some(version_number) => version_number + 1,
23            None => 0
24        };
25        self.contracts.insert((addr, new_version), container);
26        self.versions_count.insert(addr, new_version);
27    }
28
29    /// Calls the entry point with the given call definition.
30    ///
31    /// Returns bytes representing the result of the call or an error if the address
32    /// is not present in the register.
33    pub fn call(&self, addr: &Address, call_def: CallDef) -> OdraResult<Bytes> {
34        if let Some(contract) = self.get(addr) {
35            return contract.call(call_def);
36        }
37        Err(OdraError::VmError(VmError::InvalidContractAddress))
38    }
39
40    /// Returns the latest contract container for the given address.
41    pub fn get(&self, addr: &Address) -> Option<&ContractContainer> {
42        let latest_version = self.versions_count.get(addr).unwrap_or(&0);
43        self.contracts.get(&(*addr, *latest_version))
44    }
45
46    /// Returns the name of the contract at the given address.
47    pub fn get_name(&self, addr: &Address) -> Option<&str> {
48        let latest_version = self.versions_count.get(addr).unwrap_or(&0);
49        match self.contracts.get(&(*addr, *latest_version)) {
50            Some(contract) => Some(contract.name()),
51            None => None
52        }
53    }
54
55    /// Returns the address of the contract with the given name.
56    pub fn get_address(&self, name: &str) -> Option<Address> {
57        self.contracts
58            .iter()
59            .find(|contract| contract.1.name() == name)
60            .map(|a| a.0 .0)
61    }
62
63    /// Returns the latest contract container for the given address.
64    pub fn get_mut(&mut self, addr: &Address) -> Option<&mut ContractContainer> {
65        let latest_version = self.versions_count.get(addr).unwrap_or(&0);
66        self.contracts.get_mut(&(*addr, *latest_version))
67    }
68
69    /// Post install hook.
70    pub fn post_install(&mut self, addr: &Address) {
71        if let Some(contract) = self.get_mut(addr) {
72            contract.post_install();
73        }
74    }
75}