Skip to main content

neo_vm_core/
storage.rs

1//! Neo VM Storage Implementation
2//!
3//! Provides key-value storage for smart contracts with Merkle proof support.
4
5use sha2::{Digest, Sha256};
6use std::collections::BTreeMap;
7
8/// Storage context for a contract
9#[derive(Debug, Clone, Default)]
10pub struct StorageContext {
11    /// Contract script hash (20 bytes)
12    pub script_hash: [u8; 20],
13    /// Read-only flag
14    pub read_only: bool,
15}
16
17/// Storage backend trait
18pub trait StorageBackend {
19    fn get(&self, context: &StorageContext, key: &[u8]) -> Option<Vec<u8>>;
20    fn put(&mut self, context: &StorageContext, key: &[u8], value: &[u8]);
21    fn delete(&mut self, context: &StorageContext, key: &[u8]);
22    fn find(&self, context: &StorageContext, prefix: &[u8]) -> Vec<(Vec<u8>, Vec<u8>)>;
23}
24
25/// In-memory storage implementation
26#[derive(Debug, Clone, Default)]
27pub struct MemoryStorage {
28    data: BTreeMap<Vec<u8>, Vec<u8>>,
29}
30
31impl MemoryStorage {
32    #[inline]
33    pub fn new() -> Self {
34        Self::default()
35    }
36
37    #[inline]
38    fn make_key(context: &StorageContext, key: &[u8]) -> Vec<u8> {
39        let mut full_key = context.script_hash.to_vec();
40        full_key.extend_from_slice(key);
41        full_key
42    }
43
44    /// Compute Merkle root of storage
45    #[inline]
46    pub fn merkle_root(&self) -> [u8; 32] {
47        if self.data.is_empty() {
48            return [0u8; 32];
49        }
50
51        // Collect and sort leaves by key for deterministic Merkle root
52        // This ensures cross-platform/environment determinism
53        let mut leaves: Vec<[u8; 32]> = self
54            .data
55            .iter()
56            .map(|(k, v)| {
57                let mut hasher = Sha256::new();
58                hasher.update(k);
59                hasher.update(v);
60                hasher.finalize().into()
61            })
62            .collect();
63
64        // Sort leaves to ensure deterministic ordering
65        leaves.sort();
66
67        Self::compute_merkle_root(&leaves)
68    }
69
70    #[inline]
71    fn compute_merkle_root(leaves: &[[u8; 32]]) -> [u8; 32] {
72        if leaves.is_empty() {
73            return [0u8; 32];
74        }
75        if leaves.len() == 1 {
76            return leaves[0];
77        }
78
79        let mut current: Vec<[u8; 32]> = leaves.to_vec();
80        while current.len() > 1 {
81            let mut next_level = Vec::with_capacity(current.len().div_ceil(2));
82            for chunk in current.chunks(2) {
83                let mut hasher = Sha256::new();
84                hasher.update(chunk[0]);
85                if chunk.len() > 1 {
86                    hasher.update(chunk[1]);
87                } else {
88                    hasher.update([0u8; 32]);
89                }
90                next_level.push(hasher.finalize().into());
91            }
92            current = next_level;
93        }
94        current.first().copied().unwrap_or([0u8; 32])
95    }
96}
97
98impl StorageBackend for MemoryStorage {
99    fn get(&self, context: &StorageContext, key: &[u8]) -> Option<Vec<u8>> {
100        let full_key = Self::make_key(context, key);
101        self.data.get(&full_key).cloned()
102    }
103
104    fn put(&mut self, context: &StorageContext, key: &[u8], value: &[u8]) {
105        if context.read_only {
106            return;
107        }
108        let full_key = Self::make_key(context, key);
109        self.data.insert(full_key, value.to_vec());
110    }
111
112    fn delete(&mut self, context: &StorageContext, key: &[u8]) {
113        if context.read_only {
114            return;
115        }
116        let full_key = Self::make_key(context, key);
117        self.data.remove(&full_key);
118    }
119
120    fn find(&self, context: &StorageContext, prefix: &[u8]) -> Vec<(Vec<u8>, Vec<u8>)> {
121        let full_prefix = Self::make_key(context, prefix);
122        self.data
123            .range(full_prefix.clone()..)
124            .take_while(|(k, _)| k.starts_with(&full_prefix))
125            .map(|(k, v)| {
126                let key = k[context.script_hash.len()..].to_vec();
127                (key, v.clone())
128            })
129            .collect()
130    }
131}
132
133/// Storage proof for ZK verification
134#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
135pub struct StorageProof {
136    pub key: Vec<u8>,
137    pub value: Option<Vec<u8>>,
138    pub merkle_path: Vec<[u8; 32]>,
139    pub root: [u8; 32],
140}
141
142impl StorageProof {
143    /// Verify a storage proof against a given root
144    pub fn verify(&self, expected_root: [u8; 32]) -> bool {
145        // Compute leaf hash from key and value
146        let leaf = if let Some(ref value) = self.value {
147            let mut hasher = Sha256::new();
148            hasher.update(&self.key);
149            hasher.update(value);
150            hasher.finalize().into()
151        } else {
152            // For deleted/missing values, use zero hash with key
153            let mut hasher = Sha256::new();
154            hasher.update(&self.key);
155            hasher.update([0u8; 32]);
156            hasher.finalize().into()
157        };
158
159        // Compute root from leaf and merkle path
160        let computed_root = Self::compute_root_from_path(&leaf, &self.merkle_path);
161
162        computed_root == expected_root
163    }
164
165    /// Compute root hash from leaf and path
166    fn compute_root_from_path(leaf: &[u8; 32], path: &[[u8; 32]]) -> [u8; 32] {
167        let mut current = *leaf;
168        for sibling in path {
169            let mut hasher = Sha256::new();
170            // Determine left/right based on hash ordering
171            if current < *sibling {
172                hasher.update(current);
173                hasher.update(*sibling);
174            } else {
175                hasher.update(*sibling);
176                hasher.update(current);
177            }
178            current = hasher.finalize().into();
179        }
180        current
181    }
182}
183
184/// Storage change record
185#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
186pub struct StorageChange {
187    pub script_hash: [u8; 20],
188    pub key: Vec<u8>,
189    pub old_value: Option<Vec<u8>>,
190    pub new_value: Option<Vec<u8>>,
191}
192
193/// Tracked storage with change log
194#[derive(Debug, Clone, Default)]
195pub struct TrackedStorage {
196    inner: MemoryStorage,
197    changes: Vec<StorageChange>,
198}
199
200impl TrackedStorage {
201    pub fn new() -> Self {
202        Self::default()
203    }
204
205    pub fn changes(&self) -> &[StorageChange] {
206        &self.changes
207    }
208
209    pub fn merkle_root(&self) -> [u8; 32] {
210        self.inner.merkle_root()
211    }
212}
213
214impl StorageBackend for TrackedStorage {
215    fn get(&self, context: &StorageContext, key: &[u8]) -> Option<Vec<u8>> {
216        self.inner.get(context, key)
217    }
218
219    fn put(&mut self, context: &StorageContext, key: &[u8], value: &[u8]) {
220        if context.read_only {
221            return;
222        }
223        let old_value = self.inner.get(context, key);
224        self.inner.put(context, key, value);
225        self.changes.push(StorageChange {
226            script_hash: context.script_hash,
227            key: key.to_vec(),
228            old_value,
229            new_value: Some(value.to_vec()),
230        });
231    }
232
233    fn delete(&mut self, context: &StorageContext, key: &[u8]) {
234        if context.read_only {
235            return;
236        }
237        let old_value = self.inner.get(context, key);
238        self.inner.delete(context, key);
239        self.changes.push(StorageChange {
240            script_hash: context.script_hash,
241            key: key.to_vec(),
242            old_value,
243            new_value: None,
244        });
245    }
246
247    fn find(&self, context: &StorageContext, prefix: &[u8]) -> Vec<(Vec<u8>, Vec<u8>)> {
248        self.inner.find(context, prefix)
249    }
250}