Skip to content
paras.rs 74.7 KiB
Newer Older
				..Default::default()
			},
			..Default::default()
		};

		new_test_ext(genesis_config).execute_with(|| {
			let para_id = ParaId::from(0);
			let old_code: ValidationCode = vec![1, 2, 3].into();
			let new_code: ValidationCode = vec![4, 5, 6].into();

			// expected_at = 10 = 0 + validation_upgrade_delay = 0 + 10
			Paras::schedule_code_upgrade(para_id, new_code.clone(), 0, &Configuration::config());
			assert_eq!(<Paras as Store>::FutureCodeUpgrades::get(&para_id), Some(10));

			// no intermediate, falls back on current/past.
			assert_eq!(fetch_validation_code_at(para_id, 1, None), Some(old_code.clone()));
			assert_eq!(fetch_validation_code_at(para_id, 10, None), Some(old_code.clone()));
			assert_eq!(fetch_validation_code_at(para_id, 100, None), Some(old_code.clone()));

			// intermediate before upgrade meant to be applied, falls back on current.
			assert_eq!(fetch_validation_code_at(para_id, 9, Some(8)), Some(old_code.clone()));
			assert_eq!(fetch_validation_code_at(para_id, 10, Some(9)), Some(old_code.clone()));
			assert_eq!(fetch_validation_code_at(para_id, 11, Some(9)), Some(old_code.clone()));

			// intermediate at or after upgrade applied
			assert_eq!(fetch_validation_code_at(para_id, 11, Some(10)), Some(new_code.clone()));
			assert_eq!(fetch_validation_code_at(para_id, 100, Some(11)), Some(new_code.clone()));
			run_to_block(code_retention_period + 5, None);

			// at <= intermediate not allowed
			assert_eq!(fetch_validation_code_at(para_id, 10, Some(10)), None);
			assert_eq!(fetch_validation_code_at(para_id, 9, Some(10)), None);
	fn code_hash_at_returns_up_to_end_of_code_retention_period() {
		let code_retention_period = 10;
		let validation_upgrade_delay = 2;
		let paras = vec![(
			0u32.into(),
			ParaGenesisArgs {
				parachain: true,
				genesis_head: Default::default(),
				validation_code: vec![1, 2, 3].into(),

		let genesis_config = MockGenesisConfig {
			paras: GenesisConfig { paras, ..Default::default() },
			configuration: crate::configuration::GenesisConfig {
				config: HostConfiguration {
					code_retention_period,
					validation_upgrade_delay,
					..Default::default()
				},
				..Default::default()
			},
			..Default::default()
		};

		new_test_ext(genesis_config).execute_with(|| {
			let para_id = ParaId::from(0);
			let old_code: ValidationCode = vec![1, 2, 3].into();
			let new_code: ValidationCode = vec![4, 5, 6].into();
			Paras::schedule_code_upgrade(para_id, new_code.clone(), 0, &Configuration::config());

			run_to_block(10, None);
			Paras::note_new_head(para_id, Default::default(), 7);

			assert_eq!(Paras::past_code_meta(&para_id).upgrade_times, vec![upgrade_at(2, 10)]);
			assert_eq!(fetch_validation_code_at(para_id, 2, None), Some(old_code.clone()));
			assert_eq!(fetch_validation_code_at(para_id, 3, None), Some(old_code.clone()));
			assert_eq!(fetch_validation_code_at(para_id, 9, None), Some(old_code.clone()));
			assert_eq!(fetch_validation_code_at(para_id, 10, None), Some(new_code.clone()));
			run_to_block(10 + code_retention_period, None);
			assert_eq!(fetch_validation_code_at(para_id, 2, None), Some(old_code.clone()));
			assert_eq!(fetch_validation_code_at(para_id, 3, None), Some(old_code.clone()));
			assert_eq!(fetch_validation_code_at(para_id, 9, None), Some(old_code.clone()));
			assert_eq!(fetch_validation_code_at(para_id, 10, None), Some(new_code.clone()));
			run_to_block(10 + code_retention_period + 1, None);

			// code entry should be pruned now.

			assert_eq!(
				Paras::past_code_meta(&para_id),
				ParaPastCodeMeta { upgrade_times: Vec::new(), last_pruned: Some(10) },
			assert_eq!(fetch_validation_code_at(para_id, 2, None), None); // pruned :(
			assert_eq!(fetch_validation_code_at(para_id, 9, None), None);
			assert_eq!(fetch_validation_code_at(para_id, 10, None), Some(new_code.clone()));
			assert_eq!(fetch_validation_code_at(para_id, 11, None), Some(new_code.clone()));

	#[test]
	fn code_ref_is_cleaned_correctly() {
		new_test_ext(Default::default()).execute_with(|| {
			let code: ValidationCode = vec![1, 2, 3].into();
			Paras::increase_code_ref(&code.hash(), &code);
			Paras::increase_code_ref(&code.hash(), &code);

			assert!(<Paras as Store>::CodeByHash::contains_key(code.hash()));
			assert_eq!(<Paras as Store>::CodeByHashRefs::get(code.hash()), 2);

			Paras::decrease_code_ref(&code.hash());

			assert!(<Paras as Store>::CodeByHash::contains_key(code.hash()));
			assert_eq!(<Paras as Store>::CodeByHashRefs::get(code.hash()), 1);

			Paras::decrease_code_ref(&code.hash());

			assert!(!<Paras as Store>::CodeByHash::contains_key(code.hash()));
			assert!(!<Paras as Store>::CodeByHashRefs::contains_key(code.hash()));

	#[test]
	fn verify_upgrade_go_ahead_signal_is_externally_accessible() {
		use primitives::v1::well_known_keys;

		let a = ParaId::from(2020);

		new_test_ext(Default::default()).execute_with(|| {
			assert!(sp_io::storage::get(&well_known_keys::upgrade_go_ahead_signal(a)).is_none());
			<Paras as Store>::UpgradeGoAheadSignal::insert(&a, UpgradeGoAhead::GoAhead);
			assert_eq!(
				sp_io::storage::get(&well_known_keys::upgrade_go_ahead_signal(a)).unwrap(),
				vec![1u8],
			);
		});
	}

	#[test]
	fn verify_upgrade_restriction_signal_is_externally_accessible() {
		use primitives::v1::well_known_keys;

		let a = ParaId::from(2020);

		new_test_ext(Default::default()).execute_with(|| {
			assert!(sp_io::storage::get(&well_known_keys::upgrade_restriction_signal(a)).is_none());
			<Paras as Store>::UpgradeRestrictionSignal::insert(&a, UpgradeRestriction::Present);
			assert_eq!(
				sp_io::storage::get(&well_known_keys::upgrade_restriction_signal(a)).unwrap(),
				vec![0],
			);
		});
	}