Kill the light client, CHTs and change tries. (#10080)

* Remove light client, change tries and CHTs

* Update tests

* fmt

* Restore changes_root

* Fixed benches

* Cargo fmt

* fmt

* fmt
This commit is contained in:
Arkadiy Paronyan
2021-11-12 14:15:01 +01:00
committed by GitHub
parent 112b7dac47
commit 4cbbf0cf43
141 changed files with 532 additions and 17807 deletions
@@ -26,59 +26,49 @@ use crate::{
codec::{Decode, Encode, Error, Input},
scale_info::{
build::{Fields, Variants},
meta_type, Path, Type, TypeInfo, TypeParameter,
Path, Type, TypeInfo,
},
ConsensusEngineId,
};
use sp_core::{ChangesTrieConfiguration, RuntimeDebug};
use sp_core::RuntimeDebug;
/// Generic header digest.
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize, parity_util_mem::MallocSizeOf))]
pub struct Digest<Hash> {
pub struct Digest {
/// A list of logs in the digest.
#[cfg_attr(
feature = "std",
serde(bound(serialize = "Hash: codec::Codec", deserialize = "Hash: codec::Codec"))
)]
pub logs: Vec<DigestItem<Hash>>,
pub logs: Vec<DigestItem>,
}
impl<Item> Default for Digest<Item> {
impl Default for Digest {
fn default() -> Self {
Self { logs: Vec::new() }
}
}
impl<Hash> Digest<Hash> {
impl Digest {
/// Get reference to all digest items.
pub fn logs(&self) -> &[DigestItem<Hash>] {
pub fn logs(&self) -> &[DigestItem] {
&self.logs
}
/// Push new digest item.
pub fn push(&mut self, item: DigestItem<Hash>) {
pub fn push(&mut self, item: DigestItem) {
self.logs.push(item);
}
/// Pop a digest item.
pub fn pop(&mut self) -> Option<DigestItem<Hash>> {
pub fn pop(&mut self) -> Option<DigestItem> {
self.logs.pop()
}
/// Get reference to the first digest item that matches the passed predicate.
pub fn log<T: ?Sized, F: Fn(&DigestItem<Hash>) -> Option<&T>>(
&self,
predicate: F,
) -> Option<&T> {
pub fn log<T: ?Sized, F: Fn(&DigestItem) -> Option<&T>>(&self, predicate: F) -> Option<&T> {
self.logs().iter().find_map(predicate)
}
/// Get a conversion of the first digest item that successfully converts using the function.
pub fn convert_first<T, F: Fn(&DigestItem<Hash>) -> Option<T>>(
&self,
predicate: F,
) -> Option<T> {
pub fn convert_first<T, F: Fn(&DigestItem) -> Option<T>>(&self, predicate: F) -> Option<T> {
self.logs().iter().find_map(predicate)
}
}
@@ -87,12 +77,7 @@ impl<Hash> Digest<Hash> {
/// provide opaque access to other items.
#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
#[cfg_attr(feature = "std", derive(parity_util_mem::MallocSizeOf))]
pub enum DigestItem<Hash> {
/// System digest item that contains the root of changes trie at given
/// block. It is created for every block iff runtime supports changes
/// trie creation.
ChangesTrieRoot(Hash),
pub enum DigestItem {
/// A pre-runtime digest.
///
/// These are messages from the consensus engine to the runtime, although
@@ -116,10 +101,6 @@ pub enum DigestItem<Hash> {
/// by runtimes.
Seal(ConsensusEngineId, Vec<u8>),
/// Digest item that contains signal from changes tries manager to the
/// native code.
ChangesTrieSignal(ChangesTrieSignal),
/// Some other thing. Unsupported and experimental.
Other(Vec<u8>),
@@ -132,25 +113,8 @@ pub enum DigestItem<Hash> {
RuntimeEnvironmentUpdated,
}
/// Available changes trie signals.
#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo)]
#[cfg_attr(feature = "std", derive(Debug, parity_util_mem::MallocSizeOf))]
pub enum ChangesTrieSignal {
/// New changes trie configuration is enacted, starting from **next block**.
///
/// The block that emits this signal will contain changes trie (CT) that covers
/// blocks range [BEGIN; current block], where BEGIN is (order matters):
/// - LAST_TOP_LEVEL_DIGEST_BLOCK+1 if top level digest CT has ever been created using current
/// configuration AND the last top level digest CT has been created at block
/// LAST_TOP_LEVEL_DIGEST_BLOCK;
/// - LAST_CONFIGURATION_CHANGE_BLOCK+1 if there has been CT configuration change before and
/// the last configuration change happened at block LAST_CONFIGURATION_CHANGE_BLOCK;
/// - 1 otherwise.
NewConfiguration(Option<ChangesTrieConfiguration>),
}
#[cfg(feature = "std")]
impl<Hash: Encode> serde::Serialize for DigestItem<Hash> {
impl serde::Serialize for DigestItem {
fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
@@ -160,7 +124,7 @@ impl<Hash: Encode> serde::Serialize for DigestItem<Hash> {
}
#[cfg(feature = "std")]
impl<'a, Hash: Decode> serde::Deserialize<'a> for DigestItem<Hash> {
impl<'a> serde::Deserialize<'a> for DigestItem {
fn deserialize<D>(de: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'a>,
@@ -171,75 +135,48 @@ impl<'a, Hash: Decode> serde::Deserialize<'a> for DigestItem<Hash> {
}
}
impl<Hash> TypeInfo for DigestItem<Hash>
where
Hash: TypeInfo + 'static,
{
impl TypeInfo for DigestItem {
type Identity = Self;
fn type_info() -> Type {
Type::builder()
.path(Path::new("DigestItem", module_path!()))
.type_params(vec![TypeParameter::new("Hash", Some(meta_type::<Hash>()))])
.variant(
Variants::new()
.variant("ChangesTrieRoot", |v| {
v.index(DigestItemType::ChangesTrieRoot as u8)
.fields(Fields::unnamed().field(|f| f.ty::<Hash>().type_name("Hash")))
})
.variant("PreRuntime", |v| {
v.index(DigestItemType::PreRuntime as u8).fields(
Fields::unnamed()
.field(|f| {
f.ty::<ConsensusEngineId>().type_name("ConsensusEngineId")
})
.field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
)
})
.variant("Consensus", |v| {
v.index(DigestItemType::Consensus as u8).fields(
Fields::unnamed()
.field(|f| {
f.ty::<ConsensusEngineId>().type_name("ConsensusEngineId")
})
.field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
)
})
.variant("Seal", |v| {
v.index(DigestItemType::Seal as u8).fields(
Fields::unnamed()
.field(|f| {
f.ty::<ConsensusEngineId>().type_name("ConsensusEngineId")
})
.field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
)
})
.variant("ChangesTrieSignal", |v| {
v.index(DigestItemType::ChangesTrieSignal as u8).fields(
Fields::unnamed().field(|f| {
f.ty::<ChangesTrieSignal>().type_name("ChangesTrieSignal")
}),
)
})
.variant("Other", |v| {
v.index(DigestItemType::Other as u8).fields(
Fields::unnamed().field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
)
})
.variant("RuntimeEnvironmentUpdated", |v| {
v.index(DigestItemType::RuntimeEnvironmentUpdated as u8)
.fields(Fields::unit())
}),
)
Type::builder().path(Path::new("DigestItem", module_path!())).variant(
Variants::new()
.variant("PreRuntime", |v| {
v.index(DigestItemType::PreRuntime as u8).fields(
Fields::unnamed()
.field(|f| f.ty::<ConsensusEngineId>().type_name("ConsensusEngineId"))
.field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
)
})
.variant("Consensus", |v| {
v.index(DigestItemType::Consensus as u8).fields(
Fields::unnamed()
.field(|f| f.ty::<ConsensusEngineId>().type_name("ConsensusEngineId"))
.field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
)
})
.variant("Seal", |v| {
v.index(DigestItemType::Seal as u8).fields(
Fields::unnamed()
.field(|f| f.ty::<ConsensusEngineId>().type_name("ConsensusEngineId"))
.field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")),
)
})
.variant("Other", |v| {
v.index(DigestItemType::Other as u8)
.fields(Fields::unnamed().field(|f| f.ty::<Vec<u8>>().type_name("Vec<u8>")))
})
.variant("RuntimeEnvironmentUpdated", |v| {
v.index(DigestItemType::RuntimeEnvironmentUpdated as u8).fields(Fields::unit())
}),
)
}
}
/// A 'referencing view' for digest item. Does not own its contents. Used by
/// final runtime implementations for encoding/decoding its log items.
#[derive(PartialEq, Eq, Clone, RuntimeDebug)]
pub enum DigestItemRef<'a, Hash: 'a> {
/// Reference to `DigestItem::ChangesTrieRoot`.
ChangesTrieRoot(&'a Hash),
pub enum DigestItemRef<'a> {
/// A pre-runtime digest.
///
/// These are messages from the consensus engine to the runtime, although
@@ -254,9 +191,6 @@ pub enum DigestItemRef<'a, Hash: 'a> {
/// Put a Seal on it. This is only used by native code, and is never seen
/// by runtimes.
Seal(&'a ConsensusEngineId, &'a Vec<u8>),
/// Digest item that contains signal from changes tries manager to the
/// native code.
ChangesTrieSignal(&'a ChangesTrieSignal),
/// Any 'non-system' digest item, opaque to the native code.
Other(&'a Vec<u8>),
/// Runtime code or heap pages updated.
@@ -271,11 +205,9 @@ pub enum DigestItemRef<'a, Hash: 'a> {
#[derive(Encode, Decode)]
pub enum DigestItemType {
Other = 0,
ChangesTrieRoot = 2,
Consensus = 4,
Seal = 5,
PreRuntime = 6,
ChangesTrieSignal = 7,
RuntimeEnvironmentUpdated = 8,
}
@@ -293,25 +225,18 @@ pub enum OpaqueDigestItemId<'a> {
Other,
}
impl<Hash> DigestItem<Hash> {
impl DigestItem {
/// Returns a 'referencing view' for this digest item.
pub fn dref(&self) -> DigestItemRef<Hash> {
pub fn dref(&self) -> DigestItemRef {
match *self {
Self::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v),
Self::PreRuntime(ref v, ref s) => DigestItemRef::PreRuntime(v, s),
Self::Consensus(ref v, ref s) => DigestItemRef::Consensus(v, s),
Self::Seal(ref v, ref s) => DigestItemRef::Seal(v, s),
Self::ChangesTrieSignal(ref s) => DigestItemRef::ChangesTrieSignal(s),
Self::Other(ref v) => DigestItemRef::Other(v),
Self::RuntimeEnvironmentUpdated => DigestItemRef::RuntimeEnvironmentUpdated,
}
}
/// Returns `Some` if the entry is the `ChangesTrieRoot` entry.
pub fn as_changes_trie_root(&self) -> Option<&Hash> {
self.dref().as_changes_trie_root()
}
/// Returns `Some` if this entry is the `PreRuntime` entry.
pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &[u8])> {
self.dref().as_pre_runtime()
@@ -327,11 +252,6 @@ impl<Hash> DigestItem<Hash> {
self.dref().as_seal()
}
/// Returns `Some` if the entry is the `ChangesTrieSignal` entry.
pub fn as_changes_trie_signal(&self) -> Option<&ChangesTrieSignal> {
self.dref().as_changes_trie_signal()
}
/// Returns Some if `self` is a `DigestItem::Other`.
pub fn as_other(&self) -> Option<&[u8]> {
self.dref().as_other()
@@ -372,20 +292,19 @@ impl<Hash> DigestItem<Hash> {
}
}
impl<Hash: Encode> Encode for DigestItem<Hash> {
impl Encode for DigestItem {
fn encode(&self) -> Vec<u8> {
self.dref().encode()
}
}
impl<Hash: Encode> codec::EncodeLike for DigestItem<Hash> {}
impl codec::EncodeLike for DigestItem {}
impl<Hash: Decode> Decode for DigestItem<Hash> {
impl Decode for DigestItem {
#[allow(deprecated)]
fn decode<I: Input>(input: &mut I) -> Result<Self, Error> {
let item_type: DigestItemType = Decode::decode(input)?;
match item_type {
DigestItemType::ChangesTrieRoot => Ok(Self::ChangesTrieRoot(Decode::decode(input)?)),
DigestItemType::PreRuntime => {
let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
Ok(Self::PreRuntime(vals.0, vals.1))
@@ -398,23 +317,13 @@ impl<Hash: Decode> Decode for DigestItem<Hash> {
let vals: (ConsensusEngineId, Vec<u8>) = Decode::decode(input)?;
Ok(Self::Seal(vals.0, vals.1))
},
DigestItemType::ChangesTrieSignal =>
Ok(Self::ChangesTrieSignal(Decode::decode(input)?)),
DigestItemType::Other => Ok(Self::Other(Decode::decode(input)?)),
DigestItemType::RuntimeEnvironmentUpdated => Ok(Self::RuntimeEnvironmentUpdated),
}
}
}
impl<'a, Hash> DigestItemRef<'a, Hash> {
/// Cast this digest item into `ChangesTrieRoot`.
pub fn as_changes_trie_root(&self) -> Option<&'a Hash> {
match *self {
Self::ChangesTrieRoot(ref changes_trie_root) => Some(changes_trie_root),
_ => None,
}
}
impl<'a> DigestItemRef<'a> {
/// Cast this digest item into `PreRuntime`
pub fn as_pre_runtime(&self) -> Option<(ConsensusEngineId, &'a [u8])> {
match *self {
@@ -439,14 +348,6 @@ impl<'a, Hash> DigestItemRef<'a, Hash> {
}
}
/// Cast this digest item into `ChangesTrieSignal`.
pub fn as_changes_trie_signal(&self) -> Option<&'a ChangesTrieSignal> {
match *self {
Self::ChangesTrieSignal(ref changes_trie_signal) => Some(changes_trie_signal),
_ => None,
}
}
/// Cast this digest item into `PreRuntime`
pub fn as_other(&self) -> Option<&'a [u8]> {
match *self {
@@ -508,15 +409,11 @@ impl<'a, Hash> DigestItemRef<'a, Hash> {
}
}
impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> {
impl<'a> Encode for DigestItemRef<'a> {
fn encode(&self) -> Vec<u8> {
let mut v = Vec::new();
match *self {
Self::ChangesTrieRoot(changes_trie_root) => {
DigestItemType::ChangesTrieRoot.encode_to(&mut v);
changes_trie_root.encode_to(&mut v);
},
Self::Consensus(val, data) => {
DigestItemType::Consensus.encode_to(&mut v);
(val, data).encode_to(&mut v);
@@ -529,10 +426,6 @@ impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> {
DigestItemType::PreRuntime.encode_to(&mut v);
(val, data).encode_to(&mut v);
},
Self::ChangesTrieSignal(changes_trie_signal) => {
DigestItemType::ChangesTrieSignal.encode_to(&mut v);
changes_trie_signal.encode_to(&mut v);
},
Self::Other(val) => {
DigestItemType::Other.encode_to(&mut v);
val.encode_to(&mut v);
@@ -546,16 +439,7 @@ impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> {
}
}
impl ChangesTrieSignal {
/// Try to cast this signal to NewConfiguration.
pub fn as_new_configuration(&self) -> Option<&Option<ChangesTrieConfiguration>> {
match self {
Self::NewConfiguration(config) => Some(config),
}
}
}
impl<'a, Hash: Encode> codec::EncodeLike for DigestItemRef<'a, Hash> {}
impl<'a> codec::EncodeLike for DigestItemRef<'a> {}
#[cfg(test)]
mod tests {
@@ -564,22 +448,18 @@ mod tests {
#[test]
fn should_serialize_digest() {
let digest = Digest {
logs: vec![
DigestItem::ChangesTrieRoot(4),
DigestItem::Other(vec![1, 2, 3]),
DigestItem::Seal(*b"test", vec![1, 2, 3]),
],
logs: vec![DigestItem::Other(vec![1, 2, 3]), DigestItem::Seal(*b"test", vec![1, 2, 3])],
};
assert_eq!(
serde_json::to_string(&digest).unwrap(),
r#"{"logs":["0x0204000000","0x000c010203","0x05746573740c010203"]}"#
r#"{"logs":["0x000c010203","0x05746573740c010203"]}"#
);
}
#[test]
fn digest_item_type_info() {
let type_info = DigestItem::<u32>::type_info();
let type_info = DigestItem::type_info();
let variants = if let scale_info::TypeDef::Variant(variant) = type_info.type_def() {
variant.variants()
} else {
@@ -589,21 +469,13 @@ mod tests {
// ensure that all variants are covered by manual TypeInfo impl
let check = |digest_item_type: DigestItemType| {
let (variant_name, digest_item) = match digest_item_type {
DigestItemType::Other => ("Other", DigestItem::<u32>::Other(Default::default())),
DigestItemType::ChangesTrieRoot =>
("ChangesTrieRoot", DigestItem::ChangesTrieRoot(Default::default())),
DigestItemType::Other => ("Other", DigestItem::Other(Default::default())),
DigestItemType::Consensus =>
("Consensus", DigestItem::Consensus(Default::default(), Default::default())),
DigestItemType::Seal =>
("Seal", DigestItem::Seal(Default::default(), Default::default())),
DigestItemType::PreRuntime =>
("PreRuntime", DigestItem::PreRuntime(Default::default(), Default::default())),
DigestItemType::ChangesTrieSignal => (
"ChangesTrieSignal",
DigestItem::ChangesTrieSignal(ChangesTrieSignal::NewConfiguration(
Default::default(),
)),
),
DigestItemType::RuntimeEnvironmentUpdated =>
("RuntimeEnvironmentUpdated", DigestItem::RuntimeEnvironmentUpdated),
};
@@ -617,11 +489,9 @@ mod tests {
};
check(DigestItemType::Other);
check(DigestItemType::ChangesTrieRoot);
check(DigestItemType::Consensus);
check(DigestItemType::Seal);
check(DigestItemType::PreRuntime);
check(DigestItemType::ChangesTrieSignal);
check(DigestItemType::RuntimeEnvironmentUpdated);
}
}
@@ -51,7 +51,7 @@ pub struct Header<Number: Copy + Into<U256> + TryFrom<U256>, Hash: HashT> {
/// The merkle root of the extrinsics.
pub extrinsics_root: Hash::Output,
/// A chain-specific digest of data useful for light clients or referencing auxiliary data.
pub digest: Digest<Hash::Output>,
pub digest: Digest,
}
#[cfg(feature = "std")]
@@ -150,11 +150,11 @@ where
self.parent_hash = hash
}
fn digest(&self) -> &Digest<Self::Hash> {
fn digest(&self) -> &Digest {
&self.digest
}
fn digest_mut(&mut self) -> &mut Digest<Self::Hash> {
fn digest_mut(&mut self) -> &mut Digest {
#[cfg(feature = "std")]
log::debug!(target: "header", "Retrieving mutable reference to digest");
&mut self.digest
@@ -165,7 +165,7 @@ where
extrinsics_root: Self::Hash,
state_root: Self::Hash,
parent_hash: Self::Hash,
digest: Digest<Self::Hash>,
digest: Digest,
) -> Self {
Self { number, extrinsics_root, state_root, parent_hash, digest }
}
@@ -235,10 +235,7 @@ mod tests {
state_root: BlakeTwo256::hash(b"3"),
extrinsics_root: BlakeTwo256::hash(b"4"),
digest: crate::generic::Digest {
logs: vec![
crate::generic::DigestItem::ChangesTrieRoot(BlakeTwo256::hash(b"5")),
crate::generic::DigestItem::Other(b"6".to_vec()),
],
logs: vec![crate::generic::DigestItem::Other(b"6".to_vec())],
},
};
@@ -251,9 +248,7 @@ mod tests {
72, 51, 123, 15, 62, 20, 134, 32, 23, 61, 170, 165, 249, 77, 0, 216, 129, 112, 93,
203, 240, 170, 131, 239, 218, 186, 97, 210, 237, 225, 235, 134, 73, 33, 73, 151,
87, 78, 32, 196, 100, 56, 138, 23, 36, 32, 210, 84, 3, 104, 43, 187, 184, 12, 73,
104, 49, 200, 204, 31, 143, 13, 8, 2, 112, 178, 1, 53, 47, 36, 191, 28, 151, 112,
185, 159, 143, 113, 32, 24, 33, 65, 28, 244, 20, 55, 124, 155, 140, 45, 188, 238,
97, 219, 135, 214, 0, 4, 54
104, 49, 200, 204, 31, 143, 13, 4, 0, 4, 54
],
);
assert_eq!(header, Header::<u32, BlakeTwo256>::decode(&mut &header_encoded[..]).unwrap());
@@ -264,10 +259,7 @@ mod tests {
state_root: BlakeTwo256::hash(b"3000"),
extrinsics_root: BlakeTwo256::hash(b"4000"),
digest: crate::generic::Digest {
logs: vec![
crate::generic::DigestItem::Other(b"5000".to_vec()),
crate::generic::DigestItem::ChangesTrieRoot(BlakeTwo256::hash(b"6000")),
],
logs: vec![crate::generic::DigestItem::Other(b"5000".to_vec())],
},
};
@@ -280,9 +272,7 @@ mod tests {
47, 12, 107, 88, 153, 146, 55, 21, 226, 186, 110, 48, 167, 187, 67, 183, 228, 232,
118, 136, 30, 254, 11, 87, 48, 112, 7, 97, 31, 82, 146, 110, 96, 87, 152, 68, 98,
162, 227, 222, 78, 14, 244, 194, 120, 154, 112, 97, 222, 144, 174, 101, 220, 44,
111, 126, 54, 34, 155, 220, 253, 124, 8, 0, 16, 53, 48, 48, 48, 2, 42, 105, 109,
150, 206, 223, 24, 44, 164, 77, 27, 137, 177, 220, 25, 170, 140, 35, 156, 246, 233,
112, 26, 23, 192, 61, 226, 14, 84, 219, 144, 252
111, 126, 54, 34, 155, 220, 253, 124, 4, 0, 16, 53, 48, 48, 48
],
);
assert_eq!(header, Header::<u32, BlakeTwo256>::decode(&mut &header_encoded[..]).unwrap());
@@ -31,7 +31,7 @@ mod unchecked_extrinsic;
pub use self::{
block::{Block, BlockId, SignedBlock},
checked_extrinsic::CheckedExtrinsic,
digest::{ChangesTrieSignal, Digest, DigestItem, DigestItemRef, OpaqueDigestItemId},
digest::{Digest, DigestItem, DigestItemRef, OpaqueDigestItemId},
era::{Era, Phase},
header::Header,
unchecked_extrinsic::{SignedPayload, UncheckedExtrinsic},
@@ -19,29 +19,26 @@
use super::DigestItem;
use crate::codec::{Decode, Encode};
use sp_core::H256;
#[test]
fn system_digest_item_encoding() {
let item = DigestItem::ChangesTrieRoot::<H256>(H256::default());
let item = DigestItem::Consensus([1, 2, 3, 4], vec![5, 6, 7, 8]);
let encoded = item.encode();
assert_eq!(
encoded,
vec![
// type = DigestItemType::ChangesTrieRoot
2, // trie root
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,
4, // type = DigestItemType::Consensus
1, 2, 3, 4, 16, 5, 6, 7, 8,
]
);
let decoded: DigestItem<H256> = Decode::decode(&mut &encoded[..]).unwrap();
let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap();
assert_eq!(item, decoded);
}
#[test]
fn non_system_digest_item_encoding() {
let item = DigestItem::Other::<H256>(vec![10, 20, 30]);
let item = DigestItem::Other(vec![10, 20, 30]);
let encoded = item.encode();
assert_eq!(
encoded,
@@ -53,6 +50,6 @@ fn non_system_digest_item_encoding() {
]
);
let decoded: DigestItem<H256> = Decode::decode(&mut &encoded[..]).unwrap();
let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap();
assert_eq!(item, decoded);
}