referrerpolicy=no-referrer-when-downgrade

polkadot_runtime_parachains/paras_inherent/
weights.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot 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// Polkadot 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 Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17//! We use benchmarks to get time weights, for proof_size we manually use the size of the input
18//! data, which will be part of the block. This is because we don't care about the storage proof on
19//! the relay chain, but we do care about the size of the block, by putting the tx in the
20//! proof_size we can use the already existing weight limiting code to limit the used size as well.
21
22use crate::{configuration, inclusion};
23use codec::{Encode, WrapperTypeEncode};
24use polkadot_primitives::{
25	CheckedMultiDisputeStatementSet, MultiDisputeStatementSet, UncheckedSignedAvailabilityBitfield,
26	UncheckedSignedAvailabilityBitfields,
27};
28
29use super::{BackedCandidate, Config, DisputeStatementSet, Weight};
30
31pub trait WeightInfo {
32	/// The weight of processing an empty parachain inherent.
33	fn enter_empty() -> Weight;
34	/// Variant over `v`, the count of dispute statements in a dispute statement set. This gives the
35	/// weight of a single dispute statement set.
36	fn enter_variable_disputes(v: u32) -> Weight;
37	/// The weight of one bitfield.
38	fn enter_bitfields() -> Weight;
39	/// Variant over `v`, the count of validity votes for a backed candidate. This gives the weight
40	/// of a single backed candidate.
41	fn enter_backed_candidates_variable(v: u32) -> Weight;
42	/// The weight of a single backed candidate with a code upgrade.
43	fn enter_backed_candidate_code_upgrade() -> Weight;
44}
45
46pub struct TestWeightInfo;
47// `WeightInfo` impl for unit and integration tests. Based off of the `max_block` weight for the
48//  mock.
49#[cfg(not(feature = "runtime-benchmarks"))]
50impl WeightInfo for TestWeightInfo {
51	fn enter_empty() -> Weight {
52		Weight::zero()
53	}
54	fn enter_variable_disputes(v: u32) -> Weight {
55		// MAX Block Weight should fit 4 disputes
56		Weight::from_parts(80_000 * v as u64 + 80_000, 0)
57	}
58	fn enter_bitfields() -> Weight {
59		// MAX Block Weight should fit 4 backed candidates
60		Weight::from_parts(40_000u64, 0)
61	}
62	fn enter_backed_candidates_variable(v: u32) -> Weight {
63		// MAX Block Weight should fit 4 backed candidates
64		Weight::from_parts(40_000 * v as u64 + 40_000, 0)
65	}
66	fn enter_backed_candidate_code_upgrade() -> Weight {
67		Weight::zero()
68	}
69}
70// To simplify benchmarks running as tests, we set all the weights to 0. `enter` will exit early
71// when if the data causes it to be over weight, but we don't want that to block a benchmark from
72// running as a test.
73#[cfg(feature = "runtime-benchmarks")]
74impl WeightInfo for TestWeightInfo {
75	fn enter_empty() -> Weight {
76		Weight::zero()
77	}
78	fn enter_variable_disputes(_v: u32) -> Weight {
79		Weight::zero()
80	}
81	fn enter_bitfields() -> Weight {
82		Weight::zero()
83	}
84	fn enter_backed_candidates_variable(_v: u32) -> Weight {
85		Weight::zero()
86	}
87	fn enter_backed_candidate_code_upgrade() -> Weight {
88		Weight::zero()
89	}
90}
91
92pub fn paras_inherent_total_weight<T: Config>(
93	backed_candidates: &[BackedCandidate<<T as frame_system::Config>::Hash>],
94	bitfields: &UncheckedSignedAvailabilityBitfields,
95	disputes: &MultiDisputeStatementSet,
96) -> Weight {
97	let weight = backed_candidates_weight::<T>(backed_candidates)
98		.saturating_add(signed_bitfields_weight::<T>(bitfields))
99		.saturating_add(multi_dispute_statement_sets_weight::<T>(disputes))
100		.saturating_add(enact_candidates_max_weight::<T>(bitfields));
101	// Relay chain blocks pre-dispatch weight can be set to any high enough value
102	// but the proof size is irrelevant for the relay chain either way.
103	weight.set_proof_size(u64::MAX)
104}
105
106pub fn multi_dispute_statement_sets_weight<T: Config>(
107	disputes: &MultiDisputeStatementSet,
108) -> Weight {
109	set_proof_size_to_tx_size(
110		disputes
111			.iter()
112			.map(|d| dispute_statement_set_weight::<T, _>(d))
113			.fold(Weight::zero(), |acc_weight, weight| acc_weight.saturating_add(weight)),
114		disputes,
115	)
116}
117
118pub fn checked_multi_dispute_statement_sets_weight<T: Config>(
119	disputes: &CheckedMultiDisputeStatementSet,
120) -> Weight {
121	set_proof_size_to_tx_size(
122		disputes
123			.iter()
124			.map(|d| dispute_statement_set_weight::<T, _>(d))
125			.fold(Weight::zero(), |acc_weight, weight| acc_weight.saturating_add(weight)),
126		disputes,
127	)
128}
129
130/// Get time weights from benchmarks and set proof size to tx size.
131pub fn dispute_statement_set_weight<T, D>(statement_set: D) -> Weight
132where
133	T: Config,
134	D: AsRef<DisputeStatementSet> + WrapperTypeEncode + Sized + Encode,
135{
136	set_proof_size_to_tx_size(
137		<<T as Config>::WeightInfo as WeightInfo>::enter_variable_disputes(
138			statement_set.as_ref().statements.len() as u32,
139		)
140		.saturating_sub(<<T as Config>::WeightInfo as WeightInfo>::enter_empty()),
141		statement_set,
142	)
143}
144
145pub fn signed_bitfields_weight<T: Config>(
146	bitfields: &UncheckedSignedAvailabilityBitfields,
147) -> Weight {
148	set_proof_size_to_tx_size(
149		<<T as Config>::WeightInfo as WeightInfo>::enter_bitfields()
150			.saturating_sub(<<T as Config>::WeightInfo as WeightInfo>::enter_empty())
151			.saturating_mul(bitfields.len() as u64),
152		bitfields,
153	)
154}
155
156pub fn signed_bitfield_weight<T: Config>(bitfield: &UncheckedSignedAvailabilityBitfield) -> Weight {
157	set_proof_size_to_tx_size(
158		<<T as Config>::WeightInfo as WeightInfo>::enter_bitfields()
159			.saturating_sub(<<T as Config>::WeightInfo as WeightInfo>::enter_empty()),
160		bitfield,
161	)
162}
163
164/// Worst case scenario is all candidates have been enacted
165/// and process a maximum number of messages.
166pub fn enact_candidates_max_weight<T: Config>(
167	bitfields: &UncheckedSignedAvailabilityBitfields,
168) -> Weight {
169	let config = configuration::ActiveConfig::<T>::get();
170	let max_ump_msgs = config.max_upward_message_num_per_candidate;
171	let max_hrmp_msgs = config.hrmp_max_message_num_per_candidate;
172	// No bitfields - no enacted candidates
173	let bitfield_size = bitfields.first().map(|b| b.unchecked_payload().0.len()).unwrap_or(0);
174	set_proof_size_to_tx_size(
175		<<T as inclusion::Config>::WeightInfo as inclusion::WeightInfo>::enact_candidate(
176			max_ump_msgs,
177			max_hrmp_msgs,
178			1, // runtime upgrade
179		)
180		.saturating_mul(bitfield_size as u64),
181		bitfields,
182	)
183}
184
185pub fn backed_candidate_weight<T: frame_system::Config + Config>(
186	candidate: &BackedCandidate<T::Hash>,
187) -> Weight {
188	set_proof_size_to_tx_size(
189		if candidate.candidate().commitments.new_validation_code.is_some() {
190			<<T as Config>::WeightInfo as WeightInfo>::enter_backed_candidate_code_upgrade()
191		} else {
192			<<T as Config>::WeightInfo as WeightInfo>::enter_backed_candidates_variable(
193				candidate.validity_votes().len() as u32,
194			)
195		}
196		.saturating_sub(<<T as Config>::WeightInfo as WeightInfo>::enter_empty()),
197		candidate,
198	)
199}
200
201pub fn backed_candidates_weight<T: frame_system::Config + Config>(
202	candidates: &[BackedCandidate<T::Hash>],
203) -> Weight {
204	candidates
205		.iter()
206		.map(|c| backed_candidate_weight::<T>(c))
207		.fold(Weight::zero(), |acc, x| acc.saturating_add(x))
208}
209
210/// Set proof_size component of `Weight` to tx size.
211fn set_proof_size_to_tx_size<Arg: Encode>(weight: Weight, arg: Arg) -> Weight {
212	weight.set_proof_size(arg.encoded_size() as u64)
213}