Add Statemint (#452)

* Add Statemint

* Versioning.

* Fixes

* Fixes

* Fixes

* Fixes

* Fixes

* Benchmarking

* kick patch (paritytech/statemin#88)

* Westmint Chain Spec (paritytech/statemint#90)

* Tidy the common .toml

* Update weights

* add westmint sudo key comment

* Port consensus stuff

* fix typo

* fix typo ... again

* Recognise Westmint

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>
Co-authored-by: Bastian Köcher <info@kchr.de>
This commit is contained in:
Gavin Wood
2021-06-01 20:31:03 +01:00
committed by GitHub
parent 540e74d33c
commit 9d9ed1bc84
54 changed files with 8419 additions and 227 deletions
@@ -0,0 +1,202 @@
// Copyright (C) 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.
//! Auxillary struct/enums for Statemint runtime.
//! Taken from polkadot/runtime/common (at a21cd64) and adapted for Statemint.
use frame_support::traits::{Currency, Imbalance, OnUnbalanced};
pub type NegativeImbalance<T> = <pallet_balances::Pallet<T> as Currency<<T as frame_system::Config>::AccountId>>::NegativeImbalance;
/// Logic for the author to get a portion of fees.
pub struct ToStakingPot<R>(sp_std::marker::PhantomData<R>);
impl<R> OnUnbalanced<NegativeImbalance<R>> for ToStakingPot<R>
where
R: pallet_balances::Config + pallet_collator_selection::Config,
<R as frame_system::Config>::AccountId: From<polkadot_primitives::v1::AccountId>,
<R as frame_system::Config>::AccountId: Into<polkadot_primitives::v1::AccountId>,
<R as frame_system::Config>::Event: From<pallet_balances::Event<R>>,
{
fn on_nonzero_unbalanced(amount: NegativeImbalance<R>) {
let numeric_amount = amount.peek();
let staking_pot = <pallet_collator_selection::Pallet<R>>::account_id();
<pallet_balances::Pallet<R>>::resolve_creating(
&staking_pot,
amount,
);
<frame_system::Pallet<R>>::deposit_event(pallet_balances::Event::Deposit(
staking_pot,
numeric_amount,
));
}
}
pub struct DealWithFees<R>(sp_std::marker::PhantomData<R>);
impl<R> OnUnbalanced<NegativeImbalance<R>> for DealWithFees<R>
where
R: pallet_balances::Config + pallet_collator_selection::Config,
<R as frame_system::Config>::AccountId: From<polkadot_primitives::v1::AccountId>,
<R as frame_system::Config>::AccountId: Into<polkadot_primitives::v1::AccountId>,
<R as frame_system::Config>::Event: From<pallet_balances::Event<R>>,
{
fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance<R>>) {
if let Some(mut fees) = fees_then_tips.next() {
if let Some(tips) = fees_then_tips.next() {
tips.merge_into(&mut fees);
}
<ToStakingPot<R> as OnUnbalanced<_>>::on_unbalanced(fees);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use frame_support::traits::FindAuthor;
use frame_support::{parameter_types, weights::DispatchClass, PalletId};
use frame_system::{limits, EnsureRoot};
use polkadot_primitives::v1::AccountId;
use sp_core::H256;
use sp_runtime::{
testing::Header,
traits::{BlakeTwo256, IdentityLookup},
Perbill,
};
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
frame_support::construct_runtime!(
pub enum Test where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
CollatorSelection: pallet_collator_selection::{Pallet, Call, Storage, Event<T>},
}
);
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder()
.for_class(DispatchClass::all(), |weight| {
weight.base_extrinsic = 100;
})
.for_class(DispatchClass::non_mandatory(), |weight| {
weight.max_total = Some(1024);
})
.build_or_panic();
pub BlockLength: limits::BlockLength = limits::BlockLength::max(2 * 1024);
pub const AvailableBlockRatio: Perbill = Perbill::one();
}
impl frame_system::Config for Test {
type BaseCallFilter = ();
type Origin = Origin;
type Index = u64;
type BlockNumber = u64;
type Call = Call;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = Event;
type BlockHashCount = BlockHashCount;
type BlockLength = BlockLength;
type BlockWeights = BlockWeights;
type DbWeight = ();
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<u64>;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = ();
type OnSetCode = ();
}
impl pallet_balances::Config for Test {
type Balance = u64;
type Event = Event;
type DustRemoval = ();
type ExistentialDeposit = ();
type AccountStore = System;
type MaxLocks = ();
type WeightInfo = ();
}
pub struct OneAuthor;
impl FindAuthor<AccountId> for OneAuthor {
fn find_author<'a, I>(_: I) -> Option<AccountId>
where
I: 'a,
{
Some(Default::default())
}
}
parameter_types! {
pub const PotId: PalletId = PalletId(*b"PotStake");
pub const MaxCandidates: u32 = 20;
pub const MaxInvulnerables: u32 = 20;
}
impl pallet_collator_selection::Config for Test {
type Event = Event;
type Currency = Balances;
type UpdateOrigin = EnsureRoot<AccountId>;
type PotId = PotId;
type MaxCandidates = MaxCandidates;
type MaxInvulnerables = MaxInvulnerables;
type KickThreshold = ();
type WeightInfo = ();
}
impl pallet_authorship::Config for Test {
type FindAuthor = OneAuthor;
type UncleGenerations = ();
type FilterUncle = ();
type EventHandler = ();
}
pub fn new_test_ext() -> sp_io::TestExternalities {
let mut t = frame_system::GenesisConfig::default()
.build_storage::<Test>()
.unwrap();
// We use default for brevity, but you can configure as desired if needed.
pallet_balances::GenesisConfig::<Test>::default()
.assimilate_storage(&mut t)
.unwrap();
t.into()
}
#[test]
fn test_fees_and_tip_split() {
new_test_ext().execute_with(|| {
let fee = Balances::issue(10);
let tip = Balances::issue(20);
assert_eq!(Balances::free_balance(AccountId::default()), 0);
DealWithFees::on_unbalanceds(vec![fee, tip].into_iter());
// Author gets 100% of tip and 100% of fee = 30
assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 30);
});
}
}
@@ -0,0 +1,87 @@
// Copyright (C) 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.
#![cfg_attr(not(feature = "std"), no_std)]
pub mod impls;
pub use types::*;
pub use constants::*;
/// Common types of statemint and statemine.
mod types {
use sp_runtime::traits::{Verify, IdentifyAccount, BlakeTwo256};
/// An index to a block.
pub type BlockNumber = u32;
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
pub type Signature = sp_runtime::MultiSignature;
/// Some way of identifying an account on the chain. We intentionally make it equivalent
/// to the public key of our transaction signing scheme.
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
/// never know...
pub type AccountIndex = u32;
/// Balance of an account.
pub type Balance = u128;
/// Index of a transaction in the chain.
pub type Index = u32;
/// A hash of some data used by the chain.
pub type Hash = sp_core::H256;
/// Block header type as expected by this runtime.
pub type Header = sp_runtime::generic::Header<BlockNumber, BlakeTwo256>;
/// Digest item type.
pub type DigestItem = sp_runtime::generic::DigestItem<Hash>;
// Aura consensus authority.
pub type AuraId = sp_consensus_aura::sr25519::AuthorityId;
}
/// Common constants of statemint and statemine
mod constants {
use super::types::BlockNumber;
use sp_runtime::Perbill;
use frame_support::weights::{Weight, constants::WEIGHT_PER_SECOND};
/// This determines the average expected block time that we are targeting. Blocks will be
/// produced at a minimum duration defined by `SLOT_DURATION`. `SLOT_DURATION` is picked up by
/// `pallet_timestamp` which is in turn picked up by `pallet_aura` to implement `fn
/// slot_duration()`.
///
/// Change this to adjust the block time.
pub const MILLISECS_PER_BLOCK: u64 = 12000;
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
// Time is measured by number of blocks.
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;
/// We assume that ~5% of the block weight is consumed by `on_initialize` handlers. This is
/// used to limit the maximal weight of a single extrinsic.
pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5);
/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used by
/// Operational extrinsics.
pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
/// We allow for 0.5 seconds of compute with a 6 second average block time.
pub const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND / 2;
}