Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 56dc6d1

Browse files
Wizdave97acatangiu
andauthored
Refactor Beefy MMR and remove parachain specific implementations (#10664)
* refactor beefy mmr * use plain vector of bytes for leaf extra * update comment * update comments * remove unused vars * Use sp_std::vec::Vec Co-authored-by: Adrian Catangiu <[email protected]> * make extra data generic * fix tests * refactor beefy-mmr * Update frame/beefy-mmr/src/lib.rs * minor fix * fmt * Update frame/beefy-mmr/src/lib.rs Co-authored-by: Adrian Catangiu <[email protected]>
1 parent 2287cd8 commit 56dc6d1

File tree

4 files changed

+52
-65
lines changed

4 files changed

+52
-65
lines changed

frame/beefy-mmr/src/lib.rs

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,16 @@
2929
//! The MMR leaf contains:
3030
//! 1. Block number and parent block hash.
3131
//! 2. Merkle Tree Root Hash of next BEEFY validator set.
32-
//! 3. Merkle Tree Root Hash of current parachain heads state.
32+
//! 3. Arbitrary extra leaf data to be used by downstream pallets to include custom data.
3333
//!
3434
//! and thanks to versioning can be easily updated in the future.
3535
36-
use sp_runtime::traits::{Convert, Hash};
36+
use sp_runtime::traits::{Convert, Hash, Member};
3737
use sp_std::prelude::*;
3838

39-
use beefy_primitives::mmr::{BeefyNextAuthoritySet, MmrLeaf, MmrLeafVersion};
39+
use beefy_primitives::mmr::{BeefyDataProvider, BeefyNextAuthoritySet, MmrLeaf, MmrLeafVersion};
4040
use pallet_mmr::primitives::LeafDataProvider;
4141

42-
use codec::Encode;
4342
use frame_support::traits::Get;
4443

4544
pub use pallet::*;
@@ -90,23 +89,6 @@ impl Convert<beefy_primitives::crypto::AuthorityId, Vec<u8>> for BeefyEcdsaToEth
9089
}
9190

9291
type MerkleRootOf<T> = <T as pallet_mmr::Config>::Hash;
93-
type ParaId = u32;
94-
type ParaHead = Vec<u8>;
95-
96-
/// A type that is able to return current list of parachain heads that end up in the MMR leaf.
97-
pub trait ParachainHeadsProvider {
98-
/// Return a list of tuples containing a `ParaId` and Parachain Header data (ParaHead).
99-
///
100-
/// The returned data does not have to be sorted.
101-
fn parachain_heads() -> Vec<(ParaId, ParaHead)>;
102-
}
103-
104-
/// A default implementation for runtimes without parachains.
105-
impl ParachainHeadsProvider for () {
106-
fn parachain_heads() -> Vec<(ParaId, ParaHead)> {
107-
Default::default()
108-
}
109-
}
11092

