fuel_core/database/
contracts.rs1use 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}