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::chain_spec::{
19
        account_ids, get_account_id_from_seed, invulnerables_from_seeds, Extensions,
20
    },
21
    cumulus_primitives_core::ParaId,
22
    dancebox_runtime::{
23
        prod_or_fast, AccountId, DataPreserversConfig, MaintenanceModeConfig, MigrationsConfig,
24
        PolkadotXcmConfig, RegistrarConfig, ServicesPaymentConfig, SudoConfig,
25
    },
26
    dp_container_chain_genesis_data::{
27
        json::container_chain_genesis_data_from_path, ContainerChainGenesisData,
28
    },
29
    nimbus_primitives::NimbusId,
30
    pallet_configuration::HostConfiguration,
31
    sc_service::ChainType,
32
    sp_core::sr25519,
33
    sp_runtime::Perbill,
34
};
35

            
36
/// Specialized `ChainSpec` for the normal parachain runtime.
37
pub type ChainSpec = sc_service::GenericChainSpec<Extensions>;
38

            
39
/// Generate the session keys from individual elements.
40
///
41
/// The input must be a tuple of individual keys (a single arg for now since we have just one key).
42
72
pub fn template_session_keys(keys: NimbusId) -> dancebox_runtime::SessionKeys {
43
72
    dancebox_runtime::SessionKeys { nimbus: keys }
44
72
}
45

            
46
4
pub fn development_config(
47
4
    para_id: ParaId,
48
4
    container_chains: Vec<String>,
49
4
    mock_container_chains: Vec<ParaId>,
50
4
    invulnerables: Vec<String>,
51
4
) -> ChainSpec {
52
4
    // Give your base currency a unit name and decimal places
53
4
    let mut properties = sc_chain_spec::Properties::new();
54
4
    properties.insert("tokenSymbol".into(), "DANCE".into());
55
4
    properties.insert("tokenDecimals".into(), 12.into());
56
4
    properties.insert("ss58Format".into(), 42.into());
57
4
    properties.insert("isEthereum".into(), false.into());
58
4

            
59
4
    ChainSpec::builder(
60
4
        dancebox_runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"),
61
4
        Extensions {
62
4
            relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
63
4
            para_id: para_id.into(),
64
4
        },
65
4
    )
66
4
    .with_name("Dancebox Development Testnet")
67
4
    .with_id("dancebox_dev")
68
4
    .with_chain_type(ChainType::Development)
69
4
    .with_genesis_config(testnet_genesis(
70
4
        // initial collators.
71
4
        invulnerables_from_seeds(invulnerables.iter()),
72
4
        account_ids(&[
73
4
            "Alice",
74
4
            "Bob",
75
4
            "Charlie",
76
4
            "Dave",
77
4
            "Eve",
78
4
            "Ferdie",
79
4
            "Alice//stash",
80
4
            "Bob//stash",
81
4
            "Charlie//stash",
82
4
            "Dave//stash",
83
4
            "Eve//stash",
84
4
            "Ferdie//stash",
85
4
        ]),
86
4
        para_id,
87
4
        get_account_id_from_seed::<sr25519::Public>("Alice"),
88
4
        &container_chains,
89
4
        &mock_container_chains,
90
4
        pallet_configuration::GenesisConfig {
91
4
            config: HostConfiguration {
92
4
                max_collators: 100u32,
93
4
                min_orchestrator_collators: 1u32,
94
4
                max_orchestrator_collators: 1u32,
95
4
                collators_per_container: 2u32,
96
4
                full_rotation_period: prod_or_fast!(24u32, 5u32),
97
                collators_per_parathread: 1,
98
                parathreads_per_collator: 1,
99
4
                target_container_chain_fullness: Perbill::from_percent(80),
100
4
                max_parachain_cores_percentage: None,
101
4
                full_rotation_mode: Default::default(),
102
4
            },
103
4
            ..Default::default()
104
4
        },
105
4
    ))
106
4
    .with_properties(properties)
107
4
    .build()
108
4
}
109

            
110
14
pub fn local_dancebox_config(
111
14
    para_id: ParaId,
112
14
    container_chains: Vec<String>,
113
14
    mock_container_chains: Vec<ParaId>,
114
14
    invulnerables: Vec<String>,
115
14
) -> ChainSpec {
116
14
    // Give your base currency a unit name and decimal places
117
14
    let mut properties = sc_chain_spec::Properties::new();
118
14
    properties.insert("tokenSymbol".into(), "DANCE".into());
119
14
    properties.insert("tokenDecimals".into(), 12.into());
120
14
    properties.insert("ss58Format".into(), 42.into());
121
14
    properties.insert("isEthereum".into(), false.into());
122
14

            
123
14
    ChainSpec::builder(
124
14
        dancebox_runtime::WASM_BINARY.expect("WASM binary was not built, please build it!"),
125
14
        Extensions {
126
14
            relay_chain: "rococo-local".into(), // You MUST set this to the correct network!
127
14
            para_id: para_id.into(),
128
14
        },
129
14
    )
130
14
    .with_name("Dancebox Local Testnet")
131
14
    .with_id("dancebox_local")
132
14
    .with_chain_type(ChainType::Local)
133
14
    .with_genesis_config(testnet_genesis(
134
14
        // initial collators.
135
14
        invulnerables_from_seeds(invulnerables.iter()),
136
14
        account_ids(&[
137
14
            "Alice",
138
14
            "Bob",
139
14
            "Charlie",
140
14
            "Dave",
141
14
            "Eve",
142
14
            "Ferdie",
143
14
            "Alice//stash",
144
14
            "Bob//stash",
145
14
            "Charlie//stash",
146
14
            "Dave//stash",
147
14
            "Eve//stash",
148
14
            "Ferdie//stash",
149
14
        ]),
150
14
        para_id,
151
14
        get_account_id_from_seed::<sr25519::Public>("Alice"),
152
14
        &container_chains,
153
14
        &mock_container_chains,
154
14
        pallet_configuration::GenesisConfig {
155
14
            config: HostConfiguration {
156
14
                max_collators: 100u32,
157
14
                min_orchestrator_collators: 2u32,
158
14
                max_orchestrator_collators: 5u32,
159
14
                collators_per_container: 2u32,
160
14
                full_rotation_period: prod_or_fast!(24u32, 5u32),
161
                collators_per_parathread: 1,
162
                parathreads_per_collator: 1,
163
14
                target_container_chain_fullness: Perbill::from_percent(80),
164
14
                max_parachain_cores_percentage: None,
165
14
                full_rotation_mode: Default::default(),
166
14
            },
167
14
            ..Default::default()
168
14
        },
169
14
    ))
170
14
    .with_properties(properties)
171
14
    .with_protocol_id("orchestrator")
172
14
    .build()
173
14
}
174

            
175
18
fn testnet_genesis(
176
18
    invulnerables: Vec<(AccountId, NimbusId)>,
177
18
    endowed_accounts: Vec<AccountId>,
178
18
    id: ParaId,
179
18
    root_key: AccountId,
180
18
    container_chains: &[String],
181
18
    mock_container_chains: &[ParaId],
182
18
    configuration: pallet_configuration::GenesisConfig<dancebox_runtime::Runtime>,
183
18
) -> serde_json::Value {
184
18
    let para_ids: Vec<_> = container_chains
185
18
        .iter()
186
18
        .map(|x| {
187
            container_chain_genesis_data_from_path(x).unwrap_or_else(|e| {
188
                panic!(
189
                    "Failed to build genesis data for container chain {:?}: {}",
190
                    x, e
191
                )
192
            })
193
18
        })
194
18
        .chain(
195
18
            mock_container_chains
196
18
                .iter()
197
36
                .map(|x| (*x, mock_container_chain_genesis_data(*x), vec![])),
198
18
        )
199
18
        .collect();
200
18
    // Assign 1000 block credits to all container chains registered in genesis
201
18
    // Assign 100 collator assignment credits to all container chains registered in genesis
202
18
    let para_id_credits: Vec<_> = para_ids
203
18
        .iter()
204
36
        .map(|(para_id, _genesis_data, _boot_nodes)| (*para_id, 1000, 100).into())
205
18
        .collect();
206
18
    let data_preservers_bootnodes: Vec<_> = para_ids
207
18
        .iter()
208
36
        .flat_map(|(para_id, _genesis_data, bootnodes)| {
209
36
            bootnodes.clone().into_iter().map(|bootnode| {
210
                (
211
                    *para_id,
212
                    AccountId::from([0u8; 32]),
213
                    bootnode,
214
                    dancebox_runtime::PreserversAssignementPaymentRequest::Free,
215
                    dancebox_runtime::PreserversAssignementPaymentWitness::Free,
216
                )
217
36
            })
218
36
        })
219
18
        .collect();
220
18
    let para_ids: Vec<_> = para_ids
221
18
        .into_iter()
222
36
        .map(|(para_id, genesis_data, _boot_nodes)| (para_id, genesis_data, None))
223
18
        .collect();
224
18

            
225
18
    let accounts_with_ed = [
226
18
        dancebox_runtime::StakingAccount::get(),
227
18
        dancebox_runtime::ParachainBondAccount::get(),
228
18
        dancebox_runtime::PendingRewardsAccount::get(),
229
18
    ];
230
18
    let g = dancebox_runtime::RuntimeGenesisConfig {
231
18
        system: Default::default(),
232
18
        balances: dancebox_runtime::BalancesConfig {
233
18
            balances: endowed_accounts
234
18
                .iter()
235
18
                .cloned()
236
216
                .map(|k| (k, 1 << 60))
237
18
                .chain(
238
18
                    accounts_with_ed
239
18
                        .iter()
240
18
                        .cloned()
241
54
                        .map(|k| (k, dancebox_runtime::EXISTENTIAL_DEPOSIT)),
242
18
                )
243
18
                .collect(),
244
18
        },
245
18
        parachain_info: dancebox_runtime::ParachainInfoConfig {
246
18
            parachain_id: id,
247
18
            ..Default::default()
248
18
        },
249
18
        invulnerables: dancebox_runtime::InvulnerablesConfig {
250
72
            invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(),
251
18
        },
252
18
        session: dancebox_runtime::SessionConfig {
253
18
            keys: invulnerables
254
18
                .into_iter()
255
72
                .map(|(acc, aura)| {
256
72
                    (
257
72
                        acc.clone(),                 // account id
258
72
                        acc,                         // validator id
259
72
                        template_session_keys(aura), // session keys
260
72
                    )
261
72
                })
262
18
                .collect(),
263
18
            ..Default::default()
264
18
        },
265
18
        parachain_system: Default::default(),
266
18
        configuration,
267
18
        registrar: RegistrarConfig {
268
18
            para_ids,
269
18
            phantom: Default::default(),
270
18
        },
271
18
        services_payment: ServicesPaymentConfig { para_id_credits },
272
18
        sudo: SudoConfig {
273
18
            key: Some(root_key),
274
18
        },
275
18
        migrations: MigrationsConfig {
276
18
            ..Default::default()
277
18
        },
278
18
        maintenance_mode: MaintenanceModeConfig {
279
18
            start_in_maintenance_mode: false,
280
18
            ..Default::default()
281
18
        },
282
18
        // This should initialize it to whatever we have set in the pallet
283
18
        polkadot_xcm: PolkadotXcmConfig::default(),
284
18
        transaction_payment: Default::default(),
285
18
        tx_pause: Default::default(),
286
18
        treasury: Default::default(),
287
18
        data_preservers: DataPreserversConfig {
288
18
            bootnodes: data_preservers_bootnodes,
289
18
            ..Default::default()
290
18
        },
291
18
    };
292
18

            
293
18
    serde_json::to_value(g).unwrap()
294
18
}
295

            
296
36
fn mock_container_chain_genesis_data(para_id: ParaId) -> ContainerChainGenesisData {
297
36
    ContainerChainGenesisData {
298
36
        storage: vec![],
299
36
        name: format!("Container Chain {}", para_id).into(),
300
36
        id: format!("container-chain-{}", para_id).into(),
301
36
        fork_id: None,
302
36
        extensions: vec![],
303
36
        properties: Default::default(),
304
36
    }
305
36
}