propagate 'RuntimeError's to 'decode_raw_bytes' caller (#189)

Signed-off-by: Gregory Hill <gregorydhill@outlook.com>
This commit is contained in:
Greg Hill
2020-11-13 17:16:14 +00:00
committed by GitHub
parent 7655caac0f
commit 27c377a9d6
+110 -10
View File
@@ -153,6 +153,7 @@ 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 {
@@ -160,7 +161,7 @@ impl<T: System> EventsDecoder<T> {
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) => {
@@ -168,7 +169,7 @@ impl<T: System> EventsDecoder<T> {
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<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)?,
@@ -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)?);
}
}
}
@@ -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(()) => {
@@ -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),
@@ -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::<u8>::new();
let mut errors = Vec::<RuntimeError>::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::<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();
}
}