#[derive(Clone, Copy)]
pub struct AllExtrinsicBytes<'a> {
len: usize,
data: &'a [u8],
}
impl<'a> AllExtrinsicBytes<'a> {
pub fn new(bytes: &'a [u8]) -> Result<AllExtrinsicBytes<'a>, ExtrinsicBytesError> {
let (vec_len, vec_len_bytes) = match decode_compact_u32(bytes) {
Some(res) => res,
None => return Err(ExtrinsicBytesError { index: 0 }),
};
Ok(AllExtrinsicBytes { len: vec_len, data: &bytes[vec_len_bytes..] })
}
}
impl<'a> AllExtrinsicBytes<'a> {
pub fn len(&self) -> usize {
self.len
}
pub fn iter(&self) -> ExtrinsicBytesIter<'a> {
ExtrinsicBytesIter { remaining_len: self.len, data: self.data, cursor: 0 }
}
}
pub struct ExtrinsicBytesIter<'a> {
remaining_len: usize,
data: &'a [u8],
cursor: usize,
}
impl<'a> ExtrinsicBytesIter<'a> {
pub fn remaining_bytes(&self) -> &'a [u8] {
&self.data[self.cursor..]
}
}
impl<'a> Iterator for ExtrinsicBytesIter<'a> {
type Item = Result<ExtrinsicBytes<'a>, ExtrinsicBytesError>;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining_len == 0 || self.cursor >= self.data.len() {
return None;
}
self.remaining_len -= 1;
let (vec_len, vec_len_bytes) = match decode_compact_u32(&self.data[self.cursor..]) {
Some(res) => res,
None => {
self.remaining_len = 0;
return Some(Err(ExtrinsicBytesError { index: self.cursor }));
}
};
log::trace!("Length {}, Prefix: {}", vec_len, vec_len_bytes);
let start = self.cursor + vec_len_bytes;
let end = self.cursor + vec_len_bytes + vec_len;
if end > self.data.len() {
self.remaining_len = 0;
return Some(Err(ExtrinsicBytesError { index: self.data.len() }));
}
let res = &self.data[start..end];
self.cursor += vec_len + vec_len_bytes;
Some(Ok(ExtrinsicBytes { data: res }))
}
}
pub struct ExtrinsicBytes<'a> {
data: &'a [u8],
}
impl<'a> ExtrinsicBytes<'a> {
pub fn bytes(&self) -> &'a [u8] {
self.data
}
}
#[derive(Debug, Clone, Copy, PartialEq, thiserror::Error)]
#[error("Expected a compact encoded u32 at byte index {index}, but did not find one")]
pub struct ExtrinsicBytesError {
pub index: usize,
}
fn decode_compact_u32(mut data: &[u8]) -> Option<(usize, usize)> {
use codec::{Compact, CompactLen, Decode};
let length = u32::from(Compact::<u32>::decode(&mut data).ok()?);
let prefix = Compact::<u32>::compact_len(&length);
let length = usize::try_from(length).ok()?;
Some((length, prefix))
}
#[cfg(test)]
mod test {
use super::*;
use codec::{Compact, Encode};
fn iter_result_to_bytes<E>(res: Option<Result<ExtrinsicBytes<'_>, E>>) -> Option<Result<&[u8], E>> {
res.map(|r| r.map(|e| e.bytes()))
}
#[test]
fn no_malformed_bytes_iterated_properly() {
let mut bytes: Vec<u8> = vec![];
bytes.extend_from_slice(&Compact(2u32).encode());
bytes.extend_from_slice(&Compact(4u32).encode());
bytes.extend_from_slice(&[1, 2, 3, 4]);
bytes.extend_from_slice(&Compact(3u32).encode());
bytes.extend_from_slice(&[1, 2, 3]);
let exts = AllExtrinsicBytes::new(&bytes).unwrap();
assert_eq!(exts.len(), 2);
let mut exts = exts.iter();
assert_eq!(iter_result_to_bytes(exts.next()), Some(Ok(&[1, 2, 3, 4][..])));
assert_eq!(iter_result_to_bytes(exts.next()), Some(Ok(&[1, 2, 3][..])));
assert_eq!(iter_result_to_bytes(exts.next()), None);
}
#[test]
fn malformed_extrinsics_length() {
let mut bytes: Vec<u8> = vec![];
bytes.extend_from_slice(&Compact(3u32).encode());
bytes.extend_from_slice(&Compact(4u32).encode());
bytes.extend_from_slice(&[1, 2, 3, 4]);
bytes.extend_from_slice(&Compact(3u32).encode());
bytes.extend_from_slice(&[1, 2, 3]);
let exts = AllExtrinsicBytes::new(&bytes).unwrap();
assert_eq!(exts.len(), 3);
let mut exts = exts.iter();
assert_eq!(iter_result_to_bytes(exts.next()), Some(Ok(&[1, 2, 3, 4][..])));
assert_eq!(iter_result_to_bytes(exts.next()), Some(Ok(&[1, 2, 3][..])));
assert_eq!(iter_result_to_bytes(exts.next()), None);
}
#[test]
fn malformed_extrinsic_length() {
let mut bytes: Vec<u8> = vec![];
bytes.extend_from_slice(&Compact(2u32).encode());
bytes.extend_from_slice(&Compact(4u32).encode());
bytes.extend_from_slice(&[1, 2, 3, 4]);
bytes.extend_from_slice(&Compact(3u32).encode());
bytes.extend_from_slice(&[1, 2]);
let exts = AllExtrinsicBytes::new(&bytes).unwrap();
assert_eq!(exts.len(), 2);
let mut exts = exts.iter();
assert_eq!(iter_result_to_bytes(exts.next()), Some(Ok(&[1, 2, 3, 4][..])));
assert_eq!(iter_result_to_bytes(exts.next()), Some(Err(ExtrinsicBytesError { index: 8 })));
assert_eq!(iter_result_to_bytes(exts.next()), None);
}
#[test]
fn malformed_two_lengths() {
let mut bytes: Vec<u8> = vec![];
bytes.extend_from_slice(&Compact(3u32).encode());
bytes.extend_from_slice(&Compact(4u32).encode());
bytes.extend_from_slice(&[1, 2, 3, 4]);
bytes.extend_from_slice(&Compact(3u32).encode());
bytes.extend_from_slice(&[1, 2]);
let exts = AllExtrinsicBytes::new(&bytes).unwrap();
assert_eq!(exts.len(), 3);
let mut exts = exts.iter();
assert_eq!(iter_result_to_bytes(exts.next()), Some(Ok(&[1, 2, 3, 4][..])));
assert_eq!(iter_result_to_bytes(exts.next()), Some(Err(ExtrinsicBytesError { index: 8 })));
assert_eq!(iter_result_to_bytes(exts.next()), None);
}
#[test]
fn wont_iterate_past_advertised_length() {
let mut bytes: Vec<u8> = vec![];
bytes.extend_from_slice(&Compact(2u32).encode());
bytes.extend_from_slice(&Compact(4u32).encode());
bytes.extend_from_slice(&[1, 2, 3, 4]);
bytes.extend_from_slice(&Compact(3u32).encode());
bytes.extend_from_slice(&[1, 2, 3]);
bytes.extend_from_slice(&Compact(5u32).encode());
bytes.extend_from_slice(&[1, 2, 3, 4, 5]);
let exts = AllExtrinsicBytes::new(&bytes).unwrap();
assert_eq!(exts.len(), 2);
let mut exts = exts.iter();
assert_eq!(iter_result_to_bytes(exts.next()), Some(Ok(&[1, 2, 3, 4][..])));
assert_eq!(iter_result_to_bytes(exts.next()), Some(Ok(&[1, 2, 3][..])));
assert_eq!(iter_result_to_bytes(exts.next()), None);
let mut remaining_bytes: Vec<u8> = vec![];
remaining_bytes.extend_from_slice(&Compact(5u32).encode());
remaining_bytes.extend_from_slice(&[1, 2, 3, 4, 5]);
assert_eq!(exts.remaining_bytes(), &remaining_bytes);
}
}