// Copyright 2019-2021 Parity Technologies (UK) Ltd. // This file is part of Parity Bridges Common. // Parity Bridges Common is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Parity Bridges Common is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . use bp_rialto::derive_account_from_millau_id; use rialto_runtime::{ AccountId, AuraConfig, BalancesConfig, BridgeKovanConfig, BridgeRialtoPoaConfig, GenesisConfig, GrandpaConfig, SessionConfig, SessionKeys, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use serde_json::json; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{sr25519, Pair, Public}; use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. pub type ChainSpec = sc_service::GenericChainSpec; /// The chain specification option. This is expected to come in from the CLI and /// is little more than one of a number of alternatives which can easily be converted /// from a string (`--chain=...`) into a `ChainSpec`. #[derive(Clone, Debug)] pub enum Alternative { /// Whatever the current runtime is, with just Alice as an auth. Development, /// Whatever the current runtime is, with simple Alice/Bob/Charlie/Dave/Eve auths. LocalTestnet, } /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { TPublic::Pair::from_string(&format!("//{}", seed), None) .expect("static values are valid; qed") .public() } type AccountPublic = ::Signer; /// Helper function to generate an account ID from seed pub fn get_account_id_from_seed(seed: &str) -> AccountId where AccountPublic: From<::Public>, { AccountPublic::from(get_from_seed::(seed)).into_account() } /// Helper function to generate an authority key for Aura pub fn get_authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) { ( get_account_id_from_seed::(s), get_from_seed::(s), get_from_seed::(s), ) } impl Alternative { /// Get an actual chain config from one of the alternatives. pub(crate) fn load(self) -> ChainSpec { let properties = Some( json!({ "tokenDecimals": 9, "tokenSymbol": "RLT", "bridgeIds": { "Millau": bp_runtime::MILLAU_CHAIN_ID, } }) .as_object() .expect("Map given; qed") .clone(), ); match self { Alternative::Development => ChainSpec::from_genesis( "Development", "dev", sc_service::ChainType::Development, || { testnet_genesis( vec![get_authority_keys_from_seed("Alice")], get_account_id_from_seed::("Alice"), vec![ get_account_id_from_seed::("Alice"), get_account_id_from_seed::("Bob"), get_account_id_from_seed::("Alice//stash"), get_account_id_from_seed::("Bob//stash"), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Bob"), )), ], true, ) }, vec![], None, None, properties, None, ), Alternative::LocalTestnet => ChainSpec::from_genesis( "Local Testnet", "local_testnet", sc_service::ChainType::Local, || { testnet_genesis( vec![ get_authority_keys_from_seed("Alice"), get_authority_keys_from_seed("Bob"), get_authority_keys_from_seed("Charlie"), get_authority_keys_from_seed("Dave"), get_authority_keys_from_seed("Eve"), ], get_account_id_from_seed::("Alice"), vec![ get_account_id_from_seed::("Alice"), get_account_id_from_seed::("Bob"), get_account_id_from_seed::("Charlie"), get_account_id_from_seed::("Dave"), get_account_id_from_seed::("Eve"), get_account_id_from_seed::("Ferdie"), get_account_id_from_seed::("George"), get_account_id_from_seed::("Harry"), get_account_id_from_seed::("Alice//stash"), get_account_id_from_seed::("Bob//stash"), get_account_id_from_seed::("Charlie//stash"), get_account_id_from_seed::("Dave//stash"), get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), get_account_id_from_seed::("George//stash"), get_account_id_from_seed::("Harry//stash"), pallet_bridge_messages::Pallet::< rialto_runtime::Runtime, pallet_bridge_messages::DefaultInstance, >::relayer_fund_account_id(), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Bob"), )), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Dave"), )), derive_account_from_millau_id(bp_runtime::SourceAccount::Account( get_account_id_from_seed::("Ferdie"), )), ], true, ) }, vec![], None, None, properties, None, ), } } } fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys { SessionKeys { aura, grandpa } } fn testnet_genesis( initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>, root_key: AccountId, endowed_accounts: Vec, _enable_println: bool, ) -> GenesisConfig { GenesisConfig { system: SystemConfig { code: WASM_BINARY.expect("Rialto development WASM not available").to_vec(), changes_trie_config: Default::default(), }, balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 50)).collect(), }, aura: AuraConfig { authorities: Vec::new(), }, bridge_rialto_poa: load_rialto_poa_bridge_config(), bridge_kovan: load_kovan_bridge_config(), grandpa: GrandpaConfig { authorities: Vec::new(), }, sudo: SudoConfig { key: root_key }, session: SessionConfig { keys: initial_authorities .iter() .map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone()))) .collect::>(), }, } } fn load_rialto_poa_bridge_config() -> BridgeRialtoPoaConfig { BridgeRialtoPoaConfig { initial_header: rialto_runtime::rialto_poa::genesis_header(), initial_difficulty: 0.into(), initial_validators: rialto_runtime::rialto_poa::genesis_validators(), } } fn load_kovan_bridge_config() -> BridgeKovanConfig { BridgeKovanConfig { initial_header: rialto_runtime::kovan::genesis_header(), initial_difficulty: 0.into(), initial_validators: rialto_runtime::kovan::genesis_validators(), } } #[test] fn derived_dave_account_is_as_expected() { let dave = get_account_id_from_seed::("Dave"); let derived: AccountId = derive_account_from_millau_id(bp_runtime::SourceAccount::Account(dave)); assert_eq!( derived.to_string(), "5HZhdv53gSJmWWtD8XR5Ypu4PgbT5JNWwGw2mkE75cN61w9t".to_string() ); }