Skip to content

Commit 78517a6

Browse files
svyatonikbkontur
authored andcommitted
Introduce MessagesLaneManager (#2227)
* some useful stuff like LanesManager * clippy * more clippy * Error::LanesManager * {in, out}bound_lane -> active_{in, out}bound_lane * merge two impl blocks in one * fmt
1 parent 526a386 commit 78517a6

7 files changed

Lines changed: 380 additions & 160 deletions

File tree

bridges/modules/messages/src/inbound_lane.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use crate::{BridgedChainOf, Config};
2020

2121
use bp_messages::{
2222
target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch},
23-
ChainWithMessages, DeliveredMessages, InboundLaneData, LaneId, MessageKey, MessageNonce,
24-
OutboundLaneData, ReceptionResult, UnrewardedRelayer,
23+
ChainWithMessages, DeliveredMessages, InboundLaneData, LaneId, LaneState, MessageKey,
24+
MessageNonce, OutboundLaneData, ReceptionResult, UnrewardedRelayer,
2525
};
2626
use bp_runtime::AccountIdOf;
2727
use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};
@@ -44,6 +44,8 @@ pub trait InboundLaneStorage {
4444
fn data(&self) -> InboundLaneData<Self::Relayer>;
4545
/// Update lane data in the storage.
4646
fn set_data(&mut self, data: InboundLaneData<Self::Relayer>);
47+
/// Purge lane data from the storage.
48+
fn purge(self);
4749
}
4850

4951
/// Inbound lane data wrapper that implements `MaxEncodedLen`.
@@ -120,9 +122,21 @@ impl<S: InboundLaneStorage> InboundLane<S> {
120122
InboundLane { storage }
121123
}
122124

123-
/// Returns `mut` storage reference.
124-
pub fn storage_mut(&mut self) -> &mut S {
125-
&mut self.storage
125+
/// Get lane state.
126+
pub fn state(&self) -> LaneState {
127+
self.storage.data().state
128+
}
129+
130+
/// Returns storage reference.
131+
pub fn storage(&self) -> &S {
132+
&self.storage
133+
}
134+
135+
/// Set lane state.
136+
pub fn set_state(&mut self, state: LaneState) {
137+
let mut data = self.storage.data();
138+
data.state = state;
139+
self.storage.set_data(data);
126140
}
127141

128142
/// Receive state of the corresponding outbound lane.
@@ -211,12 +225,17 @@ impl<S: InboundLaneStorage> InboundLane<S> {
211225

212226
ReceptionResult::Dispatched(dispatch_result)
213227
}
228+
229+
/// Purge lane state from the storage.
230+
pub fn purge(self) {
231+
self.storage.purge()
232+
}
214233
}
215234

