ink_engine/
database.rs

1// Copyright (C) Use Ink (UK) Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::types::{
16    Balance,
17    H160,
18};
19use ink_primitives::{
20    AccountId,
21    H256,
22    U256,
23};
24use scale::KeyedVec;
25use std::collections::HashMap;
26
27const BALANCE_OF: &[u8] = b"balance:";
28const STORAGE_OF: &[u8] = b"contract-storage:";
29const CONTRACT_PREFIX: &[u8] = b"contract:";
30const MSG_HANDLER_OF: &[u8] = b"message-handler:";
31const CODE_HASH_OF: &[u8] = b"code-hash:";
32
33/// Returns the database key under which to find the balance for contract `who`.
34pub fn balance_of_key(who: &H160) -> [u8; 32] {
35    let keyed = who.0.to_vec().to_keyed_vec(BALANCE_OF);
36    let mut hashed_key: [u8; 32] = [0; 32];
37    super::hashing::blake2b_256(&keyed[..], &mut hashed_key);
38    hashed_key
39}
40
41/// Returns the database key under which to find the storage for contract `who`.
42pub fn storage_of_contract_key(who: &H160, key: &[u8]) -> [u8; 32] {
43    let keyed = who
44        .as_bytes()
45        .to_vec()
46        .to_keyed_vec(key)
47        .to_keyed_vec(STORAGE_OF);
48    let mut hashed_key: [u8; 32] = [0; 32];
49    super::hashing::blake2b_256(&keyed[..], &mut hashed_key);
50    hashed_key
51}
52
53pub type MessageHandler = fn(Vec<u8>) -> Vec<u8>;
54
55pub fn contract_key(f: MessageHandler) -> [u8; 32] {
56    let f = f as usize;
57    let f = f.to_le_bytes();
58    let keyed = f.to_vec().to_keyed_vec(CONTRACT_PREFIX);
59    let mut ret: [u8; 32] = [0; 32];
60    super::hashing::blake2b_256(&keyed[..], &mut ret);
61    ret
62}
63
64pub fn message_handler_of_contract_key(key: &[u8]) -> [u8; 32] {
65    let keyed = key.to_vec().to_keyed_vec(MSG_HANDLER_OF);
66    let mut hashed_key: [u8; 32] = [0; 32];
67    super::hashing::blake2b_256(&keyed[..], &mut hashed_key);
68    hashed_key
69}
70
71pub fn code_hash_for_addr(addr: &H160) -> [u8; 32] {
72    let key = addr.0;
73    let keyed = key.to_keyed_vec(CODE_HASH_OF);
74    let mut hashed_key: [u8; 32] = [0; 32];
75    super::hashing::blake2b_256(&keyed[..], &mut hashed_key);
76    hashed_key
77}
78
79/// The chain database.
80///
81/// Everything is stored in here: contracts, balances, contract storage, etc.
82/// Just like in Substrate a prefix hash is computed for every contract.
83#[derive(Default)]
84pub struct Database {
85    hmap: HashMap<Vec<u8>, Vec<u8>>,
86    fmap: HashMap<Vec<u8>, MessageHandler>,
87}
88
89impl Database {
90    /// Creates a new database instance.
91    pub fn new() -> Self {
92        Database {
93            hmap: HashMap::new(),
94            fmap: HashMap::new(),
95        }
96    }
97
98    /// Returns the amount of entries in the database.
99    #[cfg(test)]
100    fn len(&self) -> usize {
101        self.hmap.len()
102    }
103
104    /// Returns a reference to the value corresponding to the key.
105    fn get(&self, key: &[u8]) -> Option<&Vec<u8>> {
106        self.hmap.get(key)
107    }
108
109    /// Returns a reference to the value corresponding to the key.
110    pub fn get_from_contract_storage(&self, addr: &H160, key: &[u8]) -> Option<&Vec<u8>> {
111        let hashed_key = storage_of_contract_key(addr, key);
112        self.hmap.get(hashed_key.as_slice())
113    }
114
115    /// Inserts `value` into the contract storage of `addr` at storage key `key`.
116    pub fn insert_into_contract_storage(
117        &mut self,
118        addr: &H160,
119        key: &[u8],
120        value: Vec<u8>,
121    ) -> Option<Vec<u8>> {
122        let hashed_key = storage_of_contract_key(addr, key);
123        self.hmap.insert(hashed_key.to_vec(), value)
124    }
125
126    /// Removes the value at the contract storage of `addr` at storage key `key`.
127    pub fn remove_contract_storage(
128        &mut self,
129        addr: &H160,
130        key: &[u8],
131    ) -> Option<Vec<u8>> {
132        let hashed_key = storage_of_contract_key(addr, key);
133        self.hmap.remove(hashed_key.as_slice())
134    }
135
136    /// Removes a key from the storage, returning the value at the key if the key
137    /// was previously in storage.
138    pub fn remove(&mut self, key: &[u8]) -> Option<Vec<u8>> {
139        self.hmap.remove(key)
140    }
141
142    /// Sets the value of the entry, and returns the entry's old value.
143    pub fn insert(&mut self, key: Vec<u8>, value: Vec<u8>) -> Option<Vec<u8>> {
144        self.hmap.insert(key, value)
145    }
146
147    /// Clears the database, removing all key-value pairs.
148    pub fn clear(&mut self) {
149        self.hmap.clear();
150    }
151
152    /// Returns the balance of the contract at `addr`, if available.
153    pub fn get_acc_balance(&self, _addr: &AccountId) -> Option<Balance> {
154        todo!()
155    }
156
157    /// Sets the balance of `addr` to `new_balance`.
158    pub fn set_acc_balance(&mut self, _addr: &AccountId, _new_balance: Balance) {
159        todo!()
160    }
161
162    pub fn get_balance(&self, addr: &H160) -> Option<U256> {
163        let hashed_key = balance_of_key(addr);
164        self.get(&hashed_key).map(|encoded_balance| {
165            scale::Decode::decode(&mut &encoded_balance[..])
166                .expect("unable to decode balance from database")
167        })
168    }
169
170    /// Sets the balance of `addr` to `new_balance`.
171    pub fn set_balance(&mut self, addr: &H160, new_balance: U256) {
172        let hashed_key = balance_of_key(addr);
173        let encoded_balance = scale::Encode::encode(&new_balance);
174        self.hmap
175            .entry(hashed_key.to_vec())
176            .and_modify(|v| *v = encoded_balance.clone())
177            .or_insert(encoded_balance);
178    }
179
180    pub fn set_contract_message_handler(&mut self, handler: MessageHandler) -> [u8; 32] {
181        let key = contract_key(handler);
182        let hashed_key = message_handler_of_contract_key(&key);
183        self.fmap
184            .entry(hashed_key.to_vec())
185            .and_modify(|x| *x = handler)
186            .or_insert(handler);
187        key
188    }
189
190    /// Returns the message handler for a code hash.
191    pub fn get_contract_message_handler(&mut self, code_hash: &H256) -> MessageHandler {
192        let hashed_key = message_handler_of_contract_key(&code_hash.0);
193        *self.fmap.get(hashed_key.as_slice()).unwrap()
194    }
195
196    pub fn set_code_hash(&mut self, addr: &H160, code_hash: &H256) {
197        let hashed_key = code_hash_for_addr(addr);
198        self.hmap
199            .entry(hashed_key.to_vec())
200            .and_modify(|x| *x = code_hash.as_bytes().to_vec())
201            .or_insert(code_hash.as_bytes().to_vec());
202    }
203
204    pub fn get_code_hash(&self, addr: &H160) -> Option<H256> {
205        let hashed_key = code_hash_for_addr(addr);
206        self.get(&hashed_key)
207            .cloned()
208            .map(|v| H256::from_slice(v.as_slice()))
209    }
210}
211
212#[cfg(test)]
213mod tests {
214    use super::Database;
215    use crate::types::H160;
216
217    #[test]
218    fn basic_operations() {
219        let mut database = Database::new();
220        let key1 = vec![42];
221        let key2 = vec![43];
222        let val1 = vec![44];
223        let val2 = vec![45];
224        let val3 = vec![46];
225
226        assert_eq!(database.len(), 0);
227        assert_eq!(database.get(&key1), None);
228        assert_eq!(database.insert(key1.clone(), val1.clone()), None);
229        assert_eq!(database.get(&key1), Some(&val1));
230        assert_eq!(database.insert(key1.clone(), val2.clone()), Some(val1));
231        assert_eq!(database.get(&key1), Some(&val2));
232        assert_eq!(database.insert(key2.clone(), val3.clone()), None);
233        assert_eq!(database.len(), 2);
234        assert_eq!(database.remove(&key2), Some(val3));
235        assert_eq!(database.len(), 1);
236        database.clear();
237        assert_eq!(database.len(), 0);
238    }
239
240    #[test]
241    fn contract_storage() {
242        let addr = H160::from([1; 20]);
243        let mut storage = Database::new();
244        let key1 = vec![42];
245        let key2 = vec![43];
246        let val1 = vec![44];
247        let val2 = vec![45];
248        let val3 = vec![46];
249
250        assert_eq!(storage.len(), 0);
251        assert_eq!(storage.get_from_contract_storage(&addr, &key1), None);
252        assert_eq!(
253            storage.insert_into_contract_storage(&addr, &key1, val1.clone()),
254            None
255        );
256        assert_eq!(storage.get_from_contract_storage(&addr, &key1), Some(&val1));
257        assert_eq!(
258            storage.insert_into_contract_storage(&addr, &key1, val2.clone()),
259            Some(val1)
260        );
261        assert_eq!(storage.get_from_contract_storage(&addr, &key1), Some(&val2));
262        assert_eq!(
263            storage.insert_into_contract_storage(&addr, &key2, val3.clone()),
264            None
265        );
266        assert_eq!(storage.len(), 2);
267        assert_eq!(storage.remove_contract_storage(&addr, &key2), Some(val3));
268        assert_eq!(storage.len(), 1);
269        assert_eq!(storage.remove_contract_storage(&addr, &key1), Some(val2));
270        assert_eq!(storage.len(), 0);
271    }
272}