Skip to content
lib.rs 45.9 KiB
Newer Older
// Copyright 2021 Parity Technologies (UK) Ltd.
// This file is part of Parity Bridges Common.

// Parity Bridges Common 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.

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

//! Parachains finality module.
//!
//! This module needs to be deployed with GRANDPA module, which is syncing relay
//! chain blocks. The main entry point of this module is `submit_parachain_heads`, which
//! accepts storage proof of some parachain `Heads` entries from bridged relay chain.
//! It requires corresponding relay headers to be already synced.

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

pub use weights::WeightInfo;
pub use weights_ext::WeightInfoExt;

Serban Iorga's avatar
Serban Iorga committed
use bp_parachains::{parachain_head_storage_key_at_source, ParaInfo};
use bp_polkadot_core::parachains::{ParaHash, ParaHasher, ParaHead, ParaHeadsProof, ParaId};
use bp_runtime::StorageProofError;
Serban Iorga's avatar
Serban Iorga committed
use frame_support::{traits::Contains, weights::PostDispatchInfo};
use sp_runtime::traits::Header as HeaderT;
use sp_std::vec::Vec;

// Re-export in crate namespace for `construct_runtime!`.
pub use pallet::*;

pub mod weights;
pub mod weights_ext;

#[cfg(feature = "runtime-benchmarks")]
pub mod benchmarking;

#[cfg(test)]
mod mock;

/// The target that will be used when publishing logs related to this pallet.
pub const LOG_TARGET: &str = "runtime::bridge-parachains";
/// Block hash of the bridged relay chain.
pub type RelayBlockHash = bp_polkadot_core::Hash;
/// Block number of the bridged relay chain.
pub type RelayBlockNumber = bp_polkadot_core::BlockNumber;
/// Hasher of the bridged relay chain.
pub type RelayBlockHasher = bp_polkadot_core::Hasher;

/// Artifacts of the parachains head update.
struct UpdateParachainHeadArtifacts {
	/// New best head of the parachain.
Serban Iorga's avatar
Serban Iorga committed
	pub best_head: ParaInfo,
	/// If `true`, some old parachain head has been pruned during update.
	pub prune_happened: bool,
}

#[frame_support::pallet]
pub mod pallet {
	use super::*;
Serban Iorga's avatar
Serban Iorga committed
	use bp_parachains::{BestParaHeadHash, ImportedParaHeadsKeyProvider, ParasInfoKeyProvider};
	use bp_runtime::{
		BasicOperatingMode, BoundedStorageValue, OwnedBridgeModule, StorageDoubleMapKeyProvider,
		StorageMapKeyProvider,
	use frame_support::pallet_prelude::*;
	use frame_system::pallet_prelude::*;

	/// Stored parachain head of given parachains pallet.
	pub type StoredParaHeadOf<T, I> =
		BoundedStorageValue<<T as Config<I>>::MaxParaHeadSize, ParaHead>;
	/// Weight info of the given parachains pallet.
	pub type WeightInfoOf<T, I> = <T as Config<I>>::WeightInfo;

	#[pallet::event]
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
	pub enum Event<T: Config<I>, I: 'static = ()> {
		/// The caller has provided head of parachain that the pallet is not configured to track.
		UntrackedParachainRejected { parachain: ParaId },
		/// The caller has declared that he has provided given parachain head, but it is missing
		/// from the storage proof.
		MissingParachainHead { parachain: ParaId },
		/// The caller has provided parachain head hash that is not matching the hash read from the
		/// storage proof.
		IncorrectParachainHeadHash {
			parachain: ParaId,
			parachain_head_hash: ParaHash,
			actual_parachain_head_hash: ParaHash,
		},
		/// The caller has provided obsolete parachain head, which is already known to the pallet.
		RejectedObsoleteParachainHead { parachain: ParaId, parachain_head_hash: ParaHash },
		/// The caller has provided parachain head that exceeds the maximal configured head size.
		RejectedLargeParachainHead {
			parachain: ParaId,
			parachain_head_hash: ParaHash,
			parachain_head_size: u32,
		},
		/// Parachain head has been updated.
		UpdatedParachainHead { parachain: ParaId, parachain_head_hash: ParaHash },
	}

