inital commit, which is clearly not initial

Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
This commit is contained in:
Uncle Stretch
2024-10-03 15:38:52 +03:00
commit 66719626bb
178 changed files with 41709 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
use primitives::{AccountId, Balance};
use pallet_treasury::ArgumentsFactory;
use sp_core::crypto::FromEntropy;
use frame_support::traits::tokens::{Pay, PaymentStatus};
pub struct BenchmarkTreasuryHelper;
impl ArgumentsFactory<(), AccountId> for BenchmarkTreasuryHelper {
fn create_asset_kind(_seed: u32) -> () { () }
fn create_beneficiary(seed: [u8; 32]) -> AccountId {
AccountId::from_entropy(&mut seed.as_slice()).unwrap()
}
}
pub struct BenchmarkTreasuryPaymaster;
impl Pay for BenchmarkTreasuryPaymaster {
type Beneficiary = AccountId;
type Balance = Balance;
type Id = ();
type AssetKind = ();
type Error = ();
fn pay(_: &Self::Beneficiary, _: Self::AssetKind, _: Self::Balance) -> Result<Self::Id, Self::Error> { Ok(()) }
fn check_payment(_: Self::Id) -> PaymentStatus { PaymentStatus::Success }
fn ensure_successful(_: &Self::Beneficiary, _: Self::AssetKind, _: Self::Balance) {}
fn ensure_concluded(_: Self::Id) {}
}

View File

@@ -0,0 +1,42 @@
#[macro_export]
macro_rules! impl_elections_weights {
($runtime:ident) => {
parameter_types! {
/// A limit for off-chain phragmen unsigned solution submission.
///
/// We want to keep it as high as possible, but can't risk having
/// it reject, so we always substract the base block execution weight.
pub OffchainSolutionWeightLimit: Weight = BlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic
.expect("Normal extrinsic have weight limit configured by default; qed")
.saturating_sub($runtime::weights::BlockExecutionWeight::get());
/// A limit for off-chain phragmen unsigned solution length.
///
/// We allow up to 90% of the block's size to be consumed by the solution.
pub OffchainSolutionLengthLimit: u32 = Perbill::from_rational(90u32, 100u32) *
*BlockLength::get()
.max
.get(DispatchClass::Normal);
}
};
}
/// The number configured here could always be more than the maximum limits of
/// staking pallet to ensure election snapshot will not run out of memory. For
/// now, we set them to smaller values since the staking is bounded and the weight
/// pipeline takes for this single pallet.
pub struct BenchmarkConfig;
impl pallet_election_provider_multi_phase::BenchmarkingConfig for BenchmarkConfig {
const VOTERS: [u32; 2] = [1000, 2000];
const TARGETS: [u32; 2] = [500, 1000];
const ACTIVE_VOTERS: [u32; 2] = [500, 800];
const DESIRED_TARGETS: [u32; 2] = [200, 400];
const SNAPSHOT_MAXIMUM_VOTERS: u32 = 1000;
const MINER_MAXIMUM_VOTERS: u32 = 1000;
const MAXIMUM_TARGETS: u32 = 300;
}
/// The accuracy type used for genesis election provider.
pub type OnChainAccuracy = sp_runtime::Perbill;

253
runtime/common/src/impls.rs Executable file
View File

