frame_decode/
lib.rs

1// Copyright (C) 2022-2025 Parity Technologies (UK) Ltd. (admin@parity.io)
2// This file is a part of the frame-decode 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 encoding/decoding storage keys and decoding values.
21//! - See [`runtime_apis`] for encoding Runtime API inputs and decoding Runtime API responses
22//! - See [`legacy_types`] to access historic type information for certain chains.
23//!
24#![deny(missing_docs)]
25#![cfg_attr(not(feature = "std"), no_std)]
26
27extern crate alloc;
28
29mod methods;
30mod utils;
31
32pub mod extrinsics {
33    //! This module contains functions for decoding extrinsics.
34    //!
35    //! - See [`decode_extrinsic`] for a general function to decode modern or historic extrinsics.
36    //! - See [`ExtrinsicTypeInfo`] for the underlying trait which extracts the relevant information.
37
38    pub use crate::methods::extrinsic_decoder::{
39        Extrinsic, ExtrinsicDecodeError, ExtrinsicExtensions, ExtrinsicOwned, ExtrinsicSignature,
40        ExtrinsicType, NamedArg, decode_extrinsic,
41    };
42    pub use crate::methods::extrinsic_type_info::{
43        ExtrinsicCallInfo, ExtrinsicExtensionInfo, ExtrinsicInfoArg, ExtrinsicInfoError,
44        ExtrinsicSignatureInfo, ExtrinsicTypeInfo,
45    };
46}
47
48pub mod storage {
49    //! This module contains functions for decoding storage keys and values.
50    //!
51    //! - See [`decode_storage_key`] and [`decode_storage_value`] to decode storage keys or values
52    //!   from modern or historic runtimes.
53    //! - See [`encode_storage_key_prefix`] to encode storage prefixes, and [`encode_storage_key`] to encode
54    //!   storage keys.
55    //! - See [`StorageTypeInfo`] for the underlying trait which extracts the relevant information.
56
57    pub use crate::methods::Entry;
58    pub use crate::methods::storage_decoder::{
59        StorageKey, StorageKeyDecodeError, StorageKeyPart, StorageKeyPartValue,
60        StorageKeyValueDecodeError, StorageValueDecodeError,
61        decode_default_storage_value_with_info, decode_storage_key, decode_storage_key_values,
62        decode_storage_key_with_info, decode_storage_value, decode_storage_value_with_info,
63    };
64    pub use crate::methods::storage_encoder::{
65        StorageKeyEncodeError, encode_storage_key, encode_storage_key_prefix,
66        encode_storage_key_suffix, encode_storage_key_suffix_to,
67        encode_storage_key_suffix_with_info_to, encode_storage_key_to,
68        encode_storage_key_with_info, encode_storage_key_with_info_to,
69    };
70    pub use crate::methods::storage_type_info::{
71        StorageHasher, StorageInfo, StorageInfoError, StorageKeyInfo, StorageTypeInfo,
72    };
73    pub use crate::utils::{
74        DecodableValues, EncodableValues, IntoDecodableValues, IntoEncodableValues,
75    };
76}
77
78pub mod constants {
79    //! This module contains types and functions for working with constants.
80    //!
81    //! - See [`decode_constant`] and [`decode_constant_with_info`] to decode constants
82    //! - See [`ConstantTypeInfo`] for the underlying trait which extracts constant
83    //!   information from metadata.
84
85    pub use crate::methods::Entry;
86    pub use crate::methods::constant_decoder::{
87        ConstantDecodeError, decode_constant, decode_constant_with_info,
88    };
89    pub use crate::methods::constant_type_info::{
90        ConstantInfo, ConstantInfoError, ConstantTypeInfo,
91    };
92}
93
94pub mod runtime_apis {
95    //! This module contains types and functions for working with Runtime APIs.
96    //!
97    //! - See [`encode_runtime_api_name`] and [`encode_runtime_api_inputs`] to encode
98    //!   the name and inputs to make a Runtime API call.
99    //! - See [`decode_runtime_api_response`] to decode Runtime API responses.
100    //! - See [`RuntimeApiTypeInfo`] for the underlying trait which extracts the relevant information.
101
102    pub use crate::methods::Entry;
103    pub use crate::methods::runtime_api_decoder::{
104        RuntimeApiDecodeError, decode_runtime_api_response, decode_runtime_api_response_with_info,
105    };
106    pub use crate::methods::runtime_api_encoder::{
107        RuntimeApiInputsEncodeError, encode_runtime_api_inputs, encode_runtime_api_inputs_to,
108        encode_runtime_api_inputs_with_info_to, encode_runtime_api_name,
109    };
110    pub use crate::methods::runtime_api_type_info::{
111        RuntimeApiInfo, RuntimeApiInfoError, RuntimeApiInput, RuntimeApiTypeInfo,
112    };
113    pub use crate::utils::{EncodableValues, IntoEncodableValues};
114}
115
116pub mod view_functions {
117    //! This module contains types and functions for working with View Functions.
118    //!
119    //! - See [`RUNTIME_API_NAME`] and [`encode_view_function_inputs`] to obtain the Runtime API name
120    //!   and the encoded input data required to call a given View Function.
121    //! - See [`decode_view_function_response`] to decode View Function responses.
122    //! - See [`ViewFunctionTypeInfo`] for the underlying trait which extracts the relevant information.
123
124    pub use crate::methods::Entry;
125    pub use crate::methods::view_function_decoder::{
126        ViewFunctionDecodeError, decode_view_function_response,
127        decode_view_function_response_with_info,
128    };
129    pub use crate::methods::view_function_encoder::{
130        RUNTIME_API_NAME, ViewFunctionInputsEncodeError, encode_view_function_inputs,
131        encode_view_function_inputs_to, encode_view_function_inputs_with_info_to,
132    };
133    pub use crate::methods::view_function_type_info::{
134        ViewFunctionInfo, ViewFunctionInfoError, ViewFunctionInput, ViewFunctionTypeInfo,
135    };
136    pub use crate::utils::{EncodableValues, IntoEncodableValues};
137}
138
139pub mod custom_values {
140    //! This module contains types and functions for working with custom values.
141    //!
142    //! - See [`decode_custom_value`] and [`decode_custom_value_with_info`] to decode custom values
143    //! - See [`CustomValueTypeInfo`] for the underlying trait which extracts custom value
144    //!   information from metadata.
145
146    pub use crate::methods::custom_value_decoder::{
147        CustomValueDecodeError, decode_custom_value, decode_custom_value_with_info,
148    };
149    pub use crate::methods::custom_value_type_info::{
150        CustomValue, CustomValueInfo, CustomValueInfoError, CustomValueTypeInfo,
151    };
152}
153
154#[cfg(feature = "legacy-types")]
155pub mod legacy_types {
156    //! This module contains legacy types that can be used to decode pre-V14 blocks and storage.
157
158    pub mod polkadot {
159        //! Legacy types for Polkadot chains.
160
161        /// Legacy types for the Polkadot Relay Chain.
162        pub fn relay_chain() -> scale_info_legacy::ChainTypeRegistry {
163            // This is a convenience function to load the Polkadot relay chain types.
164            // It is used in the examples in this crate.
165            let bytes = include_bytes!("../types/polkadot_types.yaml");
166            serde_yaml::from_slice(bytes).expect("Polkadot types are valid YAML")
167        }
168    }
169}
170
171pub mod helpers {
172    //! Helper functions and types to assist with decoding.
173    //!
174    //! - [`type_registry_from_metadata`] is expected to be used when decoding things from historic
175    //!   runtimes, adding the ability to decode some types from information in the metadata.
176    //! - [`decode_with_error_tracing`] is like [`decode_with_visitor`], but
177    //!   will use a tracing visitor (if the `error-tracing` feature is enabled) to provide more
178    //!   information in the event that decoding fails.
179
180    pub use crate::utils::{
181        DecodableValues, DecodeErrorTrace, EncodableValues, IntoDecodableValues,
182        IntoEncodableValues, decode_with_error_tracing, list_storage_entries_any,
183    };
184    #[cfg(feature = "legacy")]
185    pub use crate::utils::{type_registry_from_metadata, type_registry_from_metadata_any};
186
187    /// An alias to [`scale_decode::visitor::decode_with_visitor`]. This can be used to decode the byte ranges
188    /// given back from functions like [`crate::extrinsics::decode_extrinsic`] or
189    /// [`crate::storage::decode_storage_key`].
190    pub use scale_decode::visitor::decode_with_visitor;
191
192    /// An alias to the underlying [`scale_decode`] crate.
193    pub use scale_decode;
194}
195
196#[cfg(test)]
197mod test {
198    use crate::methods::extrinsic_type_info::ExtrinsicTypeInfo;
199    use crate::methods::runtime_api_type_info::RuntimeApiTypeInfo;
200    use crate::methods::storage_type_info::StorageTypeInfo;
201    use crate::methods::view_function_type_info::ViewFunctionTypeInfo;
202    use crate::utils::ToTypeRegistry;
203
204    // This will panic if there is any issue decoding the legacy types we provide.
205    #[test]
206    fn test_deserializing_legacy_types() {
207        let _ = crate::legacy_types::polkadot::relay_chain();
208    }
209
210    macro_rules! impls_trait {
211        ($type:ty, $trait:path) => {
212            const _: () = {
213                const fn assert_impl<T: $trait>() {}
214                assert_impl::<$type>();
215            };
216        };
217    }
218
219    // Just a sanity check that all of the metadata versions we expect implement
220    // all of the key traits. Makes it harder to miss something when adding a new metadata
221    // version; just add it below and implement the traits until everything compiles.
222    #[rustfmt::skip]
223    const _: () = {
224        impls_trait!(frame_metadata::v8::RuntimeMetadataV8, ExtrinsicTypeInfo);
225        impls_trait!(frame_metadata::v9::RuntimeMetadataV9, ExtrinsicTypeInfo);
226        impls_trait!(frame_metadata::v10::RuntimeMetadataV10, ExtrinsicTypeInfo);
227        impls_trait!(frame_metadata::v11::RuntimeMetadataV11, ExtrinsicTypeInfo);
228        impls_trait!(frame_metadata::v12::RuntimeMetadataV12, ExtrinsicTypeInfo);
229        impls_trait!(frame_metadata::v13::RuntimeMetadataV13, ExtrinsicTypeInfo);
230        impls_trait!(frame_metadata::v14::RuntimeMetadataV14, ExtrinsicTypeInfo);
231        impls_trait!(frame_metadata::v15::RuntimeMetadataV15, ExtrinsicTypeInfo);
232        impls_trait!(frame_metadata::v16::RuntimeMetadataV16, ExtrinsicTypeInfo);
233
234        impls_trait!(frame_metadata::v8::RuntimeMetadataV8, StorageTypeInfo);
235        impls_trait!(frame_metadata::v9::RuntimeMetadataV9, StorageTypeInfo);
236        impls_trait!(frame_metadata::v10::RuntimeMetadataV10, StorageTypeInfo);
237        impls_trait!(frame_metadata::v11::RuntimeMetadataV11, StorageTypeInfo);
238        impls_trait!(frame_metadata::v12::RuntimeMetadataV12, StorageTypeInfo);
239        impls_trait!(frame_metadata::v13::RuntimeMetadataV13, StorageTypeInfo);
240        impls_trait!(frame_metadata::v14::RuntimeMetadataV14, StorageTypeInfo);
241        impls_trait!(frame_metadata::v15::RuntimeMetadataV15, StorageTypeInfo);
242        impls_trait!(frame_metadata::v16::RuntimeMetadataV16, StorageTypeInfo);
243
244        // Only V16+ metadata contains any view function information. Prior to this,
245        // hardly any view functions existed. We _could_ extend our legacy type information
246        // to support them if necessary, but it's unlikely it will be.
247        impls_trait!(frame_metadata::v16::RuntimeMetadataV16, ViewFunctionTypeInfo);
248
249        // Only V15+ metadata has Runtime API info in. For earlier, we lean on
250        // our scale-Info-legacy type registry to provide the information.
251        impls_trait!(scale_info_legacy::TypeRegistry, RuntimeApiTypeInfo);
252        impls_trait!(scale_info_legacy::TypeRegistrySet, RuntimeApiTypeInfo);
253        impls_trait!(frame_metadata::v15::RuntimeMetadataV15, RuntimeApiTypeInfo);
254        impls_trait!(frame_metadata::v16::RuntimeMetadataV16, RuntimeApiTypeInfo);
255
256        // This is a legacy trait and so only legacy metadata versions implement it:
257        impls_trait!(frame_metadata::v8::RuntimeMetadataV8, ToTypeRegistry);
258        impls_trait!(frame_metadata::v9::RuntimeMetadataV9, ToTypeRegistry);
259        impls_trait!(frame_metadata::v10::RuntimeMetadataV10, ToTypeRegistry);
260        impls_trait!(frame_metadata::v11::RuntimeMetadataV11, ToTypeRegistry);
261        impls_trait!(frame_metadata::v12::RuntimeMetadataV12, ToTypeRegistry);
262        impls_trait!(frame_metadata::v13::RuntimeMetadataV13, ToTypeRegistry);
263    };
264}