1use crate::{
18 BridgedChainOf, Config, InboundLane, InboundLaneStorage, InboundLanes, OutboundLane,
19 OutboundLaneStorage, OutboundLanes, OutboundMessages, StoredInboundLaneData,
20 StoredMessagePayload,
21};
22
23use bp_messages::{
24 target_chain::MessageDispatch, ChainWithMessages, InboundLaneData, LaneState, MessageKey,
25 MessageNonce, OutboundLaneData,
26};
27use bp_runtime::AccountIdOf;
28use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
29use frame_support::{ensure, PalletError};
30use scale_info::TypeInfo;
31use sp_std::marker::PhantomData;
32
33#[derive(Encode, Decode, DecodeWithMemTracking, Debug, PartialEq, Eq, PalletError, TypeInfo)]
35pub enum LanesManagerError {
36 InboundLaneAlreadyExists,
38 OutboundLaneAlreadyExists,
40 UnknownInboundLane,
42 UnknownOutboundLane,
44 ClosedInboundLane,
46 ClosedOutboundLane,
48 LaneDispatcherInactive,
51}
52
53pub struct LanesManager<T, I>(PhantomData<(T, I)>);
55
56impl<T: Config<I>, I: 'static> Default for LanesManager<T, I> {
57 fn default() -> Self {
58 Self::new()
59 }
60}
61
62impl<T: Config<I>, I: 'static> LanesManager<T, I> {
63 pub fn new() -> Self {
65 Self(PhantomData)
66 }
67
68 pub fn create_inbound_lane(
70 &self,
71 lane_id: T::LaneId,
72 ) -> Result<InboundLane<RuntimeInboundLaneStorage<T, I>>, LanesManagerError> {
73 InboundLanes::<T, I>::try_mutate(lane_id, |lane| match lane {
74 Some(_) => Err(LanesManagerError::InboundLaneAlreadyExists),
75 None => {
76 *lane = Some(StoredInboundLaneData(InboundLaneData {
77 state: LaneState::Opened,
78 ..Default::default()
79 }));
80 Ok(())
81 },
82 })?;
83
84 self.active_inbound_lane(lane_id)
85 }
86
87 pub fn create_outbound_lane(
89 &self,
90 lane_id: T::LaneId,
91 ) -> Result<OutboundLane<RuntimeOutboundLaneStorage<T, I>>, LanesManagerError> {
92 OutboundLanes::<T, I>::try_mutate(lane_id, |lane| match lane {
93 Some(_) => Err(LanesManagerError::OutboundLaneAlreadyExists),
94 None => {
95 *lane = Some(OutboundLaneData { state: LaneState::Opened, ..Default::default() });
96 Ok(())
97 },
98 })?;
99
100 self.active_outbound_lane(lane_id)
101 }
102
103 pub fn active_inbound_lane(
105 &self,
106 lane_id: T::LaneId,
107 ) -> Result<InboundLane<RuntimeInboundLaneStorage<T, I>>, LanesManagerError> {
108 Ok(InboundLane::new(RuntimeInboundLaneStorage::from_lane_id(lane_id, true)?))
109 }
110
111 pub fn active_outbound_lane(
113 &self,
114 lane_id: T::LaneId,
115 ) -> Result<OutboundLane<RuntimeOutboundLaneStorage<T, I>>, LanesManagerError> {
116 Ok(OutboundLane::new(RuntimeOutboundLaneStorage::from_lane_id(lane_id, true)?))
117 }
118
119 pub fn any_state_inbound_lane(
121 &self,
122 lane_id: T::LaneId,
123 ) -> Result<InboundLane<RuntimeInboundLaneStorage<T, I>>, LanesManagerError> {
124 Ok(InboundLane::new(RuntimeInboundLaneStorage::from_lane_id(lane_id, false)?))
125 }
126
127 pub fn any_state_outbound_lane(
129 &self,
130 lane_id: T::LaneId,
131 ) -> Result<OutboundLane<RuntimeOutboundLaneStorage<T, I>>, LanesManagerError> {
132 Ok(OutboundLane::new(RuntimeOutboundLaneStorage::from_lane_id(lane_id, false)?))
133 }
134}
135
136pub struct RuntimeInboundLaneStorage<T: Config<I>, I: 'static = ()> {
138 pub(crate) lane_id: T::LaneId,
139 pub(crate) cached_data: InboundLaneData<AccountIdOf<BridgedChainOf<T, I>>>,
140}
141
142impl<T: Config<I>, I: 'static> RuntimeInboundLaneStorage<T, I> {
143 fn from_lane_id(
145 lane_id: T::LaneId,
146 check_active: bool,
147 ) -> Result<RuntimeInboundLaneStorage<T, I>, LanesManagerError> {
148 let cached_data =
149 InboundLanes::<T, I>::get(lane_id).ok_or(LanesManagerError::UnknownInboundLane)?;
150
151 if check_active {
152 ensure!(cached_data.state.is_active(), LanesManagerError::ClosedInboundLane);
154 ensure!(
171 T::MessageDispatch::is_active(lane_id),
172 LanesManagerError::LaneDispatcherInactive
173 );
174 }
175
176 Ok(RuntimeInboundLaneStorage { lane_id, cached_data: cached_data.into() })
177 }
178
179 pub fn extra_proof_size_bytes(&self) -> u64 {
188 let max_encoded_len = StoredInboundLaneData::<T, I>::max_encoded_len();
189 let relayers_count = self.data().relayers.len();
190 let actual_encoded_len =
191 InboundLaneData::<AccountIdOf<BridgedChainOf<T, I>>>::encoded_size_hint(relayers_count)
192 .unwrap_or(usize::MAX);
193 max_encoded_len.saturating_sub(actual_encoded_len) as _
194 }
195}
196
197impl<T: Config<I>, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage<T, I> {
198 type Relayer = AccountIdOf<BridgedChainOf<T, I>>;
199 type LaneId = T::LaneId;
200
201 fn id(&self) -> Self::LaneId {
202 self.lane_id
203 }
204
205 fn max_unrewarded_relayer_entries(&self) -> MessageNonce {
206 BridgedChainOf::<T, I>::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX
207 }
208
209 fn max_unconfirmed_messages(&self) -> MessageNonce {
210 BridgedChainOf::<T, I>::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX
211 }
212
213 fn data(&self) -> InboundLaneData<AccountIdOf<BridgedChainOf<T, I>>> {
214 self.cached_data.clone()
215 }
216
217 fn set_data(&mut self, data: InboundLaneData<AccountIdOf<BridgedChainOf<T, I>>>) {
218 self.cached_data = data.clone();
219 InboundLanes::<T, I>::insert(self.lane_id, StoredInboundLaneData::<T, I>(data))
220 }
221
222 fn purge(self) {
223 InboundLanes::<T, I>::remove(self.lane_id)
224 }
225}
226
227#[derive(Debug, PartialEq, Eq)]
229pub struct RuntimeOutboundLaneStorage<T: Config<I>, I: 'static> {
230 pub(crate) lane_id: T::LaneId,
231 pub(crate) cached_data: OutboundLaneData,
232 pub(crate) _phantom: PhantomData<(T, I)>,
233}
234
235impl<T: Config<I>, I: 'static> RuntimeOutboundLaneStorage<T, I> {
236 fn from_lane_id(lane_id: T::LaneId, check_active: bool) -> Result<Self, LanesManagerError> {
238 let cached_data =
239 OutboundLanes::<T, I>::get(lane_id).ok_or(LanesManagerError::UnknownOutboundLane)?;
240 ensure!(
241 !check_active || cached_data.state.is_active(),
242 LanesManagerError::ClosedOutboundLane
243 );
244 Ok(Self { lane_id, cached_data, _phantom: PhantomData })
245 }
246}
247
248impl<T: Config<I>, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorage<T, I> {
249 type StoredMessagePayload = StoredMessagePayload<T, I>;
250 type LaneId = T::LaneId;
251
252 fn id(&self) -> Self::LaneId {
253 self.lane_id
254 }
255
256 fn data(&self) -> OutboundLaneData {
257 self.cached_data.clone()
258 }
259
260 fn set_data(&mut self, data: OutboundLaneData) {
261 self.cached_data = data.clone();
262 OutboundLanes::<T, I>::insert(self.lane_id, data)
263 }
264
265 #[cfg(test)]
266 fn message(&self, nonce: &MessageNonce) -> Option<Self::StoredMessagePayload> {
267 OutboundMessages::<T, I>::get(MessageKey { lane_id: self.lane_id, nonce: *nonce })
268 .map(Into::into)
269 }
270
271 fn save_message(&mut self, nonce: MessageNonce, message_payload: Self::StoredMessagePayload) {
272 OutboundMessages::<T, I>::insert(
273 MessageKey { lane_id: self.lane_id, nonce },
274 message_payload,
275 );
276 }
277
278 fn remove_message(&mut self, nonce: &MessageNonce) {
279 OutboundMessages::<T, I>::remove(MessageKey { lane_id: self.lane_id, nonce: *nonce });
280 }
281
282 fn purge(self) {
283 OutboundLanes::<T, I>::remove(self.lane_id)
284 }
285}