frame_decode/lib.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
16//! Decode extrinsics and storage values from substrate based networks which expose `frame-metadata::RuntimeMetadata`
17//! like Polkadot.
18//!
19//! - See [`extrinsics`] for decoding Extrinsics.
20//! - See [`storage`] for decoding storage keys and values.
21//!
22#![deny(missing_docs)]
23#![cfg_attr(not(feature = "std"), no_std)]
24
25extern crate alloc;
26
27mod methods;
28mod utils;
29
30pub mod extrinsics {
31 //! This module contains functions for decoding extrinsics.
32 //!
33 //! - See [`decode_extrinsic`] for a general function to decode modern or historic extrinsics.
34 //! - See [`decode_extrinsic_current`] for a helper to decode modern extrinsics.
35 //!
36
37 use crate::utils::InfoAndResolver;
38
39 pub use crate::methods::extrinsic_decoder::{
40 decode_extrinsic, Extrinsic, ExtrinsicDecodeError, ExtrinsicExtensions, ExtrinsicOwned,
41 ExtrinsicSignature, ExtrinsicType, NamedArg,
42 };
43 pub use crate::methods::extrinsic_type_info::{
44 ExtrinsicCallInfo, ExtrinsicExtensionInfo, ExtrinsicInfoArg, ExtrinsicInfoError,
45 ExtrinsicSignatureInfo, ExtrinsicTypeInfo,
46 };
47
48 /// Decode an extrinsic in a modern runtime (ie one exposing V14+ metadata).
49 ///
50 /// See [`decode_extrinsic`] for a more comprehensive example.
51 ///
52 /// # Example
53 ///
54 /// ```rust
55 /// use frame_decode::extrinsics::decode_extrinsic_current;
56 /// use frame_metadata::RuntimeMetadata;
57 /// use parity_scale_codec::Decode;
58 ///
59 /// let metadata_bytes = std::fs::read("artifacts/metadata_10000000_9180.scale").unwrap();
60 /// let RuntimeMetadata::V14(metadata) = RuntimeMetadata::decode(&mut &*metadata_bytes).unwrap() else { panic!() };
61 ///
62 /// let extrinsics_bytes = std::fs::read("artifacts/exts_10000000_9180.json").unwrap();
63 /// let extrinsics_hex: Vec<String> = serde_json::from_slice(&extrinsics_bytes).unwrap();
64 ///
65 /// for ext_hex in extrinsics_hex {
66 /// let ext_bytes = hex::decode(ext_hex.trim_start_matches("0x")).unwrap();
67 ///
68 /// // Decode the extrinsic, returning information about it:
69 /// let ext_info = decode_extrinsic_current(&mut &*ext_bytes, &metadata).unwrap();
70 ///
71 /// // Now we can use this information to inspect the extrinsic and decode the
72 /// // different values inside it (see the `decode_extrinsic` docs).
73 /// }
74 /// ```
75 pub fn decode_extrinsic_current<'info_and_resolver, T>(
76 cursor: &mut &[u8],
77 metadata: &'info_and_resolver T,
78 ) -> Result<
79 Extrinsic<'info_and_resolver, <T::Info as ExtrinsicTypeInfo>::TypeId>,
80 ExtrinsicDecodeError,
81 >
82 where
83 T: InfoAndResolver,
84 T::Info: ExtrinsicTypeInfo,
85 <T::Info as ExtrinsicTypeInfo>::TypeId: core::fmt::Debug + Clone,
86 T::Resolver:
87 scale_type_resolver::TypeResolver<TypeId = <T::Info as ExtrinsicTypeInfo>::TypeId>,
88 {
89 decode_extrinsic(cursor, metadata.info(), metadata.resolver())
90 }
91}
92
93pub mod storage {
94 //! This module contains functions for decoding storage keys and values.
95 //!
96 //! - See [`decode_storage_key`] and [`decode_storage_value`] to decode storage keys or values
97 //! from modern or historic runtimes.
98 //! - See [`decode_storage_key_current`] and [`decode_storage_value_current`] to decode modern
99 //! storage keys and values.
100 //! - See [`encode_prefix`] to encode storage prefixes, and [`encode_storage_key`] to encode
101 //! storage keys.
102
103 use crate::utils::InfoAndResolver;
104 use scale_decode::Visitor;
105 use scale_type_resolver::TypeResolver;
106
107 pub use crate::methods::storage_type_info::{
108 StorageHasher, StorageInfo, StorageInfoError, StorageKeyInfo, StorageTypeInfo,
109 };
110
111 pub use crate::methods::storage_decoder::{
112 decode_storage_key, decode_storage_key_with_info, decode_storage_value,
113 decode_storage_value_with_info, StorageKey, StorageKeyDecodeError, StorageKeyPart,
114 StorageKeyPartValue, StorageValueDecodeError,
115 };
116 pub use crate::methods::storage_encoder::{
117 encode_prefix, encode_storage_key, encode_storage_key_to, encode_storage_key_with_info_to,
118 IntoStorageKeys, StorageKeyEncodeError, StorageKeys,
119 };
120
121 type TypeIdOf<T> = <<T as InfoAndResolver>::Info as StorageTypeInfo>::TypeId;
122
123 /// Decode a storage key in a modern runtime, returning information about it.
124 ///
125 /// This information can be used to identify and, where possible, decode the parts of the storage key.
126 ///
127 /// See [`decode_storage_key`] for a more complete example.
128 ///
129 /// # Example
130 ///
131 /// Here, we decode some storage keys from a block.
132 ///
133 /// ```rust
134 /// use frame_decode::storage::decode_storage_key_current;
135 /// use frame_decode::helpers::decode_with_visitor;
136 /// use frame_metadata::RuntimeMetadata;
137 /// use parity_scale_codec::Decode;
138 /// use scale_value::scale::ValueVisitor;
139 ///
140 /// let metadata_bytes = std::fs::read("artifacts/metadata_10000000_9180.scale").unwrap();
141 /// let RuntimeMetadata::V14(metadata) = RuntimeMetadata::decode(&mut &*metadata_bytes).unwrap() else { return };
142 ///
143 /// let storage_keyval_bytes = std::fs::read("artifacts/storage_10000000_9180_system_account.json").unwrap();
144 /// let storage_keyval_hex: Vec<(String, String)> = serde_json::from_slice(&storage_keyval_bytes).unwrap();
145 ///
146 /// for (key, _val) in storage_keyval_hex {
147 /// let key_bytes = hex::decode(key.trim_start_matches("0x")).unwrap();
148 ///
149 /// // Decode the storage key, returning information about it:
150 /// let storage_info = decode_storage_key_current(
151 /// "System",
152 /// "Account",
153 /// &mut &*key_bytes,
154 /// &metadata,
155 /// ).unwrap();
156 ///
157 /// // See `decode_storage_key` for more.
158 /// }
159 /// ```
160 pub fn decode_storage_key_current<T>(
161 pallet_name: &str,
162 storage_entry: &str,
163 cursor: &mut &[u8],
164 metadata: &T,
165 ) -> Result<StorageKey<TypeIdOf<T>>, StorageKeyDecodeError<TypeIdOf<T>>>
166 where
167 T: InfoAndResolver,
168 T::Info: StorageTypeInfo,
169 TypeIdOf<T>: core::fmt::Debug + Clone,
170 T::Resolver: TypeResolver<TypeId = TypeIdOf<T>>,
171 {
172 decode_storage_key(
173 pallet_name,
174 storage_entry,
175 cursor,
176 metadata.info(),
177 metadata.resolver(),
178 )
179 }
180
181 /// Decode a storage value in a modern (V14-metadata-or-later) runtime.
182 ///
183 /// # Example
184 ///
185 /// Here, we decode some storage values from a block.
186 ///
187 /// ```rust
188 /// use frame_decode::storage::decode_storage_value_current;
189 /// use frame_decode::helpers::decode_with_visitor;
190 /// use frame_metadata::RuntimeMetadata;
191 /// use parity_scale_codec::Decode;
192 /// use scale_value::scale::ValueVisitor;
193 ///
194 /// let metadata_bytes = std::fs::read("artifacts/metadata_10000000_9180.scale").unwrap();
195 /// let RuntimeMetadata::V14(metadata) = RuntimeMetadata::decode(&mut &*metadata_bytes).unwrap() else { return };
196 ///
197 /// let storage_keyval_bytes = std::fs::read("artifacts/storage_10000000_9180_system_account.json").unwrap();
198 /// let storage_keyval_hex: Vec<(String, String)> = serde_json::from_slice(&storage_keyval_bytes).unwrap();
199 ///
200 /// for (_key, val) in storage_keyval_hex {
201 /// let value_bytes = hex::decode(val.trim_start_matches("0x")).unwrap();
202 ///
203 /// // Decode the storage value, here into a scale_value::Value:
204 /// let account_value = decode_storage_value_current(
205 /// "System",
206 /// "Account",
207 /// &mut &*value_bytes,
208 /// &metadata,
209 /// ValueVisitor::new()
210 /// ).unwrap();
211 /// }
212 /// ```
213 pub fn decode_storage_value_current<'scale, 'resolver, T, V>(
214 pallet_name: &str,
215 storage_entry: &str,
216 cursor: &mut &'scale [u8],
217 metadata: &'resolver T,
218 visitor: V,
219 ) -> Result<V::Value<'scale, 'resolver>, StorageValueDecodeError<TypeIdOf<T>>>
220 where
221 T: InfoAndResolver,
222 T::Info: StorageTypeInfo,
223 TypeIdOf<T>: core::fmt::Debug + Clone,
224 T::Resolver: scale_type_resolver::TypeResolver<TypeId = TypeIdOf<T>>,
225 V: Visitor<TypeResolver = T::Resolver>,
226 V::Error: core::fmt::Debug,
227 {
228 decode_storage_value(
229 pallet_name,
230 storage_entry,
231 cursor,
232 metadata.info(),
233 metadata.resolver(),
234 visitor,
235 )
236 }
237}
238
239#[cfg(feature = "legacy-types")]
240pub mod legacy_types {
241 //! This module contains legacy types that can be used to decode pre-V14 blocks and storage.
242
243 pub mod polkadot {
244 //! Legacy types for Polkadot chains.
245
246 /// Legacy types for the Polkadot Relay Chain.
247 pub fn relay_chain() -> scale_info_legacy::ChainTypeRegistry {
248 // This is a convenience function to load the Polkadot relay chain types.
249 // It is used in the examples in this crate.
250 let bytes = include_bytes!("../types/polkadot_types.yaml");
251 serde_yaml::from_slice(bytes).expect("Polkadot types are valid YAML")
252 }
253 }
254}
255
256pub mod helpers {
257 //! Helper functions and types to assist with decoding.
258 //!
259 //! - [`type_registry_from_metadata`] is expected to be used when decoding things from historic
260 //! runtimes, adding the ability to decode some types from information in the metadata.
261 //! - [`decode_with_error_tracing`] is like [`decode_with_visitor`], but
262 //! will use a tracing visitor (if the `error-tracing` feature is enabled) to provide more
263 //! information in the event that decoding fails.
264 //! - [`list_storage_entries`] returns an iterator over all of the storage entries available in
265 //! some metadata.
266 //!
267
268 pub use crate::utils::{decode_with_error_tracing, DecodeErrorTrace};
269 pub use crate::utils::{list_storage_entries, list_storage_entries_any, StorageEntry};
270 #[cfg(feature = "legacy")]
271 pub use crate::utils::{type_registry_from_metadata, type_registry_from_metadata_any};
272
273 /// An alias to [`scale_decode::visitor::decode_with_visitor`]. This can be used to decode the byte ranges
274 /// given back from functions like [`crate::extrinsics::decode_extrinsic_current`] or
275 /// [`crate::storage::decode_storage_key_current`].
276 ///
277 pub use scale_decode::visitor::decode_with_visitor;
278
279 /// An alias to the underlying [`scale-decode`] crate.
280 ///
281 pub use scale_decode;
282}
283
284#[cfg(test)]
285mod test {
286 use crate::methods::extrinsic_type_info::ExtrinsicTypeInfo;
287 use crate::methods::storage_type_info::StorageTypeInfo;
288 use crate::utils::{InfoAndResolver, ToStorageEntriesList, ToTypeRegistry};
289
290 // This will panic if there is any issue decoding the legacy types we provide.
291 #[test]
292 fn test_deserializing_legacy_types() {
293 let _ = crate::legacy_types::polkadot::relay_chain();
294 }
295
296 macro_rules! impls_trait {
297 ($type:ty, $trait:path) => {
298 const _: () = {
299 const fn assert_impl<T: $trait>() {}
300 assert_impl::<$type>();
301 };
302 };
303 }
304
305 // Just a sanity check that all of the metadata versions we expect implement
306 // all of the key traits. Makes it harder to miss something when adding a new metadata
307 // version; just add it below and implement the traits until everything compiles.
308 #[rustfmt::skip]
309 const _: () = {
310 impls_trait!(frame_metadata::v14::RuntimeMetadataV14, InfoAndResolver);
311 impls_trait!(frame_metadata::v15::RuntimeMetadataV15, InfoAndResolver);
312 impls_trait!(frame_metadata::v16::RuntimeMetadataV16, InfoAndResolver);
313
314 impls_trait!(frame_metadata::v8::RuntimeMetadataV8, ExtrinsicTypeInfo);
315 impls_trait!(frame_metadata::v9::RuntimeMetadataV9, ExtrinsicTypeInfo);
316 impls_trait!(frame_metadata::v10::RuntimeMetadataV10, ExtrinsicTypeInfo);
317 impls_trait!(frame_metadata::v11::RuntimeMetadataV11, ExtrinsicTypeInfo);
318 impls_trait!(frame_metadata::v12::RuntimeMetadataV12, ExtrinsicTypeInfo);
319 impls_trait!(frame_metadata::v13::RuntimeMetadataV13, ExtrinsicTypeInfo);
320 impls_trait!(frame_metadata::v14::RuntimeMetadataV14, ExtrinsicTypeInfo);
321 impls_trait!(frame_metadata::v15::RuntimeMetadataV15, ExtrinsicTypeInfo);
322 impls_trait!(frame_metadata::v16::RuntimeMetadataV16, ExtrinsicTypeInfo);
323
324 impls_trait!(frame_metadata::v8::RuntimeMetadataV8, StorageTypeInfo);
325 impls_trait!(frame_metadata::v9::RuntimeMetadataV9, StorageTypeInfo);
326 impls_trait!(frame_metadata::v10::RuntimeMetadataV10, StorageTypeInfo);
327 impls_trait!(frame_metadata::v11::RuntimeMetadataV11, StorageTypeInfo);
328 impls_trait!(frame_metadata::v12::RuntimeMetadataV12, StorageTypeInfo);
329 impls_trait!(frame_metadata::v13::RuntimeMetadataV13, StorageTypeInfo);
330 impls_trait!(frame_metadata::v14::RuntimeMetadataV14, StorageTypeInfo);
331 impls_trait!(frame_metadata::v15::RuntimeMetadataV15, StorageTypeInfo);
332 impls_trait!(frame_metadata::v16::RuntimeMetadataV16, StorageTypeInfo);
333
334 impls_trait!(frame_metadata::v8::RuntimeMetadataV8, ToStorageEntriesList);
335 impls_trait!(frame_metadata::v9::RuntimeMetadataV9, ToStorageEntriesList);
336 impls_trait!(frame_metadata::v10::RuntimeMetadataV10, ToStorageEntriesList);
337 impls_trait!(frame_metadata::v11::RuntimeMetadataV11, ToStorageEntriesList);
338 impls_trait!(frame_metadata::v12::RuntimeMetadataV12, ToStorageEntriesList);
339 impls_trait!(frame_metadata::v13::RuntimeMetadataV13, ToStorageEntriesList);
340 impls_trait!(frame_metadata::v14::RuntimeMetadataV14, ToStorageEntriesList);
341 impls_trait!(frame_metadata::v15::RuntimeMetadataV15, ToStorageEntriesList);
342 impls_trait!(frame_metadata::v16::RuntimeMetadataV16, ToStorageEntriesList);
343
344 // This is a legacy trait and so only legacy metadata versions implement it:
345 impls_trait!(frame_metadata::v8::RuntimeMetadataV8, ToTypeRegistry);
346 impls_trait!(frame_metadata::v9::RuntimeMetadataV9, ToTypeRegistry);
347 impls_trait!(frame_metadata::v10::RuntimeMetadataV10, ToTypeRegistry);
348 impls_trait!(frame_metadata::v11::RuntimeMetadataV11, ToTypeRegistry);
349 impls_trait!(frame_metadata::v12::RuntimeMetadataV12, ToTypeRegistry);
350 impls_trait!(frame_metadata::v13::RuntimeMetadataV13, ToTypeRegistry);
351 };
352}