Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

metadata/v15: Collect transaction extensions by versions into custom metadata #6755

Closed
wants to merge 10 commits into from
14 changes: 14 additions & 0 deletions prdoc/pr_6755.prdoc
Original file line number Diff line number Diff line change
@@ -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
15 changes: 13 additions & 2 deletions substrate/frame/support/test/tests/pallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -1931,13 +1931,24 @@ fn metadata() {
error_enum_ty: meta_type::<RuntimeError>(),
};

let custom_value: BTreeMap<u8, Vec<u32>> = [(0, vec![0])].into_iter().collect();
let expected_metadata: RuntimeMetadataPrefixed = RuntimeMetadataLastVersion::new(
pallets,
extrinsic,
meta_type::<Runtime>(),
vec![],
outer_enums,
CustomMetadata { map: Default::default() },
CustomMetadata {
map: [(
"transaction_extensions_by_version".into(),
CustomValueMetadata {
ty: meta_type::<BTreeMap<u8, Vec<u32>>>(),
value: custom_value.encode(),
},
)]
.into_iter()
.collect(),
},
)
.into();
let expected_metadata = match expected_metadata.1 {
Expand Down
12 changes: 12 additions & 0 deletions substrate/primitives/metadata-ir/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,18 @@ impl IntoPortable for ExtrinsicMetadataIR {
}
}

/// The type of the transaction extensions by version field.
pub type TrasactionExtensionsByVersion = BTreeMap<u8, Vec<u32>>;

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<T: Form = MetaForm> {
Expand Down
4 changes: 1 addition & 3 deletions substrate/primitives/metadata-ir/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,7 @@ impl From<TransactionExtensionMetadataIR> for TransactionExtensionMetadata {

impl From<ExtrinsicMetadataIR> 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,
Expand Down
27 changes: 20 additions & 7 deletions substrate/primitives/metadata-ir/src/v15.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<MetadataIR> 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::<TrasactionExtensionsByVersion>(),
value: transaction_extensions_by_version.encode(),
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is enough, this encode the transaction extension indices used for each version.
But the v15 metadata extensions doesn't contains all the extensions.

If we have 2 version. v15 metadata will contains the first version only.
so we need to add in custom metadata all the other transaction extension, or just all the transaction extensions same as v16.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, this will no longer work when we include new transactions in the next version.
We collect the same transaction extensions (signed extensions), but that will not be the case in the future. I'll introduce the transaction extensions as well, thanks for pointing this out 🙏

)]
.into_iter()
.collect(),
},
)
}
}
Expand Down
Loading