Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix decoding events via .as_root_event() and add test #767

Merged
merged 3 commits into from
Jan 11, 2023
Merged
Changes from 2 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
60 changes: 50 additions & 10 deletions subxt/src/events/events_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,12 @@ pub struct EventDetails {
all_bytes: Arc<[u8]>,
// start of the bytes (phase, pallet/variant index and then fields and then topic to follow).
start_idx: usize,
// start of the event (ie pallet/variant index and then the fields and topic after).
event_start_idx: usize,
// start of the fields (ie after phase nad pallet/variant index).
jsdw marked this conversation as resolved.
Show resolved Hide resolved
fields_start_idx: usize,
event_fields_start_idx: usize,
// end of the fields.
fields_end_idx: usize,
event_fields_end_idx: usize,
// end of everything (fields + topics)
end_idx: usize,
metadata: Metadata,
Expand All @@ -221,10 +223,13 @@ impl EventDetails {
let input = &mut &all_bytes[start_idx..];

let phase = Phase::decode(input)?;

let event_start_idx = all_bytes.len() - input.len();

let pallet_index = u8::decode(input)?;
let variant_index = u8::decode(input)?;

let fields_start_idx = all_bytes.len() - input.len();
let event_fields_start_idx = all_bytes.len() - input.len();

// Get metadata for the event:
let event_metadata = metadata.event(pallet_index, variant_index)?;
Expand All @@ -246,7 +251,7 @@ impl EventDetails {
}

// the end of the field bytes.
let fields_end_idx = all_bytes.len() - input.len();
let event_fields_end_idx = all_bytes.len() - input.len();

// topics come after the event data in EventRecord. They aren't used for
// anything at the moment, so just decode and throw them away.
Expand All @@ -259,8 +264,9 @@ impl EventDetails {
phase,
index,
start_idx,
fields_start_idx,
fields_end_idx,
event_start_idx,
event_fields_start_idx,
event_fields_end_idx,
end_idx,
all_bytes,
metadata,
Expand All @@ -281,14 +287,14 @@ impl EventDetails {
pub fn pallet_index(&self) -> u8 {
// Note: never panics; we expect these bytes to exist
// in order that the EventDetails could be created.
self.all_bytes[self.fields_start_idx - 2]
self.all_bytes[self.event_fields_start_idx - 2]
}

/// The index of the event variant that the event originated from.
pub fn variant_index(&self) -> u8 {
// Note: never panics; we expect these bytes to exist
// in order that the EventDetails could be created.
self.all_bytes[self.fields_start_idx - 1]
self.all_bytes[self.event_fields_start_idx - 1]
}

/// The name of the pallet from whence the Event originated.
Expand Down Expand Up @@ -319,7 +325,7 @@ impl EventDetails {

/// Return the bytes representing the fields stored in this event.
pub fn field_bytes(&self) -> &[u8] {
&self.all_bytes[self.fields_start_idx..self.fields_end_idx]
&self.all_bytes[self.event_fields_start_idx..self.event_fields_end_idx]
}

/// Decode and provide the event fields back in the form of a [`scale_value::Composite`]
Expand Down Expand Up @@ -384,7 +390,7 @@ impl EventDetails {
/// the pallet and event enum variants as well as the event fields). A compatible
/// type for this is exposed via static codegen as a root level `Event` type.
pub fn as_root_event<E: Decode>(&self) -> Result<E, CodecError> {
E::decode(&mut self.bytes())
E::decode(&mut &self.all_bytes[self.event_start_idx..self.event_fields_end_idx])
}
}

Expand Down Expand Up @@ -503,6 +509,7 @@ mod tests {
event_record,
events,
events_raw,
AllEvents,
},
*,
};
Expand Down Expand Up @@ -572,6 +579,39 @@ mod tests {
assert_eq!(actual_fields_no_context, expected.fields);
}

#[test]
fn statically_decode_single_root_event() {
#[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
enum Event {
A(u8, bool, Vec<String>),
}

// Create fake metadata that knows about our single event, above:
let metadata = metadata::<Event>();

// Encode our events in the format we expect back from a node, and
// construst an Events object to iterate them:
let event = Event::A(1, true, vec!["Hi".into()]);
let events = events::<Event>(
metadata,
vec![event_record(Phase::ApplyExtrinsic(123), event.clone())],
);

let ev = events
.iter()
.next()
.expect("one event expected")
.expect("event should be extracted OK");

// This is the line we're testing:
let decoded_event = ev
.as_root_event::<AllEvents<Event>>()
.expect("can decode event into root enum again");

// It should equal the event we put in:
assert_eq!(decoded_event, AllEvents::Test(event));
}

#[test]
fn dynamically_decode_single_event() {
#[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
Expand Down