From 2bc7c57359c3b75d5649f0a9b984dbcd7a4556fb Mon Sep 17 00:00:00 2001
From: Robert Habermeier <rphmeier@gmail.com>
Date: Mon, 5 Feb 2018 16:15:45 +0100
Subject: [PATCH] reintroduce slicable to primitives

---
 substrate/primitives/Cargo.toml              |   2 +-
 substrate/primitives/src/block.rs            | 109 +++++++++++++++---
 substrate/primitives/src/hash.rs             |  10 ++
 substrate/primitives/src/lib.rs              |  17 +++
 substrate/primitives/src/parachain.rs        |  20 ++++
 substrate/primitives/src/proposal.rs         | 112 ++++++++++++++-----
 substrate/primitives/src/runtime_function.rs | 103 +++++++++++++++--
 substrate/primitives/src/transaction.rs      |  33 ++++++
 substrate/runtime-codec/src/lib.rs           |   1 -
 9 files changed, 351 insertions(+), 56 deletions(-)

diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml
index 9421c8f6249..01aa0315aea 100644
--- a/substrate/primitives/Cargo.toml
+++ b/substrate/primitives/Cargo.toml
@@ -15,7 +15,7 @@ untrusted = "0.5"
 twox-hash = "1.1.0"
 byteorder = "1.1"
 blake2-rfc = "0.2.18"
-polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1" }
+polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1", default_features = false }
 
 [dev-dependencies]
 polkadot-serializer = { path = "../serializer", version = "0.1" }
diff --git a/substrate/primitives/src/block.rs b/substrate/primitives/src/block.rs
index 26639d7d2e3..3fd73b09cc9 100644
--- a/substrate/primitives/src/block.rs
+++ b/substrate/primitives/src/block.rs
@@ -17,6 +17,7 @@
 //! Block and header type definitions.
 
 use bytes::{self, Vec};
+use codec::Slicable;
 use hash::H256;
 use parachain;
 use transaction::UncheckedTransaction;
@@ -34,6 +35,35 @@ pub type TransactionHash = H256;
 #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
 pub struct Log(#[serde(with="bytes")] pub Vec<u8>);
 
+impl Slicable for Log {
+	fn from_slice(value: &mut &[u8]) -> Option<Self> {
+		Vec::<u8>::from_slice(value).map(Log)
+	}
+
+	fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
+		self.0.as_slice_then(f)
+	}
+}
+
+impl ::codec::NonTrivialSlicable for Log { }
+
+/// The digest of a block, useful for light-clients.
+#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
+pub struct Digest {
+	/// All logs that have happened in the block.
+	pub logs: Vec<Log>,
+}
+
+impl Slicable for Digest {
+	fn from_slice(value: &mut &[u8]) -> Option<Self> {
+		Vec::<Log>::from_slice(value).map(|logs| Digest { logs })
+	}
+
+	fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
+		self.logs.as_slice_then(f)
+	}
+}
+
 /// A Polkadot relay chain block.
 #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
 pub struct Block {
@@ -43,11 +73,26 @@ pub struct Block {
 	pub transactions: Vec<UncheckedTransaction>,
 }
 
-/// The digest of a block, useful for light-clients.
-#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
-pub struct Digest {
-	/// All logs that have happened in the block.
-	pub logs: Vec<Log>,
+impl Slicable for Block {
+	fn from_slice(value: &mut &[u8]) -> Option<Self> {
+		Some(Block {
+			header: try_opt!(Slicable::from_slice(value)),
+			transactions: try_opt!(Slicable::from_slice(value)),
+		})
+	}
+
+	fn to_vec(&self) -> Vec<u8> {
+		let mut v = Vec::new();
+
+		v.extend(self.header.to_vec());
+		v.extend(self.transactions.to_vec());
+
+		v
+	}
+
+	fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
+		f(self.to_vec().as_slice())
+	}
 }
 
 /// A relay chain block header.
@@ -65,12 +110,38 @@ pub struct Header {
 	pub state_root: H256,
 	/// The root of the trie that represents this block's transactions, indexed by a 32-byte integer.
 	pub transaction_root: H256,
-	/// Parachain activity bitfield
-	pub parachain_activity: parachain::Activity,
 	/// The digest of activity on the block.
 	pub digest: Digest,
 }
 
+impl Slicable for Header {
+	fn from_slice(value: &mut &[u8]) -> Option<Self> {
+		Some(Header {
+			parent_hash: try_opt!(Slicable::from_slice(value)),
+			number: try_opt!(Slicable::from_slice(value)),
+			state_root: try_opt!(Slicable::from_slice(value)),
+			transaction_root: try_opt!(Slicable::from_slice(value)),
+			digest: try_opt!(Slicable::from_slice(value)),
+		})
+	}
+
+	fn to_vec(&self) -> Vec<u8> {
+		let mut v = Vec::new();
+
+		self.parent_hash.as_slice_then(|s| v.extend(s));
+		self.number.as_slice_then(|s| v.extend(s));
+		self.state_root.as_slice_then(|s| v.extend(s));
+		self.transaction_root.as_slice_then(|s| v.extend(s));
+		self.digest.as_slice_then(|s| v.extend(s));
+
+		v
+	}
+
+	fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
+		f(self.to_vec().as_slice())
+	}
+}
+
 /// A relay chain block body.
 ///
 /// Included candidates should be sorted by parachain ID, and without duplicate
