referrerpolicy=no-referrer-when-downgrade

bridge_hub_test_utils/test_data/
from_grandpa_chain.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Cumulus.
3// SPDX-License-Identifier: Apache-2.0
4
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// 	http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17//! Generating test data for bridges with remote GRANDPA chains.
18
19use crate::test_data::{prepare_inbound_xcm, XcmAsPlainPayload};
20
21use bp_messages::{
22	source_chain::FromBridgedChainMessagesDeliveryProof,
23	target_chain::FromBridgedChainMessagesProof, ChainWithMessages, LaneState, MessageNonce,
24	UnrewardedRelayersState,
25};
26use bp_runtime::{AccountIdOf, BlockNumberOf, Chain, HeaderOf, UnverifiedStorageProofParams};
27use bp_test_utils::make_default_justification;
28use codec::Encode;
29use pallet_bridge_grandpa::{BridgedChain, BridgedHeader};
30use sp_runtime::traits::Header as HeaderT;
31use xcm::latest::prelude::*;
32
33use crate::test_cases::helpers::InboundRelayerId;
34use bp_header_chain::{justification::GrandpaJustification, ChainWithGrandpa};
35use bp_messages::{DeliveredMessages, InboundLaneData, UnrewardedRelayer};
36use bp_runtime::HashOf;
37use pallet_bridge_messages::{
38	messages_generation::{
39		encode_all_messages, encode_lane_data, prepare_message_delivery_storage_proof,
40		prepare_messages_storage_proof,
41	},
42	BridgedChainOf, LaneIdOf,
43};
44use sp_runtime::DigestItem;
45
46/// Prepare a batch call with bridged GRANDPA finality and message proof.
47pub fn make_complex_relayer_delivery_batch<Runtime, GPI, MPI>(
48	bridged_header: BridgedHeader<Runtime, GPI>,
49	bridged_justification: GrandpaJustification<BridgedHeader<Runtime, GPI>>,
50	message_proof: FromBridgedChainMessagesProof<
51		HashOf<BridgedChain<Runtime, GPI>>,
52		LaneIdOf<Runtime, MPI>,
53	>,
54	relayer_id_at_bridged_chain: InboundRelayerId<Runtime, MPI>,
55) -> pallet_utility::Call<Runtime>
56where
57	Runtime: pallet_bridge_grandpa::Config<GPI>
58		+ pallet_bridge_messages::Config<MPI, InboundPayload = XcmAsPlainPayload>
59		+ pallet_utility::Config,
60	GPI: 'static,
61	MPI: 'static,
62	<Runtime as pallet_utility::Config>::RuntimeCall: From<pallet_bridge_grandpa::Call<Runtime, GPI>>
63		+ From<pallet_bridge_messages::Call<Runtime, MPI>>,
64	BridgedChainOf<Runtime, MPI>: Chain<Hash = HashOf<BridgedChain<Runtime, GPI>>>,
65{
66	let submit_grandpa = pallet_bridge_grandpa::Call::<Runtime, GPI>::submit_finality_proof {
67		finality_target: Box::new(bridged_header),
68		justification: bridged_justification,
69	};
70	let submit_message = pallet_bridge_messages::Call::<Runtime, MPI>::receive_messages_proof {
71		relayer_id_at_bridged_chain,
72		proof: Box::new(message_proof),
73		messages_count: 1,
74		dispatch_weight: Weight::from_parts(1000000000, 0),
75	};
76	pallet_utility::Call::<Runtime>::batch_all {
77		calls: vec![submit_grandpa.into(), submit_message.into()],
78	}
79}
80
81/// Prepare a batch call with bridged GRANDPA finality and message delivery proof.
82pub fn make_complex_relayer_confirmation_batch<Runtime, GPI, MPI>(
83	bridged_header: BridgedHeader<Runtime, GPI>,
84	bridged_justification: GrandpaJustification<BridgedHeader<Runtime, GPI>>,
85	message_delivery_proof: FromBridgedChainMessagesDeliveryProof<
86		HashOf<BridgedChain<Runtime, GPI>>,
87		LaneIdOf<Runtime, MPI>,
88	>,
89	relayers_state: UnrewardedRelayersState,
90) -> pallet_utility::Call<Runtime>
91where
92	Runtime: pallet_bridge_grandpa::Config<GPI>
93		+ pallet_bridge_messages::Config<MPI, OutboundPayload = XcmAsPlainPayload>
94		+ pallet_utility::Config,
95	GPI: 'static,
96	MPI: 'static,
97	<Runtime as pallet_utility::Config>::RuntimeCall: From<pallet_bridge_grandpa::Call<Runtime, GPI>>
98		+ From<pallet_bridge_messages::Call<Runtime, MPI>>,
99	BridgedChainOf<Runtime, MPI>: Chain<Hash = HashOf<BridgedChain<Runtime, GPI>>>,
100{
101	let submit_grandpa = pallet_bridge_grandpa::Call::<Runtime, GPI>::submit_finality_proof {
102		finality_target: Box::new(bridged_header),
103		justification: bridged_justification,
104	};
105	let submit_message_delivery_proof =
106		pallet_bridge_messages::Call::<Runtime, MPI>::receive_messages_delivery_proof {
107			proof: message_delivery_proof,
108			relayers_state,
109		};
110	pallet_utility::Call::<Runtime>::batch_all {
111		calls: vec![submit_grandpa.into(), submit_message_delivery_proof.into()],
112	}
113}
114
115/// Prepare a call with message proof.
116pub fn make_standalone_relayer_delivery_call<Runtime, GPI, MPI>(
117	message_proof: FromBridgedChainMessagesProof<
118		HashOf<BridgedChain<Runtime, GPI>>,
119		LaneIdOf<Runtime, MPI>,
120	>,
121	relayer_id_at_bridged_chain: InboundRelayerId<Runtime, MPI>,
122) -> Runtime::RuntimeCall
123where
124	Runtime: pallet_bridge_grandpa::Config<GPI>
125		+ pallet_bridge_messages::Config<MPI, InboundPayload = XcmAsPlainPayload>,
126	MPI: 'static,
127	Runtime::RuntimeCall: From<pallet_bridge_messages::Call<Runtime, MPI>>,
128	BridgedChainOf<Runtime, MPI>: Chain<Hash = HashOf<BridgedChain<Runtime, GPI>>>,
129{
130	pallet_bridge_messages::Call::<Runtime, MPI>::receive_messages_proof {
131		relayer_id_at_bridged_chain,
132		proof: Box::new(message_proof),
133		messages_count: 1,
134		dispatch_weight: Weight::from_parts(1000000000, 0),
135	}
136	.into()
137}
138
139/// Prepare a call with message delivery proof.
140pub fn make_standalone_relayer_confirmation_call<Runtime, GPI, MPI>(
141	message_delivery_proof: FromBridgedChainMessagesDeliveryProof<
142		HashOf<BridgedChain<Runtime, GPI>>,
143		LaneIdOf<Runtime, MPI>,
144	>,
145	relayers_state: UnrewardedRelayersState,
146) -> Runtime::RuntimeCall
147where
148	Runtime: pallet_bridge_grandpa::Config<GPI>
149		+ pallet_bridge_messages::Config<MPI, OutboundPayload = XcmAsPlainPayload>,
150	MPI: 'static,
151	Runtime::RuntimeCall: From<pallet_bridge_messages::Call<Runtime, MPI>>,
152	BridgedChainOf<Runtime, MPI>: Chain<Hash = HashOf<BridgedChain<Runtime, GPI>>>,
153{
154	pallet_bridge_messages::Call::<Runtime, MPI>::receive_messages_delivery_proof {
155		proof: message_delivery_proof,
156		relayers_state,
157	}
158	.into()
159}
160
161/// Prepare storage proofs of messages, stored at the (bridged) source GRANDPA chain.
162pub fn make_complex_relayer_delivery_proofs<BridgedChain, ThisChainWithMessages, LaneId>(
163	lane_id: LaneId,
164	xcm_message: Xcm<()>,
165	message_nonce: MessageNonce,
166	message_destination: Junctions,
167	header_number: BlockNumberOf<BridgedChain>,
168	is_minimal_call: bool,
169) -> (
170	HeaderOf<BridgedChain>,
171	GrandpaJustification<HeaderOf<BridgedChain>>,
172	FromBridgedChainMessagesProof<HashOf<BridgedChain>, LaneId>,
173)
174where
175	BridgedChain: ChainWithGrandpa,
176	ThisChainWithMessages: ChainWithMessages,
177	LaneId: Copy + Encode,
178{
179	// prepare message
180	let message_payload = prepare_inbound_xcm(xcm_message, message_destination);
181	// prepare storage proof containing message
182	let (state_root, storage_proof) =
183		prepare_messages_storage_proof::<BridgedChain, ThisChainWithMessages, LaneId>(
184			lane_id,
185			message_nonce..=message_nonce,
186			None,
187			UnverifiedStorageProofParams::from_db_size(message_payload.len() as u32),
188			|_| message_payload.clone(),
189			encode_all_messages,
190			encode_lane_data,
191			false,
192			false,
193		);
194
195	let (header, justification) = make_complex_bridged_grandpa_header_proof::<BridgedChain>(
196		state_root,
197		header_number,
198		is_minimal_call,
199	);
200
201	let message_proof = FromBridgedChainMessagesProof {
202		bridged_header_hash: header.hash(),
203		storage_proof,
204		lane: lane_id,
205		nonces_start: message_nonce,
206		nonces_end: message_nonce,
207	};
208
209	(header, justification, message_proof)
210}
211
212/// Prepare storage proofs of message confirmations, stored at the (bridged) target GRANDPA chain.
213pub fn make_complex_relayer_confirmation_proofs<
214	BridgedChain,
215	ThisChainWithMessages,
216	InnerXcmRuntimeCall,
217	LaneId,
218>(
219	lane_id: LaneId,
220	header_number: BlockNumberOf<BridgedChain>,
221	relayer_id_at_this_chain: AccountIdOf<ThisChainWithMessages>,
222	relayers_state: UnrewardedRelayersState,
223) -> (
224	HeaderOf<BridgedChain>,
225	GrandpaJustification<HeaderOf<BridgedChain>>,
226	FromBridgedChainMessagesDeliveryProof<HashOf<BridgedChain>, LaneId>,
227)
228where
229	BridgedChain: ChainWithGrandpa,
230	ThisChainWithMessages: ChainWithMessages,
231	LaneId: Copy + Encode,
232{
233	// prepare storage proof containing message delivery proof
234	let (state_root, storage_proof) =
235		prepare_message_delivery_storage_proof::<BridgedChain, ThisChainWithMessages, LaneId>(
236			lane_id,
237			InboundLaneData {
238				state: LaneState::Opened,
239				relayers: vec![
240					UnrewardedRelayer {
241						relayer: relayer_id_at_this_chain,
242						messages: DeliveredMessages::new(1)
243					};
244					relayers_state.unrewarded_relayer_entries as usize
245				]
246				.into(),
247				last_confirmed_nonce: 1,
248			},
249			UnverifiedStorageProofParams::default(),
250		);
251
252	let (header, justification) =
253		make_complex_bridged_grandpa_header_proof::<BridgedChain>(state_root, header_number, false);
254
255	let message_delivery_proof = FromBridgedChainMessagesDeliveryProof {
256		bridged_header_hash: header.hash(),
257		storage_proof,
258		lane: lane_id,
259	};
260
261	(header, justification, message_delivery_proof)
262}
263
264/// Make bridged GRANDPA chain header with given state root.
265pub fn make_complex_bridged_grandpa_header_proof<BridgedChain>(
266	state_root: HashOf<BridgedChain>,
267	header_number: BlockNumberOf<BridgedChain>,
268	is_minimal_call: bool,
269) -> (HeaderOf<BridgedChain>, GrandpaJustification<HeaderOf<BridgedChain>>)
270where
271	BridgedChain: ChainWithGrandpa,
272{
273	let mut header = bp_test_utils::test_header_with_root::<HeaderOf<BridgedChain>>(
274		header_number.into(),
275		state_root.into(),
276	);
277
278	// to compute proper cost of GRANDPA call, let's add some dummy bytes to header, so that the
279	// `submit_finality_proof` call size would be close to maximal expected (and refundable)
280	let extra_bytes_required = maximal_expected_submit_finality_proof_call_size::<BridgedChain>()
281		.saturating_sub(header.encoded_size());
282	if !is_minimal_call {
283		header.digest_mut().push(DigestItem::Other(vec![42; extra_bytes_required]));
284	}
285
286	let justification = make_default_justification(&header);
287	(header, justification)
288}
289
290/// Maximal expected `submit_finality_proof` call size.
291pub fn maximal_expected_submit_finality_proof_call_size<BridgedChain: ChainWithGrandpa>() -> usize {
292	bp_header_chain::max_expected_submit_finality_proof_arguments_size::<BridgedChain>(
293		false,
294		BridgedChain::MAX_AUTHORITIES_COUNT * 2 / 3 + 1,
295	) as usize
296}