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
120 changes: 110 additions & 10 deletions src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,22 +153,23 @@ impl<T: System> EventsDecoder<T> {
args: &[EventArg],
input: &mut I,
output: &mut W,
errors: &mut Vec<RuntimeError>,
) -> Result<(), Error> {
for arg in args {
match arg {
EventArg::Vec(arg) => {
let len = <Compact<u32>>::decode(input)?;
len.encode_to(output);
for _ in 0..len.0 {
self.decode_raw_bytes(&[*arg.clone()], input, output)?
self.decode_raw_bytes(&[*arg.clone()], input, output, errors)?
}
}
EventArg::Option(arg) => {
match input.read_byte()? {
0 => output.push_byte(0),
1 => {
output.push_byte(1);
self.decode_raw_bytes(&[*arg.clone()], input, output)?
self.decode_raw_bytes(&[*arg.clone()], input, output, errors)?
}
_ => {
return Err(Error::Other(
Expand All @@ -177,7 +178,9 @@ impl<T: System> EventsDecoder<T> {
}
}
}
EventArg::Tuple(args) => self.decode_raw_bytes(args, input, output)?,
EventArg::Tuple(args) => {
self.decode_raw_bytes(args, input, output, errors)?
}
EventArg::Primitive(name) => {
let result = match name.as_str() {
"DispatchResult" => DispatchResult::decode(input)?,
Expand All @@ -194,9 +197,9 @@ impl<T: System> EventsDecoder<T> {
}
};
if let Err(error) = result {
return Err(
RuntimeError::from_dispatch(&self.metadata, error)?.into()
)
// since the input may contain any number of args we propagate
// runtime errors to the caller for handling
errors.push(RuntimeError::from_dispatch(&self.metadata, error)?);
}
}
}
Expand All @@ -220,16 +223,19 @@ impl<T: System> EventsDecoder<T> {
let event_metadata = module.event(event_variant)?;

log::debug!(
"received event '{}::{}'",
"received event '{}::{}' ({:?})",
module.name(),
event_metadata.name
event_metadata.name,
event_metadata.arguments()
);

let mut event_data = Vec::<u8>::new();
let mut event_errors = Vec::<RuntimeError>::new();
let result = self.decode_raw_bytes(
&event_metadata.arguments(),
input,
&mut event_data,
&mut event_errors,
);
let raw = match result {
Ok(()) => {
Expand All @@ -245,16 +251,22 @@ impl<T: System> EventsDecoder<T> {
let _topics = Vec::<T::Hash>::decode(input)?;
Raw::Event(event)
}
Err(Error::Runtime(err)) => Raw::Error(err),
Err(err) => return Err(err),
};

r.push((phase, raw));
if event_errors.len() == 0 {
r.push((phase.clone(), raw));
}

for err in event_errors {
r.push((phase.clone(), Raw::Error(err)));
}
}
Ok(r)
}
}

#[derive(Debug)]
pub enum Raw {
Event(RawEvent),
Error(RuntimeError),
Expand All @@ -263,6 +275,18 @@ pub enum Raw {
#[cfg(test)]
mod tests {
use super::*;
use frame_metadata::{
DecodeDifferent,
ErrorMetadata,
EventMetadata,
ExtrinsicMetadata,
ModuleMetadata,
RuntimeMetadata,
RuntimeMetadataPrefixed,
RuntimeMetadataV12,
META_RESERVED,
};
use std::convert::TryFrom;

type TestRuntime = crate::NodeTemplateRuntime;

Expand All @@ -273,6 +297,7 @@ mod tests {
let value = Some(0u8);
let input = value.encode();
let mut output = Vec::<u8>::new();
let mut errors = Vec::<RuntimeError>::new();

decoder
.decode_raw_bytes(
Expand All @@ -281,9 +306,84 @@ mod tests {
)))],
&mut &input[..],
&mut output,
&mut errors,
)
.unwrap();

assert_eq!(output, vec![1, 0]);
}

#[test]
fn test_decode_system_events_and_error() {
let decoder = EventsDecoder::<TestRuntime>::new(
Metadata::try_from(RuntimeMetadataPrefixed(
META_RESERVED,
RuntimeMetadata::V12(RuntimeMetadataV12 {
modules: DecodeDifferent::Decoded(vec![ModuleMetadata {
name: DecodeDifferent::Decoded("System".to_string()),
storage: None,
calls: None,
event: Some(DecodeDifferent::Decoded(vec![
EventMetadata {
name: DecodeDifferent::Decoded(
"ExtrinsicSuccess".to_string(),
),
arguments: DecodeDifferent::Decoded(vec![
"DispatchInfo".to_string()
]),
documentation: DecodeDifferent::Decoded(vec![]),
},
EventMetadata {
name: DecodeDifferent::Decoded(
"ExtrinsicFailed".to_string(),
),
arguments: DecodeDifferent::Decoded(vec![
"DispatchError".to_string(),
"DispatchInfo".to_string(),
]),
documentation: DecodeDifferent::Decoded(vec![]),
},
])),
constants: DecodeDifferent::Decoded(vec![]),
errors: DecodeDifferent::Decoded(vec![
ErrorMetadata {
name: DecodeDifferent::Decoded(
"InvalidSpecName".to_string(),
),
documentation: DecodeDifferent::Decoded(vec![]),
},
ErrorMetadata {
name: DecodeDifferent::Decoded(
"SpecVersionNeedsToIncrease".to_string(),
),
documentation: DecodeDifferent::Decoded(vec![]),
},
ErrorMetadata {
name: DecodeDifferent::Decoded(
"FailedToExtractRuntimeVersion".to_string(),
),
documentation: DecodeDifferent::Decoded(vec![]),
},
ErrorMetadata {
name: DecodeDifferent::Decoded(
"NonDefaultComposite".to_string(),
),
documentation: DecodeDifferent::Decoded(vec![]),
},
]),
index: 0,
}]),
extrinsic: ExtrinsicMetadata {
version: 0,
signed_extensions: vec![],
},
}),
))
.unwrap(),
);

// [(ApplyExtrinsic(0), Event(RawEvent { module: "System", variant: "ExtrinsicSuccess", data: "482d7c09000000000200" })), (ApplyExtrinsic(1), Error(Module(ModuleError { module: "System", error: "NonDefaultComposite" }))), (ApplyExtrinsic(2), Error(Module(ModuleError { module: "System", error: "NonDefaultComposite" })))]
let input = hex::decode("0c00000000000000482d7c0900000000020000000100000000010300035884723300000000000000000200000000010300035884723300000000000000").unwrap();
decoder.decode_events(&mut &input[..]).unwrap();
}
}