@@ -86,25 +157,33 @@ pub struct Body {
 #[cfg(test)]
 mod tests {
 	use super::*;
+	use codec::Slicable;
 	use polkadot_serializer as ser;
 
 	#[test]
 	fn test_header_serialization() {
-		assert_eq!(ser::to_string_pretty(&Header {
+		let header = Header {
 			parent_hash: 5.into(),
 			number: 67,
 			state_root: 3.into(),
-			parachain_activity: parachain::Activity(vec![0]),
-			logs: vec![Log(vec![1])],
-		}), r#"{
+			transaction_root: 6.into(),
+			digest: Digest { logs: vec![Log(vec![1])] },
+		};
+
+		assert_eq!(ser::to_string_pretty(&header), r#"{
   "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000005",
   "number": 67,
   "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000003",
-  "parachainActivity": "0x00",
-  "logs": [
-    "0x01"
-  ]
+  "transactionRoot": "0x0000000000000000000000000000000000000000000000000000000000000006",
+  "digest": {
+    "logs": [
+      "0x01"
+    ]
+  }
 }"#);
+
+		let v = header.to_vec();
+		assert_eq!(Header::from_slice(&mut &v[..]).unwrap(), header);
 	}
 
 	#[test]
diff --git a/substrate/primitives/src/hash.rs b/substrate/primitives/src/hash.rs
index b6711cdfcb6..8e7c6f2b8f3 100644
--- a/substrate/primitives/src/hash.rs
+++ b/substrate/primitives/src/hash.rs
@@ -34,6 +34,16 @@ macro_rules! impl_serde {
 					.map(|x| (&*x).into())
 			}
 		}
+
+		impl ::codec::Slicable for $name {
+			fn from_slice(value: &mut &[u8]) -> Option<Self> {
+				<[u8; $len] as ::codec::Slicable>::from_slice(value).map($name)
+			}
+
+			fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
+				self.0.as_slice_then(f)
+			}
+		}
 	}
 }
 
diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs
index 00ceee2d548..fb6a056dd5a 100644
--- a/substrate/primitives/src/lib.rs
+++ b/substrate/primitives/src/lib.rs
@@ -40,6 +40,7 @@ extern crate uint as uint_crate;
 
 #[cfg(feature = "std")]
 extern crate core;
+extern crate polkadot_runtime_codec as codec;
 #[cfg(test)]
 extern crate polkadot_serializer;
 #[cfg(test)]
@@ -50,6 +51,16 @@ extern crate pretty_assertions;
 #[macro_use]
 extern crate alloc;
 
