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 sp_keyring::Sr25519Keyring;
18
use {
19
    crate::chain_spec::{account_ids, invulnerables_from_seeds, Extensions},
20
    cumulus_primitives_core::ParaId,
21
    dancebox_runtime::{
22
        prod_or_fast, AccountId, DataPreserversConfig, MaintenanceModeConfig, MigrationsConfig,
23
        PolkadotXcmConfig, RegistrarConfig, ServicesPaymentConfig, SudoConfig,
24
    },
25
    dp_container_chain_genesis_data::{
26
        json::container_chain_genesis_data_from_path, ContainerChainGenesisData,
27
    },
28
    frame_support::BoundedVec,
29
    nimbus_primitives::NimbusId,
30
    pallet_configuration::HostConfiguration,
31
    sc_service::ChainType,
32
    sp_runtime::{traits::AccountIdConversion, Perbill},
33
};
34
/// Specialized `ChainSpec` for the normal parachain runtime.
35
pub type ChainSpec = sc_service::GenericChainSpec<Extensions>;
36

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

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

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

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

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

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

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

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

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