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

pallet-session: Migrate the historical part to the new pallet macro #9878

Merged
merged 16 commits into from
Nov 17, 2021
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 2 additions & 2 deletions frame/session/benchmarking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

mod mock;

use sp_runtime::traits::{One, StaticLookup};
use sp_std::{prelude::*, vec};

use frame_benchmarking::{benchmarks, impl_benchmark_test_suite};
Expand All @@ -30,12 +31,11 @@ use frame_support::{
traits::{KeyOwnerProofSystem, OnInitialize},
};
use frame_system::RawOrigin;
use pallet_session::{historical::Module as Historical, Pallet as Session, *};
use pallet_session::{historical::Pallet as Historical, Pallet as Session, *};
use pallet_staking::{
benchmarking::create_validator_with_nominators, testing_utils::create_validators,
RewardDestination,
};
use sp_runtime::traits::{One, StaticLookup};

const MAX_VALIDATORS: u32 = 1000;

Expand Down
146 changes: 84 additions & 62 deletions frame/session/src/historical/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,62 +26,84 @@
//! These roots and proofs of inclusion can be generated at any time during the current session.
//! Afterwards, the proofs can be fed to a consensus module when reporting misbehavior.

use super::{Pallet as SessionModule, SessionIndex};
pub mod offchain;
pub mod onchain;
mod shared;

use codec::{Decode, Encode};
use frame_support::{
decl_module, decl_storage, print,
traits::{ValidatorSet, ValidatorSetWithIdentification},
Parameter,
};
use sp_runtime::{
traits::{Convert, OpaqueKeys},
KeyTypeId,
};
use sp_session::{MembershipProof, ValidatorCount};
use sp_staking::SessionIndex;
use sp_std::prelude::*;
use sp_trie::{
trie_types::{TrieDB, TrieDBMut},
MemoryDB, Recorder, Trie, TrieMut, EMPTY_PREFIX,
};

pub mod offchain;
pub mod onchain;
mod shared;
use frame_support::{
print,
traits::{KeyOwnerProofSystem, StorageVersion, ValidatorSet, ValidatorSetWithIdentification},
Parameter,
};

/// Config necessary for the historical module.
pub trait Config: super::Config {
/// Full identification of the validator.
type FullIdentification: Parameter;

/// A conversion from validator ID to full identification.
///
/// This should contain any references to economic actors associated with the
/// validator, since they may be outdated by the time this is queried from a
/// historical trie.
///
/// It must return the identification for the current session index.
type FullIdentificationOf: Convert<Self::ValidatorId, Option<Self::FullIdentification>>;
}
use crate::{self as pallet_session, Pallet as Session};

