Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Implements pallet versioning #7208

Merged
merged 22 commits into from
Oct 21, 2020
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
6 changes: 6 additions & 0 deletions frame/support/procedural/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

mod storage;
mod construct_runtime;
mod pallet_version;
mod transactional;

use proc_macro::TokenStream;
Expand Down Expand Up @@ -325,3 +326,8 @@ pub fn construct_runtime(input: TokenStream) -> TokenStream {
pub fn transactional(attr: TokenStream, input: TokenStream) -> TokenStream {
transactional::transactional(attr, input).unwrap_or_else(|e| e.to_compile_error().into())
}

#[proc_macro]
pub fn crate_to_pallet_version(input: TokenStream) -> TokenStream {
kianenigma marked this conversation as resolved.
Show resolved Hide resolved
pallet_version::crate_to_pallet_version(input).unwrap_or_else(|e| e.to_compile_error()).into()
}
64 changes: 64 additions & 0 deletions frame/support/procedural/src/pallet_version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// This file is part of Substrate.

// Copyright (C) 2020 Parity Technologies (UK) Ltd.
// 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.

//! Implementation of macros related to pallet versioning.

use proc_macro2::{TokenStream, Span};
use syn::{Result, Error};
use std::{env, str::FromStr};
use frame_support_procedural_tools::generate_crate_access_2018;

/// Get the version from the given version environment variable.
///
/// The version is parsed into the requested destination type.
fn get_version<T: FromStr>(version_env: &str) -> std::result::Result<T, ()> {
bkchr marked this conversation as resolved.
Show resolved Hide resolved
let version = env::var(version_env)
.expect(&format!("`{}` is always set by cargo; qed", version_env));

T::from_str(&version).map_err(drop)
}

/// Create an error that will be shown by rustc at the call site of the macro.
fn create_error(message: &str) -> Error {
Error::new(Span::call_site(), message)
}

/// Implementation of the `crate_to_pallet_version!` macro.
pub fn crate_to_pallet_version(input: proc_macro::TokenStream) -> Result<TokenStream> {
if !input.is_empty() {
return Err(create_error("No arguments expected!"))
}

let major_version = get_version::<u16>("CARGO_PKG_VERSION_MAJOR")
.map_err(|_| create_error("Major version needs to fit into `u16`"))?;

let minor_version = get_version::<u8>("CARGO_PKG_VERSION_MINOR")
.map_err(|_| create_error("Minor version needs to fit into `u8`"))?;

let patch_version = get_version::<u8>("CARGO_PKG_VERSION_PATCH")
.map_err(|_| create_error("Patch version needs to fit into `u8`"))?;

let crate_ = generate_crate_access_2018()?;

Ok(quote::quote! {
#crate_::traits::PalletVersion {
major: #major_version,
minor: #minor_version,
patch: #patch_version,
}
})
}
72 changes: 64 additions & 8 deletions frame/support/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ pub use crate::weights::{
PaysFee, PostDispatchInfo, WithPostDispatchInfo,
};
pub use sp_runtime::{traits::Dispatchable, DispatchError};
pub use crate::traits::{CallMetadata, GetCallMetadata, GetCallName, UnfilteredDispatchable};
pub use crate::traits::{
CallMetadata, GetCallMetadata, GetCallName, UnfilteredDispatchable, GetPalletVersion,
};

/// The return typ of a `Dispatchable` in frame. When returned explicitly from
/// a dispatchable function it allows overriding the default `PostDispatchInfo`
Expand Down Expand Up @@ -230,11 +232,11 @@ impl<T> Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {}
/// # #[macro_use]
/// # extern crate frame_support;
/// # use frame_support::dispatch;
/// # use frame_system::{self as system, ensure_signed};
/// # use frame_system::ensure_signed;
/// # pub struct DefaultInstance;
/// # pub trait Instance {}
/// # pub trait Instance: 'static {}
/// # impl Instance for DefaultInstance {}
/// pub trait Trait<I: Instance=DefaultInstance>: system::Trait {}
/// pub trait Trait<I: Instance=DefaultInstance>: frame_system::Trait {}
///
/// decl_module! {
/// pub struct Module<T: Trait<I>, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {
Expand Down Expand Up @@ -1310,6 +1312,7 @@ macro_rules! decl_module {
};

