Skip to content

Commit

Permalink
lp-gateway: Add extrinsic for executing message recovery
Browse files Browse the repository at this point in the history
  • Loading branch information
cdamian committed Aug 13, 2024
1 parent f5bef43 commit c6dc81a
Show file tree
Hide file tree
Showing 4 changed files with 329 additions and 56 deletions.
85 changes: 66 additions & 19 deletions pallets/liquidity-pools-gateway/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ mod tests;
#[frame_support::pallet]
pub mod pallet {
use frame_system::pallet_prelude::BlockNumberFor;
use sp_arithmetic::traits::EnsureAdd;
use sp_arithmetic::traits::{EnsureAdd, EnsureAddAssign};

use super::*;

Expand Down Expand Up @@ -155,6 +155,7 @@ pub mod pallet {
RoutersSet {
domain: Domain,
router_ids: BoundedVec<T::RouterId, T::MaxRouterCount>,
session_id: T::SessionId,
},

/// An instance was added to a domain.
Expand All @@ -168,6 +169,13 @@ pub mod pallet {
domain: Domain,
hook_address: [u8; 20],
},

/// Message recovery was executed.
MessageRecoveryExecuted {
domain: Domain,
proof: Proof,
router_id: T::RouterId,
},
}

// TODO(cdamian): Add migration to clear this storage.
Expand Down Expand Up @@ -239,8 +247,8 @@ pub mod pallet {
/// Any `PendingInboundEntries` mapped to the invalid IDs are removed from
/// storage during `on_idle`.
#[pallet::storage]
#[pallet::getter(fn invalid_session_ids)]
pub type InvalidSessionIds<T: Config> = StorageMap<_, Blake2_128Concat, T::SessionId, ()>;
#[pallet::getter(fn invalid_message_sessions)]
pub type InvalidMessageSessions<T: Config> = StorageMap<_, Blake2_128Concat, T::SessionId, ()>;

#[pallet::error]
pub enum Error<T> {
Expand All @@ -259,8 +267,8 @@ pub mod pallet {
/// Unknown instance.
UnknownInstance,

/// Router not found.
RouterNotFound,
/// Routers not found.
RoutersNotFound,

/// Emitted when you call `start_batch_messages()` but that was already
/// called. You should finalize the message with `end_batch_messages()`
Expand Down Expand Up @@ -294,9 +302,6 @@ pub mod pallet {
/// Pending inbound entry not found.
PendingInboundEntryNotFound,

/// Multi-router not found.
MultiRouterNotFound,

/// Message proof cannot be retrieved.
MessageProofRetrieval,

Expand All @@ -322,19 +327,23 @@ pub mod pallet {

<Routers<T>>::insert(domain.clone(), router_ids.clone());

let (old_session_id, new_session_id) = SessionIdStore::<T>::try_mutate(|n| {
let old_session_id = *n;
let new_session_id = old_session_id.ensure_add(One::one())?;
if let Some(old_session_id) = InboundMessageSessions::<T>::get(domain.clone()) {
InvalidMessageSessions::<T>::insert(old_session_id, ());
}

*n = new_session_id;
let session_id = SessionIdStore::<T>::try_mutate(|n| {
n.ensure_add_assign(One::one())?;

Ok::<(T::SessionId, T::SessionId), DispatchError>((old_session_id, new_session_id))
Ok::<T::SessionId, DispatchError>(*n)
})?;

InboundMessageSessions::<T>::insert(domain.clone(), new_session_id);
InvalidSessionIds::<T>::insert(old_session_id, ());
InboundMessageSessions::<T>::insert(domain.clone(), session_id);

Self::deposit_event(Event::RoutersSet { domain, router_ids });
Self::deposit_event(Event::RoutersSet {
domain,
router_ids,
session_id,
});

Ok(())
}
Expand Down Expand Up @@ -462,10 +471,48 @@ pub mod pallet {
pub fn execute_message_recovery(
origin: OriginFor<T>,
domain: Domain,
message_proof: Proof,
proof: Proof,
router_id: T::RouterId,
) -> DispatchResult {
//TODO(cdamian): Implement this.
unimplemented!()
T::AdminOrigin::ensure_origin(origin)?;

let session_id = InboundMessageSessions::<T>::get(&domain)
.ok_or(Error::<T>::InboundDomainSessionNotFound)?;

let routers = Routers::<T>::get(&domain).ok_or(Error::<T>::RoutersNotFound)?;

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

PendingInboundEntries::<T>::try_mutate(
session_id,
(proof, router_id.clone()),
|storage_entry| match storage_entry {
Some(entry) => match entry {
InboundEntry::Proof { current_count } => {
current_count.ensure_add_assign(1).map_err(|e| e.into())
}
InboundEntry::Message { .. } => {
Err(Error::<T>::ExpectedMessageProofType.into())
}
},
None => {
*storage_entry = Some(InboundEntry::<T>::Proof { current_count: 1 });

Ok::<(), DispatchError>(())
}
},
)?;

Self::deposit_event(Event::<T>::MessageRecoveryExecuted {
domain,
proof,
router_id,
});

Ok(())
}
}

Expand Down
12 changes: 6 additions & 6 deletions pallets/liquidity-pools-gateway/src/message_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use sp_arithmetic::traits::{EnsureAddAssign, EnsureSub};
use sp_runtime::DispatchError;

use crate::{
message::GatewayMessage, Config, Error, InboundMessageSessions, InvalidSessionIds, Pallet,
message::GatewayMessage, Config, Error, InboundMessageSessions, InvalidMessageSessions, Pallet,
PendingInboundEntries, Routers,
};

Expand Down Expand Up @@ -48,7 +48,7 @@ impl<T: Config> Pallet<T> {
/// Calculates and returns the proof count required for processing one
/// inbound message.
fn get_expected_proof_count(domain: &Domain) -> Result<u32, DispatchError> {
let routers = Routers::<T>::get(domain).ok_or(Error::<T>::MultiRouterNotFound)?;
let routers = Routers::<T>::get(domain).ok_or(Error::<T>::RoutersNotFound)?;

let expected_proof_count = routers.len().ensure_sub(1)?;

Expand Down Expand Up @@ -294,7 +294,7 @@ impl<T: Config> Pallet<T> {
weight: &mut Weight,
) -> Result<InboundProcessingInfo<T>, DispatchError> {
let routers =
Routers::<T>::get(domain_address.domain()).ok_or(Error::<T>::MultiRouterNotFound)?;
Routers::<T>::get(domain_address.domain()).ok_or(Error::<T>::RoutersNotFound)?;

weight.saturating_accrue(T::DbWeight::get().reads(1));

Expand Down Expand Up @@ -404,7 +404,7 @@ impl<T: Config> Pallet<T> {
/// message and proofs accordingly.
pub(crate) fn queue_message(destination: Domain, message: T::Message) -> DispatchResult {
let router_ids =
Routers::<T>::get(destination.clone()).ok_or(Error::<T>::MultiRouterNotFound)?;
Routers::<T>::get(destination.clone()).ok_or(Error::<T>::RoutersNotFound)?;

let message_proof = message.to_message_proof();
let mut message_opt = Some(message);
Expand Down Expand Up @@ -438,7 +438,7 @@ impl<T: Config> Pallet<T> {
/// The invalid session IDs are removed from storage if all entries mapped
/// to them were cleared.
pub(crate) fn clear_invalid_session_ids(max_weight: Weight) -> Weight {
let invalid_session_ids = InvalidSessionIds::<T>::iter_keys().collect::<Vec<_>>();
let invalid_session_ids = InvalidMessageSessions::<T>::iter_keys().collect::<Vec<_>>();

let mut weight = T::DbWeight::get().reads(1);

Expand All @@ -462,7 +462,7 @@ impl<T: Config> Pallet<T> {

cursor = match res.maybe_cursor {
None => {
InvalidSessionIds::<T>::remove(invalid_session_id);
InvalidMessageSessions::<T>::remove(invalid_session_id);

weight.saturating_accrue(T::DbWeight::get().writes(1));

Expand Down
2 changes: 1 addition & 1 deletion pallets/liquidity-pools-gateway/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ impl pallet_liquidity_pools_gateway::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeOrigin = RuntimeOrigin;
type Sender = Sender;
type SessionId = u64;
type SessionId = u32;
type WeightInfo = ();
}

Expand Down
Loading

0 comments on commit c6dc81a

Please sign in to comment.