fuel_core/database/
contracts.rs

1use crate::database::OnChainIterableKeyValueView;
2use fuel_core_chain_config::TableEntry;
3use fuel_core_storage::{
4    ContractsAssetKey,
5    Result as StorageResult,
6    StorageAsRef,
7    iter::{
8        IterDirection,
9        IteratorOverTable,
10    },
11    not_found,
12    tables::{
13        ContractsAssets,
14        ContractsLatestUtxo,
15        ContractsRawCode,
16        ContractsState,
17    },
18};
19use fuel_core_types::fuel_types::{
20    AssetId,
21    ContractId,
22};
23use itertools::Itertools;
24
25impl OnChainIterableKeyValueView {
26    pub fn iter_contract_state(
27        &self,
28    ) -> impl Iterator<Item = StorageResult<TableEntry<ContractsState>>> + '_ {
29        self.iter_all::<ContractsState>(None)
30            .map_ok(|(key, value)| TableEntry { key, value })
31    }
32
33    pub fn iter_contract_balance(
34        &self,
35    ) -> impl Iterator<Item = StorageResult<TableEntry<ContractsAssets>>> + '_ {
36        self.iter_all::<ContractsAssets>(None)
37            .map_ok(|(key, value)| TableEntry { key, value })
38    }
39
40    pub fn iter_contracts_code(
41        &self,
42    ) -> impl Iterator<Item = StorageResult<TableEntry<ContractsRawCode>>> + '_ {
43        self.iter_all::<ContractsRawCode>(None)
44            .map_ok(|(key, value)| TableEntry { key, value })
45    }
46
47    pub fn iter_contracts_latest_utxo(
48        &self,
49    ) -> impl Iterator<Item = StorageResult<TableEntry<ContractsLatestUtxo>>> + '_ {
50        self.iter_all::<ContractsLatestUtxo>(None)
51            .map_ok(|(key, value)| TableEntry { key, value })
52    }
53
54    pub fn contract_code(
55        &self,
56        contract_id: ContractId,
57    ) -> StorageResult<TableEntry<ContractsRawCode>> {
58        self.storage::<ContractsRawCode>()
59            .get(&contract_id)?
60            .map(|value| TableEntry {
61                key: contract_id,
62                value: value.into_owned(),
63            })
64            .ok_or_else(|| not_found!("ContractsRawCode"))
65    }
66
67    pub fn contract_latest_utxo(
68        &self,
69        contract_id: ContractId,
70    ) -> StorageResult<TableEntry<ContractsLatestUtxo>> {
71        self.storage::<ContractsLatestUtxo>()
72            .get(&contract_id)?
73            .map(|value| TableEntry {
74                key: contract_id,
75                value: value.into_owned(),
76            })
77            .ok_or_else(|| not_found!("ContractsLatestUtxo"))
78    }
79
80    pub fn filter_contract_balances(
81        &self,
82        contract: ContractId,
83        start_asset: Option<AssetId>,
84        direction: Option<IterDirection>,
85    ) -> impl Iterator<Item = StorageResult<TableEntry<ContractsAssets>>> + '_ {
86        let start_asset =
87            start_asset.map(|asset| ContractsAssetKey::new(&contract, &asset));
88        self.iter_all_filtered::<ContractsAssets, _>(
89            Some(contract),
90            start_asset.as_ref(),
91            direction,
92        )
93        .map_ok(|(key, value)| TableEntry { key, value })
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100    use crate::database::{
101        Database,
102        database_description::on_chain::OnChain,
103    };
104    use fuel_core_storage::StorageAsMut;
105    use fuel_core_types::fuel_tx::Contract;
106    use rand::{
107        RngCore,
108        SeedableRng,
109    };
110
111    #[test]
112    fn raw_code_put_huge_contract() {
113        let rng = &mut rand::rngs::StdRng::seed_from_u64(2322u64);
114        let contract_id: ContractId = ContractId::from([1u8; 32]);
115        let mut bytes = vec![0; 16 * 1024 * 1024];
116        rng.fill_bytes(bytes.as_mut());
117        let contract: Contract = Contract::from(bytes);
118
119        let database = &mut Database::<OnChain>::default();
120        database
121            .storage::<ContractsRawCode>()
122            .insert(&contract_id, contract.as_ref())
123            .unwrap();
124
125        let returned: Contract = database
126            .storage::<ContractsRawCode>()
127            .get(&contract_id)
128            .unwrap()
129            .unwrap()
130            .into_owned();
131        assert_eq!(returned, contract);
132    }
133}