referrerpolicy=no-referrer-when-downgrade

pallet_bridge_messages/tests/
messages_generation.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//! Helpers for generating message storage proofs, that are used by tests and by benchmarks.
18
19use bp_messages::{
20	storage_keys, ChainWithMessages, InboundLaneData, MessageKey, MessageNonce, MessagePayload,
21	OutboundLaneData,
22};
23use bp_runtime::{
24	grow_storage_value, record_all_trie_keys, AccountIdOf, Chain, HashOf, HasherOf,
25	RawStorageProof, UnverifiedStorageProofParams,
26};
27use codec::Encode;
28use sp_std::{ops::RangeInclusive, prelude::*};
29use sp_trie::{trie_types::TrieDBMutBuilderV1, LayoutV1, MemoryDB, TrieMut};
30
31/// Dummy message generation function.
32pub fn generate_dummy_message(_: MessageNonce) -> MessagePayload {
33	vec![42]
34}
35
36/// Simple and correct message data encode function.
37pub fn encode_all_messages(_: MessageNonce, m: &MessagePayload) -> Option<Vec<u8>> {
38	Some(m.encode())
39}
40
41/// Simple and correct outbound lane data encode function.
42pub fn encode_lane_data(d: &OutboundLaneData) -> Vec<u8> {
43	d.encode()
44}
45
46/// Prepare storage proof of given messages.
47///
48/// Returns state trie root and nodes with prepared messages.
49#[allow(clippy::too_many_arguments)]
50pub fn prepare_messages_storage_proof<
51	BridgedChain: Chain,
52	ThisChain: ChainWithMessages,
53	LaneId: Encode + Copy,
54>(
55	lane: LaneId,
56	message_nonces: RangeInclusive<MessageNonce>,
57	outbound_lane_data: Option<OutboundLaneData>,
58	proof_params: UnverifiedStorageProofParams,
59	generate_message: impl Fn(MessageNonce) -> MessagePayload,
60	encode_message: impl Fn(MessageNonce, &MessagePayload) -> Option<Vec<u8>>,
61	encode_outbound_lane_data: impl Fn(&OutboundLaneData) -> Vec<u8>,
62	add_duplicate_key: bool,
63	add_unused_key: bool,
64) -> (HashOf<BridgedChain>, RawStorageProof)
65where
66	HashOf<BridgedChain>: Copy + Default,
67{
68	// prepare Bridged chain storage with messages and (optionally) outbound lane state
69	let message_count = message_nonces.end().saturating_sub(*message_nonces.start()) + 1;
70	let mut storage_keys = Vec::with_capacity(message_count as usize + 1);
71	let mut root = Default::default();
72	let mut mdb = MemoryDB::default();
73	{
74		let mut trie =
75			TrieDBMutBuilderV1::<HasherOf<BridgedChain>>::new(&mut mdb, &mut root).build();
76
77		// insert messages
78		for (i, nonce) in message_nonces.into_iter().enumerate() {
79			let message_key = MessageKey { lane_id: lane, nonce };
80			let message_payload = match encode_message(nonce, &generate_message(nonce)) {
81				Some(message_payload) =>
82					if i == 0 {
83						grow_storage_value(message_payload, &proof_params)
84					} else {
85						message_payload
86					},
87				None => continue,
88			};
89			let storage_key = storage_keys::message_key(
90				ThisChain::WITH_CHAIN_MESSAGES_PALLET_NAME,
91				&message_key.lane_id,
92				message_key.nonce,
93			)
94			.0;
95			trie.insert(&storage_key, &message_payload)
96				.map_err(|_| "TrieMut::insert has failed")
97				.expect("TrieMut::insert should not fail in benchmarks");
98			storage_keys.push(storage_key);
99		}
100
101		// insert outbound lane state
102		if let Some(outbound_lane_data) = outbound_lane_data.as_ref().map(encode_outbound_lane_data)
103		{
104			let storage_key = storage_keys::outbound_lane_data_key(
105				ThisChain::WITH_CHAIN_MESSAGES_PALLET_NAME,
106				&lane,
107			)
108			.0;
109			trie.insert(&storage_key, &outbound_lane_data)
110				.map_err(|_| "TrieMut::insert has failed")
111				.expect("TrieMut::insert should not fail in benchmarks");
112			storage_keys.push(storage_key);
113		}
114	}
115
116	// generate storage proof to be delivered to This chain
117	let mut storage_proof =
118		record_all_trie_keys::<LayoutV1<HasherOf<BridgedChain>>, _>(&mdb, &root)
119			.map_err(|_| "record_all_trie_keys has failed")
120			.expect("record_all_trie_keys should not fail in benchmarks");
121
122	if add_duplicate_key {
123		assert!(!storage_proof.is_empty());
124		let node = storage_proof.pop().unwrap();
125		storage_proof.push(node.clone());
126		storage_proof.push(node);
127	}
128
129	if add_unused_key {
130		storage_proof.push(b"unused_value".to_vec());
131	}
132
133	(root, storage_proof)
134}
135
136/// Prepare storage proof of given messages delivery.
137///
138/// Returns state trie root and nodes with prepared messages.
139pub fn prepare_message_delivery_storage_proof<
140	BridgedChain: Chain,
141	ThisChain: ChainWithMessages,
142	LaneId: Encode,
143>(
144	lane: LaneId,
145	inbound_lane_data: InboundLaneData<AccountIdOf<ThisChain>>,
146	proof_params: UnverifiedStorageProofParams,
147) -> (HashOf<BridgedChain>, RawStorageProof)
148where
149	HashOf<BridgedChain>: Copy + Default,
150{
151	// prepare Bridged chain storage with inbound lane state
152	let storage_key =
153		storage_keys::inbound_lane_data_key(ThisChain::WITH_CHAIN_MESSAGES_PALLET_NAME, &lane).0;
154	let mut root = Default::default();
155	let mut mdb = MemoryDB::default();
156	{
157		let mut trie =
158			TrieDBMutBuilderV1::<HasherOf<BridgedChain>>::new(&mut mdb, &mut root).build();
159		let inbound_lane_data = grow_storage_value(inbound_lane_data.encode(), &proof_params);
160		trie.insert(&storage_key, &inbound_lane_data)
161			.map_err(|_| "TrieMut::insert has failed")
162			.expect("TrieMut::insert should not fail in benchmarks");
163	}
164
165	// generate storage proof to be delivered to This chain
166	let storage_proof = record_all_trie_keys::<LayoutV1<HasherOf<BridgedChain>>, _>(&mdb, &root)
167		.map_err(|_| "record_all_trie_keys has failed")
168		.expect("record_all_trie_keys should not fail in benchmarks");
169
170	(root, storage_proof)
171}