Skip to content

Commit

Permalink
Add MerkleMountainRangeRoot digest item in header (#1)
Browse files Browse the repository at this point in the history
* add new merkle mountain range digest item for header

* introduce merkle mountain range lib

* add mmr root to digest in System::finalize(), waiting mmr crate supporting T:Hash to make compile pass

* upgrade to use mmr lib from ckb

* move mmr logic to seprate darwinia pallet

* remove useless lines

* add tests for header mmr digest

* update test comment
  • Loading branch information
hackfisher authored and yanganto committed Apr 1, 2020
1 parent d477017 commit be3ca0c
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 2 deletions.
36 changes: 34 additions & 2 deletions primitives/runtime/src/generic/digest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ pub enum DigestItem<Hash> {
/// native code.
ChangesTrieSignal(ChangesTrieSignal),

/// Blockchain history digest item that contains the merkle mountain range root
/// at given block. It is created for providing super light client a commitment
/// of all the previous blocks.
MerkleMountainRangeRoot(Hash),

/// Some other thing. Unsupported and experimental.
Other(Vec<u8>),
}
Expand Down Expand Up @@ -173,6 +178,10 @@ pub enum DigestItemRef<'a, Hash: 'a> {
/// Digest item that contains signal from changes tries manager to the
/// native code.
ChangesTrieSignal(&'a ChangesTrieSignal),

/// Reference to `DigestItem::MerkleMountainRangeRoot`.
MerkleMountainRangeRoot(&'a Hash),

/// Any 'non-system' digest item, opaque to the native code.
Other(&'a Vec<u8>),
}
Expand All @@ -190,6 +199,7 @@ pub enum DigestItemType {
Seal = 5,
PreRuntime = 6,
ChangesTrieSignal = 7,
MerkleMountainRangeRoot = 18,
}

/// Type of a digest item that contains raw data; this also names the consensus engine ID where
Expand All @@ -215,6 +225,7 @@ impl<Hash> DigestItem<Hash> {
DigestItem::Consensus(ref v, ref s) => DigestItemRef::Consensus(v, s),
DigestItem::Seal(ref v, ref s) => DigestItemRef::Seal(v, s),
DigestItem::ChangesTrieSignal(ref s) => DigestItemRef::ChangesTrieSignal(s),
DigestItem::MerkleMountainRangeRoot(ref v) => DigestItemRef::MerkleMountainRangeRoot(v),
DigestItem::Other(ref v) => DigestItemRef::Other(v),
}
}
Expand Down Expand Up @@ -244,6 +255,11 @@ impl<Hash> DigestItem<Hash> {
self.dref().as_changes_trie_signal()
}

/// Returns `Some` if the entry is the `MerkleMountainRangeRoot` entry.
pub fn as_merkle_mountain_range_root(&self) -> Option<&Hash> {
self.dref().as_merkle_mountain_range_root()
}

/// Returns Some if `self` is a `DigestItem::Other`.
pub fn as_other(&self) -> Option<&[u8]> {
match *self {
Expand Down Expand Up @@ -295,6 +311,9 @@ impl<Hash: Decode> Decode for DigestItem<Hash> {
DigestItemType::ChangesTrieSignal => Ok(DigestItem::ChangesTrieSignal(
Decode::decode(input)?,
)),
DigestItemType::MerkleMountainRangeRoot => Ok(DigestItem::MerkleMountainRangeRoot(
Decode::decode(input)?,
)),
DigestItemType::Other => Ok(DigestItem::Other(
Decode::decode(input)?,
)),
Expand Down Expand Up @@ -343,6 +362,14 @@ impl<'a, Hash> DigestItemRef<'a, Hash> {
}
}

/// Cast this digest item into `MerkleMountainRangeRoot`.
pub fn as_merkle_mountain_range_root(&self) -> Option<&'a Hash> {
match *self {
DigestItemRef::MerkleMountainRangeRoot(ref merkle_mountain_range_root) => Some(merkle_mountain_range_root),
_ => None,
}
}

/// Cast this digest item into `PreRuntime`
pub fn as_other(&self) -> Option<&'a [u8]> {
match *self {
Expand Down Expand Up @@ -396,6 +423,10 @@ impl<'a, Hash: Encode> Encode for DigestItemRef<'a, Hash> {
DigestItemType::ChangesTrieSignal.encode_to(&mut v);
changes_trie_signal.encode_to(&mut v);
},
DigestItemRef::MerkleMountainRangeRoot(merkle_mountain_range_root) => {
DigestItemType::MerkleMountainRangeRoot.encode_to(&mut v);
merkle_mountain_range_root.encode_to(&mut v);
},
DigestItemRef::Other(val) => {
DigestItemType::Other.encode_to(&mut v);
val.encode_to(&mut v);
Expand Down Expand Up @@ -427,13 +458,14 @@ mod tests {
logs: vec![
DigestItem::ChangesTrieRoot(4),
DigestItem::Other(vec![1, 2, 3]),
DigestItem::Seal(*b"test", vec![1, 2, 3])
DigestItem::Seal(*b"test", vec![1, 2, 3]),
DigestItem::MerkleMountainRangeRoot(5),
],
};

assert_eq!(
::serde_json::to_string(&digest).unwrap(),
r#"{"logs":["0x0204000000","0x000c010203","0x05746573740c010203"]}"#
r#"{"logs":["0x0204000000","0x000c010203","0x05746573740c010203","0x1205000000"]}"#
);
}
}
22 changes: 22 additions & 0 deletions primitives/runtime/src/generic/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,25 @@ fn non_system_digest_item_encoding() {
let decoded: DigestItem<H256> = Decode::decode(&mut &encoded[..]).unwrap();
assert_eq!(item, decoded);
}

#[test]
fn non_system_mmr_digest_item_encoding() {
let item = DigestItem::MerkleMountainRangeRoot::<H256>(H256::default());
let encoded = item.encode();
assert_eq!(encoded, vec![
// type = DigestItemType::MerkleMountainRangeRoot
18,
// 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,
]);

let decoded: DigestItem<H256> = Decode::decode(&mut &encoded[..]).unwrap();
assert_eq!(item, decoded);
}

0 comments on commit be3ca0c

Please sign in to comment.