Skip to main content

neo_devpack_solidity/runtime/storage/storage_impl/manager/
crud.rs

1use super::*;
2
3impl StorageManager {
4    /// Get storage value
5    pub fn get(&mut self, account: &str, key: &[u8]) -> Result<Option<Vec<u8>>, RuntimeError> {
6        self.read_count += 1;
7
8        let account_storage = self.storage.get(account);
9
10        if let Some(storage) = account_storage {
11            // Check pending changes first
12            if let Some(change) = storage.pending_changes.get(key) {
13                match change.change_type {
14                    StorageChangeType::Delete => return Ok(None),
15                    _ => {
16                        if let Some(ref new_value) = change.new_value {
17                            return Ok(Some(new_value.clone()));
18                        }
19                    }
20                }
21            }
22
23            // Check committed storage
24            if let Some(value) = storage.storage.get(key) {
25                return Ok(Some(value.clone()));
26            }
27        }
28
29        Ok(None)
30    }
31
32    /// Set storage value
33    pub fn set(&mut self, account: &str, key: &[u8], value: &[u8]) -> Result<(), RuntimeError> {
34        self.write_count += 1;
35
36        let old_value = self.get(account, key)?;
37
38        // Calculate gas cost
39        let change_type = match &old_value {
40            None => StorageChangeType::Create,
41            Some(old) if old == value => StorageChangeType::NoChange,
42            Some(_) if value.is_empty() => StorageChangeType::Delete,
43            Some(_) => StorageChangeType::Update,
44        };
45
46        let gas_cost = self.calculate_storage_gas_cost(&change_type, value.len());
47
48        // Get or create account storage
49        let account_storage =
50            self.storage
51                .entry(account.to_string())
52                .or_insert_with(|| AccountStorage {
53                    account: account.to_string(),
54                    storage: BTreeMap::new(),
55                    pending_changes: HashMap::new(),
56                });
57
58        // Record pending change
59        let change = StorageChange {
60            key: key.to_vec(),
61            old_value,
62            new_value: if value.is_empty() {
63                None
64            } else {
65                Some(value.to_vec())
66            },
67            change_type,
68            gas_cost,
69        };
70
71        account_storage.pending_changes.insert(key.to_vec(), change);
72
73        Ok(())
74    }
75
76    /// Delete storage value
77    pub fn delete(&mut self, account: &str, key: &[u8]) -> Result<(), RuntimeError> {
78        self.set(account, key, &[])
79    }
80
81    /// Check if storage key exists
82    pub fn exists(&mut self, account: &str, key: &[u8]) -> Result<bool, RuntimeError> {
83        Ok(self.get(account, key)?.is_some())
84    }
85}