diff --git a/prdoc/pr_6755.prdoc b/prdoc/pr_6755.prdoc new file mode 100644 index 000000000000..66763dc4e348 --- /dev/null +++ b/prdoc/pr_6755.prdoc @@ -0,0 +1,14 @@ +title: Collect transaction extensions by versions into custom metadata for v15 + +doc: + - audience: [ Node Dev, Node Operator ] + description: | + This PR collects the transaction_extensions_by_version type information into the metadata V15 custom types. + This ensures the V15 contains enough information to work with multiple transaction extensions. The meaning of this field is identical to the one collected by the V16 unstable. + It includes indexes of extrinsics from the signed_extension field of the extrinsic metadata. + +crates: + - name: sp-metadata-ir + bump: patch + - name: frame-support-test + bump: none diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs index 9df1f461bba2..be158ca6641d 100644 --- a/substrate/frame/support/test/tests/pallet.rs +++ b/substrate/frame/support/test/tests/pallet.rs @@ -1471,7 +1471,7 @@ fn pallet_item_docs_in_metadata() { #[test] fn metadata() { - use codec::Decode; + use codec::{Decode, Encode}; use frame_metadata::{v15::*, *}; let readme = "Very important information :D\n"; @@ -1931,13 +1931,24 @@ fn metadata() { error_enum_ty: meta_type::(), }; + let custom_value: BTreeMap> = [(0, vec![0])].into_iter().collect(); let expected_metadata: RuntimeMetadataPrefixed = RuntimeMetadataLastVersion::new( pallets, extrinsic, meta_type::(), vec![], outer_enums, - CustomMetadata { map: Default::default() }, + CustomMetadata { + map: [( + "transaction_extensions_by_version".into(), + CustomValueMetadata { + ty: meta_type::>>(), + value: custom_value.encode(), + }, + )] + .into_iter() + .collect(), + }, ) .into(); let expected_metadata = match expected_metadata.1 { diff --git a/substrate/primitives/metadata-ir/src/types.rs b/substrate/primitives/metadata-ir/src/types.rs index af217ffe16ee..a6e51cbb3de0 100644 --- a/substrate/primitives/metadata-ir/src/types.rs +++ b/substrate/primitives/metadata-ir/src/types.rs @@ -201,6 +201,18 @@ impl IntoPortable for ExtrinsicMetadataIR { } } +/// The type of the transaction extensions by version field. +pub type TrasactionExtensionsByVersion = BTreeMap>; + +impl ExtrinsicMetadataIR { + /// Returns the transaction extensions by version. + pub fn transaction_extensions_by_version(&self) -> TrasactionExtensionsByVersion { + // Assume version 0 for all extensions. + let indexes = (0..self.extensions.len()).map(|index| index as u32).collect(); + [(0, indexes)].iter().cloned().collect() + } +} + /// Metadata of a pallet's associated type. #[derive(Clone, PartialEq, Eq, Encode, Debug)] pub struct PalletAssociatedTypeMetadataIR { diff --git a/substrate/primitives/metadata-ir/src/unstable.rs b/substrate/primitives/metadata-ir/src/unstable.rs index d46ce3ec6a7d..dee63aa7fd71 100644 --- a/substrate/primitives/metadata-ir/src/unstable.rs +++ b/substrate/primitives/metadata-ir/src/unstable.rs @@ -162,9 +162,7 @@ impl From for TransactionExtensionMetadata { impl From for ExtrinsicMetadata { fn from(ir: ExtrinsicMetadataIR) -> Self { - // Assume version 0 for all extensions. - let indexes = (0..ir.extensions.len()).map(|index| index as u32).collect(); - let transaction_extensions_by_version = [(0, indexes)].iter().cloned().collect(); + let transaction_extensions_by_version = ir.transaction_extensions_by_version(); ExtrinsicMetadata { versions: ir.versions, diff --git a/substrate/primitives/metadata-ir/src/v15.rs b/substrate/primitives/metadata-ir/src/v15.rs index ed315a31e6dc..f7c7d8be84fd 100644 --- a/substrate/primitives/metadata-ir/src/v15.rs +++ b/substrate/primitives/metadata-ir/src/v15.rs @@ -17,30 +17,43 @@ //! Convert the IR to V15 metadata. -use crate::OuterEnumsIR; +use crate::{OuterEnumsIR, TrasactionExtensionsByVersion}; use super::types::{ ExtrinsicMetadataIR, MetadataIR, PalletMetadataIR, RuntimeApiMetadataIR, RuntimeApiMethodMetadataIR, RuntimeApiMethodParamMetadataIR, TransactionExtensionMetadataIR, }; +use codec::Encode; use frame_metadata::v15::{ - CustomMetadata, ExtrinsicMetadata, OuterEnums, PalletMetadata, RuntimeApiMetadata, - RuntimeApiMethodMetadata, RuntimeApiMethodParamMetadata, RuntimeMetadataV15, - SignedExtensionMetadata, + CustomMetadata, CustomValueMetadata, ExtrinsicMetadata, OuterEnums, PalletMetadata, + RuntimeApiMetadata, RuntimeApiMethodMetadata, RuntimeApiMethodParamMetadata, + RuntimeMetadataV15, SignedExtensionMetadata, }; +use scale_info::meta_type; impl From for RuntimeMetadataV15 { fn from(ir: MetadataIR) -> Self { + const TRANSACTION_EXTENSIONS_BY_VERSION: &str = "transaction_extensions_by_version"; + let transaction_extensions_by_version = ir.extrinsic.transaction_extensions_by_version(); + RuntimeMetadataV15::new( ir.pallets.into_iter().map(Into::into).collect(), ir.extrinsic.into(), ir.ty, ir.apis.into_iter().map(Into::into).collect(), ir.outer_enums.into(), - // Substrate does not collect yet the custom metadata fields. - // This allows us to extend the V15 easily. - CustomMetadata { map: Default::default() }, + CustomMetadata { + map: [( + TRANSACTION_EXTENSIONS_BY_VERSION.into(), + CustomValueMetadata { + ty: meta_type::(), + value: transaction_extensions_by_version.encode(), + }, + )] + .into_iter() + .collect(), + }, ) } }