diff --git a/libs/traits/src/liquidity_pools.rs b/libs/traits/src/liquidity_pools.rs index a0d73d98a3..8d983d272b 100644 --- a/libs/traits/src/liquidity_pools.rs +++ b/libs/traits/src/liquidity_pools.rs @@ -20,12 +20,16 @@ pub type MessageHash = [u8; 32]; /// An encoding & decoding trait for the purpose of meeting the /// LiquidityPools General Message Passing Format -pub trait LpMessage: Sized { - type Domain; - +pub trait LpMessageSerializer: Sized { + /// Serialize the message fn serialize(&self) -> Vec; + + /// Deserialize the message fn deserialize(input: &[u8]) -> Result; +} +/// Behavior or a message that can be batched +pub trait LpMessageBatch: Sized { /// Extend this message with a new one fn pack_with(&mut self, other: Self) -> DispatchResult; @@ -36,16 +40,25 @@ pub trait LpMessage: Sized { /// Creates an empty message. /// It's the identity message for composing messages with pack_with fn empty() -> Self; +} - /// Returns whether the message is a proof or not. - fn is_proof_message(&self) -> bool; - +/// Support for hashing +pub trait LpMessageHash { /// Retrieves the message hash, if the message is a proof type. fn get_message_hash(&self) -> MessageHash; +} + +/// Behavior of a message that can support proofs +pub trait LpMessageProof: LpMessageHash { + /// Returns whether the message is a proof or not. + fn is_proof_message(&self) -> bool; /// Converts the message into a message proof type. fn to_proof_message(&self) -> Self; +} +//Behavior of a message that support recovery +pub trait LpMessageRecovery: LpMessageHash { /// Creates a message used for initiating message recovery. /// /// Hash - hash of the message that should be recovered. @@ -57,6 +70,11 @@ pub trait LpMessage: Sized { /// Hash - hash of the message that should be disputed. /// Router - the address of the recovery router. fn dispute_recovery_message(hash: MessageHash, router: [u8; 32]) -> Self; +} + +/// Behavior of a message that can be forwarded +pub trait LpMessageForwarded: Sized { + type Domain; /// Checks whether a message is a forwarded one. fn is_forwarded(&self) -> bool; diff --git a/pallets/liquidity-pools-forwarder/src/lib.rs b/pallets/liquidity-pools-forwarder/src/lib.rs index 05e4800ee8..78eaf60f47 100644 --- a/pallets/liquidity-pools-forwarder/src/lib.rs +++ b/pallets/liquidity-pools-forwarder/src/lib.rs @@ -35,7 +35,7 @@ mod tests; use core::fmt::Debug; -use cfg_traits::liquidity_pools::{LpMessage as LpMessageT, MessageReceiver, MessageSender}; +use cfg_traits::liquidity_pools::{LpMessageForwarded, MessageReceiver, MessageSender}; use cfg_types::domain_address::{Domain, DomainAddress}; use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; use frame_system::pallet_prelude::OriginFor; @@ -77,7 +77,7 @@ pub mod pallet { type RuntimeEvent: From> + IsType<::RuntimeEvent>; /// The Liquidity Pools message type. - type Message: LpMessageT + type Message: LpMessageForwarded + Clone + Debug + PartialEq diff --git a/pallets/liquidity-pools-forwarder/src/mock.rs b/pallets/liquidity-pools-forwarder/src/mock.rs index 24cc25f73d..c30bf2fcbb 100644 --- a/pallets/liquidity-pools-forwarder/src/mock.rs +++ b/pallets/liquidity-pools-forwarder/src/mock.rs @@ -1,8 +1,7 @@ -use cfg_traits::liquidity_pools::{LpMessage, MessageHash}; +use cfg_traits::liquidity_pools::LpMessageForwarded; use cfg_types::domain_address::{Domain, DomainAddress}; use frame_support::{ derive_impl, - dispatch::DispatchResult, pallet_prelude::{Decode, Encode, MaxEncodedLen, TypeInfo}, weights::constants::RocksDbWeight, }; @@ -25,8 +24,6 @@ pub const SOURCE_DOMAIN_ADDRESS: DomainAddress = DomainAddress::Evm(SOURCE_CHAIN_ID, FORWARD_CONTRACT); pub const FORWARD_CONTRACT: H160 = H160::repeat_byte(2); pub const ROUTER_ID: RouterId = 1u32; -const FORWARD_SERIALIZED_MESSAGE_BYTES: [u8; 1] = [0x42]; -const NON_FORWARD_SERIALIZED_MESSAGE_BYTES: [u8; 1] = [0x43]; pub const ERROR_NESTING: DispatchError = DispatchError::Other("Nesting forward msg not allowed"); #[derive(Eq, PartialEq, Debug, Clone, Encode, Decode, TypeInfo, MaxEncodedLen, Hash)] @@ -35,56 +32,9 @@ pub enum Message { Forward, } -impl LpMessage for Message { +impl LpMessageForwarded for Message { type Domain = Domain; - fn serialize(&self) -> Vec { - match self { - Message::NonForward => NON_FORWARD_SERIALIZED_MESSAGE_BYTES.to_vec(), - Message::Forward => FORWARD_SERIALIZED_MESSAGE_BYTES.to_vec(), - } - } - - fn deserialize(input: &[u8]) -> Result { - match input { - x if x == &NON_FORWARD_SERIALIZED_MESSAGE_BYTES[..] => Ok(Self::NonForward), - x if x == &FORWARD_SERIALIZED_MESSAGE_BYTES[..] => Ok(Self::Forward), - _ => unimplemented!(), - } - } - - fn pack_with(&mut self, _: Self) -> DispatchResult { - unimplemented!("out of scope") - } - - fn submessages(&self) -> Vec { - unimplemented!("out of scope") - } - - fn empty() -> Self { - unimplemented!("out of scope") - } - - fn to_proof_message(&self) -> Self { - unimplemented!("out of scope") - } - - fn is_proof_message(&self) -> bool { - unimplemented!("out of scope") - } - - fn get_message_hash(&self) -> MessageHash { - unimplemented!("out of scope") - } - - fn initiate_recovery_message(_: [u8; 32], _: [u8; 32]) -> Self { - unimplemented!("out of scope") - } - - fn dispute_recovery_message(_: [u8; 32], _: [u8; 32]) -> Self { - unimplemented!("out of scope") - } - fn is_forwarded(&self) -> bool { matches!(self, Self::Forward) } diff --git a/pallets/liquidity-pools-gateway/src/lib.rs b/pallets/liquidity-pools-gateway/src/lib.rs index 8e6be6b4b8..5cb0b47712 100644 --- a/pallets/liquidity-pools-gateway/src/lib.rs +++ b/pallets/liquidity-pools-gateway/src/lib.rs @@ -30,8 +30,9 @@ use core::fmt::Debug; use cfg_primitives::LP_DEFENSIVE_WEIGHT; use cfg_traits::liquidity_pools::{ - InboundMessageHandler, LpMessage, MessageHash, MessageProcessor, MessageQueue, MessageReceiver, - MessageSender, OutboundMessageHandler, RouterProvider, + InboundMessageHandler, LpMessageBatch, LpMessageProof, LpMessageRecovery, LpMessageSerializer, + MessageHash, MessageProcessor, MessageQueue, MessageReceiver, MessageSender, + OutboundMessageHandler, RouterProvider, }; use cfg_types::domain_address::{Domain, DomainAddress}; use frame_support::{dispatch::DispatchResult, pallet_prelude::*}; @@ -97,7 +98,10 @@ pub mod pallet { type AdminOrigin: EnsureOrigin<::RuntimeOrigin>; /// The Liquidity Pools message type. - type Message: LpMessage + type Message: LpMessageSerializer + + LpMessageBatch + + LpMessageProof + + LpMessageRecovery + Clone + Debug + PartialEq diff --git a/pallets/liquidity-pools-gateway/src/message_processing.rs b/pallets/liquidity-pools-gateway/src/message_processing.rs index 89230e18c6..5d681f41bd 100644 --- a/pallets/liquidity-pools-gateway/src/message_processing.rs +++ b/pallets/liquidity-pools-gateway/src/message_processing.rs @@ -1,5 +1,6 @@ use cfg_traits::liquidity_pools::{ - InboundMessageHandler, LpMessage, MessageHash, MessageQueue, RouterProvider, + InboundMessageHandler, LpMessageBatch, LpMessageHash, LpMessageProof, MessageHash, + MessageQueue, RouterProvider, }; use cfg_types::domain_address::{Domain, DomainAddress}; use frame_support::{ diff --git a/pallets/liquidity-pools-gateway/src/mock.rs b/pallets/liquidity-pools-gateway/src/mock.rs index ced65ba8d8..d082646f37 100644 --- a/pallets/liquidity-pools-gateway/src/mock.rs +++ b/pallets/liquidity-pools-gateway/src/mock.rs @@ -1,7 +1,10 @@ use std::fmt::{Debug, Formatter}; use cfg_mocks::pallet_mock_liquidity_pools; -use cfg_traits::liquidity_pools::{LpMessage, MessageHash, RouterProvider}; +use cfg_traits::liquidity_pools::{ + LpMessageBatch, LpMessageHash, LpMessageProof, LpMessageRecovery, LpMessageSerializer, + MessageHash, RouterProvider, +}; use cfg_types::{ domain_address::{Domain, DomainAddress}, EVMChainId, @@ -59,9 +62,7 @@ impl MaxEncodedLen for Message { } } -impl LpMessage for Message { - type Domain = Domain; - +impl LpMessageSerializer for Message { fn serialize(&self) -> Vec { match self { Self::Pack(list) => list.iter().map(|_| 0x42).collect(), @@ -76,7 +77,9 @@ impl LpMessage for Message { n => Self::Pack(sp_std::iter::repeat(Self::Simple).take(n).collect()), }) } +} +impl LpMessageBatch for Message { fn pack_with(&mut self, other: Self) -> DispatchResult { match self { Self::Pack(list) if list.len() == MAX_PACKED_MESSAGES => { @@ -103,14 +106,18 @@ impl LpMessage for Message { fn empty() -> Self { Self::Pack(vec![]) } +} - fn is_proof_message(&self) -> bool { - matches!(self, Message::Proof(..)) - } - +impl LpMessageHash for Message { fn get_message_hash(&self) -> MessageHash { MESSAGE_HASH } +} + +impl LpMessageProof for Message { + fn is_proof_message(&self) -> bool { + matches!(self, Message::Proof(..)) + } fn to_proof_message(&self) -> Self { match self { @@ -118,7 +125,9 @@ impl LpMessage for Message { _ => Message::Proof(self.get_message_hash()), } } +} +impl LpMessageRecovery for Message { fn initiate_recovery_message(hash: MessageHash, router: [u8; 32]) -> Self { Self::InitiateMessageRecovery((hash, router)) } @@ -126,18 +135,6 @@ impl LpMessage for Message { fn dispute_recovery_message(hash: MessageHash, router: [u8; 32]) -> Self { Self::DisputeMessageRecovery((hash, router)) } - - fn is_forwarded(&self) -> bool { - unimplemented!("out of scope") - } - - fn unwrap_forwarded(self) -> Option<(Self::Domain, H160, Self)> { - unimplemented!("out of scope") - } - - fn try_wrap_forward(_: Self::Domain, _: H160, _: Self) -> Result { - unimplemented!("out of scope") - } } #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen, Hash)] diff --git a/pallets/liquidity-pools-gateway/src/tests.rs b/pallets/liquidity-pools-gateway/src/tests.rs index 1a03f69a79..4c24b5d31b 100644 --- a/pallets/liquidity-pools-gateway/src/tests.rs +++ b/pallets/liquidity-pools-gateway/src/tests.rs @@ -1,7 +1,9 @@ use std::collections::HashMap; use cfg_primitives::LP_DEFENSIVE_WEIGHT; -use cfg_traits::liquidity_pools::{LpMessage, MessageProcessor, OutboundMessageHandler}; +use cfg_traits::liquidity_pools::{ + LpMessageHash, LpMessageSerializer, MessageProcessor, OutboundMessageHandler, +}; use cfg_types::domain_address::*; use frame_support::{assert_err, assert_noop, assert_ok}; use itertools::Itertools; diff --git a/pallets/liquidity-pools/src/message.rs b/pallets/liquidity-pools/src/message.rs index f786600319..f3b3713023 100644 --- a/pallets/liquidity-pools/src/message.rs +++ b/pallets/liquidity-pools/src/message.rs @@ -6,7 +6,10 @@ //! representation for each message variant. use cfg_traits::{ - liquidity_pools::{LpMessage, MessageHash}, + liquidity_pools::{ + LpMessageBatch, LpMessageForwarded, LpMessageHash, LpMessageProof, LpMessageRecovery, + LpMessageSerializer, MessageHash, + }, Seconds, }; use cfg_types::domain_address::Domain; @@ -574,9 +577,7 @@ pub enum Message Vec { gmpf::to_vec(self).unwrap_or_default() } @@ -584,7 +585,9 @@ impl LpMessage for Message { fn deserialize(data: &[u8]) -> Result { gmpf::from_slice(data).map_err(|_| DispatchError::Other("LP Deserialization issue")) } +} +impl LpMessageBatch for Message { fn pack_with(&mut self, other: Self) -> Result<(), DispatchError> { match self { Message::Batch(content) => content.try_add(other), @@ -605,13 +608,17 @@ impl LpMessage for Message { fn empty() -> Message { Message::Batch(BatchMessages::default()) } +} - fn is_proof_message(&self) -> bool { - matches!(self, Message::MessageProof { .. }) +impl LpMessageHash for Message { + fn get_message_hash(&self) -> MessageHash { + keccak_256(&LpMessageSerializer::serialize(self)) } +} - fn get_message_hash(&self) -> MessageHash { - keccak_256(&LpMessage::serialize(self)) +impl LpMessageProof for Message { + fn is_proof_message(&self) -> bool { + matches!(self, Message::MessageProof { .. }) } fn to_proof_message(&self) -> Self { @@ -619,7 +626,9 @@ impl LpMessage for Message { hash: self.get_message_hash(), } } +} +impl LpMessageRecovery for Message { fn initiate_recovery_message(hash: MessageHash, router: [u8; 32]) -> Self { Message::InitiateMessageRecovery { hash, router } } @@ -627,6 +636,10 @@ impl LpMessage for Message { fn dispute_recovery_message(hash: MessageHash, router: [u8; 32]) -> Self { Message::DisputeMessageRecovery { hash, router } } +} + +impl LpMessageForwarded for Message { + type Domain = Domain; fn is_forwarded(&self) -> bool { matches!(self, Message::Forwarded { .. }) diff --git a/runtime/common/src/routing.rs b/runtime/common/src/routing.rs index 7b804923f3..e6b4663dbe 100644 --- a/runtime/common/src/routing.rs +++ b/runtime/common/src/routing.rs @@ -1,5 +1,5 @@ use cfg_traits::{ - liquidity_pools::{LpMessage, MessageReceiver, MessageSender, RouterProvider}, + liquidity_pools::{LpMessageSerializer, MessageReceiver, MessageSender, RouterProvider}, PreConditions, }; use cfg_types::domain_address::{Domain, DomainAddress}; @@ -71,6 +71,7 @@ where } } +/// A precondition to ensure an evm account code is configured for a contract pub struct EvmAccountCodeChecker(PhantomData); impl PreConditions<(H160, H256)> for EvmAccountCodeChecker { type Result = bool; @@ -81,6 +82,7 @@ impl PreConditions<(H160, H256)> for EvmAccountCode } } +/// Entity in charge of serializing and deserializing messages pub struct MessageSerializer(PhantomData<(Sender, Receiver)>); impl MessageSender for MessageSerializer diff --git a/runtime/integration-tests/src/cases/routers.rs b/runtime/integration-tests/src/cases/routers.rs index dd58bed554..e9faf809b1 100644 --- a/runtime/integration-tests/src/cases/routers.rs +++ b/runtime/integration-tests/src/cases/routers.rs @@ -1,5 +1,5 @@ use cfg_primitives::Balance; -use cfg_traits::liquidity_pools::{LpMessage, MessageProcessor}; +use cfg_traits::liquidity_pools::{LpMessageSerializer, MessageProcessor}; use cfg_types::{ domain_address::{Domain, DomainAddress}, EVMChainId,