From 4def98e7e557b7d359e352e1b56677d19e268768 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 18 Dec 2019 11:03:02 +0100 Subject: [PATCH 01/75] TODOs --- frame/rewards/Cargo.toml | 30 +++ frame/rewards/src/lib.rs | 381 +++++++++++++++++++++++++++++++++++++++ frame/staking/src/lib.rs | 100 +++++++++- 3 files changed, 505 insertions(+), 6 deletions(-) create mode 100644 frame/rewards/Cargo.toml create mode 100644 frame/rewards/src/lib.rs diff --git a/frame/rewards/Cargo.toml b/frame/rewards/Cargo.toml new file mode 100644 index 0000000000000..09abc2478d504 --- /dev/null +++ b/frame/rewards/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "pallet-rewards" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +serde = { version = "1.0.101", optional = true } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } +sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } +frame-support = { version = "2.0.0", default-features = false, path = "../support" } +frame-system = { version = "2.0.0", default-features = false, path = "../system" } + +[dev-dependencies] +sp-core = { version = "2.0.0", path = "../../primitives/core" } +pallet-balances = { version = "2.0.0", path = "../balances" } + +[features] +default = ["std"] +std = [ + "serde", + "codec/std", + "sp-std/std", + "sp-io/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", +] diff --git a/frame/rewards/src/lib.rs b/frame/rewards/src/lib.rs new file mode 100644 index 0000000000000..7417be7d8ca34 --- /dev/null +++ b/frame/rewards/src/lib.rs @@ -0,0 +1,381 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! # Rewards Module +//! +//! - [`nicks::Trait`](./trait.Trait.html) +//! - [`Call`](./enum.Call.html) +//! +//! ## Overview +//! +//! Nicks is a trivial module for keeping track of account names on-chain. It makes no effort to +//! create a name hierarchy, be a DNS replacement or provide reverse lookups. +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! +//! * `set_name` - Set the associated name of an account; a small deposit is reserved if not already +//! taken. +//! * `clear_name` - Remove an account's associated name; the deposit is returned. +//! * `kill_name` - Forcibly remove the associated name; the deposit is lost. +//! +//! [`Call`]: ./enum.Call.html +//! [`Trait`]: ./trait.Trait.html + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::prelude::*; +use sp_runtime::{ + traits::{StaticLookup, EnsureOrigin, Zero} +}; +use frame_support::{ + decl_module, decl_event, decl_storage, ensure, + traits::{Currency, ReservableCurrency, OnUnbalanced, Get}, + weights::SimpleDispatchInfo, +}; +use frame_system::{self as system, ensure_signed, ensure_root}; + +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; + +pub trait Staking> { + type EraIndex; + + fn exposure(when: Self::EraIndex, which: &AccountId) -> Exposure; + + fn +} + +pub trait Trait: frame_system::Trait { + /// The overarching event type. + type Event: From> + Into<::Event>; + + /// The currency trait. + type Currency: ReservableCurrency; + + /// The staking module trait. + type Staking: Staking; +} + +decl_storage! { + trait Store for Module as Sudo { + /// The historical Exposure + NameOf: map T::AccountId => Option<(Vec, BalanceOf)>; + } +} + +decl_event!( + pub enum Event where AccountId = ::AccountId, Balance = BalanceOf { + /// A name was set. + NameSet(AccountId), + /// A name was forcibly set. + NameForced(AccountId), + /// A name was changed. + NameChanged(AccountId), + /// A name was cleared, and the given balance returned. + NameCleared(AccountId, Balance), + /// A name was removed and the given balance slashed. + NameKilled(AccountId, Balance), + } +); + +decl_module! { + // Simple declaration of the `Module` type. Lets the macro know what it's working on. + pub struct Module for enum Call where origin: T::Origin { + fn deposit_event() = default; + + /// Reservation fee. + const ReservationFee: BalanceOf = T::ReservationFee::get(); + + /// The minimum length a name may be. + const MinLength: u32 = T::MinLength::get() as u32; + + /// The maximum length a name may be. + const MaxLength: u32 = T::MaxLength::get() as u32; + + /// Set an account's name. The name should be a UTF-8-encoded string by convention, though + /// we don't check it. + /// + /// The name may not be more than `T::MaxLength` bytes, nor less than `T::MinLength` bytes. + /// + /// If the account doesn't already have a name, then a fee of `ReservationFee` is reserved + /// in the account. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// # + /// - O(1). + /// - At most one balance operation. + /// - One storage read/write. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(50_000)] + fn set_name(origin, name: Vec) { + let sender = ensure_signed(origin)?; + + ensure!(name.len() >= T::MinLength::get(), "Name too short"); + ensure!(name.len() <= T::MaxLength::get(), "Name too long"); + + let deposit = if let Some((_, deposit)) = >::get(&sender) { + Self::deposit_event(RawEvent::NameSet(sender.clone())); + deposit + } else { + let deposit = T::ReservationFee::get(); + T::Currency::reserve(&sender, deposit.clone())?; + Self::deposit_event(RawEvent::NameChanged(sender.clone())); + deposit + }; + + >::insert(&sender, (name, deposit)); + } + + /// Clear an account's name and return the deposit. Fails if the account was not named. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// # + /// - O(1). + /// - One balance operation. + /// - One storage read/write. + /// - One event. + /// # + fn clear_name(origin) { + let sender = ensure_signed(origin)?; + + let deposit = >::take(&sender).ok_or("Not named")?.1; + + let _ = T::Currency::unreserve(&sender, deposit.clone()); + + Self::deposit_event(RawEvent::NameCleared(sender, deposit)); + } + + /// Remove an account's name and take charge of the deposit. + /// + /// Fails if `who` has not been named. The deposit is dealt with through `T::Slashed` + /// imbalance handler. + /// + /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. + /// + /// # + /// - O(1). + /// - One unbalanced handler (probably a balance transfer) + /// - One storage read/write. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn kill_name(origin, target: ::Source) { + T::ForceOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root) + .map_err(|_| "bad origin")?; + + // Figure out who we're meant to be clearing. + let target = T::Lookup::lookup(target)?; + // Grab their deposit (and check that they have one). + let deposit = >::take(&target).ok_or("Not named")?.1; + // Slash their deposit from them. + T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit.clone()).0); + + Self::deposit_event(RawEvent::NameKilled(target, deposit)); + } + + /// Set a third-party account's name with no deposit. + /// + /// No length checking is done on the name. + /// + /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. + /// + /// # + /// - O(1). + /// - At most one balance operation. + /// - One storage read/write. + /// - One event. + /// # + #[weight = SimpleDispatchInfo::FreeOperational] + fn force_name(origin, target: ::Source, name: Vec) { + T::ForceOrigin::try_origin(origin) + .map(|_| ()) + .or_else(ensure_root) + .map_err(|_| "bad origin")?; + + let target = T::Lookup::lookup(target)?; + let deposit = >::get(&target).map(|x| x.1).unwrap_or_else(Zero::zero); + >::insert(&target, (name, deposit)); + + Self::deposit_event(RawEvent::NameForced(target)); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use frame_support::{assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight}; + use sp_core::H256; + use frame_system::EnsureSignedBy; + // The testing primitives are very useful for avoiding having to work with signatures + // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. + use sp_runtime::{ + Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup}, + }; + + impl_outer_origin! { + pub enum Origin for Test where system = frame_system {} + } + + // For testing the module, we construct most of a mock runtime. This means + // first constructing a configuration type (`Test`) which `impl`s each of the + // configuration traits of modules we want to use. + #[derive(Clone, Eq, PartialEq)] + pub struct Test; + parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockWeight: Weight = 1024; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + impl frame_system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Call = (); + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); + type BlockHashCount = BlockHashCount; + type MaximumBlockWeight = MaximumBlockWeight; + type MaximumBlockLength = MaximumBlockLength; + type AvailableBlockRatio = AvailableBlockRatio; + type Version = (); + } + parameter_types! { + pub const ExistentialDeposit: u64 = 0; + pub const TransferFee: u64 = 0; + pub const CreationFee: u64 = 0; + } + impl pallet_balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnNewAccount = (); + type Event = (); + type TransferPayment = (); + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type TransferFee = TransferFee; + type CreationFee = CreationFee; + } + parameter_types! { + pub const ReservationFee: u64 = 2; + pub const MinLength: usize = 3; + pub const MaxLength: usize = 16; + pub const One: u64 = 1; + } + impl Trait for Test { + type Event = (); + type Currency = Balances; + type ReservationFee = ReservationFee; + type Slashed = (); + type ForceOrigin = EnsureSignedBy; + type MinLength = MinLength; + type MaxLength = MaxLength; + } + type Balances = pallet_balances::Module; + type Nicks = Module; + + // This function basically just builds a genesis storage key/value store according to + // our desired mockup. + fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + // We use default for brevity, but you can configure as desired if needed. + pallet_balances::GenesisConfig:: { + balances: vec![ + (1, 10), + (2, 10), + ], + vesting: vec![], + }.assimilate_storage(&mut t).unwrap(); + t.into() + } + + #[test] + fn kill_name_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Nicks::set_name(Origin::signed(2), b"Dave".to_vec())); + assert_eq!(Balances::total_balance(&2), 10); + assert_ok!(Nicks::kill_name(Origin::signed(1), 2)); + assert_eq!(Balances::total_balance(&2), 8); + assert_eq!(>::get(2), None); + }); + } + + #[test] + fn force_name_should_work() { + new_test_ext().execute_with(|| { + assert_noop!( + Nicks::set_name(Origin::signed(2), b"Dr. David Brubeck, III".to_vec()), + "Name too long" + ); + + assert_ok!(Nicks::set_name(Origin::signed(2), b"Dave".to_vec())); + assert_eq!(Balances::reserved_balance(&2), 2); + assert_ok!(Nicks::force_name(Origin::signed(1), 2, b"Dr. David Brubeck, III".to_vec())); + assert_eq!(Balances::reserved_balance(&2), 2); + assert_eq!(>::get(2).unwrap(), (b"Dr. David Brubeck, III".to_vec(), 2)); + }); + } + + #[test] + fn normal_operation_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Nicks::set_name(Origin::signed(1), b"Gav".to_vec())); + assert_eq!(Balances::reserved_balance(&1), 2); + assert_eq!(Balances::free_balance(&1), 8); + assert_eq!(>::get(1).unwrap().0, b"Gav".to_vec()); + + assert_ok!(Nicks::set_name(Origin::signed(1), b"Gavin".to_vec())); + assert_eq!(Balances::reserved_balance(&1), 2); + assert_eq!(Balances::free_balance(&1), 8); + assert_eq!(>::get(1).unwrap().0, b"Gavin".to_vec()); + + assert_ok!(Nicks::clear_name(Origin::signed(1))); + assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::free_balance(&1), 10); + }); + } + + #[test] + fn error_catching_should_work() { + new_test_ext().execute_with(|| { + assert_noop!(Nicks::clear_name(Origin::signed(1)), "Not named"); + + assert_noop!(Nicks::set_name(Origin::signed(3), b"Dave".to_vec()), "not enough free funds"); + + assert_noop!(Nicks::set_name(Origin::signed(1), b"Ga".to_vec()), "Name too short"); + assert_noop!( + Nicks::set_name(Origin::signed(1), b"Gavin James Wood, Esquire".to_vec()), + "Name too long" + ); + assert_ok!(Nicks::set_name(Origin::signed(1), b"Dave".to_vec())); + assert_noop!(Nicks::kill_name(Origin::signed(2), 1), "bad origin"); + assert_noop!(Nicks::force_name(Origin::signed(2), 1, b"Whatever".to_vec()), "bad origin"); + }); + } +} diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index bc43b54e91355..16d1c72966a06 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -391,8 +391,12 @@ pub struct StakingLedger { /// Any balance that is becoming free, which may eventually be transferred out /// of the stash (assuming it doesn't get slashed first). pub unlocking: Vec>, + /// The era up until which this staker had their reward paid. + pub last_reward: EraIndex, + // TODO: ^^^ this will need migration logic. } + impl< AccountId, Balance: HasCompact + Copy + Saturating, @@ -502,6 +506,7 @@ pub struct Exposure { pub own: Balance, /// The portions of nominators stashes that are exposed. pub others: Vec>, + // TODO: Should be ordered by AccountId. } /// A pending slash record. The value of the slash has been computed but not applied yet, @@ -633,6 +638,8 @@ impl Default for Forcing { fn default() -> Self { Forcing::NotForcing } } +const HISTORY_DEPTH: EraIndex = 84; + decl_storage! { trait Store for Module as Staking { @@ -668,8 +675,17 @@ decl_storage! { /// Nominators for a particular account that is in action right now. You can't iterate /// through validators here, but you can find them in the Session module. /// - /// This is keyed by the stash account. - pub Stakers get(fn stakers): map T::AccountId => Exposure>; + /// This is keyed fist by the era index to allow bulk deletion and then the stash account. + /// + /// Is it removed after `HISTORY_DEPTH` eras. + pub Stakers get(fn stakers): double_map EraIndex hasher(twox_64_concat), + twox_64_concat(T::AccountId) => Exposure>; + // TODO: ^^^ This will need a migration. + // TODO: consider switching this to a simple map EraIndex => Vec + + /// The per-validator era payout for one in the last `HISTORY_DEPTH` eras. + pub EraValidatorReward: map EraIndex => BalanceOf; + /// TODO: Will likely need initialising for the migration. /// The currently elected validator set keyed by stash account ID. pub CurrentElected get(fn current_elected): Vec; @@ -823,6 +839,7 @@ decl_module! { fn on_initialize() { Self::ensure_storage_upgraded(); + // TODO: Remove old `EraValidatorReward` and `Stakers` entries. } fn on_finalize() { @@ -932,7 +949,8 @@ decl_module! { /// - Contains a limited number of reads. /// - Each call (requires the remainder of the bonded balance to be above `minimum_balance`) /// will cause a new entry to be inserted into a vector (`Ledger.unlocking`) kept in storage. - /// The only way to clean the aforementioned storage item is also user-controlled via `withdraw_unbonded`. + /// The only way to clean the aforementioned storage item is also user-controlled via + /// `withdraw_unbonded`. /// - One DB entry. /// #[weight = SimpleDispatchInfo::FixedNormal(400_000)] @@ -1213,6 +1231,40 @@ decl_module! { ::UnappliedSlashes::insert(&era, &unapplied); } + + /// Make one staker's payout for one era. + /// + /// - `who` is the nominator to pay out. + /// - `era` may not be lower than one following the most recently paid era. If it is higher, + /// then it indicates an instruction to skip the payout of all previous eras. + /// - `validators` is the list of all validators that `who` had exposure to during `era`. + /// If it is incomplete, then less than the full reward will be paid out. + /// + /// WARNING: Incorrect arguments here can result in loss of payout. Be very careful. + /// + /// 1 balance transfer + /// Up to 16 storage reads, each of `O(N)` size and decode complexity; `N` is maximum + /// nominations that can be given to a single validator. (`MAX_NOMINATIONS` is the maximum + /// number of validators that may be nominated by a single nominator.) This is bounded only + /// economically (all nominators are required to place a minimum stake). + /// Compute: O(MAX_NOMINATIONS * logN). + // TODO: Limit the amount of nominators that can be assigned to a validator by Phragmen. + fn payout_nominator(origin, era: EraIndex, validators: Vec) { + let who = ensure_signed(origin)?; + Self::do_payout_nominator(who, era, validators) + } + + /// Make one staker's payout for one era. + /// + /// - `who` is the nominator to pay out. + /// - `era` may not be lower than one following the most recently paid era. If it is higher, + /// then it indicates an instruction to skip the payout of all previous eras. + /// + /// WARNING: Incorrect arguments here can result in loss of payout. Be very careful. + fn payout_validator(origin, era: EraIndex) { + let who = ensure_signed(origin)?; + Self::do_payout_validator(who, era) + } } } @@ -1226,6 +1278,29 @@ impl Module { // MUTABLES (DANGEROUS) + fn do_payout_nominator(who: T::AccountId, era: EraIndex, validators: Vec) { + // TODO: lookup `who` in ledger to get `StakingLedger`. + // TODO: check most recent and ensure it's less than era + // TODO: bump the staking ledger's era to `era` + // TODO: grab the payout info for the era + // TODO: for each in `validators`: + // TODO: - grab exposure information for era + // TODO: - lookup `who` and accumulate their reward + // TODO: reward `who` accordingly. + } + + fn do_payout_validator(who: T::AccountId, era: EraIndex) { + // TODO: lookup `who` in ledger to get `StakingLedger`. + // TODO: check most recent and ensure it's less than era + // TODO: bump the staking ledger's era to `era` + // TODO: grab the payout and exposure information for era + // TODO: reward `who` accordingly (if they were a validator). + } + + // TODO: at the end of session, ensure that points are accumulated within the correct era. + // TODO: currently, validator set changes lag by one session, therefore, in the first session of + // TODO: an era, the points should be accumulated by the validator set of the era before. + /// Update the ledger for a controller. This will also update the stash lock. The lock will /// will lock the entire funds except paying for further transactions. fn update_ledger( @@ -1280,8 +1355,8 @@ impl Module { /// nominators' balance, pro-rata based on their exposure, after having removed the validator's /// pre-payout cut. fn reward_validator(stash: &T::AccountId, reward: BalanceOf) -> PositiveImbalanceOf { - let off_the_table = Self::validators(stash).commission * reward; - let reward = reward.saturating_sub(off_the_table); + let commission = Self::validators(stash).commission * reward; + let reward = reward.saturating_sub(commission); let mut imbalance = >::zero(); let validator_cut = if reward.is_zero() { Zero::zero() @@ -1298,7 +1373,7 @@ impl Module { per_u64 * reward }; - imbalance.maybe_subsume(Self::make_payout(stash, validator_cut + off_the_table)); + imbalance.maybe_subsume(Self::make_payout(stash, validator_cut + commission)); imbalance } @@ -1589,6 +1664,19 @@ impl Module { /// /// COMPLEXITY: Complexity is `number_of_validator_to_reward x current_elected_len`. /// If you need to reward lots of validator consider using `reward_by_indices`. + + // TODO: This is based on a false assumption; that rewarding will always add to a validator + // in the current era. It will not, since validator set lags by some amount (currently one + // session, but this may be configurable in the future). + + // TODO: Force the rewarder to pass in the representative era index (or the session index) so + // we can figure out which era's reward this should go to and be able to add points to eras that + // have already passed. + + // TODO: We should also ban collecting rewards from an era that may yet have points added to it. + // This will likely need an additional API from session to let us know when an era will no + // longer have any points added to it (i.e. basically just when the last session whose + // validator set is some previous era). pub fn reward_by_ids(validators_points: impl IntoIterator) { CurrentEraPointsEarned::mutate(|rewards| { let current_elected = >::current_elected(); From 338362aa88bd1f3c2c89b0fee21b224666327fa5 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 18 Dec 2019 11:03:32 +0100 Subject: [PATCH 02/75] Remove superfluous: --- frame/rewards/Cargo.toml | 30 --- frame/rewards/src/lib.rs | 381 --------------------------------------- 2 files changed, 411 deletions(-) delete mode 100644 frame/rewards/Cargo.toml delete mode 100644 frame/rewards/src/lib.rs diff --git a/frame/rewards/Cargo.toml b/frame/rewards/Cargo.toml deleted file mode 100644 index 09abc2478d504..0000000000000 --- a/frame/rewards/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "pallet-rewards" -version = "2.0.0" -authors = ["Parity Technologies "] -edition = "2018" - -[dependencies] -serde = { version = "1.0.101", optional = true } -codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } -sp-std = { version = "2.0.0", default-features = false, path = "../../primitives/std" } -sp-io = { version = "2.0.0", default-features = false, path = "../../primitives/io" } -sp-runtime = { version = "2.0.0", default-features = false, path = "../../primitives/runtime" } -frame-support = { version = "2.0.0", default-features = false, path = "../support" } -frame-system = { version = "2.0.0", default-features = false, path = "../system" } - -[dev-dependencies] -sp-core = { version = "2.0.0", path = "../../primitives/core" } -pallet-balances = { version = "2.0.0", path = "../balances" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "sp-std/std", - "sp-io/std", - "sp-runtime/std", - "frame-support/std", - "frame-system/std", -] diff --git a/frame/rewards/src/lib.rs b/frame/rewards/src/lib.rs deleted file mode 100644 index 7417be7d8ca34..0000000000000 --- a/frame/rewards/src/lib.rs +++ /dev/null @@ -1,381 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate 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. - -// Substrate 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 Substrate. If not, see . - -//! # Rewards Module -//! -//! - [`nicks::Trait`](./trait.Trait.html) -//! - [`Call`](./enum.Call.html) -//! -//! ## Overview -//! -//! Nicks is a trivial module for keeping track of account names on-chain. It makes no effort to -//! create a name hierarchy, be a DNS replacement or provide reverse lookups. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! * `set_name` - Set the associated name of an account; a small deposit is reserved if not already -//! taken. -//! * `clear_name` - Remove an account's associated name; the deposit is returned. -//! * `kill_name` - Forcibly remove the associated name; the deposit is lost. -//! -//! [`Call`]: ./enum.Call.html -//! [`Trait`]: ./trait.Trait.html - -#![cfg_attr(not(feature = "std"), no_std)] - -use sp_std::prelude::*; -use sp_runtime::{ - traits::{StaticLookup, EnsureOrigin, Zero} -}; -use frame_support::{ - decl_module, decl_event, decl_storage, ensure, - traits::{Currency, ReservableCurrency, OnUnbalanced, Get}, - weights::SimpleDispatchInfo, -}; -use frame_system::{self as system, ensure_signed, ensure_root}; - -type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; - -pub trait Staking> { - type EraIndex; - - fn exposure(when: Self::EraIndex, which: &AccountId) -> Exposure; - - fn -} - -pub trait Trait: frame_system::Trait { - /// The overarching event type. - type Event: From> + Into<::Event>; - - /// The currency trait. - type Currency: ReservableCurrency; - - /// The staking module trait. - type Staking: Staking; -} - -decl_storage! { - trait Store for Module as Sudo { - /// The historical Exposure - NameOf: map T::AccountId => Option<(Vec, BalanceOf)>; - } -} - -decl_event!( - pub enum Event where AccountId = ::AccountId, Balance = BalanceOf { - /// A name was set. - NameSet(AccountId), - /// A name was forcibly set. - NameForced(AccountId), - /// A name was changed. - NameChanged(AccountId), - /// A name was cleared, and the given balance returned. - NameCleared(AccountId, Balance), - /// A name was removed and the given balance slashed. - NameKilled(AccountId, Balance), - } -); - -decl_module! { - // Simple declaration of the `Module` type. Lets the macro know what it's working on. - pub struct Module for enum Call where origin: T::Origin { - fn deposit_event() = default; - - /// Reservation fee. - const ReservationFee: BalanceOf = T::ReservationFee::get(); - - /// The minimum length a name may be. - const MinLength: u32 = T::MinLength::get() as u32; - - /// The maximum length a name may be. - const MaxLength: u32 = T::MaxLength::get() as u32; - - /// Set an account's name. The name should be a UTF-8-encoded string by convention, though - /// we don't check it. - /// - /// The name may not be more than `T::MaxLength` bytes, nor less than `T::MinLength` bytes. - /// - /// If the account doesn't already have a name, then a fee of `ReservationFee` is reserved - /// in the account. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// # - /// - O(1). - /// - At most one balance operation. - /// - One storage read/write. - /// - One event. - /// # - #[weight = SimpleDispatchInfo::FixedNormal(50_000)] - fn set_name(origin, name: Vec) { - let sender = ensure_signed(origin)?; - - ensure!(name.len() >= T::MinLength::get(), "Name too short"); - ensure!(name.len() <= T::MaxLength::get(), "Name too long"); - - let deposit = if let Some((_, deposit)) = >::get(&sender) { - Self::deposit_event(RawEvent::NameSet(sender.clone())); - deposit - } else { - let deposit = T::ReservationFee::get(); - T::Currency::reserve(&sender, deposit.clone())?; - Self::deposit_event(RawEvent::NameChanged(sender.clone())); - deposit - }; - - >::insert(&sender, (name, deposit)); - } - - /// Clear an account's name and return the deposit. Fails if the account was not named. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// # - /// - O(1). - /// - One balance operation. - /// - One storage read/write. - /// - One event. - /// # - fn clear_name(origin) { - let sender = ensure_signed(origin)?; - - let deposit = >::take(&sender).ok_or("Not named")?.1; - - let _ = T::Currency::unreserve(&sender, deposit.clone()); - - Self::deposit_event(RawEvent::NameCleared(sender, deposit)); - } - - /// Remove an account's name and take charge of the deposit. - /// - /// Fails if `who` has not been named. The deposit is dealt with through `T::Slashed` - /// imbalance handler. - /// - /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. - /// - /// # - /// - O(1). - /// - One unbalanced handler (probably a balance transfer) - /// - One storage read/write. - /// - One event. - /// # - #[weight = SimpleDispatchInfo::FreeOperational] - fn kill_name(origin, target: ::Source) { - T::ForceOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root) - .map_err(|_| "bad origin")?; - - // Figure out who we're meant to be clearing. - let target = T::Lookup::lookup(target)?; - // Grab their deposit (and check that they have one). - let deposit = >::take(&target).ok_or("Not named")?.1; - // Slash their deposit from them. - T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit.clone()).0); - - Self::deposit_event(RawEvent::NameKilled(target, deposit)); - } - - /// Set a third-party account's name with no deposit. - /// - /// No length checking is done on the name. - /// - /// The dispatch origin for this call must be _Root_ or match `T::ForceOrigin`. - /// - /// # - /// - O(1). - /// - At most one balance operation. - /// - One storage read/write. - /// - One event. - /// # - #[weight = SimpleDispatchInfo::FreeOperational] - fn force_name(origin, target: ::Source, name: Vec) { - T::ForceOrigin::try_origin(origin) - .map(|_| ()) - .or_else(ensure_root) - .map_err(|_| "bad origin")?; - - let target = T::Lookup::lookup(target)?; - let deposit = >::get(&target).map(|x| x.1).unwrap_or_else(Zero::zero); - >::insert(&target, (name, deposit)); - - Self::deposit_event(RawEvent::NameForced(target)); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use frame_support::{assert_ok, assert_noop, impl_outer_origin, parameter_types, weights::Weight}; - use sp_core::H256; - use frame_system::EnsureSignedBy; - // The testing primitives are very useful for avoiding having to work with signatures - // or public keys. `u64` is used as the `AccountId` and no `Signature`s are required. - use sp_runtime::{ - Perbill, testing::Header, traits::{BlakeTwo256, IdentityLookup}, - }; - - impl_outer_origin! { - pub enum Origin for Test where system = frame_system {} - } - - // For testing the module, we construct most of a mock runtime. This means - // first constructing a configuration type (`Test`) which `impl`s each of the - // configuration traits of modules we want to use. - #[derive(Clone, Eq, PartialEq)] - pub struct Test; - parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockWeight: Weight = 1024; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - impl frame_system::Trait for Test { - type Origin = Origin; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Call = (); - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type Event = (); - type BlockHashCount = BlockHashCount; - type MaximumBlockWeight = MaximumBlockWeight; - type MaximumBlockLength = MaximumBlockLength; - type AvailableBlockRatio = AvailableBlockRatio; - type Version = (); - } - parameter_types! { - pub const ExistentialDeposit: u64 = 0; - pub const TransferFee: u64 = 0; - pub const CreationFee: u64 = 0; - } - impl pallet_balances::Trait for Test { - type Balance = u64; - type OnFreeBalanceZero = (); - type OnNewAccount = (); - type Event = (); - type TransferPayment = (); - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type TransferFee = TransferFee; - type CreationFee = CreationFee; - } - parameter_types! { - pub const ReservationFee: u64 = 2; - pub const MinLength: usize = 3; - pub const MaxLength: usize = 16; - pub const One: u64 = 1; - } - impl Trait for Test { - type Event = (); - type Currency = Balances; - type ReservationFee = ReservationFee; - type Slashed = (); - type ForceOrigin = EnsureSignedBy; - type MinLength = MinLength; - type MaxLength = MaxLength; - } - type Balances = pallet_balances::Module; - type Nicks = Module; - - // This function basically just builds a genesis storage key/value store according to - // our desired mockup. - fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - // We use default for brevity, but you can configure as desired if needed. - pallet_balances::GenesisConfig:: { - balances: vec![ - (1, 10), - (2, 10), - ], - vesting: vec![], - }.assimilate_storage(&mut t).unwrap(); - t.into() - } - - #[test] - fn kill_name_should_work() { - new_test_ext().execute_with(|| { - assert_ok!(Nicks::set_name(Origin::signed(2), b"Dave".to_vec())); - assert_eq!(Balances::total_balance(&2), 10); - assert_ok!(Nicks::kill_name(Origin::signed(1), 2)); - assert_eq!(Balances::total_balance(&2), 8); - assert_eq!(>::get(2), None); - }); - } - - #[test] - fn force_name_should_work() { - new_test_ext().execute_with(|| { - assert_noop!( - Nicks::set_name(Origin::signed(2), b"Dr. David Brubeck, III".to_vec()), - "Name too long" - ); - - assert_ok!(Nicks::set_name(Origin::signed(2), b"Dave".to_vec())); - assert_eq!(Balances::reserved_balance(&2), 2); - assert_ok!(Nicks::force_name(Origin::signed(1), 2, b"Dr. David Brubeck, III".to_vec())); - assert_eq!(Balances::reserved_balance(&2), 2); - assert_eq!(>::get(2).unwrap(), (b"Dr. David Brubeck, III".to_vec(), 2)); - }); - } - - #[test] - fn normal_operation_should_work() { - new_test_ext().execute_with(|| { - assert_ok!(Nicks::set_name(Origin::signed(1), b"Gav".to_vec())); - assert_eq!(Balances::reserved_balance(&1), 2); - assert_eq!(Balances::free_balance(&1), 8); - assert_eq!(>::get(1).unwrap().0, b"Gav".to_vec()); - - assert_ok!(Nicks::set_name(Origin::signed(1), b"Gavin".to_vec())); - assert_eq!(Balances::reserved_balance(&1), 2); - assert_eq!(Balances::free_balance(&1), 8); - assert_eq!(>::get(1).unwrap().0, b"Gavin".to_vec()); - - assert_ok!(Nicks::clear_name(Origin::signed(1))); - assert_eq!(Balances::reserved_balance(&1), 0); - assert_eq!(Balances::free_balance(&1), 10); - }); - } - - #[test] - fn error_catching_should_work() { - new_test_ext().execute_with(|| { - assert_noop!(Nicks::clear_name(Origin::signed(1)), "Not named"); - - assert_noop!(Nicks::set_name(Origin::signed(3), b"Dave".to_vec()), "not enough free funds"); - - assert_noop!(Nicks::set_name(Origin::signed(1), b"Ga".to_vec()), "Name too short"); - assert_noop!( - Nicks::set_name(Origin::signed(1), b"Gavin James Wood, Esquire".to_vec()), - "Name too long" - ); - assert_ok!(Nicks::set_name(Origin::signed(1), b"Dave".to_vec())); - assert_noop!(Nicks::kill_name(Origin::signed(2), 1), "bad origin"); - assert_noop!(Nicks::force_name(Origin::signed(2), 1, b"Whatever".to_vec()), "bad origin"); - }); - } -} From f92f0e8a111652d2dffe8461a5130c476ffec9c0 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 7 Jan 2020 18:21:47 +0100 Subject: [PATCH 03/75] partial implementation --- frame/staking/src/lib.rs | 300 ++++++++++++++++++--------------------- 1 file changed, 142 insertions(+), 158 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index e5670db5ba88b..798b8c87896b4 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -255,7 +255,7 @@ mod slashing; pub mod inflation; -use sp_std::{prelude::*, result}; +use sp_std::{prelude::*, result, collections::btree_map::BTreeMap}; use codec::{HasCompact, Encode, Decode}; use frame_support::{ decl_module, decl_event, decl_storage, ensure, decl_error, @@ -294,29 +294,7 @@ const STAKING_ID: LockIdentifier = *b"staking "; pub type EraIndex = u32; /// Counter for the number of "reward" points earned by a given validator. -pub type Points = u32; - -/// Reward points of an era. Used to split era total payout between validators. -#[derive(Encode, Decode, Default)] -pub struct EraPoints { - /// Total number of points. Equals the sum of reward points for each validator. - total: Points, - /// The reward points earned by a given validator. The index of this vec corresponds to the - /// index into the current validator set. - individual: Vec, -} - -impl EraPoints { - /// Add the reward to the validator at the given index. Index must be valid - /// (i.e. `index < current_elected.len()`). - fn add_points_to_index(&mut self, index: u32, points: u32) { - if let Some(new_total) = self.total.checked_add(points) { - self.total = new_total; - self.individual.resize((index as usize + 1).max(self.individual.len()), 0); - self.individual[index as usize] += points; // Addition is less than total - } - } -} +pub type RewardPoint = u32; /// Indicates the initial status of the staker. #[derive(RuntimeDebug)] @@ -413,7 +391,14 @@ impl< false }) .collect(); - Self { total, active: self.active, stash: self.stash, unlocking } + + Self { + stash: self.stash, + total, + active: self.active, + unlocking, + last_reward: self.last_reward + } } } @@ -504,9 +489,8 @@ pub struct Exposure { /// The validator's own stash that is exposed. #[codec(compact)] pub own: Balance, - /// The portions of nominators stashes that are exposed. + /// The portions of nominators stashes that are exposed. Sorted by AccountId. pub others: Vec>, - // TODO: Should be ordered by AccountId. } /// A pending slash record. The value of the slash has been computed but not applied yet, @@ -678,7 +662,7 @@ decl_storage! { /// This is keyed fist by the era index to allow bulk deletion and then the stash account. /// /// Is it removed after `HISTORY_DEPTH` eras. - pub Stakers get(fn stakers): double_map EraIndex hasher(twox_64_concat), + pub Stakers get(fn stakers): double_map hasher(twox_64_concat) EraIndex, twox_64_concat(T::AccountId) => Exposure>; // TODO: ^^^ This will need a migration. // TODO: consider switching this to a simple map EraIndex => Vec @@ -687,8 +671,11 @@ decl_storage! { pub EraValidatorReward: map EraIndex => BalanceOf; /// TODO: Will likely need initialising for the migration. - /// The currently elected validator set keyed by stash account ID. - pub CurrentElected get(fn current_elected): Vec; + pub CurrentEraTotalStaked get(fn current_era_total_staked): BalanceOf; + + // /// The currently elected validator set keyed by stash account ID. + // pub CurrentElected get(fn current_elected): Vec; + // TODO TODO: clean this!!! /// The current era index. pub CurrentEra get(fn current_era) config(): EraIndex; @@ -696,11 +683,15 @@ decl_storage! { /// The start of the current era. pub CurrentEraStart get(fn current_era_start): MomentOf; - /// The session index at which the current era started. - pub CurrentEraStartSessionIndex get(fn current_era_start_session_index): SessionIndex; + /// The session index at which the era started for the last $HISTORY_DEPTH eras + pub EraStartSessionIndex get(fn era_start_session_index): Vec; + + // /// The session index at which the current era started. + // pub CurrentEraStartSessionIndex get(fn current_era_start_session_index): SessionIndex; + // TODO TODO: clean this!! /// Rewards for the current era. Using indices of current elected set. - CurrentEraPointsEarned get(fn current_era_reward): EraPoints; + RewardPoints get(fn reward_points): map EraIndex => BTreeMap; /// The amount of balance actively at stake for each validator slot, currently. /// @@ -892,7 +883,13 @@ decl_module! { let stash_balance = T::Currency::free_balance(&stash); let value = value.min(stash_balance); - let item = StakingLedger { stash, total: value, active: value, unlocking: vec![] }; + let item = StakingLedger { + stash, + total: value, + active: value, + unlocking: vec![], + last_reward: Self::current_era_start_session_index(), + }; Self::update_ledger(&controller, &item); } @@ -1268,6 +1265,13 @@ decl_module! { impl Module { // PUBLIC IMMUTABLES + fn current_era_start_session_index() -> SessionIndex { + EraStartSessionIndex::get() + .last() + .map(|i| *i) + .unwrap_or(0) + } + /// The total balance that can be slashed from a stash account as of right now. pub fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf { Self::bonded(stash).and_then(Self::ledger).map(|l| l.active).unwrap_or_default() @@ -1297,6 +1301,7 @@ impl Module { // TODO: at the end of session, ensure that points are accumulated within the correct era. // TODO: currently, validator set changes lag by one session, therefore, in the first session of // TODO: an era, the points should be accumulated by the validator set of the era before. + // TODO TODO: I'm not sure I understand that, staking doesn't rely on delay anymore at all. it just know that after HISTORY_DEPTH it removes the rewards. /// Update the ledger for a controller. This will also update the stash lock. The lock will /// will lock the entire funds except paying for further transactions. @@ -1348,39 +1353,41 @@ impl Module { } } - /// Reward a given validator by a specific amount. Add the reward to the validator's, and its - /// nominators' balance, pro-rata based on their exposure, after having removed the validator's - /// pre-payout cut. - fn reward_validator(stash: &T::AccountId, reward: BalanceOf) -> PositiveImbalanceOf { - let commission = Self::validators(stash).commission * reward; - let reward = reward.saturating_sub(commission); - let mut imbalance = >::zero(); - let validator_cut = if reward.is_zero() { - Zero::zero() - } else { - let exposure = Self::stakers(stash); - let total = exposure.total.max(One::one()); - - for i in &exposure.others { - let per_u64 = Perbill::from_rational_approximation(i.value, total); - imbalance.maybe_subsume(Self::make_payout(&i.who, per_u64 * reward)); - } - - let per_u64 = Perbill::from_rational_approximation(exposure.own, total); - per_u64 * reward - }; - - imbalance.maybe_subsume(Self::make_payout(stash, validator_cut + commission)); - - imbalance - } + // /// Reward a given validator by a specific amount. Add the reward to the validator's, and its + // /// nominators' balance, pro-rata based on their exposure, after having removed the validator's + // /// pre-payout cut. + // fn reward_validator(stash: &T::AccountId, reward: BalanceOf) -> PositiveImbalanceOf { + // let commission = Self::validators(stash).commission * reward; + // let reward = reward.saturating_sub(commission); + // let mut imbalance = >::zero(); + // let validator_cut = if reward.is_zero() { + // Zero::zero() + // } else { + // let exposure = Self::stakers(stash); + // let total = exposure.total.max(One::one()); + + // for i in &exposure.others { + // let per_u64 = Perbill::from_rational_approximation(i.value, total); + // imbalance.maybe_subsume(Self::make_payout(&i.who, per_u64 * reward)); + // } + + // let per_u64 = Perbill::from_rational_approximation(exposure.own, total); + // per_u64 * reward + // }; + + // imbalance.maybe_subsume(Self::make_payout(stash, validator_cut + commission)); + + // imbalance + // } /// Session has just ended. Provide the validator set for the next session if it's an era-end, along /// with the exposure of the prior validator set. fn new_session(session_index: SessionIndex) -> Option<(Vec, Vec<(T::AccountId, Exposure>)>)> { - let era_length = session_index.checked_sub(Self::current_era_start_session_index()).unwrap_or(0); + let era_length = session_index.checked_sub(Self::current_era_start_session_index()) + .unwrap_or(0); + match ForceEra::get() { Forcing::ForceNew => ForceEra::kill(), Forcing::ForceAlways => (), @@ -1389,7 +1396,7 @@ impl Module { } let validators = T::SessionInterface::validators(); let prior = validators.into_iter() - .map(|v| { let e = Self::stakers(&v); (v, e) }) + .map(|v| { let e = Self::stakers(&Self::current_era(), &v); (v, e) }) .collect(); Self::new_era(session_index).map(move |new| (new, prior)) @@ -1400,52 +1407,39 @@ impl Module { /// NOTE: This always happens immediately before a session change to ensure that new validators /// get a chance to set their session keys. fn new_era(start_session_index: SessionIndex) -> Option> { - // Payout - let points = CurrentEraPointsEarned::take(); + // Increment current era. + let current_era = CurrentEra::mutate(|s| { *s += 1; *s }); + let now = T::Time::now(); + + // Set new era start let previous_era_start = >::mutate(|v| { sp_std::mem::replace(v, now) }); - let era_duration = now - previous_era_start; - if !era_duration.is_zero() { - let validators = Self::current_elected(); - - let validator_len: BalanceOf = (validators.len() as u32).into(); - let total_rewarded_stake = Self::slot_stake() * validator_len; - - let (total_payout, max_payout) = inflation::compute_total_payout( - &T::RewardCurve::get(), - total_rewarded_stake.clone(), - T::Currency::total_issuance(), - // Duration of era; more than u64::MAX is rewarded as u64::MAX. - era_duration.saturated_into::(), - ); - - let mut total_imbalance = >::zero(); - for (v, p) in validators.iter().zip(points.individual.into_iter()) { - if p != 0 { - let reward = Perbill::from_rational_approximation(p, points.total) * total_payout; - total_imbalance.subsume(Self::reward_validator(v, reward)); - } - } - - // assert!(total_imbalance.peek() == total_payout) - let total_payout = total_imbalance.peek(); + let era_duration = now - previous_era_start; + let (total_payout, _max_payout) = inflation::compute_total_payout( + &T::RewardCurve::get(), + Self::current_era_total_staked(), + T::Currency::total_issuance(), + // Duration of era; more than u64::MAX is rewarded as u64::MAX. + era_duration.saturated_into::(), + ); - let rest = max_payout.saturating_sub(total_payout); - Self::deposit_event(RawEvent::Reward(total_payout, rest)); + // Set previous era reward. + >::insert(current_era - 1, total_payout); - T::Reward::on_unbalanced(total_imbalance); - T::RewardRemainder::on_unbalanced(T::Currency::issue(rest)); + if let Some(era) = current_era.checked_sub(HISTORY_DEPTH) { // TODO TODO: +- 1 ??? + >::remove_prefix(era); } - // Increment current era. - let current_era = CurrentEra::mutate(|s| { *s += 1; *s }); - - CurrentEraStartSessionIndex::mutate(|v| { - *v = start_session_index; + EraStartSessionIndex::mutate(|starts| { + starts.push(start_session_index); + if starts.len() > HISTORY_DEPTH as usize { + starts.remove(0); + } }); + let bonding_duration = T::BondingDuration::get(); BondedEras::mutate(|bonded| { @@ -1471,7 +1465,7 @@ impl Module { }); // Reassign all Stakers. - let (_slot_stake, maybe_new_validators) = Self::select_validators(); + let maybe_new_validators = Self::select_validators(); Self::apply_unapplied_slashes(current_era); maybe_new_validators @@ -1495,10 +1489,10 @@ impl Module { /// Select a new validator set from the assembled stakers and their role preferences. /// - /// Returns the new `SlotStake` value and a set of newly selected _stash_ IDs. + /// Returns a set of newly selected _stash_ IDs. /// /// Assumes storage is coherent with the declaration. - fn select_validators() -> (BalanceOf, Option>) { + fn select_validators() -> Option> { let mut all_nominators: Vec<(T::AccountId, Vec)> = Vec::new(); let all_validator_candidates_iter = >::enumerate(); let all_validators = all_validator_candidates_iter.map(|(who, _pref)| { @@ -1582,14 +1576,16 @@ impl Module { ); } - // Clear Stakers. - for v in Self::current_elected().iter() { - >::remove(v); - } - + let current_era = Self::current_era(); // Populate Stakers and figure out the minimum stake behind a slot. let mut slot_stake = BalanceOf::::max_value(); + let mut total_staked = BalanceOf::::zero(); for (c, s) in supports.into_iter() { + let mut others_exposure = s.others.into_iter() + .map(|(who, value)| IndividualExposure { who, value: to_balance(value) }) + .collect::>>(); + others_exposure.sort_by(|a, b| a.who.cmp(&b.who)); + // build `struct exposure` from `support` let exposure = Exposure { own: to_balance(s.own), @@ -1598,28 +1594,26 @@ impl Module { // of balance and receive some support. This is super unlikely to happen, yet // we simulate it in some tests. total: to_balance(s.total), - others: s.others - .into_iter() - .map(|(who, value)| IndividualExposure { who, value: to_balance(value) }) - .collect::>>(), + others: others_exposure, }; if exposure.total < slot_stake { slot_stake = exposure.total; } - >::insert(&c, exposure.clone()); + total_staked += exposure.total; + >::insert(¤t_era, &c, exposure.clone()); } // Update slot stake. >::put(&slot_stake); - // Set the new validator set in sessions. - >::put(&elected_stashes); + // Update current era total staked. + >::put(total_staked); // In order to keep the property required by `n_session_ending` // that we must return the new validator set even if it's the same as the old, // as long as any underlying economic conditions have changed, we don't attempt // to do any optimization where we compare against the prior set. - (slot_stake, Some(elected_stashes)) + Some(elected_stashes) } else { // There were not enough candidates for even our minimal level of functionality. // This is bad. @@ -1627,7 +1621,7 @@ impl Module { // and let the chain keep producing blocks until we can decide on a sufficiently // substantial set. // TODO: #2494 - (Self::slot_stake(), None) + None } } @@ -1661,45 +1655,26 @@ impl Module { /// /// COMPLEXITY: Complexity is `number_of_validator_to_reward x current_elected_len`. /// If you need to reward lots of validator consider using `reward_by_indices`. - + // // TODO: This is based on a false assumption; that rewarding will always add to a validator // in the current era. It will not, since validator set lags by some amount (currently one // session, but this may be configurable in the future). - + // // TODO: Force the rewarder to pass in the representative era index (or the session index) so // we can figure out which era's reward this should go to and be able to add points to eras that // have already passed. - + // // TODO: We should also ban collecting rewards from an era that may yet have points added to it. // This will likely need an additional API from session to let us know when an era will no // longer have any points added to it (i.e. basically just when the last session whose // validator set is some previous era). - pub fn reward_by_ids(validators_points: impl IntoIterator) { - CurrentEraPointsEarned::mutate(|rewards| { - let current_elected = >::current_elected(); + pub fn reward_by_ids( + era: EraIndex, + validators_points: impl IntoIterator + ) { + >::mutate(era, |rewards| { for (validator, points) in validators_points.into_iter() { - if let Some(index) = current_elected.iter() - .position(|elected| *elected == validator) - { - rewards.add_points_to_index(index as u32, points); - } - } - }); - } - - /// Add reward points to validators using their validator index. - /// - /// For each element in the iterator the given number of points in u32 is added to the - /// validator, thus duplicates are handled. - pub fn reward_by_indices(validators_points: impl IntoIterator) { - // TODO: This can be optimised once #3302 is implemented. - let current_elected_len = >::current_elected().len() as u32; - - CurrentEraPointsEarned::mutate(|rewards| { - for (validator_index, points) in validators_points.into_iter() { - if validator_index < current_elected_len { - rewards.add_points_to_index(validator_index, points); - } + *rewards.entry(validator).or_default() += points; } }); } @@ -1714,18 +1689,20 @@ impl Module { } impl pallet_session::OnSessionEnding for Module { - fn on_session_ending(_ending: SessionIndex, start_session: SessionIndex) -> Option> { - Self::ensure_storage_upgraded(); - Self::new_session(start_session - 1).map(|(new, _old)| new) + fn on_session_ending(session_ending: SessionIndex, will_apply_at: SessionIndex) + -> Option> + { + >::on_session_ending(session_ending, will_apply_at) + .map(|(new, _old)| new) } } impl OnSessionEnding>> for Module { - fn on_session_ending(_ending: SessionIndex, start_session: SessionIndex) + fn on_session_ending(_session_ending: SessionIndex, will_apply_at: SessionIndex) -> Option<(Vec, Vec<(T::AccountId, Exposure>)>)> { Self::ensure_storage_upgraded(); - Self::new_session(start_session - 1) + Self::new_session(will_apply_at) // TODO TODO: why was it -1 before ? } } @@ -1740,15 +1717,21 @@ impl OnFreeBalanceZero for Module { /// * 20 points to the block producer for producing a (non-uncle) block in the relay chain, /// * 2 points to the block producer for each reference to a previously unreferenced uncle, and /// * 1 point to the producer of each referenced uncle block. -impl pallet_authorship::EventHandler for Module { +impl pallet_authorship::EventHandler for Module + where + T: Trait + pallet_authorship::Trait + pallet_session::Trait +{ fn note_author(author: T::AccountId) { - Self::reward_by_ids(vec![(author, 20)]); + Self::reward_by_ids(>::current_index(), vec![(author, 20)]); } fn note_uncle(author: T::AccountId, _age: T::BlockNumber) { - Self::reward_by_ids(vec![ - (>::author(), 2), - (author, 1) - ]) + Self::reward_by_ids( + >::current_index(), + vec![ + (>::author(), 2), + (author, 1) + ] + ) } } @@ -1770,13 +1753,14 @@ impl Convert> for ExposureOf { fn convert(validator: T::AccountId) -> Option>> { - Some(>::stakers(&validator)) + // TODO TODO: which exposure do we want here ??? the one validating or the one "planned" ? + Some(>::stakers(>::current_era_start_session_index(), &validator)) } } impl SelectInitialValidators for Module { fn select_initial_validators() -> Option> { - >::select_validators().1 + >::select_validators() } } @@ -1803,10 +1787,10 @@ impl OnOffenceHandler= current_era_start_session { + let slash_era = if slash_session >= current_era_start_session_index { era_now } else { let eras = BondedEras::get(); From bb7135325abf462dae253fb21f23f831f1c2d97d Mon Sep 17 00:00:00 2001 From: thiolliere Date: Wed, 8 Jan 2020 23:16:54 +0100 Subject: [PATCH 04/75] full implementation --- frame/staking/src/lib.rs | 338 +++++++++++++++++++++++---------------- 1 file changed, 204 insertions(+), 134 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 798b8c87896b4..fd5d4727c517f 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -14,6 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . +// TODO TODO: +// * migration +// * upgrade test +// * new test //! # Staking Module //! //! The Staking module is used to manage funds at stake by network maintainers. @@ -260,6 +264,7 @@ use codec::{HasCompact, Encode, Decode}; use frame_support::{ decl_module, decl_event, decl_storage, ensure, decl_error, weights::SimpleDispatchInfo, + dispatch::DispatchResult, traits::{ Currency, OnFreeBalanceZero, LockIdentifier, LockableCurrency, WithdrawReasons, OnUnbalanced, Imbalance, Get, Time @@ -271,7 +276,7 @@ use sp_runtime::{ RuntimeDebug, curve::PiecewiseLinear, traits::{ - Convert, Zero, One, StaticLookup, CheckedSub, Saturating, Bounded, SaturatedConversion, + Convert, Zero, StaticLookup, CheckedSub, Saturating, Bounded, SaturatedConversion, SimpleArithmetic, EnsureOrigin, } }; @@ -296,6 +301,20 @@ pub type EraIndex = u32; /// Counter for the number of "reward" points earned by a given validator. pub type RewardPoint = u32; +/// Reward points of an era. Used to split era total payout between validators. +/// +/// This points will be used to reward validators and their respective nominators. +#[derive(PartialEq, Encode, Decode, Default, Debug)] +pub struct EraRewardPoints { + /// Total number of points. Equals the sum of reward points for each validator. + total: RewardPoint, + /// The reward points earned by a given validator. + individual: BTreeMap, +} +// TODO TODO: when does this rewards can be spend: we need a mecanism to tell when reward can be +// spend, either by asking session or by just saying only reward from finished session can be spend +// but then we are following sessions delay + /// Indicates the initial status of the staker. #[derive(RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -326,6 +345,7 @@ impl Default for RewardDestination { } /// Preference of what happens regarding validation. +// TODO TODO: put this into the Exposure! #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] pub struct ValidatorPrefs { /// Reward that validator takes up-front; only the rest is split between themselves and @@ -656,49 +676,61 @@ decl_storage! { /// Direct storage APIs can still bypass this protection. Nominators get(fn nominators): linked_map T::AccountId => Option>; - /// Nominators for a particular account that is in action right now. You can't iterate - /// through validators here, but you can find them in the Session module. - /// - /// This is keyed fist by the era index to allow bulk deletion and then the stash account. - /// - /// Is it removed after `HISTORY_DEPTH` eras. - pub Stakers get(fn stakers): double_map hasher(twox_64_concat) EraIndex, - twox_64_concat(T::AccountId) => Exposure>; - // TODO: ^^^ This will need a migration. - // TODO: consider switching this to a simple map EraIndex => Vec - - /// The per-validator era payout for one in the last `HISTORY_DEPTH` eras. - pub EraValidatorReward: map EraIndex => BalanceOf; /// TODO: Will likely need initialising for the migration. - pub CurrentEraTotalStaked get(fn current_era_total_staked): BalanceOf; - // /// The currently elected validator set keyed by stash account ID. // pub CurrentElected get(fn current_elected): Vec; - // TODO TODO: clean this!!! + // TODO TODO: migration: clean this!!! /// The current era index. pub CurrentEra get(fn current_era) config(): EraIndex; - /// The start of the current era. - pub CurrentEraStart get(fn current_era_start): MomentOf; + // /// The start of the current era. + // // TODO TODO: actually no this doesn't match the start of the era at index CurrentEra. + // // TODO TODO: rename ActiveEra + // pub CurrentEraStart get(fn current_era_start): MomentOf; + // TODO TODO: clean this!! - /// The session index at which the era started for the last $HISTORY_DEPTH eras - pub EraStartSessionIndex get(fn era_start_session_index): Vec; + pub ActiveEra get(fn active_era) config(): EraIndex; + + pub ActiveEraStart get(fn active_era_start): MomentOf; // /// The session index at which the current era started. // pub CurrentEraStartSessionIndex get(fn current_era_start_session_index): SessionIndex; // TODO TODO: clean this!! - /// Rewards for the current era. Using indices of current elected set. - RewardPoints get(fn reward_points): map EraIndex => BTreeMap; + /// Nominators for a particular account that is in action right now. You can't iterate + /// through validators here, but you can find them in the Session module. + /// + /// This is keyed fist by the era index to allow bulk deletion and then the stash account. + /// + /// Is it removed after `HISTORY_DEPTH` eras. + pub ErasStakers get(fn eras_stakers): double_map hasher(twox_64_concat) EraIndex, + twox_64_concat(T::AccountId) => Exposure>; + // TODO: ^^^ This will need a migration. + // TODO: consider switching this to a simple map EraIndex => Vec - /// The amount of balance actively at stake for each validator slot, currently. + /// The per-validator era payout for one in the last `HISTORY_DEPTH` eras. /// - /// This is used to derive rewards and punishments. - pub SlotStake get(fn slot_stake) build(|config: &GenesisConfig| { - config.stakers.iter().map(|&(_, _, value, _)| value).min().unwrap_or_default() - }): BalanceOf; + /// Eras that haven't finished yet doesn't have reward. + pub ErasValidatorReward get(fn eras_validator_reward): map EraIndex => BalanceOf; + + /// The session index at which the era started for the last $HISTORY_DEPTH eras + pub ErasStartSessionIndex get(fn eras_start_session_index): map EraIndex => SessionIndex; + + /// Rewards for the last $HISTORY_DEPTH eras. + pub ErasRewardPoints get(fn eras_reward_points): map EraIndex => EraRewardPoints; + + /// The total amount staked for the last $HISTORY_DEPTH eras. + pub ErasTotalStake get(fn eras_total_stake): map EraIndex => BalanceOf; + + ///// The amount of balance actively at stake for each validator slot, currently. + ///// + ///// This is used to derive punishments. + //pub SlotStake get(fn slot_stake) build(|config: &GenesisConfig| { + // config.stakers.iter().map(|&(_, _, value, _)| value).min().unwrap_or_default() + //}): BalanceOf; + //TODO TODO: clean this!! /// True if the next session change will be a new era regardless of index. pub ForceEra get(fn force_era) config(): Forcing; @@ -779,9 +811,8 @@ decl_storage! { decl_event!( pub enum Event where Balance = BalanceOf, ::AccountId { - /// All validators have been rewarded by the first balance; the second is the remainder - /// from the maximum amount of reward. - Reward(Balance, Balance), + /// The staker has been rewarded by this amount. AccountId is controller account. + Reward(AccountId, Balance), /// One validator (and its nominators) has been slashed by the given amount. Slash(AccountId, Balance), /// An old slashing report from a prior era was discarded because it could @@ -811,6 +842,8 @@ decl_error! { InsufficientValue, /// Can not schedule more unlock chunks. NoMoreChunks, + /// Invalid era to reward. + InvalidEraToReward, } } @@ -828,13 +861,13 @@ decl_module! { fn on_initialize() { Self::ensure_storage_upgraded(); - // TODO: Remove old `EraValidatorReward` and `Stakers` entries. + // TODO: Remove old `ErasValidatorReward` and `ErasStakers` entries. } fn on_finalize() { // Set the start of the first era. - if !>::exists() { - >::put(T::Time::now()); + if !>::exists() { + >::put(T::Time::now()); } } @@ -888,7 +921,7 @@ decl_module! { total: value, active: value, unlocking: vec![], - last_reward: Self::current_era_start_session_index(), + last_reward: Self::eras_start_session_index(Self::current_era()), }; Self::update_ledger(&controller, &item); } @@ -1243,7 +1276,9 @@ decl_module! { /// economically (all nominators are required to place a minimum stake). /// Compute: O(MAX_NOMINATIONS * logN). // TODO: Limit the amount of nominators that can be assigned to a validator by Phragmen. - fn payout_nominator(origin, era: EraIndex, validators: Vec) { + fn payout_nominator(origin, era: EraIndex, validators: Vec) + -> DispatchResult + { let who = ensure_signed(origin)?; Self::do_payout_nominator(who, era, validators) } @@ -1255,7 +1290,7 @@ decl_module! { /// then it indicates an instruction to skip the payout of all previous eras. /// /// WARNING: Incorrect arguments here can result in loss of payout. Be very careful. - fn payout_validator(origin, era: EraIndex) { + fn payout_validator(origin, era: EraIndex) -> DispatchResult { let who = ensure_signed(origin)?; Self::do_payout_validator(who, era) } @@ -1265,13 +1300,6 @@ decl_module! { impl Module { // PUBLIC IMMUTABLES - fn current_era_start_session_index() -> SessionIndex { - EraStartSessionIndex::get() - .last() - .map(|i| *i) - .unwrap_or(0) - } - /// The total balance that can be slashed from a stash account as of right now. pub fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf { Self::bonded(stash).and_then(Self::ledger).map(|l| l.active).unwrap_or_default() @@ -1279,29 +1307,94 @@ impl Module { // MUTABLES (DANGEROUS) - fn do_payout_nominator(who: T::AccountId, era: EraIndex, validators: Vec) { - // TODO: lookup `who` in ledger to get `StakingLedger`. - // TODO: check most recent and ensure it's less than era - // TODO: bump the staking ledger's era to `era` - // TODO: grab the payout info for the era - // TODO: for each in `validators`: - // TODO: - grab exposure information for era - // TODO: - lookup `who` and accumulate their reward - // TODO: reward `who` accordingly. + fn do_payout_nominator(who: T::AccountId, era: EraIndex, validators: Vec) + -> DispatchResult + { + let mut nominator_ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; + if nominator_ledger.last_reward >= era { + return Err(Error::::InvalidEraToReward.into()); + } + + nominator_ledger.last_reward = era; + >::insert(&who, &nominator_ledger); + + let mut reward = Perbill::zero(); + let era_reward_points = >::get(&era); + for validator in validators { + let commission = Self::validators(&validator).commission; + let validator_exposure = >::get(&era, &validator); + + if let Ok(nominator_exposure) = validator_exposure.others + .binary_search_by(|exposure| exposure.who.cmp(&nominator_ledger.stash)) + .map(|indice| &validator_exposure.others[indice]) + { + let nominator_exposure_part = Perbill::from_rational_approximation( + nominator_exposure.value, + validator_exposure.total, + ); + let validator_point = era_reward_points.individual.get(&validator) + .map(|points| *points) + .unwrap_or_else(|| Zero::zero()); + let validator_point_part = Perbill::from_rational_approximation( + validator_point, + era_reward_points.total, + ); + reward = reward.saturating_add( + validator_point_part + .saturating_mul(Perbill::one().saturating_sub(commission)) + .saturating_mul(nominator_exposure_part) + ); + } + } + + // This is zero if the era is not finished yet. + let era_payout = >::get(&era); + if let Some(imbalance) = Self::make_payout(&nominator_ledger.stash, reward * era_payout) { + Self::deposit_event(RawEvent::Reward(who, imbalance.peek())); + } + + Ok(()) } - fn do_payout_validator(who: T::AccountId, era: EraIndex) { - // TODO: lookup `who` in ledger to get `StakingLedger`. - // TODO: check most recent and ensure it's less than era - // TODO: bump the staking ledger's era to `era` - // TODO: grab the payout and exposure information for era - // TODO: reward `who` accordingly (if they were a validator). + fn do_payout_validator(who: T::AccountId, era: EraIndex) -> DispatchResult { + let mut ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; + if ledger.last_reward >= era { + return Err(Error::::InvalidEraToReward.into()); + } + + ledger.last_reward = era; + >::insert(&who, &ledger); + + let era_reward_points = >::get(&era); + let commission = Self::validators(&ledger.stash).commission; + let exposure = >::get(&era, &ledger.stash); + + let exposure_part = Perbill::from_rational_approximation( + exposure.own, + exposure.total, + ); + let validator_point = era_reward_points.individual.get(&ledger.stash) + .map(|points| *points) + .unwrap_or_else(|| Zero::zero()); + let validator_point_part = Perbill::from_rational_approximation( + validator_point, + era_reward_points.total, + ); + let reward = validator_point_part.saturating_mul(commission.saturating_add(exposure_part)); + // This is zero if the era is not finished yet. + let era_payout = >::get(&era); + if let Some(imbalance) = Self::make_payout(&ledger.stash, reward * era_payout) { + Self::deposit_event(RawEvent::Reward(who, imbalance.peek())); + } + + Ok(()) } // TODO: at the end of session, ensure that points are accumulated within the correct era. // TODO: currently, validator set changes lag by one session, therefore, in the first session of // TODO: an era, the points should be accumulated by the validator set of the era before. // TODO TODO: I'm not sure I understand that, staking doesn't rely on delay anymore at all. it just know that after HISTORY_DEPTH it removes the rewards. + // TODO TODO: either we make the reward giving the era to reward, or we follow what is the current era used in session! /// Update the ledger for a controller. This will also update the stash lock. The lock will /// will lock the entire funds except paying for further transactions. @@ -1353,40 +1446,13 @@ impl Module { } } - // /// Reward a given validator by a specific amount. Add the reward to the validator's, and its - // /// nominators' balance, pro-rata based on their exposure, after having removed the validator's - // /// pre-payout cut. - // fn reward_validator(stash: &T::AccountId, reward: BalanceOf) -> PositiveImbalanceOf { - // let commission = Self::validators(stash).commission * reward; - // let reward = reward.saturating_sub(commission); - // let mut imbalance = >::zero(); - // let validator_cut = if reward.is_zero() { - // Zero::zero() - // } else { - // let exposure = Self::stakers(stash); - // let total = exposure.total.max(One::one()); - - // for i in &exposure.others { - // let per_u64 = Perbill::from_rational_approximation(i.value, total); - // imbalance.maybe_subsume(Self::make_payout(&i.who, per_u64 * reward)); - // } - - // let per_u64 = Perbill::from_rational_approximation(exposure.own, total); - // per_u64 * reward - // }; - - // imbalance.maybe_subsume(Self::make_payout(stash, validator_cut + commission)); - - // imbalance - // } - /// Session has just ended. Provide the validator set for the next session if it's an era-end, along /// with the exposure of the prior validator set. fn new_session(session_index: SessionIndex) -> Option<(Vec, Vec<(T::AccountId, Exposure>)>)> { - let era_length = session_index.checked_sub(Self::current_era_start_session_index()) - .unwrap_or(0); + let era_length = session_index + .checked_sub(Self::eras_start_session_index(Self::current_era())).unwrap_or(0); match ForceEra::get() { Forcing::ForceNew => ForceEra::kill(), @@ -1396,50 +1462,57 @@ impl Module { } let validators = T::SessionInterface::validators(); let prior = validators.into_iter() - .map(|v| { let e = Self::stakers(&Self::current_era(), &v); (v, e) }) + .map(|v| { let e = Self::eras_stakers(&Self::current_era(), &v); (v, e) }) .collect(); Self::new_era(session_index).map(move |new| (new, prior)) } - /// The era has changed - enact new staking set. - /// - /// NOTE: This always happens immediately before a session change to ensure that new validators - /// get a chance to set their session keys. - fn new_era(start_session_index: SessionIndex) -> Option> { - // Increment current era. - let current_era = CurrentEra::mutate(|s| { *s += 1; *s }); + fn end_session(session_index: SessionIndex) { + if ErasStartSessionIndex::get(Self::active_era() + 1) == session_index + 1 { + Self::end_era(session_index); + } + } + fn end_era(_session_index: SessionIndex) { let now = T::Time::now(); - // Set new era start - let previous_era_start = >::mutate(|v| { - sp_std::mem::replace(v, now) - }); + // Set new active era start + let previous_era_start = >::mutate(|v| sp_std::mem::replace(v, now)); + let previous_era = ActiveEra::mutate(|index| sp_std::mem::replace(index, *index + 1)); let era_duration = now - previous_era_start; let (total_payout, _max_payout) = inflation::compute_total_payout( &T::RewardCurve::get(), - Self::current_era_total_staked(), + Self::eras_total_stake(previous_era), T::Currency::total_issuance(), // Duration of era; more than u64::MAX is rewarded as u64::MAX. era_duration.saturated_into::(), ); // Set previous era reward. - >::insert(current_era - 1, total_payout); + >::insert(previous_era, total_payout); + } - if let Some(era) = current_era.checked_sub(HISTORY_DEPTH) { // TODO TODO: +- 1 ??? - >::remove_prefix(era); + /// The era has changed - enact new staking set. + /// + /// NOTE: This always happens immediately before a session change to ensure that new validators + /// get a chance to set their session keys. + fn new_era(start_session_index: SessionIndex) -> Option> { + // Increment current era. + let current_era = CurrentEra::mutate(|s| { *s += 1; *s }); + // TODO TODO: either start_session_index strictly increase or we must remove old era overriden + ErasStartSessionIndex::insert(¤t_era, &start_session_index); + + // Clean old era information. + if let Some(era) = current_era.checked_sub(HISTORY_DEPTH) { + >::remove_prefix(era); + >::remove(era); + >::remove(era); + >::remove(era); + ErasStartSessionIndex::remove(era); } - EraStartSessionIndex::mutate(|starts| { - starts.push(start_session_index); - if starts.len() > HISTORY_DEPTH as usize { - starts.remove(0); - } - }); - let bonding_duration = T::BondingDuration::get(); BondedEras::mutate(|bonded| { @@ -1464,7 +1537,7 @@ impl Module { } }); - // Reassign all Stakers. + // Reassign all ErasStakers. let maybe_new_validators = Self::select_validators(); Self::apply_unapplied_slashes(current_era); @@ -1492,6 +1565,7 @@ impl Module { /// Returns a set of newly selected _stash_ IDs. /// /// Assumes storage is coherent with the declaration. + // TODO TODO: maybe remove storage alteration here and return types!!! fn select_validators() -> Option> { let mut all_nominators: Vec<(T::AccountId, Vec)> = Vec::new(); let all_validator_candidates_iter = >::enumerate(); @@ -1577,7 +1651,7 @@ impl Module { } let current_era = Self::current_era(); - // Populate Stakers and figure out the minimum stake behind a slot. + // Populate ErasStakers and figure out the minimum stake behind a slot. let mut slot_stake = BalanceOf::::max_value(); let mut total_staked = BalanceOf::::zero(); for (c, s) in supports.into_iter() { @@ -1600,14 +1674,11 @@ impl Module { slot_stake = exposure.total; } total_staked += exposure.total; - >::insert(¤t_era, &c, exposure.clone()); + >::insert(¤t_era, &c, exposure.clone()); } - // Update slot stake. - >::put(&slot_stake); - // Update current era total staked. - >::put(total_staked); + >::insert(¤t_era, total_staked); // In order to keep the property required by `n_session_ending` // that we must return the new validator set even if it's the same as the old, @@ -1669,12 +1740,12 @@ impl Module { // longer have any points added to it (i.e. basically just when the last session whose // validator set is some previous era). pub fn reward_by_ids( - era: EraIndex, validators_points: impl IntoIterator ) { - >::mutate(era, |rewards| { + >::mutate(Self::active_era(), |era_rewards| { for (validator, points) in validators_points.into_iter() { - *rewards.entry(validator).or_default() += points; + *era_rewards.individual.entry(validator).or_default() += points; + era_rewards.total += points; } }); } @@ -1698,11 +1769,13 @@ impl pallet_session::OnSessionEnding for Module { } impl OnSessionEnding>> for Module { - fn on_session_ending(_session_ending: SessionIndex, will_apply_at: SessionIndex) + fn on_session_ending(session_ending: SessionIndex, will_apply_at: SessionIndex) -> Option<(Vec, Vec<(T::AccountId, Exposure>)>)> { Self::ensure_storage_upgraded(); - Self::new_session(will_apply_at) // TODO TODO: why was it -1 before ? + let maybe_validator_sets = Self::new_session(will_apply_at); // TODO TODO: why was it -1 before ? + Self::end_session(session_ending); + maybe_validator_sets } } @@ -1722,16 +1795,13 @@ impl pallet_authorship::EventHandler for Module T: Trait + pallet_authorship::Trait + pallet_session::Trait { fn note_author(author: T::AccountId) { - Self::reward_by_ids(>::current_index(), vec![(author, 20)]); + Self::reward_by_ids(vec![(author, 20)]) } fn note_uncle(author: T::AccountId, _age: T::BlockNumber) { - Self::reward_by_ids( - >::current_index(), - vec![ - (>::author(), 2), - (author, 1) - ] - ) + Self::reward_by_ids(vec![ + (>::author(), 2), + (author, 1) + ]) } } @@ -1753,8 +1823,8 @@ impl Convert> for ExposureOf { fn convert(validator: T::AccountId) -> Option>> { - // TODO TODO: which exposure do we want here ??? the one validating or the one "planned" ? - Some(>::stakers(>::current_era_start_session_index(), &validator)) + // TODO TODO: which exposure do we want here ??? active era or current era ?? + Some(>::eras_stakers(>::current_era(), &validator)) } } @@ -1787,7 +1857,7 @@ impl OnOffenceHandler= current_era_start_session_index { From 3a4a9bebd22180fbda01cfa485950e3df775e6a6 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 9 Jan 2020 14:21:52 +0100 Subject: [PATCH 05/75] fix preferences --- frame/staking/src/lib.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index fd5d4727c517f..1a81459be5935 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -710,6 +710,10 @@ decl_storage! { // TODO: ^^^ This will need a migration. // TODO: consider switching this to a simple map EraIndex => Vec + pub ErasValidatorPrefs get(fn eras_validator_prefs): + double_map hasher(twox_64_concat) EraIndex, twox_64_concat(T::AccountId) + => ValidatorPrefs; + /// The per-validator era payout for one in the last `HISTORY_DEPTH` eras. /// /// Eras that haven't finished yet doesn't have reward. @@ -1321,7 +1325,7 @@ impl Module { let mut reward = Perbill::zero(); let era_reward_points = >::get(&era); for validator in validators { - let commission = Self::validators(&validator).commission; + let commission = Self::eras_validator_prefs(&era, &validator).commission; let validator_exposure = >::get(&era, &validator); if let Ok(nominator_exposure) = validator_exposure.others @@ -1569,11 +1573,14 @@ impl Module { fn select_validators() -> Option> { let mut all_nominators: Vec<(T::AccountId, Vec)> = Vec::new(); let all_validator_candidates_iter = >::enumerate(); - let all_validators = all_validator_candidates_iter.map(|(who, _pref)| { + let all_validators_and_prefs = all_validator_candidates_iter.map(|(who, pref)| { let self_vote = (who.clone(), vec![who.clone()]); all_nominators.push(self_vote); - who - }).collect::>(); + (who, pref) + }).collect::>(); + let all_validators = all_validators_and_prefs.iter() + .map(|(who, _pref)| who.clone()) + .collect::>(); let nominator_votes = >::enumerate().map(|(nominator, nominations)| { let Nominations { submitted_in, mut targets, suppressed: _ } = nominations; @@ -1677,8 +1684,15 @@ impl Module { >::insert(¤t_era, &c, exposure.clone()); } - // Update current era total staked. + // Insert current era informations >::insert(¤t_era, total_staked); + let default_pref = ValidatorPrefs::default(); + for stash in &elected_stashes { + let pref = all_validators_and_prefs.get(stash) + // This should always succeed but better to be safe + .unwrap_or(&default_pref); + >::insert(¤t_era, stash, pref); + } // In order to keep the property required by `n_session_ending` // that we must return the new validator set even if it's the same as the old, From 534509551f3c72d52c56023b055b7f29bb124ca9 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 9 Jan 2020 16:14:46 +0100 Subject: [PATCH 06/75] update comments --- frame/staking/src/lib.rs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 29d2c2c3e4da7..e70adecee9e7b 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -17,6 +17,7 @@ // TODO TODO: // * migration // * upgrade test +// * update doc // * new test //! # Staking Module //! @@ -311,9 +312,6 @@ pub struct EraRewardPoints { /// The reward points earned by a given validator. individual: BTreeMap, } -// TODO TODO: when does this rewards can be spend: we need a mecanism to tell when reward can be -// spend, either by asking session or by just saying only reward from finished session can be spend -// but then we are following sessions delay /// Indicates the initial status of the staker. #[derive(RuntimeDebug)] @@ -345,7 +343,6 @@ impl Default for RewardDestination { } /// Preference of what happens regarding validation. -// TODO TODO: put this into the Exposure! #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] pub struct ValidatorPrefs { /// Reward that validator takes up-front; only the rest is split between themselves and @@ -700,8 +697,6 @@ decl_storage! { /// Direct storage APIs can still bypass this protection. Nominators get(fn nominators): linked_map T::AccountId => Option>; - /// TODO: Will likely need initialising for the migration. - // /// The currently elected validator set keyed by stash account ID. // pub CurrentElected get(fn current_elected): Vec; // TODO TODO: migration: clean this!!! @@ -711,7 +706,6 @@ decl_storage! { // /// The start of the current era. // // TODO TODO: actually no this doesn't match the start of the era at index CurrentEra. - // // TODO TODO: rename ActiveEra // pub CurrentEraStart get(fn current_era_start): MomentOf; // TODO TODO: clean this!! @@ -758,7 +752,7 @@ decl_storage! { //pub SlotStake get(fn slot_stake) build(|config: &GenesisConfig| { // config.stakers.iter().map(|&(_, _, value, _)| value).min().unwrap_or_default() //}): BalanceOf; - //TODO TODO: clean this!! + //TODO TODO: Slot stake is not longer used. clean this!! /// True if the next session change will be a new era regardless of index. pub ForceEra get(fn force_era) config(): Forcing; @@ -1443,8 +1437,6 @@ impl Module { // TODO: at the end of session, ensure that points are accumulated within the correct era. // TODO: currently, validator set changes lag by one session, therefore, in the first session of // TODO: an era, the points should be accumulated by the validator set of the era before. - // TODO TODO: I'm not sure I understand that, staking doesn't rely on delay anymore at all. it just know that after HISTORY_DEPTH it removes the rewards. - // TODO TODO: either we make the reward giving the era to reward, or we follow what is the current era used in session! /// Update the ledger for a controller. This will also update the stash lock. The lock will /// will lock the entire funds except paying for further transactions. @@ -1552,6 +1544,7 @@ impl Module { // Increment current era. let current_era = CurrentEra::mutate(|s| { *s += 1; *s }); // TODO TODO: either start_session_index strictly increase or we must remove old era overriden + // TODO TODO: update doc or code to make this correct ErasStartSessionIndex::insert(¤t_era, &start_session_index); // Clean old era information. @@ -1615,7 +1608,6 @@ impl Module { /// Returns a set of newly selected _stash_ IDs. /// /// Assumes storage is coherent with the declaration. - // TODO TODO: maybe remove storage alteration here and return types!!! fn select_validators() -> Option> { let mut all_nominators: Vec<(T::AccountId, Vec)> = Vec::new(); let all_validator_candidates_iter = >::enumerate(); @@ -1833,7 +1825,7 @@ impl OnSessionEnding -> Option<(Vec, Vec<(T::AccountId, Exposure>)>)> { Self::ensure_storage_upgraded(); - let maybe_validator_sets = Self::new_session(will_apply_at); // TODO TODO: why was it -1 before ? + let maybe_validator_sets = Self::new_session(will_apply_at); Self::end_session(session_ending); maybe_validator_sets } @@ -1883,7 +1875,7 @@ impl Convert> for ExposureOf { fn convert(validator: T::AccountId) -> Option>> { - // TODO TODO: which exposure do we want here ??? active era or current era ?? + // TODO TODO: which exposure do we want here ? active era or current era ? Some(>::eras_stakers(>::current_era(), &validator)) } } From dbe3a644fa7e652059fa7011cb738f120e05c08c Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 9 Jan 2020 17:54:38 +0100 Subject: [PATCH 07/75] upgrade test WIP --- frame/staking/src/mock.rs | 103 ++-- frame/staking/src/tests.rs | 1062 +++++++++++++++++++----------------- 2 files changed, 608 insertions(+), 557 deletions(-) diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 2fdd62457e215..2659ced39ddc3 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -25,13 +25,13 @@ use sp_staking::{SessionIndex, offence::{OffenceDetails, OnOffenceHandler}}; use sp_core::{H256, crypto::key_types}; use sp_io; use frame_support::{ - assert_ok, impl_outer_origin, parameter_types, StorageLinkedMap, StorageValue, + assert_ok, impl_outer_origin, parameter_types, StorageLinkedMap, StorageValue, StorageMap, traits::{Currency, Get, FindAuthor}, weights::Weight, }; use crate::{ EraIndex, GenesisConfig, Module, Trait, StakerStatus, ValidatorPrefs, RewardDestination, - Nominators, inflation + Nominators, inflation, SessionInterface, Exposure, }; /// The AccountId alias in this test module. @@ -373,48 +373,55 @@ pub type Session = pallet_session::Module; pub type Timestamp = pallet_timestamp::Module; pub type Staking = Module; -pub fn check_exposure_all() { - Staking::current_elected().into_iter().for_each(|acc| check_exposure(acc)); +pub fn check_exposure_all(era: EraIndex) { + // TODO TODO: + // Staking::validator_for_era(era).into_iter().for_each(|info| check_exposure(info)); } -pub fn check_nominator_all() { - >::enumerate().for_each(|(acc, _)| check_nominator_exposure(acc)); +pub fn check_nominator_all(era: EraIndex) { + >::enumerate() + .for_each(|(acc, _)| check_nominator_exposure(era, acc)); } /// Check for each selected validator: expo.total = Sum(expo.other) + expo.own -pub fn check_exposure(stash: u64) { - assert_is_stash(stash); - let expo = Staking::stakers(&stash); - assert_eq!( - expo.total as u128, expo.own as u128 + expo.others.iter().map(|e| e.value as u128).sum::(), - "wrong total exposure for {:?}: {:?}", stash, expo, - ); +pub fn check_exposure(stash: AccountId) { + // TODO TODO: impl + // let stash = val_info.stash; + // let expo = val_info.exposure; + + // assert_is_stash(stash); + // assert_eq!( + // expo.total as u128, expo.own as u128 + expo.others.iter().map(|e| e.value as u128).sum::(), + // "wrong total exposure for {:?}: {:?}", stash, expo, + // ); } /// Check that for each nominator: slashable_balance > sum(used_balance) /// Note: we might not consume all of a nominator's balance, but we MUST NOT over spend it. -pub fn check_nominator_exposure(stash: u64) { - assert_is_stash(stash); - let mut sum = 0; - Staking::current_elected() - .iter() - .map(|v| Staking::stakers(v)) - .for_each(|e| e.others.iter() - .filter(|i| i.who == stash) - .for_each(|i| sum += i.value)); - let nominator_stake = Staking::slashable_balance_of(&stash); - // a nominator cannot over-spend. - assert!( - nominator_stake >= sum, - "failed: Nominator({}) stake({}) >= sum divided({})", stash, nominator_stake, sum, - ); -} - -pub fn assert_is_stash(acc: u64) { +pub fn check_nominator_exposure(era: EraIndex, stash: AccountId) { + // TODO TODO: impl + // assert_is_stash(stash); + // let mut sum = 0; + // Staking::validator_for_era(era) + // .iter() + // .for_each(|e| { + // e.exposure.others.iter() + // .filter(|i| i.who == stash) + // .for_each(|i| sum += i.value) + // }); + // let nominator_stake = Staking::slashable_balance_of(&stash); + // // a nominator cannot over-spend. + // assert!( + // nominator_stake >= sum, + // "failed: Nominator({}) stake({}) >= sum divided({})", stash, nominator_stake, sum, + // ); +} + +pub fn assert_is_stash(acc: AccountId) { assert!(Staking::bonded(&acc).is_some(), "Not a stash."); } -pub fn assert_ledger_consistent(stash: u64) { +pub fn assert_ledger_consistent(stash: AccountId) { assert_is_stash(stash); let ledger = Staking::ledger(stash - 1).unwrap(); @@ -444,8 +451,6 @@ pub fn advance_session() { } pub fn start_session(session_index: SessionIndex) { - // Compensate for session delay - let session_index = session_index + 1; for i in Session::current_index()..session_index { System::set_block_number((i + 1).into()); Timestamp::set_timestamp(System::block_number() * 1000); @@ -457,22 +462,21 @@ pub fn start_session(session_index: SessionIndex) { pub fn start_era(era_index: EraIndex) { start_session((era_index * 3).into()); - assert_eq!(Staking::current_era(), era_index); + assert_eq!(Staking::active_era(), era_index); } pub fn current_total_payout_for_duration(duration: u64) -> u64 { inflation::compute_total_payout( ::RewardCurve::get(), - >::slot_stake() * 2, + Staking::eras_total_stake(Staking::active_era()), Balances::total_issuance(), duration, ).0 } pub fn reward_all_elected() { - let rewards = >::current_elected().iter() - .map(|v| (*v, 1)) - .collect::>(); + let rewards = ::SessionInterface::validators().into_iter() + .map(|v| (v, 1)); >::reward_by_ids(rewards) } @@ -496,8 +500,8 @@ pub fn on_offence_in_era( } } - if Staking::current_era() == era { - Staking::on_offence(offenders, slash_fraction, Staking::current_era_start_session_index()); + if Staking::active_era() == era { + Staking::on_offence(offenders, slash_fraction, Staking::eras_start_session_index(era)); } else { panic!("cannot slash in era {}", era); } @@ -507,6 +511,21 @@ pub fn on_offence_now( offenders: &[OffenceDetails>], slash_fraction: &[Perbill], ) { - let now = Staking::current_era(); + let now = Staking::active_era(); on_offence_in_era(offenders, slash_fraction, now) } + +pub fn validator_current_exposure(stash: AccountId) -> Exposure { + Staking::eras_stakers(Staking::active_era(), stash) +} + +pub fn bypass_logic_change_current_exposure(stash: AccountId, exposure: Exposure) { + // TODO TODO: we can actually probably remove this function or just upgrade it. + // >::mutate(Staking::active_era(), |infos| { + // for info in infos { + // if info.stash == stash { + // info.exposure = exposure.clone(); + // } + // } + // }); +} diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 572a6667ef7b6..e5cf323ee1f65 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -67,12 +67,12 @@ fn basic_setup_works() { // Account 10 controls the stash from account 11, which is 100 * balance_factor units assert_eq!( Staking::ledger(&10), - Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![] }) + Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![], last_reward: 0 }) ); // Account 20 controls the stash from account 21, which is 200 * balance_factor units assert_eq!( Staking::ledger(&20), - Some(StakingLedger { stash: 21, total: 1000, active: 1000, unlocking: vec![] }) + Some(StakingLedger { stash: 21, total: 1000, active: 1000, unlocking: vec![], last_reward: 0 }) ); // Account 1 does not control any stash assert_eq!(Staking::ledger(&1), None); @@ -86,32 +86,48 @@ fn basic_setup_works() { assert_eq!( Staking::ledger(100), - Some(StakingLedger { stash: 101, total: 500, active: 500, unlocking: vec![] }) + Some(StakingLedger { stash: 101, total: 500, active: 500, unlocking: vec![], last_reward: 0 }) ); assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); if cfg!(feature = "equalize") { assert_eq!( - Staking::stakers(11), - Exposure { total: 1250, own: 1000, others: vec![ IndividualExposure { who: 101, value: 250 }] } + Staking::eras_stakers(Staking::active_era(), 11), + Exposure { + total: 1250, + own: 1000, + others: vec![ IndividualExposure { who: 101, value: 250 }] + }, ); assert_eq!( - Staking::stakers(21), - Exposure { total: 1250, own: 1000, others: vec![ IndividualExposure { who: 101, value: 250 }] } + Staking::eras_stakers(Staking::active_era(), 21), + Exposure { + total: 1250, + own: 1000, + others: vec![ IndividualExposure { who: 101, value: 250 }] + }, ); // initial slot_stake - assert_eq!(Staking::slot_stake(), 1250); + assert_eq!(Staking::eras_total_stake(Staking::active_era()), 2500); } else { assert_eq!( - Staking::stakers(11), - Exposure { total: 1125, own: 1000, others: vec![ IndividualExposure { who: 101, value: 125 }] } + Staking::eras_stakers(Staking::active_era(), 11), + Exposure { + total: 1125, + own: 1000, + others: vec![ IndividualExposure { who: 101, value: 125 }] + }, ); assert_eq!( - Staking::stakers(21), - Exposure { total: 1375, own: 1000, others: vec![ IndividualExposure { who: 101, value: 375 }] } + Staking::eras_stakers(Staking::active_era(), 21), + Exposure { + total: 1375, + own: 1000, + others: vec![ IndividualExposure { who: 101, value: 375 }] + }, ); // initial slot_stake - assert_eq!(Staking::slot_stake(), 1125); + assert_eq!(Staking::eras_total_stake(Staking::active_era()), 2500); } @@ -119,7 +135,7 @@ fn basic_setup_works() { assert_eq!(Staking::validator_count(), 2); // Initial Era and session - assert_eq!(Staking::current_era(), 0); + assert_eq!(Staking::active_era(), 0); // Account 10 has `balance_factor` free balance assert_eq!(Balances::free_balance(&10), 1); @@ -129,8 +145,8 @@ fn basic_setup_works() { assert_eq!(Staking::force_era(), Forcing::NotForcing); // All exposures must be correct. - check_exposure_all(); - check_nominator_all(); + check_exposure_all(Staking::active_era()); + check_nominator_all(Staking::active_era()); }); } @@ -139,10 +155,10 @@ fn change_controller_works() { ExtBuilder::default().build().execute_with(|| { assert_eq!(Staking::bonded(&11), Some(10)); - assert!(>::enumerate().map(|(c, _)| c).collect::>().contains(&11)); + assert!(Session::validators().contains(&11)); // 10 can control 11 who is initially a validator. assert_ok!(Staking::chill(Origin::signed(10))); - assert!(!>::enumerate().map(|(c, _)| c).collect::>().contains(&11)); + assert!(Session::validators().contains(&11)); assert_ok!(Staking::set_controller(Origin::signed(11), 5)); @@ -157,47 +173,25 @@ fn change_controller_works() { } #[test] +#[cfg(feature = "equalize")] fn rewards_should_work() { // should check that: // * rewards get recorded per session // * rewards get paid per Era // * Check that nominators are also rewarded - ExtBuilder::default().nominate(false).build().execute_with(|| { - // Init some balances - let _ = Balances::make_free_balance_be(&2, 500); - - let delay = 1000; - let init_balance_2 = Balances::total_balance(&2); + ExtBuilder::default().nominate(true).build().execute_with(|| { let init_balance_10 = Balances::total_balance(&10); let init_balance_11 = Balances::total_balance(&11); + let init_balance_20 = Balances::total_balance(&20); + let init_balance_21 = Balances::total_balance(&21); + let init_balance_100 = Balances::total_balance(&100); + let init_balance_101 = Balances::total_balance(&101); - // Set payee to controller - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - - // Initial config should be correct - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 0); - - // Add a dummy nominator. - // - // Equal division indicates that the reward will be equally divided among validator and - // nominator. - >::insert(&11, Exposure { - own: 500, - total: 1000, - others: vec![IndividualExposure {who: 2, value: 500 }] - }); - - >::insert(&2, RewardDestination::Stash); - assert_eq!(Staking::payee(2), RewardDestination::Stash); - assert_eq!(Staking::payee(11), RewardDestination::Controller); + // Check state + Payee::::insert(11, RewardDestination::Controller); + Payee::::insert(21, RewardDestination::Controller); + Payee::::insert(101, RewardDestination::Controller); - let mut block = 3; // Block 3 => Session 1 => Era 0 - System::set_block_number(block); - Timestamp::set_timestamp(block * 5000); // on time. - Session::on_initialize(System::block_number()); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 1); >::reward_by_ids(vec![(11, 50)]); >::reward_by_ids(vec![(11, 50)]); // This is the second validator of the current elected set. @@ -206,70 +200,51 @@ fn rewards_should_work() { >::reward_by_ids(vec![(1001, 10_000)]); // Compute total payout now for whole duration as other parameter won't change - let total_payout = current_total_payout_for_duration(9 * 5 * 1000); - assert!(total_payout > 10); // Test is meaningful if reward something - - // No reward yet - assert_eq!(Balances::total_balance(&2), init_balance_2); - assert_eq!(Balances::total_balance(&10), init_balance_10); - assert_eq!(Balances::total_balance(&11), init_balance_11); - - block = 6; // Block 6 => Session 2 => Era 0 - System::set_block_number(block); - Timestamp::set_timestamp(block * 5000 + delay); // a little late. - Session::on_initialize(System::block_number()); - assert_eq!(Staking::current_era(), 0); - assert_eq!(Session::current_index(), 2); + let total_payout_0 = current_total_payout_for_duration(3 * 1000); + assert!(total_payout_0 > 10); // Test is meaningful if reward something - block = 9; // Block 9 => Session 3 => Era 1 - System::set_block_number(block); - Timestamp::set_timestamp(block * 5000); // back to being on time. no delays - Session::on_initialize(System::block_number()); - assert_eq!(Staking::current_era(), 1); - assert_eq!(Session::current_index(), 3); + start_session(1); - // 11 validator has 2/3 of the total rewards and half half for it and its nominator - assert_eq_error_rate!(Balances::total_balance(&2), init_balance_2 + total_payout / 3, 1); - assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + total_payout / 3, 1); + assert_eq!(Balances::total_balance(&10), init_balance_10); assert_eq!(Balances::total_balance(&11), init_balance_11); - }); -} - -#[test] -fn multi_era_reward_should_work() { - // Should check that: - // The value of current_session_reward is set at the end of each era, based on - // slot_stake and session_reward. - ExtBuilder::default().nominate(false).build().execute_with(|| { - let init_balance_10 = Balances::total_balance(&10); - - // Set payee to controller - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - - // Compute now as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3000); - assert!(total_payout_0 > 10); // Test is meaningfull if reward something - >::reward_by_ids(vec![(11, 1)]); + assert_eq!(Balances::total_balance(&20), init_balance_20); + assert_eq!(Balances::total_balance(&21), init_balance_21); + assert_eq!(Balances::total_balance(&100), init_balance_100); + assert_eq!(Balances::total_balance(&101), init_balance_101); + assert_eq!(Session::validators(), vec![11, 21]); + assert_eq!(Staking::eras_reward_points(Staking::active_era()), EraRewardPoints { + total: 50*3, + individual: vec![(11, 100), (21, 50)].into_iter().collect(), + }); - start_session(0); - start_session(1); start_session(2); start_session(3); - assert_eq!(Staking::current_era(), 1); - assert_eq!(Balances::total_balance(&10), init_balance_10 + total_payout_0); + assert_eq!(Staking::active_era(), 1); - start_session(4); + assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + total_payout_0*2/3*1000/1250, 2); + assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2); + assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + total_payout_0*1/3*1000/1250, 2); + assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2); + assert_eq_error_rate!(Balances::total_balance(&100), init_balance_100 + total_payout_0*250/1250, 2); + assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); - let total_payout_1 = current_total_payout_for_duration(3000); - assert!(total_payout_1 > 10); // Test is meaningfull if reward something - >::reward_by_ids(vec![(11, 101)]); + assert_eq!(Session::validators(), vec![11, 21]); + // >::reward_by_indices(vec![(0, 1)]); TODO TODO THis has been removed + >::reward_by_ids(vec![(11, 1)]); - // new era is triggered here. - start_session(5); + // Compute total payout now for whole duration as other parameter won't change + let total_payout_1 = current_total_payout_for_duration(3 * 1000); + assert!(total_payout_1 > 10); // Test is meaningful if reward something - // pay time - assert_eq!(Balances::total_balance(&10), init_balance_10 + total_payout_0 + total_payout_1); + start_era(2); + + assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + (total_payout_0*2/3 + total_payout_1)*1000/1250, 2); + assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2); + assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + total_payout_0*1/3*1000/1250, 2); + assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2); + assert_eq_error_rate!(Balances::total_balance(&100), init_balance_100 + (total_payout_0 + total_payout_1)*250/1250, 2); + assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); }); } @@ -284,6 +259,9 @@ fn staking_should_work() { .fair(false) // to give 20 more staked value .build() .execute_with(|| { + // --- Block 1: + start_session(1); + Timestamp::set_timestamp(1); // Initialize time. // remember + compare this along with the test. @@ -292,8 +270,8 @@ fn staking_should_work() { // put some money in account that we'll use. for i in 1..5 { let _ = Balances::make_free_balance_be(&i, 2000); } - // --- Block 1: - start_session(1); + // --- Block 2: + start_session(2); // add a new candidate for being a validator. account 3 controlled by 4. assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller)); assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default())); @@ -301,37 +279,43 @@ fn staking_should_work() { // No effects will be seen so far. assert_eq_uvec!(validator_controllers(), vec![20, 10]); - // --- Block 2: - start_session(2); + // --- Block 3: + start_session(3); // No effects will be seen so far. Era has not been yet triggered. assert_eq_uvec!(validator_controllers(), vec![20, 10]); - // --- Block 3: the validators will now be queued. - start_session(3); - assert_eq!(Staking::current_era(), 1); - - // --- Block 4: the validators will now be changed. + // --- Block 4: the validators will now be queued. start_session(4); + assert_eq!(Staking::active_era(), 1); + + // --- Block 5: the validators are still in queue. + start_session(5); + + // --- Block 6: the validators will now be changed. + start_session(6); assert_eq_uvec!(validator_controllers(), vec![20, 4]); - // --- Block 4: Unstake 4 as a validator, freeing up the balance stashed in 3 + // --- Block 6: Unstake 4 as a validator, freeing up the balance stashed in 3 // 4 will chill Staking::chill(Origin::signed(4)).unwrap(); - // --- Block 5: nothing. 4 is still there. - start_session(5); + // --- Block 7: nothing. 4 is still there. + start_session(7); assert_eq_uvec!(validator_controllers(), vec![20, 4]); - // --- Block 6: 4 will not be a validator. - start_session(7); + // --- Block 8: + start_session(8); + + // --- Block 9: 4 will not be a validator. + start_session(9); assert_eq_uvec!(validator_controllers(), vec![20, 10]); // Note: the stashed value of 4 is still lock assert_eq!( Staking::ledger(&4), - Some(StakingLedger { stash: 3, total: 1500, active: 1500, unlocking: vec![] }) + Some(StakingLedger { stash: 3, total: 1500, active: 1500, unlocking: vec![], last_reward: 0 }) ); // e.g. it cannot spend more than 500 that it has free from the total 2000 assert_noop!( @@ -366,18 +350,19 @@ fn less_than_needed_candidates_works() { // But the exposure is updated in a simple way. No external votes exists. // This is purely self-vote. - assert_eq!(Staking::stakers(10).others.len(), 0); - assert_eq!(Staking::stakers(20).others.len(), 0); - assert_eq!(Staking::stakers(30).others.len(), 0); - check_exposure_all(); - check_nominator_all(); + assert!( + ErasStakers::::iter_prefix(Staking::active_era()) + .all(|exposure| exposure.others.is_empty()) + ); + check_exposure_all(Staking::active_era()); + check_nominator_all(Staking::active_era()); }); } #[test] fn no_candidate_emergency_condition() { ExtBuilder::default() - .minimum_validator_count(10) + .minimum_validator_count(4) .validator_count(15) .num_validators(4) .validator_pool(true) @@ -386,21 +371,17 @@ fn no_candidate_emergency_condition() { .execute_with(|| { // initial validators assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]); - - // set the minimum validator count. - ::MinimumValidatorCount::put(10); - ::ValidatorCount::put(15); assert_eq!(Staking::validator_count(), 15); + // try to chill let _ = Staking::chill(Origin::signed(10)); // trigger era - System::set_block_number(1); - Session::on_initialize(System::block_number()); + start_era(1); // Previous ones are elected. chill is invalidates. TODO: #2494 assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]); - assert_eq!(Staking::current_elected().len(), 0); + assert_eq!(Session::validators(), vec![11, 21, 31, 41]); }); } @@ -489,61 +470,57 @@ fn nominating_and_rewards_should_work() { // ------ check the staked value of all parties. if cfg!(feature = "equalize") { - // total expo of 10, with 1200 coming from nominators (externals), according to phragmen. - assert_eq!(Staking::stakers(11).own, 1000); - assert_eq_error_rate!(Staking::stakers(11).total, 1000 + 1000, 2); - // 2 and 4 supported 10, each with stake 600, according to phragmen. + // 30 and 40 are not chosen anymore + assert_eq!(ErasStakers::::iter_prefix(Staking::active_era()).count(), 2); assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), - vec![600, 400] - ); - assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.who).collect::>(), - vec![3, 1] - ); - // total expo of 20, with 500 coming from nominators (externals), according to phragmen. - assert_eq!(Staking::stakers(21).own, 1000); - assert_eq_error_rate!(Staking::stakers(21).total, 1000 + 1000, 2); - // 2 and 4 supported 20, each with stake 250, according to phragmen. - assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), - vec![400, 600] + Staking::eras_stakers(Staking::active_era(), 11), + Exposure { + total: 1000 + 1000, + own: 1000, + others: vec![ + IndividualExposure { who: 3, value: 600 }, + IndividualExposure { who: 1, value: 400 }, + ] + }, ); assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.who).collect::>(), - vec![3, 1] + Staking::eras_stakers(Staking::active_era(), 21), + Exposure { + total: 1000 + 1000, + own: 1000, + others: vec![ + IndividualExposure { who: 3, value: 400 }, + IndividualExposure { who: 1, value: 600 }, + ] + }, ); } else { - // total expo of 10, with 1200 coming from nominators (externals), according to phragmen. - assert_eq!(Staking::stakers(11).own, 1000); - assert_eq!(Staking::stakers(11).total, 1000 + 800); - // 2 and 4 supported 10, each with stake 600, according to phragmen. - assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.value).collect::>>(), - vec![400, 400] - ); + // 30 and 40 are not chosen anymore + assert_eq!(ErasStakers::::iter_prefix(Staking::active_era()).count(), 2); assert_eq!( - Staking::stakers(11).others.iter().map(|e| e.who).collect::>(), - vec![3, 1] - ); - // total expo of 20, with 500 coming from nominators (externals), according to phragmen. - assert_eq!(Staking::stakers(21).own, 1000); - assert_eq_error_rate!(Staking::stakers(21).total, 1000 + 1200, 2); - // 2 and 4 supported 20, each with stake 250, according to phragmen. - assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.value).collect::>>(), - vec![600, 600] + Staking::eras_stakers(Staking::active_era(), 11), + Exposure { + total: 1000 + 800, + own: 1000, + others: vec![ + IndividualExposure { who: 3, value: 400 }, + IndividualExposure { who: 1, value: 400 }, + ] + }, ); assert_eq!( - Staking::stakers(21).others.iter().map(|e| e.who).collect::>(), - vec![3, 1] + Staking::eras_stakers(Staking::active_era(), 21), + Exposure { + total: 1000 + 1200, + own: 1000, + others: vec![ + IndividualExposure { who: 3, value: 600 }, + IndividualExposure { who: 1, value: 600 }, + ] + }, ); } - // They are not chosen anymore - assert_eq!(Staking::stakers(31).total, 0); - assert_eq!(Staking::stakers(41).total, 0); - // the total reward for era 1 let total_payout_1 = current_total_payout_for_duration(3000); assert!(total_payout_1 > 100); // Test is meaningfull if reward something @@ -613,8 +590,8 @@ fn nominating_and_rewards_should_work() { ); } - check_exposure_all(); - check_nominator_all(); + check_exposure_all(Staking::active_era()); + check_nominator_all(Staking::active_era()); }); } @@ -657,13 +634,13 @@ fn nominators_also_get_slashed() { &[OffenceDetails { offender: ( 11, - Staking::stakers(&11), + mock::validator_current_exposure(11), ), reporters: vec![], }], &[Perbill::from_percent(5)], ); - let expo = Staking::stakers(11); + let expo = mock::validator_current_exposure(11); let slash_value = 50; let total_slash = expo.total.min(slash_value); let validator_slash = expo.own.min(total_slash); @@ -672,8 +649,8 @@ fn nominators_also_get_slashed() { // initial + first era reward + slash assert_eq!(Balances::total_balance(&11), initial_balance - validator_slash); assert_eq!(Balances::total_balance(&2), initial_balance - nominator_slash); - check_exposure_all(); - check_nominator_all(); + check_exposure_all(Staking::active_era()); + check_nominator_all(Staking::active_era()); // Because slashing happened. assert!(is_disabled(10)); }); @@ -728,42 +705,52 @@ fn double_controlling_should_fail() { #[test] fn session_and_eras_work() { ExtBuilder::default().build().execute_with(|| { - assert_eq!(Staking::current_era(), 0); + assert_eq!(Staking::active_era(), 0); // Block 1: No change. - start_session(0); + start_session(1); assert_eq!(Session::current_index(), 1); - assert_eq!(Staking::current_era(), 0); + assert_eq!(Staking::active_era(), 0); - // Block 2: Simple era change. + // Block 2: No change. start_session(2); - assert_eq!(Session::current_index(), 3); - assert_eq!(Staking::current_era(), 1); + assert_eq!(Session::current_index(), 2); + assert_eq!(Staking::active_era(), 0); - // Block 3: Schedule an era length change; no visible changes. + // Block 3: Era increment. start_session(3); + assert_eq!(Session::current_index(), 3); + assert_eq!(Staking::active_era(), 1); + + // Block 4: No change. + start_session(4); assert_eq!(Session::current_index(), 4); - assert_eq!(Staking::current_era(), 1); + assert_eq!(Staking::active_era(), 1); - // Block 4: Era change kicks in. + // Block 5: No change. start_session(5); - assert_eq!(Session::current_index(), 6); - assert_eq!(Staking::current_era(), 2); + assert_eq!(Session::current_index(), 5); + assert_eq!(Staking::active_era(), 1); - // Block 5: No change. + // Block 6: Era increment. start_session(6); - assert_eq!(Session::current_index(), 7); - assert_eq!(Staking::current_era(), 2); + assert_eq!(Session::current_index(), 6); + assert_eq!(Staking::active_era(), 2); - // Block 6: No change. + // Block 7: No change. start_session(7); - assert_eq!(Session::current_index(), 8); - assert_eq!(Staking::current_era(), 2); + assert_eq!(Session::current_index(), 7); + assert_eq!(Staking::active_era(), 2); - // Block 7: Era increment. + // Block 8: No change. start_session(8); + assert_eq!(Session::current_index(), 8); + assert_eq!(Staking::active_era(), 2); + + // Block 9: Era increment. + start_session(9); assert_eq!(Session::current_index(), 9); - assert_eq!(Staking::current_era(), 3); + assert_eq!(Staking::active_era(), 3); }); } @@ -771,50 +758,53 @@ fn session_and_eras_work() { fn forcing_new_era_works() { ExtBuilder::default().build().execute_with(|| { // normal flow of session. - assert_eq!(Staking::current_era(), 0); + assert_eq!(Staking::active_era(), 0); start_session(0); - assert_eq!(Staking::current_era(), 0); + assert_eq!(Staking::active_era(), 0); start_session(1); - assert_eq!(Staking::current_era(), 0); + assert_eq!(Staking::active_era(), 0); start_session(2); - assert_eq!(Staking::current_era(), 1); + assert_eq!(Staking::active_era(), 0); + start_session(3); + assert_eq!(Staking::active_era(), 1); // no era change. ForceEra::put(Forcing::ForceNone); - start_session(3); - assert_eq!(Staking::current_era(), 1); start_session(4); - assert_eq!(Staking::current_era(), 1); + assert_eq!(Staking::active_era(), 1); start_session(5); - assert_eq!(Staking::current_era(), 1); + assert_eq!(Staking::active_era(), 1); start_session(6); - assert_eq!(Staking::current_era(), 1); + assert_eq!(Staking::active_era(), 1); + start_session(7); + assert_eq!(Staking::active_era(), 1); // back to normal. // this immediately starts a new session. ForceEra::put(Forcing::NotForcing); - start_session(7); - assert_eq!(Staking::current_era(), 2); start_session(8); - assert_eq!(Staking::current_era(), 2); + assert_eq!(Staking::active_era(), 1); // There is one session delay + start_session(9); + assert_eq!(Staking::active_era(), 2); // forceful change ForceEra::put(Forcing::ForceAlways); - start_session(9); - assert_eq!(Staking::current_era(), 3); start_session(10); - assert_eq!(Staking::current_era(), 4); + assert_eq!(Staking::active_era(), 2); // There is one session delay start_session(11); - assert_eq!(Staking::current_era(), 5); + assert_eq!(Staking::active_era(), 3); + start_session(12); + assert_eq!(Staking::active_era(), 4); // just one forceful change ForceEra::put(Forcing::ForceNew); - start_session(12); - assert_eq!(Staking::current_era(), 6); - - assert_eq!(ForceEra::get(), Forcing::NotForcing); start_session(13); - assert_eq!(Staking::current_era(), 6); + assert_eq!(Staking::active_era(), 5); + assert_eq!(ForceEra::get(), Forcing::NotForcing); + start_session(14); + assert_eq!(Staking::active_era(), 6); + start_session(15); + assert_eq!(Staking::active_era(), 6); }); } @@ -828,7 +818,7 @@ fn cannot_transfer_staked_balance() { // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(&11), 1000); // Confirm account 11 (via controller 10) is totally staked - assert_eq!(Staking::stakers(&11).total, 1000); + assert_eq!(mock::validator_current_exposure(11).total, 1000); // Confirm account 11 cannot transfer as a result assert_noop!( Balances::transfer(Origin::signed(11), 20, 1), @@ -857,7 +847,7 @@ fn cannot_transfer_staked_balance_2() { // Confirm account 21 has some free balance assert_eq!(Balances::free_balance(&21), 2000); // Confirm account 21 (via controller 20) is totally staked - assert_eq!(Staking::stakers(&21).total, 1000); + assert_eq!(mock::validator_current_exposure(21).total, 1000); // Confirm account 21 can transfer at most 1000 assert_noop!( Balances::transfer(Origin::signed(21), 20, 1001), @@ -880,7 +870,7 @@ fn cannot_reserve_staked_balance() { // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(&11), 1000); // Confirm account 11 (via controller 10) is totally staked - assert_eq!(Staking::stakers(&11).own, 1000); + assert_eq!(mock::validator_current_exposure(11).own, 1000); // Confirm account 11 cannot transfer as a result assert_noop!( Balances::reserve(&11, 1), @@ -903,7 +893,7 @@ fn reward_destination_works() { // Rewards go to the correct destination as determined in Payee ExtBuilder::default().nominate(false).build().execute_with(|| { // Check that account 11 is a validator - assert!(Staking::current_elected().contains(&11)); + assert!(Session::validators().contains(&11)); // Check the balance of the validator account assert_eq!(Balances::free_balance(&10), 1); // Check the balance of the stash account @@ -914,6 +904,7 @@ fn reward_destination_works() { total: 1000, active: 1000, unlocking: vec![], + last_reward: 0, })); // Compute total payout now for whole duration as other parameter won't change @@ -933,6 +924,7 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: vec![], + last_reward: 0, })); //Change RewardDestination to Stash @@ -957,6 +949,7 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: vec![], + last_reward: 0, })); // Change RewardDestination to Controller @@ -982,6 +975,7 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: vec![], + last_reward: 0, })); // Check that amount in staked account is NOT increased. assert_eq!(Balances::free_balance(&11), recorded_stash_balance); @@ -994,45 +988,37 @@ fn validator_payment_prefs_work() { // Note: unstake threshold is being directly tested in slashing tests. // This test will focus on validator payment. ExtBuilder::default().build().execute_with(|| { - // Initial config - let stash_initial_balance = Balances::total_balance(&11); - - // check the balance of a validator accounts. - assert_eq!(Balances::total_balance(&10), 1); - // check the balance of a validator's stash accounts. - assert_eq!(Balances::total_balance(&11), stash_initial_balance); - // and the nominator (to-be) - let _ = Balances::make_free_balance_be(&2, 500); - - // add a dummy nominator. - >::insert(&11, Exposure { - own: 500, // equal division indicates that the reward will be equally divided among validator and nominator. - total: 1000, - others: vec![IndividualExposure {who: 2, value: 500 }] - }); - >::insert(&2, RewardDestination::Stash); + let commission = Perbill::from_percent(40); >::insert(&11, ValidatorPrefs { - commission: Perbill::from_percent(50), + commission: commission.clone(), }); + // Reward controller so staked ratio doesn't change. + >::insert(&11, RewardDestination::Controller); + >::insert(&101, RewardDestination::Controller); + + start_era(1); + + let balance_era_1_10 = Balances::total_balance(&10); + let balance_era_1_100 = Balances::total_balance(&100); + // Compute total payout now for whole duration as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3000); - assert!(total_payout_0 > 100); // Test is meaningfull if reward something + let total_payout_1 = current_total_payout_for_duration(3000); + let exposure_1 = mock::validator_current_exposure(11); + assert!(total_payout_1 > 100); // Test is meaningfull if reward something >::reward_by_ids(vec![(11, 1)]); - start_era(1); + start_era(2); - // whats left to be shared is the sum of 3 rounds minus the validator's cut. - let shared_cut = total_payout_0 / 2; - // Validator's payee is Staked account, 11, reward will be paid here. - assert_eq!(Balances::total_balance(&11), stash_initial_balance + shared_cut / 2 + shared_cut); - // Controller account will not get any reward. - assert_eq!(Balances::total_balance(&10), 1); - // Rest of the reward will be shared and paid to the nominator in stake. - assert_eq!(Balances::total_balance(&2), 500 + shared_cut / 2); + let taken_cut = commission * total_payout_1; + let shared_cut = total_payout_1 - taken_cut; + let reward_of_10 = shared_cut * exposure_1.own / exposure_1.total + taken_cut; + let reward_of_100 = shared_cut * exposure_1.others[0].value / exposure_1.total; + assert_eq_error_rate!(Balances::total_balance(&10), balance_era_1_10 + reward_of_10, 2); + assert_eq_error_rate!(Balances::total_balance(&100), balance_era_1_100 + reward_of_100, 2); - check_exposure_all(); - check_nominator_all(); + check_exposure_all(Staking::active_era()); + check_nominator_all(Staking::active_era()); }); } @@ -1044,7 +1030,7 @@ fn bond_extra_works() { // See `bond_extra_and_withdraw_unbonded_works` for more details and updates on `Exposure`. ExtBuilder::default().build().execute_with(|| { // Check that account 10 is a validator - assert!(>::exists(11)); + assert!(Session::validators().contains(&11)); // Check that account 10 is bonded to account 11 assert_eq!(Staking::bonded(&11), Some(10)); // Check how much is at stake @@ -1053,6 +1039,7 @@ fn bond_extra_works() { total: 1000, active: 1000, unlocking: vec![], + last_reward: 0, })); // Give account 11 some large free balance greater than total @@ -1066,6 +1053,7 @@ fn bond_extra_works() { total: 1000 + 100, active: 1000 + 100, unlocking: vec![], + last_reward: 0, })); // Call the bond_extra function with a large number, should handle it @@ -1076,6 +1064,7 @@ fn bond_extra_works() { total: 1000000, active: 1000000, unlocking: vec![], + last_reward: 0, })); }); } @@ -1095,7 +1084,7 @@ fn bond_extra_and_withdraw_unbonded_works() { let _ = Balances::make_free_balance_be(&11, 1000000); // Initial config should be correct - assert_eq!(Staking::current_era(), 0); + assert_eq!(Staking::active_era(), 0); assert_eq!(Session::current_index(), 0); // check the balance of a validator accounts. @@ -1110,8 +1099,9 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000, active: 1000, unlocking: vec![], + last_reward: 0, })); - assert_eq!(Staking::stakers(&11), Exposure { total: 1000, own: 1000, others: vec![] }); + assert_eq!(mock::validator_current_exposure(11), Exposure { total: 1000, own: 1000, others: vec![] }); // deposit the extra 100 units Staking::bond_extra(Origin::signed(11), 100).unwrap(); @@ -1121,14 +1111,15 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000 + 100, active: 1000 + 100, unlocking: vec![], + last_reward: 0, })); // Exposure is a snapshot! only updated after the next era update. - assert_ne!(Staking::stakers(&11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + assert_ne!(mock::validator_current_exposure(11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); // trigger next era. Timestamp::set_timestamp(10); start_era(2); - assert_eq!(Staking::current_era(), 2); + assert_eq!(Staking::active_era(), 2); // ledger should be the same. assert_eq!(Staking::ledger(&10), Some(StakingLedger { @@ -1136,20 +1127,21 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000 + 100, active: 1000 + 100, unlocking: vec![], + last_reward: 0, })); // Exposure is now updated. - assert_eq!(Staking::stakers(&11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + assert_eq!(mock::validator_current_exposure(11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); // Unbond almost all of the funds in stash. Staking::unbond(Origin::signed(10), 1000).unwrap(); assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}] }) + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], last_reward: 0 }) ); // Attempting to free the balances now will fail. 2 eras need to pass. Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}] })); + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], last_reward: 0 })); // trigger next era. start_era(3); @@ -1157,7 +1149,7 @@ fn bond_extra_and_withdraw_unbonded_works() { // nothing yet Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}] })); + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], last_reward: 0 })); // trigger next era. start_era(5); @@ -1165,7 +1157,7 @@ fn bond_extra_and_withdraw_unbonded_works() { Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); // Now the value is free and the staking ledger is updated. assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 100, active: 100, unlocking: vec![] })); + stash: 11, total: 100, active: 100, unlocking: vec![], last_reward: 0 })); }) } @@ -1226,11 +1218,12 @@ fn rebond_works() { total: 1000, active: 1000, unlocking: vec![], + last_reward: 0, }) ); start_era(2); - assert_eq!(Staking::current_era(), 2); + assert_eq!(Staking::active_era(), 2); // Try to rebond some funds. We get an error since no fund is unbonded. assert_noop!( @@ -1248,8 +1241,9 @@ fn rebond_works() { active: 100, unlocking: vec![UnlockChunk { value: 900, - era: 2 + 3 - },] + era: 2 + 3, + }], + last_reward: 0, }) ); @@ -1262,6 +1256,7 @@ fn rebond_works() { total: 1000, active: 1000, unlocking: vec![], + last_reward: 0, }) ); @@ -1274,6 +1269,7 @@ fn rebond_works() { total: 1000, active: 100, unlocking: vec![UnlockChunk { value: 900, era: 5 }], + last_reward: 0, }) ); @@ -1286,6 +1282,7 @@ fn rebond_works() { total: 1000, active: 600, unlocking: vec![UnlockChunk { value: 400, era: 5 }], + last_reward: 0, }) ); @@ -1297,7 +1294,8 @@ fn rebond_works() { stash: 11, total: 1000, active: 1000, - unlocking: vec![] + unlocking: vec![], + last_reward: 0, }) ); @@ -1315,7 +1313,8 @@ fn rebond_works() { UnlockChunk { value: 300, era: 5 }, UnlockChunk { value: 300, era: 5 }, UnlockChunk { value: 300, era: 5 }, - ] + ], + last_reward: 0, }) ); @@ -1330,60 +1329,67 @@ fn rebond_works() { unlocking: vec![ UnlockChunk { value: 300, era: 5 }, UnlockChunk { value: 100, era: 5 }, - ] + ], + last_reward: 0, }) ); }) } -#[test] -fn slot_stake_is_least_staked_validator_and_exposure_defines_maximum_punishment() { - // Test that slot_stake is determined by the least staked validator - // Test that slot_stake is the maximum punishment that can happen to a validator - ExtBuilder::default().nominate(false).fair(false).build().execute_with(|| { - // Confirm validator count is 2 - assert_eq!(Staking::validator_count(), 2); - // Confirm account 10 and 20 are validators - assert!(>::exists(&11) && >::exists(&21)); - - assert_eq!(Staking::stakers(&11).total, 1000); - assert_eq!(Staking::stakers(&21).total, 2000); - - // Give the man some money. - let _ = Balances::make_free_balance_be(&10, 1000); - let _ = Balances::make_free_balance_be(&20, 1000); - - // We confirm initialized slot_stake is this value - assert_eq!(Staking::slot_stake(), Staking::stakers(&11).total); - - // Now lets lower account 20 stake - >::insert(&21, Exposure { total: 69, own: 69, others: vec![] }); - assert_eq!(Staking::stakers(&21).total, 69); - >::insert(&20, StakingLedger { stash: 22, total: 69, active: 69, unlocking: vec![] }); - - // Compute total payout now for whole duration as other parameter won't change - let total_payout_0 = current_total_payout_for_duration(3000); - assert!(total_payout_0 > 100); // Test is meaningfull if reward something - >::reward_by_ids(vec![(11, 1)]); - >::reward_by_ids(vec![(21, 1)]); - - // New era --> rewards are paid --> stakes are changed - start_era(1); - - // -- new balances + reward - assert_eq!(Staking::stakers(&11).total, 1000 + total_payout_0 / 2); - assert_eq!(Staking::stakers(&21).total, 69 + total_payout_0 / 2); - - let _11_balance = Balances::free_balance(&11); - assert_eq!(_11_balance, 1000 + total_payout_0 / 2); - - // -- slot stake should also be updated. - assert_eq!(Staking::slot_stake(), 69 + total_payout_0 / 2); - - check_exposure_all(); - check_nominator_all(); - }); -} +// TODO TODO: slot stake ? +// #[test] +// fn slot_stake_is_least_staked_validator_and_exposure_defines_maximum_punishment() { +// // Test that slot_stake is determined by the least staked validator +// // Test that slot_stake is the maximum punishment that can happen to a validator +// ExtBuilder::default().nominate(false).fair(false).build().execute_with(|| { +// // Confirm validator count is 2 +// assert_eq!(Staking::validator_count(), 2); +// // Confirm account 10 and 20 are validators +// assert_eq_uvec!(Session::validators(), vec![11, 21]); + +// assert_eq!(mock::validator_current_exposure(11).total, 1000); +// assert_eq!(mock::validator_current_exposure(21).total, 2000); + +// // Give the man some money. +// let _ = Balances::make_free_balance_be(&10, 1000); +// let _ = Balances::make_free_balance_be(&20, 1000); + +// // We confirm initialized slot_stake is this value +// assert_eq!(Staking::slot_stake_for_era(Staking::active_era()), mock::validator_current_exposure(11).total); + +// // Now lets lower account 20 stake +// mock::bypass_logic_change_current_exposure(21, Exposure { total: 69, own: 69, others: vec![] }); +// assert_eq!(mock::validator_current_exposure(21).total, 69); +// >::insert(&20, StakingLedger { stash: 22, total: 69, active: 69, unlocking: vec![], last_reward: 0 }); + +// // Compute total payout now for whole duration as other parameter won't change +// let total_payout_0 = current_total_payout_for_duration(3000); +// assert!(total_payout_0 > 100); // Test is meaningfull if reward something +// >::reward_by_ids(vec![(11, 1)]); +// >::reward_by_ids(vec![(21, 1)]); + +// // New era --> rewards are paid --> stakes are changed +// start_era(1); +// assert_eq!(mock::validator_current_exposure(11).total, 1000); +// assert_eq!(mock::validator_current_exposure(21).total, 69); +// assert_eq!(Staking::slot_stake_for_era(Staking::active_era()), 69); + +// let _11_balance = Balances::free_balance(&11); +// assert_eq!(_11_balance, 1000 + total_payout_0 / 2); + +// // Trigger another new era as the info are frozen before the era start. +// start_era(2); + +// // -- new infos +// assert_eq!(mock::validator_current_exposure(11).total, 1000 + total_payout_0 / 2); +// assert_eq!(mock::validator_current_exposure(21).total, 69 + total_payout_0 / 2); +// // -- slot stake should also be updated. +// assert_eq!(Staking::slot_stake_for_era(Staking::active_era()), 69 + total_payout_0 / 2); + +// check_exposure_all(Staking::active_era()); +// check_nominator_all(Staking::active_era()); +// }); +// } #[test] fn on_free_balance_zero_stash_removes_validator() { @@ -1493,8 +1499,6 @@ fn on_free_balance_zero_stash_removes_nominator() { fn switching_roles() { // Test that it should be possible to switch between roles (nominator, validator, idle) with minimal overhead. ExtBuilder::default().nominate(false).build().execute_with(|| { - Timestamp::set_timestamp(1); // Initialize time. - // Reset reward destination for i in &[10, 20] { assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller)); } @@ -1514,20 +1518,7 @@ fn switching_roles() { assert_ok!(Staking::bond(Origin::signed(5), 6, 1000, RewardDestination::Controller)); assert_ok!(Staking::validate(Origin::signed(6), ValidatorPrefs::default())); - // new block - start_session(1); - - // no change - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - // new block - start_session(2); - - // no change - assert_eq_uvec!(validator_controllers(), vec![20, 10]); - - // new block --> ne era --> new validators - start_session(3); + start_era(1); // with current nominators 10 and 5 have the most stake assert_eq_uvec!(validator_controllers(), vec![6, 10]); @@ -1541,18 +1532,12 @@ fn switching_roles() { // 2 : 2000 self vote + 250 vote. // Winners: 20 and 2 - start_session(4); - assert_eq_uvec!(validator_controllers(), vec![6, 10]); - - start_session(5); - assert_eq_uvec!(validator_controllers(), vec![6, 10]); + start_era(2); - // ne era - start_session(6); assert_eq_uvec!(validator_controllers(), vec![2, 20]); - check_exposure_all(); - check_nominator_all(); + check_exposure_all(Staking::active_era()); + check_nominator_all(Staking::active_era()); }); } @@ -1606,7 +1591,8 @@ fn bond_with_no_staked_value() { stash: 1, active: 0, total: 5, - unlocking: vec![UnlockChunk {value: 5, era: 3}] + unlocking: vec![UnlockChunk {value: 5, era: 3}], + last_reward: 0, }) ); @@ -1627,58 +1613,61 @@ fn bond_with_no_staked_value() { }); } -#[test] -fn bond_with_little_staked_value_bounded_by_slot_stake() { - // Behavior when someone bonds with little staked value. - // Particularly when she votes and the candidate is elected. - ExtBuilder::default() - .validator_count(3) - .nominate(false) - .minimum_validator_count(1) - .build() - .execute_with(|| { - // setup - assert_ok!(Staking::chill(Origin::signed(30))); - assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); - let init_balance_2 = Balances::free_balance(&2); - let init_balance_10 = Balances::free_balance(&10); - - // Stingy validator. - assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller)); - assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); - - let total_payout_0 = current_total_payout_for_duration(3000); - assert!(total_payout_0 > 100); // Test is meaningfull if reward something - reward_all_elected(); - start_era(1); - - // 2 is elected. - // and fucks up the slot stake. - assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); - assert_eq!(Staking::slot_stake(), 1); - - // Old ones are rewarded. - assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_0 / 3); - // no rewards paid to 2. This was initial election. - assert_eq!(Balances::free_balance(&2), init_balance_2); - - let total_payout_1 = current_total_payout_for_duration(3000); - assert!(total_payout_1 > 100); // Test is meaningfull if reward something - reward_all_elected(); - start_era(2); - - assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); - assert_eq!(Staking::slot_stake(), 1); - - assert_eq!(Balances::free_balance(&2), init_balance_2 + total_payout_1 / 3); - assert_eq!( - Balances::free_balance(&10), - init_balance_10 + total_payout_0 / 3 + total_payout_1 / 3, - ); - check_exposure_all(); - check_nominator_all(); - }); -} +// TODO TODO: slot stake +// #[test] +// fn bond_with_little_staked_value_bounded_by_slot_stake() { +// // Behavior when someone bonds with little staked value. +// // Particularly when she votes and the candidate is elected. +// ExtBuilder::default() +// .validator_count(3) +// .nominate(false) +// .minimum_validator_count(1) +// .build() +// .execute_with(|| { +// // setup +// assert_ok!(Staking::chill(Origin::signed(30))); +// assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); +// let init_balance_2 = Balances::free_balance(&2); +// let init_balance_10 = Balances::free_balance(&10); + +// // Stingy validator. +// assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller)); +// assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); + +// // reward session 1 +// let total_payout_1 = current_total_payout_for_duration(3000); +// assert!(total_payout_1 > 100); // Test is meaningfull if reward something +// reward_all_elected(); +// start_era(1); + +// // 2 is elected. +// // and fucks up the slot stake. +// assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); +// assert_eq!(Staking::slot_stake_for_era(Staking::active_era()), 1); + +// // Old ones are rewarded. +// assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_1 / 3); +// // no rewards paid to 2. This was initial election. +// assert_eq!(Balances::free_balance(&2), init_balance_2); + +// // reward session 2 +// let total_payout_2 = current_total_payout_for_duration(3000); +// assert!(total_payout_2 > 100); // Test is meaningfull if reward something +// reward_all_elected(); +// start_era(2); + +// assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); +// assert_eq!(Staking::slot_stake_for_era(Staking::active_era()), 1); + +// assert_eq!(Balances::free_balance(&2), init_balance_2 + total_payout_2 / 3); +// assert_eq!( +// Balances::free_balance(&10), +// init_balance_10 + total_payout_1 / 3 + total_payout_2 / 3, +// ); +// check_exposure_all(Staking::active_era()); +// check_nominator_all(Staking::active_era()); +// }); +// } #[cfg(feature = "equalize")] #[test] @@ -1712,16 +1701,16 @@ fn phragmen_linear_worse_case_equalize() { assert_eq_uvec!(validator_controllers(), vec![10, 60, 40, 20, 50, 30, 70]); - assert_eq_error_rate!(Staking::stakers(11).total, 3000, 2); - assert_eq_error_rate!(Staking::stakers(21).total, 2255, 2); - assert_eq_error_rate!(Staking::stakers(31).total, 2255, 2); - assert_eq_error_rate!(Staking::stakers(41).total, 1925, 2); - assert_eq_error_rate!(Staking::stakers(51).total, 1870, 2); - assert_eq_error_rate!(Staking::stakers(61).total, 1890, 2); - assert_eq_error_rate!(Staking::stakers(71).total, 1800, 2); + assert_eq_error_rate!(mock::validator_current_exposure(11).total, 3000, 2); + assert_eq_error_rate!(mock::validator_current_exposure(21).total, 2255, 2); + assert_eq_error_rate!(mock::validator_current_exposure(31).total, 2255, 2); + assert_eq_error_rate!(mock::validator_current_exposure(41).total, 1925, 2); + assert_eq_error_rate!(mock::validator_current_exposure(51).total, 1870, 2); + assert_eq_error_rate!(mock::validator_current_exposure(61).total, 1890, 2); + assert_eq_error_rate!(mock::validator_current_exposure(71).total, 1800, 2); - check_exposure_all(); - check_nominator_all(); + check_exposure_all(Staking::active_era()); + check_nominator_all(Staking::active_era()); }) } @@ -1741,8 +1730,8 @@ fn new_era_elects_correct_number_of_validators() { Session::on_initialize(System::block_number()); assert_eq!(validator_controllers().len(), 1); - check_exposure_all(); - check_nominator_all(); + check_exposure_all(Staking::active_era()); + check_nominator_all(Staking::active_era()); }) } @@ -1764,8 +1753,8 @@ fn phragmen_should_not_overflow_validators() { // This test will fail this. Will saturate. // check_exposure_all(); - assert_eq!(Staking::stakers(3).total, u64::max_value()); - assert_eq!(Staking::stakers(5).total, u64::max_value()); + assert_eq!(mock::validator_current_exposure(3).total, u64::max_value()); + assert_eq!(mock::validator_current_exposure(5).total, u64::max_value()); }) } @@ -1786,8 +1775,8 @@ fn phragmen_should_not_overflow_nominators() { assert_eq_uvec!(validator_controllers(), vec![4, 2]); // Saturate. - assert_eq!(Staking::stakers(3).total, u64::max_value()); - assert_eq!(Staking::stakers(5).total, u64::max_value()); + assert_eq!(mock::validator_current_exposure(3).total, u64::max_value()); + assert_eq!(mock::validator_current_exposure(5).total, u64::max_value()); }) } @@ -1805,55 +1794,59 @@ fn phragmen_should_not_overflow_ultimate() { assert_eq_uvec!(validator_controllers(), vec![4, 2]); // Saturate. - assert_eq!(Staking::stakers(3).total, u64::max_value()); - assert_eq!(Staking::stakers(5).total, u64::max_value()); + assert_eq!(mock::validator_current_exposure(3).total, u64::max_value()); + assert_eq!(mock::validator_current_exposure(5).total, u64::max_value()); }) } -#[test] -fn reward_validator_slashing_validator_doesnt_overflow() { - ExtBuilder::default().build().execute_with(|| { - let stake = u32::max_value() as u64 * 2; - let reward_slash = u32::max_value() as u64 * 2; - - // Assert multiplication overflows in balance arithmetic. - assert!(stake.checked_mul(reward_slash).is_none()); - - // Set staker - let _ = Balances::make_free_balance_be(&11, stake); - >::insert(&11, Exposure { total: stake, own: stake, others: vec![] }); - - // Check reward - let _ = Staking::reward_validator(&11, reward_slash); - assert_eq!(Balances::total_balance(&11), stake * 2); - - // Set staker - let _ = Balances::make_free_balance_be(&11, stake); - let _ = Balances::make_free_balance_be(&2, stake); - - // only slashes out of bonded stake are applied. without this line, - // it is 0. - Staking::bond(Origin::signed(2), 20000, stake - 1, RewardDestination::default()).unwrap(); - >::insert(&11, Exposure { total: stake, own: 1, others: vec![ - IndividualExposure { who: 2, value: stake - 1 } - ]}); - - - // Check slashing - on_offence_now( - &[ - OffenceDetails { - offender: (11, Staking::stakers(&11)), - reporters: vec![], - }, - ], - &[Perbill::from_percent(100)], - ); - - assert_eq!(Balances::total_balance(&11), stake - 1); - assert_eq!(Balances::total_balance(&2), 1); - }) -} +// TODO TODO +// #[test] +// fn reward_validator_slashing_validator_doesnt_overflow() { +// ExtBuilder::default().build().execute_with(|| { +// let stake = u32::max_value() as u64 * 2; +// let reward_slash = u32::max_value() as u64 * 2; + +// // Assert multiplication overflows in balance arithmetic. +// assert!(stake.checked_mul(reward_slash).is_none()); + +// // Set staker +// let _ = Balances::make_free_balance_be(&11, stake); + +// let exposure = Exposure { total: stake, own: stake, others: vec![] }; +// let prefs = ValidatorPrefs { commission: Perbill::zero() }; + +// // Check reward +// let _ = Staking::reward_validator(&11, &prefs, &exposure, reward_slash); +// assert_eq!(Balances::total_balance(&11), stake * 2); + +// // Set staker +// let _ = Balances::make_free_balance_be(&11, stake); +// let _ = Balances::make_free_balance_be(&2, stake); + +// // only slashes out of bonded stake are applied. without this line, +// // it is 0. +// Staking::bond(Origin::signed(2), 20000, stake - 1, RewardDestination::default()).unwrap(); +// mock::bypass_logic_change_current_exposure(11, Exposure { +// total: stake, +// own: 1, +// others: vec![ IndividualExposure { who: 2, value: stake - 1 }] +// }); + +// // Check slashing +// on_offence_now( +// &[ +// OffenceDetails { +// offender: (11, mock::validator_current_exposure(11)), +// reporters: vec![], +// }, +// ], +// &[Perbill::from_percent(100)], +// ); + +// assert_eq!(Balances::total_balance(&11), stake - 1); +// assert_eq!(Balances::total_balance(&2), 1); +// }) +// } #[test] fn reward_from_authorship_event_handler_works() { @@ -1871,38 +1864,52 @@ fn reward_from_authorship_event_handler_works() { >::note_uncle(11, 1); // Not mandatory but must be coherent with rewards - assert_eq!(>::get(), vec![21, 11]); + assert_eq!(Session::validators(), vec![11, 21]); // 21 is rewarded as an uncle producer // 11 is rewarded as a block producer and uncle referencer and uncle producer - assert_eq!(CurrentEraPointsEarned::get().individual, vec![1, 20 + 2 * 3 + 1]); - assert_eq!(CurrentEraPointsEarned::get().total, 28); + assert_eq!( + ErasRewardPoints::::get(ActiveEra::get()), + EraRewardPoints { + individual: vec![(11, 20 + 2 * 3 + 1), (21, 1)].into_iter().collect(), + total: 28, + }, + ); }) } #[test] fn add_reward_points_fns_works() { ExtBuilder::default().build().execute_with(|| { - let validators = >::current_elected(); // Not mandatory but must be coherent with rewards - assert_eq!(validators, vec![21, 11]); - - >::reward_by_indices(vec![ - (0, 1), - (1, 1), - (2, 1), - (1, 1), + assert_eq!(Session::validators(), vec![11, 21]); + + // TODO TODO: no longer reward_by_indices + // >::reward_by_indices(vec![ + // (1, 1), + // (0, 1), + // (2, 1), + // (0, 1), + // ]); + >::reward_by_ids(vec![ + (21, 1), + (11, 1), + (11, 1), ]); >::reward_by_ids(vec![ (21, 1), (11, 1), - (31, 1), (11, 1), ]); - assert_eq!(CurrentEraPointsEarned::get().individual, vec![2, 4]); - assert_eq!(CurrentEraPointsEarned::get().total, 6); + assert_eq!( + ErasRewardPoints::::get(ActiveEra::get()), + EraRewardPoints { + individual: vec![(11, 4), (21, 2)].into_iter().collect(), + total: 6, + }, + ); }) } @@ -1925,19 +1932,20 @@ fn era_is_always_same_length() { // session changes. ExtBuilder::default().build().execute_with(|| { start_era(1); - assert_eq!(Staking::current_era_start_session_index(), SessionsPerEra::get()); + assert_eq!(Staking::eras_start_session_index(Staking::active_era()), SessionsPerEra::get()); start_era(2); - assert_eq!(Staking::current_era_start_session_index(), SessionsPerEra::get() * 2); + assert_eq!(Staking::eras_start_session_index(Staking::active_era()), SessionsPerEra::get() * 2); let session = Session::current_index(); ForceEra::put(Forcing::ForceNew); advance_session(); - assert_eq!(Staking::current_era(), 3); - assert_eq!(Staking::current_era_start_session_index(), session + 1); + advance_session(); + assert_eq!(Staking::active_era(), 3); + assert_eq!(Staking::eras_start_session_index(Staking::active_era()), session + 2); start_era(4); - assert_eq!(Staking::current_era_start_session_index(), session + SessionsPerEra::get() + 1); + assert_eq!(Staking::eras_start_session_index(Staking::active_era()), session + 2 + SessionsPerEra::get()); }); } @@ -1948,7 +1956,7 @@ fn offence_forces_new_era() { &[OffenceDetails { offender: ( 11, - Staking::stakers(&11), + mock::validator_current_exposure(11), ), reporters: vec![], }], @@ -1968,7 +1976,7 @@ fn offence_ensures_new_era_without_clobbering() { &[OffenceDetails { offender: ( 11, - Staking::stakers(&11), + mock::validator_current_exposure(11), ), reporters: vec![], }], @@ -1982,12 +1990,13 @@ fn offence_ensures_new_era_without_clobbering() { #[test] fn offence_deselects_validator_when_slash_is_zero() { ExtBuilder::default().build().execute_with(|| { + assert!(Session::validators().contains(&11)); assert!(>::exists(11)); on_offence_now( &[OffenceDetails { offender: ( 11, - Staking::stakers(&11), + mock::validator_current_exposure(11), ), reporters: vec![], }], @@ -1995,6 +2004,9 @@ fn offence_deselects_validator_when_slash_is_zero() { ); assert_eq!(Staking::force_era(), Forcing::ForceNew); assert!(!>::exists(11)); + start_era(1); + assert!(!Session::validators().contains(&11)); + assert!(!>::exists(11)); }); } @@ -2003,7 +2015,7 @@ fn slashing_performed_according_exposure() { // This test checks that slashing is performed according the exposure (or more precisely, // historical exposure), not the current balance. ExtBuilder::default().build().execute_with(|| { - assert_eq!(Staking::stakers(&11).own, 1000); + assert_eq!(mock::validator_current_exposure(11).own, 1000); // Handle an offence with a historical exposure. on_offence_now( @@ -2032,11 +2044,12 @@ fn slash_in_old_span_does_not_deselect() { start_era(1); assert!(>::exists(11)); + assert!(Session::validators().contains(&11)); on_offence_now( &[OffenceDetails { offender: ( 11, - Staking::stakers(&11), + mock::validator_current_exposure(11), ), reporters: vec![], }], @@ -2050,6 +2063,7 @@ fn slash_in_old_span_does_not_deselect() { Staking::validate(Origin::signed(10), Default::default()).unwrap(); assert_eq!(Staking::force_era(), Forcing::NotForcing); assert!(>::exists(11)); + assert!(!Session::validators().contains(&11)); start_era(3); @@ -2060,7 +2074,7 @@ fn slash_in_old_span_does_not_deselect() { &[OffenceDetails { offender: ( 11, - Staking::stakers(&11), + mock::validator_current_exposure(11), ), reporters: vec![], }], @@ -2071,12 +2085,13 @@ fn slash_in_old_span_does_not_deselect() { // not for zero-slash. assert_eq!(Staking::force_era(), Forcing::NotForcing); assert!(>::exists(11)); + assert!(Session::validators().contains(&11)); on_offence_in_era( &[OffenceDetails { offender: ( 11, - Staking::stakers(&11), + mock::validator_current_exposure(11), ), reporters: vec![], }], @@ -2087,6 +2102,7 @@ fn slash_in_old_span_does_not_deselect() { // or non-zero. assert_eq!(Staking::force_era(), Forcing::NotForcing); assert!(>::exists(11)); + assert!(Session::validators().contains(&11)); assert_ledger_consistent(11); }); } @@ -2102,13 +2118,13 @@ fn reporters_receive_their_slice() { #[cfg(not(feature = "equalize"))] let initial_balance = 1125; - assert_eq!(Staking::stakers(&11).total, initial_balance); + assert_eq!(mock::validator_current_exposure(11).total, initial_balance); on_offence_now( &[OffenceDetails { offender: ( 11, - Staking::stakers(&11), + mock::validator_current_exposure(11), ), reporters: vec![1, 2], }], @@ -2136,13 +2152,13 @@ fn subsequent_reports_in_same_span_pay_out_less() { #[cfg(not(feature = "equalize"))] let initial_balance = 1125; - assert_eq!(Staking::stakers(&11).total, initial_balance); + assert_eq!(mock::validator_current_exposure(11).total, initial_balance); on_offence_now( &[OffenceDetails { offender: ( 11, - Staking::stakers(&11), + mock::validator_current_exposure(11), ), reporters: vec![1], }], @@ -2158,7 +2174,7 @@ fn subsequent_reports_in_same_span_pay_out_less() { &[OffenceDetails { offender: ( 11, - Staking::stakers(&11), + mock::validator_current_exposure(11), ), reporters: vec![1], }], @@ -2182,7 +2198,7 @@ fn invulnerables_are_not_slashed() { assert_eq!(Balances::free_balance(&11), 1000); assert_eq!(Balances::free_balance(&21), 2000); - let exposure = Staking::stakers(&21); + let exposure = mock::validator_current_exposure(21); let initial_balance = Staking::slashable_balance_of(&21); let nominator_balances: Vec<_> = exposure.others @@ -2191,11 +2207,11 @@ fn invulnerables_are_not_slashed() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::stakers(&11)), + offender: (11, mock::validator_current_exposure(11)), reporters: vec![], }, OffenceDetails { - offender: (21, Staking::stakers(&21)), + offender: (21, mock::validator_current_exposure(21)), reporters: vec![], }, ], @@ -2229,7 +2245,7 @@ fn dont_slash_if_fraction_is_zero() { &[OffenceDetails { offender: ( 11, - Staking::stakers(&11), + mock::validator_current_exposure(11), ), reporters: vec![], }], @@ -2250,7 +2266,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::stakers(&11)), + offender: (11, mock::validator_current_exposure(11)), reporters: vec![], }, ], @@ -2264,7 +2280,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::stakers(&11)), + offender: (11, mock::validator_current_exposure(11)), reporters: vec![], }, ], @@ -2277,7 +2293,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::stakers(&11)), + offender: (11, mock::validator_current_exposure(11)), reporters: vec![], }, ], @@ -2298,7 +2314,7 @@ fn garbage_collection_after_slashing() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::stakers(&11)), + offender: (11, mock::validator_current_exposure(11)), reporters: vec![], }, ], @@ -2312,7 +2328,7 @@ fn garbage_collection_after_slashing() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::stakers(&11)), + offender: (11, mock::validator_current_exposure(11)), reporters: vec![], }, ], @@ -2335,21 +2351,21 @@ fn garbage_collection_on_window_pruning() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = Staking::stakers(&11); + let exposure = mock::validator_current_exposure(11); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_now( &[ OffenceDetails { - offender: (11, Staking::stakers(&11)), + offender: (11, mock::validator_current_exposure(11)), reporters: vec![], }, ], &[Perbill::from_percent(10)], ); - let now = Staking::current_era(); + let now = Staking::active_era(); assert_eq!(Balances::free_balance(&11), 900); assert_eq!(Balances::free_balance(&101), 2000 - (nominated_value / 10)); @@ -2383,8 +2399,8 @@ fn slashing_nominators_by_span_max() { assert_eq!(Staking::slashable_balance_of(&21), 1000); - let exposure_11 = Staking::stakers(&11); - let exposure_21 = Staking::stakers(&21); + let exposure_11 = mock::validator_current_exposure(11); + let exposure_21 = mock::validator_current_exposure(21); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value_11 = exposure_11.others.iter().find(|o| o.who == 101).unwrap().value; let nominated_value_21 = exposure_21.others.iter().find(|o| o.who == 101).unwrap().value; @@ -2392,7 +2408,7 @@ fn slashing_nominators_by_span_max() { on_offence_in_era( &[ OffenceDetails { - offender: (11, Staking::stakers(&11)), + offender: (11, mock::validator_current_exposure(11)), reporters: vec![], }, ], @@ -2426,7 +2442,7 @@ fn slashing_nominators_by_span_max() { on_offence_in_era( &[ OffenceDetails { - offender: (21, Staking::stakers(&21)), + offender: (21, mock::validator_current_exposure(21)), reporters: vec![], }, ], @@ -2449,7 +2465,7 @@ fn slashing_nominators_by_span_max() { on_offence_in_era( &[ OffenceDetails { - offender: (11, Staking::stakers(&11)), + offender: (11, mock::validator_current_exposure(11)), reporters: vec![], }, ], @@ -2485,7 +2501,7 @@ fn slashes_are_summed_across_spans() { on_offence_now( &[ OffenceDetails { - offender: (21, Staking::stakers(&21)), + offender: (21, mock::validator_current_exposure(21)), reporters: vec![], }, ], @@ -2510,7 +2526,7 @@ fn slashes_are_summed_across_spans() { on_offence_now( &[ OffenceDetails { - offender: (21, Staking::stakers(&21)), + offender: (21, mock::validator_current_exposure(21)), reporters: vec![], }, ], @@ -2535,14 +2551,14 @@ fn deferred_slashes_are_deferred() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = Staking::stakers(&11); + let exposure = mock::validator_current_exposure(11); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_now( &[ OffenceDetails { - offender: (11, Staking::stakers(&11)), + offender: (11, mock::validator_current_exposure(11)), reporters: vec![], }, ], @@ -2578,7 +2594,7 @@ fn remove_deferred() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = Staking::stakers(&11); + let exposure = mock::validator_current_exposure(11); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; @@ -2648,7 +2664,7 @@ fn remove_multi_deferred() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = Staking::stakers(&11); + let exposure = mock::validator_current_exposure(11); assert_eq!(Balances::free_balance(&101), 2000); on_offence_now( @@ -2664,7 +2680,7 @@ fn remove_multi_deferred() { on_offence_now( &[ OffenceDetails { - offender: (21, Staking::stakers(&21)), + offender: (21, mock::validator_current_exposure(21)), reporters: vec![], } ], @@ -2697,6 +2713,22 @@ fn version_initialized() { }); } +// // If on_session_ending is called with a decreasing will_apply_at and some era are force then some +// // planned era should be overriden +// #[test] +// fn unplanned_future_era() { +// ExtBuilder::default().build().execute_with(|| { +// assert_eq!(Session::current_index(), 0); +// Staking::on_session_ending(0, 10); +// assert_eq!(Staking::eras_start_session_index(Staking::active_era()), vec![0, 10]); +// Staking::on_session_ending(1, 20); +// assert_eq!(Staking::eras_start_session_index(Staking::active_era()), vec![0, 10, 20]); +// assert_ok!(Staking::force_new_era(Origin::ROOT)); +// Staking::on_session_ending(2, 5); +// assert_eq!(Staking::eras_start_session_index(Staking::active_era()), vec![0, 5]); +// }); +// } + #[test] fn slash_kicks_validators_not_nominators() { ExtBuilder::default().build().execute_with(|| { @@ -2704,7 +2736,7 @@ fn slash_kicks_validators_not_nominators() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = Staking::stakers(&11); + let exposure = mock::validator_current_exposure(11); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; From f41ee81fa6a38f7c3507c51b69cd0a20c4019fcf Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 10 Jan 2020 15:41:18 +0100 Subject: [PATCH 08/75] fix more tests --- frame/staking/src/lib.rs | 33 ++++++------ frame/staking/src/mock.rs | 31 ++++++++++- frame/staking/src/tests.rs | 105 +++++++++++++++++-------------------- 3 files changed, 96 insertions(+), 73 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index e70adecee9e7b..84b23382ffed7 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -15,6 +15,7 @@ // along with Substrate. If not, see . // TODO TODO: +// * fix: can someone make a new Ledger so it can claim old rewards ? // * migration // * upgrade test // * update doc @@ -386,8 +387,8 @@ pub struct StakingLedger { /// Any balance that is becoming free, which may eventually be transferred out /// of the stash (assuming it doesn't get slashed first). pub unlocking: Vec>, - /// The era up until which this staker had their reward paid. - pub last_reward: EraIndex, + /// The next era at which the staker can claim reward. + pub next_reward: EraIndex, // TODO: ^^^ this will need migration logic. } @@ -414,7 +415,7 @@ impl< total, active: self.active, unlocking, - last_reward: self.last_reward + next_reward: self.next_reward } } @@ -945,7 +946,7 @@ decl_module! { total: value, active: value, unlocking: vec![], - last_reward: Self::eras_start_session_index(Self::current_era()), + next_reward: Self::current_era(), }; Self::update_ledger(&controller, &item); } @@ -1355,11 +1356,11 @@ impl Module { -> DispatchResult { let mut nominator_ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; - if nominator_ledger.last_reward >= era { + if nominator_ledger.next_reward > era { return Err(Error::::InvalidEraToReward.into()); } - nominator_ledger.last_reward = era; + nominator_ledger.next_reward = era + 1; >::insert(&who, &nominator_ledger); let mut reward = Perbill::zero(); @@ -1402,11 +1403,11 @@ impl Module { fn do_payout_validator(who: T::AccountId, era: EraIndex) -> DispatchResult { let mut ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; - if ledger.last_reward >= era { + if ledger.next_reward > era { return Err(Error::::InvalidEraToReward.into()); } - ledger.last_reward = era; + ledger.next_reward = era + 1; >::insert(&who, &ledger); let era_reward_points = >::get(&era); @@ -1427,6 +1428,7 @@ impl Module { let reward = validator_point_part.saturating_mul(commission.saturating_add(exposure_part)); // This is zero if the era is not finished yet. let era_payout = >::get(&era); + println!("do_payout_validator: {:?}, reward: {:?}, era_payout: {:?}", who, reward, era_payout); if let Some(imbalance) = Self::make_payout(&ledger.stash, reward * era_payout) { Self::deposit_event(RawEvent::Reward(who, imbalance.peek())); } @@ -1610,15 +1612,14 @@ impl Module { /// Assumes storage is coherent with the declaration. fn select_validators() -> Option> { let mut all_nominators: Vec<(T::AccountId, Vec)> = Vec::new(); - let all_validator_candidates_iter = >::enumerate(); - let all_validators_and_prefs = all_validator_candidates_iter.map(|(who, pref)| { - let self_vote = (who.clone(), vec![who.clone()]); + let mut all_validators_and_prefs = BTreeMap::new(); + let mut all_validators = Vec::new(); + for (validator, preference) in >::enumerate() { + let self_vote = (validator.clone(), vec![validator.clone()]); all_nominators.push(self_vote); - (who, pref) - }).collect::>(); - let all_validators = all_validators_and_prefs.iter() - .map(|(who, _pref)| who.clone()) - .collect::>(); + all_validators_and_prefs.insert(validator.clone(), preference); + all_validators.push(validator); + } let nominator_votes = >::enumerate().map(|(nominator, nominations)| { let Nominations { submitted_in, mut targets, suppressed: _ } = nominations; diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 2659ced39ddc3..96d04e940683c 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -26,12 +26,13 @@ use sp_core::{H256, crypto::key_types}; use sp_io; use frame_support::{ assert_ok, impl_outer_origin, parameter_types, StorageLinkedMap, StorageValue, StorageMap, + StorageDoubleMap, traits::{Currency, Get, FindAuthor}, weights::Weight, }; use crate::{ EraIndex, GenesisConfig, Module, Trait, StakerStatus, ValidatorPrefs, RewardDestination, - Nominators, inflation, SessionInterface, Exposure, + Nominators, inflation, SessionInterface, Exposure, ErasStakers, ErasRewardPoints }; /// The AccountId alias in this test module. @@ -374,6 +375,7 @@ pub type Timestamp = pallet_timestamp::Module; pub type Staking = Module; pub fn check_exposure_all(era: EraIndex) { + // TODO TODO: and test order of nominators // TODO TODO: // Staking::validator_for_era(era).into_iter().for_each(|info| check_exposure(info)); } @@ -529,3 +531,30 @@ pub fn bypass_logic_change_current_exposure(stash: AccountId, exposure: Exposure // } // }); } + +/// Make all validator and nominator request their payment +pub fn make_all_reward_payment(era: EraIndex) { + let validators_with_reward = ErasRewardPoints::::get(era).individual.keys() + .cloned() + .collect::>(); + + // reward nominators + let mut nominator_controllers = HashSet::new(); + for exposure in ErasStakers::::iter_prefix(era) { + for controller in exposure.others.iter().filter_map(|other| Staking::bonded(other.who)) { + nominator_controllers.insert(controller); + } + } + for nominator_controller in nominator_controllers { + assert_ok!(Staking::payout_nominator( + Origin::signed(nominator_controller), + era, + validators_with_reward.clone() + )); + } + + // reward validators + for validator_controller in validators_with_reward.iter().filter_map(Staking::bonded) { + assert_ok!(Staking::payout_validator(Origin::signed(validator_controller), era)); + } +} diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index e5cf323ee1f65..1a7f3c2d0eb11 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -67,12 +67,12 @@ fn basic_setup_works() { // Account 10 controls the stash from account 11, which is 100 * balance_factor units assert_eq!( Staking::ledger(&10), - Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![], last_reward: 0 }) + Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![], next_reward: 0 }) ); // Account 20 controls the stash from account 21, which is 200 * balance_factor units assert_eq!( Staking::ledger(&20), - Some(StakingLedger { stash: 21, total: 1000, active: 1000, unlocking: vec![], last_reward: 0 }) + Some(StakingLedger { stash: 21, total: 1000, active: 1000, unlocking: vec![], next_reward: 0 }) ); // Account 1 does not control any stash assert_eq!(Staking::ledger(&1), None); @@ -86,7 +86,7 @@ fn basic_setup_works() { assert_eq!( Staking::ledger(100), - Some(StakingLedger { stash: 101, total: 500, active: 500, unlocking: vec![], last_reward: 0 }) + Some(StakingLedger { stash: 101, total: 500, active: 500, unlocking: vec![], next_reward: 0 }) ); assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); @@ -196,8 +196,6 @@ fn rewards_should_work() { >::reward_by_ids(vec![(11, 50)]); // This is the second validator of the current elected set. >::reward_by_ids(vec![(21, 50)]); - // This must be no-op as it is not an elected validator. - >::reward_by_ids(vec![(1001, 10_000)]); // Compute total payout now for whole duration as other parameter won't change let total_payout_0 = current_total_payout_for_duration(3 * 1000); @@ -211,7 +209,7 @@ fn rewards_should_work() { assert_eq!(Balances::total_balance(&21), init_balance_21); assert_eq!(Balances::total_balance(&100), init_balance_100); assert_eq!(Balances::total_balance(&101), init_balance_101); - assert_eq!(Session::validators(), vec![11, 21]); + assert_eq_uvec!(Session::validators(), vec![11, 21]); assert_eq!(Staking::eras_reward_points(Staking::active_era()), EraRewardPoints { total: 50*3, individual: vec![(11, 100), (21, 50)].into_iter().collect(), @@ -221,6 +219,7 @@ fn rewards_should_work() { start_session(3); assert_eq!(Staking::active_era(), 1); + mock::make_all_reward_payment(0); assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + total_payout_0*2/3*1000/1250, 2); assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2); @@ -229,7 +228,7 @@ fn rewards_should_work() { assert_eq_error_rate!(Balances::total_balance(&100), init_balance_100 + total_payout_0*250/1250, 2); assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); - assert_eq!(Session::validators(), vec![11, 21]); + assert_eq_uvec!(Session::validators(), vec![11, 21]); // >::reward_by_indices(vec![(0, 1)]); TODO TODO THis has been removed >::reward_by_ids(vec![(11, 1)]); @@ -238,6 +237,7 @@ fn rewards_should_work() { assert!(total_payout_1 > 10); // Test is meaningful if reward something start_era(2); + mock::make_all_reward_payment(1); assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + (total_payout_0*2/3 + total_payout_1)*1000/1250, 2); assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2); @@ -315,7 +315,7 @@ fn staking_should_work() { // Note: the stashed value of 4 is still lock assert_eq!( Staking::ledger(&4), - Some(StakingLedger { stash: 3, total: 1500, active: 1500, unlocking: vec![], last_reward: 0 }) + Some(StakingLedger { stash: 3, total: 1500, active: 1500, unlocking: vec![], next_reward: 1 }) ); // e.g. it cannot spend more than 500 that it has free from the total 2000 assert_noop!( @@ -381,7 +381,7 @@ fn no_candidate_emergency_condition() { // Previous ones are elected. chill is invalidates. TODO: #2494 assert_eq_uvec!(validator_controllers(), vec![10, 20, 30, 40]); - assert_eq!(Session::validators(), vec![11, 21, 31, 41]); + assert_eq_uvec!(Session::validators(), vec![11, 21, 31, 41]); }); } @@ -455,8 +455,6 @@ fn nominating_and_rewards_should_work() { assert!(total_payout_0 > 100); // Test is meaningfull if reward something >::reward_by_ids(vec![(41, 1)]); >::reward_by_ids(vec![(31, 1)]); - >::reward_by_ids(vec![(21, 10)]); // must be no-op - >::reward_by_ids(vec![(11, 10)]); // must be no-op start_era(1); @@ -464,6 +462,7 @@ fn nominating_and_rewards_should_work() { assert_eq_uvec!(validator_controllers(), vec![20, 10]); // OLD validators must have already received some rewards. + mock::make_all_reward_payment(0); assert_eq!(Balances::total_balance(&40), 1 + total_payout_0 / 2); assert_eq!(Balances::total_balance(&30), 1 + total_payout_0 / 2); @@ -478,8 +477,8 @@ fn nominating_and_rewards_should_work() { total: 1000 + 1000, own: 1000, others: vec![ - IndividualExposure { who: 3, value: 600 }, IndividualExposure { who: 1, value: 400 }, + IndividualExposure { who: 3, value: 600 }, ] }, ); @@ -489,8 +488,8 @@ fn nominating_and_rewards_should_work() { total: 1000 + 1000, own: 1000, others: vec![ - IndividualExposure { who: 3, value: 400 }, IndividualExposure { who: 1, value: 600 }, + IndividualExposure { who: 3, value: 400 }, ] }, ); @@ -503,8 +502,8 @@ fn nominating_and_rewards_should_work() { total: 1000 + 800, own: 1000, others: vec![ - IndividualExposure { who: 3, value: 400 }, IndividualExposure { who: 1, value: 400 }, + IndividualExposure { who: 3, value: 400 }, ] }, ); @@ -514,8 +513,8 @@ fn nominating_and_rewards_should_work() { total: 1000 + 1200, own: 1000, others: vec![ - IndividualExposure { who: 3, value: 600 }, IndividualExposure { who: 1, value: 600 }, + IndividualExposure { who: 3, value: 600 }, ] }, ); @@ -524,8 +523,6 @@ fn nominating_and_rewards_should_work() { // the total reward for era 1 let total_payout_1 = current_total_payout_for_duration(3000); assert!(total_payout_1 > 100); // Test is meaningfull if reward something - >::reward_by_ids(vec![(41, 10)]); // must be no-op - >::reward_by_ids(vec![(31, 10)]); // must be no-op >::reward_by_ids(vec![(21, 2)]); >::reward_by_ids(vec![(11, 1)]); @@ -534,6 +531,7 @@ fn nominating_and_rewards_should_work() { // nothing else will happen, era ends and rewards are paid again, // it is expected that nominators will also be paid. See below + mock::make_all_reward_payment(1); let payout_for_10 = total_payout_1 / 3; let payout_for_20 = 2 * total_payout_1 / 3; if cfg!(feature = "equalize") { @@ -904,7 +902,7 @@ fn reward_destination_works() { total: 1000, active: 1000, unlocking: vec![], - last_reward: 0, + next_reward: 0, })); // Compute total payout now for whole duration as other parameter won't change @@ -913,6 +911,7 @@ fn reward_destination_works() { >::reward_by_ids(vec![(11, 1)]); start_era(1); + mock::make_all_reward_payment(0); // Check that RewardDestination is Staked (default) assert_eq!(Staking::payee(&11), RewardDestination::Staked); @@ -924,7 +923,7 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: vec![], - last_reward: 0, + next_reward: 1, })); //Change RewardDestination to Stash @@ -936,6 +935,7 @@ fn reward_destination_works() { >::reward_by_ids(vec![(11, 1)]); start_era(2); + mock::make_all_reward_payment(1); // Check that RewardDestination is Stash assert_eq!(Staking::payee(&11), RewardDestination::Stash); @@ -949,7 +949,7 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: vec![], - last_reward: 0, + next_reward: 2, })); // Change RewardDestination to Controller @@ -964,6 +964,7 @@ fn reward_destination_works() { >::reward_by_ids(vec![(11, 1)]); start_era(3); + mock::make_all_reward_payment(2); // Check that RewardDestination is Controller assert_eq!(Staking::payee(&11), RewardDestination::Controller); @@ -975,7 +976,7 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: vec![], - last_reward: 0, + next_reward: 3, })); // Check that amount in staked account is NOT increased. assert_eq!(Balances::free_balance(&11), recorded_stash_balance); @@ -998,6 +999,7 @@ fn validator_payment_prefs_work() { >::insert(&101, RewardDestination::Controller); start_era(1); + mock::make_all_reward_payment(0); let balance_era_1_10 = Balances::total_balance(&10); let balance_era_1_100 = Balances::total_balance(&100); @@ -1009,6 +1011,7 @@ fn validator_payment_prefs_work() { >::reward_by_ids(vec![(11, 1)]); start_era(2); + mock::make_all_reward_payment(1); let taken_cut = commission * total_payout_1; let shared_cut = total_payout_1 - taken_cut; @@ -1039,7 +1042,7 @@ fn bond_extra_works() { total: 1000, active: 1000, unlocking: vec![], - last_reward: 0, + next_reward: 0, })); // Give account 11 some large free balance greater than total @@ -1053,7 +1056,7 @@ fn bond_extra_works() { total: 1000 + 100, active: 1000 + 100, unlocking: vec![], - last_reward: 0, + next_reward: 0, })); // Call the bond_extra function with a large number, should handle it @@ -1064,7 +1067,7 @@ fn bond_extra_works() { total: 1000000, active: 1000000, unlocking: vec![], - last_reward: 0, + next_reward: 0, })); }); } @@ -1099,7 +1102,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000, active: 1000, unlocking: vec![], - last_reward: 0, + next_reward: 0, })); assert_eq!(mock::validator_current_exposure(11), Exposure { total: 1000, own: 1000, others: vec![] }); @@ -1111,7 +1114,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000 + 100, active: 1000 + 100, unlocking: vec![], - last_reward: 0, + next_reward: 0, })); // Exposure is a snapshot! only updated after the next era update. assert_ne!(mock::validator_current_exposure(11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); @@ -1127,7 +1130,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000 + 100, active: 1000 + 100, unlocking: vec![], - last_reward: 0, + next_reward: 0, })); // Exposure is now updated. assert_eq!(mock::validator_current_exposure(11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); @@ -1135,13 +1138,13 @@ fn bond_extra_and_withdraw_unbonded_works() { // Unbond almost all of the funds in stash. Staking::unbond(Origin::signed(10), 1000).unwrap(); assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], last_reward: 0 }) + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], next_reward: 0 }) ); // Attempting to free the balances now will fail. 2 eras need to pass. Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], last_reward: 0 })); + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], next_reward: 0 })); // trigger next era. start_era(3); @@ -1149,7 +1152,7 @@ fn bond_extra_and_withdraw_unbonded_works() { // nothing yet Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], last_reward: 0 })); + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], next_reward: 0 })); // trigger next era. start_era(5); @@ -1157,7 +1160,7 @@ fn bond_extra_and_withdraw_unbonded_works() { Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); // Now the value is free and the staking ledger is updated. assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 100, active: 100, unlocking: vec![], last_reward: 0 })); + stash: 11, total: 100, active: 100, unlocking: vec![], next_reward: 0 })); }) } @@ -1218,7 +1221,7 @@ fn rebond_works() { total: 1000, active: 1000, unlocking: vec![], - last_reward: 0, + next_reward: 0, }) ); @@ -1243,7 +1246,7 @@ fn rebond_works() { value: 900, era: 2 + 3, }], - last_reward: 0, + next_reward: 0, }) ); @@ -1256,7 +1259,7 @@ fn rebond_works() { total: 1000, active: 1000, unlocking: vec![], - last_reward: 0, + next_reward: 0, }) ); @@ -1269,7 +1272,7 @@ fn rebond_works() { total: 1000, active: 100, unlocking: vec![UnlockChunk { value: 900, era: 5 }], - last_reward: 0, + next_reward: 0, }) ); @@ -1282,7 +1285,7 @@ fn rebond_works() { total: 1000, active: 600, unlocking: vec![UnlockChunk { value: 400, era: 5 }], - last_reward: 0, + next_reward: 0, }) ); @@ -1295,7 +1298,7 @@ fn rebond_works() { total: 1000, active: 1000, unlocking: vec![], - last_reward: 0, + next_reward: 0, }) ); @@ -1314,7 +1317,7 @@ fn rebond_works() { UnlockChunk { value: 300, era: 5 }, UnlockChunk { value: 300, era: 5 }, ], - last_reward: 0, + next_reward: 0, }) ); @@ -1330,7 +1333,7 @@ fn rebond_works() { UnlockChunk { value: 300, era: 5 }, UnlockChunk { value: 100, era: 5 }, ], - last_reward: 0, + next_reward: 0, }) ); }) @@ -1360,7 +1363,7 @@ fn rebond_works() { // // Now lets lower account 20 stake // mock::bypass_logic_change_current_exposure(21, Exposure { total: 69, own: 69, others: vec![] }); // assert_eq!(mock::validator_current_exposure(21).total, 69); -// >::insert(&20, StakingLedger { stash: 22, total: 69, active: 69, unlocking: vec![], last_reward: 0 }); +// >::insert(&20, StakingLedger { stash: 22, total: 69, active: 69, unlocking: vec![], next_reward: 0 }); // // Compute total payout now for whole duration as other parameter won't change // let total_payout_0 = current_total_payout_for_duration(3000); @@ -1592,7 +1595,7 @@ fn bond_with_no_staked_value() { active: 0, total: 5, unlocking: vec![UnlockChunk {value: 5, era: 3}], - last_reward: 0, + next_reward: 0, }) ); @@ -1857,22 +1860,19 @@ fn reward_from_authorship_event_handler_works() { >::note_author(11); >::note_uncle(21, 1); - // An uncle author that is not currently elected doesn't get rewards, - // but the block producer does get reward for referencing it. - >::note_uncle(31, 1); // Rewarding the same two times works. >::note_uncle(11, 1); // Not mandatory but must be coherent with rewards - assert_eq!(Session::validators(), vec![11, 21]); + assert_eq_uvec!(Session::validators(), vec![11, 21]); // 21 is rewarded as an uncle producer // 11 is rewarded as a block producer and uncle referencer and uncle producer assert_eq!( ErasRewardPoints::::get(ActiveEra::get()), EraRewardPoints { - individual: vec![(11, 20 + 2 * 3 + 1), (21, 1)].into_iter().collect(), - total: 28, + individual: vec![(11, 20 + 2 * 2 + 1), (21, 1)].into_iter().collect(), + total: 26, }, ); }) @@ -1882,15 +1882,8 @@ fn reward_from_authorship_event_handler_works() { fn add_reward_points_fns_works() { ExtBuilder::default().build().execute_with(|| { // Not mandatory but must be coherent with rewards - assert_eq!(Session::validators(), vec![11, 21]); - - // TODO TODO: no longer reward_by_indices - // >::reward_by_indices(vec![ - // (1, 1), - // (0, 1), - // (2, 1), - // (0, 1), - // ]); + assert_eq!(Session::validators(), vec![21, 11]); + >::reward_by_ids(vec![ (21, 1), (11, 1), From fd48681add70d5da1b1359f60590694b326af39d Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 10 Jan 2020 16:04:04 +0100 Subject: [PATCH 09/75] fix cutoff --- frame/staking/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 84b23382ffed7..d96947c61ed63 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1425,7 +1425,11 @@ impl Module { validator_point, era_reward_points.total, ); - let reward = validator_point_part.saturating_mul(commission.saturating_add(exposure_part)); + let reward = validator_point_part.saturating_mul( + commission.saturating_add( + Perbill::one().saturating_sub(commission).saturating_mul(exposure_part) + ) + ); // This is zero if the era is not finished yet. let era_payout = >::get(&era); println!("do_payout_validator: {:?}, reward: {:?}, era_payout: {:?}", who, reward, era_payout); From fa38f84a90ce3d96c546171348fca1e1b3b7ce2f Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 10 Jan 2020 16:24:15 +0100 Subject: [PATCH 10/75] fix saturation --- frame/staking/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index d96947c61ed63..ac3d21c9a7119 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1432,7 +1432,6 @@ impl Module { ); // This is zero if the era is not finished yet. let era_payout = >::get(&era); - println!("do_payout_validator: {:?}, reward: {:?}, era_payout: {:?}", who, reward, era_payout); if let Some(imbalance) = Self::make_payout(&ledger.stash, reward * era_payout) { Self::deposit_event(RawEvent::Reward(who, imbalance.peek())); } @@ -1723,7 +1722,7 @@ impl Module { if exposure.total < slot_stake { slot_stake = exposure.total; } - total_staked += exposure.total; + total_staked = total_staked.saturating_add(exposure.total); >::insert(¤t_era, &c, exposure.clone()); } From c4b0f2f5594331467bf039f37c75fead07b896a8 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 10 Jan 2020 16:27:56 +0100 Subject: [PATCH 11/75] comment --- frame/staking/src/lib.rs | 2 +- frame/staking/src/tests.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index ac3d21c9a7119..8191efc143354 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -15,11 +15,11 @@ // along with Substrate. If not, see . // TODO TODO: -// * fix: can someone make a new Ledger so it can claim old rewards ? // * migration // * upgrade test // * update doc // * new test +// * make commission updatable only one for next future era. not current_era. //! # Staking Module //! //! The Staking module is used to manage funds at stake by network maintainers. diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 1a7f3c2d0eb11..f28aadcc51da2 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -229,7 +229,6 @@ fn rewards_should_work() { assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); assert_eq_uvec!(Session::validators(), vec![11, 21]); - // >::reward_by_indices(vec![(0, 1)]); TODO TODO THis has been removed >::reward_by_ids(vec![(11, 1)]); // Compute total payout now for whole duration as other parameter won't change From 43152187cb320622fd3ee7eb3b806f037a97e260 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 10 Jan 2020 17:06:46 +0100 Subject: [PATCH 12/75] upgrade mock --- frame/staking/src/mock.rs | 52 +++++++++++++++++--------------------- frame/staking/src/tests.rs | 1 + 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 96d04e940683c..3ce3cc3503269 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -375,9 +375,7 @@ pub type Timestamp = pallet_timestamp::Module; pub type Staking = Module; pub fn check_exposure_all(era: EraIndex) { - // TODO TODO: and test order of nominators - // TODO TODO: - // Staking::validator_for_era(era).into_iter().for_each(|info| check_exposure(info)); + ErasStakers::::iter_prefix(era).for_each(check_exposure) } pub fn check_nominator_all(era: EraIndex) { @@ -386,37 +384,33 @@ pub fn check_nominator_all(era: EraIndex) { } /// Check for each selected validator: expo.total = Sum(expo.other) + expo.own -pub fn check_exposure(stash: AccountId) { - // TODO TODO: impl - // let stash = val_info.stash; - // let expo = val_info.exposure; - - // assert_is_stash(stash); - // assert_eq!( - // expo.total as u128, expo.own as u128 + expo.others.iter().map(|e| e.value as u128).sum::(), - // "wrong total exposure for {:?}: {:?}", stash, expo, - // ); +pub fn check_exposure(expo: Exposure) { + assert_eq!( + expo.total as u128, expo.own as u128 + expo.others.iter().map(|e| e.value as u128).sum::(), + "wrong total exposure {:?}", expo, + ); + let mut sorted = expo.others.clone(); + sorted.sort_by_key(|e| e.who); + assert_eq!(sorted, expo.others); } /// Check that for each nominator: slashable_balance > sum(used_balance) /// Note: we might not consume all of a nominator's balance, but we MUST NOT over spend it. pub fn check_nominator_exposure(era: EraIndex, stash: AccountId) { - // TODO TODO: impl - // assert_is_stash(stash); - // let mut sum = 0; - // Staking::validator_for_era(era) - // .iter() - // .for_each(|e| { - // e.exposure.others.iter() - // .filter(|i| i.who == stash) - // .for_each(|i| sum += i.value) - // }); - // let nominator_stake = Staking::slashable_balance_of(&stash); - // // a nominator cannot over-spend. - // assert!( - // nominator_stake >= sum, - // "failed: Nominator({}) stake({}) >= sum divided({})", stash, nominator_stake, sum, - // ); + assert_is_stash(stash); + let mut sum = 0; + ErasStakers::::iter_prefix(era) + .for_each(|exposure| { + exposure.others.iter() + .filter(|i| i.who == stash) + .for_each(|i| sum += i.value) + }); + let nominator_stake = Staking::slashable_balance_of(&stash); + // a nominator cannot over-spend. + assert!( + nominator_stake >= sum, + "failed: Nominator({}) stake({}) >= sum divided({})", stash, nominator_stake, sum, + ); } pub fn assert_is_stash(acc: AccountId) { diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index f28aadcc51da2..eac80559ff843 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2705,6 +2705,7 @@ fn version_initialized() { }); } +// TODO TODO: impl // // If on_session_ending is called with a decreasing will_apply_at and some era are force then some // // planned era should be overriden // #[test] From a26e9dac7da46687103078e9c8b92973e4f5c23b Mon Sep 17 00:00:00 2001 From: thiolliere Date: Sat, 11 Jan 2020 00:54:40 +0100 Subject: [PATCH 13/75] upgrade test --- frame/staking/src/lib.rs | 64 +++---- frame/staking/src/migration.rs | 15 ++ frame/staking/src/mock.rs | 11 -- frame/staking/src/tests.rs | 335 ++++++++++++++++----------------- 4 files changed, 197 insertions(+), 228 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 8191efc143354..1b4c4f99a6646 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -16,7 +16,6 @@ // TODO TODO: // * migration -// * upgrade test // * update doc // * new test // * make commission updatable only one for next future era. not current_era. @@ -698,26 +697,13 @@ decl_storage! { /// Direct storage APIs can still bypass this protection. Nominators get(fn nominators): linked_map T::AccountId => Option>; - // /// The currently elected validator set keyed by stash account ID. - // pub CurrentElected get(fn current_elected): Vec; - // TODO TODO: migration: clean this!!! - /// The current era index. pub CurrentEra get(fn current_era) config(): EraIndex; - // /// The start of the current era. - // // TODO TODO: actually no this doesn't match the start of the era at index CurrentEra. - // pub CurrentEraStart get(fn current_era_start): MomentOf; - // TODO TODO: clean this!! - pub ActiveEra get(fn active_era) config(): EraIndex; pub ActiveEraStart get(fn active_era_start): MomentOf; - // /// The session index at which the current era started. - // pub CurrentEraStartSessionIndex get(fn current_era_start_session_index): SessionIndex; - // TODO TODO: clean this!! - /// Nominators for a particular account that is in action right now. You can't iterate /// through validators here, but you can find them in the Session module. /// @@ -747,14 +733,6 @@ decl_storage! { /// The total amount staked for the last $HISTORY_DEPTH eras. pub ErasTotalStake get(fn eras_total_stake): map EraIndex => BalanceOf; - ///// The amount of balance actively at stake for each validator slot, currently. - ///// - ///// This is used to derive punishments. - //pub SlotStake get(fn slot_stake) build(|config: &GenesisConfig| { - // config.stakers.iter().map(|&(_, _, value, _)| value).min().unwrap_or_default() - //}): BalanceOf; - //TODO TODO: Slot stake is not longer used. clean this!! - /// True if the next session change will be a new era regardless of index. pub ForceEra get(fn force_era) config(): Forcing; @@ -795,6 +773,22 @@ decl_storage! { /// The version of storage for upgrade. StorageVersion: u32; + + /// Deprecated. + SlotStake: BalanceOf; + + /// Deprecated. + // The currently elected validator set keyed by stash account ID. + CurrentElected: Vec; + + /// Deprecated + // The start of the current era. + CurrentEraStart: MomentOf; + + /// Deprecated + // The session index at which the current era started. + CurrentEraStartSessionIndex: SessionIndex; + } add_extra_genesis { config(stakers): @@ -886,7 +880,6 @@ decl_module! { fn on_initialize() { Self::ensure_storage_upgraded(); - // TODO: Remove old `ErasValidatorReward` and `ErasStakers` entries. } fn on_finalize() { @@ -1432,6 +1425,7 @@ impl Module { ); // This is zero if the era is not finished yet. let era_payout = >::get(&era); + println!("payout_validator {:?} at {:?}: era payout {:?}", who, era, era_payout); if let Some(imbalance) = Self::make_payout(&ledger.stash, reward * era_payout) { Self::deposit_event(RawEvent::Reward(who, imbalance.peek())); } @@ -1439,10 +1433,6 @@ impl Module { Ok(()) } - // TODO: at the end of session, ensure that points are accumulated within the correct era. - // TODO: currently, validator set changes lag by one session, therefore, in the first session of - // TODO: an era, the points should be accumulated by the validator set of the era before. - /// Update the ledger for a controller. This will also update the stash lock. The lock will /// will lock the entire funds except paying for further transactions. fn update_ledger( @@ -1481,7 +1471,8 @@ impl Module { ), RewardDestination::Stash => T::Currency::deposit_into_existing(stash, amount).ok(), - RewardDestination::Staked => Self::bonded(stash) + RewardDestination::Staked => { + Self::bonded(stash) .and_then(|c| Self::ledger(&c).map(|l| (c, l))) .and_then(|(controller, mut l)| { l.active += amount; @@ -1489,7 +1480,7 @@ impl Module { let r = T::Currency::deposit_into_existing(stash, amount).ok(); Self::update_ledger(&controller, &l); r - }), + })}, } } @@ -1550,6 +1541,7 @@ impl Module { let current_era = CurrentEra::mutate(|s| { *s += 1; *s }); // TODO TODO: either start_session_index strictly increase or we must remove old era overriden // TODO TODO: update doc or code to make this correct + // TODO TODO: this should be closed by pallet-session API change. ErasStartSessionIndex::insert(¤t_era, &start_session_index); // Clean old era information. @@ -1782,19 +1774,6 @@ impl Module { /// /// COMPLEXITY: Complexity is `number_of_validator_to_reward x current_elected_len`. /// If you need to reward lots of validator consider using `reward_by_indices`. - // - // TODO: This is based on a false assumption; that rewarding will always add to a validator - // in the current era. It will not, since validator set lags by some amount (currently one - // session, but this may be configurable in the future). - // - // TODO: Force the rewarder to pass in the representative era index (or the session index) so - // we can figure out which era's reward this should go to and be able to add points to eras that - // have already passed. - // - // TODO: We should also ban collecting rewards from an era that may yet have points added to it. - // This will likely need an additional API from session to let us know when an era will no - // longer have any points added to it (i.e. basically just when the last session whose - // validator set is some previous era). pub fn reward_by_ids( validators_points: impl IntoIterator ) { @@ -1879,7 +1858,6 @@ impl Convert> for ExposureOf { fn convert(validator: T::AccountId) -> Option>> { - // TODO TODO: which exposure do we want here ? active era or current era ? Some(>::eras_stakers(>::current_era(), &validator)) } } diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs index bb020b0fc0e5f..bea9a09402637 100644 --- a/frame/staking/src/migration.rs +++ b/frame/staking/src/migration.rs @@ -60,6 +60,20 @@ mod inner { frame_support::print("Finished migrating Staking storage to v1."); } + pub fn from_v1_to_v2(version: &mut VersionNumber) { + if *version != 1 { return } + *version += 1; + + + + crate::SlotStake::::kill(); + crate::CurrentElected::::kill(); + crate::CurrentEraStart::::kill(); + crate::CurrentEraStartSessionIndex::kill(); + + frame_support::print("Finished migrating Staking storage to v2."); + } + pub(super) fn perform_migrations() { as Store>::StorageVersion::mutate(|version| { if *version < MIN_SUPPORTED_VERSION { @@ -72,6 +86,7 @@ mod inner { if *version == CURRENT_VERSION { return } to_v1::(version); + from_v1_to_v2::(version); }); } } diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 3ce3cc3503269..40a1caa08fee2 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -515,17 +515,6 @@ pub fn validator_current_exposure(stash: AccountId) -> Exposure) { - // TODO TODO: we can actually probably remove this function or just upgrade it. - // >::mutate(Staking::active_era(), |infos| { - // for info in infos { - // if info.stash == stash { - // info.exposure = exposure.clone(); - // } - // } - // }); -} - /// Make all validator and nominator request their payment pub fn make_all_reward_payment(era: EraIndex) { let validators_with_reward = ErasRewardPoints::::get(era).individual.keys() diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index eac80559ff843..962bf2027369d 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -1338,60 +1338,55 @@ fn rebond_works() { }) } -// TODO TODO: slot stake ? -// #[test] -// fn slot_stake_is_least_staked_validator_and_exposure_defines_maximum_punishment() { -// // Test that slot_stake is determined by the least staked validator -// // Test that slot_stake is the maximum punishment that can happen to a validator -// ExtBuilder::default().nominate(false).fair(false).build().execute_with(|| { -// // Confirm validator count is 2 -// assert_eq!(Staking::validator_count(), 2); -// // Confirm account 10 and 20 are validators -// assert_eq_uvec!(Session::validators(), vec![11, 21]); - -// assert_eq!(mock::validator_current_exposure(11).total, 1000); -// assert_eq!(mock::validator_current_exposure(21).total, 2000); - -// // Give the man some money. -// let _ = Balances::make_free_balance_be(&10, 1000); -// let _ = Balances::make_free_balance_be(&20, 1000); - -// // We confirm initialized slot_stake is this value -// assert_eq!(Staking::slot_stake_for_era(Staking::active_era()), mock::validator_current_exposure(11).total); - -// // Now lets lower account 20 stake -// mock::bypass_logic_change_current_exposure(21, Exposure { total: 69, own: 69, others: vec![] }); -// assert_eq!(mock::validator_current_exposure(21).total, 69); -// >::insert(&20, StakingLedger { stash: 22, total: 69, active: 69, unlocking: vec![], next_reward: 0 }); - -// // Compute total payout now for whole duration as other parameter won't change -// let total_payout_0 = current_total_payout_for_duration(3000); -// assert!(total_payout_0 > 100); // Test is meaningfull if reward something -// >::reward_by_ids(vec![(11, 1)]); -// >::reward_by_ids(vec![(21, 1)]); - -// // New era --> rewards are paid --> stakes are changed -// start_era(1); -// assert_eq!(mock::validator_current_exposure(11).total, 1000); -// assert_eq!(mock::validator_current_exposure(21).total, 69); -// assert_eq!(Staking::slot_stake_for_era(Staking::active_era()), 69); - -// let _11_balance = Balances::free_balance(&11); -// assert_eq!(_11_balance, 1000 + total_payout_0 / 2); - -// // Trigger another new era as the info are frozen before the era start. -// start_era(2); - -// // -- new infos -// assert_eq!(mock::validator_current_exposure(11).total, 1000 + total_payout_0 / 2); -// assert_eq!(mock::validator_current_exposure(21).total, 69 + total_payout_0 / 2); -// // -- slot stake should also be updated. -// assert_eq!(Staking::slot_stake_for_era(Staking::active_era()), 69 + total_payout_0 / 2); - -// check_exposure_all(Staking::active_era()); -// check_nominator_all(Staking::active_era()); -// }); -// } +#[test] +fn reward_to_stake_works() { + ExtBuilder::default().nominate(false).fair(false).build().execute_with(|| { + // Confirm validator count is 2 + assert_eq!(Staking::validator_count(), 2); + // Confirm account 10 and 20 are validators + assert_eq_uvec!(Session::validators(), vec![11, 21]); + + assert_eq!(mock::validator_current_exposure(11).total, 1000); + assert_eq!(mock::validator_current_exposure(21).total, 2000); + + // Give the man some money. + let _ = Balances::make_free_balance_be(&10, 1000); + let _ = Balances::make_free_balance_be(&20, 1000); + + // Bypass logic and change current exposure + ErasStakers::::insert(0, 21, Exposure { total: 69, own: 69, others: vec![] }); + + // Now lets lower account 20 stake + assert_eq!(mock::validator_current_exposure(21).total, 69); + >::insert(&20, StakingLedger { stash: 21, total: 69, active: 69, unlocking: vec![], next_reward: 0 }); + + // Compute total payout now for whole duration as other parameter won't change + let total_payout_0 = current_total_payout_for_duration(3000); + assert!(total_payout_0 > 100); // Test is meaningfull if reward something + >::reward_by_ids(vec![(11, 1)]); + >::reward_by_ids(vec![(21, 1)]); + + // New era --> rewards are paid --> stakes are changed + start_era(1); + mock::make_all_reward_payment(0); + + assert_eq!(mock::validator_current_exposure(11).total, 1000); + assert_eq!(mock::validator_current_exposure(21).total, 69); + + let _11_balance = Balances::free_balance(&11); + assert_eq!(_11_balance, 1000 + total_payout_0 / 2); + + // Trigger another new era as the info are frozen before the era start. + start_era(2); + + // -- new infos + assert_eq!(mock::validator_current_exposure(11).total, 1000 + total_payout_0 / 2); + assert_eq!(mock::validator_current_exposure(21).total, 69 + total_payout_0 / 2); + + check_exposure_all(Staking::active_era()); + check_nominator_all(Staking::active_era()); + }); +} #[test] fn on_free_balance_zero_stash_removes_validator() { @@ -1615,61 +1610,62 @@ fn bond_with_no_staked_value() { }); } -// TODO TODO: slot stake -// #[test] -// fn bond_with_little_staked_value_bounded_by_slot_stake() { -// // Behavior when someone bonds with little staked value. -// // Particularly when she votes and the candidate is elected. -// ExtBuilder::default() -// .validator_count(3) -// .nominate(false) -// .minimum_validator_count(1) -// .build() -// .execute_with(|| { -// // setup -// assert_ok!(Staking::chill(Origin::signed(30))); -// assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); -// let init_balance_2 = Balances::free_balance(&2); -// let init_balance_10 = Balances::free_balance(&10); - -// // Stingy validator. -// assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller)); -// assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); - -// // reward session 1 -// let total_payout_1 = current_total_payout_for_duration(3000); -// assert!(total_payout_1 > 100); // Test is meaningfull if reward something -// reward_all_elected(); -// start_era(1); - -// // 2 is elected. -// // and fucks up the slot stake. -// assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); -// assert_eq!(Staking::slot_stake_for_era(Staking::active_era()), 1); - -// // Old ones are rewarded. -// assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_1 / 3); -// // no rewards paid to 2. This was initial election. -// assert_eq!(Balances::free_balance(&2), init_balance_2); - -// // reward session 2 -// let total_payout_2 = current_total_payout_for_duration(3000); -// assert!(total_payout_2 > 100); // Test is meaningfull if reward something -// reward_all_elected(); -// start_era(2); - -// assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); -// assert_eq!(Staking::slot_stake_for_era(Staking::active_era()), 1); - -// assert_eq!(Balances::free_balance(&2), init_balance_2 + total_payout_2 / 3); -// assert_eq!( -// Balances::free_balance(&10), -// init_balance_10 + total_payout_1 / 3 + total_payout_2 / 3, -// ); -// check_exposure_all(Staking::active_era()); -// check_nominator_all(Staking::active_era()); -// }); -// } +#[test] +fn bond_with_little_staked_value_bounded() { + // Behavior when someone bonds with little staked value. + // Particularly when she votes and the candidate is elected. + ExtBuilder::default() + .validator_count(3) + .nominate(false) + .minimum_validator_count(1) + .build() + .execute_with(|| { + // setup + assert_ok!(Staking::chill(Origin::signed(30))); + assert_ok!(Staking::set_payee(Origin::signed(10), RewardDestination::Controller)); + let init_balance_2 = Balances::free_balance(&2); + let init_balance_10 = Balances::free_balance(&10); + + // Stingy validator. + assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller)); + assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); + + // reward session 1 + let total_payout_1 = current_total_payout_for_duration(3000); + assert!(total_payout_1 > 100); // Test is meaningfull if reward something + reward_all_elected(); + start_era(1); + mock::make_all_reward_payment(0); + + // 2 is elected. + assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); + // And has minimal stake + assert_eq!(Staking::eras_stakers(Staking::active_era(), 2).total, 0); + + // Old ones are rewarded. + assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_1 / 3); + // no rewards paid to 2. This was initial election. + assert_eq!(Balances::free_balance(&2), init_balance_2); + + // reward session 2 + let total_payout_2 = current_total_payout_for_duration(3000); + assert!(total_payout_2 > 100); // Test is meaningfull if reward something + reward_all_elected(); + start_era(2); + mock::make_all_reward_payment(1); + + assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 2).total, 0); + + assert_eq!(Balances::free_balance(&2), init_balance_2 + total_payout_2 / 3); + assert_eq!( + Balances::free_balance(&10), + init_balance_10 + total_payout_1 / 3 + total_payout_2 / 3, + ); + check_exposure_all(Staking::active_era()); + check_nominator_all(Staking::active_era()); + }); +} #[cfg(feature = "equalize")] #[test] @@ -1801,54 +1797,60 @@ fn phragmen_should_not_overflow_ultimate() { }) } -// TODO TODO -// #[test] -// fn reward_validator_slashing_validator_doesnt_overflow() { -// ExtBuilder::default().build().execute_with(|| { -// let stake = u32::max_value() as u64 * 2; -// let reward_slash = u32::max_value() as u64 * 2; - -// // Assert multiplication overflows in balance arithmetic. -// assert!(stake.checked_mul(reward_slash).is_none()); - -// // Set staker -// let _ = Balances::make_free_balance_be(&11, stake); - -// let exposure = Exposure { total: stake, own: stake, others: vec![] }; -// let prefs = ValidatorPrefs { commission: Perbill::zero() }; - -// // Check reward -// let _ = Staking::reward_validator(&11, &prefs, &exposure, reward_slash); -// assert_eq!(Balances::total_balance(&11), stake * 2); - -// // Set staker -// let _ = Balances::make_free_balance_be(&11, stake); -// let _ = Balances::make_free_balance_be(&2, stake); - -// // only slashes out of bonded stake are applied. without this line, -// // it is 0. -// Staking::bond(Origin::signed(2), 20000, stake - 1, RewardDestination::default()).unwrap(); -// mock::bypass_logic_change_current_exposure(11, Exposure { -// total: stake, -// own: 1, -// others: vec![ IndividualExposure { who: 2, value: stake - 1 }] -// }); - -// // Check slashing -// on_offence_now( -// &[ -// OffenceDetails { -// offender: (11, mock::validator_current_exposure(11)), -// reporters: vec![], -// }, -// ], -// &[Perbill::from_percent(100)], -// ); - -// assert_eq!(Balances::total_balance(&11), stake - 1); -// assert_eq!(Balances::total_balance(&2), 1); -// }) -// } +#[test] +fn reward_validator_slashing_validator_doesnt_overflow() { + ExtBuilder::default().build().execute_with(|| { + let stake = u32::max_value() as u64 * 2; + let reward_slash = u32::max_value() as u64 * 2; + + // Assert multiplication overflows in balance arithmetic. + assert!(stake.checked_mul(reward_slash).is_none()); + + // Set staker + let _ = Balances::make_free_balance_be(&11, stake); + + let exposure = Exposure:: { total: stake, own: stake, others: vec![] }; + let reward = EraRewardPoints:: { + total: 1, + individual: vec![(11, 1)].into_iter().collect(), + }; + + // Check reward + ErasRewardPoints::::insert(0, reward); + ErasStakers::::insert(0, 11, exposure); + ErasValidatorReward::::insert(0, stake); + assert_ok!(Staking::payout_validator(Origin::signed(10), 0)); + assert_eq!(Balances::total_balance(&11), stake * 2); + + // Set staker + let _ = Balances::make_free_balance_be(&11, stake); + let _ = Balances::make_free_balance_be(&2, stake); + + // only slashes out of bonded stake are applied. without this line, + // it is 0. + Staking::bond(Origin::signed(2), 20000, stake - 1, RewardDestination::default()).unwrap(); + // Override exposure of 11 + ErasStakers::::insert(0, 11, Exposure { + total: stake, + own: 1, + others: vec![ IndividualExposure { who: 2, value: stake - 1 }] + }); + + // Check slashing + on_offence_now( + &[ + OffenceDetails { + offender: (11, mock::validator_current_exposure(11)), + reporters: vec![], + }, + ], + &[Perbill::from_percent(100)], + ); + + assert_eq!(Balances::total_balance(&11), stake - 1); + assert_eq!(Balances::total_balance(&2), 1); + }) +} #[test] fn reward_from_authorship_event_handler_works() { @@ -2705,23 +2707,6 @@ fn version_initialized() { }); } -// TODO TODO: impl -// // If on_session_ending is called with a decreasing will_apply_at and some era are force then some -// // planned era should be overriden -// #[test] -// fn unplanned_future_era() { -// ExtBuilder::default().build().execute_with(|| { -// assert_eq!(Session::current_index(), 0); -// Staking::on_session_ending(0, 10); -// assert_eq!(Staking::eras_start_session_index(Staking::active_era()), vec![0, 10]); -// Staking::on_session_ending(1, 20); -// assert_eq!(Staking::eras_start_session_index(Staking::active_era()), vec![0, 10, 20]); -// assert_ok!(Staking::force_new_era(Origin::ROOT)); -// Staking::on_session_ending(2, 5); -// assert_eq!(Staking::eras_start_session_index(Staking::active_era()), vec![0, 5]); -// }); -// } - #[test] fn slash_kicks_validators_not_nominators() { ExtBuilder::default().build().execute_with(|| { @@ -2760,3 +2745,5 @@ fn slash_kicks_validators_not_nominators() { assert!(nominations.submitted_in < last_slash); }); } + +// TODO TODO: test that we can ask for our reward until the $HISTORY_DEPTH From 245ec98926a0d2022503743731db75eb92345d80 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 13 Jan 2020 18:20:11 +0100 Subject: [PATCH 14/75] WIP migration --- frame/staking/src/lib.rs | 17 ++++++++++- frame/staking/src/migration.rs | 56 +++++++++++++++++++++++++++++----- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 1b4c4f99a6646..c9015379b5bb5 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -19,6 +19,7 @@ // * update doc // * new test // * make commission updatable only one for next future era. not current_era. +// * new session API //! # Staking Module //! //! The Staking module is used to manage funds at stake by network maintainers. @@ -313,6 +314,17 @@ pub struct EraRewardPoints { individual: BTreeMap, } +/// Deprecated +// Reward points of an era. Used to split era total payout between validators. +#[derive(Encode, Decode, Default)] +pub struct EraPoints { + // Total number of points. Equals the sum of reward points for each validator. + total: u32, + // The reward points earned by a given validator. The index of this vec corresponds to the + // index into the current validator set. + individual: Vec, +} + /// Indicates the initial status of the staker. #[derive(RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -789,6 +801,9 @@ decl_storage! { // The session index at which the current era started. CurrentEraStartSessionIndex: SessionIndex; + /// Deprecated + // Rewards for the current era. Using indices of current elected set. + CurrentEraPointsEarned: EraPoints; } add_extra_genesis { config(stakers): @@ -1361,7 +1376,7 @@ impl Module { for validator in validators { let commission = Self::eras_validator_prefs(&era, &validator).commission; let validator_exposure = >::get(&era, &validator); - + if let Ok(nominator_exposure) = validator_exposure.others .binary_search_by(|exposure| exposure.who.cmp(&nominator_ledger.stash)) .map(|indice| &validator_exposure.others[indice]) diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs index bea9a09402637..4ef071206b14e 100644 --- a/frame/staking/src/migration.rs +++ b/frame/staking/src/migration.rs @@ -20,7 +20,7 @@ pub type VersionNumber = u32; // the current expected version of the storage -pub const CURRENT_VERSION: VersionNumber = 1; +pub const CURRENT_VERSION: VersionNumber = 2; #[cfg(any(test, feature = "migrate"))] mod inner { @@ -64,12 +64,54 @@ mod inner { if *version != 1 { return } *version += 1; - - - crate::SlotStake::::kill(); - crate::CurrentElected::::kill(); - crate::CurrentEraStart::::kill(); - crate::CurrentEraStartSessionIndex::kill(); + // Fill new storages. + + // TODO TODO: ActiveEra. + // we can't just compare current elected and T::SessionInterface::validators() because we + // could be in a new era while having the same set, we need to compare + // CurrentEraStartSessionIndex with session::current_index + // Or: what if you put a wrong one ? + + // Do ErasStakers, ErasValidatorPrefs and ErasTotalStake + let current_era = as Store>::CurrentEra::get(); + let active_era = as Store>::ActiveEra::get(); + let old_current_elected = >::CurrentElected::get(); + let mut current_total_stake = 0.into(); + for validator in &old_current_elected { + let exposure = as Store>::Stakers::get(elected); + current_total_stake += exposure.total; + let pref = as Store>::Validator::get(elected); + as Store>::ErasStakers::insert(current_era, validator, exposure); + as Store>::ErasValidatorPrefs::insert(current_era, validator, exposure); + } + as Store>::ErasTotalStake::insert(current_era, current_total_stake); + let mut active_total_stake = 0.into(); + for validator in T::SessionInterface::validators() { + let exposure = as Store>::Stakers::get(elected); + active_total_stake += exposure.total; + let pref = as Store>::Validator::get(elected); + as Store>::ErasStakers::insert(active_era, validator, exposure); + as Store>::ErasValidatorPrefs::insert(active_era, validator, exposure); + } + as Store>::ErasTotalStake::insert(active_era, active_total_stake); + + // Do ErasRewardPoints + let points = as Store>::CurrentEraPointsEarned::get(); + as Store>::ErasRewardPoints::insert(active_era, EraRewardPoints { + total: points.total, + individual: current_elected.zip(points.individual).collect(), + // TODO TODO: this or zip with active_validators? + }) + + // Do ActiveEraStart + as Store>::ActiveEraStart::put( as Store>::CurrentEraStart::get()); + + // Kill old storages + as Store>::SlotStake::kill(); + as Store>::CurrentElected::kill(); + as Store>::CurrentEraStart::kill(); + as Store>::CurrentEraStartSessionIndex::kill(); + as Store>::CurrentEraPointsEarned::kill(); frame_support::print("Finished migrating Staking storage to v2."); } From 42064353c5cc7fb40dde354abce793c54dc0e795 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 14 Jan 2020 13:45:28 +0100 Subject: [PATCH 15/75] WIP migration --- frame/staking/src/lib.rs | 47 +++++++++++++++++--------- frame/staking/src/migration.rs | 61 ++++++++++++++++++++++------------ 2 files changed, 71 insertions(+), 37 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index c9015379b5bb5..f62bc7e7daf59 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -110,6 +110,8 @@ //! The **reward and slashing** procedure is the core of the Staking module, attempting to _embrace //! valid behavior_ while _punishing any misbehavior or lack of availability_. //! +//! Reward must be claimed by stakers for each era before it gets too old by $HISTORY_DEPTH. +//! //! Slashing can occur at any point in time, once misbehavior is reported. Once slashing is //! determined, a value is deducted from the balance of the validator and all the nominators who //! voted for this validator (values are deducted from the _stash_ account of the slashed entity). @@ -165,14 +167,6 @@ //! //! ## Implementation Details //! -//! ### Slot Stake -//! -//! The term [`SlotStake`](./struct.Module.html#method.slot_stake) will be used throughout this -//! section. It refers to a value calculated at the end of each era, containing the _minimum value -//! at stake among all validators._ Note that a validator's value at stake might be a combination -//! of the validator's own stake and the votes it received. See [`Exposure`](./struct.Exposure.html) -//! for more details. -//! //! ### Reward Calculation //! //! Validators and nominators are rewarded at the end of each era. The total reward of an era is @@ -314,7 +308,7 @@ pub struct EraRewardPoints { individual: BTreeMap, } -/// Deprecated +/// Deprecated. Used for migration only. // Reward points of an era. Used to split era total payout between validators. #[derive(Encode, Decode, Default)] pub struct EraPoints { @@ -382,6 +376,17 @@ pub struct UnlockChunk { era: EraIndex, } +/// Deprecated. Used for migration only. +#[derive(Encode, Decode)] +struct StakingLedgerV1 { + stash: AccountId, + #[codec(compact)] + total: Balance, + #[codec(compact)] + active: Balance, + unlocking: Vec>, +} + /// The ledger of a (bonded) stash. #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] pub struct StakingLedger { @@ -400,10 +405,8 @@ pub struct StakingLedger { pub unlocking: Vec>, /// The next era at which the staker can claim reward. pub next_reward: EraIndex, - // TODO: ^^^ this will need migration logic. } - impl< AccountId, Balance: HasCompact + Copy + Saturating + SimpleArithmetic, @@ -584,6 +587,8 @@ pub trait SessionInterface: frame_system::Trait { fn validators() -> Vec; /// Prune historical session tries up to but not including the given index. fn prune_historical_up_to(up_to: SessionIndex); + /// The current session index. + fn current_index() -> SessionIndex; } impl SessionInterface<::AccountId> for T where @@ -608,6 +613,10 @@ impl SessionInterface<::AccountId> for T whe fn prune_historical_up_to(up_to: SessionIndex) { >::prune_up_to(up_to); } + + fn current_index() -> SessionIndex { + >::current_index() + } } pub trait Trait: frame_system::Trait { @@ -804,10 +813,18 @@ decl_storage! { /// Deprecated // Rewards for the current era. Using indices of current elected set. CurrentEraPointsEarned: EraPoints; - } - add_extra_genesis { - config(stakers): - Vec<(T::AccountId, T::AccountId, BalanceOf, StakerStatus)>; + + /// Deprecated + // Nominators for a particular account that is in action right now. You can't iterate + // through validators here, but you can find them in the Session module. + // + // This is keyed by the stash account. + Stakers: map T::AccountId => Exposure>; + +} +add_extra_genesis { +config(stakers): + Vec<(T::AccountId, T::AccountId, BalanceOf, StakerStatus)>; build(|config: &GenesisConfig| { for &(ref stash, ref controller, balance, ref status) in &config.stakers { assert!( diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs index 4ef071206b14e..e746c56ec73c7 100644 --- a/frame/staking/src/migration.rs +++ b/frame/staking/src/migration.rs @@ -24,10 +24,14 @@ pub const CURRENT_VERSION: VersionNumber = 2; #[cfg(any(test, feature = "migrate"))] mod inner { - use crate::{Store, Module, Trait}; - use frame_support::{StorageLinkedMap, StorageValue}; + use crate::{ + Store, Module, Trait, EraRewardPoints, SessionInterface, BalanceOf, StakingLedger, + StakingLedgerV1, + }; + use frame_support::{StorageLinkedMap, StorageValue, StorageMap, StorageDoubleMap, StoragePrefixedMap}; use sp_std::vec::Vec; use super::{CURRENT_VERSION, VersionNumber}; + use sp_runtime::traits::Zero; // the minimum supported version of the migration logic. const MIN_SUPPORTED_VERSION: VersionNumber = 0; @@ -60,38 +64,41 @@ mod inner { frame_support::print("Finished migrating Staking storage to v1."); } + pub fn from_v1_to_v2(version: &mut VersionNumber) { if *version != 1 { return } *version += 1; // Fill new storages. - // TODO TODO: ActiveEra. - // we can't just compare current elected and T::SessionInterface::validators() because we - // could be in a new era while having the same set, we need to compare - // CurrentEraStartSessionIndex with session::current_index - // Or: what if you put a wrong one ? + // Do ActiveEra + let current_era_start_index = as Store>::CurrentEraStartSessionIndex::get(); + let current_era = as Store>::CurrentEra::get(); + let active_era = if current_era_start_index > T::SessionInterface::current_index() { + current_era - 1 + } else { + current_era + }; + as Store>::ActiveEra::put(active_era); // Do ErasStakers, ErasValidatorPrefs and ErasTotalStake - let current_era = as Store>::CurrentEra::get(); - let active_era = as Store>::ActiveEra::get(); - let old_current_elected = >::CurrentElected::get(); - let mut current_total_stake = 0.into(); + let old_current_elected = as Store>::CurrentElected::get(); + let mut current_total_stake = >::zero(); for validator in &old_current_elected { - let exposure = as Store>::Stakers::get(elected); + let exposure = as Store>::Stakers::get(validator); current_total_stake += exposure.total; - let pref = as Store>::Validator::get(elected); + let pref = as Store>::Validators::get(validator); as Store>::ErasStakers::insert(current_era, validator, exposure); - as Store>::ErasValidatorPrefs::insert(current_era, validator, exposure); + as Store>::ErasValidatorPrefs::insert(current_era, validator, pref); } as Store>::ErasTotalStake::insert(current_era, current_total_stake); - let mut active_total_stake = 0.into(); - for validator in T::SessionInterface::validators() { - let exposure = as Store>::Stakers::get(elected); + let mut active_total_stake = >::zero(); + for validator in &T::SessionInterface::validators() { + let exposure = as Store>::Stakers::get(validator); active_total_stake += exposure.total; - let pref = as Store>::Validator::get(elected); + let pref = as Store>::Validators::get(validator); as Store>::ErasStakers::insert(active_era, validator, exposure); - as Store>::ErasValidatorPrefs::insert(active_era, validator, exposure); + as Store>::ErasValidatorPrefs::insert(active_era, validator, pref); } as Store>::ErasTotalStake::insert(active_era, active_total_stake); @@ -99,13 +106,23 @@ mod inner { let points = as Store>::CurrentEraPointsEarned::get(); as Store>::ErasRewardPoints::insert(active_era, EraRewardPoints { total: points.total, - individual: current_elected.zip(points.individual).collect(), - // TODO TODO: this or zip with active_validators? - }) + individual: old_current_elected.iter().cloned().zip(points.individual.iter().cloned()).collect(), + }); // Do ActiveEraStart as Store>::ActiveEraStart::put( as Store>::CurrentEraStart::get()); + // TODO TODO: StakingLedger + // let res = as Store>::Ledger::translate_value( + // |old: StakingLedgerV1>| StakingLedger { + // stash: old.stash, + // total: old.total, + // active: old.active, + // unlocking: old.unlocking, + // next_reward: 0, + // } + // ); + // Kill old storages as Store>::SlotStake::kill(); as Store>::CurrentElected::kill(); From 70b9ff8cac0a3d22d3beab20a7cab228c88a2b37 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 14 Jan 2020 14:19:03 +0100 Subject: [PATCH 16/75] remove slot stake stuff --- frame/staking/src/lib.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 3c9cda7219f1a..8629fe9cbbbae 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1690,8 +1690,7 @@ impl Module { ); let current_era = Self::current_era(); - // Populate ErasStakers and figure out the minimum stake behind a slot. - let mut slot_stake = BalanceOf::::max_value(); + // Populate ErasStakers and figure out the total stake. let mut total_staked = BalanceOf::::zero(); for (c, s) in supports.into_iter() { let mut others_exposure = s.others.into_iter() @@ -1709,9 +1708,6 @@ impl Module { total: to_balance(s.total), others: others_exposure, }; - if exposure.total < slot_stake { - slot_stake = exposure.total; - } total_staked = total_staked.saturating_add(exposure.total); >::insert(¤t_era, &c, exposure.clone()); } From f392d4a6c68bb6b9945f8a4cd85e425c6c6b8a12 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 14 Jan 2020 14:32:53 +0100 Subject: [PATCH 17/75] fix merge --- frame/staking/src/lib.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 0c4c72a3f4d21..dee225e6ae23a 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -731,13 +731,13 @@ decl_storage! { /// This is keyed fist by the era index to allow bulk deletion and then the stash account. /// /// Is it removed after `HISTORY_DEPTH` eras. - pub ErasStakers get(fn eras_stakers): double_map hasher(twox_64_concat) EraIndex, - twox_64_concat(T::AccountId) => Exposure>; - // TODO: ^^^ This will need a migration. + pub ErasStakers get(fn eras_stakers): + double_map hasher(twox_64_concat) EraIndex, hasher(twox_64_concat) T::AccountId + => Exposure>; // TODO: consider switching this to a simple map EraIndex => Vec pub ErasValidatorPrefs get(fn eras_validator_prefs): - double_map hasher(twox_64_concat) EraIndex, twox_64_concat(T::AccountId) + double_map hasher(twox_64_concat) EraIndex, hasher(twox_64_concat) T::AccountId => ValidatorPrefs; /// The per-validator era payout for one in the last `HISTORY_DEPTH` eras. @@ -1691,11 +1691,6 @@ impl Module { // Populate ErasStakers and figure out the total stake. let mut total_staked = BalanceOf::::zero(); for (c, s) in supports.into_iter() { - let mut others_exposure = s.others.into_iter() - .map(|(who, value)| IndividualExposure { who, value: to_balance(value) }) - .collect::>>(); - others_exposure.sort_by(|a, b| a.who.cmp(&b.who)); - // build `struct exposure` from `support` let mut others = Vec::new(); let mut own: BalanceOf = Zero::zero(); @@ -1711,6 +1706,7 @@ impl Module { } total = total.saturating_add(value); }); + others.sort_by(|a, b| a.who.cmp(&b.who)); let exposure = Exposure { own, others, From 2b9f80662d3e725c28ae102b197e10c8ed7a9385 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 14 Jan 2020 14:37:17 +0100 Subject: [PATCH 18/75] migration of ledger --- frame/staking/src/migration.rs | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs index e746c56ec73c7..16eebe86a8fed 100644 --- a/frame/staking/src/migration.rs +++ b/frame/staking/src/migration.rs @@ -112,16 +112,21 @@ mod inner { // Do ActiveEraStart as Store>::ActiveEraStart::put( as Store>::CurrentEraStart::get()); - // TODO TODO: StakingLedger - // let res = as Store>::Ledger::translate_value( - // |old: StakingLedgerV1>| StakingLedger { - // stash: old.stash, - // total: old.total, - // active: old.active, - // unlocking: old.unlocking, - // next_reward: 0, - // } - // ); + // Do StakingLedger + let res = as Store>::Ledger::translate_values( + |old: StakingLedgerV1>| StakingLedger { + stash: old.stash, + total: old.total, + active: old.active, + unlocking: old.unlocking, + next_reward: 0, + } + ); + if let Err(e) = res { + frame_support::print(&*format!("Encountered error in migration of Staking::Ledger map, \ + {} keys have been removed", e)); + } + // Kill old storages as Store>::SlotStake::kill(); From d0431f4b66c2059fcb8e165d2e6b66d021d413fa Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 14 Jan 2020 15:18:38 +0100 Subject: [PATCH 19/75] remove equalize from test --- frame/staking/src/lib.rs | 8 +-- frame/staking/src/tests.rs | 137 +++++++++++-------------------------- 2 files changed, 41 insertions(+), 104 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index dee225e6ae23a..a788f4fa73a37 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -14,12 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . -// TODO TODO: -// * migration -// * update doc -// * new test -// * make commission updatable only one for next future era. not current_era. -// * new session API //! # Staking Module //! //! The Staking module is used to manage funds at stake by network maintainers. @@ -1457,7 +1451,7 @@ impl Module { ); // This is zero if the era is not finished yet. let era_payout = >::get(&era); - println!("payout_validator {:?} at {:?}: era payout {:?}", who, era, era_payout); + println!("payout_validator {:?} at {:?}: payout {:?}/{:?}", who, era, reward * era_payout, era_payout); if let Some(imbalance) = Self::make_payout(&ledger.stash, reward * era_payout) { Self::deposit_event(RawEvent::Reward(who, imbalance.peek())); } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index b9b93be14294c..acc53a07d15b6 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -90,45 +90,24 @@ fn basic_setup_works() { ); assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); - if cfg!(feature = "equalize") { - assert_eq!( - Staking::eras_stakers(Staking::active_era(), 11), - Exposure { - total: 1250, - own: 1000, - others: vec![ IndividualExposure { who: 101, value: 250 }] - }, - ); - assert_eq!( - Staking::eras_stakers(Staking::active_era(), 21), - Exposure { - total: 1250, - own: 1000, - others: vec![ IndividualExposure { who: 101, value: 250 }] - }, - ); - // initial slot_stake - assert_eq!(Staking::eras_total_stake(Staking::active_era()), 2500); - } else { - assert_eq!( - Staking::eras_stakers(Staking::active_era(), 11), - Exposure { - total: 1125, - own: 1000, - others: vec![ IndividualExposure { who: 101, value: 125 }] - }, - ); - assert_eq!( - Staking::eras_stakers(Staking::active_era(), 21), - Exposure { - total: 1375, - own: 1000, - others: vec![ IndividualExposure { who: 101, value: 375 }] - }, - ); - // initial slot_stake - assert_eq!(Staking::eras_total_stake(Staking::active_era()), 2500); - } + assert_eq!( + Staking::eras_stakers(Staking::active_era(), 11), + Exposure { + total: 1125, + own: 1000, + others: vec![ IndividualExposure { who: 101, value: 125 }] + }, + ); + assert_eq!( + Staking::eras_stakers(Staking::active_era(), 21), + Exposure { + total: 1375, + own: 1000, + others: vec![ IndividualExposure { who: 101, value: 375 }] + }, + ); + // initial slot_stake + assert_eq!(Staking::eras_total_stake(Staking::active_era()), 2500); // The number of validators required. @@ -173,7 +152,6 @@ fn change_controller_works() { } #[test] -#[cfg(feature = "equalize")] fn rewards_should_work() { // should check that: // * rewards get recorded per session @@ -214,6 +192,10 @@ fn rewards_should_work() { total: 50*3, individual: vec![(11, 100), (21, 50)].into_iter().collect(), }); + let part_for_10 = Perbill::from_rational_approximation::(1000, 1125); + let part_for_20 = Perbill::from_rational_approximation::(1000, 1375); + let part_for_100_from_10 = Perbill::from_rational_approximation::(125, 1125); + let part_for_100_from_20 = Perbill::from_rational_approximation::(375, 1375); start_session(2); start_session(3); @@ -221,11 +203,17 @@ fn rewards_should_work() { assert_eq!(Staking::active_era(), 1); mock::make_all_reward_payment(0); - assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + total_payout_0*2/3*1000/1250, 2); + assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * total_payout_0*2/3, 2); assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2); - assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + total_payout_0*1/3*1000/1250, 2); + assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0*1/3, 2); assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2); - assert_eq_error_rate!(Balances::total_balance(&100), init_balance_100 + total_payout_0*250/1250, 2); + assert_eq_error_rate!( + Balances::total_balance(&100), + init_balance_100 + + part_for_100_from_10 * total_payout_0 * 2/3 + + part_for_100_from_20 * total_payout_0 * 1/3, + 2 + ); assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); assert_eq_uvec!(Session::validators(), vec![11, 21]); @@ -238,11 +226,17 @@ fn rewards_should_work() { start_era(2); mock::make_all_reward_payment(1); - assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + (total_payout_0*2/3 + total_payout_1)*1000/1250, 2); + assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * (total_payout_0 * 2/3 + total_payout_1), 2); assert_eq_error_rate!(Balances::total_balance(&11), init_balance_11, 2); - assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + total_payout_0*1/3*1000/1250, 2); + assert_eq_error_rate!(Balances::total_balance(&20), init_balance_20 + part_for_20 * total_payout_0 * 1/3, 2); assert_eq_error_rate!(Balances::total_balance(&21), init_balance_21, 2); - assert_eq_error_rate!(Balances::total_balance(&100), init_balance_100 + (total_payout_0 + total_payout_1)*250/1250, 2); + assert_eq_error_rate!( + Balances::total_balance(&100), + init_balance_100 + + part_for_100_from_10 * (total_payout_0 * 2/3 + total_payout_1) + + part_for_100_from_20 * total_payout_0 * 1/3, + 2 + ); assert_eq_error_rate!(Balances::total_balance(&101), init_balance_101, 2); }); } @@ -1770,51 +1764,6 @@ fn bond_with_little_staked_value_bounded() { }); } -#[cfg(feature = "equalize")] -#[test] -fn phragmen_linear_worse_case_equalize() { - ExtBuilder::default() - .nominate(false) - .validator_pool(true) - .fair(true) - .build() - .execute_with(|| { - bond_validator(50, 1000); - bond_validator(60, 1000); - bond_validator(70, 1000); - - bond_nominator(2, 2000, vec![11]); - bond_nominator(4, 1000, vec![11, 21]); - bond_nominator(6, 1000, vec![21, 31]); - bond_nominator(8, 1000, vec![31, 41]); - bond_nominator(110, 1000, vec![41, 51]); - bond_nominator(120, 1000, vec![51, 61]); - bond_nominator(130, 1000, vec![61, 71]); - - for i in &[10, 20, 30, 40, 50, 60, 70] { - assert_ok!(Staking::set_payee(Origin::signed(*i), RewardDestination::Controller)); - } - - assert_eq_uvec!(validator_controllers(), vec![40, 30]); - assert_ok!(Staking::set_validator_count(Origin::ROOT, 7)); - - start_era(1); - - assert_eq_uvec!(validator_controllers(), vec![10, 60, 40, 20, 50, 30, 70]); - - assert_eq_error_rate!(mock::validator_current_exposure(11).total, 3000, 2); - assert_eq_error_rate!(mock::validator_current_exposure(21).total, 2255, 2); - assert_eq_error_rate!(mock::validator_current_exposure(31).total, 2255, 2); - assert_eq_error_rate!(mock::validator_current_exposure(41).total, 1925, 2); - assert_eq_error_rate!(mock::validator_current_exposure(51).total, 1870, 2); - assert_eq_error_rate!(mock::validator_current_exposure(61).total, 1890, 2); - assert_eq_error_rate!(mock::validator_current_exposure(71).total, 1800, 2); - - check_exposure_all(Staking::active_era()); - check_nominator_all(Staking::active_era()); - }) -} - #[test] fn new_era_elects_correct_number_of_validators() { ExtBuilder::default() @@ -2210,9 +2159,6 @@ fn reporters_receive_their_slice() { // amount. ExtBuilder::default().build().execute_with(|| { // The reporters' reward is calculated from the total exposure. - #[cfg(feature = "equalize")] - let initial_balance = 1250; - #[cfg(not(feature = "equalize"))] let initial_balance = 1125; assert_eq!(mock::validator_current_exposure(11).total, initial_balance); @@ -2244,9 +2190,6 @@ fn subsequent_reports_in_same_span_pay_out_less() { // amount. ExtBuilder::default().build().execute_with(|| { // The reporters' reward is calculated from the total exposure. - #[cfg(feature = "equalize")] - let initial_balance = 1250; - #[cfg(not(feature = "equalize"))] let initial_balance = 1125; assert_eq!(mock::validator_current_exposure(11).total, initial_balance); From 10232de5030ddaf5a72f9a2c10188a1fd3d2893f Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 14 Jan 2020 16:01:02 +0100 Subject: [PATCH 20/75] add test --- frame/staking/src/lib.rs | 2 +- frame/staking/src/tests.rs | 68 +++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index a788f4fa73a37..f0a25f519ebb2 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1451,7 +1451,6 @@ impl Module { ); // This is zero if the era is not finished yet. let era_payout = >::get(&era); - println!("payout_validator {:?} at {:?}: payout {:?}/{:?}", who, era, reward * era_payout, era_payout); if let Some(imbalance) = Self::make_payout(&ledger.stash, reward * era_payout) { Self::deposit_event(RawEvent::Reward(who, imbalance.peek())); } @@ -1574,6 +1573,7 @@ impl Module { if let Some(era) = current_era.checked_sub(HISTORY_DEPTH) { >::remove_prefix(era); >::remove(era); + >::remove(era); >::remove(era); >::remove(era); ErasStartSessionIndex::remove(era); diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index acc53a07d15b6..56192c6b01d8d 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2792,4 +2792,70 @@ fn slash_kicks_validators_not_nominators() { }); } -// TODO TODO: test that we can ask for our reward until the $HISTORY_DEPTH +#[test] +fn claim_reward_at_the_last_era() { + // should check that: + // * rewards get paid until $HISTORY_DEPTH for both validators and nominators + ExtBuilder::default().nominate(true).build().execute_with(|| { + let init_balance_10 = Balances::total_balance(&10); + let init_balance_11 = Balances::total_balance(&11); + let init_balance_100 = Balances::total_balance(&100); + let init_balance_101 = Balances::total_balance(&101); + + let part_for_10 = Perbill::from_rational_approximation::(1000, 1125); + let part_for_100 = Perbill::from_rational_approximation::(125, 1125); + + // Check state + Payee::::insert(11, RewardDestination::Controller); + Payee::::insert(101, RewardDestination::Controller); + + >::reward_by_ids(vec![(11, 1)]); + // Compute total payout now for whole duration as other parameter won't change + let total_payout_0 = current_total_payout_for_duration(3000); + assert!(total_payout_0 > 10); // Test is meaningful if reward something + + start_era(1); + + >::reward_by_ids(vec![(11, 1)]); + // Change total issuance in order to modify total payout + let _ = Balances::deposit_creating(&999, 1_000_000_000); + // Compute total payout now for whole duration as other parameter won't change + let total_payout_1 = current_total_payout_for_duration(3000); + assert!(total_payout_1 > 10); // Test is meaningful if reward something + assert!(total_payout_1 != total_payout_0); + + start_era(2); + + >::reward_by_ids(vec![(11, 1)]); + // Change total issuance in order to modify total payout + let _ = Balances::deposit_creating(&999, 1_000_000_000); + // Compute total payout now for whole duration as other parameter won't change + let total_payout_2 = current_total_payout_for_duration(3000); + assert!(total_payout_2 > 10); // Test is meaningful if reward something + assert!(total_payout_2 != total_payout_0); + assert!(total_payout_2 != total_payout_1); + + start_era(crate::HISTORY_DEPTH); + + // This is the latest planned era in staking, not the active era + let current_era = Staking::current_era(); + assert!(current_era - crate::HISTORY_DEPTH == 0); + Staking::payout_validator(Origin::signed(10), 0); + Staking::payout_validator(Origin::signed(10), 1); + Staking::payout_validator(Origin::signed(10), 2); + Staking::payout_nominator(Origin::signed(100), 0, vec![11]); + Staking::payout_nominator(Origin::signed(100), 1, vec![11]); + Staking::payout_nominator(Origin::signed(100), 2, vec![11]); + + // Era 0 can't be rewarded anymore, only era 1 and 2 can be rewarded + + assert_eq!( + Balances::total_balance(&10), + init_balance_10 + part_for_10 * (total_payout_1 + total_payout_2), + ); + assert_eq!( + Balances::total_balance(&100), + init_balance_100 + part_for_100 * (total_payout_1 + total_payout_2), + ); + }); +} From 6367fda5e49568af61090fc0090201b38ff0c2e0 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 14 Jan 2020 16:07:40 +0100 Subject: [PATCH 21/75] fix --- frame/staking/src/lib.rs | 2 +- frame/staking/src/tests.rs | 185 +++++++++++++------------------------ 2 files changed, 65 insertions(+), 122 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index f0a25f519ebb2..260b65cb38982 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1572,8 +1572,8 @@ impl Module { // Clean old era information. if let Some(era) = current_era.checked_sub(HISTORY_DEPTH) { >::remove_prefix(era); + >::remove_prefix(era); >::remove(era); - >::remove(era); >::remove(era); >::remove(era); ErasStartSessionIndex::remove(era); diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 56192c6b01d8d..aed851c94af67 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -461,57 +461,30 @@ fn nominating_and_rewards_should_work() { // ------ check the staked value of all parties. - if cfg!(feature = "equalize") { - // 30 and 40 are not chosen anymore - assert_eq!(ErasStakers::::iter_prefix(Staking::active_era()).count(), 2); - assert_eq!( - Staking::eras_stakers(Staking::active_era(), 11), - Exposure { - total: 1000 + 1000, - own: 1000, - others: vec![ - IndividualExposure { who: 1, value: 400 }, - IndividualExposure { who: 3, value: 600 }, - ] - }, - ); - assert_eq!( - Staking::eras_stakers(Staking::active_era(), 21), - Exposure { - total: 1000 + 1000, - own: 1000, - others: vec![ - IndividualExposure { who: 1, value: 600 }, - IndividualExposure { who: 3, value: 400 }, - ] - }, - ); - } else { - // 30 and 40 are not chosen anymore - assert_eq!(ErasStakers::::iter_prefix(Staking::active_era()).count(), 2); - assert_eq!( - Staking::eras_stakers(Staking::active_era(), 11), - Exposure { - total: 1000 + 800, - own: 1000, - others: vec![ - IndividualExposure { who: 1, value: 400 }, - IndividualExposure { who: 3, value: 400 }, - ] - }, - ); - assert_eq!( - Staking::eras_stakers(Staking::active_era(), 21), - Exposure { - total: 1000 + 1200, - own: 1000, - others: vec![ - IndividualExposure { who: 1, value: 600 }, - IndividualExposure { who: 3, value: 600 }, - ] - }, - ); - } + // 30 and 40 are not chosen anymore + assert_eq!(ErasStakers::::iter_prefix(Staking::active_era()).count(), 2); + assert_eq!( + Staking::eras_stakers(Staking::active_era(), 11), + Exposure { + total: 1000 + 800, + own: 1000, + others: vec![ + IndividualExposure { who: 1, value: 400 }, + IndividualExposure { who: 3, value: 400 }, + ] + }, + ); + assert_eq!( + Staking::eras_stakers(Staking::active_era(), 21), + Exposure { + total: 1000 + 1200, + own: 1000, + others: vec![ + IndividualExposure { who: 1, value: 600 }, + IndividualExposure { who: 3, value: 600 }, + ] + }, + ); // the total reward for era 1 let total_payout_1 = current_total_payout_for_duration(3000); @@ -527,59 +500,31 @@ fn nominating_and_rewards_should_work() { mock::make_all_reward_payment(1); let payout_for_10 = total_payout_1 / 3; let payout_for_20 = 2 * total_payout_1 / 3; - if cfg!(feature = "equalize") { - // Nominator 2: has [400 / 2000 ~ 1 / 5 from 10] + [600 / 2000 ~ 3 / 10 from 20]'s reward. - assert_eq_error_rate!( - Balances::total_balance(&2), - initial_balance + payout_for_10 / 5 + payout_for_20 * 3 / 10, - 2, - ); - // Nominator 4: has [400 / 2000 ~ 1 / 5 from 20] + [600 / 2000 ~ 3 / 10 from 10]'s reward. - assert_eq_error_rate!( - Balances::total_balance(&4), - initial_balance + payout_for_20 / 5 + payout_for_10 * 3 / 10, - 2, - ); - - // Validator 10: got 1000 / 2000 external stake. - assert_eq_error_rate!( - Balances::total_balance(&10), - initial_balance + payout_for_10 / 2, - 1, - ); - // Validator 20: got 1000 / 2000 external stake. - assert_eq_error_rate!( - Balances::total_balance(&20), - initial_balance + payout_for_20 / 2, - 1, - ); - } else { - // Nominator 2: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 - assert_eq_error_rate!( - Balances::total_balance(&2), - initial_balance + (2 * payout_for_10 / 9 + 3 * payout_for_20 / 11), - 1, - ); - // Nominator 4: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 - assert_eq_error_rate!( - Balances::total_balance(&4), - initial_balance + (2 * payout_for_10 / 9 + 3 * payout_for_20 / 11), - 1, - ); - - // Validator 10: got 800 / 1800 external stake => 8/18 =? 4/9 => Validator's share = 5/9 - assert_eq_error_rate!( - Balances::total_balance(&10), - initial_balance + 5 * payout_for_10 / 9, - 1, - ); - // Validator 20: got 1200 / 2200 external stake => 12/22 =? 6/11 => Validator's share = 5/11 - assert_eq_error_rate!( - Balances::total_balance(&20), - initial_balance + 5 * payout_for_20 / 11, - 1, - ); - } + // Nominator 2: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 + assert_eq_error_rate!( + Balances::total_balance(&2), + initial_balance + (2 * payout_for_10 / 9 + 3 * payout_for_20 / 11), + 1, + ); + // Nominator 4: has [400/1800 ~ 2/9 from 10] + [600/2200 ~ 3/11 from 20]'s reward. ==> 2/9 + 3/11 + assert_eq_error_rate!( + Balances::total_balance(&4), + initial_balance + (2 * payout_for_10 / 9 + 3 * payout_for_20 / 11), + 1, + ); + + // Validator 10: got 800 / 1800 external stake => 8/18 =? 4/9 => Validator's share = 5/9 + assert_eq_error_rate!( + Balances::total_balance(&10), + initial_balance + 5 * payout_for_10 / 9, + 1, + ); + // Validator 20: got 1200 / 2200 external stake => 12/22 =? 6/11 => Validator's share = 5/11 + assert_eq_error_rate!( + Balances::total_balance(&20), + initial_balance + 5 * payout_for_20 / 11, + 1, + ); check_exposure_all(Staking::active_era()); check_nominator_all(Staking::active_era()); @@ -1727,9 +1672,9 @@ fn bond_with_little_staked_value_bounded() { assert_ok!(Staking::bond(Origin::signed(1), 2, 1, RewardDestination::Controller)); assert_ok!(Staking::validate(Origin::signed(2), ValidatorPrefs::default())); - // reward session 1 - let total_payout_1 = current_total_payout_for_duration(3000); - assert!(total_payout_1 > 100); // Test is meaningfull if reward something + // reward era 0 + let total_payout_0 = current_total_payout_for_duration(3000); + assert!(total_payout_0 > 100); // Test is meaningfull if reward something reward_all_elected(); start_era(1); mock::make_all_reward_payment(0); @@ -1740,13 +1685,13 @@ fn bond_with_little_staked_value_bounded() { assert_eq!(Staking::eras_stakers(Staking::active_era(), 2).total, 0); // Old ones are rewarded. - assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_1 / 3); + assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_0 / 3); // no rewards paid to 2. This was initial election. assert_eq!(Balances::free_balance(&2), init_balance_2); - // reward session 2 - let total_payout_2 = current_total_payout_for_duration(3000); - assert!(total_payout_2 > 100); // Test is meaningfull if reward something + // reward era 1 + let total_payout_1 = current_total_payout_for_duration(3000); + assert!(total_payout_1 > 100); // Test is meaningfull if reward something reward_all_elected(); start_era(2); mock::make_all_reward_payment(1); @@ -1754,10 +1699,10 @@ fn bond_with_little_staked_value_bounded() { assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); assert_eq!(Staking::eras_stakers(Staking::active_era(), 2).total, 0); - assert_eq!(Balances::free_balance(&2), init_balance_2 + total_payout_2 / 3); + assert_eq!(Balances::free_balance(&2), init_balance_2 + total_payout_1 / 3); assert_eq!( Balances::free_balance(&10), - init_balance_10 + total_payout_1 / 3 + total_payout_2 / 3, + init_balance_10 + total_payout_0 / 3 + total_payout_1 / 3, ); check_exposure_all(Staking::active_era()); check_nominator_all(Staking::active_era()); @@ -2798,9 +2743,7 @@ fn claim_reward_at_the_last_era() { // * rewards get paid until $HISTORY_DEPTH for both validators and nominators ExtBuilder::default().nominate(true).build().execute_with(|| { let init_balance_10 = Balances::total_balance(&10); - let init_balance_11 = Balances::total_balance(&11); let init_balance_100 = Balances::total_balance(&100); - let init_balance_101 = Balances::total_balance(&101); let part_for_10 = Perbill::from_rational_approximation::(1000, 1125); let part_for_100 = Perbill::from_rational_approximation::(125, 1125); @@ -2840,12 +2783,12 @@ fn claim_reward_at_the_last_era() { // This is the latest planned era in staking, not the active era let current_era = Staking::current_era(); assert!(current_era - crate::HISTORY_DEPTH == 0); - Staking::payout_validator(Origin::signed(10), 0); - Staking::payout_validator(Origin::signed(10), 1); - Staking::payout_validator(Origin::signed(10), 2); - Staking::payout_nominator(Origin::signed(100), 0, vec![11]); - Staking::payout_nominator(Origin::signed(100), 1, vec![11]); - Staking::payout_nominator(Origin::signed(100), 2, vec![11]); + assert_ok!(Staking::payout_validator(Origin::signed(10), 0)); + assert_ok!(Staking::payout_validator(Origin::signed(10), 1)); + assert_ok!(Staking::payout_validator(Origin::signed(10), 2)); + assert_ok!(Staking::payout_nominator(Origin::signed(100), 0, vec![11])); + assert_ok!(Staking::payout_nominator(Origin::signed(100), 1, vec![11])); + assert_ok!(Staking::payout_nominator(Origin::signed(100), 2, vec![11])); // Era 0 can't be rewarded anymore, only era 1 and 2 can be rewarded From 30eb57c8926351f66cb5489dc1cdb7fa8338cfa7 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 14 Jan 2020 16:17:52 +0100 Subject: [PATCH 22/75] update doc --- frame/staking/src/lib.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 260b65cb38982..1fb1bbb219e9c 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -713,14 +713,18 @@ decl_storage! { Nominators get(fn nominators): linked_map T::AccountId => Option>; /// The current era index. + /// + /// This is the latest planned era, depending on how session module queues the validator + /// set, it might be active or not. pub CurrentEra get(fn current_era) config(): EraIndex; + /// The active era index, the era currently rewarded. pub ActiveEra get(fn active_era) config(): EraIndex; + /// The start of the currently rewarded era. pub ActiveEraStart get(fn active_era_start): MomentOf; - /// Nominators for a particular account that is in action right now. You can't iterate - /// through validators here, but you can find them in the Session module. + /// Exposure of validator at era. /// /// This is keyed fist by the era index to allow bulk deletion and then the stash account. /// @@ -730,6 +734,11 @@ decl_storage! { => Exposure>; // TODO: consider switching this to a simple map EraIndex => Vec + /// Similarly to `ErasStakers` this holds the preferences of validators. + /// + /// This is keyed fist by the era index to allow bulk deletion and then the stash account. + /// + /// Is it removed after `HISTORY_DEPTH` eras. pub ErasValidatorPrefs get(fn eras_validator_prefs): double_map hasher(twox_64_concat) EraIndex, hasher(twox_64_concat) T::AccountId => ValidatorPrefs; @@ -739,13 +748,13 @@ decl_storage! { /// Eras that haven't finished yet doesn't have reward. pub ErasValidatorReward get(fn eras_validator_reward): map EraIndex => BalanceOf; - /// The session index at which the era started for the last $HISTORY_DEPTH eras + /// The session index at which the era started for the last `HISTORY_DEPTH` eras pub ErasStartSessionIndex get(fn eras_start_session_index): map EraIndex => SessionIndex; - /// Rewards for the last $HISTORY_DEPTH eras. + /// Rewards for the last `HISTORY_DEPTH` eras. pub ErasRewardPoints get(fn eras_reward_points): map EraIndex => EraRewardPoints; - /// The total amount staked for the last $HISTORY_DEPTH eras. + /// The total amount staked for the last `HISTORY_DEPTH` eras. pub ErasTotalStake get(fn eras_total_stake): map EraIndex => BalanceOf; /// True if the next session change will be a new era regardless of index. From 8eb8a58d8a8b5c9aeb5145ea541c50c52a672d0b Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 14 Jan 2020 18:26:14 +0100 Subject: [PATCH 23/75] fix compilation --- frame/staking/src/migration.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs index 16eebe86a8fed..0fd8da55820f9 100644 --- a/frame/staking/src/migration.rs +++ b/frame/staking/src/migration.rs @@ -123,8 +123,9 @@ mod inner { } ); if let Err(e) = res { - frame_support::print(&*format!("Encountered error in migration of Staking::Ledger map, \ - {} keys have been removed", e)); + frame_support::print("Encountered error in migration of Staking::Ledger map."); + frame_support::print("The number of removed key/value is:"); + frame_support::print(e); } From eb0d4e592ea37e8702578d4c86bc9c47fc2e0ad9 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Wed, 15 Jan 2020 23:48:21 +0100 Subject: [PATCH 24/75] improve test readibility --- frame/staking/src/mock.rs | 4 -- frame/staking/src/tests.rs | 118 ++++++++++++++++++------------------- 2 files changed, 59 insertions(+), 63 deletions(-) diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 7ba7be1f272a7..0d0fcc571d915 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -512,10 +512,6 @@ pub fn on_offence_now( on_offence_in_era(offenders, slash_fraction, now) } -pub fn validator_current_exposure(stash: AccountId) -> Exposure { - Staking::eras_stakers(Staking::active_era(), stash) -} - /// Make all validator and nominator request their payment pub fn make_all_reward_payment(era: EraIndex) { let validators_with_reward = ErasRewardPoints::::get(era).individual.keys() diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index aed851c94af67..501d7f2f2d6c9 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -570,13 +570,13 @@ fn nominators_also_get_slashed() { &[OffenceDetails { offender: ( 11, - mock::validator_current_exposure(11), + Staking::eras_stakers(Staking::active_era(), 11), ), reporters: vec![], }], &[Perbill::from_percent(5)], ); - let expo = mock::validator_current_exposure(11); + let expo = Staking::eras_stakers(Staking::active_era(), 11); let slash_value = 50; let total_slash = expo.total.min(slash_value); let validator_slash = expo.own.min(total_slash); @@ -754,7 +754,7 @@ fn cannot_transfer_staked_balance() { // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(&11), 1000); // Confirm account 11 (via controller 10) is totally staked - assert_eq!(mock::validator_current_exposure(11).total, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).total, 1000); // Confirm account 11 cannot transfer as a result assert_noop!( Balances::transfer(Origin::signed(11), 20, 1), @@ -783,7 +783,7 @@ fn cannot_transfer_staked_balance_2() { // Confirm account 21 has some free balance assert_eq!(Balances::free_balance(&21), 2000); // Confirm account 21 (via controller 20) is totally staked - assert_eq!(mock::validator_current_exposure(21).total, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 21).total, 1000); // Confirm account 21 can transfer at most 1000 assert_noop!( Balances::transfer(Origin::signed(21), 20, 1001), @@ -806,7 +806,7 @@ fn cannot_reserve_staked_balance() { // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(&11), 1000); // Confirm account 11 (via controller 10) is totally staked - assert_eq!(mock::validator_current_exposure(11).own, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).own, 1000); // Confirm account 11 cannot transfer as a result assert_noop!( Balances::reserve(&11, 1), @@ -944,7 +944,7 @@ fn validator_payment_prefs_work() { // Compute total payout now for whole duration as other parameter won't change let total_payout_1 = current_total_payout_for_duration(3000); - let exposure_1 = mock::validator_current_exposure(11); + let exposure_1 = Staking::eras_stakers(Staking::active_era(), 11); assert!(total_payout_1 > 100); // Test is meaningfull if reward something >::reward_by_ids(vec![(11, 1)]); @@ -1042,7 +1042,7 @@ fn bond_extra_and_withdraw_unbonded_works() { unlocking: vec![], next_reward: 0, })); - assert_eq!(mock::validator_current_exposure(11), Exposure { total: 1000, own: 1000, others: vec![] }); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 11), Exposure { total: 1000, own: 1000, others: vec![] }); // deposit the extra 100 units Staking::bond_extra(Origin::signed(11), 100).unwrap(); @@ -1055,7 +1055,7 @@ fn bond_extra_and_withdraw_unbonded_works() { next_reward: 0, })); // Exposure is a snapshot! only updated after the next era update. - assert_ne!(mock::validator_current_exposure(11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + assert_ne!(Staking::eras_stakers(Staking::active_era(), 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); // trigger next era. Timestamp::set_timestamp(10); @@ -1071,7 +1071,7 @@ fn bond_extra_and_withdraw_unbonded_works() { next_reward: 0, })); // Exposure is now updated. - assert_eq!(mock::validator_current_exposure(11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); // Unbond almost all of the funds in stash. Staking::unbond(Origin::signed(10), 1000).unwrap(); @@ -1388,8 +1388,8 @@ fn reward_to_stake_works() { // Confirm account 10 and 20 are validators assert_eq_uvec!(Session::validators(), vec![11, 21]); - assert_eq!(mock::validator_current_exposure(11).total, 1000); - assert_eq!(mock::validator_current_exposure(21).total, 2000); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).total, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 21).total, 2000); // Give the man some money. let _ = Balances::make_free_balance_be(&10, 1000); @@ -1399,7 +1399,7 @@ fn reward_to_stake_works() { ErasStakers::::insert(0, 21, Exposure { total: 69, own: 69, others: vec![] }); // Now lets lower account 20 stake - assert_eq!(mock::validator_current_exposure(21).total, 69); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 21).total, 69); >::insert(&20, StakingLedger { stash: 21, total: 69, active: 69, unlocking: vec![], next_reward: 0 }); // Compute total payout now for whole duration as other parameter won't change @@ -1412,8 +1412,8 @@ fn reward_to_stake_works() { start_era(1); mock::make_all_reward_payment(0); - assert_eq!(mock::validator_current_exposure(11).total, 1000); - assert_eq!(mock::validator_current_exposure(21).total, 69); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).total, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 21).total, 69); let _11_balance = Balances::free_balance(&11); assert_eq!(_11_balance, 1000 + total_payout_0 / 2); @@ -1422,8 +1422,8 @@ fn reward_to_stake_works() { start_era(2); // -- new infos - assert_eq!(mock::validator_current_exposure(11).total, 1000 + total_payout_0 / 2); - assert_eq!(mock::validator_current_exposure(21).total, 69 + total_payout_0 / 2); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).total, 1000 + total_payout_0 / 2); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 21).total, 69 + total_payout_0 / 2); check_exposure_all(Staking::active_era()); check_nominator_all(Staking::active_era()); @@ -1748,8 +1748,8 @@ fn phragmen_should_not_overflow_validators() { // This test will fail this. Will saturate. // check_exposure_all(); - assert_eq!(mock::validator_current_exposure(3).total, u64::max_value()); - assert_eq!(mock::validator_current_exposure(5).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 3).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 5).total, u64::max_value()); }) } @@ -1770,8 +1770,8 @@ fn phragmen_should_not_overflow_nominators() { assert_eq_uvec!(validator_controllers(), vec![4, 2]); // Saturate. - assert_eq!(mock::validator_current_exposure(3).total, u64::max_value()); - assert_eq!(mock::validator_current_exposure(5).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 3).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 5).total, u64::max_value()); }) } @@ -1789,8 +1789,8 @@ fn phragmen_should_not_overflow_ultimate() { assert_eq_uvec!(validator_controllers(), vec![4, 2]); // Saturate. - assert_eq!(mock::validator_current_exposure(3).total, u64::max_value()); - assert_eq!(mock::validator_current_exposure(5).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 3).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 5).total, u64::max_value()); }) } @@ -1837,7 +1837,7 @@ fn reward_validator_slashing_validator_doesnt_overflow() { on_offence_now( &[ OffenceDetails { - offender: (11, mock::validator_current_exposure(11)), + offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), reporters: vec![], }, ], @@ -1947,7 +1947,7 @@ fn offence_forces_new_era() { &[OffenceDetails { offender: ( 11, - mock::validator_current_exposure(11), + Staking::eras_stakers(Staking::active_era(), 11), ), reporters: vec![], }], @@ -1967,7 +1967,7 @@ fn offence_ensures_new_era_without_clobbering() { &[OffenceDetails { offender: ( 11, - mock::validator_current_exposure(11), + Staking::eras_stakers(Staking::active_era(), 11), ), reporters: vec![], }], @@ -1987,7 +1987,7 @@ fn offence_deselects_validator_when_slash_is_zero() { &[OffenceDetails { offender: ( 11, - mock::validator_current_exposure(11), + Staking::eras_stakers(Staking::active_era(), 11), ), reporters: vec![], }], @@ -2006,7 +2006,7 @@ fn slashing_performed_according_exposure() { // This test checks that slashing is performed according the exposure (or more precisely, // historical exposure), not the current balance. ExtBuilder::default().build().execute_with(|| { - assert_eq!(mock::validator_current_exposure(11).own, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).own, 1000); // Handle an offence with a historical exposure. on_offence_now( @@ -2040,7 +2040,7 @@ fn slash_in_old_span_does_not_deselect() { &[OffenceDetails { offender: ( 11, - mock::validator_current_exposure(11), + Staking::eras_stakers(Staking::active_era(), 11), ), reporters: vec![], }], @@ -2065,7 +2065,7 @@ fn slash_in_old_span_does_not_deselect() { &[OffenceDetails { offender: ( 11, - mock::validator_current_exposure(11), + Staking::eras_stakers(Staking::active_era(), 11), ), reporters: vec![], }], @@ -2082,7 +2082,7 @@ fn slash_in_old_span_does_not_deselect() { &[OffenceDetails { offender: ( 11, - mock::validator_current_exposure(11), + Staking::eras_stakers(Staking::active_era(), 11), ), reporters: vec![], }], @@ -2106,13 +2106,13 @@ fn reporters_receive_their_slice() { // The reporters' reward is calculated from the total exposure. let initial_balance = 1125; - assert_eq!(mock::validator_current_exposure(11).total, initial_balance); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).total, initial_balance); on_offence_now( &[OffenceDetails { offender: ( 11, - mock::validator_current_exposure(11), + Staking::eras_stakers(Staking::active_era(), 11), ), reporters: vec![1, 2], }], @@ -2137,13 +2137,13 @@ fn subsequent_reports_in_same_span_pay_out_less() { // The reporters' reward is calculated from the total exposure. let initial_balance = 1125; - assert_eq!(mock::validator_current_exposure(11).total, initial_balance); + assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).total, initial_balance); on_offence_now( &[OffenceDetails { offender: ( 11, - mock::validator_current_exposure(11), + Staking::eras_stakers(Staking::active_era(), 11), ), reporters: vec![1], }], @@ -2159,7 +2159,7 @@ fn subsequent_reports_in_same_span_pay_out_less() { &[OffenceDetails { offender: ( 11, - mock::validator_current_exposure(11), + Staking::eras_stakers(Staking::active_era(), 11), ), reporters: vec![1], }], @@ -2183,7 +2183,7 @@ fn invulnerables_are_not_slashed() { assert_eq!(Balances::free_balance(&11), 1000); assert_eq!(Balances::free_balance(&21), 2000); - let exposure = mock::validator_current_exposure(21); + let exposure = Staking::eras_stakers(Staking::active_era(), 21); let initial_balance = Staking::slashable_balance_of(&21); let nominator_balances: Vec<_> = exposure.others @@ -2192,11 +2192,11 @@ fn invulnerables_are_not_slashed() { on_offence_now( &[ OffenceDetails { - offender: (11, mock::validator_current_exposure(11)), + offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), reporters: vec![], }, OffenceDetails { - offender: (21, mock::validator_current_exposure(21)), + offender: (21, Staking::eras_stakers(Staking::active_era(), 21)), reporters: vec![], }, ], @@ -2230,7 +2230,7 @@ fn dont_slash_if_fraction_is_zero() { &[OffenceDetails { offender: ( 11, - mock::validator_current_exposure(11), + Staking::eras_stakers(Staking::active_era(), 11), ), reporters: vec![], }], @@ -2251,7 +2251,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[ OffenceDetails { - offender: (11, mock::validator_current_exposure(11)), + offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), reporters: vec![], }, ], @@ -2265,7 +2265,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[ OffenceDetails { - offender: (11, mock::validator_current_exposure(11)), + offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), reporters: vec![], }, ], @@ -2278,7 +2278,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[ OffenceDetails { - offender: (11, mock::validator_current_exposure(11)), + offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), reporters: vec![], }, ], @@ -2299,7 +2299,7 @@ fn garbage_collection_after_slashing() { on_offence_now( &[ OffenceDetails { - offender: (11, mock::validator_current_exposure(11)), + offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), reporters: vec![], }, ], @@ -2313,7 +2313,7 @@ fn garbage_collection_after_slashing() { on_offence_now( &[ OffenceDetails { - offender: (11, mock::validator_current_exposure(11)), + offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), reporters: vec![], }, ], @@ -2336,14 +2336,14 @@ fn garbage_collection_on_window_pruning() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = mock::validator_current_exposure(11); + let exposure = Staking::eras_stakers(Staking::active_era(), 11); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_now( &[ OffenceDetails { - offender: (11, mock::validator_current_exposure(11)), + offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), reporters: vec![], }, ], @@ -2384,8 +2384,8 @@ fn slashing_nominators_by_span_max() { assert_eq!(Staking::slashable_balance_of(&21), 1000); - let exposure_11 = mock::validator_current_exposure(11); - let exposure_21 = mock::validator_current_exposure(21); + let exposure_11 = Staking::eras_stakers(Staking::active_era(), 11); + let exposure_21 = Staking::eras_stakers(Staking::active_era(), 21); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value_11 = exposure_11.others.iter().find(|o| o.who == 101).unwrap().value; let nominated_value_21 = exposure_21.others.iter().find(|o| o.who == 101).unwrap().value; @@ -2393,7 +2393,7 @@ fn slashing_nominators_by_span_max() { on_offence_in_era( &[ OffenceDetails { - offender: (11, mock::validator_current_exposure(11)), + offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), reporters: vec![], }, ], @@ -2427,7 +2427,7 @@ fn slashing_nominators_by_span_max() { on_offence_in_era( &[ OffenceDetails { - offender: (21, mock::validator_current_exposure(21)), + offender: (21, Staking::eras_stakers(Staking::active_era(), 21)), reporters: vec![], }, ], @@ -2450,7 +2450,7 @@ fn slashing_nominators_by_span_max() { on_offence_in_era( &[ OffenceDetails { - offender: (11, mock::validator_current_exposure(11)), + offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), reporters: vec![], }, ], @@ -2486,7 +2486,7 @@ fn slashes_are_summed_across_spans() { on_offence_now( &[ OffenceDetails { - offender: (21, mock::validator_current_exposure(21)), + offender: (21, Staking::eras_stakers(Staking::active_era(), 21)), reporters: vec![], }, ], @@ -2511,7 +2511,7 @@ fn slashes_are_summed_across_spans() { on_offence_now( &[ OffenceDetails { - offender: (21, mock::validator_current_exposure(21)), + offender: (21, Staking::eras_stakers(Staking::active_era(), 21)), reporters: vec![], }, ], @@ -2536,14 +2536,14 @@ fn deferred_slashes_are_deferred() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = mock::validator_current_exposure(11); + let exposure = Staking::eras_stakers(Staking::active_era(), 11); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_now( &[ OffenceDetails { - offender: (11, mock::validator_current_exposure(11)), + offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), reporters: vec![], }, ], @@ -2579,7 +2579,7 @@ fn remove_deferred() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = mock::validator_current_exposure(11); + let exposure = Staking::eras_stakers(Staking::active_era(), 11); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; @@ -2649,7 +2649,7 @@ fn remove_multi_deferred() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = mock::validator_current_exposure(11); + let exposure = Staking::eras_stakers(Staking::active_era(), 11); assert_eq!(Balances::free_balance(&101), 2000); on_offence_now( @@ -2665,7 +2665,7 @@ fn remove_multi_deferred() { on_offence_now( &[ OffenceDetails { - offender: (21, mock::validator_current_exposure(21)), + offender: (21, Staking::eras_stakers(Staking::active_era(), 21)), reporters: vec![], } ], @@ -2705,7 +2705,7 @@ fn slash_kicks_validators_not_nominators() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = mock::validator_current_exposure(11); + let exposure = Staking::eras_stakers(Staking::active_era(), 11); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; From 16a6fd07f15133838b0ae5e3740be88465b74d14 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 20 Jan 2020 12:27:32 +0100 Subject: [PATCH 25/75] improve doc --- frame/staking/src/lib.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 1fb1bbb219e9c..768c0fc642ac0 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -104,7 +104,8 @@ //! The **reward and slashing** procedure is the core of the Staking module, attempting to _embrace //! valid behavior_ while _punishing any misbehavior or lack of availability_. //! -//! Reward must be claimed by stakers for each era before it gets too old by $HISTORY_DEPTH. +//! Reward must be claimed by stakers for each era before it gets too old by $HISTORY_DEPTH using +//! `payout_nominator` and `payout_validator` calls. //! //! Slashing can occur at any point in time, once misbehavior is reported. Once slashing is //! determined, a value is deducted from the balance of the validator and all the nominators who @@ -1312,14 +1313,17 @@ decl_module! { ::UnappliedSlashes::insert(&era, &unapplied); } - /// Make one staker's payout for one era. + /// Make one nominator's payout for one era. /// - /// - `who` is the nominator to pay out. + /// - `who` is the controller account of the nominator to pay out. /// - `era` may not be lower than one following the most recently paid era. If it is higher, /// then it indicates an instruction to skip the payout of all previous eras. /// - `validators` is the list of all validators that `who` had exposure to during `era`. /// If it is incomplete, then less than the full reward will be paid out. /// + /// WARNING: once an era is payed for a validator such validator can't claim the payout of + /// previous era. + /// /// WARNING: Incorrect arguments here can result in loss of payout. Be very careful. /// /// 1 balance transfer @@ -1336,12 +1340,15 @@ decl_module! { Self::do_payout_nominator(who, era, validators) } - /// Make one staker's payout for one era. + /// Make one validator's payout for one era. /// - /// - `who` is the nominator to pay out. + /// - `who` is the controller account of the validator to pay out. /// - `era` may not be lower than one following the most recently paid era. If it is higher, /// then it indicates an instruction to skip the payout of all previous eras. /// + /// WARNING: once an era is payed for a validator such validator can't claim the payout of + /// previous era. + /// /// WARNING: Incorrect arguments here can result in loss of payout. Be very careful. fn payout_validator(origin, era: EraIndex) -> DispatchResult { let who = ensure_signed(origin)?; From 3d426bb6eb2803bdd6a27c9ecd8d25bec211b9c1 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 20 Jan 2020 18:14:02 +0100 Subject: [PATCH 26/75] fix most todo --- frame/staking/src/lib.rs | 14 -------------- frame/staking/src/migration.rs | 32 +++++++++++++++++++++++++++----- frame/staking/src/tests.rs | 3 +++ 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 6f18df64ef909..89faf3025f8a8 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -371,17 +371,6 @@ pub struct UnlockChunk { era: EraIndex, } -/// Deprecated. Used for migration only. -#[derive(Encode, Decode)] -struct StakingLedgerV1 { - stash: AccountId, - #[codec(compact)] - total: Balance, - #[codec(compact)] - active: Balance, - unlocking: Vec>, -} - /// The ledger of a (bonded) stash. #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)] pub struct StakingLedger { @@ -1582,9 +1571,6 @@ impl Module { fn new_era(start_session_index: SessionIndex) -> Option> { // Increment current era. let current_era = CurrentEra::mutate(|s| { *s += 1; *s }); - // TODO TODO: either start_session_index strictly increase or we must remove old era overriden - // TODO TODO: update doc or code to make this correct - // TODO TODO: this should be closed by pallet-session API change. ErasStartSessionIndex::insert(¤t_era, &start_session_index); // Clean old era information. diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs index b95ca8b8ba385..d7f572d7873cb 100644 --- a/frame/staking/src/migration.rs +++ b/frame/staking/src/migration.rs @@ -27,12 +27,12 @@ pub const CURRENT_VERSION: VersionNumber = 2; pub mod inner { use crate::{ Store, Module, Trait, EraRewardPoints, SessionInterface, BalanceOf, StakingLedger, - StakingLedgerV1, // TODO TODO: move this from staking to here + UnlockChunk, }; use frame_support::{ StorageLinkedMap, StoragePrefixedMap, StorageValue, StorageDoubleMap, StorageMap, }; - use codec::{Encode, Decode}; + use codec::{Encode, Decode, HasCompact}; use sp_std::vec::Vec; use super::{CURRENT_VERSION, VersionNumber}; use sp_runtime::traits::Zero; @@ -117,10 +117,32 @@ pub mod inner { } } - // migrate storage from v1 to v2: - // * TODO TODO: doc + // migrate storage from v2 to v3: + // * create: + // * ActiveEraStart + // * ErasRewardPoints + // * ActiveEra + // * ErasStakers, + // * ErasValidatorPrefs + // * ErasTotalStake + // * StakingLedger + // * removal of: + // * SlotStake + // * CurrentElected + // * CurrentEraStart + // * CurrentEraStartSessionIndex + // * CurrentEraPointsEarned pub fn to_v3(version: &mut VersionNumber) { - // TODO TODO: move stakingledgerV1 here + #[derive(Encode, Decode)] + struct StakingLedgerV1 { + stash: AccountId, + #[codec(compact)] + total: Balance, + #[codec(compact)] + active: Balance, + unlocking: Vec>, + } + if *version != 2 { return } *version += 1; diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 68b894be6ffda..ff6e638b165e5 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2896,3 +2896,6 @@ fn zero_slash_keeps_nominators() { assert!(nominations.submitted_in >= last_slash); }); } + +// TODO TODO: test migration +// TODO TODO: test asynchronous creation and deletion of session From 5d4c2e5a9ab242ff0d25b9b2d0f6647dfe7ce463 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 21 Jan 2020 17:13:55 +0100 Subject: [PATCH 27/75] fix migration and test --- frame/staking/src/lib.rs | 19 +++------- frame/staking/src/migration.rs | 57 +++++++++++----------------- frame/staking/src/tests.rs | 69 ++++++++++++++++++++++++++++++++-- 3 files changed, 94 insertions(+), 51 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 89faf3025f8a8..30ddafaef1b15 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -571,8 +571,6 @@ pub trait SessionInterface: frame_system::Trait { fn validators() -> Vec; /// Prune historical session tries up to but not including the given index. fn prune_historical_up_to(up_to: SessionIndex); - /// The current session index. - fn current_index() -> SessionIndex; } impl SessionInterface<::AccountId> for T where @@ -596,10 +594,6 @@ impl SessionInterface<::AccountId> for T whe fn prune_historical_up_to(up_to: SessionIndex) { >::prune_up_to(up_to); } - - fn current_index() -> SessionIndex { - >::current_index() - } } pub trait Trait: frame_system::Trait { @@ -812,12 +806,13 @@ decl_storage! { // // This is keyed by the stash account. Stakers: map T::AccountId => Exposure>; - -} -add_extra_genesis { -config(stakers): - Vec<(T::AccountId, T::AccountId, BalanceOf, StakerStatus)>; + } + add_extra_genesis { + config(stakers): + Vec<(T::AccountId, T::AccountId, BalanceOf, StakerStatus)>; build(|config: &GenesisConfig| { + StorageVersion::put(migration::CURRENT_VERSION); + for &(ref stash, ref controller, balance, ref status) in &config.stakers { assert!( T::Currency::free_balance(&stash) >= balance, @@ -844,8 +839,6 @@ config(stakers): }, _ => Ok(()) }; } - - StorageVersion::put(migration::CURRENT_VERSION); }); } } diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs index d7f572d7873cb..d3c9caed8e202 100644 --- a/frame/staking/src/migration.rs +++ b/frame/staking/src/migration.rs @@ -25,10 +25,7 @@ pub const CURRENT_VERSION: VersionNumber = 2; /// The inner logic of migrations. #[cfg(any(test, feature = "migrate"))] pub mod inner { - use crate::{ - Store, Module, Trait, EraRewardPoints, SessionInterface, BalanceOf, StakingLedger, - UnlockChunk, - }; + use crate::{Store, Module, Trait, EraRewardPoints, BalanceOf, StakingLedger, UnlockChunk}; use frame_support::{ StorageLinkedMap, StoragePrefixedMap, StorageValue, StorageDoubleMap, StorageMap, }; @@ -118,15 +115,24 @@ pub mod inner { } // migrate storage from v2 to v3: + // + // In version 2 the staking module has several issue about handling session delay. + // In V2 the current era is considered the active one. + // + // After the migration the current era will still be considered the active one. And the delay + // issue will be fixed when planning the next era. + // // * create: // * ActiveEraStart // * ErasRewardPoints // * ActiveEra - // * ErasStakers, + // * ErasStakers // * ErasValidatorPrefs // * ErasTotalStake - // * StakingLedger + // * ErasStartSessionIndex + // * translate StakingLedger // * removal of: + // * Stakers // * SlotStake // * CurrentElected // * CurrentEraStart @@ -146,22 +152,16 @@ pub mod inner { if *version != 2 { return } *version += 1; - // Fill new storages. - - // Do ActiveEra let current_era_start_index = as Store>::CurrentEraStartSessionIndex::get(); let current_era = as Store>::CurrentEra::get(); - let active_era = if current_era_start_index > T::SessionInterface::current_index() { - current_era - 1 - } else { - current_era - }; - as Store>::ActiveEra::put(active_era); - - // Do ErasStakers, ErasValidatorPrefs and ErasTotalStake - let old_current_elected = as Store>::CurrentElected::get(); + println!("{:?}", current_era); + as Store>::ErasStartSessionIndex::insert(current_era, current_era_start_index); + as Store>::ActiveEra::put(current_era); + as Store>::ActiveEraStart::put( as Store>::CurrentEraStart::get()); + + let current_elected = as Store>::CurrentElected::get(); let mut current_total_stake = >::zero(); - for validator in &old_current_elected { + for validator in ¤t_elected { let exposure = as Store>::Stakers::get(validator); current_total_stake += exposure.total; let pref = as Store>::Validators::get(validator); @@ -169,27 +169,13 @@ pub mod inner { as Store>::ErasValidatorPrefs::insert(current_era, validator, pref); } as Store>::ErasTotalStake::insert(current_era, current_total_stake); - let mut active_total_stake = >::zero(); - for validator in &T::SessionInterface::validators() { - let exposure = as Store>::Stakers::get(validator); - active_total_stake += exposure.total; - let pref = as Store>::Validators::get(validator); - as Store>::ErasStakers::insert(active_era, validator, exposure); - as Store>::ErasValidatorPrefs::insert(active_era, validator, pref); - } - as Store>::ErasTotalStake::insert(active_era, active_total_stake); - // Do ErasRewardPoints let points = as Store>::CurrentEraPointsEarned::get(); - as Store>::ErasRewardPoints::insert(active_era, EraRewardPoints { + as Store>::ErasRewardPoints::insert(current_era, EraRewardPoints { total: points.total, - individual: old_current_elected.iter().cloned().zip(points.individual.iter().cloned()).collect(), + individual: current_elected.iter().cloned().zip(points.individual.iter().cloned()).collect(), }); - // Do ActiveEraStart - as Store>::ActiveEraStart::put( as Store>::CurrentEraStart::get()); - - // Do StakingLedger let res = as Store>::Ledger::translate_values( |old: StakingLedgerV1>| StakingLedger { stash: old.stash, @@ -207,6 +193,7 @@ pub mod inner { // Kill old storages + as Store>::Stakers::remove_all(); as Store>::SlotStake::kill(); as Store>::CurrentElected::kill(); as Store>::CurrentEraStart::kill(); diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index ff6e638b165e5..edda89d9070bb 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2859,6 +2859,72 @@ fn migration_v2() { }); } +#[test] +fn migration_v3() { + ExtBuilder::default().build().execute_with(|| { + start_era(3); + + assert_eq!(Session::validators(), vec![21, 11]); + + // Insert fake data to check the migration + ::CurrentElected::put(vec![21, 31]); + ::CurrentEraStartSessionIndex::put(5); + ::CurrentEraStart::put(777); + ::Stakers::insert(11, Exposure { + total: 10, + own: 10, + others: vec![], + }); + ::Stakers::insert(21, Exposure { + total: 20, + own: 20, + others: vec![], + }); + ::Stakers::insert(31, Exposure { + total: 30, + own: 30, + others: vec![], + }); + ::CurrentEraPointsEarned::put(EraPoints { + total: 12, + individual: vec![2, 10], + }); + ::ErasStakers::remove_all(); + + ::StorageVersion::put(2); + // Perform migration. + crate::migration::inner::to_v3::(&mut 2); + + // Check migration + assert_eq!(::ActiveEraStart::get(), 777); + assert_eq!(::ErasStartSessionIndex::get(3), 5); + assert_eq!(::ErasRewardPoints::get(3), EraRewardPoints { + total: 12, + individual: vec![(21, 2), (31, 10)].into_iter().collect(), + }); + assert_eq!(::ActiveEra::get(), 3); + assert_eq!(::CurrentEra::get(), 3); + assert_eq!(::ErasStakers::get(3, 11), Exposure { + total: 0, + own: 0, + others: vec![], + }); + assert_eq!(::ErasStakers::get(3, 21), Exposure { + total: 20, + own: 20, + others: vec![], + }); + assert_eq!(::ErasStakers::get(3, 31), Exposure { + total: 30, + own: 30, + others: vec![], + }); + assert_eq!(::ErasValidatorPrefs::get(3, 21), Staking::validators(21)); + assert_eq!(::ErasValidatorPrefs::get(3, 31), Staking::validators(31)); + assert_eq!(::ErasTotalStake::get(3), 50); + }) +} + #[test] fn zero_slash_keeps_nominators() { ExtBuilder::default().build().execute_with(|| { @@ -2896,6 +2962,3 @@ fn zero_slash_keeps_nominators() { assert!(nominations.submitted_in >= last_slash); }); } - -// TODO TODO: test migration -// TODO TODO: test asynchronous creation and deletion of session From 35907694111e5085d50a232274bb0856c64a4cbb Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 21 Jan 2020 17:21:18 +0100 Subject: [PATCH 28/75] remove println --- frame/staking/src/migration.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs index d3c9caed8e202..2c21f0426ded2 100644 --- a/frame/staking/src/migration.rs +++ b/frame/staking/src/migration.rs @@ -154,7 +154,6 @@ pub mod inner { let current_era_start_index = as Store>::CurrentEraStartSessionIndex::get(); let current_era = as Store>::CurrentEra::get(); - println!("{:?}", current_era); as Store>::ErasStartSessionIndex::insert(current_era, current_era_start_index); as Store>::ActiveEra::put(current_era); as Store>::ActiveEraStart::put( as Store>::CurrentEraStart::get()); From df3a4dea8cfd5b2ce53614a2734a34fb8ceee0dd Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 21 Jan 2020 17:31:57 +0100 Subject: [PATCH 29/75] WIP --- frame/staking/src/tests.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index edda89d9070bb..4289c6ca1573e 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2962,3 +2962,10 @@ fn zero_slash_keeps_nominators() { assert!(nominations.submitted_in >= last_slash); }); } + +// This test will make simulate a session module which delay 4 session. +#[test] +fn multiple_new_session_end_session() { + ExtBuilder::default().build().execute_with(|| { + }); +} From 70979ac2728db85c17a7b86fd1058e68bb6933ca Mon Sep 17 00:00:00 2001 From: thiolliere Date: Wed, 22 Jan 2020 12:15:20 +0100 Subject: [PATCH 30/75] add test and spec --- frame/staking/src/lib.rs | 4 ++++ frame/staking/src/tests.rs | 41 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 30ddafaef1b15..131a5534f9708 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1788,6 +1788,8 @@ impl Module { } } +/// In this implementation `new_session(session)` must be called before `end_session(session-1)` +/// i.e. the new session must be planned before the ending of the previous session. impl pallet_session::SessionManager for Module { fn new_session(new_index: SessionIndex) -> Option> { Self::ensure_storage_upgraded(); @@ -1801,6 +1803,8 @@ impl pallet_session::SessionManager for Module { } } +/// In this implementation `new_session(session)` must be called before `end_session(session-1)` +/// i.e. the new session must be planned before the ending of the previous session. impl SessionManager>> for Module { fn new_session(new_index: SessionIndex) -> Option>)>> diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 4289c6ca1573e..11d740e724e76 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2963,9 +2963,46 @@ fn zero_slash_keeps_nominators() { }); } -// This test will make simulate a session module which delay 4 session. #[test] -fn multiple_new_session_end_session() { +fn six_session_delay() { ExtBuilder::default().build().execute_with(|| { + use pallet_session::SessionManager; + + let val_set = Session::validators(); + let init_session = Session::current_index(); + let init_active_era = Staking::active_era(); + // pallet-session is delaying session by one, thus the next session to plan is +2. + assert_eq!(>::new_session(init_session + 2), None); + assert_eq!(>::new_session(init_session + 3), Some(val_set.clone())); + assert_eq!(>::new_session(init_session + 4), None); + assert_eq!(>::new_session(init_session + 5), None); + assert_eq!(>::new_session(init_session + 6), Some(val_set.clone())); + + >::end_session(init_session); + assert_eq!(Staking::active_era(), init_active_era); + >::end_session(init_session + 1); + assert_eq!(Staking::active_era(), init_active_era); + + // Reward current era + Staking::reward_by_ids(vec![(11, 1)]); + + // New active era is triggered here. + >::end_session(init_session + 2); + assert_eq!(Staking::active_era(), init_active_era + 1); + >::end_session(init_session + 3); + assert_eq!(Staking::active_era(), init_active_era + 1); + >::end_session(init_session + 4); + assert_eq!(Staking::active_era(), init_active_era + 1); + + // Reward current era + Staking::reward_by_ids(vec![(21, 2)]); + + // New active era is triggered here. + >::end_session(init_session + 5); + assert_eq!(Staking::active_era(), init_active_era + 2); + + // That reward are correct + assert_eq!(Staking::eras_reward_points(init_active_era).total, 1); + assert_eq!(Staking::eras_reward_points(init_active_era + 1).total, 2); }); } From 3c56ab3d2496bcda7581ac13416c1737dec987b7 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Wed, 22 Jan 2020 14:19:31 +0100 Subject: [PATCH 31/75] weight --- frame/staking/src/lib.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 131a5534f9708..1e1331703f63a 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1307,12 +1307,15 @@ decl_module! { /// /// WARNING: Incorrect arguments here can result in loss of payout. Be very careful. /// - /// 1 balance transfer - /// Up to 16 storage reads, each of `O(N)` size and decode complexity; `N` is maximum - /// nominations that can be given to a single validator. (`MAX_NOMINATIONS` is the maximum - /// number of validators that may be nominated by a single nominator.) This is bounded only - /// economically (all nominators are required to place a minimum stake). - /// Compute: O(MAX_NOMINATIONS * logN). + /// # + /// - Number of storage read of `O(validators)`; `validators` is the argument of the call. + /// - Each storage read is `O(N)` size and decode complexity; `N` is the maximum + /// nominations that can be given to a single validator. + /// - Computation complexity: `O(MAX_NOMINATIONS * logN)`; `MAX_NOMINATIONS` is the + /// maximum number of validators that may be nominated by a single nominator, it is + /// bounded only economically (all nominators are required to place a minimum stake). + /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] // TODO: Limit the amount of nominators that can be assigned to a validator by Phragmen. fn payout_nominator(origin, era: EraIndex, validators: Vec) -> DispatchResult @@ -1331,6 +1334,12 @@ decl_module! { /// previous era. /// /// WARNING: Incorrect arguments here can result in loss of payout. Be very careful. + /// + /// # + /// - Time complexity: O(1). + /// - Contains a limited number of reads and writes. + /// # + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] fn payout_validator(origin, era: EraIndex) -> DispatchResult { let who = ensure_signed(origin)?; Self::do_payout_validator(who, era) From c088756ee3293b2fe05b9cbe684145fb5fc4005f Mon Sep 17 00:00:00 2001 From: thiolliere Date: Wed, 22 Jan 2020 14:25:53 +0100 Subject: [PATCH 32/75] update doc --- frame/staking/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 1e1331703f63a..dfc116fbb8bc0 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1308,15 +1308,16 @@ decl_module! { /// WARNING: Incorrect arguments here can result in loss of payout. Be very careful. /// /// # - /// - Number of storage read of `O(validators)`; `validators` is the argument of the call. + /// - Number of storage read of `O(validators)`; `validators` is the argument of the call, + /// and is bounded by `MAX_NOMINATIONS`. /// - Each storage read is `O(N)` size and decode complexity; `N` is the maximum /// nominations that can be given to a single validator. /// - Computation complexity: `O(MAX_NOMINATIONS * logN)`; `MAX_NOMINATIONS` is the /// maximum number of validators that may be nominated by a single nominator, it is /// bounded only economically (all nominators are required to place a minimum stake). /// # - #[weight = SimpleDispatchInfo::FixedNormal(500_000)] // TODO: Limit the amount of nominators that can be assigned to a validator by Phragmen. + #[weight = SimpleDispatchInfo::FixedNormal(500_000)] fn payout_nominator(origin, era: EraIndex, validators: Vec) -> DispatchResult { From 72ff737d27be67d87308514b13e2574bc5f09fce Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 30 Jan 2020 11:19:18 +0100 Subject: [PATCH 33/75] safer end_era --- frame/staking/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index dfc116fbb8bc0..e3c6699400378 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1542,7 +1542,14 @@ impl Module { } fn end_session(session_index: SessionIndex) { - if ErasStartSessionIndex::get(Self::active_era() + 1) == session_index + 1 { + let next_era_start = ErasStartSessionIndex::get(Self::active_era() + 1); + + if next_era_start < session_index + 1 { + frame_support::print("Error: some era ending has been missed"); + } + + // This should be a strict equality but better be safe in case ending has been missed. + if next_era_start <= session_index + 1 { Self::end_era(session_index); } } From 58a2c906ecec965501e6c6b9dc29f5e1e0234e1a Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 30 Jan 2020 11:24:19 +0100 Subject: [PATCH 34/75] fix exposure of conversion --- frame/staking/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index e3c6699400378..188c9b1280743 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1874,15 +1874,18 @@ impl Convert> for StashOf { } } -/// A typed conversion from stash account ID to the current exposure of nominators +/// A typed conversion from stash account ID to the active exposure of nominators /// on that account. +/// +/// Active exposure is the exposure of the validator set currently validating. It can differ from +/// the latest planned exposure. pub struct ExposureOf(sp_std::marker::PhantomData); impl Convert>>> for ExposureOf { fn convert(validator: T::AccountId) -> Option>> { - Some(>::eras_stakers(>::current_era(), &validator)) + Some(>::eras_stakers(>::active_era(), &validator)) } } From dd7590f360569d3ab356b94b0482d9b15e9269e9 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 30 Jan 2020 11:55:15 +0100 Subject: [PATCH 35/75] Revert "safer end_era" This reverts commit 72ff737d27be67d87308514b13e2574bc5f09fce. --- frame/staking/src/lib.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index b322a5de9d281..0c8b2320dd134 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1553,14 +1553,7 @@ impl Module { } fn end_session(session_index: SessionIndex) { - let next_era_start = ErasStartSessionIndex::get(Self::active_era() + 1); - - if next_era_start < session_index + 1 { - frame_support::print("Error: some era ending has been missed"); - } - - // This should be a strict equality but better be safe in case ending has been missed. - if next_era_start <= session_index + 1 { + if ErasStartSessionIndex::get(Self::active_era() + 1) == session_index + 1 { Self::end_era(session_index); } } From c99772b7405785859bbab62db7f6477d94fe07e0 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 30 Jan 2020 17:44:29 +0100 Subject: [PATCH 36/75] fix useless put --- frame/staking/src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 0c8b2320dd134..3b87f741ae7ca 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -718,7 +718,6 @@ decl_storage! { pub ErasStakers get(fn eras_stakers): double_map hasher(twox_64_concat) EraIndex, hasher(twox_64_concat) T::AccountId => Exposure>; - // TODO: consider switching this to a simple map EraIndex => Vec /// Similarly to `ErasStakers` this holds the preferences of validators. /// @@ -1327,7 +1326,6 @@ decl_module! { /// maximum number of validators that may be nominated by a single nominator, it is /// bounded only economically (all nominators are required to place a minimum stake). /// # - // TODO: Limit the amount of nominators that can be assigned to a validator by Phragmen. #[weight = SimpleDispatchInfo::FixedNormal(500_000)] fn payout_nominator(origin, era: EraIndex, validators: Vec) -> DispatchResult @@ -1545,9 +1543,8 @@ impl Module { /// Initialise the session 0 (and consequently the era 0) fn initial_session() -> Option> { - // note: `CurrentEraStart` is set in `on_finalize` of the first block because now is not + // note: `ActiveEraStart` is set in `on_finalize` of the first block because now is not // available yet. - CurrentEraStartSessionIndex::put(0); BondedEras::mutate(|bonded| bonded.push((0, 0))); Self::select_validators() } From eb1a6ef1ae39bae94b347ee0c6bd365f8fd5cb6f Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 30 Jan 2020 18:52:57 +0100 Subject: [PATCH 37/75] exposure clipped --- frame/staking/src/lib.rs | 43 ++++++++++++++++++++++++++++------ frame/staking/src/migration.rs | 17 ++++++++++++-- frame/staking/src/mock.rs | 2 ++ 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 3b87f741ae7ca..be894493e9244 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -641,6 +641,12 @@ pub trait Trait: frame_system::Trait { /// The NPoS reward curve to use. type RewardCurve: Get<&'static PiecewiseLinear<'static>>; + + /// The maximum number of nominator rewarded for each validator. + /// + /// For each validator only the `$MaxNominatorRewardedPerValidator` biggest stakers can claim + /// their reward. This used to limit the i/o cost for the nominator payout. + type MaxNominatorRewardedPerValidator: Get; } /// Mode of era-forcing. @@ -719,6 +725,19 @@ decl_storage! { double_map hasher(twox_64_concat) EraIndex, hasher(twox_64_concat) T::AccountId => Exposure>; + /// Clipped Exposure of validator at era. + /// + /// This is similar to [`ErasStakers`] but number of nominators exposed is reduce to the + /// `T::MaxNominatorRewardedPerValidator` biggest stakers. + /// This used to limit the i/o cost for the nominator payout. + /// + /// This is keyed fist by the era index to allow bulk deletion and then the stash account. + /// + /// Is it removed after `HISTORY_DEPTH` eras. + pub ErasStakersClipped get(fn eras_stakers_clipped): + double_map hasher(twox_64_concat) EraIndex, hasher(twox_64_concat) T::AccountId + => Exposure>; + /// Similarly to `ErasStakers` this holds the preferences of validators. /// /// This is keyed fist by the era index to allow bulk deletion and then the stash account. @@ -1400,7 +1419,7 @@ impl Module { let mut reward = Perbill::zero(); let era_reward_points = >::get(&era); - for validator in validators { + for validator in validators.into_iter().take(MAX_NOMINATIONS) { let commission = Self::eras_validator_prefs(&era, &validator).commission; let validator_exposure = >::get(&era, &validator); @@ -1682,8 +1701,8 @@ impl Module { ); if let Some(phragmen_result) = maybe_phragmen_result { - let elected_stashes = phragmen_result.winners.iter() - .map(|(s, _)| s.clone()) + let elected_stashes = phragmen_result.winners.into_iter() + .map(|(s, _)| s) .collect::>(); let assignments = phragmen_result.assignments; @@ -1715,7 +1734,10 @@ impl Module { } total = total.saturating_add(value); }); - others.sort_by(|a, b| a.who.cmp(&b.who)); + + total_staked = total_staked.saturating_add(total); + + others.sort_unstable_by(|a, b| a.who.cmp(&b.who)); let exposure = Exposure { own, others, @@ -1725,9 +1747,16 @@ impl Module { // we simulate it in some tests. total, }; - - total_staked = total_staked.saturating_add(exposure.total); - >::insert(¤t_era, &c, exposure.clone()); + >::insert(¤t_era, &c, &exposure); + + let mut exposure_clipped = exposure; + let clipped_max_len = T::MaxNominatorRewardedPerValidator::get() as usize; + if exposure_clipped.others.len() > clipped_max_len { + exposure_clipped.others.sort_unstable_by(|a, b| a.value.cmp(&b.value)); + exposure_clipped.others.truncate(clipped_max_len); + exposure_clipped.others.sort_unstable_by(|a, b| a.who.cmp(&b.who)); + } + >::insert(¤t_era, &c, exposure_clipped); } // Insert current era informations diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs index 2c21f0426ded2..2101c7e34b08a 100644 --- a/frame/staking/src/migration.rs +++ b/frame/staking/src/migration.rs @@ -28,6 +28,7 @@ pub mod inner { use crate::{Store, Module, Trait, EraRewardPoints, BalanceOf, StakingLedger, UnlockChunk}; use frame_support::{ StorageLinkedMap, StoragePrefixedMap, StorageValue, StorageDoubleMap, StorageMap, + traits::Get, }; use codec::{Encode, Decode, HasCompact}; use sp_std::vec::Vec; @@ -127,6 +128,7 @@ pub mod inner { // * ErasRewardPoints // * ActiveEra // * ErasStakers + // * ErasStakersClipped // * ErasValidatorPrefs // * ErasTotalStake // * ErasStartSessionIndex @@ -161,10 +163,21 @@ pub mod inner { let current_elected = as Store>::CurrentElected::get(); let mut current_total_stake = >::zero(); for validator in ¤t_elected { - let exposure = as Store>::Stakers::get(validator); + let mut exposure = as Store>::Stakers::get(validator); current_total_stake += exposure.total; + exposure.others.sort_unstable_by(|a, b| a.who.cmp(&b.who)); + as Store>::ErasStakers::insert(current_era, validator, &exposure); + + let mut exposure_clipped = exposure; + let clipped_max_len = T::MaxNominatorRewardedPerValidator::get() as usize; + if exposure_clipped.others.len() > clipped_max_len { + exposure_clipped.others.sort_unstable_by(|a, b| a.value.cmp(&b.value)); + exposure_clipped.others.truncate(clipped_max_len); + exposure_clipped.others.sort_unstable_by(|a, b| a.who.cmp(&b.who)); + } + as Store>::ErasStakersClipped::insert(current_era, validator, exposure_clipped); + let pref = as Store>::Validators::get(validator); - as Store>::ErasStakers::insert(current_era, validator, exposure); as Store>::ErasValidatorPrefs::insert(current_era, validator, pref); } as Store>::ErasTotalStake::insert(current_era, current_total_stake); diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 85de27a2ecc5e..869f6dff5f960 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -205,6 +205,7 @@ parameter_types! { pub const SessionsPerEra: SessionIndex = 3; pub const BondingDuration: EraIndex = 3; pub const RewardCurve: &'static PiecewiseLinear<'static> = &I_NPOS; + pub const MaxNominatorRewardedPerValidator: u32 = 64; } impl Trait for Test { type Currency = pallet_balances::Module; @@ -220,6 +221,7 @@ impl Trait for Test { type BondingDuration = BondingDuration; type SessionInterface = Self; type RewardCurve = RewardCurve; + type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; } pub struct ExtBuilder { From 4e1d12dc34c74230e89774a5590ab26784c7f384 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 30 Jan 2020 18:55:18 +0100 Subject: [PATCH 38/75] doc --- frame/staking/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index be894493e9244..b4ff8f37605e3 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -106,6 +106,8 @@ //! //! Reward must be claimed by stakers for each era before it gets too old by $HISTORY_DEPTH using //! `payout_nominator` and `payout_validator` calls. +//! Only the [`T::MaxNominatorRewardedPerValidator`] biggest stakers can claim their reward. This +//! limit the i/o cost to compute nominators payout. //! //! Slashing can occur at any point in time, once misbehavior is reported. Once slashing is //! determined, a value is deducted from the balance of the validator and all the nominators who From 33afe3206454f65d8cc05067ce2b48cfa508f262 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 30 Jan 2020 19:02:27 +0100 Subject: [PATCH 39/75] fix payout with clipped --- frame/staking/src/lib.rs | 2 +- frame/staking/src/tests.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index b4ff8f37605e3..21568463c0f66 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1423,7 +1423,7 @@ impl Module { let era_reward_points = >::get(&era); for validator in validators.into_iter().take(MAX_NOMINATIONS) { let commission = Self::eras_validator_prefs(&era, &validator).commission; - let validator_exposure = >::get(&era, &validator); + let validator_exposure = >::get(&era, &validator); if let Ok(nominator_exposure) = validator_exposure.others .binary_search_by(|exposure| exposure.who.cmp(&nominator_ledger.stash)) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 11d740e724e76..2a4babc7015e3 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -1820,7 +1820,8 @@ fn reward_validator_slashing_validator_doesnt_overflow() { // Check reward ErasRewardPoints::::insert(0, reward); - ErasStakers::::insert(0, 11, exposure); + ErasStakers::::insert(0, 11, &exposure); + ErasStakersClipped::::insert(0, 11, exposure); ErasValidatorReward::::insert(0, stake); assert_ok!(Staking::payout_validator(Origin::signed(10), 0)); assert_eq!(Balances::total_balance(&11), stake * 2); From 35f76ab3b874ad41b42e03c7b239018ca15a5e1c Mon Sep 17 00:00:00 2001 From: thiolliere Date: Thu, 30 Jan 2020 19:07:49 +0100 Subject: [PATCH 40/75] fix node runtime --- bin/node/runtime/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 3f12957a05f89..4b7b0282d0479 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -80,7 +80,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 209, + spec_version: 210, impl_version: 0, apis: RUNTIME_API_VERSIONS, }; @@ -267,6 +267,7 @@ parameter_types! { pub const BondingDuration: pallet_staking::EraIndex = 24 * 28; pub const SlashDeferDuration: pallet_staking::EraIndex = 24 * 7; // 1/4 the bonding duration. pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; + pub const MaxNominatorRewardedPerValidator: u32 = 64; } impl pallet_staking::Trait for Runtime { @@ -284,6 +285,7 @@ impl pallet_staking::Trait for Runtime { type SlashCancelOrigin = pallet_collective::EnsureProportionAtLeast<_3, _4, AccountId, CouncilCollective>; type SessionInterface = Self; type RewardCurve = RewardCurve; + type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; } parameter_types! { From d35dafc1b978245dca9f9bb6e71be8ca1dfcb003 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 31 Jan 2020 12:18:05 +0100 Subject: [PATCH 41/75] add doc --- frame/staking/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 21568463c0f66..ec4b85705e062 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1839,6 +1839,8 @@ impl Module { /// In this implementation `new_session(session)` must be called before `end_session(session-1)` /// i.e. the new session must be planned before the ending of the previous session. +/// +/// `new_session(0)` must be called at genesis. impl pallet_session::SessionManager for Module { fn new_session(new_index: SessionIndex) -> Option> { Self::ensure_storage_upgraded(); @@ -1854,6 +1856,8 @@ impl pallet_session::SessionManager for Module { /// In this implementation `new_session(session)` must be called before `end_session(session-1)` /// i.e. the new session must be planned before the ending of the previous session. +/// +/// `new_session(0)` must be called at genesis. impl SessionManager>> for Module { fn new_session(new_index: SessionIndex) -> Option>)>> From 381d5ef38746eb95ef3d9c8af88646633ff5dddb Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 31 Jan 2020 15:29:58 +0100 Subject: [PATCH 42/75] pluggable and generalized staking module --- frame/session/src/historical.rs | 4 + frame/session/src/lib.rs | 13 +- frame/staking/src/lib.rs | 208 +++++++++++++++-------- frame/staking/src/migration.rs | 4 +- frame/staking/src/mock.rs | 14 +- frame/staking/src/tests.rs | 288 ++++++++++++++++---------------- 6 files changed, 305 insertions(+), 226 deletions(-) diff --git a/frame/session/src/historical.rs b/frame/session/src/historical.rs index 76175cd6be0e5..4090b81054287 100644 --- a/frame/session/src/historical.rs +++ b/frame/session/src/historical.rs @@ -108,6 +108,7 @@ pub trait SessionManager: crate::SessionManager /// If there was a validator set change, its returns the set of new validators along with their /// full identifications. fn new_session(new_index: SessionIndex) -> Option>; + fn start_session(end_index: SessionIndex); fn end_session(end_index: SessionIndex); } @@ -146,6 +147,9 @@ impl crate::SessionManager for NoteHistoricalRoot>::start_session(end_index) + } fn end_session(end_index: SessionIndex) { >::end_session(end_index) } diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index f98e334cbb018..9554afb13e6c4 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -161,10 +161,15 @@ pub trait SessionManager { /// Because the session pallet can queue validator set the ending session can be lower than the /// last new session index. fn end_session(end_index: SessionIndex); + /// Start the session. + /// + /// The session start to be used for validation + fn start_session(start_index: SessionIndex); } impl SessionManager for () { fn new_session(_: SessionIndex) -> Option> { None } + fn start_session(_: SessionIndex) {} fn end_session(_: SessionIndex) {} } @@ -424,6 +429,8 @@ decl_storage! { >::put(initial_validators_0); >::put(queued_keys); + + T::SessionManager::start_session(0); }); } } @@ -503,6 +510,8 @@ impl Module { // Inform the session handlers that a session is going to end. T::SessionHandler::on_before_session_ending(); + T::SessionManager::end_session(session_index); + // Get queued session keys and validators. let session_keys = >::get(); let validators = session_keys.iter() @@ -515,12 +524,12 @@ impl Module { DisabledValidators::take(); } - T::SessionManager::end_session(session_index); - // Increment session index. let session_index = session_index + 1; CurrentIndex::put(session_index); + T::SessionManager::start_session(session_index); + // Get next validator set. let maybe_next_validators = T::SessionManager::new_session(session_index + 1); let (next_validators, next_identities_changed) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index ec4b85705e062..1129a1b33b3cf 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -127,6 +127,11 @@ //! //! An account can step back via the [`chill`](enum.Call.html#variant.chill) call. //! +//! ### Session managing +//! +//! The module implement the trait `SessionManager`. Which is the only API to query new validator +//! set and allowing these validator set to be rewarded once their era is ended. +//! //! ## Interface //! //! ### Dispatchable Functions @@ -233,6 +238,7 @@ //! ## GenesisConfig //! //! The Staking module depends on the [`GenesisConfig`](./struct.GenesisConfig.html). +//! The `GenesisConfig` is optional and allow to set some initial stakers. //! //! ## Related Modules //! @@ -507,6 +513,8 @@ pub struct Nominations { /// The targets of nomination. pub targets: Vec, /// The era the nominations were submitted. + /// + /// Except for initial nominations which are considered submitted at era 0. pub submitted_in: EraIndex, /// Whether the nominations have been suppressed. pub suppressed: bool, @@ -602,7 +610,8 @@ pub trait Trait: frame_system::Trait { /// The staking balance. type Currency: LockableCurrency; - /// Time used for computing era duration. + /// Time used for computing era duration. It is guaranteed to start being called from the + /// first `on_finalize`. Thus value can be wrong at genesis. type Time: Time; /// Convert a balance into a number used for election calculation. @@ -710,13 +719,17 @@ decl_storage! { /// /// This is the latest planned era, depending on how session module queues the validator /// set, it might be active or not. - pub CurrentEra get(fn current_era) config(): EraIndex; + pub CurrentEra get(fn current_era): Option; /// The active era index, the era currently rewarded. - pub ActiveEra get(fn active_era) config(): EraIndex; + pub ActiveEra get(fn active_era): Option; /// The start of the currently rewarded era. - pub ActiveEraStart get(fn active_era_start): MomentOf; + pub ActiveEraStart get(fn active_era_start): Option>; + + /// The session index at which the era started for the last `HISTORY_DEPTH` eras + pub ErasStartSessionIndex get(fn eras_start_session_index): + map hasher(blake2_256) EraIndex => Option; /// Exposure of validator at era. /// @@ -755,10 +768,6 @@ decl_storage! { pub ErasValidatorReward get(fn eras_validator_reward): map hasher(blake2_256) EraIndex => BalanceOf; - /// The session index at which the era started for the last `HISTORY_DEPTH` eras - pub ErasStartSessionIndex get(fn eras_start_session_index): - map hasher(blake2_256) EraIndex => SessionIndex; - /// Rewards for the last `HISTORY_DEPTH` eras. pub ErasRewardPoints get(fn eras_reward_points): map hasher(blake2_256) EraIndex => EraRewardPoints; @@ -932,7 +941,7 @@ decl_module! { fn on_finalize() { // Set the start of the first era. - if !>::exists() { + if Self::active_era().is_some() && Self::active_era_start().is_none() { >::put(T::Time::now()); } } @@ -987,7 +996,7 @@ decl_module! { total: value, active: value, unlocking: vec![], - next_reward: Self::current_era(), + next_reward: Self::current_era().unwrap_or(0), }; Self::update_ledger(&controller, &item); } @@ -1067,7 +1076,7 @@ decl_module! { ledger.active = Zero::zero(); } - let era = Self::current_era() + T::BondingDuration::get(); + let era = Self::current_era().unwrap_or(0) + T::BondingDuration::get(); ledger.unlocking.push(UnlockChunk { value, era }); Self::update_ledger(&controller, &ledger); } @@ -1093,7 +1102,7 @@ decl_module! { fn withdraw_unbonded(origin) { let controller = ensure_signed(origin)?; let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; - let ledger = ledger.consolidate_unlocked(Self::current_era()); + let ledger = ledger.consolidate_unlocked(Self::current_era().unwrap_or(0)); if ledger.unlocking.is_empty() && ledger.active.is_zero() { // This account must have called `unbond()` with some value that caused the active @@ -1158,7 +1167,7 @@ decl_module! { let nominations = Nominations { targets, - submitted_in: Self::current_era(), + submitted_in: Self::current_era().unwrap_or(0), suppressed: false, }; @@ -1547,53 +1556,82 @@ impl Module { } /// New session. Provide the validator set for if it's a new era. - /// - /// NOTE: session 0 is initialised using initial_session fn new_session(session_index: SessionIndex) -> Option> { - let era_length = session_index - .checked_sub(Self::eras_start_session_index(Self::current_era())).unwrap_or(0); - match ForceEra::get() { - Forcing::ForceNew => ForceEra::kill(), - Forcing::ForceAlways => (), - Forcing::NotForcing if era_length >= T::SessionsPerEra::get() => (), - _ => return None, - } + if let Some(current_era) = Self::current_era() { + let current_era_start_session_index = Self::eras_start_session_index(current_era) + .unwrap_or_else(|| { + frame_support::print("Error: start_session_index must be set for current_era"); + 0 + }); + + let era_length = session_index.checked_sub(current_era_start_session_index) + .unwrap_or(0); // Must never happen. + + match ForceEra::get() { + Forcing::ForceNew => ForceEra::kill(), + Forcing::ForceAlways => (), + Forcing::NotForcing if era_length >= T::SessionsPerEra::get() => (), + _ => return None, + } - Self::new_era(session_index) + Self::new_era(session_index) + } else { + println!("initial era!!"); + // Set initial era + Self::new_era(session_index) + } } - /// Initialise the session 0 (and consequently the era 0) - fn initial_session() -> Option> { - // note: `ActiveEraStart` is set in `on_finalize` of the first block because now is not - // available yet. - BondedEras::mutate(|bonded| bonded.push((0, 0))); - Self::select_validators() + fn start_session(start_session: SessionIndex) { + let next_active_era = Self::active_era().map(|e| e + 1).unwrap_or(0); + if let Some(next_active_era_start_session_index) = Self::eras_start_session_index(next_active_era) { + if next_active_era_start_session_index == start_session { + Self::start_era(start_session); + } + } } fn end_session(session_index: SessionIndex) { - if ErasStartSessionIndex::get(Self::active_era() + 1) == session_index + 1 { - Self::end_era(session_index); + if let Some(active_era) = Self::active_era() { + let next_active_era_start_session_index = Self::eras_start_session_index(active_era + 1) + .unwrap_or_else(|| { + frame_support::print("Error: start_session_index must be set for active_era + 1"); + 0 + }); + + if next_active_era_start_session_index == session_index + 1 { + Self::end_era(active_era, session_index); + } } } - fn end_era(_session_index: SessionIndex) { - let now = T::Time::now(); + fn start_era(_start_session: SessionIndex) { + ActiveEra::mutate(|s| { + *s = Some(s.map(|s| s + 1).unwrap_or(0)); + }); - // Set new active era start - let previous_era_start = >::mutate(|v| sp_std::mem::replace(v, now)); - let previous_era = ActiveEra::mutate(|index| sp_std::mem::replace(index, *index + 1)); + // Set new active era start in next `on_finalize`. To guarantee usage of `Time::now`. + >::kill(); - let era_duration = now - previous_era_start; - let (total_payout, _max_payout) = inflation::compute_total_payout( - &T::RewardCurve::get(), - Self::eras_total_stake(previous_era), - T::Currency::total_issuance(), - // Duration of era; more than u64::MAX is rewarded as u64::MAX. - era_duration.saturated_into::(), - ); + } - // Set previous era reward. - >::insert(previous_era, total_payout); + fn end_era(active_era: EraIndex, _session_index: SessionIndex) { + // Note: active_era_start can be None if end era is called during genesis config. + if let Some(active_era_start) = Self::active_era_start() { + let now = T::Time::now(); + + let era_duration = now - active_era_start; + let (total_payout, _max_payout) = inflation::compute_total_payout( + &T::RewardCurve::get(), + Self::eras_total_stake(&active_era), + T::Currency::total_issuance(), + // Duration of era; more than u64::MAX is rewarded as u64::MAX. + era_duration.saturated_into::(), + ); + + // Set previous era reward. + >::insert(&active_era, total_payout); + } } /// The era has changed - enact new staking set. @@ -1601,8 +1639,11 @@ impl Module { /// NOTE: This always happens immediately before a session change to ensure that new validators /// get a chance to set their session keys. fn new_era(start_session_index: SessionIndex) -> Option> { - // Increment current era. - let current_era = CurrentEra::mutate(|s| { *s += 1; *s }); + // Increment or set current era. + let current_era = CurrentEra::mutate(|s| { + *s = Some(s.map(|s| s + 1).unwrap_or(0)); + s.unwrap() + }); ErasStartSessionIndex::insert(¤t_era, &start_session_index); // Clean old era information. @@ -1640,7 +1681,7 @@ impl Module { }); // Reassign all ErasStakers. - let maybe_new_validators = Self::select_validators(); + let maybe_new_validators = Self::select_validators(current_era); Self::apply_unapplied_slashes(current_era); maybe_new_validators @@ -1664,10 +1705,13 @@ impl Module { /// Select a new validator set from the assembled stakers and their role preferences. /// + /// Fill the storages `ErasStakers`, `ErasStakersClipped`, `ErasValidatorPrefs` and + /// `ErasTotalStake` for current era. + /// /// Returns a set of newly selected _stash_ IDs. /// /// Assumes storage is coherent with the declaration. - fn select_validators() -> Option> { + fn select_validators(current_era: EraIndex) -> Option> { let mut all_nominators: Vec<(T::AccountId, Vec)> = Vec::new(); let mut all_validators_and_prefs = BTreeMap::new(); let mut all_validators = Vec::new(); @@ -1717,7 +1761,6 @@ impl Module { Self::slashable_balance_of, ); - let current_era = Self::current_era(); // Populate ErasStakers and figure out the total stake. let mut total_staked = BalanceOf::::zero(); for (c, s) in supports.into_iter() { @@ -1820,12 +1863,14 @@ impl Module { pub fn reward_by_ids( validators_points: impl IntoIterator ) { - >::mutate(Self::active_era(), |era_rewards| { - for (validator, points) in validators_points.into_iter() { - *era_rewards.individual.entry(validator).or_default() += points; - era_rewards.total += points; - } - }); + if let Some(active_era) = Self::active_era() { + >::mutate(active_era, |era_rewards| { + for (validator, points) in validators_points.into_iter() { + *era_rewards.individual.entry(validator).or_default() += points; + era_rewards.total += points; + } + }); + } } /// Ensures that at the end of the current session there will be a new era. @@ -1840,24 +1885,24 @@ impl Module { /// In this implementation `new_session(session)` must be called before `end_session(session-1)` /// i.e. the new session must be planned before the ending of the previous session. /// -/// `new_session(0)` must be called at genesis. +/// Once the first new_session is planned, all session must start and then end in order, though +/// some session can lag in between the newest session planned and the latest session started. impl pallet_session::SessionManager for Module { fn new_session(new_index: SessionIndex) -> Option> { + println!("New session at: {}", new_index); Self::ensure_storage_upgraded(); - if new_index == 0 { - return Self::initial_session(); - } Self::new_session(new_index) } + fn start_session(start_index: SessionIndex) { + Self::start_session(start_index) + } fn end_session(end_index: SessionIndex) { Self::end_session(end_index) } } -/// In this implementation `new_session(session)` must be called before `end_session(session-1)` -/// i.e. the new session must be planned before the ending of the previous session. -/// -/// `new_session(0)` must be called at genesis. +/// This implementation has the same constrains as the implementation of +/// `pallet_session::SessionManager`. impl SessionManager>> for Module { fn new_session(new_index: SessionIndex) -> Option>)>> @@ -1869,6 +1914,9 @@ impl SessionManager> }).collect() }) } + fn start_session(start_index: SessionIndex) { + >::start_session(start_index) + } fn end_session(end_index: SessionIndex) { >::end_session(end_index) } @@ -1921,7 +1969,11 @@ impl Convert> for ExposureOf { fn convert(validator: T::AccountId) -> Option>> { - Some(>::eras_stakers(>::active_era(), &validator)) + if let Some(active_era) = >::active_era() { + Some(>::eras_stakers(active_era, &validator)) + } else { + None + } } } @@ -1945,13 +1997,21 @@ impl OnOffenceHandler= current_era_start_session_index { - era_now + current_era } else { let eras = BondedEras::get(); @@ -1964,7 +2024,7 @@ impl OnOffenceHandler::EarliestUnappliedSlash::mutate(|earliest| { if earliest.is_none() { - *earliest = Some(era_now) + *earliest = Some(current_era) } }); @@ -1985,7 +2045,7 @@ impl OnOffenceHandler OnOffenceHandler::UnappliedSlashes::mutate( - era_now, + current_era, move |for_later| for_later.push(unapplied), ); } diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs index 2101c7e34b08a..f872c0c919fc6 100644 --- a/frame/staking/src/migration.rs +++ b/frame/staking/src/migration.rs @@ -46,7 +46,7 @@ pub mod inner { if *version != 0 { return } *version += 1; - let now = >::current_era(); + let now = >::current_era().unwrap_or(0); let res = as Store>::Nominators::translate::, _, _>( |key| key, |targets| crate::Nominations { @@ -155,7 +155,7 @@ pub mod inner { *version += 1; let current_era_start_index = as Store>::CurrentEraStartSessionIndex::get(); - let current_era = as Store>::CurrentEra::get(); + let current_era = as Store>::CurrentEra::get().unwrap_or(0); as Store>::ErasStartSessionIndex::insert(current_era, current_era_start_index); as Store>::ActiveEra::put(current_era); as Store>::ActiveEraStart::put( as Store>::CurrentEraStart::get()); diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 869f6dff5f960..176345bb14e79 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -19,7 +19,7 @@ use std::{collections::HashSet, cell::RefCell}; use sp_runtime::{Perbill, KeyTypeId}; use sp_runtime::curve::PiecewiseLinear; -use sp_runtime::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize, SaturatedConversion}; +use sp_runtime::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize, OnFinalize, SaturatedConversion}; use sp_runtime::testing::{Header, UintAuthorityId}; use sp_staking::{SessionIndex, offence::{OffenceDetails, OnOffenceHandler}}; use sp_core::{H256, crypto::key_types}; @@ -338,7 +338,6 @@ impl ExtBuilder { }; let nominated = if self.nominate { vec![11, 21] } else { vec![] }; let _ = GenesisConfig::{ - current_era: 0, stakers: vec![ // (stash, controller, staked_amount, status) (11, 10, balance_factor * 1000, StakerStatus::::Validator), @@ -450,6 +449,7 @@ pub fn advance_session() { pub fn start_session(session_index: SessionIndex) { for i in Session::current_index()..session_index { + Staking::on_finalize(System::block_number()); System::set_block_number((i + 1).into()); Timestamp::set_timestamp(System::block_number() * 1000); Session::on_initialize(System::block_number()); @@ -460,13 +460,13 @@ pub fn start_session(session_index: SessionIndex) { pub fn start_era(era_index: EraIndex) { start_session((era_index * 3).into()); - assert_eq!(Staking::active_era(), era_index); + assert_eq!(Staking::active_era().unwrap(), era_index); } pub fn current_total_payout_for_duration(duration: u64) -> u64 { inflation::compute_total_payout( ::RewardCurve::get(), - Staking::eras_total_stake(Staking::active_era()), + Staking::eras_total_stake(Staking::active_era().unwrap()), Balances::total_issuance(), duration, ).0 @@ -498,8 +498,8 @@ pub fn on_offence_in_era( } } - if Staking::active_era() == era { - Staking::on_offence(offenders, slash_fraction, Staking::eras_start_session_index(era)); + if Staking::active_era().unwrap() == era { + Staking::on_offence(offenders, slash_fraction, Staking::eras_start_session_index(era).unwrap()); } else { panic!("cannot slash in era {}", era); } @@ -509,7 +509,7 @@ pub fn on_offence_now( offenders: &[OffenceDetails>], slash_fraction: &[Perbill], ) { - let now = Staking::active_era(); + let now = Staking::active_era().unwrap(); on_offence_in_era(offenders, slash_fraction, now) } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 2a4babc7015e3..694ba2b621226 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -92,7 +92,7 @@ fn basic_setup_works() { assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); assert_eq!( - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), Exposure { total: 1125, own: 1000, @@ -100,7 +100,7 @@ fn basic_setup_works() { }, ); assert_eq!( - Staking::eras_stakers(Staking::active_era(), 21), + Staking::eras_stakers(Staking::active_era().unwrap(), 21), Exposure { total: 1375, own: 1000, @@ -108,14 +108,14 @@ fn basic_setup_works() { }, ); // initial slot_stake - assert_eq!(Staking::eras_total_stake(Staking::active_era()), 2500); + assert_eq!(Staking::eras_total_stake(Staking::active_era().unwrap()), 2500); // The number of validators required. assert_eq!(Staking::validator_count(), 2); // Initial Era and session - assert_eq!(Staking::active_era(), 0); + assert_eq!(Staking::active_era().unwrap(), 0); // Account 10 has `balance_factor` free balance assert_eq!(Balances::free_balance(&10), 1); @@ -125,8 +125,8 @@ fn basic_setup_works() { assert_eq!(Staking::force_era(), Forcing::NotForcing); // All exposures must be correct. - check_exposure_all(Staking::active_era()); - check_nominator_all(Staking::active_era()); + check_exposure_all(Staking::active_era().unwrap()); + check_nominator_all(Staking::active_era().unwrap()); }); } @@ -189,7 +189,7 @@ fn rewards_should_work() { assert_eq!(Balances::total_balance(&100), init_balance_100); assert_eq!(Balances::total_balance(&101), init_balance_101); assert_eq_uvec!(Session::validators(), vec![11, 21]); - assert_eq!(Staking::eras_reward_points(Staking::active_era()), EraRewardPoints { + assert_eq!(Staking::eras_reward_points(Staking::active_era().unwrap()), EraRewardPoints { total: 50*3, individual: vec![(11, 100), (21, 50)].into_iter().collect(), }); @@ -201,7 +201,7 @@ fn rewards_should_work() { start_session(2); start_session(3); - assert_eq!(Staking::active_era(), 1); + assert_eq!(Staking::active_era().unwrap(), 1); mock::make_all_reward_payment(0); assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * total_payout_0*2/3, 2); @@ -282,7 +282,7 @@ fn staking_should_work() { // --- Block 4: the validators will now be queued. start_session(4); - assert_eq!(Staking::active_era(), 1); + assert_eq!(Staking::active_era().unwrap(), 1); // --- Block 5: the validators are still in queue. start_session(5); @@ -345,11 +345,11 @@ fn less_than_needed_candidates_works() { // But the exposure is updated in a simple way. No external votes exists. // This is purely self-vote. assert!( - ErasStakers::::iter_prefix(Staking::active_era()) + ErasStakers::::iter_prefix(Staking::active_era().unwrap()) .all(|exposure| exposure.others.is_empty()) ); - check_exposure_all(Staking::active_era()); - check_nominator_all(Staking::active_era()); + check_exposure_all(Staking::active_era().unwrap()); + check_nominator_all(Staking::active_era().unwrap()); }); } @@ -468,9 +468,9 @@ fn nominating_and_rewards_should_work() { // ------ check the staked value of all parties. // 30 and 40 are not chosen anymore - assert_eq!(ErasStakers::::iter_prefix(Staking::active_era()).count(), 2); + assert_eq!(ErasStakers::::iter_prefix(Staking::active_era().unwrap()).count(), 2); assert_eq!( - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), Exposure { total: 1000 + 800, own: 1000, @@ -481,7 +481,7 @@ fn nominating_and_rewards_should_work() { }, ); assert_eq!( - Staking::eras_stakers(Staking::active_era(), 21), + Staking::eras_stakers(Staking::active_era().unwrap(), 21), Exposure { total: 1000 + 1200, own: 1000, @@ -532,8 +532,8 @@ fn nominating_and_rewards_should_work() { 1, ); - check_exposure_all(Staking::active_era()); - check_nominator_all(Staking::active_era()); + check_exposure_all(Staking::active_era().unwrap()); + check_nominator_all(Staking::active_era().unwrap()); }); } @@ -576,13 +576,13 @@ fn nominators_also_get_slashed() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), ), reporters: vec![], }], &[Perbill::from_percent(5)], ); - let expo = Staking::eras_stakers(Staking::active_era(), 11); + let expo = Staking::eras_stakers(Staking::active_era().unwrap(), 11); let slash_value = 50; let total_slash = expo.total.min(slash_value); let validator_slash = expo.own.min(total_slash); @@ -591,8 +591,8 @@ fn nominators_also_get_slashed() { // initial + first era reward + slash assert_eq!(Balances::total_balance(&11), initial_balance - validator_slash); assert_eq!(Balances::total_balance(&2), initial_balance - nominator_slash); - check_exposure_all(Staking::active_era()); - check_nominator_all(Staking::active_era()); + check_exposure_all(Staking::active_era().unwrap()); + check_nominator_all(Staking::active_era().unwrap()); // Because slashing happened. assert!(is_disabled(10)); }); @@ -647,52 +647,52 @@ fn double_controlling_should_fail() { #[test] fn session_and_eras_work() { ExtBuilder::default().build().execute_with(|| { - assert_eq!(Staking::active_era(), 0); + assert_eq!(Staking::active_era().unwrap(), 0); // Block 1: No change. start_session(1); assert_eq!(Session::current_index(), 1); - assert_eq!(Staking::active_era(), 0); + assert_eq!(Staking::active_era().unwrap(), 0); // Block 2: No change. start_session(2); assert_eq!(Session::current_index(), 2); - assert_eq!(Staking::active_era(), 0); + assert_eq!(Staking::active_era().unwrap(), 0); // Block 3: Era increment. start_session(3); assert_eq!(Session::current_index(), 3); - assert_eq!(Staking::active_era(), 1); + assert_eq!(Staking::active_era().unwrap(), 1); // Block 4: No change. start_session(4); assert_eq!(Session::current_index(), 4); - assert_eq!(Staking::active_era(), 1); + assert_eq!(Staking::active_era().unwrap(), 1); // Block 5: No change. start_session(5); assert_eq!(Session::current_index(), 5); - assert_eq!(Staking::active_era(), 1); + assert_eq!(Staking::active_era().unwrap(), 1); // Block 6: Era increment. start_session(6); assert_eq!(Session::current_index(), 6); - assert_eq!(Staking::active_era(), 2); + assert_eq!(Staking::active_era().unwrap(), 2); // Block 7: No change. start_session(7); assert_eq!(Session::current_index(), 7); - assert_eq!(Staking::active_era(), 2); + assert_eq!(Staking::active_era().unwrap(), 2); // Block 8: No change. start_session(8); assert_eq!(Session::current_index(), 8); - assert_eq!(Staking::active_era(), 2); + assert_eq!(Staking::active_era().unwrap(), 2); // Block 9: Era increment. start_session(9); assert_eq!(Session::current_index(), 9); - assert_eq!(Staking::active_era(), 3); + assert_eq!(Staking::active_era().unwrap(), 3); }); } @@ -700,53 +700,53 @@ fn session_and_eras_work() { fn forcing_new_era_works() { ExtBuilder::default().build().execute_with(|| { // normal flow of session. - assert_eq!(Staking::active_era(), 0); + assert_eq!(Staking::active_era().unwrap(), 0); start_session(0); - assert_eq!(Staking::active_era(), 0); + assert_eq!(Staking::active_era().unwrap(), 0); start_session(1); - assert_eq!(Staking::active_era(), 0); + assert_eq!(Staking::active_era().unwrap(), 0); start_session(2); - assert_eq!(Staking::active_era(), 0); + assert_eq!(Staking::active_era().unwrap(), 0); start_session(3); - assert_eq!(Staking::active_era(), 1); + assert_eq!(Staking::active_era().unwrap(), 1); // no era change. ForceEra::put(Forcing::ForceNone); start_session(4); - assert_eq!(Staking::active_era(), 1); + assert_eq!(Staking::active_era().unwrap(), 1); start_session(5); - assert_eq!(Staking::active_era(), 1); + assert_eq!(Staking::active_era().unwrap(), 1); start_session(6); - assert_eq!(Staking::active_era(), 1); + assert_eq!(Staking::active_era().unwrap(), 1); start_session(7); - assert_eq!(Staking::active_era(), 1); + assert_eq!(Staking::active_era().unwrap(), 1); // back to normal. // this immediately starts a new session. ForceEra::put(Forcing::NotForcing); start_session(8); - assert_eq!(Staking::active_era(), 1); // There is one session delay + assert_eq!(Staking::active_era().unwrap(), 1); // There is one session delay start_session(9); - assert_eq!(Staking::active_era(), 2); + assert_eq!(Staking::active_era().unwrap(), 2); // forceful change ForceEra::put(Forcing::ForceAlways); start_session(10); - assert_eq!(Staking::active_era(), 2); // There is one session delay + assert_eq!(Staking::active_era().unwrap(), 2); // There is one session delay start_session(11); - assert_eq!(Staking::active_era(), 3); + assert_eq!(Staking::active_era().unwrap(), 3); start_session(12); - assert_eq!(Staking::active_era(), 4); + assert_eq!(Staking::active_era().unwrap(), 4); // just one forceful change ForceEra::put(Forcing::ForceNew); start_session(13); - assert_eq!(Staking::active_era(), 5); + assert_eq!(Staking::active_era().unwrap(), 5); assert_eq!(ForceEra::get(), Forcing::NotForcing); start_session(14); - assert_eq!(Staking::active_era(), 6); + assert_eq!(Staking::active_era().unwrap(), 6); start_session(15); - assert_eq!(Staking::active_era(), 6); + assert_eq!(Staking::active_era().unwrap(), 6); }); } @@ -760,7 +760,7 @@ fn cannot_transfer_staked_balance() { // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(&11), 1000); // Confirm account 11 (via controller 10) is totally staked - assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).total, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).total, 1000); // Confirm account 11 cannot transfer as a result assert_noop!( Balances::transfer(Origin::signed(11), 20, 1), @@ -789,7 +789,7 @@ fn cannot_transfer_staked_balance_2() { // Confirm account 21 has some free balance assert_eq!(Balances::free_balance(&21), 2000); // Confirm account 21 (via controller 20) is totally staked - assert_eq!(Staking::eras_stakers(Staking::active_era(), 21).total, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 21).total, 1000); // Confirm account 21 can transfer at most 1000 assert_noop!( Balances::transfer(Origin::signed(21), 20, 1001), @@ -812,7 +812,7 @@ fn cannot_reserve_staked_balance() { // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(&11), 1000); // Confirm account 11 (via controller 10) is totally staked - assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).own, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).own, 1000); // Confirm account 11 cannot transfer as a result assert_noop!( Balances::reserve(&11, 1), @@ -950,7 +950,7 @@ fn validator_payment_prefs_work() { // Compute total payout now for whole duration as other parameter won't change let total_payout_1 = current_total_payout_for_duration(3000); - let exposure_1 = Staking::eras_stakers(Staking::active_era(), 11); + let exposure_1 = Staking::eras_stakers(Staking::active_era().unwrap(), 11); assert!(total_payout_1 > 100); // Test is meaningfull if reward something >::reward_by_ids(vec![(11, 1)]); @@ -964,8 +964,8 @@ fn validator_payment_prefs_work() { assert_eq_error_rate!(Balances::total_balance(&10), balance_era_1_10 + reward_of_10, 2); assert_eq_error_rate!(Balances::total_balance(&100), balance_era_1_100 + reward_of_100, 2); - check_exposure_all(Staking::active_era()); - check_nominator_all(Staking::active_era()); + check_exposure_all(Staking::active_era().unwrap()); + check_nominator_all(Staking::active_era().unwrap()); }); } @@ -1031,7 +1031,7 @@ fn bond_extra_and_withdraw_unbonded_works() { let _ = Balances::make_free_balance_be(&11, 1000000); // Initial config should be correct - assert_eq!(Staking::active_era(), 0); + assert_eq!(Staking::active_era().unwrap(), 0); assert_eq!(Session::current_index(), 0); // check the balance of a validator accounts. @@ -1048,7 +1048,7 @@ fn bond_extra_and_withdraw_unbonded_works() { unlocking: vec![], next_reward: 0, })); - assert_eq!(Staking::eras_stakers(Staking::active_era(), 11), Exposure { total: 1000, own: 1000, others: vec![] }); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11), Exposure { total: 1000, own: 1000, others: vec![] }); // deposit the extra 100 units Staking::bond_extra(Origin::signed(11), 100).unwrap(); @@ -1061,12 +1061,12 @@ fn bond_extra_and_withdraw_unbonded_works() { next_reward: 0, })); // Exposure is a snapshot! only updated after the next era update. - assert_ne!(Staking::eras_stakers(Staking::active_era(), 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + assert_ne!(Staking::eras_stakers(Staking::active_era().unwrap(), 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); // trigger next era. Timestamp::set_timestamp(10); start_era(2); - assert_eq!(Staking::active_era(), 2); + assert_eq!(Staking::active_era().unwrap(), 2); // ledger should be the same. assert_eq!(Staking::ledger(&10), Some(StakingLedger { @@ -1077,7 +1077,7 @@ fn bond_extra_and_withdraw_unbonded_works() { next_reward: 0, })); // Exposure is now updated. - assert_eq!(Staking::eras_stakers(Staking::active_era(), 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); // Unbond almost all of the funds in stash. Staking::unbond(Origin::signed(10), 1000).unwrap(); @@ -1170,7 +1170,7 @@ fn rebond_works() { ); start_era(2); - assert_eq!(Staking::active_era(), 2); + assert_eq!(Staking::active_era().unwrap(), 2); // Try to rebond some funds. We get an error since no fund is unbonded. assert_noop!( @@ -1394,8 +1394,8 @@ fn reward_to_stake_works() { // Confirm account 10 and 20 are validators assert_eq_uvec!(Session::validators(), vec![11, 21]); - assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).total, 1000); - assert_eq!(Staking::eras_stakers(Staking::active_era(), 21).total, 2000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).total, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 21).total, 2000); // Give the man some money. let _ = Balances::make_free_balance_be(&10, 1000); @@ -1405,7 +1405,7 @@ fn reward_to_stake_works() { ErasStakers::::insert(0, 21, Exposure { total: 69, own: 69, others: vec![] }); // Now lets lower account 20 stake - assert_eq!(Staking::eras_stakers(Staking::active_era(), 21).total, 69); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 21).total, 69); >::insert(&20, StakingLedger { stash: 21, total: 69, active: 69, unlocking: vec![], next_reward: 0 }); // Compute total payout now for whole duration as other parameter won't change @@ -1418,8 +1418,8 @@ fn reward_to_stake_works() { start_era(1); mock::make_all_reward_payment(0); - assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).total, 1000); - assert_eq!(Staking::eras_stakers(Staking::active_era(), 21).total, 69); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).total, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 21).total, 69); let _11_balance = Balances::free_balance(&11); assert_eq!(_11_balance, 1000 + total_payout_0 / 2); @@ -1428,11 +1428,11 @@ fn reward_to_stake_works() { start_era(2); // -- new infos - assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).total, 1000 + total_payout_0 / 2); - assert_eq!(Staking::eras_stakers(Staking::active_era(), 21).total, 69 + total_payout_0 / 2); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).total, 1000 + total_payout_0 / 2); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 21).total, 69 + total_payout_0 / 2); - check_exposure_all(Staking::active_era()); - check_nominator_all(Staking::active_era()); + check_exposure_all(Staking::active_era().unwrap()); + check_nominator_all(Staking::active_era().unwrap()); }); } @@ -1581,8 +1581,8 @@ fn switching_roles() { assert_eq_uvec!(validator_controllers(), vec![2, 20]); - check_exposure_all(Staking::active_era()); - check_nominator_all(Staking::active_era()); + check_exposure_all(Staking::active_era().unwrap()); + check_nominator_all(Staking::active_era().unwrap()); }); } @@ -1688,7 +1688,7 @@ fn bond_with_little_staked_value_bounded() { // 2 is elected. assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); // And has minimal stake - assert_eq!(Staking::eras_stakers(Staking::active_era(), 2).total, 0); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 2).total, 0); // Old ones are rewarded. assert_eq!(Balances::free_balance(&10), init_balance_10 + total_payout_0 / 3); @@ -1703,15 +1703,15 @@ fn bond_with_little_staked_value_bounded() { mock::make_all_reward_payment(1); assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); - assert_eq!(Staking::eras_stakers(Staking::active_era(), 2).total, 0); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 2).total, 0); assert_eq!(Balances::free_balance(&2), init_balance_2 + total_payout_1 / 3); assert_eq!( Balances::free_balance(&10), init_balance_10 + total_payout_0 / 3 + total_payout_1 / 3, ); - check_exposure_all(Staking::active_era()); - check_nominator_all(Staking::active_era()); + check_exposure_all(Staking::active_era().unwrap()); + check_nominator_all(Staking::active_era().unwrap()); }); } @@ -1731,8 +1731,8 @@ fn new_era_elects_correct_number_of_validators() { Session::on_initialize(System::block_number()); assert_eq!(validator_controllers().len(), 1); - check_exposure_all(Staking::active_era()); - check_nominator_all(Staking::active_era()); + check_exposure_all(Staking::active_era().unwrap()); + check_nominator_all(Staking::active_era().unwrap()); }) } @@ -1754,8 +1754,8 @@ fn phragmen_should_not_overflow_validators() { // This test will fail this. Will saturate. // check_exposure_all(); - assert_eq!(Staking::eras_stakers(Staking::active_era(), 3).total, u64::max_value()); - assert_eq!(Staking::eras_stakers(Staking::active_era(), 5).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 3).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 5).total, u64::max_value()); }) } @@ -1776,8 +1776,8 @@ fn phragmen_should_not_overflow_nominators() { assert_eq_uvec!(validator_controllers(), vec![4, 2]); // Saturate. - assert_eq!(Staking::eras_stakers(Staking::active_era(), 3).total, u64::max_value()); - assert_eq!(Staking::eras_stakers(Staking::active_era(), 5).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 3).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 5).total, u64::max_value()); }) } @@ -1795,8 +1795,8 @@ fn phragmen_should_not_overflow_ultimate() { assert_eq_uvec!(validator_controllers(), vec![4, 2]); // Saturate. - assert_eq!(Staking::eras_stakers(Staking::active_era(), 3).total, u64::max_value()); - assert_eq!(Staking::eras_stakers(Staking::active_era(), 5).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 3).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 5).total, u64::max_value()); }) } @@ -1844,7 +1844,7 @@ fn reward_validator_slashing_validator_doesnt_overflow() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), reporters: vec![], }, ], @@ -1874,7 +1874,7 @@ fn reward_from_authorship_event_handler_works() { // 21 is rewarded as an uncle producer // 11 is rewarded as a block producer and uncle referencer and uncle producer assert_eq!( - ErasRewardPoints::::get(ActiveEra::get()), + ErasRewardPoints::::get(Staking::active_era().unwrap()), EraRewardPoints { individual: vec![(11, 20 + 2 * 2 + 1), (21, 1)].into_iter().collect(), total: 26, @@ -1902,7 +1902,7 @@ fn add_reward_points_fns_works() { ]); assert_eq!( - ErasRewardPoints::::get(ActiveEra::get()), + ErasRewardPoints::::get(Staking::active_era().unwrap()), EraRewardPoints { individual: vec![(11, 4), (21, 2)].into_iter().collect(), total: 6, @@ -1930,20 +1930,20 @@ fn era_is_always_same_length() { // session changes. ExtBuilder::default().build().execute_with(|| { start_era(1); - assert_eq!(Staking::eras_start_session_index(Staking::active_era()), SessionsPerEra::get()); + assert_eq!(Staking::eras_start_session_index(Staking::active_era().unwrap()).unwrap(), SessionsPerEra::get()); start_era(2); - assert_eq!(Staking::eras_start_session_index(Staking::active_era()), SessionsPerEra::get() * 2); + assert_eq!(Staking::eras_start_session_index(Staking::active_era().unwrap()).unwrap(), SessionsPerEra::get() * 2); let session = Session::current_index(); ForceEra::put(Forcing::ForceNew); advance_session(); advance_session(); - assert_eq!(Staking::active_era(), 3); - assert_eq!(Staking::eras_start_session_index(Staking::active_era()), session + 2); + assert_eq!(Staking::active_era().unwrap(), 3); + assert_eq!(Staking::eras_start_session_index(Staking::active_era().unwrap()).unwrap(), session + 2); start_era(4); - assert_eq!(Staking::eras_start_session_index(Staking::active_era()), session + 2 + SessionsPerEra::get()); + assert_eq!(Staking::eras_start_session_index(Staking::active_era().unwrap()).unwrap(), session + 2 + SessionsPerEra::get()); }); } @@ -1954,7 +1954,7 @@ fn offence_forces_new_era() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), ), reporters: vec![], }], @@ -1974,7 +1974,7 @@ fn offence_ensures_new_era_without_clobbering() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), ), reporters: vec![], }], @@ -1994,7 +1994,7 @@ fn offence_deselects_validator_when_slash_is_zero() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), ), reporters: vec![], }], @@ -2013,7 +2013,7 @@ fn slashing_performed_according_exposure() { // This test checks that slashing is performed according the exposure (or more precisely, // historical exposure), not the current balance. ExtBuilder::default().build().execute_with(|| { - assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).own, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).own, 1000); // Handle an offence with a historical exposure. on_offence_now( @@ -2047,7 +2047,7 @@ fn slash_in_old_span_does_not_deselect() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), ), reporters: vec![], }], @@ -2072,7 +2072,7 @@ fn slash_in_old_span_does_not_deselect() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), ), reporters: vec![], }], @@ -2089,7 +2089,7 @@ fn slash_in_old_span_does_not_deselect() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), ), reporters: vec![], }], @@ -2113,13 +2113,13 @@ fn reporters_receive_their_slice() { // The reporters' reward is calculated from the total exposure. let initial_balance = 1125; - assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).total, initial_balance); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).total, initial_balance); on_offence_now( &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), ), reporters: vec![1, 2], }], @@ -2144,13 +2144,13 @@ fn subsequent_reports_in_same_span_pay_out_less() { // The reporters' reward is calculated from the total exposure. let initial_balance = 1125; - assert_eq!(Staking::eras_stakers(Staking::active_era(), 11).total, initial_balance); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).total, initial_balance); on_offence_now( &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), ), reporters: vec![1], }], @@ -2166,7 +2166,7 @@ fn subsequent_reports_in_same_span_pay_out_less() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), ), reporters: vec![1], }], @@ -2190,7 +2190,7 @@ fn invulnerables_are_not_slashed() { assert_eq!(Balances::free_balance(&11), 1000); assert_eq!(Balances::free_balance(&21), 2000); - let exposure = Staking::eras_stakers(Staking::active_era(), 21); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 21); let initial_balance = Staking::slashable_balance_of(&21); let nominator_balances: Vec<_> = exposure.others @@ -2199,11 +2199,11 @@ fn invulnerables_are_not_slashed() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), reporters: vec![], }, OffenceDetails { - offender: (21, Staking::eras_stakers(Staking::active_era(), 21)), + offender: (21, Staking::eras_stakers(Staking::active_era().unwrap(), 21)), reporters: vec![], }, ], @@ -2237,7 +2237,7 @@ fn dont_slash_if_fraction_is_zero() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era(), 11), + Staking::eras_stakers(Staking::active_era().unwrap(), 11), ), reporters: vec![], }], @@ -2258,7 +2258,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), reporters: vec![], }, ], @@ -2272,7 +2272,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), reporters: vec![], }, ], @@ -2285,7 +2285,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), reporters: vec![], }, ], @@ -2306,7 +2306,7 @@ fn garbage_collection_after_slashing() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), reporters: vec![], }, ], @@ -2320,7 +2320,7 @@ fn garbage_collection_after_slashing() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), reporters: vec![], }, ], @@ -2343,21 +2343,21 @@ fn garbage_collection_on_window_pruning() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = Staking::eras_stakers(Staking::active_era(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 11); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), reporters: vec![], }, ], &[Perbill::from_percent(10)], ); - let now = Staking::active_era(); + let now = Staking::active_era().unwrap(); assert_eq!(Balances::free_balance(&11), 900); assert_eq!(Balances::free_balance(&101), 2000 - (nominated_value / 10)); @@ -2391,8 +2391,8 @@ fn slashing_nominators_by_span_max() { assert_eq!(Staking::slashable_balance_of(&21), 1000); - let exposure_11 = Staking::eras_stakers(Staking::active_era(), 11); - let exposure_21 = Staking::eras_stakers(Staking::active_era(), 21); + let exposure_11 = Staking::eras_stakers(Staking::active_era().unwrap(), 11); + let exposure_21 = Staking::eras_stakers(Staking::active_era().unwrap(), 21); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value_11 = exposure_11.others.iter().find(|o| o.who == 101).unwrap().value; let nominated_value_21 = exposure_21.others.iter().find(|o| o.who == 101).unwrap().value; @@ -2400,7 +2400,7 @@ fn slashing_nominators_by_span_max() { on_offence_in_era( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), reporters: vec![], }, ], @@ -2434,7 +2434,7 @@ fn slashing_nominators_by_span_max() { on_offence_in_era( &[ OffenceDetails { - offender: (21, Staking::eras_stakers(Staking::active_era(), 21)), + offender: (21, Staking::eras_stakers(Staking::active_era().unwrap(), 21)), reporters: vec![], }, ], @@ -2457,7 +2457,7 @@ fn slashing_nominators_by_span_max() { on_offence_in_era( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), reporters: vec![], }, ], @@ -2493,7 +2493,7 @@ fn slashes_are_summed_across_spans() { on_offence_now( &[ OffenceDetails { - offender: (21, Staking::eras_stakers(Staking::active_era(), 21)), + offender: (21, Staking::eras_stakers(Staking::active_era().unwrap(), 21)), reporters: vec![], }, ], @@ -2518,7 +2518,7 @@ fn slashes_are_summed_across_spans() { on_offence_now( &[ OffenceDetails { - offender: (21, Staking::eras_stakers(Staking::active_era(), 21)), + offender: (21, Staking::eras_stakers(Staking::active_era().unwrap(), 21)), reporters: vec![], }, ], @@ -2543,14 +2543,14 @@ fn deferred_slashes_are_deferred() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = Staking::eras_stakers(Staking::active_era(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 11); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), reporters: vec![], }, ], @@ -2586,7 +2586,7 @@ fn remove_deferred() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = Staking::eras_stakers(Staking::active_era(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 11); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; @@ -2656,7 +2656,7 @@ fn remove_multi_deferred() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = Staking::eras_stakers(Staking::active_era(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 11); assert_eq!(Balances::free_balance(&101), 2000); on_offence_now( @@ -2672,7 +2672,7 @@ fn remove_multi_deferred() { on_offence_now( &[ OffenceDetails { - offender: (21, Staking::eras_stakers(Staking::active_era(), 21)), + offender: (21, Staking::eras_stakers(Staking::active_era().unwrap(), 21)), reporters: vec![], } ], @@ -2712,7 +2712,7 @@ fn slash_kicks_validators_not_nominators() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = Staking::eras_stakers(Staking::active_era(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 11); assert_eq!(Balances::free_balance(&101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; @@ -2788,7 +2788,7 @@ fn claim_reward_at_the_last_era() { start_era(crate::HISTORY_DEPTH); // This is the latest planned era in staking, not the active era - let current_era = Staking::current_era(); + let current_era = Staking::current_era().unwrap(); assert!(current_era - crate::HISTORY_DEPTH == 0); assert_ok!(Staking::payout_validator(Origin::signed(10), 0)); assert_ok!(Staking::payout_validator(Origin::signed(10), 1)); @@ -2897,14 +2897,14 @@ fn migration_v3() { crate::migration::inner::to_v3::(&mut 2); // Check migration - assert_eq!(::ActiveEraStart::get(), 777); - assert_eq!(::ErasStartSessionIndex::get(3), 5); + assert_eq!(::ActiveEraStart::get().unwrap(), 777); + assert_eq!(::ErasStartSessionIndex::get(3).unwrap(), 5); assert_eq!(::ErasRewardPoints::get(3), EraRewardPoints { total: 12, individual: vec![(21, 2), (31, 10)].into_iter().collect(), }); - assert_eq!(::ActiveEra::get(), 3); - assert_eq!(::CurrentEra::get(), 3); + assert_eq!(::ActiveEra::get().unwrap(), 3); + assert_eq!(::CurrentEra::get().unwrap(), 3); assert_eq!(::ErasStakers::get(3, 11), Exposure { total: 0, own: 0, @@ -2933,7 +2933,7 @@ fn zero_slash_keeps_nominators() { assert_eq!(Balances::free_balance(&11), 1000); - let exposure = Staking::eras_stakers(Staking::active_era(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 11); assert_eq!(Balances::free_balance(&101), 2000); on_offence_now( @@ -2971,7 +2971,7 @@ fn six_session_delay() { let val_set = Session::validators(); let init_session = Session::current_index(); - let init_active_era = Staking::active_era(); + let init_active_era = Staking::active_era().unwrap(); // pallet-session is delaying session by one, thus the next session to plan is +2. assert_eq!(>::new_session(init_session + 2), None); assert_eq!(>::new_session(init_session + 3), Some(val_set.clone())); @@ -2980,27 +2980,33 @@ fn six_session_delay() { assert_eq!(>::new_session(init_session + 6), Some(val_set.clone())); >::end_session(init_session); - assert_eq!(Staking::active_era(), init_active_era); + >::start_session(init_session + 1); + assert_eq!(Staking::active_era().unwrap(), init_active_era); >::end_session(init_session + 1); - assert_eq!(Staking::active_era(), init_active_era); + >::start_session(init_session + 2); + assert_eq!(Staking::active_era().unwrap(), init_active_era); // Reward current era Staking::reward_by_ids(vec![(11, 1)]); // New active era is triggered here. >::end_session(init_session + 2); - assert_eq!(Staking::active_era(), init_active_era + 1); + >::start_session(init_session + 3); + assert_eq!(Staking::active_era().unwrap(), init_active_era + 1); >::end_session(init_session + 3); - assert_eq!(Staking::active_era(), init_active_era + 1); + >::start_session(init_session + 4); + assert_eq!(Staking::active_era().unwrap(), init_active_era + 1); >::end_session(init_session + 4); - assert_eq!(Staking::active_era(), init_active_era + 1); + >::start_session(init_session + 5); + assert_eq!(Staking::active_era().unwrap(), init_active_era + 1); // Reward current era Staking::reward_by_ids(vec![(21, 2)]); // New active era is triggered here. >::end_session(init_session + 5); - assert_eq!(Staking::active_era(), init_active_era + 2); + >::start_session(init_session + 6); + assert_eq!(Staking::active_era().unwrap(), init_active_era + 2); // That reward are correct assert_eq!(Staking::eras_reward_points(init_active_era).total, 1); From 2519aefb806ae4eb091a940b904252f064744b3f Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 31 Jan 2020 16:04:01 +0100 Subject: [PATCH 43/75] remove print --- frame/staking/src/lib.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 1129a1b33b3cf..191790848cf49 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1542,8 +1542,7 @@ impl Module { ), RewardDestination::Stash => T::Currency::deposit_into_existing(stash, amount).ok(), - RewardDestination::Staked => { - Self::bonded(stash) + RewardDestination::Staked => Self::bonded(stash) .and_then(|c| Self::ledger(&c).map(|l| (c, l))) .and_then(|(controller, mut l)| { l.active += amount; @@ -1551,7 +1550,7 @@ impl Module { let r = T::Currency::deposit_into_existing(stash, amount).ok(); Self::update_ledger(&controller, &l); r - })}, + }), } } @@ -1576,7 +1575,6 @@ impl Module { Self::new_era(session_index) } else { - println!("initial era!!"); // Set initial era Self::new_era(session_index) } @@ -1889,7 +1887,6 @@ impl Module { /// some session can lag in between the newest session planned and the latest session started. impl pallet_session::SessionManager for Module { fn new_session(new_index: SessionIndex) -> Option> { - println!("New session at: {}", new_index); Self::ensure_storage_upgraded(); Self::new_session(new_index) } From e881addba93e86cfeea0186bd480450810b6b364 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 31 Jan 2020 16:08:42 +0100 Subject: [PATCH 44/75] update doc --- frame/staking/src/lib.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 191790848cf49..fea0cd62b4c15 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1554,7 +1554,7 @@ impl Module { } } - /// New session. Provide the validator set for if it's a new era. + /// Plan a new session potentially trigger a new era. fn new_session(session_index: SessionIndex) -> Option> { if let Some(current_era) = Self::current_era() { let current_era_start_session_index = Self::eras_start_session_index(current_era) @@ -1580,6 +1580,7 @@ impl Module { } } + /// Start a session potentially starting an era. fn start_session(start_session: SessionIndex) { let next_active_era = Self::active_era().map(|e| e + 1).unwrap_or(0); if let Some(next_active_era_start_session_index) = Self::eras_start_session_index(next_active_era) { @@ -1589,6 +1590,7 @@ impl Module { } } + /// End a session potentially ending an era. fn end_session(session_index: SessionIndex) { if let Some(active_era) = Self::active_era() { let next_active_era_start_session_index = Self::eras_start_session_index(active_era + 1) @@ -1603,6 +1605,7 @@ impl Module { } } + /// Increment `ActiveEra` and reset `ActiveEraStart` fn start_era(_start_session: SessionIndex) { ActiveEra::mutate(|s| { *s = Some(s.map(|s| s + 1).unwrap_or(0)); @@ -1613,6 +1616,7 @@ impl Module { } + /// Compute payout for era. fn end_era(active_era: EraIndex, _session_index: SessionIndex) { // Note: active_era_start can be None if end era is called during genesis config. if let Some(active_era_start) = Self::active_era_start() { @@ -1627,15 +1631,12 @@ impl Module { era_duration.saturated_into::(), ); - // Set previous era reward. + // Set ending era reward. >::insert(&active_era, total_payout); } } - /// The era has changed - enact new staking set. - /// - /// NOTE: This always happens immediately before a session change to ensure that new validators - /// get a chance to set their session keys. + /// Plan a new era. Return the potential new staking set. fn new_era(start_session_index: SessionIndex) -> Option> { // Increment or set current era. let current_era = CurrentEra::mutate(|s| { From 1f7b3530d4a2ca029ff9020c353de0e9e32af2e9 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 31 Jan 2020 16:17:37 +0100 Subject: [PATCH 45/75] refactor --- frame/staking/src/lib.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index fea0cd62b4c15..1833a9de5c0dd 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1995,11 +1995,13 @@ impl OnOffenceHandler Date: Sat, 1 Feb 2020 13:42:28 +0100 Subject: [PATCH 46/75] improve documentation and implementation --- frame/staking/src/lib.rs | 70 ++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 1833a9de5c0dd..e2604b465afe5 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -610,8 +610,10 @@ pub trait Trait: frame_system::Trait { /// The staking balance. type Currency: LockableCurrency; - /// Time used for computing era duration. It is guaranteed to start being called from the - /// first `on_finalize`. Thus value can be wrong at genesis. + /// Time used for computing era duration. + /// + /// It is guaranteed to start being called from the first `on_finalize`. Thus value at genesis + /// is not used. type Time: Time; /// Convert a balance into a number used for election calculation. @@ -685,6 +687,7 @@ decl_storage! { /// The ideal number of staking participants. pub ValidatorCount get(fn validator_count) config(): u32; + /// Minimum number of staking participants before emergency conditions are imposed. pub MinimumValidatorCount get(fn minimum_validator_count) config(): u32 = DEFAULT_MINIMUM_VALIDATOR_COUNT; @@ -696,6 +699,7 @@ decl_storage! { /// Map from all locked "stash" accounts to the controller account. pub Bonded get(fn bonded): map hasher(blake2_256) T::AccountId => Option; + /// Map from all (unlocked) "controller" accounts to the info regarding the staking. pub Ledger get(fn ledger): map hasher(blake2_256) T::AccountId @@ -722,20 +726,23 @@ decl_storage! { pub CurrentEra get(fn current_era): Option; /// The active era index, the era currently rewarded. + /// + /// Validator set of this era must be equal to `SessionInterface::validators`. pub ActiveEra get(fn active_era): Option; - /// The start of the currently rewarded era. + /// The start of the active era. pub ActiveEraStart get(fn active_era_start): Option>; - /// The session index at which the era started for the last `HISTORY_DEPTH` eras + /// The session index at which the era start for the last `HISTORY_DEPTH` eras pub ErasStartSessionIndex get(fn eras_start_session_index): map hasher(blake2_256) EraIndex => Option; /// Exposure of validator at era. /// - /// This is keyed fist by the era index to allow bulk deletion and then the stash account. + /// This is keyed first by the era index to allow bulk deletion and then the stash account. /// /// Is it removed after `HISTORY_DEPTH` eras. + // If stakers hasn't been set or has been removed then empty exposure is returned. pub ErasStakers get(fn eras_stakers): double_map hasher(twox_64_concat) EraIndex, hasher(twox_64_concat) T::AccountId => Exposure>; @@ -744,11 +751,12 @@ decl_storage! { /// /// This is similar to [`ErasStakers`] but number of nominators exposed is reduce to the /// `T::MaxNominatorRewardedPerValidator` biggest stakers. - /// This used to limit the i/o cost for the nominator payout. + /// This is used to limit the i/o cost for the nominator payout. /// /// This is keyed fist by the era index to allow bulk deletion and then the stash account. /// /// Is it removed after `HISTORY_DEPTH` eras. + // If stakers hasn't been set or has been removed then empty exposure is returned. pub ErasStakersClipped get(fn eras_stakers_clipped): double_map hasher(twox_64_concat) EraIndex, hasher(twox_64_concat) T::AccountId => Exposure>; @@ -758,6 +766,7 @@ decl_storage! { /// This is keyed fist by the era index to allow bulk deletion and then the stash account. /// /// Is it removed after `HISTORY_DEPTH` eras. + // If prefs hasn't been set or has been removed then 0 commission is returned. pub ErasValidatorPrefs get(fn eras_validator_prefs): double_map hasher(twox_64_concat) EraIndex, hasher(twox_64_concat) T::AccountId => ValidatorPrefs; @@ -769,10 +778,12 @@ decl_storage! { map hasher(blake2_256) EraIndex => BalanceOf; /// Rewards for the last `HISTORY_DEPTH` eras. + // If reward hasn't been set or has been removed then 0 reward is returned. pub ErasRewardPoints get(fn eras_reward_points): map hasher(blake2_256) EraIndex => EraRewardPoints; /// The total amount staked for the last `HISTORY_DEPTH` eras. + // If total hasn't been set or has been removed then 0 stake is returned. pub ErasTotalStake get(fn eras_total_stake): map hasher(blake2_256) EraIndex => BalanceOf; @@ -1076,6 +1087,7 @@ decl_module! { ledger.active = Zero::zero(); } + // Note: in case there is no current era it is fine to bond one era more. let era = Self::current_era().unwrap_or(0) + T::BondingDuration::get(); ledger.unlocking.push(UnlockChunk { value, era }); Self::update_ledger(&controller, &ledger); @@ -1101,8 +1113,10 @@ decl_module! { #[weight = SimpleDispatchInfo::FixedNormal(400_000)] fn withdraw_unbonded(origin) { let controller = ensure_signed(origin)?; - let ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; - let ledger = ledger.consolidate_unlocked(Self::current_era().unwrap_or(0)); + let mut ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + if let Some(current_era) = Self::current_era() { + ledger = ledger.consolidate_unlocked(current_era) + } if ledger.unlocking.is_empty() && ledger.active.is_zero() { // This account must have called `unbond()` with some value that caused the active @@ -1167,6 +1181,7 @@ decl_module! { let nominations = Nominations { targets, + // initial nominations are considered submitted at era 0. See `Nominations` doc submitted_in: Self::current_era().unwrap_or(0), suppressed: false, }; @@ -1430,6 +1445,9 @@ impl Module { let mut reward = Perbill::zero(); let era_reward_points = >::get(&era); + + // Note: iterator take only `MAX_NOMINATIONS` to avoid querying more validator exposure + // than necessary. Anyway a nominator can't validate more than `MAX_NOMINATIONS`. for validator in validators.into_iter().take(MAX_NOMINATIONS) { let commission = Self::eras_validator_prefs(&era, &validator).commission; let validator_exposure = >::get(&era, &validator); @@ -1457,7 +1475,7 @@ impl Module { } } - // This is zero if the era is not finished yet. + // Note: this is zero if the era is not finished yet. let era_payout = >::get(&era); if let Some(imbalance) = Self::make_payout(&nominator_ledger.stash, reward * era_payout) { Self::deposit_event(RawEvent::Reward(who, imbalance.peek())); @@ -1495,6 +1513,7 @@ impl Module { Perbill::one().saturating_sub(commission).saturating_mul(exposure_part) ) ); + // This is zero if the era is not finished yet. let era_payout = >::get(&era); if let Some(imbalance) = Self::make_payout(&ledger.stash, reward * era_payout) { @@ -1557,6 +1576,8 @@ impl Module { /// Plan a new session potentially trigger a new era. fn new_session(session_index: SessionIndex) -> Option> { if let Some(current_era) = Self::current_era() { + // Initial era has been set. + let current_era_start_session_index = Self::eras_start_session_index(current_era) .unwrap_or_else(|| { frame_support::print("Error: start_session_index must be set for current_era"); @@ -1646,13 +1667,14 @@ impl Module { ErasStartSessionIndex::insert(¤t_era, &start_session_index); // Clean old era information. - if let Some(era) = current_era.checked_sub(HISTORY_DEPTH) { - >::remove_prefix(era); - >::remove_prefix(era); - >::remove(era); - >::remove(era); - >::remove(era); - ErasStartSessionIndex::remove(era); + if let Some(old_era) = current_era.checked_sub(HISTORY_DEPTH) { + >::remove_prefix(old_era); + >::remove_prefix(old_era); + >::remove_prefix(old_era); + >::remove(old_era); + >::remove(old_era); + >::remove(old_era); + ErasStartSessionIndex::remove(old_era); } let bonding_duration = T::BondingDuration::get(); @@ -1679,7 +1701,7 @@ impl Module { } }); - // Reassign all ErasStakers. + // Set staking information for new era. let maybe_new_validators = Self::select_validators(current_era); Self::apply_unapplied_slashes(current_era); @@ -1702,7 +1724,8 @@ impl Module { }) } - /// Select a new validator set from the assembled stakers and their role preferences. + /// Select a new validator set from the assembled stakers and their role preferences, and store + /// staking information for the new current era. /// /// Fill the storages `ErasStakers`, `ErasStakersClipped`, `ErasValidatorPrefs` and /// `ErasTotalStake` for current era. @@ -1760,7 +1783,7 @@ impl Module { Self::slashable_balance_of, ); - // Populate ErasStakers and figure out the total stake. + // Populate stakers information and figure out the total stake. let mut total_staked = BalanceOf::::zero(); for (c, s) in supports.into_iter() { // build `struct exposure` from `support` @@ -1803,13 +1826,12 @@ impl Module { >::insert(¤t_era, &c, exposure_clipped); } - // Insert current era informations + // Insert current era staking informations >::insert(¤t_era, total_staked); let default_pref = ValidatorPrefs::default(); for stash in &elected_stashes { let pref = all_validators_and_prefs.get(stash) - // This should always succeed but better to be safe - .unwrap_or(&default_pref); + .unwrap_or(&default_pref); // Must never happen, but better to be safe. >::insert(¤t_era, stash, pref); } @@ -1959,8 +1981,8 @@ impl Convert> for StashOf { /// A typed conversion from stash account ID to the active exposure of nominators /// on that account. /// -/// Active exposure is the exposure of the validator set currently validating. It can differ from -/// the latest planned exposure. +/// Active exposure is the exposure of the validator set currently validating, i.e. in +/// `active_era`. It can differ from the latest planned exposure in `current_era`. pub struct ExposureOf(sp_std::marker::PhantomData); impl Convert>>> From 5162c0b45f89fb6d489d6776b43f041400e1ba6f Mon Sep 17 00:00:00 2001 From: thiolliere Date: Sat, 1 Feb 2020 13:44:11 +0100 Subject: [PATCH 47/75] fix test --- frame/im-online/src/mock.rs | 1 + frame/session/src/mock.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/frame/im-online/src/mock.rs b/frame/im-online/src/mock.rs index 5c428c38582ff..e741ec3198049 100644 --- a/frame/im-online/src/mock.rs +++ b/frame/im-online/src/mock.rs @@ -49,6 +49,7 @@ impl pallet_session::SessionManager for TestSessionManager { VALIDATORS.with(|l| l.borrow_mut().take()) } fn end_session(_: SessionIndex) {} + fn start_session(_: SessionIndex) {} } impl pallet_session::historical::SessionManager for TestSessionManager { diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs index ff84743a61596..71e79f526c08d 100644 --- a/frame/session/src/mock.rs +++ b/frame/session/src/mock.rs @@ -91,6 +91,7 @@ impl SessionHandler for TestSessionHandler { pub struct TestSessionManager; impl SessionManager for TestSessionManager { fn end_session(_: SessionIndex) {} + fn start_session(_: SessionIndex) {} fn new_session(_: SessionIndex) -> Option> { if !TEST_SESSION_CHANGED.with(|l| *l.borrow()) { VALIDATORS.with(|v| { From 9cd88e2fba7364d1a02260a4f9efa2020775f48e Mon Sep 17 00:00:00 2001 From: thiolliere Date: Sat, 1 Feb 2020 13:55:10 +0100 Subject: [PATCH 48/75] Fix test --- frame/session/src/mock.rs | 1 + frame/staking/src/tests.rs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs index 71e79f526c08d..b717acad1cc06 100644 --- a/frame/session/src/mock.rs +++ b/frame/session/src/mock.rs @@ -112,6 +112,7 @@ impl SessionManager for TestSessionManager { #[cfg(feature = "historical")] impl crate::historical::SessionManager for TestSessionManager { fn end_session(_: SessionIndex) {} + fn start_session(_: SessionIndex) {} fn new_session(new_index: SessionIndex) -> Option> { diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 694ba2b621226..793b1c95ec840 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2891,6 +2891,7 @@ fn migration_v3() { individual: vec![2, 10], }); ::ErasStakers::remove_all(); + ::ErasStakersClipped::remove_all(); ::StorageVersion::put(2); // Perform migration. @@ -2920,6 +2921,21 @@ fn migration_v3() { own: 30, others: vec![], }); + assert_eq!(::ErasStakersClipped::get(3, 11), Exposure { + total: 0, + own: 0, + others: vec![], + }); + assert_eq!(::ErasStakersClipped::get(3, 21), Exposure { + total: 20, + own: 20, + others: vec![], + }); + assert_eq!(::ErasStakersClipped::get(3, 31), Exposure { + total: 30, + own: 30, + others: vec![], + }); assert_eq!(::ErasValidatorPrefs::get(3, 21), Staking::validators(21)); assert_eq!(::ErasValidatorPrefs::get(3, 31), Staking::validators(31)); assert_eq!(::ErasTotalStake::get(3), 50); From 68105c83a5d07da5f086a96359c54e966b7b8fdf Mon Sep 17 00:00:00 2001 From: thiolliere Date: Sat, 1 Feb 2020 14:06:03 +0100 Subject: [PATCH 49/75] fix test --- frame/im-online/src/mock.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/frame/im-online/src/mock.rs b/frame/im-online/src/mock.rs index e741ec3198049..69518622d215b 100644 --- a/frame/im-online/src/mock.rs +++ b/frame/im-online/src/mock.rs @@ -63,6 +63,7 @@ impl pallet_session::historical::SessionManager for TestSessionManager ) } fn end_session(_: SessionIndex) {} + fn start_session(_: SessionIndex) {} } /// An extrinsic type used for tests. From 827847ba076905915eb24f62b518b234a2854c61 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Sat, 1 Feb 2020 14:58:45 +0100 Subject: [PATCH 50/75] fix test --- bin/node/cli/src/chain_spec.rs | 1 - bin/node/testing/src/genesis.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/bin/node/cli/src/chain_spec.rs b/bin/node/cli/src/chain_spec.rs index b8ff948b01b24..4643826be183d 100644 --- a/bin/node/cli/src/chain_spec.rs +++ b/bin/node/cli/src/chain_spec.rs @@ -250,7 +250,6 @@ pub fn testnet_genesis( }).collect::>(), }), pallet_staking: Some(StakingConfig { - current_era: 0, validator_count: initial_authorities.len() as u32 * 2, minimum_validator_count: initial_authorities.len() as u32, stakers: initial_authorities.iter().map(|x| { diff --git a/bin/node/testing/src/genesis.rs b/bin/node/testing/src/genesis.rs index 183515f27274b..034a7a32d1b25 100644 --- a/bin/node/testing/src/genesis.rs +++ b/bin/node/testing/src/genesis.rs @@ -68,7 +68,6 @@ pub fn config(support_changes_trie: bool, code: Option<&[u8]>) -> GenesisConfig ] }), pallet_staking: Some(StakingConfig { - current_era: 0, stakers: vec![ (dave(), alice(), 111 * DOLLARS, pallet_staking::StakerStatus::Validator), (eve(), bob(), 100 * DOLLARS, pallet_staking::StakerStatus::Validator), From e2af768e249fe807c8fb7989bfa7cff3f8bc0d79 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 3 Feb 2020 14:29:58 +0100 Subject: [PATCH 51/75] fix remove lowest stake from exposure, not biggest. --- frame/staking/src/lib.rs | 3 ++- frame/staking/src/migration.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index e2604b465afe5..3b01b48e2440b 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1356,6 +1356,7 @@ decl_module! { /// then it indicates an instruction to skip the payout of all previous eras. /// - `validators` is the list of all validators that `who` had exposure to during `era`. /// If it is incomplete, then less than the full reward will be paid out. + /// It must not exceed `MAX_NOMINATIONS`. /// /// WARNING: once an era is payed for a validator such validator can't claim the payout of /// previous era. @@ -1819,7 +1820,7 @@ impl Module { let mut exposure_clipped = exposure; let clipped_max_len = T::MaxNominatorRewardedPerValidator::get() as usize; if exposure_clipped.others.len() > clipped_max_len { - exposure_clipped.others.sort_unstable_by(|a, b| a.value.cmp(&b.value)); + exposure_clipped.others.sort_unstable_by(|a, b| a.value.cmp(&b.value).reverse()); exposure_clipped.others.truncate(clipped_max_len); exposure_clipped.others.sort_unstable_by(|a, b| a.who.cmp(&b.who)); } diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs index f872c0c919fc6..0f5e44846e19d 100644 --- a/frame/staking/src/migration.rs +++ b/frame/staking/src/migration.rs @@ -171,7 +171,7 @@ pub mod inner { let mut exposure_clipped = exposure; let clipped_max_len = T::MaxNominatorRewardedPerValidator::get() as usize; if exposure_clipped.others.len() > clipped_max_len { - exposure_clipped.others.sort_unstable_by(|a, b| a.value.cmp(&b.value)); + exposure_clipped.others.sort_unstable_by(|a, b| a.value.cmp(&b.value).reverse()); exposure_clipped.others.truncate(clipped_max_len); exposure_clipped.others.sort_unstable_by(|a, b| a.who.cmp(&b.who)); } From ea4ef674b2954c80e80e45e6e593e595eaa4abee Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 3 Feb 2020 14:32:42 +0100 Subject: [PATCH 52/75] nomination index arguments in nominator_payout --- frame/staking/src/lib.rs | 19 ++++++++++--------- frame/staking/src/migration.rs | 4 +--- frame/staking/src/mock.rs | 22 ++++++++++++---------- frame/staking/src/tests.rs | 10 +++++----- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 3b01b48e2440b..5f555be4635b9 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -539,7 +539,7 @@ pub struct Exposure { /// The validator's own stash that is exposed. #[codec(compact)] pub own: Balance, - /// The portions of nominators stashes that are exposed. Sorted by AccountId. + /// The portions of nominators stashes that are exposed. pub others: Vec>, } @@ -1373,7 +1373,7 @@ decl_module! { /// bounded only economically (all nominators are required to place a minimum stake). /// # #[weight = SimpleDispatchInfo::FixedNormal(500_000)] - fn payout_nominator(origin, era: EraIndex, validators: Vec) + fn payout_nominator(origin, era: EraIndex, validators: Vec<(T::AccountId, u32)>) -> DispatchResult { let who = ensure_signed(origin)?; @@ -1433,7 +1433,7 @@ impl Module { // MUTABLES (DANGEROUS) - fn do_payout_nominator(who: T::AccountId, era: EraIndex, validators: Vec) + fn do_payout_nominator(who: T::AccountId, era: EraIndex, validators: Vec<(T::AccountId, u32)>) -> DispatchResult { let mut nominator_ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; @@ -1449,14 +1449,17 @@ impl Module { // Note: iterator take only `MAX_NOMINATIONS` to avoid querying more validator exposure // than necessary. Anyway a nominator can't validate more than `MAX_NOMINATIONS`. - for validator in validators.into_iter().take(MAX_NOMINATIONS) { + for (validator, nominator_index) in validators.into_iter().take(MAX_NOMINATIONS) { let commission = Self::eras_validator_prefs(&era, &validator).commission; let validator_exposure = >::get(&era, &validator); - if let Ok(nominator_exposure) = validator_exposure.others - .binary_search_by(|exposure| exposure.who.cmp(&nominator_ledger.stash)) - .map(|indice| &validator_exposure.others[indice]) + if let Some(nominator_exposure) = validator_exposure.others + .get(nominator_index as usize) { + if nominator_exposure.who != nominator_ledger.stash { + continue; + } + let nominator_exposure_part = Perbill::from_rational_approximation( nominator_exposure.value, validator_exposure.total, @@ -1805,7 +1808,6 @@ impl Module { total_staked = total_staked.saturating_add(total); - others.sort_unstable_by(|a, b| a.who.cmp(&b.who)); let exposure = Exposure { own, others, @@ -1822,7 +1824,6 @@ impl Module { if exposure_clipped.others.len() > clipped_max_len { exposure_clipped.others.sort_unstable_by(|a, b| a.value.cmp(&b.value).reverse()); exposure_clipped.others.truncate(clipped_max_len); - exposure_clipped.others.sort_unstable_by(|a, b| a.who.cmp(&b.who)); } >::insert(¤t_era, &c, exposure_clipped); } diff --git a/frame/staking/src/migration.rs b/frame/staking/src/migration.rs index 0f5e44846e19d..180eeb436399a 100644 --- a/frame/staking/src/migration.rs +++ b/frame/staking/src/migration.rs @@ -163,9 +163,8 @@ pub mod inner { let current_elected = as Store>::CurrentElected::get(); let mut current_total_stake = >::zero(); for validator in ¤t_elected { - let mut exposure = as Store>::Stakers::get(validator); + let exposure = as Store>::Stakers::get(validator); current_total_stake += exposure.total; - exposure.others.sort_unstable_by(|a, b| a.who.cmp(&b.who)); as Store>::ErasStakers::insert(current_era, validator, &exposure); let mut exposure_clipped = exposure; @@ -173,7 +172,6 @@ pub mod inner { if exposure_clipped.others.len() > clipped_max_len { exposure_clipped.others.sort_unstable_by(|a, b| a.value.cmp(&b.value).reverse()); exposure_clipped.others.truncate(clipped_max_len); - exposure_clipped.others.sort_unstable_by(|a, b| a.who.cmp(&b.who)); } as Store>::ErasStakersClipped::insert(current_era, validator, exposure_clipped); diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 176345bb14e79..3e01553ebfdd8 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -16,7 +16,7 @@ //! Test utilities -use std::{collections::HashSet, cell::RefCell}; +use std::{collections::{HashSet, HashMap}, cell::RefCell}; use sp_runtime::{Perbill, KeyTypeId}; use sp_runtime::curve::PiecewiseLinear; use sp_runtime::traits::{IdentityLookup, Convert, OpaqueKeys, OnInitialize, OnFinalize, SaturatedConversion}; @@ -390,9 +390,6 @@ pub fn check_exposure(expo: Exposure) { expo.total as u128, expo.own as u128 + expo.others.iter().map(|e| e.value as u128).sum::(), "wrong total exposure {:?}", expo, ); - let mut sorted = expo.others.clone(); - sorted.sort_by_key(|e| e.who); - assert_eq!(sorted, expo.others); } /// Check that for each nominator: slashable_balance > sum(used_balance) @@ -520,17 +517,22 @@ pub fn make_all_reward_payment(era: EraIndex) { .collect::>(); // reward nominators - let mut nominator_controllers = HashSet::new(); - for exposure in ErasStakers::::iter_prefix(era) { - for controller in exposure.others.iter().filter_map(|other| Staking::bonded(other.who)) { - nominator_controllers.insert(controller); + let mut nominator_controllers = HashMap::new(); + for validator in Staking::eras_reward_points(era).individual.keys() { + let validator_exposure = Staking::eras_stakers_clipped(era, validator); + for (nom_index, nom) in validator_exposure.others.iter().enumerate() { + if let Some(nom_ctrl) = Staking::bonded(nom.who) { + nominator_controllers.entry(nom_ctrl) + .or_insert(vec![]) + .push((validator.clone(), nom_index as u32)); + } } } - for nominator_controller in nominator_controllers { + for (nominator_controller, validators_with_nom_index) in nominator_controllers { assert_ok!(Staking::payout_nominator( Origin::signed(nominator_controller), era, - validators_with_reward.clone() + validators_with_nom_index, )); } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 793b1c95ec840..252c70d8bb246 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -475,8 +475,8 @@ fn nominating_and_rewards_should_work() { total: 1000 + 800, own: 1000, others: vec![ - IndividualExposure { who: 1, value: 400 }, IndividualExposure { who: 3, value: 400 }, + IndividualExposure { who: 1, value: 400 }, ] }, ); @@ -486,8 +486,8 @@ fn nominating_and_rewards_should_work() { total: 1000 + 1200, own: 1000, others: vec![ - IndividualExposure { who: 1, value: 600 }, IndividualExposure { who: 3, value: 600 }, + IndividualExposure { who: 1, value: 600 }, ] }, ); @@ -2793,9 +2793,9 @@ fn claim_reward_at_the_last_era() { assert_ok!(Staking::payout_validator(Origin::signed(10), 0)); assert_ok!(Staking::payout_validator(Origin::signed(10), 1)); assert_ok!(Staking::payout_validator(Origin::signed(10), 2)); - assert_ok!(Staking::payout_nominator(Origin::signed(100), 0, vec![11])); - assert_ok!(Staking::payout_nominator(Origin::signed(100), 1, vec![11])); - assert_ok!(Staking::payout_nominator(Origin::signed(100), 2, vec![11])); + assert_ok!(Staking::payout_nominator(Origin::signed(100), 0, vec![(11, 0)])); + assert_ok!(Staking::payout_nominator(Origin::signed(100), 1, vec![(11, 0)])); + assert_ok!(Staking::payout_nominator(Origin::signed(100), 2, vec![(11, 0)])); // Era 0 can't be rewarded anymore, only era 1 and 2 can be rewarded From 74a4cbe330ddb0d8b33124b4ff510cdc91c06dab Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 3 Feb 2020 14:33:16 +0100 Subject: [PATCH 53/75] add test --- frame/staking/src/tests.rs | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 252c70d8bb246..5f086f0c8cd88 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -3029,3 +3029,52 @@ fn six_session_delay() { assert_eq!(Staking::eras_reward_points(init_active_era + 1).total, 2); }); } + +#[test] +fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward() { + // Test: + // * If nominator nomination is below the $MaxNominatorRewardedPerValidator other nominator + // then the nominator can't claim its reward + // * A nominator can't claim another nominator reward + ExtBuilder::default().build().execute_with(|| { + for i in 0..=::MaxNominatorRewardedPerValidator::get() { + let stash = 10_000 + i as u64; + let controller = 20_000 + i as u64; + let balance = 10_000 + i as u64; + Balances::make_free_balance_be(&stash, balance); + assert_ok!( + Staking::bond( + Origin::signed(stash), + controller, + balance, + RewardDestination::Stash + ) + ); + assert_ok!(Staking::nominate(Origin::signed(controller), vec![11])); + } + mock::start_era(1); + + >::reward_by_ids(vec![(11, 1)]); + // Compute total payout now for whole duration as other parameter won't change + let total_payout_0 = current_total_payout_for_duration(3 * 1000); + assert!(total_payout_0 > 100); // Test is meaningful if reward something + + mock::start_era(2); + mock::make_all_reward_payment(1); + + // nominator 10_000 can't get its reward because exposure is clipped. However it will try + // to query other people reward. + assert_ok!(Staking::payout_nominator(Origin::signed(20_000), 1, vec![(11, 0)])); + + // Assert only nominators from 1 to Max are rewarded + for i in 0..=::MaxNominatorRewardedPerValidator::get() { + let stash = 10_000 + i as u64; + let balance = 10_000 + i as u64; + if stash == 10_000 { + assert!(Balances::free_balance(&stash) == balance); + } else { + assert!(Balances::free_balance(&stash) > balance); + } + } + }); +} From faaddec974a6d64b050f4e80b3393271d3e1e453 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 3 Feb 2020 16:07:28 +0100 Subject: [PATCH 54/75] try to fix offence --- frame/staking/src/lib.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index c043db8e555dd..d937bdee1f8dc 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -2019,23 +2019,30 @@ impl OnOffenceHandler= current_era_start_session_index { - current_era + let window_start = current_era.saturating_sub(T::BondingDuration::get()); + + // fast path for active-era report - most likely. + // `slash_session` cannot be in a future active era. It must be in `active_era` or before. + let slash_era = if slash_session >= active_era_start_session_index { + active_era } else { let eras = BondedEras::get(); From 20b28b3d1f3ec176b1264176c0a2645f081f9e59 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 3 Feb 2020 16:47:34 +0100 Subject: [PATCH 55/75] apply slashed and bond eras until active era --- frame/staking/src/lib.rs | 75 ++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index d937bdee1f8dc..c57aff7484be0 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -805,6 +805,9 @@ decl_storage! { map hasher(blake2_256) EraIndex => Vec>>; /// A mapping from still-bonded eras to the first session index of that era. + /// + /// Must contains information for eras for the range: + /// `[active_era - bounding_duration; active_era]` BondedEras: Vec<(EraIndex, SessionIndex)>; /// All slashing events on validators, mapped by era to the highest slash proportion @@ -1631,14 +1634,40 @@ impl Module { } /// Increment `ActiveEra` and reset `ActiveEraStart` - fn start_era(_start_session: SessionIndex) { - ActiveEra::mutate(|s| { + fn start_era(start_session: SessionIndex) { + let active_era = ActiveEra::mutate(|s| { *s = Some(s.map(|s| s + 1).unwrap_or(0)); + s.unwrap() }); // Set new active era start in next `on_finalize`. To guarantee usage of `Time::now`. >::kill(); + let bonding_duration = T::BondingDuration::get(); + + BondedEras::mutate(|bonded| { + bonded.push((active_era, start_session)); + + if active_era > bonding_duration { + let first_kept = active_era - bonding_duration; + + // prune out everything that's from before the first-kept index. + let n_to_prune = bonded.iter() + .take_while(|&&(era_idx, _)| era_idx < first_kept) + .count(); + + // kill slashing metadata. + for (pruned_era, _) in bonded.drain(..n_to_prune) { + slashing::clear_era_metadata::(pruned_era); + } + + if let Some(&(_, first_session)) = bonded.first() { + T::SessionInterface::prune_historical_up_to(first_session); + } + } + }); + + Self::apply_unapplied_slashes(active_era); } /// Compute payout for era. @@ -1681,42 +1710,17 @@ impl Module { ErasStartSessionIndex::remove(old_era); } - let bonding_duration = T::BondingDuration::get(); - - BondedEras::mutate(|bonded| { - bonded.push((current_era, start_session_index)); - - if current_era > bonding_duration { - let first_kept = current_era - bonding_duration; - - // prune out everything that's from before the first-kept index. - let n_to_prune = bonded.iter() - .take_while(|&&(era_idx, _)| era_idx < first_kept) - .count(); - - // kill slashing metadata. - for (pruned_era, _) in bonded.drain(..n_to_prune) { - slashing::clear_era_metadata::(pruned_era); - } - - if let Some(&(_, first_session)) = bonded.first() { - T::SessionInterface::prune_historical_up_to(first_session); - } - } - }); - // Set staking information for new era. let maybe_new_validators = Self::select_validators(current_era); - Self::apply_unapplied_slashes(current_era); maybe_new_validators } /// Apply previously-unapplied slashes on the beginning of a new era, after a delay. - fn apply_unapplied_slashes(current_era: EraIndex) { + fn apply_unapplied_slashes(active_era: EraIndex) { let slash_defer_duration = T::SlashDeferDuration::get(); ::EarliestUnappliedSlash::mutate(|earliest| if let Some(ref mut earliest) = earliest { - let keep_from = current_era.saturating_sub(slash_defer_duration); + let keep_from = active_era.saturating_sub(slash_defer_duration); for era in (*earliest)..keep_from { let era_slashes = ::UnappliedSlashes::take(&era); for slash in era_slashes { @@ -2026,18 +2030,13 @@ impl OnOffenceHandler OnOffenceHandler::EarliestUnappliedSlash::mutate(|earliest| { if earliest.is_none() { - *earliest = Some(current_era) + *earliest = Some(active_era) } }); @@ -2076,7 +2075,7 @@ impl OnOffenceHandler OnOffenceHandler::UnappliedSlashes::mutate( - current_era, + active_era, move |for_later| for_later.push(unapplied), ); } From 7dd7975f2ceece389443ae8f52929f43ce3e8e4d Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 3 Feb 2020 16:49:48 +0100 Subject: [PATCH 56/75] doc --- frame/staking/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index c57aff7484be0..6642f348c4736 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1633,7 +1633,7 @@ impl Module { } } - /// Increment `ActiveEra` and reset `ActiveEraStart` + /// Increment `ActiveEra`, reset `ActiveEraStart`, update `BondedEras` and apply slashes. fn start_era(start_session: SessionIndex) { let active_era = ActiveEra::mutate(|s| { *s = Some(s.map(|s| s + 1).unwrap_or(0)); From a89202ee3c64217c906bfc3a26dc275ff2a00080 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 3 Feb 2020 16:50:13 +0100 Subject: [PATCH 57/75] update spec version --- bin/node/runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 3e7b9c6d83e90..36d8f5ce41cfd 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -79,7 +79,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 212, + spec_version: 213, impl_version: 0, apis: RUNTIME_API_VERSIONS, }; From c87a3d686e7cc519d5463d694a6c3d44a347a00a Mon Sep 17 00:00:00 2001 From: thiolliere Date: Wed, 19 Feb 2020 17:52:10 +0900 Subject: [PATCH 58/75] add test upgrade from previous test environment --- frame/staking/src/tests.rs | 116 ++++++++++++++++++ .../tests/test_upgrade_from_master_dataset.rs | 59 +++++++++ 2 files changed, 175 insertions(+) create mode 100644 frame/staking/src/tests/test_upgrade_from_master_dataset.rs diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 546589115cd46..0759153ec2df3 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -16,6 +16,8 @@ //! Tests for the module. +mod test_upgrade_from_master_dataset; + use super::*; use mock::*; use sp_runtime::{assert_eq_error_rate, traits::{OnInitialize, BadOrigin}}; @@ -26,6 +28,7 @@ use frame_support::{ dispatch::DispatchError, StorageMap, }; use substrate_test_utils::assert_eq_uvec; +use crate::Store; #[test] fn force_unstake_works() { @@ -3024,3 +3027,116 @@ fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward( } }); } + +// Test that an upgrade from previous test environment works. +#[test] +fn test_upgrade_from_master_works() { + let data_sets = &[ + test_upgrade_from_master_dataset::_0, + test_upgrade_from_master_dataset::_1, + test_upgrade_from_master_dataset::_2, + test_upgrade_from_master_dataset::_3, + test_upgrade_from_master_dataset::_4, + test_upgrade_from_master_dataset::_5, + test_upgrade_from_master_dataset::_6, + test_upgrade_from_master_dataset::_7, + test_upgrade_from_master_dataset::_8, + ]; + for data_set in data_sets.iter() { + let mut storage = sp_runtime::Storage::default(); + for (key, value) in data_set.iter() { + storage.top.insert(key.to_vec(), value.to_vec()); + } + let mut ext = sp_io::TestExternalities::from(storage); + ext.execute_with(|| { + let old_stakers = ::CurrentElected::get(); + let old_staker_0 = old_stakers[0]; + let old_staker_1 = old_stakers[1]; + let old_current_era = ::CurrentEra::get().unwrap(); + let old_staker_0_exposure = ::Stakers::get(old_staker_0); + let old_staker_1_exposure = ::Stakers::get(old_staker_1); + let old_era_points_earned = ::CurrentEraPointsEarned::get(); + + Staking::ensure_storage_upgraded(); + assert!(::IsUpgraded::get()); + + // Check ActiveEra and CurrentEra + let active_era = Staking::active_era().unwrap(); + let current_era = Staking::current_era().unwrap(); + assert!(current_era == active_era); + assert!(current_era == old_current_era); + + // Check ErasStartSessionIndex + let active_era_start = Staking::eras_start_session_index(active_era).unwrap(); + let current_era_start = Staking::eras_start_session_index(current_era).unwrap(); + let current_session_index = Session::current_index(); + assert!(current_era_start == active_era_start); + assert!(active_era_start <= current_session_index); + assert_eq!(::ErasStartSessionIndex::iter().count(), 1); + + // Check ErasStakers + assert_eq!(::ErasStakers::iter().count(), 2); + assert_eq!( + ::ErasStakers::get(current_era, old_staker_0), + old_staker_0_exposure + ); + assert_eq!( + ::ErasStakers::get(current_era, old_staker_1), + old_staker_1_exposure + ); + + // Check ErasStakersClipped + assert_eq!(::ErasStakersClipped::iter().count(), 2); + assert!(::ErasStakersClipped::iter().all(|exposure_clipped| { + let max = ::MaxNominatorRewardedPerValidator::get() as usize; + exposure_clipped.others.len() <= max + })); + assert_eq!( + ::ErasStakersClipped::get(current_era, old_staker_0), + old_staker_0_exposure + ); + assert_eq!( + ::ErasStakersClipped::get(current_era, old_staker_1), + old_staker_1_exposure + ); + + // Check ErasValidatorPrefs + assert_eq!(::ErasValidatorPrefs::iter().count(), 2); + assert_eq!( + ::ErasValidatorPrefs::get(current_era, old_staker_0), + Staking::validators(old_staker_0) + ); + assert_eq!( + ::ErasValidatorPrefs::get(current_era, old_staker_1), + Staking::validators(old_staker_1) + ); + + // Check ErasTotalStake + assert_eq!(::ErasTotalStake::iter().count(), 1); + assert_eq!( + ::ErasTotalStake::get(current_era), + old_staker_0_exposure.total + old_staker_1_exposure.total + ); + + // Check ErasRewardPoints + assert_eq!(::ErasRewardPoints::iter().count(), 1); + let mut individual = BTreeMap::new(); + if let Some(p) = old_era_points_earned.individual.get(0) { + individual.insert(old_staker_0, p.clone()); + } + if let Some(p) = old_era_points_earned.individual.get(1) { + individual.insert(old_staker_1, p.clone()); + } + assert_eq!( + ::ErasRewardPoints::get(current_era), + EraRewardPoints { + total: old_era_points_earned.total, + individual, + } + ); + + // Check ErasValidatorReward + assert_eq!(::ErasValidatorReward::iter().count(), 0); + }); + } +} diff --git a/frame/staking/src/tests/test_upgrade_from_master_dataset.rs b/frame/staking/src/tests/test_upgrade_from_master_dataset.rs new file mode 100644 index 0000000000000..32f9b0a3edb96 --- /dev/null +++ b/frame/staking/src/tests/test_upgrade_from_master_dataset.rs @@ -0,0 +1,59 @@ +// Copyright 2020-2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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. + +// Substrate 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 Substrate. If not, see . + +//! Data set for testing update from previous staking module. +//! +//! Each data set correspond to the storage state for its corresponding block just before the +//! staking initialisation. +//! +//! it has been generated using the following code at commit +//! dc92587bea4032e0a0fc96785bfd9aa17c95459e +//! +//! ```nocompile +//! fn print_storage(i: u32) { +//! let mut storage = vec![]; +//! let mut current_key = vec![]; +//! while let Some(key) = sp_io::storage::next_key(¤t_key) { +//! storage.push((key.clone(), sp_io::storage::get(&key).unwrap())); +//! current_key = key; +//! } +//! println!("const _{}: &[(&[u8], &[u8])] = {:?};", i, storage); +//! } +//! +//! #[test] +//! fn get_states() { +//! let mut ext = ExtBuilder::default().build(); +//! +//! for index in 1..10u32 { +//! ext.execute_with(|| { +//! print_storage(index - 1); +//! System::set_block_number((index).into()); +//! Timestamp::set_timestamp(System::block_number() * 1000); +//! Session::on_initialize(System::block_number()); +//! }); +//! } +//! } +//! ``` + +pub const _0: &[(&[u8], &[u8])] = &[(&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 2, 165, 193, 177, 154, 183, 160, 79, 83, 108, 81, 154, 202, 73, 131, 172], &[1, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 10, 152, 253, 190, 156, 230, 197, 88, 55, 87, 108, 96, 199, 175, 56, 80], &[15, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 128, 212, 30, 94, 22, 5, 103, 101, 188, 132, 97, 133, 16, 114, 201, 215], &[60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 138, 66, 243, 51, 35, 203, 92, 237, 59, 68, 221, 130, 95, 218, 159, 204], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 164, 71, 4, 181, 104, 210, 22, 103, 53, 106, 90, 5, 12, 17, 135, 70, 129, 228, 122, 25, 230, 178, 155, 10, 101, 185, 89, 23, 98, 206, 81, 67, 237, 48, 208, 38, 30, 93, 36, 163, 32, 23, 82, 80, 107, 32, 241, 92], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 29, 189, 125, 11, 86, 26, 65, 210, 60, 42, 70, 154, 212, 47, 189, 112, 213, 67, 139, 174, 130, 111, 111, 214, 7, 65, 49, 144, 195, 124, 54, 59], &[0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 100, 74, 81, 252, 33, 158, 145, 69, 184, 87, 123, 183, 118, 40, 118, 123, 28, 47, 115, 116, 142, 218, 139, 120, 139, 252, 102, 161, 181, 42, 32, 248], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 165, 212, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 108, 221, 179, 103, 175, 189, 88, 59, 180, 143, 155, 189, 125, 91, 163, 177, 208, 115, 139, 72, 129, 177, 205, 221, 56, 22, 149, 38, 216, 21, 129, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 232, 139, 67, 253, 237, 99, 35, 239, 2, 255, 239, 251, 216, 196, 8, 70, 238, 9, 191, 49, 98, 113, 189, 34, 54, 150, 89, 201, 89, 221, 115, 58], &[0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 233, 103, 96, 210, 116, 101, 58, 57, 180, 41, 168, 126, 186, 174, 157, 58, 164, 253, 245, 139, 144, 150, 207, 11, 235, 199, 196, 229, 164, 194, 237, 141], &[0, 0, 0, 0, 0, 0, 0, 0, 144, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0]), (&[58, 99, 111, 100, 101], &[]), (&[58, 101, 120, 116, 114, 105, 110, 115, 105, 99, 95, 105, 110, 100, 101, 120], &[0, 0, 0, 0]), (&[58, 104, 101, 97, 112, 112, 97, 103, 101, 115], &[8, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 11, 106, 69, 50, 30, 250, 233, 42, 234, 21, 224, 116, 14, 199, 175, 231], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 14, 160, 236, 172, 118, 69, 125, 15, 155, 57, 185, 129, 221, 16, 112, 18], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 19, 142, 113, 97, 36, 145, 25, 45, 104, 222, 171, 126, 111, 86, 63, 225], &[2, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 40, 220, 203, 85, 155, 149, 196, 1, 104, 161, 178, 105, 101, 129, 181, 167], &[0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[40, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[10, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[30, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[20, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[100, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[21, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[31, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[11, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[101, 0, 0, 0, 0, 0, 0, 0, 209, 7, 209, 7, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[41, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 80, 154, 155, 110, 250, 147, 245, 187, 131, 248, 88, 240, 186, 191, 211, 11], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 85, 121, 41, 127, 77, 251, 150, 9, 231, 228, 194, 235, 171, 156, 228, 10], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 86, 239, 98, 39, 206, 203, 47, 7, 39, 76, 176, 87, 45, 143, 164, 194], &[101, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 106, 147, 17, 38, 51, 187, 51, 84, 230, 121, 82, 252, 221, 116, 12, 213], &[31, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[149, 17, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 245, 1]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[125, 21, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 221, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 1, 31, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 106, 99, 127, 98, 174, 42, 241, 199, 227, 30, 237, 126, 150, 190, 4, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[8, 11, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 189, 47, 11, 41, 160, 8, 163, 96, 9, 172, 68, 204, 160, 201, 105], &[101, 4, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 180, 154, 39, 56, 238, 179, 8, 150, 170, 203, 139, 63, 180, 100, 113, 189], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 194, 154, 3, 16, 225, 187, 69, 210, 12, 172, 231, 124, 203, 98, 201, 125], &[0, 225, 245, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 234, 7, 222, 43, 143, 1, 5, 22, 220, 163, 247, 239, 82, 247, 172, 90], &[4, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 247, 218, 208, 49, 115, 36, 174, 202, 232, 116, 75, 135, 252, 149, 242, 243], &[0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 1, 0, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 244, 1, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 87, 200, 117, 228, 207, 247, 65, 72, 228, 98, 143, 38, 75, 151, 76, 128], &[214, 61, 165, 212, 232, 0, 0, 0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 227, 253, 141, 247, 41, 112, 188, 130, 229, 38, 126, 160, 30, 221, 217, 73], &[1]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 109, 123, 24, 86, 30, 19, 159, 228, 49, 200, 33, 139, 70, 205, 244, 47, 40, 190, 110, 43, 138, 12, 26, 121, 5, 219, 103, 1, 110, 91, 142, 123], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 238, 43, 102, 225, 142, 104, 190, 12, 183, 86, 115, 25, 37, 223, 229, 65, 253, 167, 152, 54, 57, 147, 167, 137, 80, 161, 2, 235, 195, 174, 40, 244], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 17, 218, 109, 31, 118, 29, 223, 155, 219, 76, 157, 110, 83, 3, 235, 212, 31, 97, 133, 141, 10, 86, 71, 161, 167, 191, 224, 137, 191, 146, 27, 233], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 225, 44, 34, 212, 241, 98, 217, 160, 18, 201, 49, 146, 51, 218, 93, 62, 146, 60, 197, 225, 2, 155, 143, 144, 228, 114, 73, 201, 171, 37, 107, 53], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 224, 205, 208, 98, 230, 234, 242, 66, 149, 173, 76, 207, 196, 29, 70, 9], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 255, 58, 225, 39, 112, 190, 162, 228, 141, 155, 222, 115, 133, 231, 162, 95], &[0, 0, 0, 0, 2, 0, 0, 0])]; +pub const _1: &[(&[u8], &[u8])] = &[(&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 2, 165, 193, 177, 154, 183, 160, 79, 83, 108, 81, 154, 202, 73, 131, 172], &[1, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 10, 152, 253, 190, 156, 230, 197, 88, 55, 87, 108, 96, 199, 175, 56, 80], &[16, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 128, 212, 30, 94, 22, 5, 103, 101, 188, 132, 97, 133, 16, 114, 201, 215], &[64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 138, 66, 243, 51, 35, 203, 92, 237, 59, 68, 221, 130, 95, 218, 159, 204], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 164, 71, 4, 181, 104, 210, 22, 103, 53, 106, 90, 5, 12, 17, 135, 70, 129, 228, 122, 25, 230, 178, 155, 10, 101, 185, 89, 23, 98, 206, 81, 67, 237, 48, 208, 38, 30, 93, 36, 163, 32, 23, 82, 80, 107, 32, 241, 92], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 29, 189, 125, 11, 86, 26, 65, 210, 60, 42, 70, 154, 212, 47, 189, 112, 213, 67, 139, 174, 130, 111, 111, 214, 7, 65, 49, 144, 195, 124, 54, 59], &[0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 100, 74, 81, 252, 33, 158, 145, 69, 184, 87, 123, 183, 118, 40, 118, 123, 28, 47, 115, 116, 142, 218, 139, 120, 139, 252, 102, 161, 181, 42, 32, 248], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 165, 212, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 108, 221, 179, 103, 175, 189, 88, 59, 180, 143, 155, 189, 125, 91, 163, 177, 208, 115, 139, 72, 129, 177, 205, 221, 56, 22, 149, 38, 216, 21, 129, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 232, 139, 67, 253, 237, 99, 35, 239, 2, 255, 239, 251, 216, 196, 8, 70, 238, 9, 191, 49, 98, 113, 189, 34, 54, 150, 89, 201, 89, 221, 115, 58], &[0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 233, 103, 96, 210, 116, 101, 58, 57, 180, 41, 168, 126, 186, 174, 157, 58, 164, 253, 245, 139, 144, 150, 207, 11, 235, 199, 196, 229, 164, 194, 237, 141], &[0, 0, 0, 0, 0, 0, 0, 0, 144, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0]), (&[58, 99, 111, 100, 101], &[]), (&[58, 101, 120, 116, 114, 105, 110, 115, 105, 99, 95, 105, 110, 100, 101, 120], &[0, 0, 0, 0]), (&[58, 104, 101, 97, 112, 112, 97, 103, 101, 115], &[8, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 11, 106, 69, 50, 30, 250, 233, 42, 234, 21, 224, 116, 14, 199, 175, 231], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 14, 160, 236, 172, 118, 69, 125, 15, 155, 57, 185, 129, 221, 16, 112, 18], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 19, 142, 113, 97, 36, 145, 25, 45, 104, 222, 171, 126, 111, 86, 63, 225], &[2, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 40, 220, 203, 85, 155, 149, 196, 1, 104, 161, 178, 105, 101, 129, 181, 167], &[0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[40, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[10, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[30, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[20, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[100, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[21, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[31, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[11, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[101, 0, 0, 0, 0, 0, 0, 0, 209, 7, 209, 7, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[41, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 80, 154, 155, 110, 250, 147, 245, 187, 131, 248, 88, 240, 186, 191, 211, 11], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 85, 121, 41, 127, 77, 251, 150, 9, 231, 228, 194, 235, 171, 156, 228, 10], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 86, 239, 98, 39, 206, 203, 47, 7, 39, 76, 176, 87, 45, 143, 164, 194], &[101, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 106, 147, 17, 38, 51, 187, 51, 84, 230, 121, 82, 252, 221, 116, 12, 213], &[31, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[149, 17, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 245, 1]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[125, 21, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 221, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 1, 31, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 106, 99, 127, 98, 174, 42, 241, 199, 227, 30, 237, 126, 150, 190, 4, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[8, 11, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 189, 47, 11, 41, 160, 8, 163, 96, 9, 172, 68, 204, 160, 201, 105], &[101, 4, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 180, 154, 39, 56, 238, 179, 8, 150, 170, 203, 139, 63, 180, 100, 113, 189], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 194, 154, 3, 16, 225, 187, 69, 210, 12, 172, 231, 124, 203, 98, 201, 125], &[0, 225, 245, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 234, 7, 222, 43, 143, 1, 5, 22, 220, 163, 247, 239, 82, 247, 172, 90], &[4, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 247, 218, 208, 49, 115, 36, 174, 202, 232, 116, 75, 135, 252, 149, 242, 243], &[0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 1, 0, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 244, 1, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 87, 200, 117, 228, 207, 247, 65, 72, 228, 98, 143, 38, 75, 151, 76, 128], &[214, 61, 165, 212, 232, 0, 0, 0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 227, 253, 141, 247, 41, 112, 188, 130, 229, 38, 126, 160, 30, 221, 217, 73], &[1]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 109, 123, 24, 86, 30, 19, 159, 228, 49, 200, 33, 139, 70, 205, 244, 47, 40, 190, 110, 43, 138, 12, 26, 121, 5, 219, 103, 1, 110, 91, 142, 123], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 238, 43, 102, 225, 142, 104, 190, 12, 183, 86, 115, 25, 37, 223, 229, 65, 253, 167, 152, 54, 57, 147, 167, 137, 80, 161, 2, 235, 195, 174, 40, 244], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 118, 56, 0, 163, 106, 153, 253, 252, 124, 16, 246, 65, 95, 110, 230], &[1, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 148, 80, 191, 164, 185, 106, 63, 167, 163, 200, 244, 13, 166, 191, 50, 225], &[0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 17, 218, 109, 31, 118, 29, 223, 155, 219, 76, 157, 110, 83, 3, 235, 212, 31, 97, 133, 141, 10, 86, 71, 161, 167, 191, 224, 137, 191, 146, 27, 233], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 123, 10, 161, 115, 94, 91, 165, 141, 50, 54, 49, 108, 103, 31, 228, 240, 14, 211, 102, 238, 114, 65, 124, 158, 208, 42, 83, 168, 1, 158, 133, 184], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 225, 44, 34, 212, 241, 98, 217, 160, 18, 201, 49, 146, 51, 218, 93, 62, 146, 60, 197, 225, 2, 155, 143, 144, 228, 114, 73, 201, 171, 37, 107, 53], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 224, 205, 208, 98, 230, 234, 242, 66, 149, 173, 76, 207, 196, 29, 70, 9], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 255, 58, 225, 39, 112, 190, 162, 228, 141, 155, 222, 115, 133, 231, 162, 95], &[0, 0, 0, 0, 3, 0, 0, 0]), (&[240, 195, 101, 195, 207, 89, 214, 113, 235, 114, 218, 14, 122, 65, 19, 196, 159, 31, 5, 21, 244, 98, 205, 207, 132, 224, 241, 214, 4, 93, 252, 187], &[232, 3, 0, 0, 0, 0, 0, 0])]; +pub const _2: &[(&[u8], &[u8])] = &[(&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 2, 165, 193, 177, 154, 183, 160, 79, 83, 108, 81, 154, 202, 73, 131, 172], &[2, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 10, 152, 253, 190, 156, 230, 197, 88, 55, 87, 108, 96, 199, 175, 56, 80], &[17, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 128, 212, 30, 94, 22, 5, 103, 101, 188, 132, 97, 133, 16, 114, 201, 215], &[68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 138, 66, 243, 51, 35, 203, 92, 237, 59, 68, 221, 130, 95, 218, 159, 204], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 164, 71, 4, 181, 104, 210, 22, 103, 53, 106, 90, 5, 12, 17, 135, 70, 129, 228, 122, 25, 230, 178, 155, 10, 101, 185, 89, 23, 98, 206, 81, 67, 237, 48, 208, 38, 30, 93, 36, 163, 32, 23, 82, 80, 107, 32, 241, 92], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 29, 189, 125, 11, 86, 26, 65, 210, 60, 42, 70, 154, 212, 47, 189, 112, 213, 67, 139, 174, 130, 111, 111, 214, 7, 65, 49, 144, 195, 124, 54, 59], &[0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 100, 74, 81, 252, 33, 158, 145, 69, 184, 87, 123, 183, 118, 40, 118, 123, 28, 47, 115, 116, 142, 218, 139, 120, 139, 252, 102, 161, 181, 42, 32, 248], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 165, 212, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 108, 221, 179, 103, 175, 189, 88, 59, 180, 143, 155, 189, 125, 91, 163, 177, 208, 115, 139, 72, 129, 177, 205, 221, 56, 22, 149, 38, 216, 21, 129, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 232, 139, 67, 253, 237, 99, 35, 239, 2, 255, 239, 251, 216, 196, 8, 70, 238, 9, 191, 49, 98, 113, 189, 34, 54, 150, 89, 201, 89, 221, 115, 58], &[0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 233, 103, 96, 210, 116, 101, 58, 57, 180, 41, 168, 126, 186, 174, 157, 58, 164, 253, 245, 139, 144, 150, 207, 11, 235, 199, 196, 229, 164, 194, 237, 141], &[0, 0, 0, 0, 0, 0, 0, 0, 144, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0]), (&[58, 99, 111, 100, 101], &[]), (&[58, 101, 120, 116, 114, 105, 110, 115, 105, 99, 95, 105, 110, 100, 101, 120], &[0, 0, 0, 0]), (&[58, 104, 101, 97, 112, 112, 97, 103, 101, 115], &[8, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 11, 106, 69, 50, 30, 250, 233, 42, 234, 21, 224, 116, 14, 199, 175, 231], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 14, 160, 236, 172, 118, 69, 125, 15, 155, 57, 185, 129, 221, 16, 112, 18], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 19, 142, 113, 97, 36, 145, 25, 45, 104, 222, 171, 126, 111, 86, 63, 225], &[2, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 40, 220, 203, 85, 155, 149, 196, 1, 104, 161, 178, 105, 101, 129, 181, 167], &[0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[40, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[10, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[30, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[20, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[100, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[21, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[31, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[11, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[101, 0, 0, 0, 0, 0, 0, 0, 209, 7, 209, 7, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[41, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 80, 154, 155, 110, 250, 147, 245, 187, 131, 248, 88, 240, 186, 191, 211, 11], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 85, 121, 41, 127, 77, 251, 150, 9, 231, 228, 194, 235, 171, 156, 228, 10], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 86, 239, 98, 39, 206, 203, 47, 7, 39, 76, 176, 87, 45, 143, 164, 194], &[101, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 106, 147, 17, 38, 51, 187, 51, 84, 230, 121, 82, 252, 221, 116, 12, 213], &[31, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[149, 17, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 245, 1]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[125, 21, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 221, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 1, 31, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 106, 99, 127, 98, 174, 42, 241, 199, 227, 30, 237, 126, 150, 190, 4, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[8, 11, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 189, 47, 11, 41, 160, 8, 163, 96, 9, 172, 68, 204, 160, 201, 105], &[101, 4, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 180, 154, 39, 56, 238, 179, 8, 150, 170, 203, 139, 63, 180, 100, 113, 189], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 194, 154, 3, 16, 225, 187, 69, 210, 12, 172, 231, 124, 203, 98, 201, 125], &[0, 225, 245, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 234, 7, 222, 43, 143, 1, 5, 22, 220, 163, 247, 239, 82, 247, 172, 90], &[4, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 247, 218, 208, 49, 115, 36, 174, 202, 232, 116, 75, 135, 252, 149, 242, 243], &[0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 1, 0, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 244, 1, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 87, 200, 117, 228, 207, 247, 65, 72, 228, 98, 143, 38, 75, 151, 76, 128], &[214, 61, 165, 212, 232, 0, 0, 0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 227, 253, 141, 247, 41, 112, 188, 130, 229, 38, 126, 160, 30, 221, 217, 73], &[1]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 109, 123, 24, 86, 30, 19, 159, 228, 49, 200, 33, 139, 70, 205, 244, 47, 40, 190, 110, 43, 138, 12, 26, 121, 5, 219, 103, 1, 110, 91, 142, 123], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 238, 43, 102, 225, 142, 104, 190, 12, 183, 86, 115, 25, 37, 223, 229, 65, 253, 167, 152, 54, 57, 147, 167, 137, 80, 161, 2, 235, 195, 174, 40, 244], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 118, 56, 0, 163, 106, 153, 253, 252, 124, 16, 246, 65, 95, 110, 230], &[2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 148, 80, 191, 164, 185, 106, 63, 167, 163, 200, 244, 13, 166, 191, 50, 225], &[0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 17, 218, 109, 31, 118, 29, 223, 155, 219, 76, 157, 110, 83, 3, 235, 212, 31, 97, 133, 141, 10, 86, 71, 161, 167, 191, 224, 137, 191, 146, 27, 233], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 123, 10, 161, 115, 94, 91, 165, 141, 50, 54, 49, 108, 103, 31, 228, 240, 14, 211, 102, 238, 114, 65, 124, 158, 208, 42, 83, 168, 1, 158, 133, 184], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 140, 3, 159, 247, 202, 161, 124, 206, 191, 202, 220, 68, 189, 159, 206, 106, 75, 102, 153, 196, 208, 61, 226, 227, 52, 154, 161, 220, 17, 25, 60, 215], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 225, 44, 34, 212, 241, 98, 217, 160, 18, 201, 49, 146, 51, 218, 93, 62, 146, 60, 197, 225, 2, 155, 143, 144, 228, 114, 73, 201, 171, 37, 107, 53], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 224, 205, 208, 98, 230, 234, 242, 66, 149, 173, 76, 207, 196, 29, 70, 9], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 255, 58, 225, 39, 112, 190, 162, 228, 141, 155, 222, 115, 133, 231, 162, 95], &[0, 0, 0, 0, 4, 0, 0, 0]), (&[240, 195, 101, 195, 207, 89, 214, 113, 235, 114, 218, 14, 122, 65, 19, 196, 159, 31, 5, 21, 244, 98, 205, 207, 132, 224, 241, 214, 4, 93, 252, 187], &[208, 7, 0, 0, 0, 0, 0, 0])]; +pub const _3: &[(&[u8], &[u8])] = &[(&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 2, 165, 193, 177, 154, 183, 160, 79, 83, 108, 81, 154, 202, 73, 131, 172], &[3, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 10, 152, 253, 190, 156, 230, 197, 88, 55, 87, 108, 96, 199, 175, 56, 80], &[19, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 128, 212, 30, 94, 22, 5, 103, 101, 188, 132, 97, 133, 16, 114, 201, 215], &[76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 138, 66, 243, 51, 35, 203, 92, 237, 59, 68, 221, 130, 95, 218, 159, 204], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 164, 71, 4, 181, 104, 210, 22, 103, 53, 106, 90, 5, 12, 17, 135, 70, 129, 228, 122, 25, 230, 178, 155, 10, 101, 185, 89, 23, 98, 206, 81, 67, 237, 48, 208, 38, 30, 93, 36, 163, 32, 23, 82, 80, 107, 32, 241, 92], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 29, 189, 125, 11, 86, 26, 65, 210, 60, 42, 70, 154, 212, 47, 189, 112, 213, 67, 139, 174, 130, 111, 111, 214, 7, 65, 49, 144, 195, 124, 54, 59], &[0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 100, 74, 81, 252, 33, 158, 145, 69, 184, 87, 123, 183, 118, 40, 118, 123, 28, 47, 115, 116, 142, 218, 139, 120, 139, 252, 102, 161, 181, 42, 32, 248], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 165, 212, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 108, 221, 179, 103, 175, 189, 88, 59, 180, 143, 155, 189, 125, 91, 163, 177, 208, 115, 139, 72, 129, 177, 205, 221, 56, 22, 149, 38, 216, 21, 129, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 232, 139, 67, 253, 237, 99, 35, 239, 2, 255, 239, 251, 216, 196, 8, 70, 238, 9, 191, 49, 98, 113, 189, 34, 54, 150, 89, 201, 89, 221, 115, 58], &[0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 233, 103, 96, 210, 116, 101, 58, 57, 180, 41, 168, 126, 186, 174, 157, 58, 164, 253, 245, 139, 144, 150, 207, 11, 235, 199, 196, 229, 164, 194, 237, 141], &[0, 0, 0, 0, 0, 0, 0, 0, 144, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0]), (&[58, 99, 111, 100, 101], &[]), (&[58, 101, 120, 116, 114, 105, 110, 115, 105, 99, 95, 105, 110, 100, 101, 120], &[0, 0, 0, 0]), (&[58, 104, 101, 97, 112, 112, 97, 103, 101, 115], &[8, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 11, 106, 69, 50, 30, 250, 233, 42, 234, 21, 224, 116, 14, 199, 175, 231], &[1, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 14, 160, 236, 172, 118, 69, 125, 15, 155, 57, 185, 129, 221, 16, 112, 18], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 19, 142, 113, 97, 36, 145, 25, 45, 104, 222, 171, 126, 111, 86, 63, 225], &[2, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 40, 220, 203, 85, 155, 149, 196, 1, 104, 161, 178, 105, 101, 129, 181, 167], &[0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[40, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[10, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[30, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[20, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[100, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[21, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[31, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[11, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[101, 0, 0, 0, 0, 0, 0, 0, 209, 7, 209, 7, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[41, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 80, 154, 155, 110, 250, 147, 245, 187, 131, 248, 88, 240, 186, 191, 211, 11], &[3, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 85, 121, 41, 127, 77, 251, 150, 9, 231, 228, 194, 235, 171, 156, 228, 10], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 86, 239, 98, 39, 206, 203, 47, 7, 39, 76, 176, 87, 45, 143, 164, 194], &[101, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 106, 147, 17, 38, 51, 187, 51, 84, 230, 121, 82, 252, 221, 116, 12, 213], &[31, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[149, 17, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 245, 1]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[125, 21, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 221, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 1, 31, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 106, 99, 127, 98, 174, 42, 241, 199, 227, 30, 237, 126, 150, 190, 4, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[8, 11, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 189, 47, 11, 41, 160, 8, 163, 96, 9, 172, 68, 204, 160, 201, 105], &[101, 4, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 166, 97, 104, 247, 231, 37, 155, 102, 112, 160, 111, 37, 101, 227, 229, 242], &[184, 11, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 180, 154, 39, 56, 238, 179, 8, 150, 170, 203, 139, 63, 180, 100, 113, 189], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 194, 154, 3, 16, 225, 187, 69, 210, 12, 172, 231, 124, 203, 98, 201, 125], &[0, 225, 245, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 234, 7, 222, 43, 143, 1, 5, 22, 220, 163, 247, 239, 82, 247, 172, 90], &[8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 247, 218, 208, 49, 115, 36, 174, 202, 232, 116, 75, 135, 252, 149, 242, 243], &[0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 1, 0, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 244, 1, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 87, 200, 117, 228, 207, 247, 65, 72, 228, 98, 143, 38, 75, 151, 76, 128], &[214, 61, 165, 212, 232, 0, 0, 0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 227, 253, 141, 247, 41, 112, 188, 130, 229, 38, 126, 160, 30, 221, 217, 73], &[1]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 109, 123, 24, 86, 30, 19, 159, 228, 49, 200, 33, 139, 70, 205, 244, 47, 40, 190, 110, 43, 138, 12, 26, 121, 5, 219, 103, 1, 110, 91, 142, 123], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 238, 43, 102, 225, 142, 104, 190, 12, 183, 86, 115, 25, 37, 223, 229, 65, 253, 167, 152, 54, 57, 147, 167, 137, 80, 161, 2, 235, 195, 174, 40, 244], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 118, 56, 0, 163, 106, 153, 253, 252, 124, 16, 246, 65, 95, 110, 230], &[3, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 148, 80, 191, 164, 185, 106, 63, 167, 163, 200, 244, 13, 166, 191, 50, 225], &[1]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 17, 218, 109, 31, 118, 29, 223, 155, 219, 76, 157, 110, 83, 3, 235, 212, 31, 97, 133, 141, 10, 86, 71, 161, 167, 191, 224, 137, 191, 146, 27, 233], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 38, 160, 142, 77, 12, 81, 144, 240, 24, 113, 224, 86, 155, 98, 144, 184, 103, 96, 8, 93, 153, 241, 126, 180, 231, 230, 181, 143, 235, 141, 98, 73], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 123, 10, 161, 115, 94, 91, 165, 141, 50, 54, 49, 108, 103, 31, 228, 240, 14, 211, 102, 238, 114, 65, 124, 158, 208, 42, 83, 168, 1, 158, 133, 184], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 140, 3, 159, 247, 202, 161, 124, 206, 191, 202, 220, 68, 189, 159, 206, 106, 75, 102, 153, 196, 208, 61, 226, 227, 52, 154, 161, 220, 17, 25, 60, 215], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 225, 44, 34, 212, 241, 98, 217, 160, 18, 201, 49, 146, 51, 218, 93, 62, 146, 60, 197, 225, 2, 155, 143, 144, 228, 114, 73, 201, 171, 37, 107, 53], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 224, 205, 208, 98, 230, 234, 242, 66, 149, 173, 76, 207, 196, 29, 70, 9], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 255, 58, 225, 39, 112, 190, 162, 228, 141, 155, 222, 115, 133, 231, 162, 95], &[0, 0, 0, 0, 5, 0, 0, 0]), (&[240, 195, 101, 195, 207, 89, 214, 113, 235, 114, 218, 14, 122, 65, 19, 196, 159, 31, 5, 21, 244, 98, 205, 207, 132, 224, 241, 214, 4, 93, 252, 187], &[184, 11, 0, 0, 0, 0, 0, 0])]; +pub const _4: &[(&[u8], &[u8])] = &[(&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 2, 165, 193, 177, 154, 183, 160, 79, 83, 108, 81, 154, 202, 73, 131, 172], &[4, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 10, 152, 253, 190, 156, 230, 197, 88, 55, 87, 108, 96, 199, 175, 56, 80], &[20, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 128, 212, 30, 94, 22, 5, 103, 101, 188, 132, 97, 133, 16, 114, 201, 215], &[80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 138, 66, 243, 51, 35, 203, 92, 237, 59, 68, 221, 130, 95, 218, 159, 204], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 164, 71, 4, 181, 104, 210, 22, 103, 53, 106, 90, 5, 12, 17, 135, 70, 129, 228, 122, 25, 230, 178, 155, 10, 101, 185, 89, 23, 98, 206, 81, 67, 237, 48, 208, 38, 30, 93, 36, 163, 32, 23, 82, 80, 107, 32, 241, 92], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 29, 189, 125, 11, 86, 26, 65, 210, 60, 42, 70, 154, 212, 47, 189, 112, 213, 67, 139, 174, 130, 111, 111, 214, 7, 65, 49, 144, 195, 124, 54, 59], &[0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 100, 74, 81, 252, 33, 158, 145, 69, 184, 87, 123, 183, 118, 40, 118, 123, 28, 47, 115, 116, 142, 218, 139, 120, 139, 252, 102, 161, 181, 42, 32, 248], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 165, 212, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 108, 221, 179, 103, 175, 189, 88, 59, 180, 143, 155, 189, 125, 91, 163, 177, 208, 115, 139, 72, 129, 177, 205, 221, 56, 22, 149, 38, 216, 21, 129, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 232, 139, 67, 253, 237, 99, 35, 239, 2, 255, 239, 251, 216, 196, 8, 70, 238, 9, 191, 49, 98, 113, 189, 34, 54, 150, 89, 201, 89, 221, 115, 58], &[0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 233, 103, 96, 210, 116, 101, 58, 57, 180, 41, 168, 126, 186, 174, 157, 58, 164, 253, 245, 139, 144, 150, 207, 11, 235, 199, 196, 229, 164, 194, 237, 141], &[0, 0, 0, 0, 0, 0, 0, 0, 144, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0]), (&[58, 99, 111, 100, 101], &[]), (&[58, 101, 120, 116, 114, 105, 110, 115, 105, 99, 95, 105, 110, 100, 101, 120], &[0, 0, 0, 0]), (&[58, 104, 101, 97, 112, 112, 97, 103, 101, 115], &[8, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 11, 106, 69, 50, 30, 250, 233, 42, 234, 21, 224, 116, 14, 199, 175, 231], &[1, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 14, 160, 236, 172, 118, 69, 125, 15, 155, 57, 185, 129, 221, 16, 112, 18], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 19, 142, 113, 97, 36, 145, 25, 45, 104, 222, 171, 126, 111, 86, 63, 225], &[2, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 40, 220, 203, 85, 155, 149, 196, 1, 104, 161, 178, 105, 101, 129, 181, 167], &[0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[40, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[10, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[30, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[20, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[100, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[21, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[31, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[11, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[101, 0, 0, 0, 0, 0, 0, 0, 209, 7, 209, 7, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[41, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 80, 154, 155, 110, 250, 147, 245, 187, 131, 248, 88, 240, 186, 191, 211, 11], &[3, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 85, 121, 41, 127, 77, 251, 150, 9, 231, 228, 194, 235, 171, 156, 228, 10], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 86, 239, 98, 39, 206, 203, 47, 7, 39, 76, 176, 87, 45, 143, 164, 194], &[101, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 106, 147, 17, 38, 51, 187, 51, 84, 230, 121, 82, 252, 221, 116, 12, 213], &[31, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[149, 17, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 245, 1]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[125, 21, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 221, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 1, 31, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 106, 99, 127, 98, 174, 42, 241, 199, 227, 30, 237, 126, 150, 190, 4, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[8, 11, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 189, 47, 11, 41, 160, 8, 163, 96, 9, 172, 68, 204, 160, 201, 105], &[101, 4, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 166, 97, 104, 247, 231, 37, 155, 102, 112, 160, 111, 37, 101, 227, 229, 242], &[184, 11, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 180, 154, 39, 56, 238, 179, 8, 150, 170, 203, 139, 63, 180, 100, 113, 189], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 194, 154, 3, 16, 225, 187, 69, 210, 12, 172, 231, 124, 203, 98, 201, 125], &[0, 225, 245, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 234, 7, 222, 43, 143, 1, 5, 22, 220, 163, 247, 239, 82, 247, 172, 90], &[8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 247, 218, 208, 49, 115, 36, 174, 202, 232, 116, 75, 135, 252, 149, 242, 243], &[0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 1, 0, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 244, 1, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 87, 200, 117, 228, 207, 247, 65, 72, 228, 98, 143, 38, 75, 151, 76, 128], &[214, 61, 165, 212, 232, 0, 0, 0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 227, 253, 141, 247, 41, 112, 188, 130, 229, 38, 126, 160, 30, 221, 217, 73], &[1]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 109, 123, 24, 86, 30, 19, 159, 228, 49, 200, 33, 139, 70, 205, 244, 47, 40, 190, 110, 43, 138, 12, 26, 121, 5, 219, 103, 1, 110, 91, 142, 123], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 238, 43, 102, 225, 142, 104, 190, 12, 183, 86, 115, 25, 37, 223, 229, 65, 253, 167, 152, 54, 57, 147, 167, 137, 80, 161, 2, 235, 195, 174, 40, 244], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 118, 56, 0, 163, 106, 153, 253, 252, 124, 16, 246, 65, 95, 110, 230], &[4, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 148, 80, 191, 164, 185, 106, 63, 167, 163, 200, 244, 13, 166, 191, 50, 225], &[0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 17, 218, 109, 31, 118, 29, 223, 155, 219, 76, 157, 110, 83, 3, 235, 212, 31, 97, 133, 141, 10, 86, 71, 161, 167, 191, 224, 137, 191, 146, 27, 233], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 38, 160, 142, 77, 12, 81, 144, 240, 24, 113, 224, 86, 155, 98, 144, 184, 103, 96, 8, 93, 153, 241, 126, 180, 231, 230, 181, 143, 235, 141, 98, 73], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 123, 10, 161, 115, 94, 91, 165, 141, 50, 54, 49, 108, 103, 31, 228, 240, 14, 211, 102, 238, 114, 65, 124, 158, 208, 42, 83, 168, 1, 158, 133, 184], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 140, 3, 159, 247, 202, 161, 124, 206, 191, 202, 220, 68, 189, 159, 206, 106, 75, 102, 153, 196, 208, 61, 226, 227, 52, 154, 161, 220, 17, 25, 60, 215], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 140, 53, 210, 47, 69, 157, 119, 202, 76, 11, 11, 80, 53, 134, 151, 102, 214, 13, 24, 43, 151, 22, 171, 62, 136, 121, 224, 102, 71, 136, 153, 168], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 225, 44, 34, 212, 241, 98, 217, 160, 18, 201, 49, 146, 51, 218, 93, 62, 146, 60, 197, 225, 2, 155, 143, 144, 228, 114, 73, 201, 171, 37, 107, 53], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 224, 205, 208, 98, 230, 234, 242, 66, 149, 173, 76, 207, 196, 29, 70, 9], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 255, 58, 225, 39, 112, 190, 162, 228, 141, 155, 222, 115, 133, 231, 162, 95], &[0, 0, 0, 0, 6, 0, 0, 0]), (&[240, 195, 101, 195, 207, 89, 214, 113, 235, 114, 218, 14, 122, 65, 19, 196, 159, 31, 5, 21, 244, 98, 205, 207, 132, 224, 241, 214, 4, 93, 252, 187], &[160, 15, 0, 0, 0, 0, 0, 0])]; +pub const _5: &[(&[u8], &[u8])] = &[(&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 2, 165, 193, 177, 154, 183, 160, 79, 83, 108, 81, 154, 202, 73, 131, 172], &[5, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 10, 152, 253, 190, 156, 230, 197, 88, 55, 87, 108, 96, 199, 175, 56, 80], &[21, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 128, 212, 30, 94, 22, 5, 103, 101, 188, 132, 97, 133, 16, 114, 201, 215], &[84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 138, 66, 243, 51, 35, 203, 92, 237, 59, 68, 221, 130, 95, 218, 159, 204], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 164, 71, 4, 181, 104, 210, 22, 103, 53, 106, 90, 5, 12, 17, 135, 70, 129, 228, 122, 25, 230, 178, 155, 10, 101, 185, 89, 23, 98, 206, 81, 67, 237, 48, 208, 38, 30, 93, 36, 163, 32, 23, 82, 80, 107, 32, 241, 92], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 29, 189, 125, 11, 86, 26, 65, 210, 60, 42, 70, 154, 212, 47, 189, 112, 213, 67, 139, 174, 130, 111, 111, 214, 7, 65, 49, 144, 195, 124, 54, 59], &[0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 100, 74, 81, 252, 33, 158, 145, 69, 184, 87, 123, 183, 118, 40, 118, 123, 28, 47, 115, 116, 142, 218, 139, 120, 139, 252, 102, 161, 181, 42, 32, 248], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 165, 212, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 108, 221, 179, 103, 175, 189, 88, 59, 180, 143, 155, 189, 125, 91, 163, 177, 208, 115, 139, 72, 129, 177, 205, 221, 56, 22, 149, 38, 216, 21, 129, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 232, 139, 67, 253, 237, 99, 35, 239, 2, 255, 239, 251, 216, 196, 8, 70, 238, 9, 191, 49, 98, 113, 189, 34, 54, 150, 89, 201, 89, 221, 115, 58], &[0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 233, 103, 96, 210, 116, 101, 58, 57, 180, 41, 168, 126, 186, 174, 157, 58, 164, 253, 245, 139, 144, 150, 207, 11, 235, 199, 196, 229, 164, 194, 237, 141], &[0, 0, 0, 0, 0, 0, 0, 0, 144, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0]), (&[58, 99, 111, 100, 101], &[]), (&[58, 101, 120, 116, 114, 105, 110, 115, 105, 99, 95, 105, 110, 100, 101, 120], &[0, 0, 0, 0]), (&[58, 104, 101, 97, 112, 112, 97, 103, 101, 115], &[8, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 11, 106, 69, 50, 30, 250, 233, 42, 234, 21, 224, 116, 14, 199, 175, 231], &[1, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 14, 160, 236, 172, 118, 69, 125, 15, 155, 57, 185, 129, 221, 16, 112, 18], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 19, 142, 113, 97, 36, 145, 25, 45, 104, 222, 171, 126, 111, 86, 63, 225], &[2, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 40, 220, 203, 85, 155, 149, 196, 1, 104, 161, 178, 105, 101, 129, 181, 167], &[0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[40, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[10, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[30, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[20, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[100, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[21, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[31, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[11, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[101, 0, 0, 0, 0, 0, 0, 0, 209, 7, 209, 7, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[41, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 80, 154, 155, 110, 250, 147, 245, 187, 131, 248, 88, 240, 186, 191, 211, 11], &[3, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 85, 121, 41, 127, 77, 251, 150, 9, 231, 228, 194, 235, 171, 156, 228, 10], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 86, 239, 98, 39, 206, 203, 47, 7, 39, 76, 176, 87, 45, 143, 164, 194], &[101, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 106, 147, 17, 38, 51, 187, 51, 84, 230, 121, 82, 252, 221, 116, 12, 213], &[31, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[149, 17, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 245, 1]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[125, 21, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 221, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 1, 31, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 106, 99, 127, 98, 174, 42, 241, 199, 227, 30, 237, 126, 150, 190, 4, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[8, 11, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 189, 47, 11, 41, 160, 8, 163, 96, 9, 172, 68, 204, 160, 201, 105], &[101, 4, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 166, 97, 104, 247, 231, 37, 155, 102, 112, 160, 111, 37, 101, 227, 229, 242], &[184, 11, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 180, 154, 39, 56, 238, 179, 8, 150, 170, 203, 139, 63, 180, 100, 113, 189], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 194, 154, 3, 16, 225, 187, 69, 210, 12, 172, 231, 124, 203, 98, 201, 125], &[0, 225, 245, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 234, 7, 222, 43, 143, 1, 5, 22, 220, 163, 247, 239, 82, 247, 172, 90], &[8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 247, 218, 208, 49, 115, 36, 174, 202, 232, 116, 75, 135, 252, 149, 242, 243], &[0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 1, 0, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 244, 1, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 87, 200, 117, 228, 207, 247, 65, 72, 228, 98, 143, 38, 75, 151, 76, 128], &[214, 61, 165, 212, 232, 0, 0, 0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 227, 253, 141, 247, 41, 112, 188, 130, 229, 38, 126, 160, 30, 221, 217, 73], &[1]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 109, 123, 24, 86, 30, 19, 159, 228, 49, 200, 33, 139, 70, 205, 244, 47, 40, 190, 110, 43, 138, 12, 26, 121, 5, 219, 103, 1, 110, 91, 142, 123], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 238, 43, 102, 225, 142, 104, 190, 12, 183, 86, 115, 25, 37, 223, 229, 65, 253, 167, 152, 54, 57, 147, 167, 137, 80, 161, 2, 235, 195, 174, 40, 244], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 118, 56, 0, 163, 106, 153, 253, 252, 124, 16, 246, 65, 95, 110, 230], &[5, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 148, 80, 191, 164, 185, 106, 63, 167, 163, 200, 244, 13, 166, 191, 50, 225], &[0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 17, 218, 109, 31, 118, 29, 223, 155, 219, 76, 157, 110, 83, 3, 235, 212, 31, 97, 133, 141, 10, 86, 71, 161, 167, 191, 224, 137, 191, 146, 27, 233], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 38, 160, 142, 77, 12, 81, 144, 240, 24, 113, 224, 86, 155, 98, 144, 184, 103, 96, 8, 93, 153, 241, 126, 180, 231, 230, 181, 143, 235, 141, 98, 73], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 123, 10, 161, 115, 94, 91, 165, 141, 50, 54, 49, 108, 103, 31, 228, 240, 14, 211, 102, 238, 114, 65, 124, 158, 208, 42, 83, 168, 1, 158, 133, 184], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 140, 3, 159, 247, 202, 161, 124, 206, 191, 202, 220, 68, 189, 159, 206, 106, 75, 102, 153, 196, 208, 61, 226, 227, 52, 154, 161, 220, 17, 25, 60, 215], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 140, 53, 210, 47, 69, 157, 119, 202, 76, 11, 11, 80, 53, 134, 151, 102, 214, 13, 24, 43, 151, 22, 171, 62, 136, 121, 224, 102, 71, 136, 153, 168], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 225, 44, 34, 212, 241, 98, 217, 160, 18, 201, 49, 146, 51, 218, 93, 62, 146, 60, 197, 225, 2, 155, 143, 144, 228, 114, 73, 201, 171, 37, 107, 53], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 244, 170, 194, 251, 227, 63, 3, 85, 75, 254, 181, 89, 234, 38, 144, 237, 133, 33, 202, 164, 190, 150, 30, 97, 201, 26, 201, 161, 83, 13, 206, 122], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 224, 205, 208, 98, 230, 234, 242, 66, 149, 173, 76, 207, 196, 29, 70, 9], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 255, 58, 225, 39, 112, 190, 162, 228, 141, 155, 222, 115, 133, 231, 162, 95], &[0, 0, 0, 0, 7, 0, 0, 0]), (&[240, 195, 101, 195, 207, 89, 214, 113, 235, 114, 218, 14, 122, 65, 19, 196, 159, 31, 5, 21, 244, 98, 205, 207, 132, 224, 241, 214, 4, 93, 252, 187], &[136, 19, 0, 0, 0, 0, 0, 0])]; +pub const _6: &[(&[u8], &[u8])] = &[(&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 2, 165, 193, 177, 154, 183, 160, 79, 83, 108, 81, 154, 202, 73, 131, 172], &[6, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 10, 152, 253, 190, 156, 230, 197, 88, 55, 87, 108, 96, 199, 175, 56, 80], &[23, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 128, 212, 30, 94, 22, 5, 103, 101, 188, 132, 97, 133, 16, 114, 201, 215], &[92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 138, 66, 243, 51, 35, 203, 92, 237, 59, 68, 221, 130, 95, 218, 159, 204], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 164, 71, 4, 181, 104, 210, 22, 103, 53, 106, 90, 5, 12, 17, 135, 70, 129, 228, 122, 25, 230, 178, 155, 10, 101, 185, 89, 23, 98, 206, 81, 67, 237, 48, 208, 38, 30, 93, 36, 163, 32, 23, 82, 80, 107, 32, 241, 92], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 29, 189, 125, 11, 86, 26, 65, 210, 60, 42, 70, 154, 212, 47, 189, 112, 213, 67, 139, 174, 130, 111, 111, 214, 7, 65, 49, 144, 195, 124, 54, 59], &[0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 100, 74, 81, 252, 33, 158, 145, 69, 184, 87, 123, 183, 118, 40, 118, 123, 28, 47, 115, 116, 142, 218, 139, 120, 139, 252, 102, 161, 181, 42, 32, 248], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 165, 212, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 108, 221, 179, 103, 175, 189, 88, 59, 180, 143, 155, 189, 125, 91, 163, 177, 208, 115, 139, 72, 129, 177, 205, 221, 56, 22, 149, 38, 216, 21, 129, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 232, 139, 67, 253, 237, 99, 35, 239, 2, 255, 239, 251, 216, 196, 8, 70, 238, 9, 191, 49, 98, 113, 189, 34, 54, 150, 89, 201, 89, 221, 115, 58], &[0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 233, 103, 96, 210, 116, 101, 58, 57, 180, 41, 168, 126, 186, 174, 157, 58, 164, 253, 245, 139, 144, 150, 207, 11, 235, 199, 196, 229, 164, 194, 237, 141], &[0, 0, 0, 0, 0, 0, 0, 0, 144, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0]), (&[58, 99, 111, 100, 101], &[]), (&[58, 101, 120, 116, 114, 105, 110, 115, 105, 99, 95, 105, 110, 100, 101, 120], &[0, 0, 0, 0]), (&[58, 104, 101, 97, 112, 112, 97, 103, 101, 115], &[8, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 11, 106, 69, 50, 30, 250, 233, 42, 234, 21, 224, 116, 14, 199, 175, 231], &[2, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 14, 160, 236, 172, 118, 69, 125, 15, 155, 57, 185, 129, 221, 16, 112, 18], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 19, 142, 113, 97, 36, 145, 25, 45, 104, 222, 171, 126, 111, 86, 63, 225], &[2, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 40, 220, 203, 85, 155, 149, 196, 1, 104, 161, 178, 105, 101, 129, 181, 167], &[0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[40, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[10, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[30, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[20, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[100, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[21, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[31, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[11, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[101, 0, 0, 0, 0, 0, 0, 0, 209, 7, 209, 7, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[41, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 80, 154, 155, 110, 250, 147, 245, 187, 131, 248, 88, 240, 186, 191, 211, 11], &[6, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 85, 121, 41, 127, 77, 251, 150, 9, 231, 228, 194, 235, 171, 156, 228, 10], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 86, 239, 98, 39, 206, 203, 47, 7, 39, 76, 176, 87, 45, 143, 164, 194], &[101, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 106, 147, 17, 38, 51, 187, 51, 84, 230, 121, 82, 252, 221, 116, 12, 213], &[31, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[149, 17, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 245, 1]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[125, 21, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 221, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 1, 31, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 106, 99, 127, 98, 174, 42, 241, 199, 227, 30, 237, 126, 150, 190, 4, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[8, 11, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 189, 47, 11, 41, 160, 8, 163, 96, 9, 172, 68, 204, 160, 201, 105], &[101, 4, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 166, 97, 104, 247, 231, 37, 155, 102, 112, 160, 111, 37, 101, 227, 229, 242], &[112, 23, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 180, 154, 39, 56, 238, 179, 8, 150, 170, 203, 139, 63, 180, 100, 113, 189], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 194, 154, 3, 16, 225, 187, 69, 210, 12, 172, 231, 124, 203, 98, 201, 125], &[0, 225, 245, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 234, 7, 222, 43, 143, 1, 5, 22, 220, 163, 247, 239, 82, 247, 172, 90], &[12, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 247, 218, 208, 49, 115, 36, 174, 202, 232, 116, 75, 135, 252, 149, 242, 243], &[0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 1, 0, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 244, 1, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 87, 200, 117, 228, 207, 247, 65, 72, 228, 98, 143, 38, 75, 151, 76, 128], &[214, 61, 165, 212, 232, 0, 0, 0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 227, 253, 141, 247, 41, 112, 188, 130, 229, 38, 126, 160, 30, 221, 217, 73], &[1]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 109, 123, 24, 86, 30, 19, 159, 228, 49, 200, 33, 139, 70, 205, 244, 47, 40, 190, 110, 43, 138, 12, 26, 121, 5, 219, 103, 1, 110, 91, 142, 123], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 238, 43, 102, 225, 142, 104, 190, 12, 183, 86, 115, 25, 37, 223, 229, 65, 253, 167, 152, 54, 57, 147, 167, 137, 80, 161, 2, 235, 195, 174, 40, 244], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 118, 56, 0, 163, 106, 153, 253, 252, 124, 16, 246, 65, 95, 110, 230], &[6, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 148, 80, 191, 164, 185, 106, 63, 167, 163, 200, 244, 13, 166, 191, 50, 225], &[1]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 17, 218, 109, 31, 118, 29, 223, 155, 219, 76, 157, 110, 83, 3, 235, 212, 31, 97, 133, 141, 10, 86, 71, 161, 167, 191, 224, 137, 191, 146, 27, 233], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 38, 160, 142, 77, 12, 81, 144, 240, 24, 113, 224, 86, 155, 98, 144, 184, 103, 96, 8, 93, 153, 241, 126, 180, 231, 230, 181, 143, 235, 141, 98, 73], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 91, 143, 41, 219, 118, 207, 78, 103, 110, 79, 201, 177, 112, 64, 49, 45, 235, 237, 175, 205, 86, 55, 251, 60, 123, 173, 210, 205, 220, 230, 164, 69], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 123, 10, 161, 115, 94, 91, 165, 141, 50, 54, 49, 108, 103, 31, 228, 240, 14, 211, 102, 238, 114, 65, 124, 158, 208, 42, 83, 168, 1, 158, 133, 184], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 140, 3, 159, 247, 202, 161, 124, 206, 191, 202, 220, 68, 189, 159, 206, 106, 75, 102, 153, 196, 208, 61, 226, 227, 52, 154, 161, 220, 17, 25, 60, 215], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 140, 53, 210, 47, 69, 157, 119, 202, 76, 11, 11, 80, 53, 134, 151, 102, 214, 13, 24, 43, 151, 22, 171, 62, 136, 121, 224, 102, 71, 136, 153, 168], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 225, 44, 34, 212, 241, 98, 217, 160, 18, 201, 49, 146, 51, 218, 93, 62, 146, 60, 197, 225, 2, 155, 143, 144, 228, 114, 73, 201, 171, 37, 107, 53], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 244, 170, 194, 251, 227, 63, 3, 85, 75, 254, 181, 89, 234, 38, 144, 237, 133, 33, 202, 164, 190, 150, 30, 97, 201, 26, 201, 161, 83, 13, 206, 122], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 224, 205, 208, 98, 230, 234, 242, 66, 149, 173, 76, 207, 196, 29, 70, 9], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 255, 58, 225, 39, 112, 190, 162, 228, 141, 155, 222, 115, 133, 231, 162, 95], &[0, 0, 0, 0, 8, 0, 0, 0]), (&[240, 195, 101, 195, 207, 89, 214, 113, 235, 114, 218, 14, 122, 65, 19, 196, 159, 31, 5, 21, 244, 98, 205, 207, 132, 224, 241, 214, 4, 93, 252, 187], &[112, 23, 0, 0, 0, 0, 0, 0])]; +pub const _7: &[(&[u8], &[u8])] = &[(&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 2, 165, 193, 177, 154, 183, 160, 79, 83, 108, 81, 154, 202, 73, 131, 172], &[7, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 10, 152, 253, 190, 156, 230, 197, 88, 55, 87, 108, 96, 199, 175, 56, 80], &[24, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 128, 212, 30, 94, 22, 5, 103, 101, 188, 132, 97, 133, 16, 114, 201, 215], &[96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 138, 66, 243, 51, 35, 203, 92, 237, 59, 68, 221, 130, 95, 218, 159, 204], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 164, 71, 4, 181, 104, 210, 22, 103, 53, 106, 90, 5, 12, 17, 135, 70, 129, 228, 122, 25, 230, 178, 155, 10, 101, 185, 89, 23, 98, 206, 81, 67, 237, 48, 208, 38, 30, 93, 36, 163, 32, 23, 82, 80, 107, 32, 241, 92], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 29, 189, 125, 11, 86, 26, 65, 210, 60, 42, 70, 154, 212, 47, 189, 112, 213, 67, 139, 174, 130, 111, 111, 214, 7, 65, 49, 144, 195, 124, 54, 59], &[0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 100, 74, 81, 252, 33, 158, 145, 69, 184, 87, 123, 183, 118, 40, 118, 123, 28, 47, 115, 116, 142, 218, 139, 120, 139, 252, 102, 161, 181, 42, 32, 248], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 165, 212, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 108, 221, 179, 103, 175, 189, 88, 59, 180, 143, 155, 189, 125, 91, 163, 177, 208, 115, 139, 72, 129, 177, 205, 221, 56, 22, 149, 38, 216, 21, 129, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 232, 139, 67, 253, 237, 99, 35, 239, 2, 255, 239, 251, 216, 196, 8, 70, 238, 9, 191, 49, 98, 113, 189, 34, 54, 150, 89, 201, 89, 221, 115, 58], &[0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 233, 103, 96, 210, 116, 101, 58, 57, 180, 41, 168, 126, 186, 174, 157, 58, 164, 253, 245, 139, 144, 150, 207, 11, 235, 199, 196, 229, 164, 194, 237, 141], &[0, 0, 0, 0, 0, 0, 0, 0, 144, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0]), (&[58, 99, 111, 100, 101], &[]), (&[58, 101, 120, 116, 114, 105, 110, 115, 105, 99, 95, 105, 110, 100, 101, 120], &[0, 0, 0, 0]), (&[58, 104, 101, 97, 112, 112, 97, 103, 101, 115], &[8, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 11, 106, 69, 50, 30, 250, 233, 42, 234, 21, 224, 116, 14, 199, 175, 231], &[2, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 14, 160, 236, 172, 118, 69, 125, 15, 155, 57, 185, 129, 221, 16, 112, 18], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 19, 142, 113, 97, 36, 145, 25, 45, 104, 222, 171, 126, 111, 86, 63, 225], &[2, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 40, 220, 203, 85, 155, 149, 196, 1, 104, 161, 178, 105, 101, 129, 181, 167], &[0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[40, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[10, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[30, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[20, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[100, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[21, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[31, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[11, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[101, 0, 0, 0, 0, 0, 0, 0, 209, 7, 209, 7, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[41, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 80, 154, 155, 110, 250, 147, 245, 187, 131, 248, 88, 240, 186, 191, 211, 11], &[6, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 85, 121, 41, 127, 77, 251, 150, 9, 231, 228, 194, 235, 171, 156, 228, 10], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 86, 239, 98, 39, 206, 203, 47, 7, 39, 76, 176, 87, 45, 143, 164, 194], &[101, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 106, 147, 17, 38, 51, 187, 51, 84, 230, 121, 82, 252, 221, 116, 12, 213], &[31, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[149, 17, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 245, 1]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[125, 21, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 221, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 1, 31, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 106, 99, 127, 98, 174, 42, 241, 199, 227, 30, 237, 126, 150, 190, 4, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[8, 11, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 189, 47, 11, 41, 160, 8, 163, 96, 9, 172, 68, 204, 160, 201, 105], &[101, 4, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 166, 97, 104, 247, 231, 37, 155, 102, 112, 160, 111, 37, 101, 227, 229, 242], &[112, 23, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 180, 154, 39, 56, 238, 179, 8, 150, 170, 203, 139, 63, 180, 100, 113, 189], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 194, 154, 3, 16, 225, 187, 69, 210, 12, 172, 231, 124, 203, 98, 201, 125], &[0, 225, 245, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 234, 7, 222, 43, 143, 1, 5, 22, 220, 163, 247, 239, 82, 247, 172, 90], &[12, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 247, 218, 208, 49, 115, 36, 174, 202, 232, 116, 75, 135, 252, 149, 242, 243], &[0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 1, 0, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 244, 1, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 87, 200, 117, 228, 207, 247, 65, 72, 228, 98, 143, 38, 75, 151, 76, 128], &[214, 61, 165, 212, 232, 0, 0, 0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 227, 253, 141, 247, 41, 112, 188, 130, 229, 38, 126, 160, 30, 221, 217, 73], &[1]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 109, 123, 24, 86, 30, 19, 159, 228, 49, 200, 33, 139, 70, 205, 244, 47, 40, 190, 110, 43, 138, 12, 26, 121, 5, 219, 103, 1, 110, 91, 142, 123], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 238, 43, 102, 225, 142, 104, 190, 12, 183, 86, 115, 25, 37, 223, 229, 65, 253, 167, 152, 54, 57, 147, 167, 137, 80, 161, 2, 235, 195, 174, 40, 244], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 118, 56, 0, 163, 106, 153, 253, 252, 124, 16, 246, 65, 95, 110, 230], &[7, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 148, 80, 191, 164, 185, 106, 63, 167, 163, 200, 244, 13, 166, 191, 50, 225], &[0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 17, 218, 109, 31, 118, 29, 223, 155, 219, 76, 157, 110, 83, 3, 235, 212, 31, 97, 133, 141, 10, 86, 71, 161, 167, 191, 224, 137, 191, 146, 27, 233], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 38, 160, 142, 77, 12, 81, 144, 240, 24, 113, 224, 86, 155, 98, 144, 184, 103, 96, 8, 93, 153, 241, 126, 180, 231, 230, 181, 143, 235, 141, 98, 73], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 91, 143, 41, 219, 118, 207, 78, 103, 110, 79, 201, 177, 112, 64, 49, 45, 235, 237, 175, 205, 86, 55, 251, 60, 123, 173, 210, 205, 220, 230, 164, 69], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 123, 10, 161, 115, 94, 91, 165, 141, 50, 54, 49, 108, 103, 31, 228, 240, 14, 211, 102, 238, 114, 65, 124, 158, 208, 42, 83, 168, 1, 158, 133, 184], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 140, 3, 159, 247, 202, 161, 124, 206, 191, 202, 220, 68, 189, 159, 206, 106, 75, 102, 153, 196, 208, 61, 226, 227, 52, 154, 161, 220, 17, 25, 60, 215], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 140, 53, 210, 47, 69, 157, 119, 202, 76, 11, 11, 80, 53, 134, 151, 102, 214, 13, 24, 43, 151, 22, 171, 62, 136, 121, 224, 102, 71, 136, 153, 168], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 157, 255, 135, 106, 75, 148, 45, 10, 151, 17, 209, 130, 33, 137, 143, 17, 202, 57, 117, 21, 137, 235, 244, 212, 157, 116, 159, 107, 62, 73, 50, 146], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 225, 44, 34, 212, 241, 98, 217, 160, 18, 201, 49, 146, 51, 218, 93, 62, 146, 60, 197, 225, 2, 155, 143, 144, 228, 114, 73, 201, 171, 37, 107, 53], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 244, 170, 194, 251, 227, 63, 3, 85, 75, 254, 181, 89, 234, 38, 144, 237, 133, 33, 202, 164, 190, 150, 30, 97, 201, 26, 201, 161, 83, 13, 206, 122], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 224, 205, 208, 98, 230, 234, 242, 66, 149, 173, 76, 207, 196, 29, 70, 9], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 255, 58, 225, 39, 112, 190, 162, 228, 141, 155, 222, 115, 133, 231, 162, 95], &[0, 0, 0, 0, 9, 0, 0, 0]), (&[240, 195, 101, 195, 207, 89, 214, 113, 235, 114, 218, 14, 122, 65, 19, 196, 159, 31, 5, 21, 244, 98, 205, 207, 132, 224, 241, 214, 4, 93, 252, 187], &[88, 27, 0, 0, 0, 0, 0, 0])]; +pub const _8: &[(&[u8], &[u8])] = &[(&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 2, 165, 193, 177, 154, 183, 160, 79, 83, 108, 81, 154, 202, 73, 131, 172], &[8, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 10, 152, 253, 190, 156, 230, 197, 88, 55, 87, 108, 96, 199, 175, 56, 80], &[25, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 128, 212, 30, 94, 22, 5, 103, 101, 188, 132, 97, 133, 16, 114, 201, 215], &[100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 138, 66, 243, 51, 35, 203, 92, 237, 59, 68, 221, 130, 95, 218, 159, 204], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 164, 71, 4, 181, 104, 210, 22, 103, 53, 106, 90, 5, 12, 17, 135, 70, 129, 228, 122, 25, 230, 178, 155, 10, 101, 185, 89, 23, 98, 206, 81, 67, 237, 48, 208, 38, 30, 93, 36, 163, 32, 23, 82, 80, 107, 32, 241, 92], &[69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 29, 189, 125, 11, 86, 26, 65, 210, 60, 42, 70, 154, 212, 47, 189, 112, 213, 67, 139, 174, 130, 111, 111, 214, 7, 65, 49, 144, 195, 124, 54, 59], &[0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 100, 74, 81, 252, 33, 158, 145, 69, 184, 87, 123, 183, 118, 40, 118, 123, 28, 47, 115, 116, 142, 218, 139, 120, 139, 252, 102, 161, 181, 42, 32, 248], &[0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 165, 212, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 108, 221, 179, 103, 175, 189, 88, 59, 180, 143, 155, 189, 125, 91, 163, 177, 208, 115, 139, 72, 129, 177, 205, 221, 56, 22, 149, 38, 216, 21, 129, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0, 232, 3, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 232, 139, 67, 253, 237, 99, 35, 239, 2, 255, 239, 251, 216, 196, 8, 70, 238, 9, 191, 49, 98, 113, 189, 34, 54, 150, 89, 201, 89, 221, 115, 58], &[0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 233, 103, 96, 210, 116, 101, 58, 57, 180, 41, 168, 126, 186, 174, 157, 58, 164, 253, 245, 139, 144, 150, 207, 11, 235, 199, 196, 229, 164, 194, 237, 141], &[0, 0, 0, 0, 0, 0, 0, 0, 144, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0, 0, 0, 0, 0, 0, 0, 0, 208, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0, 244, 1, 0, 0, 0, 0, 0, 0]), (&[58, 99, 111, 100, 101], &[]), (&[58, 101, 120, 116, 114, 105, 110, 115, 105, 99, 95, 105, 110, 100, 101, 120], &[0, 0, 0, 0]), (&[58, 104, 101, 97, 112, 112, 97, 103, 101, 115], &[8, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 11, 106, 69, 50, 30, 250, 233, 42, 234, 21, 224, 116, 14, 199, 175, 231], &[2, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 14, 160, 236, 172, 118, 69, 125, 15, 155, 57, 185, 129, 221, 16, 112, 18], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 19, 142, 113, 97, 36, 145, 25, 45, 104, 222, 171, 126, 111, 86, 63, 225], &[2, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 40, 220, 203, 85, 155, 149, 196, 1, 104, 161, 178, 105, 101, 129, 181, 167], &[0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[40, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[10, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[30, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[20, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 62, 209, 75, 69, 237, 32, 208, 84, 240, 94, 55, 226, 84, 44, 254, 112, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[100, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 94, 90, 15, 75, 176, 234, 179, 121, 134, 37, 171, 24, 100, 84, 93, 19, 212, 232, 208, 104, 153, 217, 219, 77, 97, 219, 157, 238, 147, 186, 2, 221], &[21, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 165, 186, 85, 195, 163, 151, 212, 60, 23, 89, 63, 40, 154, 164, 151, 157, 10, 229, 146, 68, 179, 47, 3, 236, 19, 65, 97, 129, 175, 134, 209, 11], &[31, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 189, 225, 131, 90, 186, 237, 15, 242, 121, 87, 0, 55, 252, 73, 213, 189, 23, 110, 180, 130, 163, 178, 129, 109, 244, 252, 194, 204, 27, 200, 106, 202], &[11, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 213, 92, 123, 109, 126, 139, 228, 10, 88, 51, 198, 4, 8, 188, 78, 184, 171, 234, 78, 93, 168, 211, 37, 233, 8, 135, 156, 195, 59, 151, 205, 153], &[101, 0, 0, 0, 0, 0, 0, 0, 209, 7, 209, 7, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 66, 42, 219, 87, 159, 29, 191, 79, 56, 134, 197, 207, 163, 187, 140, 196, 216, 247, 229, 16, 146, 46, 205, 71, 180, 10, 28, 88, 41, 56, 34, 6, 69, 103, 185, 191, 60, 126, 225, 114, 12, 144, 76, 94, 12, 87, 247, 55], &[41, 0, 0, 0, 0, 0, 0, 0, 161, 15, 161, 15, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 80, 154, 155, 110, 250, 147, 245, 187, 131, 248, 88, 240, 186, 191, 211, 11], &[6, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 85, 121, 41, 127, 77, 251, 150, 9, 231, 228, 194, 235, 171, 156, 228, 10], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 86, 239, 98, 39, 206, 203, 47, 7, 39, 76, 176, 87, 45, 143, 164, 194], &[101, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 106, 147, 17, 38, 51, 187, 51, 84, 230, 121, 82, 252, 221, 116, 12, 213], &[31, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[149, 17, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 245, 1]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 131, 229, 133, 187, 197, 253, 206, 197, 114, 25, 192, 220, 129, 239, 95, 244, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[125, 21, 161, 15, 4, 101, 0, 0, 0, 0, 0, 0, 0, 221, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0, 1, 21, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0, 0, 1, 21, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0, 1, 31, 0, 0, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 146, 32, 225, 114, 190, 211, 22, 96, 95, 115, 241, 255, 123, 74, 222, 152, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 106, 99, 127, 98, 174, 42, 241, 199, 227, 30, 237, 126, 150, 190, 4, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[8, 11, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 156, 189, 47, 11, 41, 160, 8, 163, 96, 9, 172, 68, 204, 160, 201, 105], &[101, 4, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 166, 97, 104, 247, 231, 37, 155, 102, 112, 160, 111, 37, 101, 227, 229, 242], &[112, 23, 0, 0, 0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 180, 154, 39, 56, 238, 179, 8, 150, 170, 203, 139, 63, 180, 100, 113, 189], &[0, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 194, 154, 3, 16, 225, 187, 69, 210, 12, 172, 231, 124, 203, 98, 201, 125], &[0, 225, 245, 5]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 234, 7, 222, 43, 143, 1, 5, 22, 220, 163, 247, 239, 82, 247, 172, 90], &[12, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0]), (&[95, 62, 73, 7, 247, 22, 172, 137, 182, 52, 125, 21, 236, 236, 237, 202, 247, 218, 208, 49, 115, 36, 174, 202, 232, 116, 75, 135, 252, 149, 242, 243], &[0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 77, 254, 57, 245, 78, 123, 168, 74, 190, 191, 139, 138, 100, 234, 72, 46, 45, 174, 43, 141, 96, 79, 230, 7, 252, 242, 172, 39, 100, 43, 161, 177], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 137, 6, 59, 94, 171, 160, 104, 80, 196, 182, 201, 87, 28, 70, 86, 200, 124, 206, 182, 4, 38, 77, 37, 233, 32, 121, 227, 154, 137, 129, 91, 166], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 1, 0, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 232, 3, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 33, 143, 38, 199, 58, 221, 99, 72, 151, 85, 11, 64, 3, 178, 107, 198, 250, 67, 84, 127, 177, 206, 187, 248, 7, 171, 139, 143, 54, 116, 13, 218, 140, 198, 7, 172, 12, 47, 130, 190, 178, 198, 48, 211, 195, 137, 122, 61], &[4, 115, 116, 97, 107, 105, 110, 103, 32, 244, 1, 0, 0, 0, 0, 0, 0, 2]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 87, 200, 117, 228, 207, 247, 65, 72, 228, 98, 143, 38, 75, 151, 76, 128], &[214, 61, 165, 212, 232, 0, 0, 0]), (&[194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 227, 253, 141, 247, 41, 112, 188, 130, 229, 38, 126, 160, 30, 221, 217, 73], &[1]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 83, 50, 194, 39, 103, 192, 178, 217, 125, 32, 22, 246, 168, 239, 120, 222, 173, 2, 155, 120, 7, 166, 176, 226, 172, 7, 43, 102, 21, 204, 92, 8], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 76, 1, 78, 107, 248, 184, 194, 192, 17, 231, 41, 11, 133, 105, 107, 179, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 170, 10, 228, 226, 42, 96, 247, 17, 144, 247, 250, 141, 205, 84, 104, 175, 49, 59, 161, 58, 250, 178, 59, 219, 34, 1, 81, 12, 128, 142, 182, 22], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 109, 123, 24, 86, 30, 19, 159, 228, 49, 200, 33, 139, 70, 205, 244, 47, 40, 190, 110, 43, 138, 12, 26, 121, 5, 219, 103, 1, 110, 91, 142, 123], &[11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 99, 128, 64, 70, 131, 252, 137, 232, 35, 52, 80, 200, 170, 25, 80, 159, 230, 50, 156, 192, 179, 158, 9, 52, 58, 115, 101, 115, 115, 105, 111, 110, 58, 107, 101, 121, 115, 238, 43, 102, 225, 142, 104, 190, 12, 183, 86, 115, 25, 37, 223, 229, 65, 253, 167, 152, 54, 57, 147, 167, 137, 80, 161, 2, 235, 195, 174, 40, 244], &[21, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 114, 118, 56, 0, 163, 106, 153, 253, 252, 124, 16, 246, 65, 95, 110, 230], &[8, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 136, 220, 222, 147, 76, 101, 130, 39, 238, 29, 250, 252, 214, 225, 105, 3], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 148, 80, 191, 164, 185, 106, 63, 167, 163, 200, 244, 13, 166, 191, 50, 225], &[0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 17, 218, 109, 31, 118, 29, 223, 155, 219, 76, 157, 110, 83, 3, 235, 212, 31, 97, 133, 141, 10, 86, 71, 161, 167, 191, 224, 137, 191, 146, 27, 233], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 38, 160, 142, 77, 12, 81, 144, 240, 24, 113, 224, 86, 155, 98, 144, 184, 103, 96, 8, 93, 153, 241, 126, 180, 231, 230, 181, 143, 235, 141, 98, 73], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 47, 1, 107, 122, 93, 185, 48, 218, 189, 234, 3, 170, 104, 210, 115, 77, 47, 164, 122, 5, 87, 226, 13, 19, 12, 193, 224, 68, 248, 220, 87, 150], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 91, 143, 41, 219, 118, 207, 78, 103, 110, 79, 201, 177, 112, 64, 49, 45, 235, 237, 175, 205, 86, 55, 251, 60, 123, 173, 210, 205, 220, 230, 164, 69], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 123, 10, 161, 115, 94, 91, 165, 141, 50, 54, 49, 108, 103, 31, 228, 240, 14, 211, 102, 238, 114, 65, 124, 158, 208, 42, 83, 168, 1, 158, 133, 184], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 140, 3, 159, 247, 202, 161, 124, 206, 191, 202, 220, 68, 189, 159, 206, 106, 75, 102, 153, 196, 208, 61, 226, 227, 52, 154, 161, 220, 17, 25, 60, 215], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 140, 53, 210, 47, 69, 157, 119, 202, 76, 11, 11, 80, 53, 134, 151, 102, 214, 13, 24, 43, 151, 22, 171, 62, 136, 121, 224, 102, 71, 136, 153, 168], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 157, 255, 135, 106, 75, 148, 45, 10, 151, 17, 209, 130, 33, 137, 143, 17, 202, 57, 117, 21, 137, 235, 244, 212, 157, 116, 159, 107, 62, 73, 50, 146], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 225, 44, 34, 212, 241, 98, 217, 160, 18, 201, 49, 146, 51, 218, 93, 62, 146, 60, 197, 225, 2, 155, 143, 144, 228, 114, 73, 201, 171, 37, 107, 53], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 152, 239, 125, 192, 96, 67, 110, 78, 216, 3, 175, 7, 99, 43, 137, 182, 244, 170, 194, 251, 227, 63, 3, 85, 75, 254, 181, 89, 234, 38, 144, 237, 133, 33, 202, 164, 190, 150, 30, 97, 201, 26, 201, 161, 83, 13, 206, 122], &[44, 175, 112, 32, 141, 187, 198, 225, 208, 96, 126, 2, 8, 79, 212, 67, 222, 67, 84, 75, 213, 91, 72, 122, 231, 108, 125, 176, 42, 11, 117, 78, 2, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 224, 205, 208, 98, 230, 234, 242, 66, 149, 173, 76, 207, 196, 29, 70, 9], &[8, 21, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0]), (&[206, 197, 7, 13, 96, 157, 211, 73, 127, 114, 189, 224, 127, 201, 107, 160, 255, 58, 225, 39, 112, 190, 162, 228, 141, 155, 222, 115, 133, 231, 162, 95], &[0, 0, 0, 0, 10, 0, 0, 0]), (&[240, 195, 101, 195, 207, 89, 214, 113, 235, 114, 218, 14, 122, 65, 19, 196, 159, 31, 5, 21, 244, 98, 205, 207, 132, 224, 241, 214, 4, 93, 252, 187], &[64, 31, 0, 0, 0, 0, 0, 0])]; From 961618d4370166568af28684fd6ada3b78abd4d7 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 21 Feb 2020 16:47:09 +0900 Subject: [PATCH 59/75] Apply suggestions from code review Co-Authored-By: Shawn Tabrizi --- frame/session/src/historical.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frame/session/src/historical.rs b/frame/session/src/historical.rs index 4090b81054287..af7df557e3059 100644 --- a/frame/session/src/historical.rs +++ b/frame/session/src/historical.rs @@ -108,7 +108,7 @@ pub trait SessionManager: crate::SessionManager /// If there was a validator set change, its returns the set of new validators along with their /// full identifications. fn new_session(new_index: SessionIndex) -> Option>; - fn start_session(end_index: SessionIndex); + fn start_session(start_index: SessionIndex); fn end_session(end_index: SessionIndex); } @@ -147,8 +147,8 @@ impl crate::SessionManager for NoteHistoricalRoot>::start_session(end_index) + fn start_session(start_index: SessionIndex) { + >::start_session(start_index) } fn end_session(end_index: SessionIndex) { >::end_session(end_index) From 751b9930722df669f7ff1dac37c60975af4f3159 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 21 Feb 2020 18:05:14 +0900 Subject: [PATCH 60/75] nominators upgrade has been cleaned --- frame/staking/src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index b29ec4ca9c90a..c4eba5c444d8f 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -712,10 +712,7 @@ decl_storage! { linked_map hasher(blake2_256) T::AccountId => ValidatorPrefs; /// The map from nominator stash key to the set of stash keys of all validators to nominate. - /// - /// NOTE: is private so that we can ensure upgraded before all typical accesses. - /// Direct storage APIs can still bypass this protection. - Nominators get(fn nominators): + pub Nominators get(fn nominators): linked_map hasher(blake2_256) T::AccountId => Option>; /// The current era index. From e56e70aec214dde2038a1497fcbba0b0fa87c02c Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 21 Feb 2020 20:17:26 +0900 Subject: [PATCH 61/75] dynamic history depth implementation --- frame/staking/src/lib.rs | 47 ++++++++++++++++++++++++++++++-------- frame/staking/src/tests.rs | 26 ++++++++++++++++++--- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index c4eba5c444d8f..e770fad7e450e 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -679,10 +679,17 @@ impl Default for Forcing { fn default() -> Self { Forcing::NotForcing } } -const HISTORY_DEPTH: EraIndex = 84; - decl_storage! { trait Store for Module as Staking { + /// Set the number of era to keep in history. + /// + /// Information is kept for eras in `[current_era - history_depth + 1; current_era] + // TODO TODO: maybe better to make it `[current_era - history_depth; current_era]` + /// + /// Must be more than the number of era delayed by session otherwise. + /// i.e. active era must always be in history. + /// i.e. `active_era > current_era - history_depth` must be guaranteed. + HistoryDepth get(fn history_depth) config(): u32 = 84; /// The ideal number of staking participants. pub ValidatorCount get(fn validator_count) config(): u32; @@ -1419,6 +1426,21 @@ decl_module! { Self::update_ledger(&controller, &ledger); } + + #[weight = SimpleDispatchInfo::FixedOperational(500_000)] + fn set_history_depth(origin, #[compact] new_history_depth: EraIndex) { + ensure_root(origin)?; + if let Some(current_era) = Self::current_era() { + HistoryDepth::mutate(|history_depth| { + let last_kept = (current_era + 1).checked_sub(*history_depth).unwrap_or(0); + let new_last_kept = (current_era + 1).checked_sub(new_history_depth).unwrap_or(0); + for era_index in last_kept..new_last_kept { + Self::clear_era_information(era_index); + } + *history_depth = new_history_depth + }) + } + } } } @@ -1701,14 +1723,8 @@ impl Module { ErasStartSessionIndex::insert(¤t_era, &start_session_index); // Clean old era information. - if let Some(old_era) = current_era.checked_sub(HISTORY_DEPTH) { - >::remove_prefix(old_era); - >::remove_prefix(old_era); - >::remove_prefix(old_era); - >::remove(old_era); - >::remove(old_era); - >::remove(old_era); - ErasStartSessionIndex::remove(old_era); + if let Some(old_era) = current_era.checked_sub(Self::history_depth()) { + Self::clear_era_information(old_era); } // Set staking information for new era. @@ -1717,6 +1733,17 @@ impl Module { maybe_new_validators } + /// Clear all era information for given era. + fn clear_era_information(era_index: EraIndex) { + >::remove_prefix(era_index); + >::remove_prefix(era_index); + >::remove_prefix(era_index); + >::remove(era_index); + >::remove(era_index); + >::remove(era_index); + ErasStartSessionIndex::remove(era_index); + } + /// Apply previously-unapplied slashes on the beginning of a new era, after a delay. fn apply_unapplied_slashes(active_era: EraIndex) { let slash_defer_duration = T::SlashDeferDuration::get(); diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 0759153ec2df3..caa835d2a4a90 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2743,7 +2743,7 @@ fn slash_kicks_validators_not_nominators() { #[test] fn claim_reward_at_the_last_era() { // should check that: - // * rewards get paid until $HISTORY_DEPTH for both validators and nominators + // * rewards get paid until history_depth for both validators and nominators ExtBuilder::default().nominate(true).build().execute_with(|| { let init_balance_10 = Balances::total_balance(&10); let init_balance_100 = Balances::total_balance(&100); @@ -2781,11 +2781,11 @@ fn claim_reward_at_the_last_era() { assert!(total_payout_2 != total_payout_0); assert!(total_payout_2 != total_payout_1); - start_era(crate::HISTORY_DEPTH); + start_era(Staking::history_depth()); // This is the latest planned era in staking, not the active era let current_era = Staking::current_era().unwrap(); - assert!(current_era - crate::HISTORY_DEPTH == 0); + assert!(current_era - Staking::history_depth() == 0); assert_ok!(Staking::payout_validator(Origin::signed(10), 0)); assert_ok!(Staking::payout_validator(Origin::signed(10), 1)); assert_ok!(Staking::payout_validator(Origin::signed(10), 2)); @@ -3140,3 +3140,23 @@ fn test_upgrade_from_master_works() { }); } } + +#[test] +fn set_history_depth_works() { + ExtBuilder::default().build().execute_with(|| { + start_era(10); + Staking::set_history_depth(Origin::ROOT, 20).unwrap(); + assert!(::ErasTotalStake::contains_key(10 - 4)); + assert!(::ErasTotalStake::contains_key(10 - 5)); + Staking::set_history_depth(Origin::ROOT, 5).unwrap(); + assert!(::ErasTotalStake::contains_key(10 - 4)); + assert!(!::ErasTotalStake::contains_key(10 - 5)); + Staking::set_history_depth(Origin::ROOT, 4).unwrap(); + assert!(!::ErasTotalStake::contains_key(10 - 4)); + assert!(!::ErasTotalStake::contains_key(10 - 5)); + Staking::set_history_depth(Origin::ROOT, 8).unwrap(); + assert!(!::ErasTotalStake::contains_key(10 - 4)); + assert!(!::ErasTotalStake::contains_key(10 - 5)); + }); +} + From 975a6eb2dff007837d391e1837ea09566304180f Mon Sep 17 00:00:00 2001 From: thiolliere Date: Fri, 21 Feb 2020 20:39:50 +0900 Subject: [PATCH 62/75] make current_era - history_depth included --- frame/staking/src/lib.rs | 11 +++++------ frame/staking/src/tests.rs | 9 +++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index e770fad7e450e..8bc5d3047b992 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -681,10 +681,9 @@ impl Default for Forcing { decl_storage! { trait Store for Module as Staking { - /// Set the number of era to keep in history. + /// Number of era to keep in history. /// - /// Information is kept for eras in `[current_era - history_depth + 1; current_era] - // TODO TODO: maybe better to make it `[current_era - history_depth; current_era]` + /// Information is kept for eras in `[current_era - history_depth; current_era] /// /// Must be more than the number of era delayed by session otherwise. /// i.e. active era must always be in history. @@ -1432,8 +1431,8 @@ decl_module! { ensure_root(origin)?; if let Some(current_era) = Self::current_era() { HistoryDepth::mutate(|history_depth| { - let last_kept = (current_era + 1).checked_sub(*history_depth).unwrap_or(0); - let new_last_kept = (current_era + 1).checked_sub(new_history_depth).unwrap_or(0); + let last_kept = current_era.checked_sub(*history_depth).unwrap_or(0); + let new_last_kept = current_era.checked_sub(new_history_depth).unwrap_or(0); for era_index in last_kept..new_last_kept { Self::clear_era_information(era_index); } @@ -1723,7 +1722,7 @@ impl Module { ErasStartSessionIndex::insert(¤t_era, &start_session_index); // Clean old era information. - if let Some(old_era) = current_era.checked_sub(Self::history_depth()) { + if let Some(old_era) = current_era.checked_sub(Self::history_depth() + 1) { Self::clear_era_information(old_era); } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index caa835d2a4a90..8f2015df09f85 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2781,11 +2781,12 @@ fn claim_reward_at_the_last_era() { assert!(total_payout_2 != total_payout_0); assert!(total_payout_2 != total_payout_1); - start_era(Staking::history_depth()); + start_era(Staking::history_depth() + 1); // This is the latest planned era in staking, not the active era let current_era = Staking::current_era().unwrap(); - assert!(current_era - Staking::history_depth() == 0); + // Last kept is 1: + assert!(current_era - Staking::history_depth() == 1); assert_ok!(Staking::payout_validator(Origin::signed(10), 0)); assert_ok!(Staking::payout_validator(Origin::signed(10), 1)); assert_ok!(Staking::payout_validator(Origin::signed(10), 2)); @@ -3148,10 +3149,10 @@ fn set_history_depth_works() { Staking::set_history_depth(Origin::ROOT, 20).unwrap(); assert!(::ErasTotalStake::contains_key(10 - 4)); assert!(::ErasTotalStake::contains_key(10 - 5)); - Staking::set_history_depth(Origin::ROOT, 5).unwrap(); + Staking::set_history_depth(Origin::ROOT, 4).unwrap(); assert!(::ErasTotalStake::contains_key(10 - 4)); assert!(!::ErasTotalStake::contains_key(10 - 5)); - Staking::set_history_depth(Origin::ROOT, 4).unwrap(); + Staking::set_history_depth(Origin::ROOT, 3).unwrap(); assert!(!::ErasTotalStake::contains_key(10 - 4)); assert!(!::ErasTotalStake::contains_key(10 - 5)); Staking::set_history_depth(Origin::ROOT, 8).unwrap(); From 3d78f792ff81d788fd1d046d2e9e643997846c83 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sat, 22 Feb 2020 15:53:10 +0100 Subject: [PATCH 63/75] Change equality check to start era to less than or equal --- frame/staking/src/lib.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 8bc5d3047b992..cd28b3ce355e6 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -744,7 +744,7 @@ decl_storage! { /// This is keyed first by the era index to allow bulk deletion and then the stash account. /// /// Is it removed after `HISTORY_DEPTH` eras. - // If stakers hasn't been set or has been removed then empty exposure is returned. + /// If stakers hasn't been set or has been removed then empty exposure is returned. pub ErasStakers get(fn eras_stakers): double_map hasher(twox_64_concat) EraIndex, hasher(twox_64_concat) T::AccountId => Exposure>; @@ -758,7 +758,7 @@ decl_storage! { /// This is keyed fist by the era index to allow bulk deletion and then the stash account. /// /// Is it removed after `HISTORY_DEPTH` eras. - // If stakers hasn't been set or has been removed then empty exposure is returned. + /// If stakers hasn't been set or has been removed then empty exposure is returned. pub ErasStakersClipped get(fn eras_stakers_clipped): double_map hasher(twox_64_concat) EraIndex, hasher(twox_64_concat) T::AccountId => Exposure>; @@ -773,19 +773,19 @@ decl_storage! { double_map hasher(twox_64_concat) EraIndex, hasher(twox_64_concat) T::AccountId => ValidatorPrefs; - /// The per-validator era payout for one in the last `HISTORY_DEPTH` eras. + /// The total validator era payout for the last `HISTORY_DEPTH` eras. /// /// Eras that haven't finished yet doesn't have reward. pub ErasValidatorReward get(fn eras_validator_reward): map hasher(blake2_256) EraIndex => BalanceOf; /// Rewards for the last `HISTORY_DEPTH` eras. - // If reward hasn't been set or has been removed then 0 reward is returned. + /// If reward hasn't been set or has been removed then 0 reward is returned. pub ErasRewardPoints get(fn eras_reward_points): map hasher(blake2_256) EraIndex => EraRewardPoints; /// The total amount staked for the last `HISTORY_DEPTH` eras. - // If total hasn't been set or has been removed then 0 stake is returned. + /// If total hasn't been set or has been removed then 0 stake is returned. pub ErasTotalStake get(fn eras_total_stake): map hasher(blake2_256) EraIndex => BalanceOf; @@ -1569,9 +1569,6 @@ impl Module { } /// Ensures storage is upgraded to most recent necessary state. - /// - /// Right now it's a no-op as all networks that are supported by Substrate Frame Core are - /// running with the latest staking storage scheme. fn ensure_storage_upgraded() { if !IsUpgraded::get() { IsUpgraded::put(true); @@ -1634,7 +1631,7 @@ impl Module { fn start_session(start_session: SessionIndex) { let next_active_era = Self::active_era().map(|e| e + 1).unwrap_or(0); if let Some(next_active_era_start_session_index) = Self::eras_start_session_index(next_active_era) { - if next_active_era_start_session_index == start_session { + if next_active_era_start_session_index <= start_session { Self::start_era(start_session); } } From b834b4e498e87c97ad88e09ee719941ab27f3186 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sun, 23 Feb 2020 04:22:02 +0100 Subject: [PATCH 64/75] Use era specific validator prefs --- frame/staking/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index cd28b3ce355e6..c2a48e960e797 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1518,7 +1518,7 @@ impl Module { >::insert(&who, &ledger); let era_reward_points = >::get(&era); - let commission = Self::validators(&ledger.stash).commission; + let commission = Self::eras_validator_prefs(&era, &ledger.stash).commission; let exposure = >::get(&era, &ledger.stash); let exposure_part = Perbill::from_rational_approximation( From 23a4b2b3eb444d7e7c10505992669c2222d54bf5 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Sun, 23 Feb 2020 04:31:16 +0100 Subject: [PATCH 65/75] Add print statement and comment about start era if < --- frame/staking/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index c2a48e960e797..22acca59ece84 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1631,7 +1631,12 @@ impl Module { fn start_session(start_session: SessionIndex) { let next_active_era = Self::active_era().map(|e| e + 1).unwrap_or(0); if let Some(next_active_era_start_session_index) = Self::eras_start_session_index(next_active_era) { - if next_active_era_start_session_index <= start_session { + if next_active_era_start_session_index == start_session { + Self::start_era(start_session); + } else if next_active_era_start_session_index < start_session { + // This arm should never happen, but better handle it than to stall the + // staking pallet. + frame_support::print("Warning: A session appears to have been skipped."); Self::start_era(start_session); } } From 45bf05b115f845aa4bbcdc81d8bbed712fbd55d7 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 24 Feb 2020 11:11:24 +0900 Subject: [PATCH 66/75] fix next_reward overflow --- frame/staking/src/lib.rs | 20 ++++++----- frame/staking/src/tests.rs | 74 +++++++++++++++++++++----------------- 2 files changed, 52 insertions(+), 42 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 22acca59ece84..3fa76a56d25e3 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -394,8 +394,8 @@ pub struct StakingLedger { /// Any balance that is becoming free, which may eventually be transferred out /// of the stash (assuming it doesn't get slashed first). pub unlocking: Vec>, - /// The next era at which the staker can claim reward. - pub next_reward: EraIndex, + /// The latest and highest era which the staker has claimed reward for. + pub last_reward: Option, } impl< @@ -420,7 +420,7 @@ impl< total, active: self.active, unlocking, - next_reward: self.next_reward + last_reward: self.last_reward } } @@ -1012,7 +1012,7 @@ decl_module! { total: value, active: value, unlocking: vec![], - next_reward: Self::current_era().unwrap_or(0), + last_reward: Self::current_era(), }; Self::update_ledger(&controller, &item); } @@ -1457,11 +1457,13 @@ impl Module { -> DispatchResult { let mut nominator_ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; - if nominator_ledger.next_reward > era { + + if nominator_ledger.last_reward.map(|last_reward| last_reward >= era).unwrap_or(false) { return Err(Error::::InvalidEraToReward.into()); } - nominator_ledger.next_reward = era + 1; + // Note: This means that the reward for EraIndex::max() can be called indefinitely. + nominator_ledger.last_reward = Some(era); >::insert(&who, &nominator_ledger); let mut reward = Perbill::zero(); @@ -1510,11 +1512,11 @@ impl Module { fn do_payout_validator(who: T::AccountId, era: EraIndex) -> DispatchResult { let mut ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; - if ledger.next_reward > era { + if ledger.last_reward.map(|last_reward| last_reward >= era).unwrap_or(false) { return Err(Error::::InvalidEraToReward.into()); } - ledger.next_reward = era + 1; + ledger.last_reward = Some(era); >::insert(&who, &ledger); let era_reward_points = >::get(&era); @@ -2010,7 +2012,7 @@ impl Module { total: old.total, active: old.active, unlocking: old.unlocking, - next_reward: 0, + last_reward: None, } ); if let Err(e) = res { diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 8f2015df09f85..2f825081df669 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -70,12 +70,12 @@ fn basic_setup_works() { // Account 10 controls the stash from account 11, which is 100 * balance_factor units assert_eq!( Staking::ledger(&10), - Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![], next_reward: 0 }) + Some(StakingLedger { stash: 11, total: 1000, active: 1000, unlocking: vec![], last_reward: None }) ); // Account 20 controls the stash from account 21, which is 200 * balance_factor units assert_eq!( Staking::ledger(&20), - Some(StakingLedger { stash: 21, total: 1000, active: 1000, unlocking: vec![], next_reward: 0 }) + Some(StakingLedger { stash: 21, total: 1000, active: 1000, unlocking: vec![], last_reward: None }) ); // Account 1 does not control any stash assert_eq!(Staking::ledger(&1), None); @@ -89,7 +89,7 @@ fn basic_setup_works() { assert_eq!( Staking::ledger(100), - Some(StakingLedger { stash: 101, total: 500, active: 500, unlocking: vec![], next_reward: 0 }) + Some(StakingLedger { stash: 101, total: 500, active: 500, unlocking: vec![], last_reward: None }) ); assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); @@ -270,6 +270,7 @@ fn staking_should_work() { start_session(2); // add a new candidate for being a validator. account 3 controlled by 4. assert_ok!(Staking::bond(Origin::signed(3), 4, 1500, RewardDestination::Controller)); + let current_era_at_bond = Staking::current_era(); assert_ok!(Staking::validate(Origin::signed(4), ValidatorPrefs::default())); // No effects will be seen so far. @@ -311,7 +312,13 @@ fn staking_should_work() { // Note: the stashed value of 4 is still lock assert_eq!( Staking::ledger(&4), - Some(StakingLedger { stash: 3, total: 1500, active: 1500, unlocking: vec![], next_reward: 1 }) + Some(StakingLedger { + stash: 3, + total: 1500, + active: 1500, + unlocking: vec![], + last_reward: current_era_at_bond, + }) ); // e.g. it cannot spend more than 500 that it has free from the total 2000 assert_noop!( @@ -848,7 +855,7 @@ fn reward_destination_works() { total: 1000, active: 1000, unlocking: vec![], - next_reward: 0, + last_reward: None, })); // Compute total payout now for whole duration as other parameter won't change @@ -869,7 +876,7 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: vec![], - next_reward: 1, + last_reward: Some(0), })); //Change RewardDestination to Stash @@ -895,7 +902,7 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: vec![], - next_reward: 2, + last_reward: Some(1), })); // Change RewardDestination to Controller @@ -922,7 +929,7 @@ fn reward_destination_works() { total: 1000 + total_payout_0, active: 1000 + total_payout_0, unlocking: vec![], - next_reward: 3, + last_reward: Some(2), })); // Check that amount in staked account is NOT increased. assert_eq!(Balances::free_balance(11), recorded_stash_balance); @@ -988,7 +995,7 @@ fn bond_extra_works() { total: 1000, active: 1000, unlocking: vec![], - next_reward: 0, + last_reward: None, })); // Give account 11 some large free balance greater than total @@ -1002,7 +1009,7 @@ fn bond_extra_works() { total: 1000 + 100, active: 1000 + 100, unlocking: vec![], - next_reward: 0, + last_reward: None, })); // Call the bond_extra function with a large number, should handle it @@ -1013,7 +1020,7 @@ fn bond_extra_works() { total: 1000000, active: 1000000, unlocking: vec![], - next_reward: 0, + last_reward: None, })); }); } @@ -1048,7 +1055,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000, active: 1000, unlocking: vec![], - next_reward: 0, + last_reward: None, })); assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11), Exposure { total: 1000, own: 1000, others: vec![] }); @@ -1060,7 +1067,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000 + 100, active: 1000 + 100, unlocking: vec![], - next_reward: 0, + last_reward: None, })); // Exposure is a snapshot! only updated after the next era update. assert_ne!(Staking::eras_stakers(Staking::active_era().unwrap(), 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); @@ -1076,7 +1083,7 @@ fn bond_extra_and_withdraw_unbonded_works() { total: 1000 + 100, active: 1000 + 100, unlocking: vec![], - next_reward: 0, + last_reward: None, })); // Exposure is now updated. assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); @@ -1084,13 +1091,13 @@ fn bond_extra_and_withdraw_unbonded_works() { // Unbond almost all of the funds in stash. Staking::unbond(Origin::signed(10), 1000).unwrap(); assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], next_reward: 0 }) + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], last_reward: None }) ); // Attempting to free the balances now will fail. 2 eras need to pass. Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], next_reward: 0 })); + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], last_reward: None })); // trigger next era. start_era(3); @@ -1098,7 +1105,7 @@ fn bond_extra_and_withdraw_unbonded_works() { // nothing yet Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], next_reward: 0 })); + stash: 11, total: 1000 + 100, active: 100, unlocking: vec![UnlockChunk{ value: 1000, era: 2 + 3}], last_reward: None })); // trigger next era. start_era(5); @@ -1106,7 +1113,7 @@ fn bond_extra_and_withdraw_unbonded_works() { Staking::withdraw_unbonded(Origin::signed(10)).unwrap(); // Now the value is free and the staking ledger is updated. assert_eq!(Staking::ledger(&10), Some(StakingLedger { - stash: 11, total: 100, active: 100, unlocking: vec![], next_reward: 0 })); + stash: 11, total: 100, active: 100, unlocking: vec![], last_reward: None })); }) } @@ -1167,7 +1174,7 @@ fn rebond_works() { total: 1000, active: 1000, unlocking: vec![], - next_reward: 0, + last_reward: None, }) ); @@ -1192,7 +1199,7 @@ fn rebond_works() { value: 900, era: 2 + 3, }], - next_reward: 0, + last_reward: None, }) ); @@ -1205,7 +1212,7 @@ fn rebond_works() { total: 1000, active: 1000, unlocking: vec![], - next_reward: 0, + last_reward: None, }) ); @@ -1218,7 +1225,7 @@ fn rebond_works() { total: 1000, active: 100, unlocking: vec![UnlockChunk { value: 900, era: 5 }], - next_reward: 0, + last_reward: None, }) ); @@ -1231,7 +1238,7 @@ fn rebond_works() { total: 1000, active: 600, unlocking: vec![UnlockChunk { value: 400, era: 5 }], - next_reward: 0, + last_reward: None, }) ); @@ -1244,7 +1251,7 @@ fn rebond_works() { total: 1000, active: 1000, unlocking: vec![], - next_reward: 0, + last_reward: None, }) ); @@ -1263,7 +1270,7 @@ fn rebond_works() { UnlockChunk { value: 300, era: 5 }, UnlockChunk { value: 300, era: 5 }, ], - next_reward: 0, + last_reward: None, }) ); @@ -1279,7 +1286,7 @@ fn rebond_works() { UnlockChunk { value: 300, era: 5 }, UnlockChunk { value: 100, era: 5 }, ], - next_reward: 0, + last_reward: None, }) ); }) @@ -1312,7 +1319,7 @@ fn rebond_is_fifo() { total: 1000, active: 1000, unlocking: vec![], - next_reward: 0, + last_reward: None, }) ); @@ -1329,7 +1336,7 @@ fn rebond_is_fifo() { unlocking: vec![ UnlockChunk { value: 400, era: 2 + 3 }, ], - next_reward: 0, + last_reward: None, }) ); @@ -1347,7 +1354,7 @@ fn rebond_is_fifo() { UnlockChunk { value: 400, era: 2 + 3 }, UnlockChunk { value: 300, era: 3 + 3 }, ], - next_reward: 0, + last_reward: None, }) ); @@ -1366,7 +1373,7 @@ fn rebond_is_fifo() { UnlockChunk { value: 300, era: 3 + 3 }, UnlockChunk { value: 200, era: 4 + 3 }, ], - next_reward: 0, + last_reward: None, }) ); @@ -1382,7 +1389,7 @@ fn rebond_is_fifo() { UnlockChunk { value: 400, era: 2 + 3 }, UnlockChunk { value: 100, era: 3 + 3 }, ], - next_reward: 0, + last_reward: None, }) ); }) @@ -1408,7 +1415,7 @@ fn reward_to_stake_works() { // Now lets lower account 20 stake assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 21).total, 69); - >::insert(&20, StakingLedger { stash: 21, total: 69, active: 69, unlocking: vec![], next_reward: 0 }); + >::insert(&20, StakingLedger { stash: 21, total: 69, active: 69, unlocking: vec![], last_reward: None }); // Compute total payout now for whole duration as other parameter won't change let total_payout_0 = current_total_payout_for_duration(3000); @@ -1628,6 +1635,7 @@ fn bond_with_no_staked_value() { ); // bonded with absolute minimum value possible. assert_ok!(Staking::bond(Origin::signed(1), 2, 5, RewardDestination::Controller)); + let current_era_at_bond = Staking::current_era(); assert_eq!(Balances::locks(&1)[0].amount, 5); // unbonding even 1 will cause all to be unbonded. @@ -1639,7 +1647,7 @@ fn bond_with_no_staked_value() { active: 0, total: 5, unlocking: vec![UnlockChunk {value: 5, era: 3}], - next_reward: 0, + last_reward: current_era_at_bond, }) ); From 3dce1b01fd30d4a315a9f508eaa2bb7faa78ccc0 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 24 Feb 2020 12:16:44 +0900 Subject: [PATCH 67/75] make more check for bad era claim for zero cost --- frame/staking/src/lib.rs | 34 ++++++++++++++++++++++-------- frame/staking/src/tests.rs | 43 ++++++++++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 13 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 3fa76a56d25e3..1f463dcf7d04f 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -775,9 +775,9 @@ decl_storage! { /// The total validator era payout for the last `HISTORY_DEPTH` eras. /// - /// Eras that haven't finished yet doesn't have reward. + /// Eras that haven't finished yet or has been removed doesn't have reward. pub ErasValidatorReward get(fn eras_validator_reward): - map hasher(blake2_256) EraIndex => BalanceOf; + map hasher(blake2_256) EraIndex => Option>; /// Rewards for the last `HISTORY_DEPTH` eras. /// If reward hasn't been set or has been removed then 0 reward is returned. @@ -936,6 +936,8 @@ decl_error! { InvalidEraToReward, /// Can not rebond without unlocking chunks. NoUnlockChunk, + /// Invalid number of nominations. + InvalidNumberOfNominations, } } @@ -1456,6 +1458,19 @@ impl Module { fn do_payout_nominator(who: T::AccountId, era: EraIndex, validators: Vec<(T::AccountId, u32)>) -> DispatchResult { + // validators len must not exceed `MAX_NOMINATIONS` to avoid querying more validator + // exposure than necessary. + if validators.len() > MAX_NOMINATIONS { + return Err(Error::::InvalidNumberOfNominations.into()); + } + + let era_payout = match >::get(&era) { + Some(era_payout) => era_payout, + // Note: Era has no reward to be claimed, era may be futur. better not to update + // `ledger.last_reward` in this case. + None => return Err(Error::::InvalidEraToReward.into()) + }; + let mut nominator_ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; if nominator_ledger.last_reward.map(|last_reward| last_reward >= era).unwrap_or(false) { @@ -1469,9 +1484,7 @@ impl Module { let mut reward = Perbill::zero(); let era_reward_points = >::get(&era); - // Note: iterator take only `MAX_NOMINATIONS` to avoid querying more validator exposure - // than necessary. Anyway a nominator can't validate more than `MAX_NOMINATIONS`. - for (validator, nominator_index) in validators.into_iter().take(MAX_NOMINATIONS) { + for (validator, nominator_index) in validators.into_iter() { let commission = Self::eras_validator_prefs(&era, &validator).commission; let validator_exposure = >::get(&era, &validator); @@ -1501,8 +1514,6 @@ impl Module { } } - // Note: this is zero if the era is not finished yet. - let era_payout = >::get(&era); if let Some(imbalance) = Self::make_payout(&nominator_ledger.stash, reward * era_payout) { Self::deposit_event(RawEvent::Reward(who, imbalance.peek())); } @@ -1511,6 +1522,13 @@ impl Module { } fn do_payout_validator(who: T::AccountId, era: EraIndex) -> DispatchResult { + let era_payout = match >::get(&era) { + Some(era_payout) => era_payout, + // Note: Era has no reward to be claimed, era may be futur. better not to update + // `ledger.last_reward` in this case. + None => return Err(Error::::InvalidEraToReward.into()) + }; + let mut ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; if ledger.last_reward.map(|last_reward| last_reward >= era).unwrap_or(false) { return Err(Error::::InvalidEraToReward.into()); @@ -1540,8 +1558,6 @@ impl Module { ) ); - // This is zero if the era is not finished yet. - let era_payout = >::get(&era); if let Some(imbalance) = Self::make_payout(&ledger.stash, reward * era_payout) { Self::deposit_event(RawEvent::Reward(who, imbalance.peek())); } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 2f825081df669..689a652325d74 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -2749,9 +2749,11 @@ fn slash_kicks_validators_not_nominators() { } #[test] -fn claim_reward_at_the_last_era() { +fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { // should check that: // * rewards get paid until history_depth for both validators and nominators + // * an invalid era to claim doesn't update last_reward + // * double claim of one era fails ExtBuilder::default().nominate(true).build().execute_with(|| { let init_balance_10 = Balances::total_balance(&10); let init_balance_100 = Balances::total_balance(&100); @@ -2791,18 +2793,51 @@ fn claim_reward_at_the_last_era() { start_era(Staking::history_depth() + 1); + let active_era = Staking::active_era().unwrap(); + // This is the latest planned era in staking, not the active era let current_era = Staking::current_era().unwrap(); + // Last kept is 1: assert!(current_era - Staking::history_depth() == 1); - assert_ok!(Staking::payout_validator(Origin::signed(10), 0)); + assert_noop!( + Staking::payout_validator(Origin::signed(10), 0), + // Fail: Era out of history + DispatchError::Module { index: 0, error: 9, message: Some("InvalidEraToReward") } + ); assert_ok!(Staking::payout_validator(Origin::signed(10), 1)); assert_ok!(Staking::payout_validator(Origin::signed(10), 2)); - assert_ok!(Staking::payout_nominator(Origin::signed(100), 0, vec![(11, 0)])); + assert_noop!( + Staking::payout_validator(Origin::signed(10), 2), + // Fail: Double claim + DispatchError::Module { index: 0, error: 9, message: Some("InvalidEraToReward") } + ); + assert_noop!( + Staking::payout_validator(Origin::signed(10), active_era), + // Fail: Era not finished yet + DispatchError::Module { index: 0, error: 9, message: Some("InvalidEraToReward") } + ); + + assert_noop!( + Staking::payout_nominator(Origin::signed(100), 0, vec![(11, 0)]), + // Fail: Era out of history + DispatchError::Module { index: 0, error: 9, message: Some("InvalidEraToReward") } + ); assert_ok!(Staking::payout_nominator(Origin::signed(100), 1, vec![(11, 0)])); assert_ok!(Staking::payout_nominator(Origin::signed(100), 2, vec![(11, 0)])); + assert_noop!( + Staking::payout_nominator(Origin::signed(100), 2, vec![(11, 0)]), + // Fail: Double claim + DispatchError::Module { index: 0, error: 9, message: Some("InvalidEraToReward") } + ); + assert_noop!( + Staking::payout_nominator(Origin::signed(100), active_era, vec![(11, 0)]), + // Fail: Era not finished yet + DispatchError::Module { index: 0, error: 9, message: Some("InvalidEraToReward") } + ); - // Era 0 can't be rewarded anymore, only era 1 and 2 can be rewarded + // Era 0 can't be rewarded anymore and current era can't be rewarded yet + // only era 1 and 2 can be rewarded. assert_eq!( Balances::total_balance(&10), From 22c46b5f720c199d89ea91c13c0a6f2d3bdbe232 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 24 Feb 2020 12:26:56 +0900 Subject: [PATCH 68/75] small refactor --- frame/staking/src/lib.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 1f463dcf7d04f..ed65cd2aaebe1 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1464,12 +1464,10 @@ impl Module { return Err(Error::::InvalidNumberOfNominations.into()); } - let era_payout = match >::get(&era) { - Some(era_payout) => era_payout, - // Note: Era has no reward to be claimed, era may be futur. better not to update - // `ledger.last_reward` in this case. - None => return Err(Error::::InvalidEraToReward.into()) - }; + // Note: if era has no reward to be claimed, era may be futur. better not to update + // `nominator_ledger.last_reward` in this case. + let era_payout = >::get(&era) + .ok_or_else(|| Error::::InvalidEraToReward)?; let mut nominator_ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; @@ -1522,12 +1520,10 @@ impl Module { } fn do_payout_validator(who: T::AccountId, era: EraIndex) -> DispatchResult { - let era_payout = match >::get(&era) { - Some(era_payout) => era_payout, - // Note: Era has no reward to be claimed, era may be futur. better not to update - // `ledger.last_reward` in this case. - None => return Err(Error::::InvalidEraToReward.into()) - }; + // Note: if era has no reward to be claimed, era may be futur. better not to update + // `ledger.last_reward` in this case. + let era_payout = >::get(&era) + .ok_or_else(|| Error::::InvalidEraToReward)?; let mut ledger = >::get(&who).ok_or_else(|| Error::::NotController)?; if ledger.last_reward.map(|last_reward| last_reward >= era).unwrap_or(false) { From 24d334f566e48151812e599b215497102e3da13b Mon Sep 17 00:00:00 2001 From: thiolliere Date: Wed, 26 Feb 2020 10:31:37 +0100 Subject: [PATCH 69/75] code refactor + fix use of deprecated storage --- frame/staking/src/lib.rs | 110 ++++++++++++++++++++----------------- frame/staking/src/tests.rs | 78 ++++++++++++++++---------- 2 files changed, 109 insertions(+), 79 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index ed65cd2aaebe1..92635c300933a 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -310,17 +310,6 @@ pub struct EraRewardPoints { individual: BTreeMap, } -/// Deprecated. Used for migration only. -// Reward points of an era. Used to split era total payout between validators. -#[derive(Encode, Decode, Default)] -pub struct EraPoints { - // Total number of points. Equals the sum of reward points for each validator. - total: u32, - // The reward points earned by a given validator. The index of this vec corresponds to the - // index into the current validator set. - individual: Vec, -} - /// Indicates the initial status of the staker. #[derive(RuntimeDebug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -838,32 +827,6 @@ decl_storage! { /// /// True for new networks. IsUpgraded build(|_| true): bool; - - /// Deprecated. - SlotStake: BalanceOf; - - /// Deprecated. - // The currently elected validator set keyed by stash account ID. - CurrentElected: Vec; - - /// Deprecated - // The start of the current era. - CurrentEraStart: MomentOf; - - /// Deprecated - // The session index at which the current era started. - CurrentEraStartSessionIndex: SessionIndex; - - /// Deprecated - // Rewards for the current era. Using indices of current elected set. - CurrentEraPointsEarned: EraPoints; - - /// Deprecated - // Nominators for a particular account that is in action right now. You can't iterate - // through validators here, but you can find them in the Session module. - // - // This is keyed by the stash account. - Stakers: map hasher(blake2_256) T::AccountId => Exposure>; } add_extra_genesis { config(stakers): @@ -1976,6 +1939,51 @@ impl Module { // * CurrentEraStartSessionIndex // * CurrentEraPointsEarned fn do_upgrade() { + /// Deprecated storages used for migration only. + mod deprecated { + use crate::{Trait, BalanceOf, MomentOf, SessionIndex, Exposure}; + use codec::{Encode, Decode}; + use frame_support::{decl_module, decl_storage}; + + /// Reward points of an era. Used to split era total payout between validators. + #[derive(Encode, Decode, Default)] + pub struct EraPoints { + /// Total number of points. Equals the sum of reward points for each validator. + pub total: u32, + /// The reward points earned by a given validator. The index of this vec corresponds to the + /// index into the current validator set. + pub individual: Vec, + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin { } + } + + decl_storage! { + pub trait Store for Module as Staking { + pub SlotStake: BalanceOf; + + /// The currently elected validator set keyed by stash account ID. + pub CurrentElected: Vec; + + /// The start of the current era. + pub CurrentEraStart: MomentOf; + + /// The session index at which the current era started. + pub CurrentEraStartSessionIndex: SessionIndex; + + /// Rewards for the current era. Using indices of current elected set. + pub CurrentEraPointsEarned: EraPoints; + + /// Nominators for a particular account that is in action right now. You can't iterate + /// through validators here, but you can find them in the Session module. + /// + /// This is keyed by the stash account. + pub Stakers: map hasher(blake2_256) T::AccountId => Exposure>; + } + } + } + #[derive(Encode, Decode)] struct OldStakingLedger { stash: AccountId, @@ -1986,16 +1994,16 @@ impl Module { unlocking: Vec>, } - let current_era_start_index = as Store>::CurrentEraStartSessionIndex::get(); + let current_era_start_index = deprecated::CurrentEraStartSessionIndex::get(); let current_era = as Store>::CurrentEra::get().unwrap_or(0); as Store>::ErasStartSessionIndex::insert(current_era, current_era_start_index); as Store>::ActiveEra::put(current_era); - as Store>::ActiveEraStart::put( as Store>::CurrentEraStart::get()); + as Store>::ActiveEraStart::put(deprecated::CurrentEraStart::::get()); - let current_elected = as Store>::CurrentElected::get(); + let current_elected = deprecated::CurrentElected::::get(); let mut current_total_stake = >::zero(); for validator in ¤t_elected { - let exposure = as Store>::Stakers::get(validator); + let exposure = deprecated::Stakers::::get(validator); current_total_stake += exposure.total; as Store>::ErasStakers::insert(current_era, validator, &exposure); @@ -2012,7 +2020,7 @@ impl Module { } as Store>::ErasTotalStake::insert(current_era, current_total_stake); - let points = as Store>::CurrentEraPointsEarned::get(); + let points = deprecated::CurrentEraPointsEarned::get(); as Store>::ErasRewardPoints::insert(current_era, EraRewardPoints { total: points.total, individual: current_elected.iter().cloned().zip(points.individual.iter().cloned()).collect(), @@ -2035,12 +2043,12 @@ impl Module { // Kill old storages - as Store>::Stakers::remove_all(); - as Store>::SlotStake::kill(); - as Store>::CurrentElected::kill(); - as Store>::CurrentEraStart::kill(); - as Store>::CurrentEraStartSessionIndex::kill(); - as Store>::CurrentEraPointsEarned::kill(); + deprecated::Stakers::::remove_all(); + deprecated::SlotStake::::kill(); + deprecated::CurrentElected::::kill(); + deprecated::CurrentEraStart::::kill(); + deprecated::CurrentEraStartSessionIndex::kill(); + deprecated::CurrentEraPointsEarned::kill(); } } @@ -2069,8 +2077,12 @@ impl SessionManager> -> Option>)>> { >::new_session(new_index).map(|validators| { + let current_era = Self::current_era() + // Must be some as a new era has been created. + .unwrap_or(0); + validators.into_iter().map(|v| { - let exposure = >::get(&v); + let exposure = Self::eras_stakers(current_era, &v); (v, exposure) }).collect() }) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 689a652325d74..41a17e0c970ae 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -26,7 +26,9 @@ use frame_support::{ assert_ok, assert_noop, traits::{Currency, ReservableCurrency}, dispatch::DispatchError, StorageMap, + storage::migration::{put_storage_value, get_storage_value}, }; +use sp_io::hashing::blake2_256; use substrate_test_utils::assert_eq_uvec; use crate::Store; @@ -2858,28 +2860,34 @@ fn upgrade_works() { assert_eq!(Session::validators(), vec![21, 11]); // Insert fake data to check the migration - ::CurrentElected::put(vec![21, 31]); - ::CurrentEraStartSessionIndex::put(5); - ::CurrentEraStart::put(777); - ::Stakers::insert(11, Exposure { - total: 10, - own: 10, - others: vec![], - }); - ::Stakers::insert(21, Exposure { - total: 20, - own: 20, - others: vec![], - }); - ::Stakers::insert(31, Exposure { - total: 30, - own: 30, - others: vec![], - }); - ::CurrentEraPointsEarned::put(EraPoints { - total: 12, - individual: vec![2, 10], - }); + put_storage_value::>(b"Staking", b"CurrentElected", b"", vec![21, 31]); + put_storage_value::(b"Staking", b"CurrentEraStartSessionIndex", b"", 5); + put_storage_value::>(b"Staking", b"CurrentEraStart", b"", 777); + put_storage_value( + b"Staking", b"Stakers", &blake2_256(&11u64.encode()), + Exposure:: { + total: 10, + own: 10, + others: vec![], + } + ); + put_storage_value( + b"Staking", b"Stakers", &blake2_256(&21u64.encode()), + Exposure:: { + total: 20, + own: 20, + others: vec![], + } + ); + put_storage_value( + b"Staking", b"Stakers", &blake2_256(&31u64.encode()), + Exposure:: { + total: 30, + own: 30, + others: vec![], + } + ); + put_storage_value::<(u32, Vec)>(b"Staking", b"CurrentEraPointsEarned", b"", (12, vec![2, 10])); ::ErasStakers::remove_all(); ::ErasStakersClipped::remove_all(); @@ -3093,13 +3101,23 @@ fn test_upgrade_from_master_works() { } let mut ext = sp_io::TestExternalities::from(storage); ext.execute_with(|| { - let old_stakers = ::CurrentElected::get(); + let old_stakers = + get_storage_value::>(b"Staking", b"CurrentElected", b"").unwrap(); let old_staker_0 = old_stakers[0]; let old_staker_1 = old_stakers[1]; - let old_current_era = ::CurrentEra::get().unwrap(); - let old_staker_0_exposure = ::Stakers::get(old_staker_0); - let old_staker_1_exposure = ::Stakers::get(old_staker_1); - let old_era_points_earned = ::CurrentEraPointsEarned::get(); + let old_current_era = + get_storage_value::(b"Staking", b"CurrentEra", b"").unwrap(); + let old_staker_0_exposure = get_storage_value::>( + b"Staking", b"Stakers", &blake2_256(&old_staker_0.encode()) + ).unwrap(); + let old_staker_1_exposure = get_storage_value::>( + b"Staking", b"Stakers", &blake2_256(&old_staker_1.encode()) + ).unwrap(); + let ( + old_era_points_earned_total, + old_era_points_earned_individual + ) = get_storage_value::<(u32, Vec)>(b"Staking", b"CurrentEraPointsEarned", b"") + .unwrap_or((0, vec![])); Staking::ensure_storage_upgraded(); assert!(::IsUpgraded::get()); @@ -3165,16 +3183,16 @@ fn test_upgrade_from_master_works() { // Check ErasRewardPoints assert_eq!(::ErasRewardPoints::iter().count(), 1); let mut individual = BTreeMap::new(); - if let Some(p) = old_era_points_earned.individual.get(0) { + if let Some(p) = old_era_points_earned_individual.get(0) { individual.insert(old_staker_0, p.clone()); } - if let Some(p) = old_era_points_earned.individual.get(1) { + if let Some(p) = old_era_points_earned_individual.get(1) { individual.insert(old_staker_1, p.clone()); } assert_eq!( ::ErasRewardPoints::get(current_era), EraRewardPoints { - total: old_era_points_earned.total, + total: old_era_points_earned_total, individual, } ); From 7edfdae53511e84e194349c99c9062d128b88866 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Wed, 26 Feb 2020 15:38:14 +0100 Subject: [PATCH 70/75] fix wasm build --- frame/staking/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 92635c300933a..a2cf24faf074a 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1944,6 +1944,7 @@ impl Module { use crate::{Trait, BalanceOf, MomentOf, SessionIndex, Exposure}; use codec::{Encode, Decode}; use frame_support::{decl_module, decl_storage}; + use sp_std::prelude::*; /// Reward points of an era. Used to split era total payout between validators. #[derive(Encode, Decode, Default)] From 4caa747c88d01bc71adaae49e1a9536a035732a2 Mon Sep 17 00:00:00 2001 From: thiolliere Date: Wed, 26 Feb 2020 15:46:28 +0100 Subject: [PATCH 71/75] add comment --- frame/staking/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 1d57fd850b947..2e24d219fab71 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1394,6 +1394,9 @@ decl_module! { Self::update_ledger(&controller, &ledger); } + /// Set history_depth value. + /// + /// Origin must be root. #[weight = SimpleDispatchInfo::FixedOperational(500_000)] fn set_history_depth(origin, #[compact] new_history_depth: EraIndex) { ensure_root(origin)?; From 015c39a80c5f775b3e104db6cfe3683f23d73d88 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Fri, 28 Feb 2020 03:01:27 +0200 Subject: [PATCH 72/75] Fix tests --- frame/staking/src/tests.rs | 45 +++++++++++--------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 1a116272b0f8a..3de8610de36dd 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -25,9 +25,10 @@ use sp_staking::offence::OffenceDetails; use frame_support::{ assert_ok, assert_noop, traits::{Currency, ReservableCurrency}, - dispatch::DispatchError, StorageMap, + StorageMap, storage::migration::{put_storage_value, get_storage_value}, }; +use pallet_balances::Error as BalancesError; use sp_io::hashing::blake2_256; use substrate_test_utils::assert_eq_uvec; use crate::Store; @@ -41,11 +42,7 @@ fn force_unstake_works() { // Cant transfer assert_noop!( Balances::transfer(Origin::signed(11), 1, 10), - DispatchError::Module { - index: 0, - error: 1, - message: Some("LiquidityRestrictions"), - } + BalancesError::::LiquidityRestrictions ); // Force unstake requires root. assert_noop!(Staking::force_unstake(Origin::signed(11), 11), BadOrigin); @@ -325,11 +322,7 @@ fn staking_should_work() { // e.g. it cannot spend more than 500 that it has free from the total 2000 assert_noop!( Balances::reserve(&3, 501), - DispatchError::Module { - index: 0, - error: 1, - message: Some("LiquidityRestrictions"), - } + BalancesError::::LiquidityRestrictions ); assert_ok!(Balances::reserve(&3, 409)); }); @@ -775,11 +768,7 @@ fn cannot_transfer_staked_balance() { // Confirm account 11 cannot transfer as a result assert_noop!( Balances::transfer(Origin::signed(11), 20, 1), - DispatchError::Module { - index: 0, - error: 1, - message: Some("LiquidityRestrictions"), - } + BalancesError::::LiquidityRestrictions ); // Give account 11 extra free balance @@ -804,11 +793,7 @@ fn cannot_transfer_staked_balance_2() { // Confirm account 21 can transfer at most 1000 assert_noop!( Balances::transfer(Origin::signed(21), 20, 1001), - DispatchError::Module { - index: 0, - error: 1, - message: Some("LiquidityRestrictions"), - } + BalancesError::::LiquidityRestrictions ); assert_ok!(Balances::transfer(Origin::signed(21), 20, 1000)); }); @@ -827,11 +812,7 @@ fn cannot_reserve_staked_balance() { // Confirm account 11 cannot transfer as a result assert_noop!( Balances::reserve(&11, 1), - DispatchError::Module { - index: 0, - error: 1, - message: Some("LiquidityRestrictions"), - } + BalancesError::::LiquidityRestrictions ); // Give account 11 extra free balance @@ -2815,37 +2796,37 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { assert_noop!( Staking::payout_validator(Origin::signed(10), 0), // Fail: Era out of history - DispatchError::Module { index: 0, error: 9, message: Some("InvalidEraToReward") } + Error::::InvalidEraToReward ); assert_ok!(Staking::payout_validator(Origin::signed(10), 1)); assert_ok!(Staking::payout_validator(Origin::signed(10), 2)); assert_noop!( Staking::payout_validator(Origin::signed(10), 2), // Fail: Double claim - DispatchError::Module { index: 0, error: 9, message: Some("InvalidEraToReward") } + Error::::InvalidEraToReward ); assert_noop!( Staking::payout_validator(Origin::signed(10), active_era), // Fail: Era not finished yet - DispatchError::Module { index: 0, error: 9, message: Some("InvalidEraToReward") } + Error::::InvalidEraToReward ); assert_noop!( Staking::payout_nominator(Origin::signed(100), 0, vec![(11, 0)]), // Fail: Era out of history - DispatchError::Module { index: 0, error: 9, message: Some("InvalidEraToReward") } + Error::::InvalidEraToReward ); assert_ok!(Staking::payout_nominator(Origin::signed(100), 1, vec![(11, 0)])); assert_ok!(Staking::payout_nominator(Origin::signed(100), 2, vec![(11, 0)])); assert_noop!( Staking::payout_nominator(Origin::signed(100), 2, vec![(11, 0)]), // Fail: Double claim - DispatchError::Module { index: 0, error: 9, message: Some("InvalidEraToReward") } + Error::::InvalidEraToReward ); assert_noop!( Staking::payout_nominator(Origin::signed(100), active_era, vec![(11, 0)]), // Fail: Era not finished yet - DispatchError::Module { index: 0, error: 9, message: Some("InvalidEraToReward") } + Error::::InvalidEraToReward ); // Era 0 can't be rewarded anymore and current era can't be rewarded yet From c4d27b24c874e573dbcf9bdfc9c8aeef8bb8ee7c Mon Sep 17 00:00:00 2001 From: thiolliere Date: Mon, 2 Mar 2020 13:21:31 +0100 Subject: [PATCH 73/75] remove outdated comment --- frame/staking/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 2e24d219fab71..88d6b931b9675 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1458,7 +1458,6 @@ impl Module { return Err(Error::::InvalidEraToReward.into()); } - // Note: This means that the reward for EraIndex::max() can be called indefinitely. nominator_ledger.last_reward = Some(era); >::insert(&who, &nominator_ledger); From 129a6d9add2820c09933f2717bdc6f1a485ffe2d Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 3 Mar 2020 13:00:52 +0100 Subject: [PATCH 74/75] Apply suggestions from code review Co-Authored-By: Shawn Tabrizi --- frame/staking/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 88d6b931b9675..48f85dc83f962 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1447,7 +1447,7 @@ impl Module { return Err(Error::::InvalidNumberOfNominations.into()); } - // Note: if era has no reward to be claimed, era may be futur. better not to update + // Note: if era has no reward to be claimed, era may be future. better not to update // `nominator_ledger.last_reward` in this case. let era_payout = >::get(&era) .ok_or_else(|| Error::::InvalidEraToReward)?; @@ -1502,7 +1502,7 @@ impl Module { } fn do_payout_validator(who: T::AccountId, era: EraIndex) -> DispatchResult { - // Note: if era has no reward to be claimed, era may be futur. better not to update + // Note: if era has no reward to be claimed, era may be future. better not to update // `ledger.last_reward` in this case. let era_payout = >::get(&era) .ok_or_else(|| Error::::InvalidEraToReward)?; From d5b3080ad46d4239aa96d9fe445df242885d0d0b Mon Sep 17 00:00:00 2001 From: thiolliere Date: Tue, 3 Mar 2020 14:11:16 +0100 Subject: [PATCH 75/75] gather active era information into one storage --- frame/staking/src/lib.rs | 85 +++++++---- frame/staking/src/mock.rs | 8 +- frame/staking/src/tests.rs | 280 ++++++++++++++++++------------------- 3 files changed, 199 insertions(+), 174 deletions(-) diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 48f85dc83f962..434d4603ca696 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -298,6 +298,18 @@ pub type EraIndex = u32; /// Counter for the number of "reward" points earned by a given validator. pub type RewardPoint = u32; +/// Information regarding the active era (era in used in session). +#[derive(Encode, Decode, Debug)] +pub struct ActiveEraInfo { + /// Index of era. + index: EraIndex, + /// Moment of start + /// + /// Start can be none if start hasn't been set for the era yet, + /// Start is set on the first on_finalize of the era to guarantee usage of `Time`. + start: Option, +} + /// Reward points of an era. Used to split era total payout between validators. /// /// This points will be used to reward validators and their respective nominators. @@ -715,13 +727,11 @@ decl_storage! { /// set, it might be active or not. pub CurrentEra get(fn current_era): Option; - /// The active era index, the era currently rewarded. + /// The active era information, it holds index and start. /// + /// The active era is the era currently rewarded. /// Validator set of this era must be equal to `SessionInterface::validators`. - pub ActiveEra get(fn active_era): Option; - - /// The start of the active era. - pub ActiveEraStart get(fn active_era_start): Option>; + pub ActiveEra get(fn active_era): Option>>; /// The session index at which the era start for the last `HISTORY_DEPTH` eras pub ErasStartSessionIndex get(fn eras_start_session_index): @@ -923,8 +933,11 @@ decl_module! { fn on_finalize() { // Set the start of the first era. - if Self::active_era().is_some() && Self::active_era_start().is_none() { - >::put(T::Time::now()); + if let Some(mut active_era) = Self::active_era() { + if active_era.start.is_none() { + active_era.start = Some(T::Time::now()); + >::put(active_era); + } } } @@ -1625,8 +1638,10 @@ impl Module { /// Start a session potentially starting an era. fn start_session(start_session: SessionIndex) { - let next_active_era = Self::active_era().map(|e| e + 1).unwrap_or(0); - if let Some(next_active_era_start_session_index) = Self::eras_start_session_index(next_active_era) { + let next_active_era = Self::active_era().map(|e| e.index + 1).unwrap_or(0); + if let Some(next_active_era_start_session_index) = + Self::eras_start_session_index(next_active_era) + { if next_active_era_start_session_index == start_session { Self::start_era(start_session); } else if next_active_era_start_session_index < start_session { @@ -1641,11 +1656,14 @@ impl Module { /// End a session potentially ending an era. fn end_session(session_index: SessionIndex) { if let Some(active_era) = Self::active_era() { - let next_active_era_start_session_index = Self::eras_start_session_index(active_era + 1) - .unwrap_or_else(|| { - frame_support::print("Error: start_session_index must be set for active_era + 1"); - 0 - }); + let next_active_era_start_session_index = + Self::eras_start_session_index(active_era.index + 1) + .unwrap_or_else(|| { + frame_support::print( + "Error: start_session_index must be set for active_era + 1" + ); + 0 + }); if next_active_era_start_session_index == session_index + 1 { Self::end_era(active_era, session_index); @@ -1653,16 +1671,20 @@ impl Module { } } - /// Increment `ActiveEra`, reset `ActiveEraStart`, update `BondedEras` and apply slashes. + /// * Increment `active_era.index`, + /// * reset `active_era.start`, + /// * update `BondedEras` and apply slashes. fn start_era(start_session: SessionIndex) { - let active_era = ActiveEra::mutate(|s| { - *s = Some(s.map(|s| s + 1).unwrap_or(0)); - s.unwrap() + let active_era = >::mutate(|active_era| { + let new_index = active_era.as_ref().map(|info| info.index + 1).unwrap_or(0); + *active_era = Some(ActiveEraInfo { + index: new_index, + // Set new active era start in next `on_finalize`. To guarantee usage of `Time` + start: None, + }); + new_index }); - // Set new active era start in next `on_finalize`. To guarantee usage of `Time::now`. - >::kill(); - let bonding_duration = T::BondingDuration::get(); BondedEras::mutate(|bonded| { @@ -1691,22 +1713,22 @@ impl Module { } /// Compute payout for era. - fn end_era(active_era: EraIndex, _session_index: SessionIndex) { + fn end_era(active_era: ActiveEraInfo>, _session_index: SessionIndex) { // Note: active_era_start can be None if end era is called during genesis config. - if let Some(active_era_start) = Self::active_era_start() { + if let Some(active_era_start) = active_era.start { let now = T::Time::now(); let era_duration = now - active_era_start; let (total_payout, _max_payout) = inflation::compute_total_payout( &T::RewardCurve::get(), - Self::eras_total_stake(&active_era), + Self::eras_total_stake(&active_era.index), T::Currency::total_issuance(), // Duration of era; more than u64::MAX is rewarded as u64::MAX. era_duration.saturated_into::(), ); // Set ending era reward. - >::insert(&active_era, total_payout); + >::insert(&active_era.index, total_payout); } } @@ -1920,7 +1942,7 @@ impl Module { validators_points: impl IntoIterator ) { if let Some(active_era) = Self::active_era() { - >::mutate(active_era, |era_rewards| { + >::mutate(active_era.index, |era_rewards| { for (validator, points) in validators_points.into_iter() { *era_rewards.individual.entry(validator).or_default() += points; era_rewards.total += points; @@ -2020,9 +2042,12 @@ impl Module { let current_era_start_index = deprecated::CurrentEraStartSessionIndex::get(); let current_era = as Store>::CurrentEra::get().unwrap_or(0); + let current_era_start = deprecated::CurrentEraStart::::get(); as Store>::ErasStartSessionIndex::insert(current_era, current_era_start_index); - as Store>::ActiveEra::put(current_era); - as Store>::ActiveEraStart::put(deprecated::CurrentEraStart::::get()); + as Store>::ActiveEra::put(ActiveEraInfo { + index: current_era, + start: Some(current_era_start), + }); let current_elected = deprecated::CurrentElected::::get(); let mut current_total_stake = >::zero(); @@ -2160,7 +2185,7 @@ impl Convert> { fn convert(validator: T::AccountId) -> Option>> { if let Some(active_era) = >::active_era() { - Some(>::eras_stakers(active_era, &validator)) + Some(>::eras_stakers(active_era.index, &validator)) } else { None } @@ -2192,7 +2217,7 @@ impl OnOffenceHandler u64 { inflation::compute_total_payout( ::RewardCurve::get(), - Staking::eras_total_stake(Staking::active_era().unwrap()), + Staking::eras_total_stake(Staking::active_era().unwrap().index), Balances::total_issuance(), duration, ).0 @@ -488,7 +488,7 @@ pub fn on_offence_in_era( } } - if Staking::active_era().unwrap() == era { + if Staking::active_era().unwrap().index == era { Staking::on_offence(offenders, slash_fraction, Staking::eras_start_session_index(era).unwrap()); } else { panic!("cannot slash in era {}", era); @@ -499,7 +499,7 @@ pub fn on_offence_now( offenders: &[OffenceDetails>], slash_fraction: &[Perbill], ) { - let now = Staking::active_era().unwrap(); + let now = Staking::active_era().unwrap().index; on_offence_in_era(offenders, slash_fraction, now) } diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 3de8610de36dd..98536a042aa82 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -93,7 +93,7 @@ fn basic_setup_works() { assert_eq!(Staking::nominators(101).unwrap().targets, vec![11, 21]); assert_eq!( - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), Exposure { total: 1125, own: 1000, @@ -101,7 +101,7 @@ fn basic_setup_works() { }, ); assert_eq!( - Staking::eras_stakers(Staking::active_era().unwrap(), 21), + Staking::eras_stakers(Staking::active_era().unwrap().index, 21), Exposure { total: 1375, own: 1000, @@ -109,14 +109,14 @@ fn basic_setup_works() { }, ); // initial slot_stake - assert_eq!(Staking::eras_total_stake(Staking::active_era().unwrap()), 2500); + assert_eq!(Staking::eras_total_stake(Staking::active_era().unwrap().index), 2500); // The number of validators required. assert_eq!(Staking::validator_count(), 2); // Initial Era and session - assert_eq!(Staking::active_era().unwrap(), 0); + assert_eq!(Staking::active_era().unwrap().index, 0); // Account 10 has `balance_factor` free balance assert_eq!(Balances::free_balance(10), 1); @@ -126,8 +126,8 @@ fn basic_setup_works() { assert_eq!(Staking::force_era(), Forcing::NotForcing); // All exposures must be correct. - check_exposure_all(Staking::active_era().unwrap()); - check_nominator_all(Staking::active_era().unwrap()); + check_exposure_all(Staking::active_era().unwrap().index); + check_nominator_all(Staking::active_era().unwrap().index); }); } @@ -190,7 +190,7 @@ fn rewards_should_work() { assert_eq!(Balances::total_balance(&100), init_balance_100); assert_eq!(Balances::total_balance(&101), init_balance_101); assert_eq_uvec!(Session::validators(), vec![11, 21]); - assert_eq!(Staking::eras_reward_points(Staking::active_era().unwrap()), EraRewardPoints { + assert_eq!(Staking::eras_reward_points(Staking::active_era().unwrap().index), EraRewardPoints { total: 50*3, individual: vec![(11, 100), (21, 50)].into_iter().collect(), }); @@ -202,7 +202,7 @@ fn rewards_should_work() { start_session(2); start_session(3); - assert_eq!(Staking::active_era().unwrap(), 1); + assert_eq!(Staking::active_era().unwrap().index, 1); mock::make_all_reward_payment(0); assert_eq_error_rate!(Balances::total_balance(&10), init_balance_10 + part_for_10 * total_payout_0*2/3, 2); @@ -284,7 +284,7 @@ fn staking_should_work() { // --- Block 4: the validators will now be queued. start_session(4); - assert_eq!(Staking::active_era().unwrap(), 1); + assert_eq!(Staking::active_era().unwrap().index, 1); // --- Block 5: the validators are still in queue. start_session(5); @@ -349,11 +349,11 @@ fn less_than_needed_candidates_works() { // But the exposure is updated in a simple way. No external votes exists. // This is purely self-vote. assert!( - ErasStakers::::iter_prefix(Staking::active_era().unwrap()) + ErasStakers::::iter_prefix(Staking::active_era().unwrap().index) .all(|exposure| exposure.others.is_empty()) ); - check_exposure_all(Staking::active_era().unwrap()); - check_nominator_all(Staking::active_era().unwrap()); + check_exposure_all(Staking::active_era().unwrap().index); + check_nominator_all(Staking::active_era().unwrap().index); }); } @@ -472,9 +472,9 @@ fn nominating_and_rewards_should_work() { // ------ check the staked value of all parties. // 30 and 40 are not chosen anymore - assert_eq!(ErasStakers::::iter_prefix(Staking::active_era().unwrap()).count(), 2); + assert_eq!(ErasStakers::::iter_prefix(Staking::active_era().unwrap().index).count(), 2); assert_eq!( - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), Exposure { total: 1000 + 800, own: 1000, @@ -485,7 +485,7 @@ fn nominating_and_rewards_should_work() { }, ); assert_eq!( - Staking::eras_stakers(Staking::active_era().unwrap(), 21), + Staking::eras_stakers(Staking::active_era().unwrap().index, 21), Exposure { total: 1000 + 1200, own: 1000, @@ -536,8 +536,8 @@ fn nominating_and_rewards_should_work() { 1, ); - check_exposure_all(Staking::active_era().unwrap()); - check_nominator_all(Staking::active_era().unwrap()); + check_exposure_all(Staking::active_era().unwrap().index); + check_nominator_all(Staking::active_era().unwrap().index); }); } @@ -580,13 +580,13 @@ fn nominators_also_get_slashed() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), ), reporters: vec![], }], &[Perbill::from_percent(5)], ); - let expo = Staking::eras_stakers(Staking::active_era().unwrap(), 11); + let expo = Staking::eras_stakers(Staking::active_era().unwrap().index, 11); let slash_value = 50; let total_slash = expo.total.min(slash_value); let validator_slash = expo.own.min(total_slash); @@ -595,8 +595,8 @@ fn nominators_also_get_slashed() { // initial + first era reward + slash assert_eq!(Balances::total_balance(&11), initial_balance - validator_slash); assert_eq!(Balances::total_balance(&2), initial_balance - nominator_slash); - check_exposure_all(Staking::active_era().unwrap()); - check_nominator_all(Staking::active_era().unwrap()); + check_exposure_all(Staking::active_era().unwrap().index); + check_nominator_all(Staking::active_era().unwrap().index); // Because slashing happened. assert!(is_disabled(10)); }); @@ -651,52 +651,52 @@ fn double_controlling_should_fail() { #[test] fn session_and_eras_work() { ExtBuilder::default().build().execute_with(|| { - assert_eq!(Staking::active_era().unwrap(), 0); + assert_eq!(Staking::active_era().unwrap().index, 0); // Block 1: No change. start_session(1); assert_eq!(Session::current_index(), 1); - assert_eq!(Staking::active_era().unwrap(), 0); + assert_eq!(Staking::active_era().unwrap().index, 0); // Block 2: No change. start_session(2); assert_eq!(Session::current_index(), 2); - assert_eq!(Staking::active_era().unwrap(), 0); + assert_eq!(Staking::active_era().unwrap().index, 0); // Block 3: Era increment. start_session(3); assert_eq!(Session::current_index(), 3); - assert_eq!(Staking::active_era().unwrap(), 1); + assert_eq!(Staking::active_era().unwrap().index, 1); // Block 4: No change. start_session(4); assert_eq!(Session::current_index(), 4); - assert_eq!(Staking::active_era().unwrap(), 1); + assert_eq!(Staking::active_era().unwrap().index, 1); // Block 5: No change. start_session(5); assert_eq!(Session::current_index(), 5); - assert_eq!(Staking::active_era().unwrap(), 1); + assert_eq!(Staking::active_era().unwrap().index, 1); // Block 6: Era increment. start_session(6); assert_eq!(Session::current_index(), 6); - assert_eq!(Staking::active_era().unwrap(), 2); + assert_eq!(Staking::active_era().unwrap().index, 2); // Block 7: No change. start_session(7); assert_eq!(Session::current_index(), 7); - assert_eq!(Staking::active_era().unwrap(), 2); + assert_eq!(Staking::active_era().unwrap().index, 2); // Block 8: No change. start_session(8); assert_eq!(Session::current_index(), 8); - assert_eq!(Staking::active_era().unwrap(), 2); + assert_eq!(Staking::active_era().unwrap().index, 2); // Block 9: Era increment. start_session(9); assert_eq!(Session::current_index(), 9); - assert_eq!(Staking::active_era().unwrap(), 3); + assert_eq!(Staking::active_era().unwrap().index, 3); }); } @@ -704,53 +704,53 @@ fn session_and_eras_work() { fn forcing_new_era_works() { ExtBuilder::default().build().execute_with(|| { // normal flow of session. - assert_eq!(Staking::active_era().unwrap(), 0); + assert_eq!(Staking::active_era().unwrap().index, 0); start_session(0); - assert_eq!(Staking::active_era().unwrap(), 0); + assert_eq!(Staking::active_era().unwrap().index, 0); start_session(1); - assert_eq!(Staking::active_era().unwrap(), 0); + assert_eq!(Staking::active_era().unwrap().index, 0); start_session(2); - assert_eq!(Staking::active_era().unwrap(), 0); + assert_eq!(Staking::active_era().unwrap().index, 0); start_session(3); - assert_eq!(Staking::active_era().unwrap(), 1); + assert_eq!(Staking::active_era().unwrap().index, 1); // no era change. ForceEra::put(Forcing::ForceNone); start_session(4); - assert_eq!(Staking::active_era().unwrap(), 1); + assert_eq!(Staking::active_era().unwrap().index, 1); start_session(5); - assert_eq!(Staking::active_era().unwrap(), 1); + assert_eq!(Staking::active_era().unwrap().index, 1); start_session(6); - assert_eq!(Staking::active_era().unwrap(), 1); + assert_eq!(Staking::active_era().unwrap().index, 1); start_session(7); - assert_eq!(Staking::active_era().unwrap(), 1); + assert_eq!(Staking::active_era().unwrap().index, 1); // back to normal. // this immediately starts a new session. ForceEra::put(Forcing::NotForcing); start_session(8); - assert_eq!(Staking::active_era().unwrap(), 1); // There is one session delay + assert_eq!(Staking::active_era().unwrap().index, 1); // There is one session delay start_session(9); - assert_eq!(Staking::active_era().unwrap(), 2); + assert_eq!(Staking::active_era().unwrap().index, 2); // forceful change ForceEra::put(Forcing::ForceAlways); start_session(10); - assert_eq!(Staking::active_era().unwrap(), 2); // There is one session delay + assert_eq!(Staking::active_era().unwrap().index, 2); // There is one session delay start_session(11); - assert_eq!(Staking::active_era().unwrap(), 3); + assert_eq!(Staking::active_era().unwrap().index, 3); start_session(12); - assert_eq!(Staking::active_era().unwrap(), 4); + assert_eq!(Staking::active_era().unwrap().index, 4); // just one forceful change ForceEra::put(Forcing::ForceNew); start_session(13); - assert_eq!(Staking::active_era().unwrap(), 5); + assert_eq!(Staking::active_era().unwrap().index, 5); assert_eq!(ForceEra::get(), Forcing::NotForcing); start_session(14); - assert_eq!(Staking::active_era().unwrap(), 6); + assert_eq!(Staking::active_era().unwrap().index, 6); start_session(15); - assert_eq!(Staking::active_era().unwrap(), 6); + assert_eq!(Staking::active_era().unwrap().index, 6); }); } @@ -764,7 +764,7 @@ fn cannot_transfer_staked_balance() { // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(11), 1000); // Confirm account 11 (via controller 10) is totally staked - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).total, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11).total, 1000); // Confirm account 11 cannot transfer as a result assert_noop!( Balances::transfer(Origin::signed(11), 20, 1), @@ -789,7 +789,7 @@ fn cannot_transfer_staked_balance_2() { // Confirm account 21 has some free balance assert_eq!(Balances::free_balance(21), 2000); // Confirm account 21 (via controller 20) is totally staked - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 21).total, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 21).total, 1000); // Confirm account 21 can transfer at most 1000 assert_noop!( Balances::transfer(Origin::signed(21), 20, 1001), @@ -808,7 +808,7 @@ fn cannot_reserve_staked_balance() { // Confirm account 11 has some free balance assert_eq!(Balances::free_balance(11), 1000); // Confirm account 11 (via controller 10) is totally staked - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).own, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11).own, 1000); // Confirm account 11 cannot transfer as a result assert_noop!( Balances::reserve(&11, 1), @@ -943,7 +943,7 @@ fn validator_payment_prefs_work() { // Compute total payout now for whole duration as other parameter won't change let total_payout_1 = current_total_payout_for_duration(3000); assert!(total_payout_1 > 100); // Test is meaningful if reward something - let exposure_1 = Staking::eras_stakers(Staking::active_era().unwrap(), 11); + let exposure_1 = Staking::eras_stakers(Staking::active_era().unwrap().index, 11); >::reward_by_ids(vec![(11, 1)]); start_era(2); @@ -956,8 +956,8 @@ fn validator_payment_prefs_work() { assert_eq_error_rate!(Balances::total_balance(&10), balance_era_1_10 + reward_of_10, 2); assert_eq_error_rate!(Balances::total_balance(&100), balance_era_1_100 + reward_of_100, 2); - check_exposure_all(Staking::active_era().unwrap()); - check_nominator_all(Staking::active_era().unwrap()); + check_exposure_all(Staking::active_era().unwrap().index); + check_nominator_all(Staking::active_era().unwrap().index); }); } @@ -1023,7 +1023,7 @@ fn bond_extra_and_withdraw_unbonded_works() { let _ = Balances::make_free_balance_be(&11, 1000000); // Initial config should be correct - assert_eq!(Staking::active_era().unwrap(), 0); + assert_eq!(Staking::active_era().unwrap().index, 0); assert_eq!(Session::current_index(), 0); // check the balance of a validator accounts. @@ -1040,7 +1040,7 @@ fn bond_extra_and_withdraw_unbonded_works() { unlocking: vec![], last_reward: None, })); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11), Exposure { total: 1000, own: 1000, others: vec![] }); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11), Exposure { total: 1000, own: 1000, others: vec![] }); // deposit the extra 100 units Staking::bond_extra(Origin::signed(11), 100).unwrap(); @@ -1053,12 +1053,12 @@ fn bond_extra_and_withdraw_unbonded_works() { last_reward: None, })); // Exposure is a snapshot! only updated after the next era update. - assert_ne!(Staking::eras_stakers(Staking::active_era().unwrap(), 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + assert_ne!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); // trigger next era. Timestamp::set_timestamp(10); start_era(2); - assert_eq!(Staking::active_era().unwrap(), 2); + assert_eq!(Staking::active_era().unwrap().index, 2); // ledger should be the same. assert_eq!(Staking::ledger(&10), Some(StakingLedger { @@ -1069,7 +1069,7 @@ fn bond_extra_and_withdraw_unbonded_works() { last_reward: None, })); // Exposure is now updated. - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11), Exposure { total: 1000 + 100, own: 1000 + 100, others: vec![] }); // Unbond almost all of the funds in stash. Staking::unbond(Origin::signed(10), 1000).unwrap(); @@ -1162,7 +1162,7 @@ fn rebond_works() { ); start_era(2); - assert_eq!(Staking::active_era().unwrap(), 2); + assert_eq!(Staking::active_era().unwrap().index, 2); // Try to rebond some funds. We get an error since no fund is unbonded. assert_noop!( @@ -1386,8 +1386,8 @@ fn reward_to_stake_works() { // Confirm account 10 and 20 are validators assert!(>::contains_key(&11) && >::contains_key(&21)); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).total, 1000); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 21).total, 2000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11).total, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 21).total, 2000); // Give the man some money. let _ = Balances::make_free_balance_be(&10, 1000); @@ -1397,7 +1397,7 @@ fn reward_to_stake_works() { ErasStakers::::insert(0, 21, Exposure { total: 69, own: 69, others: vec![] }); // Now lets lower account 20 stake - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 21).total, 69); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 21).total, 69); >::insert(&20, StakingLedger { stash: 21, total: 69, active: 69, unlocking: vec![], last_reward: None }); // Compute total payout now for whole duration as other parameter won't change @@ -1410,8 +1410,8 @@ fn reward_to_stake_works() { start_era(1); mock::make_all_reward_payment(0); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).total, 1000); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 21).total, 69); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11).total, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 21).total, 69); let _11_balance = Balances::free_balance(&11); assert_eq!(_11_balance, 1000 + total_payout_0 / 2); @@ -1420,11 +1420,11 @@ fn reward_to_stake_works() { start_era(2); // -- new infos - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).total, 1000 + total_payout_0 / 2); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 21).total, 69 + total_payout_0 / 2); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11).total, 1000 + total_payout_0 / 2); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 21).total, 69 + total_payout_0 / 2); - check_exposure_all(Staking::active_era().unwrap()); - check_nominator_all(Staking::active_era().unwrap()); + check_exposure_all(Staking::active_era().unwrap().index); + check_nominator_all(Staking::active_era().unwrap().index); }); } @@ -1579,8 +1579,8 @@ fn switching_roles() { assert_eq_uvec!(validator_controllers(), vec![2, 20]); - check_exposure_all(Staking::active_era().unwrap()); - check_nominator_all(Staking::active_era().unwrap()); + check_exposure_all(Staking::active_era().unwrap().index); + check_nominator_all(Staking::active_era().unwrap().index); }); } @@ -1687,7 +1687,7 @@ fn bond_with_little_staked_value_bounded() { // 2 is elected. assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); // And has minimal stake - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 2).total, 0); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 2).total, 0); // Old ones are rewarded. assert_eq!(Balances::free_balance(10), init_balance_10 + total_payout_0 / 3); @@ -1702,15 +1702,15 @@ fn bond_with_little_staked_value_bounded() { mock::make_all_reward_payment(1); assert_eq_uvec!(validator_controllers(), vec![20, 10, 2]); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 2).total, 0); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 2).total, 0); assert_eq!(Balances::free_balance(2), init_balance_2 + total_payout_1 / 3); assert_eq!( Balances::free_balance(&10), init_balance_10 + total_payout_0 / 3 + total_payout_1 / 3, ); - check_exposure_all(Staking::active_era().unwrap()); - check_nominator_all(Staking::active_era().unwrap()); + check_exposure_all(Staking::active_era().unwrap().index); + check_nominator_all(Staking::active_era().unwrap().index); }); } @@ -1730,8 +1730,8 @@ fn new_era_elects_correct_number_of_validators() { Session::on_initialize(System::block_number()); assert_eq!(validator_controllers().len(), 1); - check_exposure_all(Staking::active_era().unwrap()); - check_nominator_all(Staking::active_era().unwrap()); + check_exposure_all(Staking::active_era().unwrap().index); + check_nominator_all(Staking::active_era().unwrap().index); }) } @@ -1753,8 +1753,8 @@ fn phragmen_should_not_overflow_validators() { // This test will fail this. Will saturate. // check_exposure_all(); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 3).total, u64::max_value()); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 5).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 3).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 5).total, u64::max_value()); }) } @@ -1775,8 +1775,8 @@ fn phragmen_should_not_overflow_nominators() { assert_eq_uvec!(validator_controllers(), vec![4, 2]); // Saturate. - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 3).total, u64::max_value()); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 5).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 3).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 5).total, u64::max_value()); }) } @@ -1794,8 +1794,8 @@ fn phragmen_should_not_overflow_ultimate() { assert_eq_uvec!(validator_controllers(), vec![4, 2]); // Saturate. - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 3).total, u64::max_value()); - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 5).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 3).total, u64::max_value()); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 5).total, u64::max_value()); }) } @@ -1843,7 +1843,7 @@ fn reward_validator_slashing_validator_doesnt_overflow() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), reporters: vec![], }, ], @@ -1873,7 +1873,7 @@ fn reward_from_authorship_event_handler_works() { // 21 is rewarded as an uncle producer // 11 is rewarded as a block producer and uncle referencer and uncle producer assert_eq!( - ErasRewardPoints::::get(Staking::active_era().unwrap()), + ErasRewardPoints::::get(Staking::active_era().unwrap().index), EraRewardPoints { individual: vec![(11, 20 + 2 * 2 + 1), (21, 1)].into_iter().collect(), total: 26, @@ -1901,7 +1901,7 @@ fn add_reward_points_fns_works() { ]); assert_eq!( - ErasRewardPoints::::get(Staking::active_era().unwrap()), + ErasRewardPoints::::get(Staking::active_era().unwrap().index), EraRewardPoints { individual: vec![(11, 4), (21, 2)].into_iter().collect(), total: 6, @@ -1929,20 +1929,20 @@ fn era_is_always_same_length() { // session changes. ExtBuilder::default().build().execute_with(|| { start_era(1); - assert_eq!(Staking::eras_start_session_index(Staking::active_era().unwrap()).unwrap(), SessionsPerEra::get()); + assert_eq!(Staking::eras_start_session_index(Staking::active_era().unwrap().index).unwrap(), SessionsPerEra::get()); start_era(2); - assert_eq!(Staking::eras_start_session_index(Staking::active_era().unwrap()).unwrap(), SessionsPerEra::get() * 2); + assert_eq!(Staking::eras_start_session_index(Staking::active_era().unwrap().index).unwrap(), SessionsPerEra::get() * 2); let session = Session::current_index(); ForceEra::put(Forcing::ForceNew); advance_session(); advance_session(); - assert_eq!(Staking::active_era().unwrap(), 3); - assert_eq!(Staking::eras_start_session_index(Staking::active_era().unwrap()).unwrap(), session + 2); + assert_eq!(Staking::active_era().unwrap().index, 3); + assert_eq!(Staking::eras_start_session_index(Staking::active_era().unwrap().index).unwrap(), session + 2); start_era(4); - assert_eq!(Staking::eras_start_session_index(Staking::active_era().unwrap()).unwrap(), session + 2 + SessionsPerEra::get()); + assert_eq!(Staking::eras_start_session_index(Staking::active_era().unwrap().index).unwrap(), session + 2 + SessionsPerEra::get()); }); } @@ -1953,7 +1953,7 @@ fn offence_forces_new_era() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), ), reporters: vec![], }], @@ -1973,7 +1973,7 @@ fn offence_ensures_new_era_without_clobbering() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), ), reporters: vec![], }], @@ -1993,7 +1993,7 @@ fn offence_deselects_validator_when_slash_is_zero() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), ), reporters: vec![], }], @@ -2012,7 +2012,7 @@ fn slashing_performed_according_exposure() { // This test checks that slashing is performed according the exposure (or more precisely, // historical exposure), not the current balance. ExtBuilder::default().build().execute_with(|| { - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).own, 1000); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11).own, 1000); // Handle an offence with a historical exposure. on_offence_now( @@ -2046,7 +2046,7 @@ fn slash_in_old_span_does_not_deselect() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), ), reporters: vec![], }], @@ -2071,7 +2071,7 @@ fn slash_in_old_span_does_not_deselect() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), ), reporters: vec![], }], @@ -2088,7 +2088,7 @@ fn slash_in_old_span_does_not_deselect() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), ), reporters: vec![], }], @@ -2113,13 +2113,13 @@ fn reporters_receive_their_slice() { // The reporters' reward is calculated from the total exposure. let initial_balance = 1125; - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).total, initial_balance); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11).total, initial_balance); on_offence_now( &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), ), reporters: vec![1, 2], }], @@ -2144,13 +2144,13 @@ fn subsequent_reports_in_same_span_pay_out_less() { // The reporters' reward is calculated from the total exposure. let initial_balance = 1125; - assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap(), 11).total, initial_balance); + assert_eq!(Staking::eras_stakers(Staking::active_era().unwrap().index, 11).total, initial_balance); on_offence_now( &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), ), reporters: vec![1], }], @@ -2166,7 +2166,7 @@ fn subsequent_reports_in_same_span_pay_out_less() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), ), reporters: vec![1], }], @@ -2190,7 +2190,7 @@ fn invulnerables_are_not_slashed() { assert_eq!(Balances::free_balance(11), 1000); assert_eq!(Balances::free_balance(21), 2000); - let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 21); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap().index, 21); let initial_balance = Staking::slashable_balance_of(&21); let nominator_balances: Vec<_> = exposure.others @@ -2199,11 +2199,11 @@ fn invulnerables_are_not_slashed() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), reporters: vec![], }, OffenceDetails { - offender: (21, Staking::eras_stakers(Staking::active_era().unwrap(), 21)), + offender: (21, Staking::eras_stakers(Staking::active_era().unwrap().index, 21)), reporters: vec![], }, ], @@ -2237,7 +2237,7 @@ fn dont_slash_if_fraction_is_zero() { &[OffenceDetails { offender: ( 11, - Staking::eras_stakers(Staking::active_era().unwrap(), 11), + Staking::eras_stakers(Staking::active_era().unwrap().index, 11), ), reporters: vec![], }], @@ -2258,7 +2258,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), reporters: vec![], }, ], @@ -2272,7 +2272,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), reporters: vec![], }, ], @@ -2285,7 +2285,7 @@ fn only_slash_for_max_in_era() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), reporters: vec![], }, ], @@ -2306,7 +2306,7 @@ fn garbage_collection_after_slashing() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), reporters: vec![], }, ], @@ -2320,7 +2320,7 @@ fn garbage_collection_after_slashing() { on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), reporters: vec![], }, ], @@ -2347,21 +2347,21 @@ fn garbage_collection_on_window_pruning() { assert_eq!(Balances::free_balance(11), 1000); - let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap().index, 11); assert_eq!(Balances::free_balance(101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), reporters: vec![], }, ], &[Perbill::from_percent(10)], ); - let now = Staking::active_era().unwrap(); + let now = Staking::active_era().unwrap().index; assert_eq!(Balances::free_balance(11), 900); assert_eq!(Balances::free_balance(101), 2000 - (nominated_value / 10)); @@ -2395,8 +2395,8 @@ fn slashing_nominators_by_span_max() { assert_eq!(Staking::slashable_balance_of(&21), 1000); - let exposure_11 = Staking::eras_stakers(Staking::active_era().unwrap(), 11); - let exposure_21 = Staking::eras_stakers(Staking::active_era().unwrap(), 21); + let exposure_11 = Staking::eras_stakers(Staking::active_era().unwrap().index, 11); + let exposure_21 = Staking::eras_stakers(Staking::active_era().unwrap().index, 21); assert_eq!(Balances::free_balance(101), 2000); let nominated_value_11 = exposure_11.others.iter().find(|o| o.who == 101).unwrap().value; let nominated_value_21 = exposure_21.others.iter().find(|o| o.who == 101).unwrap().value; @@ -2404,7 +2404,7 @@ fn slashing_nominators_by_span_max() { on_offence_in_era( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), reporters: vec![], }, ], @@ -2438,7 +2438,7 @@ fn slashing_nominators_by_span_max() { on_offence_in_era( &[ OffenceDetails { - offender: (21, Staking::eras_stakers(Staking::active_era().unwrap(), 21)), + offender: (21, Staking::eras_stakers(Staking::active_era().unwrap().index, 21)), reporters: vec![], }, ], @@ -2461,7 +2461,7 @@ fn slashing_nominators_by_span_max() { on_offence_in_era( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), reporters: vec![], }, ], @@ -2497,7 +2497,7 @@ fn slashes_are_summed_across_spans() { on_offence_now( &[ OffenceDetails { - offender: (21, Staking::eras_stakers(Staking::active_era().unwrap(), 21)), + offender: (21, Staking::eras_stakers(Staking::active_era().unwrap().index, 21)), reporters: vec![], }, ], @@ -2522,7 +2522,7 @@ fn slashes_are_summed_across_spans() { on_offence_now( &[ OffenceDetails { - offender: (21, Staking::eras_stakers(Staking::active_era().unwrap(), 21)), + offender: (21, Staking::eras_stakers(Staking::active_era().unwrap().index, 21)), reporters: vec![], }, ], @@ -2547,14 +2547,14 @@ fn deferred_slashes_are_deferred() { assert_eq!(Balances::free_balance(11), 1000); - let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap().index, 11); assert_eq!(Balances::free_balance(101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; on_offence_now( &[ OffenceDetails { - offender: (11, Staking::eras_stakers(Staking::active_era().unwrap(), 11)), + offender: (11, Staking::eras_stakers(Staking::active_era().unwrap().index, 11)), reporters: vec![], }, ], @@ -2590,7 +2590,7 @@ fn remove_deferred() { assert_eq!(Balances::free_balance(11), 1000); - let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap().index, 11); assert_eq!(Balances::free_balance(101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; @@ -2660,7 +2660,7 @@ fn remove_multi_deferred() { assert_eq!(Balances::free_balance(11), 1000); - let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap().index, 11); assert_eq!(Balances::free_balance(101), 2000); on_offence_now( @@ -2676,7 +2676,7 @@ fn remove_multi_deferred() { on_offence_now( &[ OffenceDetails { - offender: (21, Staking::eras_stakers(Staking::active_era().unwrap(), 21)), + offender: (21, Staking::eras_stakers(Staking::active_era().unwrap().index, 21)), reporters: vec![], } ], @@ -2709,7 +2709,7 @@ fn slash_kicks_validators_not_nominators() { assert_eq!(Balances::free_balance(11), 1000); - let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap().index, 11); assert_eq!(Balances::free_balance(101), 2000); let nominated_value = exposure.others.iter().find(|o| o.who == 101).unwrap().value; @@ -2786,7 +2786,7 @@ fn claim_reward_at_the_last_era_and_no_double_claim_and_invalid_claim() { start_era(Staking::history_depth() + 1); - let active_era = Staking::active_era().unwrap(); + let active_era = Staking::active_era().unwrap().index; // This is the latest planned era in staking, not the active era let current_era = Staking::current_era().unwrap(); @@ -2890,13 +2890,13 @@ fn upgrade_works() { assert_eq!(::IsUpgraded::get(), true); // Check migration - assert_eq!(::ActiveEraStart::get().unwrap(), 777); assert_eq!(::ErasStartSessionIndex::get(3).unwrap(), 5); assert_eq!(::ErasRewardPoints::get(3), EraRewardPoints { total: 12, individual: vec![(21, 2), (31, 10)].into_iter().collect(), }); - assert_eq!(::ActiveEra::get().unwrap(), 3); + assert_eq!(::ActiveEra::get().unwrap().index, 3); + assert_eq!(::ActiveEra::get().unwrap().start, Some(777)); assert_eq!(::CurrentEra::get().unwrap(), 3); assert_eq!(::ErasStakers::get(3, 11), Exposure { total: 0, @@ -2941,7 +2941,7 @@ fn zero_slash_keeps_nominators() { assert_eq!(Balances::free_balance(11), 1000); - let exposure = Staking::eras_stakers(Staking::active_era().unwrap(), 11); + let exposure = Staking::eras_stakers(Staking::active_era().unwrap().index, 11); assert_eq!(Balances::free_balance(101), 2000); on_offence_now( @@ -2979,7 +2979,7 @@ fn six_session_delay() { let val_set = Session::validators(); let init_session = Session::current_index(); - let init_active_era = Staking::active_era().unwrap(); + let init_active_era = Staking::active_era().unwrap().index; // pallet-session is delaying session by one, thus the next session to plan is +2. assert_eq!(>::new_session(init_session + 2), None); assert_eq!(>::new_session(init_session + 3), Some(val_set.clone())); @@ -2989,10 +2989,10 @@ fn six_session_delay() { >::end_session(init_session); >::start_session(init_session + 1); - assert_eq!(Staking::active_era().unwrap(), init_active_era); + assert_eq!(Staking::active_era().unwrap().index, init_active_era); >::end_session(init_session + 1); >::start_session(init_session + 2); - assert_eq!(Staking::active_era().unwrap(), init_active_era); + assert_eq!(Staking::active_era().unwrap().index, init_active_era); // Reward current era Staking::reward_by_ids(vec![(11, 1)]); @@ -3000,13 +3000,13 @@ fn six_session_delay() { // New active era is triggered here. >::end_session(init_session + 2); >::start_session(init_session + 3); - assert_eq!(Staking::active_era().unwrap(), init_active_era + 1); + assert_eq!(Staking::active_era().unwrap().index, init_active_era + 1); >::end_session(init_session + 3); >::start_session(init_session + 4); - assert_eq!(Staking::active_era().unwrap(), init_active_era + 1); + assert_eq!(Staking::active_era().unwrap().index, init_active_era + 1); >::end_session(init_session + 4); >::start_session(init_session + 5); - assert_eq!(Staking::active_era().unwrap(), init_active_era + 1); + assert_eq!(Staking::active_era().unwrap().index, init_active_era + 1); // Reward current era Staking::reward_by_ids(vec![(21, 2)]); @@ -3014,7 +3014,7 @@ fn six_session_delay() { // New active era is triggered here. >::end_session(init_session + 5); >::start_session(init_session + 6); - assert_eq!(Staking::active_era().unwrap(), init_active_era + 2); + assert_eq!(Staking::active_era().unwrap().index, init_active_era + 2); // That reward are correct assert_eq!(Staking::eras_reward_points(init_active_era).total, 1); @@ -3114,7 +3114,7 @@ fn test_upgrade_from_master_works() { assert!(::IsUpgraded::get()); // Check ActiveEra and CurrentEra - let active_era = Staking::active_era().unwrap(); + let active_era = Staking::active_era().unwrap().index; let current_era = Staking::current_era().unwrap(); assert!(current_era == active_era); assert!(current_era == old_current_era);