bittensor_core/codec/
storage.rs1#![allow(clippy::indexing_slicing)]
12
13use sp_core::hashing::{blake2_128, blake2_256, twox_128, twox_64};
14
15use crate::codec::decode::Cursor;
16use crate::codec::value::Value;
17use crate::error::CoreError;
18use crate::runtime::{Runtime, StorageInfo};
19
20pub fn hash_param(hasher: &str, data: &[u8]) -> Result<Vec<u8>, CoreError> {
22 Ok(match hasher {
23 "Blake2_256" => blake2_256(data).to_vec(),
24 "Blake2_128" => blake2_128(data).to_vec(),
25 "Blake2_128Concat" => {
26 let mut out = blake2_128(data).to_vec();
27 out.extend_from_slice(data);
28 out
29 }
30 "Twox256" => sp_core::hashing::twox_256(data).to_vec(),
31 "Twox128" => twox_128(data).to_vec(),
32 "Twox64Concat" => {
33 let mut out = twox_64(data).to_vec();
34 out.extend_from_slice(data);
35 out
36 }
37 "Identity" => data.to_vec(),
38 other => {
39 return Err(CoreError::Codec(format!(
40 "unknown storage hasher {other:?}"
41 )))
42 }
43 })
44}
45
46pub fn concat_hash_len(hasher: &str) -> Result<usize, CoreError> {
49 match hasher {
50 "Blake2_128Concat" => Ok(16),
51 "Twox64Concat" => Ok(8),
52 "Identity" => Ok(0),
53 other => Err(CoreError::Codec(format!(
54 "cannot recover map keys hashed with {other:?}"
55 ))),
56 }
57}
58
59pub fn storage_prefix(entry: &StorageInfo) -> Vec<u8> {
61 let mut out = twox_128(entry.prefix.as_bytes()).to_vec();
62 out.extend_from_slice(&twox_128(entry.name.as_bytes()));
63 out
64}
65
66impl Runtime {
67 pub fn storage_key(&self, entry: &StorageInfo, params: &[Value]) -> Result<Vec<u8>, CoreError> {
70 if params.len() > entry.key_types.len() {
71 return Err(CoreError::Codec(format!(
72 "{}.{} accepts at most {} parameters, {} given",
73 entry.prefix,
74 entry.name,
75 entry.key_types.len(),
76 params.len()
77 )));
78 }
79 let mut key = storage_prefix(entry);
80 for (index, param) in params.iter().enumerate() {
81 let hasher = entry.hashers.get(index).ok_or_else(|| {
82 CoreError::Codec(format!(
83 "{}.{} metadata declares no hasher for param #{}",
84 entry.prefix,
85 entry.name,
86 index.saturating_add(1)
87 ))
88 })?;
89 let mut encoded = Vec::new();
90 self.encode_id(entry.key_types[index], param, &mut encoded)?;
91 key.extend_from_slice(&hash_param(hasher, &encoded)?);
92 }
93 Ok(key)
94 }
95
96 pub fn decode_storage_key_params(
102 &self,
103 entry: &StorageInfo,
104 key: &[u8],
105 fixed: usize,
106 ) -> Result<Vec<Value>, CoreError> {
107 let mut prefix_len = 32usize; for index in 0..fixed {
109 let hasher = entry.hashers.get(index).ok_or_else(|| {
110 CoreError::Codec(format!(
111 "{}.{} metadata declares no hasher for param #{}",
112 entry.prefix,
113 entry.name,
114 index.saturating_add(1)
115 ))
116 })?;
117 let encoded_len = match hasher.as_str() {
120 "Blake2_256" | "Twox256" => 32,
121 "Blake2_128" | "Twox128" => 16,
122 _ => {
123 let hash_len = concat_hash_len(hasher)?;
126 let rest = key
127 .get(prefix_len.saturating_add(hash_len)..)
128 .ok_or_else(|| {
129 CoreError::Codec("storage key shorter than its prefix".into())
130 })?;
131 let mut cursor = Cursor::new(rest);
132 self.decode_id(entry.key_types[index], &mut cursor)?;
133 hash_len.saturating_add(cursor.offset)
134 }
135 };
136 prefix_len = prefix_len.saturating_add(encoded_len);
137 }
138
139 let trailing = key
140 .get(prefix_len..)
141 .ok_or_else(|| CoreError::Codec("storage key shorter than its prefix".into()))?;
142 let mut cursor = Cursor::new(trailing);
143 let mut out = Vec::new();
144 for index in fixed..entry.key_types.len() {
145 let hasher = entry.hashers.get(index).ok_or_else(|| {
146 CoreError::Codec(format!(
147 "{}.{} metadata declares no hasher for param #{}",
148 entry.prefix,
149 entry.name,
150 index.saturating_add(1)
151 ))
152 })?;
153 let skip = concat_hash_len(hasher)?;
154 cursor.take(skip)?;
155 out.push(self.decode_id(entry.key_types[index], &mut cursor)?);
156 }
157 if cursor.remaining() != 0 {
158 return Err(CoreError::Codec(format!(
159 "{} undecoded bytes remain in storage key",
160 cursor.remaining()
161 )));
162 }
163 Ok(out)
164 }
165}