1use cosmwasm_std::{
2 Api, Addr, CanonicalAddr, Empty, Order, OwnedDeps, Querier, RecoverPubkeyError, StdError,
3 StdResult, Storage, VerificationError,
4};
5use serde::{Deserialize, Serialize};
6use serde_with::serde_as;
7use std::collections::{BTreeMap, HashMap};
8use std::iter;
9use std::marker::PhantomData;
10use std::ops::{Bound, RangeBounds};
11
12const CANONICAL_LENGTH: usize = 54;
13
14#[derive(Default)]
15pub struct MemoryStorage {
17 data: BTreeMap<Vec<u8>, Vec<u8>>,
18}
19
20impl MemoryStorage {
21 pub fn new() -> Self {
23 Self::default()
24 }
25}
26
27impl Storage for MemoryStorage {
28 fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
29 self.data.get(key).cloned()
30 }
31
32 fn set(&mut self, key: &[u8], value: &[u8]) {
33 if value.is_empty() {
34 panic!(
35 "TL;DR: Value must not be empty in Storage::set but in most cases you can use Storage::remove instead. Long story: Getting empty values from storage is not well supported at the moment. Some of our internal interfaces cannot differentiate between a non-existent key and an empty value. Right now, you cannot rely on the behaviour of empty values. To protect you from trouble later on, we stop here. Sorry for the inconvenience! We highly welcome you to contribute to CosmWasm, making this more solid one way or the other."
36 );
37 }
38
39 self.data.insert(key.to_vec(), value.to_vec());
40 }
41
42 fn remove(&mut self, key: &[u8]) {
43 self.data.remove(key);
44 }
45
46 fn range<'a>(
47 &'a self,
48 start: Option<&[u8]>,
49 end: Option<&[u8]>,
50 order: Order,
51 ) -> Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + 'a> {
52 let bounds = range_bounds(start, end);
53
54 match (bounds.start_bound(), bounds.end_bound()) {
55 (Bound::Included(start), Bound::Excluded(end)) if start > end => {
56 return Box::new(iter::empty());
57 }
58 _ => {}
59 }
60
61 let iter = self.data.range(bounds);
62 match order {
63 Order::Ascending => Box::new(iter.map(clone_item)),
64 Order::Descending => Box::new(iter.rev().map(clone_item)),
65 }
66 }
67}
68
69fn range_bounds(start: Option<&[u8]>, end: Option<&[u8]>) -> impl RangeBounds<Vec<u8>> {
70 (
71 start.map_or(Bound::Unbounded, |x| Bound::Included(x.to_vec())),
72 end.map_or(Bound::Unbounded, |x| Bound::Excluded(x.to_vec())),
73 )
74}
75
76type BTreeMapRecordRef<'a> = (&'a Vec<u8>, &'a Vec<u8>);
77
78fn clone_item(item_ref: BTreeMapRecordRef) -> (Vec<u8>, Vec<u8>) {
79 let (key, value) = item_ref;
80 (key.clone(), value.clone())
81}
82
83pub fn load_owned_deps(
85 state_dump: Option<IdbStateDump>,
86) -> OwnedDeps<MemoryStorage, EmptyApi, EmptyQuerier, Empty> {
87 match state_dump {
88 None => OwnedDeps {
89 storage: MemoryStorage::default(),
90 api: EmptyApi::default(),
91 querier: EmptyQuerier::default(),
92 custom_query_type: PhantomData,
93 },
94 Some(dump) => {
95 let idb_storage = IdbStorage::load(dump);
96 OwnedDeps {
97 storage: idb_storage.storage,
98 api: EmptyApi::default(),
99 querier: EmptyQuerier::default(),
100 custom_query_type: PhantomData,
101 }
102 }
103 }
104}
105
106pub struct IdbStorage {
108 pub storage: MemoryStorage,
109}
110
111impl IdbStorage {
112 pub fn load(idb: IdbStateDump) -> Self {
114 let mut store = IdbStorage {
115 storage: MemoryStorage::new(),
116 };
117 store.load_to_mem_storage(idb);
118 store
119 }
120
121 pub fn load_to_mem_storage(&mut self, idb_state: IdbStateDump) {
123 for (k, v) in idb_state.state_dump {
124 self.storage.set(&k, &v);
125 }
126 }
127}
128
129#[serde_as]
130#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
131pub struct IdbStateDump {
133 #[serde_as(as = "Vec<(serde_with::Bytes, serde_with::Bytes)>")]
134 pub state_dump: HashMap<Vec<u8>, Vec<u8>>,
135}
136
137impl IdbStateDump {
138 pub fn from(store: MemoryStorage) -> IdbStateDump {
140 let mut state: HashMap<Vec<u8>, Vec<u8>> = HashMap::new();
141
142 for (key, value) in store.range(None, None, Order::Ascending) {
143 state.insert(key, value);
144 }
145 IdbStateDump { state_dump: state }
146 }
147}
148
149#[derive(Copy, Clone)]
151pub struct EmptyApi {
152 canonical_length: usize,
153}
154
155impl Default for EmptyApi {
156 fn default() -> Self {
157 EmptyApi {
158 canonical_length: CANONICAL_LENGTH,
159 }
160 }
161}
162
163impl Api for EmptyApi {
164 fn addr_validate(&self, human: &str) -> StdResult<Addr> {
165 self.addr_canonicalize(human).map(|_canonical| ())?;
166 Ok(Addr::unchecked(human))
167 }
168
169 fn addr_canonicalize(&self, human: &str) -> StdResult<CanonicalAddr> {
170 if human.len() < 3 {
171 return Err(StdError::msg("Invalid input: human address too short"));
172 }
173 if human.len() > self.canonical_length {
174 return Err(StdError::msg("Invalid input: human address too long"));
175 }
176
177 let mut out = Vec::from(human);
178 out.resize(self.canonical_length, 0x00);
179 Ok(out.into())
180 }
181
182 fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult<Addr> {
183 if canonical.len() != self.canonical_length {
184 return Err(StdError::msg(
185 "Invalid input: canonical address length not correct",
186 ));
187 }
188
189 let tmp: Vec<u8> = canonical.clone().into();
190 let trimmed = tmp.into_iter().filter(|&x| x != 0x00).collect();
191 let human = String::from_utf8(trimmed)?;
192 Ok(Addr::unchecked(human))
193 }
194
195 fn secp256k1_verify(
196 &self,
197 _message_hash: &[u8],
198 _signature: &[u8],
199 _public_key: &[u8],
200 ) -> Result<bool, VerificationError> {
201 Err(VerificationError::unknown_err(0))
202 }
203
204 fn secp256k1_recover_pubkey(
205 &self,
206 _message_hash: &[u8],
207 _signature: &[u8],
208 _recovery_param: u8,
209 ) -> Result<Vec<u8>, RecoverPubkeyError> {
210 Err(RecoverPubkeyError::unknown_err(0))
211 }
212
213 fn ed25519_verify(
214 &self,
215 _message: &[u8],
216 _signature: &[u8],
217 _public_key: &[u8],
218 ) -> Result<bool, VerificationError> {
219 Ok(true)
220 }
221
222 fn ed25519_batch_verify(
223 &self,
224 _messages: &[&[u8]],
225 _signatures: &[&[u8]],
226 _public_keys: &[&[u8]],
227 ) -> Result<bool, VerificationError> {
228 Ok(true)
229 }
230
231 fn debug(&self, message: &str) {
232 println!("{message}");
233 }
234}
235
236#[derive(Default)]
238pub struct EmptyQuerier {}
239
240impl Querier for EmptyQuerier {
241 fn raw_query(&self, _bin_request: &[u8]) -> cosmwasm_std::QuerierResult {
242 todo!()
243 }
244}
245
246#[cfg(test)]
247mod tests {
248 use super::*;
249
250 #[test]
251 fn idb_state_dump_round_trips_through_storage() {
252 let mut storage = MemoryStorage::new();
253 storage.set(b"key1", b"value1");
254 storage.set(b"key2", b"value2");
255
256 let dump = IdbStateDump::from(storage);
257 assert_eq!(
258 dump.state_dump.get(b"key1".as_ref()),
259 Some(&b"value1".to_vec())
260 );
261 assert_eq!(
262 dump.state_dump.get(b"key2".as_ref()),
263 Some(&b"value2".to_vec())
264 );
265 }
266
267 #[test]
268 fn idb_storage_load_restores_all_keys() {
269 let mut storage = MemoryStorage::new();
270 storage.set(b"foo", b"bar");
271 storage.set(b"baz", b"qux");
272
273 let dump = IdbStateDump::from(storage);
274 let loaded = IdbStorage::load(dump);
275
276 assert_eq!(loaded.storage.get(b"foo"), Some(b"bar".to_vec()));
277 assert_eq!(loaded.storage.get(b"baz"), Some(b"qux".to_vec()));
278 }
279
280 #[test]
281 fn idb_state_dump_empty_storage_produces_empty_map() {
282 let storage = MemoryStorage::new();
283 let dump = IdbStateDump::from(storage);
284 assert!(dump.state_dump.is_empty());
285 }
286}