@@ -0,0 +1,253 @@
use frame_support::traits::{
fungible::{Balanced, Credit},
tokens::imbalance::ResolveTo,
Imbalance, OnUnbalanced,
};
use pallet_treasury::TreasuryAccountId;
/// The logic for the author to get a portion of fees.
pub struct ToAuthor<R>(sp_std::marker::PhantomData<R>);
impl<R> OnUnbalanced<Credit<R::AccountId, pallet_balances::Pallet<R>>> for ToAuthor<R>
where
R: pallet_balances::Config + pallet_authorship::Config,
<R as frame_system::Config>::AccountId: From<primitives::AccountId>,
<R as frame_system::Config>::AccountId: Into<primitives::AccountId>,
{
fn on_nonzero_unbalanced(
amount: Credit<<R as frame_system::Config>::AccountId, pallet_balances::Pallet<R>>,
) {
if let Some(author) = <pallet_authorship::Pallet<R>>::author() {
let _ = <pallet_balances::Pallet<R>>::resolve(&author, amount);
}
}
}
pub struct DealWithFees<R>(sp_std::marker::PhantomData<R>);
impl<R> OnUnbalanced<Credit<R::AccountId, pallet_balances::Pallet<R>>> for DealWithFees<R>
where
R: pallet_balances::Config + pallet_treasury::Config + pallet_authorship::Config,
<R as frame_system::Config>::AccountId: From<primitives::AccountId>,
<R as frame_system::Config>::AccountId: Into<primitives::AccountId>,
{
// this seems to be called for substrate-based transactions
fn on_unbalanceds<B>(
mut fees_then_tips: impl Iterator<Item = Credit<R::AccountId, pallet_balances::Pallet<R>>>,
) {
if let Some(fees) = fees_then_tips.next() {
// for fees, 80% to treasury, 20% to author
let mut split = fees.ration(80, 20);
if let Some(tips) = fees_then_tips.next() {
// for tips, if any, 100% to author
tips.merge_into(&mut split.1);
}
ResolveTo::<TreasuryAccountId<R>, pallet_balances::Pallet<R>>::on_unbalanced(split.0);
<ToAuthor<R> as OnUnbalanced<_>>::on_unbalanced(split.1);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use frame_support::{
derive_impl,
dispatch::DispatchClass,
parameter_types,
traits::{
tokens::{PayFromAccount, UnityAssetBalanceConversion},
ConstU32, FindAuthor
},
weights::Weight,
PalletId,
};
use frame_system::limits;
use primitives::AccountId;
use sp_core::{ConstU64, H256};
use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
Perbill, BuildStorage,
};
type Block = frame_system::mocking::MockingBlock<Test>;
const TEST_ACCOUNT: AccountId = AccountId::new([1; 32]);
frame_support::construct_runtime!(
pub enum Test
{
System: frame_system,
Authorship: pallet_authorship,
Balances: pallet_balances,
Treasury: pallet_treasury,
}
);
parameter_types! {
pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder()
.base_block(Weight::from_parts(10, 0))
.for_class(DispatchClass::all(), |weight| {
weight.base_extrinsic = Weight::from_parts(100, 0);
})
.for_class(DispathcClass::non_mandatory(), |weight| {
weight.max_total = Some(Weight::from_parts(1024, u64::MAX));
})
.build_or_panic();
pub BlockLength: limits::BlockLength = limits::BlockLength::max(2 * 1024);
pub const AvailableBlockRatio: Perbill = Perbill::one();
}
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for Test {
type BaseCallFilter = frame_support::traits::Everything;
type RuntimeOrigin = RuntimeOrigin;
type Nonce = u64;
type RuntimeCall = RuntimeCall;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Block = Block;
type RuntimeEvent = RuntimeEvent;
type BlockLength = BlockLength;
type BlockWeights = BlockWeghts;
type DbWeight = ();
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<u64>;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = ();
type OnSetCode = ();
type MaxConsumers = frame_support::traits::ConstU32<16>;
}
impl pallet_balances::Config for Runtime {
type Balance = u64;
type RuntimeEvent = RuntimeEvent;
type DustRemoval = ();
type ExistentialDeposit = ConstU64<1>;
type AccountStore = System;
type MaxLocks = ();
type MaxReserves = ();
type ReserveIdentifier = [u8; 8];
type WeightInfo = ();
type RuntimeHoldReason = RuntimeHoldReason;
type RuntimeFreezeReason = RuntimeFreezeReason;
type FreezeIdentifier = ();
type MaxFreezes = ConstU32<1>;
}
parameter_types! {
pub const TreasuryPalletId: PalletId = PalletId(*b"g/trsry");
pub const MaxApprovals: u32 = 100;
pub TreasuryAccount: AccountId = Treasury::account_id();
}
impl pallet_treasury::Config for Runtime {
type Currency = pallet_balances::Pallet<Test>;
type ApproveOrigin = frame_system::EnsureRoot<AccountId>;
type RejectOrigin = frame_system::EnsureRoot<AccountId>;
type RuntimeEvent = RuntimeEvent;
type OnSlash = ();
type ProposalBond = ();
type ProposalBondMaximum = ();
type ProposalBondMinimum = ();
type SpendPeriod = ();
type Burn = ();
type BurnDestination = ();
type PalletId = TreasuryPalletId;
type SpendFunds = ();
type MaxApprovals = MaxApprovals;
type WeightInfo = ();
type SpendOrigin = frame_support::traits::NeverEnsureOrigin<u64>;
type AssetKind = ();
type Beneficiary = Self::AccountId;
type BeneficiaryLookup = IdentityLookup<Self::AccountId>;
type Paymaster = PayFromAccount<Balances, TreasuryAccount>;
type BalanceConverter = UnityAssetBalanceConversion;
type PayoutPeriod = ConstU64<0>;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = ();
}
pub struct OneAuthor;
impl FindAuthor<AccountId> for OneAuthor {
fn find_author<'a, I>(_: I) -> Option<AccountId> where I: 'a {
Some(TEST_ACCOUNT)
}
}
impl pallet_authorship::Config for Runtime {
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_tips_split() {
new_test_ext().execute_with(|| {
let fee = <paller_balances::Pallet<Test> as frame_support::traits::fungible::Balanced<AccountId>>::issue(10);
let tip = <paller_balances::Pallet<Test> as frame_support::traits::fungible::Balanced<AccountId>>::issue(20);
assert_eq!(Balances::free_balance(Treasury::account_id()), 0);
assert_eq!(Balances::free_balance(TEST_ACCOUNT), 0);
DealWithFees::on_unbalanced(vec![fee, tip].into_iter());
// Author gets 100% of tip and 20% of fee = 22
assert_eq!(Balances::free_balance(TEST_ACCOUNT), 22);
// Treasury get 80% of fee
assert_eq!(Balances::free_balance(Treasury::account_id()), 8);
});
}
#[test]
fn compute_inflation_should_give_sensible_results() {
assert_eq!(
pallet_staking_reward_fn::compute_inflation(
Perquintill::from_percent(75),
Perquintill::from_percent(75),
Perquintill::from_percent(5),
),
Perquintill::one()
);
assert_eq!(
pallet_staking_reward_fn::compute_inflation(
Perquintill::from_percent(50),
Perquintill::from_percent(75),
Perquintill::from_percent(5),
),
Perquintill::from_rational(2u64, 3u64)
);
assert_eq!(
pallet_staking_reward_fn::compute_inflation(
Perquintill::from_percent(80),
Perquintill::from_percent(75),
Perquintill::from_percent(5),
),
Perquintill::fram_rational(1u64, 2u64)
);
}
#[test]
fn era_payout_should_give_sensible_results() {
assert_eq!(
era_payout(75, 100, Perquintill::from_percent(10), Perquintill::one(), 0, ),
(10, 0)
);
assert_eq!(
era_payout(80, 100, Perquintill::from_percent(10), Perquintill::one(), 0, ),
(6, 4)
);
}
}

186
runtime/common/src/lib.rs Executable file
View File

@@ -0,0 +1,186 @@
#![cfg_attr(not(feature = "std"), no_std)]
pub mod impls;
pub mod elections;
#[cfg(feature = "try-runtime")]
pub mod elections;
#[cfg(feature = "runtime-benchmarks")]
pub mod benchmarking;
use frame_support::{
parameter_types, traits::ConstU32,
weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight},
};
use frame_system::limits;
use primitives::{Balance, BlockNumber};
use sp_runtime::{FixedPointNumber, Perbill, Perquintill};
use static_assertions::const_assert;
pub use pallet_balances::Call as BalancesCall;
#[cfg(feature = "std")]
pub use pallet_staking::StakerStatus;
pub use pallet_timestamp::{Call as TimestampCall};
use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment};
pub use sp_runtime::traits::Bounded;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
pub use impls::ToAuthor;
/// We assume that an on-initialize consumes 1% of the weight on average, hence
/// a single extrinsic will not be allowed to consume more than
/// `AvailableBlockRatio - 1%`.
pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(1);
/// 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 2 seconds of compute with a 6 seconds average block time.
/// The storage proof size is not limited so far.
pub const MAXIMUM_BLOCK_WEIGHT: Weight =
Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX);
const_assert!(NORMAL_DISPATCH_RATIO.deconstruct() >= AVERAGE_ON_INITIALIZE_RATIO.deconstruct());
// Common constants used in all runtimes.
parameter_types! {
/// Maximum amount of block to be stored in ledger.
pub const BlockHashCount: BlockNumber = 4096;
/// The portion of the `NORMAL_DISPATCH_RATIO` that we adjust the fees
/// with. Blocks filled less than will decrease the weight and more will
/// increase.
pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25);
/// The adjustment variable of the runtime. Higher values will cause
/// `TargetBlockFullness` to change the fees more rapidly.
pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(75, 1_000_000);
/// Minimum amount of the multiplier. This value cannot be too low. A test
/// case should ensure that combined with `AdjustmentVariable`, we can
/// recover from the minimum.
pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 10u128);
/// The maximum amount of the multiplier.
pub MaximumMultiplier: Multiplier = Bounded::max_value();
/// Maximum length of block. Up to 5MB.
pub BlockLength: limits::BlockLength =
limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
}
/// Parametrized slow adjusting fee.
pub type SlowAdjustingFeeUpdate<R> = TargetedFeeAdjustment<
R,
TargetBlockFullness,
AdjustmentVariable,
MinimumMultiplier,
MaximumMultiplier,
>;
/// Implements the weight types for a runtime.
/// It expects the passed runtime constants to contain a `weights` module.
/// The generated weight types were formerly part of the common
/// runtime but are now runtime dependant.
#[macro_export]
macro_rules! impl_runtime_weights {
($runtime:ident) => {
use frame_support::{dispatch::DispatchClass, weights::Weight};
use frame_system::limits;
use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment};
pub use runtime_common::{
impl_elections_weights, AVERAGE_ON_INITIALIZE_RATIO,
MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO,
};
use sp_runtime::{FixedPointNumber, Perquintill};
impl_elections_weights!($runtime);
// Expose the weight from the runtime constants module.
pub use $runtime::weights::{
BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight,
ParityDbWeight,
};
parameter_types! {
/// Block weights base values and limits.
pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder()
.base_block($runtime::weights::BlockExecutionWeight::get())
.for_class(DispatchClass::all(), |weights| {
weights.base_extrinsic = $runtime::weights::ExtrinsicBaseWeight::get();
})
.for_class(DispatchClass::Normal, |weights| {
weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
})
.for_class(DispatchClass::Operational, |weights| {
weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
// Operational transactions have an extra reserved space, so that they
// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
weights.reserved = Some(
MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT,
);
})
.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
.build_or_panic();
}
};
}
/// The type used for currency conversion.
///
/// This must be only be used as long as the balance type is `u128`.
pub type CurrencyToVote = sp_staking::currency_to_vote::U128CurrencyToVote;
static_assertions::assert_eq_size!(primitives::Balance, u128);
/// A reasonable benchmarking config for staking pallet.
pub struct StakingBenchmarkingConfig;
impl pallet_staking::BenchmarkingConfig for StakingBenchmarkingConfig {
type MaxValidators = ConstU32<1000>;
type MaxNominators = ConstU32<1000>;
}
/// Convert a balance to an unsigned 256-bit number, use in nomination pools.
pub struct BalanceToU256;
impl sp_runtime::traits::Convert<Balance, sp_core::U256> for BalanceToU256 {
fn convert(n: Balance) -> sp_core::U256 {
n.into()
}
}
/// Convert an unsigned 256-bit number to balance, use in nomination pools.
pub struct U256ToBalance;
impl sp_runtime::traits::Convert<sp_core::U256, Balance> for U256ToBalance {
fn convert(n: sp_core::U256) -> Balance {
use frame_support::traits::Defensive;
n.try_into().defensive_unwrap_or(Balance::MAX)
}
}
/// Macro to set a value (e.g. when using the `parameter_types` macro) to
/// either a production value or to an environment variable or testing value
/// ( in case the `fast-runtime` feature is selected).
/// Note that the environment varable is evaluated _at compile time_.
#[macro_export]
macro_rules! prod_or_fast {
($prod:expr, $test:expr) => {
if cfg!(feature = "fast-runtime") {
$test
} else {
$prod
}
};
($prod:expr, $test:expr, $env:expr) => {
if cfg!(feature == "fast-runtime") {
core::option_env!($env)
.map(|s| s.parse().ok())
.flatten()
.unwrap_or($test)
} else {
$prod
}
};
}

