diff --git a/src/events.rs b/src/events.rs index 9ecc63d4ff..15b74dca6f 100644 --- a/src/events.rs +++ b/src/events.rs @@ -253,10 +253,10 @@ where } } } - TypeDef::Compact(_compact) => { + TypeDef::Compact(compact) => { let inner = self .metadata - .resolve_type(type_id) + .resolve_type(compact.type_param().id()) .ok_or(MetadataError::TypeNotFound(type_id))?; let mut decode_compact_primitive = |primitive: &TypeDefPrimitive| { match primitive { @@ -339,35 +339,187 @@ pub enum EventsDecodingError { InvalidCompactType(String), } -// #[cfg(test)] -// mod tests { -// use super::*; -// use std::convert::TryFrom; -// -// type DefaultConfig = crate::NodeTemplateRuntime; -// -// #[test] -// fn test_decode_option() { -// let decoder = EventsDecoder::::new( -// Metadata::default(), -// ); -// -// let value = Some(0u8); -// let input = value.encode(); -// let mut output = Vec::::new(); -// let mut errors = Vec::::new(); -// -// decoder -// .decode_raw_bytes( -// &[EventArg::Option(Box::new(EventArg::Primitive( -// "u8".to_string(), -// )))], -// &mut &input[..], -// &mut output, -// &mut errors, -// ) -// .unwrap(); -// -// assert_eq!(output, vec![1, 0]); -// } -// } +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + Config, + DefaultConfig, + Phase, + }; + use frame_metadata::{ + v14::{ + ExtrinsicMetadata, + PalletEventMetadata, + PalletMetadata, + RuntimeMetadataLastVersion, + }, + RuntimeMetadataPrefixed, + }; + use scale_info::{ + meta_type, + TypeInfo, + }; + use std::convert::TryFrom; + + #[derive(Encode)] + pub struct EventRecord { + phase: Phase, + pallet_index: u8, + event: E, + topics: Vec<::Hash>, + } + + fn event_record(pallet_index: u8, event: E) -> EventRecord { + EventRecord { + phase: Phase::Finalization, + pallet_index, + event, + topics: vec![], + } + } + + fn pallet_metadata(pallet_index: u8) -> PalletMetadata { + let event = PalletEventMetadata { + ty: meta_type::(), + }; + PalletMetadata { + name: "Test", + storage: None, + calls: None, + event: Some(event), + constants: vec![], + error: None, + index: pallet_index, + } + } + + fn init_decoder(pallets: Vec) -> EventsDecoder { + let extrinsic = ExtrinsicMetadata { + ty: meta_type::<()>(), + version: 0, + signed_extensions: vec![], + }; + let v14 = RuntimeMetadataLastVersion::new(pallets, extrinsic, meta_type::<()>()); + let runtime_metadata: RuntimeMetadataPrefixed = v14.into(); + let metadata = Metadata::try_from(runtime_metadata).unwrap(); + EventsDecoder::::new(metadata) + } + + #[test] + fn decode_single_event() { + #[derive(Clone, Encode, TypeInfo)] + enum Event { + A(u8), + } + + let pallet_index = 0; + let pallet = pallet_metadata::(pallet_index); + let decoder = init_decoder(vec![pallet]); + + let event = Event::A(1); + let encoded_event = event.encode(); + let event_records = vec![event_record(pallet_index, event)]; + + let mut input = Vec::new(); + event_records.encode_to(&mut input); + + let events = decoder.decode_events(&mut &input[..]).unwrap(); + + assert_eq!(events[0].1.variant_index, encoded_event[0]); + assert_eq!(events[0].1.data.0, encoded_event[1..]); + } + + #[test] + fn decode_multiple_events() { + #[derive(Clone, Encode, TypeInfo)] + enum Event { + A(u8), + B, + C { a: u32 }, + } + + let pallet_index = 0; + let pallet = pallet_metadata::(pallet_index); + let decoder = init_decoder(vec![pallet]); + + let event1 = Event::A(1); + let event2 = Event::B; + let event3 = Event::C { a: 3 }; + + let encoded_event1 = event1.encode(); + let encoded_event2 = event2.encode(); + let encoded_event3 = event3.encode(); + + let event_records = vec![ + event_record(pallet_index, event1), + event_record(pallet_index, event2), + event_record(pallet_index, event3), + ]; + + let mut input = Vec::new(); + event_records.encode_to(&mut input); + + let events = decoder.decode_events(&mut &input[..]).unwrap(); + + assert_eq!(events[0].1.variant_index, encoded_event1[0]); + assert_eq!(events[0].1.data.0, encoded_event1[1..]); + + assert_eq!(events[1].1.variant_index, encoded_event2[0]); + assert_eq!(events[1].1.data.0, encoded_event2[1..]); + + assert_eq!(events[2].1.variant_index, encoded_event3[0]); + assert_eq!(events[2].1.data.0, encoded_event3[1..]); + } + + #[test] + fn compact_event_field() { + #[derive(Clone, Encode, TypeInfo)] + enum Event { + A(#[codec(compact)] u32), + } + + let pallet_index = 0; + let pallet = pallet_metadata::(pallet_index); + let decoder = init_decoder(vec![pallet]); + + let event = Event::A(u32::MAX); + let encoded_event = event.encode(); + let event_records = vec![event_record(pallet_index, event)]; + + let mut input = Vec::new(); + event_records.encode_to(&mut input); + + let events = decoder.decode_events(&mut &input[..]).unwrap(); + + assert_eq!(events[0].1.variant_index, encoded_event[0]); + assert_eq!(events[0].1.data.0, encoded_event[1..]); + } + + #[test] + fn compact_wrapper_struct_field() { + #[derive(Clone, Encode, TypeInfo)] + enum Event { + A(#[codec(compact)] CompactWrapper), + } + + #[derive(Clone, codec::CompactAs, Encode, TypeInfo)] + struct CompactWrapper(u64); + + let pallet_index = 0; + let pallet = pallet_metadata::(pallet_index); + let decoder = init_decoder(vec![pallet]); + + let event = Event::A(CompactWrapper(0)); + let encoded_event = event.encode(); + let event_records = vec![event_record(pallet_index, event)]; + + let mut input = Vec::new(); + event_records.encode_to(&mut input); + + let events = decoder.decode_events(&mut &input[..]).unwrap(); + + assert_eq!(events[0].1.variant_index, encoded_event[0]); + assert_eq!(events[0].1.data.0, encoded_event[1..]); + } +} diff --git a/src/lib.rs b/src/lib.rs index f3b2dbef25..0d8db57693 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -166,7 +166,7 @@ impl codec::Encode for Encoded { } /// A phase of a block's execution. -#[derive(Clone, Debug, Eq, PartialEq, Decode)] +#[derive(Clone, Debug, Eq, PartialEq, Decode, Encode)] pub enum Phase { /// Applying an extrinsic. ApplyExtrinsic(u32),