referrerpolicy=no-referrer-when-downgrade

pallet_bridge_grandpa/
storage_types.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Parity Bridges Common.
3
4// Parity Bridges Common is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Bridges Common is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Wrappers for public types that are implementing `MaxEncodedLen`
18
19use crate::{Config, Error};
20
21use bp_header_chain::{AuthoritySet, ChainWithGrandpa};
22use codec::{Decode, Encode, MaxEncodedLen};
23use frame_support::{traits::Get, BoundedVec, CloneNoBound, DebugNoBound};
24use scale_info::TypeInfo;
25use sp_consensus_grandpa::{AuthorityId, AuthorityList, AuthorityWeight, SetId};
26use sp_std::marker::PhantomData;
27
28/// A bounded list of Grandpa authorities with associated weights.
29pub type StoredAuthorityList<MaxBridgedAuthorities> =
30	BoundedVec<(AuthorityId, AuthorityWeight), MaxBridgedAuthorities>;
31
32/// Adapter for using `T::BridgedChain::MAX_BRIDGED_AUTHORITIES` in `BoundedVec`.
33pub struct StoredAuthorityListLimit<T, I>(PhantomData<(T, I)>);
34
35impl<T: Config<I>, I: 'static> Get<u32> for StoredAuthorityListLimit<T, I> {
36	fn get() -> u32 {
37		T::BridgedChain::MAX_AUTHORITIES_COUNT
38	}
39}
40
41/// A bounded GRANDPA Authority List and ID.
42#[derive(CloneNoBound, Decode, Encode, Eq, TypeInfo, MaxEncodedLen, DebugNoBound)]
43#[scale_info(skip_type_params(T, I))]
44pub struct StoredAuthoritySet<T: Config<I>, I: 'static> {
45	/// List of GRANDPA authorities for the current round.
46	pub authorities: StoredAuthorityList<StoredAuthorityListLimit<T, I>>,
47	/// Monotonic identifier of the current GRANDPA authority set.
48	pub set_id: SetId,
49}
50
51impl<T: Config<I>, I: 'static> StoredAuthoritySet<T, I> {
52	/// Try to create a new bounded GRANDPA Authority Set from unbounded list.
53	///
54	/// Returns error if number of authorities in the provided list is too large.
55	pub fn try_new(authorities: AuthorityList, set_id: SetId) -> Result<Self, Error<T, I>> {
56		Ok(Self {
57			authorities: TryFrom::try_from(authorities)
58				.map_err(|_| Error::TooManyAuthoritiesInSet)?,
59			set_id,
60		})
61	}
62
63	/// Returns number of bytes that may be subtracted from the PoV component of
64	/// `submit_finality_proof` call, because the actual authorities set is smaller than the maximal
65	/// configured.
66	///
67	/// Maximal authorities set size is configured by the `MaxBridgedAuthorities` constant from
68	/// the pallet configuration. The PoV of the call includes the size of maximal authorities
69	/// count. If the actual size is smaller, we may subtract extra bytes from this component.
70	pub fn unused_proof_size(&self) -> u64 {
71		// we can only safely estimate bytes that are occupied by the authority data itself. We have
72		// no means here to compute PoV bytes, occupied by extra trie nodes or extra bytes in the
73		// whole set encoding
74		let single_authority_max_encoded_len =
75			<(AuthorityId, AuthorityWeight)>::max_encoded_len() as u64;
76		let extra_authorities =
77			T::BridgedChain::MAX_AUTHORITIES_COUNT.saturating_sub(self.authorities.len() as _);
78		single_authority_max_encoded_len.saturating_mul(extra_authorities as u64)
79	}
80}
81
82impl<T: Config<I>, I: 'static> PartialEq for StoredAuthoritySet<T, I> {
83	fn eq(&self, other: &Self) -> bool {
84		self.set_id == other.set_id && self.authorities == other.authorities
85	}
86}
87
88impl<T: Config<I>, I: 'static> Default for StoredAuthoritySet<T, I> {
89	fn default() -> Self {
90		StoredAuthoritySet { authorities: BoundedVec::default(), set_id: 0 }
91	}
92}
93
94impl<T: Config<I>, I: 'static> From<StoredAuthoritySet<T, I>> for AuthoritySet {
95	fn from(t: StoredAuthoritySet<T, I>) -> Self {
96		AuthoritySet { authorities: t.authorities.into(), set_id: t.set_id }
97	}
98}
99
100#[cfg(test)]
101mod tests {
102	use crate::mock::{TestRuntime, MAX_BRIDGED_AUTHORITIES};
103	use bp_test_utils::authority_list;
104
105	type StoredAuthoritySet = super::StoredAuthoritySet<TestRuntime, ()>;
106
107	#[test]
108	fn unused_proof_size_works() {
109		let authority_entry = authority_list().pop().unwrap();
110
111		// when we have exactly `MaxBridgedAuthorities` authorities
112		assert_eq!(
113			StoredAuthoritySet::try_new(
114				vec![authority_entry.clone(); MAX_BRIDGED_AUTHORITIES as usize],
115				0,
116			)
117			.unwrap()
118			.unused_proof_size(),
119			0,
120		);
121
122		// when we have less than `MaxBridgedAuthorities` authorities
123		assert_eq!(
124			StoredAuthoritySet::try_new(
125				vec![authority_entry; MAX_BRIDGED_AUTHORITIES as usize - 1],
126				0,
127			)
128			.unwrap()
129			.unused_proof_size(),
130			40,
131		);
132
133		// and we can't have more than `MaxBridgedAuthorities` authorities in the bounded vec, so
134		// no test for this case
135	}
136}