Skip to content

Commit

Permalink
propagate 'RuntimeError's to 'decode_raw_bytes' caller
Browse files Browse the repository at this point in the history
Signed-off-by: Gregory Hill <gregorydhill@outlook.com>
  • Loading branch information
gregdhill committed Nov 5, 2020
1 parent 7655caa commit 9d0b60c
Showing 1 changed file with 110 additions and 10 deletions.
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();
}
}

0 comments on commit 9d0b60c

Please sign in to comment.