ac_node_api/
storage.rs

1/*
2	Copyright 2021 Integritee AG and Supercomputing Systems AG
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		http://www.apache.org/licenses/LICENSE-2.0
7	Unless required by applicable law or agreed to in writing, software
8	distributed under the License is distributed on an "AS IS" BASIS,
9	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10	See the License for the specific language governing permissions and
11	limitations under the License.
12*/
13
14//! For querying runtime storage.
15
16use 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
75/// trait to extract the storage based on the [`StorageEntryMetadata`].
76pub 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				// hashers do not implement debug in no_std
104				#[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				// hashers do not implement debug in no_std
134				#[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
187/// generates the key's hash depending on the StorageHasher selected
188fn 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			// copied from substrate Blake2_128Concat::hash since StorageHasher is not public
195			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}