datahaven/operator/runtime/mainnet/tests/migrations.rs
Ahmad Kaouk eb94be1e3f
feat: multi block migration pallet (#180)
## Overview

This PR integrates Substrate's `pallet-migrations` into all DataHaven
runtimes (mainnet, stagenet, testnet) to enable robust multi-block
migration capabilities. This infrastructure allows complex runtime
upgrades to be executed across multiple blocks while maintaining chain
stability and providing governance controls.

## What Changed

### Core Integration
- **Added `pallet-migrations` dependency** across all runtime
configurations
- **Integrated migration pallet** as pallet index 39 in all runtimes  
- **Created shared migration configuration** in
`datahaven-runtime-common`

### Runtime Configuration
- **Mainnet, Stagenet, and Testnet** now include identical migration
configurations
- **MaxServiceWeight** parameter set to 75% of max block weight for safe
migration execution
- **Migration cursor limits** configured (65KB max cursor, 256B max
identifier)
- **Failure handling** configured to freeze the chain on migration
failures (similar to Moonbeam's maintenance mode)

## Future Work

- [ ] Add custom failure handler (safe mode) to replace chain freeze
- [ ] Generate DataHaven-specific benchmarks for migration weights

---------

Co-authored-by: undercover-cactus <lola@moonsonglabs.com>
2025-09-24 12:27:44 +02:00

55 lines
2 KiB
Rust

#[path = "common.rs"]
mod common;
use common::*;
use datahaven_mainnet_runtime::{Runtime, RuntimeCall, RuntimeOrigin};
use frame_support::{assert_noop, assert_ok};
use pallet_migrations::{Call as MigrationsCall, HistoricCleanupSelector};
use sp_runtime::{traits::Dispatchable, DispatchError};
#[test]
fn migrations_force_calls_are_root_only() {
ExtBuilder::default().build().execute_with(|| {
let signed_origin = RuntimeOrigin::signed(account_id(ALICE));
let force_onboard =
RuntimeCall::MultiBlockMigrations(MigrationsCall::<Runtime>::force_onboard_mbms {});
assert_noop!(
force_onboard.clone().dispatch(signed_origin.clone()),
DispatchError::BadOrigin
);
assert_ok!(force_onboard.dispatch(RuntimeOrigin::root()));
let force_set_cursor =
RuntimeCall::MultiBlockMigrations(MigrationsCall::<Runtime>::force_set_cursor {
cursor: None,
});
assert_noop!(
force_set_cursor.clone().dispatch(signed_origin.clone()),
DispatchError::BadOrigin
);
assert_ok!(force_set_cursor.dispatch(RuntimeOrigin::root()));
let force_set_active =
RuntimeCall::MultiBlockMigrations(MigrationsCall::<Runtime>::force_set_active_cursor {
index: 0,
inner_cursor: None,
started_at: None,
});
assert_noop!(
force_set_active.clone().dispatch(signed_origin.clone()),
DispatchError::BadOrigin
);
assert_ok!(force_set_active.dispatch(RuntimeOrigin::root()));
let clear_historic =
RuntimeCall::MultiBlockMigrations(MigrationsCall::<Runtime>::clear_historic {
selector: HistoricCleanupSelector::Specific(Vec::new()),
});
assert_noop!(
clear_historic.clone().dispatch(signed_origin),
DispatchError::BadOrigin
);
assert_ok!(clear_historic.dispatch(RuntimeOrigin::root()));
});
}