difftreelog
test(CollatorSelection) verification of correct block authoring
in: master
2 files changed
runtime/common/mod.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617pub mod config;18pub mod construct_runtime;19pub mod dispatch;20pub mod ethereum;21pub mod instance;22pub mod runtime_apis;23pub mod scheduler;24pub mod sponsoring;25pub mod weights;2627use sp_core::H160;28use frame_support::{29 traits::{Currency, OnUnbalanced, Imbalance},30 weights::Weight,31};32use sp_runtime::{33 generic,34 traits::{BlakeTwo256, BlockNumberProvider},35 impl_opaque_keys,36};37use sp_std::vec::Vec;3839#[cfg(feature = "std")]40use sp_version::NativeVersion;4142use crate::{43 Runtime, Call, Balances, Treasury, Aura, Signature, AllPalletsReversedWithSystemFirst,44 InherentDataExt,45};46use up_common::types::{AccountId, BlockNumber};4748#[macro_export]49macro_rules! unsupported {50 () => {51 pallet_common::unsupported!($crate::Runtime)52 };53}5455/// The address format for describing accounts.56pub type Address = sp_runtime::MultiAddress<AccountId, ()>;57/// Block header type as expected by this runtime.58pub type Header = generic::Header<BlockNumber, BlakeTwo256>;59/// Block type as expected by this runtime.60pub type Block = generic::Block<Header, UncheckedExtrinsic>;61/// A Block signed with a Justification62pub type SignedBlock = generic::SignedBlock<Block>;63/// BlockId type as expected by this runtime.64pub type BlockId = generic::BlockId<Block>;6566impl_opaque_keys! {67 pub struct SessionKeys {68 pub aura: Aura,69 }70}7172/// The version information used to identify this runtime when compiled natively.73#[cfg(feature = "std")]74pub fn native_version() -> NativeVersion {75 NativeVersion {76 runtime_version: crate::VERSION,77 can_author_with: Default::default(),78 }79}8081pub type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;8283pub type SignedExtra = (84 frame_system::CheckSpecVersion<Runtime>,85 // system::CheckTxVersion<Runtime>,86 frame_system::CheckGenesis<Runtime>,87 frame_system::CheckEra<Runtime>,88 frame_system::CheckNonce<Runtime>,89 frame_system::CheckWeight<Runtime>,90 ChargeTransactionPayment,91 //pallet_contract_helpers::ContractHelpersExtension<Runtime>,92 pallet_ethereum::FakeTransactionFinalizer<Runtime>,93);9495/// Unchecked extrinsic type as expected by this runtime.96pub type UncheckedExtrinsic =97 fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;9899/// Extrinsic type that has already been checked.100pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;101102/// Executive: handles dispatch to the various modules.103pub type Executive = frame_executive::Executive<104 Runtime,105 Block,106 frame_system::ChainContext<Runtime>,107 Runtime,108 AllPalletsReversedWithSystemFirst,109 AuraToCollatorSelection,110>;111112type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;113114pub struct DealWithFees;115impl OnUnbalanced<NegativeImbalance> for DealWithFees {116 fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {117 if let Some(fees) = fees_then_tips.next() {118 // for fees, 100% to treasury119 let mut split = fees.ration(100, 0);120 if let Some(tips) = fees_then_tips.next() {121 // for tips, if any, 100% to treasury122 tips.ration_merge_into(100, 0, &mut split);123 }124 Treasury::on_unbalanced(split.0);125 // Author::on_unbalanced(split.1);126 }127 }128}129130pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);131132impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider133 for RelayChainBlockNumberProvider<T>134{135 type BlockNumber = BlockNumber;136137 fn current_block_number() -> Self::BlockNumber {138 cumulus_pallet_parachain_system::Pallet::<T>::validation_data()139 .map(|d| d.relay_parent_number)140 .unwrap_or_default()141 }142}143144pub(crate) struct CheckInherents;145146impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {147 fn check_inherents(148 block: &Block,149 relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,150 ) -> sp_inherents::CheckInherentsResult {151 let relay_chain_slot = relay_state_proof152 .read_slot()153 .expect("Could not read the relay chain slot from the proof");154155 let inherent_data =156 cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(157 relay_chain_slot,158 sp_std::time::Duration::from_secs(6),159 )160 .create_inherent_data()161 .expect("Could not create the timestamp inherent data");162163 inherent_data.check_extrinsics(block)164 }165}166167#[derive(codec::Encode, codec::Decode)]168pub enum XCMPMessage<XAccountId, XBalance> {169 /// Transfer tokens to the given account from the Parachain account.170 TransferToken(XAccountId, XBalance),171}172173pub struct AuraToCollatorSelection;174impl frame_support::traits::OnRuntimeUpgrade for AuraToCollatorSelection {175 fn on_runtime_upgrade() -> Weight {176 use frame_support::{BoundedVec, storage::migration};177 use sp_runtime::{178 traits::{OpaqueKeys, Saturating},179 RuntimeAppPublic,180 };181 use pallet_session::SessionManager;182 use up_common::constants::EXISTENTIAL_DEPOSIT;183 use crate::config::substrate::MaxInvulnerables;184185 let mut weight = <Runtime as frame_system::Config>::DbWeight::get().reads(1);186187 let version =188 migration::get_storage_value::<()>(b"AuraToCollatorSelection", b"StorageVersion", &[]);189190 let should_upgrade = match version {191 None => true,192 Some(_) => false,193 };194195 if should_upgrade {196 log::info!(197 target: "runtime::aura_to_collator_selection",198 "Running migration of Aura authorities to Collator Selection invulnerables"199 );200201 let invulnerables = pallet_aura::Pallet::<Runtime>::authorities()202 .iter()203 .cloned()204 .filter_map(|authority_id| {205 weight.saturating_accrue(<Runtime as frame_system::Config>::DbWeight::get().reads_writes(1, 1));206 let vec = authority_id.clone().to_raw_vec();207 let slice = vec.as_slice();208 let array: Option<[u8; 32]> = match slice.try_into() {209 Ok(a) => Some(a),210 Err(_) => {211 log::error!("Failed to convert an Aura authority to a Collator Selection invulnerable: {:?}", authority_id);212 None213 },214 };215 array.map(|a| (AccountId::from(a), authority_id))216 })217 .collect::<Vec<_>>();218219 let bounded_invulnerables = BoundedVec::<_, MaxInvulnerables>::try_from(220 invulnerables221 .iter()222 .cloned()223 .map(|(acc, _)| acc)224 .collect::<Vec<_>>(),225 )226 .expect("Existing collators/invulnerables are more than MaxInvulnerables");227 228 <pallet_collator_selection::Invulnerables<Runtime>>::put(bounded_invulnerables);229 <pallet_collator_selection::DesiredCandidates<Runtime>>::put(0);230 <pallet_collator_selection::CandidacyBond<Runtime>>::put(EXISTENTIAL_DEPOSIT * 16);231232 let keys = invulnerables233 .into_iter()234 .map(|(acc, aura)| {235 (236 acc.clone(), // account id237 acc, // validator id238 SessionKeys { aura: aura.clone() }, // session keys239 )240 })241 .collect::<Vec<_>>();242243 for (account, val, keys) in keys.iter().cloned() {244 for id in <Runtime as pallet_session::Config>::Keys::key_ids() {245 <pallet_session::KeyOwner<Runtime>>::insert((*id, keys.get_raw(*id)), &val)246 }247 <pallet_session::NextKeys<Runtime>>::insert(&val, &keys);248 // todo exercise caution, the following is taken from genesis249 if frame_system::Pallet::<Runtime>::inc_consumers_without_limit(&account).is_err() {250 log::warn!(251 "We have entered an error with incrementing consumers without limit"252 );253 // This will leak a provider reference, however it only happens once (at254 // genesis) so it's really not a big deal and we assume that the user wants to255 // do this since it's the only way a non-endowed account can contain a session256 // key.257 frame_system::Pallet::<Runtime>::inc_providers(&account);258 }259 }260261 let initial_validators_0 =262 <Runtime as pallet_session::Config>::SessionManager::new_session(0).unwrap_or_else(263 || {264 frame_support::print(265 "No initial validator provided by `SessionManager`, use \266 session config keys to generate initial validator set.",267 );268 keys.iter().map(|x| x.1.clone()).collect()269 },270 );271 /*assert!(272 !initial_validators_0.is_empty(),273 "Empty validator set for session 0 in (pseudo) genesis block!"274 );*/275276 let initial_validators_1 =277 <Runtime as pallet_session::Config>::SessionManager::new_session(1)278 .unwrap_or_else(|| initial_validators_0.clone());279 /*assert!(280 !initial_validators_1.is_empty(),281 "Empty validator set for session 1 in (pseudo) genesis block!"282 );*/283284 let queued_keys: Vec<_> = initial_validators_1285 .iter()286 .cloned()287 .map(|v| {288 (289 v.clone(),290 <pallet_session::NextKeys<Runtime>>::get(&v)291 .expect("Validator in session 1 missing keys!"),292 )293 })294 .collect();295296 // Tell everyone about the genesis session keys -- Aura must've already initialized it297 //<Runtime as pallet_session::Config>::SessionHandler::on_genesis_session::<<Runtime as pallet_session::Config>::Keys>(&queued_keys);298299 <pallet_session::Validators<Runtime>>::put(initial_validators_0);300 <pallet_session::QueuedKeys<Runtime>>::put(queued_keys);301302 <Runtime as pallet_session::Config>::SessionManager::start_session(0);303304 log::info!(305 target: "runtime::aura_to_collator_selection",306 "Migration of Aura authorities to Collator Selection invulnerables is complete."307 );308309 migration::put_storage_value::<()>(310 b"AuraToCollatorSelection",311 b"StorageVersion",312 &[],313 (),314 );315316 weight += <Runtime as frame_system::Config>::DbWeight::get().writes(1)317 } else {318 log::info!(319 target: "runtime::aura_to_collator_selection",320 "The storage migration has already been flagged as complete. No migration needs to be done.",321 );322 }323324 weight325 }326}1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617pub mod config;18pub mod construct_runtime;19pub mod dispatch;20pub mod ethereum;21pub mod instance;22pub mod runtime_apis;23pub mod scheduler;24pub mod sponsoring;25pub mod weights;2627use sp_core::H160;28use frame_support::{29 traits::{Currency, OnUnbalanced, Imbalance},30 weights::Weight,31};32use sp_runtime::{33 generic,34 traits::{BlakeTwo256, BlockNumberProvider},35 impl_opaque_keys,36};37use sp_std::vec::Vec;3839#[cfg(feature = "std")]40use sp_version::NativeVersion;4142use crate::{43 Runtime, Call, Balances, Treasury, Aura, Signature, AllPalletsReversedWithSystemFirst,44 InherentDataExt,45};46use up_common::types::{AccountId, BlockNumber};4748#[macro_export]49macro_rules! unsupported {50 () => {51 pallet_common::unsupported!($crate::Runtime)52 };53}5455/// The address format for describing accounts.56pub type Address = sp_runtime::MultiAddress<AccountId, ()>;57/// Block header type as expected by this runtime.58pub type Header = generic::Header<BlockNumber, BlakeTwo256>;59/// Block type as expected by this runtime.60pub type Block = generic::Block<Header, UncheckedExtrinsic>;61/// A Block signed with a Justification62pub type SignedBlock = generic::SignedBlock<Block>;63/// BlockId type as expected by this runtime.64pub type BlockId = generic::BlockId<Block>;6566impl_opaque_keys! {67 pub struct SessionKeys {68 pub aura: Aura,69 }70}7172/// The version information used to identify this runtime when compiled natively.73#[cfg(feature = "std")]74pub fn native_version() -> NativeVersion {75 NativeVersion {76 runtime_version: crate::VERSION,77 can_author_with: Default::default(),78 }79}8081pub type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;8283pub type SignedExtra = (84 frame_system::CheckSpecVersion<Runtime>,85 // system::CheckTxVersion<Runtime>,86 frame_system::CheckGenesis<Runtime>,87 frame_system::CheckEra<Runtime>,88 frame_system::CheckNonce<Runtime>,89 frame_system::CheckWeight<Runtime>,90 ChargeTransactionPayment,91 //pallet_contract_helpers::ContractHelpersExtension<Runtime>,92 pallet_ethereum::FakeTransactionFinalizer<Runtime>,93);9495/// Unchecked extrinsic type as expected by this runtime.96pub type UncheckedExtrinsic =97 fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;9899/// Extrinsic type that has already been checked.100pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;101102/// Executive: handles dispatch to the various modules.103pub type Executive = frame_executive::Executive<104 Runtime,105 Block,106 frame_system::ChainContext<Runtime>,107 Runtime,108 AllPalletsReversedWithSystemFirst,109 AuraToCollatorSelection,110>;111112type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;113114pub struct DealWithFees;115impl OnUnbalanced<NegativeImbalance> for DealWithFees {116 fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {117 if let Some(fees) = fees_then_tips.next() {118 // for fees, 100% to treasury119 let mut split = fees.ration(100, 0);120 if let Some(tips) = fees_then_tips.next() {121 // for tips, if any, 100% to treasury122 tips.ration_merge_into(100, 0, &mut split);123 }124 Treasury::on_unbalanced(split.0);125 // Author::on_unbalanced(split.1);126 }127 }128}129130pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);131132impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider133 for RelayChainBlockNumberProvider<T>134{135 type BlockNumber = BlockNumber;136137 fn current_block_number() -> Self::BlockNumber {138 cumulus_pallet_parachain_system::Pallet::<T>::validation_data()139 .map(|d| d.relay_parent_number)140 .unwrap_or_default()141 }142}143144pub(crate) struct CheckInherents;145146impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {147 fn check_inherents(148 block: &Block,149 relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,150 ) -> sp_inherents::CheckInherentsResult {151 let relay_chain_slot = relay_state_proof152 .read_slot()153 .expect("Could not read the relay chain slot from the proof");154155 let inherent_data =156 cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(157 relay_chain_slot,158 sp_std::time::Duration::from_secs(6),159 )160 .create_inherent_data()161 .expect("Could not create the timestamp inherent data");162163 inherent_data.check_extrinsics(block)164 }165}166167#[derive(codec::Encode, codec::Decode)]168pub enum XCMPMessage<XAccountId, XBalance> {169 /// Transfer tokens to the given account from the Parachain account.170 TransferToken(XAccountId, XBalance),171}172173pub struct AuraToCollatorSelection;174impl frame_support::traits::OnRuntimeUpgrade for AuraToCollatorSelection {175 fn on_runtime_upgrade() -> Weight {176 use frame_support::{BoundedVec, storage::migration};177 use sp_runtime::{178 traits::{OpaqueKeys, Saturating},179 RuntimeAppPublic,180 };181 use pallet_session::SessionManager;182 use up_common::constants::EXISTENTIAL_DEPOSIT;183 use crate::config::substrate::MaxInvulnerables;184185 let mut weight = <Runtime as frame_system::Config>::DbWeight::get().reads(1);186187 let version =188 migration::get_storage_value::<()>(b"AuraToCollatorSelection", b"StorageVersion", &[]);189190 let should_upgrade = match version {191 None => true,192 Some(_) => false,193 };194195 if should_upgrade {196 log::info!(197 target: "runtime::aura_to_collator_selection",198 "Running migration of Aura authorities to Collator Selection invulnerables"199 );200201 let invulnerables = pallet_aura::Pallet::<Runtime>::authorities()202 .iter()203 .cloned()204 .filter_map(|authority_id| {205 weight.saturating_accrue(<Runtime as frame_system::Config>::DbWeight::get().reads_writes(1, 1));206 let vec = authority_id.clone().to_raw_vec();207 let slice = vec.as_slice();208 let array: Option<[u8; 32]> = match slice.try_into() {209 Ok(a) => Some(a),210 Err(_) => {211 log::error!("Failed to convert an Aura authority to a Collator Selection invulnerable: {:?}", authority_id);212 None213 },214 };215 array.map(|a| (AccountId::from(a), authority_id))216 })217 .collect::<Vec<_>>();218219 let bounded_invulnerables = BoundedVec::<_, MaxInvulnerables>::try_from(220 invulnerables221 .iter()222 .cloned()223 .map(|(acc, _)| acc)224 .collect::<Vec<_>>(),225 )226 .expect("Existing collators/invulnerables are more than MaxInvulnerables");227228 <pallet_collator_selection::Invulnerables<Runtime>>::put(bounded_invulnerables);229 <pallet_collator_selection::DesiredCandidates<Runtime>>::put(0);230 <pallet_collator_selection::CandidacyBond<Runtime>>::put(EXISTENTIAL_DEPOSIT * 16);231232 let keys = invulnerables233 .into_iter()234 .map(|(acc, aura)| {235 (236 acc.clone(), // account id237 acc, // validator id238 SessionKeys { aura: aura.clone() }, // session keys239 )240 })241 .collect::<Vec<_>>();242243 for (account, val, keys) in keys.iter().cloned() {244 for id in <Runtime as pallet_session::Config>::Keys::key_ids() {245 <pallet_session::KeyOwner<Runtime>>::insert((*id, keys.get_raw(*id)), &val)246 }247 <pallet_session::NextKeys<Runtime>>::insert(&val, &keys);248 // todo exercise caution, the following is taken from genesis249 if frame_system::Pallet::<Runtime>::inc_consumers_without_limit(&account).is_err() {250 log::warn!(251 "We have entered an error with incrementing consumers without limit during the migration"252 );253 // This will leak a provider reference, however it only happens once (at254 // genesis) so it's really not a big deal and we assume that the user wants to255 // do this since it's the only way a non-endowed account can contain a session256 // key.257 frame_system::Pallet::<Runtime>::inc_providers(&account);258 }259 }260261 let initial_validators_0 =262 <Runtime as pallet_session::Config>::SessionManager::new_session(0).unwrap_or_else(263 || {264 frame_support::print(265 "No initial validator provided by `SessionManager`, use \266 session config keys to generate initial validator set.",267 );268 keys.iter().map(|x| x.1.clone()).collect()269 },270 );271 /*assert!(272 !initial_validators_0.is_empty(),273 "Empty validator set for session 0 in (pseudo) genesis block!"274 );*/275276 let initial_validators_1 =277 <Runtime as pallet_session::Config>::SessionManager::new_session(1)278 .unwrap_or_else(|| initial_validators_0.clone());279 /*assert!(280 !initial_validators_1.is_empty(),281 "Empty validator set for session 1 in (pseudo) genesis block!"282 );*/283284 let queued_keys: Vec<_> = initial_validators_1285 .iter()286 .cloned()287 .map(|v| {288 (289 v.clone(),290 <pallet_session::NextKeys<Runtime>>::get(&v)291 .expect("Validator in session 1 missing keys!"),292 )293 })294 .collect();295296 // Tell everyone about the genesis session keys -- Aura must've already initialized it297 //<Runtime as pallet_session::Config>::SessionHandler::on_genesis_session::<<Runtime as pallet_session::Config>::Keys>(&queued_keys);298299 <pallet_session::Validators<Runtime>>::put(initial_validators_0);300 <pallet_session::QueuedKeys<Runtime>>::put(queued_keys);301302 <Runtime as pallet_session::Config>::SessionManager::start_session(0);303304 log::info!(305 target: "runtime::aura_to_collator_selection",306 "Migration of Aura authorities to Collator Selection invulnerables is complete."307 );308309 migration::put_storage_value::<()>(310 b"AuraToCollatorSelection",311 b"StorageVersion",312 &[],313 (),314 );315316 weight += <Runtime as frame_system::Config>::DbWeight::get().writes(1)317 } else {318 log::info!(319 target: "runtime::aura_to_collator_selection",320 "The storage migration has already been flagged as complete. No migration needs to be done.",321 );322 }323324 weight325 }326}tests/src/shuffleCollators.test.tsdiffbeforeafterboth--- a/tests/src/shuffleCollators.test.ts
+++ b/tests/src/shuffleCollators.test.ts
@@ -16,85 +16,89 @@
import {IKeyringPair} from '@polkadot/types/types';
import privateKey from './substrate/privateKey';
-import usingApi, { submitTransactionAsync } from './substrate/substrate-api';
+import usingApi, {submitTransactionAsync} from './substrate/substrate-api';
import waitNewBlocks from './substrate/wait-new-blocks';
import {expect} from 'chai';
-import { getGenericResult } from './util/helpers';
+import {getBlockNumber, getGenericResult} from './util/helpers';
let alice: IKeyringPair;
let bob: IKeyringPair;
let charlie: IKeyringPair;
let dave: IKeyringPair;
-let eve: IKeyringPair;
+//let eve: IKeyringPair;
describe('Integration Test: Dynamic shuffling of collators', () => {
- before(async () => {
- await usingApi(async () => {
- alice = privateKey('//Alice');
- bob = privateKey('//Bob');
- charlie = privateKey('//Charlie');
- dave = privateKey('//Dave');
- eve = privateKey('//Eve');
- });
+ before(async () => {
+ await usingApi(async () => {
+ alice = privateKey('//Alice');
+ bob = privateKey('//Bob');
+ charlie = privateKey('//Charlie');
+ dave = privateKey('//Dave');
+ //eve = privateKey('//Eve');
});
+ });
- it('Change invulnerables and make sure they start producing blocks', async () => {
- await usingApi(async (api) => {
- const txC = api.tx.session.setKeys(
- '0x' + Buffer.from(charlie.addressRaw).toString('hex'),
- '0x0'
- );
- const eventsC = await submitTransactionAsync(charlie, txC);
- const resultC = getGenericResult(eventsC);
- expect(resultC.success).to.be.true;
+ it('Change invulnerables and make sure they start producing blocks', async () => {
+ await usingApi(async (api) => {
+ const txC = api.tx.session.setKeys(
+ '0x' + Buffer.from(charlie.addressRaw).toString('hex'),
+ '0x0',
+ );
+ const eventsC = await submitTransactionAsync(charlie, txC);
+ const resultC = getGenericResult(eventsC);
+ expect(resultC.success).to.be.true;
- const txD = api.tx.session.setKeys(
- '0x' + Buffer.from(dave.addressRaw).toString('hex'),
- '0x0'
- );
- const eventsD = await submitTransactionAsync(dave, txD);
- const resultD = getGenericResult(eventsD);
- expect(resultD.success).to.be.true;
+ const txD = api.tx.session.setKeys(
+ '0x' + Buffer.from(dave.addressRaw).toString('hex'),
+ '0x0',
+ );
+ const eventsD = await submitTransactionAsync(dave, txD);
+ const resultD = getGenericResult(eventsD);
+ expect(resultD.success).to.be.true;
- const tx = api.tx.collatorSelection.setInvulnerables([
- charlie.address,
- dave.address
- ]);
- const sudoTx = api.tx.sudo.sudo(tx as any);
- const events = await submitTransactionAsync(alice, sudoTx);
- const result = getGenericResult(events);
- expect(result.success).to.be.true;
+ const tx = api.tx.collatorSelection.setInvulnerables([
+ charlie.address,
+ dave.address,
+ ]);
+ const sudoTx = api.tx.sudo.sudo(tx as any);
+ const events = await submitTransactionAsync(alice, sudoTx);
+ const result = getGenericResult(events);
+ expect(result.success).to.be.true;
- let newInvulnerables = (await api.query.collatorSelection.invulnerables()).toJSON();
- expect(newInvulnerables).to.contain(charlie.address).and.contain(dave.address);
- expect(newInvulnerables).to.be.length(2);
+ const newInvulnerables = (await api.query.collatorSelection.invulnerables()).toJSON();
+ expect(newInvulnerables).to.contain(charlie.address).and.contain(dave.address);
+ expect(newInvulnerables).to.be.length(2);
- const expectedSessionIndex = (await api.query.session.currentIndex() as any).toNumber() + 2;
- let currentSessionIndex = -1;
- while (currentSessionIndex < expectedSessionIndex) {
- await waitNewBlocks(api, 1);
- currentSessionIndex = (await api.query.session.currentIndex() as any).toNumber();
- // todo implement a timeout in case new blocks are not being produced
- }
+ const expectedSessionIndex = (await api.query.session.currentIndex() as any).toNumber() + 2;
+ let currentSessionIndex = -1;
+ while (currentSessionIndex < expectedSessionIndex) {
+ await waitNewBlocks(api, 1);
+ currentSessionIndex = (await api.query.session.currentIndex() as any).toNumber();
+ // todo implement a timeout in case new blocks are not being produced? session length needed
+ }
- let newValidators = (await api.query.session.validators()).toJSON();
- expect(newValidators).to.contain(charlie.address).and.contain(dave.address);
- expect(newValidators).to.be.length(2);
+ const newValidators = (await api.query.session.validators()).toJSON();
+ expect(newValidators).to.contain(charlie.address).and.contain(dave.address);
+ expect(newValidators).to.be.length(2);
- // todo add delay to check that new blocks are authored by these
- });
+ const lastBlockNumber = await getBlockNumber(api);
+ await waitNewBlocks(api, 1);
+ const lastCharlieBlock = (await api.query.collatorSelection.lastAuthoredBlock(charlie.address) as any).toNumber();
+ const lastDaveBlock = (await api.query.collatorSelection.lastAuthoredBlock(dave.address) as any).toNumber();
+ expect(lastCharlieBlock >= lastBlockNumber || lastDaveBlock >= lastBlockNumber).to.be.true;
});
+ });
- after(async () => {
- await usingApi(async (api) => {
- const tx = api.tx.collatorSelection.setInvulnerables([
- alice.address,
- bob.address
- ]);
- const sudoTx = api.tx.sudo.sudo(tx as any);
- const events = await submitTransactionAsync(alice, sudoTx);
- const result = getGenericResult(events);
- expect(result.success).to.be.true;
- });
+ after(async () => {
+ await usingApi(async (api) => {
+ const tx = api.tx.collatorSelection.setInvulnerables([
+ alice.address,
+ bob.address,
+ ]);
+ const sudoTx = api.tx.sudo.sudo(tx as any);
+ const events = await submitTransactionAsync(alice, sudoTx);
+ const result = getGenericResult(events);
+ expect(result.success).to.be.true;
});
+ });
});