11193
#[frame_support::pallet]
11294
pub mod pallet {
@@ -138,12 +120,11 @@ pub mod pallet {
138120
/// efficiency reasons.
139121
type BeefyAuthorityToMerkleLeaf: Convert<<Self as pallet_beefy::Config>::BeefyId, Vec<u8>>;
140122

141-
/// Retrieve a list of current parachain heads.
142-
///
143-
/// The trait is implemented for `paras` module, but since not all chains might have
144-
/// parachains, and we want to keep the MMR leaf structure uniform, it's possible to use
145-
/// `()` as well to simply put dummy data to the leaf.
146-
type ParachainHeads: ParachainHeadsProvider;
123+
/// The type expected for the leaf extra data
124+
type LeafExtra: Member + codec::FullCodec;
125+
126+
/// Retrieve arbitrary data that should be added to the mmr leaf
127+
type BeefyDataProvider: BeefyDataProvider<Self::LeafExtra>;
147128
}
148129

149130
/// Details of next BEEFY authority set.
@@ -163,13 +144,14 @@ where
163144
<T as frame_system::Config>::BlockNumber,
164145
<T as frame_system::Config>::Hash,
165146
MerkleRootOf<T>,
147+
T::LeafExtra,
166148
>;
167149

168150
fn leaf_data() -> Self::LeafData {
169151
MmrLeaf {
170152
version: T::LeafVersion::get(),
171153
parent_number_and_hash: frame_system::Pallet::<T>::leaf_data(),
172-
parachain_heads: Pallet::<T>::parachain_heads_merkle_root(),
154+
leaf_extra: T::BeefyDataProvider::extra_data(),
173155
beefy_next_authority_set: Pallet::<T>::update_beefy_next_authority_set(),
174156
}
175157
}
@@ -188,23 +170,6 @@ impl<T: Config> Pallet<T>
188170
where
189171
MerkleRootOf<T>: From<beefy_merkle_tree::Hash> + Into<beefy_merkle_tree::Hash>,
190172
{
191-
/// Returns latest root hash of a merkle tree constructed from all active parachain headers.
192-
///
193-
/// The leafs are sorted by `ParaId` to allow more efficient lookups and non-existence proofs.
194-
///
195-
/// NOTE this does not include parathreads - only parachains are part of the merkle tree.
196-
///
197-
/// NOTE This is an initial and inefficient implementation, which re-constructs
198-
/// the merkle tree every block. Instead we should update the merkle root in
199-
/// [Self::on_initialize] call of this pallet and update the merkle tree efficiently (use
200-
/// on-chain storage to persist inner nodes).
201-
fn parachain_heads_merkle_root() -> MerkleRootOf<T> {
202-
let mut para_heads = T::ParachainHeads::parachain_heads();
203-
para_heads.sort();
204-
let para_heads = para_heads.into_iter().map(|pair| pair.encode());
205-
beefy_merkle_tree::merkle_root::<Self, _, _>(para_heads).into()
206-
}
207-
208173
/// Returns details of the next BEEFY authority set.
209174
///
210175
/// Details contain authority set id, authority set length and a merkle root,

frame/beefy-mmr/src/mock.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use std::vec;
1919

2020
use beefy_primitives::mmr::MmrLeafVersion;
21+
use codec::Encode;
2122
use frame_support::{
2223
construct_runtime, parameter_types,
2324
sp_io::TestExternalities,
@@ -34,7 +35,9 @@ use sp_runtime::{
3435

3536
use crate as pallet_beefy_mmr;
3637

37-
pub use beefy_primitives::{crypto::AuthorityId as BeefyId, ConsensusLog, BEEFY_ENGINE_ID};
38+
pub use beefy_primitives::{
39+
crypto::AuthorityId as BeefyId, mmr::BeefyDataProvider, ConsensusLog, BEEFY_ENGINE_ID,
40+
};
3841

3942
impl_opaque_keys! {
4043
pub struct MockSessionKeys {
@@ -102,6 +105,7 @@ pub type MmrLeaf = beefy_primitives::mmr::MmrLeaf<
102105
<Test as frame_system::Config>::BlockNumber,
103106
<Test as frame_system::Config>::Hash,
104107
<Test as pallet_mmr::Config>::Hash,
108+
Vec<u8>,
105109
>;
106110

107111
impl pallet_mmr::Config for Test {
@@ -131,13 +135,20 @@ impl pallet_beefy_mmr::Config for Test {
131135

132136
type BeefyAuthorityToMerkleLeaf = pallet_beefy_mmr::BeefyEcdsaToEthereum;
133137

134-
type ParachainHeads = DummyParaHeads;
138+
type LeafExtra = Vec<u8>;
139+
140+
type BeefyDataProvider = DummyDataProvider;
135141
}
136142

137-
pub struct DummyParaHeads;
138-
impl pallet_beefy_mmr::ParachainHeadsProvider for DummyParaHeads {
139-
fn parachain_heads() -> Vec<(pallet_beefy_mmr::ParaId, pallet_beefy_mmr::ParaHead)> {
140-
vec![(15, vec![1, 2, 3]), (5, vec![4, 5, 6])]
143+
pub struct DummyDataProvider;
144+
impl BeefyDataProvider<Vec<u8>> for DummyDataProvider {
145+
fn extra_data() -> Vec<u8> {
146+
let mut col = vec![(15, vec![1, 2, 3]), (5, vec![4, 5, 6])];
147+
col.sort();
148+
beefy_merkle_tree::merkle_root::<crate::Pallet<Test>, _, _>(
149+
col.into_iter().map(|pair| pair.encode()),
150+
)
151+
.to_vec()
141152
}
142153
}
143154

frame/beefy-mmr/src/tests.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ fn should_contain_mmr_digest() {
7171
assert_eq!(
7272
System::digest().logs,
7373
vec![beefy_log(ConsensusLog::MmrRoot(
74-
hex!("969d516e5279540ef38e4a710fb0645cab4c3b01e528be7285b85ec9c5fb55c8").into()
74+
hex!("fa0275b19b2565089f7e2377ee73b9050e8d53bce108ef722a3251fd9d371d4b").into()
7575
))]
7676
);
7777

@@ -82,13 +82,13 @@ fn should_contain_mmr_digest() {
8282
System::digest().logs,
8383
vec![
8484
beefy_log(ConsensusLog::MmrRoot(
85-
hex!("969d516e5279540ef38e4a710fb0645cab4c3b01e528be7285b85ec9c5fb55c8").into()
85+
hex!("fa0275b19b2565089f7e2377ee73b9050e8d53bce108ef722a3251fd9d371d4b").into()
8686
)),
8787
beefy_log(ConsensusLog::AuthoritiesChange(
8888
ValidatorSet::new(vec![mock_beefy_id(3), mock_beefy_id(4),], 1,).unwrap()
8989
)),
9090
beefy_log(ConsensusLog::MmrRoot(
91-
hex!("8c42b7b040d262f7f2e26abeb61ab0c3c448f60c7f2f19e6ca0035d9bb3ae7e2").into()
91+
hex!("85554fa7d4e863cce3cdce668c1ae82c0174ad37f8d1399284018bec9f9971c3").into()
9292
)),
9393
]
9494
);
@@ -114,10 +114,8 @@ fn should_contain_valid_leaf_data() {
114114
root: hex!("176e73f1bf656478b728e28dd1a7733c98621b8acf830bff585949763dca7a96")
115115
.into(),
116116
},
117-
parachain_heads: hex!(
118-
"ed893c8f8cc87195a5d4d2805b011506322036bcace79642aa3e94ab431e442e"
119-
)
120-
.into(),
117+
leaf_extra: hex!("55b8e9e1cc9f0db7776fac0ca66318ef8acfb8ec26db11e373120583e07ee648")
118+
.to_vec(),
121119
}
122120
);
123121

@@ -138,10 +136,8 @@ fn should_contain_valid_leaf_data() {
138136
root: hex!("9c6b2c1b0d0b25a008e6c882cc7b415f309965c72ad2b944ac0931048ca31cd5")
139137
.into(),
140138
},
141-
parachain_heads: hex!(
142-
"ed893c8f8cc87195a5d4d2805b011506322036bcace79642aa3e94ab431e442e"
143-
)
144-
.into(),
139+
leaf_extra: hex!("55b8e9e1cc9f0db7776fac0ca66318ef8acfb8ec26db11e373120583e07ee648")
140+
.to_vec()
145141
}
146142
);
147143
}

primitives/beefy/src/mmr.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,26 @@
2626
//! but we imagine they will be useful for other chains that either want to bridge with Polkadot
2727
//! or are completely standalone, but heavily inspired by Polkadot.
2828
29+
use crate::Vec;
2930
use codec::{Decode, Encode, MaxEncodedLen};
3031
use scale_info::TypeInfo;
3132

33+
/// A provider for extra data that gets added to the Mmr leaf
34+
pub trait BeefyDataProvider<ExtraData> {
35+
/// Return a vector of bytes, ideally should be a merkle root hash
36+
fn extra_data() -> ExtraData;
37+
}
38+
39+
/// A default implementation for runtimes.
40+
impl BeefyDataProvider<Vec<u8>> for () {
41+
fn extra_data() -> Vec<u8> {
42+
Vec::new()
43+
}
44+
}
45+
3246
/// A standard leaf that gets added every block to the MMR constructed by Substrate's `pallet_mmr`.
3347
#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
34-
pub struct MmrLeaf<BlockNumber, Hash, MerkleRoot> {
48+
pub struct MmrLeaf<BlockNumber, Hash, MerkleRoot, ExtraData> {
3549
/// Version of the leaf format.
3650
///
3751
/// Can be used to enable future format migrations and compatibility.
@@ -41,8 +55,9 @@ pub struct MmrLeaf<BlockNumber, Hash, MerkleRoot> {
4155
pub parent_number_and_hash: (BlockNumber, Hash),
4256
/// A merkle root of the next BEEFY authority set.
4357
pub beefy_next_authority_set: BeefyNextAuthoritySet<MerkleRoot>,
44-
/// A merkle root of all registered parachain heads.
45-
pub parachain_heads: MerkleRoot,
58+
/// Arbitrary extra leaf data to be used by downstream pallets to include custom data in the
59+
/// [`MmrLeaf`]
60+
pub leaf_extra: ExtraData,
4661
}
4762

4863
/// A MMR leaf versioning scheme.

0 commit comments

Comments
 (0)