Skip to content

Commit

Permalink
Fix compact event field decoding (paritytech#384)
Browse files Browse the repository at this point in the history
* Add basic event decoding test

* Failing compact event field test

* Fmt

* Fix compact event field decoding

* Remove println

* Add test for compact wrapper struct

* Revert "Add test for compact wrapper struct"

This reverts commit 4e8332d.

* Split compact tests and add multiple events test
  • Loading branch information
ascjones authored and 0623forbidden committed Feb 15, 2022
1 parent 492feb9 commit 12a5ec0
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 35 deletions.
220 changes: 186 additions & 34 deletions src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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::<DefaultConfig>::new(
// Metadata::default(),
// );
//
// let value = Some(0u8);
// let input = value.encode();
// let mut output = Vec::<u8>::new();
// let mut errors = Vec::<RuntimeError>::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<E: Encode> {
phase: Phase,
pallet_index: u8,
event: E,
topics: Vec<<DefaultConfig as Config>::Hash>,
}

fn event_record<E: Encode>(pallet_index: u8, event: E) -> EventRecord<E> {
EventRecord {
phase: Phase::Finalization,
pallet_index,
event,
topics: vec![],
}
}

fn pallet_metadata<E: TypeInfo + 'static>(pallet_index: u8) -> PalletMetadata {
let event = PalletEventMetadata {
ty: meta_type::<E>(),
};
PalletMetadata {
name: "Test",
storage: None,
calls: None,
event: Some(event),
constants: vec![],
error: None,
index: pallet_index,
}
}

fn init_decoder(pallets: Vec<PalletMetadata>) -> EventsDecoder<DefaultConfig> {
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::<DefaultConfig>::new(metadata)
}

#[test]
fn decode_single_event() {
#[derive(Clone, Encode, TypeInfo)]
enum Event {
A(u8),
}

let pallet_index = 0;
let pallet = pallet_metadata::<Event>(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::<Event>(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::<Event>(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::<Event>(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..]);
}
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down

0 comments on commit 12a5ec0

Please sign in to comment.