diff --git a/Cargo.lock b/Cargo.lock index 3c1230464..ac344ea6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7730,7 +7730,7 @@ version = "0.1.1" [[package]] name = "ismp-grandpa" -version = "1.15.1" +version = "1.15.3" dependencies = [ "ckb-merkle-mountain-range", "cumulus-primitives-core", @@ -7754,7 +7754,7 @@ dependencies = [ [[package]] name = "ismp-parachain" -version = "1.15.1" +version = "1.15.3" dependencies = [ "cumulus-pallet-parachain-system", "cumulus-primitives-core", @@ -7778,7 +7778,7 @@ dependencies = [ [[package]] name = "ismp-parachain-inherent" -version = "1.15.1" +version = "1.15.3" dependencies = [ "anyhow", "async-trait", @@ -10355,11 +10355,12 @@ dependencies = [ [[package]] name = "mmr-primitives" -version = "1.15.1" +version = "1.15.2" dependencies = [ "ckb-merkle-mountain-range", "frame-system", "ismp", + "pallet-ismp", "parity-scale-codec", "scale-info", "serde", @@ -12146,7 +12147,7 @@ dependencies = [ [[package]] name = "pallet-hyperbridge" -version = "1.15.2" +version = "1.15.3" dependencies = [ "anyhow", "frame-support 37.0.0", @@ -12215,7 +12216,7 @@ dependencies = [ [[package]] name = "pallet-ismp" -version = "1.15.2" +version = "1.15.3" dependencies = [ "anyhow", "env_logger 0.10.2", @@ -12226,7 +12227,6 @@ dependencies = [ "ismp", "ismp-testsuite", "log", - "mmr-primitives", "pallet-timestamp", "parity-scale-codec", "scale-info", @@ -12310,7 +12310,7 @@ dependencies = [ [[package]] name = "pallet-ismp-rpc" -version = "1.15.2" +version = "1.15.3" dependencies = [ "anyhow", "frame-system", @@ -12339,7 +12339,7 @@ dependencies = [ [[package]] name = "pallet-ismp-runtime-api" -version = "1.15.2" +version = "1.15.3" dependencies = [ "ismp", "pallet-ismp", @@ -12472,6 +12472,7 @@ dependencies = [ "itertools 0.10.5", "log", "mmr-primitives", + "pallet-ismp", "parity-scale-codec", "scale-info", "serde", @@ -12981,7 +12982,7 @@ dependencies = [ [[package]] name = "pallet-token-gateway" -version = "1.15.2" +version = "1.15.3" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -23201,7 +23202,7 @@ dependencies = [ [[package]] name = "substrate-state-machine" -version = "1.15.1" +version = "1.15.3" dependencies = [ "frame-support 37.0.0", "hash-db", @@ -24189,7 +24190,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "token-gateway-primitives" -version = "1.15.2" +version = "1.15.3" dependencies = [ "alloy-primitives", "alloy-sol-macro", diff --git a/Cargo.toml b/Cargo.toml index 962d0981f..146c2d60e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -287,9 +287,9 @@ grandpa-prover = { path = "./modules/consensus/grandpa/prover" } # consensus clients ismp-bsc = { path = "./modules/ismp/clients/bsc", default-features = false } -ismp-grandpa = { version = "1.15.1", path = "./modules/ismp/clients/grandpa", default-features = false } -ismp-parachain = { version = "1.15.1", path = "./modules/ismp/clients/parachain/client", default-features = false } -ismp-parachain-inherent = { version = "1.15.1", path = "./modules/ismp/clients/parachain/inherent" } +ismp-grandpa = { version = "1.15.3", path = "./modules/ismp/clients/grandpa", default-features = false } +ismp-parachain = { version = "1.15.3", path = "./modules/ismp/clients/parachain/client", default-features = false } +ismp-parachain-inherent = { version = "1.15.3", path = "./modules/ismp/clients/parachain/inherent" } ismp-parachain-runtime-api = { version = "1.15.1", path = "./modules/ismp/clients/parachain/runtime-api", default-features = false } ismp-sync-committee = { path = "./modules/ismp/clients/sync-committee", default-features = false } arbitrum-verifier = { path = "./modules/ismp/clients/arbitrum", default-features = false } @@ -297,16 +297,16 @@ op-verifier = { path = "./modules/ismp/clients/optimism", default-features = fal # state machine clients evm-state-machine = { path = "./modules/ismp/state-machines/evm", default-features = false } -substrate-state-machine = { version = "1.15.1", path = "modules/ismp/state-machines/substrate", default-features = false } +substrate-state-machine = { version = "1.15.3", path = "modules/ismp/state-machines/substrate", default-features = false } hyperbridge-client-machine = { path = "modules/ismp/state-machines/hyperbridge", default-features = false } # published pallets -pallet-ismp = { version = "1.15.2", path = "modules/ismp/pallets/pallet", default-features = false } -pallet-ismp-rpc = { version = "1.15.2", path = "modules/ismp/pallets/rpc" } -pallet-ismp-runtime-api = { version = "1.15.2", path = "modules/ismp/pallets/runtime-api", default-features = false } -pallet-hyperbridge = { version = "1.15.2", path = "modules/ismp/pallets/hyperbridge", default-features = false } -pallet-token-gateway = { version = "1.15.2", path = "modules/ismp/pallets/token-gateway", default-features = false } -token-gateway-primitives = { version = "1.15.2", path = "modules/ismp/pallets/token-gateway/primitives", default-features = false } +pallet-ismp = { version = "1.15.3", path = "modules/ismp/pallets/pallet", default-features = false } +pallet-ismp-rpc = { version = "1.15.3", path = "modules/ismp/pallets/rpc" } +pallet-ismp-runtime-api = { version = "1.15.3", path = "modules/ismp/pallets/runtime-api", default-features = false } +pallet-hyperbridge = { version = "1.15.3", path = "modules/ismp/pallets/hyperbridge", default-features = false } +pallet-token-gateway = { version = "1.15.3", path = "modules/ismp/pallets/token-gateway", default-features = false } +token-gateway-primitives = { version = "1.15.3", path = "modules/ismp/pallets/token-gateway/primitives", default-features = false } # ismp modules pallet-fishermen = { path = "modules/ismp/pallets/fishermen", default-features = false } @@ -321,10 +321,10 @@ pallet-mmr = { path = "modules/trees/mmr/pallet", default-features = false } pallet-token-gateway-inspector = { path = "modules/ismp/pallets/token-gateway-inspector", default-features = false } # merkle trees +ethereum-triedb = { version = "0.1.1", path = "./modules/trees/ethereum", default-features = false } +mmr-primitives = { path = "modules/trees/mmr/primitives", default-features = false } pallet-mmr-runtime-api = { path = "modules/trees/mmr/pallet/runtime-api", default-features = false } mmr-gadget = { path = "modules/trees/mmr/gadget" } -ethereum-triedb = { version = "0.1.1", path = "./modules/trees/ethereum", default-features = false } -mmr-primitives = { version = "1.15.1", path = "modules/trees/mmr/primitives", default-features = false } # runtimes gargantua-runtime = { path = "./parachain/runtimes/gargantua", default-features = false } diff --git a/docs/pages/developers/polkadot/getting-started.mdx b/docs/pages/developers/polkadot/getting-started.mdx index 1109350e9..cb9727ede 100644 --- a/docs/pages/developers/polkadot/getting-started.mdx +++ b/docs/pages/developers/polkadot/getting-started.mdx @@ -84,4 +84,4 @@ cargo add pallet-token-gateway ## Versioning -The versioning of these crates track the LTS releases of Polkadot SDK and are only updated when new LTS versions are released. For instance the `stable2407` version is available for all crates as **v1.15.x**. Subsequent LTS releases will see a minor version bump. eg `stable2409` will be supportted by **v1.16.x** and so on. \ No newline at end of file +The versioning of these crates track the LTS releases of Polkadot SDK and are only updated when new LTS versions are released. For instance the `stable2407` version is available for all crates as **v1.15.x**. Subsequent LTS releases will see a minor version bump. eg `stable2409` will be supported by **v1.16.x** and so on. diff --git a/docs/pages/developers/polkadot/pallet-ismp.mdx b/docs/pages/developers/polkadot/pallet-ismp.mdx index 0a486c752..fa294836a 100644 --- a/docs/pages/developers/polkadot/pallet-ismp.mdx +++ b/docs/pages/developers/polkadot/pallet-ismp.mdx @@ -45,8 +45,10 @@ impl pallet_ismp::Config for Runtime { ismp_parachain::ParachainConsensusClient, ); // Offchain database implementation. Outgoing requests and responses are - // inserted in this database, while their commitments are stored onchain. - type OffchainDB = TransparentOffchainDB; + // inserted in this database, while their commitments are stored onchain. + // + // The default implementation for `()` should suffice + type OffchainDB = (); // Weight provider for local modules type WeightProvider = (); } diff --git a/modules/consensus/beefy/prover/src/lib.rs b/modules/consensus/beefy/prover/src/lib.rs index b01b98c52..9ac5c7ad3 100644 --- a/modules/consensus/beefy/prover/src/lib.rs +++ b/modules/consensus/beefy/prover/src/lib.rs @@ -23,16 +23,10 @@ pub mod relay; /// Helper functions and types pub mod util; -/// Some consensus related constants -pub mod constants { - - /// Block at which BEEFY was activated on rococo - pub const ROCOCO_BEEFY_ACTIVATION_BLOCK: u32 = 3_804_028; -} - use anyhow::anyhow; use beefy_verifier_primitives::{ - ConsensusMessage, ConsensusState, MmrProof, ParachainHeader, ParachainProof, SignedCommitment, + ConsensusMessage, ConsensusState, MmrProof, ParachainHeader, ParachainProof, + SignatureWithAuthorityIndex, SignedCommitment, }; use codec::{Decode, Encode}; use hex_literal::hex; @@ -46,7 +40,7 @@ use sp_consensus_beefy::{ use sp_io::hashing::keccak_256; use sp_mmr_primitives::LeafProof; use subxt::{rpc_params, Config, OnlineClient}; -use util::{hash_authority_addresses, prove_authority_set, AuthorityProofWithSignatures}; +use util::hash_authority_addresses; /// This contains methods for fetching BEEFY proofs for parachain headers. #[derive(Clone, Debug)] @@ -208,30 +202,49 @@ impl Prover { &self, signed_commitment: sp_consensus_beefy::SignedCommitment, ) -> Result { - let subxt_block_number: subxt::rpc::types::BlockNumber = - (signed_commitment.commitment.block_number - 1).into(); + let block_number: subxt::rpc::types::NumberOrHex = + signed_commitment.commitment.block_number.into(); let block_hash = self .relay .rpc() - .block_hash(Some(subxt_block_number)) + .block_hash(Some(block_number.into())) .await? .ok_or_else(|| anyhow!("Failed to query blockhash for blocknumber"))?; - let current_authorities = self.beefy_authorities(Some(block_hash)).await?; - // Current LeafIndex - let block_number = signed_commitment.commitment.block_number; - let leaf_proof = fetch_mmr_proof(&self.relay, block_number.into()).await?; + let leaf_proof = fetch_mmr_proof(&self.relay, block_number.try_into()?).await?; let leaves: Vec> = codec::Decode::decode(&mut &*leaf_proof.leaves.0)?; let latest_leaf: MmrLeaf = codec::Decode::decode(&mut &*leaves[0])?; let mmr_proof: LeafProof = Decode::decode(&mut &*leaf_proof.proof.0)?; + // create authorities proof + let signatures = signed_commitment + .signatures + .iter() + .enumerate() + .map(|(index, x)| { + if let Some(sig) = x { + let mut temp = [0u8; 65]; + if sig.len() == 65 { + temp.copy_from_slice(&*sig.encode()); + let last = temp.last_mut().unwrap(); + *last = *last + 27; + Some(SignatureWithAuthorityIndex { index: index as u32, signature: temp }) + } else { + None + } + } else { + None + } + }) + .filter_map(|x| x) + .collect::>(); + let current_authorities = self.beefy_authorities(Some(block_hash)).await?; let authority_address_hashes = hash_authority_addresses( current_authorities.into_iter().map(|x| x.encode()).collect(), )?; - - let AuthorityProofWithSignatures { authority_proof, signatures } = - prove_authority_set(&signed_commitment, authority_address_hashes)?; + let indices = signatures.iter().map(|x| x.index as usize).collect::>(); + let authority_proof = util::merkle_proof(&authority_address_hashes, &indices); let mmr = MmrProof { signed_commitment: SignedCommitment { @@ -243,8 +256,11 @@ impl Prover { authority_proof, }; - let heads = self.paras_parachains(Some(block_hash)).await?; - + let heads = self + .paras_parachains(Some(R::Hash::decode( + &mut &*latest_leaf.parent_number_and_hash.1.encode(), + )?)) + .await?; let (parachains, indices): (Vec<_>, Vec<_>) = self .para_ids .iter() diff --git a/modules/consensus/beefy/prover/src/util.rs b/modules/consensus/beefy/prover/src/util.rs index 282ba3a41..2dabe5b97 100644 --- a/modules/consensus/beefy/prover/src/util.rs +++ b/modules/consensus/beefy/prover/src/util.rs @@ -106,42 +106,6 @@ pub async fn fetch_timestamp_extrinsic_with_proof( Ok(TimeStampExtWithProof { ext, proof }) } -/// Get the proof for authority set that signed this commitment -pub fn prove_authority_set( - signed_commitment: &sp_consensus_beefy::SignedCommitment< - u32, - sp_consensus_beefy::ecdsa_crypto::Signature, - >, - authority_address_hashes: Vec, -) -> Result { - let signatures = signed_commitment - .signatures - .iter() - .enumerate() - .map(|(index, x)| { - if let Some(sig) = x { - let mut temp = [0u8; 65]; - if sig.len() == 65 { - temp.copy_from_slice(&*sig.encode()); - let last = temp.last_mut().unwrap(); - *last = *last + 27; - Some(SignatureWithAuthorityIndex { index: index as u32, signature: temp }) - } else { - None - } - } else { - None - } - }) - .filter_map(|x| x) - .collect::>(); - - let signature_indices = signatures.iter().map(|x| x.index as usize).collect::>(); - let authority_proof = merkle_proof(&authority_address_hashes, &signature_indices); - - Ok(AuthorityProofWithSignatures { authority_proof, signatures }) -} - /// Hash encoded authority public keys pub fn hash_authority_addresses( encoded_public_keys: Vec>, diff --git a/modules/consensus/sync-committee/prover/src/lib.rs b/modules/consensus/sync-committee/prover/src/lib.rs index 702405c01..1ecf7a91c 100644 --- a/modules/consensus/sync-committee/prover/src/lib.rs +++ b/modules/consensus/sync-committee/prover/src/lib.rs @@ -1,8 +1,8 @@ -mod middleware; +pub mod middleware; #[warn(unused_imports)] #[warn(unused_variables)] -mod responses; -mod routes; +pub mod responses; +pub mod routes; #[cfg(test)] mod test; @@ -251,8 +251,8 @@ impl SyncCommitteeProver, ) -> Result, anyhow::Error> { - if finality_checkpoint.root == Node::default() || - client_state.latest_finalized_epoch >= finality_checkpoint.epoch + if finality_checkpoint.root == Node::default() + || client_state.latest_finalized_epoch >= finality_checkpoint.epoch { trace!(target: "sync-committee-prover", "No new epoch finalized yet {}", finality_checkpoint.epoch); return Ok(None); @@ -287,9 +287,9 @@ impl SyncCommitteeProver(block.slot); - if num_signatures >= min_signatures && - (state_period..=state_period + 1).contains(&signature_period) && - parent_block_finality_checkpoint.epoch > client_state.latest_finalized_epoch + if num_signatures >= min_signatures + && (state_period..=state_period + 1).contains(&signature_period) + && parent_block_finality_checkpoint.epoch > client_state.latest_finalized_epoch { break; } @@ -354,10 +354,10 @@ impl SyncCommitteeProver Result { trace!(target: "sync-committee-prover", "latest_update_for_period {period}"); - let mut higest_slot_in_epoch = ((period * C::EPOCHS_PER_SYNC_COMMITTEE_PERIOD) * - C::SLOTS_PER_EPOCH) + - (C::EPOCHS_PER_SYNC_COMMITTEE_PERIOD * C::SLOTS_PER_EPOCH) - - 1; + let mut higest_slot_in_epoch = ((period * C::EPOCHS_PER_SYNC_COMMITTEE_PERIOD) + * C::SLOTS_PER_EPOCH) + + (C::EPOCHS_PER_SYNC_COMMITTEE_PERIOD * C::SLOTS_PER_EPOCH) + - 1; let mut count = 0; // Some slots are empty so we'll use a loop to fetch the highest available slot in an epoch let mut block = loop { @@ -494,8 +494,8 @@ pub fn prove_block_roots_proof( let epoch_for_header = compute_epoch_at_slot::(header.slot) as usize; let epoch_for_state = compute_epoch_at_slot::(state.slot) as usize; - if epoch_for_state.saturating_sub(epoch_for_header) >= - SLOTS_PER_HISTORICAL_ROOT / C::SLOTS_PER_EPOCH as usize + if epoch_for_state.saturating_sub(epoch_for_header) + >= SLOTS_PER_HISTORICAL_ROOT / C::SLOTS_PER_EPOCH as usize { // todo: Historical root proofs unimplemented!() diff --git a/modules/consensus/sync-committee/prover/src/responses/beacon_block_header_response.rs b/modules/consensus/sync-committee/prover/src/responses/beacon_block_header_response.rs index 9a3e6b167..a8bbdd1ad 100644 --- a/modules/consensus/sync-committee/prover/src/responses/beacon_block_header_response.rs +++ b/modules/consensus/sync-committee/prover/src/responses/beacon_block_header_response.rs @@ -2,7 +2,7 @@ use sync_committee_primitives::consensus_types::BeaconBlockHeader; #[derive(Default, Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct Response { - pub(crate) data: ResponseData, + pub data: ResponseData, execution_optimistic: bool, } @@ -10,7 +10,7 @@ pub struct Response { pub struct ResponseData { root: String, canonical: bool, - pub(crate) header: ResponseDataBeaconBlockHeaderMessage, + pub header: ResponseDataBeaconBlockHeaderMessage, } #[derive(Default, Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] diff --git a/modules/ismp/clients/grandpa/Cargo.toml b/modules/ismp/clients/grandpa/Cargo.toml index 5ce17c1a2..39cf8ec41 100644 --- a/modules/ismp/clients/grandpa/Cargo.toml +++ b/modules/ismp/clients/grandpa/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ismp-grandpa" -version = "1.15.1" +version = "1.15.3" edition = "2021" authors = ["Polytope Labs "] license = "Apache-2.0" @@ -24,7 +24,6 @@ grandpa-verifier-primitives = { workspace = true } grandpa-verifier = { workspace = true } pallet-ismp = { workspace = true } - # substrate frame-support = { workspace = true } frame-system = { workspace = true } diff --git a/modules/ismp/clients/parachain/client/Cargo.toml b/modules/ismp/clients/parachain/client/Cargo.toml index 66787174a..0c6f8a654 100644 --- a/modules/ismp/clients/parachain/client/Cargo.toml +++ b/modules/ismp/clients/parachain/client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ismp-parachain" -version = "1.15.1" +version = "1.15.3" edition = "2021" authors = ["Polytope Labs "] license = "Apache-2.0" diff --git a/modules/ismp/clients/parachain/inherent/Cargo.toml b/modules/ismp/clients/parachain/inherent/Cargo.toml index e1434c76d..ebb3ac92d 100644 --- a/modules/ismp/clients/parachain/inherent/Cargo.toml +++ b/modules/ismp/clients/parachain/inherent/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ismp-parachain-inherent" -version = "1.15.1" +version = "1.15.3" edition = "2021" authors = ["Polytope Labs "] license = "Apache-2.0" diff --git a/modules/ismp/pallets/hyperbridge/Cargo.toml b/modules/ismp/pallets/hyperbridge/Cargo.toml index c2b756469..d59904754 100644 --- a/modules/ismp/pallets/hyperbridge/Cargo.toml +++ b/modules/ismp/pallets/hyperbridge/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-hyperbridge" -version = "1.15.2" +version = "1.15.3" edition = "2021" authors = ["Polytope Labs "] license = "Apache-2.0" diff --git a/modules/ismp/pallets/pallet/Cargo.toml b/modules/ismp/pallets/pallet/Cargo.toml index 15835da3d..125e2b80a 100644 --- a/modules/ismp/pallets/pallet/Cargo.toml +++ b/modules/ismp/pallets/pallet/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-ismp" -version = "1.15.2" +version = "1.15.3" edition = "2021" authors = ["Polytope Labs "] license = "Apache-2.0" @@ -25,7 +25,6 @@ ismp = { workspace = true } codec = { workspace = true } scale-info = { workspace = true } sp-mmr-primitives = { workspace = true } -mmr-primitives = { workspace = true } anyhow = { workspace = true, default-features = false } # crates.io @@ -55,7 +54,6 @@ std = [ "sp-api/std", "serde/default", "sp-mmr-primitives/std", - "mmr-primitives/std", "anyhow/std" ] disable-panic-handler = ["sp-io/disable_panic_handler", "sp-io/disable_oom", "sp-io/disable_allocator"] diff --git a/modules/ismp/pallets/pallet/README.md b/modules/ismp/pallets/pallet/README.md index 1cde2b1af..bd982f027 100644 --- a/modules/ismp/pallets/pallet/README.md +++ b/modules/ismp/pallets/pallet/README.md @@ -48,7 +48,6 @@ The following example shows how to configure `pallet-ismp` in your runtime use frame_support::parameter_types; use frame_system::EnsureRoot; use ismp::Error; -use pallet_ismp::TransparentOffchainDB; use ismp::host::StateMachine; use ismp::module::IsmpModule; use ismp::router::{IsmpRouter, Post, Response, Timeout}; @@ -84,7 +83,7 @@ impl pallet_ismp::Config for Runtime { ); // Offchain database implementation. Outgoing requests and responses are // inserted in this database, while their commitments are stored onchain. - type OffchainDB = TransparentOffchainDB; + type OffchainDB = (); // Weight provider for local modules type WeightProvider = (); } diff --git a/modules/ismp/pallets/pallet/src/impls.rs b/modules/ismp/pallets/pallet/src/impls.rs index 282a36254..c19a37901 100644 --- a/modules/ismp/pallets/pallet/src/impls.rs +++ b/modules/ismp/pallets/pallet/src/impls.rs @@ -18,9 +18,9 @@ use crate::{ child_trie::{RequestCommitments, ResponseCommitments}, dispatcher::{FeeMetadata, RequestMetadata}, - offchain::{Leaf, LeafIndexAndPos, Proof, ProofKeys}, + offchain::{self, ForkIdentifier, Leaf, LeafIndexAndPos, OffchainDBProvider, Proof, ProofKeys}, weights::get_weight, - Config, Error, Event, Pallet, Responded, TransparentOffchainDB, + Config, Error, Event, Pallet, Responded, }; use alloc::{string::ToString, vec, vec::Vec}; use codec::Decode; @@ -31,7 +31,6 @@ use ismp::{ messaging::{hash_request, hash_response, Message}, router::{Request, Response}, }; -use mmr_primitives::{ForkIdentifier, OffchainDBProvider}; use sp_core::{offchain::StorageKind, H256}; impl Pallet { @@ -203,10 +202,8 @@ impl Pallet { match T::OffchainDB::leaf(pos) { Ok(Some(Leaf::Request(req))) => Some(req), _ => { - // Try getting the request from the offchain db using `TransparentOffchainDB` - let offchain_key = TransparentOffchainDB::::offchain_key(commitment); - let Some(elem) = - sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &offchain_key) + let key = offchain::default_key(commitment); + let Some(elem) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &key) else { None? }; @@ -224,10 +221,8 @@ impl Pallet { match T::OffchainDB::leaf(pos) { Ok(Some(Leaf::Response(res))) => Some(res), _ => { - // Try getting the response from the offchain db using the `TransparentOffchainDB` - let offchain_key = TransparentOffchainDB::::offchain_key(commitment); - let Some(elem) = - sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &offchain_key) + let key = offchain::default_key(commitment); + let Some(elem) = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &key) else { None? }; diff --git a/modules/ismp/pallets/pallet/src/lib.rs b/modules/ismp/pallets/pallet/src/lib.rs index 1422c3044..dd4aa7d8c 100644 --- a/modules/ismp/pallets/pallet/src/lib.rs +++ b/modules/ismp/pallets/pallet/src/lib.rs @@ -84,7 +84,6 @@ //! use frame_support::parameter_types; //! use frame_system::EnsureRoot; //! use ismp::Error; -//! use pallet_ismp::TransparentOffchainDB; //! use ismp::host::StateMachine; //! use ismp::module::IsmpModule; //! use ismp::router::{IsmpRouter, Post, Response, Timeout}; @@ -120,7 +119,7 @@ //! ); //! // Offchain database implementation. Outgoing requests and responses are //! // inserted in this database, while their commitments are stored onchain. -//! type OffchainDB = TransparentOffchainDB; +//! type OffchainDB = (); //! // Weight provider for local modules //! type WeightProvider = (); //! } @@ -186,16 +185,10 @@ mod utils; pub mod weights; use crate::offchain::Leaf; -use mmr_primitives::{OffchainDBProvider, PlainOffChainDB}; +use offchain::OffchainDBProvider; // Re-export pallet items so that they can be accessed from the crate namespace. pub use pallet::*; -/// The `TransparentOffchainDB` stores the requests and responses directly inside the offchain -/// db using the commitment as the offchain key -/// -/// *NOTE* it will return an error if you try to generate proofs. -pub type TransparentOffchainDB = PlainOffChainDB>; - // Definition of the pallet logic, to be aggregated at runtime definition through // `construct_runtime`. #[frame_support::pallet] @@ -309,7 +302,7 @@ pub mod pallet { /// inserted in this database, while their commitments are stored onchain. /// /// This offchain DB is also allowed to "merkelize" and "generate proofs" for messages. - /// Most state machines will likey not need this can default to the `TransparentOffchainDB` + /// Most state machines will likey not need this and can just provide `()` type OffchainDB: OffchainDBProvider; } diff --git a/modules/ismp/pallets/pallet/src/offchain.rs b/modules/ismp/pallets/pallet/src/offchain.rs index b077cc9e6..58c626c53 100644 --- a/modules/ismp/pallets/pallet/src/offchain.rs +++ b/modules/ismp/pallets/pallet/src/offchain.rs @@ -13,14 +13,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Mmr utilities +//! Offchain DB interfaces and utilities use codec::{Decode, Encode}; -use frame_support::__private::RuntimeDebug; use ismp::router::{Request, Response}; -use mmr_primitives::FullLeaf; use scale_info::TypeInfo; -use sp_core::H256; +use sp_core::{RuntimeDebug, H256}; use sp_mmr_primitives::NodeIndex; use sp_std::prelude::*; @@ -53,7 +51,7 @@ pub struct LeafIndexAndPos { pub pos: u64, } -/// A concrete Leaf for the MMR +/// A concrete Leaf for the offchain DB #[derive(Debug, Clone, Encode, Decode, PartialEq, Eq, scale_info::TypeInfo)] pub enum Leaf { /// A request variant @@ -71,6 +69,104 @@ impl FullLeaf for Leaf { } } +/// Leaf index and position +#[derive( + codec::Encode, + codec::Decode, + scale_info::TypeInfo, + Ord, + PartialOrd, + Eq, + PartialEq, + Clone, + Copy, + RuntimeDebug, + Default, +)] +#[cfg_attr(feature = "std", derive(serde::Deserialize, serde::Serialize))] +pub struct LeafMetadata { + /// Leaf index in the tree + pub index: u64, + /// Leaf node position in the tree + pub position: u64, +} + +/// The pallet-ismp will use this interface to insert leaves into the offchain db. +/// This allows for batch insertions and asychronous root hash computation, so that +/// the root is only computed once per block. +pub trait OffchainDBProvider { + /// Concrete leaf type used by the implementation. + type Leaf; + + /// Returns the total number of leaves that have been persisted to the db. + fn count() -> u64; + + /// Push a new leaf into the offchain db. + fn push(leaf: Self::Leaf) -> LeafMetadata; + + /// Merkelize the offchain db and compute it's new root hash. This should only be called once a + /// block. This should pull the leaves from the buffer and commit them. + fn finalize() -> Result; + + /// Given the leaf position, return the leaf from the offchain db + fn leaf(pos: NodeIndex) -> Result, sp_mmr_primitives::Error>; + + /// Generate a proof for the given leaf indices. The implementation should provide + /// a proof for the leaves at the current block height. + fn proof( + indices: Vec, + ) -> Result<(Vec, sp_mmr_primitives::LeafProof), sp_mmr_primitives::Error>; +} + +/// Offchain key for storing requests using the commitment as identifiers +pub fn default_key(commitment: H256) -> Vec { + let prefix = b"no_op"; + (prefix, commitment).encode() +} + +impl OffchainDBProvider for () { + type Leaf = Leaf; + + fn count() -> u64 { + 0 + } + + fn proof( + _indices: Vec, + ) -> Result<(Vec, sp_mmr_primitives::LeafProof), sp_mmr_primitives::Error> { + Err(sp_mmr_primitives::Error::GenerateProof)? + } + + fn push(leaf: Self::Leaf) -> LeafMetadata { + let encoded = leaf.preimage(); + let commitment = sp_io::hashing::keccak_256(&encoded); + let offchain_key = default_key(commitment.into()); + sp_io::offchain_index::set(&offchain_key, &leaf.encode()); + Default::default() + } + + fn finalize() -> Result { + Ok(H256::default()) + } + + fn leaf(_pos: NodeIndex) -> Result, sp_mmr_primitives::Error> { + Ok(None) + } +} + +/// A full leaf content stored in the offchain-db. +pub trait FullLeaf: Clone + PartialEq + core::fmt::Debug + codec::FullCodec { + /// Compute the leaf preimage to be hashed. + fn preimage(&self) -> Vec; +} + +/// This trait should provide a hash that is unique to each block +/// This hash will be used as an identifier when creating the non canonical offchain key +pub trait ForkIdentifier { + /// Returns a unique identifier for the current block + fn identifier() -> T::Hash; +} + /// Distinguish between requests and responses #[derive(TypeInfo, Encode, Decode, serde::Deserialize, serde::Serialize)] pub enum ProofKeys { diff --git a/modules/ismp/pallets/rpc/Cargo.toml b/modules/ismp/pallets/rpc/Cargo.toml index f91fa3f06..5ea71cfc6 100644 --- a/modules/ismp/pallets/rpc/Cargo.toml +++ b/modules/ismp/pallets/rpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-ismp-rpc" -version = "1.15.2" +version = "1.15.3" edition = "2021" authors = ["Polytope Labs "] license = "Apache-2.0" diff --git a/modules/ismp/pallets/runtime-api/Cargo.toml b/modules/ismp/pallets/runtime-api/Cargo.toml index e74e6b502..845b18703 100644 --- a/modules/ismp/pallets/runtime-api/Cargo.toml +++ b/modules/ismp/pallets/runtime-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-ismp-runtime-api" -version = "1.15.2" +version = "1.15.3" edition = "2021" authors = ["Polytope Labs "] license = "Apache-2.0" diff --git a/modules/ismp/pallets/state-coprocessor/src/impls.rs b/modules/ismp/pallets/state-coprocessor/src/impls.rs index cfa662bf6..5e6dd1968 100644 --- a/modules/ismp/pallets/state-coprocessor/src/impls.rs +++ b/modules/ismp/pallets/state-coprocessor/src/impls.rs @@ -27,11 +27,10 @@ use ismp::{ router::{GetRequest, GetResponse, Request, RequestResponse, Response, StorageValue}, Error, }; -use mmr_primitives::OffchainDBProvider; use pallet_ismp::{ child_trie::RequestCommitments, dispatcher::{FeeMetadata, RequestMetadata}, - offchain::{Leaf, LeafIndexAndPos}, + offchain::{Leaf, LeafIndexAndPos, OffchainDBProvider}, }; use sp_core::U256; diff --git a/modules/ismp/pallets/state-coprocessor/src/lib.rs b/modules/ismp/pallets/state-coprocessor/src/lib.rs index ac847cf52..70e2193f9 100644 --- a/modules/ismp/pallets/state-coprocessor/src/lib.rs +++ b/modules/ismp/pallets/state-coprocessor/src/lib.rs @@ -32,8 +32,7 @@ pub mod pallet { use frame_system::pallet_prelude::*; use impls::GetRequestsWithProof; use ismp::{host::IsmpHost, messaging::hash_request, router::Request}; - use mmr_primitives::OffchainDBProvider; - use pallet_ismp::offchain::Leaf; + use pallet_ismp::offchain::{Leaf, OffchainDBProvider}; #[pallet::pallet] #[pallet::without_storage_info] pub struct Pallet(_); diff --git a/modules/ismp/pallets/token-gateway/Cargo.toml b/modules/ismp/pallets/token-gateway/Cargo.toml index 8ff40a254..3b50b0a6e 100644 --- a/modules/ismp/pallets/token-gateway/Cargo.toml +++ b/modules/ismp/pallets/token-gateway/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pallet-token-gateway" -version = "1.15.2" +version = "1.15.3" edition = "2021" description = "A substrate implementation of the token gateway protocol" authors = ["Polytope Labs "] diff --git a/modules/ismp/pallets/token-gateway/primitives/Cargo.toml b/modules/ismp/pallets/token-gateway/primitives/Cargo.toml index 3b8300cbe..ab1b2541c 100644 --- a/modules/ismp/pallets/token-gateway/primitives/Cargo.toml +++ b/modules/ismp/pallets/token-gateway/primitives/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "token-gateway-primitives" -version = "1.15.2" +version = "1.15.3" edition = "2021" description = "A collection of types used by token gateway" authors = ["Polytope Labs "] diff --git a/modules/ismp/state-machines/substrate/Cargo.toml b/modules/ismp/state-machines/substrate/Cargo.toml index 4e3db8a09..a8c48f746 100644 --- a/modules/ismp/state-machines/substrate/Cargo.toml +++ b/modules/ismp/state-machines/substrate/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "substrate-state-machine" -version = "1.15.1" +version = "1.15.3" edition = "2021" authors = ["Polytope Labs "] license = "Apache-2.0" diff --git a/modules/trees/mmr/pallet/Cargo.toml b/modules/trees/mmr/pallet/Cargo.toml index b6135f17a..ceac2e9cd 100644 --- a/modules/trees/mmr/pallet/Cargo.toml +++ b/modules/trees/mmr/pallet/Cargo.toml @@ -25,6 +25,7 @@ mmr-primitives = { workspace = true } sp-runtime = { workspace = true } sp-std = { workspace = true } merkle-mountain-range = { workspace = true } +pallet-ismp = { workspace = true } [dev-dependencies] array-bytes = "6.1" @@ -48,6 +49,7 @@ std = [ "sp-std/std", "merkle-mountain-range/std", "serde/default", + "pallet-ismp/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", diff --git a/modules/trees/mmr/pallet/runtime-api/src/lib.rs b/modules/trees/mmr/pallet/runtime-api/src/lib.rs index a0e2ac510..8fac31e65 100644 --- a/modules/trees/mmr/pallet/runtime-api/src/lib.rs +++ b/modules/trees/mmr/pallet/runtime-api/src/lib.rs @@ -1,3 +1,18 @@ +// Copyright (C) Polytope Labs Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + //! Pallet-mmr runtime Apis #![cfg_attr(not(feature = "std"), no_std)] diff --git a/modules/trees/mmr/pallet/src/lib.rs b/modules/trees/mmr/pallet/src/lib.rs index 8b22f125f..bf62f4b52 100644 --- a/modules/trees/mmr/pallet/src/lib.rs +++ b/modules/trees/mmr/pallet/src/lib.rs @@ -67,8 +67,9 @@ use sp_core::H256; use sp_runtime::traits::{self, One}; use sp_std::prelude::*; -use mmr_primitives::{DataOrHash, LeafMetadata, OffchainDBProvider}; +use mmr_primitives::DataOrHash; pub use pallet::*; +use pallet_ismp::offchain::{ForkIdentifier, FullLeaf, LeafMetadata, OffchainDBProvider}; use sp_mmr_primitives::mmr_lib::leaf_index_to_pos; pub use sp_mmr_primitives::{ self as primitives, utils::NodesUtils, Error, LeafDataProvider, LeafIndex, NodeIndex, @@ -93,7 +94,6 @@ pub(crate) type HashOf = <>::Hashing as traits::Hash>::Outp pub mod pallet { use super::*; use frame_support::pallet_prelude::*; - use mmr_primitives::ForkIdentifier; #[pallet::pallet] #[pallet::without_storage_info] @@ -125,7 +125,7 @@ pub mod pallet { type Hashing: traits::Hash; /// Generic leaf type to be inserted into the MMR. - type Leaf: mmr_primitives::FullLeaf + scale_info::TypeInfo; + type Leaf: FullLeaf + scale_info::TypeInfo; /// A type that returns a hash unique to every block as a fork identifer for offchain keys type ForkIdentifierProvider: ForkIdentifier; diff --git a/modules/trees/mmr/pallet/src/mmr/mmr.rs b/modules/trees/mmr/pallet/src/mmr/mmr.rs index 711849350..34d0f67dc 100644 --- a/modules/trees/mmr/pallet/src/mmr/mmr.rs +++ b/modules/trees/mmr/pallet/src/mmr/mmr.rs @@ -34,7 +34,7 @@ pub struct Mmr where T: Config, I: 'static, - L: mmr_primitives::FullLeaf, + L: pallet_ismp::offchain::FullLeaf, Storage: merkle_mountain_range::MMRStore>, { mmr: merkle_mountain_range::MMR< @@ -49,7 +49,7 @@ impl Mmr where T: Config, I: 'static, - L: mmr_primitives::FullLeaf, + L: pallet_ismp::offchain::FullLeaf, Storage: merkle_mountain_range::MMRStore>, { /// Create a pointer to an existing MMR with given number of leaves. @@ -70,7 +70,7 @@ impl Mmr where T: Config, I: 'static, - L: mmr_primitives::FullLeaf, + L: pallet_ismp::offchain::FullLeaf, { /// Push another item to the MMR. /// @@ -98,7 +98,7 @@ impl Mmr where T: Config, I: 'static, - L: mmr_primitives::FullLeaf, + L: pallet_ismp::offchain::FullLeaf, { /// Generate a proof for given leaf indices. /// diff --git a/modules/trees/mmr/pallet/src/mmr/mod.rs b/modules/trees/mmr/pallet/src/mmr/mod.rs index fd15eeeb4..4f710436d 100644 --- a/modules/trees/mmr/pallet/src/mmr/mod.rs +++ b/modules/trees/mmr/pallet/src/mmr/mod.rs @@ -18,7 +18,8 @@ mod mmr; pub mod storage; -use mmr_primitives::{DataOrHash, FullLeaf}; +use mmr_primitives::DataOrHash; +use pallet_ismp::offchain::FullLeaf; use sp_runtime::traits; pub use self::mmr::Mmr; diff --git a/modules/trees/mmr/pallet/src/mmr/storage.rs b/modules/trees/mmr/pallet/src/mmr/storage.rs index df14bdb06..649adee3d 100644 --- a/modules/trees/mmr/pallet/src/mmr/storage.rs +++ b/modules/trees/mmr/pallet/src/mmr/storage.rs @@ -21,7 +21,7 @@ use alloc::{vec, vec::Vec}; use codec::Encode; use log::{debug, trace}; use merkle_mountain_range::helper; -use mmr_primitives::ForkIdentifier; +use pallet_ismp::offchain::ForkIdentifier; use sp_core::offchain::StorageKind; use sp_io::offchain_index; use sp_mmr_primitives::utils::NodesUtils; @@ -65,7 +65,7 @@ impl merkle_mountain_range::MMRStore> for Storage, I: 'static, - L: mmr_primitives::FullLeaf, + L: pallet_ismp::offchain::FullLeaf, { fn get_elem(&self, pos: NodeIndex) -> merkle_mountain_range::Result>> { // We should only get here when trying to generate proofs. The client requests @@ -98,7 +98,7 @@ impl merkle_mountain_range::MMRStore> for Storage, I: 'static, - L: mmr_primitives::FullLeaf, + L: pallet_ismp::offchain::FullLeaf, { fn get_elem(&self, pos: NodeIndex) -> merkle_mountain_range::Result>> { Ok(Nodes::::get(pos).map(Node::Hash)) @@ -169,7 +169,7 @@ impl Storage where T: Config, I: 'static, - L: mmr_primitives::FullLeaf, + L: pallet_ismp::offchain::FullLeaf, { fn store_to_offchain( pos: NodeIndex, diff --git a/modules/trees/mmr/primitives/Cargo.toml b/modules/trees/mmr/primitives/Cargo.toml index a7120281b..adde8bc1a 100644 --- a/modules/trees/mmr/primitives/Cargo.toml +++ b/modules/trees/mmr/primitives/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mmr-primitives" -version = "1.15.1" +version = "1.15.2" edition = "2021" authors = ["Polytope Labs "] license = "Apache-2.0" @@ -10,7 +10,7 @@ documentation = "https://docs.rs/ismp-parachain" description = "Merkle mountain range primitives for pallet-ismp" keywords = ["substrate", "polkadot-sdk", "ISMP", "interoperability"] readme = "./README.md" - +publish = false [dependencies] merkle-mountain-range = { workspace = true } @@ -19,10 +19,11 @@ sp-core = { workspace = true } sp-runtime = { workspace = true } sp-std = { workspace = true } sp-mmr-primitives = { workspace = true } -serde = { workspace = true, features = ["derive"], default-features = false } +serde = { workspace = true, features = ["derive"] } scale-info = { workspace = true } frame-system = { workspace = true } ismp = { workspace = true } +pallet-ismp = { workspace = true } sp-io = { workspace = true } [features] @@ -38,5 +39,6 @@ std = [ "merkle-mountain-range/std", "frame-system/std", "ismp/std", + "pallet-ismp/std", "sp-io/std" ] diff --git a/modules/trees/mmr/primitives/src/lib.rs b/modules/trees/mmr/primitives/src/lib.rs index 799338685..43ae8bacf 100644 --- a/modules/trees/mmr/primitives/src/lib.rs +++ b/modules/trees/mmr/primitives/src/lib.rs @@ -1,114 +1,28 @@ +// Copyright (C) Polytope Labs Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Some primitives for the pallet-mmr + #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; + use alloc::{vec, vec::Vec}; -use codec::Encode; -use core::marker::PhantomData; use merkle_mountain_range::helper::{get_peaks, parent_offset, pos_height_in_tree, sibling_offset}; -use sp_core::H256; -use sp_mmr_primitives as primitives; -use sp_mmr_primitives::NodeIndex; -use sp_runtime::{scale_info, traits, RuntimeDebug}; -use sp_std::fmt; - -/// Leaf index and position -#[derive( - codec::Encode, - codec::Decode, - scale_info::TypeInfo, - Ord, - PartialOrd, - Eq, - PartialEq, - Clone, - Copy, - RuntimeDebug, - Default, -)] -#[cfg_attr(feature = "std", derive(serde::Deserialize, serde::Serialize))] -pub struct LeafMetadata { - /// Leaf index in the tree - pub index: u64, - /// Leaf node position in the tree - pub position: u64, -} - -/// Public interface for this pallet. Other runtime pallets will use this interface to insert leaves -/// into the offchain db. This allows for batch insertions and asychronous root hash computation -/// This is so that the root is only computed once per block. -/// -/// Internally, the pallet makes use of temporary storage item where it places leaves that have not -/// yet been finalized. -pub trait OffchainDBProvider { - /// Concrete leaf type used by the implementation. - type Leaf; - - /// Returns the total number of leaves that have been persisted to the db. - fn count() -> u64; - - /// Push a new leaf into the offchain db. - fn push(leaf: Self::Leaf) -> LeafMetadata; - - /// Merkelize the offchain db and compute it's new root hash. This should only be called once a - /// block. This should pull the leaves from the buffer and commit them. - fn finalize() -> Result; - - /// Given the leaf position, return the leaf from the offchain db - fn leaf(pos: NodeIndex) -> Result, primitives::Error>; - - /// Generate a proof for the given leaf indices. The implementation should provide - /// a proof for the leaves at the current block height. - fn proof( - indices: Vec, - ) -> Result<(Vec, primitives::LeafProof), primitives::Error>; -} - -/// The `PlainOffChainDB` simply persists requests and responses directly to the offchain-db. -pub struct PlainOffChainDB(PhantomData<(T, H)>); - -impl PlainOffChainDB { - /// Offchain key for storing requests using the commitment as identifiers - pub fn offchain_key(commitment: H256) -> Vec { - let prefix = b"no_op"; - (prefix, commitment).encode() - } -} - -impl OffchainDBProvider for PlainOffChainDB { - type Leaf = T; - - fn count() -> u64 { - 0 - } - - fn proof( - _indices: Vec, - ) -> Result<(Vec, primitives::LeafProof), primitives::Error> { - Err(primitives::Error::GenerateProof)? - } - - fn push(leaf: T) -> LeafMetadata { - let encoded = leaf.preimage(); - let commitment = H::keccak256(&encoded); - let offchain_key = Self::offchain_key(commitment); - sp_io::offchain_index::set(&offchain_key, &leaf.encode()); - Default::default() - } - - fn finalize() -> Result { - Ok(H256::default()) - } - - fn leaf(_pos: NodeIndex) -> Result, primitives::Error> { - Ok(None) - } -} - -/// A full leaf content stored in the offchain-db. -pub trait FullLeaf: Clone + PartialEq + fmt::Debug + codec::FullCodec { - /// Compute the leaf preimage to be hashed. - fn preimage(&self) -> Vec; -} +use pallet_ismp::offchain::FullLeaf; +use sp_runtime::{traits, RuntimeDebug}; /// An element representing either full data or its hash. /// @@ -219,10 +133,3 @@ fn take_while_vec bool>(v: &mut Vec, p: P) -> Vec { } v.drain(..).collect() } - -/// This trait should provide a hash that is unique to each block -/// This hash will be used as an identifier when creating the non canonical offchain key -pub trait ForkIdentifier { - /// Returns a unique identifier for the current block - fn identifier() -> T::Hash; -} diff --git a/parachain/simtests/src/pallet_mmr.rs b/parachain/simtests/src/pallet_mmr.rs index ea36ce5ce..2db5975da 100644 --- a/parachain/simtests/src/pallet_mmr.rs +++ b/parachain/simtests/src/pallet_mmr.rs @@ -12,8 +12,8 @@ use sp_runtime::traits::Keccak256; use subxt::{rpc_params, tx::SubmittableExtrinsic, utils::H160}; use merkle_mountain_range::util::MemMMR; -use mmr_primitives::{DataOrHash, FullLeaf}; -use pallet_ismp::offchain::{Leaf, ProofKeys}; +use mmr_primitives::DataOrHash; +use pallet_ismp::offchain::{FullLeaf, Leaf, ProofKeys}; use pallet_mmr::mmr::Hasher as MmrHasher; use subxt_utils::{ gargantua, gargantua::api::runtime_types::pallet_ismp_demo::pallet::EvmParams, Hyperbridge,