diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9315fc135..f692d6437 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -440,6 +440,61 @@ jobs: name: logs path: logs + zombienet-tests-rotation: + runs-on: self-hosted + needs: ["set-tags", "build"] + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + ref: ${{ needs.set-tags.outputs.git_ref }} + + - name: Pnpm + uses: pnpm/action-setup@v2 + with: + version: 8 + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: 20.x + cache: "pnpm" + + - name: "Download binaries" + uses: actions/download-artifact@v3.0.2 + with: + name: binaries + path: target/release + + - name: "Run zombie test" + run: | + chmod uog+x target/release/tanssi-node + chmod uog+x target/release/container-chain-template-simple-node + chmod uog+x target/release/container-chain-template-frontier-node + + cd test + pnpm install + + ## Run tests + + pnpm moonwall test zombie_tanssi_rotation + + - name: "Gather zombie logs" + if: failure() + run: | + ls -ltr /tmp + latest_zombie_dir=$(find /tmp -type d -iname "*zombie*" -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" ") + logs_dir="logs" + mkdir -p "$logs_dir" + find "$latest_zombie_dir" -type f -name "*.log" -exec cp {} "$logs_dir" \; + + - name: "Upload zombie logs" + if: failure() + uses: actions/upload-artifact@v3.1.2 + with: + name: logs-rotation + path: logs + zombienet-tests-warp-sync: runs-on: ubuntu-latest needs: ["set-tags", "build"] diff --git a/Cargo.lock b/Cargo.lock index c935c8424..b3732ad09 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2820,8 +2820,10 @@ dependencies = [ "cumulus-pallet-xcm", "cumulus-pallet-xcmp-queue", "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", "cumulus-primitives-timestamp", "cumulus-primitives-utility", + "cumulus-test-relay-sproof-builder", "frame-benchmarking", "frame-executive", "frame-support", @@ -7499,6 +7501,7 @@ dependencies = [ "log", "parity-scale-codec", "rand 0.8.5", + "rand_chacha 0.3.1", "scale-info", "serde", "sp-core", diff --git a/Cargo.toml b/Cargo.toml index a8082e567..2302a4e6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -186,6 +186,7 @@ cumulus-client-pov-recovery = { git = "https://github.com/moondance-labs/polkado cumulus-client-service = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-v1.1.0", default-features = false } cumulus-primitives-parachain-inherent = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-v1.1.0", default-features = false } cumulus-relay-chain-interface = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-v1.1.0", default-features = false } +cumulus-test-relay-sproof-builder = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-v1.1.0", default-features = false } xcm-emulator = { git = "https://github.com/moondance-labs/polkadot-sdk", branch = "tanssi-polkadot-v1.1.0", default-features = false } # Frontier (wasm) @@ -220,6 +221,7 @@ hex-literal = { version = "0.3.4" } log = { version = "0.4.17", default-features = false } serde = { version = "1.0.152", default-features = false } smallvec = "1.10.0" +rand_chacha = { version = "0.3.1", default-features = false } # General (client) async-io = "1.3" diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index caaea5549..a839793db 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -17,8 +17,8 @@ use { cumulus_primitives_core::ParaId, dancebox_runtime::{ - AccountId, MaintenanceModeConfig, MigrationsConfig, PolkadotXcmConfig, RegistrarConfig, - Signature, SudoConfig, + prod_or_fast, AccountId, MaintenanceModeConfig, MigrationsConfig, PolkadotXcmConfig, + RegistrarConfig, Signature, SudoConfig, }, nimbus_primitives::NimbusId, pallet_configuration::HostConfiguration, @@ -195,6 +195,7 @@ pub fn development_config( min_orchestrator_collators: 1u32, max_orchestrator_collators: 1u32, collators_per_container: 2u32, + full_rotation_period: prod_or_fast!(24u32, 5u32), }, ..Default::default() }, @@ -259,6 +260,7 @@ pub fn local_dancebox_config( min_orchestrator_collators: 2u32, max_orchestrator_collators: 5u32, collators_per_container: 2u32, + full_rotation_period: prod_or_fast!(24u32, 5u32), }, ..Default::default() }, diff --git a/pallets/authority-assignment/src/mock.rs b/pallets/authority-assignment/src/mock.rs index 5b56de7fc..d8b876fd9 100644 --- a/pallets/authority-assignment/src/mock.rs +++ b/pallets/authority-assignment/src/mock.rs @@ -140,6 +140,7 @@ pub fn run_to_block(n: u64) { let old_block_number = System::block_number(); for x in (old_block_number + 1)..=n { + System::reset_events(); System::set_block_number(x); if x % SESSION_LEN == 1 { diff --git a/pallets/collator-assignment/Cargo.toml b/pallets/collator-assignment/Cargo.toml index b957c13b5..0e55cb101 100644 --- a/pallets/collator-assignment/Cargo.toml +++ b/pallets/collator-assignment/Cargo.toml @@ -21,7 +21,8 @@ sp-std = { workspace = true } tp-collator-assignment = { workspace = true } tp-traits = { workspace = true } frame-benchmarking = { workspace = true } -rand = { workspace = true, optional = true } +rand = { workspace = true } +rand_chacha = { workspace = true } [dev-dependencies] sp-io = { workspace = true } @@ -44,7 +45,6 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "rand", "tp-traits/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime" ] diff --git a/pallets/collator-assignment/src/benchmarking.rs b/pallets/collator-assignment/src/benchmarking.rs index 105bd38cc..851fbdfd3 100644 --- a/pallets/collator-assignment/src/benchmarking.rs +++ b/pallets/collator-assignment/src/benchmarking.rs @@ -47,6 +47,14 @@ fn invulnerables(count: u32, seed: u32) -> Vec invulnerables } +fn assert_last_event(generic_event: ::RuntimeEvent) { + let events = frame_system::Pallet::::events(); + let system_event: ::RuntimeEvent = generic_event.into(); + // compare to the last event record + let EventRecord { event, .. } = &events[events.len() - 1]; + assert_eq!(event, &system_event); +} + #[benchmarks] mod benchmarks { use super::*; @@ -75,6 +83,9 @@ mod benchmarks { container_chains: BTreeMap::from_iter(old_container_chains), }; >::put(&old_assigned); + // Do not use [0; 32] because that seed will not shuffle the list of collators + let random_seed = [1; 32]; + >::put(random_seed); #[block] { @@ -89,6 +100,16 @@ mod benchmarks { 0 ); + // Worst case is `full_rotation: false` because it needs to check the previous assignment + assert_last_event::( + Event::NewPendingAssignment { + random_seed, + full_rotation: false, + target_session: T::SessionIndex::from(1u32), + } + .into(), + ); + Ok(()) } diff --git a/pallets/collator-assignment/src/lib.rs b/pallets/collator-assignment/src/lib.rs index 2e59067e0..561e4cb01 100644 --- a/pallets/collator-assignment/src/lib.rs +++ b/pallets/collator-assignment/src/lib.rs @@ -45,14 +45,18 @@ pub use pallet::*; use { crate::weights::WeightInfo, frame_support::pallet_prelude::*, + frame_system::pallet_prelude::BlockNumberFor, + rand::{seq::SliceRandom, SeedableRng}, + rand_chacha::ChaCha20Rng, sp_runtime::{ traits::{AtLeast32BitUnsigned, One, Zero}, Saturating, }, - sp_std::{prelude::*, vec}, + sp_std::{fmt::Debug, prelude::*, vec}, tp_collator_assignment::AssignedCollators, tp_traits::{ - GetContainerChainAuthor, GetHostConfiguration, GetSessionContainerChains, ParaId, Slot, + GetContainerChainAuthor, GetHostConfiguration, GetSessionContainerChains, ParaId, + ShouldRotateAllCollators, Slot, }, }; @@ -77,16 +81,34 @@ pub mod pallet { /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] pub trait Config: frame_system::Config { - type SessionIndex: parity_scale_codec::FullCodec + TypeInfo + Copy + AtLeast32BitUnsigned; + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type SessionIndex: parity_scale_codec::FullCodec + + TypeInfo + + Copy + + AtLeast32BitUnsigned + + Debug; // `SESSION_DELAY` is used to delay any changes to Paras registration or configurations. // Wait until the session index is 2 larger then the current index to apply any changes, // which guarantees that at least one full session has passed before any changes are applied. type HostConfiguration: GetHostConfiguration; type ContainerChains: GetSessionContainerChains; + type ShouldRotateAllCollators: ShouldRotateAllCollators; + type GetRandomnessForNextBlock: GetRandomnessForNextBlock>; /// The weight information of this pallet. type WeightInfo: WeightInfo; } + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + NewPendingAssignment { + random_seed: [u8; 32], + full_rotation: bool, + target_session: T::SessionIndex, + }, + } + #[pallet::storage] #[pallet::getter(fn collator_container_chain)] pub(crate) type CollatorContainerChain = @@ -104,6 +126,13 @@ pub mod pallet { pub(crate) type PendingCollatorContainerChain = StorageValue<_, Option>, ValueQuery>; + /// Randomness from previous block. Used to shuffle collators on session change. + /// Should only be set on the last block of each session and should be killed on the on_initialize of the next block. + /// The default value of [0; 32] disables randomness in the pallet. + #[pallet::storage] + #[pallet::getter(fn randomness)] + pub(crate) type Randomness = StorageValue<_, [u8; 32], ValueQuery>; + #[pallet::call] impl Pallet {} @@ -121,26 +150,78 @@ pub mod pallet { /// collators should be queued collators pub fn assign_collators( current_session_index: &T::SessionIndex, - collators: Vec, + random_seed: [u8; 32], + mut collators: Vec, ) -> SessionChangeOutcome { // We work with one session delay to calculate assignments let session_delay = T::SessionIndex::one(); let target_session_index = current_session_index.saturating_add(session_delay); // We get the containerChains that we will have at the target session - let container_chain_ids = + let mut container_chain_ids = T::ContainerChains::session_container_chains(target_session_index); + + // If the random_seed is all zeros, we don't shuffle the list of collators nor the list + // of container chains. + // This should only happen in tests, and in the genesis block. + if random_seed != [0; 32] { + let mut rng: ChaCha20Rng = SeedableRng::from_seed(random_seed); + collators.shuffle(&mut rng); + container_chain_ids.shuffle(&mut rng); + } + // We read current assigned collators let old_assigned = Self::read_assigned_collators(); // We assign new collators // we use the config scheduled at the target_session_index - let new_assigned = Self::assign_collators_always_keep_old( - collators, - &container_chain_ids, - T::HostConfiguration::min_collators_for_orchestrator(target_session_index) as usize, - T::HostConfiguration::max_collators_for_orchestrator(target_session_index) as usize, - T::HostConfiguration::collators_per_container(target_session_index) as usize, - old_assigned.clone(), - ); + let new_assigned = + if T::ShouldRotateAllCollators::should_rotate_all_collators(target_session_index) { + log::info!( + "Collator assignment: rotating collators. Session {:?}, Seed: {:?}", + current_session_index.encode(), + random_seed + ); + + Self::deposit_event(Event::NewPendingAssignment { + random_seed, + full_rotation: true, + target_session: target_session_index, + }); + + Self::assign_collators_rotate_all( + collators, + &container_chain_ids, + T::HostConfiguration::min_collators_for_orchestrator(target_session_index) + as usize, + T::HostConfiguration::max_collators_for_orchestrator(target_session_index) + as usize, + T::HostConfiguration::collators_per_container(target_session_index) + as usize, + ) + } else { + log::info!( + "Collator assignment: keep old assigned. Session {:?}, Seed: {:?}", + current_session_index.encode(), + random_seed + ); + + Self::deposit_event(Event::NewPendingAssignment { + random_seed, + full_rotation: false, + target_session: target_session_index, + }); + + Self::assign_collators_always_keep_old( + collators, + &container_chain_ids, + T::HostConfiguration::min_collators_for_orchestrator(target_session_index) + as usize, + T::HostConfiguration::max_collators_for_orchestrator(target_session_index) + as usize, + T::HostConfiguration::collators_per_container(target_session_index) + as usize, + old_assigned.clone(), + ) + }; let mut pending = PendingCollatorContainerChain::::get(); let old_assigned_changed = old_assigned != new_assigned; @@ -174,9 +255,35 @@ pub mod pallet { } } + /// Recompute collator assignment from scratch. If the list of collators and the list of + /// container chains are shuffled, this returns a random assignment. + fn assign_collators_rotate_all( + collators: Vec, + container_chain_ids: &[ParaId], + min_num_orchestrator_chain: usize, + max_num_orchestrator_chain: usize, + num_each_container_chain: usize, + ) -> AssignedCollators { + // This is just the "always_keep_old" algorithm but with an empty "old" + let old_assigned = Default::default(); + + Self::assign_collators_always_keep_old( + collators, + container_chain_ids, + min_num_orchestrator_chain, + max_num_orchestrator_chain, + num_each_container_chain, + old_assigned, + ) + } + /// Assign new collators to missing container_chains. /// Old collators always have preference to remain on the same chain. /// If there are no missing collators, nothing is changed. + /// + /// `container_chain_ids` should be shuffled or at least rotated on every session to ensure + /// a fair distribution, because the order of that list affects container chain priority: + /// the first container chain on that list will be the first one to get new collators. fn assign_collators_always_keep_old( collators: Vec, container_chain_ids: &[ParaId], @@ -196,10 +303,8 @@ pub mod pallet { new_assigned.remove_container_chain_excess_collators(num_each_container_chain); // Collators that are not present in old_assigned - // TODO: unless we save all the old_collators somewhere, it is still possible for a - // collator to change from container_chain 1001 to None to 1002 - // And ideally that should not happen until the automatic chain rotation is implemented - // But the current implementation allows changes, even without passing through None + // This is used to keep track of which collators are old and which ones are new, to keep + // the old collators on the same chain if possible. let mut new_collators = vec![]; for c in collators { if !new_assigned.find_collator(&c) && !extra_orchestrator_collators.contains(&c) { @@ -219,9 +324,10 @@ pub mod pallet { let mut new_plus_extra_collators = new_collators .by_ref() .chain(&mut extra_orchestrator_collators); - new_assigned.add_new_container_chains(container_chain_ids); - new_assigned.fill_container_chain_collators( + + new_assigned.add_and_fill_new_container_chains_in_order( num_each_container_chain, + container_chain_ids, &mut new_plus_extra_collators, ); @@ -243,7 +349,10 @@ pub mod pallet { // [2, 2, 0, 0, 0] // and assign 1 extra collator to the orchestrator chain, if needed. let incomplete_container_chains_collators = new_assigned - .reorganize_incomplete_container_chains_collators(num_each_container_chain); + .reorganize_incomplete_container_chains_collators( + container_chain_ids, + num_each_container_chain, + ); // Assign collators from container chains that do not reach // "num_each_container_chain" to orchestrator chain @@ -273,8 +382,9 @@ pub mod pallet { session_index: &T::SessionIndex, collators: Vec, ) -> SessionChangeOutcome { + let random_seed = Randomness::::take(); let num_collators = collators.len(); - let assigned_collators = Self::assign_collators(session_index, collators); + let assigned_collators = Self::assign_collators(session_index, random_seed, collators); let num_parachains = assigned_collators.next_assignment.container_chains.len(); frame_system::Pallet::::register_extra_weight_unchecked( @@ -305,4 +415,49 @@ pub mod pallet { CollatorContainerChain::::put(assigned_collators); } } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(n: BlockNumberFor) -> Weight { + let mut weight = Weight::zero(); + + // Account reads and writes for on_finalize + if T::GetRandomnessForNextBlock::should_end_session(n.saturating_add(One::one())) { + weight += T::DbWeight::get().reads_writes(1, 1); + } + + weight + } + + fn on_finalize(n: BlockNumberFor) { + // If the next block is a session change, read randomness and store in pallet storage + if T::GetRandomnessForNextBlock::should_end_session(n.saturating_add(One::one())) { + let random_seed = T::GetRandomnessForNextBlock::get_randomness(); + Randomness::::put(random_seed); + } + } + } +} + +pub struct RotateCollatorsEveryNSessions(PhantomData); + +impl ShouldRotateAllCollators for RotateCollatorsEveryNSessions +where + Period: Get, +{ + fn should_rotate_all_collators(session_index: u32) -> bool { + let period = Period::get(); + + if period == 0 { + // A period of 0 disables rotation + false + } else { + session_index % Period::get() == 0 + } + } +} + +pub trait GetRandomnessForNextBlock { + fn should_end_session(block_number: BlockNumber) -> bool; + fn get_randomness() -> [u8; 32]; } diff --git a/pallets/collator-assignment/src/mock.rs b/pallets/collator-assignment/src/mock.rs index 8bbea622b..db2e8f5bd 100644 --- a/pallets/collator-assignment/src/mock.rs +++ b/pallets/collator-assignment/src/mock.rs @@ -15,8 +15,14 @@ // along with Tanssi. If not, see use { - crate::{self as pallet_collator_assignment}, - frame_support::traits::{ConstU16, ConstU64}, + crate::{ + self as pallet_collator_assignment, GetRandomnessForNextBlock, + RotateCollatorsEveryNSessions, + }, + frame_support::{ + parameter_types, + traits::{ConstU16, ConstU64, Hooks}, + }, frame_system as system, parity_scale_codec::{Decode, Encode}, sp_core::H256, @@ -107,6 +113,7 @@ pub struct Mocks { pub collators_per_container: u32, pub collators: Vec, pub container_chains: Vec, + pub random_seed: [u8; 32], } impl mock_data::Config for Test {} @@ -157,10 +164,29 @@ impl tp_traits::GetSessionContainerChains for ContainerChainsGetter { } } +pub struct MockGetRandomnessForNextBlock; + +impl GetRandomnessForNextBlock for MockGetRandomnessForNextBlock { + fn should_end_session(n: u64) -> bool { + n % 5 == 0 + } + + fn get_randomness() -> [u8; 32] { + MockData::mock().random_seed + } +} + +parameter_types! { + pub const CollatorRotationSessionPeriod: u32 = 5; +} + impl pallet_collator_assignment::Config for Test { + type RuntimeEvent = RuntimeEvent; type SessionIndex = u32; type HostConfiguration = HostConfigurationGetter; type ContainerChains = ContainerChainsGetter; + type ShouldRotateAllCollators = RotateCollatorsEveryNSessions; + type GetRandomnessForNextBlock = MockGetRandomnessForNextBlock; type WeightInfo = (); } @@ -181,7 +207,9 @@ pub fn run_to_block(n: u64) { let session_len = 5; for x in (old_block_number + 1)..=n { + System::reset_events(); System::set_block_number(x); + CollatorAssignment::on_initialize(x); if x % session_len == 1 { let session_index = (x / session_len) as u32; @@ -190,5 +218,7 @@ pub fn run_to_block(n: u64) { CollatorsGetter::collators(session_index), ); } + + CollatorAssignment::on_finalize(x); } } diff --git a/pallets/collator-assignment/src/tests.rs b/pallets/collator-assignment/src/tests.rs index 006973c0d..35737d260 100644 --- a/pallets/collator-assignment/src/tests.rs +++ b/pallets/collator-assignment/src/tests.rs @@ -15,7 +15,7 @@ // along with Tanssi. If not, see use { - crate::{mock::*, CollatorContainerChain}, + crate::{mock::*, CollatorContainerChain, Event, PendingCollatorContainerChain}, std::collections::BTreeMap, }; @@ -638,3 +638,312 @@ fn assign_collators_reorganize_container_chains_if_not_enough_collators() { ); }); } + +#[test] +fn assign_collators_set_zero_per_container() { + new_test_ext().execute_with(|| { + run_to_block(1); + + MockData::mutate(|m| { + m.collators_per_container = 2; + m.min_orchestrator_chain_collators = 2; + m.max_orchestrator_chain_collators = 5; + + m.collators = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + m.container_chains = vec![1001, 1002, 1003, 1004]; + }); + assert_eq!(assigned_collators(), BTreeMap::new(),); + run_to_block(11); + + assert_eq!( + assigned_collators(), + BTreeMap::from_iter(vec![ + (1, 999), + (2, 999), + (3, 1001), + (4, 1001), + (5, 1002), + (6, 1002), + (7, 1003), + (8, 1003), + (9, 1004), + (10, 1004), + (11, 999), + (12, 999) + ]), + ); + + MockData::mutate(|m| { + // We don't want to assign collators to container chains anymore + m.collators_per_container = 0; + }); + run_to_block(21); + + // There are 5 collators in total: 0x4 container chains, plus 5 in the orchestrator chain + assert_eq!( + assigned_collators(), + BTreeMap::from_iter(vec![(1, 999), (2, 999), (3, 999), (11, 999), (12, 999),]), + ); + }); +} + +#[test] +fn assign_collators_rotation() { + new_test_ext().execute_with(|| { + run_to_block(1); + + MockData::mutate(|m| { + m.collators_per_container = 2; + m.min_orchestrator_chain_collators = 2; + m.max_orchestrator_chain_collators = 5; + + m.collators = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + m.container_chains = vec![1001, 1002, 1003, 1004]; + }); + assert_eq!(assigned_collators(), BTreeMap::new(),); + run_to_block(11); + + let initial_assignment = BTreeMap::from_iter(vec![ + (1, 999), + (2, 999), + (3, 1001), + (4, 1001), + (5, 1002), + (6, 1002), + (7, 1003), + (8, 1003), + (9, 1004), + (10, 1004), + (11, 999), + (12, 999), + ]); + + assert_eq!(assigned_collators(), initial_assignment,); + + MockData::mutate(|m| { + m.random_seed = [1; 32]; + }); + + // The rotation period is every 5 sessions, so the first session with a different assignment + // will be session 5. Collators are calculated one session in advance, so they will be decided + // on session 4. + run_to_block(20); + + assert_eq!(assigned_collators(), initial_assignment,); + assert_eq!(PendingCollatorContainerChain::::get(), None,); + + run_to_block(21); + assert_eq!(assigned_collators(), initial_assignment,); + + assert!(PendingCollatorContainerChain::::get().is_some(),); + + run_to_block(25); + assert_eq!(assigned_collators(), initial_assignment,); + run_to_block(26); + + // Random assignment depends on the seed, shouldn't change unless the algorithm changes + let shuffled_assignment = BTreeMap::from_iter(vec![ + (1, 1004), + (2, 999), + (3, 999), + (4, 1003), + (5, 1001), + (6, 1001), + (7, 999), + (8, 1002), + (9, 999), + (10, 1003), + (11, 1004), + (12, 1002), + ]); + + assert_eq!(assigned_collators(), shuffled_assignment,); + }); +} + +#[test] +fn assign_collators_rotation_container_chains_are_shuffled() { + new_test_ext().execute_with(|| { + run_to_block(1); + + MockData::mutate(|m| { + m.collators_per_container = 2; + m.min_orchestrator_chain_collators = 2; + m.max_orchestrator_chain_collators = 5; + + // 4 collators so we can only assign to one container chain + m.collators = vec![1, 2, 3, 4]; + m.container_chains = vec![1001, 1002]; + }); + assert_eq!(assigned_collators(), BTreeMap::new(),); + run_to_block(11); + + let initial_assignment = + BTreeMap::from_iter(vec![(1, 999), (2, 999), (3, 1001), (4, 1001)]); + + assert_eq!(assigned_collators(), initial_assignment,); + + MockData::mutate(|m| { + // Seed chosen manually to see the case where container 1002 is given priority + m.random_seed = [2; 32]; + }); + + run_to_block(26); + + // Random assignment depends on the seed, shouldn't change unless the algorithm changes + // Test that container chains are shuffled because 1001 does not have priority + let shuffled_assignment = + BTreeMap::from_iter(vec![(1, 999), (2, 1002), (3, 999), (4, 1002)]); + + assert_eq!(assigned_collators(), shuffled_assignment,); + }); +} + +#[test] +fn assign_collators_rotation_collators_are_shuffled() { + new_test_ext().execute_with(|| { + run_to_block(1); + + MockData::mutate(|m| { + m.collators_per_container = 2; + m.min_orchestrator_chain_collators = 2; + m.max_orchestrator_chain_collators = 5; + + // 10 collators but we only need 9, so 1 collator will not be assigned + m.collators = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + m.container_chains = vec![1001, 1002]; + }); + assert_eq!(assigned_collators(), BTreeMap::new(),); + run_to_block(11); + + let initial_assignment = BTreeMap::from_iter(vec![ + (1, 999), + (2, 999), + (3, 1001), + (4, 1001), + (5, 1002), + (6, 1002), + (7, 999), + (8, 999), + (9, 999), + ]); + + assert_eq!(assigned_collators(), initial_assignment,); + + MockData::mutate(|m| { + m.random_seed = [1; 32]; + }); + + run_to_block(26); + + // Random assignment depends on the seed, shouldn't change unless the algorithm changes + // Test that collators are shuffled because collator 10 should be the last one to be assigned, + // and here it is present + let shuffled_assignment = BTreeMap::from_iter(vec![ + (1, 999), + (3, 1001), + (4, 1001), + (5, 1002), + (6, 999), + (7, 999), + (8, 999), + (9, 1002), + (10, 999), + ]); + + assert_eq!(assigned_collators(), shuffled_assignment,); + }); +} + +#[test] +fn rotation_events() { + // Ensure that the NewPendingAssignment is correct + new_test_ext().execute_with(|| { + run_to_block(1); + + MockData::mutate(|m| { + m.collators_per_container = 2; + m.min_orchestrator_chain_collators = 2; + m.max_orchestrator_chain_collators = 5; + + m.collators = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + m.container_chains = vec![1001, 1002, 1003, 1004]; + }); + assert_eq!(assigned_collators(), BTreeMap::new(),); + + // Block 1 should emit event, random seed was not set + System::assert_last_event( + Event::NewPendingAssignment { + random_seed: [0; 32], + full_rotation: false, + target_session: 1, + } + .into(), + ); + + for i in 2..=11 { + run_to_block(i); + match i { + 6 | 11 => { + System::assert_last_event( + Event::NewPendingAssignment { + random_seed: [0; 32], + full_rotation: false, + target_session: (i / 5) as u32 + 1, + } + .into(), + ); + } + _ => { + assert_eq!( + System::events(), + vec![], + "Block #{} should not have any events", + i + ); + } + } + } + + MockData::mutate(|m| { + m.random_seed = [1; 32]; + }); + + // The rotation period is every 5 sessions, so the first session with a different assignment + // will be session 5. Collators are calculated one session in advance, so they will be decided + // on session 4, which starts on block 21. + for i in 12..=51 { + run_to_block(i); + match i { + 16 | 26 | 31 | 36 | 41 | 51 => { + System::assert_last_event( + Event::NewPendingAssignment { + random_seed: [1; 32], + full_rotation: false, + target_session: (i / 5) as u32 + 1, + } + .into(), + ); + } + 21 | 46 => { + System::assert_last_event( + Event::NewPendingAssignment { + random_seed: [1; 32], + full_rotation: true, + target_session: (i / 5) as u32 + 1, + } + .into(), + ); + } + _ => { + assert_eq!( + System::events(), + vec![], + "Block #{} should not have any events", + i + ); + } + } + } + }); +} diff --git a/pallets/configuration/src/lib.rs b/pallets/configuration/src/lib.rs index 3d2fea224..867a0240a 100644 --- a/pallets/configuration/src/lib.rs +++ b/pallets/configuration/src/lib.rs @@ -69,6 +69,7 @@ pub struct HostConfiguration { pub min_orchestrator_collators: u32, pub max_orchestrator_collators: u32, pub collators_per_container: u32, + pub full_rotation_period: u32, } impl Default for HostConfiguration { @@ -79,6 +80,7 @@ impl Default for HostConfiguration { // TODO: for zombienet testing max_orchestrator_collators: 5u32, collators_per_container: 2u32, + full_rotation_period: 24u32, } } } @@ -92,6 +94,8 @@ pub enum InconsistentError { MinOrchestratorCollatorsTooLow, /// `max_collators` must be at least 1 MaxCollatorsTooLow, + /// `full_rotation_period` must be at least 1 + FullRotationPeriodTooLow, } impl HostConfiguration { @@ -110,6 +114,9 @@ impl HostConfiguration { if self.max_orchestrator_collators < self.min_orchestrator_collators { return Err(InconsistentError::MaxCollatorsLowerThanMinCollators); } + if self.full_rotation_period < 1 { + return Err(InconsistentError::FullRotationPeriodTooLow); + } Ok(()) } @@ -258,6 +265,18 @@ pub mod pallet { }) } + #[pallet::call_index(4)] + #[pallet::weight(( + T::WeightInfo::set_config_with_u32(), + DispatchClass::Operational, + ))] + pub fn set_full_rotation_period(origin: OriginFor, new: u32) -> DispatchResult { + ensure_root(origin)?; + Self::schedule_config_update(|config| { + config.full_rotation_period = new; + }) + } + /// Setting this to true will disable consistency checks for the configuration setters. /// Use with caution. #[pallet::call_index(44)] diff --git a/pallets/configuration/src/mock.rs b/pallets/configuration/src/mock.rs index 7dbf8fc24..cf4f39985 100644 --- a/pallets/configuration/src/mock.rs +++ b/pallets/configuration/src/mock.rs @@ -108,6 +108,7 @@ pub fn run_to_block(n: u64) { let session_len = 5; for x in (old_block_number + 1)..=n { + System::reset_events(); System::set_block_number(x); if x % session_len == 1 { diff --git a/pallets/configuration/src/tests.rs b/pallets/configuration/src/tests.rs index 7e0926d02..9ba88a7fb 100644 --- a/pallets/configuration/src/tests.rs +++ b/pallets/configuration/src/tests.rs @@ -27,6 +27,7 @@ fn config_sets_values_from_genesis() { min_orchestrator_collators: 40, max_orchestrator_collators: 40, collators_per_container: 20, + full_rotation_period: 24, }; new_test_ext_with_genesis(custom_config.clone()).execute_with(|| { run_to_block(1); @@ -41,6 +42,7 @@ fn config_sets_default_values() { min_orchestrator_collators: 2, max_orchestrator_collators: 5, collators_per_container: 2, + full_rotation_period: 24, }; new_test_ext().execute_with(|| { run_to_block(1); @@ -55,6 +57,7 @@ fn config_set_value() { min_orchestrator_collators: 2, max_orchestrator_collators: 5, collators_per_container: 2, + full_rotation_period: 24, }) .execute_with(|| { run_to_block(1); @@ -73,6 +76,7 @@ fn config_set_value() { min_orchestrator_collators: 2, max_orchestrator_collators: 5, collators_per_container: 2, + full_rotation_period: 24, } )] ); @@ -100,6 +104,7 @@ fn config_set_many_values_same_block() { min_orchestrator_collators: 2, max_orchestrator_collators: 5, collators_per_container: 2, + full_rotation_period: 24, }) .execute_with(|| { run_to_block(1); @@ -128,6 +133,7 @@ fn config_set_many_values_same_block() { min_orchestrator_collators: 20, max_orchestrator_collators: 20, collators_per_container: 10, + full_rotation_period: 24, } )] ); @@ -153,6 +159,7 @@ fn config_set_many_values_different_blocks() { min_orchestrator_collators: 2, max_orchestrator_collators: 5, collators_per_container: 2, + full_rotation_period: 24, }) .execute_with(|| { run_to_block(1); @@ -183,6 +190,7 @@ fn config_set_many_values_different_blocks() { min_orchestrator_collators: 20, max_orchestrator_collators: 20, collators_per_container: 10, + full_rotation_period: 24, } )] ); @@ -208,6 +216,7 @@ fn config_set_many_values_different_sessions() { min_orchestrator_collators: 2, max_orchestrator_collators: 5, collators_per_container: 2, + full_rotation_period: 24, }) .execute_with(|| { run_to_block(1); @@ -242,6 +251,7 @@ fn config_set_many_values_different_sessions() { min_orchestrator_collators: 20, max_orchestrator_collators: 20, collators_per_container: 2, + full_rotation_period: 24, } ), ( @@ -251,6 +261,7 @@ fn config_set_many_values_different_sessions() { min_orchestrator_collators: 20, max_orchestrator_collators: 20, collators_per_container: 10, + full_rotation_period: 24, } ) ] @@ -277,6 +288,7 @@ fn config_cannot_set_invalid_values() { min_orchestrator_collators: 2, max_orchestrator_collators: 5, collators_per_container: 2, + full_rotation_period: 24, }) .execute_with(|| { run_to_block(1); diff --git a/pallets/invulnerables/src/lib.rs b/pallets/invulnerables/src/lib.rs index e6ee27336..0a87195dc 100644 --- a/pallets/invulnerables/src/lib.rs +++ b/pallets/invulnerables/src/lib.rs @@ -39,8 +39,8 @@ pub mod weights; #[frame_support::pallet] pub mod pallet { - pub use crate::weights::WeightInfo; use { + crate::weights::WeightInfo, frame_support::{ dispatch::DispatchResultWithPostInfo, pallet_prelude::*, diff --git a/primitives/collator-assignment/src/lib.rs b/primitives/collator-assignment/src/lib.rs index d1f341933..f9b7a8ca7 100644 --- a/primitives/collator-assignment/src/lib.rs +++ b/primitives/collator-assignment/src/lib.rs @@ -97,6 +97,13 @@ where } } + /// Fill orchestrator chain with collators until it has `num_orchestrator_chain`. + /// + /// If the `next_collator` iterator does not have enough elements, this function will try to + /// fill the list as much as it can. + /// + /// Call `remove_orchestrator_chain_excess_collators` before calling this function to ensure + /// that the list has no more than `num_orchestrator_chain`. pub fn fill_orchestrator_chain_collators( &mut self, num_orchestrator_chain: usize, @@ -113,43 +120,48 @@ where } } - pub fn fill_container_chain_collators( + /// For each container chain in `container_chains`, add it to the list if it didn't already + /// exist, and fill it with collators. The order determines priority. + pub fn add_and_fill_new_container_chains_in_order( &mut self, num_each_container_chain: usize, + container_chains: &[ParaId], next_collator: &mut I, ) where I: Iterator, { - for (_id, cs) in self.container_chains.iter_mut() { + for para_id in container_chains { + let cs = self.container_chains.entry(*para_id).or_default(); + while cs.len() < num_each_container_chain { if let Some(nc) = next_collator.next() { cs.push(nc); } else { - return; + // No more collators but continue the outer for loop to add all the remaining + // container chains + break; } } } } - pub fn add_new_container_chains(&mut self, container_chains: &[ParaId]) { - for para_id in container_chains { - self.container_chains.entry(*para_id).or_default(); - } - } - /// Check container chains and remove all collators from container chains /// that do not reach the target number of collators. Reassign those to other - /// container chains. + /// container chains, giving priority to the container chains with most collators + /// first, and in case of tie the container chains that appear first in the input + /// `container_chains` parameter. /// /// Returns the collators that could not be assigned to any container chain, /// those can be assigned to the orchestrator chain by the caller. pub fn reorganize_incomplete_container_chains_collators( &mut self, + container_chains: &[ParaId], num_each_container_chain: usize, ) -> Vec { let mut incomplete_container_chains: VecDeque<_> = VecDeque::new(); - for (para_id, collators) in self.container_chains.iter_mut() { + for para_id in container_chains { + let collators = self.container_chains.entry(*para_id).or_default(); if !collators.is_empty() && collators.len() < num_each_container_chain { // Do not remove the para_id from the map, instead replace the list of // collators with an empty vec using mem::take. @@ -160,6 +172,7 @@ where } } + // Stable sort because we want to keep input order in case of tie incomplete_container_chains .make_contiguous() .sort_by_key(|(_para_id, collators)| collators.len()); diff --git a/primitives/traits/src/lib.rs b/primitives/traits/src/lib.rs index 6e753f071..68b17b37a 100644 --- a/primitives/traits/src/lib.rs +++ b/primitives/traits/src/lib.rs @@ -57,3 +57,8 @@ pub trait GetHostConfiguration { pub trait GetSessionIndex { fn session_index() -> SessionIndex; } + +/// Should pallet_collator_assignment trigger a full rotation on this session? +pub trait ShouldRotateAllCollators { + fn should_rotate_all_collators(session_index: SessionIndex) -> bool; +} diff --git a/runtime/dancebox/Cargo.toml b/runtime/dancebox/Cargo.toml index 6dd79f54b..5b4441cea 100644 --- a/runtime/dancebox/Cargo.toml +++ b/runtime/dancebox/Cargo.toml @@ -10,7 +10,7 @@ version = "0.1.0" targets = [ "x86_64-unknown-linux-gnu" ] [dependencies] -hex-literal = { workspace = true, optional = true } +hex-literal = { workspace = true } log = { workspace = true } parity-scale-codec = { workspace = true, features = [ "derive" ] } scale-info = { workspace = true, features = [ "derive" ] } @@ -86,7 +86,6 @@ cumulus-pallet-parachain-system = { workspace = true } cumulus-pallet-session-benchmarking = { workspace = true } cumulus-pallet-xcm = { workspace = true } cumulus-pallet-xcmp-queue = { workspace = true } - cumulus-primitives-core = { workspace = true } cumulus-primitives-timestamp = { workspace = true } cumulus-primitives-utility = { workspace = true } @@ -101,7 +100,8 @@ frame-try-runtime = { workspace = true, optional = true } [dev-dependencies] container-chain-template-frontier-runtime = { workspace = true, features = [ "std" ] } container-chain-template-simple-runtime = { workspace = true, features = [ "std" ] } -hex-literal = { workspace = true } +cumulus-primitives-parachain-inherent = { workspace = true } +cumulus-test-relay-sproof-builder = { workspace = true } pallet-im-online = { workspace = true, features = [ "std" ] } pallet-message-queue = { workspace = true } pallet-staking = { workspace = true, features = [ "std" ] } @@ -193,7 +193,6 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", - "hex-literal", "pallet-author-noting/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-collator-assignment/runtime-benchmarks", diff --git a/runtime/dancebox/src/lib.rs b/runtime/dancebox/src/lib.rs index 8c329610a..54f3f9b88 100644 --- a/runtime/dancebox/src/lib.rs +++ b/runtime/dancebox/src/lib.rs @@ -34,9 +34,9 @@ pub mod migrations; pub mod weights; use { - cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases, + cumulus_pallet_parachain_system::{RelayChainStateProof, RelayNumberStrictlyIncreases}, cumulus_primitives_core::{ - relay_chain::{BlockNumber as RelayBlockNumber, SessionIndex}, + relay_chain::{self, BlockNumber as RelayBlockNumber, SessionIndex}, BodyId, DmpMessageHandler, ParaId, }, frame_support::{ @@ -63,6 +63,7 @@ use { EnsureRoot, }, nimbus_primitives::NimbusId, + pallet_collator_assignment::{GetRandomnessForNextBlock, RotateCollatorsEveryNSessions}, pallet_pooled_staking::traits::{IsCandidateEligible, Timer}, pallet_registrar_runtime_api::ContainerChainGenesisData, pallet_session::{SessionManager, ShouldEndSession}, @@ -74,7 +75,9 @@ use { sp_core::{crypto::KeyTypeId, Decode, Encode, Get, MaxEncodedLen, OpaqueMetadata}, sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT}, + traits::{ + AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Hash as HashT, + }, transaction_validity::{TransactionSource, TransactionValidity}, AccountId32, ApplyExtrinsicResult, }, @@ -435,6 +438,67 @@ impl cumulus_pallet_parachain_system::Config for Runtime { type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } +/// Only callable after `set_validation_data` is called which forms this proof the same way +fn relay_chain_state_proof() -> RelayChainStateProof { + let relay_storage_root = ParachainSystem::validation_data() + .expect("set in `set_validation_data`") + .relay_parent_storage_root; + let relay_chain_state = + ParachainSystem::relay_state_proof().expect("set in `set_validation_data`"); + RelayChainStateProof::new(ParachainInfo::get(), relay_storage_root, relay_chain_state) + .expect("Invalid relay chain state proof, already constructed in `set_validation_data`") +} + +pub struct BabeCurrentBlockRandomnessGetter; +impl BabeCurrentBlockRandomnessGetter { + fn get_block_randomness() -> Option { + if cfg!(feature = "runtime-benchmarks") { + // storage reads as per actual reads + let _relay_storage_root = ParachainSystem::validation_data(); + let _relay_chain_state = ParachainSystem::relay_state_proof(); + let benchmarking_babe_output = Hash::default(); + return Some(benchmarking_babe_output); + } + + relay_chain_state_proof() + .read_optional_entry::>( + relay_chain::well_known_keys::CURRENT_BLOCK_RANDOMNESS, + ) + .ok() + .flatten() + .flatten() + } + + /// Return the block randomness from the relay mixed with the provided subject. + /// This ensures that the randomness will be different on different pallets, as long as the subject is different. + // TODO: audit usage of randomness API + // https://github.com/paritytech/polkadot/issues/2601 + fn get_block_randomness_mixed(subject: &[u8]) -> Option { + Self::get_block_randomness() + .map(|random_hash| mix_randomness::(random_hash, subject)) + } +} + +/// Combines the vrf output of the previous relay block with the provided subject. +/// This ensures that the randomness will be different on different pallets, as long as the subject is different. +fn mix_randomness(vrf_output: Hash, subject: &[u8]) -> T::Hash { + let mut digest = Vec::new(); + digest.extend_from_slice(vrf_output.as_ref()); + digest.extend_from_slice(subject); + + T::Hashing::hash(digest.as_slice()) +} + +// Randomness trait +impl frame_support::traits::Randomness for BabeCurrentBlockRandomnessGetter { + fn random(subject: &[u8]) -> (Hash, BlockNumber) { + let block_number = frame_system::Pallet::::block_number(); + let randomness = Self::get_block_randomness_mixed(subject).unwrap_or_default(); + + (randomness, block_number) + } +} + pub struct OwnApplySession; impl pallet_initializer::ApplyNewSession for OwnApplySession { fn apply_new_session( @@ -544,10 +608,56 @@ impl pallet_session::Config for Runtime { type WeightInfo = pallet_session::weights::SubstrateWeight; } +/// Read full_rotation_period from pallet_configuration +pub struct ConfigurationCollatorRotationSessionPeriod; + +impl Get for ConfigurationCollatorRotationSessionPeriod { + fn get() -> u32 { + Configuration::config().full_rotation_period + } +} + +pub struct BabeGetRandomnessForNextBlock; + +impl GetRandomnessForNextBlock for BabeGetRandomnessForNextBlock { + fn should_end_session(n: u32) -> bool { + ::ShouldEndSession::should_end_session(n) + } + + fn get_randomness() -> [u8; 32] { + let block_number = System::block_number(); + let random_seed = if block_number != 0 { + if let Some(random_hash) = + BabeCurrentBlockRandomnessGetter::get_block_randomness_mixed(b"CollatorAssignment") + { + // Return random_hash as a [u8; 32] instead of a Hash + let mut buf = [0u8; 32]; + let len = sp_std::cmp::min(32, random_hash.as_ref().len()); + buf[..len].copy_from_slice(&random_hash.as_ref()[..len]); + + buf + } else { + // If there is no randomness (e.g when running in dev mode), return [0; 32] + // TODO: smoke test to ensure this never happens in a live network + [0; 32] + } + } else { + // In block 0 (genesis) there is randomness + [0; 32] + }; + + random_seed + } +} + impl pallet_collator_assignment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type HostConfiguration = Configuration; type ContainerChains = Registrar; type SessionIndex = u32; + type ShouldRotateAllCollators = + RotateCollatorsEveryNSessions; + type GetRandomnessForNextBlock = BabeGetRandomnessForNextBlock; type WeightInfo = pallet_collator_assignment::weights::SubstrateWeight; } diff --git a/runtime/dancebox/src/migrations.rs b/runtime/dancebox/src/migrations.rs index bd6bb4a36..e5a649e06 100644 --- a/runtime/dancebox/src/migrations.rs +++ b/runtime/dancebox/src/migrations.rs @@ -19,20 +19,36 @@ //! This module acts as a registry where each migration is defined. Each migration should implement //! the "Migration" trait declared in the pallet-migrations crate. -use frame_support::{ - migration::storage_key_iter, storage::types::StorageValue, weights::Weight, Blake2_128Concat, -}; - use { crate::{Invulnerables, Runtime, RuntimeOrigin, LOG_TARGET}, + frame_support::{ + migration::storage_key_iter, storage::types::StorageValue, weights::Weight, + Blake2_128Concat, + }, pallet_balances::IdAmount, - pallet_invulnerables::WeightInfo, + pallet_configuration::{weights::WeightInfo as _, HostConfiguration}, + pallet_invulnerables::weights::WeightInfo as _, pallet_migrations::{GetMigrations, Migration}, sp_core::Get, sp_runtime::BoundedVec, sp_std::{marker::PhantomData, prelude::*}, }; +#[derive( + Clone, + parity_scale_codec::Encode, + parity_scale_codec::Decode, + PartialEq, + sp_core::RuntimeDebug, + scale_info::TypeInfo, +)] +struct HostConfigurationV0 { + pub max_collators: u32, + pub min_orchestrator_collators: u32, + pub max_orchestrator_collators: u32, + pub collators_per_container: u32, +} + pub struct CollatorSelectionStorageValuePrefix; impl frame_support::traits::StorageInstance for CollatorSelectionStorageValuePrefix { const STORAGE_PREFIX: &'static str = "Invulnerables"; @@ -209,6 +225,91 @@ where } } +pub struct MigrateConfigurationFullRotationPeriod(pub PhantomData); +impl Migration for MigrateConfigurationFullRotationPeriod +where + T: pallet_configuration::Config, +{ + fn friendly_name(&self) -> &str { + "TM_MigrateConfigurationFullRotationPeriod" + } + + fn migrate(&self, _available_weight: Weight) -> Weight { + log::info!(target: LOG_TARGET, "migrate"); + + const CONFIGURATION_ACTIVE_CONFIG_KEY: &[u8] = + &hex_literal::hex!("06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385"); + const CONFIGURATION_PENDING_CONFIGS_KEY: &[u8] = + &hex_literal::hex!("06de3d8a54d27e44a9d5ce189618f22d53b4123b2e186e07fb7bad5dda5f55c0"); + + // Modify active config + let old_config: HostConfigurationV0 = + frame_support::storage::unhashed::get(CONFIGURATION_ACTIVE_CONFIG_KEY) + .expect("configuration.activeConfig should have value"); + let new_config = HostConfiguration { + max_collators: old_config.max_collators, + min_orchestrator_collators: old_config.min_orchestrator_collators, + max_orchestrator_collators: old_config.max_orchestrator_collators, + collators_per_container: old_config.collators_per_container, + full_rotation_period: 24, + }; + frame_support::storage::unhashed::put(CONFIGURATION_ACTIVE_CONFIG_KEY, &new_config); + + // Modify pending configs, if any + let old_pending_configs: Vec<(u32, HostConfigurationV0)> = + frame_support::storage::unhashed::get(CONFIGURATION_PENDING_CONFIGS_KEY) + .unwrap_or_default(); + let mut new_pending_configs: Vec<(u32, HostConfiguration)> = vec![]; + + for (session_index, old_config) in old_pending_configs { + let new_config = HostConfiguration { + max_collators: old_config.max_collators, + min_orchestrator_collators: old_config.min_orchestrator_collators, + max_orchestrator_collators: old_config.max_orchestrator_collators, + collators_per_container: old_config.collators_per_container, + full_rotation_period: 24, + }; + new_pending_configs.push((session_index, new_config)); + } + + if !new_pending_configs.is_empty() { + frame_support::storage::unhashed::put( + CONFIGURATION_PENDING_CONFIGS_KEY, + &new_pending_configs, + ); + } + + ::WeightInfo::set_config_with_u32() + } + + /// Run a standard pre-runtime test. This works the same way as in a normal runtime upgrade. + #[cfg(feature = "try-runtime")] + fn pre_upgrade(&self) -> Result, sp_runtime::DispatchError> { + const CONFIGURATION_ACTIVE_CONFIG_KEY: &[u8] = + &hex_literal::hex!("06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385"); + const CONFIGURATION_PENDING_CONFIGS_KEY: &[u8] = + &hex_literal::hex!("06de3d8a54d27e44a9d5ce189618f22d53b4123b2e186e07fb7bad5dda5f55c0"); + + let old_config_bytes = + frame_support::storage::unhashed::get_raw(CONFIGURATION_ACTIVE_CONFIG_KEY) + .expect("configuration.activeConfig should have value"); + assert_eq!(old_config_bytes.len(), 16); + + Ok((old_config_bytes).encode()) + } + + /// Run a standard post-runtime test. This works the same way as in a normal runtime upgrade. + #[cfg(feature = "try-runtime")] + fn post_upgrade( + &self, + number_of_invulnerables: Vec, + ) -> Result<(), sp_runtime::DispatchError> { + let new_period = Configuration::config().full_rotation_period; + assert_eq!(new_period, 24); + + Ok(()) + } +} pub struct DanceboxMigrations(PhantomData); impl GetMigrations for DanceboxMigrations @@ -216,12 +317,18 @@ where Runtime: pallet_invulnerables::Config, Runtime: pallet_pooled_staking::Config, Runtime: pallet_balances::Config, + Runtime: pallet_configuration::Config, Runtime::RuntimeHoldReason: From, { fn get_migrations() -> Vec> { let migrate_invulnerables = MigrateInvulnerables::(Default::default()); let migrate_holds = MigrateHoldReason::(Default::default()); + let migrate_config = MigrateConfigurationFullRotationPeriod::(Default::default()); - vec![Box::new(migrate_invulnerables), Box::new(migrate_holds)] + vec![ + Box::new(migrate_invulnerables), + Box::new(migrate_holds), + Box::new(migrate_config), + ] } } diff --git a/runtime/dancebox/tests/common/mod.rs b/runtime/dancebox/tests/common/mod.rs index c7cd384d4..79b2428ea 100644 --- a/runtime/dancebox/tests/common/mod.rs +++ b/runtime/dancebox/tests/common/mod.rs @@ -16,7 +16,10 @@ use { cumulus_primitives_core::{ParaId, PersistedValidationData}, - dancebox_runtime::{AuthorInherent, AuthorityAssignment}, + cumulus_primitives_parachain_inherent::ParachainInherentData, + dancebox_runtime::{ + AuthorInherent, AuthorityAssignment, CollatorAssignment, MaxLengthTokenSymbol, + }, frame_support::{ assert_ok, traits::{OnFinalize, OnInitialize}, @@ -35,7 +38,6 @@ use { mod xcm; -use dancebox_runtime::MaxLengthTokenSymbol; pub use dancebox_runtime::{ AccountId, Balance, Balances, Initializer, ParachainInfo, Registrar, Runtime, RuntimeCall, RuntimeEvent, Session, System, @@ -78,20 +80,48 @@ pub fn run_to_block(n: u32) { ); // Initialize the new block - Session::on_initialize(System::block_number()); + CollatorAssignment::on_initialize(System::block_number()); Initializer::on_initialize(System::block_number()); + Session::on_initialize(System::block_number()); AuthorInherent::on_initialize(System::block_number()); pallet_author_inherent::Pallet::::kick_off_authorship_validation(None.into()) .expect("author inherent to dispatch correctly"); // Finalize the block - Session::on_finalize(System::block_number()); + CollatorAssignment::on_finalize(System::block_number()); Initializer::on_finalize(System::block_number()); + Session::on_finalize(System::block_number()); AuthorInherent::on_finalize(System::block_number()); } } +/// Mock the inherent that sets validation data in ParachainSystem, which +/// contains the `relay_chain_block_number`, which is used in `collator-assignment` as a +/// source of randomness. +pub fn set_parachain_inherent_data() { + use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; + let (relay_parent_storage_root, relay_chain_state) = + RelayStateSproofBuilder::default().into_state_root_and_proof(); + let vfp = PersistedValidationData { + relay_parent_number: 1u32, + relay_parent_storage_root, + ..Default::default() + }; + let parachain_inherent_data = ParachainInherentData { + validation_data: vfp, + relay_chain_state: relay_chain_state, + downward_messages: Default::default(), + horizontal_messages: Default::default(), + }; + assert_ok!(RuntimeCall::ParachainSystem( + cumulus_pallet_parachain_system::Call::::set_validation_data { + data: parachain_inherent_data + } + ) + .dispatch(inherent_origin())); +} + #[derive(Default)] pub struct ExtBuilder { // endowed accounts with balances @@ -238,6 +268,7 @@ impl ExtBuilder { ext.execute_with(|| { System::set_block_number(1); + set_parachain_inherent_data(); }); ext } diff --git a/runtime/dancebox/tests/integration_test.rs b/runtime/dancebox/tests/integration_test.rs index eba0a6ce8..e051d6968 100644 --- a/runtime/dancebox/tests/integration_test.rs +++ b/runtime/dancebox/tests/integration_test.rs @@ -20,7 +20,10 @@ use { common::*, cumulus_primitives_core::ParaId, dancebox_runtime::{ - migrations::{CollatorSelectionInvulnerablesValue, MigrateInvulnerables}, + migrations::{ + CollatorSelectionInvulnerablesValue, MigrateConfigurationFullRotationPeriod, + MigrateInvulnerables, + }, AuthorNoting, AuthorityAssignment, AuthorityMapping, CollatorAssignment, Configuration, Invulnerables, MinimumSelfDelegation, PooledStaking, Proxy, ProxyType, }, @@ -41,7 +44,7 @@ use { sp_consensus_aura::AURA_ENGINE_ID, sp_core::Get, sp_runtime::{ - traits::{BadOrigin, BlakeTwo256, OpaqueKeys}, + traits::{BadOrigin, BlakeTwo256, Dispatchable, OpaqueKeys}, DigestItem, }, sp_std::vec, @@ -96,6 +99,16 @@ fn genesis_para_registrar() { }); } +fn default_config() -> pallet_configuration::HostConfiguration { + pallet_configuration::HostConfiguration { + max_collators: 100, + min_orchestrator_collators: 2, + max_orchestrator_collators: 2, + collators_per_container: 2, + full_rotation_period: 24, + } +} + #[test] fn genesis_para_registrar_deregister() { ExtBuilder::default() @@ -112,12 +125,7 @@ fn genesis_para_registrar_deregister() { (AccountId::from(ALICE), 210 * UNIT), (AccountId::from(BOB), 100 * UNIT), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { assert_eq!( @@ -166,12 +174,7 @@ fn genesis_para_registrar_runtime_api() { (AccountId::from(ALICE), 210 * UNIT), (AccountId::from(BOB), 100 * UNIT), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { assert_eq!( @@ -222,12 +225,7 @@ fn genesis_para_registrar_container_chain_genesis_data_runtime_api() { (AccountId::from(ALICE), 210 * UNIT), (AccountId::from(BOB), 100 * UNIT), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { assert_eq!( @@ -299,12 +297,7 @@ fn test_author_collation_aura() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(5); @@ -339,12 +332,7 @@ fn test_author_collation_aura_change_of_authorities_on_session() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -416,12 +404,7 @@ fn test_author_collation_aura_add_assigned_to_paras() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -490,12 +473,7 @@ fn test_authors_without_paras() { (AccountId::from(CHARLIE), 100 * UNIT), (AccountId::from(DAVE), 100 * UNIT), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -543,12 +521,7 @@ fn test_authors_paras_inserted_a_posteriori() { (AccountId::from(CHARLIE), 100 * UNIT), (AccountId::from(DAVE), 100 * UNIT), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -615,6 +588,7 @@ fn test_authors_paras_inserted_a_posteriori_with_collators_already_assigned() { min_orchestrator_collators: 2, max_orchestrator_collators: 5, collators_per_container: 2, + full_rotation_period: 24, }) .build() .execute_with(|| { @@ -679,12 +653,7 @@ fn test_parachains_deregister_collators_re_assigned() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -747,12 +716,7 @@ fn test_parachains_deregister_collators_config_change_reassigned() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -819,12 +783,7 @@ fn test_orchestrator_collators_with_non_sufficient_collators() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -851,12 +810,7 @@ fn test_configuration_on_session_change() { (AccountId::from(ALICE), 210 * UNIT), (AccountId::from(BOB), 100 * UNIT), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(1); @@ -916,12 +870,7 @@ fn test_author_collation_aura_add_assigned_to_paras_runtime_api() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -1085,12 +1034,7 @@ fn test_consensus_runtime_api() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -1185,12 +1129,7 @@ fn test_consensus_runtime_api_session_changes() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -1306,12 +1245,7 @@ fn test_consensus_runtime_api_next_session() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -1711,6 +1645,104 @@ fn test_author_noting_runtime_api() { }); } +#[test] +fn test_collator_assignment_rotation() { + ExtBuilder::default() + .with_balances(vec![ + // Alice gets 10k extra tokens for her mapping deposit + (AccountId::from(ALICE), 210_000 * UNIT), + (AccountId::from(BOB), 100_000 * UNIT), + (AccountId::from(CHARLIE), 100_000 * UNIT), + (AccountId::from(DAVE), 100_000 * UNIT), + ]) + .with_collators(vec![ + (AccountId::from(ALICE), 210 * UNIT), + (AccountId::from(BOB), 100 * UNIT), + (AccountId::from(CHARLIE), 100 * UNIT), + (AccountId::from(DAVE), 100 * UNIT), + ]) + .with_para_ids(vec![ + (1001, empty_genesis_data(), vec![]), + (1002, empty_genesis_data(), vec![]), + ]) + .build() + .execute_with(|| { + // Charlie and Dave to 1001 + let assignment = CollatorAssignment::collator_container_chain(); + let initial_assignment = assignment.clone(); + assert_eq!( + assignment.container_chains[&1001u32.into()], + vec![CHARLIE.into(), DAVE.into()] + ); + + pub fn set_parachain_inherent_data_random_seed(random_seed: [u8; 32]) { + use cumulus_primitives_core::relay_chain::well_known_keys; + use cumulus_primitives_core::PersistedValidationData; + use cumulus_primitives_parachain_inherent::ParachainInherentData; + use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; + + let (relay_parent_storage_root, relay_chain_state) = { + let mut sproof = RelayStateSproofBuilder::default(); + sproof.additional_key_values.push(( + well_known_keys::CURRENT_BLOCK_RANDOMNESS.to_vec(), + Some(random_seed).encode(), + )); + + sproof.into_state_root_and_proof() + }; + let vfp = PersistedValidationData { + // TODO: this is previous relay_parent_number + 1, but not sure where can I get that value + relay_parent_number: 2u32, + relay_parent_storage_root, + ..Default::default() + }; + let parachain_inherent_data = ParachainInherentData { + validation_data: vfp, + relay_chain_state: relay_chain_state, + downward_messages: Default::default(), + horizontal_messages: Default::default(), + }; + // Delete existing flag to avoid error + // 'ValidationData must be updated only once in a block' + // TODO: this is a hack + frame_support::storage::unhashed::kill(&frame_support::storage::storage_prefix( + b"ParachainSystem", + b"ValidationData", + )); + assert_ok!( + RuntimeCall::ParachainSystem( + cumulus_pallet_parachain_system::Call::::set_validation_data { + data: parachain_inherent_data + } + ) + .dispatch(inherent_origin()) + ); + } + + let rotation_period = Configuration::config().full_rotation_period; + + run_to_session(rotation_period - 2); + + set_parachain_inherent_data_random_seed([1; 32]); + + assert!(CollatorAssignment::pending_collator_container_chain().is_none()); + + run_to_session(rotation_period - 1); + assert_eq!( + CollatorAssignment::collator_container_chain(), + initial_assignment, + ); + assert!(CollatorAssignment::pending_collator_container_chain().is_some()); + + run_to_session(rotation_period); + // Assignment changed + assert_ne!( + CollatorAssignment::collator_container_chain(), + initial_assignment, + ); + }); +} + #[test] fn session_keys_key_type_id() { assert_eq!( @@ -1737,12 +1769,7 @@ fn test_session_keys_with_authority_mapping() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -1827,12 +1854,7 @@ fn test_session_keys_with_authority_assignment() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -1966,12 +1988,7 @@ fn test_proxy_any() { (AccountId::from(ALICE), 210 * UNIT), (AccountId::from(BOB), 100 * UNIT), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2012,12 +2029,7 @@ fn test_proxy_non_transfer() { (AccountId::from(ALICE), 210 * UNIT), (AccountId::from(BOB), 100 * UNIT), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2088,12 +2100,7 @@ fn test_invulnerables_migration() { (AccountId::from(ALICE), 210 * UNIT), (AccountId::from(BOB), 100 * UNIT), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { // Populate the invulnerables storage @@ -2138,12 +2145,7 @@ fn test_staking_no_candidates_in_genesis() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2175,12 +2177,7 @@ fn test_staking_join() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2233,12 +2230,7 @@ fn test_staking_join_no_keys_registered() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2294,12 +2286,7 @@ fn test_staking_register_keys_after_joining() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2388,12 +2375,7 @@ fn test_staking_join_bad_origin() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2431,12 +2413,7 @@ fn test_staking_join_below_self_delegation_min() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2509,12 +2486,7 @@ fn test_staking_join_no_self_delegation() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2554,12 +2526,7 @@ fn test_staking_join_before_self_delegation() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2630,12 +2597,7 @@ fn test_staking_join_twice_in_same_block() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2705,12 +2667,7 @@ fn test_staking_join_execute_before_time() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2786,12 +2743,7 @@ fn test_staking_join_execute_any_origin() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2851,12 +2803,7 @@ fn test_staking_join_execute_bad_origin() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -2925,12 +2872,7 @@ fn setup_staking_join_and_execute(ops: Vec, f: impl FnOnce() -> R) { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -3375,12 +3317,7 @@ fn test_pallet_session_takes_validators_from_invulnerables_and_staking() { (1001, empty_genesis_data(), vec![]), (1002, empty_genesis_data(), vec![]), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { run_to_block(2); @@ -3476,6 +3413,7 @@ fn test_pallet_session_limits_num_validators() { min_orchestrator_collators: 2, max_orchestrator_collators: 2, collators_per_container: 2, + full_rotation_period: 24, }) .build() .execute_with(|| { @@ -3563,6 +3501,7 @@ fn test_pallet_session_limits_num_validators_from_staking() { min_orchestrator_collators: 2, max_orchestrator_collators: 2, collators_per_container: 2, + full_rotation_period: 24, }) .build() .execute_with(|| { @@ -3668,12 +3607,7 @@ fn test_migration_holds() { (AccountId::from(ALICE), 210 * UNIT), (AccountId::from(BOB), 100 * UNIT), ]) - .with_config(pallet_configuration::HostConfiguration { - max_collators: 100, - min_orchestrator_collators: 2, - max_orchestrator_collators: 2, - collators_per_container: 2, - }) + .with_config(default_config()) .build() .execute_with(|| { let pallet_prefix: &[u8] = b"Balances"; @@ -3707,3 +3641,47 @@ fn test_migration_holds() { assert_eq!(new_holds[0].amount, 100u128); }); } + +#[test] +fn test_migration_config_full_rotation_period() { + ExtBuilder::default() + .with_balances(vec![ + // Alice gets 10k extra tokens for her mapping deposit + (AccountId::from(ALICE), 210_000 * UNIT), + (AccountId::from(BOB), 100_000 * UNIT), + ]) + .with_collators(vec![ + (AccountId::from(ALICE), 210 * UNIT), + (AccountId::from(BOB), 100 * UNIT), + ]) + .with_config(default_config()) + .build() + .execute_with(|| { + const CONFIGURATION_ACTIVE_CONFIG_KEY: &[u8] = + &hex_literal::hex!("06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385"); + const CONFIGURATION_PENDING_CONFIGS_KEY: &[u8] = + &hex_literal::hex!("06de3d8a54d27e44a9d5ce189618f22d53b4123b2e186e07fb7bad5dda5f55c0"); + + // Modify active config + frame_support::storage::unhashed::put_raw(CONFIGURATION_ACTIVE_CONFIG_KEY, &hex_literal::hex!("63000000020000000500000002000000")); + // Modify pending configs + frame_support::storage::unhashed::put_raw(CONFIGURATION_PENDING_CONFIGS_KEY, &hex_literal::hex!("08b108000063000000020000000500000002000000b208000064000000020000000500000002000000")); + + let migration = MigrateConfigurationFullRotationPeriod::(Default::default()); + migration.migrate(Default::default()); + + let expected_active = pallet_configuration::HostConfiguration { + max_collators: 99, + min_orchestrator_collators: 2, + max_orchestrator_collators: 5, + collators_per_container: 2, + full_rotation_period: 24, + }; + assert_eq!(Configuration::config(), expected_active); + + let expected_pending = vec![ + (2225, pallet_configuration::HostConfiguration { max_collators: 99, min_orchestrator_collators: 2, max_orchestrator_collators: 5, collators_per_container: 2, full_rotation_period: 24 }), (2226, pallet_configuration::HostConfiguration { max_collators: 100, min_orchestrator_collators: 2, max_orchestrator_collators: 5, collators_per_container: 2, full_rotation_period: 24 }) + ]; + assert_eq!(Configuration::pending_configs(), expected_pending); + }); +} diff --git a/test/configs/zombieTanssiRotation.json b/test/configs/zombieTanssiRotation.json new file mode 100644 index 000000000..a3e9603d7 --- /dev/null +++ b/test/configs/zombieTanssiRotation.json @@ -0,0 +1,105 @@ +{ + "settings": { + "timeout": 1000, + "provider": "native" + }, + "relaychain": { + "chain": "rococo-local", + "default_command": "tmp/polkadot", + "default_args": ["--no-hardware-benchmarks", "-lparachain=debug", "--database=paritydb"], + "nodes": [ + { + "name": "alice", + "ws_port": "9947", + "validator": true + }, + { + "name": "bob", + "validator": true + }, + { + "name": "charlie", + "validator": true + }, + { + "name": "dave", + "validator": true + } + ] + }, + "parachains": [ + { + "id": 1000, + "chain_spec_path": "specs/tanssi-1000.json", + "COMMENT": "Important: these collators will not be injected to pallet-invulnerables because zombienet does not support that. When changing the collators list, make sure to update `scripts/build-spec.sh`", + "collators": [ + { + "name": "Collator1000-01", + "ws_port": "9948", + "command": "../target/release/tanssi-node" + }, + { + "name": "Collator1000-02", + "command": "../target/release/tanssi-node" + }, + { + "name": "Collator2000-01", + "command": "../target/release/tanssi-node" + }, + { + "name": "Collator2000-02", + "command": "../target/release/tanssi-node" + }, + { + "name": "Collator2001-01", + "command": "../target/release/tanssi-node" + }, + { + "name": "Collator2001-02", + "command": "../target/release/tanssi-node" + }, + { + "name": "Collator2002-01", + "command": "../target/release/tanssi-node" + }, + { + "name": "Collator2002-02", + "command": "../target/release/tanssi-node" + } + ] + }, + { + "id": 2000, + "chain_spec_path": "specs/template-container-2000.json", + "collators": [ + { + "name": "FullNode-2000", + "validator": false, + "command": "../target/release/container-chain-template-simple-node", + "ws_port": 9949, + "p2p_port": 33049 + } + ] + }, + { + "id": 2001, + "chain_spec_path": "specs/template-container-2001.json", + "collators": [ + { + "name": "FullNode-2001", + "validator": false, + "command": "../target/release/container-chain-template-frontier-node", + "ws_port": 9950, + "p2p_port": 33050 + } + ] + } + ], + "types": { + "Header": { + "number": "u64", + "parent_hash": "Hash", + "post_state": "Hash" + } + } +} diff --git a/test/moonwall.config.json b/test/moonwall.config.json index f2f2c2979..932fb9823 100644 --- a/test/moonwall.config.json +++ b/test/moonwall.config.json @@ -143,6 +143,55 @@ } ] }, + { + "name": "zombie_tanssi_rotation", + "testFileDir": ["suites/rotation-para"], + "runScripts": ["build-spec.sh", "download-polkadot.sh"], + "foundation": { + "type": "zombie", + "zombieSpec": { + "configPath": "./configs/zombieTanssi.json", + "skipBlockCheck": ["Container2002"] + } + }, + "connections": [ + { + "name": "Relay", + "type": "polkadotJs", + "endpoints": ["ws://127.0.0.1:9947"] + }, + { + "name": "Tanssi", + "type": "polkadotJs", + "endpoints": ["ws://127.0.0.1:9948"] + }, + { + "name": "Container2000", + "type": "polkadotJs", + "endpoints": ["ws://127.0.0.1:9949"] + }, + { + "name": "Container2001", + "type": "polkadotJs", + "endpoints": ["ws://127.0.0.1:9950"] + }, + { + "name": "Container2002", + "type": "polkadotJs", + "endpoints": ["ws://127.0.0.1:9951"] + }, + { + "name": "ethers", + "type": "ethers", + "endpoints": ["ws://127.0.0.1:9950"] + }, + { + "name": "w3", + "type": "web3", + "endpoints": ["ws://127.0.0.1:9950"] + } + ] + }, { "name": "zombie_tanssi_warp_sync", "testFileDir": ["suites/warp-sync"], diff --git a/test/suites/para/test_tanssi_containers.ts b/test/suites/para/test_tanssi_containers.ts index e3249c40b..add517cdf 100644 --- a/test/suites/para/test_tanssi_containers.ts +++ b/test/suites/para/test_tanssi_containers.ts @@ -220,7 +220,7 @@ describeSuite({ it({ id: "T12", title: "Test live registration of container chain 2002", - timeout: 300000, + timeout: 240000, test: async function () { const keyring = new Keyring({ type: "sr25519" }); const alice = keyring.addFromUri("//Alice", { name: "Alice default" }); @@ -257,22 +257,8 @@ describeSuite({ // TODO: fix once we have types expect(registered3.toJSON().includes(2002)).to.be.false; - // The node should be syncing the container 2002, but not collating yet - // so it should still try to produce blocks in orchestrator chain. - // Use database path to check that the container chain started - // TODO: use collator rpc instead to check if the container chain is running, - // that's not possible now because we would need to guess the port number - - const container2002DbPath = - getTmpZombiePath() + - "/Collator2002-01/data/containers/chains/simple_container_2002/db/full-container-2002"; - expect(await directoryExists(container2002DbPath)).to.be.false; // The node starts one session before the container chain is in registered list await waitSessions(context, paraApi, 1); - // The node detects assignment when the block is finalized, but "waitSessions" ignores finality. - // So wait a few blocks more hoping that the current block will be finalized by then. - await context.waitBlock(3, "Tanssi"); - expect(await directoryExists(container2002DbPath)).to.be.true; // Not registered yet, still pending const registered4 = await paraApi.query.registrar.registeredParaIds(); // TODO: fix once we have types @@ -423,25 +409,3 @@ async function countUniqueBlockAuthors(paraApi, blockStart, blockEnd, numAuthors expect(false).to.be.true; } } - -async function directoryExists(directoryPath) { - try { - await fs.access(directoryPath, fs.constants.F_OK); - return true; - } catch (err) { - return false; - } -} - -/// Returns the /tmp/zombie-52234... path -function getTmpZombiePath() { - const logFilePath = process.env.MOON_MONITORED_NODE; - - if (logFilePath) { - const lastIndex = logFilePath.lastIndexOf("/"); - return lastIndex !== -1 ? logFilePath.substring(0, lastIndex) : null; - } - - // Return null if the environment variable is not set - return null; -} diff --git a/test/suites/rotation-para/test_rotation.ts b/test/suites/rotation-para/test_rotation.ts new file mode 100644 index 000000000..d28356d07 --- /dev/null +++ b/test/suites/rotation-para/test_rotation.ts @@ -0,0 +1,455 @@ +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { MIN_GAS_PRICE, customWeb3Request, generateKeyringPair } from "@moonwall/util"; +import { ApiPromise, Keyring } from "@polkadot/api"; +import { Signer } from "ethers"; +import fs from "fs/promises"; +import { getAuthorFromDigest } from "../../util/author"; +import { signAndSendAndInclude, waitToSession } from "../../util/block"; +import { createTransfer, waitUntilEthTxIncluded } from "../../util/ethereum"; +import { getKeyringNimbusIdHex } from "../../util/keys"; +import { getHeaderFromRelay } from "../../util/relayInterface"; + +describeSuite({ + id: "R01", + title: "Zombie Tanssi Rotation Test", + foundationMethods: "zombie", + testCases: function ({ it, context }) { + let paraApi: ApiPromise; + let relayApi: ApiPromise; + let container2000Api: ApiPromise; + let container2001Api: ApiPromise; + let ethersSigner: Signer; + let assignment3; + let assignment5; + let allCollators: string[]; + let collatorName: Record; + let containerDbPaths: string[]; + + beforeAll(async () => { + paraApi = context.polkadotJs("Tanssi"); + relayApi = context.polkadotJs("Relay"); + container2000Api = context.polkadotJs("Container2000"); + container2001Api = context.polkadotJs("Container2001"); + ethersSigner = context.ethers(); + + const relayNetwork = relayApi.consts.system.version.specName.toString(); + expect(relayNetwork, "Relay API incorrect").to.contain("rococo"); + + const paraNetwork = paraApi.consts.system.version.specName.toString(); + const paraId1000 = (await paraApi.query.parachainInfo.parachainId()).toString(); + expect(paraNetwork, "Para API incorrect").to.contain("dancebox"); + expect(paraId1000, "Para API incorrect").to.be.equal("1000"); + + const container2000Network = container2000Api.consts.system.version.specName.toString(); + const paraId2000 = (await container2000Api.query.parachainInfo.parachainId()).toString(); + expect(container2000Network, "Container2000 API incorrect").to.contain("container-chain-template"); + expect(paraId2000, "Container2000 API incorrect").to.be.equal("2000"); + + const container2001Network = container2001Api.consts.system.version.specName.toString(); + const paraId2001 = (await container2001Api.query.parachainInfo.parachainId()).toString(); + expect(container2001Network, "Container2001 API incorrect").to.contain("frontier-template"); + expect(paraId2001, "Container2001 API incorrect").to.be.equal("2001"); + + // Test block numbers in relay are 0 yet + const header2000 = await getHeaderFromRelay(relayApi, 2000); + const header2001 = await getHeaderFromRelay(relayApi, 2001); + + expect(header2000.number.toNumber()).to.be.equal(0); + expect(header2001.number.toNumber()).to.be.equal(0); + + // Initialize list of all collators, this should match the names from build-spec.sh script + allCollators = [ + "Collator1000-01", + "Collator1000-02", + "Collator2000-01", + "Collator2000-02", + "Collator2001-01", + "Collator2001-02", + "Collator2002-01", + "Collator2002-02", + ]; + // Initialize reverse map of collator key to collator name + collatorName = createCollatorKeyToNameMap(paraApi, allCollators); + console.log(collatorName); + + containerDbPaths = [ + "/data/containers/chains/simple_container_2000/db/full-container-2000", + "/data/containers/chains/frontier_container_2001/db/full-container-2001", + ]; + }, 120000); + + it({ + id: "T01", + title: "Blocks are being produced on parachain", + test: async function () { + const blockNum = (await paraApi.rpc.chain.getBlock()).block.header.number.toNumber(); + expect(blockNum).to.be.greaterThan(0); + }, + }); + + it({ + id: "T02", + title: "Set 1 collator per parachain, and full_rotation every 5 sessions", + timeout: 60000, + test: async function () { + const keyring = new Keyring({ type: "sr25519" }); + const alice = keyring.addFromUri("//Alice", { name: "Alice default" }); + + const tx1 = await paraApi.tx.configuration.setCollatorsPerContainer(1); + const tx2 = await paraApi.tx.configuration.setMinOrchestratorCollators(1); + const tx3 = await paraApi.tx.configuration.setMaxOrchestratorCollators(1); + const tx4 = await paraApi.tx.configuration.setFullRotationPeriod(5); + const tx1234 = paraApi.tx.utility.batchAll([tx1, tx2, tx3, tx4]); + await signAndSendAndInclude(paraApi.tx.sudo.sudo(tx1234), alice); + }, + }); + + it({ + id: "T03", + title: "Test assignation did not change", + test: async function () { + const currentSession = (await paraApi.query.session.currentIndex()).toNumber(); + // TODO: fix once we have types + const allCollators = ( + await paraApi.query.authorityAssignment.collatorContainerChain(currentSession) + ).toJSON(); + const expectedAllCollators = { + orchestratorChain: [ + getKeyringNimbusIdHex("Collator1000-01"), + getKeyringNimbusIdHex("Collator1000-02"), + getKeyringNimbusIdHex("Collator2002-01"), + getKeyringNimbusIdHex("Collator2002-02"), + ], + containerChains: { + "2000": [getKeyringNimbusIdHex("Collator2000-01"), getKeyringNimbusIdHex("Collator2000-02")], + "2001": [getKeyringNimbusIdHex("Collator2001-01"), getKeyringNimbusIdHex("Collator2001-02")], + }, + }; + + expect(allCollators).to.deep.equal(expectedAllCollators); + }, + }); + + it({ + id: "T04", + title: "Blocks are being produced on container 2000", + test: async function () { + const blockNum = (await container2000Api.rpc.chain.getBlock()).block.header.number.toNumber(); + expect(blockNum).to.be.greaterThan(0); + }, + }); + + it({ + id: "T05", + title: "Blocks are being produced on container 2001", + test: async function () { + const blockNum = (await container2001Api.rpc.chain.getBlock()).block.header.number.toNumber(); + + expect(blockNum).to.be.greaterThan(0); + expect(await ethersSigner.provider.getBlockNumber(), "Safe tag is not present").to.be.greaterThan(0); + }, + }); + + it({ + id: "T06", + title: "Test container chain 2000 assignation is correct", + test: async function () { + const currentSession = (await paraApi.query.session.currentIndex()).toNumber(); + const paraId = (await container2000Api.query.parachainInfo.parachainId()).toString(); + const containerChainCollators = ( + await paraApi.query.authorityAssignment.collatorContainerChain(currentSession) + ).toJSON().containerChains[paraId]; + + // TODO: fix once we have types + const writtenCollators = (await container2000Api.query.authoritiesNoting.authorities()).toJSON(); + + expect(containerChainCollators).to.deep.equal(writtenCollators); + }, + }); + + it({ + id: "T07", + title: "Test container chain 2001 assignation is correct", + test: async function () { + const currentSession = (await paraApi.query.session.currentIndex()).toNumber(); + const paraId = (await container2001Api.query.parachainInfo.parachainId()).toString(); + const containerChainCollators = ( + await paraApi.query.authorityAssignment.collatorContainerChain(currentSession) + ).toJSON().containerChains[paraId]; + + const writtenCollators = (await container2001Api.query.authoritiesNoting.authorities()).toJSON(); + + expect(containerChainCollators).to.deep.equal(writtenCollators); + }, + }); + + it({ + id: "T08", + title: "Test author noting is correct for both containers", + timeout: 60000, + test: async function () { + const assignment = await paraApi.query.collatorAssignment.collatorContainerChain(); + const paraId2000 = await container2000Api.query.parachainInfo.parachainId(); + const paraId2001 = await container2001Api.query.parachainInfo.parachainId(); + + // TODO: fix once we have types + const containerChainCollators2000 = assignment.containerChains.toJSON()[paraId2000.toString()]; + const containerChainCollators2001 = assignment.containerChains.toJSON()[paraId2001.toString()]; + + await context.waitBlock(3, "Tanssi"); + const author2000 = await paraApi.query.authorNoting.latestAuthor(paraId2000); + const author2001 = await paraApi.query.authorNoting.latestAuthor(paraId2001); + + expect(containerChainCollators2000.includes(author2000.toJSON().author)).to.be.true; + expect(containerChainCollators2001.includes(author2001.toJSON().author)).to.be.true; + }, + }); + + it({ + id: "T09", + title: "Test author is correct in Orchestrator", + test: async function () { + const sessionIndex = (await paraApi.query.session.currentIndex()).toNumber(); + const authorities = await paraApi.query.authorityAssignment.collatorContainerChain(sessionIndex); + const author = await getAuthorFromDigest(paraApi); + // TODO: fix once we have types + expect(authorities.toJSON().orchestratorChain.includes(author.toString())).to.be.true; + }, + }); + + it({ + id: "T10", + title: "Test frontier template isEthereum", + test: async function () { + // TODO: fix once we have types + const genesisData2000 = await paraApi.query.registrar.paraGenesisData(2000); + expect(genesisData2000.toJSON().properties.isEthereum).to.be.false; + const genesisData2001 = await paraApi.query.registrar.paraGenesisData(2001); + expect(genesisData2001.toJSON().properties.isEthereum).to.be.true; + }, + }); + it({ + id: "T11", + title: "Transactions can be made with ethers", + timeout: 60000, + test: async function () { + const randomAccount = generateKeyringPair(); + const tx = await createTransfer(context, randomAccount.address, 1_000_000_000_000, { + gasPrice: MIN_GAS_PRICE, + }); + const txHash = await customWeb3Request(context.web3(), "eth_sendRawTransaction", [tx]); + await waitUntilEthTxIncluded( + () => context.waitBlock(1, "Container2001"), + context.web3(), + txHash.result + ); + expect(Number(await context.web3().eth.getBalance(randomAccount.address))).to.be.greaterThan(0); + }, + }); + it({ + id: "T12", + title: "On session 3 we have 1 collator per chain", + timeout: 90000, + test: async function () { + await waitToSession(context, paraApi, 3); + + // The node detects assignment when the block is finalized, but "waitSessions" ignores finality. + // So wait a few blocks more hoping that the current block will be finalized by then. + await context.waitBlock(3, "Tanssi"); + const assignment = await paraApi.query.collatorAssignment.collatorContainerChain(); + assignment3 = assignment.toJSON(); + console.log("assignment session 3:"); + logAssignment(collatorName, assignment3); + + expect(assignment.orchestratorChain.length).toBe(1); + expect(assignment.containerChains.toJSON()[2000].length).toBe(1); + expect(assignment.containerChains.toJSON()[2001].length).toBe(1); + }, + }); + it({ + id: "T13", + title: "On session 4 collators start syncing the new chains", + timeout: 90000, + test: async function () { + await waitToSession(context, paraApi, 4); + + // The node detects assignment when the block is finalized, but "waitSessions" ignores finality. + // So wait a few blocks more hoping that the current block will be finalized by then. + await context.waitBlock(3, "Tanssi"); + const futureAssignment = await paraApi.query.collatorAssignment.pendingCollatorContainerChain(); + // The assignment is random, so there is a small chance that it will be the same, + // and in that case this test shouldn't fail + if (futureAssignment.isNone) { + assignment5 = assignment3; + } else { + assignment5 = futureAssignment.toJSON(); + } + console.log("assignment session 5:"); + logAssignment(collatorName, assignment5); + + // First, check that nodes are still running in their previously assigned chain + const oldC2000 = collatorName[assignment3.containerChains[2000][0]]; + const oldC2001 = collatorName[assignment3.containerChains[2001][0]]; + const oldContainer2000DbPath = + getTmpZombiePath() + + `/${oldC2000}/data/containers/chains/simple_container_2000/db/full-container-2000`; + const oldContainer2001DbPath = + getTmpZombiePath() + + `/${oldC2001}/data/containers/chains/frontier_container_2001/db/full-container-2001`; + expect(await directoryExists(oldContainer2000DbPath)).to.be.true; + expect(await directoryExists(oldContainer2001DbPath)).to.be.true; + + // Check that new assigned collators have started syncing + const c2000 = collatorName[assignment5.containerChains[2000][0]]; + const c2001 = collatorName[assignment5.containerChains[2001][0]]; + let unassignedCollators = getUnassignedCollators(allCollators, [c2000, c2001]); + // Remove old collators because they will still have some chains running + unassignedCollators = unassignedCollators.filter((x) => x !== oldC2000); + unassignedCollators = unassignedCollators.filter((x) => x !== oldC2001); + + // Verify that collators have container chain running by looking at db path, + // and unassignedCollators should not have any db path + const container2000DbPath = + getTmpZombiePath() + + `/${c2000}/data/containers/chains/simple_container_2000/db/full-container-2000`; + const container2001DbPath = + getTmpZombiePath() + + `/${c2001}/data/containers/chains/frontier_container_2001/db/full-container-2001`; + expect(await directoryExists(container2000DbPath)).to.be.true; + expect(await directoryExists(container2001DbPath)).to.be.true; + + await ensureContainerDbPathsDontExist(unassignedCollators, containerDbPaths); + }, + }); + it({ + id: "T14", + title: "On session 5 collators stop the previously assigned chains", + timeout: 90000, + test: async function () { + await waitToSession(context, paraApi, 5); + const assignment = await paraApi.query.collatorAssignment.collatorContainerChain(); + expect(assignment.toJSON()).to.deep.equal(assignment5); + + // The node detects assignment when the block is finalized, but "waitSessions" ignores finality. + // So wait a few blocks more hoping that the current block will be finalized by then. + // This also serves to check that Tanssi is producing blocks after the rotation + await context.waitBlock(3, "Tanssi"); + + // First, check that nodes have stopped in their previously assigned chain + const oldC2000 = collatorName[assignment3.containerChains[2000][0]]; + const oldC2001 = collatorName[assignment3.containerChains[2001][0]]; + const c2000 = collatorName[assignment5.containerChains[2000][0]]; + const c2001 = collatorName[assignment5.containerChains[2001][0]]; + const oldContainer2000DbPath = + getTmpZombiePath() + + `/${oldC2000}/data/containers/chains/simple_container_2000/db/full-container-2000`; + const oldContainer2001DbPath = + getTmpZombiePath() + + `/${oldC2001}/data/containers/chains/frontier_container_2001/db/full-container-2001`; + // Edge case: collators may be assigned to the same chain, in that case the directory will still exist + if (oldC2000 != c2000) { + expect(await directoryExists(oldContainer2000DbPath)).to.be.false; + } + if (oldC2001 != c2001) { + expect(await directoryExists(oldContainer2001DbPath)).to.be.false; + } + + // Check that new assigned collators are running + const unassignedCollators = getUnassignedCollators(allCollators, [c2000, c2001]); + + // Verify that collators have container chain running by looking at db path, + // and unassignedCollators should not have any db path + const container2000DbPath = + getTmpZombiePath() + + `/${c2000}/data/containers/chains/simple_container_2000/db/full-container-2000`; + const container2001DbPath = + getTmpZombiePath() + + `/${c2001}/data/containers/chains/frontier_container_2001/db/full-container-2001`; + expect(await directoryExists(container2000DbPath)).to.be.true; + expect(await directoryExists(container2001DbPath)).to.be.true; + await ensureContainerDbPathsDontExist(unassignedCollators, containerDbPaths); + }, + }); + + it({ + id: "T15", + title: "Blocks are being produced on container 2000", + test: async function () { + await context.waitBlock(1, "Container2000"); + }, + }); + + it({ + id: "T16", + title: "Blocks are being produced on container 2001", + test: async function () { + await context.waitBlock(1, "Container2001"); + }, + }); + }, +}); + +async function directoryExists(directoryPath) { + try { + await fs.access(directoryPath, fs.constants.F_OK); + return true; + } catch (err) { + return false; + } +} + +/// Returns the /tmp/zombie-52234... path +function getTmpZombiePath() { + const logFilePath = process.env.MOON_MONITORED_NODE; + + if (logFilePath) { + const lastIndex = logFilePath.lastIndexOf("/"); + return lastIndex !== -1 ? logFilePath.substring(0, lastIndex) : null; + } + + // Return null if the environment variable is not set + return null; +} + +/// Given a list of collators and a list of dbPaths, checks that the path does not exist for all the collators. +/// This can be used to ensure that all the unassigned collators do not have any container chains running. +async function ensureContainerDbPathsDontExist(collators: string[], pathsToVerify: string[]) { + for (const collator of collators) { + for (const path of pathsToVerify) { + const fullPath = getTmpZombiePath() + `/${collator}${path}`; + expect(await directoryExists(fullPath), `Container DB path exists for ${collator}: ${fullPath}`).to.be + .false; + } + } +} + +/// Create a map of collator key "5C5p..." to collator name "Collator1000-01". +function createCollatorKeyToNameMap(paraApi, collatorNames: string[]): Record { + const collatorName: Record = {}; + + collatorNames.forEach((name) => { + const hexAddress = getKeyringNimbusIdHex(name); + const k = paraApi.createType("AccountId", hexAddress); + collatorName[k] = name; + }); + + return collatorName; +} + +/// Given a list of all collators and collators assigned to containers, returns the collators that are not assigned to +/// containers. +function getUnassignedCollators(allCollators: string[], assignedToContainers: string[]): string[] { + return allCollators.filter((collator) => !assignedToContainers.includes(collator)); +} + +function logAssignment(collatorName, assignment) { + const nameAssignment = { + orchestratorChain: assignment.orchestratorChain.map((x) => collatorName[x]), + containerChains: Object.keys(assignment.containerChains).reduce((result, key) => { + result[key] = assignment.containerChains[key].map((x) => collatorName[x]); + return result; + }, {}), + }; + + console.log(nameAssignment); +} diff --git a/typescript-api/src/dancebox/interfaces/augment-api-events.ts b/typescript-api/src/dancebox/interfaces/augment-api-events.ts index 7ec1f3ad3..0a0447546 100644 --- a/typescript-api/src/dancebox/interfaces/augment-api-events.ts +++ b/typescript-api/src/dancebox/interfaces/augment-api-events.ts @@ -6,7 +6,7 @@ import "@polkadot/api-base/types/events"; import type { ApiTypes, AugmentedEvent } from "@polkadot/api-base/types"; -import type { Bytes, Null, Option, Result, U8aFixed, Vec, u128, u16, u32, u64, u8 } from "@polkadot/types-codec"; +import type { Bytes, Null, Option, Result, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 } from "@polkadot/types-codec"; import type { AccountId32, H256 } from "@polkadot/types/interfaces/runtime"; import type { DanceboxRuntimeProxyType, @@ -116,6 +116,15 @@ declare module "@polkadot/api-base/types/events" { /** Generic event */ [key: string]: AugmentedEvent; }; + collatorAssignment: { + NewPendingAssignment: AugmentedEvent< + ApiType, + [randomSeed: U8aFixed, fullRotation: bool, targetSession: u32], + { randomSeed: U8aFixed; fullRotation: bool; targetSession: u32 } + >; + /** Generic event */ + [key: string]: AugmentedEvent; + }; cumulusXcm: { /** Downward message executed with the given outcome. [ id, outcome ] */ ExecutedDownward: AugmentedEvent; diff --git a/typescript-api/src/dancebox/interfaces/augment-api-query.ts b/typescript-api/src/dancebox/interfaces/augment-api-query.ts index 96e3286c5..d1f4abdee 100644 --- a/typescript-api/src/dancebox/interfaces/augment-api-query.ts +++ b/typescript-api/src/dancebox/interfaces/augment-api-query.ts @@ -205,6 +205,12 @@ declare module "@polkadot/api-base/types/storage" { [] > & QueryableStorageEntry; + /** + * Randomness from previous block. Used to shuffle collators on session change. Should only be set on the last + * block of each session and should be killed on the on_initialize of the next block. The default value of [0; 32] + * disables randomness in the pallet. + */ + randomness: AugmentedQuery Observable, []> & QueryableStorageEntry; /** Generic query */ [key: string]: QueryableStorageEntry; }; diff --git a/typescript-api/src/dancebox/interfaces/augment-api-tx.ts b/typescript-api/src/dancebox/interfaces/augment-api-tx.ts index 0d63c63ad..33b4de79a 100644 --- a/typescript-api/src/dancebox/interfaces/augment-api-tx.ts +++ b/typescript-api/src/dancebox/interfaces/augment-api-tx.ts @@ -240,6 +240,11 @@ declare module "@polkadot/api-base/types/submittable" { (updated: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32] >; + /** See [`Pallet::set_full_rotation_period`]. */ + setFullRotationPeriod: AugmentedSubmittable< + (updated: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, + [u32] + >; /** See [`Pallet::set_max_collators`]. */ setMaxCollators: AugmentedSubmittable< (updated: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, diff --git a/typescript-api/src/dancebox/interfaces/lookup.ts b/typescript-api/src/dancebox/interfaces/lookup.ts index b3e33b151..ed58dd3e2 100644 --- a/typescript-api/src/dancebox/interfaces/lookup.ts +++ b/typescript-api/src/dancebox/interfaces/lookup.ts @@ -389,7 +389,17 @@ export default { }, }, }, - /** Lookup47: pallet_author_noting::pallet::Event */ + /** Lookup47: pallet_collator_assignment::pallet::Event */ + PalletCollatorAssignmentEvent: { + _enum: { + NewPendingAssignment: { + randomSeed: "[u8;32]", + fullRotation: "bool", + targetSession: "u32", + }, + }, + }, + /** Lookup49: pallet_author_noting::pallet::Event */ PalletAuthorNotingEvent: { _enum: { LatestAuthorChanged: { @@ -402,7 +412,7 @@ export default { }, }, }, - /** Lookup48: pallet_invulnerables::pallet::Event */ + /** Lookup50: pallet_invulnerables::pallet::Event */ PalletInvulnerablesEvent: { _enum: { NewInvulnerables: { @@ -419,7 +429,7 @@ export default { }, }, }, - /** Lookup50: pallet_session::pallet::Event */ + /** Lookup52: pallet_session::pallet::Event */ PalletSessionEvent: { _enum: { NewSession: { @@ -427,7 +437,7 @@ export default { }, }, }, - /** Lookup51: pallet_pooled_staking::pallet::Event */ + /** Lookup53: pallet_pooled_staking::pallet::Event */ PalletPooledStakingEvent: { _enum: { UpdatedCandidatePosition: { @@ -522,11 +532,11 @@ export default { }, }, }, - /** Lookup53: pallet_pooled_staking::pallet::TargetPool */ + /** Lookup55: pallet_pooled_staking::pallet::TargetPool */ PalletPooledStakingTargetPool: { _enum: ["AutoCompounding", "ManualRewards"], }, - /** Lookup54: cumulus_pallet_xcmp_queue::pallet::Event */ + /** Lookup56: cumulus_pallet_xcmp_queue::pallet::Event */ CumulusPalletXcmpQueueEvent: { _enum: { Success: { @@ -561,7 +571,7 @@ export default { }, }, }, - /** Lookup55: staging_xcm::v3::traits::Error */ + /** Lookup57: staging_xcm::v3::traits::Error */ StagingXcmV3TraitsError: { _enum: { Overflow: "Null", @@ -606,7 +616,7 @@ export default { ExceedsStackLimit: "Null", }, }, - /** Lookup56: cumulus_pallet_xcm::pallet::Event */ + /** Lookup58: cumulus_pallet_xcm::pallet::Event */ CumulusPalletXcmEvent: { _enum: { InvalidFormat: "[u8;32]", @@ -614,7 +624,7 @@ export default { ExecutedDownward: "([u8;32],StagingXcmV3TraitsOutcome)", }, }, - /** Lookup57: staging_xcm::v3::traits::Outcome */ + /** Lookup59: staging_xcm::v3::traits::Outcome */ StagingXcmV3TraitsOutcome: { _enum: { Complete: "SpWeightsWeightV2Weight", @@ -622,7 +632,7 @@ export default { Error: "StagingXcmV3TraitsError", }, }, - /** Lookup58: cumulus_pallet_dmp_queue::pallet::Event */ + /** Lookup60: cumulus_pallet_dmp_queue::pallet::Event */ CumulusPalletDmpQueueEvent: { _enum: { InvalidFormat: { @@ -657,7 +667,7 @@ export default { }, }, }, - /** Lookup59: pallet_xcm::pallet::Event */ + /** Lookup61: pallet_xcm::pallet::Event */ PalletXcmEvent: { _enum: { Attempted: { @@ -777,12 +787,12 @@ export default { }, }, }, - /** Lookup60: staging_xcm::v3::multilocation::MultiLocation */ + /** Lookup62: staging_xcm::v3::multilocation::MultiLocation */ StagingXcmV3MultiLocation: { parents: "u8", interior: "StagingXcmV3Junctions", }, - /** Lookup61: staging_xcm::v3::junctions::Junctions */ + /** Lookup63: staging_xcm::v3::junctions::Junctions */ StagingXcmV3Junctions: { _enum: { Here: "Null", @@ -796,7 +806,7 @@ export default { X8: "(StagingXcmV3Junction,StagingXcmV3Junction,StagingXcmV3Junction,StagingXcmV3Junction,StagingXcmV3Junction,StagingXcmV3Junction,StagingXcmV3Junction,StagingXcmV3Junction)", }, }, - /** Lookup62: staging_xcm::v3::junction::Junction */ + /** Lookup64: staging_xcm::v3::junction::Junction */ StagingXcmV3Junction: { _enum: { Parachain: "Compact", @@ -826,7 +836,7 @@ export default { GlobalConsensus: "StagingXcmV3JunctionNetworkId", }, }, - /** Lookup65: staging_xcm::v3::junction::NetworkId */ + /** Lookup67: staging_xcm::v3::junction::NetworkId */ StagingXcmV3JunctionNetworkId: { _enum: { ByGenesis: "[u8;32]", @@ -846,7 +856,7 @@ export default { BitcoinCash: "Null", }, }, - /** Lookup68: staging_xcm::v3::junction::BodyId */ + /** Lookup70: staging_xcm::v3::junction::BodyId */ StagingXcmV3JunctionBodyId: { _enum: { Unit: "Null", @@ -861,7 +871,7 @@ export default { Treasury: "Null", }, }, - /** Lookup69: staging_xcm::v3::junction::BodyPart */ + /** Lookup71: staging_xcm::v3::junction::BodyPart */ StagingXcmV3JunctionBodyPart: { _enum: { Voice: "Null", @@ -882,9 +892,9 @@ export default { }, }, }, - /** Lookup70: staging_xcm::v3::Xcm */ + /** Lookup72: staging_xcm::v3::Xcm */ StagingXcmV3Xcm: "Vec", - /** Lookup72: staging_xcm::v3::Instruction */ + /** Lookup74: staging_xcm::v3::Instruction */ StagingXcmV3Instruction: { _enum: { WithdrawAsset: "StagingXcmV3MultiassetMultiAssets", @@ -1024,28 +1034,28 @@ export default { }, }, }, - /** Lookup73: staging_xcm::v3::multiasset::MultiAssets */ + /** Lookup75: staging_xcm::v3::multiasset::MultiAssets */ StagingXcmV3MultiassetMultiAssets: "Vec", - /** Lookup75: staging_xcm::v3::multiasset::MultiAsset */ + /** Lookup77: staging_xcm::v3::multiasset::MultiAsset */ StagingXcmV3MultiAsset: { id: "StagingXcmV3MultiassetAssetId", fun: "StagingXcmV3MultiassetFungibility", }, - /** Lookup76: staging_xcm::v3::multiasset::AssetId */ + /** Lookup78: staging_xcm::v3::multiasset::AssetId */ StagingXcmV3MultiassetAssetId: { _enum: { Concrete: "StagingXcmV3MultiLocation", Abstract: "[u8;32]", }, }, - /** Lookup77: staging_xcm::v3::multiasset::Fungibility */ + /** Lookup79: staging_xcm::v3::multiasset::Fungibility */ StagingXcmV3MultiassetFungibility: { _enum: { Fungible: "Compact", NonFungible: "StagingXcmV3MultiassetAssetInstance", }, }, - /** Lookup78: staging_xcm::v3::multiasset::AssetInstance */ + /** Lookup80: staging_xcm::v3::multiasset::AssetInstance */ StagingXcmV3MultiassetAssetInstance: { _enum: { Undefined: "Null", @@ -1056,7 +1066,7 @@ export default { Array32: "[u8;32]", }, }, - /** Lookup81: staging_xcm::v3::Response */ + /** Lookup83: staging_xcm::v3::Response */ StagingXcmV3Response: { _enum: { Null: "Null", @@ -1067,7 +1077,7 @@ export default { DispatchResult: "StagingXcmV3MaybeErrorCode", }, }, - /** Lookup85: staging_xcm::v3::PalletInfo */ + /** Lookup87: staging_xcm::v3::PalletInfo */ StagingXcmV3PalletInfo: { index: "Compact", name: "Bytes", @@ -1076,7 +1086,7 @@ export default { minor: "Compact", patch: "Compact", }, - /** Lookup88: staging_xcm::v3::MaybeErrorCode */ + /** Lookup90: staging_xcm::v3::MaybeErrorCode */ StagingXcmV3MaybeErrorCode: { _enum: { Success: "Null", @@ -1084,28 +1094,28 @@ export default { TruncatedError: "Bytes", }, }, - /** Lookup91: staging_xcm::v2::OriginKind */ + /** Lookup93: staging_xcm::v2::OriginKind */ StagingXcmV2OriginKind: { _enum: ["Native", "SovereignAccount", "Superuser", "Xcm"], }, - /** Lookup92: staging_xcm::double_encoded::DoubleEncoded */ + /** Lookup94: staging_xcm::double_encoded::DoubleEncoded */ StagingXcmDoubleEncoded: { encoded: "Bytes", }, - /** Lookup93: staging_xcm::v3::QueryResponseInfo */ + /** Lookup95: staging_xcm::v3::QueryResponseInfo */ StagingXcmV3QueryResponseInfo: { destination: "StagingXcmV3MultiLocation", queryId: "Compact", maxWeight: "SpWeightsWeightV2Weight", }, - /** Lookup94: staging_xcm::v3::multiasset::MultiAssetFilter */ + /** Lookup96: staging_xcm::v3::multiasset::MultiAssetFilter */ StagingXcmV3MultiassetMultiAssetFilter: { _enum: { Definite: "StagingXcmV3MultiassetMultiAssets", Wild: "StagingXcmV3MultiassetWildMultiAsset", }, }, - /** Lookup95: staging_xcm::v3::multiasset::WildMultiAsset */ + /** Lookup97: staging_xcm::v3::multiasset::WildMultiAsset */ StagingXcmV3MultiassetWildMultiAsset: { _enum: { All: "Null", @@ -1121,18 +1131,18 @@ export default { }, }, }, - /** Lookup96: staging_xcm::v3::multiasset::WildFungibility */ + /** Lookup98: staging_xcm::v3::multiasset::WildFungibility */ StagingXcmV3MultiassetWildFungibility: { _enum: ["Fungible", "NonFungible"], }, - /** Lookup98: staging_xcm::v3::WeightLimit */ + /** Lookup99: staging_xcm::v3::WeightLimit */ StagingXcmV3WeightLimit: { _enum: { Unlimited: "Null", Limited: "SpWeightsWeightV2Weight", }, }, - /** Lookup99: staging_xcm::VersionedMultiAssets */ + /** Lookup100: staging_xcm::VersionedMultiAssets */ StagingXcmVersionedMultiAssets: { _enum: { __Unused0: "Null", @@ -1141,26 +1151,26 @@ export default { V3: "StagingXcmV3MultiassetMultiAssets", }, }, - /** Lookup100: staging_xcm::v2::multiasset::MultiAssets */ + /** Lookup101: staging_xcm::v2::multiasset::MultiAssets */ StagingXcmV2MultiassetMultiAssets: "Vec", - /** Lookup102: staging_xcm::v2::multiasset::MultiAsset */ + /** Lookup103: staging_xcm::v2::multiasset::MultiAsset */ StagingXcmV2MultiAsset: { id: "StagingXcmV2MultiassetAssetId", fun: "StagingXcmV2MultiassetFungibility", }, - /** Lookup103: staging_xcm::v2::multiasset::AssetId */ + /** Lookup104: staging_xcm::v2::multiasset::AssetId */ StagingXcmV2MultiassetAssetId: { _enum: { Concrete: "StagingXcmV2MultiLocation", Abstract: "Bytes", }, }, - /** Lookup104: staging_xcm::v2::multilocation::MultiLocation */ + /** Lookup105: staging_xcm::v2::multilocation::MultiLocation */ StagingXcmV2MultiLocation: { parents: "u8", interior: "StagingXcmV2MultilocationJunctions", }, - /** Lookup105: staging_xcm::v2::multilocation::Junctions */ + /** Lookup106: staging_xcm::v2::multilocation::Junctions */ StagingXcmV2MultilocationJunctions: { _enum: { Here: "Null", @@ -1174,7 +1184,7 @@ export default { X8: "(StagingXcmV2Junction,StagingXcmV2Junction,StagingXcmV2Junction,StagingXcmV2Junction,StagingXcmV2Junction,StagingXcmV2Junction,StagingXcmV2Junction,StagingXcmV2Junction)", }, }, - /** Lookup106: staging_xcm::v2::junction::Junction */ + /** Lookup107: staging_xcm::v2::junction::Junction */ StagingXcmV2Junction: { _enum: { Parachain: "Compact", @@ -1200,7 +1210,7 @@ export default { }, }, }, - /** Lookup107: staging_xcm::v2::NetworkId */ + /** Lookup108: staging_xcm::v2::NetworkId */ StagingXcmV2NetworkId: { _enum: { Any: "Null", @@ -1209,7 +1219,7 @@ export default { Kusama: "Null", }, }, - /** Lookup109: staging_xcm::v2::BodyId */ + /** Lookup110: staging_xcm::v2::BodyId */ StagingXcmV2BodyId: { _enum: { Unit: "Null", @@ -1224,7 +1234,7 @@ export default { Treasury: "Null", }, }, - /** Lookup110: staging_xcm::v2::BodyPart */ + /** Lookup111: staging_xcm::v2::BodyPart */ StagingXcmV2BodyPart: { _enum: { Voice: "Null", @@ -1245,14 +1255,14 @@ export default { }, }, }, - /** Lookup111: staging_xcm::v2::multiasset::Fungibility */ + /** Lookup112: staging_xcm::v2::multiasset::Fungibility */ StagingXcmV2MultiassetFungibility: { _enum: { Fungible: "Compact", NonFungible: "StagingXcmV2MultiassetAssetInstance", }, }, - /** Lookup112: staging_xcm::v2::multiasset::AssetInstance */ + /** Lookup113: staging_xcm::v2::multiasset::AssetInstance */ StagingXcmV2MultiassetAssetInstance: { _enum: { Undefined: "Null", @@ -1264,7 +1274,7 @@ export default { Blob: "Bytes", }, }, - /** Lookup113: staging_xcm::VersionedMultiLocation */ + /** Lookup114: staging_xcm::VersionedMultiLocation */ StagingXcmVersionedMultiLocation: { _enum: { __Unused0: "Null", @@ -1273,7 +1283,7 @@ export default { V3: "StagingXcmV3MultiLocation", }, }, - /** Lookup114: frame_system::Phase */ + /** Lookup115: frame_system::Phase */ FrameSystemPhase: { _enum: { ApplyExtrinsic: "u32", @@ -1281,12 +1291,12 @@ export default { Initialization: "Null", }, }, - /** Lookup118: frame_system::LastRuntimeUpgradeInfo */ + /** Lookup119: frame_system::LastRuntimeUpgradeInfo */ FrameSystemLastRuntimeUpgradeInfo: { specVersion: "Compact", specName: "Text", }, - /** Lookup120: frame_system::pallet::Call */ + /** Lookup121: frame_system::pallet::Call */ FrameSystemCall: { _enum: { remark: { @@ -1319,41 +1329,41 @@ export default { }, }, }, - /** Lookup124: frame_system::limits::BlockWeights */ + /** Lookup125: frame_system::limits::BlockWeights */ FrameSystemLimitsBlockWeights: { baseBlock: "SpWeightsWeightV2Weight", maxBlock: "SpWeightsWeightV2Weight", perClass: "FrameSupportDispatchPerDispatchClassWeightsPerClass", }, - /** Lookup125: frame_support::dispatch::PerDispatchClass */ + /** Lookup126: frame_support::dispatch::PerDispatchClass */ FrameSupportDispatchPerDispatchClassWeightsPerClass: { normal: "FrameSystemLimitsWeightsPerClass", operational: "FrameSystemLimitsWeightsPerClass", mandatory: "FrameSystemLimitsWeightsPerClass", }, - /** Lookup126: frame_system::limits::WeightsPerClass */ + /** Lookup127: frame_system::limits::WeightsPerClass */ FrameSystemLimitsWeightsPerClass: { baseExtrinsic: "SpWeightsWeightV2Weight", maxExtrinsic: "Option", maxTotal: "Option", reserved: "Option", }, - /** Lookup128: frame_system::limits::BlockLength */ + /** Lookup129: frame_system::limits::BlockLength */ FrameSystemLimitsBlockLength: { max: "FrameSupportDispatchPerDispatchClassU32", }, - /** Lookup129: frame_support::dispatch::PerDispatchClass */ + /** Lookup130: frame_support::dispatch::PerDispatchClass */ FrameSupportDispatchPerDispatchClassU32: { normal: "u32", operational: "u32", mandatory: "u32", }, - /** Lookup130: sp_weights::RuntimeDbWeight */ + /** Lookup131: sp_weights::RuntimeDbWeight */ SpWeightsRuntimeDbWeight: { read: "u64", write: "u64", }, - /** Lookup131: sp_version::RuntimeVersion */ + /** Lookup132: sp_version::RuntimeVersion */ SpVersionRuntimeVersion: { specName: "Text", implName: "Text", @@ -1364,7 +1374,7 @@ export default { transactionVersion: "u32", stateVersion: "u8", }, - /** Lookup135: frame_system::pallet::Error */ + /** Lookup136: frame_system::pallet::Error */ FrameSystemError: { _enum: [ "InvalidSpecName", @@ -1375,49 +1385,49 @@ export default { "CallFiltered", ], }, - /** Lookup137: cumulus_pallet_parachain_system::unincluded_segment::Ancestor */ + /** Lookup138: cumulus_pallet_parachain_system::unincluded_segment::Ancestor */ CumulusPalletParachainSystemUnincludedSegmentAncestor: { usedBandwidth: "CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth", paraHeadHash: "Option", consumedGoAheadSignal: "Option", }, - /** Lookup138: cumulus_pallet_parachain_system::unincluded_segment::UsedBandwidth */ + /** Lookup139: cumulus_pallet_parachain_system::unincluded_segment::UsedBandwidth */ CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth: { umpMsgCount: "u32", umpTotalBytes: "u32", hrmpOutgoing: "BTreeMap", }, - /** Lookup140: cumulus_pallet_parachain_system::unincluded_segment::HrmpChannelUpdate */ + /** Lookup141: cumulus_pallet_parachain_system::unincluded_segment::HrmpChannelUpdate */ CumulusPalletParachainSystemUnincludedSegmentHrmpChannelUpdate: { msgCount: "u32", totalBytes: "u32", }, - /** Lookup145: polkadot_primitives::v5::UpgradeGoAhead */ + /** Lookup146: polkadot_primitives::v5::UpgradeGoAhead */ PolkadotPrimitivesV5UpgradeGoAhead: { _enum: ["Abort", "GoAhead"], }, - /** Lookup146: cumulus_pallet_parachain_system::unincluded_segment::SegmentTracker */ + /** Lookup147: cumulus_pallet_parachain_system::unincluded_segment::SegmentTracker */ CumulusPalletParachainSystemUnincludedSegmentSegmentTracker: { usedBandwidth: "CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth", hrmpWatermark: "Option", consumedGoAheadSignal: "Option", }, - /** Lookup147: polkadot_primitives::v5::PersistedValidationData */ + /** Lookup148: polkadot_primitives::v5::PersistedValidationData */ PolkadotPrimitivesV5PersistedValidationData: { parentHead: "Bytes", relayParentNumber: "u32", relayParentStorageRoot: "H256", maxPovSize: "u32", }, - /** Lookup150: polkadot_primitives::v5::UpgradeRestriction */ + /** Lookup151: polkadot_primitives::v5::UpgradeRestriction */ PolkadotPrimitivesV5UpgradeRestriction: { _enum: ["Present"], }, - /** Lookup151: sp_trie::storage_proof::StorageProof */ + /** Lookup152: sp_trie::storage_proof::StorageProof */ SpTrieStorageProof: { trieNodes: "BTreeSet", }, - /** Lookup153: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot */ + /** Lookup154: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot */ CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: { dmqMqcHead: "H256", relayDispatchQueueRemainingCapacity: @@ -1425,12 +1435,12 @@ export default { ingressChannels: "Vec<(u32,PolkadotPrimitivesV5AbridgedHrmpChannel)>", egressChannels: "Vec<(u32,PolkadotPrimitivesV5AbridgedHrmpChannel)>", }, - /** Lookup154: cumulus_pallet_parachain_system::relay_state_snapshot::RelayDispatchQueueRemainingCapacity */ + /** Lookup155: cumulus_pallet_parachain_system::relay_state_snapshot::RelayDispatchQueueRemainingCapacity */ CumulusPalletParachainSystemRelayStateSnapshotRelayDispatchQueueRemainingCapacity: { remainingCount: "u32", remainingSize: "u32", }, - /** Lookup157: polkadot_primitives::v5::AbridgedHrmpChannel */ + /** Lookup158: polkadot_primitives::v5::AbridgedHrmpChannel */ PolkadotPrimitivesV5AbridgedHrmpChannel: { maxCapacity: "u32", maxTotalSize: "u32", @@ -1439,7 +1449,7 @@ export default { totalSize: "u32", mqcHead: "Option", }, - /** Lookup158: polkadot_primitives::v5::AbridgedHostConfiguration */ + /** Lookup159: polkadot_primitives::v5::AbridgedHostConfiguration */ PolkadotPrimitivesV5AbridgedHostConfiguration: { maxCodeSize: "u32", maxHeadDataSize: "u32", @@ -1452,22 +1462,22 @@ export default { validationUpgradeDelay: "u32", asyncBackingParams: "PolkadotPrimitivesVstagingAsyncBackingParams", }, - /** Lookup159: polkadot_primitives::vstaging::AsyncBackingParams */ + /** Lookup160: polkadot_primitives::vstaging::AsyncBackingParams */ PolkadotPrimitivesVstagingAsyncBackingParams: { maxCandidateDepth: "u32", allowedAncestryLen: "u32", }, - /** Lookup165: polkadot_core_primitives::OutboundHrmpMessage */ + /** Lookup166: polkadot_core_primitives::OutboundHrmpMessage */ PolkadotCorePrimitivesOutboundHrmpMessage: { recipient: "u32", data: "Bytes", }, - /** Lookup166: cumulus_pallet_parachain_system::CodeUpgradeAuthorization */ + /** Lookup167: cumulus_pallet_parachain_system::CodeUpgradeAuthorization */ CumulusPalletParachainSystemCodeUpgradeAuthorization: { codeHash: "H256", checkVersion: "bool", }, - /** Lookup167: cumulus_pallet_parachain_system::pallet::Call */ + /** Lookup168: cumulus_pallet_parachain_system::pallet::Call */ CumulusPalletParachainSystemCall: { _enum: { set_validation_data: { @@ -1485,24 +1495,24 @@ export default { }, }, }, - /** Lookup168: cumulus_primitives_parachain_inherent::ParachainInherentData */ + /** Lookup169: cumulus_primitives_parachain_inherent::ParachainInherentData */ CumulusPrimitivesParachainInherentParachainInherentData: { validationData: "PolkadotPrimitivesV5PersistedValidationData", relayChainState: "SpTrieStorageProof", downwardMessages: "Vec", horizontalMessages: "BTreeMap>", }, - /** Lookup170: polkadot_core_primitives::InboundDownwardMessage */ + /** Lookup171: polkadot_core_primitives::InboundDownwardMessage */ PolkadotCorePrimitivesInboundDownwardMessage: { sentAt: "u32", msg: "Bytes", }, - /** Lookup173: polkadot_core_primitives::InboundHrmpMessage */ + /** Lookup174: polkadot_core_primitives::InboundHrmpMessage */ PolkadotCorePrimitivesInboundHrmpMessage: { sentAt: "u32", data: "Bytes", }, - /** Lookup176: cumulus_pallet_parachain_system::pallet::Error */ + /** Lookup177: cumulus_pallet_parachain_system::pallet::Error */ CumulusPalletParachainSystemError: { _enum: [ "OverlappingUpgrades", @@ -1515,7 +1525,7 @@ export default { "Unauthorized", ], }, - /** Lookup177: pallet_timestamp::pallet::Call */ + /** Lookup178: pallet_timestamp::pallet::Call */ PalletTimestampCall: { _enum: { set: { @@ -1523,9 +1533,9 @@ export default { }, }, }, - /** Lookup178: parachain_info::pallet::Call */ + /** Lookup179: parachain_info::pallet::Call */ ParachainInfoCall: "Null", - /** Lookup179: pallet_sudo::pallet::Call */ + /** Lookup180: pallet_sudo::pallet::Call */ PalletSudoCall: { _enum: { sudo: { @@ -1547,7 +1557,7 @@ export default { }, }, }, - /** Lookup181: pallet_utility::pallet::Call */ + /** Lookup182: pallet_utility::pallet::Call */ PalletUtilityCall: { _enum: { batch: { @@ -1573,7 +1583,7 @@ export default { }, }, }, - /** Lookup183: dancebox_runtime::OriginCaller */ + /** Lookup184: dancebox_runtime::OriginCaller */ DanceboxRuntimeOriginCaller: { _enum: { system: "FrameSupportDispatchRawOrigin", @@ -1632,7 +1642,7 @@ export default { PolkadotXcm: "PalletXcmOrigin", }, }, - /** Lookup184: frame_support::dispatch::RawOrigin */ + /** Lookup185: frame_support::dispatch::RawOrigin */ FrameSupportDispatchRawOrigin: { _enum: { Root: "Null", @@ -1640,23 +1650,23 @@ export default { None: "Null", }, }, - /** Lookup185: cumulus_pallet_xcm::pallet::Origin */ + /** Lookup186: cumulus_pallet_xcm::pallet::Origin */ CumulusPalletXcmOrigin: { _enum: { Relay: "Null", SiblingParachain: "u32", }, }, - /** Lookup186: pallet_xcm::pallet::Origin */ + /** Lookup187: pallet_xcm::pallet::Origin */ PalletXcmOrigin: { _enum: { Xcm: "StagingXcmV3MultiLocation", Response: "StagingXcmV3MultiLocation", }, }, - /** Lookup187: sp_core::Void */ + /** Lookup188: sp_core::Void */ SpCoreVoid: "Null", - /** Lookup188: pallet_proxy::pallet::Call */ + /** Lookup189: pallet_proxy::pallet::Call */ PalletProxyCall: { _enum: { proxy: { @@ -1707,11 +1717,11 @@ export default { }, }, }, - /** Lookup192: pallet_maintenance_mode::pallet::Call */ + /** Lookup193: pallet_maintenance_mode::pallet::Call */ PalletMaintenanceModeCall: { _enum: ["enter_maintenance_mode", "resume_normal_operation"], }, - /** Lookup193: pallet_balances::pallet::Call */ + /** Lookup194: pallet_balances::pallet::Call */ PalletBalancesCall: { _enum: { transfer_allow_death: { @@ -1753,7 +1763,7 @@ export default { }, }, }, - /** Lookup194: pallet_registrar::pallet::Call */ + /** Lookup195: pallet_registrar::pallet::Call */ PalletRegistrarCall: { _enum: { register: { @@ -1775,7 +1785,7 @@ export default { }, }, }, - /** Lookup195: tp_container_chain_genesis_data::ContainerChainGenesisData */ + /** Lookup196: tp_container_chain_genesis_data::ContainerChainGenesisData */ TpContainerChainGenesisDataContainerChainGenesisData: { storage: "Vec", name: "Bytes", @@ -1784,23 +1794,23 @@ export default { extensions: "Bytes", properties: "TpContainerChainGenesisDataProperties", }, - /** Lookup197: tp_container_chain_genesis_data::ContainerChainGenesisDataItem */ + /** Lookup198: tp_container_chain_genesis_data::ContainerChainGenesisDataItem */ TpContainerChainGenesisDataContainerChainGenesisDataItem: { key: "Bytes", value: "Bytes", }, - /** Lookup199: tp_container_chain_genesis_data::Properties */ + /** Lookup200: tp_container_chain_genesis_data::Properties */ TpContainerChainGenesisDataProperties: { tokenMetadata: "TpContainerChainGenesisDataTokenMetadata", isEthereum: "bool", }, - /** Lookup200: tp_container_chain_genesis_data::TokenMetadata */ + /** Lookup201: tp_container_chain_genesis_data::TokenMetadata */ TpContainerChainGenesisDataTokenMetadata: { tokenSymbol: "Bytes", ss58Format: "u32", tokenDecimals: "u32", }, - /** Lookup205: pallet_configuration::pallet::Call */ + /** Lookup206: pallet_configuration::pallet::Call */ PalletConfigurationCall: { _enum: { set_max_collators: { @@ -1827,7 +1837,12 @@ export default { }, new_: "u32", }, - __Unused4: "Null", + set_full_rotation_period: { + _alias: { + new_: "new", + }, + new_: "u32", + }, __Unused5: "Null", __Unused6: "Null", __Unused7: "Null", @@ -1875,9 +1890,9 @@ export default { }, }, }, - /** Lookup206: pallet_collator_assignment::pallet::Call */ + /** Lookup207: pallet_collator_assignment::pallet::Call */ PalletCollatorAssignmentCall: "Null", - /** Lookup207: pallet_author_noting::pallet::Call */ + /** Lookup208: pallet_author_noting::pallet::Call */ PalletAuthorNotingCall: { _enum: { set_latest_author_data: { @@ -1893,13 +1908,13 @@ export default { }, }, }, - /** Lookup208: tp_author_noting_inherent::OwnParachainInherentData */ + /** Lookup209: tp_author_noting_inherent::OwnParachainInherentData */ TpAuthorNotingInherentOwnParachainInherentData: { relayStorageProof: "SpTrieStorageProof", }, - /** Lookup209: pallet_authority_assignment::pallet::Call */ + /** Lookup210: pallet_authority_assignment::pallet::Call */ PalletAuthorityAssignmentCall: "Null", - /** Lookup210: pallet_invulnerables::pallet::Call */ + /** Lookup211: pallet_invulnerables::pallet::Call */ PalletInvulnerablesCall: { _enum: { set_invulnerables: { @@ -1916,7 +1931,7 @@ export default { }, }, }, - /** Lookup211: pallet_session::pallet::Call */ + /** Lookup212: pallet_session::pallet::Call */ PalletSessionCall: { _enum: { set_keys: { @@ -1929,19 +1944,19 @@ export default { purge_keys: "Null", }, }, - /** Lookup212: dancebox_runtime::SessionKeys */ + /** Lookup213: dancebox_runtime::SessionKeys */ DanceboxRuntimeSessionKeys: { nimbus: "NimbusPrimitivesNimbusCryptoPublic", }, - /** Lookup213: nimbus_primitives::nimbus_crypto::Public */ + /** Lookup214: nimbus_primitives::nimbus_crypto::Public */ NimbusPrimitivesNimbusCryptoPublic: "SpCoreSr25519Public", - /** Lookup214: sp_core::sr25519::Public */ + /** Lookup215: sp_core::sr25519::Public */ SpCoreSr25519Public: "[u8;32]", - /** Lookup215: pallet_author_inherent::pallet::Call */ + /** Lookup216: pallet_author_inherent::pallet::Call */ PalletAuthorInherentCall: { _enum: ["kick_off_authorship_validation"], }, - /** Lookup216: pallet_pooled_staking::pallet::Call */ + /** Lookup217: pallet_pooled_staking::pallet::Call */ PalletPooledStakingCall: { _enum: { rebalance_hold: { @@ -1975,16 +1990,16 @@ export default { }, }, }, - /** Lookup217: pallet_pooled_staking::pallet::AllTargetPool */ + /** Lookup218: pallet_pooled_staking::pallet::AllTargetPool */ PalletPooledStakingAllTargetPool: { _enum: ["Joining", "AutoCompounding", "ManualRewards", "Leaving"], }, - /** Lookup219: pallet_pooled_staking::pallet::PendingOperationQuery */ + /** Lookup220: pallet_pooled_staking::pallet::PendingOperationQuery */ PalletPooledStakingPendingOperationQuery: { delegator: "AccountId32", operation: "PalletPooledStakingPendingOperationKey", }, - /** Lookup220: pallet_pooled_staking::pallet::PendingOperationKey */ + /** Lookup221: pallet_pooled_staking::pallet::PendingOperationKey */ PalletPooledStakingPendingOperationKey: { _enum: { JoiningAutoCompounding: { @@ -2001,14 +2016,14 @@ export default { }, }, }, - /** Lookup221: pallet_pooled_staking::pallet::SharesOrStake */ + /** Lookup222: pallet_pooled_staking::pallet::SharesOrStake */ PalletPooledStakingSharesOrStake: { _enum: { Shares: "u128", Stake: "u128", }, }, - /** Lookup224: cumulus_pallet_xcmp_queue::pallet::Call */ + /** Lookup225: cumulus_pallet_xcmp_queue::pallet::Call */ CumulusPalletXcmpQueueCall: { _enum: { service_overweight: { @@ -2055,7 +2070,7 @@ export default { }, }, }, - /** Lookup225: cumulus_pallet_dmp_queue::pallet::Call */ + /** Lookup226: cumulus_pallet_dmp_queue::pallet::Call */ CumulusPalletDmpQueueCall: { _enum: { service_overweight: { @@ -2064,7 +2079,7 @@ export default { }, }, }, - /** Lookup226: pallet_xcm::pallet::Call */ + /** Lookup227: pallet_xcm::pallet::Call */ PalletXcmCall: { _enum: { send: { @@ -2119,7 +2134,7 @@ export default { }, }, }, - /** Lookup227: staging_xcm::VersionedXcm */ + /** Lookup228: staging_xcm::VersionedXcm */ StagingXcmVersionedXcm: { _enum: { __Unused0: "Null", @@ -2128,9 +2143,9 @@ export default { V3: "StagingXcmV3Xcm", }, }, - /** Lookup228: staging_xcm::v2::Xcm */ + /** Lookup229: staging_xcm::v2::Xcm */ StagingXcmV2Xcm: "Vec", - /** Lookup230: staging_xcm::v2::Instruction */ + /** Lookup231: staging_xcm::v2::Instruction */ StagingXcmV2Instruction: { _enum: { WithdrawAsset: "StagingXcmV2MultiassetMultiAssets", @@ -2226,7 +2241,7 @@ export default { UnsubscribeVersion: "Null", }, }, - /** Lookup231: staging_xcm::v2::Response */ + /** Lookup232: staging_xcm::v2::Response */ StagingXcmV2Response: { _enum: { Null: "Null", @@ -2235,7 +2250,7 @@ export default { Version: "u32", }, }, - /** Lookup234: staging_xcm::v2::traits::Error */ + /** Lookup235: staging_xcm::v2::traits::Error */ StagingXcmV2TraitsError: { _enum: { Overflow: "Null", @@ -2266,14 +2281,14 @@ export default { WeightNotComputable: "Null", }, }, - /** Lookup235: staging_xcm::v2::multiasset::MultiAssetFilter */ + /** Lookup236: staging_xcm::v2::multiasset::MultiAssetFilter */ StagingXcmV2MultiassetMultiAssetFilter: { _enum: { Definite: "StagingXcmV2MultiassetMultiAssets", Wild: "StagingXcmV2MultiassetWildMultiAsset", }, }, - /** Lookup236: staging_xcm::v2::multiasset::WildMultiAsset */ + /** Lookup237: staging_xcm::v2::multiasset::WildMultiAsset */ StagingXcmV2MultiassetWildMultiAsset: { _enum: { All: "Null", @@ -2283,18 +2298,18 @@ export default { }, }, }, - /** Lookup237: staging_xcm::v2::multiasset::WildFungibility */ + /** Lookup238: staging_xcm::v2::multiasset::WildFungibility */ StagingXcmV2MultiassetWildFungibility: { _enum: ["Fungible", "NonFungible"], }, - /** Lookup238: staging_xcm::v2::WeightLimit */ + /** Lookup239: staging_xcm::v2::WeightLimit */ StagingXcmV2WeightLimit: { _enum: { Unlimited: "Null", Limited: "Compact", }, }, - /** Lookup247: pallet_root_testing::pallet::Call */ + /** Lookup248: pallet_root_testing::pallet::Call */ PalletRootTestingCall: { _enum: { fill_block: { @@ -2302,27 +2317,27 @@ export default { }, }, }, - /** Lookup249: pallet_sudo::pallet::Error */ + /** Lookup250: pallet_sudo::pallet::Error */ PalletSudoError: { _enum: ["RequireSudo"], }, - /** Lookup250: pallet_utility::pallet::Error */ + /** Lookup251: pallet_utility::pallet::Error */ PalletUtilityError: { _enum: ["TooManyCalls"], }, - /** Lookup253: pallet_proxy::ProxyDefinition */ + /** Lookup254: pallet_proxy::ProxyDefinition */ PalletProxyProxyDefinition: { delegate: "AccountId32", proxyType: "DanceboxRuntimeProxyType", delay: "u32", }, - /** Lookup257: pallet_proxy::Announcement */ + /** Lookup258: pallet_proxy::Announcement */ PalletProxyAnnouncement: { real: "AccountId32", callHash: "H256", height: "u32", }, - /** Lookup259: pallet_proxy::pallet::Error */ + /** Lookup260: pallet_proxy::pallet::Error */ PalletProxyError: { _enum: [ "TooMany", @@ -2335,39 +2350,39 @@ export default { "NoSelfProxy", ], }, - /** Lookup260: pallet_migrations::pallet::Error */ + /** Lookup261: pallet_migrations::pallet::Error */ PalletMigrationsError: { _enum: ["PreimageMissing", "WrongUpperBound", "PreimageIsTooBig", "PreimageAlreadyExists"], }, - /** Lookup261: pallet_maintenance_mode::pallet::Error */ + /** Lookup262: pallet_maintenance_mode::pallet::Error */ PalletMaintenanceModeError: { _enum: ["AlreadyInMaintenanceMode", "NotInMaintenanceMode"], }, - /** Lookup263: pallet_balances::types::BalanceLock */ + /** Lookup264: pallet_balances::types::BalanceLock */ PalletBalancesBalanceLock: { id: "[u8;8]", amount: "u128", reasons: "PalletBalancesReasons", }, - /** Lookup264: pallet_balances::types::Reasons */ + /** Lookup265: pallet_balances::types::Reasons */ PalletBalancesReasons: { _enum: ["Fee", "Misc", "All"], }, - /** Lookup267: pallet_balances::types::ReserveData */ + /** Lookup268: pallet_balances::types::ReserveData */ PalletBalancesReserveData: { id: "[u8;8]", amount: "u128", }, - /** Lookup271: dancebox_runtime::HoldReason */ + /** Lookup272: dancebox_runtime::HoldReason */ DanceboxRuntimeHoldReason: { _enum: ["PooledStake"], }, - /** Lookup274: pallet_balances::types::IdAmount */ + /** Lookup275: pallet_balances::types::IdAmount */ PalletBalancesIdAmount: { id: "[u8;8]", amount: "u128", }, - /** Lookup276: pallet_balances::pallet::Error */ + /** Lookup277: pallet_balances::pallet::Error */ PalletBalancesError: { _enum: [ "VestingBalance", @@ -2382,16 +2397,16 @@ export default { "TooManyFreezes", ], }, - /** Lookup278: pallet_transaction_payment::Releases */ + /** Lookup279: pallet_transaction_payment::Releases */ PalletTransactionPaymentReleases: { _enum: ["V1Ancient", "V2"], }, - /** Lookup283: pallet_registrar::pallet::DepositInfo */ + /** Lookup284: pallet_registrar::pallet::DepositInfo */ PalletRegistrarDepositInfo: { creator: "AccountId32", deposit: "u128", }, - /** Lookup284: pallet_registrar::pallet::Error */ + /** Lookup285: pallet_registrar::pallet::Error */ PalletRegistrarError: { _enum: [ "ParaIdAlreadyRegistered", @@ -2403,28 +2418,29 @@ export default { "NotSufficientDeposit", ], }, - /** Lookup285: pallet_configuration::HostConfiguration */ + /** Lookup286: pallet_configuration::HostConfiguration */ PalletConfigurationHostConfiguration: { maxCollators: "u32", minOrchestratorCollators: "u32", maxOrchestratorCollators: "u32", collatorsPerContainer: "u32", + fullRotationPeriod: "u32", }, - /** Lookup288: pallet_configuration::pallet::Error */ + /** Lookup289: pallet_configuration::pallet::Error */ PalletConfigurationError: { _enum: ["InvalidNewValue"], }, - /** Lookup289: tp_collator_assignment::AssignedCollators */ + /** Lookup290: tp_collator_assignment::AssignedCollators */ TpCollatorAssignmentAssignedCollatorsAccountId32: { orchestratorChain: "Vec", containerChains: "BTreeMap>", }, - /** Lookup294: pallet_author_noting::pallet::ContainerChainBlockInfo */ + /** Lookup295: pallet_author_noting::pallet::ContainerChainBlockInfo */ PalletAuthorNotingContainerChainBlockInfo: { blockNumber: "u32", author: "AccountId32", }, - /** Lookup295: pallet_author_noting::pallet::Error */ + /** Lookup296: pallet_author_noting::pallet::Error */ PalletAuthorNotingError: { _enum: [ "FailedReading", @@ -2436,31 +2452,31 @@ export default { "NonAuraDigest", ], }, - /** Lookup296: tp_collator_assignment::AssignedCollators */ + /** Lookup297: tp_collator_assignment::AssignedCollators */ TpCollatorAssignmentAssignedCollatorsPublic: { orchestratorChain: "Vec", containerChains: "BTreeMap>", }, - /** Lookup302: pallet_invulnerables::pallet::Error */ + /** Lookup303: pallet_invulnerables::pallet::Error */ PalletInvulnerablesError: { _enum: ["TooManyInvulnerables", "AlreadyInvulnerable", "NotInvulnerable"], }, - /** Lookup307: sp_core::crypto::KeyTypeId */ + /** Lookup308: sp_core::crypto::KeyTypeId */ SpCoreCryptoKeyTypeId: "[u8;4]", - /** Lookup308: pallet_session::pallet::Error */ + /** Lookup309: pallet_session::pallet::Error */ PalletSessionError: { _enum: ["InvalidProof", "NoAssociatedValidatorId", "DuplicatedKey", "NoKeys", "NoAccount"], }, - /** Lookup312: pallet_author_inherent::pallet::Error */ + /** Lookup313: pallet_author_inherent::pallet::Error */ PalletAuthorInherentError: { _enum: ["AuthorAlreadySet", "NoAccountId", "CannotBeAuthor"], }, - /** Lookup314: pallet_pooled_staking::candidate::EligibleCandidate */ + /** Lookup315: pallet_pooled_staking::candidate::EligibleCandidate */ PalletPooledStakingCandidateEligibleCandidate: { candidate: "AccountId32", stake: "u128", }, - /** Lookup317: pallet_pooled_staking::pallet::PoolsKey */ + /** Lookup318: pallet_pooled_staking::pallet::PoolsKey */ PalletPooledStakingPoolsKey: { _enum: { CandidateTotalStake: "Null", @@ -2502,7 +2518,7 @@ export default { }, }, }, - /** Lookup319: pallet_pooled_staking::pallet::Error */ + /** Lookup320: pallet_pooled_staking::pallet::Error */ PalletPooledStakingError: { _enum: { InvalidPalletSetting: "Null", @@ -2521,21 +2537,21 @@ export default { SwapResultsInZeroShares: "Null", }, }, - /** Lookup321: cumulus_pallet_xcmp_queue::InboundChannelDetails */ + /** Lookup322: cumulus_pallet_xcmp_queue::InboundChannelDetails */ CumulusPalletXcmpQueueInboundChannelDetails: { sender: "u32", state: "CumulusPalletXcmpQueueInboundState", messageMetadata: "Vec<(u32,PolkadotParachainPrimitivesPrimitivesXcmpMessageFormat)>", }, - /** Lookup322: cumulus_pallet_xcmp_queue::InboundState */ + /** Lookup323: cumulus_pallet_xcmp_queue::InboundState */ CumulusPalletXcmpQueueInboundState: { _enum: ["Ok", "Suspended"], }, - /** Lookup325: polkadot_parachain_primitives::primitives::XcmpMessageFormat */ + /** Lookup326: polkadot_parachain_primitives::primitives::XcmpMessageFormat */ PolkadotParachainPrimitivesPrimitivesXcmpMessageFormat: { _enum: ["ConcatenatedVersionedXcm", "ConcatenatedEncodedBlob", "Signals"], }, - /** Lookup328: cumulus_pallet_xcmp_queue::OutboundChannelDetails */ + /** Lookup329: cumulus_pallet_xcmp_queue::OutboundChannelDetails */ CumulusPalletXcmpQueueOutboundChannelDetails: { recipient: "u32", state: "CumulusPalletXcmpQueueOutboundState", @@ -2543,11 +2559,11 @@ export default { firstIndex: "u16", lastIndex: "u16", }, - /** Lookup329: cumulus_pallet_xcmp_queue::OutboundState */ + /** Lookup330: cumulus_pallet_xcmp_queue::OutboundState */ CumulusPalletXcmpQueueOutboundState: { _enum: ["Ok", "Suspended"], }, - /** Lookup331: cumulus_pallet_xcmp_queue::QueueConfigData */ + /** Lookup332: cumulus_pallet_xcmp_queue::QueueConfigData */ CumulusPalletXcmpQueueQueueConfigData: { suspendThreshold: "u32", dropThreshold: "u32", @@ -2556,27 +2572,27 @@ export default { weightRestrictDecay: "SpWeightsWeightV2Weight", xcmpMaxIndividualWeight: "SpWeightsWeightV2Weight", }, - /** Lookup333: cumulus_pallet_xcmp_queue::pallet::Error */ + /** Lookup334: cumulus_pallet_xcmp_queue::pallet::Error */ CumulusPalletXcmpQueueError: { _enum: ["FailedToSend", "BadXcmOrigin", "BadXcm", "BadOverweightIndex", "WeightOverLimit"], }, - /** Lookup334: cumulus_pallet_xcm::pallet::Error */ + /** Lookup335: cumulus_pallet_xcm::pallet::Error */ CumulusPalletXcmError: "Null", - /** Lookup335: cumulus_pallet_dmp_queue::ConfigData */ + /** Lookup336: cumulus_pallet_dmp_queue::ConfigData */ CumulusPalletDmpQueueConfigData: { maxIndividual: "SpWeightsWeightV2Weight", }, - /** Lookup336: cumulus_pallet_dmp_queue::PageIndexData */ + /** Lookup337: cumulus_pallet_dmp_queue::PageIndexData */ CumulusPalletDmpQueuePageIndexData: { beginUsed: "u32", endUsed: "u32", overweightCount: "u64", }, - /** Lookup339: cumulus_pallet_dmp_queue::pallet::Error */ + /** Lookup340: cumulus_pallet_dmp_queue::pallet::Error */ CumulusPalletDmpQueueError: { _enum: ["Unknown", "OverLimit"], }, - /** Lookup340: pallet_xcm::pallet::QueryStatus */ + /** Lookup341: pallet_xcm::pallet::QueryStatus */ PalletXcmQueryStatus: { _enum: { Pending: { @@ -2595,7 +2611,7 @@ export default { }, }, }, - /** Lookup344: staging_xcm::VersionedResponse */ + /** Lookup345: staging_xcm::VersionedResponse */ StagingXcmVersionedResponse: { _enum: { __Unused0: "Null", @@ -2604,7 +2620,7 @@ export default { V3: "StagingXcmV3Response", }, }, - /** Lookup350: pallet_xcm::pallet::VersionMigrationStage */ + /** Lookup351: pallet_xcm::pallet::VersionMigrationStage */ PalletXcmVersionMigrationStage: { _enum: { MigrateSupportedVersion: "Null", @@ -2613,7 +2629,7 @@ export default { MigrateAndNotifyOldTargets: "Null", }, }, - /** Lookup352: staging_xcm::VersionedAssetId */ + /** Lookup353: staging_xcm::VersionedAssetId */ StagingXcmVersionedAssetId: { _enum: { __Unused0: "Null", @@ -2622,14 +2638,14 @@ export default { V3: "StagingXcmV3MultiassetAssetId", }, }, - /** Lookup353: pallet_xcm::pallet::RemoteLockedFungibleRecord */ + /** Lookup354: pallet_xcm::pallet::RemoteLockedFungibleRecord */ PalletXcmRemoteLockedFungibleRecord: { amount: "u128", owner: "StagingXcmVersionedMultiLocation", locker: "StagingXcmVersionedMultiLocation", consumers: "Vec<(Null,u128)>", }, - /** Lookup360: pallet_xcm::pallet::Error */ + /** Lookup361: pallet_xcm::pallet::Error */ PalletXcmError: { _enum: [ "Unreachable", @@ -2654,7 +2670,7 @@ export default { "InUse", ], }, - /** Lookup362: sp_runtime::MultiSignature */ + /** Lookup363: sp_runtime::MultiSignature */ SpRuntimeMultiSignature: { _enum: { Ed25519: "SpCoreEd25519Signature", @@ -2662,26 +2678,26 @@ export default { Ecdsa: "SpCoreEcdsaSignature", }, }, - /** Lookup363: sp_core::ed25519::Signature */ + /** Lookup364: sp_core::ed25519::Signature */ SpCoreEd25519Signature: "[u8;64]", - /** Lookup365: sp_core::sr25519::Signature */ + /** Lookup366: sp_core::sr25519::Signature */ SpCoreSr25519Signature: "[u8;64]", - /** Lookup366: sp_core::ecdsa::Signature */ + /** Lookup367: sp_core::ecdsa::Signature */ SpCoreEcdsaSignature: "[u8;65]", - /** Lookup369: frame_system::extensions::check_non_zero_sender::CheckNonZeroSender */ + /** Lookup370: frame_system::extensions::check_non_zero_sender::CheckNonZeroSender */ FrameSystemExtensionsCheckNonZeroSender: "Null", - /** Lookup370: frame_system::extensions::check_spec_version::CheckSpecVersion */ + /** Lookup371: frame_system::extensions::check_spec_version::CheckSpecVersion */ FrameSystemExtensionsCheckSpecVersion: "Null", - /** Lookup371: frame_system::extensions::check_tx_version::CheckTxVersion */ + /** Lookup372: frame_system::extensions::check_tx_version::CheckTxVersion */ FrameSystemExtensionsCheckTxVersion: "Null", - /** Lookup372: frame_system::extensions::check_genesis::CheckGenesis */ + /** Lookup373: frame_system::extensions::check_genesis::CheckGenesis */ FrameSystemExtensionsCheckGenesis: "Null", - /** Lookup375: frame_system::extensions::check_nonce::CheckNonce */ + /** Lookup376: frame_system::extensions::check_nonce::CheckNonce */ FrameSystemExtensionsCheckNonce: "Compact", - /** Lookup376: frame_system::extensions::check_weight::CheckWeight */ + /** Lookup377: frame_system::extensions::check_weight::CheckWeight */ FrameSystemExtensionsCheckWeight: "Null", - /** Lookup377: pallet_transaction_payment::ChargeTransactionPayment */ + /** Lookup378: pallet_transaction_payment::ChargeTransactionPayment */ PalletTransactionPaymentChargeTransactionPayment: "Compact", - /** Lookup378: dancebox_runtime::Runtime */ + /** Lookup379: dancebox_runtime::Runtime */ DanceboxRuntimeRuntime: "Null", }; diff --git a/typescript-api/src/dancebox/interfaces/registry.ts b/typescript-api/src/dancebox/interfaces/registry.ts index 4faca09eb..51fc1a9f6 100644 --- a/typescript-api/src/dancebox/interfaces/registry.ts +++ b/typescript-api/src/dancebox/interfaces/registry.ts @@ -79,6 +79,7 @@ import type { PalletBalancesReasons, PalletBalancesReserveData, PalletCollatorAssignmentCall, + PalletCollatorAssignmentEvent, PalletConfigurationCall, PalletConfigurationError, PalletConfigurationHostConfiguration, @@ -292,6 +293,7 @@ declare module "@polkadot/types/types/registry" { PalletBalancesReasons: PalletBalancesReasons; PalletBalancesReserveData: PalletBalancesReserveData; PalletCollatorAssignmentCall: PalletCollatorAssignmentCall; + PalletCollatorAssignmentEvent: PalletCollatorAssignmentEvent; PalletConfigurationCall: PalletConfigurationCall; PalletConfigurationError: PalletConfigurationError; PalletConfigurationHostConfiguration: PalletConfigurationHostConfiguration; diff --git a/typescript-api/src/dancebox/interfaces/types-lookup.ts b/typescript-api/src/dancebox/interfaces/types-lookup.ts index 5a0037301..6bdb78493 100644 --- a/typescript-api/src/dancebox/interfaces/types-lookup.ts +++ b/typescript-api/src/dancebox/interfaces/types-lookup.ts @@ -582,7 +582,18 @@ declare module "@polkadot/types/lookup" { | "BootNodesChanged"; } - /** @name PalletAuthorNotingEvent (47) */ + /** @name PalletCollatorAssignmentEvent (47) */ + interface PalletCollatorAssignmentEvent extends Enum { + readonly isNewPendingAssignment: boolean; + readonly asNewPendingAssignment: { + readonly randomSeed: U8aFixed; + readonly fullRotation: bool; + readonly targetSession: u32; + } & Struct; + readonly type: "NewPendingAssignment"; + } + + /** @name PalletAuthorNotingEvent (49) */ interface PalletAuthorNotingEvent extends Enum { readonly isLatestAuthorChanged: boolean; readonly asLatestAuthorChanged: { @@ -597,7 +608,7 @@ declare module "@polkadot/types/lookup" { readonly type: "LatestAuthorChanged" | "RemovedAuthorData"; } - /** @name PalletInvulnerablesEvent (48) */ + /** @name PalletInvulnerablesEvent (50) */ interface PalletInvulnerablesEvent extends Enum { readonly isNewInvulnerables: boolean; readonly asNewInvulnerables: { @@ -618,7 +629,7 @@ declare module "@polkadot/types/lookup" { readonly type: "NewInvulnerables" | "InvulnerableAdded" | "InvulnerableRemoved" | "InvalidInvulnerableSkipped"; } - /** @name PalletSessionEvent (50) */ + /** @name PalletSessionEvent (52) */ interface PalletSessionEvent extends Enum { readonly isNewSession: boolean; readonly asNewSession: { @@ -627,7 +638,7 @@ declare module "@polkadot/types/lookup" { readonly type: "NewSession"; } - /** @name PalletPooledStakingEvent (51) */ + /** @name PalletPooledStakingEvent (53) */ interface PalletPooledStakingEvent extends Enum { readonly isUpdatedCandidatePosition: boolean; readonly asUpdatedCandidatePosition: { @@ -752,14 +763,14 @@ declare module "@polkadot/types/lookup" { | "SwappedPool"; } - /** @name PalletPooledStakingTargetPool (53) */ + /** @name PalletPooledStakingTargetPool (55) */ interface PalletPooledStakingTargetPool extends Enum { readonly isAutoCompounding: boolean; readonly isManualRewards: boolean; readonly type: "AutoCompounding" | "ManualRewards"; } - /** @name CumulusPalletXcmpQueueEvent (54) */ + /** @name CumulusPalletXcmpQueueEvent (56) */ interface CumulusPalletXcmpQueueEvent extends Enum { readonly isSuccess: boolean; readonly asSuccess: { @@ -808,7 +819,7 @@ declare module "@polkadot/types/lookup" { | "OverweightServiced"; } - /** @name StagingXcmV3TraitsError (55) */ + /** @name StagingXcmV3TraitsError (57) */ interface StagingXcmV3TraitsError extends Enum { readonly isOverflow: boolean; readonly isUnimplemented: boolean; @@ -895,7 +906,7 @@ declare module "@polkadot/types/lookup" { | "ExceedsStackLimit"; } - /** @name CumulusPalletXcmEvent (56) */ + /** @name CumulusPalletXcmEvent (58) */ interface CumulusPalletXcmEvent extends Enum { readonly isInvalidFormat: boolean; readonly asInvalidFormat: U8aFixed; @@ -906,7 +917,7 @@ declare module "@polkadot/types/lookup" { readonly type: "InvalidFormat" | "UnsupportedVersion" | "ExecutedDownward"; } - /** @name StagingXcmV3TraitsOutcome (57) */ + /** @name StagingXcmV3TraitsOutcome (59) */ interface StagingXcmV3TraitsOutcome extends Enum { readonly isComplete: boolean; readonly asComplete: SpWeightsWeightV2Weight; @@ -917,7 +928,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Complete" | "Incomplete" | "Error"; } - /** @name CumulusPalletDmpQueueEvent (58) */ + /** @name CumulusPalletDmpQueueEvent (60) */ interface CumulusPalletDmpQueueEvent extends Enum { readonly isInvalidFormat: boolean; readonly asInvalidFormat: { @@ -966,7 +977,7 @@ declare module "@polkadot/types/lookup" { | "MaxMessagesExhausted"; } - /** @name PalletXcmEvent (59) */ + /** @name PalletXcmEvent (61) */ interface PalletXcmEvent extends Enum { readonly isAttempted: boolean; readonly asAttempted: { @@ -1126,13 +1137,13 @@ declare module "@polkadot/types/lookup" { | "AssetsClaimed"; } - /** @name StagingXcmV3MultiLocation (60) */ + /** @name StagingXcmV3MultiLocation (62) */ interface StagingXcmV3MultiLocation extends Struct { readonly parents: u8; readonly interior: StagingXcmV3Junctions; } - /** @name StagingXcmV3Junctions (61) */ + /** @name StagingXcmV3Junctions (63) */ interface StagingXcmV3Junctions extends Enum { readonly isHere: boolean; readonly isX1: boolean; @@ -1192,7 +1203,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Here" | "X1" | "X2" | "X3" | "X4" | "X5" | "X6" | "X7" | "X8"; } - /** @name StagingXcmV3Junction (62) */ + /** @name StagingXcmV3Junction (64) */ interface StagingXcmV3Junction extends Enum { readonly isParachain: boolean; readonly asParachain: Compact; @@ -1241,7 +1252,7 @@ declare module "@polkadot/types/lookup" { | "GlobalConsensus"; } - /** @name StagingXcmV3JunctionNetworkId (65) */ + /** @name StagingXcmV3JunctionNetworkId (67) */ interface StagingXcmV3JunctionNetworkId extends Enum { readonly isByGenesis: boolean; readonly asByGenesis: U8aFixed; @@ -1274,7 +1285,7 @@ declare module "@polkadot/types/lookup" { | "BitcoinCash"; } - /** @name StagingXcmV3JunctionBodyId (68) */ + /** @name StagingXcmV3JunctionBodyId (70) */ interface StagingXcmV3JunctionBodyId extends Enum { readonly isUnit: boolean; readonly isMoniker: boolean; @@ -1301,7 +1312,7 @@ declare module "@polkadot/types/lookup" { | "Treasury"; } - /** @name StagingXcmV3JunctionBodyPart (69) */ + /** @name StagingXcmV3JunctionBodyPart (71) */ interface StagingXcmV3JunctionBodyPart extends Enum { readonly isVoice: boolean; readonly isMembers: boolean; @@ -1326,10 +1337,10 @@ declare module "@polkadot/types/lookup" { readonly type: "Voice" | "Members" | "Fraction" | "AtLeastProportion" | "MoreThanProportion"; } - /** @name StagingXcmV3Xcm (70) */ + /** @name StagingXcmV3Xcm (72) */ interface StagingXcmV3Xcm extends Vec {} - /** @name StagingXcmV3Instruction (72) */ + /** @name StagingXcmV3Instruction (74) */ interface StagingXcmV3Instruction extends Enum { readonly isWithdrawAsset: boolean; readonly asWithdrawAsset: StagingXcmV3MultiassetMultiAssets; @@ -1559,16 +1570,16 @@ declare module "@polkadot/types/lookup" { | "UnpaidExecution"; } - /** @name StagingXcmV3MultiassetMultiAssets (73) */ + /** @name StagingXcmV3MultiassetMultiAssets (75) */ interface StagingXcmV3MultiassetMultiAssets extends Vec {} - /** @name StagingXcmV3MultiAsset (75) */ + /** @name StagingXcmV3MultiAsset (77) */ interface StagingXcmV3MultiAsset extends Struct { readonly id: StagingXcmV3MultiassetAssetId; readonly fun: StagingXcmV3MultiassetFungibility; } - /** @name StagingXcmV3MultiassetAssetId (76) */ + /** @name StagingXcmV3MultiassetAssetId (78) */ interface StagingXcmV3MultiassetAssetId extends Enum { readonly isConcrete: boolean; readonly asConcrete: StagingXcmV3MultiLocation; @@ -1577,7 +1588,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Concrete" | "Abstract"; } - /** @name StagingXcmV3MultiassetFungibility (77) */ + /** @name StagingXcmV3MultiassetFungibility (79) */ interface StagingXcmV3MultiassetFungibility extends Enum { readonly isFungible: boolean; readonly asFungible: Compact; @@ -1586,7 +1597,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Fungible" | "NonFungible"; } - /** @name StagingXcmV3MultiassetAssetInstance (78) */ + /** @name StagingXcmV3MultiassetAssetInstance (80) */ interface StagingXcmV3MultiassetAssetInstance extends Enum { readonly isUndefined: boolean; readonly isIndex: boolean; @@ -1602,7 +1613,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Undefined" | "Index" | "Array4" | "Array8" | "Array16" | "Array32"; } - /** @name StagingXcmV3Response (81) */ + /** @name StagingXcmV3Response (83) */ interface StagingXcmV3Response extends Enum { readonly isNull: boolean; readonly isAssets: boolean; @@ -1618,7 +1629,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Null" | "Assets" | "ExecutionResult" | "Version" | "PalletsInfo" | "DispatchResult"; } - /** @name StagingXcmV3PalletInfo (85) */ + /** @name StagingXcmV3PalletInfo (87) */ interface StagingXcmV3PalletInfo extends Struct { readonly index: Compact; readonly name: Bytes; @@ -1628,7 +1639,7 @@ declare module "@polkadot/types/lookup" { readonly patch: Compact; } - /** @name StagingXcmV3MaybeErrorCode (88) */ + /** @name StagingXcmV3MaybeErrorCode (90) */ interface StagingXcmV3MaybeErrorCode extends Enum { readonly isSuccess: boolean; readonly isError: boolean; @@ -1638,7 +1649,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Success" | "Error" | "TruncatedError"; } - /** @name StagingXcmV2OriginKind (91) */ + /** @name StagingXcmV2OriginKind (93) */ interface StagingXcmV2OriginKind extends Enum { readonly isNative: boolean; readonly isSovereignAccount: boolean; @@ -1647,19 +1658,19 @@ declare module "@polkadot/types/lookup" { readonly type: "Native" | "SovereignAccount" | "Superuser" | "Xcm"; } - /** @name StagingXcmDoubleEncoded (92) */ + /** @name StagingXcmDoubleEncoded (94) */ interface StagingXcmDoubleEncoded extends Struct { readonly encoded: Bytes; } - /** @name StagingXcmV3QueryResponseInfo (93) */ + /** @name StagingXcmV3QueryResponseInfo (95) */ interface StagingXcmV3QueryResponseInfo extends Struct { readonly destination: StagingXcmV3MultiLocation; readonly queryId: Compact; readonly maxWeight: SpWeightsWeightV2Weight; } - /** @name StagingXcmV3MultiassetMultiAssetFilter (94) */ + /** @name StagingXcmV3MultiassetMultiAssetFilter (96) */ interface StagingXcmV3MultiassetMultiAssetFilter extends Enum { readonly isDefinite: boolean; readonly asDefinite: StagingXcmV3MultiassetMultiAssets; @@ -1668,7 +1679,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Definite" | "Wild"; } - /** @name StagingXcmV3MultiassetWildMultiAsset (95) */ + /** @name StagingXcmV3MultiassetWildMultiAsset (97) */ interface StagingXcmV3MultiassetWildMultiAsset extends Enum { readonly isAll: boolean; readonly isAllOf: boolean; @@ -1687,14 +1698,14 @@ declare module "@polkadot/types/lookup" { readonly type: "All" | "AllOf" | "AllCounted" | "AllOfCounted"; } - /** @name StagingXcmV3MultiassetWildFungibility (96) */ + /** @name StagingXcmV3MultiassetWildFungibility (98) */ interface StagingXcmV3MultiassetWildFungibility extends Enum { readonly isFungible: boolean; readonly isNonFungible: boolean; readonly type: "Fungible" | "NonFungible"; } - /** @name StagingXcmV3WeightLimit (98) */ + /** @name StagingXcmV3WeightLimit (99) */ interface StagingXcmV3WeightLimit extends Enum { readonly isUnlimited: boolean; readonly isLimited: boolean; @@ -1702,7 +1713,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Unlimited" | "Limited"; } - /** @name StagingXcmVersionedMultiAssets (99) */ + /** @name StagingXcmVersionedMultiAssets (100) */ interface StagingXcmVersionedMultiAssets extends Enum { readonly isV2: boolean; readonly asV2: StagingXcmV2MultiassetMultiAssets; @@ -1711,16 +1722,16 @@ declare module "@polkadot/types/lookup" { readonly type: "V2" | "V3"; } - /** @name StagingXcmV2MultiassetMultiAssets (100) */ + /** @name StagingXcmV2MultiassetMultiAssets (101) */ interface StagingXcmV2MultiassetMultiAssets extends Vec {} - /** @name StagingXcmV2MultiAsset (102) */ + /** @name StagingXcmV2MultiAsset (103) */ interface StagingXcmV2MultiAsset extends Struct { readonly id: StagingXcmV2MultiassetAssetId; readonly fun: StagingXcmV2MultiassetFungibility; } - /** @name StagingXcmV2MultiassetAssetId (103) */ + /** @name StagingXcmV2MultiassetAssetId (104) */ interface StagingXcmV2MultiassetAssetId extends Enum { readonly isConcrete: boolean; readonly asConcrete: StagingXcmV2MultiLocation; @@ -1729,13 +1740,13 @@ declare module "@polkadot/types/lookup" { readonly type: "Concrete" | "Abstract"; } - /** @name StagingXcmV2MultiLocation (104) */ + /** @name StagingXcmV2MultiLocation (105) */ interface StagingXcmV2MultiLocation extends Struct { readonly parents: u8; readonly interior: StagingXcmV2MultilocationJunctions; } - /** @name StagingXcmV2MultilocationJunctions (105) */ + /** @name StagingXcmV2MultilocationJunctions (106) */ interface StagingXcmV2MultilocationJunctions extends Enum { readonly isHere: boolean; readonly isX1: boolean; @@ -1795,7 +1806,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Here" | "X1" | "X2" | "X3" | "X4" | "X5" | "X6" | "X7" | "X8"; } - /** @name StagingXcmV2Junction (106) */ + /** @name StagingXcmV2Junction (107) */ interface StagingXcmV2Junction extends Enum { readonly isParachain: boolean; readonly asParachain: Compact; @@ -1838,7 +1849,7 @@ declare module "@polkadot/types/lookup" { | "Plurality"; } - /** @name StagingXcmV2NetworkId (107) */ + /** @name StagingXcmV2NetworkId (108) */ interface StagingXcmV2NetworkId extends Enum { readonly isAny: boolean; readonly isNamed: boolean; @@ -1848,7 +1859,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Any" | "Named" | "Polkadot" | "Kusama"; } - /** @name StagingXcmV2BodyId (109) */ + /** @name StagingXcmV2BodyId (110) */ interface StagingXcmV2BodyId extends Enum { readonly isUnit: boolean; readonly isNamed: boolean; @@ -1875,7 +1886,7 @@ declare module "@polkadot/types/lookup" { | "Treasury"; } - /** @name StagingXcmV2BodyPart (110) */ + /** @name StagingXcmV2BodyPart (111) */ interface StagingXcmV2BodyPart extends Enum { readonly isVoice: boolean; readonly isMembers: boolean; @@ -1900,7 +1911,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Voice" | "Members" | "Fraction" | "AtLeastProportion" | "MoreThanProportion"; } - /** @name StagingXcmV2MultiassetFungibility (111) */ + /** @name StagingXcmV2MultiassetFungibility (112) */ interface StagingXcmV2MultiassetFungibility extends Enum { readonly isFungible: boolean; readonly asFungible: Compact; @@ -1909,7 +1920,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Fungible" | "NonFungible"; } - /** @name StagingXcmV2MultiassetAssetInstance (112) */ + /** @name StagingXcmV2MultiassetAssetInstance (113) */ interface StagingXcmV2MultiassetAssetInstance extends Enum { readonly isUndefined: boolean; readonly isIndex: boolean; @@ -1927,7 +1938,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Undefined" | "Index" | "Array4" | "Array8" | "Array16" | "Array32" | "Blob"; } - /** @name StagingXcmVersionedMultiLocation (113) */ + /** @name StagingXcmVersionedMultiLocation (114) */ interface StagingXcmVersionedMultiLocation extends Enum { readonly isV2: boolean; readonly asV2: StagingXcmV2MultiLocation; @@ -1936,7 +1947,7 @@ declare module "@polkadot/types/lookup" { readonly type: "V2" | "V3"; } - /** @name FrameSystemPhase (114) */ + /** @name FrameSystemPhase (115) */ interface FrameSystemPhase extends Enum { readonly isApplyExtrinsic: boolean; readonly asApplyExtrinsic: u32; @@ -1945,13 +1956,13 @@ declare module "@polkadot/types/lookup" { readonly type: "ApplyExtrinsic" | "Finalization" | "Initialization"; } - /** @name FrameSystemLastRuntimeUpgradeInfo (118) */ + /** @name FrameSystemLastRuntimeUpgradeInfo (119) */ interface FrameSystemLastRuntimeUpgradeInfo extends Struct { readonly specVersion: Compact; readonly specName: Text; } - /** @name FrameSystemCall (120) */ + /** @name FrameSystemCall (121) */ interface FrameSystemCall extends Enum { readonly isRemark: boolean; readonly asRemark: { @@ -1997,21 +2008,21 @@ declare module "@polkadot/types/lookup" { | "RemarkWithEvent"; } - /** @name FrameSystemLimitsBlockWeights (124) */ + /** @name FrameSystemLimitsBlockWeights (125) */ interface FrameSystemLimitsBlockWeights extends Struct { readonly baseBlock: SpWeightsWeightV2Weight; readonly maxBlock: SpWeightsWeightV2Weight; readonly perClass: FrameSupportDispatchPerDispatchClassWeightsPerClass; } - /** @name FrameSupportDispatchPerDispatchClassWeightsPerClass (125) */ + /** @name FrameSupportDispatchPerDispatchClassWeightsPerClass (126) */ interface FrameSupportDispatchPerDispatchClassWeightsPerClass extends Struct { readonly normal: FrameSystemLimitsWeightsPerClass; readonly operational: FrameSystemLimitsWeightsPerClass; readonly mandatory: FrameSystemLimitsWeightsPerClass; } - /** @name FrameSystemLimitsWeightsPerClass (126) */ + /** @name FrameSystemLimitsWeightsPerClass (127) */ interface FrameSystemLimitsWeightsPerClass extends Struct { readonly baseExtrinsic: SpWeightsWeightV2Weight; readonly maxExtrinsic: Option; @@ -2019,25 +2030,25 @@ declare module "@polkadot/types/lookup" { readonly reserved: Option; } - /** @name FrameSystemLimitsBlockLength (128) */ + /** @name FrameSystemLimitsBlockLength (129) */ interface FrameSystemLimitsBlockLength extends Struct { readonly max: FrameSupportDispatchPerDispatchClassU32; } - /** @name FrameSupportDispatchPerDispatchClassU32 (129) */ + /** @name FrameSupportDispatchPerDispatchClassU32 (130) */ interface FrameSupportDispatchPerDispatchClassU32 extends Struct { readonly normal: u32; readonly operational: u32; readonly mandatory: u32; } - /** @name SpWeightsRuntimeDbWeight (130) */ + /** @name SpWeightsRuntimeDbWeight (131) */ interface SpWeightsRuntimeDbWeight extends Struct { readonly read: u64; readonly write: u64; } - /** @name SpVersionRuntimeVersion (131) */ + /** @name SpVersionRuntimeVersion (132) */ interface SpVersionRuntimeVersion extends Struct { readonly specName: Text; readonly implName: Text; @@ -2049,7 +2060,7 @@ declare module "@polkadot/types/lookup" { readonly stateVersion: u8; } - /** @name FrameSystemError (135) */ + /** @name FrameSystemError (136) */ interface FrameSystemError extends Enum { readonly isInvalidSpecName: boolean; readonly isSpecVersionNeedsToIncrease: boolean; @@ -2066,41 +2077,41 @@ declare module "@polkadot/types/lookup" { | "CallFiltered"; } - /** @name CumulusPalletParachainSystemUnincludedSegmentAncestor (137) */ + /** @name CumulusPalletParachainSystemUnincludedSegmentAncestor (138) */ interface CumulusPalletParachainSystemUnincludedSegmentAncestor extends Struct { readonly usedBandwidth: CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth; readonly paraHeadHash: Option; readonly consumedGoAheadSignal: Option; } - /** @name CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth (138) */ + /** @name CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth (139) */ interface CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth extends Struct { readonly umpMsgCount: u32; readonly umpTotalBytes: u32; readonly hrmpOutgoing: BTreeMap; } - /** @name CumulusPalletParachainSystemUnincludedSegmentHrmpChannelUpdate (140) */ + /** @name CumulusPalletParachainSystemUnincludedSegmentHrmpChannelUpdate (141) */ interface CumulusPalletParachainSystemUnincludedSegmentHrmpChannelUpdate extends Struct { readonly msgCount: u32; readonly totalBytes: u32; } - /** @name PolkadotPrimitivesV5UpgradeGoAhead (145) */ + /** @name PolkadotPrimitivesV5UpgradeGoAhead (146) */ interface PolkadotPrimitivesV5UpgradeGoAhead extends Enum { readonly isAbort: boolean; readonly isGoAhead: boolean; readonly type: "Abort" | "GoAhead"; } - /** @name CumulusPalletParachainSystemUnincludedSegmentSegmentTracker (146) */ + /** @name CumulusPalletParachainSystemUnincludedSegmentSegmentTracker (147) */ interface CumulusPalletParachainSystemUnincludedSegmentSegmentTracker extends Struct { readonly usedBandwidth: CumulusPalletParachainSystemUnincludedSegmentUsedBandwidth; readonly hrmpWatermark: Option; readonly consumedGoAheadSignal: Option; } - /** @name PolkadotPrimitivesV5PersistedValidationData (147) */ + /** @name PolkadotPrimitivesV5PersistedValidationData (148) */ interface PolkadotPrimitivesV5PersistedValidationData extends Struct { readonly parentHead: Bytes; readonly relayParentNumber: u32; @@ -2108,18 +2119,18 @@ declare module "@polkadot/types/lookup" { readonly maxPovSize: u32; } - /** @name PolkadotPrimitivesV5UpgradeRestriction (150) */ + /** @name PolkadotPrimitivesV5UpgradeRestriction (151) */ interface PolkadotPrimitivesV5UpgradeRestriction extends Enum { readonly isPresent: boolean; readonly type: "Present"; } - /** @name SpTrieStorageProof (151) */ + /** @name SpTrieStorageProof (152) */ interface SpTrieStorageProof extends Struct { readonly trieNodes: BTreeSet; } - /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (153) */ + /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (154) */ interface CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot extends Struct { readonly dmqMqcHead: H256; readonly relayDispatchQueueRemainingCapacity: CumulusPalletParachainSystemRelayStateSnapshotRelayDispatchQueueRemainingCapacity; @@ -2127,13 +2138,13 @@ declare module "@polkadot/types/lookup" { readonly egressChannels: Vec>; } - /** @name CumulusPalletParachainSystemRelayStateSnapshotRelayDispatchQueueRemainingCapacity (154) */ + /** @name CumulusPalletParachainSystemRelayStateSnapshotRelayDispatchQueueRemainingCapacity (155) */ interface CumulusPalletParachainSystemRelayStateSnapshotRelayDispatchQueueRemainingCapacity extends Struct { readonly remainingCount: u32; readonly remainingSize: u32; } - /** @name PolkadotPrimitivesV5AbridgedHrmpChannel (157) */ + /** @name PolkadotPrimitivesV5AbridgedHrmpChannel (158) */ interface PolkadotPrimitivesV5AbridgedHrmpChannel extends Struct { readonly maxCapacity: u32; readonly maxTotalSize: u32; @@ -2143,7 +2154,7 @@ declare module "@polkadot/types/lookup" { readonly mqcHead: Option; } - /** @name PolkadotPrimitivesV5AbridgedHostConfiguration (158) */ + /** @name PolkadotPrimitivesV5AbridgedHostConfiguration (159) */ interface PolkadotPrimitivesV5AbridgedHostConfiguration extends Struct { readonly maxCodeSize: u32; readonly maxHeadDataSize: u32; @@ -2157,25 +2168,25 @@ declare module "@polkadot/types/lookup" { readonly asyncBackingParams: PolkadotPrimitivesVstagingAsyncBackingParams; } - /** @name PolkadotPrimitivesVstagingAsyncBackingParams (159) */ + /** @name PolkadotPrimitivesVstagingAsyncBackingParams (160) */ interface PolkadotPrimitivesVstagingAsyncBackingParams extends Struct { readonly maxCandidateDepth: u32; readonly allowedAncestryLen: u32; } - /** @name PolkadotCorePrimitivesOutboundHrmpMessage (165) */ + /** @name PolkadotCorePrimitivesOutboundHrmpMessage (166) */ interface PolkadotCorePrimitivesOutboundHrmpMessage extends Struct { readonly recipient: u32; readonly data: Bytes; } - /** @name CumulusPalletParachainSystemCodeUpgradeAuthorization (166) */ + /** @name CumulusPalletParachainSystemCodeUpgradeAuthorization (167) */ interface CumulusPalletParachainSystemCodeUpgradeAuthorization extends Struct { readonly codeHash: H256; readonly checkVersion: bool; } - /** @name CumulusPalletParachainSystemCall (167) */ + /** @name CumulusPalletParachainSystemCall (168) */ interface CumulusPalletParachainSystemCall extends Enum { readonly isSetValidationData: boolean; readonly asSetValidationData: { @@ -2197,7 +2208,7 @@ declare module "@polkadot/types/lookup" { readonly type: "SetValidationData" | "SudoSendUpwardMessage" | "AuthorizeUpgrade" | "EnactAuthorizedUpgrade"; } - /** @name CumulusPrimitivesParachainInherentParachainInherentData (168) */ + /** @name CumulusPrimitivesParachainInherentParachainInherentData (169) */ interface CumulusPrimitivesParachainInherentParachainInherentData extends Struct { readonly validationData: PolkadotPrimitivesV5PersistedValidationData; readonly relayChainState: SpTrieStorageProof; @@ -2205,19 +2216,19 @@ declare module "@polkadot/types/lookup" { readonly horizontalMessages: BTreeMap>; } - /** @name PolkadotCorePrimitivesInboundDownwardMessage (170) */ + /** @name PolkadotCorePrimitivesInboundDownwardMessage (171) */ interface PolkadotCorePrimitivesInboundDownwardMessage extends Struct { readonly sentAt: u32; readonly msg: Bytes; } - /** @name PolkadotCorePrimitivesInboundHrmpMessage (173) */ + /** @name PolkadotCorePrimitivesInboundHrmpMessage (174) */ interface PolkadotCorePrimitivesInboundHrmpMessage extends Struct { readonly sentAt: u32; readonly data: Bytes; } - /** @name CumulusPalletParachainSystemError (176) */ + /** @name CumulusPalletParachainSystemError (177) */ interface CumulusPalletParachainSystemError extends Enum { readonly isOverlappingUpgrades: boolean; readonly isProhibitedByPolkadot: boolean; @@ -2238,7 +2249,7 @@ declare module "@polkadot/types/lookup" { | "Unauthorized"; } - /** @name PalletTimestampCall (177) */ + /** @name PalletTimestampCall (178) */ interface PalletTimestampCall extends Enum { readonly isSet: boolean; readonly asSet: { @@ -2247,10 +2258,10 @@ declare module "@polkadot/types/lookup" { readonly type: "Set"; } - /** @name ParachainInfoCall (178) */ + /** @name ParachainInfoCall (179) */ type ParachainInfoCall = Null; - /** @name PalletSudoCall (179) */ + /** @name PalletSudoCall (180) */ interface PalletSudoCall extends Enum { readonly isSudo: boolean; readonly asSudo: { @@ -2273,7 +2284,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Sudo" | "SudoUncheckedWeight" | "SetKey" | "SudoAs"; } - /** @name PalletUtilityCall (181) */ + /** @name PalletUtilityCall (182) */ interface PalletUtilityCall extends Enum { readonly isBatch: boolean; readonly asBatch: { @@ -2305,7 +2316,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Batch" | "AsDerivative" | "BatchAll" | "DispatchAs" | "ForceBatch" | "WithWeight"; } - /** @name DanceboxRuntimeOriginCaller (183) */ + /** @name DanceboxRuntimeOriginCaller (184) */ interface DanceboxRuntimeOriginCaller extends Enum { readonly isSystem: boolean; readonly asSystem: FrameSupportDispatchRawOrigin; @@ -2317,7 +2328,7 @@ declare module "@polkadot/types/lookup" { readonly type: "System" | "Void" | "CumulusXcm" | "PolkadotXcm"; } - /** @name FrameSupportDispatchRawOrigin (184) */ + /** @name FrameSupportDispatchRawOrigin (185) */ interface FrameSupportDispatchRawOrigin extends Enum { readonly isRoot: boolean; readonly isSigned: boolean; @@ -2326,7 +2337,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Root" | "Signed" | "None"; } - /** @name CumulusPalletXcmOrigin (185) */ + /** @name CumulusPalletXcmOrigin (186) */ interface CumulusPalletXcmOrigin extends Enum { readonly isRelay: boolean; readonly isSiblingParachain: boolean; @@ -2334,7 +2345,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Relay" | "SiblingParachain"; } - /** @name PalletXcmOrigin (186) */ + /** @name PalletXcmOrigin (187) */ interface PalletXcmOrigin extends Enum { readonly isXcm: boolean; readonly asXcm: StagingXcmV3MultiLocation; @@ -2343,10 +2354,10 @@ declare module "@polkadot/types/lookup" { readonly type: "Xcm" | "Response"; } - /** @name SpCoreVoid (187) */ + /** @name SpCoreVoid (188) */ type SpCoreVoid = Null; - /** @name PalletProxyCall (188) */ + /** @name PalletProxyCall (189) */ interface PalletProxyCall extends Enum { readonly isProxy: boolean; readonly asProxy: { @@ -2416,14 +2427,14 @@ declare module "@polkadot/types/lookup" { | "ProxyAnnounced"; } - /** @name PalletMaintenanceModeCall (192) */ + /** @name PalletMaintenanceModeCall (193) */ interface PalletMaintenanceModeCall extends Enum { readonly isEnterMaintenanceMode: boolean; readonly isResumeNormalOperation: boolean; readonly type: "EnterMaintenanceMode" | "ResumeNormalOperation"; } - /** @name PalletBalancesCall (193) */ + /** @name PalletBalancesCall (194) */ interface PalletBalancesCall extends Enum { readonly isTransferAllowDeath: boolean; readonly asTransferAllowDeath: { @@ -2483,7 +2494,7 @@ declare module "@polkadot/types/lookup" { | "ForceSetBalance"; } - /** @name PalletRegistrarCall (194) */ + /** @name PalletRegistrarCall (195) */ interface PalletRegistrarCall extends Enum { readonly isRegister: boolean; readonly asRegister: { @@ -2510,7 +2521,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Register" | "Deregister" | "MarkValidForCollating" | "SetBootNodes" | "PauseContainerChain"; } - /** @name TpContainerChainGenesisDataContainerChainGenesisData (195) */ + /** @name TpContainerChainGenesisDataContainerChainGenesisData (196) */ interface TpContainerChainGenesisDataContainerChainGenesisData extends Struct { readonly storage: Vec; readonly name: Bytes; @@ -2520,26 +2531,26 @@ declare module "@polkadot/types/lookup" { readonly properties: TpContainerChainGenesisDataProperties; } - /** @name TpContainerChainGenesisDataContainerChainGenesisDataItem (197) */ + /** @name TpContainerChainGenesisDataContainerChainGenesisDataItem (198) */ interface TpContainerChainGenesisDataContainerChainGenesisDataItem extends Struct { readonly key: Bytes; readonly value: Bytes; } - /** @name TpContainerChainGenesisDataProperties (199) */ + /** @name TpContainerChainGenesisDataProperties (200) */ interface TpContainerChainGenesisDataProperties extends Struct { readonly tokenMetadata: TpContainerChainGenesisDataTokenMetadata; readonly isEthereum: bool; } - /** @name TpContainerChainGenesisDataTokenMetadata (200) */ + /** @name TpContainerChainGenesisDataTokenMetadata (201) */ interface TpContainerChainGenesisDataTokenMetadata extends Struct { readonly tokenSymbol: Bytes; readonly ss58Format: u32; readonly tokenDecimals: u32; } - /** @name PalletConfigurationCall (205) */ + /** @name PalletConfigurationCall (206) */ interface PalletConfigurationCall extends Enum { readonly isSetMaxCollators: boolean; readonly asSetMaxCollators: { @@ -2557,6 +2568,10 @@ declare module "@polkadot/types/lookup" { readonly asSetCollatorsPerContainer: { readonly new_: u32; } & Struct; + readonly isSetFullRotationPeriod: boolean; + readonly asSetFullRotationPeriod: { + readonly new_: u32; + } & Struct; readonly isSetBypassConsistencyCheck: boolean; readonly asSetBypassConsistencyCheck: { readonly new_: bool; @@ -2566,13 +2581,14 @@ declare module "@polkadot/types/lookup" { | "SetMinOrchestratorCollators" | "SetMaxOrchestratorCollators" | "SetCollatorsPerContainer" + | "SetFullRotationPeriod" | "SetBypassConsistencyCheck"; } - /** @name PalletCollatorAssignmentCall (206) */ + /** @name PalletCollatorAssignmentCall (207) */ type PalletCollatorAssignmentCall = Null; - /** @name PalletAuthorNotingCall (207) */ + /** @name PalletAuthorNotingCall (208) */ interface PalletAuthorNotingCall extends Enum { readonly isSetLatestAuthorData: boolean; readonly asSetLatestAuthorData: { @@ -2591,15 +2607,15 @@ declare module "@polkadot/types/lookup" { readonly type: "SetLatestAuthorData" | "SetAuthor" | "KillAuthorData"; } - /** @name TpAuthorNotingInherentOwnParachainInherentData (208) */ + /** @name TpAuthorNotingInherentOwnParachainInherentData (209) */ interface TpAuthorNotingInherentOwnParachainInherentData extends Struct { readonly relayStorageProof: SpTrieStorageProof; } - /** @name PalletAuthorityAssignmentCall (209) */ + /** @name PalletAuthorityAssignmentCall (210) */ type PalletAuthorityAssignmentCall = Null; - /** @name PalletInvulnerablesCall (210) */ + /** @name PalletInvulnerablesCall (211) */ interface PalletInvulnerablesCall extends Enum { readonly isSetInvulnerables: boolean; readonly asSetInvulnerables: { @@ -2616,7 +2632,7 @@ declare module "@polkadot/types/lookup" { readonly type: "SetInvulnerables" | "AddInvulnerable" | "RemoveInvulnerable"; } - /** @name PalletSessionCall (211) */ + /** @name PalletSessionCall (212) */ interface PalletSessionCall extends Enum { readonly isSetKeys: boolean; readonly asSetKeys: { @@ -2627,24 +2643,24 @@ declare module "@polkadot/types/lookup" { readonly type: "SetKeys" | "PurgeKeys"; } - /** @name DanceboxRuntimeSessionKeys (212) */ + /** @name DanceboxRuntimeSessionKeys (213) */ interface DanceboxRuntimeSessionKeys extends Struct { readonly nimbus: NimbusPrimitivesNimbusCryptoPublic; } - /** @name NimbusPrimitivesNimbusCryptoPublic (213) */ + /** @name NimbusPrimitivesNimbusCryptoPublic (214) */ interface NimbusPrimitivesNimbusCryptoPublic extends SpCoreSr25519Public {} - /** @name SpCoreSr25519Public (214) */ + /** @name SpCoreSr25519Public (215) */ interface SpCoreSr25519Public extends U8aFixed {} - /** @name PalletAuthorInherentCall (215) */ + /** @name PalletAuthorInherentCall (216) */ interface PalletAuthorInherentCall extends Enum { readonly isKickOffAuthorshipValidation: boolean; readonly type: "KickOffAuthorshipValidation"; } - /** @name PalletPooledStakingCall (216) */ + /** @name PalletPooledStakingCall (217) */ interface PalletPooledStakingCall extends Enum { readonly isRebalanceHold: boolean; readonly asRebalanceHold: { @@ -2692,7 +2708,7 @@ declare module "@polkadot/types/lookup" { | "SwapPool"; } - /** @name PalletPooledStakingAllTargetPool (217) */ + /** @name PalletPooledStakingAllTargetPool (218) */ interface PalletPooledStakingAllTargetPool extends Enum { readonly isJoining: boolean; readonly isAutoCompounding: boolean; @@ -2701,13 +2717,13 @@ declare module "@polkadot/types/lookup" { readonly type: "Joining" | "AutoCompounding" | "ManualRewards" | "Leaving"; } - /** @name PalletPooledStakingPendingOperationQuery (219) */ + /** @name PalletPooledStakingPendingOperationQuery (220) */ interface PalletPooledStakingPendingOperationQuery extends Struct { readonly delegator: AccountId32; readonly operation: PalletPooledStakingPendingOperationKey; } - /** @name PalletPooledStakingPendingOperationKey (220) */ + /** @name PalletPooledStakingPendingOperationKey (221) */ interface PalletPooledStakingPendingOperationKey extends Enum { readonly isJoiningAutoCompounding: boolean; readonly asJoiningAutoCompounding: { @@ -2727,7 +2743,7 @@ declare module "@polkadot/types/lookup" { readonly type: "JoiningAutoCompounding" | "JoiningManualRewards" | "Leaving"; } - /** @name PalletPooledStakingSharesOrStake (221) */ + /** @name PalletPooledStakingSharesOrStake (222) */ interface PalletPooledStakingSharesOrStake extends Enum { readonly isShares: boolean; readonly asShares: u128; @@ -2736,7 +2752,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Shares" | "Stake"; } - /** @name CumulusPalletXcmpQueueCall (224) */ + /** @name CumulusPalletXcmpQueueCall (225) */ interface CumulusPalletXcmpQueueCall extends Enum { readonly isServiceOverweight: boolean; readonly asServiceOverweight: { @@ -2781,7 +2797,7 @@ declare module "@polkadot/types/lookup" { | "UpdateXcmpMaxIndividualWeight"; } - /** @name CumulusPalletDmpQueueCall (225) */ + /** @name CumulusPalletDmpQueueCall (226) */ interface CumulusPalletDmpQueueCall extends Enum { readonly isServiceOverweight: boolean; readonly asServiceOverweight: { @@ -2791,7 +2807,7 @@ declare module "@polkadot/types/lookup" { readonly type: "ServiceOverweight"; } - /** @name PalletXcmCall (226) */ + /** @name PalletXcmCall (227) */ interface PalletXcmCall extends Enum { readonly isSend: boolean; readonly asSend: { @@ -2868,7 +2884,7 @@ declare module "@polkadot/types/lookup" { | "ForceSuspension"; } - /** @name StagingXcmVersionedXcm (227) */ + /** @name StagingXcmVersionedXcm (228) */ interface StagingXcmVersionedXcm extends Enum { readonly isV2: boolean; readonly asV2: StagingXcmV2Xcm; @@ -2877,10 +2893,10 @@ declare module "@polkadot/types/lookup" { readonly type: "V2" | "V3"; } - /** @name StagingXcmV2Xcm (228) */ + /** @name StagingXcmV2Xcm (229) */ interface StagingXcmV2Xcm extends Vec {} - /** @name StagingXcmV2Instruction (230) */ + /** @name StagingXcmV2Instruction (231) */ interface StagingXcmV2Instruction extends Enum { readonly isWithdrawAsset: boolean; readonly asWithdrawAsset: StagingXcmV2MultiassetMultiAssets; @@ -3028,7 +3044,7 @@ declare module "@polkadot/types/lookup" { | "UnsubscribeVersion"; } - /** @name StagingXcmV2Response (231) */ + /** @name StagingXcmV2Response (232) */ interface StagingXcmV2Response extends Enum { readonly isNull: boolean; readonly isAssets: boolean; @@ -3040,7 +3056,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Null" | "Assets" | "ExecutionResult" | "Version"; } - /** @name StagingXcmV2TraitsError (234) */ + /** @name StagingXcmV2TraitsError (235) */ interface StagingXcmV2TraitsError extends Enum { readonly isOverflow: boolean; readonly isUnimplemented: boolean; @@ -3099,7 +3115,7 @@ declare module "@polkadot/types/lookup" { | "WeightNotComputable"; } - /** @name StagingXcmV2MultiassetMultiAssetFilter (235) */ + /** @name StagingXcmV2MultiassetMultiAssetFilter (236) */ interface StagingXcmV2MultiassetMultiAssetFilter extends Enum { readonly isDefinite: boolean; readonly asDefinite: StagingXcmV2MultiassetMultiAssets; @@ -3108,7 +3124,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Definite" | "Wild"; } - /** @name StagingXcmV2MultiassetWildMultiAsset (236) */ + /** @name StagingXcmV2MultiassetWildMultiAsset (237) */ interface StagingXcmV2MultiassetWildMultiAsset extends Enum { readonly isAll: boolean; readonly isAllOf: boolean; @@ -3119,14 +3135,14 @@ declare module "@polkadot/types/lookup" { readonly type: "All" | "AllOf"; } - /** @name StagingXcmV2MultiassetWildFungibility (237) */ + /** @name StagingXcmV2MultiassetWildFungibility (238) */ interface StagingXcmV2MultiassetWildFungibility extends Enum { readonly isFungible: boolean; readonly isNonFungible: boolean; readonly type: "Fungible" | "NonFungible"; } - /** @name StagingXcmV2WeightLimit (238) */ + /** @name StagingXcmV2WeightLimit (239) */ interface StagingXcmV2WeightLimit extends Enum { readonly isUnlimited: boolean; readonly isLimited: boolean; @@ -3134,7 +3150,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Unlimited" | "Limited"; } - /** @name PalletRootTestingCall (247) */ + /** @name PalletRootTestingCall (248) */ interface PalletRootTestingCall extends Enum { readonly isFillBlock: boolean; readonly asFillBlock: { @@ -3143,33 +3159,33 @@ declare module "@polkadot/types/lookup" { readonly type: "FillBlock"; } - /** @name PalletSudoError (249) */ + /** @name PalletSudoError (250) */ interface PalletSudoError extends Enum { readonly isRequireSudo: boolean; readonly type: "RequireSudo"; } - /** @name PalletUtilityError (250) */ + /** @name PalletUtilityError (251) */ interface PalletUtilityError extends Enum { readonly isTooManyCalls: boolean; readonly type: "TooManyCalls"; } - /** @name PalletProxyProxyDefinition (253) */ + /** @name PalletProxyProxyDefinition (254) */ interface PalletProxyProxyDefinition extends Struct { readonly delegate: AccountId32; readonly proxyType: DanceboxRuntimeProxyType; readonly delay: u32; } - /** @name PalletProxyAnnouncement (257) */ + /** @name PalletProxyAnnouncement (258) */ interface PalletProxyAnnouncement extends Struct { readonly real: AccountId32; readonly callHash: H256; readonly height: u32; } - /** @name PalletProxyError (259) */ + /** @name PalletProxyError (260) */ interface PalletProxyError extends Enum { readonly isTooMany: boolean; readonly isNotFound: boolean; @@ -3190,7 +3206,7 @@ declare module "@polkadot/types/lookup" { | "NoSelfProxy"; } - /** @name PalletMigrationsError (260) */ + /** @name PalletMigrationsError (261) */ interface PalletMigrationsError extends Enum { readonly isPreimageMissing: boolean; readonly isWrongUpperBound: boolean; @@ -3199,21 +3215,21 @@ declare module "@polkadot/types/lookup" { readonly type: "PreimageMissing" | "WrongUpperBound" | "PreimageIsTooBig" | "PreimageAlreadyExists"; } - /** @name PalletMaintenanceModeError (261) */ + /** @name PalletMaintenanceModeError (262) */ interface PalletMaintenanceModeError extends Enum { readonly isAlreadyInMaintenanceMode: boolean; readonly isNotInMaintenanceMode: boolean; readonly type: "AlreadyInMaintenanceMode" | "NotInMaintenanceMode"; } - /** @name PalletBalancesBalanceLock (263) */ + /** @name PalletBalancesBalanceLock (264) */ interface PalletBalancesBalanceLock extends Struct { readonly id: U8aFixed; readonly amount: u128; readonly reasons: PalletBalancesReasons; } - /** @name PalletBalancesReasons (264) */ + /** @name PalletBalancesReasons (265) */ interface PalletBalancesReasons extends Enum { readonly isFee: boolean; readonly isMisc: boolean; @@ -3221,25 +3237,25 @@ declare module "@polkadot/types/lookup" { readonly type: "Fee" | "Misc" | "All"; } - /** @name PalletBalancesReserveData (267) */ + /** @name PalletBalancesReserveData (268) */ interface PalletBalancesReserveData extends Struct { readonly id: U8aFixed; readonly amount: u128; } - /** @name DanceboxRuntimeHoldReason (271) */ + /** @name DanceboxRuntimeHoldReason (272) */ interface DanceboxRuntimeHoldReason extends Enum { readonly isPooledStake: boolean; readonly type: "PooledStake"; } - /** @name PalletBalancesIdAmount (274) */ + /** @name PalletBalancesIdAmount (275) */ interface PalletBalancesIdAmount extends Struct { readonly id: U8aFixed; readonly amount: u128; } - /** @name PalletBalancesError (276) */ + /** @name PalletBalancesError (277) */ interface PalletBalancesError extends Enum { readonly isVestingBalance: boolean; readonly isLiquidityRestrictions: boolean; @@ -3264,20 +3280,20 @@ declare module "@polkadot/types/lookup" { | "TooManyFreezes"; } - /** @name PalletTransactionPaymentReleases (278) */ + /** @name PalletTransactionPaymentReleases (279) */ interface PalletTransactionPaymentReleases extends Enum { readonly isV1Ancient: boolean; readonly isV2: boolean; readonly type: "V1Ancient" | "V2"; } - /** @name PalletRegistrarDepositInfo (283) */ + /** @name PalletRegistrarDepositInfo (284) */ interface PalletRegistrarDepositInfo extends Struct { readonly creator: AccountId32; readonly deposit: u128; } - /** @name PalletRegistrarError (284) */ + /** @name PalletRegistrarError (285) */ interface PalletRegistrarError extends Enum { readonly isParaIdAlreadyRegistered: boolean; readonly isParaIdAlreadyPaused: boolean; @@ -3296,33 +3312,34 @@ declare module "@polkadot/types/lookup" { | "NotSufficientDeposit"; } - /** @name PalletConfigurationHostConfiguration (285) */ + /** @name PalletConfigurationHostConfiguration (286) */ interface PalletConfigurationHostConfiguration extends Struct { readonly maxCollators: u32; readonly minOrchestratorCollators: u32; readonly maxOrchestratorCollators: u32; readonly collatorsPerContainer: u32; + readonly fullRotationPeriod: u32; } - /** @name PalletConfigurationError (288) */ + /** @name PalletConfigurationError (289) */ interface PalletConfigurationError extends Enum { readonly isInvalidNewValue: boolean; readonly type: "InvalidNewValue"; } - /** @name TpCollatorAssignmentAssignedCollatorsAccountId32 (289) */ + /** @name TpCollatorAssignmentAssignedCollatorsAccountId32 (290) */ interface TpCollatorAssignmentAssignedCollatorsAccountId32 extends Struct { readonly orchestratorChain: Vec; readonly containerChains: BTreeMap>; } - /** @name PalletAuthorNotingContainerChainBlockInfo (294) */ + /** @name PalletAuthorNotingContainerChainBlockInfo (295) */ interface PalletAuthorNotingContainerChainBlockInfo extends Struct { readonly blockNumber: u32; readonly author: AccountId32; } - /** @name PalletAuthorNotingError (295) */ + /** @name PalletAuthorNotingError (296) */ interface PalletAuthorNotingError extends Enum { readonly isFailedReading: boolean; readonly isFailedDecodingHeader: boolean; @@ -3341,13 +3358,13 @@ declare module "@polkadot/types/lookup" { | "NonAuraDigest"; } - /** @name TpCollatorAssignmentAssignedCollatorsPublic (296) */ + /** @name TpCollatorAssignmentAssignedCollatorsPublic (297) */ interface TpCollatorAssignmentAssignedCollatorsPublic extends Struct { readonly orchestratorChain: Vec; readonly containerChains: BTreeMap>; } - /** @name PalletInvulnerablesError (302) */ + /** @name PalletInvulnerablesError (303) */ interface PalletInvulnerablesError extends Enum { readonly isTooManyInvulnerables: boolean; readonly isAlreadyInvulnerable: boolean; @@ -3355,10 +3372,10 @@ declare module "@polkadot/types/lookup" { readonly type: "TooManyInvulnerables" | "AlreadyInvulnerable" | "NotInvulnerable"; } - /** @name SpCoreCryptoKeyTypeId (307) */ + /** @name SpCoreCryptoKeyTypeId (308) */ interface SpCoreCryptoKeyTypeId extends U8aFixed {} - /** @name PalletSessionError (308) */ + /** @name PalletSessionError (309) */ interface PalletSessionError extends Enum { readonly isInvalidProof: boolean; readonly isNoAssociatedValidatorId: boolean; @@ -3368,7 +3385,7 @@ declare module "@polkadot/types/lookup" { readonly type: "InvalidProof" | "NoAssociatedValidatorId" | "DuplicatedKey" | "NoKeys" | "NoAccount"; } - /** @name PalletAuthorInherentError (312) */ + /** @name PalletAuthorInherentError (313) */ interface PalletAuthorInherentError extends Enum { readonly isAuthorAlreadySet: boolean; readonly isNoAccountId: boolean; @@ -3376,13 +3393,13 @@ declare module "@polkadot/types/lookup" { readonly type: "AuthorAlreadySet" | "NoAccountId" | "CannotBeAuthor"; } - /** @name PalletPooledStakingCandidateEligibleCandidate (314) */ + /** @name PalletPooledStakingCandidateEligibleCandidate (315) */ interface PalletPooledStakingCandidateEligibleCandidate extends Struct { readonly candidate: AccountId32; readonly stake: u128; } - /** @name PalletPooledStakingPoolsKey (317) */ + /** @name PalletPooledStakingPoolsKey (318) */ interface PalletPooledStakingPoolsKey extends Enum { readonly isCandidateTotalStake: boolean; readonly isJoiningShares: boolean; @@ -3452,7 +3469,7 @@ declare module "@polkadot/types/lookup" { | "LeavingSharesHeldStake"; } - /** @name PalletPooledStakingError (319) */ + /** @name PalletPooledStakingError (320) */ interface PalletPooledStakingError extends Enum { readonly isInvalidPalletSetting: boolean; readonly isDisabledFeature: boolean; @@ -3486,21 +3503,21 @@ declare module "@polkadot/types/lookup" { | "SwapResultsInZeroShares"; } - /** @name CumulusPalletXcmpQueueInboundChannelDetails (321) */ + /** @name CumulusPalletXcmpQueueInboundChannelDetails (322) */ interface CumulusPalletXcmpQueueInboundChannelDetails extends Struct { readonly sender: u32; readonly state: CumulusPalletXcmpQueueInboundState; readonly messageMetadata: Vec>; } - /** @name CumulusPalletXcmpQueueInboundState (322) */ + /** @name CumulusPalletXcmpQueueInboundState (323) */ interface CumulusPalletXcmpQueueInboundState extends Enum { readonly isOk: boolean; readonly isSuspended: boolean; readonly type: "Ok" | "Suspended"; } - /** @name PolkadotParachainPrimitivesPrimitivesXcmpMessageFormat (325) */ + /** @name PolkadotParachainPrimitivesPrimitivesXcmpMessageFormat (326) */ interface PolkadotParachainPrimitivesPrimitivesXcmpMessageFormat extends Enum { readonly isConcatenatedVersionedXcm: boolean; readonly isConcatenatedEncodedBlob: boolean; @@ -3508,7 +3525,7 @@ declare module "@polkadot/types/lookup" { readonly type: "ConcatenatedVersionedXcm" | "ConcatenatedEncodedBlob" | "Signals"; } - /** @name CumulusPalletXcmpQueueOutboundChannelDetails (328) */ + /** @name CumulusPalletXcmpQueueOutboundChannelDetails (329) */ interface CumulusPalletXcmpQueueOutboundChannelDetails extends Struct { readonly recipient: u32; readonly state: CumulusPalletXcmpQueueOutboundState; @@ -3517,14 +3534,14 @@ declare module "@polkadot/types/lookup" { readonly lastIndex: u16; } - /** @name CumulusPalletXcmpQueueOutboundState (329) */ + /** @name CumulusPalletXcmpQueueOutboundState (330) */ interface CumulusPalletXcmpQueueOutboundState extends Enum { readonly isOk: boolean; readonly isSuspended: boolean; readonly type: "Ok" | "Suspended"; } - /** @name CumulusPalletXcmpQueueQueueConfigData (331) */ + /** @name CumulusPalletXcmpQueueQueueConfigData (332) */ interface CumulusPalletXcmpQueueQueueConfigData extends Struct { readonly suspendThreshold: u32; readonly dropThreshold: u32; @@ -3534,7 +3551,7 @@ declare module "@polkadot/types/lookup" { readonly xcmpMaxIndividualWeight: SpWeightsWeightV2Weight; } - /** @name CumulusPalletXcmpQueueError (333) */ + /** @name CumulusPalletXcmpQueueError (334) */ interface CumulusPalletXcmpQueueError extends Enum { readonly isFailedToSend: boolean; readonly isBadXcmOrigin: boolean; @@ -3544,29 +3561,29 @@ declare module "@polkadot/types/lookup" { readonly type: "FailedToSend" | "BadXcmOrigin" | "BadXcm" | "BadOverweightIndex" | "WeightOverLimit"; } - /** @name CumulusPalletXcmError (334) */ + /** @name CumulusPalletXcmError (335) */ type CumulusPalletXcmError = Null; - /** @name CumulusPalletDmpQueueConfigData (335) */ + /** @name CumulusPalletDmpQueueConfigData (336) */ interface CumulusPalletDmpQueueConfigData extends Struct { readonly maxIndividual: SpWeightsWeightV2Weight; } - /** @name CumulusPalletDmpQueuePageIndexData (336) */ + /** @name CumulusPalletDmpQueuePageIndexData (337) */ interface CumulusPalletDmpQueuePageIndexData extends Struct { readonly beginUsed: u32; readonly endUsed: u32; readonly overweightCount: u64; } - /** @name CumulusPalletDmpQueueError (339) */ + /** @name CumulusPalletDmpQueueError (340) */ interface CumulusPalletDmpQueueError extends Enum { readonly isUnknown: boolean; readonly isOverLimit: boolean; readonly type: "Unknown" | "OverLimit"; } - /** @name PalletXcmQueryStatus (340) */ + /** @name PalletXcmQueryStatus (341) */ interface PalletXcmQueryStatus extends Enum { readonly isPending: boolean; readonly asPending: { @@ -3588,7 +3605,7 @@ declare module "@polkadot/types/lookup" { readonly type: "Pending" | "VersionNotifier" | "Ready"; } - /** @name StagingXcmVersionedResponse (344) */ + /** @name StagingXcmVersionedResponse (345) */ interface StagingXcmVersionedResponse extends Enum { readonly isV2: boolean; readonly asV2: StagingXcmV2Response; @@ -3597,7 +3614,7 @@ declare module "@polkadot/types/lookup" { readonly type: "V2" | "V3"; } - /** @name PalletXcmVersionMigrationStage (350) */ + /** @name PalletXcmVersionMigrationStage (351) */ interface PalletXcmVersionMigrationStage extends Enum { readonly isMigrateSupportedVersion: boolean; readonly isMigrateVersionNotifiers: boolean; @@ -3611,14 +3628,14 @@ declare module "@polkadot/types/lookup" { | "MigrateAndNotifyOldTargets"; } - /** @name StagingXcmVersionedAssetId (352) */ + /** @name StagingXcmVersionedAssetId (353) */ interface StagingXcmVersionedAssetId extends Enum { readonly isV3: boolean; readonly asV3: StagingXcmV3MultiassetAssetId; readonly type: "V3"; } - /** @name PalletXcmRemoteLockedFungibleRecord (353) */ + /** @name PalletXcmRemoteLockedFungibleRecord (354) */ interface PalletXcmRemoteLockedFungibleRecord extends Struct { readonly amount: u128; readonly owner: StagingXcmVersionedMultiLocation; @@ -3626,7 +3643,7 @@ declare module "@polkadot/types/lookup" { readonly consumers: Vec>; } - /** @name PalletXcmError (360) */ + /** @name PalletXcmError (361) */ interface PalletXcmError extends Enum { readonly isUnreachable: boolean; readonly isSendFailure: boolean; @@ -3671,7 +3688,7 @@ declare module "@polkadot/types/lookup" { | "InUse"; } - /** @name SpRuntimeMultiSignature (362) */ + /** @name SpRuntimeMultiSignature (363) */ interface SpRuntimeMultiSignature extends Enum { readonly isEd25519: boolean; readonly asEd25519: SpCoreEd25519Signature; @@ -3682,36 +3699,36 @@ declare module "@polkadot/types/lookup" { readonly type: "Ed25519" | "Sr25519" | "Ecdsa"; } - /** @name SpCoreEd25519Signature (363) */ + /** @name SpCoreEd25519Signature (364) */ interface SpCoreEd25519Signature extends U8aFixed {} - /** @name SpCoreSr25519Signature (365) */ + /** @name SpCoreSr25519Signature (366) */ interface SpCoreSr25519Signature extends U8aFixed {} - /** @name SpCoreEcdsaSignature (366) */ + /** @name SpCoreEcdsaSignature (367) */ interface SpCoreEcdsaSignature extends U8aFixed {} - /** @name FrameSystemExtensionsCheckNonZeroSender (369) */ + /** @name FrameSystemExtensionsCheckNonZeroSender (370) */ type FrameSystemExtensionsCheckNonZeroSender = Null; - /** @name FrameSystemExtensionsCheckSpecVersion (370) */ + /** @name FrameSystemExtensionsCheckSpecVersion (371) */ type FrameSystemExtensionsCheckSpecVersion = Null; - /** @name FrameSystemExtensionsCheckTxVersion (371) */ + /** @name FrameSystemExtensionsCheckTxVersion (372) */ type FrameSystemExtensionsCheckTxVersion = Null; - /** @name FrameSystemExtensionsCheckGenesis (372) */ + /** @name FrameSystemExtensionsCheckGenesis (373) */ type FrameSystemExtensionsCheckGenesis = Null; - /** @name FrameSystemExtensionsCheckNonce (375) */ + /** @name FrameSystemExtensionsCheckNonce (376) */ interface FrameSystemExtensionsCheckNonce extends Compact {} - /** @name FrameSystemExtensionsCheckWeight (376) */ + /** @name FrameSystemExtensionsCheckWeight (377) */ type FrameSystemExtensionsCheckWeight = Null; - /** @name PalletTransactionPaymentChargeTransactionPayment (377) */ + /** @name PalletTransactionPaymentChargeTransactionPayment (378) */ interface PalletTransactionPaymentChargeTransactionPayment extends Compact {} - /** @name DanceboxRuntimeRuntime (378) */ + /** @name DanceboxRuntimeRuntime (379) */ type DanceboxRuntimeRuntime = Null; } // declare module