difftreelog
feat(collator-selection) initial post-pallet-transmigration commit + minor refactoring
in: master
14 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5780,21 +5780,27 @@
[[package]]
name = "pallet-collator-selection"
version = "3.0.0"
-source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.30#7b1fc0ed107fe42bb7e6a5dfefb586f4c3ae4328"
dependencies = [
"frame-benchmarking",
"frame-support",
"frame-system",
"log",
+ "pallet-aura",
"pallet-authorship",
+ "pallet-balances",
"pallet-session",
+ "pallet-timestamp",
"parity-scale-codec 3.2.1",
"rand 0.8.5",
"scale-info",
"serde",
+ "sp-consensus-aura",
+ "sp-core",
+ "sp-io",
"sp-runtime",
"sp-staking",
"sp-std",
+ "sp-tracing",
]
[[package]]
node/cli/src/chain_spec.rsdiffbeforeafterboth--- a/node/cli/src/chain_spec.rs
+++ b/node/cli/src/chain_spec.rs
@@ -24,7 +24,7 @@
use serde_json::map::Map;
use up_common::types::opaque::*;
-use up_common::constants::CANDIDACY_BOND;
+use up_common::constants::GENESIS_CANDIDACY_BOND;
#[cfg(feature = "unique-runtime")]
pub use unique_runtime as default_runtime;
@@ -192,7 +192,7 @@
.cloned()
.map(|(acc, _)| acc)
.collect(),
- candidacy_bond: CANDIDACY_BOND,
+ candidacy_bond: GENESIS_CANDIDACY_BOND,
..Default::default()
},
session: SessionConfig {
pallets/collator-selection/CHANGELOG.mddiffbeforeafterboth--- /dev/null
+++ b/pallets/collator-selection/CHANGELOG.md
@@ -0,0 +1,5 @@
+## [3.0.0] - 2022-10-28
+
+### Added
+
+ - Entire functionality moved over from cumulus/pallet-collator-selection (v3.0.0).
\ No newline at end of file
pallets/collator-selection/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/pallets/collator-selection/Cargo.toml
@@ -0,0 +1,63 @@
+[package]
+name = "pallet-collator-selection"
+version = "3.0.0"
+description = "Simple staking pallet with a fixed stake."
+authors = ["Unique Network <support@uniquenetwork.io>"]
+edition = "2021"
+homepage = "https://unique.network"
+repository = "https://github.com/UniqueNetwork/unique-chain"
+license = "GPLv3"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
+[dependencies]
+log = { version = "0.4.17", default-features = false }
+codec = { default-features = false, features = ["derive"], package = "parity-scale-codec", version = "3.0.0" }
+rand = { version = "0.8.5", features = ["std_rng"], default-features = false }
+scale-info = { version = "2.2.0", default-features = false, features = ["derive"] }
+serde = { version = "1.0.145", default-features = false }
+
+sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+sp-staking = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+pallet-authorship = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+pallet-session = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+
+frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+
+[dev-dependencies]
+sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" }
+
+[features]
+default = ["std"]
+runtime-benchmarks = [
+ "frame-benchmarking/runtime-benchmarks",
+ "frame-support/runtime-benchmarks",
+ "frame-system/runtime-benchmarks",
+]
+std = [
+ "codec/std",
+ "log/std",
+ "scale-info/std",
+ "rand/std",
+ "sp-runtime/std",
+ "sp-staking/std",
+ "sp-std/std",
+ "frame-support/std",
+ "frame-system/std",
+ "frame-benchmarking/std",
+ "pallet-authorship/std",
+ "pallet-session/std",
+]
+
+try-runtime = [ "frame-support/try-runtime" ]
pallets/collator-selection/src/benchmarking.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/collator-selection/src/benchmarking.rs
@@ -0,0 +1,275 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network 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.
+
+// Unique Network 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 Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+// Original license:
+// 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.
+
+//! Benchmarking setup for pallet-collator-selection
+
+use super::*;
+
+#[allow(unused)]
+use crate::Pallet as CollatorSelection;
+use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, whitelisted_caller};
+use frame_support::{
+ assert_ok,
+ codec::Decode,
+ traits::{Currency, EnsureOrigin, Get},
+};
+use frame_system::{EventRecord, RawOrigin};
+use pallet_authorship::EventHandler;
+use pallet_session::{self as session, SessionManager};
+use sp_std::prelude::*;
+
+pub type BalanceOf<T> =
+ <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
+
+const SEED: u32 = 0;
+
+// TODO: remove if this is given in substrate commit.
+macro_rules! whitelist {
+ ($acc:ident) => {
+ frame_benchmarking::benchmarking::add_to_whitelist(
+ frame_system::Account::<T>::hashed_key_for(&$acc).into(),
+ );
+ };
+}
+
+fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
+ let events = frame_system::Pallet::<T>::events();
+ let system_event: <T as frame_system::Config>::RuntimeEvent = generic_event.into();
+ // compare to the last event record
+ let EventRecord { event, .. } = &events[events.len() - 1];
+ assert_eq!(event, &system_event);
+}
+
+fn create_funded_user<T: Config>(
+ string: &'static str,
+ n: u32,
+ balance_factor: u32,
+) -> T::AccountId {
+ let user = account(string, n, SEED);
+ let balance = T::Currency::minimum_balance() * balance_factor.into();
+ let _ = T::Currency::make_free_balance_be(&user, balance);
+ user
+}
+
+fn keys<T: Config + session::Config>(c: u32) -> <T as session::Config>::Keys {
+ use rand::{RngCore, SeedableRng};
+
+ let keys = {
+ let mut keys = [0u8; 128];
+
+ if c > 0 {
+ let mut rng = rand::rngs::StdRng::seed_from_u64(c as u64);
+ rng.fill_bytes(&mut keys);
+ }
+
+ keys
+ };
+
+ Decode::decode(&mut &keys[..]).unwrap()
+}
+
+fn validator<T: Config + session::Config>(c: u32) -> (T::AccountId, <T as session::Config>::Keys) {
+ (create_funded_user::<T>("candidate", c, 1000), keys::<T>(c))
+}
+
+fn register_validators<T: Config + session::Config>(count: u32) -> Vec<T::AccountId> {
+ let validators = (0..count).map(|c| validator::<T>(c)).collect::<Vec<_>>();
+
+ for (who, keys) in validators.clone() {
+ <session::Pallet<T>>::set_keys(RawOrigin::Signed(who).into(), keys, Vec::new()).unwrap();
+ }
+
+ validators.into_iter().map(|(who, _)| who).collect()
+}
+
+fn register_candidates<T: Config>(count: u32) {
+ let candidates = (0..count).map(|c| account("candidate", c, SEED)).collect::<Vec<_>>();
+ assert!(<CandidacyBond<T>>::get() > 0u32.into(), "Bond cannot be zero!");
+
+ for who in candidates {
+ T::Currency::make_free_balance_be(&who, <CandidacyBond<T>>::get() * 2u32.into());
+ <CollatorSelection<T>>::register_as_candidate(RawOrigin::Signed(who).into()).unwrap();
+ }
+}
+
+benchmarks! {
+ where_clause { where T: pallet_authorship::Config + session::Config }
+
+ set_invulnerables {
+ let b in 1 .. T::MaxInvulnerables::get();
+ let new_invulnerables = register_validators::<T>(b);
+ let origin = T::UpdateOrigin::successful_origin();
+ }: {
+ assert_ok!(
+ <CollatorSelection<T>>::set_invulnerables(origin, new_invulnerables.clone())
+ );
+ }
+ verify {
+ assert_last_event::<T>(Event::NewInvulnerables{invulnerables: new_invulnerables}.into());
+ }
+
+ set_desired_candidates {
+ let max: u32 = 999;
+ let origin = T::UpdateOrigin::successful_origin();
+ }: {
+ assert_ok!(
+ <CollatorSelection<T>>::set_desired_candidates(origin, max.clone())
+ );
+ }
+ verify {
+ assert_last_event::<T>(Event::NewDesiredCandidates{desired_candidates: max}.into());
+ }
+
+ set_candidacy_bond {
+ let bond_amount: BalanceOf<T> = T::Currency::minimum_balance() * 10u32.into();
+ let origin = T::UpdateOrigin::successful_origin();
+ }: {
+ assert_ok!(
+ <CollatorSelection<T>>::set_candidacy_bond(origin, bond_amount.clone())
+ );
+ }
+ verify {
+ assert_last_event::<T>(Event::NewCandidacyBond{bond_amount}.into());
+ }
+
+ // worse case is when we have all the max-candidate slots filled except one, and we fill that
+ // one.
+ register_as_candidate {
+ let c in 1 .. T::MaxCandidates::get();
+
+ <CandidacyBond<T>>::put(T::Currency::minimum_balance());
+ <DesiredCandidates<T>>::put(c + 1);
+
+ register_validators::<T>(c);
+ register_candidates::<T>(c);
+
+ let caller: T::AccountId = whitelisted_caller();
+ let bond: BalanceOf<T> = T::Currency::minimum_balance() * 2u32.into();
+ T::Currency::make_free_balance_be(&caller, bond.clone());
+
+ <session::Pallet<T>>::set_keys(
+ RawOrigin::Signed(caller.clone()).into(),
+ keys::<T>(c + 1),
+ Vec::new()
+ ).unwrap();
+
+ }: _(RawOrigin::Signed(caller.clone()))
+ verify {
+ assert_last_event::<T>(Event::CandidateAdded{account_id: caller, deposit: bond / 2u32.into()}.into());
+ }
+
+ // worse case is the last candidate leaving.
+ leave_intent {
+ let c in (T::MinCandidates::get() + 1) .. T::MaxCandidates::get();
+ <CandidacyBond<T>>::put(T::Currency::minimum_balance());
+ <DesiredCandidates<T>>::put(c);
+
+ register_validators::<T>(c);
+ register_candidates::<T>(c);
+
+ let leaving = <Candidates<T>>::get().last().unwrap().who.clone();
+ whitelist!(leaving);
+ }: _(RawOrigin::Signed(leaving.clone()))
+ verify {
+ assert_last_event::<T>(Event::CandidateRemoved{account_id: leaving}.into());
+ }
+
+ // worse case is paying a non-existing candidate account.
+ note_author {
+ <CandidacyBond<T>>::put(T::Currency::minimum_balance());
+ T::Currency::make_free_balance_be(
+ &<CollatorSelection<T>>::account_id(),
+ T::Currency::minimum_balance() * 4u32.into(),
+ );
+ let author = account("author", 0, SEED);
+ let new_block: T::BlockNumber = 10u32.into();
+
+ frame_system::Pallet::<T>::set_block_number(new_block);
+ assert!(T::Currency::free_balance(&author) == 0u32.into());
+ }: {
+ <CollatorSelection<T> as EventHandler<_, _>>::note_author(author.clone())
+ } verify {
+ assert!(T::Currency::free_balance(&author) > 0u32.into());
+ assert_eq!(frame_system::Pallet::<T>::block_number(), new_block);
+ }
+
+ // worst case for new session.
+ new_session {
+ let r in 1 .. T::MaxCandidates::get();
+ let c in 1 .. T::MaxCandidates::get();
+
+ <CandidacyBond<T>>::put(T::Currency::minimum_balance());
+ <DesiredCandidates<T>>::put(c);
+ frame_system::Pallet::<T>::set_block_number(0u32.into());
+
+ register_validators::<T>(c);
+ register_candidates::<T>(c);
+
+ let new_block: T::BlockNumber = 1800u32.into();
+ let zero_block: T::BlockNumber = 0u32.into();
+ let candidates = <Candidates<T>>::get();
+
+ let non_removals = c.saturating_sub(r);
+
+ for i in 0..c {
+ <LastAuthoredBlock<T>>::insert(candidates[i as usize].who.clone(), zero_block);
+ }
+
+ if non_removals > 0 {
+ for i in 0..non_removals {
+ <LastAuthoredBlock<T>>::insert(candidates[i as usize].who.clone(), new_block);
+ }
+ } else {
+ for i in 0..c {
+ <LastAuthoredBlock<T>>::insert(candidates[i as usize].who.clone(), new_block);
+ }
+ }
+
+ let pre_length = <Candidates<T>>::get().len();
+
+ frame_system::Pallet::<T>::set_block_number(new_block);
+
+ assert!(<Candidates<T>>::get().len() == c as usize);
+ }: {
+ <CollatorSelection<T> as SessionManager<_>>::new_session(0)
+ } verify {
+ if c > r && non_removals >= T::MinCandidates::get() {
+ assert!(<Candidates<T>>::get().len() < pre_length);
+ } else if c > r && non_removals < T::MinCandidates::get() {
+ assert!(<Candidates<T>>::get().len() == T::MinCandidates::get() as usize);
+ } else {
+ assert!(<Candidates<T>>::get().len() == pre_length);
+ }
+ }
+}
+
+impl_benchmark_test_suite!(CollatorSelection, crate::mock::new_test_ext(), crate::mock::Test,);
pallets/collator-selection/src/lib.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/collator-selection/src/lib.rs
@@ -0,0 +1,545 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network 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.
+
+// Unique Network 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 Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+// Original license:
+// 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.
+
+//! Collator Selection pallet.
+//!
+//! A pallet to manage collators in a parachain.
+//!
+//! ## Overview
+//!
+//! The Collator Selection pallet manages the collators of a parachain. **Collation is _not_ a
+//! secure activity** and this pallet does not implement any game-theoretic mechanisms to meet BFT
+//! safety assumptions of the chosen set.
+//!
+//! ## Terminology
+//!
+//! - Collator: A parachain block producer.
+//! - Bond: An amount of `Balance` _reserved_ for candidate registration.
+//! - Invulnerable: An account guaranteed to be in the collator set.
+//!
+//! ## Implementation
+//!
+//! The final `Collators` are aggregated from two individual lists:
+//!
+//! 1. [`Invulnerables`]: a set of collators appointed by governance. These accounts will always be
+//! collators.
+//! 2. [`Candidates`]: these are *candidates to the collation task* and may or may not be elected as
+//! a final collator.
+//!
+//! The current implementation resolves congestion of [`Candidates`] in a first-come-first-serve
+//! manner.
+//!
+//! Candidates will not be allowed to get kicked or leave_intent if the total number of candidates
+//! fall below MinCandidates. This is for potential disaster recovery scenarios.
+//!
+//! ### Rewards
+//!
+//! The Collator Selection pallet maintains an on-chain account (the "Pot"). In each block, the
+//! collator who authored it receives:
+//!
+//! - Half the value of the Pot.
+//! - Half the value of the transaction fees within the block. The other half of the transaction
+//! fees are deposited into the Pot.
+//!
+//! To initiate rewards an ED needs to be transferred to the pot address.
+//!
+//! Note: Eventually the Pot distribution may be modified as discussed in
+//! [this issue](https://github.com/paritytech/statemint/issues/21#issuecomment-810481073).
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+pub use pallet::*;
+
+#[cfg(test)]
+mod mock;
+
+#[cfg(test)]
+mod tests;
+
+#[cfg(feature = "runtime-benchmarks")]
+mod benchmarking;
+pub mod weights;
+
+#[frame_support::pallet]
+pub mod pallet {
+ pub use crate::weights::WeightInfo;
+ use core::ops::Div;
+ use frame_support::{
+ dispatch::{DispatchClass, DispatchResultWithPostInfo},
+ inherent::Vec,
+ pallet_prelude::*,
+ sp_runtime::{
+ traits::{AccountIdConversion, CheckedSub, Saturating, Zero},
+ RuntimeDebug,
+ },
+ traits::{
+ Currency, EnsureOrigin, ExistenceRequirement::KeepAlive, ReservableCurrency,
+ ValidatorRegistration,
+ },
+ BoundedVec, PalletId,
+ };
+ use frame_system::{pallet_prelude::*, Config as SystemConfig};
+ use pallet_session::SessionManager;
+ use sp_runtime::traits::Convert;
+ use sp_staking::SessionIndex;
+
+ type BalanceOf<T> =
+ <<T as Config>::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance;
+
+ /// A convertor from collators id. Since this pallet does not have stash/controller, this is
+ /// just identity.
+ pub struct IdentityCollator;
+ impl<T> sp_runtime::traits::Convert<T, Option<T>> for IdentityCollator {
+ fn convert(t: T) -> Option<T> {
+ Some(t)
+ }
+ }
+
+ /// Configure the pallet by specifying the parameters and types on which it depends.
+ #[pallet::config]
+ pub trait Config: frame_system::Config {
+ /// Overarching event type.
+ type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
+
+ /// The currency mechanism.
+ type Currency: ReservableCurrency<Self::AccountId>;
+
+ /// Origin that can dictate updating parameters of this pallet.
+ type UpdateOrigin: EnsureOrigin<Self::RuntimeOrigin>;
+
+ /// Account Identifier from which the internal Pot is generated.
+ type PotId: Get<PalletId>;
+
+ /// Maximum number of candidates that we should have. This is enforced in code.
+ ///
+ /// This does not take into account the invulnerables.
+ type MaxCandidates: Get<u32>;
+
+ /// Minimum number of candidates that we should have. This is used for disaster recovery.
+ ///
+ /// This does not take into account the invulnerables.
+ type MinCandidates: Get<u32>;
+
+ /// Maximum number of invulnerables. This is enforced in code.
+ type MaxInvulnerables: Get<u32>;
+
+ // Will be kicked if block is not produced in threshold.
+ type KickThreshold: Get<Self::BlockNumber>;
+
+ /// A stable ID for a validator.
+ type ValidatorId: Member + Parameter;
+
+ /// A conversion from account ID to validator ID.
+ ///
+ /// Its cost must be at most one storage read.
+ type ValidatorIdOf: Convert<Self::AccountId, Option<Self::ValidatorId>>;
+
+ /// Validate a user is registered
+ type ValidatorRegistration: ValidatorRegistration<Self::ValidatorId>;
+
+ /// The weight information of this pallet.
+ type WeightInfo: WeightInfo;
+ }
+
+ /// Basic information about a collation candidate.
+ #[derive(
+ PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, scale_info::TypeInfo, MaxEncodedLen,
+ )]
+ pub struct CandidateInfo<AccountId, Balance> {
+ /// Account identifier.
+ pub who: AccountId,
+ /// Reserved deposit.
+ pub deposit: Balance,
+ }
+
+ #[pallet::pallet]
+ #[pallet::generate_store(pub(super) trait Store)]
+ pub struct Pallet<T>(_);
+
+ /// The invulnerable, fixed collators.
+ #[pallet::storage]
+ #[pallet::getter(fn invulnerables)]
+ pub type Invulnerables<T: Config> =
+ StorageValue<_, BoundedVec<T::AccountId, T::MaxInvulnerables>, ValueQuery>;
+
+ /// The (community, limited) collation candidates.
+ #[pallet::storage]
+ #[pallet::getter(fn candidates)]
+ pub type Candidates<T: Config> = StorageValue<
+ _,
+ BoundedVec<CandidateInfo<T::AccountId, BalanceOf<T>>, T::MaxCandidates>,
+ ValueQuery,
+ >;
+
+ /// Last block authored by collator.
+ #[pallet::storage]
+ #[pallet::getter(fn last_authored_block)]
+ pub type LastAuthoredBlock<T: Config> =
+ StorageMap<_, Twox64Concat, T::AccountId, T::BlockNumber, ValueQuery>;
+
+ /// Desired number of candidates.
+ ///
+ /// This should ideally always be less than [`Config::MaxCandidates`] for weights to be correct.
+ #[pallet::storage]
+ #[pallet::getter(fn desired_candidates)]
+ pub type DesiredCandidates<T> = StorageValue<_, u32, ValueQuery>;
+
+ /// Fixed amount to deposit to become a collator.
+ ///
+ /// When a collator calls `leave_intent` they immediately receive the deposit back.
+ #[pallet::storage]
+ #[pallet::getter(fn candidacy_bond)]
+ pub type CandidacyBond<T> = StorageValue<_, BalanceOf<T>, ValueQuery>;
+
+ #[pallet::genesis_config]
+ pub struct GenesisConfig<T: Config> {
+ pub invulnerables: Vec<T::AccountId>,
+ pub candidacy_bond: BalanceOf<T>,
+ pub desired_candidates: u32,
+ }
+
+ #[cfg(feature = "std")]
+ impl<T: Config> Default for GenesisConfig<T> {
+ fn default() -> Self {
+ Self {
+ invulnerables: Default::default(),
+ candidacy_bond: Default::default(),
+ desired_candidates: Default::default(),
+ }
+ }
+ }
+
+ #[pallet::genesis_build]
+ impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
+ fn build(&self) {
+ let duplicate_invulnerables =
+ self.invulnerables.iter().collect::<std::collections::BTreeSet<_>>();
+ assert!(
+ duplicate_invulnerables.len() == self.invulnerables.len(),
+ "duplicate invulnerables in genesis."
+ );
+
+ let bounded_invulnerables =
+ BoundedVec::<_, T::MaxInvulnerables>::try_from(self.invulnerables.clone())
+ .expect("genesis invulnerables are more than T::MaxInvulnerables");
+ assert!(
+ T::MaxCandidates::get() >= self.desired_candidates,
+ "genesis desired_candidates are more than T::MaxCandidates",
+ );
+
+ <DesiredCandidates<T>>::put(&self.desired_candidates);
+ <CandidacyBond<T>>::put(&self.candidacy_bond);
+ <Invulnerables<T>>::put(bounded_invulnerables);
+ }
+ }
+
+ #[pallet::event]
+ #[pallet::generate_deposit(pub(super) fn deposit_event)]
+ pub enum Event<T: Config> {
+ NewInvulnerables { invulnerables: Vec<T::AccountId> },
+ NewDesiredCandidates { desired_candidates: u32 },
+ NewCandidacyBond { bond_amount: BalanceOf<T> },
+ CandidateAdded { account_id: T::AccountId, deposit: BalanceOf<T> },
+ CandidateRemoved { account_id: T::AccountId },
+ }
+
+ // Errors inform users that something went wrong.
+ #[pallet::error]
+ pub enum Error<T> {
+ /// Too many candidates
+ TooManyCandidates,
+ /// Too few candidates
+ TooFewCandidates,
+ /// Unknown error
+ Unknown,
+ /// Permission issue
+ Permission,
+ /// User is already a candidate
+ AlreadyCandidate,
+ /// User is not a candidate
+ NotCandidate,
+ /// Too many invulnerables
+ TooManyInvulnerables,
+ /// User is already an Invulnerable
+ AlreadyInvulnerable,
+ /// Account has no associated validator ID
+ NoAssociatedValidatorId,
+ /// Validator ID is not yet registered
+ ValidatorNotRegistered,
+ }
+
+ #[pallet::hooks]
+ impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
+
+ #[pallet::call]
+ impl<T: Config> Pallet<T> {
+ /// Set the list of invulnerable (fixed) collators.
+ #[pallet::weight(T::WeightInfo::set_invulnerables(new.len() as u32))]
+ pub fn set_invulnerables(
+ origin: OriginFor<T>,
+ new: Vec<T::AccountId>,
+ ) -> DispatchResultWithPostInfo {
+ T::UpdateOrigin::ensure_origin(origin)?;
+ let bounded_invulnerables = BoundedVec::<_, T::MaxInvulnerables>::try_from(new)
+ .map_err(|_| Error::<T>::TooManyInvulnerables)?;
+
+ // check if the invulnerables have associated validator keys before they are set
+ for account_id in bounded_invulnerables.iter() {
+ let validator_key = T::ValidatorIdOf::convert(account_id.clone())
+ .ok_or(Error::<T>::NoAssociatedValidatorId)?;
+ ensure!(
+ T::ValidatorRegistration::is_registered(&validator_key),
+ Error::<T>::ValidatorNotRegistered
+ );
+ }
+
+ <Invulnerables<T>>::put(&bounded_invulnerables);
+ Self::deposit_event(Event::NewInvulnerables {
+ invulnerables: bounded_invulnerables.to_vec(),
+ });
+ Ok(().into())
+ }
+
+ /// Set the ideal number of collators (not including the invulnerables).
+ /// If lowering this number, then the number of running collators could be higher than this figure.
+ /// Aside from that edge case, there should be no other way to have more collators than the desired number.
+ #[pallet::weight(T::WeightInfo::set_desired_candidates())]
+ pub fn set_desired_candidates(
+ origin: OriginFor<T>,
+ max: u32,
+ ) -> DispatchResultWithPostInfo {
+ T::UpdateOrigin::ensure_origin(origin)?;
+ // we trust origin calls, this is just a for more accurate benchmarking
+ if max > T::MaxCandidates::get() {
+ log::warn!("max > T::MaxCandidates; you might need to run benchmarks again");
+ }
+ <DesiredCandidates<T>>::put(&max);
+ Self::deposit_event(Event::NewDesiredCandidates { desired_candidates: max });
+ Ok(().into())
+ }
+
+ /// Set the candidacy bond amount.
+ #[pallet::weight(T::WeightInfo::set_candidacy_bond())]
+ pub fn set_candidacy_bond(
+ origin: OriginFor<T>,
+ bond: BalanceOf<T>,
+ ) -> DispatchResultWithPostInfo {
+ T::UpdateOrigin::ensure_origin(origin)?;
+ <CandidacyBond<T>>::put(&bond);
+ Self::deposit_event(Event::NewCandidacyBond { bond_amount: bond });
+ Ok(().into())
+ }
+
+ /// Register this account as a collator candidate. The account must (a) already have
+ /// registered session keys and (b) be able to reserve the `CandidacyBond`.
+ ///
+ /// This call is not available to `Invulnerable` collators.
+ #[pallet::weight(T::WeightInfo::register_as_candidate(T::MaxCandidates::get()))]
+ pub fn register_as_candidate(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
+ let who = ensure_signed(origin)?;
+
+ // ensure we are below limit.
+ let length = <Candidates<T>>::decode_len().unwrap_or_default();
+ ensure!((length as u32) < Self::desired_candidates(), Error::<T>::TooManyCandidates);
+ ensure!(!Self::invulnerables().contains(&who), Error::<T>::AlreadyInvulnerable);
+
+ let validator_key = T::ValidatorIdOf::convert(who.clone())
+ .ok_or(Error::<T>::NoAssociatedValidatorId)?;
+ ensure!(
+ T::ValidatorRegistration::is_registered(&validator_key),
+ Error::<T>::ValidatorNotRegistered
+ );
+
+ let deposit = Self::candidacy_bond();
+ // First authored block is current block plus kick threshold to handle session delay
+ let incoming = CandidateInfo { who: who.clone(), deposit };
+
+ let current_count =
+ <Candidates<T>>::try_mutate(|candidates| -> Result<usize, DispatchError> {
+ if candidates.iter().any(|candidate| candidate.who == who) {
+ Err(Error::<T>::AlreadyCandidate)?
+ } else {
+ T::Currency::reserve(&who, deposit)?;
+ candidates.try_push(incoming).map_err(|_| Error::<T>::TooManyCandidates)?;
+ <LastAuthoredBlock<T>>::insert(
+ who.clone(),
+ frame_system::Pallet::<T>::block_number() + T::KickThreshold::get(),
+ );
+ Ok(candidates.len())
+ }
+ })?;
+
+ Self::deposit_event(Event::CandidateAdded { account_id: who, deposit });
+ Ok(Some(T::WeightInfo::register_as_candidate(current_count as u32)).into())
+ }
+
+ /// Deregister `origin` as a collator candidate. Note that the collator can only leave on
+ /// session change. The `CandidacyBond` will be unreserved immediately.
+ ///
+ /// This call will fail if the total number of candidates would drop below `MinCandidates`.
+ ///
+ /// This call is not available to `Invulnerable` collators.
+ #[pallet::weight(T::WeightInfo::leave_intent(T::MaxCandidates::get()))]
+ pub fn leave_intent(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
+ let who = ensure_signed(origin)?;
+ ensure!(
+ Self::candidates().len() as u32 > T::MinCandidates::get(),
+ Error::<T>::TooFewCandidates
+ );
+ let current_count = Self::try_remove_candidate(&who)?;
+
+ Ok(Some(T::WeightInfo::leave_intent(current_count as u32)).into())
+ }
+ }
+
+ impl<T: Config> Pallet<T> {
+ /// Get a unique, inaccessible account id from the `PotId`.
+ pub fn account_id() -> T::AccountId {
+ T::PotId::get().into_account_truncating()
+ }
+
+ /// Removes a candidate if they exist and sends them back their deposit
+ fn try_remove_candidate(who: &T::AccountId) -> Result<usize, DispatchError> {
+ let current_count =
+ <Candidates<T>>::try_mutate(|candidates| -> Result<usize, DispatchError> {
+ let index = candidates
+ .iter()
+ .position(|candidate| candidate.who == *who)
+ .ok_or(Error::<T>::NotCandidate)?;
+ let candidate = candidates.remove(index);
+ T::Currency::unreserve(who, candidate.deposit);
+ <LastAuthoredBlock<T>>::remove(who.clone());
+ Ok(candidates.len())
+ })?;
+ Self::deposit_event(Event::CandidateRemoved { account_id: who.clone() });
+ Ok(current_count)
+ }
+
+ /// Assemble the current set of candidates and invulnerables into the next collator set.
+ ///
+ /// This is done on the fly, as frequent as we are told to do so, as the session manager.
+ pub fn assemble_collators(
+ candidates: BoundedVec<T::AccountId, T::MaxCandidates>,
+ ) -> Vec<T::AccountId> {
+ let mut collators = Self::invulnerables().to_vec();
+ collators.extend(candidates);
+ collators
+ }
+
+ /// Kicks out candidates that did not produce a block in the kick threshold
+ /// and refund their deposits.
+ pub fn kick_stale_candidates(
+ candidates: BoundedVec<CandidateInfo<T::AccountId, BalanceOf<T>>, T::MaxCandidates>,
+ ) -> BoundedVec<T::AccountId, T::MaxCandidates> {
+ let now = frame_system::Pallet::<T>::block_number();
+ let kick_threshold = T::KickThreshold::get();
+ candidates
+ .into_iter()
+ .filter_map(|c| {
+ let last_block = <LastAuthoredBlock<T>>::get(c.who.clone());
+ let since_last = now.saturating_sub(last_block);
+ if since_last < kick_threshold ||
+ Self::candidates().len() as u32 <= T::MinCandidates::get()
+ {
+ Some(c.who)
+ } else {
+ let outcome = Self::try_remove_candidate(&c.who);
+ if let Err(why) = outcome {
+ log::warn!("Failed to remove candidate {:?}", why);
+ debug_assert!(false, "failed to remove candidate {:?}", why);
+ }
+ None
+ }
+ })
+ .collect::<Vec<_>>()
+ .try_into()
+ .expect("filter_map operation can't result in a bounded vec larger than its original; qed")
+ }
+ }
+
+ /// Keep track of number of authored blocks per authority, uncles are counted as well since
+ /// they're a valid proof of being online.
+ impl<T: Config + pallet_authorship::Config>
+ pallet_authorship::EventHandler<T::AccountId, T::BlockNumber> for Pallet<T>
+ {
+ fn note_author(author: T::AccountId) {
+ let pot = Self::account_id();
+ // assumes an ED will be sent to pot.
+ let reward = T::Currency::free_balance(&pot)
+ .checked_sub(&T::Currency::minimum_balance())
+ .unwrap_or_else(Zero::zero)
+ .div(2u32.into());
+ // `reward` is half of pot account minus ED, this should never fail.
+ let _success = T::Currency::transfer(&pot, &author, reward, KeepAlive);
+ debug_assert!(_success.is_ok());
+ <LastAuthoredBlock<T>>::insert(author, frame_system::Pallet::<T>::block_number());
+
+ frame_system::Pallet::<T>::register_extra_weight_unchecked(
+ T::WeightInfo::note_author(),
+ DispatchClass::Mandatory,
+ );
+ }
+
+ fn note_uncle(_author: T::AccountId, _age: T::BlockNumber) {
+ //TODO can we ignore this?
+ }
+ }
+
+ /// Play the role of the session manager.
+ impl<T: Config> SessionManager<T::AccountId> for Pallet<T> {
+ fn new_session(index: SessionIndex) -> Option<Vec<T::AccountId>> {
+ log::info!(
+ "assembling new collators for new session {} at #{:?}",
+ index,
+ <frame_system::Pallet<T>>::block_number(),
+ );
+
+ let candidates = Self::candidates();
+ let candidates_len_before = candidates.len();
+ let active_candidates = Self::kick_stale_candidates(candidates);
+ let removed = candidates_len_before - active_candidates.len();
+ let result = Self::assemble_collators(active_candidates);
+
+ frame_system::Pallet::<T>::register_extra_weight_unchecked(
+ T::WeightInfo::new_session(candidates_len_before as u32, removed as u32),
+ DispatchClass::Mandatory,
+ );
+ Some(result)
+ }
+ fn start_session(_: SessionIndex) {
+ // we don't care.
+ }
+ fn end_session(_: SessionIndex) {
+ // we don't care.
+ }
+ }
+}
pallets/collator-selection/src/mock.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/collator-selection/src/mock.rs
@@ -0,0 +1,272 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network 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.
+
+// Unique Network 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 Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+// Original license:
+// 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.
+
+use super::*;
+use crate as collator_selection;
+use frame_support::{
+ ord_parameter_types, parameter_types,
+ traits::{FindAuthor, GenesisBuild, ValidatorRegistration},
+ PalletId,
+};
+use frame_system as system;
+use frame_system::EnsureSignedBy;
+use sp_core::H256;
+use sp_runtime::{
+ testing::{Header, UintAuthorityId},
+ traits::{BlakeTwo256, IdentityLookup, OpaqueKeys},
+ RuntimeAppPublic,
+};
+
+type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
+type Block = frame_system::mocking::MockBlock<Test>;
+
+// Configure a mock runtime to test the pallet.
+frame_support::construct_runtime!(
+ pub enum Test where
+ Block = Block,
+ NodeBlock = Block,
+ UncheckedExtrinsic = UncheckedExtrinsic,
+ {
+ System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
+ Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
+ Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>},
+ Aura: pallet_aura::{Pallet, Storage, Config<T>},
+ Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
+ CollatorSelection: collator_selection::{Pallet, Call, Storage, Event<T>},
+ Authorship: pallet_authorship::{Pallet, Call, Storage, Inherent},
+ }
+);
+
+parameter_types! {
+ pub const BlockHashCount: u64 = 250;
+ pub const SS58Prefix: u8 = 42;
+}
+
+impl system::Config for Test {
+ type BaseCallFilter = frame_support::traits::Everything;
+ type BlockWeights = ();
+ type BlockLength = ();
+ type DbWeight = ();
+ type RuntimeOrigin = RuntimeOrigin;
+ type RuntimeCall = RuntimeCall;
+ type Index = u64;
+ type BlockNumber = u64;
+ type Hash = H256;
+ type Hashing = BlakeTwo256;
+ type AccountId = u64;
+ type Lookup = IdentityLookup<Self::AccountId>;
+ type Header = Header;
+ type RuntimeEvent = RuntimeEvent;
+ type BlockHashCount = BlockHashCount;
+ type Version = ();
+ type PalletInfo = PalletInfo;
+ type AccountData = pallet_balances::AccountData<u64>;
+ type OnNewAccount = ();
+ type OnKilledAccount = ();
+ type SystemWeightInfo = ();
+ type SS58Prefix = SS58Prefix;
+ type OnSetCode = ();
+ type MaxConsumers = frame_support::traits::ConstU32<16>;
+}
+
+parameter_types! {
+ pub const ExistentialDeposit: u64 = 5;
+ pub const MaxReserves: u32 = 50;
+}
+
+impl pallet_balances::Config for Test {
+ type Balance = u64;
+ type RuntimeEvent = RuntimeEvent;
+ type DustRemoval = ();
+ type ExistentialDeposit = ExistentialDeposit;
+ type AccountStore = System;
+ type WeightInfo = ();
+ type MaxLocks = ();
+ type MaxReserves = MaxReserves;
+ type ReserveIdentifier = [u8; 8];
+}
+
+pub struct Author4;
+impl FindAuthor<u64> for Author4 {
+ fn find_author<'a, I>(_digests: I) -> Option<u64>
+ where
+ I: 'a + IntoIterator<Item = (frame_support::ConsensusEngineId, &'a [u8])>,
+ {
+ Some(4)
+ }
+}
+
+impl pallet_authorship::Config for Test {
+ type FindAuthor = Author4;
+ type UncleGenerations = ();
+ type FilterUncle = ();
+ type EventHandler = CollatorSelection;
+}
+
+parameter_types! {
+ pub const MinimumPeriod: u64 = 1;
+}
+
+impl pallet_timestamp::Config for Test {
+ type Moment = u64;
+ type OnTimestampSet = Aura;
+ type MinimumPeriod = MinimumPeriod;
+ type WeightInfo = ();
+}
+
+impl pallet_aura::Config for Test {
+ type AuthorityId = sp_consensus_aura::sr25519::AuthorityId;
+ type MaxAuthorities = MaxAuthorities;
+ type DisabledValidators = ();
+}
+
+sp_runtime::impl_opaque_keys! {
+ pub struct MockSessionKeys {
+ // a key for aura authoring
+ pub aura: UintAuthorityId,
+ }
+}
+
+impl From<UintAuthorityId> for MockSessionKeys {
+ fn from(aura: sp_runtime::testing::UintAuthorityId) -> Self {
+ Self { aura }
+ }
+}
+
+parameter_types! {
+ pub static SessionHandlerCollators: Vec<u64> = Vec::new();
+ pub static SessionChangeBlock: u64 = 0;
+}
+
+pub struct TestSessionHandler;
+impl pallet_session::SessionHandler<u64> for TestSessionHandler {
+ const KEY_TYPE_IDS: &'static [sp_runtime::KeyTypeId] = &[UintAuthorityId::ID];
+ fn on_genesis_session<Ks: OpaqueKeys>(keys: &[(u64, Ks)]) {
+ SessionHandlerCollators::set(keys.into_iter().map(|(a, _)| *a).collect::<Vec<_>>())
+ }
+ fn on_new_session<Ks: OpaqueKeys>(_: bool, keys: &[(u64, Ks)], _: &[(u64, Ks)]) {
+ SessionChangeBlock::set(System::block_number());
+ dbg!(keys.len());
+ SessionHandlerCollators::set(keys.into_iter().map(|(a, _)| *a).collect::<Vec<_>>())
+ }
+ fn on_before_session_ending() {}
+ fn on_disabled(_: u32) {}
+}
+
+parameter_types! {
+ pub const Offset: u64 = 0;
+ pub const Period: u64 = 10;
+}
+
+impl pallet_session::Config for Test {
+ type RuntimeEvent = RuntimeEvent;
+ type ValidatorId = <Self as frame_system::Config>::AccountId;
+ // we don't have stash and controller, thus we don't need the convert as well.
+ type ValidatorIdOf = IdentityCollator;
+ type ShouldEndSession = pallet_session::PeriodicSessions<Period, Offset>;
+ type NextSessionRotation = pallet_session::PeriodicSessions<Period, Offset>;
+ type SessionManager = CollatorSelection;
+ type SessionHandler = TestSessionHandler;
+ type Keys = MockSessionKeys;
+ type WeightInfo = ();
+}
+
+ord_parameter_types! {
+ pub const RootAccount: u64 = 777;
+}
+
+parameter_types! {
+ pub const PotId: PalletId = PalletId(*b"PotStake");
+ pub const MaxCandidates: u32 = 20;
+ pub const MaxInvulnerables: u32 = 20;
+ pub const MinCandidates: u32 = 1;
+ pub const MaxAuthorities: u32 = 100_000;
+}
+
+pub struct IsRegistered;
+impl ValidatorRegistration<u64> for IsRegistered {
+ fn is_registered(id: &u64) -> bool {
+ if *id == 7u64 {
+ false
+ } else {
+ true
+ }
+ }
+}
+
+impl Config for Test {
+ type RuntimeEvent = RuntimeEvent;
+ type Currency = Balances;
+ type UpdateOrigin = EnsureSignedBy<RootAccount, u64>;
+ type PotId = PotId;
+ type MaxCandidates = MaxCandidates;
+ type MinCandidates = MinCandidates;
+ type MaxInvulnerables = MaxInvulnerables;
+ type KickThreshold = Period;
+ type ValidatorId = <Self as frame_system::Config>::AccountId;
+ type ValidatorIdOf = IdentityCollator;
+ type ValidatorRegistration = IsRegistered;
+ type WeightInfo = ();
+}
+
+pub fn new_test_ext() -> sp_io::TestExternalities {
+ sp_tracing::try_init_simple();
+ let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
+ let invulnerables = vec![1, 2];
+
+ let balances = vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100)];
+ let keys = balances
+ .iter()
+ .map(|&(i, _)| (i, i, MockSessionKeys { aura: UintAuthorityId(i) }))
+ .collect::<Vec<_>>();
+ let collator_selection = collator_selection::GenesisConfig::<Test> {
+ desired_candidates: 2,
+ candidacy_bond: 10,
+ invulnerables,
+ };
+ let session = pallet_session::GenesisConfig::<Test> { keys };
+ pallet_balances::GenesisConfig::<Test> { balances }
+ .assimilate_storage(&mut t)
+ .unwrap();
+ // collator selection must be initialized before session.
+ collator_selection.assimilate_storage(&mut t).unwrap();
+ session.assimilate_storage(&mut t).unwrap();
+
+ t.into()
+}
+
+pub fn initialize_to_block(n: u64) {
+ for i in System::block_number() + 1..=n {
+ System::set_block_number(i);
+ <AllPalletsWithSystem as frame_support::traits::OnInitialize<u64>>::on_initialize(i);
+ }
+}
pallets/collator-selection/src/tests.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/collator-selection/src/tests.rs
@@ -0,0 +1,414 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network 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.
+
+// Unique Network 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 Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+// Original license:
+// 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.
+
+use crate as collator_selection;
+use crate::{mock::*, CandidateInfo, Error};
+use frame_support::{
+ assert_noop, assert_ok,
+ traits::{Currency, GenesisBuild, OnInitialize},
+};
+use pallet_balances::Error as BalancesError;
+use sp_runtime::traits::BadOrigin;
+
+#[test]
+fn basic_setup_works() {
+ new_test_ext().execute_with(|| {
+ assert_eq!(CollatorSelection::desired_candidates(), 2);
+ assert_eq!(CollatorSelection::candidacy_bond(), 10);
+
+ assert!(CollatorSelection::candidates().is_empty());
+ assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);
+ });
+}
+
+#[test]
+fn it_should_set_invulnerables() {
+ new_test_ext().execute_with(|| {
+ let new_set = vec![1, 2, 3, 4];
+ assert_ok!(CollatorSelection::set_invulnerables(
+ RuntimeOrigin::signed(RootAccount::get()),
+ new_set.clone()
+ ));
+ assert_eq!(CollatorSelection::invulnerables(), new_set);
+
+ // cannot set with non-root.
+ assert_noop!(
+ CollatorSelection::set_invulnerables(RuntimeOrigin::signed(1), new_set.clone()),
+ BadOrigin
+ );
+
+ // cannot set invulnerables without associated validator keys
+ let invulnerables = vec![7];
+ assert_noop!(
+ CollatorSelection::set_invulnerables(
+ RuntimeOrigin::signed(RootAccount::get()),
+ invulnerables.clone()
+ ),
+ Error::<Test>::ValidatorNotRegistered
+ );
+ });
+}
+
+#[test]
+fn set_desired_candidates_works() {
+ new_test_ext().execute_with(|| {
+ // given
+ assert_eq!(CollatorSelection::desired_candidates(), 2);
+
+ // can set
+ assert_ok!(CollatorSelection::set_desired_candidates(
+ RuntimeOrigin::signed(RootAccount::get()),
+ 7
+ ));
+ assert_eq!(CollatorSelection::desired_candidates(), 7);
+
+ // rejects bad origin
+ assert_noop!(
+ CollatorSelection::set_desired_candidates(RuntimeOrigin::signed(1), 8),
+ BadOrigin
+ );
+ });
+}
+
+#[test]
+fn set_candidacy_bond() {
+ new_test_ext().execute_with(|| {
+ // given
+ assert_eq!(CollatorSelection::candidacy_bond(), 10);
+
+ // can set
+ assert_ok!(CollatorSelection::set_candidacy_bond(
+ RuntimeOrigin::signed(RootAccount::get()),
+ 7
+ ));
+ assert_eq!(CollatorSelection::candidacy_bond(), 7);
+
+ // rejects bad origin.
+ assert_noop!(CollatorSelection::set_candidacy_bond(RuntimeOrigin::signed(1), 8), BadOrigin);
+ });
+}
+
+#[test]
+fn cannot_register_candidate_if_too_many() {
+ new_test_ext().execute_with(|| {
+ // reset desired candidates:
+ <crate::DesiredCandidates<Test>>::put(0);
+
+ // can't accept anyone anymore.
+ assert_noop!(
+ CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)),
+ Error::<Test>::TooManyCandidates,
+ );
+
+ // reset desired candidates:
+ <crate::DesiredCandidates<Test>>::put(1);
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4)));
+
+ // but no more
+ assert_noop!(
+ CollatorSelection::register_as_candidate(RuntimeOrigin::signed(5)),
+ Error::<Test>::TooManyCandidates,
+ );
+ })
+}
+
+#[test]
+fn cannot_unregister_candidate_if_too_few() {
+ new_test_ext().execute_with(|| {
+ // reset desired candidates:
+ <crate::DesiredCandidates<Test>>::put(1);
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4)));
+
+ // can not remove too few
+ assert_noop!(
+ CollatorSelection::leave_intent(RuntimeOrigin::signed(4)),
+ Error::<Test>::TooFewCandidates,
+ );
+ })
+}
+
+#[test]
+fn cannot_register_as_candidate_if_invulnerable() {
+ new_test_ext().execute_with(|| {
+ assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);
+
+ // can't 1 because it is invulnerable.
+ assert_noop!(
+ CollatorSelection::register_as_candidate(RuntimeOrigin::signed(1)),
+ Error::<Test>::AlreadyInvulnerable,
+ );
+ })
+}
+
+#[test]
+fn cannot_register_as_candidate_if_keys_not_registered() {
+ new_test_ext().execute_with(|| {
+ // can't 7 because keys not registered.
+ assert_noop!(
+ CollatorSelection::register_as_candidate(RuntimeOrigin::signed(7)),
+ Error::<Test>::ValidatorNotRegistered
+ );
+ })
+}
+
+#[test]
+fn cannot_register_dupe_candidate() {
+ new_test_ext().execute_with(|| {
+ // can add 3 as candidate
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)));
+ let addition = CandidateInfo { who: 3, deposit: 10 };
+ assert_eq!(CollatorSelection::candidates(), vec![addition]);
+ assert_eq!(CollatorSelection::last_authored_block(3), 10);
+ assert_eq!(Balances::free_balance(3), 90);
+
+ // but no more
+ assert_noop!(
+ CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)),
+ Error::<Test>::AlreadyCandidate,
+ );
+ })
+}
+
+#[test]
+fn cannot_register_as_candidate_if_poor() {
+ new_test_ext().execute_with(|| {
+ assert_eq!(Balances::free_balance(&3), 100);
+ assert_eq!(Balances::free_balance(&33), 0);
+
+ // works
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)));
+
+ // poor
+ assert_noop!(
+ CollatorSelection::register_as_candidate(RuntimeOrigin::signed(33)),
+ BalancesError::<Test>::InsufficientBalance,
+ );
+ });
+}
+
+#[test]
+fn register_as_candidate_works() {
+ new_test_ext().execute_with(|| {
+ // given
+ assert_eq!(CollatorSelection::desired_candidates(), 2);
+ assert_eq!(CollatorSelection::candidacy_bond(), 10);
+ assert_eq!(CollatorSelection::candidates(), Vec::new());
+ assert_eq!(CollatorSelection::invulnerables(), vec![1, 2]);
+
+ // take two endowed, non-invulnerables accounts.
+ assert_eq!(Balances::free_balance(&3), 100);
+ assert_eq!(Balances::free_balance(&4), 100);
+
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)));
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4)));
+
+ assert_eq!(Balances::free_balance(&3), 90);
+ assert_eq!(Balances::free_balance(&4), 90);
+
+ assert_eq!(CollatorSelection::candidates().len(), 2);
+ });
+}
+
+#[test]
+fn leave_intent() {
+ new_test_ext().execute_with(|| {
+ // register a candidate.
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)));
+ assert_eq!(Balances::free_balance(3), 90);
+
+ // register too so can leave above min candidates
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(5)));
+ assert_eq!(Balances::free_balance(5), 90);
+
+ // cannot leave if not candidate.
+ assert_noop!(
+ CollatorSelection::leave_intent(RuntimeOrigin::signed(4)),
+ Error::<Test>::NotCandidate
+ );
+
+ // bond is returned
+ assert_ok!(CollatorSelection::leave_intent(RuntimeOrigin::signed(3)));
+ assert_eq!(Balances::free_balance(3), 100);
+ assert_eq!(CollatorSelection::last_authored_block(3), 0);
+ });
+}
+
+#[test]
+fn authorship_event_handler() {
+ new_test_ext().execute_with(|| {
+ // put 100 in the pot + 5 for ED
+ Balances::make_free_balance_be(&CollatorSelection::account_id(), 105);
+
+ // 4 is the default author.
+ assert_eq!(Balances::free_balance(4), 100);
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4)));
+ // triggers `note_author`
+ Authorship::on_initialize(1);
+
+ let collator = CandidateInfo { who: 4, deposit: 10 };
+
+ assert_eq!(CollatorSelection::candidates(), vec![collator]);
+ assert_eq!(CollatorSelection::last_authored_block(4), 0);
+
+ // half of the pot goes to the collator who's the author (4 in tests).
+ assert_eq!(Balances::free_balance(4), 140);
+ // half + ED stays.
+ assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 55);
+ });
+}
+
+#[test]
+fn fees_edgecases() {
+ new_test_ext().execute_with(|| {
+ // Nothing panics, no reward when no ED in balance
+ Authorship::on_initialize(1);
+ // put some money into the pot at ED
+ Balances::make_free_balance_be(&CollatorSelection::account_id(), 5);
+ // 4 is the default author.
+ assert_eq!(Balances::free_balance(4), 100);
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4)));
+ // triggers `note_author`
+ Authorship::on_initialize(1);
+
+ let collator = CandidateInfo { who: 4, deposit: 10 };
+
+ assert_eq!(CollatorSelection::candidates(), vec![collator]);
+ assert_eq!(CollatorSelection::last_authored_block(4), 0);
+ // Nothing received
+ assert_eq!(Balances::free_balance(4), 90);
+ // all fee stays
+ assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 5);
+ });
+}
+
+#[test]
+fn session_management_works() {
+ new_test_ext().execute_with(|| {
+ initialize_to_block(1);
+
+ assert_eq!(SessionChangeBlock::get(), 0);
+ assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);
+
+ initialize_to_block(4);
+
+ assert_eq!(SessionChangeBlock::get(), 0);
+ assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);
+
+ // add a new collator
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)));
+
+ // session won't see this.
+ assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);
+ // but we have a new candidate.
+ assert_eq!(CollatorSelection::candidates().len(), 1);
+
+ initialize_to_block(10);
+ assert_eq!(SessionChangeBlock::get(), 10);
+ // pallet-session has 1 session delay; current validators are the same.
+ assert_eq!(Session::validators(), vec![1, 2]);
+ // queued ones are changed, and now we have 3.
+ assert_eq!(Session::queued_keys().len(), 3);
+ // session handlers (aura, et. al.) cannot see this yet.
+ assert_eq!(SessionHandlerCollators::get(), vec![1, 2]);
+
+ initialize_to_block(20);
+ assert_eq!(SessionChangeBlock::get(), 20);
+ // changed are now reflected to session handlers.
+ assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3]);
+ });
+}
+
+#[test]
+fn kick_mechanism() {
+ new_test_ext().execute_with(|| {
+ // add a new collator
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)));
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(4)));
+ initialize_to_block(10);
+ assert_eq!(CollatorSelection::candidates().len(), 2);
+ initialize_to_block(20);
+ assert_eq!(SessionChangeBlock::get(), 20);
+ // 4 authored this block, gets to stay 3 was kicked
+ assert_eq!(CollatorSelection::candidates().len(), 1);
+ // 3 will be kicked after 1 session delay
+ assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 4]);
+ let collator = CandidateInfo { who: 4, deposit: 10 };
+ assert_eq!(CollatorSelection::candidates(), vec![collator]);
+ assert_eq!(CollatorSelection::last_authored_block(4), 20);
+ initialize_to_block(30);
+ // 3 gets kicked after 1 session delay
+ assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 4]);
+ // kicked collator gets funds back
+ assert_eq!(Balances::free_balance(3), 100);
+ });
+}
+
+#[test]
+fn should_not_kick_mechanism_too_few() {
+ new_test_ext().execute_with(|| {
+ // add a new collator
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(3)));
+ assert_ok!(CollatorSelection::register_as_candidate(RuntimeOrigin::signed(5)));
+ initialize_to_block(10);
+ assert_eq!(CollatorSelection::candidates().len(), 2);
+ initialize_to_block(20);
+ assert_eq!(SessionChangeBlock::get(), 20);
+ // 4 authored this block, 5 gets to stay too few 3 was kicked
+ assert_eq!(CollatorSelection::candidates().len(), 1);
+ // 3 will be kicked after 1 session delay
+ assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 3, 5]);
+ let collator = CandidateInfo { who: 5, deposit: 10 };
+ assert_eq!(CollatorSelection::candidates(), vec![collator]);
+ assert_eq!(CollatorSelection::last_authored_block(4), 20);
+ initialize_to_block(30);
+ // 3 gets kicked after 1 session delay
+ assert_eq!(SessionHandlerCollators::get(), vec![1, 2, 5]);
+ // kicked collator gets funds back
+ assert_eq!(Balances::free_balance(3), 100);
+ });
+}
+
+#[test]
+#[should_panic = "duplicate invulnerables in genesis."]
+fn cannot_set_genesis_value_twice() {
+ sp_tracing::try_init_simple();
+ let mut t = frame_system::GenesisConfig::default().build_storage::<Test>().unwrap();
+ let invulnerables = vec![1, 1];
+
+ let collator_selection = collator_selection::GenesisConfig::<Test> {
+ desired_candidates: 2,
+ candidacy_bond: 10,
+ invulnerables,
+ };
+ // collator selection must be initialized before session.
+ collator_selection.assimilate_storage(&mut t).unwrap();
+}
pallets/collator-selection/src/weights.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/collator-selection/src/weights.rs
@@ -0,0 +1,148 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network 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.
+
+// Unique Network 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 Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+// Original license:
+// This file is part of Substrate.
+
+// 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.
+
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+
+use frame_support::{
+ traits::Get,
+ weights::{constants::RocksDbWeight, Weight},
+};
+use sp_std::marker::PhantomData;
+
+// The weight info trait for `pallet_collator_selection`.
+pub trait WeightInfo {
+ fn set_invulnerables(_b: u32) -> Weight;
+ fn set_desired_candidates() -> Weight;
+ fn set_candidacy_bond() -> Weight;
+ fn register_as_candidate(_c: u32) -> Weight;
+ fn leave_intent(_c: u32) -> Weight;
+ fn note_author() -> Weight;
+ fn new_session(_c: u32, _r: u32) -> Weight;
+}
+
+/// Weights for pallet_collator_selection using the Substrate node and recommended hardware.
+pub struct SubstrateWeight<T>(PhantomData<T>);
+impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
+ fn set_invulnerables(b: u32) -> Weight {
+ Weight::from_ref_time(18_563_000 as u64)
+ // Standard Error: 0
+ .saturating_add(Weight::from_ref_time(68_000 as u64).saturating_mul(b as u64))
+ .saturating_add(T::DbWeight::get().writes(1 as u64))
+ }
+ fn set_desired_candidates() -> Weight {
+ Weight::from_ref_time(16_363_000 as u64).saturating_add(T::DbWeight::get().writes(1 as u64))
+ }
+ fn set_candidacy_bond() -> Weight {
+ Weight::from_ref_time(16_840_000 as u64).saturating_add(T::DbWeight::get().writes(1 as u64))
+ }
+ fn register_as_candidate(c: u32) -> Weight {
+ Weight::from_ref_time(71_196_000 as u64)
+ // Standard Error: 0
+ .saturating_add(Weight::from_ref_time(198_000 as u64).saturating_mul(c as u64))
+ .saturating_add(T::DbWeight::get().reads(4 as u64))
+ .saturating_add(T::DbWeight::get().writes(2 as u64))
+ }
+ fn leave_intent(c: u32) -> Weight {
+ Weight::from_ref_time(55_336_000 as u64)
+ // Standard Error: 0
+ .saturating_add(Weight::from_ref_time(151_000 as u64).saturating_mul(c as u64))
+ .saturating_add(T::DbWeight::get().reads(1 as u64))
+ .saturating_add(T::DbWeight::get().writes(2 as u64))
+ }
+ fn note_author() -> Weight {
+ Weight::from_ref_time(71_461_000 as u64)
+ .saturating_add(T::DbWeight::get().reads(3 as u64))
+ .saturating_add(T::DbWeight::get().writes(4 as u64))
+ }
+ fn new_session(r: u32, c: u32) -> Weight {
+ Weight::from_ref_time(0 as u64)
+ // Standard Error: 1_010_000
+ .saturating_add(Weight::from_ref_time(109_961_000 as u64).saturating_mul(r as u64))
+ // Standard Error: 1_010_000
+ .saturating_add(Weight::from_ref_time(151_952_000 as u64).saturating_mul(c as u64))
+ .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(r as u64)))
+ .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(c as u64)))
+ .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(r as u64)))
+ .saturating_add(T::DbWeight::get().writes((2 as u64).saturating_mul(c as u64)))
+ }
+}
+
+// For backwards compatibility and tests
+impl WeightInfo for () {
+ fn set_invulnerables(b: u32) -> Weight {
+ Weight::from_ref_time(18_563_000 as u64)
+ // Standard Error: 0
+ .saturating_add(Weight::from_ref_time(68_000 as u64).saturating_mul(b as u64))
+ .saturating_add(RocksDbWeight::get().writes(1 as u64))
+ }
+ fn set_desired_candidates() -> Weight {
+ Weight::from_ref_time(16_363_000 as u64)
+ .saturating_add(RocksDbWeight::get().writes(1 as u64))
+ }
+ fn set_candidacy_bond() -> Weight {
+ Weight::from_ref_time(16_840_000 as u64)
+ .saturating_add(RocksDbWeight::get().writes(1 as u64))
+ }
+ fn register_as_candidate(c: u32) -> Weight {
+ Weight::from_ref_time(71_196_000 as u64)
+ // Standard Error: 0
+ .saturating_add(Weight::from_ref_time(198_000 as u64).saturating_mul(c as u64))
+ .saturating_add(RocksDbWeight::get().reads(4 as u64))
+ .saturating_add(RocksDbWeight::get().writes(2 as u64))
+ }
+ fn leave_intent(c: u32) -> Weight {
+ Weight::from_ref_time(55_336_000 as u64)
+ // Standard Error: 0
+ .saturating_add(Weight::from_ref_time(151_000 as u64).saturating_mul(c as u64))
+ .saturating_add(RocksDbWeight::get().reads(1 as u64))
+ .saturating_add(RocksDbWeight::get().writes(2 as u64))
+ }
+ fn note_author() -> Weight {
+ Weight::from_ref_time(71_461_000 as u64)
+ .saturating_add(RocksDbWeight::get().reads(3 as u64))
+ .saturating_add(RocksDbWeight::get().writes(4 as u64))
+ }
+ fn new_session(r: u32, c: u32) -> Weight {
+ Weight::from_ref_time(0 as u64)
+ // Standard Error: 1_010_000
+ .saturating_add(Weight::from_ref_time(109_961_000 as u64).saturating_mul(r as u64))
+ // Standard Error: 1_010_000
+ .saturating_add(Weight::from_ref_time(151_952_000 as u64).saturating_mul(c as u64))
+ .saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(r as u64)))
+ .saturating_add(RocksDbWeight::get().reads((2 as u64).saturating_mul(c as u64)))
+ .saturating_add(RocksDbWeight::get().writes((2 as u64).saturating_mul(r as u64)))
+ .saturating_add(RocksDbWeight::get().writes((2 as u64).saturating_mul(c as u64)))
+ }
+}
primitives/common/src/constants.rsdiffbeforeafterboth--- a/primitives/common/src/constants.rs
+++ b/primitives/common/src/constants.rs
@@ -44,7 +44,7 @@
/// Minimum balance required to create or keep an account open.
pub const EXISTENTIAL_DEPOSIT: u128 = 0;
/// Amount of Balance reserved for candidate registration.
-pub const CANDIDACY_BOND: u128 = EXISTENTIAL_DEPOSIT;
+pub const GENESIS_CANDIDACY_BOND: u128 = EXISTENTIAL_DEPOSIT;
// Targeting 0.1 UNQ per transfer
pub const WEIGHT_TO_FEE_COEFF: u32 = /*<weight2fee>*/207_163_598/*</weight2fee>*/;
runtime/common/mod.rsdiffbeforeafterboth--- a/runtime/common/mod.rs
+++ b/runtime/common/mod.rs
@@ -188,7 +188,7 @@
RuntimeAppPublic,
};
use pallet_session::SessionManager;
- use up_common::constants::CANDIDACY_BOND;
+ use up_common::constants::GENESIS_CANDIDACY_BOND;
use crate::config::pallets::collator_selection::MaxInvulnerables;
let mut weight = <Runtime as frame_system::Config>::DbWeight::get().reads(1);
@@ -239,7 +239,7 @@
<pallet_collator_selection::Invulnerables<Runtime>>::put(bounded_invulnerables);
<pallet_collator_selection::DesiredCandidates<Runtime>>::put(0);
- <pallet_collator_selection::CandidacyBond<Runtime>>::put(CANDIDACY_BOND);
+ <pallet_collator_selection::CandidacyBond<Runtime>>::put(GENESIS_CANDIDACY_BOND);
let keys = invulnerables
.into_iter()
runtime/opal/Cargo.tomldiffbeforeafterboth--- a/runtime/opal/Cargo.toml
+++ b/runtime/opal/Cargo.toml
@@ -29,7 +29,6 @@
'pallet-evm-migration/runtime-benchmarks',
'pallet-evm-coder-substrate/runtime-benchmarks',
'pallet-balances/runtime-benchmarks',
- "pallet-collator-selection/runtime-benchmarks",
'pallet-timestamp/runtime-benchmarks',
'pallet-common/runtime-benchmarks',
'pallet-structure/runtime-benchmarks',
@@ -69,6 +68,9 @@
'pallet-xcm/try-runtime',
'cumulus-pallet-xcm/try-runtime',
'cumulus-pallet-dmp-queue/try-runtime',
+ "pallet-authorship/try-runtime",
+ "pallet-collator-selection/try-runtime",
+ "pallet-session/try-runtime",
'pallet-inflation/try-runtime',
'pallet-unique/try-runtime',
'pallet-unique-scheduler/try-runtime',
@@ -243,11 +245,6 @@
default-features = false
git = "https://github.com/paritytech/substrate"
branch = "polkadot-v0.9.30"
-
-[dependencies.pallet-collator-selection]
-default-features = false
-git = 'https://github.com/paritytech/cumulus'
-branch = 'polkadot-v0.9.30'
[dependencies.pallet-authorship]
default-features = false
@@ -480,6 +477,7 @@
pallet-inflation = { path = '../../pallets/inflation', default-features = false }
pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
up-data-structs = { path = '../../primitives/data-structs', default-features = false }
+pallet-collator-selection = { default-features = false, path = "../../pallets/collator-selection" }
pallet-configuration = { default-features = false, path = "../../pallets/configuration" }
pallet-common = { default-features = false, path = "../../pallets/common" }
pallet-structure = { default-features = false, path = "../../pallets/structure" }
runtime/quartz/Cargo.tomldiffbeforeafterboth--- a/runtime/quartz/Cargo.toml
+++ b/runtime/quartz/Cargo.toml
@@ -29,7 +29,6 @@
'pallet-evm-migration/runtime-benchmarks',
'pallet-evm-coder-substrate/runtime-benchmarks',
'pallet-balances/runtime-benchmarks',
- "pallet-collator-selection/runtime-benchmarks",
'pallet-timestamp/runtime-benchmarks',
'pallet-common/runtime-benchmarks',
'pallet-structure/runtime-benchmarks',
@@ -68,6 +67,9 @@
'pallet-xcm/try-runtime',
'cumulus-pallet-xcm/try-runtime',
'cumulus-pallet-dmp-queue/try-runtime',
+ "pallet-authorship/try-runtime",
+ "pallet-collator-selection/try-runtime",
+ "pallet-session/try-runtime",
'pallet-inflation/try-runtime',
'pallet-unique/try-runtime',
'pallet-unique-scheduler/try-runtime',
@@ -240,11 +242,6 @@
default-features = false
git = "https://github.com/paritytech/substrate"
branch = "polkadot-v0.9.30"
-
-[dependencies.pallet-collator-selection]
-default-features = false
-git = 'https://github.com/paritytech/cumulus'
-branch = 'polkadot-v0.9.30'
[dependencies.pallet-authorship]
default-features = false
@@ -484,6 +481,7 @@
pallet-inflation = { path = '../../pallets/inflation', default-features = false }
pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }
up-data-structs = { path = '../../primitives/data-structs', default-features = false }
+pallet-collator-selection = { default-features = false, path = "../../pallets/collator-selection" }
pallet-configuration = { default-features = false, path = "../../pallets/configuration" }
pallet-common = { default-features = false, path = "../../pallets/common" }
pallet-structure = { default-features = false, path = "../../pallets/structure" }
runtime/unique/Cargo.tomldiffbeforeafterboth1################################################################################2# Package34cargo-features = ["workspace-inheritance"]56[package]7authors = ['Unique Network <support@uniquenetwork.io>']8build = 'build.rs'9description = 'Unique Runtime'10edition = '2021'11homepage = 'https://unique.network'12license = 'GPLv3'13name = 'unique-runtime'14repository = 'https://github.com/UniqueNetwork/unique-chain'15version = '0.9.30'1617[package.metadata.docs.rs]18targets = ['x86_64-unknown-linux-gnu']1920[features]21default = ['std', 'unique-runtime']22runtime-benchmarks = [23 'hex-literal',24 'frame-benchmarking',25 'frame-support/runtime-benchmarks',26 'frame-system-benchmarking',27 'frame-system/runtime-benchmarks',28 'pallet-ethereum/runtime-benchmarks',29 'pallet-evm-migration/runtime-benchmarks',30 'pallet-evm-coder-substrate/runtime-benchmarks',31 'pallet-balances/runtime-benchmarks',32 "pallet-collator-selection/runtime-benchmarks",33 'pallet-timestamp/runtime-benchmarks',34 'pallet-common/runtime-benchmarks',35 'pallet-structure/runtime-benchmarks',36 'pallet-fungible/runtime-benchmarks',37 'pallet-refungible/runtime-benchmarks',38 'pallet-nonfungible/runtime-benchmarks',39 'pallet-proxy-rmrk-core/runtime-benchmarks',40 'pallet-proxy-rmrk-equip/runtime-benchmarks',41 'pallet-unique/runtime-benchmarks',42 'pallet-foreign-assets/runtime-benchmarks',43 'pallet-inflation/runtime-benchmarks',44 'pallet-unique-scheduler/runtime-benchmarks',45 'pallet-xcm/runtime-benchmarks',46 'sp-runtime/runtime-benchmarks',47 'xcm-builder/runtime-benchmarks',48 'up-data-structs/runtime-benchmarks',49]50try-runtime = [51 'frame-try-runtime',52 'frame-executive/try-runtime',53 'frame-support/try-runtime',54 'frame-system/try-runtime',55 'cumulus-pallet-parachain-system/try-runtime',56 'parachain-info/try-runtime',57 'pallet-aura/try-runtime',58 'cumulus-pallet-aura-ext/try-runtime',59 'pallet-balances/try-runtime',60 'pallet-randomness-collective-flip/try-runtime',61 'pallet-timestamp/try-runtime',62 'pallet-transaction-payment/try-runtime',63 'pallet-treasury/try-runtime',64 'pallet-sudo/try-runtime',65 'orml-vesting/try-runtime',66 'orml-xtokens/try-runtime',67 'orml-tokens/try-runtime',68 'cumulus-pallet-xcmp-queue/try-runtime',69 'pallet-xcm/try-runtime',70 'cumulus-pallet-xcm/try-runtime',71 'cumulus-pallet-dmp-queue/try-runtime',72 'pallet-inflation/try-runtime',73 'pallet-unique/try-runtime',74 'pallet-unique-scheduler/try-runtime',75 'pallet-configuration/try-runtime',76 'pallet-charge-transaction/try-runtime',77 'pallet-common/try-runtime',78 'pallet-fungible/try-runtime',79 'pallet-refungible/try-runtime',80 'pallet-nonfungible/try-runtime',81 'pallet-structure/try-runtime',82 'pallet-proxy-rmrk-core/try-runtime',83 'pallet-proxy-rmrk-equip/try-runtime',84 'pallet-app-promotion/try-runtime',85 'pallet-foreign-assets/try-runtime',86 'pallet-evm/try-runtime',87 'pallet-ethereum/try-runtime',88 'pallet-evm-coder-substrate/try-runtime',89 'pallet-evm-contract-helpers/try-runtime',90 'pallet-evm-transaction-payment/try-runtime',91 'pallet-evm-migration/try-runtime',92]93std = [94 'codec/std',95 'cumulus-pallet-aura-ext/std',96 'cumulus-pallet-parachain-system/std',97 'cumulus-pallet-xcm/std',98 'cumulus-pallet-xcmp-queue/std',99 'cumulus-primitives-core/std',100 'cumulus-primitives-utility/std',101 'frame-try-runtime/std',102 'frame-executive/std',103 'frame-support/std',104 'frame-system/std',105 'frame-system-rpc-runtime-api/std',106 'pallet-aura/std',107 'pallet-balances/std',108 # 'pallet-contracts/std',109 # 'pallet-contracts-primitives/std',110 # 'pallet-contracts-rpc-runtime-api/std',111 # 'pallet-contract-helpers/std',112 "pallet-authorship/std",113 'pallet-collator-selection/std',114 "pallet-session/std",115 'pallet-randomness-collective-flip/std',116 'pallet-sudo/std',117 'pallet-timestamp/std',118 'pallet-transaction-payment/std',119 'pallet-transaction-payment-rpc-runtime-api/std',120 'pallet-treasury/std',121 'pallet-evm/std',122 'pallet-evm-migration/std',123 'pallet-evm-contract-helpers/std',124 'pallet-evm-transaction-payment/std',125 'pallet-evm-coder-substrate/std',126 'pallet-ethereum/std',127 'pallet-base-fee/std',128 'fp-rpc/std',129 'up-rpc/std',130 'app-promotion-rpc/std',131 'fp-evm-mapping/std',132 'fp-self-contained/std',133 'parachain-info/std',134 'serde',135 'pallet-inflation/std',136 'pallet-configuration/std',137 'pallet-common/std',138 'pallet-structure/std',139 'pallet-fungible/std',140 'pallet-refungible/std',141 'pallet-nonfungible/std',142 'pallet-proxy-rmrk-core/std',143 'pallet-proxy-rmrk-equip/std',144 'pallet-unique/std',145 'pallet-unique-scheduler/std',146 'pallet-charge-transaction/std',147 'up-data-structs/std',148 'sp-api/std',149 'sp-block-builder/std',150 "sp-consensus-aura/std",151 'sp-core/std',152 'sp-inherents/std',153 'sp-io/std',154 'sp-offchain/std',155 'sp-runtime/std',156 'sp-session/std',157 'sp-std/std',158 'sp-transaction-pool/std',159 'sp-version/std',160 'xcm/std',161 'xcm-builder/std',162 'xcm-executor/std',163 'up-common/std',164 'rmrk-rpc/std',165 'evm-coder/std',166 'up-sponsorship/std',167168 "orml-vesting/std",169 "orml-tokens/std",170 "orml-xtokens/std",171 "orml-traits/std",172 "pallet-foreign-assets/std",173]174limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']175unique-runtime = []176177refungible = []178scheduler = []179rmrk = []180foreign-assets = []181collator-selection = []182183################################################################################184# Substrate Dependencies185186[dependencies.codec]187default-features = false188features = ['derive']189package = 'parity-scale-codec'190version = '3.1.2'191192[dependencies.frame-benchmarking]193default-features = false194git = "https://github.com/paritytech/substrate"195optional = true196branch = "polkadot-v0.9.30"197198[dependencies.frame-try-runtime]199default-features = false200git = "https://github.com/paritytech/substrate"201optional = true202branch = "polkadot-v0.9.30"203204[dependencies.frame-executive]205default-features = false206git = "https://github.com/paritytech/substrate"207branch = "polkadot-v0.9.30"208209[dependencies.frame-support]210default-features = false211git = "https://github.com/paritytech/substrate"212branch = "polkadot-v0.9.30"213214[dependencies.frame-system]215default-features = false216git = "https://github.com/paritytech/substrate"217branch = "polkadot-v0.9.30"218219[dependencies.frame-system-benchmarking]220default-features = false221git = "https://github.com/paritytech/substrate"222optional = true223branch = "polkadot-v0.9.30"224225[dependencies.frame-system-rpc-runtime-api]226default-features = false227git = "https://github.com/paritytech/substrate"228branch = "polkadot-v0.9.30"229230[dependencies.hex-literal]231optional = true232version = '0.3.3'233234[dependencies.serde]235default-features = false236features = ['derive']237optional = true238version = '1.0.130'239240[dependencies.pallet-aura]241default-features = false242git = "https://github.com/paritytech/substrate"243branch = "polkadot-v0.9.30"244245[dependencies.pallet-collator-selection]246default-features = false247git = 'https://github.com/paritytech/cumulus'248branch = 'polkadot-v0.9.30'249250[dependencies.pallet-authorship]251default-features = false252git = 'https://github.com/paritytech/substrate'253branch = 'polkadot-v0.9.30'254255[dependencies.pallet-session]256default-features = false257git = 'https://github.com/paritytech/substrate'258branch = 'polkadot-v0.9.30'259260[dependencies.pallet-balances]261default-features = false262git = "https://github.com/paritytech/substrate"263branch = "polkadot-v0.9.30"264265# Contracts specific packages266# [dependencies.pallet-contracts]267# git = 'https://github.com/paritytech/substrate'268# default-features = false269# branch = 'master'270# version = '4.0.0-dev'271272# [dependencies.pallet-contracts-primitives]273# git = 'https://github.com/paritytech/substrate'274# default-features = false275# branch = 'master'276# version = '4.0.0-dev'277278# [dependencies.pallet-contracts-rpc-runtime-api]279# git = 'https://github.com/paritytech/substrate'280# default-features = false281# branch = 'master'282# version = '4.0.0-dev'283284[dependencies.pallet-randomness-collective-flip]285default-features = false286git = "https://github.com/paritytech/substrate"287branch = "polkadot-v0.9.30"288289[dependencies.pallet-sudo]290default-features = false291git = "https://github.com/paritytech/substrate"292branch = "polkadot-v0.9.30"293294[dependencies.pallet-timestamp]295default-features = false296git = "https://github.com/paritytech/substrate"297branch = "polkadot-v0.9.30"298299[dependencies.pallet-transaction-payment]300default-features = false301git = "https://github.com/paritytech/substrate"302branch = "polkadot-v0.9.30"303304[dependencies.pallet-transaction-payment-rpc-runtime-api]305default-features = false306git = "https://github.com/paritytech/substrate"307branch = "polkadot-v0.9.30"308309[dependencies.pallet-treasury]310default-features = false311git = "https://github.com/paritytech/substrate"312branch = "polkadot-v0.9.30"313314[dependencies.sp-arithmetic]315default-features = false316git = "https://github.com/paritytech/substrate"317branch = "polkadot-v0.9.30"318319[dependencies.sp-api]320default-features = false321git = "https://github.com/paritytech/substrate"322branch = "polkadot-v0.9.30"323324[dependencies.sp-block-builder]325default-features = false326git = "https://github.com/paritytech/substrate"327branch = "polkadot-v0.9.30"328329[dependencies.sp-core]330default-features = false331git = "https://github.com/paritytech/substrate"332branch = "polkadot-v0.9.30"333334[dependencies.sp-consensus-aura]335default-features = false336git = "https://github.com/paritytech/substrate"337branch = "polkadot-v0.9.30"338339[dependencies.sp-inherents]340default-features = false341git = "https://github.com/paritytech/substrate"342branch = "polkadot-v0.9.30"343344[dependencies.sp-io]345default-features = false346git = "https://github.com/paritytech/substrate"347branch = "polkadot-v0.9.30"348349[dependencies.sp-offchain]350default-features = false351git = "https://github.com/paritytech/substrate"352branch = "polkadot-v0.9.30"353354[dependencies.sp-runtime]355default-features = false356git = "https://github.com/paritytech/substrate"357branch = "polkadot-v0.9.30"358359[dependencies.sp-session]360default-features = false361git = "https://github.com/paritytech/substrate"362branch = "polkadot-v0.9.30"363364[dependencies.sp-std]365default-features = false366git = "https://github.com/paritytech/substrate"367branch = "polkadot-v0.9.30"368369[dependencies.sp-transaction-pool]370default-features = false371git = "https://github.com/paritytech/substrate"372branch = "polkadot-v0.9.30"373374[dependencies.sp-version]375default-features = false376git = "https://github.com/paritytech/substrate"377branch = "polkadot-v0.9.30"378379[dependencies.smallvec]380version = '1.6.1'381382################################################################################383# Cumulus dependencies384385[dependencies.parachain-info]386default-features = false387git = "https://github.com/paritytech/cumulus"388branch = "polkadot-v0.9.30"389390[dependencies.cumulus-pallet-aura-ext]391git = "https://github.com/paritytech/cumulus"392branch = "polkadot-v0.9.30"393default-features = false394395[dependencies.cumulus-pallet-parachain-system]396git = "https://github.com/paritytech/cumulus"397branch = "polkadot-v0.9.30"398default-features = false399400[dependencies.cumulus-primitives-core]401git = "https://github.com/paritytech/cumulus"402branch = "polkadot-v0.9.30"403default-features = false404405[dependencies.cumulus-pallet-xcm]406git = "https://github.com/paritytech/cumulus"407branch = "polkadot-v0.9.30"408default-features = false409410[dependencies.cumulus-pallet-dmp-queue]411git = "https://github.com/paritytech/cumulus"412branch = "polkadot-v0.9.30"413default-features = false414415[dependencies.cumulus-pallet-xcmp-queue]416git = "https://github.com/paritytech/cumulus"417branch = "polkadot-v0.9.30"418default-features = false419420[dependencies.cumulus-primitives-utility]421git = "https://github.com/paritytech/cumulus"422branch = "polkadot-v0.9.30"423default-features = false424425[dependencies.cumulus-primitives-timestamp]426git = "https://github.com/paritytech/cumulus"427branch = "polkadot-v0.9.30"428default-features = false429430################################################################################431# Polkadot dependencies432433[dependencies.polkadot-parachain]434git = "https://github.com/paritytech/polkadot"435branch = "release-v0.9.30"436default-features = false437438[dependencies.xcm]439git = "https://github.com/paritytech/polkadot"440branch = "release-v0.9.30"441default-features = false442443[dependencies.xcm-builder]444git = "https://github.com/paritytech/polkadot"445branch = "release-v0.9.30"446default-features = false447448[dependencies.xcm-executor]449git = "https://github.com/paritytech/polkadot"450branch = "release-v0.9.30"451default-features = false452453[dependencies.pallet-xcm]454git = "https://github.com/paritytech/polkadot"455branch = "release-v0.9.30"456default-features = false457458################################################################################459# local dependencies460461[dependencies]462orml-vesting.workspace = true463orml-xtokens.workspace = true464orml-tokens.workspace = true465orml-traits.workspace = true466467log = { version = "0.4.16", default-features = false }468up-common = { path = "../../primitives/common", default-features = false }469scale-info = { version = "2.0.1", default-features = false, features = [470 "derive",471] }472derivative = "2.2.0"473pallet-unique = { path = '../../pallets/unique', default-features = false }474up-rpc = { path = "../../primitives/rpc", default-features = false }475app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false }476rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false }477pallet-inflation = { path = '../../pallets/inflation', default-features = false }478pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }479up-data-structs = { path = '../../primitives/data-structs', default-features = false }480pallet-configuration = { default-features = false, path = "../../pallets/configuration" }481pallet-common = { default-features = false, path = "../../pallets/common" }482pallet-structure = { default-features = false, path = "../../pallets/structure" }483pallet-fungible = { default-features = false, path = "../../pallets/fungible" }484pallet-refungible = { default-features = false, path = "../../pallets/refungible" }485pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" }486pallet-proxy-rmrk-core = { default-features = false, path = "../../pallets/proxy-rmrk-core", package = "pallet-rmrk-core" }487pallet-proxy-rmrk-equip = { default-features = false, path = "../../pallets/proxy-rmrk-equip", package = "pallet-rmrk-equip" }488pallet-unique-scheduler = { path = '../../pallets/scheduler', default-features = false }489# pallet-contract-helpers = { path = '../pallets/contract-helpers', default-features = false, version = '0.1.0' }490pallet-charge-transaction = { git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.30", package = "pallet-template-transaction-payment", default-features = false, version = "3.0.0" }491pallet-evm-migration = { path = '../../pallets/evm-migration', default-features = false }492pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }493pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }494pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }495pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }496pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }497pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }498fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }499fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }500fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }501evm-coder = { default-features = false, path = '../../crates/evm-coder' }502up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.30' }503pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }504505################################################################################506# Other Dependencies507508impl-trait-for-tuples = "0.2.2"509510################################################################################511# Dev Dependencies512513[dev-dependencies.logtest]514version = "2.0.0"515516################################################################################517# Build Dependencies518519[build-dependencies.substrate-wasm-builder]520git = "https://github.com/paritytech/substrate"521branch = "polkadot-v0.9.30"1################################################################################2# Package34cargo-features = ["workspace-inheritance"]56[package]7authors = ['Unique Network <support@uniquenetwork.io>']8build = 'build.rs'9description = 'Unique Runtime'10edition = '2021'11homepage = 'https://unique.network'12license = 'GPLv3'13name = 'unique-runtime'14repository = 'https://github.com/UniqueNetwork/unique-chain'15version = '0.9.30'1617[package.metadata.docs.rs]18targets = ['x86_64-unknown-linux-gnu']1920[features]21default = ['std', 'unique-runtime']22runtime-benchmarks = [23 'hex-literal',24 'frame-benchmarking',25 'frame-support/runtime-benchmarks',26 'frame-system-benchmarking',27 'frame-system/runtime-benchmarks',28 'pallet-ethereum/runtime-benchmarks',29 'pallet-evm-migration/runtime-benchmarks',30 'pallet-evm-coder-substrate/runtime-benchmarks',31 'pallet-balances/runtime-benchmarks',32 'pallet-timestamp/runtime-benchmarks',33 'pallet-common/runtime-benchmarks',34 'pallet-structure/runtime-benchmarks',35 'pallet-fungible/runtime-benchmarks',36 'pallet-refungible/runtime-benchmarks',37 'pallet-nonfungible/runtime-benchmarks',38 'pallet-proxy-rmrk-core/runtime-benchmarks',39 'pallet-proxy-rmrk-equip/runtime-benchmarks',40 'pallet-unique/runtime-benchmarks',41 'pallet-foreign-assets/runtime-benchmarks',42 'pallet-inflation/runtime-benchmarks',43 'pallet-unique-scheduler/runtime-benchmarks',44 'pallet-xcm/runtime-benchmarks',45 'sp-runtime/runtime-benchmarks',46 'xcm-builder/runtime-benchmarks',47 'up-data-structs/runtime-benchmarks',48]49try-runtime = [50 'frame-try-runtime',51 'frame-executive/try-runtime',52 'frame-support/try-runtime',53 'frame-system/try-runtime',54 'cumulus-pallet-parachain-system/try-runtime',55 'parachain-info/try-runtime',56 'pallet-aura/try-runtime',57 'cumulus-pallet-aura-ext/try-runtime',58 'pallet-balances/try-runtime',59 'pallet-randomness-collective-flip/try-runtime',60 'pallet-timestamp/try-runtime',61 'pallet-transaction-payment/try-runtime',62 'pallet-treasury/try-runtime',63 'pallet-sudo/try-runtime',64 'orml-vesting/try-runtime',65 'orml-xtokens/try-runtime',66 'orml-tokens/try-runtime',67 'cumulus-pallet-xcmp-queue/try-runtime',68 'pallet-xcm/try-runtime',69 'cumulus-pallet-xcm/try-runtime',70 'cumulus-pallet-dmp-queue/try-runtime',71 "pallet-authorship/try-runtime",72 "pallet-collator-selection/try-runtime",73 "pallet-session/try-runtime",74 'pallet-inflation/try-runtime',75 'pallet-unique/try-runtime',76 'pallet-unique-scheduler/try-runtime',77 'pallet-configuration/try-runtime',78 'pallet-charge-transaction/try-runtime',79 'pallet-common/try-runtime',80 'pallet-fungible/try-runtime',81 'pallet-refungible/try-runtime',82 'pallet-nonfungible/try-runtime',83 'pallet-structure/try-runtime',84 'pallet-proxy-rmrk-core/try-runtime',85 'pallet-proxy-rmrk-equip/try-runtime',86 'pallet-app-promotion/try-runtime',87 'pallet-foreign-assets/try-runtime',88 'pallet-evm/try-runtime',89 'pallet-ethereum/try-runtime',90 'pallet-evm-coder-substrate/try-runtime',91 'pallet-evm-contract-helpers/try-runtime',92 'pallet-evm-transaction-payment/try-runtime',93 'pallet-evm-migration/try-runtime',94]95std = [96 'codec/std',97 'cumulus-pallet-aura-ext/std',98 'cumulus-pallet-parachain-system/std',99 'cumulus-pallet-xcm/std',100 'cumulus-pallet-xcmp-queue/std',101 'cumulus-primitives-core/std',102 'cumulus-primitives-utility/std',103 'frame-try-runtime/std',104 'frame-executive/std',105 'frame-support/std',106 'frame-system/std',107 'frame-system-rpc-runtime-api/std',108 'pallet-aura/std',109 'pallet-balances/std',110 # 'pallet-contracts/std',111 # 'pallet-contracts-primitives/std',112 # 'pallet-contracts-rpc-runtime-api/std',113 # 'pallet-contract-helpers/std',114 "pallet-authorship/std",115 'pallet-collator-selection/std',116 "pallet-session/std",117 'pallet-randomness-collective-flip/std',118 'pallet-sudo/std',119 'pallet-timestamp/std',120 'pallet-transaction-payment/std',121 'pallet-transaction-payment-rpc-runtime-api/std',122 'pallet-treasury/std',123 'pallet-evm/std',124 'pallet-evm-migration/std',125 'pallet-evm-contract-helpers/std',126 'pallet-evm-transaction-payment/std',127 'pallet-evm-coder-substrate/std',128 'pallet-ethereum/std',129 'pallet-base-fee/std',130 'fp-rpc/std',131 'up-rpc/std',132 'app-promotion-rpc/std',133 'fp-evm-mapping/std',134 'fp-self-contained/std',135 'parachain-info/std',136 'serde',137 'pallet-inflation/std',138 'pallet-configuration/std',139 'pallet-common/std',140 'pallet-structure/std',141 'pallet-fungible/std',142 'pallet-refungible/std',143 'pallet-nonfungible/std',144 'pallet-proxy-rmrk-core/std',145 'pallet-proxy-rmrk-equip/std',146 'pallet-unique/std',147 'pallet-unique-scheduler/std',148 'pallet-charge-transaction/std',149 'up-data-structs/std',150 'sp-api/std',151 'sp-block-builder/std',152 "sp-consensus-aura/std",153 'sp-core/std',154 'sp-inherents/std',155 'sp-io/std',156 'sp-offchain/std',157 'sp-runtime/std',158 'sp-session/std',159 'sp-std/std',160 'sp-transaction-pool/std',161 'sp-version/std',162 'xcm/std',163 'xcm-builder/std',164 'xcm-executor/std',165 'up-common/std',166 'rmrk-rpc/std',167 'evm-coder/std',168 'up-sponsorship/std',169170 "orml-vesting/std",171 "orml-tokens/std",172 "orml-xtokens/std",173 "orml-traits/std",174 "pallet-foreign-assets/std",175]176limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']177unique-runtime = []178179refungible = []180scheduler = []181rmrk = []182foreign-assets = []183collator-selection = []184185################################################################################186# Substrate Dependencies187188[dependencies.codec]189default-features = false190features = ['derive']191package = 'parity-scale-codec'192version = '3.1.2'193194[dependencies.frame-benchmarking]195default-features = false196git = "https://github.com/paritytech/substrate"197optional = true198branch = "polkadot-v0.9.30"199200[dependencies.frame-try-runtime]201default-features = false202git = "https://github.com/paritytech/substrate"203optional = true204branch = "polkadot-v0.9.30"205206[dependencies.frame-executive]207default-features = false208git = "https://github.com/paritytech/substrate"209branch = "polkadot-v0.9.30"210211[dependencies.frame-support]212default-features = false213git = "https://github.com/paritytech/substrate"214branch = "polkadot-v0.9.30"215216[dependencies.frame-system]217default-features = false218git = "https://github.com/paritytech/substrate"219branch = "polkadot-v0.9.30"220221[dependencies.frame-system-benchmarking]222default-features = false223git = "https://github.com/paritytech/substrate"224optional = true225branch = "polkadot-v0.9.30"226227[dependencies.frame-system-rpc-runtime-api]228default-features = false229git = "https://github.com/paritytech/substrate"230branch = "polkadot-v0.9.30"231232[dependencies.hex-literal]233optional = true234version = '0.3.3'235236[dependencies.serde]237default-features = false238features = ['derive']239optional = true240version = '1.0.130'241242[dependencies.pallet-aura]243default-features = false244git = "https://github.com/paritytech/substrate"245branch = "polkadot-v0.9.30"246247[dependencies.pallet-authorship]248default-features = false249git = 'https://github.com/paritytech/substrate'250branch = 'polkadot-v0.9.30'251252[dependencies.pallet-session]253default-features = false254git = 'https://github.com/paritytech/substrate'255branch = 'polkadot-v0.9.30'256257[dependencies.pallet-balances]258default-features = false259git = "https://github.com/paritytech/substrate"260branch = "polkadot-v0.9.30"261262# Contracts specific packages263# [dependencies.pallet-contracts]264# git = 'https://github.com/paritytech/substrate'265# default-features = false266# branch = 'master'267# version = '4.0.0-dev'268269# [dependencies.pallet-contracts-primitives]270# git = 'https://github.com/paritytech/substrate'271# default-features = false272# branch = 'master'273# version = '4.0.0-dev'274275# [dependencies.pallet-contracts-rpc-runtime-api]276# git = 'https://github.com/paritytech/substrate'277# default-features = false278# branch = 'master'279# version = '4.0.0-dev'280281[dependencies.pallet-randomness-collective-flip]282default-features = false283git = "https://github.com/paritytech/substrate"284branch = "polkadot-v0.9.30"285286[dependencies.pallet-sudo]287default-features = false288git = "https://github.com/paritytech/substrate"289branch = "polkadot-v0.9.30"290291[dependencies.pallet-timestamp]292default-features = false293git = "https://github.com/paritytech/substrate"294branch = "polkadot-v0.9.30"295296[dependencies.pallet-transaction-payment]297default-features = false298git = "https://github.com/paritytech/substrate"299branch = "polkadot-v0.9.30"300301[dependencies.pallet-transaction-payment-rpc-runtime-api]302default-features = false303git = "https://github.com/paritytech/substrate"304branch = "polkadot-v0.9.30"305306[dependencies.pallet-treasury]307default-features = false308git = "https://github.com/paritytech/substrate"309branch = "polkadot-v0.9.30"310311[dependencies.sp-arithmetic]312default-features = false313git = "https://github.com/paritytech/substrate"314branch = "polkadot-v0.9.30"315316[dependencies.sp-api]317default-features = false318git = "https://github.com/paritytech/substrate"319branch = "polkadot-v0.9.30"320321[dependencies.sp-block-builder]322default-features = false323git = "https://github.com/paritytech/substrate"324branch = "polkadot-v0.9.30"325326[dependencies.sp-core]327default-features = false328git = "https://github.com/paritytech/substrate"329branch = "polkadot-v0.9.30"330331[dependencies.sp-consensus-aura]332default-features = false333git = "https://github.com/paritytech/substrate"334branch = "polkadot-v0.9.30"335336[dependencies.sp-inherents]337default-features = false338git = "https://github.com/paritytech/substrate"339branch = "polkadot-v0.9.30"340341[dependencies.sp-io]342default-features = false343git = "https://github.com/paritytech/substrate"344branch = "polkadot-v0.9.30"345346[dependencies.sp-offchain]347default-features = false348git = "https://github.com/paritytech/substrate"349branch = "polkadot-v0.9.30"350351[dependencies.sp-runtime]352default-features = false353git = "https://github.com/paritytech/substrate"354branch = "polkadot-v0.9.30"355356[dependencies.sp-session]357default-features = false358git = "https://github.com/paritytech/substrate"359branch = "polkadot-v0.9.30"360361[dependencies.sp-std]362default-features = false363git = "https://github.com/paritytech/substrate"364branch = "polkadot-v0.9.30"365366[dependencies.sp-transaction-pool]367default-features = false368git = "https://github.com/paritytech/substrate"369branch = "polkadot-v0.9.30"370371[dependencies.sp-version]372default-features = false373git = "https://github.com/paritytech/substrate"374branch = "polkadot-v0.9.30"375376[dependencies.smallvec]377version = '1.6.1'378379################################################################################380# Cumulus dependencies381382[dependencies.parachain-info]383default-features = false384git = "https://github.com/paritytech/cumulus"385branch = "polkadot-v0.9.30"386387[dependencies.cumulus-pallet-aura-ext]388git = "https://github.com/paritytech/cumulus"389branch = "polkadot-v0.9.30"390default-features = false391392[dependencies.cumulus-pallet-parachain-system]393git = "https://github.com/paritytech/cumulus"394branch = "polkadot-v0.9.30"395default-features = false396397[dependencies.cumulus-primitives-core]398git = "https://github.com/paritytech/cumulus"399branch = "polkadot-v0.9.30"400default-features = false401402[dependencies.cumulus-pallet-xcm]403git = "https://github.com/paritytech/cumulus"404branch = "polkadot-v0.9.30"405default-features = false406407[dependencies.cumulus-pallet-dmp-queue]408git = "https://github.com/paritytech/cumulus"409branch = "polkadot-v0.9.30"410default-features = false411412[dependencies.cumulus-pallet-xcmp-queue]413git = "https://github.com/paritytech/cumulus"414branch = "polkadot-v0.9.30"415default-features = false416417[dependencies.cumulus-primitives-utility]418git = "https://github.com/paritytech/cumulus"419branch = "polkadot-v0.9.30"420default-features = false421422[dependencies.cumulus-primitives-timestamp]423git = "https://github.com/paritytech/cumulus"424branch = "polkadot-v0.9.30"425default-features = false426427################################################################################428# Polkadot dependencies429430[dependencies.polkadot-parachain]431git = "https://github.com/paritytech/polkadot"432branch = "release-v0.9.30"433default-features = false434435[dependencies.xcm]436git = "https://github.com/paritytech/polkadot"437branch = "release-v0.9.30"438default-features = false439440[dependencies.xcm-builder]441git = "https://github.com/paritytech/polkadot"442branch = "release-v0.9.30"443default-features = false444445[dependencies.xcm-executor]446git = "https://github.com/paritytech/polkadot"447branch = "release-v0.9.30"448default-features = false449450[dependencies.pallet-xcm]451git = "https://github.com/paritytech/polkadot"452branch = "release-v0.9.30"453default-features = false454455################################################################################456# local dependencies457458[dependencies]459orml-vesting.workspace = true460orml-xtokens.workspace = true461orml-tokens.workspace = true462orml-traits.workspace = true463464log = { version = "0.4.16", default-features = false }465up-common = { path = "../../primitives/common", default-features = false }466scale-info = { version = "2.0.1", default-features = false, features = [467 "derive",468] }469derivative = "2.2.0"470pallet-unique = { path = '../../pallets/unique', default-features = false }471up-rpc = { path = "../../primitives/rpc", default-features = false }472app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false }473rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false }474pallet-inflation = { path = '../../pallets/inflation', default-features = false }475pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false }476up-data-structs = { path = '../../primitives/data-structs', default-features = false }477pallet-collator-selection = { default-features = false, path = "../../pallets/collator-selection" }478pallet-configuration = { default-features = false, path = "../../pallets/configuration" }479pallet-common = { default-features = false, path = "../../pallets/common" }480pallet-structure = { default-features = false, path = "../../pallets/structure" }481pallet-fungible = { default-features = false, path = "../../pallets/fungible" }482pallet-refungible = { default-features = false, path = "../../pallets/refungible" }483pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" }484pallet-proxy-rmrk-core = { default-features = false, path = "../../pallets/proxy-rmrk-core", package = "pallet-rmrk-core" }485pallet-proxy-rmrk-equip = { default-features = false, path = "../../pallets/proxy-rmrk-equip", package = "pallet-rmrk-equip" }486pallet-unique-scheduler = { path = '../../pallets/scheduler', default-features = false }487# pallet-contract-helpers = { path = '../pallets/contract-helpers', default-features = false, version = '0.1.0' }488pallet-charge-transaction = { git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.30", package = "pallet-template-transaction-payment", default-features = false, version = "3.0.0" }489pallet-evm-migration = { path = '../../pallets/evm-migration', default-features = false }490pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }491pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }492pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }493pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }494pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }495pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }496fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }497fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }498fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.30" }499evm-coder = { default-features = false, path = '../../crates/evm-coder' }500up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.30' }501pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }502503################################################################################504# Other Dependencies505506impl-trait-for-tuples = "0.2.2"507508################################################################################509# Dev Dependencies510511[dev-dependencies.logtest]512version = "2.0.0"513514################################################################################515# Build Dependencies516517[build-dependencies.substrate-wasm-builder]518git = "https://github.com/paritytech/substrate"519branch = "polkadot-v0.9.30"