Add set custom header to Seedling Runtime (#846)

* before adding seedling client side

* seedling runtime compiles

* create seedling spec script added

* seedling node & BaseCallFilter fixes

* update AllPalets

* formatting

* CallFilter + SignedExtra + AccountData fix

* XCM removed

* cleanup

* solo-to-para pallet added & before testing

* fix runtime upgrade method

* soloToPara pallet + set header

* clean up

* clean up 2

* signed extension check sudo added

* fmt + cleanup

* Refac code and fixes

* fmt

* Update pallets/solo-to-para/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update pallets/solo-to-para/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update pallets/solo-to-para/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* small fixes

* OnValidationData used

* small changes

* Update pallets/solo-to-para/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update pallets/solo-to-para/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update pallets/solo-to-para/src/lib.rs

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* OnValidationData replaced by OnSystemEvent

* fmt + cargo fix

* disable-default-bootnodes for seedling script

Co-authored-by: Ricardo Rius <ricardo@parity.io>
Co-authored-by: Ricardo Rius <9488369+riusricardo@users.noreply.github.com>
Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
Ignacio Palacios
2022-01-14 14:21:10 +01:00
committed by GitHub
parent 60f5e0cf2d
commit 6f763b5e71
19 changed files with 285 additions and 45 deletions
@@ -35,6 +35,7 @@ scale-info = { version = "1.0.0", default-features = false, features = ["derive"
serde = { version = "1.0.132", optional = true, features = ["derive"] }
log = { version = "0.4.14", default-features = false }
environmental = { version = "1.1.2", default-features = false }
impl-trait-for-tuples = "0.2.1"
[dev-dependencies]
# Other Dependencies
+22 -6
View File
@@ -30,7 +30,7 @@
use codec::Encode;
use cumulus_primitives_core::{
relay_chain, AbridgedHostConfiguration, ChannelStatus, CollationInfo, DmpMessageHandler,
GetChannelInfo, InboundDownwardMessage, InboundHrmpMessage, MessageSendError, OnValidationData,
GetChannelInfo, InboundDownwardMessage, InboundHrmpMessage, MessageSendError,
OutboundHrmpMessage, ParaId, PersistedValidationData, UpwardMessage, UpwardMessageSender,
XcmpMessageHandler, XcmpMessageSource,
};
@@ -105,7 +105,7 @@ pub mod pallet {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
/// Something which can be notified when the validation data is set.
type OnValidationData: OnValidationData;
type OnSystemEvent: OnSystemEvent;
/// Returns the parachain ID we are running with.
type SelfParaId: Get<ParaId>;
@@ -329,6 +329,7 @@ pub mod pallet {
let validation_code = <PendingValidationCode<T>>::take();
Self::put_parachain_code(&validation_code);
<T::OnSystemEvent as OnSystemEvent>::on_validation_code_applied();
Self::deposit_event(Event::ValidationFunctionApplied(vfp.relay_parent_number));
},
Some(relay_chain::v1::UpgradeGoAhead::Abort) => {
@@ -354,7 +355,7 @@ pub mod pallet {
<RelevantMessagingState<T>>::put(relevant_messaging_state.clone());
<HostConfiguration<T>>::put(host_config);
<T::OnValidationData as OnValidationData>::on_validation_data(&vfp);
<T::OnSystemEvent as OnSystemEvent>::on_validation_data(&vfp);
// TODO: This is more than zero, but will need benchmarking to figure out what.
let mut total_weight = 0;
@@ -397,7 +398,7 @@ pub mod pallet {
code: Vec<u8>,
) -> DispatchResultWithPostInfo {
Self::validate_authorized_upgrade(&code[..])?;
Self::set_code_impl(code)?;
Self::schedule_code_upgrade(code)?;
AuthorizedUpgrade::<T>::kill();
Ok(Pays::No.into())
}
@@ -883,7 +884,7 @@ impl<T: Config> Pallet<T> {
}
/// The implementation of the runtime upgrade functionality for parachains.
fn set_code_impl(validation_function: Vec<u8>) -> DispatchResult {
pub fn schedule_code_upgrade(validation_function: Vec<u8>) -> DispatchResult {
// Ensure that `ValidationData` exists. We do not care about the validation data per se,
// but we do care about the [`UpgradeRestrictionSignal`] which arrives with the same inherent.
ensure!(<ValidationData<T>>::exists(), Error::<T>::ValidationDataNotAvailable,);
@@ -949,7 +950,7 @@ pub struct ParachainSetCode<T>(sp_std::marker::PhantomData<T>);
impl<T: Config> frame_system::SetCode<T> for ParachainSetCode<T> {
fn set_code(code: Vec<u8>) -> DispatchResult {
Pallet::<T>::set_code_impl(code)
Pallet::<T>::schedule_code_upgrade(code)
}
}
@@ -1007,6 +1008,21 @@ pub trait CheckInherents<Block: BlockT> {
) -> frame_support::inherent::CheckInherentsResult;
}
/// Something that should be informed about system related events.
///
/// This includes events like [`on_validation_data`](Self::on_validation_data) that is being
/// called when the parachain inherent is executed that contains the validation data.
/// Or like [`on_validation_code_applied`](Self::on_validation_code_applied) that is called
/// when the new validation is written to the state. This means that
/// from the next block the runtime is being using this new code.
#[impl_trait_for_tuples::impl_for_tuples(30)]
pub trait OnSystemEvent {
/// Called in each blocks once when the validation data is set by the inherent.
fn on_validation_data(data: &PersistedValidationData);
/// Called when the validation code is being applied, aka from the next block on this is the new runtime.
fn on_validation_code_applied();
}
/// Implements [`BlockNumberProvider`] that returns relay chain block number fetched from
/// validation data.
/// NTOE: When validation data is not available (e.g. within on_initialize), 0 will be returned.
@@ -100,7 +100,7 @@ impl frame_system::Config for Test {
}
impl Config for Test {
type Event = Event;
type OnValidationData = ();
type OnSystemEvent = ();
type SelfParaId = ParachainId;
type OutboundXcmpMessageSource = FromThreadLocal;
type DmpMessageHandler = SaveIntoThreadLocal;
+40
View File
@@ -0,0 +1,40 @@
[package]
name = "cumulus-pallet-solo-to-para"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
description = "Adds functionality to migrate from a Solo to a Parachain"
[dependencies]
# Substrate dependencies
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# Cumulus dependencies
cumulus-pallet-parachain-system = { default-features = false, path = "../parachain-system" }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
# Polkadot dependecies
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
# Other Dependencies
codec = { package = "parity-scale-codec", version = "2.3.0", default-features = false, features = ["derive"]}
scale-info = { version = "1.0.0", default-features = false, features = ["derive"] }
[features]
default = [ "std" ]
std = [
"codec/std",
"scale-info/std",
"pallet-sudo/std",
"cumulus-pallet-parachain-system/std",
"cumulus-primitives-core/std",
"polkadot-primitives/std",
"frame-support/std",
"sp-runtime/std",
"sp-std/std",
"frame-system/std",
]
+181
View File
@@ -0,0 +1,181 @@
// Copyright 2022 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/>.
#![cfg_attr(not(feature = "std"), no_std)]
use codec::{Decode, Encode};
use cumulus_pallet_parachain_system as parachain_system;
use frame_support::{dispatch::DispatchResult, pallet_prelude::*, weights::DispatchInfo};
use frame_system::pallet_prelude::*;
pub use pallet::*;
use polkadot_primitives::v1::PersistedValidationData;
use scale_info::TypeInfo;
use sp_runtime::{
traits::{DispatchInfoOf, Dispatchable, SignedExtension},
transaction_validity::{
InvalidTransaction, TransactionLongevity, TransactionPriority, TransactionValidity,
TransactionValidityError, ValidTransaction,
},
};
use sp_std::{prelude::*, vec::Vec};
#[frame_support::pallet]
pub mod pallet {
use super::*;
#[pallet::config]
pub trait Config:
frame_system::Config + parachain_system::Config + pallet_sudo::Config
{
type Event: From<Event> + IsType<<Self as frame_system::Config>::Event>;
}
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
/// In case of a scheduled migration, this storage field contains the custom head data to be applied.
#[pallet::storage]
pub(super) type PendingCustomValidationHeadData<T: Config> =
StorageValue<_, Vec<u8>, OptionQuery>;
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event {
/// The custom validation head data has been scheduled to apply.
CustomValidationHeadDataStored,
/// The custom validation head data was applied as of the contained relay chain block number.
CustomValidationHeadDataApplied,
}
#[pallet::error]
pub enum Error<T> {
/// CustomHeadData is not stored in storage.
NoCustomHeadData,
}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(0)]
pub fn schedule_migration(
origin: OriginFor<T>,
code: Vec<u8>,
head_data: Vec<u8>,
) -> DispatchResult {
ensure_root(origin)?;
parachain_system::Pallet::<T>::schedule_code_upgrade(code)?;
Self::store_pending_custom_validation_head_data(head_data);
Ok(())
}
}
impl<T: Config> Pallet<T> {
/// Set a custom head data that should only be applied when upgradeGoAheadSignal from
/// the Relay Chain is GoAhead
fn store_pending_custom_validation_head_data(head_data: Vec<u8>) {
PendingCustomValidationHeadData::<T>::put(head_data);
Self::deposit_event(Event::CustomValidationHeadDataStored);
}
/// Set pending custom head data as head data that will be returned by `validate_block`. on the relay chain.
fn set_pending_custom_validation_head_data() {
if let Some(head_data) = <PendingCustomValidationHeadData<T>>::take() {
parachain_system::Pallet::<T>::set_custom_validation_head_data(head_data);
Self::deposit_event(Event::CustomValidationHeadDataApplied);
}
}
}
impl<T: Config> parachain_system::OnSystemEvent for Pallet<T> {
fn on_validation_data(_data: &PersistedValidationData) {}
fn on_validation_code_applied() {
crate::Pallet::<T>::set_pending_custom_validation_head_data();
}
}
/// Ensure that signed transactions are only valid if they are signed by root.
#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo, Default)]
#[scale_info(skip_type_params(T))]
pub struct CheckSudo<T: Config + Send + Sync>(sp_std::marker::PhantomData<T>);
impl<T: Config + Send + Sync> CheckSudo<T> {
pub fn new() -> Self {
Self(Default::default())
}
}
impl<T: Config + Send + Sync> sp_std::fmt::Debug for CheckSudo<T> {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "CheckSudo")
}
#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
Ok(())
}
}
impl<T: Config + Send + Sync> SignedExtension for CheckSudo<T>
where
<T as frame_system::Config>::Call: Dispatchable<Info = DispatchInfo>,
{
type AccountId = T::AccountId;
type Call = <T as frame_system::Config>::Call;
type AdditionalSigned = ();
type Pre = ();
const IDENTIFIER: &'static str = "CheckSudo";
fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {
Ok(())
}
fn pre_dispatch(
self,
who: &Self::AccountId,
call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
len: usize,
) -> Result<Self::Pre, TransactionValidityError> {
Ok(self.validate(who, call, info, len).map(|_| ())?)
}
fn validate(
&self,
who: &Self::AccountId,
_call: &Self::Call,
info: &DispatchInfoOf<Self::Call>,
_len: usize,
) -> TransactionValidity {
let root_account = match pallet_sudo::Pallet::<T>::key() {
Some(account) => account,
None => return Err(InvalidTransaction::BadSigner.into()),
};
if *who == root_account {
Ok(ValidTransaction {
priority: info.weight as TransactionPriority,
longevity: TransactionLongevity::max_value(),
propagate: true,
..Default::default()
})
} else {
Err(InvalidTransaction::BadSigner.into())
}
}
}
}
+1 -1
View File
@@ -98,7 +98,7 @@ impl pallet_balances::Config for Test {
impl cumulus_pallet_parachain_system::Config for Test {
type Event = Event;
type OnValidationData = ();
type OnSystemEvent = ();
type SelfParaId = ();
type OutboundXcmpMessageSource = XcmpQueue;
type DmpMessageHandler = ();