1
// Copyright (C) Parity Technologies (UK) Ltd.
2
// This file is part of Cumulus.
3

            
4
// Cumulus is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Cumulus is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Cumulus.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
//! Pallet for stuff specific to parachains' usage of XCM. Right now that's just the origin
18
//! used by parachains when receiving `Transact` messages from other parachains or the Relay chain
19
//! which must be natively represented.
20

            
21
#![cfg_attr(not(feature = "std"), no_std)]
22

            
23
use codec::{Decode, Encode};
24
use cumulus_primitives_core::ParaId;
25
pub use pallet::*;
26
use scale_info::TypeInfo;
27
use sp_runtime::{traits::BadOrigin, RuntimeDebug};
28
use xcm::latest::{ExecuteXcm, Outcome};
29

            
30
#[frame_support::pallet]
31
pub mod pallet {
32
	use super::*;
33
	use frame_support::pallet_prelude::*;
34

            
35
	#[pallet::pallet]
36
	pub struct Pallet<T>(_);
37

            
38
	/// The module configuration trait.
39
	#[pallet::config]
40
	pub trait Config: frame_system::Config {
41
		/// The overarching event type.
42
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
43

            
44
		type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;
45
	}
46

            
47
	#[pallet::event]
48
	pub enum Event<T: Config> {
49
		/// Downward message is invalid XCM.
50
		/// \[ id \]
51
		InvalidFormat([u8; 32]),
52
		/// Downward message is unsupported version of XCM.
53
		/// \[ id \]
54
		UnsupportedVersion([u8; 32]),
55
		/// Downward message executed with the given outcome.
56
		/// \[ id, outcome \]
57
		ExecutedDownward([u8; 32], Outcome),
58
	}
59

            
60
	/// Origin for the parachains module.
61
	#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, RuntimeDebug, MaxEncodedLen)]
62
	#[pallet::origin]
63
	pub enum Origin {
64
		/// It comes from the (parent) relay chain.
65
		Relay,
66
		/// It comes from a (sibling) parachain.
67
		SiblingParachain(ParaId),
68
	}
69

            
70
	#[pallet::call]
71
	impl<T: Config> Pallet<T> {}
72

            
73
	impl From<ParaId> for Origin {
74
		fn from(id: ParaId) -> Origin {
75
			Origin::SiblingParachain(id)
76
		}
77
	}
78
	impl From<u32> for Origin {
79
		fn from(id: u32) -> Origin {
80
			Origin::SiblingParachain(id.into())
81
		}
82
	}
83
}
84

            
85
/// Ensure that the origin `o` represents a sibling parachain.
86
/// Returns `Ok` with the parachain ID of the sibling or an `Err` otherwise.
87
pub fn ensure_sibling_para<OuterOrigin>(o: OuterOrigin) -> Result<ParaId, BadOrigin>
88
where
89
	OuterOrigin: Into<Result<Origin, OuterOrigin>>,
90
{
91
	match o.into() {
92
		Ok(Origin::SiblingParachain(id)) => Ok(id),
93
		_ => Err(BadOrigin),
94
	}
95
}
96

            
97
/// Ensure that the origin `o` represents is the relay chain.
98
/// Returns `Ok` if it does or an `Err` otherwise.
99
pub fn ensure_relay<OuterOrigin>(o: OuterOrigin) -> Result<(), BadOrigin>
100
where
101
	OuterOrigin: Into<Result<Origin, OuterOrigin>>,
102
{
103
	match o.into() {
104
		Ok(Origin::Relay) => Ok(()),
105
		_ => Err(BadOrigin),
106
	}
107
}