decl_storage! {
trait Store for Module<T: Config> as Session {
/// Mapping from historical session indices to session-data root hash and validator count.
HistoricalSessions get(fn historical_root):
map hasher(twox_64_concat) SessionIndex => Option<(T::Hash, ValidatorCount)>;
/// The range of historical sessions we store. [first, last)
StoredRange: Option<(SessionIndex, SessionIndex)>;
/// Deprecated.
CachedObsolete:
map hasher(twox_64_concat) SessionIndex
=> Option<Vec<(T::ValidatorId, T::FullIdentification)>>;
pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;

/// The current storage version.
const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
#[pallet::storage_version(STORAGE_VERSION)]
pub struct Pallet<T>(_);

/// Config necessary for the historical pallet.
#[pallet::config]
pub trait Config: pallet_session::Config + frame_system::Config {
/// Full identification of the validator.
type FullIdentification: Parameter;

/// A conversion from validator ID to full identification.
///
/// This should contain any references to economic actors associated with the
/// validator, since they may be outdated by the time this is queried from a
/// historical trie.
///
/// It must return the identification for the current session index.
type FullIdentificationOf: Convert<Self::ValidatorId, Option<Self::FullIdentification>>;
}
}

decl_module! {
pub struct Module<T: Config> for enum Call where origin: T::Origin {}
/// Mapping from historical session indices to session-data root hash and validator count.
#[pallet::storage]
#[pallet::getter(fn historical_root)]
pub type HistoricalSessions<T: Config> =
StorageMap<_, Twox64Concat, SessionIndex, (T::Hash, ValidatorCount), OptionQuery>;

/// The range of historical sessions we store. [first, last)
#[pallet::storage]
pub type StoredRange<T> = StorageValue<_, (SessionIndex, SessionIndex), OptionQuery>;

gui1117 marked this conversation as resolved.
Show resolved Hide resolved
/// Deprecated.
#[pallet::storage]
pub type CachedObsolete<T: Config> = StorageMap<
_,
Twox64Concat,
SessionIndex,
Vec<(T::ValidatorId, T::FullIdentification)>,
OptionQuery,
>;
gui1117 marked this conversation as resolved.
Show resolved Hide resolved
}

impl<T: Config> Module<T> {
impl<T: Config> Pallet<T> {
/// Prune historical stored session roots up to (but not including)
/// `up_to`.
pub fn prune_up_to(up_to: SessionIndex) {
Expand Down Expand Up @@ -109,7 +131,7 @@ impl<T: Config> Module<T> {
}
}

impl<T: Config> ValidatorSet<T::AccountId> for Module<T> {
impl<T: Config> ValidatorSet<T::AccountId> for Pallet<T> {
type ValidatorId = T::ValidatorId;
type ValidatorIdOf = T::ValidatorIdOf;

Expand All @@ -122,15 +144,15 @@ impl<T: Config> ValidatorSet<T::AccountId> for Module<T> {
}
}

impl<T: Config> ValidatorSetWithIdentification<T::AccountId> for Module<T> {
impl<T: Config> ValidatorSetWithIdentification<T::AccountId> for Pallet<T> {
type Identification = T::FullIdentification;
type IdentificationOf = T::FullIdentificationOf;
}

/// Specialization of the crate-level `SessionManager` which returns the set of full identification
/// when creating a new session.
pub trait SessionManager<ValidatorId, FullIdentification>:
crate::SessionManager<ValidatorId>
pallet_session::SessionManager<ValidatorId>
{
/// If there was a validator set change, its returns the set of new validators along with their
/// full identifications.
Expand All @@ -150,7 +172,7 @@ pub struct NoteHistoricalRoot<T, I>(sp_std::marker::PhantomData<(T, I)>);

impl<T: Config, I: SessionManager<T::ValidatorId, T::FullIdentification>> NoteHistoricalRoot<T, I> {
fn do_new_session(new_index: SessionIndex, is_genesis: bool) -> Option<Vec<T::ValidatorId>> {
StoredRange::mutate(|range| {
<StoredRange<T>>::mutate(|range| {
range.get_or_insert_with(|| (new_index, new_index)).1 = new_index + 1;
});

Expand Down Expand Up @@ -183,7 +205,7 @@ impl<T: Config, I: SessionManager<T::ValidatorId, T::FullIdentification>> NoteHi
}
}

impl<T: Config, I> crate::SessionManager<T::ValidatorId> for NoteHistoricalRoot<T, I>
impl<T: Config, I> pallet_session::SessionManager<T::ValidatorId> for NoteHistoricalRoot<T, I>
where
I: SessionManager<T::ValidatorId, T::FullIdentification>,
{
Expand All @@ -207,7 +229,7 @@ where

/// A tuple of the validator's ID and their full identification.
pub type IdentificationTuple<T> =
(<T as crate::Config>::ValidatorId, <T as Config>::FullIdentification);
(<T as pallet_session::Config>::ValidatorId, <T as Config>::FullIdentification);

/// A trie instance for checking and generating proofs.
pub struct ProvingTrie<T: Config> {
Expand All @@ -227,7 +249,7 @@ impl<T: Config> ProvingTrie<T> {
let mut trie = TrieDBMut::new(&mut db, &mut root);
for (i, (validator, full_id)) in validators.into_iter().enumerate() {
let i = i as u32;
let keys = match <SessionModule<T>>::load_keys(&validator) {
let keys = match <Session<T>>::load_keys(&validator) {
None => continue,
Some(k) => k,
};
Expand Down Expand Up @@ -304,15 +326,13 @@ impl<T: Config> ProvingTrie<T> {
}
}

impl<T: Config, D: AsRef<[u8]>> frame_support::traits::KeyOwnerProofSystem<(KeyTypeId, D)>
for Module<T>
{
impl<T: Config, D: AsRef<[u8]>> KeyOwnerProofSystem<(KeyTypeId, D)> for Pallet<T> {
type Proof = MembershipProof;
type IdentificationTuple = IdentificationTuple<T>;

fn prove(key: (KeyTypeId, D)) -> Option<Self::Proof> {
let session = <SessionModule<T>>::current_index();
let validators = <SessionModule<T>>::validators()
let session = <Session<T>>::current_index();
let validators = <Session<T>>::validators()
.into_iter()
.filter_map(|validator| {
T::FullIdentificationOf::convert(validator.clone())
Expand All @@ -335,10 +355,10 @@ impl<T: Config, D: AsRef<[u8]>> frame_support::traits::KeyOwnerProofSystem<(KeyT
fn check_proof(key: (KeyTypeId, D), proof: Self::Proof) -> Option<IdentificationTuple<T>> {
let (id, data) = key;

if proof.session == <SessionModule<T>>::current_index() {
<SessionModule<T>>::key_owner(id, data.as_ref()).and_then(|owner| {
if proof.session == <Session<T>>::current_index() {
<Session<T>>::key_owner(id, data.as_ref()).and_then(|owner| {
T::FullIdentificationOf::convert(owner.clone()).and_then(move |id| {
let count = <SessionModule<T>>::validators().len() as ValidatorCount;
let count = <Session<T>>::validators().len() as ValidatorCount;

if count != proof.validator_count {
return None
Expand Down Expand Up @@ -374,7 +394,7 @@ pub(crate) mod tests {
BasicExternalities,
};

type Historical = Module<Test>;
type Historical = Pallet<Test>;

pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
Expand All @@ -386,7 +406,9 @@ pub(crate) mod tests {
frame_system::Pallet::<Test>::inc_providers(k);
}
});
crate::GenesisConfig::<Test> { keys }.assimilate_storage(&mut t).unwrap();
pallet_session::GenesisConfig::<Test> { keys }
.assimilate_storage(&mut t)
.unwrap();
sp_io::TestExternalities::new(t)
}

Expand Down Expand Up @@ -436,27 +458,27 @@ pub(crate) mod tests {
Session::on_initialize(i);
}

assert_eq!(StoredRange::get(), Some((0, 100)));
assert_eq!(<StoredRange<Test>>::get(), Some((0, 100)));

for i in 0..100 {
assert!(Historical::historical_root(i).is_some())
}

Historical::prune_up_to(10);
assert_eq!(StoredRange::get(), Some((10, 100)));
assert_eq!(<StoredRange<Test>>::get(), Some((10, 100)));

Historical::prune_up_to(9);
assert_eq!(StoredRange::get(), Some((10, 100)));
assert_eq!(<StoredRange<Test>>::get(), Some((10, 100)));

for i in 10..100 {
assert!(Historical::historical_root(i).is_some())
}

Historical::prune_up_to(99);
assert_eq!(StoredRange::get(), Some((99, 100)));
assert_eq!(<StoredRange<Test>>::get(), Some((99, 100)));

Historical::prune_up_to(100);
assert_eq!(StoredRange::get(), None);
assert_eq!(<StoredRange<Test>>::get(), None);

for i in 99..199u64 {
set_next_validators(vec![i]);
Expand All @@ -466,14 +488,14 @@ pub(crate) mod tests {
Session::on_initialize(i);
}

assert_eq!(StoredRange::get(), Some((100, 200)));
assert_eq!(<StoredRange<Test>>::get(), Some((100, 200)));

for i in 100..200 {
assert!(Historical::historical_root(i).is_some())
}

Historical::prune_up_to(9999);
assert_eq!(StoredRange::get(), None);
assert_eq!(<StoredRange<Test>>::get(), None);

for i in 100..200 {
assert!(Historical::historical_root(i).is_none())
Expand Down
4 changes: 2 additions & 2 deletions frame/session/src/historical/offchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ pub fn keep_newest<T: Config>(n_to_keep: usize) {
mod tests {
use super::*;
use crate::{
historical::{onchain, Module},
historical::{onchain, Pallet},
mock::{force_new_session, set_next_validators, Session, System, Test, NEXT_VALIDATORS},
};

Expand All @@ -156,7 +156,7 @@ mod tests {
BasicExternalities,
};

type Historical = Module<Test>;
type Historical = Pallet<Test>;

pub fn new_test_ext() -> sp_io::TestExternalities {
let mut t = frame_system::GenesisConfig::default()
Expand Down
1 change: 1 addition & 0 deletions frame/session/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@

#[cfg(feature = "historical")]
pub mod historical;
pub mod migrations;
#[cfg(test)]
mod mock;
#[cfg(test)]
Expand Down
24 changes: 24 additions & 0 deletions frame/session/src/migrations/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// This file is part of Substrate.

// Copyright (C) 2019-2021 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.

/// Version 1.
///
/// For backward compatability reasons, session historical pallet uses `Session`
/// for storage module prefix before calling this migration.
/// After calling this migration, it will get replaced with own storage identifier.
koushiro marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(feature = "historical")]
pub mod v1;
Loading