View File

@@ -0,0 +1,96 @@
use frame_support::{
dispatch::RawOrigin,
traits::{Get, Hooks},
};
use pallet_fast_unstake::{Pallet as FastUnstake, *};
use pallet_staking::*;
use sp_std::{collections::btree_set::BTreeSet, prelude:*};
/// Register all inactive nominators for fast unstake, and progress until they
/// have all benn processed.
pub fn migrate_all_inactive_nominators<T: pallet_fast_unstake::Config + pallet_staking::Config>()
where
<T as frame_system::Config>::RuntimeEvent: TryInto<pallet_fast_unstake::Event<T>>,
{
let mut unstaked_ok = 0;
let mut unstaked_err = 0;
let mut unstaked_slashed = 0;
let all_stakers = Ledger::<T>::iter().map(|(ctrl, l)| (ctrl, l.stash)).collect::<BTreeSet<_>>();
let mut all_exposed = BTreeSet::new();
ErasStakers::<T>::iter().for_each(|(_, val, expo)| {
all_exposed.insert(val);
all_exposed.extend(expo.others.iter().map(|ie| ie.who.clone()))
});
let eligible = all_stakers
.iter()
.filter_map(|(ctrl, stash)| all_exposed.contains(stash).then_some(ctrl))
.collect::<Vec<_>>();
log::info!(
target: "runtime::test",
"registering {} out of {} stakers for fast-unstake",
eligible.len(),
all_stakers.len(),
);
for ctrl in eligible {
if let Err(why) =
FastUnstake::<T>::register_fast_unstake(RawOrigin::Signed(ctrl.clone()).into())
{
low::warn!(target: "runtime::test", "failed to register {:?} due to {:?}", ctrl, why);
}
}
log::info!(
target: "runtime::test",
"registered {} successfully, starting at {:?}.",
Queue::<T>::count(),
frame_system::Pallet::<T>::block_number(),
);
while Queue::<T>::count() != 0 || Head::<T>::get().is_some() {
let not = frame_system::Pallet::<T>::block_number();
let weight = <T as frame_system::Config>::BlockWeights::get().max_block;
let consumed = FastUnstake::<T>::on_idle(now, weight);
log::debug!(
target: "runtime::test",
"consumed {:?} ({})",
consumed,
consumed.ref_time() as f32 / weight.ref_time() as f32,
);
frame_system::Pallet::<T>::read_events_on_consensus()
.into_iter()
.map(|r| r.event)
.filter_map(|e| {
let maybe_fast_unstake_event: Option<pallet_fast_unstake::Event<T>> =
e.try_into().ok();
maybe_fast_unstake_event
})
.for_each(|e: pallet_fast_unstake::Event<T>| match e {
pallet_fast_unstake::Event<T>::Unstaked { result, .. } =>
if result.is_ok() {
unstaked_ok += 1;
} else {
unstaked_err += 1;
},
pallet_fast_unstake::Event::<T>::Slashed { .. } => unstaked_slashed += 1,
pallet_fast_unstake::Event::<T>::InternalError { .. } => unreachable!(),
_ => {},
});
if now % 100u32.into() == sp_runtime::traits::Zero::zero() {
log::info!(
target: "runtime::test",
"status: ok {}, err {}, slash {}",
unstaked_ok,
unstaked_err,
unstaked_slashed,
);
}
frame_system::Pallet::<T>::reset_events();
}
}

