Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", default-features
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "cumulus-branch" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "cumulus-branch" }
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "cumulus-branch" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "cumulus-branch" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "cumulus-branch" }
sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "cumulus-branch" }

# Polkadot dependencies
parachain = { package = "polkadot-parachain", git = "https://github.com/paritytech/polkadot", branch = "cumulus-branch", default-features = false, features = [ "wasm-api" ] }
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "cumulus-branch" }

[dev-dependencies]
sc-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "cumulus-branch" }
Expand All @@ -40,9 +43,12 @@ std = [
"sp-runtime/std",
"sp-core/std",
"frame-executive/std",
"frame-support/std",
"frame-system/std",
"memory-db/std",
"hash-db/std",
"trie-db/std",
"sp-trie/std",
"polkadot-primitives/std",
"parachain/std",
]
190 changes: 190 additions & 0 deletions runtime/src/icmp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Cumulus.

// Cumulus 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.

// Cumulus 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.

//! The main entry point for messaging I/O of the runtime.
//!
//! This module includes:
//! - logic for creating inherent extrinsics on the client-side from a set of incoming messages;
//! - API to allow runtimes to configure the how messages are handled;
//! - API to allow runtimes to deposit outgoing messages.

use sp_std::prelude::*;
use codec::Codec;
use frame_support::{decl_module, decl_storage, decl_event, dispatch::SimpleDispatchInfo};
use frame_system::{self as system, ensure_none};
use sp_runtime::traits::Dispatchable;
use polkadot_primitives::parachain::{Chain, Id as ParaId};

/// Means of handling a bunch of "messages" (opaque blobs of data) coming in from other chains.
pub trait HandleMessages {
/// Messages have arrived: do something with them. The default implementation just forwards
/// each message to be handled by `handle_message`.
fn handle_messages(messages: &[(Chain, Vec<u8>)]) {
for (from, ref data) in messages.iter() {
Self::handle_message(*from, data)
}
}

/// Handle an individual message of `_data` from endpoint `_from`. The default implementation
/// simply drops the message.
fn handle_message(_from: Chain, _data: &[u8]) {}
}

/// Empty tuple drops all messages.
impl HandleMessages for () {}

/// An origin for this module.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Origin {
/// It comes from a parachain.
Parachain(ParaId),

/// It comes from the Relay chain.
Relay,
}

/// A message handler which treats each message as a `Call` and dispatches them as per `Call`s
/// with a corresponding `Origin`.
pub struct DispatchCall<Origin, Call>(::sp_std::marker::PhantomData<(Origin, Call)>);

impl<
Call: Codec + Dispatchable
> HandleMessages for DispatchCall<Origin, Call> where Call::Origin: From<Origin> {
fn handle_message(from: Chain, mut data: &[u8]) {
if let Ok(call) = Call::decode(&mut data) {
let origin: Call::Origin = match from {
Chain::Parachain(id) => Origin::Parachain(id),
Chain::Relay => Origin::Relay,
}.into();
// we disregard the result for now, much like transactions. If we eventually get some
// economic disincentive to spam the chain, then we could place events down here.
let _ = call.dispatch(origin);
}
}
}

/// The module's configuration trait.
pub trait Trait: system::Trait {
/// The type which is used to handle incoming messages.
type OnIncoming: HandleMessages;

/// The outer origin type.
type Origin: From<Origin> + From<system::RawOrigin<Self::AccountId>>;

/// The overarching event type.
type Event: From<Event> + Into<<Self as system::Trait>::Event>;
}

// This module's storage items.
decl_storage! {
trait Store for Module<T: Trait> as TemplateModule {
}
}

// The module's dispatchable functions.
decl_module! {
/// The module declaration.
pub struct Module<T: Trait> for enum Call where origin: <T as system::Trait>::Origin {
fn deposit_event() = default;

/// Provide any incoming messages from external ICMP chains (i.e. parachains or the relay
/// chain) for this block to execute.
/// # <weight>
/// Weight TODO
/// # </weight>
#[weight = SimpleDispatchInfo::FixedNormal(1_000_000)]
fn note_incoming(origin, messages: Vec<(Chain, Vec<u8>)>) {
ensure_none(origin)?;

T::OnIncoming::handle_messages(&messages);
}
}
}

decl_event!(
pub enum Event {
// Just a dummy event.
Dummy,
}
);

/// tests for this module
#[cfg(test)]
mod tests {
use super::*;

use primitives::H256;
use support::{impl_outer_origin, assert_ok, parameter_types};
use sr_primitives::{
traits::{BlakeTwo256, IdentityLookup}, testing::Header, weights::Weight, Perbill,
};

impl_outer_origin! {
pub enum Origin for Test {}
}

// For testing the module, we construct most of a mock runtime. This means
// first constructing a configuration type (`Test`) which `impl`s each of the
// configuration traits of modules we want to use.
#[derive(Clone, Eq, PartialEq)]
pub struct Test;
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const MaximumBlockWeight: Weight = 1024;
pub const MaximumBlockLength: u32 = 2 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
}
impl system::Trait for Test {
type Origin = Origin;
type Call = ();
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type WeightMultiplierUpdate = ();
type Event = ();
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
type MaximumBlockLength = MaximumBlockLength;
type AvailableBlockRatio = AvailableBlockRatio;
type Version = ();
}
impl Trait for Test {
type Event = ();
}
type TemplateModule = Module<Test>;

// This function basically just builds a genesis storage key/value store according to
// our desired mockup.
fn new_test_ext() -> runtime_io::TestExternalities {
system::GenesisConfig::default().build_storage::<Test>().unwrap().into()
}

#[test]
fn it_works_for_default_value() {
new_test_ext().execute_with(|| {
// Just a dummy test for the dummy funtion `do_something`
// calling the `do_something` function with a value 42
assert_ok!(TemplateModule::do_something(Origin::signed(1), 42));
// asserting that the stored value is equal to what we stored
assert_eq!(TemplateModule::something(), Some(42));
});
}
}
2 changes: 2 additions & 0 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ pub use sp_std::slice;
#[macro_use]
pub mod validate_block;

pub mod icmp;

/// The witness data type.
type WitnessData = Vec<Vec<u8>>;

Expand Down