	#[pallet::error]
	pub enum Error<T, I = ()> {
		/// Relay chain block hash is unknown to us.
		UnknownRelayChainBlock,
		/// The number of stored relay block is different from what the relayer has provided.
		InvalidRelayChainBlockNumber,
		/// Invalid storage proof has been passed.
		InvalidStorageProof,
		/// Given parachain head is unknown.
		UnknownParaHead,
		/// The storage proof doesn't contains storage root. So it is invalid for given header.
		StorageRootMismatch,
		/// Failed to extract state root from given parachain head.
		FailedToExtractStateRoot,
		/// Error generated by the `OwnedBridgeModule` trait.
		BridgeModule(bp_runtime::OwnedBridgeModuleError),
	}

	#[pallet::config]
	#[pallet::disable_frame_system_supertrait_check]
	pub trait Config<I: 'static = ()>:
		pallet_bridge_grandpa::Config<Self::BridgesGrandpaPalletInstance>
	{
		/// The overarching event type.
		type Event: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::Event>;
		/// Benchmarks results from runtime we're plugged into.
		type WeightInfo: WeightInfoExt;

		/// Instance of bridges GRANDPA pallet (within this runtime) that this pallet is linked to.
		///
		/// The GRANDPA pallet instance must be configured to import headers of relay chain that
		/// we're interested in.
		type BridgesGrandpaPalletInstance: 'static;

		/// Name of the original `paras` pallet in the `construct_runtime!()` call at the bridged
		/// chain.
		///
		/// Please keep in mind that this should be the name of the `runtime_parachains::paras`
		/// pallet from polkadot repository, not the `pallet-bridge-parachains`.
		#[pallet::constant]
		type ParasPalletName: Get<&'static str>;

		/// Set of parachains that are tracked by this pallet.
		///
		/// The set may be extended easily, without requiring any runtime upgrades. Removing tracked
		/// parachain requires special handling - pruning existing heads and cleaning related data
		/// structures.
		type TrackedParachains: Contains<ParaId>;

		/// Maximal number of single parachain heads to keep in the storage.
		///
		/// The setting is there to prevent growing the on-chain state indefinitely. Note
		/// the setting does not relate to parachain block numbers - we will simply keep as much
		/// items in the storage, so it doesn't guarantee any fixed timeframe for heads.
		///
		/// Incautious change of this constant may lead to orphan entries in the runtime storage.
		#[pallet::constant]
		type HeadsToKeep: Get<u32>;

		/// Maximal size (in bytes) of the SCALE-encoded parachain head.
		///
		/// Keep in mind that the size of any tracked parachain header must not exceed this value.
		/// So if you're going to track multiple parachains, one of which is storing large digests
		/// in its headers, you shall choose this maximal value.
		///
		/// There's no mandatory headers in this pallet, so it can't stall if there's some header
		/// that exceeds this bound.
		#[pallet::constant]
		type MaxParaHeadSize: Get<u32>;
	/// Optional pallet owner.
	///
	/// Pallet owner has a right to halt all pallet operations and then resume them. If it is
	/// `None`, then there are no direct ways to halt/resume pallet operations, but other
	/// runtime methods may still be used to do that (i.e. democracy::referendum to update halt
	/// flag directly or call the `halt_operations`).
	#[pallet::storage]
	pub type PalletOwner<T: Config<I>, I: 'static = ()> =
		StorageValue<_, T::AccountId, OptionQuery>;

	/// The current operating mode of the pallet.
	///
	/// Depending on the mode either all, or no transactions will be allowed.
	#[pallet::storage]
	pub type PalletOperatingMode<T: Config<I>, I: 'static = ()> =
		StorageValue<_, BasicOperatingMode, ValueQuery>;

Serban Iorga's avatar
Serban Iorga committed
	/// Parachains info.
	///
Loading full blame...