diff --git a/runtime/parachains/src/paras/mod.rs b/runtime/parachains/src/paras/mod.rs index 8c8eabf9d2e9..554a393d6057 100644 --- a/runtime/parachains/src/paras/mod.rs +++ b/runtime/parachains/src/paras/mod.rs @@ -1262,7 +1262,7 @@ impl Pallet { // Persist parachains into the storage explicitly. drop(parachains); - return outgoing + outgoing } // note replacement of the code of para with given `id`, which occured in the @@ -1389,9 +1389,15 @@ impl Pallet { /// See `process_scheduled_upgrade_changes` for more details. fn process_scheduled_upgrade_cooldowns(now: T::BlockNumber) { UpgradeCooldowns::::mutate(|upgrade_cooldowns: &mut Vec<(ParaId, T::BlockNumber)>| { - for &(para, _) in upgrade_cooldowns.iter().take_while(|&(_, at)| at <= &now) { - UpgradeRestrictionSignal::::remove(¶); - } + // Remove all expired signals and also prune the cooldowns. + upgrade_cooldowns.retain(|(para, at)| { + if at <= &now { + UpgradeRestrictionSignal::::remove(¶); + false + } else { + true + } + }); }); } diff --git a/runtime/parachains/src/paras/tests.rs b/runtime/parachains/src/paras/tests.rs index 1acd88094124..7e3e80d10265 100644 --- a/runtime/parachains/src/paras/tests.rs +++ b/runtime/parachains/src/paras/tests.rs @@ -441,7 +441,7 @@ fn code_upgrade_applied_after_delay() { run_to_block(2, Some(vec![1])); assert_eq!(Paras::current_code(¶_id), Some(original_code.clone())); - let expected_at = { + let (expected_at, next_possible_upgrade_at) = { // this parablock is in the context of block 1. let expected_at = 1 + validation_upgrade_delay; let next_possible_upgrade_at = 1 + validation_upgrade_cooldown; @@ -460,7 +460,7 @@ fn code_upgrade_applied_after_delay() { check_code_is_stored(&original_code); check_code_is_stored(&new_code); - expected_at + (expected_at, next_possible_upgrade_at) }; run_to_block(expected_at, None); @@ -495,9 +495,21 @@ fn code_upgrade_applied_after_delay() { assert!(FutureCodeHash::::get(¶_id).is_none()); assert!(UpgradeGoAheadSignal::::get(¶_id).is_none()); assert_eq!(Paras::current_code(¶_id), Some(new_code.clone())); + assert_eq!( + UpgradeRestrictionSignal::::get(¶_id), + Some(UpgradeRestriction::Present), + ); + assert_eq!(UpgradeCooldowns::::get(), vec![(para_id, next_possible_upgrade_at)]); check_code_is_stored(&original_code); check_code_is_stored(&new_code); } + + run_to_block(next_possible_upgrade_at + 1, None); + + { + assert!(UpgradeRestrictionSignal::::get(¶_id).is_none()); + assert!(UpgradeCooldowns::::get().is_empty()); + } }); } @@ -568,7 +580,7 @@ fn code_upgrade_applied_after_delay_even_when_late() { // the upgrade. { // The signal should be set to go-ahead until the new head is actually processed. - assert_eq!(UpgradeGoAheadSignal::::get(¶_id), Some(UpgradeGoAhead::GoAhead),); + assert_eq!(UpgradeGoAheadSignal::::get(¶_id), Some(UpgradeGoAhead::GoAhead)); Paras::note_new_head(para_id, Default::default(), expected_at + 4);