216235
#[cfg(test)]
217236
mod tests {
218237
use super::*;
219-
use crate::{inbound_lane, tests::mock::*, RuntimeInboundLaneStorage};
238+
use crate::{inbound_lane, lanes_manager::RuntimeInboundLaneStorage, tests::mock::*};
220239
use bp_messages::UnrewardedRelayersState;
221240

222241
fn receive_regular_message(
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
// Copyright 2019-2021 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+
use crate::{
18+
BridgedChainOf, Config, InboundLane, InboundLaneStorage, InboundLanes, OutboundLane,
19+
OutboundLaneStorage, OutboundLanes, OutboundMessages, StoredInboundLaneData,
20+
StoredMessagePayload,
21+
};
22+
23+
use bp_messages::{
24+
ChainWithMessages, InboundLaneData, LaneId, LaneState, MessageKey, MessageNonce,
25+
OutboundLaneData,
26+
};
27+
use bp_runtime::AccountIdOf;
28+
use codec::{Decode, Encode, MaxEncodedLen};
29+
use frame_support::{ensure, sp_runtime::RuntimeDebug, PalletError};
30+
use scale_info::TypeInfo;
31+
use sp_std::marker::PhantomData;
32+
33+
/// Lanes manager errors.
34+
#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)]
35+
pub enum LanesManagerError {
36+
/// Inbound lane already exists.
37+
InboundLaneAlreadyExists,
38+
/// Outbound lane already exists.
39+
OutboundLaneAlreadyExists,
40+
/// No inbound lane with given id.
41+
UnknownInboundLane,
42+
/// No outbound lane with given id.
43+
UnknownOutboundLane,
44+
/// Inbound lane with given id is closed.
45+
ClosedInboundLane,
46+
/// Outbound lane with given id is closed.
47+
ClosedOutboundLane,
48+
}
49+
50+
/// Message lanes manager.
51+
pub struct LanesManager<T, I>(PhantomData<(T, I)>);
52+
53+
impl<T: Config<I>, I: 'static> Default for LanesManager<T, I> {
54+
fn default() -> Self {
55+
Self::new()
56+
}
57+
}
58+
59+
impl<T: Config<I>, I: 'static> LanesManager<T, I> {
60+
/// Create new lanes manager.
61+
pub fn new() -> Self {
62+
Self(PhantomData)
63+
}
64+
65+
/// Create new inbound lane in `Opened` state.
66+
pub fn create_inbound_lane(
67+
&self,
68+
lane_id: LaneId,
69+
) -> Result<InboundLane<RuntimeInboundLaneStorage<T, I>>, LanesManagerError> {
70+
InboundLanes::<T, I>::try_mutate(lane_id, |lane| match lane {
71+
Some(_) => Err(LanesManagerError::InboundLaneAlreadyExists),
72+
None => {
73+
*lane = Some(StoredInboundLaneData(InboundLaneData {
74+
state: LaneState::Opened,
75+
..Default::default()
76+
}));
77+
Ok(())
78+
},
79+
})?;
80+
81+
self.active_inbound_lane(lane_id)
82+
}
83+
84+
/// Create new outbound lane in `Opened` state.
85+
pub fn create_outbound_lane(
86+
&self,
87+
lane_id: LaneId,
88+
) -> Result<OutboundLane<RuntimeOutboundLaneStorage<T, I>>, LanesManagerError> {
89+
OutboundLanes::<T, I>::try_mutate(lane_id, |lane| match lane {
90+
Some(_) => Err(LanesManagerError::OutboundLaneAlreadyExists),
91+
None => {
92+
*lane = Some(OutboundLaneData { state: LaneState::Opened, ..Default::default() });
93+
Ok(())
94+
},
95+
})?;
96+
97+
self.active_outbound_lane(lane_id)
98+
}
99+
100+
/// Get existing inbound lane, checking that it is in usable state.
101+
pub fn active_inbound_lane(
102+
&self,
103+
lane_id: LaneId,
104+
) -> Result<InboundLane<RuntimeInboundLaneStorage<T, I>>, LanesManagerError> {
105+
Ok(InboundLane::new(RuntimeInboundLaneStorage::from_lane_id(lane_id, true)?))
106+
}
107+
108+
/// Get existing outbound lane, checking that it is in usable state.
109+
pub fn active_outbound_lane(
110+
&self,
111+
lane_id: LaneId,
112+
) -> Result<OutboundLane<RuntimeOutboundLaneStorage<T, I>>, LanesManagerError> {
113+
Ok(OutboundLane::new(RuntimeOutboundLaneStorage::from_lane_id(lane_id, true)?))
114+
}
115+
116+
/// Get existing inbound lane without any additional state checks.
117+
pub fn any_state_inbound_lane(
118+
&self,
119+
lane_id: LaneId,
120+
) -> Result<InboundLane<RuntimeInboundLaneStorage<T, I>>, LanesManagerError> {
121+
Ok(InboundLane::new(RuntimeInboundLaneStorage::from_lane_id(lane_id, false)?))
122+
}
123+
124+
/// Get existing outbound lane without any additional state checks.
125+
pub fn any_state_outbound_lane(
126+
&self,
127+
lane_id: LaneId,
128+
) -> Result<OutboundLane<RuntimeOutboundLaneStorage<T, I>>, LanesManagerError> {
129+
Ok(OutboundLane::new(RuntimeOutboundLaneStorage::from_lane_id(lane_id, false)?))
130+
}
131+
}
132+
133+
/// Runtime inbound lane storage.
134+
pub struct RuntimeInboundLaneStorage<T: Config<I>, I: 'static = ()> {
135+
pub(crate) lane_id: LaneId,
136+
pub(crate) cached_data: InboundLaneData<AccountIdOf<BridgedChainOf<T, I>>>,
137+
pub(crate) _phantom: PhantomData<I>,
138+
}
139+
140+
impl<T: Config<I>, I: 'static> RuntimeInboundLaneStorage<T, I> {
141+
/// Creates new runtime inbound lane storage for given **existing** lane.
142+
fn from_lane_id(
143+
lane_id: LaneId,
144+
check_active: bool,
145+
) -> Result<RuntimeInboundLaneStorage<T, I>, LanesManagerError> {
146+
let cached_data =
147+
InboundLanes::<T, I>::get(lane_id).ok_or(LanesManagerError::UnknownInboundLane)?;
148+
ensure!(
149+
!check_active || cached_data.state.is_active(),
150+
LanesManagerError::ClosedInboundLane
151+
);
152+
Ok(RuntimeInboundLaneStorage {
153+
lane_id,
154+
cached_data: cached_data.into(),
155+
_phantom: Default::default(),
156+
})
157+
}
158+
159+
/// Returns number of bytes that may be subtracted from the PoV component of
160+
/// `receive_messages_proof` call, because the actual inbound lane state is smaller than the
161+
/// maximal configured.
162+
///
163+
/// Maximal inbound lane state set size is configured by the
164+
/// `MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX` constant from the pallet configuration. The PoV
165+
/// of the call includes the maximal size of inbound lane state. If the actual size is smaller,
166+
/// we may subtract extra bytes from this component.
167+
pub fn extra_proof_size_bytes(&self) -> u64 {
168+
let max_encoded_len = StoredInboundLaneData::<T, I>::max_encoded_len();
169+
let relayers_count = self.data().relayers.len();
170+
let actual_encoded_len =
171+
InboundLaneData::<AccountIdOf<BridgedChainOf<T, I>>>::encoded_size_hint(relayers_count)
172+
.unwrap_or(usize::MAX);
173+
max_encoded_len.saturating_sub(actual_encoded_len) as _
174+
}
175+
}
176+
177+
impl<T: Config<I>, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage<T, I> {
178+
type Relayer = AccountIdOf<BridgedChainOf<T, I>>;
179+
180+
fn id(&self) -> LaneId {
181+
self.lane_id
182+
}
183+
184+
fn max_unrewarded_relayer_entries(&self) -> MessageNonce {
185+
BridgedChainOf::<T, I>::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX
186+
}
187+
188+
fn max_unconfirmed_messages(&self) -> MessageNonce {
189+
BridgedChainOf::<T, I>::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX
190+
}
191+
192+
fn data(&self) -> InboundLaneData<AccountIdOf<BridgedChainOf<T, I>>> {
193+
self.cached_data.clone()
194+
}
195+
196+
fn set_data(&mut self, data: InboundLaneData<AccountIdOf<BridgedChainOf<T, I>>>) {
197+
self.cached_data = data.clone();
198+
InboundLanes::<T, I>::insert(self.lane_id, StoredInboundLaneData::<T, I>(data))
199+
}
200+
201+
fn purge(self) {
202+
InboundLanes::<T, I>::remove(self.lane_id)
203+
}
204+
}
205+
206+
/// Runtime outbound lane storage.
207+
#[derive(Debug, PartialEq, Eq)]
208+
pub struct RuntimeOutboundLaneStorage<T, I = ()> {
209+
pub(crate) lane_id: LaneId,
210+
pub(crate) cached_data: OutboundLaneData,
211+
pub(crate) _phantom: PhantomData<(T, I)>,
212+
}
213+
214+
impl<T: Config<I>, I: 'static> RuntimeOutboundLaneStorage<T, I> {
215+
/// Creates new runtime outbound lane storage for given **existing** lane.
216+
fn from_lane_id(lane_id: LaneId, check_active: bool) -> Result<Self, LanesManagerError> {
217+
let cached_data =
218+
OutboundLanes::<T, I>::get(lane_id).ok_or(LanesManagerError::UnknownOutboundLane)?;
219+
ensure!(
220+
!check_active || cached_data.state.is_active(),
221+
LanesManagerError::ClosedOutboundLane
222+
);
223+
Ok(Self { lane_id, cached_data, _phantom: PhantomData })
224+
}
225+
}
226+
227+
impl<T: Config<I>, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorage<T, I> {
228+
type StoredMessagePayload = StoredMessagePayload<T, I>;
229+
230+
fn id(&self) -> LaneId {
231+
self.lane_id
232+
}
233+
234+
fn data(&self) -> OutboundLaneData {
235+
self.cached_data.clone()
236+
}
237+
238+
fn set_data(&mut self, data: OutboundLaneData) {
239+
self.cached_data = data.clone();
240+
OutboundLanes::<T, I>::insert(self.lane_id, data)
241+
}
242+
243+
#[cfg(test)]
244+
fn message(&self, nonce: &MessageNonce) -> Option<Self::StoredMessagePayload> {
245+
OutboundMessages::<T, I>::get(MessageKey { lane_id: self.lane_id, nonce: *nonce })
246+
.map(Into::into)
247+
}
248+
249+
fn save_message(&mut self, nonce: MessageNonce, message_payload: Self::StoredMessagePayload) {
250+
OutboundMessages::<T, I>::insert(
251+
MessageKey { lane_id: self.lane_id, nonce },
252+
message_payload,
253+
);
254+
}
255+
256+
fn remove_message(&mut self, nonce: &MessageNonce) {
257+
OutboundMessages::<T, I>::remove(MessageKey { lane_id: self.lane_id, nonce: *nonce });
258+
}
259+
260+
fn purge(self) {
261+
OutboundLanes::<T, I>::remove(self.lane_id)
262+
}
263+
}

0 commit comments

Comments
 (0)