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

            
127
102
fn testnet_genesis(
128
102
    invulnerables: Vec<(AccountId, NimbusId)>,
129
102
    endowed_accounts: Vec<AccountId>,
130
102
    id: ParaId,
131
102
    root_key: AccountId,
132
102
    container_chains_spec_contents: &[String],
133
102
    mock_container_chains: &[ParaId],
134
102
    configuration: pallet_configuration::GenesisConfig<dancebox_runtime::Runtime>,
135
102
) -> serde_json::Value {
136
102
    let para_ids: Vec<_> = container_chains_spec_contents
137
102
        .iter()
138
102
        .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
102
        .chain(
147
102
            mock_container_chains
148
102
                .iter()
149
204
                .map(|x| (*x, mock_container_chain_genesis_data(*x), vec![])),
150
        )
151
102
        .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
102
    let para_id_credits: Vec<_> = para_ids
155
102
        .iter()
156
204
        .map(|(para_id, _genesis_data, _boot_nodes)| (*para_id, 1000, 100).into())
157
102
        .collect();
158
102
    let data_preservers_bootnodes: Vec<_> = para_ids
159
102
        .iter()
160
204
        .flat_map(|(para_id, _genesis_data, bootnodes)| {
161
204
            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
204
        })
171
102
        .collect();
172
102
    let para_ids: Vec<_> = para_ids
173
102
        .into_iter()
174
204
        .map(|(para_id, genesis_data, _boot_nodes)| (para_id, genesis_data, None))
175
102
        .collect();
176

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

            
247
102
    serde_json::to_value(g).unwrap()
248
102
}
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
102
pub fn invulnerables_from_seeds<S: AsRef<str>, I: Iterator<Item = S>>(
253
102
    names: I,
254
102
) -> Vec<(AccountId, NimbusId)> {
255
102
    names
256
408
        .map(|name| {
257
408
            let name = name.as_ref();
258
408
            (
259
408
                get_public_from_string_or_panic::<sr25519::Public>(name).into(),
260
408
                get_collator_keys_from_seed(name),
261
408
            )
262
408
        })
263
102
        .collect()
264
102
}
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
408
pub fn get_collator_keys_from_seed(seed: &str) -> NimbusId {
270
408
    get_public_from_string_or_panic::<NimbusId>(seed)
271
408
}
272

            
273
/// Helper function to turn a list of names into a list of `AccountId`
274
102
pub fn account_ids(names: &[&str]) -> Vec<AccountId> {
275
102
    names
276
102
        .iter()
277
1224
        .map(|name| get_public_from_string_or_panic::<sr25519::Public>(name).into())
278
102
        .collect()
279
102
}
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
408
pub fn template_session_keys(keys: NimbusId) -> dancebox_runtime::SessionKeys {
285
408
    dancebox_runtime::SessionKeys { nimbus: keys }
286
408
}
287

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

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

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