1use 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
26pub 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 fn try_new<E: Ord + Encode>(endpoint1: E, endpoint2: E) -> Result<Self, ()>;
44}
45
46#[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 fn try_new<T: Ord + Encode>(_endpoint1: T, _endpoint2: T) -> Result<Self, ()> {
70 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#[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 #[cfg(feature = "std")]
146 pub const fn from_inner(inner: H256) -> Self {
147 Self(inner)
148 }
149
150 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 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#[derive(Clone, Copy, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen, RuntimeDebug)]
203pub enum LaneState {
204 Opened,
206 Closed,
214}
215
216impl LaneState {
217 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 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 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 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 let expected_lane = LegacyLaneId([0, 0, 0, 1]);
269 let expected_nonce_start = 1088_u64;
270 let expected_nonce_end = 9185_u64;
271
272 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 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 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 #[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}