referrerpolicy=no-referrer-when-downgrade

bp_messages/
lane.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//! Primitives of messages module, that represents lane id.
18
19use codec::{Codec, Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen};
20use scale_info::TypeInfo;
21use serde::{de::DeserializeOwned, Deserialize, Serialize};
22use sp_core::{RuntimeDebug, TypeId, H256};
23use sp_io::hashing::blake2_256;
24use sp_std::fmt::Debug;
25
26/// Trait representing a generic `LaneId` type.
27pub trait LaneIdType:
28	Clone
29	+ Copy
30	+ Codec
31	+ EncodeLike
32	+ Debug
33	+ Default
34	+ PartialEq
35	+ Eq
36	+ Ord
37	+ TypeInfo
38	+ MaxEncodedLen
39	+ Serialize
40	+ DeserializeOwned
41{
42	/// Creates a new `LaneId` type (if supported).
43	fn try_new<E: Ord + Encode>(endpoint1: E, endpoint2: E) -> Result<Self, ()>;
44}
45
46/// Bridge lane identifier (legacy).
47///
48/// Note: For backwards compatibility reasons, we also handle the older format `[u8; 4]`.
49#[derive(
50	Clone,
51	Copy,
52	Decode,
53	DecodeWithMemTracking,
54	Default,
55	Encode,
56	Eq,
57	Ord,
58	PartialOrd,
59	PartialEq,
60	TypeInfo,
61	MaxEncodedLen,
62	Serialize,
63	Deserialize,
64)]
65pub struct LegacyLaneId(pub [u8; 4]);
66
67impl LaneIdType for LegacyLaneId {
68	/// Create lane identifier from two locations.
69	fn try_new<T: Ord + Encode>(_endpoint1: T, _endpoint2: T) -> Result<Self, ()> {
70		// we don't support this for `LegacyLaneId`, because it was hard-coded before
71		Err(())
72	}
73}
74
75#[cfg(feature = "std")]
76impl TryFrom<Vec<u8>> for LegacyLaneId {
77	type Error = ();
78
79	fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
80		if value.len() == 4 {
81			return <[u8; 4]>::try_from(value).map(Self).map_err(|_| ());
82		}
83		Err(())
84	}
85}
86
87impl core::fmt::Debug for LegacyLaneId {
88	fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
89		self.0.fmt(fmt)
90	}
91}
92
93impl AsRef<[u8]> for LegacyLaneId {
94	fn as_ref(&self) -> &[u8] {
95		&self.0
96	}
97}
98
99impl TypeId for LegacyLaneId {
100	const TYPE_ID: [u8; 4] = *b"blan";
101}
102
103/// Bridge lane identifier.
104///
105/// Lane connects two endpoints at both sides of the bridge. We assume that every endpoint
106/// has its own unique identifier. We want lane identifiers to be **the same on the both sides
107/// of the bridge** (and naturally unique across global consensus if endpoints have unique
108/// identifiers). So lane id is the hash (`blake2_256`) of **ordered** encoded locations
109/// concatenation (separated by some binary data). I.e.:
110///
111/// ```nocompile
112/// let endpoint1 = X2(GlobalConsensus(NetworkId::Polkadot), Parachain(42));
113/// let endpoint2 = X2(GlobalConsensus(NetworkId::Kusama), Parachain(777));
114///
115/// let final_lane_key = if endpoint1 < endpoint2 {
116///     (endpoint1, VALUES_SEPARATOR, endpoint2)
117/// } else {
118///     (endpoint2, VALUES_SEPARATOR, endpoint1)
119/// }.using_encoded(blake2_256);
120/// ```
121#[derive(
122	Clone,
123	Copy,
124	Decode,
125	DecodeWithMemTracking,
126	Default,
127	Encode,
128	Eq,
129	Ord,
130	PartialOrd,
131	PartialEq,
132	TypeInfo,
133	MaxEncodedLen,
134	Serialize,
135	Deserialize,
136)]
137pub struct HashedLaneId(H256);
138
139impl HashedLaneId {
140	/// Create lane identifier from given hash.
141	///
142	/// There's no `From<H256>` implementation for the `LaneId`, because using this conversion
143	/// in a wrong way (i.e. computing hash of endpoints manually) may lead to issues. So we
144	/// want the call to be explicit.
145	#[cfg(feature = "std")]
146	pub const fn from_inner(inner: H256) -> Self {
147		Self(inner)
148	}
149
150	/// Access the inner lane representation.
151	pub fn inner(&self) -> &H256 {
152		&self.0
153	}
154}
155
156impl core::fmt::Display for HashedLaneId {
157	fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
158		core::fmt::Display::fmt(&self.0, f)
159	}
160}
161
162impl core::fmt::Debug for HashedLaneId {
163	fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
164		core::fmt::Debug::fmt(&self.0, f)
165	}
166}
167
168impl TypeId for HashedLaneId {
169	const TYPE_ID: [u8; 4] = *b"hlan";
170}
171
172impl LaneIdType for HashedLaneId {
173	/// Create lane identifier from two locations.
174	fn try_new<T: Ord + Encode>(endpoint1: T, endpoint2: T) -> Result<Self, ()> {
175		const VALUES_SEPARATOR: [u8; 31] = *b"bridges-lane-id-value-separator";
176
177		Ok(Self(
178			if endpoint1 < endpoint2 {
179				(endpoint1, VALUES_SEPARATOR, endpoint2)
180			} else {
181				(endpoint2, VALUES_SEPARATOR, endpoint1)
182			}
183			.using_encoded(blake2_256)
184			.into(),
185		))
186	}
187}
188
189#[cfg(feature = "std")]
190impl TryFrom<Vec<u8>> for HashedLaneId {
191	type Error = ();
192
193	fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
194		if value.len() == 32 {
195			return <[u8; 32]>::try_from(value).map(|v| Self(H256::from(v))).map_err(|_| ());
196		}
197		Err(())
198	}
199}
200
201/// Lane state.
202#[derive(Clone, Copy, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen, RuntimeDebug)]
203pub enum LaneState {
204	/// Lane is opened and messages may be sent/received over it.
205	Opened,
206	/// Lane is closed and all attempts to send/receive messages to/from this lane
207	/// will fail.
208	///
209	/// Keep in mind that the lane has two ends and the state of the same lane at
210	/// its ends may be different. Those who are controlling/serving the lane
211	/// and/or sending messages over the lane, have to coordinate their actions on
212	/// both ends to make sure that lane is operating smoothly on both ends.
213	Closed,
214}
215
216impl LaneState {
217	/// Returns true if lane state allows sending/receiving messages.
218	pub fn is_active(&self) -> bool {
219		matches!(*self, LaneState::Opened)
220	}
221}
222
223#[cfg(test)]
224mod tests {
225	use super::*;
226	use crate::MessageNonce;
227
228	#[test]
229	fn lane_id_debug_format_matches_inner_hash_format() {
230		assert_eq!(
231			format!("{:?}", HashedLaneId(H256::from([1u8; 32]))),
232			format!("{:?}", H256::from([1u8; 32])),
233		);
234		assert_eq!(format!("{:?}", LegacyLaneId([0, 0, 0, 1])), format!("{:?}", [0, 0, 0, 1]),);
235	}
236
237	#[test]
238	fn hashed_encode_decode_works() {
239		// simple encode/decode - new format
240		let lane_id = HashedLaneId(H256::from([1u8; 32]));
241		let encoded_lane_id = lane_id.encode();
242		let decoded_lane_id = HashedLaneId::decode(&mut &encoded_lane_id[..]).expect("decodable");
243		assert_eq!(lane_id, decoded_lane_id);
244		assert_eq!(
245			"0101010101010101010101010101010101010101010101010101010101010101",
246			hex::encode(encoded_lane_id)
247		);
248	}
249
250	#[test]
251	fn legacy_encode_decode_works() {
252		// simple encode/decode - old format
253		let lane_id = LegacyLaneId([0, 0, 0, 1]);
254		let encoded_lane_id = lane_id.encode();
255		let decoded_lane_id = LegacyLaneId::decode(&mut &encoded_lane_id[..]).expect("decodable");
256		assert_eq!(lane_id, decoded_lane_id);
257		assert_eq!("00000001", hex::encode(encoded_lane_id));
258
259		// decode sample
260		let bytes = vec![0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0];
261		let (lane, nonce_start, nonce_end): (LegacyLaneId, MessageNonce, MessageNonce) =
262			Decode::decode(&mut &bytes[..]).unwrap();
263		assert_eq!(lane, LegacyLaneId([0, 0, 0, 2]));
264		assert_eq!(nonce_start, 1);
265		assert_eq!(nonce_end, 1);
266
267		// run encode/decode for `LaneId` with different positions
268		let expected_lane = LegacyLaneId([0, 0, 0, 1]);
269		let expected_nonce_start = 1088_u64;
270		let expected_nonce_end = 9185_u64;
271
272		// decode: LaneId,Nonce,Nonce
273		let bytes = (expected_lane, expected_nonce_start, expected_nonce_end).encode();
274		let (lane, nonce_start, nonce_end): (LegacyLaneId, MessageNonce, MessageNonce) =
275			Decode::decode(&mut &bytes[..]).unwrap();
276		assert_eq!(lane, expected_lane);
277		assert_eq!(nonce_start, expected_nonce_start);
278		assert_eq!(nonce_end, expected_nonce_end);
279
280		// decode: Nonce,LaneId,Nonce
281		let bytes = (expected_nonce_start, expected_lane, expected_nonce_end).encode();
282		let (nonce_start, lane, nonce_end): (MessageNonce, LegacyLaneId, MessageNonce) =
283			Decode::decode(&mut &bytes[..]).unwrap();
284		assert_eq!(lane, expected_lane);
285		assert_eq!(nonce_start, expected_nonce_start);
286		assert_eq!(nonce_end, expected_nonce_end);
287
288		// decode: Nonce,Nonce,LaneId
289		let bytes = (expected_nonce_start, expected_nonce_end, expected_lane).encode();
290		let (nonce_start, nonce_end, lane): (MessageNonce, MessageNonce, LegacyLaneId) =
291			Decode::decode(&mut &bytes[..]).unwrap();
292		assert_eq!(lane, expected_lane);
293		assert_eq!(nonce_start, expected_nonce_start);
294		assert_eq!(nonce_end, expected_nonce_end);
295	}
296
297	#[test]
298	fn hashed_lane_id_is_generated_using_ordered_endpoints() {
299		assert_eq!(HashedLaneId::try_new(1, 2).unwrap(), HashedLaneId::try_new(2, 1).unwrap());
300	}
301
302	#[test]
303	fn hashed_lane_id_is_different_for_different_endpoints() {
304		assert_ne!(HashedLaneId::try_new(1, 2).unwrap(), HashedLaneId::try_new(1, 3).unwrap());
305	}
306
307	#[test]
308	fn hashed_lane_id_is_different_even_if_arguments_has_partial_matching_encoding() {
309		/// Some artificial type that generates the same encoding for different values
310		/// concatenations. I.e. the encoding for `(Either::Two(1, 2), Either::Two(3, 4))`
311		/// is the same as encoding of `(Either::Three(1, 2, 3), Either::One(4))`.
312		/// In practice, this type is not useful, because you can't do a proper decoding.
313		/// But still there may be some collisions even in proper types.
314		#[derive(Eq, Ord, PartialEq, PartialOrd)]
315		enum Either {
316			Three(u64, u64, u64),
317			Two(u64, u64),
318			One(u64),
319		}
320
321		impl codec::Encode for Either {
322			fn encode(&self) -> Vec<u8> {
323				match *self {
324					Self::One(a) => a.encode(),
325					Self::Two(a, b) => (a, b).encode(),
326					Self::Three(a, b, c) => (a, b, c).encode(),
327				}
328			}
329		}
330
331		assert_ne!(
332			HashedLaneId::try_new(Either::Two(1, 2), Either::Two(3, 4)).unwrap(),
333			HashedLaneId::try_new(Either::Three(1, 2, 3), Either::One(4)).unwrap(),
334		);
335	}
336}