Skip to content

Instantly share code, notes, and snippets.

@tomusdrw
Created January 13, 2021 13:38
Show Gist options
  • Save tomusdrw/c6ae3a84bdb2c7b56302c7496cae24f2 to your computer and use it in GitHub Desktop.
Save tomusdrw/c6ae3a84bdb2c7b56302c7496cae24f2 to your computer and use it in GitHub Desktop.
/// A helper type to allow using arbitrary SCALE-encoded leaf data in the RuntimeApi.
///
/// The point is to be able to verify MMR proofs from external MMRs, where we don't
/// know the exact leaf type, but it's enough for us to have it SCALE-encoded.
///
/// Note the leaf type should be encoded in it's compact form when passed through this type.
/// See [FullLeaf] documentation for details.
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
#[derive(RuntimeDebug, Clone, PartialEq)]
pub struct OpaqueLeaf(
#[cfg_attr(feature = "std", serde(with = "sp_core::bytes"))]
Vec<u8>
);
impl codec::Encode for OpaqueLeaf {
fn size_hint(&self) -> usize {
self.0.len()
}
fn encode_to<T: codec::Output>(&self, dest: &mut T) {
dest.write(&self.0)
}
}
impl codec::Decode for OpaqueLeaf {
fn decode<I: codec::Input>(value: &mut I) -> Result<Self, codec::Error> {
const MAX_LENGTH: usize = 1 * 1024 * 1024;
let capacity = value.remaining_len()?;
match capacity {
Some(capacity) if capacity > MAX_LENGTH => {
Err(codec::Error::from("maximal leaf length exceeded."))
},
Some(capacity) => {
let mut buffer = Vec::with_capacity(capacity);
buffer.resize(capacity, 0);
value.read(&mut buffer)?;
Ok(OpaqueLeaf(buffer))
},
// read byte-by-byte, up to MAX_LENGTH
None => {
let mut buffer = Vec::with_capacity(MAX_LENGTH / 1024);
while buffer.len() < MAX_LENGTH {
if let Ok(byte) = value.read_byte() {
buffer.push(byte);
} else {
return Ok(OpaqueLeaf(buffer))
}
}
Err(codec::Error::from("maximal leaf length exceeded."))
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment