Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions substrate/primitives/statement-store/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Proof>,
decryption_key: Option<DecryptionKey>,
Expand All @@ -184,6 +184,20 @@ pub struct Statement {
data: Option<Vec<u8>>,
}

/// Note: The `TypeInfo` implementation reflects the actual encoding format (`Vec<Field>`)
/// 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<Field>, 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::<Vec<Field>>()))
}
}

impl Decode for Statement {
fn decode<I: codec::Input>(input: &mut I) -> core::result::Result<Self, codec::Error> {
// Encoding matches that of Vec<Field>. Basically this just means accepting that there
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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<Field>.
// Verify that TypeInfo reflects this by containing a reference to Vec<Field>.
let statement_type = Statement::type_info();
let vec_field_meta = MetaType::new::<Vec<Field>>();

// The Statement type should be a composite with one unnamed field of type Vec<Field>
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<Field>");
},
_ => panic!("Statement TypeInfo should be a Composite"),
}
}
}
Loading