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 {
18
    crate as dancebox_runtime,
19
    crate::{
20
        prod_or_fast, AccountId, DataPreserversConfig, MaintenanceModeConfig, MigrationsConfig,
21
        PolkadotXcmConfig, RegistrarConfig, ServicesPaymentConfig, SudoConfig,
22
    },
23
    alloc::{string::String, vec, vec::Vec},
24
    cumulus_primitives_core::ParaId,
25
    dp_container_chain_genesis_data::{
26
        json::container_chain_genesis_data_from_str, ContainerChainGenesisData,
27
    },
28
    frame_support::BoundedVec,
29
    nimbus_primitives::NimbusId,
30
    pallet_configuration::HostConfiguration,
31
    sp_core::crypto::get_public_from_string_or_panic,
32
    sp_core::sr25519,
33
    sp_keyring::Sr25519Keyring,
34
    sp_runtime::{traits::AccountIdConversion, Perbill},
35
};
36

            
37
90
pub fn local(
38
90
    para_id: ParaId,
39
90
    container_chains_spec_contents: Vec<String>,
40
90
    mock_container_chains: Vec<ParaId>,
41
90
    invulnerables: Vec<String>,
42
90
) -> serde_json::Value {
43
90
    testnet_genesis(
44
        // initial collators.
45
90
        invulnerables_from_seeds(invulnerables.iter()),
46
90
        account_ids(&[
47
90
            "Alice",
48
90
            "Bob",
49
90
            "Charlie",
50
90
            "Dave",
51
90
            "Eve",
52
90
            "Ferdie",
53
90
            "Alice//stash",
54
90
            "Bob//stash",
55
90
            "Charlie//stash",
56
90
            "Dave//stash",
57
90
            "Eve//stash",
58
90
            "Ferdie//stash",
59
90
        ]),
60
90
        para_id,
61
90
        Sr25519Keyring::Alice.to_account_id(),
62
90
        &container_chains_spec_contents,
63
90
        &mock_container_chains,
64
        pallet_configuration::GenesisConfig {
65
            config: HostConfiguration {
66
                max_collators: 100u32,
67
                min_orchestrator_collators: 2u32,
68
                max_orchestrator_collators: 5u32,
69
                collators_per_container: 2u32,
70
90
                full_rotation_period: prod_or_fast!(24u32, 5u32),
71
                collators_per_parathread: 1,
72
                parathreads_per_collator: 1,
73
90
                target_container_chain_fullness: Perbill::from_percent(80),
74
90
                max_parachain_cores_percentage: None,
75
90
                full_rotation_mode: Default::default(),
76
            },
77
90
            ..Default::default()
78
        },
79
    )
80
90
}
81

            
82
6
pub fn development(
83
6
    para_id: ParaId,
84
6
    container_chains_spec_contents: Vec<String>,
85
6
    mock_container_chains: Vec<ParaId>,
86
6
    invulnerables: Vec<String>,
87
6
) -> serde_json::Value {
88
6
    testnet_genesis(
89
        // initial collators.
90
6
        invulnerables_from_seeds(invulnerables.iter()),
91
6
        account_ids(&[
92
6
            "Alice",
93
6
            "Bob",
94
6
            "Charlie",
95
6
            "Dave",
96
6
            "Eve",
97
6
            "Ferdie",
98
6
            "Alice//stash",
99
6
            "Bob//stash",
100
6
            "Charlie//stash",
101
6
            "Dave//stash",
102
6
            "Eve//stash",
103
6
            "Ferdie//stash",
104
6
        ]),
105
6
        para_id,
106
6
        Sr25519Keyring::Alice.to_account_id(),
107
6
        &container_chains_spec_contents,
108
6
        &mock_container_chains,
109
        pallet_configuration::GenesisConfig {
110
            config: HostConfiguration {
111
                max_collators: 100u32,
112
                min_orchestrator_collators: 1u32,
113
                max_orchestrator_collators: 1u32,
114
                collators_per_container: 2u32,
115
6
                full_rotation_period: prod_or_fast!(24u32, 5u32),
116
                collators_per_parathread: 1,
117
                parathreads_per_collator: 1,
118
6
                target_container_chain_fullness: Perbill::from_percent(80),
119
6
                max_parachain_cores_percentage: None,
120
6
                full_rotation_mode: Default::default(),
121
            },
122
6
            ..Default::default()
123
        },
124
    )
125
6
}
126

            
127
96
fn testnet_genesis(
128
96
    invulnerables: Vec<(AccountId, NimbusId)>,
129
96
    endowed_accounts: Vec<AccountId>,
130
96
    id: ParaId,
131
96
    root_key: AccountId,
132
96
    container_chains_spec_contents: &[String],
133
96
    mock_container_chains: &[ParaId],
134
96
    configuration: pallet_configuration::GenesisConfig<dancebox_runtime::Runtime>,
135
96
) -> serde_json::Value {
136
96
    let para_ids: Vec<_> = container_chains_spec_contents
137
96
        .iter()
138
96
        .map(|content_str| {
139
            container_chain_genesis_data_from_str(content_str).unwrap_or_else(|e| {
140
                panic!(
141
                    "Failed to build genesis data for container chain {:?}: {}",
142
                    content_str, e
143
                )
144
            })
145
        })
146
96
        .chain(
147
96
            mock_container_chains
148
96
                .iter()
149
192
                .map(|x| (*x, mock_container_chain_genesis_data(*x), vec![])),
150
        )
151
96
        .collect();
152
    // Assign 1000 block credits to all container chains registered in genesis
153
    // Assign 100 collator assignment credits to all container chains registered in genesis
154
96
    let para_id_credits: Vec<_> = para_ids
155
96
        .iter()
156
192
        .map(|(para_id, _genesis_data, _boot_nodes)| (*para_id, 1000, 100).into())
157
96
        .collect();
158
96
    let data_preservers_bootnodes: Vec<_> = para_ids
159
96
        .iter()
160
192
        .flat_map(|(para_id, _genesis_data, bootnodes)| {
161
192
            bootnodes.clone().into_iter().map(|bootnode| {
162
                (
163
                    *para_id,
164
                    AccountId::from([0u8; 32]),
165
                    bootnode,
166
                    tp_data_preservers_common::ProviderRequest::Free,
167
                    tp_data_preservers_common::AssignmentWitness::Free,
168
                )
169
            })
170
192
        })
171
96
        .collect();
172
96
    let para_ids: Vec<_> = para_ids
173
96
        .into_iter()
174
192
        .map(|(para_id, genesis_data, _boot_nodes)| (para_id, genesis_data, None))
175
96
        .collect();
176

            
177
96
    let accounts_with_ed = [
178
96
        dancebox_runtime::StakingAccount::get(),
179
96
        dancebox_runtime::ParachainBondAccount::get(),
180
96
        dancebox_runtime::PendingRewardsAccount::get(),
181
96
        dancebox_runtime::TreasuryId::get().into_account_truncating(),
182
96
    ];
183
96
    let g = dancebox_runtime::RuntimeGenesisConfig {
184
96
        system: Default::default(),
185
        balances: dancebox_runtime::BalancesConfig {
186
96
            balances: endowed_accounts
187
96
                .iter()
188
96
                .cloned()
189
1152
                .map(|k| (k, 1 << 60))
190
96
                .chain(
191
96
                    accounts_with_ed
192
96
                        .iter()
193
96
                        .cloned()
194
384
                        .map(|k| (k, dancebox_runtime::EXISTENTIAL_DEPOSIT)),
195
                )
196
96
                .collect(),
197
96
            ..Default::default()
198
        },
199
96
        parachain_info: dancebox_runtime::ParachainInfoConfig {
200
96
            parachain_id: id,
201
96
            ..Default::default()
202
96
        },
203
        invulnerables: dancebox_runtime::InvulnerablesConfig {
204
96
            invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(),
205
        },
206
        session: dancebox_runtime::SessionConfig {
207
96
            keys: invulnerables
208
96
                .into_iter()
209
384
                .map(|(acc, aura)| {
210
384
                    (
211
384
                        acc.clone(),                 // account id
212
384
                        acc,                         // validator id
213
384
                        template_session_keys(aura), // session keys
214
384
                    )
215
384
                })
216
96
                .collect(),
217
96
            ..Default::default()
218
        },
219
96
        parachain_system: Default::default(),
220
96
        configuration,
221
96
        registrar: RegistrarConfig {
222
96
            para_ids,
223
96
            phantom: Default::default(),
224
96
        },
225
96
        services_payment: ServicesPaymentConfig { para_id_credits },
226
96
        sudo: SudoConfig {
227
96
            key: Some(root_key),
228
96
        },
229
96
        migrations: MigrationsConfig {
230
96
            ..Default::default()
231
96
        },
232
96
        maintenance_mode: MaintenanceModeConfig {
233
96
            start_in_maintenance_mode: false,
234
96
            ..Default::default()
235
96
        },
236
        // This should initialize it to whatever we have set in the pallet
237
96
        polkadot_xcm: PolkadotXcmConfig::default(),
238
96
        transaction_payment: Default::default(),
239
96
        tx_pause: Default::default(),
240
96
        treasury: Default::default(),
241
96
        data_preservers: DataPreserversConfig {
242
96
            bootnodes: data_preservers_bootnodes,
243
96
            ..Default::default()
244
96
        },
245
    };
246

            
247
96
    serde_json::to_value(g).unwrap()
248
96
}
249

            
250
// TODO: move to primitives and remove duplication from flashbox/dancebox
251
/// Helper function to turn a list of names into a list of `(AccountId, NimbusId)`
252
96
pub fn invulnerables_from_seeds<S: AsRef<str>, I: Iterator<Item = S>>(
253
96
    names: I,
254
96
) -> Vec<(AccountId, NimbusId)> {
255
96
    names
256
384
        .map(|name| {
257
384
            let name = name.as_ref();
258
384
            (
259
384
                get_public_from_string_or_panic::<sr25519::Public>(name).into(),
260
384
                get_collator_keys_from_seed(name),
261
384
            )
262
384
        })
263
96
        .collect()
264
96
}
265

            
266
/// Generate collator keys from seed.
267
///
268
/// This function's return type must always match the session keys of the chain in tuple format.
269
384
pub fn get_collator_keys_from_seed(seed: &str) -> NimbusId {
270
384
    get_public_from_string_or_panic::<NimbusId>(seed)
271
384
}
272

            
273
/// Helper function to turn a list of names into a list of `AccountId`
274
96
pub fn account_ids(names: &[&str]) -> Vec<AccountId> {
275
96
    names
276
96
        .iter()
277
1152
        .map(|name| get_public_from_string_or_panic::<sr25519::Public>(name).into())
278
96
        .collect()
279
96
}
280

            
281
/// Generate the session keys from individual elements.
282
///
283
/// The input must be a tuple of individual keys (a single arg for now since we have just one key).
284
384
pub fn template_session_keys(keys: NimbusId) -> dancebox_runtime::SessionKeys {
285
384
    dancebox_runtime::SessionKeys { nimbus: keys }
286
384
}
287

            
288
192
fn mock_container_chain_genesis_data(para_id: ParaId) -> ContainerChainGenesisData {
289
192
    let mut name_buf = alloc::string::String::new();
290
192
    let mut id_buf = alloc::string::String::new();
291

            
292
    use core::fmt::Write;
293
192
    write!(name_buf, "Container Chain {}", u32::from(para_id)).unwrap();
294
192
    write!(id_buf, "container-chain-{}", u32::from(para_id)).unwrap();
295

            
296
192
    ContainerChainGenesisData {
297
192
        storage: BoundedVec::try_from(alloc::vec![]).unwrap(),
298
192
        name: BoundedVec::try_from(name_buf.into_bytes()).unwrap(),
299
192
        id: BoundedVec::try_from(id_buf.into_bytes()).unwrap(),
300
192
        fork_id: None,
301
192
        extensions: BoundedVec::try_from(alloc::vec![]).unwrap(),
302
192
        properties: Default::default(),
303
192
    }
304
192
}