1use crate::metadata::MetadataError;
17use alloc::{borrow::ToOwned, vec::Vec};
18use codec::Encode;
19use core::marker::PhantomData;
20use frame_metadata::v15::{StorageEntryMetadata, StorageEntryType, StorageHasher};
21use scale_info::form::PortableForm;
22use sp_storage::StorageKey;
23
24#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
25pub struct StorageValue {
26 module_prefix: Vec<u8>,
27 storage_prefix: Vec<u8>,
28}
29
30impl StorageValue {
31 pub fn key(&self) -> StorageKey {
32 let mut bytes = sp_crypto_hashing::twox_128(&self.module_prefix).to_vec();
33 bytes.extend(&sp_crypto_hashing::twox_128(&self.storage_prefix)[..]);
34 StorageKey(bytes)
35 }
36}
37
38#[derive(Clone, PartialEq, Eq, Debug)]
39pub struct StorageMap<K> {
40 _marker: PhantomData<K>,
41 module_prefix: Vec<u8>,
42 storage_prefix: Vec<u8>,
43 hasher: StorageHasher,
44}
45
46impl<K: Encode> StorageMap<K> {
47 pub fn key(&self, key: K) -> StorageKey {
48 let mut bytes = sp_crypto_hashing::twox_128(&self.module_prefix).to_vec();
49 bytes.extend(&sp_crypto_hashing::twox_128(&self.storage_prefix)[..]);
50 bytes.extend(key_hash(&key, &self.hasher));
51 StorageKey(bytes)
52 }
53}
54
55#[derive(Clone, PartialEq, Eq, Debug)]
56pub struct StorageDoubleMap<K, Q> {
57 _marker: PhantomData<K>,
58 _marker2: PhantomData<Q>,
59 module_prefix: Vec<u8>,
60 storage_prefix: Vec<u8>,
61 hasher: StorageHasher,
62 key2_hasher: StorageHasher,
63}
64
65impl<K: Encode, Q: Encode> StorageDoubleMap<K, Q> {
66 pub fn key(&self, key1: K, key2: Q) -> StorageKey {
67 let mut bytes = sp_crypto_hashing::twox_128(&self.module_prefix).to_vec();
68 bytes.extend(&sp_crypto_hashing::twox_128(&self.storage_prefix)[..]);
69 bytes.extend(key_hash(&key1, &self.hasher));
70 bytes.extend(key_hash(&key2, &self.key2_hasher));
71 StorageKey(bytes)
72 }
73}
74
75pub trait GetStorageTypes {
77 fn get_double_map<K: Encode, Q: Encode>(
78 &self,
79 pallet_prefix: &str,
80 ) -> Result<StorageDoubleMap<K, Q>, MetadataError>;
81 fn get_map<K: Encode>(&self, pallet_prefix: &str) -> Result<StorageMap<K>, MetadataError>;
82 fn get_map_prefix(&self, pallet_prefix: &str) -> Result<StorageKey, MetadataError>;
83 fn get_value(&self, pallet_prefix: &str) -> Result<StorageValue, MetadataError>;
84 fn get_double_map_prefix<K: Encode>(
85 &self,
86 pallet_prefix: &str,
87 key1: K,
88 ) -> Result<StorageKey, MetadataError>;
89}
90
91impl GetStorageTypes for StorageEntryMetadata<PortableForm> {
92 fn get_double_map<K: Encode, Q: Encode>(
93 &self,
94 pallet_prefix: &str,
95 ) -> Result<StorageDoubleMap<K, Q>, MetadataError> {
96 match &self.ty {
97 StorageEntryType::Map { hashers, .. } => {
98 let module_prefix = pallet_prefix.as_bytes().to_vec();
99 let storage_prefix = self.name.as_bytes().to_vec();
100 let hasher1 = hashers.first().ok_or(MetadataError::StorageTypeError)?;
101 let hasher2 = hashers.get(1).ok_or(MetadataError::StorageTypeError)?;
102
103 #[cfg(feature = "std")]
105 log::debug!(
106 "map for '{}' '{}' has hasher1 {:?} hasher2 {:?}",
107 pallet_prefix,
108 self.name,
109 hasher1,
110 hasher2
111 );
112
113 Ok(StorageDoubleMap {
114 _marker: PhantomData,
115 _marker2: PhantomData,
116 module_prefix,
117 storage_prefix,
118 hasher: hasher1.to_owned(),
119 key2_hasher: hasher2.to_owned(),
120 })
121 },
122 _ => Err(MetadataError::StorageTypeError),
123 }
124 }
125 fn get_map<K: Encode>(&self, pallet_prefix: &str) -> Result<StorageMap<K>, MetadataError> {
126 match &self.ty {
127 StorageEntryType::Map { hashers, .. } => {
128 let hasher = hashers.first().ok_or(MetadataError::StorageTypeError)?.to_owned();
129
130 let module_prefix = pallet_prefix.as_bytes().to_vec();
131 let storage_prefix = self.name.as_bytes().to_vec();
132
133 #[cfg(feature = "std")]
135 log::debug!("map for '{}' '{}' has hasher {:?}", pallet_prefix, self.name, hasher);
136
137 Ok(StorageMap { _marker: PhantomData, module_prefix, storage_prefix, hasher })
138 },
139 _ => Err(MetadataError::StorageTypeError),
140 }
141 }
142 fn get_map_prefix(&self, pallet_prefix: &str) -> Result<StorageKey, MetadataError> {
143 match &self.ty {
144 StorageEntryType::Map { .. } => {
145 let mut bytes = sp_crypto_hashing::twox_128(pallet_prefix.as_bytes()).to_vec();
146 bytes.extend(&sp_crypto_hashing::twox_128(self.name.as_bytes())[..]);
147 Ok(StorageKey(bytes))
148 },
149 _ => Err(MetadataError::StorageTypeError),
150 }
151 }
152
153 fn get_double_map_prefix<K: Encode>(
154 &self,
155 pallet_prefix: &str,
156 key1: K,
157 ) -> Result<StorageKey, MetadataError> {
158 match &self.ty {
159 StorageEntryType::Map { hashers, .. } => {
160 let module_prefix = pallet_prefix.as_bytes();
161 let storage_prefix = self.name.as_bytes();
162
163 let hasher1 = hashers.first().ok_or(MetadataError::StorageTypeError)?;
164
165 let mut bytes = sp_crypto_hashing::twox_128(module_prefix).to_vec();
166 bytes.extend(&sp_crypto_hashing::twox_128(storage_prefix)[..]);
167 bytes.extend(key_hash(&key1, hasher1));
168
169 Ok(StorageKey(bytes))
170 },
171 _ => Err(MetadataError::StorageTypeError),
172 }
173 }
174
175 fn get_value(&self, pallet_prefix: &str) -> Result<StorageValue, MetadataError> {
176 match &self.ty {
177 StorageEntryType::Plain { .. } => {
178 let module_prefix = pallet_prefix.as_bytes().to_vec();
179 let storage_prefix = self.name.as_bytes().to_vec();
180 Ok(StorageValue { module_prefix, storage_prefix })
181 },
182 _ => Err(MetadataError::StorageTypeError),
183 }
184 }
185}
186
187fn key_hash<K: Encode>(key: &K, hasher: &StorageHasher) -> Vec<u8> {
189 let encoded_key = key.encode();
190 match hasher {
191 StorageHasher::Identity => encoded_key.to_vec(),
192 StorageHasher::Blake2_128 => sp_crypto_hashing::blake2_128(&encoded_key).to_vec(),
193 StorageHasher::Blake2_128Concat => {
194 let x: &[u8] = encoded_key.as_slice();
196 sp_crypto_hashing::blake2_128(x)
197 .iter()
198 .chain(x.iter())
199 .cloned()
200 .collect::<Vec<_>>()
201 },
202 StorageHasher::Blake2_256 => sp_crypto_hashing::blake2_256(&encoded_key).to_vec(),
203 StorageHasher::Twox128 => sp_crypto_hashing::twox_128(&encoded_key).to_vec(),
204 StorageHasher::Twox256 => sp_crypto_hashing::twox_256(&encoded_key).to_vec(),
205 StorageHasher::Twox64Concat => sp_crypto_hashing::twox_64(&encoded_key)
206 .iter()
207 .chain(&encoded_key)
208 .cloned()
209 .collect(),
210 }
211}