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
    dp_container_chain_genesis_data::{
22
        json::container_chain_genesis_data_from_path, ContainerChainGenesisData,
23
    },
24
    flashbox_runtime::{
25
        AccountId, DataPreserversConfig, MaintenanceModeConfig, MigrationsConfig, RegistrarConfig,
26
        ServicesPaymentConfig, SudoConfig,
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

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

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

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

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

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

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

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

            
220
10
    let para_ids: Vec<_> = para_ids
221
10
        .into_iter()
222
20
        .map(|(para_id, genesis_data, _boot_nodes)| (para_id, genesis_data, None))
223
10
        .collect();
224
10

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

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

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