diff --git a/substrate/primitives/statement-store/src/lib.rs b/substrate/primitives/statement-store/src/lib.rs index 5c1ba7839209f..9b47451331056 100644 --- a/substrate/primitives/statement-store/src/lib.rs +++ b/substrate/primitives/statement-store/src/lib.rs @@ -24,7 +24,7 @@ extern crate alloc; use alloc::vec::Vec; use codec::{Decode, DecodeWithMemTracking, Encode}; -use scale_info::TypeInfo; +use scale_info::{build::Fields, Path, Type, TypeInfo}; use sp_application_crypto::RuntimeAppPublic; #[cfg(feature = "std")] use sp_core::Pair; @@ -173,7 +173,7 @@ impl Field { } /// Statement structure. -#[derive(DecodeWithMemTracking, TypeInfo, Debug, Clone, PartialEq, Eq, Default)] +#[derive(DecodeWithMemTracking, Debug, Clone, PartialEq, Eq, Default)] pub struct Statement { proof: Option, decryption_key: Option, @@ -184,6 +184,20 @@ pub struct Statement { data: Option>, } +/// Note: The `TypeInfo` implementation reflects the actual encoding format (`Vec`) +/// rather than the struct fields, since `Statement` has custom `Encode`/`Decode` implementations. +impl TypeInfo for Statement { + type Identity = Self; + + fn type_info() -> Type { + // Statement encodes as Vec, so we report the same type info + Type::builder() + .path(Path::new("Statement", module_path!())) + .docs(&["Statement structure"]) + .composite(Fields::unnamed().field(|f| f.ty::>())) + } +} + impl Decode for Statement { fn decode(input: &mut I) -> core::result::Result { // Encoding matches that of Vec. Basically this just means accepting that there @@ -543,6 +557,7 @@ impl Statement { mod test { use crate::{hash_encoded, Field, Proof, SignatureVerificationResult, Statement}; use codec::{Decode, Encode}; + use scale_info::{MetaType, TypeInfo}; use sp_application_crypto::Pair; #[test] @@ -659,4 +674,23 @@ mod test { let decrypted = statement.decrypt_private(&pair).unwrap(); assert_eq!(decrypted, Some(plain)); } + + #[test] + fn statement_type_info_matches_encoding() { + // Statement has custom Encode/Decode that encodes as Vec. + // Verify that TypeInfo reflects this by containing a reference to Vec. + let statement_type = Statement::type_info(); + let vec_field_meta = MetaType::new::>(); + + // The Statement type should be a composite with one unnamed field of type Vec + match statement_type.type_def { + scale_info::TypeDef::Composite(composite) => { + assert_eq!(composite.fields.len(), 1, "Statement should have exactly one field"); + let field = &composite.fields[0]; + assert!(field.name.is_none(), "Field should be unnamed (newtype pattern)"); + assert_eq!(field.ty, vec_field_meta, "Statement's inner type should be Vec"); + }, + _ => panic!("Statement TypeInfo should be a Composite"), + } + } }