From 9d0b60c0c3b4e6c24f0167b310a1c9b8c52f8e6c Mon Sep 17 00:00:00 2001 From: Gregory Hill Date: Thu, 5 Nov 2020 20:02:25 +0000 Subject: [PATCH] propagate 'RuntimeError's to 'decode_raw_bytes' caller Signed-off-by: Gregory Hill --- src/events.rs | 120 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 110 insertions(+), 10 deletions(-) diff --git a/src/events.rs b/src/events.rs index ec05909c52..989242a570 100644 --- a/src/events.rs +++ b/src/events.rs @@ -153,6 +153,7 @@ impl EventsDecoder { args: &[EventArg], input: &mut I, output: &mut W, + errors: &mut Vec, ) -> Result<(), Error> { for arg in args { match arg { @@ -160,7 +161,7 @@ impl EventsDecoder { let len = >::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) => { @@ -168,7 +169,7 @@ impl EventsDecoder { 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( @@ -177,7 +178,9 @@ impl EventsDecoder { } } } - 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)?, @@ -194,9 +197,9 @@ impl EventsDecoder { } }; 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)?); } } } @@ -220,16 +223,19 @@ impl EventsDecoder { 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::::new(); + let mut event_errors = Vec::::new(); let result = self.decode_raw_bytes( &event_metadata.arguments(), input, &mut event_data, + &mut event_errors, ); let raw = match result { Ok(()) => { @@ -245,16 +251,22 @@ impl EventsDecoder { let _topics = Vec::::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), @@ -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; @@ -273,6 +297,7 @@ mod tests { let value = Some(0u8); let input = value.encode(); let mut output = Vec::::new(); + let mut errors = Vec::::new(); decoder .decode_raw_bytes( @@ -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::::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(); + } }