Skip to content

Commit

Permalink
Update ismp (#38)
Browse files Browse the repository at this point in the history
* update ismp-rs

* nit
  • Loading branch information
Wizdave97 authored May 18, 2023
1 parent 237b3bf commit fa50fe4
Show file tree
Hide file tree
Showing 11 changed files with 443 additions and 179 deletions.
452 changes: 313 additions & 139 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions ismp-assets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.

//! ISMP Assets
//! Simple Demo for Asset transfer over ISMP
#![cfg_attr(not(feature = "std"), no_std)]

extern crate alloc;
Expand Down
1 change: 1 addition & 0 deletions pallet-ismp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ ismp-primitives = { path = "./primitives", default-features = false }
[dev-dependencies]
env_logger = "0.10.0"
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" }
ismp-testsuite = { git = "ssh://[email protected]/polytope-labs/ismp-rs.git", branch = "main" }

[features]
default = ["std"]
Expand Down
2 changes: 2 additions & 0 deletions pallet-ismp/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ pub enum HandlingError {
source: StateMachine,
dest: StateMachine,
},
InsufficientProofHeight,
}

impl From<ismp_rs::error::Error> for HandlingError {
Expand Down Expand Up @@ -145,6 +146,7 @@ impl From<ismp_rs::error::Error> for HandlingError {
IsmpError::RequestTimeoutVerificationFailed { nonce, source, dest } => {
HandlingError::RequestTimeoutVerificationFailed { nonce, source, dest }
}
IsmpError::InsufficientProofHeight => HandlingError::InsufficientProofHeight,
}
}
}
31 changes: 29 additions & 2 deletions pallet-ismp/src/host.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
primitives::ConsensusClientProvider, Config, ConsensusClientUpdateTime, ConsensusStates,
FrozenHeights, LatestStateMachineHeight, RequestAcks, StateCommitments,
primitives::ConsensusClientProvider, router::Receipt, Config, ConsensusClientUpdateTime,
ConsensusStates, FrozenHeights, LatestStateMachineHeight, RequestAcks, StateCommitments,
};
use alloc::{format, string::ToString};
use core::time::Duration;
Expand Down Expand Up @@ -88,6 +88,20 @@ where
Ok(commitment)
}

fn get_request_receipt(&self, req: &Request) -> Option<()> {
let commitment = hash_request::<Self>(req);

let _ = RequestAcks::<T>::get(commitment.0.to_vec())
.ok_or_else(|| Error::RequestCommitmentNotFound {
nonce: req.nonce(),
source: req.source_chain(),
dest: req.dest_chain(),
})
.ok()?;

Some(())
}

fn store_consensus_state(&self, id: ConsensusClientId, state: Vec<u8>) -> Result<(), Error> {
ConsensusStates::<T>::insert(id, state);
Ok(())
Expand Down Expand Up @@ -121,6 +135,19 @@ where
Ok(())
}

fn delete_request_commitment(&self, req: &Request) -> Result<(), Error> {
let hash = hash_request::<Self>(req);
// We can't delete actual leaves in the mmr so this serves as a replacement for that
RequestAcks::<T>::remove(hash.0.to_vec());
Ok(())
}

fn store_request_receipt(&self, req: &Request) -> Result<(), Error> {
let hash = hash_request::<Self>(req);
RequestAcks::<T>::insert(hash.0.to_vec(), Receipt::Ok);
Ok(())
}

fn consensus_client(&self, id: ConsensusClientId) -> Result<Box<dyn ConsensusClient>, Error> {
<T as Config>::ConsensusClientProvider::consensus_client(id)
}
Expand Down
12 changes: 6 additions & 6 deletions pallet-ismp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ pub mod pallet {

#[pallet::storage]
#[pallet::getter(fn request_acks)]
/// Acknowledgements for receipt of requests
/// Acknowledgements for incoming and outgoing requests
/// The key is the request commitment
pub type RequestAcks<T: Config> =
StorageMap<_, Blake2_128Concat, Vec<u8>, Receipt, OptionQuery>;
Expand Down Expand Up @@ -556,9 +556,9 @@ where
req.nonce(),
),
Leaf::Response(res) => Pallet::<T>::response_leaf_index_offchain_key(
res.request.dest_chain(),
res.request.source_chain(),
res.request.nonce(),
res.dest_chain(),
res.source_chain(),
res.nonce(),
),
};
let leaves = Self::number_of_leaves();
Expand Down Expand Up @@ -605,8 +605,8 @@ impl<T: Config> IsmpDispatch for Pallet<T> {
};
router.dispatch(Request::Get(get)).map(|_| ())
}
IsmpMessage::Response { response, request } => {
router.write_response(Response { request, response }).map(|_| ())
IsmpMessage::Response { response, post } => {
router.write_response(Response::Post { post, response }).map(|_| ())
}
}
}
Expand Down
18 changes: 5 additions & 13 deletions pallet-ismp/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,21 @@ pub struct StateMachineProvider;

impl Get<StateMachine> for StateMachineProvider {
fn get() -> StateMachine {
StateMachine::Kusama(2000)
StateMachine::Kusama(100)
}
}

pub struct ConsensusProvider;

