diff --git a/pallet-ismp/rpc/src/lib.rs b/pallet-ismp/rpc/src/lib.rs index fc84fa0..df39fe2 100644 --- a/pallet-ismp/rpc/src/lib.rs +++ b/pallet-ismp/rpc/src/lib.rs @@ -127,6 +127,10 @@ where #[method(name = "ismp_queryStateMachineLatestHeight")] fn query_state_machine_latest_height(&self, id: StateMachineId) -> Result; + /// Query the most recent height at which we've processed requests for a state machine + #[method(name = "ismp_queryLatestMessagingHeight")] + fn query_latest_messaging_height(&self, id: StateMachineId) -> Result; + /// Query ISMP Events that were deposited in a series of blocks /// Using String keys because HashMap fails to deserialize when key is not a String #[method(name = "ismp_queryEvents")] @@ -390,4 +394,12 @@ where } Ok(events) } + + fn query_latest_messaging_height(&self, id: StateMachineId) -> Result { + let api = self.client.runtime_api(); + let at = self.client.info().best_hash; + api.latest_messaging_height(at, id).ok().flatten().ok_or_else(|| { + runtime_error_into_rpc_error("Error fetching latest state machine height") + }) + } } diff --git a/pallet-ismp/runtime-api/src/lib.rs b/pallet-ismp/runtime-api/src/lib.rs index a8364c5..7384add 100644 --- a/pallet-ismp/runtime-api/src/lib.rs +++ b/pallet-ismp/runtime-api/src/lib.rs @@ -60,6 +60,9 @@ sp_api::decl_runtime_apis! { /// Return the latest height of the state machine fn latest_state_machine_height(id: StateMachineId) -> Option; + /// Return the most recent height we've processed requests for a state machine + fn latest_messaging_height(id: StateMachineId) -> Option; + /// Get Request Leaf Indices fn get_request_leaf_indices(leaf_queries: Vec) -> Vec; diff --git a/pallet-ismp/src/lib.rs b/pallet-ismp/src/lib.rs index a940dd8..349cb3f 100644 --- a/pallet-ismp/src/lib.rs +++ b/pallet-ismp/src/lib.rs @@ -65,7 +65,7 @@ use ismp_primitives::{ mmr::{DataOrHash, Leaf, LeafIndex, NodeIndex}, LeafIndexQuery, }; -use ismp_rs::{host::IsmpHost, messaging::Message}; +use ismp_rs::{consensus::StateMachineHeight, host::IsmpHost, messaging::Message}; pub use pallet::*; use sp_runtime::RuntimeDebug; use sp_std::prelude::*; @@ -170,10 +170,16 @@ pub mod pallet { /// Holds a map of state machines to the height at which they've been frozen due to byzantine /// behaviour #[pallet::storage] - #[pallet::getter(fn frozen_heights)] + #[pallet::getter(fn latest_messaging_heights)] pub type FrozenHeights = StorageMap<_, Blake2_128Concat, StateMachineId, u64, OptionQuery>; + /// Holds a map of state machines to the latest height we've processed requests for + #[pallet::storage] + #[pallet::getter(fn frozen_heights)] + pub type LatestMessagingHeight = + StorageMap<_, Blake2_128Concat, StateMachineId, u64, ValueQuery>; + /// A mapping of ConsensusStateId to ConsensusClientId #[pallet::storage] pub type ConsensusStateClient = @@ -468,7 +474,7 @@ impl Pallet { let mut errors: Vec = vec![]; let total_weight = get_weight::(&messages); for message in messages { - match handle_incoming_message(&host, message) { + match handle_incoming_message(&host, message.clone()) { Ok(MessageResult::ConsensusMessage(res)) => { // check if this is a trusted state machine let is_trusted_state_machine = host @@ -508,9 +514,25 @@ impl Pallet { } } Ok(MessageResult::Response(res)) => { + let StateMachineHeight { id, height } = match message { + Message::Request(ref request) => request.proof.height.clone(), + _ => unreachable!(), + }; + // update the messaging heights + if LatestMessagingHeight::::get(&id) > height { + LatestMessagingHeight::::insert(id, height); + } debug!(target: "ismp-modules", "Module Callback Results {:?}", ModuleCallbackResult::Response(res)); } Ok(MessageResult::Request(res)) => { + let StateMachineHeight { id, height } = match message { + Message::Request(ref request) => request.proof.height.clone(), + _ => unreachable!(), + }; + // update the messaging heights + if LatestMessagingHeight::::get(&id) > height { + LatestMessagingHeight::::insert(id, height); + } debug!(target: "ismp-modules", "Module Callback Results {:?}", ModuleCallbackResult::Request(res)); } Ok(MessageResult::Timeout(res)) => {