diff --git a/ismp-testsuite/src/mocks.rs b/ismp-testsuite/src/mocks.rs index 1b9d072..f26f137 100644 --- a/ismp-testsuite/src/mocks.rs +++ b/ismp-testsuite/src/mocks.rs @@ -291,6 +291,14 @@ impl IsmpHost for Host { todo!() } + fn allowed_proxies(&self) -> Vec { + todo!() + } + + fn store_allowed_proxies(&self, _allowed: Vec) { + todo!() + } + fn unbonding_period(&self, _consensus_state_id: ConsensusStateId) -> Option { Some(Duration::from_secs(60 * 60 * 60)) } diff --git a/ismp/src/handlers/request.rs b/ismp/src/handlers/request.rs index 08b806c..006e555 100644 --- a/ismp/src/handlers/request.rs +++ b/ismp/src/handlers/request.rs @@ -18,7 +18,7 @@ use crate::{ error::Error, handlers::{validate_state_machine, MessageResult}, - host::IsmpHost, + host::{IsmpHost, StateMachine}, messaging::RequestMessage, module::{DispatchError, DispatchSuccess}, router::{Request, RequestResponse}, @@ -41,6 +41,10 @@ where &msg.proof, )?; + let check_source = |source: StateMachine| -> bool { + msg.proof.height.id.state_id == source || host.is_allowed_proxy(&source) + }; + let router = host.ismp_router(); // If a receipt exists for any request then it's a duplicate and it is not dispatched let result = msg @@ -48,7 +52,9 @@ where .into_iter() .filter(|req| { let req = Request::Post(req.clone()); - host.request_receipt(&req).is_none() && !req.timed_out(state.timestamp()) + host.request_receipt(&req).is_none() && + !req.timed_out(state.timestamp()) && + check_source(req.source_chain()) }) .map(|request| { let cb = router.module_for_id(request.to.clone())?; diff --git a/ismp/src/host.rs b/ismp/src/host.rs index f428d80..8d0aeb0 100644 --- a/ismp/src/host.rs +++ b/ismp/src/host.rs @@ -173,6 +173,17 @@ pub trait IsmpHost { Ok(()) } + /// return the state machines that are allowed to proxy requests. + fn allowed_proxies(&self) -> Vec; + + /// Store the whitelist of allowed proxies, this should overwrite the existing whitelist. + fn store_allowed_proxies(&self, allowed: Vec); + + /// Checks if the host allows this state machine to proxy requests. + fn is_allowed_proxy(&self, source: &StateMachine) -> bool { + self.allowed_proxies().iter().any(|proxy| proxy == source) + } + /// Return the unbonding period (i.e the time it takes for a validator's deposit to be unstaked /// from the network) fn unbonding_period(&self, consensus_state_id: ConsensusStateId) -> Option; @@ -224,9 +235,9 @@ impl ToString for StateMachine { fn to_string(&self) -> String { match self { StateMachine::Ethereum(ethereum) => match ethereum { - Ethereum::ExecutionLayer => "ETHE".to_string(), - Ethereum::Arbitrum => "ARBI".to_string(), - Ethereum::Optimism => "OPTI".to_string(), + Ethereum::ExecutionLayer => "ETH".to_string(), + Ethereum::Arbitrum => "ARB".to_string(), + Ethereum::Optimism => "OP".to_string(), Ethereum::Base => "BASE".to_string(), }, StateMachine::Polkadot(id) => format!("POLKADOT-{id}"),