diff --git a/bridges/modules/messages/src/inbound_lane.rs b/bridges/modules/messages/src/inbound_lane.rs index 3f397d025d27..ccc1b1b60caa 100644 --- a/bridges/modules/messages/src/inbound_lane.rs +++ b/bridges/modules/messages/src/inbound_lane.rs @@ -20,8 +20,8 @@ use crate::{BridgedChainOf, Config}; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - ChainWithMessages, DeliveredMessages, InboundLaneData, LaneId, MessageKey, MessageNonce, - OutboundLaneData, ReceptionResult, UnrewardedRelayer, + ChainWithMessages, DeliveredMessages, InboundLaneData, LaneId, LaneState, MessageKey, + MessageNonce, OutboundLaneData, ReceptionResult, UnrewardedRelayer, }; use bp_runtime::AccountIdOf; use codec::{Decode, Encode, EncodeLike, MaxEncodedLen}; @@ -44,6 +44,8 @@ pub trait InboundLaneStorage { fn data(&self) -> InboundLaneData; /// Update lane data in the storage. fn set_data(&mut self, data: InboundLaneData); + /// Purge lane data from the storage. + fn purge(self); } /// Inbound lane data wrapper that implements `MaxEncodedLen`. @@ -120,9 +122,21 @@ impl InboundLane { InboundLane { storage } } - /// Returns `mut` storage reference. - pub fn storage_mut(&mut self) -> &mut S { - &mut self.storage + /// Get lane state. + pub fn state(&self) -> LaneState { + self.storage.data().state + } + + /// Returns storage reference. + pub fn storage(&self) -> &S { + &self.storage + } + + /// Set lane state. + pub fn set_state(&mut self, state: LaneState) { + let mut data = self.storage.data(); + data.state = state; + self.storage.set_data(data); } /// Receive state of the corresponding outbound lane. @@ -211,12 +225,17 @@ impl InboundLane { ReceptionResult::Dispatched(dispatch_result) } + + /// Purge lane state from the storage. + pub fn purge(self) { + self.storage.purge() + } } #[cfg(test)] mod tests { use super::*; - use crate::{inbound_lane, tests::mock::*, RuntimeInboundLaneStorage}; + use crate::{inbound_lane, lanes_manager::RuntimeInboundLaneStorage, tests::mock::*}; use bp_messages::UnrewardedRelayersState; fn receive_regular_message( diff --git a/bridges/modules/messages/src/lanes_manager.rs b/bridges/modules/messages/src/lanes_manager.rs new file mode 100644 index 000000000000..911bed9fcb67 --- /dev/null +++ b/bridges/modules/messages/src/lanes_manager.rs @@ -0,0 +1,263 @@ +// Copyright 2019-2021 Parity Technologies (UK) Ltd. +// This file is part of Parity Bridges Common. + +// Parity Bridges Common is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity Bridges Common is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity Bridges Common. If not, see . + +use crate::{ + BridgedChainOf, Config, InboundLane, InboundLaneStorage, InboundLanes, OutboundLane, + OutboundLaneStorage, OutboundLanes, OutboundMessages, StoredInboundLaneData, + StoredMessagePayload, +}; + +use bp_messages::{ + ChainWithMessages, InboundLaneData, LaneId, LaneState, MessageKey, MessageNonce, + OutboundLaneData, +}; +use bp_runtime::AccountIdOf; +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::{ensure, sp_runtime::RuntimeDebug, PalletError}; +use scale_info::TypeInfo; +use sp_std::marker::PhantomData; + +/// Lanes manager errors. +#[derive(Encode, Decode, RuntimeDebug, PartialEq, Eq, PalletError, TypeInfo)] +pub enum LanesManagerError { + /// Inbound lane already exists. + InboundLaneAlreadyExists, + /// Outbound lane already exists. + OutboundLaneAlreadyExists, + /// No inbound lane with given id. + UnknownInboundLane, + /// No outbound lane with given id. + UnknownOutboundLane, + /// Inbound lane with given id is closed. + ClosedInboundLane, + /// Outbound lane with given id is closed. + ClosedOutboundLane, +} + +/// Message lanes manager. +pub struct LanesManager(PhantomData<(T, I)>); + +impl, I: 'static> Default for LanesManager { + fn default() -> Self { + Self::new() + } +} + +impl, I: 'static> LanesManager { + /// Create new lanes manager. + pub fn new() -> Self { + Self(PhantomData) + } + + /// Create new inbound lane in `Opened` state. + pub fn create_inbound_lane( + &self, + lane_id: LaneId, + ) -> Result>, LanesManagerError> { + InboundLanes::::try_mutate(lane_id, |lane| match lane { + Some(_) => Err(LanesManagerError::InboundLaneAlreadyExists), + None => { + *lane = Some(StoredInboundLaneData(InboundLaneData { + state: LaneState::Opened, + ..Default::default() + })); + Ok(()) + }, + })?; + + self.active_inbound_lane(lane_id) + } + + /// Create new outbound lane in `Opened` state. + pub fn create_outbound_lane( + &self, + lane_id: LaneId, + ) -> Result>, LanesManagerError> { + OutboundLanes::::try_mutate(lane_id, |lane| match lane { + Some(_) => Err(LanesManagerError::OutboundLaneAlreadyExists), + None => { + *lane = Some(OutboundLaneData { state: LaneState::Opened, ..Default::default() }); + Ok(()) + }, + })?; + + self.active_outbound_lane(lane_id) + } + + /// Get existing inbound lane, checking that it is in usable state. + pub fn active_inbound_lane( + &self, + lane_id: LaneId, + ) -> Result>, LanesManagerError> { + Ok(InboundLane::new(RuntimeInboundLaneStorage::from_lane_id(lane_id, true)?)) + } + + /// Get existing outbound lane, checking that it is in usable state. + pub fn active_outbound_lane( + &self, + lane_id: LaneId, + ) -> Result>, LanesManagerError> { + Ok(OutboundLane::new(RuntimeOutboundLaneStorage::from_lane_id(lane_id, true)?)) + } + + /// Get existing inbound lane without any additional state checks. + pub fn any_state_inbound_lane( + &self, + lane_id: LaneId, + ) -> Result>, LanesManagerError> { + Ok(InboundLane::new(RuntimeInboundLaneStorage::from_lane_id(lane_id, false)?)) + } + + /// Get existing outbound lane without any additional state checks. + pub fn any_state_outbound_lane( + &self, + lane_id: LaneId, + ) -> Result>, LanesManagerError> { + Ok(OutboundLane::new(RuntimeOutboundLaneStorage::from_lane_id(lane_id, false)?)) + } +} + +/// Runtime inbound lane storage. +pub struct RuntimeInboundLaneStorage, I: 'static = ()> { + pub(crate) lane_id: LaneId, + pub(crate) cached_data: InboundLaneData>>, + pub(crate) _phantom: PhantomData, +} + +impl, I: 'static> RuntimeInboundLaneStorage { + /// Creates new runtime inbound lane storage for given **existing** lane. + fn from_lane_id( + lane_id: LaneId, + check_active: bool, + ) -> Result, LanesManagerError> { + let cached_data = + InboundLanes::::get(lane_id).ok_or(LanesManagerError::UnknownInboundLane)?; + ensure!( + !check_active || cached_data.state.is_active(), + LanesManagerError::ClosedInboundLane + ); + Ok(RuntimeInboundLaneStorage { + lane_id, + cached_data: cached_data.into(), + _phantom: Default::default(), + }) + } + + /// Returns number of bytes that may be subtracted from the PoV component of + /// `receive_messages_proof` call, because the actual inbound lane state is smaller than the + /// maximal configured. + /// + /// Maximal inbound lane state set size is configured by the + /// `MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX` constant from the pallet configuration. The PoV + /// of the call includes the maximal size of inbound lane state. If the actual size is smaller, + /// we may subtract extra bytes from this component. + pub fn extra_proof_size_bytes(&self) -> u64 { + let max_encoded_len = StoredInboundLaneData::::max_encoded_len(); + let relayers_count = self.data().relayers.len(); + let actual_encoded_len = + InboundLaneData::>>::encoded_size_hint(relayers_count) + .unwrap_or(usize::MAX); + max_encoded_len.saturating_sub(actual_encoded_len) as _ + } +} + +impl, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage { + type Relayer = AccountIdOf>; + + fn id(&self) -> LaneId { + self.lane_id + } + + fn max_unrewarded_relayer_entries(&self) -> MessageNonce { + BridgedChainOf::::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX + } + + fn max_unconfirmed_messages(&self) -> MessageNonce { + BridgedChainOf::::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX + } + + fn data(&self) -> InboundLaneData>> { + self.cached_data.clone() + } + + fn set_data(&mut self, data: InboundLaneData>>) { + self.cached_data = data.clone(); + InboundLanes::::insert(self.lane_id, StoredInboundLaneData::(data)) + } + + fn purge(self) { + InboundLanes::::remove(self.lane_id) + } +} + +/// Runtime outbound lane storage. +#[derive(Debug, PartialEq, Eq)] +pub struct RuntimeOutboundLaneStorage { + pub(crate) lane_id: LaneId, + pub(crate) cached_data: OutboundLaneData, + pub(crate) _phantom: PhantomData<(T, I)>, +} + +impl, I: 'static> RuntimeOutboundLaneStorage { + /// Creates new runtime outbound lane storage for given **existing** lane. + fn from_lane_id(lane_id: LaneId, check_active: bool) -> Result { + let cached_data = + OutboundLanes::::get(lane_id).ok_or(LanesManagerError::UnknownOutboundLane)?; + ensure!( + !check_active || cached_data.state.is_active(), + LanesManagerError::ClosedOutboundLane + ); + Ok(Self { lane_id, cached_data, _phantom: PhantomData }) + } +} + +impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorage { + type StoredMessagePayload = StoredMessagePayload; + + fn id(&self) -> LaneId { + self.lane_id + } + + fn data(&self) -> OutboundLaneData { + self.cached_data.clone() + } + + fn set_data(&mut self, data: OutboundLaneData) { + self.cached_data = data.clone(); + OutboundLanes::::insert(self.lane_id, data) + } + + #[cfg(test)] + fn message(&self, nonce: &MessageNonce) -> Option { + OutboundMessages::::get(MessageKey { lane_id: self.lane_id, nonce: *nonce }) + .map(Into::into) + } + + fn save_message(&mut self, nonce: MessageNonce, message_payload: Self::StoredMessagePayload) { + OutboundMessages::::insert( + MessageKey { lane_id: self.lane_id, nonce }, + message_payload, + ); + } + + fn remove_message(&mut self, nonce: &MessageNonce) { + OutboundMessages::::remove(MessageKey { lane_id: self.lane_id, nonce: *nonce }); + } + + fn purge(self) { + OutboundLanes::::remove(self.lane_id) + } +} diff --git a/bridges/modules/messages/src/lib.rs b/bridges/modules/messages/src/lib.rs index 7bb2bb650197..bd18f592c930 100644 --- a/bridges/modules/messages/src/lib.rs +++ b/bridges/modules/messages/src/lib.rs @@ -36,8 +36,13 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -pub use inbound_lane::StoredInboundLaneData; -pub use outbound_lane::StoredMessagePayload; +pub use inbound_lane::{InboundLane, InboundLaneStorage, StoredInboundLaneData}; +pub use lanes_manager::{ + LanesManager, LanesManagerError, RuntimeInboundLaneStorage, RuntimeOutboundLaneStorage, +}; +pub use outbound_lane::{ + OutboundLane, OutboundLaneStorage, ReceptionConfirmationError, StoredMessagePayload, +}; pub use weights::WeightInfo; pub use weights_ext::{ ensure_able_to_receive_confirmation, ensure_able_to_receive_message, @@ -45,11 +50,6 @@ pub use weights_ext::{ EXPECTED_DEFAULT_MESSAGE_LENGTH, EXTRA_STORAGE_PROOF_SIZE, }; -use crate::{ - inbound_lane::{InboundLane, InboundLaneStorage}, - outbound_lane::{OutboundLane, OutboundLaneStorage, ReceptionConfirmationError}, -}; - use bp_header_chain::HeaderChain; use bp_messages::{ source_chain::{ @@ -61,18 +61,19 @@ use bp_messages::{ ProvedLaneMessages, ProvedMessages, }, ChainWithMessages, DeliveredMessages, InboundLaneData, InboundMessageDetails, LaneId, - LaneState, MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData, + MessageKey, MessageNonce, MessagePayload, MessagesOperatingMode, OutboundLaneData, OutboundMessageDetails, UnrewardedRelayersState, VerificationError, }; use bp_runtime::{ AccountIdOf, BasicOperatingMode, HashOf, OwnedBridgeModule, PreComputedSize, RangeInclusiveExt, Size, }; -use codec::{Decode, Encode, MaxEncodedLen}; +use codec::{Decode, Encode}; use frame_support::{dispatch::PostDispatchInfo, ensure, fail, traits::Get, DefaultNoBound}; use sp_std::{marker::PhantomData, prelude::*}; mod inbound_lane; +mod lanes_manager; mod outbound_lane; mod proofs; mod tests; @@ -250,7 +251,7 @@ pub mod pallet { // subtract extra storage proof bytes from the actual PoV size - there may be // less unrewarded relayers than the maximal configured value - let lane_extra_proof_size_bytes = lane.storage_mut().extra_proof_size_bytes(); + let lane_extra_proof_size_bytes = lane.storage().extra_proof_size_bytes(); actual_weight = actual_weight.set_proof_size( actual_weight.proof_size().saturating_sub(lane_extra_proof_size_bytes), ); @@ -263,7 +264,7 @@ pub mod pallet { "Received lane {:?} state update: latest_confirmed_nonce={}. Unrewarded relayers: {:?}", lane_id, updated_latest_confirmed_nonce, - UnrewardedRelayersState::from(&lane.storage_mut().data()), + UnrewardedRelayersState::from(&lane.storage().data()), ); } } @@ -467,20 +468,10 @@ pub mod pallet { NotOperatingNormally, /// The inbound message dispatcher is inactive. MessageDispatchInactive, - /// The outbound lane is unknown. - UnknownOutboundLane, - /// The outbound lane exists, but it is currently closed. - ClosedOutboundLane, - /// The inbound lane is unknown. - UnknownInboundLane, - /// The inbound lane exists, but it is currently closed. - ClosedInboundLane, - /// Message has been treated as invalid by chain verifier. - MessageRejectedByChainVerifier(VerificationError), + /// Error that is reported by the lanes manager. + LanesManager(LanesManagerError), /// Message has been treated as invalid by the pallet logic. MessageRejectedByPallet(VerificationError), - /// Submitter has failed to pay fee for delivering and dispatching messages. - FailedToWithdrawMessageFee, /// The transaction brings too many messages. TooManyMessagesInTheProof, /// Invalid messages has been submitted. @@ -493,8 +484,6 @@ pub mod pallet { /// The cumulative dispatch weight, passed by relayer is not enough to cover dispatch /// of all bundled messages. InsufficientDispatchWeight, - /// The message someone is trying to work with (i.e. increase fee) is not yet sent. - MessageIsNotYetSent, /// Error confirming messages receival. ReceptionConfirmation(ReceptionConfirmationError), /// Error generated by the `OwnedBridgeModule` trait. @@ -706,130 +695,18 @@ fn ensure_normal_operating_mode, I: 'static>() -> Result<(), Error< fn inbound_lane, I: 'static>( lane_id: LaneId, ) -> Result>, Error> { - Ok(InboundLane::new(RuntimeInboundLaneStorage::from_lane_id(lane_id)?)) + LanesManager::::new() + .active_inbound_lane(lane_id) + .map_err(Error::LanesManager) } /// Creates new outbound lane object, backed by runtime storage. fn outbound_lane, I: 'static>( lane_id: LaneId, ) -> Result>, Error> { - Ok(OutboundLane::new(RuntimeOutboundLaneStorage::from_lane_id(lane_id)?)) -} - -/// Runtime inbound lane storage. -struct RuntimeInboundLaneStorage, I: 'static = ()> { - lane_id: LaneId, - cached_data: InboundLaneData>>, - _phantom: PhantomData, -} - -impl, I: 'static> RuntimeInboundLaneStorage { - /// Creates new runtime inbound lane storage for given **existing** lane. - fn from_lane_id(lane_id: LaneId) -> Result, Error> { - let cached_data = - InboundLanes::::get(lane_id).ok_or(Error::::UnknownInboundLane)?; - ensure!(cached_data.state == LaneState::Opened, Error::::ClosedInboundLane); - Ok(RuntimeInboundLaneStorage { - lane_id, - cached_data: cached_data.into(), - _phantom: Default::default(), - }) - } -} - -impl, I: 'static> RuntimeInboundLaneStorage { - /// Returns number of bytes that may be subtracted from the PoV component of - /// `receive_messages_proof` call, because the actual inbound lane state is smaller than the - /// maximal configured. - /// - /// Maximal inbound lane state set size is configured by the - /// `MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX` constant from the pallet configuration. The PoV - /// of the call includes the maximal size of inbound lane state. If the actual size is smaller, - /// we may subtract extra bytes from this component. - pub fn extra_proof_size_bytes(&mut self) -> u64 { - let max_encoded_len = StoredInboundLaneData::::max_encoded_len(); - let relayers_count = self.data().relayers.len(); - let actual_encoded_len = - InboundLaneData::>>::encoded_size_hint(relayers_count) - .unwrap_or(usize::MAX); - max_encoded_len.saturating_sub(actual_encoded_len) as _ - } -} - -impl, I: 'static> InboundLaneStorage for RuntimeInboundLaneStorage { - type Relayer = AccountIdOf>; - - fn id(&self) -> LaneId { - self.lane_id - } - - fn max_unrewarded_relayer_entries(&self) -> MessageNonce { - BridgedChainOf::::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX - } - - fn max_unconfirmed_messages(&self) -> MessageNonce { - BridgedChainOf::::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX - } - - fn data(&self) -> InboundLaneData>> { - self.cached_data.clone() - } - - fn set_data(&mut self, data: InboundLaneData>>) { - self.cached_data = data.clone(); - InboundLanes::::insert(self.lane_id, StoredInboundLaneData::(data)) - } -} - -/// Runtime outbound lane storage. -#[derive(Debug, PartialEq, Eq)] -struct RuntimeOutboundLaneStorage { - lane_id: LaneId, - cached_data: OutboundLaneData, - _phantom: PhantomData<(T, I)>, -} - -impl, I: 'static> RuntimeOutboundLaneStorage { - /// Creates new runtime outbound lane storage for given **existing** lane. - fn from_lane_id(lane_id: LaneId) -> Result> { - let cached_data = - OutboundLanes::::get(lane_id).ok_or(Error::::UnknownOutboundLane)?; - ensure!(cached_data.state == LaneState::Opened, Error::::ClosedOutboundLane); - Ok(Self { lane_id, cached_data, _phantom: PhantomData }) - } -} - -impl, I: 'static> OutboundLaneStorage for RuntimeOutboundLaneStorage { - type StoredMessagePayload = StoredMessagePayload; - - fn id(&self) -> LaneId { - self.lane_id - } - - fn data(&self) -> OutboundLaneData { - self.cached_data.clone() - } - - fn set_data(&mut self, data: OutboundLaneData) { - self.cached_data = data.clone(); - OutboundLanes::::insert(self.lane_id, data) - } - - #[cfg(test)] - fn message(&self, nonce: &MessageNonce) -> Option { - OutboundMessages::::get(MessageKey { lane_id: self.lane_id, nonce: *nonce }) - } - - fn save_message(&mut self, nonce: MessageNonce, message_payload: Self::StoredMessagePayload) { - OutboundMessages::::insert( - MessageKey { lane_id: self.lane_id, nonce }, - message_payload, - ); - } - - fn remove_message(&mut self, nonce: &MessageNonce) { - OutboundMessages::::remove(MessageKey { lane_id: self.lane_id, nonce: *nonce }); - } + LanesManager::::new() + .active_outbound_lane(lane_id) + .map_err(Error::LanesManager) } /// Verify messages proof and return proved messages with decoded payload. diff --git a/bridges/modules/messages/src/outbound_lane.rs b/bridges/modules/messages/src/outbound_lane.rs index 07144afdab81..c27243a5597f 100644 --- a/bridges/modules/messages/src/outbound_lane.rs +++ b/bridges/modules/messages/src/outbound_lane.rs @@ -19,16 +19,18 @@ use crate::{Config, LOG_TARGET}; use bp_messages::{ - ChainWithMessages, DeliveredMessages, LaneId, MessageNonce, OutboundLaneData, UnrewardedRelayer, + ChainWithMessages, DeliveredMessages, LaneId, LaneState, MessageNonce, OutboundLaneData, + UnrewardedRelayer, }; use codec::{Decode, Encode}; use frame_support::{traits::Get, BoundedVec, PalletError}; use scale_info::TypeInfo; use sp_runtime::RuntimeDebug; -use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData}; +use sp_std::{collections::vec_deque::VecDeque, marker::PhantomData, ops::RangeInclusive}; /// Outbound lane storage. pub trait OutboundLaneStorage { + /// Stored message payload type. type StoredMessagePayload; /// Lane id. @@ -44,6 +46,8 @@ pub trait OutboundLaneStorage { fn save_message(&mut self, nonce: MessageNonce, message_payload: Self::StoredMessagePayload); /// Remove outbound message from the storage. fn remove_message(&mut self, nonce: &MessageNonce); + /// Purge lane data from the storage. + fn purge(self); } /// Limit for the `StoredMessagePayload` vector. @@ -91,6 +95,24 @@ impl OutboundLane { self.storage.data() } + /// Get lane state. + pub fn state(&self) -> LaneState { + self.storage.data().state + } + + /// Set lane state. + pub fn set_state(&mut self, state: LaneState) { + let mut data = self.storage.data(); + data.state = state; + self.storage.set_data(data); + } + + /// Return nonces of all currently queued messages. + pub fn queued_messages(&self) -> RangeInclusive { + let data = self.storage.data(); + data.oldest_unpruned_nonce..=data.latest_generated_nonce + } + /// Send message over lane. /// /// Returns new message nonce. @@ -151,6 +173,19 @@ impl OutboundLane { Ok(Some(confirmed_messages)) } + + /// Remove message from the storage. Doesn't perform any checks. + pub fn remove_oldest_unpruned_message(&mut self) { + let mut data = self.storage.data(); + self.storage.remove_message(&data.oldest_unpruned_nonce); + data.oldest_unpruned_nonce += 1; + self.storage.set_data(data); + } + + /// Purge lane state from the storage. + pub fn purge(self) { + self.storage.purge() + } } /// Verifies unrewarded relayers vec. diff --git a/bridges/modules/messages/src/tests/pallet_tests.rs b/bridges/modules/messages/src/tests/pallet_tests.rs index 0b8acd99afc3..581a0cfb75f6 100644 --- a/bridges/modules/messages/src/tests/pallet_tests.rs +++ b/bridges/modules/messages/src/tests/pallet_tests.rs @@ -17,12 +17,13 @@ //! Pallet-level tests. use crate::{ + lanes_manager::RuntimeInboundLaneStorage, outbound_lane, outbound_lane::ReceptionConfirmationError, tests::mock::{RuntimeEvent as TestEvent, *}, weights_ext::WeightInfoExt, - Call, Config, Error, Event, InboundLanes, OutboundLanes, OutboundMessages, Pallet, - PalletOperatingMode, PalletOwner, RuntimeInboundLaneStorage, StoredInboundLaneData, + Call, Config, Error, Event, InboundLanes, LanesManagerError, OutboundLanes, OutboundMessages, + Pallet, PalletOperatingMode, PalletOwner, StoredInboundLaneData, }; use bp_messages::{ @@ -978,12 +979,12 @@ fn send_messages_fails_if_outbound_lane_is_not_opened() { run_test(|| { assert_noop!( Pallet::::validate_message(unknown_lane_id(), ®ULAR_PAYLOAD), - Error::::UnknownOutboundLane, + Error::::LanesManager(LanesManagerError::UnknownOutboundLane), ); assert_noop!( Pallet::::validate_message(closed_lane_id(), ®ULAR_PAYLOAD), - Error::::ClosedOutboundLane, + Error::::LanesManager(LanesManagerError::ClosedOutboundLane), ); }); } @@ -1003,7 +1004,7 @@ fn receive_messages_proof_fails_if_inbound_lane_is_not_opened() { 1, REGULAR_PAYLOAD.declared_weight, ), - Error::::UnknownInboundLane, + Error::::LanesManager(LanesManagerError::UnknownInboundLane), ); message.key.lane_id = closed_lane_id(); @@ -1017,7 +1018,7 @@ fn receive_messages_proof_fails_if_inbound_lane_is_not_opened() { 1, REGULAR_PAYLOAD.declared_weight, ), - Error::::ClosedInboundLane, + Error::::LanesManager(LanesManagerError::ClosedInboundLane), ); }); } @@ -1052,7 +1053,7 @@ fn receive_messages_delivery_proof_fails_if_outbound_lane_is_unknown() { last_delivered_nonce: 1, }, ), - Error::::UnknownOutboundLane, + Error::::LanesManager(LanesManagerError::UnknownOutboundLane), ); let proof = make_proof(closed_lane_id()); @@ -1067,7 +1068,7 @@ fn receive_messages_delivery_proof_fails_if_outbound_lane_is_unknown() { last_delivered_nonce: 1, }, ), - Error::::ClosedOutboundLane, + Error::::LanesManager(LanesManagerError::ClosedOutboundLane), ); }); } diff --git a/bridges/primitives/header-chain/src/lib.rs b/bridges/primitives/header-chain/src/lib.rs index 08d7bcd64f3e..b4d4fa31a293 100644 --- a/bridges/primitives/header-chain/src/lib.rs +++ b/bridges/primitives/header-chain/src/lib.rs @@ -90,6 +90,19 @@ pub trait HeaderChain { } } +impl HeaderChain for () { + fn finalized_header_state_root(_header_hash: HashOf) -> Option> { + None + } + + fn verify_storage_proof( + _header_hash: HashOf, + _db: UnverifiedStorageProof, + ) -> Result { + Err(HeaderChainError::UnknownHeader) + } +} + /// A type that can be used as a parameter in a dispatchable function. /// /// When using `decl_module` all arguments for call functions must implement this trait. diff --git a/bridges/primitives/messages/src/lib.rs b/bridges/primitives/messages/src/lib.rs index 69f254c2db83..4a2b0772655f 100644 --- a/bridges/primitives/messages/src/lib.rs +++ b/bridges/primitives/messages/src/lib.rs @@ -252,6 +252,12 @@ impl TypeId for LaneId { /// Lane state. #[derive(Clone, Copy, Decode, Encode, Eq, PartialEq, TypeInfo, MaxEncodedLen, RuntimeDebug)] pub enum LaneState { + /// Lane is opened and messages may be sent/received over it. + Opened, + /// Lane is closing. It is equal to the `Opened` state, but it will switch to + /// the `Closed` state and then vanish after some period. This state is here + /// to give bridged chain ability to know that the lane is going to be closed. + Closing, /// Lane is closed and all attempts to send/receive messages to/from this lane /// will fail. /// @@ -260,8 +266,13 @@ pub enum LaneState { /// and/or sending messages over the lane, have to coordinate their actions on /// both ends to make sure that lane is operating smoothly on both ends. Closed, - /// Lane is opened and messages may be sent/received over it. - Opened, +} + +impl LaneState { + /// Returns true if lane state allows sending/receiving messages. + pub fn is_active(&self) -> bool { + matches!(*self, LaneState::Opened | LaneState::Closing) + } } /// Message nonce. Valid messages will never have 0 nonce. diff --git a/bridges/primitives/messages/src/target_chain.rs b/bridges/primitives/messages/src/target_chain.rs index 974cb38cbc0a..ca6ce4f55164 100644 --- a/bridges/primitives/messages/src/target_chain.rs +++ b/bridges/primitives/messages/src/target_chain.rs @@ -172,13 +172,9 @@ impl DeliveryPayments for () { /// Structure that may be used in place of `MessageDispatch` on chains, /// where inbound messages are forbidden. -pub struct ForbidInboundMessages( - PhantomData<(MessagesProof, DispatchPayload)>, -); +pub struct ForbidInboundMessages(PhantomData); -impl MessageDispatch - for ForbidInboundMessages -{ +impl MessageDispatch for ForbidInboundMessages { type DispatchPayload = DispatchPayload; type DispatchLevelResult = ();