impl ConsensusClientProvider for ConsensusProvider {
fn consensus_client(
id: ConsensusClientId,
_id: ConsensusClientId,
) -> Result<Box<dyn ConsensusClient>, ismp_rs::error::Error> {
let client = match id {
_ => Err(ismp_rs::error::Error::ImplementationSpecific(
"Unknown consensus client".into(),
))?,
};

Ok(client)
Ok(Box::new(ismp_testsuite::mocks::MockClient))
}

fn challenge_period(id: ConsensusClientId) -> Duration {
match id {
_ => Duration::MAX,
}
fn challenge_period(_id: ConsensusClientId) -> Duration {
Duration::from_secs(60 * 60)
}
}

Expand Down
12 changes: 6 additions & 6 deletions pallet-ismp/src/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use ismp_primitives::mmr::{LeafIndex, NodeIndex};
use ismp_rs::{
consensus::{ConsensusClient, ConsensusClientId, StateMachineHeight},
host::StateMachine,
router::Request,
router::Post,
};
use scale_info::TypeInfo;
use sp_std::prelude::*;
Expand Down Expand Up @@ -50,7 +50,7 @@ pub enum IsmpMessage {
Post {
/// The destination state machine of this request.
dest_chain: StateMachine,
/// Moudle Id of the sending module
/// Module Id of the sending module
from: Vec<u8>,
/// Module ID of the receiving module
to: Vec<u8>,
Expand All @@ -62,17 +62,17 @@ pub enum IsmpMessage {
Get {
/// The destination state machine of this request.
dest_chain: StateMachine,
/// Moudle Id of the sending module
/// Module Id of the sending module
from: Vec<u8>,
/// Storage keys that this request is interested in.
/// Raw Storage keys that this request is interested in.
keys: Vec<Vec<u8>>,
/// Height at which to read the state machine.
height: StateMachineHeight,
/// Timestamp which this request expires in seconds
/// Host Timestamp which this request expires in seconds
timeout_timestamp: u64,
},
Response {
request: Request,
post: Post,
response: Vec<u8>,
},
}
Expand Down
23 changes: 11 additions & 12 deletions pallet-ismp/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ where
source_chain,
dest_chain,
});
// We have this step because we can't delete leaves from the mmr
// So this helps us prevent processing of duplicate outgoing requests
RequestAcks::<T>::insert(commitment, Receipt::Ok);
Ok(DispatchSuccess { dest_chain, source_chain, nonce })
} else if let Some(ref router) = self.inner {
Expand Down Expand Up @@ -102,23 +104,20 @@ where
fn write_response(&self, response: Response) -> DispatchResult {
let host = Host::<T>::default();

if host.host_state_machine() != response.request.source_chain() {
if host.host_state_machine() != response.dest_chain() {
let commitment = hash_response::<Host<T>>(&response).0.to_vec();

if ResponseAcks::<T>::contains_key(commitment.clone()) {
Err(DispatchError {
msg: "Duplicate response".to_string(),
nonce: response.request.nonce(),
source: response.request.source_chain(),
dest: response.request.dest_chain(),
nonce: response.nonce(),
source: response.source_chain(),
dest: response.dest_chain(),
})?
}

let (dest_chain, source_chain, nonce) = (
response.request.source_chain(),
response.request.dest_chain(),
response.request.nonce(),
);
let (dest_chain, source_chain, nonce) =
(response.dest_chain(), response.source_chain(), response.nonce());

Pallet::<T>::mmr_push(Leaf::Response(response)).ok_or_else(|| DispatchError {
msg: "Failed to push response into mmr".to_string(),
Expand All @@ -139,9 +138,9 @@ where
} else {
Err(DispatchError {
msg: "Missing a module router".to_string(),
nonce: response.request.nonce(),
source: response.request.source_chain(),
dest: response.request.dest_chain(),
nonce: response.nonce(),
source: response.source_chain(),
dest: response.dest_chain(),
})?
}
}
Expand Down
69 changes: 68 additions & 1 deletion pallet-ismp/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
use crate::{mock::*, *};
use std::ops::Range;
use std::{
ops::Range,
time::{SystemTime, UNIX_EPOCH},
};

use frame_support::traits::OnFinalize;
use ismp_primitives::mmr::MmrHasher;
use ismp_testsuite::{
check_challenge_period, check_client_expiry, frozen_check, timeout_post_processing_check,
write_outgoing_commitments,
};
use mmr_lib::MerkleProof;
use sp_core::{
offchain::{testing::TestOffchainExt, OffchainDbExt, OffchainWorkerExt},
Expand Down Expand Up @@ -159,3 +166,63 @@ fn should_generate_and_verify_batch_proof_for_leaves_inserted_across_multiple_bl
assert_eq!(root, calculated_root.hash::<Host<Test>>())
})
}

fn set_timestamp() {
Timestamp::set_timestamp(
SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as u64
);
}

#[test]
fn check_for_duplicate_requests_and_responses() {
let mut ext = new_test_ext();

ext.execute_with(|| {
set_timestamp();
let host = Host::<Test>::default();
write_outgoing_commitments(&host).unwrap();
})
}

#[test]
fn should_reject_updates_within_challenge_period() {
let mut ext = new_test_ext();

ext.execute_with(|| {
set_timestamp();
let host = Host::<Test>::default();
check_challenge_period(&host).unwrap()
})
}

#[test]
fn should_reject_messages_for_frozen_state_machines() {
let mut ext = new_test_ext();

ext.execute_with(|| {
set_timestamp();
let host = Host::<Test>::default();
frozen_check(&host).unwrap()
})
}

#[test]
fn should_reject_expired_check_clients() {
let mut ext = new_test_ext();

ext.execute_with(|| {
set_timestamp();
let host = Host::<Test>::default();
check_client_expiry(&host).unwrap()
})
}
#[test]
fn should_process_timeouts_correctly() {
let mut ext = new_test_ext();

ext.execute_with(|| {
set_timestamp();
let host = Host::<Test>::default();
timeout_post_processing_check(&host).unwrap()
})
}
1 change: 1 addition & 0 deletions parachain-consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pallet-ismp = { path = "../pallet-ismp", default-features = false }

[dev-dependencies]


[features]
default = ["std"]
std = [
Expand Down

0 comments on commit fa50fe4

Please sign in to comment.