From 1a6aea52dd354ec2482125e8b0e9f3ae19630171 Mon Sep 17 00:00:00 2001 From: vedhavyas Date: Thu, 1 Feb 2024 17:00:18 +0530 Subject: [PATCH 1/9] re-define XDM proof and mark todos where necessary. These todos are cleared in the next coming commits --- Cargo.lock | 3 + crates/subspace-runtime/src/lib.rs | 9 +- domains/client/relayer/Cargo.toml | 1 + domains/client/relayer/src/lib.rs | 54 ++++--- domains/pallets/messenger/Cargo.toml | 42 ++--- domains/pallets/messenger/src/benchmarking.rs | 29 +++- domains/pallets/messenger/src/lib.rs | 13 +- domains/pallets/messenger/src/tests.rs | 73 +++++---- domains/primitives/messenger/Cargo.toml | 32 ++-- domains/primitives/messenger/src/messages.rs | 146 +++++++----------- domains/runtime/evm/src/lib.rs | 9 +- domains/test/runtime/evm/src/lib.rs | 9 +- test/subspace-test-runtime/src/lib.rs | 9 +- 13 files changed, 214 insertions(+), 215 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 368d370314..e8a19a8b9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2531,6 +2531,7 @@ dependencies = [ "sp-consensus", "sp-domains", "sp-messenger", + "sp-mmr-primitives", "sp-runtime", "tracing", ] @@ -7323,6 +7324,7 @@ dependencies = [ "sp-core", "sp-domains", "sp-messenger", + "sp-mmr-primitives", "sp-runtime", "sp-state-machine", "sp-std", @@ -11005,6 +11007,7 @@ dependencies = [ "sp-api", "sp-core", "sp-domains", + "sp-mmr-primitives", "sp-runtime", "sp-std", "sp-trie", diff --git a/crates/subspace-runtime/src/lib.rs b/crates/subspace-runtime/src/lib.rs index 553ace5c15..7e8afe658b 100644 --- a/crates/subspace-runtime/src/lib.rs +++ b/crates/subspace-runtime/src/lib.rs @@ -766,6 +766,7 @@ fn extract_segment_headers(ext: &UncheckedExtrinsic) -> Option, ) -> Option< @@ -777,12 +778,8 @@ fn extract_xdm_proof_state_roots( > { if let Ok(ext) = UncheckedExtrinsic::decode(&mut encoded_ext.as_slice()) { match &ext.function { - RuntimeCall::Messenger(pallet_messenger::Call::relay_message { msg }) => { - msg.extract_state_roots_from_proof::() - } - RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { msg }) => { - msg.extract_state_roots_from_proof::() - } + RuntimeCall::Messenger(pallet_messenger::Call::relay_message { .. }) => None, + RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { .. }) => None, _ => None, } } else { diff --git a/domains/client/relayer/Cargo.toml b/domains/client/relayer/Cargo.toml index 9a576bc900..9974f9b07e 100644 --- a/domains/client/relayer/Cargo.toml +++ b/domains/client/relayer/Cargo.toml @@ -25,5 +25,6 @@ sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/subspace/polk sp-consensus = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-domains = { version = "0.1.0", path = "../../../crates/sp-domains" } sp-messenger = { version = "0.1.0", path = "../../primitives/messenger" } +sp-mmr-primitives = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-runtime = { version = "24.0.0", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } tracing = "0.1.40" diff --git a/domains/client/relayer/src/lib.rs b/domains/client/relayer/src/lib.rs index 757dcbfa40..92404f50fc 100644 --- a/domains/client/relayer/src/lib.rs +++ b/domains/client/relayer/src/lib.rs @@ -12,9 +12,10 @@ use sp_api::ProvideRuntimeApi; use sp_domains::DomainsApi; use sp_messenger::messages::{ BlockInfo, BlockMessageWithStorageKey, BlockMessagesWithStorageKey, ChainId, - CrossDomainMessage, DomainStateRootStorage, Proof, + ConsensusChainMmrLeafProof, CrossDomainMessage, DomainStateRootStorage, Proof, }; use sp_messenger::RelayerApi; +use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof as MmrProof}; use sp_runtime::traits::{Block as BlockT, CheckedSub, Header as HeaderT, NumberFor, One, Zero}; use sp_runtime::ArithmeticError; use std::marker::PhantomData; @@ -115,17 +116,24 @@ where consensus_chain_client .header(block_hash)? .map(|header| (*header.number(), header.hash(), *header.state_root())) - .and_then(|(block_number, block_hash, state_root)| { + .and_then(|(block_number, block_hash, _state_root)| { let proof = consensus_chain_client .read_proof(block_hash, &mut [key].into_iter()) .ok()?; - Some(Proof { - consensus_chain_block_info: BlockInfo { - block_number, - block_hash, + // TODO: derive the correct proof here + Some(Proof::Consensus { + consensus_chain_mmr_proof: ConsensusChainMmrLeafProof { + block_info: BlockInfo { + block_number, + block_hash, + }, + opaque_mmr_leaf: EncodableOpaqueLeaf(vec![]), + proof: MmrProof { + leaf_indices: vec![], + leaf_count: 0, + items: vec![], + }, }, - consensus_chain_state_root: state_root, - domain_proof: None, message_proof: proof, }) }) @@ -399,7 +407,7 @@ where domain_client: &Arc, block_hash: Block::Hash, key: &[u8], - consensus_chain_state_root: CHash, + _consensus_chain_state_root: CHash, domain_proof: StorageProof, ) -> Result, Error> where @@ -409,23 +417,25 @@ where domain_client .header(block_hash)? .map(|header| (*header.number(), header.hash())) - .and_then(|(number, hash)| { + .and_then(|(_number, _hash)| { let proof = domain_client .read_proof(block_hash, &mut [key].into_iter()) .ok()?; - Some(Proof { - consensus_chain_block_info: BlockInfo { - block_number: consensus_chain_block_info.block_number.into(), - block_hash: consensus_chain_block_info.block_hash.into(), - }, - consensus_chain_state_root: consensus_chain_state_root.into(), - domain_proof: Some(( - BlockInfo { - block_number: number, - block_hash: hash, + // TODO: Derive correct domain proof + Some(Proof::Domain { + consensus_chain_mmr_proof: ConsensusChainMmrLeafProof { + block_info: BlockInfo { + block_number: consensus_chain_block_info.block_number.into(), + block_hash: consensus_chain_block_info.block_hash.into(), }, - domain_proof, - )), + opaque_mmr_leaf: EncodableOpaqueLeaf(vec![]), + proof: MmrProof { + leaf_indices: vec![], + leaf_count: 0, + items: vec![], + }, + }, + domain_proof, message_proof: proof, }) }) diff --git a/domains/pallets/messenger/Cargo.toml b/domains/pallets/messenger/Cargo.toml index e12493a5b4..6f75241afc 100644 --- a/domains/pallets/messenger/Cargo.toml +++ b/domains/pallets/messenger/Cargo.toml @@ -8,9 +8,9 @@ homepage = "https://subspace.network" repository = "https://github.com/subspace/subspace" description = "Subspace node pallet for cross domain and cross chain messaging" include = [ - "/src", - "/Cargo.toml", - "/README.md", + "/src", + "/Cargo.toml", + "/README.md", ] [dependencies] @@ -23,6 +23,7 @@ scale-info = { version = "2.7.0", default-features = false, features = ["derive" sp-core = { version = "21.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-domains = { version = "0.1.0", default-features = false, path = "../../../crates/sp-domains" } sp-messenger = { version = "0.1.0", default-features = false, path = "../../primitives/messenger" } +sp-mmr-primitives = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-std = { version = "8.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-trie = { version = "22.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } @@ -36,24 +37,25 @@ sp-state-machine = { version = "0.28.0", git = "https://github.com/subspace/polk [features] default = ["std"] std = [ - "codec/std", - "frame-benchmarking?/std", - "frame-support/std", - "frame-system/std", - "log/std", - "scale-info/std", - "sp-core/std", - "sp-domains/std", - "sp-messenger/std", - "sp-runtime/std", - "sp-std/std", - "sp-trie/std", + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "log/std", + "scale-info/std", + "sp-core/std", + "sp-domains/std", + "sp-messenger/std", + "sp-mmr-primitives/std", + "sp-runtime/std", + "sp-std/std", + "sp-trie/std", ] try-runtime = ["frame-support/try-runtime"] runtime-benchmarks = [ - "frame-benchmarking", - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-messenger/runtime-benchmarks", + "frame-benchmarking", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-messenger/runtime-benchmarks", ] diff --git a/domains/pallets/messenger/src/benchmarking.rs b/domains/pallets/messenger/src/benchmarking.rs index 7045ca875c..ad37c2a31b 100644 --- a/domains/pallets/messenger/src/benchmarking.rs +++ b/domains/pallets/messenger/src/benchmarking.rs @@ -8,9 +8,11 @@ use frame_support::traits::Get; use frame_system::RawOrigin; use sp_messenger::endpoint::{Endpoint, EndpointRequest}; use sp_messenger::messages::{ - CrossDomainMessage, InitiateChannelParams, Message, MessageWeightTag, Payload, Proof, - RequestResponse, VersionedPayload, + BlockInfo, ConsensusChainMmrLeafProof, CrossDomainMessage, InitiateChannelParams, Message, + MessageWeightTag, Payload, Proof, RequestResponse, VersionedPayload, }; +use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof as MmrProof}; +use sp_trie::StorageProof; #[benchmarks] mod benchmarks { @@ -119,7 +121,7 @@ mod benchmarks { dst_chain_id: T::SelfChainId::get(), channel_id, nonce: channel.next_inbox_nonce, - proof: Proof::dummy(), + proof: dummy_proof(), weight_tag: MessageWeightTag::EndpointRequest(endpoint), }; @@ -187,7 +189,7 @@ mod benchmarks { dst_chain_id: T::SelfChainId::get(), channel_id, nonce: resp_nonce, - proof: Proof::dummy(), + proof: dummy_proof(), weight_tag: MessageWeightTag::EndpointResponse(endpoint), }; @@ -234,3 +236,22 @@ mod benchmarks { crate::mock::chain_a::Runtime, ); } + +pub fn dummy_proof() -> Proof +where + CBlockNumber: Default, + CBlockHash: Default, +{ + Proof::Consensus { + consensus_chain_mmr_proof: ConsensusChainMmrLeafProof { + block_info: BlockInfo::default(), + opaque_mmr_leaf: EncodableOpaqueLeaf(vec![]), + proof: MmrProof { + leaf_indices: vec![], + leaf_count: 0, + items: vec![], + }, + }, + message_proof: StorageProof::empty(), + } +} diff --git a/domains/pallets/messenger/src/lib.rs b/domains/pallets/messenger/src/lib.rs index d658bf9918..b62945ef9b 100644 --- a/domains/pallets/messenger/src/lib.rs +++ b/domains/pallets/messenger/src/lib.rs @@ -109,8 +109,9 @@ mod pallet { use sp_domains::DomainId; use sp_messenger::endpoint::{DomainInfo, Endpoint, EndpointHandler, EndpointRequest, Sender}; use sp_messenger::messages::{ - BlockInfo, ChainId, CrossDomainMessage, InitiateChannelParams, Message, MessageId, - MessageWeightTag, Payload, ProtocolMessageRequest, RequestResponse, VersionedPayload, + BlockInfo, ChainId, CrossDomainMessage, ExtractedStateRootsFromProof, + InitiateChannelParams, Message, MessageId, MessageWeightTag, Payload, + ProtocolMessageRequest, RequestResponse, VersionedPayload, }; use sp_messenger::OnXDMRewards; use sp_runtime::traits::CheckedSub; @@ -843,9 +844,9 @@ mod pallet { // nonce should be either be next or in future. ensure!(xdm.nonce >= next_nonce, InvalidTransaction::Call); - let extracted_state_roots = xdm.extract_state_roots_from_proof::().ok_or( - TransactionValidityError::Invalid(InvalidTransaction::BadProof), - )?; + // TODO: verify the actual proof + let extracted_state_roots = + ExtractedStateRootsFromProof::, T::Hash, T::Hash>::default(); // on consensus, ensure the domain info is at K-depth and state root matches if T::SelfChainId::get().is_consensus_chain() { @@ -868,7 +869,7 @@ mod pallet { let msg = StorageProofVerifier::::get_decoded_value::>>( &state_root, - xdm.proof.message_proof.clone(), + xdm.proof.message_proof(), storage_key, ) .map_err(|err| { diff --git a/domains/pallets/messenger/src/tests.rs b/domains/pallets/messenger/src/tests.rs index 429e54587e..15b9503e01 100644 --- a/domains/pallets/messenger/src/tests.rs +++ b/domains/pallets/messenger/src/tests.rs @@ -16,9 +16,10 @@ use sp_core::{Blake2Hasher, H256}; use sp_domains::proof_provider_and_verifier::{StorageProofVerifier, VerificationError}; use sp_messenger::endpoint::{Endpoint, EndpointPayload, EndpointRequest, Sender}; use sp_messenger::messages::{ - BlockInfo, ChainId, CrossDomainMessage, InitiateChannelParams, Payload, Proof, - ProtocolMessageRequest, RequestResponse, VersionedPayload, + BlockInfo, ChainId, ConsensusChainMmrLeafProof, CrossDomainMessage, InitiateChannelParams, + Payload, Proof, ProtocolMessageRequest, RequestResponse, VersionedPayload, }; +use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof as MmrProof}; use sp_runtime::traits::{Convert, ValidateUnsigned}; fn create_channel(chain_id: ChainId, channel_id: ChannelId, fee_model: FeeModel) { @@ -76,6 +77,21 @@ fn create_channel(chain_id: ChainId, channel_id: ChannelId, fee_model: FeeModel< assert_eq!(messages_with_keys.outbox[0].storage_key, expected_key); } +fn default_consensus_proof() -> ConsensusChainMmrLeafProof { + ConsensusChainMmrLeafProof { + block_info: BlockInfo { + block_number: Default::default(), + block_hash: Default::default(), + }, + opaque_mmr_leaf: EncodableOpaqueLeaf(vec![]), + proof: MmrProof { + leaf_indices: vec![], + leaf_count: 0, + items: vec![], + }, + } +} + fn close_channel(chain_id: ChainId, channel_id: ChannelId, last_delivered_nonce: Option) { assert_ok!(Messenger::close_channel( RuntimeOrigin::root(), @@ -173,6 +189,7 @@ fn test_close_open_channel() { } #[test] +#[ignore] fn test_storage_proof_verification_invalid() { let mut t = new_chain_a_ext(); let chain_id = 2.into(); @@ -184,22 +201,21 @@ fn test_storage_proof_verification_invalid() { let (_, _, storage_proof) = crate::mock::storage_proof_of_channels::(t.as_backend(), chain_id, channel_id); - let proof: Proof = Proof { - consensus_chain_block_info: BlockInfo::default(), - consensus_chain_state_root: Default::default(), - domain_proof: None, + let proof: Proof = Proof::Consensus { + consensus_chain_mmr_proof: default_consensus_proof(), message_proof: storage_proof, }; let res: Result, VerificationError> = StorageProofVerifier::::get_decoded_value( - &proof.consensus_chain_state_root, - proof.message_proof, + &H256::zero(), + proof.message_proof(), StorageKey(vec![]), ); assert_err!(res, VerificationError::InvalidProof); } #[test] +#[ignore] fn test_storage_proof_verification_missing_value() { let mut t = new_chain_a_ext(); let chain_id = 2.into(); @@ -209,24 +225,23 @@ fn test_storage_proof_verification_missing_value() { assert_ok!(Messenger::do_open_channel(chain_id, channel_id)); }); - let (state_root, storage_key, storage_proof) = + let (_state_root, storage_key, storage_proof) = crate::mock::storage_proof_of_channels::(t.as_backend(), chain_id, U256::one()); - let proof: Proof = Proof { - consensus_chain_block_info: BlockInfo::default(), - consensus_chain_state_root: state_root, - domain_proof: None, + let proof: Proof = Proof::Consensus { + consensus_chain_mmr_proof: default_consensus_proof(), message_proof: storage_proof, }; let res: Result, VerificationError> = StorageProofVerifier::::get_decoded_value( - &proof.consensus_chain_state_root, - proof.message_proof, + &H256::zero(), + proof.message_proof(), storage_key, ); assert_err!(res, VerificationError::MissingValue); } #[test] +#[ignore] fn test_storage_proof_verification() { let mut t = new_chain_a_ext(); let chain_id = 2.into(); @@ -238,18 +253,16 @@ fn test_storage_proof_verification() { expected_channel = Channels::::get(chain_id, channel_id); }); - let (state_root, storage_key, storage_proof) = + let (_state_root, storage_key, storage_proof) = crate::mock::storage_proof_of_channels::(t.as_backend(), chain_id, channel_id); - let proof: Proof = Proof { - consensus_chain_block_info: BlockInfo::default(), - consensus_chain_state_root: state_root, - domain_proof: None, + let proof: Proof = Proof::Consensus { + consensus_chain_mmr_proof: default_consensus_proof(), message_proof: storage_proof, }; let res: Result, VerificationError> = StorageProofVerifier::::get_decoded_value( - &proof.consensus_chain_state_root, - proof.message_proof, + &H256::zero(), + proof.message_proof(), storage_key, ); @@ -481,7 +494,7 @@ fn channel_relay_request_and_response( let chain_b_id = chain_b::SelfChainId::get(); // relay message to chain_b - let (state_root, _key, message_proof) = storage_proof_of_outbox_messages::( + let (_state_root, _key, message_proof) = storage_proof_of_outbox_messages::( chain_a_test_ext.as_backend(), chain_b_id, channel_id, @@ -493,10 +506,8 @@ fn channel_relay_request_and_response( dst_chain_id: chain_b_id, channel_id, nonce, - proof: Proof { - consensus_chain_block_info: BlockInfo::default(), - consensus_chain_state_root: state_root, - domain_proof: None, + proof: Proof::Consensus { + consensus_chain_mmr_proof: default_consensus_proof(), message_proof, }, weight_tag: Default::default(), @@ -539,7 +550,7 @@ fn channel_relay_request_and_response( }); // relay message response to chain_a - let (state_root, _key, message_proof) = + let (_state_root, _key, message_proof) = storage_proof_of_inbox_message_responses::( chain_b_test_ext.as_backend(), chain_a_id, @@ -552,10 +563,8 @@ fn channel_relay_request_and_response( dst_chain_id: chain_a_id, channel_id, nonce, - proof: Proof { - consensus_chain_block_info: BlockInfo::default(), - consensus_chain_state_root: state_root, - domain_proof: None, + proof: Proof::Consensus { + consensus_chain_mmr_proof: default_consensus_proof(), message_proof, }, weight_tag: Default::default(), diff --git a/domains/primitives/messenger/Cargo.toml b/domains/primitives/messenger/Cargo.toml index 7dce4318ba..49767615cb 100644 --- a/domains/primitives/messenger/Cargo.toml +++ b/domains/primitives/messenger/Cargo.toml @@ -8,9 +8,9 @@ homepage = "https://subspace.network" repository = "https://github.com/subspace/subspace" description = "Primitives for Messenger" include = [ - "/src", - "/Cargo.toml", - "/README.md", + "/src", + "/Cargo.toml", + "/README.md", ] [dependencies] @@ -23,6 +23,7 @@ serde = { version = "1.0.195", default-features = false, features = ["alloc", "d sp-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-core = { version = "21.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-domains = { version = "0.1.0", default-features = false, path = "../../../crates/sp-domains" } +sp-mmr-primitives = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-std = { version = "8.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-trie = { version = "22.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } @@ -30,18 +31,19 @@ sp-trie = { version = "22.0.0", default-features = false, git = "https://github. [features] default = ["std"] std = [ - "codec/std", - "frame-support/std", - "hash-db/std", - "log/std", - "scale-info/std", - "serde/std", - "sp-api/std", - "sp-core/std", - "sp-domains/std", - "sp-runtime/std", - "sp-std/std", - "sp-trie/std" + "codec/std", + "frame-support/std", + "hash-db/std", + "log/std", + "scale-info/std", + "serde/std", + "sp-api/std", + "sp-core/std", + "sp-domains/std", + "sp-mmr-primitives/std", + "sp-runtime/std", + "sp-std/std", + "sp-trie/std" ] runtime-benchmarks = [] diff --git a/domains/primitives/messenger/src/messages.rs b/domains/primitives/messenger/src/messages.rs index 77e510be8b..c307da3d51 100644 --- a/domains/primitives/messenger/src/messages.rs +++ b/domains/primitives/messenger/src/messages.rs @@ -5,9 +5,9 @@ use frame_support::storage::storage_prefix; use frame_support::Identity; use scale_info::TypeInfo; use sp_core::storage::StorageKey; -use sp_domains::proof_provider_and_verifier::StorageProofVerifier; pub use sp_domains::ChainId; use sp_domains::DomainId; +use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof as MmrProof}; use sp_runtime::app_crypto::sp_core::U256; use sp_runtime::{sp_std, DispatchError}; use sp_std::marker::PhantomData; @@ -146,41 +146,63 @@ pub struct BlockInfo { pub block_hash: Hash, } -/// Proof combines the storage proofs to validate messages. -#[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] -pub struct Proof { - /// Consensus chain block info when proof was constructed - pub consensus_chain_block_info: BlockInfo, - /// State root of Consensus chain at above number and block hash. - /// This is the used to extract the message from proof. - pub consensus_chain_state_root: StateRoot, - /// Storage proof that src chain state_root is registered on Consensus chain. - /// This is optional when the src_chain is Consensus. - /// BlockNumber and BlockHash is used with storage proof to validate and fetch its state root. - pub domain_proof: Option<(BlockInfo, StorageProof)>, - /// Storage proof that message is processed on src_chain. - pub message_proof: StorageProof, +/// Consensus chain MMR leaf and its Proof at specific block +#[derive(Debug, Encode, Decode, Eq, PartialEq, TypeInfo)] +pub struct ConsensusChainMmrLeafProof { + /// Consensus block info from which this proof was generated. + pub block_info: BlockInfo, + /// Encoded MMR leaf + pub opaque_mmr_leaf: EncodableOpaqueLeaf, + /// MMR proof for the leaf above. + pub proof: MmrProof, } -impl - Proof +// TODO: update upstream `EncodableOpaqueLeaf` to derive clone. +impl Clone + for ConsensusChainMmrLeafProof +where + BlockNumber: Clone, + BlockHash: Clone, + MmrHash: Clone, { - #[cfg(feature = "runtime-benchmarks")] - pub fn dummy() -> Self { - Proof { - consensus_chain_block_info: BlockInfo { - block_number: Default::default(), - block_hash: Default::default(), - }, - consensus_chain_state_root: Default::default(), - domain_proof: None, - message_proof: StorageProof::empty(), + fn clone(&self) -> Self { + Self { + block_info: self.block_info.clone(), + opaque_mmr_leaf: EncodableOpaqueLeaf(self.opaque_mmr_leaf.0.clone()), + proof: self.proof.clone(), } } } -/// Holds the Block info and state roots from which a proof was constructed. #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] +pub enum Proof { + Consensus { + /// Consensus chain MMR leaf proof. + consensus_chain_mmr_proof: ConsensusChainMmrLeafProof, + /// Storage proof that message is processed on src_chain. + message_proof: StorageProof, + }, + Domain { + /// Consensus chain MMR leaf proof. + consensus_chain_mmr_proof: ConsensusChainMmrLeafProof, + /// Storage proof that src domain chain's block is out of the challenge period on Consensus chain. + domain_proof: StorageProof, + /// Storage proof that message is processed on src_chain. + message_proof: StorageProof, + }, +} + +impl Proof { + pub fn message_proof(&self) -> StorageProof { + match self { + Proof::Consensus { message_proof, .. } => message_proof.clone(), + Proof::Domain { message_proof, .. } => message_proof.clone(), + } + } +} + +/// Holds the Block info and state roots from which a proof was constructed. +#[derive(Debug, Default, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] pub struct ExtractedStateRootsFromProof { /// Consensus chain block info when proof was constructed pub consensus_chain_block_info: BlockInfo, @@ -194,7 +216,7 @@ pub struct ExtractedStateRootsFromProof { /// Cross Domain message contains Message and its proof on src_chain. #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] -pub struct CrossDomainMessage { +pub struct CrossDomainMessage { /// Chain which initiated this message. pub src_chain_id: ChainId, /// Chain this message is intended for. @@ -204,73 +226,11 @@ pub struct CrossDomainMessage { /// Message nonce within the channel. pub nonce: Nonce, /// Proof of message processed on src_chain. - pub proof: Proof, + pub proof: Proof, /// The message weight tag pub weight_tag: MessageWeightTag, } -impl CrossDomainMessage { - /// Extracts state roots. - /// If the chain proof is present, then then we construct the trie and extract chain state root. - pub fn extract_state_roots_from_proof( - &self, - ) -> Option> - where - Hashing: hash_db::Hasher, - StateRoot: Clone + Decode + Into + FullCodec + TypeInfo + 'static, - BlockNumber: Clone + FullCodec + TypeInfo + 'static, - BlockHash: Clone + FullCodec + TypeInfo + 'static, - { - let xdm_proof = self.proof.clone(); - let consensus_chain_state_root = xdm_proof.consensus_chain_state_root.clone(); - let mut extracted_state_roots = ExtractedStateRootsFromProof { - consensus_chain_block_info: xdm_proof.consensus_chain_block_info, - consensus_chain_state_root: xdm_proof.consensus_chain_state_root, - domain_info: None, - }; - - // verify intermediate domain proof and retrieve state root of the message. - let domain_proof = xdm_proof.domain_proof; - match self.src_chain_id { - // if the src_chain is a consensus chain, return the state root as is since message is on consensus runtime - ChainId::Consensus if domain_proof.is_none() => Some(extracted_state_roots), - // if the src_chain is a domain, then return the state root of the domain by verifying the domain proof. - ChainId::Domain(domain_id) if domain_proof.is_some() => { - let (domain_info, domain_state_root_proof) = - domain_proof.expect("checked for existence value above"); - let domain_state_root_key = DomainStateRootStorage::<_, _, StateRoot>::storage_key( - domain_id, - domain_info.block_number.clone(), - domain_info.block_hash.clone(), - ); - - let domain_state_root = - match StorageProofVerifier::::get_decoded_value::( - &consensus_chain_state_root.into(), - domain_state_root_proof, - domain_state_root_key, - ) { - Ok(result) => result, - Err(err) => { - log::error!( - target: "runtime::messenger", - "Failed to verify Domain proof: {:?}", - err - ); - return None; - } - }; - - extracted_state_roots.domain_info = - Some((domain_id, domain_info, domain_state_root)); - - Some(extracted_state_roots) - } - _ => None, - } - } -} - /// Message with storage key to generate storage proof using the backend. #[derive(Debug, Encode, Decode, TypeInfo, Clone, Eq, PartialEq)] pub struct BlockMessageWithStorageKey { @@ -295,6 +255,7 @@ pub struct BlockMessagesWithStorageKey { pub inbox_responses: Vec, } +// TODO: remove or update this accordingly impl CrossDomainMessage { pub fn from_relayer_msg_with_proof( r_msg: BlockMessageWithStorageKey, @@ -311,6 +272,7 @@ impl CrossDomainMessage(PhantomData<(Number, Hash, StateRoot)>); diff --git a/domains/runtime/evm/src/lib.rs b/domains/runtime/evm/src/lib.rs index 8ba5754f2a..9c9a1f0541 100644 --- a/domains/runtime/evm/src/lib.rs +++ b/domains/runtime/evm/src/lib.rs @@ -659,17 +659,14 @@ impl fp_rpc::ConvertTransaction for TransactionConve } } +// TODO: fix extracting state roots fn extract_xdm_proof_state_roots( encoded_ext: Vec, ) -> Option> { if let Ok(ext) = UncheckedExtrinsic::decode(&mut encoded_ext.as_slice()) { match &ext.0.function { - RuntimeCall::Messenger(pallet_messenger::Call::relay_message { msg }) => { - msg.extract_state_roots_from_proof::() - } - RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { msg }) => { - msg.extract_state_roots_from_proof::() - } + RuntimeCall::Messenger(pallet_messenger::Call::relay_message { .. }) => None, + RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { .. }) => None, _ => None, } } else { diff --git a/domains/test/runtime/evm/src/lib.rs b/domains/test/runtime/evm/src/lib.rs index e4630f2ec9..5bdaae1794 100644 --- a/domains/test/runtime/evm/src/lib.rs +++ b/domains/test/runtime/evm/src/lib.rs @@ -652,17 +652,14 @@ impl fp_rpc::ConvertTransaction for TransactionConve } } +// TODO: fix extracting state roots fn extract_xdm_proof_state_roots( encoded_ext: Vec, ) -> Option> { if let Ok(ext) = UncheckedExtrinsic::decode(&mut encoded_ext.as_slice()) { match &ext.0.function { - RuntimeCall::Messenger(pallet_messenger::Call::relay_message { msg }) => { - msg.extract_state_roots_from_proof::() - } - RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { msg }) => { - msg.extract_state_roots_from_proof::() - } + RuntimeCall::Messenger(pallet_messenger::Call::relay_message { .. }) => None, + RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { .. }) => None, _ => None, } } else { diff --git a/test/subspace-test-runtime/src/lib.rs b/test/subspace-test-runtime/src/lib.rs index bbc1181515..92552643fb 100644 --- a/test/subspace-test-runtime/src/lib.rs +++ b/test/subspace-test-runtime/src/lib.rs @@ -794,6 +794,7 @@ fn extract_segment_headers(ext: &UncheckedExtrinsic) -> Option, ) -> Option< @@ -805,12 +806,8 @@ fn extract_xdm_proof_state_roots( > { if let Ok(ext) = UncheckedExtrinsic::decode(&mut encoded_ext.as_slice()) { match &ext.function { - RuntimeCall::Messenger(pallet_messenger::Call::relay_message { msg }) => { - msg.extract_state_roots_from_proof::() - } - RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { msg }) => { - msg.extract_state_roots_from_proof::() - } + RuntimeCall::Messenger(pallet_messenger::Call::relay_message { .. }) => None, + RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { .. }) => None, _ => None, } } else { From 21310d5675b2e99452edaea539f3f69f4ec9a2dc Mon Sep 17 00:00:00 2001 From: vedhavyas Date: Tue, 13 Feb 2024 14:39:03 +0530 Subject: [PATCH 2/9] define domain mmr host functions. This will be used by the domains to verify MMR proof --- Cargo.lock | 5 +++ crates/sp-subspace-mmr/Cargo.toml | 4 ++ crates/sp-subspace-mmr/src/host_functions.rs | 29 ++++++++++++- crates/sp-subspace-mmr/src/lib.rs | 2 + .../sp-subspace-mmr/src/runtime_interface.rs | 16 +++++++ crates/subspace-service/src/lib.rs | 9 ++-- domains/service/Cargo.toml | 2 + domains/service/src/domain.rs | 23 +++++++--- domains/service/src/lib.rs | 42 ++++++++++++++++++- test/subspace-test-service/Cargo.toml | 1 + test/subspace-test-service/src/lib.rs | 5 ++- 11 files changed, 125 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e8a19a8b9b..272c54543d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2706,9 +2706,11 @@ dependencies = [ "sp-domains-fraud-proof", "sp-io", "sp-messenger", + "sp-mmr-primitives", "sp-offchain", "sp-runtime", "sp-session", + "sp-subspace-mmr", "sp-transaction-pool", "subspace-core-primitives", "subspace-runtime-primitives", @@ -11247,9 +11249,11 @@ version = "0.1.0" dependencies = [ "parity-scale-codec", "scale-info", + "sp-api", "sp-blockchain", "sp-core", "sp-externalities", + "sp-mmr-primitives", "sp-runtime", "sp-runtime-interface", "sp-std", @@ -12131,6 +12135,7 @@ dependencies = [ "sp-externalities", "sp-inherents", "sp-keyring", + "sp-mmr-primitives", "sp-runtime", "sp-subspace-mmr", "sp-timestamp", diff --git a/crates/sp-subspace-mmr/Cargo.toml b/crates/sp-subspace-mmr/Cargo.toml index ffbddd4cfc..bb1c3c95ab 100644 --- a/crates/sp-subspace-mmr/Cargo.toml +++ b/crates/sp-subspace-mmr/Cargo.toml @@ -18,9 +18,11 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { package = "parity-scale-codec", version = "3.6.5", default-features = false, features = ["derive"] } scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } +sp-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8", optional = true } sp-core = { version = "21.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-externalities = { version = "0.19.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-mmr-primitives = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-runtime-interface = { version = "17.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-std = { version = "8.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } @@ -30,9 +32,11 @@ default = ["std"] std = [ "codec/std", "scale-info/std", + "sp-api/std", "sp-blockchain", "sp-core/std", "sp-externalities/std", + "sp-mmr-primitives/std", "sp-runtime/std", "sp-runtime-interface/std", "sp-std/std", diff --git a/crates/sp-subspace-mmr/src/host_functions.rs b/crates/sp-subspace-mmr/src/host_functions.rs index f85a33ea97..e17f205e62 100644 --- a/crates/sp-subspace-mmr/src/host_functions.rs +++ b/crates/sp-subspace-mmr/src/host_functions.rs @@ -1,7 +1,10 @@ use crate::runtime_interface::LeafData; +use codec::Decode; +use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; use sp_core::H256; -use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; +use sp_mmr_primitives::{EncodableOpaqueLeaf, MmrApi, Proof}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use std::marker::PhantomData; use std::sync::Arc; @@ -9,6 +12,9 @@ use std::sync::Arc; pub trait SubspaceMmrHostFunctions: Send + Sync { /// Returns the MMR Leaf data for given consensus block hash fn get_mmr_leaf_data(&self, consensus_block_hash: H256) -> Option; + + /// Verifies the mmr proof using consensus chain. + fn verify_mmr_proof(&self, leaves: Vec, encoded_proof: Vec) -> bool; } sp_externalities::decl_extension! { @@ -41,7 +47,8 @@ impl SubspaceMmrHostFunctions for SubspaceMmrHostFunctionsImpl, - Client: HeaderBackend, + Client: HeaderBackend + ProvideRuntimeApi, + Client::Api: MmrApi>, { fn get_mmr_leaf_data(&self, consensus_block_hash: H256) -> Option { let header = self @@ -56,4 +63,22 @@ where extrinsics_root: H256::from_slice(header.extrinsics_root().as_ref()), }) } + + fn verify_mmr_proof(&self, leaves: Vec, encoded_proof: Vec) -> bool { + // always use the parent hash in case there is a re-org happening + let parent_hash = *self + .consensus_client + .header(self.consensus_client.info().best_hash) + .expect("Database error is fatal in host function, there is no recovery from this; qed") + .expect("Header must be available. There is no recovery if not available; qed.") + .parent_hash(); + let api = self.consensus_client.runtime_api(); + let proof = match Proof::::decode(&mut encoded_proof.as_ref()) { + Ok(proof) => proof, + Err(_) => return false, + }; + api.verify_proof(parent_hash, leaves, proof).expect( + "Runtime Api should not fail in host function, there is no recovery from this; qed.", + ).is_ok() + } } diff --git a/crates/sp-subspace-mmr/src/lib.rs b/crates/sp-subspace-mmr/src/lib.rs index 913825b04f..91a71f4940 100644 --- a/crates/sp-subspace-mmr/src/lib.rs +++ b/crates/sp-subspace-mmr/src/lib.rs @@ -20,6 +20,8 @@ #[cfg(feature = "std")] pub mod host_functions; mod runtime_interface; +#[cfg(feature = "std")] +pub use runtime_interface::domain_mmr_runtime_interface::HostFunctions as DomainHostFunctions; pub use runtime_interface::subspace_mmr_runtime_interface; #[cfg(feature = "std")] pub use runtime_interface::subspace_mmr_runtime_interface::HostFunctions; diff --git a/crates/sp-subspace-mmr/src/runtime_interface.rs b/crates/sp-subspace-mmr/src/runtime_interface.rs index f62f1187cf..c5d826e65e 100644 --- a/crates/sp-subspace-mmr/src/runtime_interface.rs +++ b/crates/sp-subspace-mmr/src/runtime_interface.rs @@ -5,6 +5,7 @@ use scale_info::TypeInfo; use sp_core::H256; #[cfg(feature = "std")] use sp_externalities::ExternalitiesExt; +use sp_mmr_primitives::EncodableOpaqueLeaf; use sp_runtime_interface::runtime_interface; /// MMR related runtime interface @@ -24,3 +25,18 @@ pub struct LeafData { pub state_root: H256, pub extrinsics_root: H256, } + +#[runtime_interface] +pub trait DomainMmrRuntimeInterface { + /// Verifies the given MMR proof using the leaves provided + #[allow(dead_code)] + fn verify_mmr_proof( + &mut self, + leaves: Vec, + encoded_proof: Vec, + ) -> bool { + self.extension::() + .expect("No `SubspaceMmrExtension` associated for the current context!") + .verify_mmr_proof(leaves, encoded_proof) + } +} diff --git a/crates/subspace-service/src/lib.rs b/crates/subspace-service/src/lib.rs index 82c0e735c3..d7b8d83e94 100644 --- a/crates/subspace-service/src/lib.rs +++ b/crates/subspace-service/src/lib.rs @@ -243,7 +243,8 @@ where + 'static, Client::Api: SubspaceApi + DomainsApi - + BundleProducerElectionApi, + + BundleProducerElectionApi + + MmrApi>, { fn extensions_for( &self, @@ -421,7 +422,8 @@ where + DomainsApi + FraudProofApi + BundleProducerElectionApi - + ObjectsApi, + + ObjectsApi + + MmrApi>, { let telemetry = config .telemetry_endpoints @@ -582,7 +584,8 @@ where Client::Api: TaggedTransactionQueue + DomainsApi + FraudProofApi - + SubspaceApi, + + SubspaceApi + + MmrApi>, { /// Task manager. pub task_manager: TaskManager, diff --git a/domains/service/Cargo.toml b/domains/service/Cargo.toml index 4f79eec666..3a77d1621b 100644 --- a/domains/service/Cargo.toml +++ b/domains/service/Cargo.toml @@ -54,9 +54,11 @@ sp-core = { version = "21.0.0", git = "https://github.com/subspace/polkadot-sdk" sp-domains = { version = "0.1.0", path = "../../crates/sp-domains" } sp-domains-fraud-proof = { version = "0.1.0", path = "../../crates/sp-domains-fraud-proof" } sp-messenger = { version = "0.1.0", path = "../../domains/primitives/messenger" } +sp-mmr-primitives = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-offchain = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-runtime = { version = "24.0.0", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-session = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-subspace-mmr = { version = "0.1.0", path = "../../crates/sp-subspace-mmr" } sp-transaction-pool = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } subspace-core-primitives = { version = "0.1.0", path = "../../crates/subspace-core-primitives" } subspace-runtime-primitives = { version = "0.1.0", path = "../../crates/subspace-runtime-primitives" } diff --git a/domains/service/src/domain.rs b/domains/service/src/domain.rs index 53bacd5390..9d16bcab2c 100644 --- a/domains/service/src/domain.rs +++ b/domains/service/src/domain.rs @@ -1,6 +1,6 @@ use crate::providers::{BlockImportProvider, RpcProvider}; use crate::transaction_pool::FullChainApiWrapper; -use crate::{FullBackend, FullClient, RuntimeExecutor}; +use crate::{DomainExtensionsFactory, FullBackend, FullClient, RuntimeExecutor}; use cross_domain_message_gossip::ChainTxPoolMsg; use domain_client_block_preprocessor::inherents::CreateInherentDataProvider; use domain_client_message_relayer::GossipMessageSink; @@ -10,7 +10,9 @@ use domain_runtime_primitives::{Balance, DomainCoreApi, Hash}; use futures::channel::mpsc; use futures::Stream; use pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi; -use sc_client_api::{BlockBackend, BlockImportNotification, BlockchainEvents, ProofProvider}; +use sc_client_api::{ + BlockBackend, BlockImportNotification, BlockchainEvents, ExecutorProvider, ProofProvider, +}; use sc_consensus::SharedBlockImport; use sc_network::NetworkPeers; use sc_rpc_api::DenyUnsafe; @@ -28,11 +30,12 @@ use sp_blockchain::{HeaderBackend, HeaderMetadata}; use sp_consensus::SyncOracle; use sp_consensus_slots::Slot; use sp_core::traits::SpawnEssentialNamed; -use sp_core::{Decode, Encode}; +use sp_core::{Decode, Encode, H256}; use sp_domains::{BundleProducerElectionApi, DomainId, DomainsApi, OperatorId}; use sp_domains_fraud_proof::FraudProofApi; use sp_messenger::messages::ChainId; use sp_messenger::{MessengerApi, RelayerApi}; +use sp_mmr_primitives::MmrApi; use sp_offchain::OffchainWorkerApi; use sp_runtime::traits::{Block as BlockT, NumberFor}; use sp_session::SessionKeys; @@ -141,7 +144,9 @@ where + Send + Sync + 'static, - CClient::Api: DomainsApi + MessengerApi>, + CClient::Api: DomainsApi + + MessengerApi> + + MmrApi>, RuntimeApi: ConstructRuntimeApi> + Send + Sync + 'static, RuntimeApi::RuntimeApi: TaggedTransactionQueue + MessengerApi> + ApiExt, @@ -167,6 +172,13 @@ where )?; let client = Arc::new(client); + client + .execution_extensions() + .set_extensions_factory(DomainExtensionsFactory::<_, CBlock, Block> { + consensus_client: consensus_client.clone(), + _marker: Default::default(), + }); + let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); let telemetry = telemetry.map(|(worker, telemetry)| { @@ -267,7 +279,8 @@ where + RelayerApi> + MessengerApi> + BundleProducerElectionApi - + FraudProofApi, + + FraudProofApi + + MmrApi>, IBNS: Stream, mpsc::Sender<()>)> + Send + 'static, CIBNS: Stream> + Send + 'static, NSNS: Stream + Send + 'static, diff --git a/domains/service/src/lib.rs b/domains/service/src/lib.rs index fe4332f865..5f4f5ee7b6 100644 --- a/domains/service/src/lib.rs +++ b/domains/service/src/lib.rs @@ -9,6 +9,7 @@ mod transaction_pool; pub use self::domain::{new_full, DomainOperator, DomainParams, FullPool, NewFull}; use futures::channel::oneshot; use futures::{FutureExt, StreamExt}; +use sc_client_api::execution_extensions::ExtensionsFactory; use sc_client_api::{BlockBackend, BlockchainEvents, HeaderBackend, ProofProvider}; use sc_consensus::ImportQueue; use sc_network::config::Roles; @@ -27,19 +28,28 @@ use sc_service::{ use sc_transaction_pool_api::MaintainedTransactionPool; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender}; use sp_api::ProvideRuntimeApi; +use sp_api::__private::Extensions; use sp_blockchain::HeaderMetadata; use sp_consensus::block_validation::{Chain, DefaultBlockAnnounceValidator}; -use sp_runtime::traits::{Block as BlockT, BlockIdTo, Zero}; +use sp_core::H256; +use sp_mmr_primitives::MmrApi; +use sp_runtime::traits::{Block as BlockT, BlockIdTo, NumberFor, Zero}; +use sp_subspace_mmr::host_functions::{SubspaceMmrExtension, SubspaceMmrHostFunctionsImpl}; +use std::marker::PhantomData; use std::sync::Arc; /// Host functions required for Subspace domain #[cfg(not(feature = "runtime-benchmarks"))] -pub type HostFunctions = (sp_io::SubstrateHostFunctions,); +pub type HostFunctions = ( + sp_io::SubstrateHostFunctions, + sp_subspace_mmr::DomainHostFunctions, +); /// Host functions required for Subspace domain #[cfg(feature = "runtime-benchmarks")] pub type HostFunctions = ( sp_io::SubstrateHostFunctions, + sp_subspace_mmr::DomainHostFunctions, frame_benchmarking::benchmarking::HostFunctions, ); @@ -51,6 +61,34 @@ pub type FullClient = TFullClient = sc_service::TFullBackend; +pub(crate) struct DomainExtensionsFactory { + consensus_client: Arc, + _marker: PhantomData<(CBlock, Block)>, +} + +impl ExtensionsFactory + for DomainExtensionsFactory +where + Block: BlockT, + CBlock: BlockT, + CBlock::Hash: From, + CClient: HeaderBackend + ProvideRuntimeApi + 'static, + CClient::Api: MmrApi>, +{ + fn extensions_for( + &self, + _block_hash: Block::Hash, + _block_number: NumberFor, + ) -> Extensions { + let mut exts = Extensions::new(); + exts.register(SubspaceMmrExtension::new(Arc::new( + SubspaceMmrHostFunctionsImpl::::new(self.consensus_client.clone()), + ))); + + exts + } +} + /// Build the network service, the network status sinks and an RPC sender. /// /// Port from `sc_service::build_network` mostly the same with block sync disabled. diff --git a/test/subspace-test-service/Cargo.toml b/test/subspace-test-service/Cargo.toml index df67b1a7c0..c2fdfb3130 100644 --- a/test/subspace-test-service/Cargo.toml +++ b/test/subspace-test-service/Cargo.toml @@ -46,6 +46,7 @@ sp-domains = { version = "0.1.0", path = "../../crates/sp-domains" } sp-domains-fraud-proof = { version = "0.1.0", path = "../../crates/sp-domains-fraud-proof" } sp-externalities = { version = "0.19.0", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-keyring = { git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-mmr-primitives = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-subspace-mmr = { version = "0.1.0", path = "../../crates/sp-subspace-mmr" } sp-timestamp = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-inherents = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } diff --git a/test/subspace-test-service/src/lib.rs b/test/subspace-test-service/src/lib.rs index e67f4160ca..70e169c9e0 100644 --- a/test/subspace-test-service/src/lib.rs +++ b/test/subspace-test-service/src/lib.rs @@ -63,6 +63,7 @@ use sp_domains_fraud_proof::{FraudProofExtension, FraudProofHostFunctionsImpl}; use sp_externalities::Extensions; use sp_inherents::{InherentData, InherentDataProvider}; use sp_keyring::Sr25519Keyring; +use sp_mmr_primitives::MmrApi; use sp_runtime::generic::{BlockId, Digest}; use sp_runtime::traits::{ BlakeTwo256, Block as BlockT, Hash as HashT, Header as HeaderT, NumberFor, @@ -221,7 +222,9 @@ where DomainBlock: BlockT, DomainBlock::Hash: Into + From, Client: BlockBackend + HeaderBackend + ProvideRuntimeApi + 'static, - Client::Api: DomainsApi + BundleProducerElectionApi, + Client::Api: DomainsApi + + BundleProducerElectionApi + + MmrApi>, Executor: CodeExecutor + sc_executor::RuntimeVersionOf, { fn extensions_for( From 489e22e682ef23d0c2d2297f0620009a4e612f35 Mon Sep 17 00:00:00 2001 From: vedhavyas Date: Mon, 5 Feb 2024 11:40:14 +0530 Subject: [PATCH 3/9] define singular mmr proof verification and state root extraction for paller-messenger --- Cargo.lock | 4 ++++ crates/sp-subspace-mmr/src/lib.rs | 10 ++++++++- crates/subspace-runtime/src/lib.rs | 16 ++++++++++++++ domains/pallets/messenger/src/lib.rs | 6 ++++- domains/pallets/messenger/src/mock.rs | 2 ++ domains/primitives/messenger/src/lib.rs | 19 ++++++++++++++++ domains/runtime/evm/Cargo.toml | 4 ++++ domains/runtime/evm/src/lib.rs | 29 ++++++++++++++++++++++--- domains/test/runtime/evm/Cargo.toml | 4 ++++ domains/test/runtime/evm/src/lib.rs | 29 ++++++++++++++++++++++--- test/subspace-test-runtime/src/lib.rs | 16 ++++++++++++++ 11 files changed, 131 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 272c54543d..c3d58215e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3137,11 +3137,13 @@ dependencies = [ "sp-domains", "sp-inherents", "sp-messenger", + "sp-mmr-primitives", "sp-offchain", "sp-runtime", "sp-session", "sp-std", "sp-storage", + "sp-subspace-mmr", "sp-transaction-pool", "sp-version", "subspace-core-primitives", @@ -3186,10 +3188,12 @@ dependencies = [ "sp-domains", "sp-inherents", "sp-messenger", + "sp-mmr-primitives", "sp-offchain", "sp-runtime", "sp-session", "sp-std", + "sp-subspace-mmr", "sp-transaction-pool", "sp-version", "subspace-core-primitives", diff --git a/crates/sp-subspace-mmr/src/lib.rs b/crates/sp-subspace-mmr/src/lib.rs index 91a71f4940..86a7652512 100644 --- a/crates/sp-subspace-mmr/src/lib.rs +++ b/crates/sp-subspace-mmr/src/lib.rs @@ -22,9 +22,9 @@ pub mod host_functions; mod runtime_interface; #[cfg(feature = "std")] pub use runtime_interface::domain_mmr_runtime_interface::HostFunctions as DomainHostFunctions; -pub use runtime_interface::subspace_mmr_runtime_interface; #[cfg(feature = "std")] pub use runtime_interface::subspace_mmr_runtime_interface::HostFunctions; +pub use runtime_interface::{domain_mmr_runtime_interface, subspace_mmr_runtime_interface}; use codec::{Codec, Decode, Encode}; use scale_info::TypeInfo; @@ -38,6 +38,14 @@ pub enum MmrLeaf { V0(LeafDataV0), } +impl MmrLeaf { + pub fn state_root(&self) -> Hash { + match self { + MmrLeaf::V0(leaf) => leaf.state_root.clone(), + } + } +} + /// MMR v0 leaf data #[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone)] pub struct LeafDataV0 { diff --git a/crates/subspace-runtime/src/lib.rs b/crates/subspace-runtime/src/lib.rs index 7e8afe658b..622d18c88e 100644 --- a/crates/subspace-runtime/src/lib.rs +++ b/crates/subspace-runtime/src/lib.rs @@ -69,6 +69,7 @@ use sp_messenger::messages::{ BlockInfo, BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, ExtractedStateRootsFromProof, MessageId, }; +use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_runtime::traits::{ AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Convert, Keccak256, NumberFor, @@ -492,6 +493,19 @@ impl sp_messenger::OnXDMRewards for OnXDMRewards { } } +pub struct MmrProofVerifier; +impl sp_messenger::MmrProofVerifier for MmrProofVerifier { + fn verify_proof_and_extract_consensus_state_root( + opaque_leaf: EncodableOpaqueLeaf, + proof: Proof, + ) -> Option { + let leaf: mmr::Leaf = opaque_leaf.into_opaque_leaf().try_decode()?; + let state_root = leaf.state_root(); + Mmr::verify_leaves(vec![leaf], proof).ok()?; + Some(state_root) + } +} + impl pallet_messenger::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SelfChainId = SelfChainId; @@ -510,6 +524,8 @@ impl pallet_messenger::Config for Runtime { type WeightInfo = pallet_messenger::weights::SubstrateWeight; type WeightToFee = IdentityFee; type OnXDMRewards = OnXDMRewards; + type MmrHash = mmr::Hash; + type MmrProofVerifier = MmrProofVerifier; } impl frame_system::offchain::SendTransactionTypes for Runtime diff --git a/domains/pallets/messenger/src/lib.rs b/domains/pallets/messenger/src/lib.rs index b62945ef9b..d248c1d137 100644 --- a/domains/pallets/messenger/src/lib.rs +++ b/domains/pallets/messenger/src/lib.rs @@ -113,7 +113,7 @@ mod pallet { InitiateChannelParams, Message, MessageId, MessageWeightTag, Payload, ProtocolMessageRequest, RequestResponse, VersionedPayload, }; - use sp_messenger::OnXDMRewards; + use sp_messenger::{MmrProofVerifier, OnXDMRewards}; use sp_runtime::traits::CheckedSub; use sp_runtime::ArithmeticError; use sp_std::boxed::Box; @@ -138,6 +138,10 @@ mod pallet { type WeightToFee: WeightToFee>; /// Handle XDM rewards. type OnXDMRewards: OnXDMRewards>; + /// Hash type of MMR + type MmrHash; + /// MMR proof verifier + type MmrProofVerifier: MmrProofVerifier>; } /// Pallet messenger used to communicate between chains and other blockchains. diff --git a/domains/pallets/messenger/src/mock.rs b/domains/pallets/messenger/src/mock.rs index 834337d7cb..8362296193 100644 --- a/domains/pallets/messenger/src/mock.rs +++ b/domains/pallets/messenger/src/mock.rs @@ -94,6 +94,8 @@ macro_rules! impl_runtime { type WeightInfo = (); type WeightToFee = frame_support::weights::IdentityFee; type OnXDMRewards = (); + type MmrHash = H256; + type MmrProofVerifier = (); /// function to fetch endpoint response handler by Endpoint. fn get_endpoint_handler( #[allow(unused_variables)] endpoint: &Endpoint, diff --git a/domains/primitives/messenger/src/lib.rs b/domains/primitives/messenger/src/lib.rs index fd6973fb0b..1b0bcdaff0 100644 --- a/domains/primitives/messenger/src/lib.rs +++ b/domains/primitives/messenger/src/lib.rs @@ -27,6 +27,7 @@ use messages::{ MessageId, }; use sp_domains::DomainId; +use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_std::vec::Vec; /// Trait to handle XDM rewards. @@ -38,6 +39,24 @@ impl OnXDMRewards for () { fn on_xdm_rewards(_: Balance) {} } +/// Trait to verify MMR proofs +pub trait MmrProofVerifier { + /// Returns consensus state root if the given MMR proof is valid + fn verify_proof_and_extract_consensus_state_root( + leaf: EncodableOpaqueLeaf, + proof: Proof, + ) -> Option; +} + +impl MmrProofVerifier for () { + fn verify_proof_and_extract_consensus_state_root( + _leaf: EncodableOpaqueLeaf, + _proof: Proof, + ) -> Option { + None + } +} + sp_api::decl_runtime_apis! { /// Api useful for relayers to fetch messages and submit transactions. pub trait RelayerApi< BlockNumber> diff --git a/domains/runtime/evm/Cargo.toml b/domains/runtime/evm/Cargo.toml index 599d3f7e30..f2c3fce475 100644 --- a/domains/runtime/evm/Cargo.toml +++ b/domains/runtime/evm/Cargo.toml @@ -51,11 +51,13 @@ sp-core = { version = "21.0.0", default-features = false, git = "https://github. sp-domains = { version = "0.1.0", path = "../../../crates/sp-domains", default-features = false } sp-inherents = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-messenger = { version = "0.1.0", default-features = false, path = "../../primitives/messenger" } +sp-mmr-primitives = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-offchain = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-session = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-std = { version = "8.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-storage = { version = "13.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8", optional = true } +sp-subspace-mmr = { version = "0.1.0", default-features = false, path = "../../../crates/sp-subspace-mmr" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-version = { version = "22.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } subspace-core-primitives = { version = "0.1.0", path = "../../../crates/subspace-core-primitives", default-features = false } @@ -105,10 +107,12 @@ std = [ "sp-session/std", "sp-inherents/std", "sp-messenger/std", + "sp-mmr-primitives/std", "sp-offchain/std", "sp-runtime/std", "sp-std/std", "sp-storage?/std", + "sp-subspace-mmr/std", "sp-transaction-pool/std", "sp-version/std", "subspace-core-primitives/std", diff --git a/domains/runtime/evm/src/lib.rs b/domains/runtime/evm/src/lib.rs index 9c9a1f0541..ed0cddc32f 100644 --- a/domains/runtime/evm/src/lib.rs +++ b/domains/runtime/evm/src/lib.rs @@ -48,11 +48,12 @@ use sp_messenger::messages::{ BlockInfo, BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, ExtractedStateRootsFromProof, MessageId, }; +use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_runtime::generic::Era; use sp_runtime::traits::{ BlakeTwo256, Block as BlockT, Checkable, Convert, DispatchInfoOf, Dispatchable, - IdentifyAccount, IdentityLookup, One, PostDispatchInfoOf, SignedExtension, UniqueSaturatedInto, - ValidateUnsigned, Verify, Zero, + IdentifyAccount, IdentityLookup, Keccak256, One, PostDispatchInfoOf, SignedExtension, + UniqueSaturatedInto, ValidateUnsigned, Verify, Zero, }; use sp_runtime::transaction_validity::{ InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError, @@ -63,8 +64,12 @@ use sp_runtime::{ pub use sp_runtime::{MultiAddress, Perbill, Permill}; use sp_std::marker::PhantomData; use sp_std::prelude::*; +use sp_subspace_mmr::domain_mmr_runtime_interface::verify_mmr_proof; +use sp_subspace_mmr::MmrLeaf; use sp_version::RuntimeVersion; -use subspace_runtime_primitives::{Moment, SlowAdjustingFeeUpdate}; +use subspace_runtime_primitives::{ + BlockNumber as ConsensusBlockNumber, Hash as ConsensusBlockHash, Moment, SlowAdjustingFeeUpdate, +}; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = EthereumSignature; @@ -394,6 +399,22 @@ impl sp_messenger::OnXDMRewards for OnXDMRewards { } } +type MmrHash = ::Output; + +pub struct MmrProofVerifier; +impl sp_messenger::MmrProofVerifier for MmrProofVerifier { + fn verify_proof_and_extract_consensus_state_root( + opaque_leaf: EncodableOpaqueLeaf, + proof: Proof, + ) -> Option { + let leaf: MmrLeaf = + opaque_leaf.into_opaque_leaf().try_decode()?; + let state_root = leaf.state_root(); + verify_mmr_proof(vec![EncodableOpaqueLeaf::from_leaf(&leaf)], proof.encode()) + .then_some(state_root) + } +} + impl pallet_messenger::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SelfChainId = SelfChainId; @@ -412,6 +433,8 @@ impl pallet_messenger::Config for Runtime { type WeightInfo = pallet_messenger::weights::SubstrateWeight; type WeightToFee = IdentityFee; type OnXDMRewards = OnXDMRewards; + type MmrHash = MmrHash; + type MmrProofVerifier = MmrProofVerifier; } impl frame_system::offchain::SendTransactionTypes for Runtime diff --git a/domains/test/runtime/evm/Cargo.toml b/domains/test/runtime/evm/Cargo.toml index 5e2cfb09b3..b07e4a07a2 100644 --- a/domains/test/runtime/evm/Cargo.toml +++ b/domains/test/runtime/evm/Cargo.toml @@ -50,10 +50,12 @@ sp-core = { version = "21.0.0", default-features = false, git = "https://github. sp-domains = { version = "0.1.0", path = "../../../../crates/sp-domains", default-features = false } sp-inherents = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-messenger = { version = "0.1.0", default-features = false, path = "../../../primitives/messenger" } +sp-mmr-primitives = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-offchain = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-session = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-std = { version = "8.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-subspace-mmr = { version = "0.1.0", default-features = false, path = "../../../../crates/sp-subspace-mmr" } sp-transaction-pool = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-version = { version = "22.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } subspace-core-primitives = { version = "0.1.0", path = "../../../../crates/subspace-core-primitives", default-features = false } @@ -101,9 +103,11 @@ std = [ "sp-session/std", "sp-inherents/std", "sp-messenger/std", + "sp-mmr-primitives/std", "sp-offchain/std", "sp-runtime/std", "sp-std/std", + "sp-subspace-mmr/std", "sp-transaction-pool/std", "sp-version/std", "subspace-core-primitives/std", diff --git a/domains/test/runtime/evm/src/lib.rs b/domains/test/runtime/evm/src/lib.rs index 5bdaae1794..ee7effbe83 100644 --- a/domains/test/runtime/evm/src/lib.rs +++ b/domains/test/runtime/evm/src/lib.rs @@ -47,11 +47,12 @@ use sp_messenger::messages::{ BlockInfo, BlockMessagesWithStorageKey, ChainId, ChannelId, CrossDomainMessage, ExtractedStateRootsFromProof, MessageId, }; +use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_runtime::generic::Era; use sp_runtime::traits::{ BlakeTwo256, Block as BlockT, Checkable, Convert, DispatchInfoOf, Dispatchable, - IdentifyAccount, IdentityLookup, One, PostDispatchInfoOf, SignedExtension, UniqueSaturatedInto, - ValidateUnsigned, Verify, Zero, + IdentifyAccount, IdentityLookup, Keccak256, One, PostDispatchInfoOf, SignedExtension, + UniqueSaturatedInto, ValidateUnsigned, Verify, Zero, }; use sp_runtime::transaction_validity::{ InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError, @@ -62,8 +63,12 @@ use sp_runtime::{ pub use sp_runtime::{MultiAddress, Perbill, Permill}; use sp_std::marker::PhantomData; use sp_std::prelude::*; +use sp_subspace_mmr::domain_mmr_runtime_interface::verify_mmr_proof; +use sp_subspace_mmr::MmrLeaf; use sp_version::RuntimeVersion; -use subspace_runtime_primitives::Moment; +use subspace_runtime_primitives::{ + BlockNumber as ConsensusBlockNumber, Hash as ConsensusBlockHash, Moment, +}; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = EthereumSignature; @@ -392,6 +397,22 @@ impl sp_messenger::OnXDMRewards for OnXDMRewards { } } +type MmrHash = ::Output; + +pub struct MmrProofVerifier; +impl sp_messenger::MmrProofVerifier for MmrProofVerifier { + fn verify_proof_and_extract_consensus_state_root( + opaque_leaf: EncodableOpaqueLeaf, + proof: Proof, + ) -> Option { + let leaf: MmrLeaf = + opaque_leaf.into_opaque_leaf().try_decode()?; + let state_root = leaf.state_root(); + verify_mmr_proof(vec![EncodableOpaqueLeaf::from_leaf(&leaf)], proof.encode()) + .then_some(state_root) + } +} + impl pallet_messenger::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SelfChainId = SelfChainId; @@ -410,6 +431,8 @@ impl pallet_messenger::Config for Runtime { type WeightInfo = pallet_messenger::weights::SubstrateWeight; type WeightToFee = IdentityFee; type OnXDMRewards = OnXDMRewards; + type MmrHash = MmrHash; + type MmrProofVerifier = MmrProofVerifier; } impl frame_system::offchain::SendTransactionTypes for Runtime diff --git a/test/subspace-test-runtime/src/lib.rs b/test/subspace-test-runtime/src/lib.rs index 92552643fb..0acb82e18e 100644 --- a/test/subspace-test-runtime/src/lib.rs +++ b/test/subspace-test-runtime/src/lib.rs @@ -63,6 +63,7 @@ use sp_messenger::messages::{ BlockInfo, BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, ExtractedStateRootsFromProof, MessageId, }; +use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_runtime::traits::{ AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, ConstBool, Convert, DispatchInfoOf, Keccak256, NumberFor, PostDispatchInfoOf, Zero, @@ -537,6 +538,19 @@ impl sp_messenger::endpoint::DomainInfo for DomainInfo } } +pub struct MmrProofVerifier; +impl sp_messenger::MmrProofVerifier for MmrProofVerifier { + fn verify_proof_and_extract_consensus_state_root( + opaque_leaf: EncodableOpaqueLeaf, + proof: Proof, + ) -> Option { + let leaf: mmr::Leaf = opaque_leaf.into_opaque_leaf().try_decode()?; + let state_root = leaf.state_root(); + Mmr::verify_leaves(vec![leaf], proof).ok()?; + Some(state_root) + } +} + impl pallet_messenger::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SelfChainId = SelfChainId; @@ -555,6 +569,8 @@ impl pallet_messenger::Config for Runtime { type WeightInfo = pallet_messenger::weights::SubstrateWeight; type WeightToFee = IdentityFee; type OnXDMRewards = (); + type MmrHash = mmr::Hash; + type MmrProofVerifier = MmrProofVerifier; } impl frame_system::offchain::SendTransactionTypes for Runtime From 3cc34b4e9b8efc3d3e4812d3559fe6805fe3a292 Mon Sep 17 00:00:00 2001 From: vedhavyas Date: Mon, 5 Feb 2024 17:46:01 +0530 Subject: [PATCH 4/9] define host function to get storage keys for a given chain and update messenger xdm verification. --- Cargo.lock | 26 ++++ crates/pallet-domains/src/lib.rs | 4 + crates/sp-domains/src/lib.rs | 8 + crates/subspace-runtime/Cargo.toml | 2 + crates/subspace-runtime/src/lib.rs | 35 +++++ crates/subspace-service/Cargo.toml | 2 + crates/subspace-service/src/lib.rs | 23 ++- .../src/stateless_runtime.rs | 20 ++- domains/pallets/messenger/src/benchmarking.rs | 34 ++--- domains/pallets/messenger/src/lib.rs | 114 +++++++++----- domains/pallets/messenger/src/mock.rs | 1 + .../messenger-host-functions/Cargo.toml | 49 ++++++ .../src/host_functions.rs | 139 ++++++++++++++++++ .../messenger-host-functions/src/lib.rs | 55 +++++++ .../src/runtime_interface.rs | 17 +++ domains/primitives/messenger/src/lib.rs | 35 +++++ domains/primitives/messenger/src/messages.rs | 27 ++++ domains/runtime/evm/Cargo.toml | 2 + domains/runtime/evm/src/lib.rs | 36 +++++ domains/service/Cargo.toml | 1 + domains/service/src/domain.rs | 6 +- domains/service/src/lib.rs | 17 ++- domains/test/runtime/evm/Cargo.toml | 2 + domains/test/runtime/evm/src/lib.rs | 35 +++++ test/subspace-test-runtime/Cargo.toml | 2 + test/subspace-test-runtime/src/lib.rs | 35 +++++ 26 files changed, 660 insertions(+), 67 deletions(-) create mode 100644 domains/primitives/messenger-host-functions/Cargo.toml create mode 100644 domains/primitives/messenger-host-functions/src/host_functions.rs create mode 100644 domains/primitives/messenger-host-functions/src/lib.rs create mode 100644 domains/primitives/messenger-host-functions/src/runtime_interface.rs diff --git a/Cargo.lock b/Cargo.lock index c3d58215e6..6649786d56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2706,6 +2706,7 @@ dependencies = [ "sp-domains-fraud-proof", "sp-io", "sp-messenger", + "sp-messenger-host-functions", "sp-mmr-primitives", "sp-offchain", "sp-runtime", @@ -3137,6 +3138,7 @@ dependencies = [ "sp-domains", "sp-inherents", "sp-messenger", + "sp-messenger-host-functions", "sp-mmr-primitives", "sp-offchain", "sp-runtime", @@ -3188,6 +3190,7 @@ dependencies = [ "sp-domains", "sp-inherents", "sp-messenger", + "sp-messenger-host-functions", "sp-mmr-primitives", "sp-offchain", "sp-runtime", @@ -11019,6 +11022,25 @@ dependencies = [ "sp-trie", ] +[[package]] +name = "sp-messenger-host-functions" +version = "0.1.0" +dependencies = [ + "domain-block-preprocessor", + "parity-scale-codec", + "sc-executor", + "scale-info", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-domains", + "sp-externalities", + "sp-messenger", + "sp-runtime", + "sp-runtime-interface", + "sp-std", +] + [[package]] name = "sp-metadata-ir" version = "0.1.0" @@ -11922,6 +11944,7 @@ dependencies = [ "sp-inherents", "sp-io", "sp-messenger", + "sp-messenger-host-functions", "sp-mmr-primitives", "sp-objects", "sp-offchain", @@ -12003,6 +12026,8 @@ dependencies = [ "sp-domains-fraud-proof", "sp-externalities", "sp-io", + "sp-messenger", + "sp-messenger-host-functions", "sp-mmr-primitives", "sp-objects", "sp-offchain", @@ -12089,6 +12114,7 @@ dependencies = [ "sp-domains-fraud-proof", "sp-inherents", "sp-messenger", + "sp-messenger-host-functions", "sp-mmr-primitives", "sp-objects", "sp-offchain", diff --git a/crates/pallet-domains/src/lib.rs b/crates/pallet-domains/src/lib.rs index 25b8159dc3..2bbd896126 100644 --- a/crates/pallet-domains/src/lib.rs +++ b/crates/pallet-domains/src/lib.rs @@ -2005,6 +2005,10 @@ impl Pallet { ) -> Option> { BlockTree::::get(domain_id, domain_number) } + + pub fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Vec { + LatestConfirmedDomainBlock::::hashed_key_for(domain_id) + } } impl Pallet diff --git a/crates/sp-domains/src/lib.rs b/crates/sp-domains/src/lib.rs index 2bf5415bea..9d84c77890 100644 --- a/crates/sp-domains/src/lib.rs +++ b/crates/sp-domains/src/lib.rs @@ -230,6 +230,14 @@ impl ChainId { ChainId::Domain(_) => false, } } + + #[inline] + pub fn maybe_domain_chain(&self) -> Option { + match self { + ChainId::Consensus => None, + ChainId::Domain(domain_id) => Some(*domain_id), + } + } } impl From for ChainId { diff --git a/crates/subspace-runtime/Cargo.toml b/crates/subspace-runtime/Cargo.toml index 442e0e1f6b..1ac8a7f95b 100644 --- a/crates/subspace-runtime/Cargo.toml +++ b/crates/subspace-runtime/Cargo.toml @@ -51,6 +51,7 @@ sp-domains = { version = "0.1.0", default-features = false, path = "../sp-domain sp-domains-fraud-proof = { version = "0.1.0", default-features = false, path = "../sp-domains-fraud-proof" } sp-inherents = { git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8", default-features = false, version = "4.0.0-dev" } sp-messenger = { version = "0.1.0", default-features = false, path = "../../domains/primitives/messenger" } +sp-messenger-host-functions = { version = "0.1.0", default-features = false, path = "../../domains/primitives/messenger-host-functions" } sp-mmr-primitives = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-objects = { version = "0.1.0", default-features = false, path = "../sp-objects" } sp-offchain = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } @@ -110,6 +111,7 @@ std = [ "sp-inherents/std", "sp-io/std", "sp-messenger/std", + "sp-messenger-host-functions/std", "sp-mmr-primitives/std", "sp-objects/std", "sp-offchain/std", diff --git a/crates/subspace-runtime/src/lib.rs b/crates/subspace-runtime/src/lib.rs index 622d18c88e..219fb7e34a 100644 --- a/crates/subspace-runtime/src/lib.rs +++ b/crates/subspace-runtime/src/lib.rs @@ -69,6 +69,7 @@ use sp_messenger::messages::{ BlockInfo, BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, ExtractedStateRootsFromProof, MessageId, }; +use sp_messenger_host_functions::{get_storage_key, StorageKeyRequest}; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_runtime::traits::{ AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Convert, Keccak256, @@ -506,6 +507,27 @@ impl sp_messenger::MmrProofVerifier for MmrProofVerifier { } } +pub struct StorageKeys; +impl sp_messenger::StorageKeys for StorageKeys { + fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Option> { + Some(Domains::confirmed_domain_block_storage_key(domain_id)) + } + + fn outbox_storage_key(chain_id: ChainId, message_id: MessageId) -> Option> { + get_storage_key(StorageKeyRequest::OutboxStorageKey { + chain_id, + message_id, + }) + } + + fn inbox_responses_storage_key(chain_id: ChainId, message_id: MessageId) -> Option> { + get_storage_key(StorageKeyRequest::InboxResponseStorageKey { + chain_id, + message_id, + }) + } +} + impl pallet_messenger::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SelfChainId = SelfChainId; @@ -526,6 +548,7 @@ impl pallet_messenger::Config for Runtime { type OnXDMRewards = OnXDMRewards; type MmrHash = mmr::Hash; type MmrProofVerifier = MmrProofVerifier; + type StorageKeys = StorageKeys; } impl frame_system::offchain::SendTransactionTypes for Runtime @@ -1181,6 +1204,18 @@ impl_runtime_apis! { ) -> bool{ Messenger::is_domain_info_confirmed(domain_id, domain_block_info, domain_state_root) } + + fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Vec { + Domains::confirmed_domain_block_storage_key(domain_id) + } + + fn outbox_storage_key(message_id: MessageId) -> Vec { + Messenger::outbox_storage_key(message_id) + } + + fn inbox_response_storage_key(message_id: MessageId) -> Vec { + Messenger::inbox_response_storage_key(message_id) + } } impl sp_messenger::RelayerApi for Runtime { diff --git a/crates/subspace-service/Cargo.toml b/crates/subspace-service/Cargo.toml index 19d4a7256d..24550de837 100644 --- a/crates/subspace-service/Cargo.toml +++ b/crates/subspace-service/Cargo.toml @@ -63,6 +63,8 @@ sp-domains = { version = "0.1.0", path = "../sp-domains" } sp-domains-fraud-proof = { version = "0.1.0", path = "../sp-domains-fraud-proof" } sp-externalities = { version = "0.19.0", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-io = { version = "23.0.0", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-messenger = { version = "0.1.0", path = "../../domains/primitives/messenger" } +sp-messenger-host-functions = { version = "0.1.0", path = "../../domains/primitives/messenger-host-functions" } sp-mmr-primitives = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-objects = { version = "0.1.0", path = "../sp-objects" } sp-offchain = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } diff --git a/crates/subspace-service/src/lib.rs b/crates/subspace-service/src/lib.rs index d7b8d83e94..a5f1484d86 100644 --- a/crates/subspace-service/src/lib.rs +++ b/crates/subspace-service/src/lib.rs @@ -91,6 +91,8 @@ use sp_core::H256; use sp_domains::{BundleProducerElectionApi, DomainsApi}; use sp_domains_fraud_proof::{FraudProofApi, FraudProofExtension, FraudProofHostFunctionsImpl}; use sp_externalities::Extensions; +use sp_messenger::MessengerApi; +use sp_messenger_host_functions::{MessengerExtension, MessengerHostFunctionsImpl}; use sp_mmr_primitives::MmrApi; use sp_objects::ObjectsApi; use sp_offchain::OffchainWorkerApi; @@ -198,6 +200,7 @@ pub type HostFunctions = ( sp_consensus_subspace::consensus::HostFunctions, sp_domains_fraud_proof::HostFunctions, sp_subspace_mmr::HostFunctions, + sp_messenger_host_functions::HostFunctions, ); /// Host functions required for Subspace @@ -208,6 +211,7 @@ pub type HostFunctions = ( sp_consensus_subspace::consensus::HostFunctions, sp_domains_fraud_proof::HostFunctions, sp_subspace_mmr::HostFunctions, + sp_messenger_host_functions::HostFunctions, ); /// Runtime executor for Subspace @@ -244,7 +248,8 @@ where Client::Api: SubspaceApi + DomainsApi + BundleProducerElectionApi - + MmrApi>, + + MmrApi> + + MessengerApi>, { fn extensions_for( &self, @@ -371,6 +376,13 @@ where SubspaceMmrHostFunctionsImpl::::new(self.client.clone()), ))); + exts.register(MessengerExtension::new(Arc::new( + MessengerHostFunctionsImpl::::new( + self.client.clone(), + self.executor.clone(), + ), + ))); + exts } } @@ -423,7 +435,8 @@ where + FraudProofApi + BundleProducerElectionApi + ObjectsApi - + MmrApi>, + + MmrApi> + + MessengerApi>, { let telemetry = config .telemetry_endpoints @@ -585,7 +598,8 @@ where + DomainsApi + FraudProofApi + SubspaceApi - + MmrApi>, + + MmrApi> + + MessengerApi>, { /// Task manager. pub task_manager: TaskManager, @@ -644,7 +658,8 @@ where + DomainsApi + FraudProofApi + ObjectsApi - + MmrApi, + + MmrApi + + MessengerApi>, { let PartialComponents { client, diff --git a/domains/client/block-preprocessor/src/stateless_runtime.rs b/domains/client/block-preprocessor/src/stateless_runtime.rs index d885d53db6..334a4ed61e 100644 --- a/domains/client/block-preprocessor/src/stateless_runtime.rs +++ b/domains/client/block-preprocessor/src/stateless_runtime.rs @@ -7,7 +7,7 @@ use sc_executor::RuntimeVersionOf; use sp_api::{ApiError, Core}; use sp_core::traits::{CallContext, CodeExecutor, FetchRuntimeCode, RuntimeCode}; use sp_core::Hasher; -use sp_messenger::messages::ExtractedStateRootsFromProof; +use sp_messenger::messages::{ExtractedStateRootsFromProof, MessageId}; use sp_messenger::MessengerApi; use sp_runtime::traits::{Block as BlockT, NumberFor}; use sp_runtime::Storage; @@ -167,6 +167,24 @@ where maybe_state_roots.ok_or(ApiError::Application("Empty state roots".into())) } + pub fn outbox_storage_key(&self, message_id: MessageId) -> Result, ApiError> { + let storage_key = >::outbox_storage_key( + self, + Default::default(), + message_id, + )?; + Ok(storage_key) + } + + pub fn inbox_response_storage_key(&self, message_id: MessageId) -> Result, ApiError> { + let storage_key = >::inbox_response_storage_key( + self, + Default::default(), + message_id, + )?; + Ok(storage_key) + } + pub fn extract_signer( &self, extrinsics: Vec<::Extrinsic>, diff --git a/domains/pallets/messenger/src/benchmarking.rs b/domains/pallets/messenger/src/benchmarking.rs index ad37c2a31b..ed356eb603 100644 --- a/domains/pallets/messenger/src/benchmarking.rs +++ b/domains/pallets/messenger/src/benchmarking.rs @@ -115,15 +115,14 @@ mod benchmarks { }; Inbox::::put(msg); - let xdm: CrossDomainMessage, T::Hash, StateRootOf> = - CrossDomainMessage { - src_chain_id: dst_chain_id, - dst_chain_id: T::SelfChainId::get(), - channel_id, - nonce: channel.next_inbox_nonce, - proof: dummy_proof(), - weight_tag: MessageWeightTag::EndpointRequest(endpoint), - }; + let xdm = CrossDomainMessage::, T::Hash, T::MmrHash> { + src_chain_id: dst_chain_id, + dst_chain_id: T::SelfChainId::get(), + channel_id, + nonce: channel.next_inbox_nonce, + proof: dummy_proof(), + weight_tag: MessageWeightTag::EndpointRequest(endpoint), + }; #[extrinsic_call] _(RawOrigin::None, xdm); @@ -183,15 +182,14 @@ mod benchmarks { }; OutboxResponses::::put(resp_msg); - let xdm: CrossDomainMessage, T::Hash, StateRootOf> = - CrossDomainMessage { - src_chain_id: dst_chain_id, - dst_chain_id: T::SelfChainId::get(), - channel_id, - nonce: resp_nonce, - proof: dummy_proof(), - weight_tag: MessageWeightTag::EndpointResponse(endpoint), - }; + let xdm = CrossDomainMessage::, T::Hash, T::MmrHash> { + src_chain_id: dst_chain_id, + dst_chain_id: T::SelfChainId::get(), + channel_id, + nonce: resp_nonce, + proof: dummy_proof(), + weight_tag: MessageWeightTag::EndpointResponse(endpoint), + }; #[extrinsic_call] _(RawOrigin::None, xdm); diff --git a/domains/pallets/messenger/src/lib.rs b/domains/pallets/messenger/src/lib.rs index d248c1d137..0e672b7b1e 100644 --- a/domains/pallets/messenger/src/lib.rs +++ b/domains/pallets/messenger/src/lib.rs @@ -18,6 +18,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![forbid(unsafe_code)] #![warn(rust_2018_idioms, missing_debug_implementations)] +#![feature(let_chains)] #[cfg(test)] mod mock; @@ -109,11 +110,11 @@ mod pallet { use sp_domains::DomainId; use sp_messenger::endpoint::{DomainInfo, Endpoint, EndpointHandler, EndpointRequest, Sender}; use sp_messenger::messages::{ - BlockInfo, ChainId, CrossDomainMessage, ExtractedStateRootsFromProof, - InitiateChannelParams, Message, MessageId, MessageWeightTag, Payload, - ProtocolMessageRequest, RequestResponse, VersionedPayload, + BlockInfo, ChainId, CrossDomainMessage, InitiateChannelParams, Message, MessageId, + MessageWeightTag, Payload, ProtocolMessageRequest, RequestResponse, VersionedPayload, }; - use sp_messenger::{MmrProofVerifier, OnXDMRewards}; + use sp_messenger::{MmrProofVerifier, OnXDMRewards, StorageKeys}; + use sp_mmr_primitives::EncodableOpaqueLeaf; use sp_runtime::traits::CheckedSub; use sp_runtime::ArithmeticError; use sp_std::boxed::Box; @@ -139,9 +140,11 @@ mod pallet { /// Handle XDM rewards. type OnXDMRewards: OnXDMRewards>; /// Hash type of MMR - type MmrHash; + type MmrHash: Parameter + Member + Default + Clone; /// MMR proof verifier type MmrProofVerifier: MmrProofVerifier>; + /// Storage key provider. + type StorageKeys: StorageKeys; } /// Pallet messenger used to communicate between chains and other blockchains. @@ -506,7 +509,7 @@ mod pallet { #[pallet::weight((T::WeightInfo::relay_message().saturating_add(Pallet::< T >::message_weight(& msg.weight_tag)), Pays::No))] pub fn relay_message( origin: OriginFor, - msg: CrossDomainMessage, T::Hash, StateRootOf>, + msg: CrossDomainMessage, T::Hash, T::MmrHash>, ) -> DispatchResult { ensure_none(origin)?; let inbox_msg = Inbox::::take().ok_or(Error::::MissingMessage)?; @@ -519,7 +522,7 @@ mod pallet { #[pallet::weight((T::WeightInfo::relay_message_response().saturating_add(Pallet::< T >::message_weight(& msg.weight_tag)), Pays::No))] pub fn relay_message_response( origin: OriginFor, - msg: CrossDomainMessage, T::Hash, StateRootOf>, + msg: CrossDomainMessage, T::Hash, T::MmrHash>, ) -> DispatchResult { ensure_none(origin)?; let outbox_resp_msg = OutboxResponses::::take().ok_or(Error::::MissingMessage)?; @@ -698,7 +701,7 @@ mod pallet { } pub(crate) fn do_validate_relay_message( - xdm: &CrossDomainMessage, T::Hash, StateRootOf>, + xdm: &CrossDomainMessage, T::Hash, T::MmrHash>, ) -> Result>, TransactionValidityError> { let mut should_init_channel = false; let next_nonce = match Channels::::get(xdm.src_chain_id, xdm.channel_id) { @@ -730,11 +733,13 @@ mod pallet { }; // derive the key as stored on the src_chain. - let key = StorageKey(Outbox::::hashed_key_for(( - T::SelfChainId::get(), - xdm.channel_id, - xdm.nonce, - ))); + let key = StorageKey( + T::StorageKeys::outbox_storage_key( + T::SelfChainId::get(), + (xdm.channel_id, xdm.nonce), + ) + .ok_or(UnknownTransaction::CannotLookup)?, + ); // verify and decode message let msg = Self::do_verify_xdm(next_nonce, key, xdm)?; @@ -793,7 +798,7 @@ mod pallet { } pub(crate) fn do_validate_relay_message_response( - xdm: &CrossDomainMessage, T::Hash, StateRootOf>, + xdm: &CrossDomainMessage, T::Hash, T::MmrHash>, ) -> Result<(Message>, Nonce), TransactionValidityError> { // channel should be open and message should be present in outbox let next_nonce = match Channels::::get(xdm.src_chain_id, xdm.channel_id) { @@ -810,11 +815,13 @@ mod pallet { .ok_or(TransactionValidityError::Invalid(InvalidTransaction::Call))?; // derive the key as stored on the src_chain. - let key = StorageKey(InboxResponses::::hashed_key_for(( - T::SelfChainId::get(), - xdm.channel_id, - xdm.nonce, - ))); + let key = StorageKey( + T::StorageKeys::inbox_responses_storage_key( + T::SelfChainId::get(), + (xdm.channel_id, xdm.nonce), + ) + .ok_or(UnknownTransaction::CannotLookup)?, + ); // verify, decode, and store the message let msg = Self::do_verify_xdm(next_nonce, key, xdm)?; @@ -838,7 +845,7 @@ mod pallet { pub(crate) fn do_verify_xdm( next_nonce: Nonce, storage_key: StorageKey, - xdm: &CrossDomainMessage, T::Hash, StateRootOf>, + xdm: &CrossDomainMessage, T::Hash, T::MmrHash>, ) -> Result>, TransactionValidityError> { // channel should be either already be created or match the next channelId for chain. let next_channel_id = NextChannelId::::get(xdm.src_chain_id); @@ -848,26 +855,43 @@ mod pallet { // nonce should be either be next or in future. ensure!(xdm.nonce >= next_nonce, InvalidTransaction::Call); - // TODO: verify the actual proof - let extracted_state_roots = - ExtractedStateRootsFromProof::, T::Hash, T::Hash>::default(); + let mmr_leaf = + EncodableOpaqueLeaf(xdm.proof.consensus_mmr_proof().opaque_mmr_leaf.0.clone()); - // on consensus, ensure the domain info is at K-depth and state root matches - if T::SelfChainId::get().is_consensus_chain() { - if let Some((domain_id, block_info, state_root)) = - extracted_state_roots.domain_info.clone() - { - ensure!( - Self::is_domain_info_confirmed(domain_id, block_info, state_root), - InvalidTransaction::BadProof - ) - } - } + let mmr_proof = xdm.proof.consensus_mmr_proof().proof.clone(); - let state_root = extracted_state_roots - .domain_info - .map(|(_chain_id, _info, state_root)| state_root) - .unwrap_or(extracted_state_roots.consensus_chain_state_root); + let state_root = T::MmrProofVerifier::verify_proof_and_extract_consensus_state_root( + mmr_leaf, mmr_proof, + ) + .ok_or(InvalidTransaction::BadProof)?; + + // if the message is from domain, verify domain confirmation proof + let state_root = if let Some(domain_proof) = xdm.proof.domain_proof().clone() + && let Some(domain_id) = xdm.src_chain_id.maybe_domain_chain() + { + let confirmed_domain_block_storage_key = + T::StorageKeys::confirmed_domain_block_storage_key(domain_id) + .ok_or(UnknownTransaction::CannotLookup)?; + + StorageProofVerifier::::get_decoded_value::< + sp_domains::ConfirmedDomainBlock, T::Hash>, + >( + &state_root, + domain_proof, + StorageKey(confirmed_domain_block_storage_key), + ) + .map_err(|err| { + log::error!( + target: "runtime::messenger", + "Failed to verify storage proof: {:?}", + err + ); + TransactionValidityError::Invalid(InvalidTransaction::BadProof) + })? + .state_root + } else { + state_root + }; // verify and decode the message let msg = @@ -913,6 +937,16 @@ mod pallet { confirmed && valid_state_root } + + pub fn outbox_storage_key(message_id: MessageId) -> Vec { + let (channel_id, nonce) = message_id; + Outbox::::hashed_key_for((T::SelfChainId::get(), channel_id, nonce)) + } + + pub fn inbox_response_storage_key(message_id: MessageId) -> Vec { + let (channel_id, nonce) = message_id; + InboxResponses::::hashed_key_for((T::SelfChainId::get(), channel_id, nonce)) + } } } @@ -921,14 +955,14 @@ where T: Config + frame_system::offchain::SendTransactionTypes>, { pub fn outbox_message_unsigned( - msg: CrossDomainMessage, T::Hash, StateRootOf>, + msg: CrossDomainMessage, T::Hash, T::MmrHash>, ) -> Option { let call = Call::relay_message { msg }; T::Extrinsic::new(call.into(), None) } pub fn inbox_response_message_unsigned( - msg: CrossDomainMessage, T::Hash, StateRootOf>, + msg: CrossDomainMessage, T::Hash, T::MmrHash>, ) -> Option { let call = Call::relay_message_response { msg }; T::Extrinsic::new(call.into(), None) diff --git a/domains/pallets/messenger/src/mock.rs b/domains/pallets/messenger/src/mock.rs index 8362296193..50514cdf7f 100644 --- a/domains/pallets/messenger/src/mock.rs +++ b/domains/pallets/messenger/src/mock.rs @@ -96,6 +96,7 @@ macro_rules! impl_runtime { type OnXDMRewards = (); type MmrHash = H256; type MmrProofVerifier = (); + type StorageKeys = (); /// function to fetch endpoint response handler by Endpoint. fn get_endpoint_handler( #[allow(unused_variables)] endpoint: &Endpoint, diff --git a/domains/primitives/messenger-host-functions/Cargo.toml b/domains/primitives/messenger-host-functions/Cargo.toml new file mode 100644 index 0000000000..6c90ddf6d1 --- /dev/null +++ b/domains/primitives/messenger-host-functions/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "sp-messenger-host-functions" +version = "0.1.0" +authors = ["Vedhavyas Singareddi "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://subspace.network" +repository = "https://github.com/subspace/subspace" +description = "Host functions for Messenger" +include = [ + "/src", + "/Cargo.toml", + "/README.md", +] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.6.5", default-features = false, features = ["derive"] } +domain-block-preprocessor = { version = "0.1.0", default-features = false, path = "../../../domains/client/block-preprocessor", optional = true } +scale-info = { version = "2.7.0", default-features = false, features = ["derive"] } +sc-executor = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8", default-features = false, optional = true } +sp-api = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8", optional = true } +sp-core = { version = "21.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-domains = { version = "0.1.0", default-features = false, path = "../../../crates/sp-domains" } +sp-externalities = { version = "0.19.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-messenger = { version = "0.1.0", default-features = false, path = "../../primitives/messenger" } +sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-runtime-interface = { version = "17.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-std = { version = "8.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } + +[features] +default = ["std"] +std = [ + "codec/std", + "domain-block-preprocessor", + "scale-info/std", + "sc-executor", + "sp-api/std", + "sp-blockchain", + "sp-core/std", + "sp-domains/std", + "sp-externalities/std", + "sp-messenger/std", + "sp-runtime/std", + "sp-runtime-interface/std", + "sp-std/std", +] + +runtime-benchmarks = [] diff --git a/domains/primitives/messenger-host-functions/src/host_functions.rs b/domains/primitives/messenger-host-functions/src/host_functions.rs new file mode 100644 index 0000000000..1a6c1ba01a --- /dev/null +++ b/domains/primitives/messenger-host-functions/src/host_functions.rs @@ -0,0 +1,139 @@ +use crate::StorageKeyRequest; +use domain_block_preprocessor::stateless_runtime::StatelessRuntime; +use sc_executor::RuntimeVersionOf; +use sp_api::ProvideRuntimeApi; +use sp_blockchain::HeaderBackend; +use sp_core::traits::CodeExecutor; +use sp_core::H256; +use sp_domains::{DomainId, DomainsApi}; +use sp_messenger::messages::ChainId; +use sp_messenger::MessengerApi; +use sp_runtime::traits::{Block as BlockT, Header, NumberFor}; +use std::marker::PhantomData; +use std::sync::Arc; + +/// Trait to query messenger specific details. +pub trait MessengerHostFunctions: Send + Sync { + /// Returns the storage key for the given request. + fn get_storage_key(&self, req: StorageKeyRequest) -> Option>; +} + +sp_externalities::decl_extension! { + pub struct MessengerExtension(Arc); +} + +impl MessengerExtension { + /// Create a new instance of [`MessengerExtension`]. + pub fn new(inner: Arc) -> Self { + Self(inner) + } +} + +/// Implementation of Messenger host function. +pub struct MessengerHostFunctionsImpl { + consensus_client: Arc, + executor: Arc, + _phantom: PhantomData<(Block, DomainBlock)>, +} + +impl + MessengerHostFunctionsImpl +{ + pub fn new(consensus_client: Arc, executor: Arc) -> Self { + MessengerHostFunctionsImpl { + consensus_client, + executor, + _phantom: Default::default(), + } + } +} + +impl + MessengerHostFunctionsImpl +where + Block: BlockT, + DomainBlock: BlockT, + Client: HeaderBackend + ProvideRuntimeApi, + Client::Api: DomainsApi, +{ + fn get_domain_runtime_code( + &self, + consensus_block_hash: Block::Hash, + domain_id: DomainId, + ) -> Option> { + let runtime_api = self.consensus_client.runtime_api(); + // Use the parent hash to get the actual used domain runtime code + // TODO: update once we can get the actual used domain runtime code by `consensus_block_hash` + let consensus_block_header = self + .consensus_client + .header(consensus_block_hash) + .ok() + .flatten()?; + runtime_api + .domain_runtime_code(*consensus_block_header.parent_hash(), domain_id) + .ok() + .flatten() + } +} + +impl MessengerHostFunctions + for MessengerHostFunctionsImpl +where + Block: BlockT, + Block::Hash: From, + DomainBlock: BlockT, + Client: HeaderBackend + ProvideRuntimeApi, + Client::Api: MessengerApi> + DomainsApi, + Executor: CodeExecutor + RuntimeVersionOf, +{ + fn get_storage_key(&self, req: StorageKeyRequest) -> Option> { + let best_hash = self.consensus_client.info().best_hash; + let runtime_api = self.consensus_client.runtime_api(); + match req { + StorageKeyRequest::ConfirmedDomainBlockStorageKey(domain_id) => runtime_api + .confirmed_domain_block_storage_key(best_hash, domain_id) + .map(Some), + StorageKeyRequest::OutboxStorageKey { + message_id, + chain_id: ChainId::Consensus, + } => runtime_api + .outbox_storage_key(best_hash, message_id) + .map(Some), + StorageKeyRequest::OutboxStorageKey { + message_id, + chain_id: ChainId::Domain(domain_id), + } => { + let runtime_code = self.get_domain_runtime_code(best_hash, domain_id)?; + let domain_stateless_runtime = StatelessRuntime::::new( + self.executor.clone(), + runtime_code.into(), + ); + domain_stateless_runtime + .outbox_storage_key(message_id) + .map(Some) + } + StorageKeyRequest::InboxResponseStorageKey { + message_id, + chain_id: ChainId::Consensus, + } => runtime_api + .inbox_response_storage_key(best_hash, message_id) + .map(Some), + StorageKeyRequest::InboxResponseStorageKey { + message_id, + chain_id: ChainId::Domain(domain_id), + } => { + let runtime_code = self.get_domain_runtime_code(best_hash, domain_id)?; + let domain_stateless_runtime = StatelessRuntime::::new( + self.executor.clone(), + runtime_code.into(), + ); + domain_stateless_runtime + .inbox_response_storage_key(message_id) + .map(Some) + } + } + .expect( + "Runtime Api should not fail in host function, there is no recovery from this; qed.", + ) + } +} diff --git a/domains/primitives/messenger-host-functions/src/lib.rs b/domains/primitives/messenger-host-functions/src/lib.rs new file mode 100644 index 0000000000..31a9d4eb78 --- /dev/null +++ b/domains/primitives/messenger-host-functions/src/lib.rs @@ -0,0 +1,55 @@ +// Copyright (C) 2021 Subspace Labs, Inc. +// 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. + +//! Host functions for Messenger. + +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_domains::DomainId; +use sp_messenger::messages::{ChainId, MessageId}; +use sp_runtime_interface::pass_by; +use sp_runtime_interface::pass_by::PassBy; + +#[cfg(feature = "std")] +mod host_functions; +mod runtime_interface; + +#[cfg(feature = "std")] +pub use host_functions::{MessengerExtension, MessengerHostFunctionsImpl}; +pub use runtime_interface::messenger_runtime_interface::get_storage_key; +#[cfg(feature = "std")] +pub use runtime_interface::messenger_runtime_interface::HostFunctions; + +#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone)] +pub enum StorageKeyRequest { + /// Request to get confirmed domain block storage key for given domain. + ConfirmedDomainBlockStorageKey(DomainId), + /// Request to get Outbox storage key for given chain and message. + OutboxStorageKey { + chain_id: ChainId, + message_id: MessageId, + }, + /// Request to get Inbox response storage key for given chain and message. + InboxResponseStorageKey { + chain_id: ChainId, + message_id: MessageId, + }, +} + +impl PassBy for StorageKeyRequest { + type PassBy = pass_by::Codec; +} diff --git a/domains/primitives/messenger-host-functions/src/runtime_interface.rs b/domains/primitives/messenger-host-functions/src/runtime_interface.rs new file mode 100644 index 0000000000..bc9a969441 --- /dev/null +++ b/domains/primitives/messenger-host-functions/src/runtime_interface.rs @@ -0,0 +1,17 @@ +#[cfg(feature = "std")] +use crate::host_functions::MessengerExtension; +use crate::StorageKeyRequest; +#[cfg(feature = "std")] +use sp_externalities::ExternalitiesExt; +use sp_runtime_interface::runtime_interface; + +/// Messenger related runtime interface +#[runtime_interface] +pub trait MessengerRuntimeInterface { + /// Returns the storage key. + fn get_storage_key(&mut self, req: StorageKeyRequest) -> Option> { + self.extension::() + .expect("No `MessengerExtension` associated for the current context!") + .get_storage_key(req) + } +} diff --git a/domains/primitives/messenger/src/lib.rs b/domains/primitives/messenger/src/lib.rs index 1b0bcdaff0..1f371dfe51 100644 --- a/domains/primitives/messenger/src/lib.rs +++ b/domains/primitives/messenger/src/lib.rs @@ -57,6 +57,32 @@ impl MmrProofVerifier for () { } } +/// Trait that return various storage keys for storages on Consensus chain and domains +pub trait StorageKeys { + /// Returns the storage key for confirmed domain block on conensus chain + fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Option>; + + /// Returns the outbox storage key for given chain. + fn outbox_storage_key(chain_id: ChainId, message_id: MessageId) -> Option>; + + /// Returns the inbox responses storage key for given chain. + fn inbox_responses_storage_key(chain_id: ChainId, message_id: MessageId) -> Option>; +} + +impl StorageKeys for () { + fn confirmed_domain_block_storage_key(_domain_id: DomainId) -> Option> { + None + } + + fn outbox_storage_key(_chain_id: ChainId, _message_id: MessageId) -> Option> { + None + } + + fn inbox_responses_storage_key(_chain_id: ChainId, _message_id: MessageId) -> Option> { + None + } +} + sp_api::decl_runtime_apis! { /// Api useful for relayers to fetch messages and submit transactions. pub trait RelayerApi< BlockNumber> @@ -101,5 +127,14 @@ sp_api::decl_runtime_apis! { domain_block_info: BlockInfo, domain_state_root: Block::Hash, ) -> bool; + + /// Returns the confirmed domain block storage for given domain. + fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Vec; + + /// Returns storage key for outbox for a given message_id. + fn outbox_storage_key(message_id: MessageId) -> Vec; + + /// Returns storage key for inbox response for a given message_id. + fn inbox_response_storage_key(message_id: MessageId) -> Vec; } } diff --git a/domains/primitives/messenger/src/messages.rs b/domains/primitives/messenger/src/messages.rs index c307da3d51..3589d47987 100644 --- a/domains/primitives/messenger/src/messages.rs +++ b/domains/primitives/messenger/src/messages.rs @@ -199,6 +199,33 @@ impl Proof Proof::Domain { message_proof, .. } => message_proof.clone(), } } + + pub fn consensus_mmr_proof( + &self, + ) -> ConsensusChainMmrLeafProof + where + CBlockNumber: Clone, + CBlockHash: Clone, + MmrHash: Clone, + { + match self { + Proof::Consensus { + consensus_chain_mmr_proof, + .. + } => consensus_chain_mmr_proof.clone(), + Proof::Domain { + consensus_chain_mmr_proof, + .. + } => consensus_chain_mmr_proof.clone(), + } + } + + pub fn domain_proof(&self) -> Option { + match self { + Proof::Consensus { .. } => None, + Proof::Domain { domain_proof, .. } => Some(domain_proof.clone()), + } + } } /// Holds the Block info and state roots from which a proof was constructed. diff --git a/domains/runtime/evm/Cargo.toml b/domains/runtime/evm/Cargo.toml index f2c3fce475..b268667e0c 100644 --- a/domains/runtime/evm/Cargo.toml +++ b/domains/runtime/evm/Cargo.toml @@ -51,6 +51,7 @@ sp-core = { version = "21.0.0", default-features = false, git = "https://github. sp-domains = { version = "0.1.0", path = "../../../crates/sp-domains", default-features = false } sp-inherents = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-messenger = { version = "0.1.0", default-features = false, path = "../../primitives/messenger" } +sp-messenger-host-functions = { version = "0.1.0", default-features = false, path = "../../primitives/messenger-host-functions" } sp-mmr-primitives = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-offchain = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } @@ -107,6 +108,7 @@ std = [ "sp-session/std", "sp-inherents/std", "sp-messenger/std", + "sp-messenger-host-functions/std", "sp-mmr-primitives/std", "sp-offchain/std", "sp-runtime/std", diff --git a/domains/runtime/evm/src/lib.rs b/domains/runtime/evm/src/lib.rs index ed0cddc32f..3ac56cb9e2 100644 --- a/domains/runtime/evm/src/lib.rs +++ b/domains/runtime/evm/src/lib.rs @@ -48,6 +48,7 @@ use sp_messenger::messages::{ BlockInfo, BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, ExtractedStateRootsFromProof, MessageId, }; +use sp_messenger_host_functions::{get_storage_key, StorageKeyRequest}; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_runtime::generic::Era; use sp_runtime::traits::{ @@ -415,6 +416,27 @@ impl sp_messenger::MmrProofVerifier for MmrProofVerifier { } } +pub struct StorageKeys; +impl sp_messenger::StorageKeys for StorageKeys { + fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Option> { + get_storage_key(StorageKeyRequest::ConfirmedDomainBlockStorageKey(domain_id)) + } + + fn outbox_storage_key(chain_id: ChainId, message_id: MessageId) -> Option> { + get_storage_key(StorageKeyRequest::OutboxStorageKey { + chain_id, + message_id, + }) + } + + fn inbox_responses_storage_key(chain_id: ChainId, message_id: MessageId) -> Option> { + get_storage_key(StorageKeyRequest::InboxResponseStorageKey { + chain_id, + message_id, + }) + } +} + impl pallet_messenger::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SelfChainId = SelfChainId; @@ -435,6 +457,7 @@ impl pallet_messenger::Config for Runtime { type OnXDMRewards = OnXDMRewards; type MmrHash = MmrHash; type MmrProofVerifier = MmrProofVerifier; + type StorageKeys = StorageKeys; } impl frame_system::offchain::SendTransactionTypes for Runtime @@ -1030,6 +1053,19 @@ impl_runtime_apis! { // not valid on evm domain false } + + fn confirmed_domain_block_storage_key(_domain_id: DomainId) -> Vec { + // invalid call from Domain runtime + vec![] + } + + fn outbox_storage_key(message_id: MessageId) -> Vec { + Messenger::outbox_storage_key(message_id) + } + + fn inbox_response_storage_key(message_id: MessageId) -> Vec { + Messenger::inbox_response_storage_key(message_id) + } } impl sp_messenger::RelayerApi for Runtime { diff --git a/domains/service/Cargo.toml b/domains/service/Cargo.toml index 3a77d1621b..9ceda3809c 100644 --- a/domains/service/Cargo.toml +++ b/domains/service/Cargo.toml @@ -54,6 +54,7 @@ sp-core = { version = "21.0.0", git = "https://github.com/subspace/polkadot-sdk" sp-domains = { version = "0.1.0", path = "../../crates/sp-domains" } sp-domains-fraud-proof = { version = "0.1.0", path = "../../crates/sp-domains-fraud-proof" } sp-messenger = { version = "0.1.0", path = "../../domains/primitives/messenger" } +sp-messenger-host-functions = { version = "0.1.0", path = "../../domains/primitives/messenger-host-functions" } sp-mmr-primitives = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-offchain = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-runtime = { version = "24.0.0", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } diff --git a/domains/service/src/domain.rs b/domains/service/src/domain.rs index 9d16bcab2c..e48f55ffc6 100644 --- a/domains/service/src/domain.rs +++ b/domains/service/src/domain.rs @@ -128,7 +128,7 @@ fn new_partial( ( Option, Option, - RuntimeExecutor, + Arc, SharedBlockImport, ), >, @@ -172,10 +172,12 @@ where )?; let client = Arc::new(client); + let executor = Arc::new(executor); client .execution_extensions() .set_extensions_factory(DomainExtensionsFactory::<_, CBlock, Block> { consensus_client: consensus_client.clone(), + executor: executor.clone(), _marker: Default::default(), }); @@ -421,8 +423,6 @@ where telemetry: telemetry.as_mut(), })?; - let code_executor = Arc::new(code_executor); - let spawn_essential = task_manager.spawn_essential_handle(); let (bundle_sender, _bundle_receiver) = tracing_unbounded("domain_bundle_stream", 100); diff --git a/domains/service/src/lib.rs b/domains/service/src/lib.rs index 5f4f5ee7b6..3514069133 100644 --- a/domains/service/src/lib.rs +++ b/domains/service/src/lib.rs @@ -32,6 +32,9 @@ use sp_api::__private::Extensions; use sp_blockchain::HeaderMetadata; use sp_consensus::block_validation::{Chain, DefaultBlockAnnounceValidator}; use sp_core::H256; +use sp_domains::DomainsApi; +use sp_messenger::MessengerApi; +use sp_messenger_host_functions::{MessengerExtension, MessengerHostFunctionsImpl}; use sp_mmr_primitives::MmrApi; use sp_runtime::traits::{Block as BlockT, BlockIdTo, NumberFor, Zero}; use sp_subspace_mmr::host_functions::{SubspaceMmrExtension, SubspaceMmrHostFunctionsImpl}; @@ -42,6 +45,7 @@ use std::sync::Arc; #[cfg(not(feature = "runtime-benchmarks"))] pub type HostFunctions = ( sp_io::SubstrateHostFunctions, + sp_messenger_host_functions::HostFunctions, sp_subspace_mmr::DomainHostFunctions, ); @@ -49,6 +53,7 @@ pub type HostFunctions = ( #[cfg(feature = "runtime-benchmarks")] pub type HostFunctions = ( sp_io::SubstrateHostFunctions, + sp_messenger_host_functions::HostFunctions, sp_subspace_mmr::DomainHostFunctions, frame_benchmarking::benchmarking::HostFunctions, ); @@ -63,6 +68,7 @@ pub type FullBackend = sc_service::TFullBackend; pub(crate) struct DomainExtensionsFactory { consensus_client: Arc, + executor: Arc, _marker: PhantomData<(CBlock, Block)>, } @@ -73,7 +79,9 @@ where CBlock: BlockT, CBlock::Hash: From, CClient: HeaderBackend + ProvideRuntimeApi + 'static, - CClient::Api: MmrApi>, + CClient::Api: MmrApi> + + MessengerApi> + + DomainsApi, { fn extensions_for( &self, @@ -85,6 +93,13 @@ where SubspaceMmrHostFunctionsImpl::::new(self.consensus_client.clone()), ))); + exts.register(MessengerExtension::new(Arc::new( + MessengerHostFunctionsImpl::::new( + self.consensus_client.clone(), + self.executor.clone(), + ), + ))); + exts } } diff --git a/domains/test/runtime/evm/Cargo.toml b/domains/test/runtime/evm/Cargo.toml index b07e4a07a2..2481e7053c 100644 --- a/domains/test/runtime/evm/Cargo.toml +++ b/domains/test/runtime/evm/Cargo.toml @@ -50,6 +50,7 @@ sp-core = { version = "21.0.0", default-features = false, git = "https://github. sp-domains = { version = "0.1.0", path = "../../../../crates/sp-domains", default-features = false } sp-inherents = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-messenger = { version = "0.1.0", default-features = false, path = "../../../primitives/messenger" } +sp-messenger-host-functions = { version = "0.1.0", default-features = false, path = "../../../primitives/messenger-host-functions" } sp-mmr-primitives = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-offchain = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } @@ -103,6 +104,7 @@ std = [ "sp-session/std", "sp-inherents/std", "sp-messenger/std", + "sp-messenger-host-functions/std", "sp-mmr-primitives/std", "sp-offchain/std", "sp-runtime/std", diff --git a/domains/test/runtime/evm/src/lib.rs b/domains/test/runtime/evm/src/lib.rs index ee7effbe83..69e3167f73 100644 --- a/domains/test/runtime/evm/src/lib.rs +++ b/domains/test/runtime/evm/src/lib.rs @@ -47,6 +47,7 @@ use sp_messenger::messages::{ BlockInfo, BlockMessagesWithStorageKey, ChainId, ChannelId, CrossDomainMessage, ExtractedStateRootsFromProof, MessageId, }; +use sp_messenger_host_functions::{get_storage_key, StorageKeyRequest}; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_runtime::generic::Era; use sp_runtime::traits::{ @@ -413,6 +414,27 @@ impl sp_messenger::MmrProofVerifier for MmrProofVerifier { } } +pub struct StorageKeys; +impl sp_messenger::StorageKeys for StorageKeys { + fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Option> { + get_storage_key(StorageKeyRequest::ConfirmedDomainBlockStorageKey(domain_id)) + } + + fn outbox_storage_key(chain_id: ChainId, message_id: MessageId) -> Option> { + get_storage_key(StorageKeyRequest::OutboxStorageKey { + chain_id, + message_id, + }) + } + + fn inbox_responses_storage_key(chain_id: ChainId, message_id: MessageId) -> Option> { + get_storage_key(StorageKeyRequest::InboxResponseStorageKey { + chain_id, + message_id, + }) + } +} + impl pallet_messenger::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SelfChainId = SelfChainId; @@ -433,6 +455,7 @@ impl pallet_messenger::Config for Runtime { type OnXDMRewards = OnXDMRewards; type MmrHash = MmrHash; type MmrProofVerifier = MmrProofVerifier; + type StorageKeys = StorageKeys; } impl frame_system::offchain::SendTransactionTypes for Runtime @@ -1014,6 +1037,18 @@ impl_runtime_apis! { // this is always invalid on domains since we do not have info other domains. false } + + fn confirmed_domain_block_storage_key(_domain_id: DomainId) -> Vec { + vec![] + } + + fn outbox_storage_key(message_id: MessageId) -> Vec { + Messenger::outbox_storage_key(message_id) + } + + fn inbox_response_storage_key(message_id: MessageId) -> Vec { + Messenger::inbox_response_storage_key(message_id) + } } impl sp_messenger::RelayerApi for Runtime { diff --git a/test/subspace-test-runtime/Cargo.toml b/test/subspace-test-runtime/Cargo.toml index 23b993f68f..901c2c597b 100644 --- a/test/subspace-test-runtime/Cargo.toml +++ b/test/subspace-test-runtime/Cargo.toml @@ -46,6 +46,7 @@ sp-domains = { version = "0.1.0", default-features = false, path = "../../crates sp-domains-fraud-proof = { version = "0.1.0", default-features = false, path = "../../crates/sp-domains-fraud-proof" } sp-inherents = { git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8", default-features = false, version = "4.0.0-dev" } sp-messenger = { version = "0.1.0", default-features = false, path = "../../domains/primitives/messenger" } +sp-messenger-host-functions = { version = "0.1.0", default-features = false, path = "../../domains/primitives/messenger-host-functions" } sp-mmr-primitives = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-objects = { version = "0.1.0", default-features = false, path = "../../crates/sp-objects" } sp-offchain = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } @@ -100,6 +101,7 @@ std = [ "sp-domains-fraud-proof/std", "sp-inherents/std", "sp-messenger/std", + "sp-messenger-host-functions/std", "sp-mmr-primitives/std", "sp-objects/std", "sp-offchain/std", diff --git a/test/subspace-test-runtime/src/lib.rs b/test/subspace-test-runtime/src/lib.rs index 0acb82e18e..d8f527bdfc 100644 --- a/test/subspace-test-runtime/src/lib.rs +++ b/test/subspace-test-runtime/src/lib.rs @@ -63,6 +63,7 @@ use sp_messenger::messages::{ BlockInfo, BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, ExtractedStateRootsFromProof, MessageId, }; +use sp_messenger_host_functions::{get_storage_key, StorageKeyRequest}; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_runtime::traits::{ AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, ConstBool, Convert, @@ -551,6 +552,27 @@ impl sp_messenger::MmrProofVerifier for MmrProofVerifier { } } +pub struct StorageKeys; +impl sp_messenger::StorageKeys for StorageKeys { + fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Option> { + Some(Domains::confirmed_domain_block_storage_key(domain_id)) + } + + fn outbox_storage_key(chain_id: ChainId, message_id: MessageId) -> Option> { + get_storage_key(StorageKeyRequest::OutboxStorageKey { + chain_id, + message_id, + }) + } + + fn inbox_responses_storage_key(chain_id: ChainId, message_id: MessageId) -> Option> { + get_storage_key(StorageKeyRequest::InboxResponseStorageKey { + chain_id, + message_id, + }) + } +} + impl pallet_messenger::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SelfChainId = SelfChainId; @@ -571,6 +593,7 @@ impl pallet_messenger::Config for Runtime { type OnXDMRewards = (); type MmrHash = mmr::Hash; type MmrProofVerifier = MmrProofVerifier; + type StorageKeys = StorageKeys; } impl frame_system::offchain::SendTransactionTypes for Runtime @@ -1373,6 +1396,18 @@ impl_runtime_apis! { ) -> bool{ Messenger::is_domain_info_confirmed(domain_id, domain_block_info, domain_state_root) } + + fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Vec { + Domains::confirmed_domain_block_storage_key(domain_id) + } + + fn outbox_storage_key(message_id: MessageId) -> Vec { + Messenger::outbox_storage_key(message_id) + } + + fn inbox_response_storage_key(message_id: MessageId) -> Vec { + Messenger::inbox_response_storage_key(message_id) + } } impl sp_messenger::RelayerApi for Runtime { From faf85fd8dd09f210bb2d0d55957c60347f590082 Mon Sep 17 00:00:00 2001 From: vedhavyas Date: Mon, 5 Feb 2024 18:53:12 +0530 Subject: [PATCH 5/9] update messenger runtime api definitions and cleanup unused leftover code --- crates/subspace-runtime/src/lib.rs | 50 ++------ domains/client/block-preprocessor/src/lib.rs | 10 +- .../src/stateless_runtime.rs | 20 +--- .../block-preprocessor/src/xdm_verifier.rs | 61 ---------- domains/client/relayer/src/lib.rs | 54 +++------ domains/client/relayer/src/worker.rs | 4 +- domains/pallets/messenger/src/benchmarking.rs | 11 +- domains/pallets/messenger/src/lib.rs | 51 ++------ domains/pallets/messenger/src/mock.rs | 1 - domains/pallets/messenger/src/tests.rs | 17 ++- domains/primitives/messenger/src/endpoint.rs | 21 +--- domains/primitives/messenger/src/lib.rs | 23 ++-- domains/primitives/messenger/src/messages.rs | 111 +++--------------- domains/runtime/evm/src/lib.rs | 30 ++--- domains/service/src/domain.rs | 21 ++-- domains/service/src/transaction_pool.rs | 43 ++----- domains/test/runtime/evm/src/lib.rs | 28 ++--- test/subspace-test-runtime/src/lib.rs | 50 ++------ 18 files changed, 123 insertions(+), 483 deletions(-) delete mode 100644 domains/client/block-preprocessor/src/xdm_verifier.rs diff --git a/crates/subspace-runtime/src/lib.rs b/crates/subspace-runtime/src/lib.rs index 219fb7e34a..36ac25974f 100644 --- a/crates/subspace-runtime/src/lib.rs +++ b/crates/subspace-runtime/src/lib.rs @@ -65,10 +65,7 @@ use sp_domains::{ }; use sp_domains_fraud_proof::fraud_proof::FraudProof; use sp_messenger::endpoint::{Endpoint, EndpointHandler as EndpointHandlerT, EndpointId}; -use sp_messenger::messages::{ - BlockInfo, BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, - ExtractedStateRootsFromProof, MessageId, -}; +use sp_messenger::messages::{BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, MessageId}; use sp_messenger_host_functions::{get_storage_key, StorageKeyRequest}; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_runtime::traits::{ @@ -472,18 +469,6 @@ parameter_types! { pub const SelfChainId: ChainId = ChainId::Consensus; } -pub struct DomainInfo; - -impl sp_messenger::endpoint::DomainInfo for DomainInfo { - fn domain_best_number(domain_id: DomainId) -> Option { - Domains::domain_best_number(domain_id) - } - - fn domain_state_root(_domain_id: DomainId, _number: BlockNumber, _hash: Hash) -> Option { - None - } -} - pub struct OnXDMRewards; impl sp_messenger::OnXDMRewards for OnXDMRewards { @@ -495,6 +480,7 @@ impl sp_messenger::OnXDMRewards for OnXDMRewards { } pub struct MmrProofVerifier; + impl sp_messenger::MmrProofVerifier for MmrProofVerifier { fn verify_proof_and_extract_consensus_state_root( opaque_leaf: EncodableOpaqueLeaf, @@ -508,6 +494,7 @@ impl sp_messenger::MmrProofVerifier for MmrProofVerifier { } pub struct StorageKeys; + impl sp_messenger::StorageKeys for StorageKeys { fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Option> { Some(Domains::confirmed_domain_block_storage_key(domain_id)) @@ -541,7 +528,6 @@ impl pallet_messenger::Config for Runtime { } type Currency = Balances; - type DomainInfo = DomainInfo; type ConfirmationDepth = RelayConfirmationDepth; type WeightInfo = pallet_messenger::weights::SubstrateWeight; type WeightToFee = IdentityFee; @@ -633,6 +619,7 @@ const_assert!(MinOperatorStake::get() >= MinNominatorStake::get()); const_assert!(StakeWithdrawalLockingPeriod::get() >= BlockTreePruningDepth::get()); pub struct BlockSlot; + impl pallet_domains::BlockSlot for BlockSlot { fn current_slot() -> sp_consensus_slots::Slot { Subspace::current_slot() @@ -805,16 +792,7 @@ fn extract_segment_headers(ext: &UncheckedExtrinsic) -> Option, -) -> Option< - ExtractedStateRootsFromProof< - domain_runtime_primitives::BlockNumber, - domain_runtime_primitives::Hash, - domain_runtime_primitives::Hash, - >, -> { +fn is_xdm_valid(encoded_ext: Vec) -> Option { if let Ok(ext) = UncheckedExtrinsic::decode(&mut encoded_ext.as_slice()) { match &ext.function { RuntimeCall::Messenger(pallet_messenger::Call::relay_message { .. }) => None, @@ -1191,18 +1169,10 @@ impl_runtime_apis! { } impl sp_messenger::MessengerApi for Runtime { - fn extract_xdm_proof_state_roots( + fn is_xdm_valid( extrinsic: Vec, - ) -> Option::Hash, ::Hash>> { - extract_xdm_proof_state_roots(extrinsic) - } - - fn is_domain_info_confirmed( - domain_id: DomainId, - domain_block_info: BlockInfo::Hash>, - domain_state_root: ::Hash, - ) -> bool{ - Messenger::is_domain_info_confirmed(domain_id, domain_block_info, domain_state_root) + ) -> Option { + is_xdm_valid(extrinsic) } fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Vec { @@ -1231,11 +1201,11 @@ impl_runtime_apis! { Messenger::get_block_messages() } - fn outbox_message_unsigned(msg: CrossDomainMessage::Hash, ::Hash>) -> Option<::Extrinsic> { + fn outbox_message_unsigned(msg: CrossDomainMessage<::Hash, ::Hash>) -> Option<::Extrinsic> { Messenger::outbox_message_unsigned(msg) } - fn inbox_response_message_unsigned(msg: CrossDomainMessage::Hash, ::Hash>) -> Option<::Extrinsic> { + fn inbox_response_message_unsigned(msg: CrossDomainMessage<::Hash, ::Hash>) -> Option<::Extrinsic> { Messenger::inbox_response_message_unsigned(msg) } diff --git a/domains/client/block-preprocessor/src/lib.rs b/domains/client/block-preprocessor/src/lib.rs index 7dcea37fb5..0be63c46ac 100644 --- a/domains/client/block-preprocessor/src/lib.rs +++ b/domains/client/block-preprocessor/src/lib.rs @@ -9,13 +9,12 @@ //! 5. Push back the potential new domain runtime extrisnic. #![warn(rust_2018_idioms)] +#![feature(let_chains)] pub mod inherents; pub mod stateless_runtime; -pub mod xdm_verifier; use crate::inherents::is_runtime_upgraded; -use crate::xdm_verifier::is_valid_xdm; use codec::Encode; use domain_runtime_primitives::opaque::AccountId; use domain_runtime_primitives::DomainCoreApi; @@ -320,12 +319,7 @@ where // TODO: the behavior is changed, as before invalid XDM will be dropped silently, // and the other extrinsic of the bundle will be continue processed, now the whole // bundle is considered as invalid and excluded from further processing. - if !is_valid_xdm::( - &self.consensus_client, - at, - &self.client, - &extrinsic, - )? { + if let Some(false) = runtime_api.is_xdm_valid(at, extrinsic.encode())? { // TODO: Generate a fraud proof for this invalid bundle return Ok(BundleValidity::Invalid(InvalidBundleType::InvalidXDM( index as u32, diff --git a/domains/client/block-preprocessor/src/stateless_runtime.rs b/domains/client/block-preprocessor/src/stateless_runtime.rs index 334a4ed61e..8230e03357 100644 --- a/domains/client/block-preprocessor/src/stateless_runtime.rs +++ b/domains/client/block-preprocessor/src/stateless_runtime.rs @@ -7,7 +7,7 @@ use sc_executor::RuntimeVersionOf; use sp_api::{ApiError, Core}; use sp_core::traits::{CallContext, CodeExecutor, FetchRuntimeCode, RuntimeCode}; use sp_core::Hasher; -use sp_messenger::messages::{ExtractedStateRootsFromProof, MessageId}; +use sp_messenger::messages::MessageId; use sp_messenger::MessengerApi; use sp_runtime::traits::{Block as BlockT, NumberFor}; use sp_runtime::Storage; @@ -86,12 +86,6 @@ impl FetchRuntimeCode for StatelessRuntime { } } -pub type ExtractedStateRoots = ExtractedStateRootsFromProof< - NumberFor, - ::Hash, - ::Hash, ->; - pub type ExtractSignerResult = Vec<(Option, ::Extrinsic)>; impl StatelessRuntime @@ -155,18 +149,6 @@ where }) } - pub fn extract_state_roots( - &self, - ext: &Block::Extrinsic, - ) -> Result, ApiError> { - let maybe_state_roots = >::extract_xdm_proof_state_roots( - self, - Default::default(), - ext.encode(), - )?; - maybe_state_roots.ok_or(ApiError::Application("Empty state roots".into())) - } - pub fn outbox_storage_key(&self, message_id: MessageId) -> Result, ApiError> { let storage_key = >::outbox_storage_key( self, diff --git a/domains/client/block-preprocessor/src/xdm_verifier.rs b/domains/client/block-preprocessor/src/xdm_verifier.rs deleted file mode 100644 index 3d90589e56..0000000000 --- a/domains/client/block-preprocessor/src/xdm_verifier.rs +++ /dev/null @@ -1,61 +0,0 @@ -use codec::Encode; -use sp_api::ProvideRuntimeApi; -use sp_blockchain::{Error, HeaderBackend}; -use sp_domains::DomainsApi; -use sp_messenger::messages::BlockInfo; -use sp_messenger::MessengerApi; -use sp_runtime::traits::{Block as BlockT, Header, NumberFor}; -use std::sync::Arc; - -/// Verifies if the xdm has the correct proof generated from known parent block. -/// This is used by the Domains to validate Extrinsics using their embeded consensus chain. -/// Returns either true if the XDM is valid else false. -/// Returns Error when required calls to fetch header info fails. -pub fn is_valid_xdm( - consensus_client: &Arc, - at: Block::Hash, - client: &Arc, - extrinsic: &Block::Extrinsic, -) -> Result -where - CClient: HeaderBackend + ProvideRuntimeApi + 'static, - CClient::Api: DomainsApi + MessengerApi>, - Block: BlockT, - CBlock: BlockT, - NumberFor: From>, - CBlock::Hash: From, - Client: ProvideRuntimeApi, - Client::Api: MessengerApi>, -{ - // TODO: Type conversions here do not make sense, it shouldn't ever be required to convert between domain/consensus - // blocks because they are never 1:1. - if let Some(state_roots) = client - .runtime_api() - .extract_xdm_proof_state_roots(at, extrinsic.encode())? - { - // verify consensus chain state root - if let Some(header) = consensus_client.header(CBlock::Hash::from( - state_roots.consensus_chain_block_info.block_hash, - ))? { - if *header.state_root() != CBlock::Hash::from(state_roots.consensus_chain_state_root) { - return Ok(false); - } - } - - if let Some((domain_id, block_info, state_root)) = state_roots.domain_info { - if !consensus_client.runtime_api().is_domain_info_confirmed( - consensus_client.info().best_hash, - domain_id, - BlockInfo { - block_number: NumberFor::::from(block_info.block_number), - block_hash: block_info.block_hash.into(), - }, - state_root.into(), - )? { - return Ok(false); - } - } - } - - Ok(true) -} diff --git a/domains/client/relayer/src/lib.rs b/domains/client/relayer/src/lib.rs index 92404f50fc..0a4f561135 100644 --- a/domains/client/relayer/src/lib.rs +++ b/domains/client/relayer/src/lib.rs @@ -11,10 +11,10 @@ use scale_info::TypeInfo; use sp_api::ProvideRuntimeApi; use sp_domains::DomainsApi; use sp_messenger::messages::{ - BlockInfo, BlockMessageWithStorageKey, BlockMessagesWithStorageKey, ChainId, - ConsensusChainMmrLeafProof, CrossDomainMessage, DomainStateRootStorage, Proof, + BlockMessageWithStorageKey, BlockMessagesWithStorageKey, ChainId, ConsensusChainMmrLeafProof, + CrossDomainMessage, Proof, }; -use sp_messenger::RelayerApi; +use sp_messenger::{MessengerApi, RelayerApi}; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof as MmrProof}; use sp_runtime::traits::{Block as BlockT, CheckedSub, Header as HeaderT, NumberFor, One, Zero}; use sp_runtime::ArithmeticError; @@ -82,7 +82,7 @@ impl From for Error { } } -type ProofOf = Proof, ::Hash, ::Hash>; +type ProofOf = Proof<::Hash, ::Hash>; type UnProcessedBlocks = Vec<(NumberFor, ::Hash)>; impl Relayer @@ -115,18 +115,15 @@ where ) -> Result, Error> { consensus_chain_client .header(block_hash)? - .map(|header| (*header.number(), header.hash(), *header.state_root())) - .and_then(|(block_number, block_hash, _state_root)| { + .map(|header| (header.hash(), *header.state_root())) + .and_then(|(block_hash, _state_root)| { let proof = consensus_chain_client .read_proof(block_hash, &mut [key].into_iter()) .ok()?; // TODO: derive the correct proof here Some(Proof::Consensus { consensus_chain_mmr_proof: ConsensusChainMmrLeafProof { - block_info: BlockInfo { - block_number, - block_hash, - }, + consensus_block_hash: block_hash, opaque_mmr_leaf: EncodableOpaqueLeaf(vec![]), proof: MmrProof { leaf_indices: vec![], @@ -141,8 +138,8 @@ where } fn construct_cross_chain_message_and_submit< - Submitter: Fn(CrossDomainMessage, Block::Hash, Block::Hash>) -> Result<(), Error>, - ProofConstructor: Fn(Block::Hash, &[u8]) -> Result, Block::Hash, Block::Hash>, Error>, + Submitter: Fn(CrossDomainMessage) -> Result<(), Error>, + ProofConstructor: Fn(Block::Hash, &[u8]) -> Result, Error>, >( block_hash: Block::Hash, msgs: Vec, @@ -283,7 +280,7 @@ where NumberFor: Into>, CCBlock::Hash: Into, CCC: HeaderBackend + ProvideRuntimeApi + ProofProvider, - CCC::Api: DomainsApi, + CCC::Api: DomainsApi + MessengerApi>, { let chain_id = Self::chain_id(domain_client)?; let ChainId::Domain(domain_id) = chain_id else { @@ -348,12 +345,8 @@ where } // generate domain proof that points to the state root of the domain block on Consensus chain. - let storage_key = - DomainStateRootStorage::, Block::Hash, Block::Hash>::storage_key( - domain_id, - *domain_block_header.number(), - domain_block_header.hash(), - ); + let storage_key = consensus_chain_api + .confirmed_domain_block_storage_key(best_consensus_chain_hash, domain_id)?; // construct storage proof for the core domain state root using system domain backend. let domain_state_root_proof = consensus_chain_client.read_proof( @@ -361,17 +354,12 @@ where &mut [storage_key.as_ref()].into_iter(), )?; - let consensus_chain_block_info = BlockInfo { - block_number: *best_consensus_chain_block_header.number(), - block_hash: best_consensus_chain_hash, - }; - Self::construct_cross_chain_message_and_submit( confirmed_block_hash, filtered_messages.outbox, |block_hash, key| { Self::construct_domain_storage_proof_for_key_at( - consensus_chain_block_info.clone(), + best_consensus_chain_hash, domain_client, block_hash, key, @@ -387,7 +375,7 @@ where filtered_messages.inbox_responses, |block_id, key| { Self::construct_domain_storage_proof_for_key_at( - consensus_chain_block_info.clone(), + best_consensus_chain_hash, domain_client, block_id, key, @@ -402,8 +390,8 @@ where } /// Constructs the proof for the given key using the domain backend. - fn construct_domain_storage_proof_for_key_at( - consensus_chain_block_info: BlockInfo, + fn construct_domain_storage_proof_for_key_at( + consensus_chain_block_hash: CHash, domain_client: &Arc, block_hash: Block::Hash, key: &[u8], @@ -411,7 +399,6 @@ where domain_proof: StorageProof, ) -> Result, Error> where - CNumber: Into>, CHash: Into, { domain_client @@ -424,10 +411,7 @@ where // TODO: Derive correct domain proof Some(Proof::Domain { consensus_chain_mmr_proof: ConsensusChainMmrLeafProof { - block_info: BlockInfo { - block_number: consensus_chain_block_info.block_number.into(), - block_hash: consensus_chain_block_info.block_hash.into(), - }, + consensus_block_hash: consensus_chain_block_hash.into(), opaque_mmr_leaf: EncodableOpaqueLeaf(vec![]), proof: MmrProof { leaf_indices: vec![], @@ -445,7 +429,7 @@ where /// Sends an Outbox message from src_domain to dst_domain. fn gossip_outbox_message( client: &Arc, - msg: CrossDomainMessage, Block::Hash, Block::Hash>, + msg: CrossDomainMessage, sink: &GossipMessageSink, ) -> Result<(), Error> { let best_hash = client.info().best_hash; @@ -467,7 +451,7 @@ where /// this message is the response of the Inbox message execution. fn gossip_inbox_message_response( client: &Arc, - msg: CrossDomainMessage, Block::Hash, Block::Hash>, + msg: CrossDomainMessage, sink: &GossipMessageSink, ) -> Result<(), Error> { let best_hash = client.info().best_hash; diff --git a/domains/client/relayer/src/worker.rs b/domains/client/relayer/src/worker.rs index 16c9a8a7a9..eda26b3461 100644 --- a/domains/client/relayer/src/worker.rs +++ b/domains/client/relayer/src/worker.rs @@ -7,7 +7,7 @@ use sp_api::{ApiError, ProvideRuntimeApi}; use sp_consensus::SyncOracle; use sp_domains::DomainsApi; use sp_messenger::messages::ChainId; -use sp_messenger::RelayerApi; +use sp_messenger::{MessengerApi, RelayerApi}; use sp_runtime::scale_info::TypeInfo; use sp_runtime::traits::{CheckedSub, NumberFor, Zero}; use std::sync::Arc; @@ -79,7 +79,7 @@ pub async fn relay_domain_messages( + ProvideRuntimeApi, DC::Api: RelayerApi>, CCC: HeaderBackend + ProvideRuntimeApi + ProofProvider, - CCC::Api: DomainsApi, + CCC::Api: DomainsApi + MessengerApi>, SO: SyncOracle + Send, { let relay_confirmation_depth = match Relayer::relay_confirmation_depth(&domain_client) { diff --git a/domains/pallets/messenger/src/benchmarking.rs b/domains/pallets/messenger/src/benchmarking.rs index ed356eb603..fd305cf727 100644 --- a/domains/pallets/messenger/src/benchmarking.rs +++ b/domains/pallets/messenger/src/benchmarking.rs @@ -8,7 +8,7 @@ use frame_support::traits::Get; use frame_system::RawOrigin; use sp_messenger::endpoint::{Endpoint, EndpointRequest}; use sp_messenger::messages::{ - BlockInfo, ConsensusChainMmrLeafProof, CrossDomainMessage, InitiateChannelParams, Message, + ConsensusChainMmrLeafProof, CrossDomainMessage, InitiateChannelParams, Message, MessageWeightTag, Payload, Proof, RequestResponse, VersionedPayload, }; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof as MmrProof}; @@ -115,7 +115,7 @@ mod benchmarks { }; Inbox::::put(msg); - let xdm = CrossDomainMessage::, T::Hash, T::MmrHash> { + let xdm = CrossDomainMessage:: { src_chain_id: dst_chain_id, dst_chain_id: T::SelfChainId::get(), channel_id, @@ -182,7 +182,7 @@ mod benchmarks { }; OutboxResponses::::put(resp_msg); - let xdm = CrossDomainMessage::, T::Hash, T::MmrHash> { + let xdm = CrossDomainMessage:: { src_chain_id: dst_chain_id, dst_chain_id: T::SelfChainId::get(), channel_id, @@ -235,14 +235,13 @@ mod benchmarks { ); } -pub fn dummy_proof() -> Proof +pub fn dummy_proof() -> Proof where - CBlockNumber: Default, CBlockHash: Default, { Proof::Consensus { consensus_chain_mmr_proof: ConsensusChainMmrLeafProof { - block_info: BlockInfo::default(), + consensus_block_hash: Default::default(), opaque_mmr_leaf: EncodableOpaqueLeaf(vec![]), proof: MmrProof { leaf_indices: vec![], diff --git a/domains/pallets/messenger/src/lib.rs b/domains/pallets/messenger/src/lib.rs index 0e672b7b1e..a0e627865d 100644 --- a/domains/pallets/messenger/src/lib.rs +++ b/domains/pallets/messenger/src/lib.rs @@ -35,7 +35,6 @@ mod messages; use codec::{Decode, Encode}; use frame_support::traits::fungible::Inspect; -use frame_system::pallet_prelude::*; pub use pallet::*; use scale_info::TypeInfo; use sp_core::U256; @@ -107,15 +106,13 @@ mod pallet { use frame_system::pallet_prelude::*; use sp_core::storage::StorageKey; use sp_domains::proof_provider_and_verifier::{StorageProofVerifier, VerificationError}; - use sp_domains::DomainId; - use sp_messenger::endpoint::{DomainInfo, Endpoint, EndpointHandler, EndpointRequest, Sender}; + use sp_messenger::endpoint::{Endpoint, EndpointHandler, EndpointRequest, Sender}; use sp_messenger::messages::{ - BlockInfo, ChainId, CrossDomainMessage, InitiateChannelParams, Message, MessageId, - MessageWeightTag, Payload, ProtocolMessageRequest, RequestResponse, VersionedPayload, + ChainId, CrossDomainMessage, InitiateChannelParams, Message, MessageId, MessageWeightTag, + Payload, ProtocolMessageRequest, RequestResponse, VersionedPayload, }; use sp_messenger::{MmrProofVerifier, OnXDMRewards, StorageKeys}; use sp_mmr_primitives::EncodableOpaqueLeaf; - use sp_runtime::traits::CheckedSub; use sp_runtime::ArithmeticError; use sp_std::boxed::Box; @@ -129,8 +126,6 @@ mod pallet { -> Option>>; /// Currency type pallet uses for fees and deposits. type Currency: Mutate; - /// Chain info to verify chain state roots at a confirmation depth. - type DomainInfo: DomainInfo, Self::Hash, StateRootOf>; /// Confirmation depth for XDM coming from chains. type ConfirmationDepth: Get>; /// Weight information for extrinsics in this pallet. @@ -509,7 +504,7 @@ mod pallet { #[pallet::weight((T::WeightInfo::relay_message().saturating_add(Pallet::< T >::message_weight(& msg.weight_tag)), Pays::No))] pub fn relay_message( origin: OriginFor, - msg: CrossDomainMessage, T::Hash, T::MmrHash>, + msg: CrossDomainMessage, ) -> DispatchResult { ensure_none(origin)?; let inbox_msg = Inbox::::take().ok_or(Error::::MissingMessage)?; @@ -522,7 +517,7 @@ mod pallet { #[pallet::weight((T::WeightInfo::relay_message_response().saturating_add(Pallet::< T >::message_weight(& msg.weight_tag)), Pays::No))] pub fn relay_message_response( origin: OriginFor, - msg: CrossDomainMessage, T::Hash, T::MmrHash>, + msg: CrossDomainMessage, ) -> DispatchResult { ensure_none(origin)?; let outbox_resp_msg = OutboxResponses::::take().ok_or(Error::::MissingMessage)?; @@ -701,7 +696,7 @@ mod pallet { } pub(crate) fn do_validate_relay_message( - xdm: &CrossDomainMessage, T::Hash, T::MmrHash>, + xdm: &CrossDomainMessage, ) -> Result>, TransactionValidityError> { let mut should_init_channel = false; let next_nonce = match Channels::::get(xdm.src_chain_id, xdm.channel_id) { @@ -798,7 +793,7 @@ mod pallet { } pub(crate) fn do_validate_relay_message_response( - xdm: &CrossDomainMessage, T::Hash, T::MmrHash>, + xdm: &CrossDomainMessage, ) -> Result<(Message>, Nonce), TransactionValidityError> { // channel should be open and message should be present in outbox let next_nonce = match Channels::::get(xdm.src_chain_id, xdm.channel_id) { @@ -845,7 +840,7 @@ mod pallet { pub(crate) fn do_verify_xdm( next_nonce: Nonce, storage_key: StorageKey, - xdm: &CrossDomainMessage, T::Hash, T::MmrHash>, + xdm: &CrossDomainMessage, ) -> Result>, TransactionValidityError> { // channel should be either already be created or match the next channelId for chain. let next_channel_id = NextChannelId::::get(xdm.src_chain_id); @@ -912,32 +907,6 @@ mod pallet { Ok(msg) } - pub fn is_domain_info_confirmed( - domain_id: DomainId, - domain_block_info: BlockInfo, T::Hash>, - domain_state_root: T::Hash, - ) -> bool { - // ensure the block is at-least k-deep - let confirmed = T::DomainInfo::domain_best_number(domain_id) - .and_then(|best_number| { - best_number - .checked_sub(&T::ConfirmationDepth::get()) - .map(|confirmed_number| confirmed_number >= domain_block_info.block_number) - }) - .unwrap_or(false); - - // verify state root of the block - let valid_state_root = T::DomainInfo::domain_state_root( - domain_id, - domain_block_info.block_number, - domain_block_info.block_hash, - ) - .map(|got_state_root| got_state_root == domain_state_root) - .unwrap_or(false); - - confirmed && valid_state_root - } - pub fn outbox_storage_key(message_id: MessageId) -> Vec { let (channel_id, nonce) = message_id; Outbox::::hashed_key_for((T::SelfChainId::get(), channel_id, nonce)) @@ -955,14 +924,14 @@ where T: Config + frame_system::offchain::SendTransactionTypes>, { pub fn outbox_message_unsigned( - msg: CrossDomainMessage, T::Hash, T::MmrHash>, + msg: CrossDomainMessage, ) -> Option { let call = Call::relay_message { msg }; T::Extrinsic::new(call.into(), None) } pub fn inbox_response_message_unsigned( - msg: CrossDomainMessage, T::Hash, T::MmrHash>, + msg: CrossDomainMessage, ) -> Option { let call = Call::relay_message_response { msg }; T::Extrinsic::new(call.into(), None) diff --git a/domains/pallets/messenger/src/mock.rs b/domains/pallets/messenger/src/mock.rs index 50514cdf7f..29adda0890 100644 --- a/domains/pallets/messenger/src/mock.rs +++ b/domains/pallets/messenger/src/mock.rs @@ -90,7 +90,6 @@ macro_rules! impl_runtime { type SelfChainId = SelfChainId; type Currency = Balances; type ConfirmationDepth = RelayerConfirmationDepth; - type DomainInfo = (); type WeightInfo = (); type WeightToFee = frame_support::weights::IdentityFee; type OnXDMRewards = (); diff --git a/domains/pallets/messenger/src/tests.rs b/domains/pallets/messenger/src/tests.rs index 15b9503e01..97f100871e 100644 --- a/domains/pallets/messenger/src/tests.rs +++ b/domains/pallets/messenger/src/tests.rs @@ -16,8 +16,8 @@ use sp_core::{Blake2Hasher, H256}; use sp_domains::proof_provider_and_verifier::{StorageProofVerifier, VerificationError}; use sp_messenger::endpoint::{Endpoint, EndpointPayload, EndpointRequest, Sender}; use sp_messenger::messages::{ - BlockInfo, ChainId, ConsensusChainMmrLeafProof, CrossDomainMessage, InitiateChannelParams, - Payload, Proof, ProtocolMessageRequest, RequestResponse, VersionedPayload, + ChainId, ConsensusChainMmrLeafProof, CrossDomainMessage, InitiateChannelParams, Payload, Proof, + ProtocolMessageRequest, RequestResponse, VersionedPayload, }; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof as MmrProof}; use sp_runtime::traits::{Convert, ValidateUnsigned}; @@ -77,12 +77,9 @@ fn create_channel(chain_id: ChainId, channel_id: ChannelId, fee_model: FeeModel< assert_eq!(messages_with_keys.outbox[0].storage_key, expected_key); } -fn default_consensus_proof() -> ConsensusChainMmrLeafProof { +fn default_consensus_proof() -> ConsensusChainMmrLeafProof { ConsensusChainMmrLeafProof { - block_info: BlockInfo { - block_number: Default::default(), - block_hash: Default::default(), - }, + consensus_block_hash: Default::default(), opaque_mmr_leaf: EncodableOpaqueLeaf(vec![]), proof: MmrProof { leaf_indices: vec![], @@ -201,7 +198,7 @@ fn test_storage_proof_verification_invalid() { let (_, _, storage_proof) = crate::mock::storage_proof_of_channels::(t.as_backend(), chain_id, channel_id); - let proof: Proof = Proof::Consensus { + let proof = Proof::::Consensus { consensus_chain_mmr_proof: default_consensus_proof(), message_proof: storage_proof, }; @@ -227,7 +224,7 @@ fn test_storage_proof_verification_missing_value() { let (_state_root, storage_key, storage_proof) = crate::mock::storage_proof_of_channels::(t.as_backend(), chain_id, U256::one()); - let proof: Proof = Proof::Consensus { + let proof = Proof::::Consensus { consensus_chain_mmr_proof: default_consensus_proof(), message_proof: storage_proof, }; @@ -255,7 +252,7 @@ fn test_storage_proof_verification() { let (_state_root, storage_key, storage_proof) = crate::mock::storage_proof_of_channels::(t.as_backend(), chain_id, channel_id); - let proof: Proof = Proof::Consensus { + let proof = Proof::::Consensus { consensus_chain_mmr_proof: default_consensus_proof(), message_proof: storage_proof, }; diff --git a/domains/primitives/messenger/src/endpoint.rs b/domains/primitives/messenger/src/endpoint.rs index 0404ce4263..67e595b42e 100644 --- a/domains/primitives/messenger/src/endpoint.rs +++ b/domains/primitives/messenger/src/endpoint.rs @@ -1,9 +1,8 @@ -use crate::messages::ChainId; use codec::{Decode, Encode}; use frame_support::weights::Weight; use frame_support::Parameter; use scale_info::TypeInfo; -use sp_domains::DomainId; +use sp_domains::ChainId; use sp_runtime::traits::Member; use sp_runtime::{sp_std, DispatchError, DispatchResult}; use sp_std::vec::Vec; @@ -110,21 +109,3 @@ impl EndpointHandler for BenchmarkEndpointHandler { Weight::zero() } } - -/// Trait that can provide info for a given Domain. -pub trait DomainInfo { - /// Returns the best known number of a given Domain. - fn domain_best_number(domain_id: DomainId) -> Option; - /// Returns the known state root of a specific block. - fn domain_state_root(domain_id: DomainId, number: Number, hash: Hash) -> Option; -} - -impl DomainInfo for () { - fn domain_best_number(_domain_id: DomainId) -> Option { - None - } - - fn domain_state_root(_domain_id: DomainId, _number: Number, _hash: Hash) -> Option { - None - } -} diff --git a/domains/primitives/messenger/src/lib.rs b/domains/primitives/messenger/src/lib.rs index 1f371dfe51..717d0f8a27 100644 --- a/domains/primitives/messenger/src/lib.rs +++ b/domains/primitives/messenger/src/lib.rs @@ -20,13 +20,9 @@ pub mod endpoint; pub mod messages; -use crate::messages::BlockInfo; use codec::{Decode, Encode}; -use messages::{ - BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, ExtractedStateRootsFromProof, - MessageId, -}; -use sp_domains::DomainId; +use messages::{BlockMessagesWithStorageKey, CrossDomainMessage, MessageId}; +use sp_domains::{ChainId, DomainId}; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_std::vec::Vec; @@ -101,12 +97,12 @@ sp_api::decl_runtime_apis! { /// Constructs an outbox message to the dst_chain as an unsigned extrinsic. fn outbox_message_unsigned( - msg: CrossDomainMessage, + msg: CrossDomainMessage, ) -> Option; /// Constructs an inbox response message to the dst_chain as an unsigned extrinsic. fn inbox_response_message_unsigned( - msg: CrossDomainMessage, + msg: CrossDomainMessage, ) -> Option; /// Returns true if the outbox message is ready to be relayed to dst_chain. @@ -118,15 +114,12 @@ sp_api::decl_runtime_apis! { /// Api to provide XDM extraction from Runtime Calls. pub trait MessengerApi where BlockNumber: Encode + Decode{ - fn extract_xdm_proof_state_roots( + /// Returns `Some(true)` if valid XDM or `Some(false)` if not + /// Returns None if this is not an XDM + fn is_xdm_valid( extrinsic: Vec - ) -> Option>; + ) -> Option; - fn is_domain_info_confirmed( - domain_id: DomainId, - domain_block_info: BlockInfo, - domain_state_root: Block::Hash, - ) -> bool; /// Returns the confirmed domain block storage for given domain. fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Vec; diff --git a/domains/primitives/messenger/src/messages.rs b/domains/primitives/messenger/src/messages.rs index 3589d47987..38bfe290ab 100644 --- a/domains/primitives/messenger/src/messages.rs +++ b/domains/primitives/messenger/src/messages.rs @@ -1,16 +1,10 @@ use crate::endpoint::{Endpoint, EndpointRequest, EndpointResponse}; -use codec::{Decode, Encode, FullCodec}; -use frame_support::storage::generator::StorageMap; -use frame_support::storage::storage_prefix; -use frame_support::Identity; +use codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_core::storage::StorageKey; pub use sp_domains::ChainId; -use sp_domains::DomainId; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof as MmrProof}; use sp_runtime::app_crypto::sp_core::U256; use sp_runtime::{sp_std, DispatchError}; -use sp_std::marker::PhantomData; use sp_std::vec::Vec; use sp_trie::StorageProof; @@ -137,20 +131,11 @@ pub struct Message { pub last_delivered_message_response_nonce: Option, } -/// Block info used as part of the Cross chain message proof. -#[derive(Default, Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] -pub struct BlockInfo { - /// Block number of the chain. - pub block_number: Number, - /// Block hash of the chain. - pub block_hash: Hash, -} - /// Consensus chain MMR leaf and its Proof at specific block #[derive(Debug, Encode, Decode, Eq, PartialEq, TypeInfo)] -pub struct ConsensusChainMmrLeafProof { +pub struct ConsensusChainMmrLeafProof { /// Consensus block info from which this proof was generated. - pub block_info: BlockInfo, + pub consensus_block_hash: BlockHash, /// Encoded MMR leaf pub opaque_mmr_leaf: EncodableOpaqueLeaf, /// MMR proof for the leaf above. @@ -158,16 +143,14 @@ pub struct ConsensusChainMmrLeafProof { } // TODO: update upstream `EncodableOpaqueLeaf` to derive clone. -impl Clone - for ConsensusChainMmrLeafProof +impl Clone for ConsensusChainMmrLeafProof where - BlockNumber: Clone, BlockHash: Clone, MmrHash: Clone, { fn clone(&self) -> Self { Self { - block_info: self.block_info.clone(), + consensus_block_hash: self.consensus_block_hash.clone(), opaque_mmr_leaf: EncodableOpaqueLeaf(self.opaque_mmr_leaf.0.clone()), proof: self.proof.clone(), } @@ -175,16 +158,16 @@ where } #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] -pub enum Proof { +pub enum Proof { Consensus { /// Consensus chain MMR leaf proof. - consensus_chain_mmr_proof: ConsensusChainMmrLeafProof, + consensus_chain_mmr_proof: ConsensusChainMmrLeafProof, /// Storage proof that message is processed on src_chain. message_proof: StorageProof, }, Domain { /// Consensus chain MMR leaf proof. - consensus_chain_mmr_proof: ConsensusChainMmrLeafProof, + consensus_chain_mmr_proof: ConsensusChainMmrLeafProof, /// Storage proof that src domain chain's block is out of the challenge period on Consensus chain. domain_proof: StorageProof, /// Storage proof that message is processed on src_chain. @@ -192,7 +175,7 @@ pub enum Proof { }, } -impl Proof { +impl Proof { pub fn message_proof(&self) -> StorageProof { match self { Proof::Consensus { message_proof, .. } => message_proof.clone(), @@ -200,11 +183,8 @@ impl Proof } } - pub fn consensus_mmr_proof( - &self, - ) -> ConsensusChainMmrLeafProof + pub fn consensus_mmr_proof(&self) -> ConsensusChainMmrLeafProof where - CBlockNumber: Clone, CBlockHash: Clone, MmrHash: Clone, { @@ -228,22 +208,9 @@ impl Proof } } -/// Holds the Block info and state roots from which a proof was constructed. -#[derive(Debug, Default, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] -pub struct ExtractedStateRootsFromProof { - /// Consensus chain block info when proof was constructed - pub consensus_chain_block_info: BlockInfo, - /// State root of Consensus chain at above number and block hash. - pub consensus_chain_state_root: StateRoot, - /// Storage proof that src chain state_root is registered on Consensus chain. - /// This is optional when the src_chain is the consensus chain. - /// BlockNumber and BlockHash is used with storage proof to validate and fetch its state root. - pub domain_info: Option<(DomainId, BlockInfo, StateRoot)>, -} - /// Cross Domain message contains Message and its proof on src_chain. #[derive(Debug, Encode, Decode, Clone, Eq, PartialEq, TypeInfo)] -pub struct CrossDomainMessage { +pub struct CrossDomainMessage { /// Chain which initiated this message. pub src_chain_id: ChainId, /// Chain this message is intended for. @@ -253,7 +220,7 @@ pub struct CrossDomainMessage { /// Message nonce within the channel. pub nonce: Nonce, /// Proof of message processed on src_chain. - pub proof: Proof, + pub proof: Proof, /// The message weight tag pub weight_tag: MessageWeightTag, } @@ -282,11 +249,10 @@ pub struct BlockMessagesWithStorageKey { pub inbox_responses: Vec, } -// TODO: remove or update this accordingly -impl CrossDomainMessage { +impl CrossDomainMessage { pub fn from_relayer_msg_with_proof( r_msg: BlockMessageWithStorageKey, - proof: Proof, + proof: Proof, ) -> Self { CrossDomainMessage { src_chain_id: r_msg.src_chain_id, @@ -298,52 +264,3 @@ impl CrossDomainMessage(PhantomData<(Number, Hash, StateRoot)>); - -impl StorageMap<(DomainId, Number, Hash), StateRoot> - for DomainStateRootStorage -where - Number: FullCodec + TypeInfo + 'static, - Hash: FullCodec + TypeInfo + 'static, - StateRoot: FullCodec + TypeInfo + 'static, -{ - type Query = Option; - type Hasher = Identity; - - fn pallet_prefix() -> &'static [u8] { - "Domains".as_ref() - } - - fn storage_prefix() -> &'static [u8] { - "StateRoots".as_ref() - } - - fn prefix_hash() -> [u8; 32] { - storage_prefix(Self::pallet_prefix(), Self::storage_prefix()) - } - - fn from_optional_value_to_query(v: Option) -> Self::Query { - v - } - - fn from_query_to_optional_value(v: Self::Query) -> Option { - v - } -} - -impl DomainStateRootStorage -where - Number: FullCodec + TypeInfo + 'static, - Hash: FullCodec + TypeInfo + 'static, - StateRoot: FullCodec + TypeInfo + 'static, -{ - pub fn storage_key(domain_id: DomainId, number: Number, hash: Hash) -> StorageKey { - StorageKey(Self::storage_map_final_key::<(DomainId, Number, Hash)>(( - domain_id, number, hash, - ))) - } -} diff --git a/domains/runtime/evm/src/lib.rs b/domains/runtime/evm/src/lib.rs index 3ac56cb9e2..b942d6fad0 100644 --- a/domains/runtime/evm/src/lib.rs +++ b/domains/runtime/evm/src/lib.rs @@ -44,10 +44,7 @@ use sp_core::crypto::KeyTypeId; use sp_core::{Get, OpaqueMetadata, H160, H256, U256}; use sp_domains::DomainId; use sp_messenger::endpoint::{Endpoint, EndpointHandler as EndpointHandlerT, EndpointId}; -use sp_messenger::messages::{ - BlockInfo, BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, - ExtractedStateRootsFromProof, MessageId, -}; +use sp_messenger::messages::{BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, MessageId}; use sp_messenger_host_functions::{get_storage_key, StorageKeyRequest}; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_runtime::generic::Era; @@ -450,7 +447,6 @@ impl pallet_messenger::Config for Runtime { } type Currency = Balances; - type DomainInfo = (); type ConfirmationDepth = RelayConfirmationDepth; type WeightInfo = pallet_messenger::weights::SubstrateWeight; type WeightToFee = IdentityFee; @@ -705,10 +701,7 @@ impl fp_rpc::ConvertTransaction for TransactionConve } } -// TODO: fix extracting state roots -fn extract_xdm_proof_state_roots( - encoded_ext: Vec, -) -> Option> { +fn is_xdm_valid(encoded_ext: Vec) -> Option { if let Ok(ext) = UncheckedExtrinsic::decode(&mut encoded_ext.as_slice()) { match &ext.0.function { RuntimeCall::Messenger(pallet_messenger::Call::relay_message { .. }) => None, @@ -1039,19 +1032,10 @@ impl_runtime_apis! { } impl sp_messenger::MessengerApi for Runtime { - fn extract_xdm_proof_state_roots( + fn is_xdm_valid( extrinsic: Vec, - ) -> Option::Hash, ::Hash>> { - extract_xdm_proof_state_roots(extrinsic) - } - - fn is_domain_info_confirmed( - _domain_id: DomainId, - _domain_block_info: BlockInfo::Hash>, - _domain_state_root: ::Hash, - ) -> bool{ - // not valid on evm domain - false + ) -> Option { + is_xdm_valid(extrinsic) } fn confirmed_domain_block_storage_key(_domain_id: DomainId) -> Vec { @@ -1081,11 +1065,11 @@ impl_runtime_apis! { Messenger::get_block_messages() } - fn outbox_message_unsigned(msg: CrossDomainMessage::Hash, ::Hash>) -> Option<::Extrinsic> { + fn outbox_message_unsigned(msg: CrossDomainMessage<::Hash, ::Hash>) -> Option<::Extrinsic> { Messenger::outbox_message_unsigned(msg) } - fn inbox_response_message_unsigned(msg: CrossDomainMessage::Hash, ::Hash>) -> Option<::Extrinsic> { + fn inbox_response_message_unsigned(msg: CrossDomainMessage<::Hash, ::Hash>) -> Option<::Extrinsic> { Messenger::inbox_response_message_unsigned(msg) } diff --git a/domains/service/src/domain.rs b/domains/service/src/domain.rs index e48f55ffc6..97f1cc05c4 100644 --- a/domains/service/src/domain.rs +++ b/domains/service/src/domain.rs @@ -53,7 +53,7 @@ pub type DomainOperator = Operator< CBlock, FullClient, CClient, - FullPool, + FullPool, FullBackend, RuntimeExecutor, >; @@ -105,12 +105,12 @@ where /// Operator. pub operator: DomainOperator, /// Transaction pool - pub transaction_pool: Arc>, + pub transaction_pool: Arc>, _phantom_data: PhantomData, } -pub type FullPool = - crate::transaction_pool::FullPool>; +pub type FullPool = + crate::transaction_pool::FullPool>; /// Constructs a partial domain node. #[allow(clippy::type_complexity)] @@ -124,7 +124,7 @@ fn new_partial( FullBackend, (), sc_consensus::DefaultImportQueue, - FullPool, + FullPool, ( Option, Option, @@ -190,12 +190,7 @@ where telemetry }); - let transaction_pool = crate::transaction_pool::new_full( - config, - &task_manager, - client.clone(), - consensus_client.clone(), - ); + let transaction_pool = crate::transaction_pool::new_full(config, &task_manager, client.clone()); let block_import = SharedBlockImport::new(BlockImportProvider::block_import( block_import_provider, @@ -312,8 +307,8 @@ where Provider: RpcProvider< Block, FullClient, - FullPool, - FullChainApiWrapper>, + FullPool, + FullChainApiWrapper>, TFullBackend, AccountId, CreateInherentDataProvider, diff --git a/domains/service/src/transaction_pool.rs b/domains/service/src/transaction_pool.rs index c21ddad3e0..28904d41b8 100644 --- a/domains/service/src/transaction_pool.rs +++ b/domains/service/src/transaction_pool.rs @@ -1,5 +1,5 @@ -use domain_client_block_preprocessor::xdm_verifier::is_valid_xdm; use futures::future::{Future, FutureExt, Ready}; +use parity_scale_codec::Encode; use sc_client_api::blockchain::HeaderBackend; use sc_client_api::{BlockBackend, ExecutorProvider, UsageProvider}; use sc_service::{Configuration, TaskManager}; @@ -8,13 +8,11 @@ use sc_transaction_pool::{BasicPool, ChainApi, FullChainApi, RevalidationType}; use sc_transaction_pool_api::TransactionSource; use sp_api::ProvideRuntimeApi; use sp_blockchain::{HeaderMetadata, TreeRoute}; -use sp_domains::DomainsApi; use sp_messenger::MessengerApi; use sp_runtime::generic::BlockId; use sp_runtime::traits::{Block as BlockT, BlockIdTo, NumberFor}; use sp_runtime::transaction_validity::TransactionValidity; use sp_transaction_pool::runtime_api::TaggedTransactionQueue; -use std::marker::PhantomData; use std::pin::Pin; use std::sync::Arc; use substrate_prometheus_endpoint::Registry as PrometheusRegistry; @@ -29,20 +27,16 @@ type ExtrinsicHash = <::Block as BlockT>::Hash; type ExtrinsicFor = <::Block as BlockT>::Extrinsic; /// A transaction pool for a full node. -pub type FullPool = - BasicPool, Block>; +pub type FullPool = BasicPool, Block>; #[derive(Clone)] -pub struct FullChainApiWrapper { +pub struct FullChainApiWrapper { inner: Arc>, client: Arc, - consensus_client: Arc, - marker: PhantomData, } -impl FullChainApiWrapper +impl FullChainApiWrapper where - CBlock: BlockT, Block: BlockT, Client: ProvideRuntimeApi + BlockBackend @@ -55,7 +49,6 @@ where Client::Api: TaggedTransactionQueue, { fn new( - consensus_client: Arc, client: Arc, prometheus: Option<&PrometheusRegistry>, task_manager: &TaskManager, @@ -67,21 +60,15 @@ where &task_manager.spawn_essential_handle(), )), client, - consensus_client, - marker: Default::default(), } } } pub type ValidationFuture = Pin> + Send>>; -impl ChainApi - for FullChainApiWrapper +impl ChainApi for FullChainApiWrapper where - CBlock: BlockT, Block: BlockT, - NumberFor: From>, - CBlock::Hash: From, Client: ProvideRuntimeApi + BlockBackend + BlockIdTo @@ -91,8 +78,6 @@ where + Sync + 'static, Client::Api: TaggedTransactionQueue + MessengerApi>, - CClient: HeaderBackend + ProvideRuntimeApi + Send + Sync + 'static, - CClient::Api: DomainsApi + MessengerApi>, { type Block = Block; type Error = sc_transaction_pool::error::Error; @@ -106,10 +91,13 @@ where uxt: ExtrinsicFor, ) -> Self::ValidationFuture { let chain_api = self.inner.clone(); - let consensus_client = self.consensus_client.clone(); let client = self.client.clone(); async move { - if !is_valid_xdm(&consensus_client, at, &client, &uxt)? { + if let Some(false) = client + .runtime_api() + .is_xdm_valid(at, uxt.encode()) + .map_err(|err| TxPoolError::RuntimeApi(err.to_string()))? + { return Err(TxPoolError::Pool( sc_transaction_pool_api::error::Error::ImmediatelyDropped, )); @@ -155,17 +143,13 @@ where } } -pub(crate) fn new_full( +pub(crate) fn new_full( config: &Configuration, task_manager: &TaskManager, client: Arc, - consensus_client: Arc, -) -> Arc> +) -> Arc> where - CBlock: BlockT, Block: BlockT, - NumberFor: From>, - CBlock::Hash: From, Client: ProvideRuntimeApi + BlockBackend + HeaderBackend @@ -177,12 +161,9 @@ where + Sync + 'static, Client::Api: TaggedTransactionQueue + MessengerApi>, - CClient: HeaderBackend + ProvideRuntimeApi + Send + Sync + 'static, - CClient::Api: DomainsApi + MessengerApi>, { let prometheus = config.prometheus_registry(); let pool_api = Arc::new(FullChainApiWrapper::new( - consensus_client, client.clone(), prometheus, task_manager, diff --git a/domains/test/runtime/evm/src/lib.rs b/domains/test/runtime/evm/src/lib.rs index 69e3167f73..726b212150 100644 --- a/domains/test/runtime/evm/src/lib.rs +++ b/domains/test/runtime/evm/src/lib.rs @@ -44,8 +44,7 @@ use sp_core::{Get, OpaqueMetadata, H160, H256, U256}; use sp_domains::DomainId; use sp_messenger::endpoint::{Endpoint, EndpointHandler as EndpointHandlerT, EndpointId}; use sp_messenger::messages::{ - BlockInfo, BlockMessagesWithStorageKey, ChainId, ChannelId, CrossDomainMessage, - ExtractedStateRootsFromProof, MessageId, + BlockMessagesWithStorageKey, ChainId, ChannelId, CrossDomainMessage, MessageId, }; use sp_messenger_host_functions::{get_storage_key, StorageKeyRequest}; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; @@ -448,7 +447,6 @@ impl pallet_messenger::Config for Runtime { } type Currency = Balances; - type DomainInfo = (); type ConfirmationDepth = RelayConfirmationDepth; type WeightInfo = pallet_messenger::weights::SubstrateWeight; type WeightToFee = IdentityFee; @@ -698,10 +696,7 @@ impl fp_rpc::ConvertTransaction for TransactionConve } } -// TODO: fix extracting state roots -fn extract_xdm_proof_state_roots( - encoded_ext: Vec, -) -> Option> { +fn is_xdm_valid(encoded_ext: Vec) -> Option { if let Ok(ext) = UncheckedExtrinsic::decode(&mut encoded_ext.as_slice()) { match &ext.0.function { RuntimeCall::Messenger(pallet_messenger::Call::relay_message { .. }) => None, @@ -1023,19 +1018,10 @@ impl_runtime_apis! { } impl sp_messenger::MessengerApi for Runtime { - fn extract_xdm_proof_state_roots( + fn is_xdm_valid( extrinsic: Vec, - ) -> Option::Hash, ::Hash>> { - extract_xdm_proof_state_roots(extrinsic) - } - - fn is_domain_info_confirmed( - _domain_id: DomainId, - _domain_block_info: BlockInfo::Hash>, - _domain_state_root: ::Hash, - ) -> bool{ - // this is always invalid on domains since we do not have info other domains. - false + ) -> Option { + is_xdm_valid(extrinsic) } fn confirmed_domain_block_storage_key(_domain_id: DomainId) -> Vec { @@ -1064,11 +1050,11 @@ impl_runtime_apis! { Messenger::get_block_messages() } - fn outbox_message_unsigned(msg: CrossDomainMessage::Hash, ::Hash>) -> Option<::Extrinsic> { + fn outbox_message_unsigned(msg: CrossDomainMessage<::Hash, ::Hash>) -> Option<::Extrinsic> { Messenger::outbox_message_unsigned(msg) } - fn inbox_response_message_unsigned(msg: CrossDomainMessage::Hash, ::Hash>) -> Option<::Extrinsic> { + fn inbox_response_message_unsigned(msg: CrossDomainMessage<::Hash, ::Hash>) -> Option<::Extrinsic> { Messenger::inbox_response_message_unsigned(msg) } diff --git a/test/subspace-test-runtime/src/lib.rs b/test/subspace-test-runtime/src/lib.rs index d8f527bdfc..dfb764050f 100644 --- a/test/subspace-test-runtime/src/lib.rs +++ b/test/subspace-test-runtime/src/lib.rs @@ -59,10 +59,7 @@ use sp_domains::{ }; use sp_domains_fraud_proof::fraud_proof::FraudProof; use sp_messenger::endpoint::{Endpoint, EndpointHandler as EndpointHandlerT, EndpointId}; -use sp_messenger::messages::{ - BlockInfo, BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, - ExtractedStateRootsFromProof, MessageId, -}; +use sp_messenger::messages::{BlockMessagesWithStorageKey, ChainId, CrossDomainMessage, MessageId}; use sp_messenger_host_functions::{get_storage_key, StorageKeyRequest}; use sp_mmr_primitives::{EncodableOpaqueLeaf, Proof}; use sp_runtime::traits::{ @@ -527,19 +524,8 @@ parameter_types! { pub SelfChainId: ChainId = ChainId::Consensus; } -pub struct DomainInfo; - -impl sp_messenger::endpoint::DomainInfo for DomainInfo { - fn domain_best_number(domain_id: DomainId) -> Option { - Domains::domain_best_number(domain_id) - } - - fn domain_state_root(_domain_id: DomainId, _number: BlockNumber, _hash: Hash) -> Option { - None - } -} - pub struct MmrProofVerifier; + impl sp_messenger::MmrProofVerifier for MmrProofVerifier { fn verify_proof_and_extract_consensus_state_root( opaque_leaf: EncodableOpaqueLeaf, @@ -553,6 +539,7 @@ impl sp_messenger::MmrProofVerifier for MmrProofVerifier { } pub struct StorageKeys; + impl sp_messenger::StorageKeys for StorageKeys { fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Option> { Some(Domains::confirmed_domain_block_storage_key(domain_id)) @@ -586,7 +573,6 @@ impl pallet_messenger::Config for Runtime { } type Currency = Balances; - type DomainInfo = DomainInfo; type ConfirmationDepth = RelayConfirmationDepth; type WeightInfo = pallet_messenger::weights::SubstrateWeight; type WeightToFee = IdentityFee; @@ -668,6 +654,7 @@ parameter_types! { const_assert!(MinOperatorStake::get() >= MinNominatorStake::get()); pub struct BlockSlot; + impl pallet_domains::BlockSlot for BlockSlot { fn current_slot() -> sp_consensus_slots::Slot { Subspace::current_slot() @@ -833,16 +820,7 @@ fn extract_segment_headers(ext: &UncheckedExtrinsic) -> Option, -) -> Option< - ExtractedStateRootsFromProof< - domain_runtime_primitives::BlockNumber, - domain_runtime_primitives::Hash, - domain_runtime_primitives::Hash, - >, -> { +fn is_xdm_valid(encoded_ext: Vec) -> Option { if let Ok(ext) = UncheckedExtrinsic::decode(&mut encoded_ext.as_slice()) { match &ext.function { RuntimeCall::Messenger(pallet_messenger::Call::relay_message { .. }) => None, @@ -1383,18 +1361,10 @@ impl_runtime_apis! { } impl sp_messenger::MessengerApi for Runtime { - fn extract_xdm_proof_state_roots( + fn is_xdm_valid( extrinsic: Vec, - ) -> Option::Hash, ::Hash>> { - extract_xdm_proof_state_roots(extrinsic) - } - - fn is_domain_info_confirmed( - domain_id: DomainId, - domain_block_info: BlockInfo::Hash>, - domain_state_root: ::Hash, - ) -> bool{ - Messenger::is_domain_info_confirmed(domain_id, domain_block_info, domain_state_root) + ) -> Option { + is_xdm_valid(extrinsic) } fn confirmed_domain_block_storage_key(domain_id: DomainId) -> Vec { @@ -1423,11 +1393,11 @@ impl_runtime_apis! { Messenger::get_block_messages() } - fn outbox_message_unsigned(msg: CrossDomainMessage::Hash, ::Hash>) -> Option<::Extrinsic> { + fn outbox_message_unsigned(msg: CrossDomainMessage<::Hash, ::Hash>) -> Option<::Extrinsic> { Messenger::outbox_message_unsigned(msg) } - fn inbox_response_message_unsigned(msg: CrossDomainMessage::Hash, ::Hash>) -> Option<::Extrinsic> { + fn inbox_response_message_unsigned(msg: CrossDomainMessage<::Hash, ::Hash>) -> Option<::Extrinsic> { Messenger::inbox_response_message_unsigned(msg) } From 9c6a75040ae901d319cad717f939f606c04edeff Mon Sep 17 00:00:00 2001 From: vedhavyas Date: Mon, 5 Feb 2024 19:10:54 +0530 Subject: [PATCH 6/9] update runtimes with actual xdm verification --- crates/subspace-runtime/src/lib.rs | 8 ++++++-- domains/pallets/messenger/src/lib.rs | 16 +++++++++------- domains/runtime/evm/src/lib.rs | 8 ++++++-- domains/test/runtime/evm/src/lib.rs | 8 ++++++-- test/subspace-test-runtime/src/lib.rs | 8 ++++++-- 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/crates/subspace-runtime/src/lib.rs b/crates/subspace-runtime/src/lib.rs index 36ac25974f..e389f1fc1e 100644 --- a/crates/subspace-runtime/src/lib.rs +++ b/crates/subspace-runtime/src/lib.rs @@ -795,8 +795,12 @@ fn extract_segment_headers(ext: &UncheckedExtrinsic) -> Option) -> Option { if let Ok(ext) = UncheckedExtrinsic::decode(&mut encoded_ext.as_slice()) { match &ext.function { - RuntimeCall::Messenger(pallet_messenger::Call::relay_message { .. }) => None, - RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { .. }) => None, + RuntimeCall::Messenger(pallet_messenger::Call::relay_message { msg }) => { + Some(Messenger::validate_relay_message(msg).is_ok()) + } + RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { msg }) => { + Some(Messenger::validate_relay_message_response(msg).is_ok()) + } _ => None, } } else { diff --git a/domains/pallets/messenger/src/lib.rs b/domains/pallets/messenger/src/lib.rs index a0e627865d..8dc7562052 100644 --- a/domains/pallets/messenger/src/lib.rs +++ b/domains/pallets/messenger/src/lib.rs @@ -87,7 +87,9 @@ pub(crate) type StateRootOf = <::Hashing as Hash>: pub(crate) type BalanceOf = <::Currency as Inspect<::AccountId>>::Balance; -pub(crate) struct ValidatedRelayMessage { +/// A validated relay message. +#[derive(Debug)] +pub struct ValidatedRelayMessage { msg: Message, next_nonce: Nonce, should_init_channel: bool, @@ -306,7 +308,7 @@ mod pallet { msg, next_nonce, should_init_channel, - } = Self::do_validate_relay_message(xdm)?; + } = Self::validate_relay_message(xdm)?; if msg.nonce != next_nonce { log::error!( "Unexpected message nonce, channel next nonce {:?}, msg nonce {:?}", @@ -323,7 +325,7 @@ mod pallet { Self::pre_dispatch_relay_message(msg, should_init_channel) } Call::relay_message_response { msg: xdm } => { - let (msg, next_nonce) = Self::do_validate_relay_message_response(xdm)?; + let (msg, next_nonce) = Self::validate_relay_message_response(xdm)?; if msg.nonce != next_nonce { log::error!( "Unexpected message response nonce, channel next nonce {:?}, msg nonce {:?}", @@ -351,7 +353,7 @@ mod pallet { msg, next_nonce, should_init_channel: _, - } = Self::do_validate_relay_message(xdm)?; + } = Self::validate_relay_message(xdm)?; let mut valid_tx_builder = ValidTransaction::with_tag_prefix("MessengerInbox"); // Only add the requires tag if the msg nonce is in future @@ -370,7 +372,7 @@ mod pallet { .build() } Call::relay_message_response { msg: xdm } => { - let (msg, next_nonce) = Self::do_validate_relay_message_response(xdm)?; + let (msg, next_nonce) = Self::validate_relay_message_response(xdm)?; let mut valid_tx_builder = ValidTransaction::with_tag_prefix("MessengerOutboxResponse"); @@ -695,7 +697,7 @@ mod pallet { Ok(channel_id) } - pub(crate) fn do_validate_relay_message( + pub fn validate_relay_message( xdm: &CrossDomainMessage, ) -> Result>, TransactionValidityError> { let mut should_init_channel = false; @@ -792,7 +794,7 @@ mod pallet { Ok(()) } - pub(crate) fn do_validate_relay_message_response( + pub fn validate_relay_message_response( xdm: &CrossDomainMessage, ) -> Result<(Message>, Nonce), TransactionValidityError> { // channel should be open and message should be present in outbox diff --git a/domains/runtime/evm/src/lib.rs b/domains/runtime/evm/src/lib.rs index b942d6fad0..abb47c0dd9 100644 --- a/domains/runtime/evm/src/lib.rs +++ b/domains/runtime/evm/src/lib.rs @@ -704,8 +704,12 @@ impl fp_rpc::ConvertTransaction for TransactionConve fn is_xdm_valid(encoded_ext: Vec) -> Option { if let Ok(ext) = UncheckedExtrinsic::decode(&mut encoded_ext.as_slice()) { match &ext.0.function { - RuntimeCall::Messenger(pallet_messenger::Call::relay_message { .. }) => None, - RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { .. }) => None, + RuntimeCall::Messenger(pallet_messenger::Call::relay_message { msg }) => { + Some(Messenger::validate_relay_message(msg).is_ok()) + } + RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { msg }) => { + Some(Messenger::validate_relay_message_response(msg).is_ok()) + } _ => None, } } else { diff --git a/domains/test/runtime/evm/src/lib.rs b/domains/test/runtime/evm/src/lib.rs index 726b212150..13f303eff7 100644 --- a/domains/test/runtime/evm/src/lib.rs +++ b/domains/test/runtime/evm/src/lib.rs @@ -699,8 +699,12 @@ impl fp_rpc::ConvertTransaction for TransactionConve fn is_xdm_valid(encoded_ext: Vec) -> Option { if let Ok(ext) = UncheckedExtrinsic::decode(&mut encoded_ext.as_slice()) { match &ext.0.function { - RuntimeCall::Messenger(pallet_messenger::Call::relay_message { .. }) => None, - RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { .. }) => None, + RuntimeCall::Messenger(pallet_messenger::Call::relay_message { msg }) => { + Some(Messenger::validate_relay_message(msg).is_ok()) + } + RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { msg }) => { + Some(Messenger::validate_relay_message_response(msg).is_ok()) + } _ => None, } } else { diff --git a/test/subspace-test-runtime/src/lib.rs b/test/subspace-test-runtime/src/lib.rs index dfb764050f..d82537b950 100644 --- a/test/subspace-test-runtime/src/lib.rs +++ b/test/subspace-test-runtime/src/lib.rs @@ -823,8 +823,12 @@ fn extract_segment_headers(ext: &UncheckedExtrinsic) -> Option) -> Option { if let Ok(ext) = UncheckedExtrinsic::decode(&mut encoded_ext.as_slice()) { match &ext.function { - RuntimeCall::Messenger(pallet_messenger::Call::relay_message { .. }) => None, - RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { .. }) => None, + RuntimeCall::Messenger(pallet_messenger::Call::relay_message { msg }) => { + Some(Messenger::validate_relay_message(msg).is_ok()) + } + RuntimeCall::Messenger(pallet_messenger::Call::relay_message_response { msg }) => { + Some(Messenger::validate_relay_message_response(msg).is_ok()) + } _ => None, } } else { From 2acab7cc981f2039abba332467013dd73334dbe2 Mon Sep 17 00:00:00 2001 From: vedhavyas Date: Mon, 5 Feb 2024 20:16:29 +0530 Subject: [PATCH 7/9] remove state root api since relayer would not use it anymore but instead rely on on Confirmed domain blocks Also fixed some WASM sp-std and missing exclusion of default features --- crates/sp-domains/src/lib.rs | 6 ---- .../sp-subspace-mmr/src/runtime_interface.rs | 2 +- crates/subspace-runtime/src/lib.rs | 4 --- domains/client/relayer/src/lib.rs | 35 +++---------------- domains/pallets/messenger/src/lib.rs | 1 + .../src/runtime_interface.rs | 1 + test/subspace-test-runtime/src/lib.rs | 4 --- 7 files changed, 7 insertions(+), 46 deletions(-) diff --git a/crates/sp-domains/src/lib.rs b/crates/sp-domains/src/lib.rs index 9d84c77890..2c0911f5a1 100644 --- a/crates/sp-domains/src/lib.rs +++ b/crates/sp-domains/src/lib.rs @@ -1091,12 +1091,6 @@ sp_api::decl_runtime_apis! { /// Returns the current best number of the domain. fn domain_best_number(domain_id: DomainId) -> Option>; - /// Returns the chain state root at the given block. - fn domain_state_root( - domain_id: DomainId, - number: HeaderNumberFor, - hash: HeaderHashFor) -> Option>; - /// Returns the execution receipt fn execution_receipt(receipt_hash: HeaderHashFor) -> Option>; diff --git a/crates/sp-subspace-mmr/src/runtime_interface.rs b/crates/sp-subspace-mmr/src/runtime_interface.rs index c5d826e65e..6dfb321f68 100644 --- a/crates/sp-subspace-mmr/src/runtime_interface.rs +++ b/crates/sp-subspace-mmr/src/runtime_interface.rs @@ -7,6 +7,7 @@ use sp_core::H256; use sp_externalities::ExternalitiesExt; use sp_mmr_primitives::EncodableOpaqueLeaf; use sp_runtime_interface::runtime_interface; +use sp_std::vec::Vec; /// MMR related runtime interface #[runtime_interface] @@ -29,7 +30,6 @@ pub struct LeafData { #[runtime_interface] pub trait DomainMmrRuntimeInterface { /// Verifies the given MMR proof using the leaves provided - #[allow(dead_code)] fn verify_mmr_proof( &mut self, leaves: Vec, diff --git a/crates/subspace-runtime/src/lib.rs b/crates/subspace-runtime/src/lib.rs index e389f1fc1e..25ccaf0159 100644 --- a/crates/subspace-runtime/src/lib.rs +++ b/crates/subspace-runtime/src/lib.rs @@ -1091,10 +1091,6 @@ impl_runtime_apis! { Domains::domain_best_number(domain_id) } - fn domain_state_root(_domain_id: DomainId, _number: DomainNumber, _hash: DomainHash) -> Option{ - None - } - fn execution_receipt(receipt_hash: DomainHash) -> Option> { Domains::execution_receipt(receipt_hash) } diff --git a/domains/client/relayer/src/lib.rs b/domains/client/relayer/src/lib.rs index 0a4f561135..88106ed8eb 100644 --- a/domains/client/relayer/src/lib.rs +++ b/domains/client/relayer/src/lib.rs @@ -53,8 +53,6 @@ pub enum Error { ApiError(sp_api::ApiError), /// Emits when the core domain block is not yet confirmed on the system domain. DomainNonConfirmedOnConsensusChain, - /// Emits when the core domain block state root is invalid. - DomainStateRootInvalid, /// Failed to submit a cross domain message UnableToSubmitCrossDomainMessage(TrySendError), /// Invalid ChainId @@ -320,36 +318,11 @@ where return Ok(()); } - // verify if the state root is matching. - let domain_number = *domain_block_header.number(); - if !consensus_chain_api - .domain_state_root( - best_consensus_chain_hash, - domain_id, - domain_number, - confirmed_block_hash, - )? - .map(|state_root| state_root == (*domain_block_header.state_root())) - .unwrap_or_else(|| { - // if this is genesis block, ignore as state root of genesis for domain is not tracked on runtime - domain_number.is_zero() - }) - { - tracing::error!( - target: LOG_TARGET, - "Domain state root mismatch at: Number: {:?}, Hash: {:?}", - domain_number, - confirmed_block_hash - ); - return Err(Error::DomainStateRootInvalid); - } - - // generate domain proof that points to the state root of the domain block on Consensus chain. + // generate domain proof that points to the confirmed domain block on consensus chain let storage_key = consensus_chain_api .confirmed_domain_block_storage_key(best_consensus_chain_hash, domain_id)?; - // construct storage proof for the core domain state root using system domain backend. - let domain_state_root_proof = consensus_chain_client.read_proof( + let domain_proof = consensus_chain_client.read_proof( best_consensus_chain_hash, &mut [storage_key.as_ref()].into_iter(), )?; @@ -364,7 +337,7 @@ where block_hash, key, *best_consensus_chain_block_header.state_root(), - domain_state_root_proof.clone(), + domain_proof.clone(), ) }, |msg| Self::gossip_outbox_message(domain_client, msg, gossip_message_sink), @@ -380,7 +353,7 @@ where block_id, key, *best_consensus_chain_block_header.state_root(), - domain_state_root_proof.clone(), + domain_proof.clone(), ) }, |msg| Self::gossip_inbox_message_response(domain_client, msg, gossip_message_sink), diff --git a/domains/pallets/messenger/src/lib.rs b/domains/pallets/messenger/src/lib.rs index 8dc7562052..200f20b9b2 100644 --- a/domains/pallets/messenger/src/lib.rs +++ b/domains/pallets/messenger/src/lib.rs @@ -117,6 +117,7 @@ mod pallet { use sp_mmr_primitives::EncodableOpaqueLeaf; use sp_runtime::ArithmeticError; use sp_std::boxed::Box; + use sp_std::vec::Vec; #[pallet::config] pub trait Config: frame_system::Config { diff --git a/domains/primitives/messenger-host-functions/src/runtime_interface.rs b/domains/primitives/messenger-host-functions/src/runtime_interface.rs index bc9a969441..f1eefb1bcf 100644 --- a/domains/primitives/messenger-host-functions/src/runtime_interface.rs +++ b/domains/primitives/messenger-host-functions/src/runtime_interface.rs @@ -4,6 +4,7 @@ use crate::StorageKeyRequest; #[cfg(feature = "std")] use sp_externalities::ExternalitiesExt; use sp_runtime_interface::runtime_interface; +use sp_std::vec::Vec; /// Messenger related runtime interface #[runtime_interface] diff --git a/test/subspace-test-runtime/src/lib.rs b/test/subspace-test-runtime/src/lib.rs index d82537b950..458c568ad6 100644 --- a/test/subspace-test-runtime/src/lib.rs +++ b/test/subspace-test-runtime/src/lib.rs @@ -1283,10 +1283,6 @@ impl_runtime_apis! { Domains::domain_best_number(domain_id) } - fn domain_state_root(_domain_id: DomainId, _number: DomainNumber, _hash: DomainHash) -> Option{ - None - } - fn execution_receipt(receipt_hash: DomainHash) -> Option> { Domains::execution_receipt(receipt_hash) } From 4ee91fdb9aa0925608c0aae127447e8d067e0b3f Mon Sep 17 00:00:00 2001 From: vedhavyas Date: Wed, 14 Feb 2024 12:02:37 +0530 Subject: [PATCH 8/9] refactor domain specific host functions and ext factory and update fraud proof verifier to use the extensions --- Cargo.lock | 2 + crates/pallet-domains/src/lib.rs | 1 + crates/pallet-domains/src/tests.rs | 7 ++ .../src/host_functions.rs | 66 +++++++++++++-- .../src/runtime_interface.rs | 3 + .../src/verification.rs | 11 ++- crates/sp-subspace-mmr/src/host_functions.rs | 2 +- crates/subspace-node/src/main.rs | 2 +- crates/subspace-service/src/domains.rs | 83 +++++++++++++++++++ crates/subspace-service/src/lib.rs | 13 ++- .../src/host_functions.rs | 2 +- .../messenger-host-functions/src/lib.rs | 2 +- domains/service/Cargo.toml | 1 + domains/service/src/domain.rs | 13 ++- domains/service/src/lib.rs | 70 +--------------- test/subspace-test-service/Cargo.toml | 1 + test/subspace-test-service/src/lib.rs | 16 +++- 17 files changed, 203 insertions(+), 92 deletions(-) create mode 100644 crates/subspace-service/src/domains.rs diff --git a/Cargo.lock b/Cargo.lock index 6649786d56..3494f44e65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2715,6 +2715,7 @@ dependencies = [ "sp-transaction-pool", "subspace-core-primitives", "subspace-runtime-primitives", + "subspace-service", "substrate-build-script-utils", "substrate-frame-rpc-system", "substrate-prometheus-endpoint", @@ -12165,6 +12166,7 @@ dependencies = [ "sp-externalities", "sp-inherents", "sp-keyring", + "sp-messenger", "sp-mmr-primitives", "sp-runtime", "sp-subspace-mmr", diff --git a/crates/pallet-domains/src/lib.rs b/crates/pallet-domains/src/lib.rs index 2bbd896126..5d22d770d7 100644 --- a/crates/pallet-domains/src/lib.rs +++ b/crates/pallet-domains/src/lib.rs @@ -343,6 +343,7 @@ mod pallet { /// Starting EVM chain ID for evm runtimes. pub struct StartingEVMChainId; + impl Get for StartingEVMChainId { fn get() -> EVMChainId { // after looking at `https://chainlist.org/?testnets=false` diff --git a/crates/pallet-domains/src/tests.rs b/crates/pallet-domains/src/tests.rs index a723bf6c2d..387395cd2d 100644 --- a/crates/pallet-domains/src/tests.rs +++ b/crates/pallet-domains/src/tests.rs @@ -75,6 +75,7 @@ frame_support::construct_runtime!( type BlockNumber = u64; type Hash = H256; type AccountId = u128; + impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -116,6 +117,7 @@ parameter_types! { } pub struct ConfirmationDepthK; + impl Get for ConfirmationDepthK { fn get() -> BlockNumber { 10 @@ -193,6 +195,7 @@ impl frame_support::traits::Randomness for MockRandomness { } const SLOT_DURATION: u64 = 1000; + impl pallet_timestamp::Config for Test { /// A timestamp: milliseconds since the unix epoch. type Moment = Moment; @@ -202,6 +205,7 @@ impl pallet_timestamp::Config for Test { } pub struct DummyStorageFee; + impl StorageFee for DummyStorageFee { fn transaction_byte_fee() -> Balance { SSC @@ -210,6 +214,7 @@ impl StorageFee for DummyStorageFee { } pub struct DummyBlockSlot; + impl BlockSlot for DummyBlockSlot { fn current_slot() -> sp_consensus_slots::Slot { 0u64.into() @@ -253,6 +258,7 @@ impl pallet_domains::Config for Test { } pub struct ExtrinsicStorageFees; + impl domain_pallet_executive::ExtrinsicStorageFees for ExtrinsicStorageFees { fn extract_signer(_xt: MockUncheckedExtrinsic) -> (Option, DispatchInfo) { (None, DispatchInfo::default()) @@ -385,6 +391,7 @@ impl FraudProofHostFunctions for MockDomainFraudProofExtension { fn execution_proof_check( &self, + _domain_id: (u32, H256), _pre_state_root: H256, _encoded_proof: Vec, _execution_method: &str, diff --git a/crates/sp-domains-fraud-proof/src/host_functions.rs b/crates/sp-domains-fraud-proof/src/host_functions.rs index f010c09b5b..4fb333129e 100644 --- a/crates/sp-domains-fraud-proof/src/host_functions.rs +++ b/crates/sp-domains-fraud-proof/src/host_functions.rs @@ -5,18 +5,22 @@ use codec::{Decode, Encode}; use domain_block_preprocessor::inherents::extract_domain_runtime_upgrade_code; use domain_block_preprocessor::stateless_runtime::StatelessRuntime; use domain_runtime_primitives::{ - CheckExtrinsicsValidityError, CHECK_EXTRINSICS_AND_DO_PRE_DISPATCH_METHOD_NAME, + BlockNumber, CheckExtrinsicsValidityError, CHECK_EXTRINSICS_AND_DO_PRE_DISPATCH_METHOD_NAME, }; +use hash_db::Hasher; +use sc_client_api::execution_extensions::ExtensionsFactory; use sc_client_api::BlockBackend; use sc_executor::RuntimeVersionOf; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; -use sp_core::traits::{CodeExecutor, FetchRuntimeCode, RuntimeCode}; +use sp_core::traits::{CallContext, CodeExecutor, FetchRuntimeCode, RuntimeCode}; use sp_core::H256; use sp_domains::bundle_producer_election::BundleProducerElectionParams; use sp_domains::{BundleProducerElectionApi, DomainId, DomainsApi, OperatorId}; -use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT}; +use sp_externalities::Extensions; +use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, NumberFor}; use sp_runtime::OpaqueExtrinsic; +use sp_state_machine::{create_proof_check_backend, Error, OverlayedChanges, StateMachine}; use sp_std::vec::Vec; use sp_trie::StorageProof; use std::borrow::Cow; @@ -53,6 +57,7 @@ pub trait FraudProofHostFunctions: Send + Sync { /// Check the execution proof fn execution_proof_check( &self, + domain_block_id: (BlockNumber, H256), pre_state_root: H256, // TODO: implement `PassBy` for `sp_trie::StorageProof` in upstream to pass it directly here encoded_proof: Vec, @@ -78,16 +83,22 @@ impl FraudProofExtension { pub struct FraudProofHostFunctionsImpl { consensus_client: Arc, executor: Arc, + domain_extensions_factory: Box>, _phantom: PhantomData<(Block, DomainBlock)>, } impl FraudProofHostFunctionsImpl { - pub fn new(consensus_client: Arc, executor: Arc) -> Self { + pub fn new( + consensus_client: Arc, + executor: Arc, + domain_extensions_factory: Box>, + ) -> Self { FraudProofHostFunctionsImpl { consensus_client, executor, + domain_extensions_factory, _phantom: Default::default(), } } @@ -327,7 +338,7 @@ where &self, consensus_block_hash: H256, domain_id: DomainId, - domain_block_id: (u32, H256), + domain_block_id: (BlockNumber, H256), domain_block_state_root: H256, bundle_extrinsics: Vec, storage_proof: StorageProof, @@ -337,6 +348,7 @@ where let runtime_code = self.get_domain_runtime_code(consensus_block_hash, domain_id)?; let raw_response = self.execution_proof_check( + domain_block_id, domain_block_state_root, storage_proof.encode(), CHECK_EXTRINSICS_AND_DO_PRE_DISPATCH_METHOD_NAME, @@ -362,6 +374,7 @@ where Block::Hash: From, DomainBlock: BlockT, DomainBlock::Hash: From + Into, + NumberFor: From, Client: BlockBackend + HeaderBackend + ProvideRuntimeApi, Client::Api: DomainsApi + BundleProducerElectionApi, Executor: CodeExecutor + RuntimeVersionOf, @@ -516,6 +529,7 @@ where fn execution_proof_check( &self, + domain_block_id: (BlockNumber, H256), pre_state_root: H256, encoded_proof: Vec, execution_method: &str, @@ -532,7 +546,12 @@ where heap_pages: None, }; - sp_state_machine::execution_proof_check::<::Hashing, _>( + let (domain_block_number, domain_block_hash) = domain_block_id; + let mut domain_extensions = self + .domain_extensions_factory + .extensions_for(domain_block_hash.into(), domain_block_number.into()); + + execution_proof_check::<::Hashing, _>( pre_state_root.into(), proof, &mut Default::default(), @@ -540,7 +559,42 @@ where execution_method, call_data, &runtime_code, + &mut domain_extensions, ) .ok() } } + +#[allow(clippy::too_many_arguments)] +/// Executes the given proof using the runtime +/// The only difference between sp_state_machine::execution_proof_check is Extensions +pub(crate) fn execution_proof_check( + root: H::Out, + proof: StorageProof, + overlay: &mut OverlayedChanges, + exec: &Exec, + method: &str, + call_data: &[u8], + runtime_code: &RuntimeCode, + extensions: &mut Extensions, +) -> Result, Box> +where + H: Hasher, + H::Out: Ord + 'static + codec::Codec, + Exec: CodeExecutor + Clone + 'static, +{ + let trie_backend = create_proof_check_backend::(root, proof)?; + let result = StateMachine::<_, H, Exec>::new( + &trie_backend, + overlay, + exec, + method, + call_data, + extensions, + runtime_code, + CallContext::Offchain, + ) + .execute(); + + result +} diff --git a/crates/sp-domains-fraud-proof/src/runtime_interface.rs b/crates/sp-domains-fraud-proof/src/runtime_interface.rs index 8c7823e237..473c497824 100644 --- a/crates/sp-domains-fraud-proof/src/runtime_interface.rs +++ b/crates/sp-domains-fraud-proof/src/runtime_interface.rs @@ -1,6 +1,7 @@ #[cfg(feature = "std")] use crate::FraudProofExtension; use crate::{FraudProofVerificationInfoRequest, FraudProofVerificationInfoResponse}; +use domain_runtime_primitives::BlockNumber; use sp_core::H256; use sp_domains::DomainId; #[cfg(feature = "std")] @@ -38,6 +39,7 @@ pub trait FraudProofRuntimeInterface { /// Check the execution proof fn execution_proof_check( &mut self, + domain_block_id: (BlockNumber, H256), pre_state_root: H256, encoded_proof: Vec, execution_method: &str, @@ -47,6 +49,7 @@ pub trait FraudProofRuntimeInterface { self.extension::() .expect("No `FraudProofExtension` associated for the current context!") .execution_proof_check( + domain_block_id, pre_state_root, encoded_proof, execution_method, diff --git a/crates/sp-domains-fraud-proof/src/verification.rs b/crates/sp-domains-fraud-proof/src/verification.rs index 5a7a8a43d2..388a4f768a 100644 --- a/crates/sp-domains-fraud-proof/src/verification.rs +++ b/crates/sp-domains-fraud-proof/src/verification.rs @@ -8,7 +8,7 @@ use crate::{ FraudProofVerificationInfoResponse, SetCodeExtrinsic, }; use codec::{Decode, Encode}; -use domain_runtime_primitives::BlockFees; +use domain_runtime_primitives::{BlockFees, BlockNumber}; use hash_db::Hasher; use sp_core::storage::StorageKey; use sp_core::H256; @@ -21,7 +21,9 @@ use sp_domains::{ HeaderNumberFor, InboxedBundle, InvalidBundleType, OperatorPublicKey, SealedBundleHeader, }; use sp_runtime::generic::Digest; -use sp_runtime::traits::{Block as BlockT, Hash, Header as HeaderT, NumberFor}; +use sp_runtime::traits::{ + Block as BlockT, Hash, Header as HeaderT, NumberFor, UniqueSaturatedInto, +}; use sp_runtime::{OpaqueExtrinsic, RuntimeAppPublic, SaturatedConversion}; use sp_std::vec::Vec; use sp_trie::{LayoutV1, StorageProof}; @@ -219,6 +221,7 @@ where CBlock::Hash: Into, DomainHeader: HeaderT, DomainHeader::Hash: Into + From, + DomainHeader::Number: UniqueSaturatedInto + From, { let InvalidStateTransitionProof { domain_id, @@ -241,6 +244,10 @@ where .call_data::(&bad_receipt, &bad_receipt_parent)?; let execution_result = fraud_proof_runtime_interface::execution_proof_check( + ( + bad_receipt_parent.domain_block_number.saturated_into(), + bad_receipt_parent.domain_block_hash.into(), + ), pre_state_root, proof.encode(), execution_phase.execution_method(), diff --git a/crates/sp-subspace-mmr/src/host_functions.rs b/crates/sp-subspace-mmr/src/host_functions.rs index e17f205e62..9b88e22d53 100644 --- a/crates/sp-subspace-mmr/src/host_functions.rs +++ b/crates/sp-subspace-mmr/src/host_functions.rs @@ -3,7 +3,7 @@ use codec::Decode; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; use sp_core::H256; -use sp_mmr_primitives::{EncodableOpaqueLeaf, MmrApi, Proof}; +pub use sp_mmr_primitives::{EncodableOpaqueLeaf, MmrApi, Proof}; use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; use std::marker::PhantomData; use std::sync::Arc; diff --git a/crates/subspace-node/src/main.rs b/crates/subspace-node/src/main.rs index b0785ff29c..d1c38210a8 100644 --- a/crates/subspace-node/src/main.rs +++ b/crates/subspace-node/src/main.rs @@ -28,7 +28,6 @@ use crate::domain::cli::DomainKey; use crate::domain::{DomainCli, DomainSubcommand}; use clap::Parser; use domain_runtime_primitives::opaque::Block as DomainBlock; -use domain_service::HostFunctions as DomainHostFunctions; use frame_benchmarking_cli::BenchmarkCmd; use futures::future::TryFutureExt; use sc_cli::{ChainSpec, SubstrateCli}; @@ -37,6 +36,7 @@ use serde_json::Value; use sp_core::crypto::Ss58AddressFormat; use subspace_proof_of_space::chia::ChiaTable; use subspace_runtime::{Block, RuntimeApi}; +use subspace_service::domains::HostFunctions as DomainHostFunctions; use subspace_service::HostFunctions; use tracing::warn; diff --git a/crates/subspace-service/src/domains.rs b/crates/subspace-service/src/domains.rs new file mode 100644 index 0000000000..f25c2135fc --- /dev/null +++ b/crates/subspace-service/src/domains.rs @@ -0,0 +1,83 @@ +use sc_client_api::execution_extensions::ExtensionsFactory as ExtensionsFactoryT; +use sc_executor::RuntimeVersionOf; +use sp_api::ProvideRuntimeApi; +use sp_blockchain::HeaderBackend; +use sp_core::traits::CodeExecutor; +use sp_core::H256; +use sp_domains::DomainsApi; +use sp_externalities::Extensions; +use sp_messenger_host_functions::{MessengerApi, MessengerExtension, MessengerHostFunctionsImpl}; +use sp_runtime::traits::{Block as BlockT, NumberFor}; +use sp_subspace_mmr::host_functions::{MmrApi, SubspaceMmrExtension, SubspaceMmrHostFunctionsImpl}; +use std::marker::PhantomData; +use std::sync::Arc; + +/// Host functions required for Subspace domain +#[cfg(not(feature = "runtime-benchmarks"))] +pub type HostFunctions = ( + sp_io::SubstrateHostFunctions, + sp_messenger_host_functions::HostFunctions, + sp_subspace_mmr::DomainHostFunctions, +); + +/// Host functions required for Subspace domain +#[cfg(feature = "runtime-benchmarks")] +pub type HostFunctions = ( + sp_io::SubstrateHostFunctions, + sp_messenger_host_functions::HostFunctions, + sp_subspace_mmr::DomainHostFunctions, + frame_benchmarking::benchmarking::HostFunctions, +); + +/// Runtime executor for Domains +pub type RuntimeExecutor = sc_executor::WasmExecutor; + +/// Extensions factory for subspace domains. +pub struct ExtensionsFactory { + consensus_client: Arc, + executor: Arc, + _marker: PhantomData<(CBlock, Block)>, +} + +impl ExtensionsFactory { + pub fn new(consensus_client: Arc, executor: Arc) -> Self { + Self { + consensus_client, + executor, + _marker: Default::default(), + } + } +} + +impl ExtensionsFactoryT + for ExtensionsFactory +where + Block: BlockT, + CBlock: BlockT, + CBlock::Hash: From, + CClient: HeaderBackend + ProvideRuntimeApi + 'static, + CClient::Api: MmrApi> + + MessengerApi> + + DomainsApi, + Executor: CodeExecutor + RuntimeVersionOf, +{ + fn extensions_for( + &self, + _block_hash: Block::Hash, + _block_number: NumberFor, + ) -> Extensions { + let mut exts = Extensions::new(); + exts.register(SubspaceMmrExtension::new(Arc::new( + SubspaceMmrHostFunctionsImpl::::new(self.consensus_client.clone()), + ))); + + exts.register(MessengerExtension::new(Arc::new( + MessengerHostFunctionsImpl::::new( + self.consensus_client.clone(), + self.executor.clone(), + ), + ))); + + exts + } +} diff --git a/crates/subspace-service/src/lib.rs b/crates/subspace-service/src/lib.rs index a5f1484d86..b49d995b4c 100644 --- a/crates/subspace-service/src/lib.rs +++ b/crates/subspace-service/src/lib.rs @@ -25,6 +25,7 @@ )] pub mod config; +pub mod domains; pub mod dsn; mod metrics; pub mod rpc; @@ -39,6 +40,7 @@ use crate::transaction_pool::FullPool; use core::sync::atomic::{AtomicU32, Ordering}; use cross_domain_message_gossip::xdm_gossip_peers_set_config; use domain_runtime_primitives::opaque::{Block as DomainBlock, Header as DomainHeader}; +use domains::ExtensionsFactory as DomainsExtensionFactory; use frame_system_rpc_runtime_api::AccountNonceApi; use futures::channel::oneshot; use futures::FutureExt; @@ -228,6 +230,7 @@ struct SubspaceExtensionsFactory { client: Arc, pot_verifier: PotVerifier, executor: Arc, + domains_executor: Arc, _pos_table: PhantomData<(PosTable, DomainBlock)>, } @@ -366,9 +369,13 @@ where })); exts.register(FraudProofExtension::new(Arc::new( - FraudProofHostFunctionsImpl::<_, _, DomainBlock, RuntimeExecutor>::new( + FraudProofHostFunctionsImpl::<_, _, DomainBlock, _>::new( self.client.clone(), - self.executor.clone(), + self.domains_executor.clone(), + Box::new(DomainsExtensionFactory::<_, Block, DomainBlock, _>::new( + self.client.clone(), + self.domains_executor.clone(), + )), ), ))); @@ -450,6 +457,7 @@ where .transpose()?; let executor = sc_service::new_wasm_executor(config); + let domains_executor = sc_service::new_wasm_executor(config); let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( @@ -477,6 +485,7 @@ where client: Arc::clone(&client), pot_verifier: pot_verifier.clone(), executor: executor.clone(), + domains_executor: Arc::new(domains_executor), _pos_table: PhantomData, }); diff --git a/domains/primitives/messenger-host-functions/src/host_functions.rs b/domains/primitives/messenger-host-functions/src/host_functions.rs index 1a6c1ba01a..5f85fe140e 100644 --- a/domains/primitives/messenger-host-functions/src/host_functions.rs +++ b/domains/primitives/messenger-host-functions/src/host_functions.rs @@ -7,7 +7,7 @@ use sp_core::traits::CodeExecutor; use sp_core::H256; use sp_domains::{DomainId, DomainsApi}; use sp_messenger::messages::ChainId; -use sp_messenger::MessengerApi; +pub use sp_messenger::MessengerApi; use sp_runtime::traits::{Block as BlockT, Header, NumberFor}; use std::marker::PhantomData; use std::sync::Arc; diff --git a/domains/primitives/messenger-host-functions/src/lib.rs b/domains/primitives/messenger-host-functions/src/lib.rs index 31a9d4eb78..1a5c02a06e 100644 --- a/domains/primitives/messenger-host-functions/src/lib.rs +++ b/domains/primitives/messenger-host-functions/src/lib.rs @@ -29,7 +29,7 @@ mod host_functions; mod runtime_interface; #[cfg(feature = "std")] -pub use host_functions::{MessengerExtension, MessengerHostFunctionsImpl}; +pub use host_functions::{MessengerApi, MessengerExtension, MessengerHostFunctionsImpl}; pub use runtime_interface::messenger_runtime_interface::get_storage_key; #[cfg(feature = "std")] pub use runtime_interface::messenger_runtime_interface::HostFunctions; diff --git a/domains/service/Cargo.toml b/domains/service/Cargo.toml index 9ceda3809c..ba549cf9fc 100644 --- a/domains/service/Cargo.toml +++ b/domains/service/Cargo.toml @@ -63,6 +63,7 @@ sp-subspace-mmr = { version = "0.1.0", path = "../../crates/sp-subspace-mmr" } sp-transaction-pool = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } subspace-core-primitives = { version = "0.1.0", path = "../../crates/subspace-core-primitives" } subspace-runtime-primitives = { version = "0.1.0", path = "../../crates/subspace-runtime-primitives" } +subspace-service = { version = "0.1.0", path = "../../crates/subspace-service" } substrate-frame-rpc-system = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } substrate-prometheus-endpoint = { git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } tokio = "1.35.1" diff --git a/domains/service/src/domain.rs b/domains/service/src/domain.rs index 97f1cc05c4..7f66fc7fd8 100644 --- a/domains/service/src/domain.rs +++ b/domains/service/src/domain.rs @@ -1,6 +1,6 @@ use crate::providers::{BlockImportProvider, RpcProvider}; use crate::transaction_pool::FullChainApiWrapper; -use crate::{DomainExtensionsFactory, FullBackend, FullClient, RuntimeExecutor}; +use crate::{FullBackend, FullClient}; use cross_domain_message_gossip::ChainTxPoolMsg; use domain_client_block_preprocessor::inherents::CreateInherentDataProvider; use domain_client_message_relayer::GossipMessageSink; @@ -46,6 +46,7 @@ use std::str::FromStr; use std::sync::Arc; use subspace_core_primitives::PotOutput; use subspace_runtime_primitives::Nonce; +use subspace_service::domains::{ExtensionsFactory, RuntimeExecutor}; use substrate_frame_rpc_system::AccountNonceApi; pub type DomainOperator = Operator< @@ -173,13 +174,9 @@ where let client = Arc::new(client); let executor = Arc::new(executor); - client - .execution_extensions() - .set_extensions_factory(DomainExtensionsFactory::<_, CBlock, Block> { - consensus_client: consensus_client.clone(), - executor: executor.clone(), - _marker: Default::default(), - }); + client.execution_extensions().set_extensions_factory( + ExtensionsFactory::<_, CBlock, Block, _>::new(consensus_client.clone(), executor.clone()), + ); let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); diff --git a/domains/service/src/lib.rs b/domains/service/src/lib.rs index 3514069133..74ca989796 100644 --- a/domains/service/src/lib.rs +++ b/domains/service/src/lib.rs @@ -9,7 +9,6 @@ mod transaction_pool; pub use self::domain::{new_full, DomainOperator, DomainParams, FullPool, NewFull}; use futures::channel::oneshot; use futures::{FutureExt, StreamExt}; -use sc_client_api::execution_extensions::ExtensionsFactory; use sc_client_api::{BlockBackend, BlockchainEvents, HeaderBackend, ProofProvider}; use sc_consensus::ImportQueue; use sc_network::config::Roles; @@ -28,82 +27,17 @@ use sc_service::{ use sc_transaction_pool_api::MaintainedTransactionPool; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender}; use sp_api::ProvideRuntimeApi; -use sp_api::__private::Extensions; use sp_blockchain::HeaderMetadata; use sp_consensus::block_validation::{Chain, DefaultBlockAnnounceValidator}; -use sp_core::H256; -use sp_domains::DomainsApi; -use sp_messenger::MessengerApi; -use sp_messenger_host_functions::{MessengerExtension, MessengerHostFunctionsImpl}; -use sp_mmr_primitives::MmrApi; -use sp_runtime::traits::{Block as BlockT, BlockIdTo, NumberFor, Zero}; -use sp_subspace_mmr::host_functions::{SubspaceMmrExtension, SubspaceMmrHostFunctionsImpl}; -use std::marker::PhantomData; +use sp_runtime::traits::{Block as BlockT, BlockIdTo, Zero}; use std::sync::Arc; - -/// Host functions required for Subspace domain -#[cfg(not(feature = "runtime-benchmarks"))] -pub type HostFunctions = ( - sp_io::SubstrateHostFunctions, - sp_messenger_host_functions::HostFunctions, - sp_subspace_mmr::DomainHostFunctions, -); - -/// Host functions required for Subspace domain -#[cfg(feature = "runtime-benchmarks")] -pub type HostFunctions = ( - sp_io::SubstrateHostFunctions, - sp_messenger_host_functions::HostFunctions, - sp_subspace_mmr::DomainHostFunctions, - frame_benchmarking::benchmarking::HostFunctions, -); - -/// Runtime executor for Subspace domain -pub type RuntimeExecutor = sc_executor::WasmExecutor; +pub use subspace_service::domains::RuntimeExecutor; /// Domain full client. pub type FullClient = TFullClient; pub type FullBackend = sc_service::TFullBackend; -pub(crate) struct DomainExtensionsFactory { - consensus_client: Arc, - executor: Arc, - _marker: PhantomData<(CBlock, Block)>, -} - -impl ExtensionsFactory - for DomainExtensionsFactory -where - Block: BlockT, - CBlock: BlockT, - CBlock::Hash: From, - CClient: HeaderBackend + ProvideRuntimeApi + 'static, - CClient::Api: MmrApi> - + MessengerApi> - + DomainsApi, -{ - fn extensions_for( - &self, - _block_hash: Block::Hash, - _block_number: NumberFor, - ) -> Extensions { - let mut exts = Extensions::new(); - exts.register(SubspaceMmrExtension::new(Arc::new( - SubspaceMmrHostFunctionsImpl::::new(self.consensus_client.clone()), - ))); - - exts.register(MessengerExtension::new(Arc::new( - MessengerHostFunctionsImpl::::new( - self.consensus_client.clone(), - self.executor.clone(), - ), - ))); - - exts - } -} - /// Build the network service, the network status sinks and an RPC sender. /// /// Port from `sc_service::build_network` mostly the same with block sync disabled. diff --git a/test/subspace-test-service/Cargo.toml b/test/subspace-test-service/Cargo.toml index c2fdfb3130..546f3b2805 100644 --- a/test/subspace-test-service/Cargo.toml +++ b/test/subspace-test-service/Cargo.toml @@ -46,6 +46,7 @@ sp-domains = { version = "0.1.0", path = "../../crates/sp-domains" } sp-domains-fraud-proof = { version = "0.1.0", path = "../../crates/sp-domains-fraud-proof" } sp-externalities = { version = "0.19.0", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-keyring = { git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-messenger = { version = "0.1.0", path = "../../domains/primitives/messenger" } sp-mmr-primitives = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sp-subspace-mmr = { version = "0.1.0", path = "../../crates/sp-subspace-mmr" } sp-timestamp = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } diff --git a/test/subspace-test-service/src/lib.rs b/test/subspace-test-service/src/lib.rs index 70e169c9e0..f3cb5578d8 100644 --- a/test/subspace-test-service/src/lib.rs +++ b/test/subspace-test-service/src/lib.rs @@ -63,6 +63,7 @@ use sp_domains_fraud_proof::{FraudProofExtension, FraudProofHostFunctionsImpl}; use sp_externalities::Extensions; use sp_inherents::{InherentData, InherentDataProvider}; use sp_keyring::Sr25519Keyring; +use sp_messenger::MessengerApi; use sp_mmr_primitives::MmrApi; use sp_runtime::generic::{BlockId, Digest}; use sp_runtime::traits::{ @@ -81,6 +82,7 @@ use std::time; use subspace_core_primitives::{PotOutput, Solution}; use subspace_runtime_primitives::opaque::Block; use subspace_runtime_primitives::{AccountId, Balance, Hash}; +use subspace_service::domains::ExtensionsFactory as DomainsExtensionFactory; use subspace_service::transaction_pool::FullPool; use subspace_service::{FullSelectChain, RuntimeExecutor}; use subspace_test_client::{chain_spec, Backend, Client}; @@ -224,6 +226,7 @@ where Client: BlockBackend + HeaderBackend + ProvideRuntimeApi + 'static, Client::Api: DomainsApi + BundleProducerElectionApi + + MessengerApi> + MmrApi>, Executor: CodeExecutor + sc_executor::RuntimeVersionOf, { @@ -237,6 +240,10 @@ where FraudProofHostFunctionsImpl::<_, _, DomainBlock, Executor>::new( self.consensus_client.clone(), self.executor.clone(), + Box::new(DomainsExtensionFactory::<_, Block, DomainBlock, _>::new( + self.consensus_client.clone(), + self.executor.clone(), + )), ), ))); exts.register(SubspaceMmrExtension::new(Arc::new( @@ -345,13 +352,18 @@ impl MockConsensusNode { sc_service::new_full_parts::(&config, None, executor.clone()) .expect("Fail to new full parts"); + let domain_executor = sc_service::new_wasm_executor(&config); let client = Arc::new(client); let mock_pot_verifier = Arc::new(MockPotVerfier::default()); client .execution_extensions() - .set_extensions_factory(MockExtensionsFactory::<_, DomainBlock, _>::new( + .set_extensions_factory(MockExtensionsFactory::< + _, + DomainBlock, + subspace_service::domains::RuntimeExecutor, + >::new( client.clone(), - Arc::new(executor.clone()), + Arc::new(domain_executor), Arc::clone(&mock_pot_verifier), )); From 5cdebfd4ea21f70b317d5d46e5dc546f6e68d799 Mon Sep 17 00:00:00 2001 From: vedhavyas Date: Fri, 23 Feb 2024 17:17:19 +0530 Subject: [PATCH 9/9] create sc-domains to hold domain specific host functions and extension factory --- Cargo.lock | 24 +++++++++++++- crates/sc-domains/Cargo.toml | 33 +++++++++++++++++++ .../src/domains.rs => sc-domains/src/lib.rs} | 18 ++++++++++ crates/subspace-node/Cargo.toml | 1 + crates/subspace-node/src/main.rs | 6 ++-- crates/subspace-service/Cargo.toml | 6 +++- crates/subspace-service/src/lib.rs | 5 ++- domains/service/Cargo.toml | 7 ++-- domains/service/src/domain.rs | 2 +- domains/service/src/lib.rs | 2 +- domains/test/service/Cargo.toml | 1 + domains/test/service/src/domain.rs | 3 +- test/subspace-test-service/Cargo.toml | 1 + test/subspace-test-service/src/lib.rs | 4 +-- 14 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 crates/sc-domains/Cargo.toml rename crates/{subspace-service/src/domains.rs => sc-domains/src/lib.rs} (78%) diff --git a/Cargo.lock b/Cargo.lock index aff108ccce..8231865203 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2683,6 +2683,7 @@ dependencies = [ "sc-chain-spec", "sc-client-api", "sc-consensus", + "sc-domains", "sc-executor", "sc-informant", "sc-network", @@ -2717,7 +2718,6 @@ dependencies = [ "sp-transaction-pool", "subspace-core-primitives", "subspace-runtime-primitives", - "subspace-service", "substrate-build-script-utils", "substrate-frame-rpc-system", "substrate-prometheus-endpoint", @@ -2753,6 +2753,7 @@ dependencies = [ "pallet-transaction-payment-rpc", "rand", "sc-client-api", + "sc-domains", "sc-network", "sc-network-sync", "sc-service", @@ -9291,6 +9292,24 @@ dependencies = [ "tracing", ] +[[package]] +name = "sc-domains" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "sc-client-api", + "sc-executor", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-domains", + "sp-externalities", + "sp-io", + "sp-messenger-host-functions", + "sp-runtime", + "sp-subspace-mmr", +] + [[package]] name = "sc-executor" version = "0.10.0-dev" @@ -11833,6 +11852,7 @@ dependencies = [ "sc-client-api", "sc-consensus-slots", "sc-consensus-subspace", + "sc-domains", "sc-informant", "sc-keystore", "sc-network", @@ -12005,6 +12025,7 @@ dependencies = [ "sc-consensus-slots", "sc-consensus-subspace", "sc-consensus-subspace-rpc", + "sc-domains", "sc-executor", "sc-informant", "sc-network", @@ -12152,6 +12173,7 @@ dependencies = [ "sc-block-builder", "sc-client-api", "sc-consensus", + "sc-domains", "sc-executor", "sc-network", "sc-network-sync", diff --git a/crates/sc-domains/Cargo.toml b/crates/sc-domains/Cargo.toml new file mode 100644 index 0000000000..67e9648b04 --- /dev/null +++ b/crates/sc-domains/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "sc-domains" +version = "0.1.0" +authors = ["Subspace Labs "] +description = "Subspace service." +edition = "2021" +license = "GPL-3.0-or-later" +homepage = "https://subspace.network" +repository = "https://github.com/subspace/subspace" +include = [ + "/src", + "/Cargo.toml", +] + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +frame-benchmarking = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8", optional = true } +sc-client-api = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sc-executor = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-api = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-blockchain = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-core = { version = "21.0.0", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-domains = { version = "0.1.0", path = "../sp-domains" } +sp-externalities = { version = "0.19.0", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-io = { version = "23.0.0", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-messenger-host-functions = { version = "0.1.0", path = "../../domains/primitives/messenger-host-functions" } +sp-runtime = { version = "24.0.0", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sp-subspace-mmr = { version = "0.1.0", path = "../sp-subspace-mmr" } + +[features] +runtime-benchmarks = ["dep:frame-benchmarking"] diff --git a/crates/subspace-service/src/domains.rs b/crates/sc-domains/src/lib.rs similarity index 78% rename from crates/subspace-service/src/domains.rs rename to crates/sc-domains/src/lib.rs index f25c2135fc..0355e3c78f 100644 --- a/crates/subspace-service/src/domains.rs +++ b/crates/sc-domains/src/lib.rs @@ -1,3 +1,21 @@ +// Copyright (C) 2021 Subspace Labs, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Domain specific Host functions and Extension factory + use sc_client_api::execution_extensions::ExtensionsFactory as ExtensionsFactoryT; use sc_executor::RuntimeVersionOf; use sp_api::ProvideRuntimeApi; diff --git a/crates/subspace-node/Cargo.toml b/crates/subspace-node/Cargo.toml index 892d9f2159..7a6a081211 100644 --- a/crates/subspace-node/Cargo.toml +++ b/crates/subspace-node/Cargo.toml @@ -46,6 +46,7 @@ sc-cli = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-s sc-client-api = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-consensus-slots = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-consensus-subspace = { version = "0.1.0", path = "../sc-consensus-subspace" } +sc-domains = { version = "0.1.0", path = "../sc-domains" } sc-informant = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-keystore = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-network = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } diff --git a/crates/subspace-node/src/main.rs b/crates/subspace-node/src/main.rs index d1c38210a8..0c17951a0a 100644 --- a/crates/subspace-node/src/main.rs +++ b/crates/subspace-node/src/main.rs @@ -31,12 +31,12 @@ use domain_runtime_primitives::opaque::Block as DomainBlock; use frame_benchmarking_cli::BenchmarkCmd; use futures::future::TryFutureExt; use sc_cli::{ChainSpec, SubstrateCli}; +use sc_domains::HostFunctions as DomainsHostFunctions; use sc_service::{Configuration, PartialComponents}; use serde_json::Value; use sp_core::crypto::Ss58AddressFormat; use subspace_proof_of_space::chia::ChiaTable; use subspace_runtime::{Block, RuntimeApi}; -use subspace_service::domains::HostFunctions as DomainHostFunctions; use subspace_service::HostFunctions; use tracing::warn; @@ -349,7 +349,7 @@ fn main() -> Result<(), Error> { .into(), ); } - cmd.run::(domain_config) + cmd.run::(domain_config) } _ => todo!("Not implemented"), } @@ -372,7 +372,7 @@ fn main() -> Result<(), Error> { })?; let executor = - sc_service::new_wasm_executor::(&domain_config); + sc_service::new_wasm_executor::(&domain_config); let (client, _, _, _) = sc_service::new_full_parts::< DomainBlock, diff --git a/crates/subspace-service/Cargo.toml b/crates/subspace-service/Cargo.toml index 24550de837..86b3289316 100644 --- a/crates/subspace-service/Cargo.toml +++ b/crates/subspace-service/Cargo.toml @@ -36,6 +36,7 @@ sc-consensus = { version = "0.10.0-dev", git = "https://github.com/subspace/polk sc-consensus-subspace = { version = "0.1.0", path = "../sc-consensus-subspace" } sc-consensus-subspace-rpc = { version = "0.1.0", path = "../sc-consensus-subspace-rpc" } sc-consensus-slots = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sc-domains = { version = "0.1.0", path = "../sc-domains" } sc-executor = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-informant = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-network = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } @@ -89,4 +90,7 @@ frame-system-rpc-runtime-api = { version = "4.0.0-dev", git = "https://github.co pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } [features] -runtime-benchmarks = ["dep:frame-benchmarking"] +runtime-benchmarks = [ + "dep:frame-benchmarking", + "sc-domains/runtime-benchmarks", +] diff --git a/crates/subspace-service/src/lib.rs b/crates/subspace-service/src/lib.rs index f3bf9c0289..1589fbff80 100644 --- a/crates/subspace-service/src/lib.rs +++ b/crates/subspace-service/src/lib.rs @@ -25,7 +25,6 @@ )] pub mod config; -pub mod domains; pub mod dsn; mod metrics; pub mod rpc; @@ -40,7 +39,6 @@ use crate::transaction_pool::FullPool; use core::sync::atomic::{AtomicU32, Ordering}; use cross_domain_message_gossip::xdm_gossip_peers_set_config; use domain_runtime_primitives::opaque::{Block as DomainBlock, Header as DomainHeader}; -use domains::ExtensionsFactory as DomainsExtensionFactory; use frame_system_rpc_runtime_api::AccountNonceApi; use futures::channel::oneshot; use futures::FutureExt; @@ -69,6 +67,7 @@ use sc_consensus_subspace::slot_worker::{ }; use sc_consensus_subspace::verifier::{SubspaceVerifier, SubspaceVerifierOptions}; use sc_consensus_subspace::SubspaceLink; +use sc_domains::ExtensionsFactory as DomainsExtensionFactory; use sc_network::{NetworkService, NotificationService}; use sc_proof_of_time::source::gossip::pot_gossip_peers_set_config; use sc_proof_of_time::source::PotSourceWorker; @@ -230,7 +229,7 @@ struct SubspaceExtensionsFactory { client: Arc, pot_verifier: PotVerifier, executor: Arc, - domains_executor: Arc, + domains_executor: Arc, _pos_table: PhantomData<(PosTable, DomainBlock)>, } diff --git a/domains/service/Cargo.toml b/domains/service/Cargo.toml index ba549cf9fc..d5c8ac7e3f 100644 --- a/domains/service/Cargo.toml +++ b/domains/service/Cargo.toml @@ -30,6 +30,7 @@ sp-io = { version = "23.0.0", git = "https://github.com/subspace/polkadot-sdk", sc-chain-spec = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-client-api = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-consensus = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sc-domains = { version = "0.1.0", path = "../../crates/sc-domains" } sc-executor = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-informant = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-network = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } @@ -63,7 +64,6 @@ sp-subspace-mmr = { version = "0.1.0", path = "../../crates/sp-subspace-mmr" } sp-transaction-pool = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } subspace-core-primitives = { version = "0.1.0", path = "../../crates/subspace-core-primitives" } subspace-runtime-primitives = { version = "0.1.0", path = "../../crates/subspace-runtime-primitives" } -subspace-service = { version = "0.1.0", path = "../../crates/subspace-service" } substrate-frame-rpc-system = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } substrate-prometheus-endpoint = { git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } tokio = "1.35.1" @@ -73,4 +73,7 @@ tracing = "0.1.40" substrate-build-script-utils = { version = "3.0.0", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } [features] -runtime-benchmarks = ["dep:frame-benchmarking"] +runtime-benchmarks = [ + "dep:frame-benchmarking", + "sc-domains/runtime-benchmarks", +] diff --git a/domains/service/src/domain.rs b/domains/service/src/domain.rs index 42729ba18d..6039a3a9c8 100644 --- a/domains/service/src/domain.rs +++ b/domains/service/src/domain.rs @@ -14,6 +14,7 @@ use sc_client_api::{ BlockBackend, BlockImportNotification, BlockchainEvents, ExecutorProvider, ProofProvider, }; use sc_consensus::SharedBlockImport; +use sc_domains::{ExtensionsFactory, RuntimeExecutor}; use sc_network::NetworkPeers; use sc_rpc_api::DenyUnsafe; use sc_service::{ @@ -47,7 +48,6 @@ use std::str::FromStr; use std::sync::Arc; use subspace_core_primitives::PotOutput; use subspace_runtime_primitives::Nonce; -use subspace_service::domains::{ExtensionsFactory, RuntimeExecutor}; use substrate_frame_rpc_system::AccountNonceApi; pub type DomainOperator = Operator< diff --git a/domains/service/src/lib.rs b/domains/service/src/lib.rs index 74ca989796..48a4883a80 100644 --- a/domains/service/src/lib.rs +++ b/domains/service/src/lib.rs @@ -11,6 +11,7 @@ use futures::channel::oneshot; use futures::{FutureExt, StreamExt}; use sc_client_api::{BlockBackend, BlockchainEvents, HeaderBackend, ProofProvider}; use sc_consensus::ImportQueue; +use sc_domains::RuntimeExecutor; use sc_network::config::Roles; use sc_network::peer_store::PeerStore; use sc_network::NetworkService; @@ -31,7 +32,6 @@ use sp_blockchain::HeaderMetadata; use sp_consensus::block_validation::{Chain, DefaultBlockAnnounceValidator}; use sp_runtime::traits::{Block as BlockT, BlockIdTo, Zero}; use std::sync::Arc; -pub use subspace_service::domains::RuntimeExecutor; /// Domain full client. pub type FullClient = TFullClient; diff --git a/domains/test/service/Cargo.toml b/domains/test/service/Cargo.toml index 3b463c1456..0628a0363b 100644 --- a/domains/test/service/Cargo.toml +++ b/domains/test/service/Cargo.toml @@ -26,6 +26,7 @@ rand = "0.8.5" pallet-transaction-payment = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } pallet-transaction-payment-rpc = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-client-api = { version = "4.0.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sc-domains = { version = "0.1.0", path = "../../../crates/sc-domains" } sc-network = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-network-sync = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-service = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8", default-features = false } diff --git a/domains/test/service/src/domain.rs b/domains/test/service/src/domain.rs index bb20baccb7..2c15928626 100644 --- a/domains/test/service/src/domain.rs +++ b/domains/test/service/src/domain.rs @@ -10,7 +10,7 @@ use domain_client_operator::{fetch_domain_bootstrap_info, BootstrapResult, Opera use domain_runtime_primitives::opaque::Block; use domain_runtime_primitives::Balance; use domain_service::providers::DefaultProvider; -use domain_service::{FullClient, RuntimeExecutor}; +use domain_service::FullClient; use domain_test_primitives::OnchainStateApi; use evm_domain_test_runtime; use evm_domain_test_runtime::AccountId as AccountId20; @@ -19,6 +19,7 @@ use frame_support::dispatch::{DispatchInfo, PostDispatchInfo}; use frame_system::pallet_prelude::BlockNumberFor; use pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi; use sc_client_api::HeaderBackend; +use sc_domains::RuntimeExecutor; use sc_network::{NetworkService, NetworkStateInfo}; use sc_network_sync::SyncingService; use sc_service::config::MultiaddrWithPeerId; diff --git a/test/subspace-test-service/Cargo.toml b/test/subspace-test-service/Cargo.toml index 546f3b2805..b4a003ebdc 100644 --- a/test/subspace-test-service/Cargo.toml +++ b/test/subspace-test-service/Cargo.toml @@ -27,6 +27,7 @@ parking_lot = "0.12.1" sc-block-builder = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-client-api = { git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-consensus = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } +sc-domains = { version = "0.1.0", path = "../../crates/sc-domains" } sc-executor = { git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-network = { git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } sc-network-sync = { version = "0.10.0-dev", git = "https://github.com/subspace/polkadot-sdk", rev = "d6b500960579d73c43fc4ef550b703acfa61c4c8" } diff --git a/test/subspace-test-service/src/lib.rs b/test/subspace-test-service/src/lib.rs index b54be2993c..dce4e1a029 100644 --- a/test/subspace-test-service/src/lib.rs +++ b/test/subspace-test-service/src/lib.rs @@ -34,6 +34,7 @@ use sc_consensus::block_import::{ use sc_consensus::{ BasicQueue, BlockImport, SharedBlockImport, StateAction, Verifier as VerifierT, }; +use sc_domains::ExtensionsFactory as DomainsExtensionFactory; use sc_network::config::{NetworkConfiguration, TransportConfig}; use sc_network::{multiaddr, NotificationService}; use sc_service::config::{ @@ -82,7 +83,6 @@ use std::time; use subspace_core_primitives::{PotOutput, Solution}; use subspace_runtime_primitives::opaque::Block; use subspace_runtime_primitives::{AccountId, Balance, Hash}; -use subspace_service::domains::ExtensionsFactory as DomainsExtensionFactory; use subspace_service::transaction_pool::FullPool; use subspace_service::{FullSelectChain, RuntimeExecutor}; use subspace_test_client::{chain_spec, Backend, Client}; @@ -362,7 +362,7 @@ impl MockConsensusNode { .set_extensions_factory(MockExtensionsFactory::< _, DomainBlock, - subspace_service::domains::RuntimeExecutor, + sc_domains::RuntimeExecutor, >::new( client.clone(), Arc::new(domain_executor),