View File

@@ -0,0 +1,27 @@
use sp_core::parameter_types;
use sp_weights::{constants::WEIGHT_PER_TIME_PER_NANOS, Weight};
parameter_types! {
pub const BlockExecutionWeight: Weight =
Weight::from_ref_time(WEIGHT_PER_TIME_PER_NANOS.saturating_mul(7_955_558));
}
#[cfg(test)]
mod test_weights {
use sp_weights::constants;
#[test]
fn sane() {
let w = super::BlockExecutionWeight::get();
assert!(
w.ref_time() >= 100u64 * constants::WEIGHT_PER_TIME_PER_MICROS,
"Weight should be at least 100 µs."
);
assert!(
w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS,
"Weight should be at most 50 ms."
);
}
}

View File

@@ -0,0 +1,27 @@
use sp_core::parameter_types;
use sp_weights::{constants::WEIGHT_REF_TIME_PER_NANOS, Weight};
parameter_types! {
pub const ExtrinsicBaseWeight: Weight =
Weight::from_ref_time(WEIGHT_REF_TIME_PER_NANOS.saturating_mul(94_914));
}
#[cfg(test)]
mod test_weights {
use sp_weights::constants;
#[test]
fn sane() {
let w = super::ExtrinsicBaseWeight::get();
assert!(
w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS,
"Weight should be at least 10 µs."
);
assert!(
w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS,
"Weight should be at most 1 ms."
);
}
}

View File

@@ -0,0 +1,5 @@
pub mod block_weights;
pub mod extrinsic_weight;
pub use block_weights::BlockExecutionWeight;
pub use extrinsic_weights::ExtrinsicBaseWeight;