Skip to content

Commit

Permalink
lp-gateway: Unit tests WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
cdamian committed Aug 13, 2024
1 parent cc08445 commit f5bef43
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 217 deletions.
31 changes: 15 additions & 16 deletions pallets/liquidity-pools-gateway/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@ use message::GatewayMessage;
use orml_traits::GetByKey;
pub use pallet::*;
use parity_scale_codec::{EncodeLike, FullCodec};
use sp_arithmetic::traits::{BaseArithmetic, EnsureSub, One};
use sp_runtime::traits::EnsureAddAssign;
use sp_std::{convert::TryInto, vec::Vec};
use sp_arithmetic::traits::{BaseArithmetic, One};
use sp_std::convert::TryInto;

use crate::{message_processing::InboundEntry, weights::WeightInfo};

Expand Down Expand Up @@ -131,7 +130,7 @@ pub mod pallet {

/// Type used for queueing messages.
type MessageQueue: MessageQueue<
Message = GatewayMessage<Self::AccountId, Self::Message, Self::Hash>,
Message = GatewayMessage<Self::AccountId, Self::Message, Self::RouterId>,
>;

/// Maximum number of routers allowed for a domain.
Expand All @@ -155,8 +154,7 @@ pub mod pallet {
/// The routers for a given domain were set.
RoutersSet {
domain: Domain,
//TODO(cdamian): Use T::RouterId
router_ids: BoundedVec<T::Hash, T::MaxRouterCount>,
router_ids: BoundedVec<T::RouterId, T::MaxRouterCount>,
},

/// An instance was added to a domain.
Expand Down Expand Up @@ -187,7 +185,7 @@ pub mod pallet {
#[pallet::storage]
#[pallet::getter(fn routers)]
pub type Routers<T: Config> =
StorageMap<_, Blake2_128Concat, Domain, BoundedVec<T::Hash, T::MaxRouterCount>>;
StorageMap<_, Blake2_128Concat, Domain, BoundedVec<T::RouterId, T::MaxRouterCount>>;

/// Storage that contains a limited number of whitelisted instances of
/// deployed liquidity pools for a particular domain.
Expand Down Expand Up @@ -222,7 +220,7 @@ pub mod pallet {
Blake2_128Concat,
T::SessionId,
Blake2_128Concat,
(Proof, T::Hash),
(Proof, T::RouterId),
InboundEntry<T>,
>;

Expand Down Expand Up @@ -314,11 +312,12 @@ pub mod pallet {
pub fn set_domain_routers(
origin: OriginFor<T>,
domain: Domain,
//TODO(cdamian): Use T::RouterId
router_ids: BoundedVec<T::Hash, T::MaxRouterCount>,
router_ids: BoundedVec<T::RouterId, T::MaxRouterCount>,
) -> DispatchResult {
T::AdminOrigin::ensure_origin(origin)?;

ensure!(domain != Domain::Centrifuge, Error::<T>::DomainNotSupported);

//TODO(cdamian): Outbound - Call router.init() for each router?

<Routers<T>>::insert(domain.clone(), router_ids.clone());
Expand Down Expand Up @@ -462,8 +461,8 @@ pub mod pallet {
#[pallet::call_index(11)]
pub fn execute_message_recovery(
origin: OriginFor<T>,
domain: Domain,
message_proof: Proof,
proof_count: u32,
) -> DispatchResult {
//TODO(cdamian): Implement this.
unimplemented!()
Expand Down Expand Up @@ -499,20 +498,20 @@ pub mod pallet {
}

impl<T: Config> MessageProcessor for Pallet<T> {
type Message = GatewayMessage<T::AccountId, T::Message, T::Hash>;
type Message = GatewayMessage<T::AccountId, T::Message, T::RouterId>;

fn process(msg: Self::Message) -> (DispatchResult, Weight) {
match msg {
GatewayMessage::Inbound {
domain_address,
message,
router_hash,
} => Self::process_inbound_message(domain_address, message, router_hash),
router_id,
} => Self::process_inbound_message(domain_address, message, router_id),
GatewayMessage::Outbound {
sender,
message,
router_hash,
} => Self::process_outbound_message(sender, message, router_hash),
router_id,
} => Self::process_outbound_message(sender, message, router_id),
}
}

Expand Down
10 changes: 5 additions & 5 deletions pallets/liquidity-pools-gateway/src/message.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use cfg_types::domain_address::{Domain, DomainAddress};
use cfg_types::domain_address::DomainAddress;
use frame_support::pallet_prelude::{Decode, Encode, MaxEncodedLen, TypeInfo};

/// Message type used by the LP gateway.
#[derive(Debug, Encode, Decode, Clone, Eq, MaxEncodedLen, PartialEq, TypeInfo)]
pub enum GatewayMessage<AccountId, Message, Hash> {
pub enum GatewayMessage<AccountId, Message, RouterId> {
Inbound {
domain_address: DomainAddress,
message: Message,
router_hash: Hash,
router_id: RouterId,
},
Outbound {
sender: AccountId,
message: Message,
router_hash: Hash,
router_id: RouterId,
},
}

Expand All @@ -23,7 +23,7 @@ impl<AccountId, Message: Default, Hash: Default> Default
GatewayMessage::Inbound {
domain_address: Default::default(),
message: Default::default(),
router_hash: Default::default(),
router_id: Default::default(),
}
}
}
59 changes: 34 additions & 25 deletions pallets/liquidity-pools-gateway/src/message_processing.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use cfg_primitives::LP_DEFENSIVE_WEIGHT;
use cfg_traits::liquidity_pools::{InboundMessageHandler, LPEncoding, MessageQueue, Proof, Router};
use cfg_traits::liquidity_pools::{InboundMessageHandler, LPEncoding, MessageQueue, Proof};
use cfg_types::domain_address::{Domain, DomainAddress};
use frame_support::{
dispatch::DispatchResult,
Expand Down Expand Up @@ -39,7 +39,7 @@ pub enum InboundEntry<T: Config> {
#[derive(Clone)]
pub struct InboundProcessingInfo<T: Config> {
domain_address: DomainAddress,
routers: BoundedVec<T::Hash, T::MaxRouterCount>,
routers: BoundedVec<T::RouterId, T::MaxRouterCount>,
current_session_id: T::SessionId,
expected_proof_count_per_message: u32,
}
Expand Down Expand Up @@ -91,28 +91,28 @@ impl<T: Config> Pallet<T> {
/// - proofs are not sent by the first inbound router.
fn validate_inbound_entry(
inbound_processing_info: &InboundProcessingInfo<T>,
router_hash: T::Hash,
router_id: &T::RouterId,
inbound_entry: &InboundEntry<T>,
) -> DispatchResult {
let routers = inbound_processing_info.routers.clone();

ensure!(
routers.iter().any(|x| x == &router_hash),
routers.iter().any(|x| x == router_id),
Error::<T>::UnknownInboundMessageRouter
);

match inbound_entry {
InboundEntry::Message { .. } => {
ensure!(
routers.get(0) == Some(&router_hash),
routers.get(0) == Some(&router_id),
Error::<T>::MessageExpectedFromFirstRouter
);

Ok(())
}
InboundEntry::Proof { .. } => {
ensure!(
routers.get(0) != Some(&router_hash),
routers.get(0) != Some(&router_id),
Error::<T>::ProofNotExpectedFromFirstRouter
);

Expand All @@ -126,15 +126,15 @@ impl<T: Config> Pallet<T> {
fn upsert_pending_entry(
session_id: T::SessionId,
message_proof: Proof,
router_hash: T::Hash,
router_id: T::RouterId,
inbound_entry: InboundEntry<T>,
weight: &mut Weight,
) -> DispatchResult {
weight.saturating_accrue(T::DbWeight::get().writes(1));

PendingInboundEntries::<T>::try_mutate(
session_id,
(message_proof, router_hash),
(message_proof, router_id),
|storage_entry| match storage_entry {
None => {
*storage_entry = Some(inbound_entry);
Expand Down Expand Up @@ -170,7 +170,7 @@ impl<T: Config> Pallet<T> {
inbound_processing_info: &InboundProcessingInfo<T>,
message: T::Message,
message_proof: Proof,
router_hash: T::Hash,
router_id: T::RouterId,
weight: &mut Weight,
) -> DispatchResult {
let inbound_entry = Self::create_inbound_entry(
Expand All @@ -179,12 +179,12 @@ impl<T: Config> Pallet<T> {
inbound_processing_info.expected_proof_count_per_message,
);

Self::validate_inbound_entry(&inbound_processing_info, router_hash, &inbound_entry)?;
Self::validate_inbound_entry(&inbound_processing_info, &router_id, &inbound_entry)?;

Self::upsert_pending_entry(
inbound_processing_info.current_session_id,
message_proof,
router_hash,
router_id,
inbound_entry,
weight,
)?;
Expand All @@ -197,11 +197,14 @@ impl<T: Config> Pallet<T> {
fn get_executable_message(
inbound_processing_info: &InboundProcessingInfo<T>,
message_proof: Proof,
weight: &mut Weight,
) -> Option<T::Message> {
let mut message = None;
let mut votes = 0;

for router in &inbound_processing_info.routers {
weight.saturating_accrue(T::DbWeight::get().reads(1));

match PendingInboundEntries::<T>::get(
inbound_processing_info.current_session_id,
(message_proof, router),
Expand Down Expand Up @@ -235,8 +238,11 @@ impl<T: Config> Pallet<T> {
fn decrease_pending_entries_counts(
inbound_processing_info: &InboundProcessingInfo<T>,
message_proof: Proof,
weight: &mut Weight,
) -> DispatchResult {
for router in &inbound_processing_info.routers {
weight.saturating_accrue(T::DbWeight::get().writes(1));

match PendingInboundEntries::<T>::try_mutate(
inbound_processing_info.current_session_id,
(message_proof, router),
Expand Down Expand Up @@ -314,7 +320,7 @@ impl<T: Config> Pallet<T> {
pub(crate) fn process_inbound_message(
domain_address: DomainAddress,
message: T::Message,
router_hash: T::Hash,
router_id: T::RouterId,
) -> (DispatchResult, Weight) {
let mut weight = Default::default();

Expand All @@ -340,17 +346,19 @@ impl<T: Config> Pallet<T> {
&inbound_processing_info,
submessage.clone(),
message_proof,
router_hash,
router_id.clone(),
&mut weight,
) {
return (Err(e), weight);
}

match Self::get_executable_message(&inbound_processing_info, message_proof) {
match Self::get_executable_message(&inbound_processing_info, message_proof, &mut weight)
{
Some(m) => {
if let Err(e) = Self::decrease_pending_entries_counts(
&inbound_processing_info,
message_proof,
&mut weight,
) {
return (Err(e), weight.saturating_mul(count));
}
Expand All @@ -364,21 +372,21 @@ impl<T: Config> Pallet<T> {
}
}

(Ok(()), LP_DEFENSIVE_WEIGHT.saturating_mul(count))
(Ok(()), weight.saturating_mul(count))
}

/// Retrieves the stored router, sends the message, and calculates and
/// returns the router operation result and the weight used.
pub(crate) fn process_outbound_message(
sender: T::AccountId,
message: T::Message,
router_hash: T::Hash,
router_id: T::RouterId,
) -> (DispatchResult, Weight) {
let read_weight = T::DbWeight::get().reads(1);

// TODO(cdamian): Update when the router refactor is done.

// let Some(router) = Routers::<T>::get(router_hash) else {
// let Some(router) = Routers::<T>::get(router_id) else {
// return (Err(Error::<T>::RouterNotFound.into()), read_weight);
// };
//
Expand All @@ -392,16 +400,16 @@ impl<T: Config> Pallet<T> {
(Ok(()), read_weight)
}

/// Retrieves the hashes of the routers set for a domain and queues the
/// Retrieves the IDs of the routers set for a domain and queues the
/// message and proofs accordingly.
pub(crate) fn queue_message(destination: Domain, message: T::Message) -> DispatchResult {
let router_hashes =
let router_ids =
Routers::<T>::get(destination.clone()).ok_or(Error::<T>::MultiRouterNotFound)?;

let message_proof = message.to_message_proof();
let mut message_opt = Some(message);

for router_hash in router_hashes {
for router_id in router_ids {
// Ensure that we only send the actual message once, using one router.
// The remaining routers will send the message proof.
let router_msg = match message_opt.take() {
Expand All @@ -411,11 +419,12 @@ impl<T: Config> Pallet<T> {

// We are using the sender specified in the pallet config so that we can
// ensure that the account is funded
let gateway_message = GatewayMessage::<T::AccountId, T::Message, T::Hash>::Outbound {
sender: T::Sender::get(),
message: router_msg,
router_hash,
};
let gateway_message =
GatewayMessage::<T::AccountId, T::Message, T::RouterId>::Outbound {
sender: T::Sender::get(),
message: router_msg,
router_id,
};

T::MessageQueue::submit(gateway_message)?;
}
Expand Down
2 changes: 0 additions & 2 deletions pallets/liquidity-pools-gateway/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,6 @@ impl pallet_liquidity_pools_gateway::Config for Runtime {
type WeightInfo = ();
}

/*
pub fn new_test_ext() -> sp_io::TestExternalities {
System::externalities()
}
*/
Loading

0 comments on commit f5bef43

Please sign in to comment.