frame_decode/decoding/
storage_decoder.rs

1// Copyright (C) 2022-2023 Parity Technologies (UK) Ltd. (admin@parity.io)
2// This file is a part of the scale-value crate.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//         http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use super::storage_type_info::{StorageHasher, StorageTypeInfo};
17use crate::decoding::storage_type_info::StorageInfoError;
18use crate::utils::{decode_with_error_tracing, DecodeErrorTrace};
19use alloc::vec;
20use alloc::vec::Vec;
21use core::ops::Range;
22use scale_type_resolver::TypeResolver;
23
24/// An error returned trying to decode storage bytes.
25#[non_exhaustive]
26#[allow(missing_docs)]
27#[derive(Clone, Debug)]
28pub enum StorageKeyDecodeError<TypeId> {
29    CannotGetInfo(StorageInfoError<'static>),
30    PrefixMismatch,
31    NotEnoughBytes {
32        needed: usize,
33        have: usize,
34    },
35    CannotDecodeKey {
36        ty: TypeId,
37        reason: DecodeErrorTrace,
38        decoded_so_far: StorageKey<TypeId>,
39    },
40}
41
42impl<TypeId: core::fmt::Debug> core::error::Error for StorageKeyDecodeError<TypeId> {}
43
44impl<TypeId: core::fmt::Debug> core::fmt::Display for StorageKeyDecodeError<TypeId> {
45    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
46        match self {
47            StorageKeyDecodeError::CannotGetInfo(storage_info_error) => {
48                write!(f, "Cannot get storage info:\n\n{storage_info_error}")
49            }
50            StorageKeyDecodeError::PrefixMismatch => {
51                write!(f, "The hashed storage prefix given does not match the pallet and storage name asked to decode.")
52            }
53            StorageKeyDecodeError::NotEnoughBytes { needed, have } => {
54                write!(
55                    f,
56                    "Not enough bytes left: we need at least {needed} bytes but have {have} bytes"
57                )
58            }
59            StorageKeyDecodeError::CannotDecodeKey {
60                ty,
61                reason,
62                decoded_so_far,
63            } => {
64                write!(f, "Cannot decode storage key '{ty:?}':\n\n{reason}\n\nDecoded so far:\n\n{decoded_so_far}")
65            }
66        }
67    }
68}
69
70impl<TypeId> StorageKeyDecodeError<TypeId> {
71    /// Map the storage key error type IDs to something else.
72    pub fn map_type_id<NewTypeId, F>(self, mut f: F) -> StorageKeyDecodeError<NewTypeId>
73    where
74        F: FnMut(TypeId) -> NewTypeId,
75    {
76        match self {
77            StorageKeyDecodeError::CannotGetInfo(e) => StorageKeyDecodeError::CannotGetInfo(e),
78            StorageKeyDecodeError::PrefixMismatch => StorageKeyDecodeError::PrefixMismatch,
79            StorageKeyDecodeError::NotEnoughBytes { needed, have } => {
80                StorageKeyDecodeError::NotEnoughBytes { needed, have }
81            }
82            StorageKeyDecodeError::CannotDecodeKey {
83                ty,
84                reason,
85                decoded_so_far,
86            } => StorageKeyDecodeError::CannotDecodeKey {
87                ty: f(ty),
88                reason,
89                decoded_so_far: decoded_so_far.map_type_id(f),
90            },
91        }
92    }
93}
94
95/// An error returned trying to decode storage bytes.
96#[non_exhaustive]
97#[allow(missing_docs)]
98#[derive(Clone, Debug)]
99pub enum StorageValueDecodeError<TypeId> {
100    CannotGetInfo(StorageInfoError<'static>),
101    CannotDecodeValue {
102        ty: TypeId,
103        reason: DecodeErrorTrace,
104    },
105}
106
107impl<TypeId: core::fmt::Debug> core::error::Error for StorageValueDecodeError<TypeId> {}
108
109impl<TypeId: core::fmt::Debug> core::fmt::Display for StorageValueDecodeError<TypeId> {
110    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
111        match self {
112            StorageValueDecodeError::CannotGetInfo(storage_info_error) => {
113                write!(f, "Cannot get storage info:\n\n{storage_info_error}")
114            }
115            StorageValueDecodeError::CannotDecodeValue { ty, reason } => {
116                write!(f, "Cannot decode value with type ID {ty:?}:\n\n{reason}")
117            }
118        }
119    }
120}
121
122impl<TypeId> StorageValueDecodeError<TypeId> {
123    /// Map the storage value error type IDs to something else.
124    pub fn map_type_id<NewTypeId, F>(self, mut f: F) -> StorageValueDecodeError<NewTypeId>
125    where
126        F: FnMut(TypeId) -> NewTypeId,
127    {
128        match self {
129            StorageValueDecodeError::CannotGetInfo(e) => StorageValueDecodeError::CannotGetInfo(e),
130            StorageValueDecodeError::CannotDecodeValue { ty, reason } => {
131                StorageValueDecodeError::CannotDecodeValue { ty: f(ty), reason }
132            }
133        }
134    }
135}
136
137/// Details about a storage key.
138#[derive(Clone, Debug)]
139pub struct StorageKey<TypeId> {
140    parts: Vec<StorageKeyPart<TypeId>>,
141}
142
143impl<TypeId: core::fmt::Debug> core::fmt::Display for StorageKey<TypeId> {
144    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
145        // Plain entries have no keys:
146        if self.parts.is_empty() {
147            write!(f, "No storage parts")?;
148            return Ok(());
149        }
150
151        // hash type: blake2,
152        // hash range: 0..13,
153        // value range: 13..23,
154        // value type: AccountId
155        //
156        // ...
157        for key in self.parts.iter() {
158            writeln!(f, "Hash type: {:?}", key.hasher)?;
159            writeln!(
160                f,
161                "Hash range: {}..{}",
162                key.hash_range.start, key.hash_range.end
163            )?;
164            if let Some(v) = &key.value {
165                writeln!(f, "Value type: {:?}", v.ty)?;
166                writeln!(f, "Value range: {}..{}", v.range.start, v.range.end)?;
167            }
168
169            writeln!(f)?;
170        }
171
172        Ok(())
173    }
174}
175
176impl<TypeId> StorageKey<TypeId> {
177    /// Iterate over the parts of this storage key.
178    pub fn parts(&self) -> impl ExactSizeIterator<Item = &StorageKeyPart<TypeId>> {
179        self.parts.iter()
180    }
181
182    /// Map the storage key type IDs to something else.
183    pub fn map_type_id<NewTypeId, F>(self, mut f: F) -> StorageKey<NewTypeId>
184    where
185        F: FnMut(TypeId) -> NewTypeId,
186    {
187        StorageKey {
188            parts: self
189                .parts
190                .into_iter()
191                .map(|p| p.map_type_id(&mut f))
192                .collect(),
193        }
194    }
195}
196
197/// The decoded representation of a storage key.
198#[derive(Clone, Debug)]
199pub struct StorageKeyPart<TypeId> {
200    hash_range: Range<u32>,
201    value: Option<StorageKeyPartValue<TypeId>>,
202    hasher: StorageHasher,
203}
204
205impl<TypeId> StorageKeyPart<TypeId> {
206    /// The byte range of the hash for this storage key part.
207    pub fn hash_range(&self) -> Range<usize> {
208        Range {
209            start: self.hash_range.start as usize,
210            end: self.hash_range.end as usize,
211        }
212    }
213
214    /// The hasher used for this storage key part.
215    pub fn hasher(&self) -> StorageHasher {
216        self.hasher
217    }
218
219    /// If applicable (ie this part uses a concat or ident hasher), return information
220    /// about the value encoded into this hash.
221    pub fn value(&self) -> Option<&StorageKeyPartValue<TypeId>> {
222        self.value.as_ref()
223    }
224
225    /// Map the storage part type ID to something else.
226    pub fn map_type_id<NewTypeId, F>(self, f: F) -> StorageKeyPart<NewTypeId>
227    where
228        F: FnMut(TypeId) -> NewTypeId,
229    {
230        StorageKeyPart {
231            hash_range: self.hash_range,
232            value: self.value.map(|v| v.map_type_id(f)),
233            hasher: self.hasher,
234        }
235    }
236}
237
238/// Information about the value contained within a storage key part hash.
239#[derive(Clone, Debug)]
240pub struct StorageKeyPartValue<TypeId> {
241    range: Range<u32>,
242    ty: TypeId,
243}
244
245impl<TypeId> StorageKeyPartValue<TypeId> {
246    /// The byte range for this value in the storage key.
247    pub fn range(&self) -> Range<usize> {
248        Range {
249            start: self.range.start as usize,
250            end: self.range.end as usize,
251        }
252    }
253
254    /// The type ID for this value.
255    pub fn ty(&self) -> &TypeId {
256        &self.ty
257    }
258
259    /// Map the storage part type ID to something else.
260    pub fn map_type_id<NewTypeId, F>(self, mut f: F) -> StorageKeyPartValue<NewTypeId>
261    where
262        F: FnMut(TypeId) -> NewTypeId,
263    {
264        StorageKeyPartValue {
265            range: self.range,
266            ty: f(self.ty),
267        }
268    }
269}
270
271/// Decode a storage key, returning information about it.
272///
273/// This information can be used to identify and, where possible, decode the parts of the storage key.
274///
275/// # Example
276///
277/// Here, we decode some storage keys from a block.
278///
279/// ```rust
280/// use frame_decode::storage::decode_storage_key;
281/// use frame_decode::helpers::decode_with_visitor;
282/// use frame_metadata::RuntimeMetadata;
283/// use parity_scale_codec::Decode;
284/// use scale_value::scale::ValueVisitor;
285///
286/// let metadata_bytes = std::fs::read("artifacts/metadata_10000000_9180.scale").unwrap();
287/// let RuntimeMetadata::V14(metadata) = RuntimeMetadata::decode(&mut &*metadata_bytes).unwrap() else { return };
288///
289/// let storage_keyval_bytes = std::fs::read("artifacts/storage_10000000_9180_system_account.json").unwrap();
290/// let storage_keyval_hex: Vec<(String, String)> = serde_json::from_slice(&storage_keyval_bytes).unwrap();
291///
292/// for (key, _val) in storage_keyval_hex {
293///     let key_bytes = hex::decode(key.trim_start_matches("0x")).unwrap();
294///
295///     // Decode the storage key, returning information about it:
296///     let storage_info = decode_storage_key(
297///         "System",
298///         "Account",
299///         &mut &*key_bytes,
300///         &metadata,
301///         &metadata.types
302///     ).unwrap();
303///
304///     for part in storage_info.parts() {
305///         // Access information about the hasher for this part of the key:
306///         let hash_bytes = &key_bytes[part.hash_range()];
307///         let hasher = part.hasher();
308///
309///         // If the value is encoded as part of the hasher, we can find and
310///         // decode the value too:
311///         if let Some(value_info) = part.value() {
312///             let value_bytes = &key_bytes[value_info.range()];
313///             let value = decode_with_visitor(
314///                 &mut &*value_bytes,
315///                 *value_info.ty(),
316///                 &metadata.types,
317///                 ValueVisitor::new()
318///             ).unwrap();
319///         }
320///     }
321/// }
322/// ```
323pub fn decode_storage_key<Info, Resolver>(
324    pallet_name: &str,
325    storage_entry: &str,
326    cursor: &mut &[u8],
327    info: &Info,
328    type_resolver: &Resolver,
329) -> Result<StorageKey<Info::TypeId>, StorageKeyDecodeError<Info::TypeId>>
330where
331    Info: StorageTypeInfo,
332    Info::TypeId: Clone + core::fmt::Debug,
333    Resolver: TypeResolver<TypeId = Info::TypeId>,
334{
335    let storage_info = info
336        .get_storage_info(pallet_name, storage_entry)
337        .map_err(|e| StorageKeyDecodeError::CannotGetInfo(e.into_owned()))?;
338
339    let bytes = *cursor;
340    let curr_idx = |cursor: &mut &[u8]| (bytes.len() - cursor.len()) as u32;
341
342    let prefix = strip_bytes(cursor, 32)?;
343
344    // Check that the storage key prefix is what we expect:
345    let expected_prefix = {
346        let mut v = Vec::<u8>::with_capacity(16);
347        v.extend(&sp_crypto_hashing::twox_128(pallet_name.as_bytes()));
348        v.extend(&sp_crypto_hashing::twox_128(storage_entry.as_bytes()));
349        v
350    };
351    if prefix != expected_prefix {
352        return Err(StorageKeyDecodeError::PrefixMismatch);
353    }
354
355    let mut parts = vec![];
356    for key in storage_info.keys {
357        let hasher = key.hasher;
358        let start_idx = curr_idx(cursor);
359        let part = match &hasher {
360            StorageHasher::Blake2_128 | StorageHasher::Twox128 => {
361                strip_bytes(cursor, 16)?;
362                StorageKeyPart {
363                    hash_range: Range {
364                        start: start_idx,
365                        end: curr_idx(cursor),
366                    },
367                    value: None,
368                    hasher,
369                }
370            }
371            StorageHasher::Blake2_256 | StorageHasher::Twox256 => {
372                strip_bytes(cursor, 32)?;
373                StorageKeyPart {
374                    hash_range: Range {
375                        start: start_idx,
376                        end: curr_idx(cursor),
377                    },
378                    value: None,
379                    hasher,
380                }
381            }
382            StorageHasher::Blake2_128Concat => {
383                strip_bytes(cursor, 16)?;
384                let hash_end_idx = curr_idx(cursor);
385                decode_with_error_tracing(
386                    cursor,
387                    key.key_id.clone(),
388                    type_resolver,
389                    scale_decode::visitor::IgnoreVisitor::new(),
390                )
391                .map_err(|e| StorageKeyDecodeError::CannotDecodeKey {
392                    ty: key.key_id.clone(),
393                    reason: e,
394                    decoded_so_far: StorageKey {
395                        parts: parts.clone(),
396                    },
397                })?;
398                StorageKeyPart {
399                    hash_range: Range {
400                        start: start_idx,
401                        end: hash_end_idx,
402                    },
403                    value: Some(StorageKeyPartValue {
404                        range: Range {
405                            start: hash_end_idx,
406                            end: curr_idx(cursor),
407                        },
408                        ty: key.key_id,
409                    }),
410                    hasher,
411                }
412            }
413            StorageHasher::Twox64Concat => {
414                strip_bytes(cursor, 8)?;
415                let hash_end_idx = curr_idx(cursor);
416                decode_with_error_tracing(
417                    cursor,
418                    key.key_id.clone(),
419                    type_resolver,
420                    scale_decode::visitor::IgnoreVisitor::new(),
421                )
422                .map_err(|e| StorageKeyDecodeError::CannotDecodeKey {
423                    ty: key.key_id.clone(),
424                    reason: e,
425                    decoded_so_far: StorageKey {
426                        parts: parts.clone(),
427                    },
428                })?;
429                StorageKeyPart {
430                    hash_range: Range {
431                        start: start_idx,
432                        end: hash_end_idx,
433                    },
434                    value: Some(StorageKeyPartValue {
435                        range: Range {
436                            start: hash_end_idx,
437                            end: curr_idx(cursor),
438                        },
439                        ty: key.key_id,
440                    }),
441                    hasher,
442                }
443            }
444            StorageHasher::Identity => {
445                decode_with_error_tracing(
446                    cursor,
447                    key.key_id.clone(),
448                    type_resolver,
449                    scale_decode::visitor::IgnoreVisitor::new(),
450                )
451                .map_err(|e| StorageKeyDecodeError::CannotDecodeKey {
452                    ty: key.key_id.clone(),
453                    reason: e,
454                    decoded_so_far: StorageKey {
455                        parts: parts.clone(),
456                    },
457                })?;
458                StorageKeyPart {
459                    hash_range: Range {
460                        start: start_idx,
461                        end: start_idx,
462                    },
463                    value: Some(StorageKeyPartValue {
464                        range: Range {
465                            start: start_idx,
466                            end: curr_idx(cursor),
467                        },
468                        ty: key.key_id,
469                    }),
470                    hasher,
471                }
472            }
473        };
474        parts.push(part)
475    }
476
477    Ok(StorageKey { parts })
478}
479
480/// Decode a storage value.
481///
482/// # Example
483///
484/// Here, we decode some storage values from a block.
485///
486/// ```rust
487/// use frame_decode::storage::decode_storage_value;
488/// use frame_decode::helpers::decode_with_visitor;
489/// use frame_metadata::RuntimeMetadata;
490/// use parity_scale_codec::Decode;
491/// use scale_value::scale::ValueVisitor;
492///
493/// let metadata_bytes = std::fs::read("artifacts/metadata_10000000_9180.scale").unwrap();
494/// let RuntimeMetadata::V14(metadata) = RuntimeMetadata::decode(&mut &*metadata_bytes).unwrap() else { return };
495///
496/// let storage_keyval_bytes = std::fs::read("artifacts/storage_10000000_9180_system_account.json").unwrap();
497/// let storage_keyval_hex: Vec<(String, String)> = serde_json::from_slice(&storage_keyval_bytes).unwrap();
498///
499/// for (_key, val) in storage_keyval_hex {
500///     let value_bytes = hex::decode(val.trim_start_matches("0x")).unwrap();
501///
502///     // Decode the storage value, here into a scale_value::Value:
503///     let account_value = decode_storage_value(
504///         "System",
505///         "Account",
506///         &mut &*value_bytes,
507///         &metadata,
508///         &metadata.types,
509///         ValueVisitor::new()
510///     ).unwrap();
511/// }
512/// ```
513pub fn decode_storage_value<'scale, 'resolver, Info, Resolver, V>(
514    pallet_name: &str,
515    storage_entry: &str,
516    cursor: &mut &'scale [u8],
517    info: &Info,
518    type_resolver: &'resolver Resolver,
519    visitor: V,
520) -> Result<V::Value<'scale, 'resolver>, StorageValueDecodeError<Info::TypeId>>
521where
522    Info: StorageTypeInfo,
523    Info::TypeId: Clone + core::fmt::Debug,
524    Resolver: TypeResolver<TypeId = Info::TypeId>,
525    V: scale_decode::Visitor<TypeResolver = Resolver>,
526    V::Error: core::fmt::Debug,
527{
528    let storage_info = info
529        .get_storage_info(pallet_name, storage_entry)
530        .map_err(|e| StorageValueDecodeError::CannotGetInfo(e.into_owned()))?;
531
532    let value_id = storage_info.value_id;
533
534    let decoded = decode_with_error_tracing(cursor, value_id.clone(), type_resolver, visitor)
535        .map_err(|e| StorageValueDecodeError::CannotDecodeValue {
536            ty: value_id,
537            reason: e,
538        })?;
539
540    Ok(decoded)
541}
542
543fn strip_bytes<'a, T>(
544    cursor: &mut &'a [u8],
545    num: usize,
546) -> Result<&'a [u8], StorageKeyDecodeError<T>> {
547    let bytes = cursor
548        .get(..num)
549        .ok_or_else(|| StorageKeyDecodeError::NotEnoughBytes {
550            needed: num,
551            have: cursor.len(),
552        })?;
553
554    *cursor = &cursor[num..];
555    Ok(bytes)
556}
557
558#[cfg(test)]
559mod test {
560    use super::*;
561
562    #[test]
563    fn test_strip_bytes() {
564        let v = vec![0, 1, 2, 3, 4, 5, 6, 7, 8];
565        let cursor = &mut &*v;
566        let stripped = strip_bytes::<()>(cursor, 4).unwrap();
567        assert_eq!(stripped, &[0, 1, 2, 3]);
568        assert_eq!(cursor, &[4, 5, 6, 7, 8]);
569    }
570}