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
            },
102
4
            ..Default::default()
103
4
        },
104
4
    ))
105
4
    .with_properties(properties)
106
4
    .build()
107
4
}
108

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

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

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

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

            
291
18
    serde_json::to_value(g).unwrap()
292
18
}
293

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