+// TODO: factor out to separate crate.
+macro_rules! try_opt {
+	($e: expr) => {
+		match $e {
+			Some(x) => x,
+			None => return None,
+		}
+	}
+}
+
 mod bytes;
 pub mod block;
 pub mod contract;
@@ -95,6 +106,12 @@ pub type Hash = [u8; 32];
 /// Alias to 520-bit hash when used in the context of a signature.
 pub type Signature = hash::H512;
 
+/// A balance in the staking subsystem.
+pub type Balance = u64;
+
+/// A timestamp.
+pub type Timestamp = u64;
+
 /// A hash function.
 pub fn hash(data: &[u8]) -> hash::H256 {
 	blake2_256(data).into()
diff --git a/substrate/primitives/src/parachain.rs b/substrate/primitives/src/parachain.rs
index 360b7bacdda..5c5429e0199 100644
--- a/substrate/primitives/src/parachain.rs
+++ b/substrate/primitives/src/parachain.rs
@@ -30,6 +30,16 @@ impl From<u64> for Id {
 	fn from(x: u64) -> Self { Id(x) }
 }
 
+impl ::codec::Slicable for Id {
+	fn from_slice(value: &mut &[u8]) -> Option<Self> {
+		u64::from_slice(value).map(Id)
+	}
+
+	fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
+		self.0.as_slice_then(f)
+	}
+}
+
 /// Candidate parachain block.
 ///
 /// https://github.com/w3f/polkadot-spec/blob/master/spec.md#candidate-para-chain-block
