1use super::*;
2use sp_core::hashing::{blake2_128, blake2_256, twox_128, twox_256, twox_64};
3
4#[derive(Clone)]
8pub struct StorageMetadata {
9 pub prefix: String,
11 pub entries: BTreeMap<String, StorageEntryMetadata>,
13}
14
15impl StorageMetadata {
16 #[cfg(feature = "v12")]
27 pub fn from_v12_meta(
28 md: frame_metadata::v12::StorageMetadata,
29 lookup: &mut Types,
30 ) -> Result<Self> {
31 let prefix = decode_meta(&md.prefix)?.clone();
32 let mut entries = BTreeMap::new();
33
34 decode_meta(&md.entries)?
35 .iter()
36 .try_for_each(|entry| -> Result<()> {
37 let entry_md = StorageEntryMetadata::from_v12_meta(entry, lookup)?;
38 let name = entry_md.name.clone();
39 entries.insert(name, entry_md);
40 Ok(())
41 })?;
42
43 Ok(Self { prefix, entries })
44 }
45
46 #[cfg(feature = "v13")]
57 pub fn from_v13_meta(
58 md: frame_metadata::v13::StorageMetadata,
59 lookup: &mut Types,
60 ) -> Result<Self> {
61 let prefix = decode_meta(&md.prefix)?.clone();
62 let mut entries = BTreeMap::new();
63
64 decode_meta(&md.entries)?
65 .iter()
66 .try_for_each(|entry| -> Result<()> {
67 let entry_md = StorageEntryMetadata::from_v13_meta(entry, lookup)?;
68 let name = entry_md.name.clone();
69 entries.insert(name, entry_md);
70 Ok(())
71 })?;
72
73 Ok(Self { prefix, entries })
74 }
75
76 #[cfg(feature = "v14")]
87 pub fn from_v14_meta(
88 md: &frame_metadata::v14::PalletStorageMetadata<PortableForm>,
89 types: &PortableRegistry,
90 ) -> Result<Self> {
91 let prefix = md.prefix.clone();
92 let mut entries = BTreeMap::new();
93
94 md.entries.iter().try_for_each(|entry| -> Result<()> {
95 let entry_md = StorageEntryMetadata::from_v14_meta(entry, types)?;
96 let name = entry_md.name.clone();
97 entries.insert(name, entry_md);
98 Ok(())
99 })?;
100
101 Ok(Self { prefix, entries })
102 }
103
104 pub fn pallet_prefix_hash(&self) -> Vec<u8> {
110 twox_128(self.prefix.as_bytes()).to_vec()
111 }
112
113 pub fn storage_prefix_hash(&self, entry_name: &str) -> Result<Vec<u8>> {
124 let entry = self.entries.get(entry_name).ok_or_else(|| {
125 Error::StorageKeyGenerationFailed(format!("Storage entry '{}' not found", entry_name))
126 })?;
127 Ok(entry.entry_prefix_hash(&self.pallet_prefix_hash()))
128 }
129
130 pub fn storage_key(&self, entry_name: &str, keys: &[Vec<u8>]) -> Result<Vec<u8>> {
143 let entry = self.entries.get(entry_name).ok_or_else(|| {
144 Error::StorageKeyGenerationFailed(format!("Storage entry '{}' not found", entry_name))
145 })?;
146 entry.storage_key(&self.pallet_prefix_hash(), keys)
147 }
148}
149
150#[derive(Clone)]
152pub enum StorageHasher {
153 Blake2_128,
155 Blake2_256,
157 Blake2_128Concat,
159 Twox128,
161 Twox256,
163 Twox64Concat,
165 Identity,
167}
168
169impl StorageHasher {
170 pub fn hash_data(&self, data: &[u8]) -> Vec<u8> {
180 match self {
181 Self::Blake2_128 => blake2_128(data).to_vec(),
182 Self::Blake2_256 => blake2_256(data).to_vec(),
183 Self::Blake2_128Concat => {
184 let mut result = blake2_128(data).to_vec();
185 result.extend_from_slice(data);
186 result
187 }
188 Self::Twox128 => twox_128(data).to_vec(),
189 Self::Twox256 => twox_256(data).to_vec(),
190 Self::Twox64Concat => {
191 let mut result = twox_64(data).to_vec();
192 result.extend_from_slice(data);
193 result
194 }
195 Self::Identity => data.to_vec(),
196 }
197 }
198}
199
200#[cfg(feature = "v12")]
201impl From<&frame_metadata::v12::StorageHasher> for StorageHasher {
202 fn from(hasher: &frame_metadata::v12::StorageHasher) -> Self {
203 use frame_metadata::v12::StorageHasher as MetadataHasher;
204 match hasher {
205 MetadataHasher::Blake2_128 => Self::Blake2_128,
206 MetadataHasher::Blake2_256 => Self::Blake2_256,
207 MetadataHasher::Blake2_128Concat => Self::Blake2_128Concat,
208 MetadataHasher::Twox128 => Self::Twox128,
209 MetadataHasher::Twox256 => Self::Twox256,
210 MetadataHasher::Twox64Concat => Self::Twox64Concat,
211 MetadataHasher::Identity => Self::Identity,
212 }
213 }
214}
215
216#[cfg(feature = "v13")]
217impl From<&frame_metadata::v13::StorageHasher> for StorageHasher {
218 fn from(hasher: &frame_metadata::v13::StorageHasher) -> Self {
219 use frame_metadata::v13::StorageHasher as MetadataHasher;
220 match hasher {
221 MetadataHasher::Blake2_128 => Self::Blake2_128,
222 MetadataHasher::Blake2_256 => Self::Blake2_256,
223 MetadataHasher::Blake2_128Concat => Self::Blake2_128Concat,
224 MetadataHasher::Twox128 => Self::Twox128,
225 MetadataHasher::Twox256 => Self::Twox256,
226 MetadataHasher::Twox64Concat => Self::Twox64Concat,
227 MetadataHasher::Identity => Self::Identity,
228 }
229 }
230}
231
232#[cfg(feature = "v14")]
233impl From<&frame_metadata::v14::StorageHasher> for StorageHasher {
234 fn from(hasher: &frame_metadata::v14::StorageHasher) -> Self {
235 use frame_metadata::v14::StorageHasher as MetadataHasher;
236 match hasher {
237 MetadataHasher::Blake2_128 => Self::Blake2_128,
238 MetadataHasher::Blake2_256 => Self::Blake2_256,
239 MetadataHasher::Blake2_128Concat => Self::Blake2_128Concat,
240 MetadataHasher::Twox128 => Self::Twox128,
241 MetadataHasher::Twox256 => Self::Twox256,
242 MetadataHasher::Twox64Concat => Self::Twox64Concat,
243 MetadataHasher::Identity => Self::Identity,
244 }
245 }
246}
247
248#[derive(Clone)]
252pub enum StorageEntryType {
253 Plain(TypeId),
255 Map {
257 hasher: StorageHasher,
259 key: TypeId,
261 value: TypeId,
263 additional_hashers_keys: Vec<(StorageHasher, TypeId)>,
266 },
267}
268
269#[derive(Clone)]
271pub enum StorageEntryModifier {
272 Optional,
274 Default,
276}
277
278#[cfg(feature = "v12")]
279impl From<&frame_metadata::v12::StorageEntryModifier> for StorageEntryModifier {
280 fn from(modifier: &frame_metadata::v12::StorageEntryModifier) -> Self {
281 use frame_metadata::v12::StorageEntryModifier as MetadataModifier;
282 match modifier {
283 MetadataModifier::Optional => Self::Optional,
284 MetadataModifier::Default => Self::Default,
285 }
286 }
287}
288
289#[cfg(feature = "v13")]
290impl From<&frame_metadata::v13::StorageEntryModifier> for StorageEntryModifier {
291 fn from(modifier: &frame_metadata::v13::StorageEntryModifier) -> Self {
292 use frame_metadata::v13::StorageEntryModifier as MetadataModifier;
293 match modifier {
294 MetadataModifier::Optional => Self::Optional,
295 MetadataModifier::Default => Self::Default,
296 }
297 }
298}
299
300#[cfg(feature = "v14")]
301impl From<&frame_metadata::v14::StorageEntryModifier> for StorageEntryModifier {
302 fn from(modifier: &frame_metadata::v14::StorageEntryModifier) -> Self {
303 use frame_metadata::v14::StorageEntryModifier as MetadataModifier;
304 match modifier {
305 MetadataModifier::Optional => Self::Optional,
306 MetadataModifier::Default => Self::Default,
307 }
308 }
309}
310
311#[derive(Clone)]
313pub struct StorageEntryMetadata {
314 pub name: String,
316 pub modifier: StorageEntryModifier,
318 pub ty: StorageEntryType,
320 pub default: Vec<u8>,
322 pub docs: Docs,
324}
325
326impl StorageEntryMetadata {
327 #[cfg(feature = "v12")]
338 fn from_v12_meta(
339 md: &frame_metadata::v12::StorageEntryMetadata,
340 lookup: &mut Types,
341 ) -> Result<Self> {
342 let name = decode_meta(&md.name)?.clone();
343 let modifier = (&md.modifier).into();
344 let docs = Docs::from_v12_meta(&md.documentation)?;
345 let default = decode_meta(&md.default)?.clone();
346
347 let ty = match &md.ty {
348 frame_metadata::v12::StorageEntryType::Plain(plain_ty) => {
349 let ty_name = decode_meta(plain_ty)?;
350 let ty_id = lookup.parse_type(&ty_name)?;
351 StorageEntryType::Plain(ty_id)
352 }
353 frame_metadata::v12::StorageEntryType::Map {
354 hasher, key, value, ..
355 } => {
356 let key_ty = decode_meta(key)?;
357 let value_ty = decode_meta(value)?;
358 let key_id = lookup.parse_type(&key_ty)?;
359 let value_id = lookup.parse_type(&value_ty)?;
360 let hasher = hasher.into();
361
362 StorageEntryType::Map {
363 hasher,
364 key: key_id,
365 value: value_id,
366 additional_hashers_keys: Vec::new(),
367 }
368 }
369 frame_metadata::v12::StorageEntryType::DoubleMap {
370 hasher,
371 key1,
372 key2,
373 value,
374 key2_hasher,
375 } => {
376 let key1_ty = decode_meta(key1)?;
377 let key2_ty = decode_meta(key2)?;
378 let value_ty = decode_meta(value)?;
379 let key1_id = lookup.parse_type(&key1_ty)?;
380 let key2_id = lookup.parse_type(&key2_ty)?;
381 let value_id = lookup.parse_type(&value_ty)?;
382 let hasher1 = (hasher).into();
383 let hasher2 = (key2_hasher).into();
384
385 StorageEntryType::Map {
386 hasher: hasher1,
387 key: key1_id,
388 value: value_id,
389 additional_hashers_keys: vec![(hasher2, key2_id)],
390 }
391 }
392 };
393
394 Ok(Self {
395 name,
396 modifier,
397 ty,
398 default,
399 docs,
400 })
401 }
402
403 #[cfg(feature = "v13")]
414 fn from_v13_meta(
415 md: &frame_metadata::v13::StorageEntryMetadata,
416 lookup: &mut Types,
417 ) -> Result<Self> {
418 let name = decode_meta(&md.name)?.clone();
419 let modifier = (&md.modifier).into();
420 let docs = Docs::from_v13_meta(&md.documentation)?;
421 let default = decode_meta(&md.default)?.clone();
422
423 let ty = match &md.ty {
424 frame_metadata::v13::StorageEntryType::Plain(plain_ty) => {
425 let ty_name = decode_meta(plain_ty)?;
426 let ty_id = lookup.parse_type(&ty_name)?;
427 StorageEntryType::Plain(ty_id)
428 }
429 frame_metadata::v13::StorageEntryType::Map {
430 hasher, key, value, ..
431 } => {
432 let key_ty = decode_meta(key)?;
433 let value_ty = decode_meta(value)?;
434 let key_id = lookup.parse_type(&key_ty)?;
435 let value_id = lookup.parse_type(&value_ty)?;
436 let hasher = (hasher).into();
437
438 StorageEntryType::Map {
439 hasher,
440 key: key_id,
441 value: value_id,
442 additional_hashers_keys: Vec::new(),
443 }
444 }
445 frame_metadata::v13::StorageEntryType::DoubleMap {
446 hasher,
447 key1,
448 key2,
449 value,
450 key2_hasher,
451 } => {
452 let key1_ty = decode_meta(key1)?;
453 let key2_ty = decode_meta(key2)?;
454 let value_ty = decode_meta(value)?;
455 let key1_id = lookup.parse_type(&key1_ty)?;
456 let key2_id = lookup.parse_type(&key2_ty)?;
457 let value_id = lookup.parse_type(&value_ty)?;
458 let hasher1 = (hasher).into();
459 let hasher2 = (key2_hasher).into();
460
461 StorageEntryType::Map {
462 hasher: hasher1,
463 key: key1_id,
464 value: value_id,
465 additional_hashers_keys: vec![(hasher2, key2_id)],
466 }
467 }
468 frame_metadata::v13::StorageEntryType::NMap {
469 hashers,
470 keys,
471 value,
472 } => {
473 let keys_ty = decode_meta(keys)?;
474 let value_ty = decode_meta(value)?;
475 let hashers_vec = decode_meta(hashers)?;
476
477 let first_key_ty = &keys_ty[0];
479 let first_key_id = lookup.parse_type(first_key_ty)?;
480 let first_hasher = (&hashers_vec[0]).into();
481
482 let mut additional_hashers_keys = Vec::new();
484 for i in 1..keys_ty.len() {
485 let key_ty = &keys_ty[i];
486 let key_id = lookup.parse_type(key_ty)?;
487 let hasher = (&hashers_vec[i]).into();
488 additional_hashers_keys.push((hasher, key_id));
489 }
490
491 let value_id = lookup.parse_type(&value_ty)?;
492
493 StorageEntryType::Map {
494 hasher: first_hasher,
495 key: first_key_id,
496 value: value_id,
497 additional_hashers_keys,
498 }
499 }
500 };
501
502 Ok(Self {
503 name,
504 modifier,
505 ty,
506 default,
507 docs,
508 })
509 }
510
511 #[cfg(feature = "v14")]
522 fn from_v14_meta(
523 md: &frame_metadata::v14::StorageEntryMetadata<PortableForm>,
524 types: &PortableRegistry,
525 ) -> Result<Self> {
526 let name = md.name.clone();
527 let modifier = (&md.modifier).into();
528 let docs = Docs::from_v14_meta(&md.docs);
529 let default = md.default.clone();
530
531 let ty = match &md.ty {
532 frame_metadata::v14::StorageEntryType::Plain(plain_ty) => {
533 StorageEntryType::Plain(TypeId::from(plain_ty.id))
534 }
535 frame_metadata::v14::StorageEntryType::Map {
536 hashers,
537 key,
538 value,
539 } => {
540 if hashers.len() == 1 {
541 let hasher = (&hashers[0]).into();
543 StorageEntryType::Map {
544 hasher,
545 key: TypeId::from(key.id),
546 value: TypeId::from(value.id),
547 additional_hashers_keys: Vec::new(),
548 }
549 } else if hashers.len() > 1 {
550 let first_hasher = (&hashers[0]).into();
552
553 let key_type = types
555 .resolve(key.id)
556 .ok_or_else(|| Error::MetadataParseFailed("Failed to resolve NMap key type".into()))?;
557
558 let mut additional_hashers_keys = Vec::new();
559
560 if let TypeDef::Tuple(tuple) = key_type.type_def() {
561 if tuple.fields.len() != hashers.len() {
562 return Err(Error::MetadataParseFailed(
563 "Mismatch between hashers and key types count".into(),
564 ));
565 }
566
567 for i in 1..hashers.len() {
569 let key_id = tuple.fields[i].id();
570 let hasher = (&hashers[i]).into();
571 additional_hashers_keys.push((hasher, TypeId::from(key_id)));
572 }
573
574 StorageEntryType::Map {
575 hasher: first_hasher,
576 key: TypeId::from(tuple.fields[0].id()),
577 value: TypeId::from(value.id),
578 additional_hashers_keys,
579 }
580 } else {
581 return Err(Error::MetadataParseFailed(
582 "Expected tuple type for NMap keys".into(),
583 ));
584 }
585 } else {
586 return Err(Error::MetadataParseFailed(
587 "Empty hashers list in map storage entry".into(),
588 ));
589 }
590 }
591 };
592
593 Ok(Self {
594 name,
595 modifier,
596 ty,
597 default,
598 docs,
599 })
600 }
601
602 pub fn entry_prefix_hash(&self, pallet_prefix_hash: &[u8]) -> Vec<u8> {
612 let mut result = pallet_prefix_hash.to_vec();
613 result.extend_from_slice(&twox_128(self.name.as_bytes()));
614 result
615 }
616
617 pub fn storage_key(&self, pallet_prefix_hash: &[u8], keys: &[Vec<u8>]) -> Result<Vec<u8>> {
629 let mut key = self.entry_prefix_hash(pallet_prefix_hash);
631
632 match &self.ty {
633 StorageEntryType::Plain(_) => {
634 if !keys.is_empty() {
636 return Err(Error::StorageKeyGenerationFailed(
637 "Plain storage takes no keys".into(),
638 ));
639 }
640 }
641 StorageEntryType::Map {
642 hasher,
643 additional_hashers_keys,
644 ..
645 } => {
646 let expected_keys = 1 + additional_hashers_keys.len();
648 if keys.len() != expected_keys {
649 return Err(Error::StorageKeyGenerationFailed(format!(
650 "Expected {} keys for this map, got {}",
651 expected_keys,
652 keys.len()
653 )));
654 }
655
656 key.extend_from_slice(&hasher.hash_data(&keys[0]));
658
659 for (i, (hasher, _)) in additional_hashers_keys.iter().enumerate() {
661 key.extend_from_slice(&hasher.hash_data(&keys[i + 1]));
662 }
663 }
664 }
665
666 Ok(key)
667 }
668}