diff --git a/frame-metadata/src/v15.rs b/frame-metadata/src/v15.rs index 4b1536c..f292b92 100644 --- a/frame-metadata/src/v15.rs +++ b/frame-metadata/src/v15.rs @@ -73,8 +73,10 @@ impl RuntimeMetadataV15 { custom: CustomMetadata, ) -> Self { let mut registry = Registry::new(); - let pallets = registry.map_into_portable(pallets); + // extrinsic types need to be collected first to ensure CheckMetadataHash hash + // is stable across different metadata versions let extrinsic = extrinsic.into_portable(&mut registry); + let pallets = registry.map_into_portable(pallets); let ty = registry.register_type(&runtime_type); let apis = registry.map_into_portable(apis); let outer_enums = outer_enums.into_portable(&mut registry); @@ -206,13 +208,15 @@ impl IntoPortable for ExtrinsicMetadata { type Output = ExtrinsicMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { + // the collection order needs to be stable across different metadata versions + // to ensure CheckMetadataHash hash is invariant ExtrinsicMetadata { version: self.version, address_ty: registry.register_type(&self.address_ty), call_ty: registry.register_type(&self.call_ty), signature_ty: registry.register_type(&self.signature_ty), - extra_ty: registry.register_type(&self.extra_ty), signed_extensions: registry.map_into_portable(self.signed_extensions), + extra_ty: registry.register_type(&self.extra_ty), } } } diff --git a/frame-metadata/src/v16.rs b/frame-metadata/src/v16.rs index 3d15772..e23c400 100644 --- a/frame-metadata/src/v16.rs +++ b/frame-metadata/src/v16.rs @@ -72,8 +72,10 @@ impl RuntimeMetadataV16 { custom: CustomMetadata, ) -> Self { let mut registry = Registry::new(); - let pallets = registry.map_into_portable(pallets); + // extrinsic types need to be collected first to ensure CheckMetadataHash hash + // is stable across different metadata versions let extrinsic = extrinsic.into_portable(&mut registry); + let pallets = registry.map_into_portable(pallets); let apis = registry.map_into_portable(apis); let outer_enums = outer_enums.into_portable(&mut registry); let custom = custom.into_portable(&mut registry); @@ -191,6 +193,8 @@ impl IntoPortable for ExtrinsicMetadata { type Output = ExtrinsicMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { + // the collection order needs to be stable across different metadata versions + // to ensure CheckMetadataHash hash is invariant ExtrinsicMetadata { versions: self.versions, address_ty: registry.register_type(&self.address_ty),