@@ -101,6 +111,16 @@ pub struct ValidationCode(#[serde(with="bytes")] pub Vec<u8>);
 #[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)]
 pub struct Activity(#[serde(with="bytes")] pub Vec<u8>);
 
+impl ::codec::Slicable for Activity {
+	fn from_slice(value: &mut &[u8]) -> Option<Self> {
+		Vec::<u8>::from_slice(value).map(Activity)
+	}
+
+	fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
+		self.0.as_slice_then(f)
+	}
+}
+
 #[cfg(test)]
 mod tests {
 	use super::*;
diff --git a/substrate/primitives/src/proposal.rs b/substrate/primitives/src/proposal.rs
index f8f39c815bc..833f08a94ad 100644
--- a/substrate/primitives/src/proposal.rs
+++ b/substrate/primitives/src/proposal.rs
@@ -19,12 +19,12 @@
 //! This describes a combination of a function ID and data that can be used to call into
 //! an internal function.
 
-use bytes;
+use block::Number as BlockNumber;
+use codec::Slicable;
 
-/// Internal functions that can be dispatched to.
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
 #[repr(u8)]
-pub enum InternalFunction {
+enum InternalFunctionId {
 	/// Set the system's code.
 	SystemSetCode = 0,
 	/// Set the number of sessions per era.
@@ -39,17 +39,17 @@ pub enum InternalFunction {
 	SessionSetLength = 5,
 }
 
-impl InternalFunction {
+impl InternalFunctionId {
 	/// Derive `Some` value from a `u8`, or `None` if it's invalid.
-	pub fn from_u8(value: u8) -> Option<InternalFunction> {
+	fn from_u8(value: u8) -> Option<InternalFunctionId> {
 		use self::*;
 		let functions = [
-			InternalFunction::SystemSetCode,
-			InternalFunction::StakingSetSessionsPerEra,
-			InternalFunction::StakingSetBondingDuration,
-			InternalFunction::StakingSetValidatorCount,
-			InternalFunction::GovernanceSetApprovalPpmRequired,
-			InternalFunction::SessionSetLength
+			InternalFunctionId::SystemSetCode,
+			InternalFunctionId::StakingSetSessionsPerEra,
+			InternalFunctionId::StakingSetBondingDuration,
+			InternalFunctionId::StakingSetValidatorCount,
+			InternalFunctionId::GovernanceSetApprovalPpmRequired,
+			InternalFunctionId::SessionSetLength
 		];
 		if (value as usize) < functions.len() {
 			Some(functions[value as usize])
@@ -59,31 +59,85 @@ impl InternalFunction {
 	}
 }
 
+/// Internal functions that can be dispatched to.
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[repr(u8)]
+pub enum InternalFunction {
+	/// Set the system's code.
+	SystemSetCode(Vec<u8>),
+	/// Set the number of sessions per era.
+	StakingSetSessionsPerEra(BlockNumber),
+	/// Set the minimum bonding duration for staking.
+	StakingSetBondingDuration(BlockNumber),
+	/// Set the validator count for staking.
+	StakingSetValidatorCount(u32),
+	/// Set the per-mille of validator approval required for governance changes.
+	GovernanceSetApprovalPpmRequired(u32),
+	/// Set the session length.
+	SessionSetLength(BlockNumber),
+}
+
 /// An internal function.
-#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
 pub struct Proposal {
 	/// The privileged function to call.
 	pub function: InternalFunction,
-	/// The serialised data to call it with.
-	#[serde(with = "bytes")]
-	pub input_data: Vec<u8>,
 }
 
-#[cfg(test)]
-mod test {
-	use super::*;
-	use support::StaticHexInto;
-
-	#[test]
-	fn slicing_should_work() {
-		let p = Proposal {
-			function: InternalFunction::SystemSetCode,
-			input_data: b"Hello world".to_vec(),
+impl Slicable for Proposal {
+	fn from_slice(value: &mut &[u8]) -> Option<Self> {
+		let id = try_opt!(u8::from_slice(value).and_then(InternalFunctionId::from_u8));
+		let function = match id {
+			InternalFunctionId::SystemSetCode =>
+				InternalFunction::SystemSetCode(try_opt!(Slicable::from_slice(value))),
+			InternalFunctionId::StakingSetSessionsPerEra =>
+				InternalFunction::StakingSetSessionsPerEra(try_opt!(Slicable::from_slice(value))),
+			InternalFunctionId::StakingSetBondingDuration =>
+				InternalFunction::StakingSetBondingDuration(try_opt!(Slicable::from_slice(value))),
+			InternalFunctionId::StakingSetValidatorCount =>
+				InternalFunction::StakingSetValidatorCount(try_opt!(Slicable::from_slice(value))),
+			InternalFunctionId::GovernanceSetApprovalPpmRequired =>
+				InternalFunction::GovernanceSetApprovalPpmRequired(try_opt!(Slicable::from_slice(value))),
+			InternalFunctionId::SessionSetLength =>
+				InternalFunction::SessionSetLength(try_opt!(Slicable::from_slice(value))),
 		};
-		let v = p.to_vec();
-		assert_eq!(v, "000b00000048656c6c6f20776f726c64".convert::<Vec<u8>>());
 
-		let o = Proposal::from_slice(&v).unwrap();
-		assert_eq!(p, o);
+		Some(Proposal { function })
+	}
+
+	fn to_vec(&self) -> Vec<u8> {
+		let mut v = Vec::new();
+		match self.function {
+			InternalFunction::SystemSetCode(ref data) => {
+				(InternalFunctionId::SystemSetCode as u8).as_slice_then(|s| v.extend(s));
+				data.as_slice_then(|s| v.extend(s));
+			}
+			InternalFunction::StakingSetSessionsPerEra(ref data) => {
+				(InternalFunctionId::StakingSetSessionsPerEra as u8).as_slice_then(|s| v.extend(s));
+				data.as_slice_then(|s| v.extend(s));
+			}
+			InternalFunction::StakingSetBondingDuration(ref data) => {
+				(InternalFunctionId::StakingSetBondingDuration as u8).as_slice_then(|s| v.extend(s));
+				data.as_slice_then(|s| v.extend(s));
+			}
+			InternalFunction::StakingSetValidatorCount(ref data) => {
+				(InternalFunctionId::StakingSetValidatorCount as u8).as_slice_then(|s| v.extend(s));
+				data.as_slice_then(|s| v.extend(s));
+			}
+			InternalFunction::GovernanceSetApprovalPpmRequired(ref data) => {
+				(InternalFunctionId::GovernanceSetApprovalPpmRequired as u8).as_slice_then(|s| v.extend(s));
+				data.as_slice_then(|s| v.extend(s));
+			}
+			InternalFunction::SessionSetLength(ref data) => {
+				(InternalFunctionId::SessionSetLength as u8).as_slice_then(|s| v.extend(s));
+				data.as_slice_then(|s| v.extend(s));
+			}
+		}
+
+		v
+	}
+
+	fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
+		f(self.to_vec().as_slice())
 	}
 }
diff --git a/substrate/primitives/src/runtime_function.rs b/substrate/primitives/src/runtime_function.rs
index 0104447f022..c4f6298f747 100644
--- a/substrate/primitives/src/runtime_function.rs
+++ b/substrate/primitives/src/runtime_function.rs
@@ -17,10 +17,12 @@
 //! Polkadot runtime functions.
 //! This describes a function that can be called from an external transaction.
 
+use codec::Slicable;
+
 /// Public functions that can be dispatched to.
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
 #[repr(u8)]
-pub enum Function {
+enum FunctionId {
 	/// Staking subsystem: begin staking.
 	StakingStake = 0,
 	/// Staking subsystem: stop staking.
@@ -37,18 +39,99 @@ pub enum Function {
 	GovernanceApprove = 6,
 }
 
-impl Function {
+impl FunctionId {
 	/// Derive `Some` value from a `u8`, or `None` if it's invalid.
-	pub fn from_u8(value: u8) -> Option<Function> {
+	fn from_u8(value: u8) -> Option<FunctionId> {
 		match value {
-			0 => Some(Function::StakingStake),
-			1 => Some(Function::StakingUnstake),
-			2 => Some(Function::StakingTransfer),
-			3 => Some(Function::SessionSetKey),
-			4 => Some(Function::TimestampSet),
-			5 => Some(Function::GovernancePropose),
-			6 => Some(Function::GovernanceApprove),
+			0 => Some(FunctionId::StakingStake),
+			1 => Some(FunctionId::StakingUnstake),
+			2 => Some(FunctionId::StakingTransfer),
+			3 => Some(FunctionId::SessionSetKey),
+			4 => Some(FunctionId::TimestampSet),
+			5 => Some(FunctionId::GovernancePropose),
+			6 => Some(FunctionId::GovernanceApprove),
 			_ => None,
 		}
 	}
 }
+
+/// Functions on the runtime.
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[repr(u8)]
+pub enum Function {
+	/// Staking subsystem: begin staking.
+	StakingStake,
+	/// Staking subsystem: stop staking.
+	StakingUnstake,
+	/// Staking subsystem: transfer stake.
+	StakingTransfer(::AccountId, ::Balance),
+	/// Set temporary session key as a validator.
+	SessionSetKey(::SessionKey),
+	/// Set the timestamp.
+	TimestampSet(::Timestamp),
+	/// Make a proposal for the governance system.
+	GovernancePropose(::proposal::Proposal),
+	/// Approve a proposal for the governance system.
+	GovernanceApprove(::block::Number),
+}
+
+impl Slicable for Function {
+	fn from_slice(value: &mut &[u8]) -> Option<Self> {
+		let id = try_opt!(u8::from_slice(value).and_then(FunctionId::from_u8));
+		Some(match id {
+			FunctionId::StakingStake => Function::StakingStake,
+			FunctionId::StakingUnstake => Function::StakingUnstake,
+			FunctionId::StakingTransfer => Function::StakingTransfer(
+				try_opt!(Slicable::from_slice(value)),
+				try_opt!(Slicable::from_slice(value)),
+			),
+			FunctionId::SessionSetKey =>
+				Function::SessionSetKey(try_opt!(Slicable::from_slice(value))),
+			FunctionId::TimestampSet =>
+				Function::TimestampSet(try_opt!(Slicable::from_slice(value))),
+			FunctionId::GovernancePropose =>
+				Function::GovernancePropose(try_opt!(Slicable::from_slice(value))),
+			FunctionId::GovernanceApprove =>
+				Function::GovernanceApprove(try_opt!(Slicable::from_slice(value))),
+		})
+	}
+
+	fn to_vec(&self) -> Vec<u8> {
+		let mut v = Vec::new();
+		match *self {
+			Function::StakingStake => {
+				(FunctionId::StakingStake as u8).as_slice_then(|s| v.extend(s));
+			}
+			Function::StakingUnstake => {
+				(FunctionId::StakingUnstake as u8).as_slice_then(|s| v.extend(s));
+			}
+			Function::StakingTransfer(ref to, ref amount) => {
+				(FunctionId::StakingTransfer as u8).as_slice_then(|s| v.extend(s));
+				to.as_slice_then(|s| v.extend(s));
+				amount.as_slice_then(|s| v.extend(s));
+			}
+			Function::SessionSetKey(ref data) => {
+				(FunctionId::SessionSetKey as u8).as_slice_then(|s| v.extend(s));
+				data.as_slice_then(|s| v.extend(s));
+			}
+			Function::TimestampSet(ref data) => {
+				(FunctionId::TimestampSet as u8).as_slice_then(|s| v.extend(s));
+				data.as_slice_then(|s| v.extend(s));
+			}
+			Function::GovernancePropose(ref data) => {
+				(FunctionId::GovernancePropose as u8).as_slice_then(|s| v.extend(s));
+				data.as_slice_then(|s| v.extend(s));
+			}
+			Function::GovernanceApprove(ref data) => {
+				(FunctionId::GovernanceApprove as u8).as_slice_then(|s| v.extend(s));
+				data.as_slice_then(|s| v.extend(s));
+			}
+		}
+
+		v
+	}
+
+	fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
+		f(self.to_vec().as_slice())
+	}
+}
diff --git a/substrate/primitives/src/transaction.rs b/substrate/primitives/src/transaction.rs
index eb3e823c582..57b62c878b3 100644
--- a/substrate/primitives/src/transaction.rs
+++ b/substrate/primitives/src/transaction.rs
@@ -17,6 +17,7 @@
 //! Transaction type.
 
 use bytes::{self, Vec};
+use codec::Slicable;
 use runtime_function::Function;
 
 #[cfg(feature = "std")]
@@ -48,6 +49,38 @@ pub struct UncheckedTransaction {
 	pub signature: ::Signature,
 }
 
+impl Slicable for UncheckedTransaction {
+	fn from_slice(value: &mut &[u8]) -> Option<Self> {
+		Some(UncheckedTransaction {
+			transaction: Transaction {
+				signed: try_opt!(Slicable::from_slice(value)),
+				nonce: try_opt!(Slicable::from_slice(value)),
+				function: try_opt!(Slicable::from_slice(value)),
+				input_data: try_opt!(Slicable::from_slice(value)),
+			},
+			signature: try_opt!(Slicable::from_slice(value)),
+		})
+	}
+
+	fn to_vec(&self) -> Vec<u8> {
+		let mut v = Vec::new();
+
+		self.transaction.signed.as_slice_then(|s| v.extend(s));
+		self.transaction.nonce.as_slice_then(|s| v.extend(s));
+		self.transaction.function.as_slice_then(|s| v.extend(s));
+		self.transaction.input_data.as_slice_then(|s| v.extend(s));
+		self.signature.as_slice_then(|s| v.extend(s));
+
+		v
+	}
+
+	fn as_slice_then<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
+		f(self.to_vec().as_slice())
+	}
+}
+
+impl ::codec::NonTrivialSlicable for UncheckedTransaction {}
+
 impl PartialEq for UncheckedTransaction {
 	fn eq(&self, other: &Self) -> bool {
 		self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction
diff --git a/substrate/runtime-codec/src/lib.rs b/substrate/runtime-codec/src/lib.rs
index 05999531568..3e076858beb 100644
--- a/substrate/runtime-codec/src/lib.rs
+++ b/substrate/runtime-codec/src/lib.rs
@@ -22,7 +22,6 @@
 
 mod endiansensitive;
 mod slicable;
-mod streamreader;
 mod joiner;
 mod keyedvec;
 
-- 
GitLab