1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>
16

            
17
use crate::tests::common::ExtBuilder;
18
use crate::{
19
    BeefyMmrLeaf, CollatorConfiguration, ExternalValidators, PalletInfo, Runtime, Session,
20
};
21
use beefy_primitives::mmr::BeefyAuthoritySet;
22
use frame_support::migration::clear_storage_prefix;
23
use frame_support::storage::unhashed;
24
use frame_support::traits::PalletInfo as _;
25
use pallet_migrations::Migration;
26
use parity_scale_codec::Encode;
27
use sp_arithmetic::Perbill;
28
use tanssi_runtime_common::migrations::{
29
    BondedErasTimestampMigration, ExternalValidatorsInitialMigration, HostConfigurationV3,
30
    MigrateConfigurationAddFullRotationMode, MigrateMMRLeafPallet,
31
};
32
use xcm::v3::Weight;
33

            
34
#[test]
35
1
fn test_migration_mmr_leaf_pallet_renaming() {
36
1
    ExtBuilder::default().build().execute_with(|| {
37
1
        let migrate_mmr_leaf_pallet = MigrateMMRLeafPallet::<Runtime>(Default::default());
38
1
        let old_pallet_name = MigrateMMRLeafPallet::<Runtime>::old_pallet_name();
39
1
        let old_storage_1 = frame_support::storage::storage_prefix(
40
1
            old_pallet_name.as_bytes(),
41
1
            b"example_storage_1",
42
1
        );
43
1
        let new_storage_1 = frame_support::storage::storage_prefix(
44
1
            PalletInfo::name::<BeefyMmrLeaf>()
45
1
                .expect("BeefyMMRLeaf pallet must be part of the runtime")
46
1
                .as_bytes(),
47
1
            b"example_storage_1",
48
1
        );
49
1
        unhashed::put(&old_storage_1, &1u64);
50
1

            
51
1
        let beefy_authority_set: BeefyAuthoritySet<()> = BeefyAuthoritySet {
52
1
            len: 5,
53
1
            ..Default::default()
54
1
        };
55
1
        let old_storage_2 = frame_support::storage::storage_prefix(
56
1
            old_pallet_name.as_bytes(),
57
1
            b"example_storage_2",
58
1
        );
59
1
        let new_storage_2 = frame_support::storage::storage_prefix(
60
1
            PalletInfo::name::<BeefyMmrLeaf>()
61
1
                .expect("BeefyMMRLeaf pallet must be part of the runtime")
62
1
                .as_bytes(),
63
1
            b"example_storage_2",
64
1
        );
65
1
        unhashed::put(&old_storage_2, &beefy_authority_set);
66
1

            
67
1
        let used_weight = migrate_mmr_leaf_pallet.migrate(Weight::MAX);
68
1
        assert_eq!(used_weight, Weight::MAX);
69

            
70
1
        assert_eq!(unhashed::get::<u64>(&old_storage_1), None);
71
1
        assert_eq!(unhashed::get::<BeefyAuthoritySet<()>>(&old_storage_2), None);
72

            
73
1
        assert_eq!(unhashed::get::<u64>(&new_storage_1), Some(1u64));
74
1
        assert_eq!(
75
1
            unhashed::get::<BeefyAuthoritySet<()>>(&new_storage_2),
76
1
            Some(BeefyAuthoritySet {
77
1
                len: 5,
78
1
                ..Default::default()
79
1
            })
80
1
        );
81
1
    });
82
1
}
83

            
84
#[test]
85
1
fn test_migration_external_validators_pallet() {
86
1
    ExtBuilder::default().build().execute_with(|| {
87
1
        let migrate_external_validators =
88
1
            ExternalValidatorsInitialMigration::<Runtime>(Default::default());
89
1
        let old_pallet_name = b"ValidatorManager";
90
1

            
91
1
        // Kill storage of ExternalValidators pallet, because this migration will initialize this pallet
92
1
        let _ = clear_storage_prefix(b"ExternalValidators", b"", b"", None, None);
93
1

            
94
1
        // Simulate adding data to the old pallet storage
95
1
        // The value is not used for anything, we only care that it is removed by the migration.
96
1
        let old_storage_key =
97
1
            frame_support::storage::storage_prefix(old_pallet_name, b"ValidatorsToAdd");
98
1
        let expected_validators: Vec<u64> = vec![5, 6];
99
1
        unhashed::put(&old_storage_key, &expected_validators);
100
1

            
101
1
        // Run migration
102
1
        let _used_weight = migrate_external_validators.migrate(Weight::MAX);
103
1

            
104
1
        // Assert that ValidatorManager pallet prefix is empty after migration
105
1
        let old_pallet_key = frame_support::storage::storage_prefix(old_pallet_name, b"");
106
1
        let old_storage_exists = unhashed::contains_prefixed_key(&old_pallet_key);
107
1
        assert!(
108
1
            !old_storage_exists,
109
            "Old pallet storage should be cleared after migration"
110
        );
111

            
112
        // Assert that ExternalValidators has the validators from ValidatorManager
113
1
        let migrated_validators = ExternalValidators::validators();
114
1
        let empty = vec![];
115
1
        assert_ne!(
116
            migrated_validators, empty,
117
            "ExternalValidators should not be empty after migration"
118
        );
119

            
120
        // ExternalValidators should be equal to validators from Session::queued_keys
121
2
        let expected_validators: Vec<_> = Session::queued_keys().into_iter().map(|x| x.0).collect();
122
1
        assert_eq!(migrated_validators, expected_validators);
123
1
    });
124
1
}
125

            
126
#[test]
127
1
fn test_migration_config_add_full_rotation_mode() {
128
1
    ExtBuilder::default().build().execute_with(|| {
129
        const CONFIGURATION_ACTIVE_CONFIG_KEY: &[u8] =
130
            &hex_literal::hex!("86e86c1d728ee2b18f76dd0e04d96cdbb4b49d95320d9021994c850f25b8e385");
131
        const CONFIGURATION_PENDING_CONFIGS_KEY: &[u8] =
132
            &hex_literal::hex!("86e86c1d728ee2b18f76dd0e04d96cdb53b4123b2e186e07fb7bad5dda5f55c0");
133

            
134
        // Modify active config
135
1
        frame_support::storage::unhashed::put_raw(
136
1
            CONFIGURATION_ACTIVE_CONFIG_KEY,
137
1
            &HostConfigurationV3 {
138
1
                max_collators: 5,
139
1
                min_orchestrator_collators: 2,
140
1
                max_orchestrator_collators: 1,
141
1
                collators_per_container: 3,
142
1
                full_rotation_period: 4,
143
1
                collators_per_parathread: 2,
144
1
                parathreads_per_collator: 1,
145
1
                target_container_chain_fullness: Perbill::from_percent(45),
146
1
                max_parachain_cores_percentage: Some(Perbill::from_percent(75)),
147
1
            }
148
1
            .encode(),
149
1
        );
150
1
        // Modify pending configs
151
1
        frame_support::storage::unhashed::put_raw(
152
1
            CONFIGURATION_PENDING_CONFIGS_KEY,
153
1
            &vec![
154
1
                (
155
1
                    1234u32,
156
1
                    HostConfigurationV3 {
157
1
                        max_collators: 1,
158
1
                        min_orchestrator_collators: 4,
159
1
                        max_orchestrator_collators: 45,
160
1
                        collators_per_container: 5,
161
1
                        full_rotation_period: 1,
162
1
                        collators_per_parathread: 1,
163
1
                        parathreads_per_collator: 1,
164
1
                        target_container_chain_fullness: Perbill::from_percent(65),
165
1
                        max_parachain_cores_percentage: Some(Perbill::from_percent(75)),
166
1
                    },
167
1
                ),
168
1
                (
169
1
                    5678u32,
170
1
                    HostConfigurationV3 {
171
1
                        max_collators: 1,
172
1
                        min_orchestrator_collators: 4,
173
1
                        max_orchestrator_collators: 45,
174
1
                        collators_per_container: 5,
175
1
                        full_rotation_period: 1,
176
1
                        collators_per_parathread: 1,
177
1
                        parathreads_per_collator: 1,
178
1
                        target_container_chain_fullness: Perbill::from_percent(65),
179
1
                        max_parachain_cores_percentage: Some(Perbill::from_percent(75)),
180
1
                    },
181
1
                ),
182
1
            ]
183
1
            .encode(),
184
1
        );
185
1

            
186
1
        let migration = MigrateConfigurationAddFullRotationMode::<Runtime>(Default::default());
187
1
        migration.migrate(Default::default());
188
1

            
189
1
        let expected_active = pallet_configuration::HostConfiguration {
190
1
            max_collators: 5,
191
1
            min_orchestrator_collators: 2,
192
1
            max_orchestrator_collators: 1,
193
1
            collators_per_container: 3,
194
1
            full_rotation_period: 4,
195
1
            collators_per_parathread: 2,
196
1
            parathreads_per_collator: 1,
197
1
            target_container_chain_fullness: Perbill::from_percent(45),
198
1
            max_parachain_cores_percentage: Some(Perbill::from_percent(75)),
199
1
            ..Default::default()
200
1
        };
201
1
        assert_eq!(CollatorConfiguration::config(), expected_active);
202

            
203
1
        let expected_pending = vec![
204
1
            (
205
1
                1234u32,
206
1
                pallet_configuration::HostConfiguration {
207
1
                    max_collators: 1,
208
1
                    min_orchestrator_collators: 4,
209
1
                    max_orchestrator_collators: 45,
210
1
                    collators_per_container: 5,
211
1
                    full_rotation_period: 1,
212
1
                    collators_per_parathread: 1,
213
1
                    parathreads_per_collator: 1,
214
1
                    target_container_chain_fullness: Perbill::from_percent(65),
215
1
                    max_parachain_cores_percentage: Some(Perbill::from_percent(75)),
216
1
                    ..Default::default()
217
1
                },
218
1
            ),
219
1
            (
220
1
                5678u32,
221
1
                pallet_configuration::HostConfiguration {
222
1
                    max_collators: 1,
223
1
                    min_orchestrator_collators: 4,
224
1
                    max_orchestrator_collators: 45,
225
1
                    collators_per_container: 5,
226
1
                    full_rotation_period: 1,
227
1
                    collators_per_parathread: 1,
228
1
                    parathreads_per_collator: 1,
229
1
                    target_container_chain_fullness: Perbill::from_percent(65),
230
1
                    max_parachain_cores_percentage: Some(Perbill::from_percent(75)),
231
1
                    ..Default::default()
232
1
                },
233
1
            ),
234
1
        ];
235
1
        assert_eq!(CollatorConfiguration::pending_configs(), expected_pending);
236
1
    });
237
1
}
238

            
239
#[test]
240
1
fn test_add_timestamp_to_bonded_eras_migration() {
241
1
    ExtBuilder::default().build().execute_with(|| {
242
1
        let bonded_eras_key =
243
1
            pallet_external_validator_slashes::BondedEras::<Runtime>::hashed_key();
244
1

            
245
1
        let previous_value: Vec<(sp_staking::EraIndex, sp_staking::SessionIndex)> =
246
1
            vec![(1, 1), (2, 2), (3, 3)];
247
1

            
248
1
        // Modify storage to pevious value
249
1
        frame_support::storage::unhashed::put_raw(&bonded_eras_key, &previous_value.encode());
250
1

            
251
1
        let migration = BondedErasTimestampMigration::<Runtime>(Default::default());
252
1
        migration.migrate(Default::default());
253
1

            
254
1
        let expected_bonded_eras_after: Vec<(sp_staking::EraIndex, sp_staking::SessionIndex, u64)> =
255
1
            previous_value
256
1
                .iter()
257
3
                .map(|(era, session)| (*era, *session, 0u64))
258
1
                .collect();
259
1
        assert_eq!(
260
1
            pallet_external_validator_slashes::BondedEras::<Runtime>::get(),
261
1
            expected_bonded_eras_after
262
1
        );
263
1
    });
264
1
}