(@impl_on_runtime_upgrade
{ $system:ident }
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
{ $( $other_where_bounds:tt )* }
fn on_runtime_upgrade() -> $return:ty { $( $impl:tt )* }
Expand All @@ -1320,19 +1323,40 @@ macro_rules! decl_module {
{
fn on_runtime_upgrade() -> $return {
$crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!("on_runtime_upgrade"));
{ $( $impl )* }
let result = { $( $impl )* };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if user write return Ok(..); inside the impl block, I think they would expect to have storage version written.
Maybe it is better to wrap it into a closure or something, no ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point


let key = $crate::traits::PalletVersion::storage_key::<
<$trait_instance as $system::Trait>::PalletInfo, Self
>().expect("Every active pallet has a name in the runtime; qed");
let version = $crate::crate_to_pallet_version!();
$crate::storage::unhashed::put(&key, &version);

result
bkchr marked this conversation as resolved.
Show resolved Hide resolved
}
}
};

(@impl_on_runtime_upgrade
{ $system:ident }
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
{ $( $other_where_bounds:tt )* }
) => {
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
$crate::traits::OnRuntimeUpgrade
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
{}
{
fn on_runtime_upgrade() -> $crate::dispatch::Weight {
$crate::sp_tracing::enter_span!($crate::sp_tracing::trace_span!("on_runtime_upgrade"));

let key = $crate::traits::PalletVersion::storage_key::<
<$trait_instance as $system::Trait>::PalletInfo, Self
>().expect("Every active pallet has a name in the runtime; qed");
let version = $crate::crate_to_pallet_version!();
$crate::storage::unhashed::put(&key, &version);

0
apopiak marked this conversation as resolved.
Show resolved Hide resolved
bkchr marked this conversation as resolved.
Show resolved Hide resolved
}
}
};

(@impl_integrity_test
Expand Down Expand Up @@ -1652,6 +1676,7 @@ macro_rules! decl_module {

$crate::decl_module! {
@impl_on_runtime_upgrade
{ $system }
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
{ $( $other_where_bounds )* }
$( $on_runtime_upgrade )*
Expand Down Expand Up @@ -1787,6 +1812,31 @@ macro_rules! decl_module {
}
}

// Bring `GetPalletVersion` into scope to make it easily usable.
pub use $crate::traits::GetPalletVersion as _;
// Implement `GetPalletVersion` for `Module`
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::traits::GetPalletVersion
for $mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
{
fn current_version() -> $crate::traits::PalletVersion {
$crate::crate_to_pallet_version!()
}

fn storage_version() -> $crate::traits::PalletVersion {
let key = $crate::traits::PalletVersion::storage_key::<
<$trait_instance as $system::Trait>::PalletInfo, Self
>().expect("Every active pallet has a name in the runtime; qed");

let value: Option<$crate::traits::PalletVersion> =
$crate::storage::unhashed::get(&key);

match value {
Some(version) => version,
None => $crate::crate_to_pallet_version!(),
apopiak marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

// manual implementation of clone/eq/partialeq because using derive erroneously requires
// clone/eq/partialeq from T.
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Clone
Expand All @@ -1802,6 +1852,7 @@ macro_rules! decl_module {
}
}
}

impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::PartialEq
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
{
Expand All @@ -1824,6 +1875,7 @@ macro_rules! decl_module {
}
}
}

impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Eq
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
{}
Expand Down Expand Up @@ -2365,12 +2417,13 @@ mod tests {
pub mod system {
use codec::{Encode, Decode};

pub trait Trait {
pub trait Trait: 'static {
type AccountId;
type Call;
type BaseCallFilter;
type Origin: crate::traits::OriginTrait<Call = Self::Call>;
type BlockNumber: Into<u32>;
type PalletInfo: crate::traits::PalletInfo;
}

#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
Expand Down Expand Up @@ -2514,6 +2567,7 @@ mod tests {
type Call = OuterCall;
type BaseCallFilter = ();
type BlockNumber = u32;
type PalletInfo = ();
}

#[test]
Expand Down Expand Up @@ -2569,7 +2623,9 @@ mod tests {

#[test]
fn on_runtime_upgrade_should_work() {
assert_eq!(<Module<TraitImpl> as OnRuntimeUpgrade>::on_runtime_upgrade(), 10);
sp_io::TestExternalities::default().execute_with(||
assert_eq!(<Module<TraitImpl> as OnRuntimeUpgrade>::on_runtime_upgrade(), 10)
);
}

#[test]
Expand Down
Loading