Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • network/gdev-800 protected
  • cgeek/issue-297-cpu
  • gdev-800-tests
  • update-docker-compose-rpc-squid-names
  • fix-252
  • 1000i100-test
  • hugo/tmp-0.9.1
  • network/gdev-803 protected
  • hugo/endpoint-gossip
  • network/gdev-802 protected
  • hugo/distance-precompute
  • network/gdev-900 protected
  • tuxmain/anonymous-tx
  • debug/podman
  • hugo/195-doc
  • hugo/195-graphql-schema
  • hugo-tmp-dockerfile-cache
  • release/client-800.2 protected
  • release/runtime-800 protected
  • gdev-900-0.10.1 protected
  • gdev-900-0.10.0 protected
  • gdev-900-0.9.2 protected
  • gdev-800-0.8.0 protected
  • gdev-900-0.9.1 protected
  • gdev-900-0.9.0 protected
  • gdev-803 protected
  • gdev-802 protected
  • runtime-801 protected
  • gdev-800 protected
  • runtime-800-bis protected
  • runtime-800 protected
  • runtime-800-backup protected
  • runtime-701 protected
  • runtime-700 protected
  • runtime-600 protected
  • runtime-500 protected
  • v0.4.1 protected
  • runtime-401 protected
  • v0.4.0 protected
40 results

gtest.rs

Blame
  • gtest.rs 11.88 KiB
    // Copyright 2021 Axiom-Team
    //
    // This file is part of Duniter-v2S.
    //
    // Duniter-v2S is free software: you can redistribute it and/or modify
    // it under the terms of the GNU Affero General Public License as published by
    // the Free Software Foundation, version 3 of the License.
    //
    // Duniter-v2S 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 Affero General Public License for more details.
    //
    // You should have received a copy of the GNU Affero General Public License
    // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
    
    use super::*;
    use crate::chain_spec::gen_genesis_data::{
        CommonParameters, GenesisData, GenesisIdentity, SessionKeysProvider,
    };
    use common_runtime::constants::*;
    use common_runtime::entities::IdtyData;
    use common_runtime::*;
    use gtest_runtime::{
        opaque::SessionKeys, parameters, AccountConfig, AccountId, AuthorityMembersConfig, BabeConfig,
        CertConfig, GenesisConfig, IdentityConfig, ImOnlineId, MembershipConfig, Perbill,
        SessionConfig, SmithCertConfig, SmithMembershipConfig, SudoConfig, SystemConfig,
        TechnicalCommitteeConfig, UniversalDividendConfig, WASM_BINARY,
    };
    use jsonrpsee::core::JsonValue;
    use sc_network_common::config::MultiaddrWithPeerId; // in the future available in sc_network::config
    use sc_service::ChainType;
    use sc_telemetry::TelemetryEndpoints;
    use serde::Deserialize;
    use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
    use sp_consensus_babe::AuthorityId as BabeId;
    use sp_core::{blake2_256, sr25519, Encode, H256};
    use sp_finality_grandpa::AuthorityId as GrandpaId;
    use sp_membership::MembershipData;
    use std::collections::BTreeMap;
    use std::{env, fs};
    
    pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>;
    pub type AuthorityKeys = (
        AccountId,
        GrandpaId,
        BabeId,
        ImOnlineId,
        AuthorityDiscoveryId,
    );
    
    const TOKEN_DECIMALS: usize = 2;
    const TOKEN_SYMBOL: &str = "ĞT";
    
    #[derive(Default, Clone, Deserialize)]
    // No parameters for GTest (unlike GDev)
    struct GenesisParameters {}
    
    struct GTestSKP;
    impl SessionKeysProvider<SessionKeys> for GTestSKP {
        fn session_keys(keys: &AuthorityKeys) -> SessionKeys {
            let cloned = keys.clone();
            SessionKeys {
                grandpa: cloned.1,
                babe: cloned.2,
                im_online: cloned.3,
                authority_discovery: cloned.4,
            }
        }
    }
    
    fn get_parameters(_: &Option<GenesisParameters>) -> CommonParameters {
        CommonParameters {
            currency_name: TOKEN_SYMBOL.to_string(),
            decimals: TOKEN_DECIMALS,
            existential_deposit: parameters::ExistentialDeposit::get(),
            membership_period: parameters::MembershipPeriod::get(),
            cert_period: parameters::CertPeriod::get(),
            smith_membership_period: parameters::SmithMembershipPeriod::get(),
            smith_certs_validity_period: parameters::SmithValidityPeriod::get(),
            min_cert: parameters::WotMinCertForMembership::get(),
            smith_min_cert: parameters::SmithWotMinCertForMembership::get(),
            cert_max_by_issuer: parameters::MaxByIssuer::get(),
            cert_validity_period: parameters::ValidityPeriod::get(),
            c2: parameters::SquareMoneyGrowthRate::get(),
            ud_creation_period: parameters::UdCreationPeriod::get() as u64, // TODO: cast?
            distance_min_accessible_referees: Perbill::from_percent(80),    // TODO: generalize
            max_depth: 5,                                                   // TODO: generalize value
            ud_reeval_period: parameters::UdReevalPeriod::get() as u64,     // TODO: cast?
        }
    }
    
    /// Generate an authority keys.
    pub fn get_authority_keys_from_seed(s: &str) -> AuthorityKeys {
        (
            get_account_id_from_seed::<sr25519::Public>(s),
            get_from_seed::<GrandpaId>(s),
            get_from_seed::<BabeId>(s),
            get_from_seed::<ImOnlineId>(s),
            get_from_seed::<AuthorityDiscoveryId>(s),
        )
    }
    /// Generate session keys
    fn get_session_keys_from_seed(s: &str) -> SessionKeys {
        let authority_keys = get_authority_keys_from_seed(s);
        session_keys(
            authority_keys.1,
            authority_keys.2,
            authority_keys.3,
            authority_keys.4,
        )
    }
    /// make session keys struct
    fn session_keys(
        grandpa: GrandpaId,
        babe: BabeId,
        im_online: ImOnlineId,
        authority_discovery: AuthorityDiscoveryId,
    ) -> SessionKeys {
        SessionKeys {
            grandpa,
            babe,
            im_online,
            authority_discovery,
        }
    }
    
    // === client specifications ===
    
    /// emulate client specifications to get them from json
    #[derive(Deserialize, Clone)]
    #[serde(rename_all = "camelCase")]
    #[serde(deny_unknown_fields)]
    pub struct ClientSpec {
        name: String,
        id: String,
        chain_type: ChainType,
        boot_nodes: Vec<MultiaddrWithPeerId>,
        telemetry_endpoints: Option<TelemetryEndpoints>,
        // protocol_id: Option<String>,
        // #[serde(default = "Default::default", skip_serializing_if = "Option::is_none")]
        // fork_id: Option<String>,
        properties: Option<serde_json::Map<std::string::String, JsonValue>>,
        // #[serde(default)]
        // code_substitutes: BTreeMap<String, Bytes>,
    }
    
    // === development chainspecs ===
    
    /// generate development chainspec with Alice validator
    // there is some code duplication because we can not use ClientSpec
    pub fn development_chainspecs(json_file_path: String) -> Result<ChainSpec, String> {
        let wasm_binary = get_wasm_binary().ok_or_else(|| "wasm not available".to_string())?;
        Ok(ChainSpec::from_genesis(
            // Name
            "ĞTest Development",
            // ID
            "gtest_dev",
            // chain type
            sc_service::ChainType::Development,
            // constructor
            move || {
                let genesis_data =
                    gen_genesis_data::generate_genesis_data::<_, _, SessionKeys, GTestSKP>(
                        json_file_path.clone(),
                        get_parameters,
                        Some("Alice".to_owned()),
                    )
                    .expect("Genesis Data must be buildable");
                genesis_data_to_gtest_genesis_conf(genesis_data, &wasm_binary)
            },
            // Bootnodes
            vec![],
            // Telemetry
            None,
            // Protocol ID
            None,
            //Fork ID
            None,
            // Properties
            Some(
                serde_json::json!({
                    "tokenDecimals": TOKEN_DECIMALS,
                    "tokenSymbol": TOKEN_SYMBOL,
                })
                .as_object()
                .expect("must be a map")
                .clone(),
            ),
            // Extensions
            None,
        ))
    }
    
    // === live chainspecs ===
    
    /// live chainspecs
    // one smith must have session keys
    pub fn live_chainspecs(
        client_spec: ClientSpec,
        json_file_path: String,
    ) -> Result<ChainSpec, String> {
        let wasm_binary = get_wasm_binary().ok_or_else(|| "wasm not available".to_string())?;
        Ok(ChainSpec::from_genesis(
            // Name
            client_spec.name.as_str(),
            // ID
            client_spec.id.as_str(),
            // chain type
            client_spec.chain_type,
            // genesis config constructor
            move || {
                let genesis_data =
                    gen_genesis_data::generate_genesis_data::<_, _, SessionKeys, GTestSKP>(
                        json_file_path.clone(),
                        get_parameters,
                        None,
                    )
                    .expect("Genesis Data must be buildable");
                genesis_data_to_gtest_genesis_conf(genesis_data, &wasm_binary)
            },
            // Bootnodes
            client_spec.boot_nodes,
            // Telemetry (by default, enable telemetry, can be disabled with argument)
            client_spec.telemetry_endpoints,
            // Protocol ID
            None,
            // Fork ID
            None,
            // Properties
            client_spec.properties,
            // Extensions
            None,
        ))
    }
    
    /// custom genesis
    fn genesis_data_to_gtest_genesis_conf(
        genesis_data: super::gen_genesis_data::GenesisData<GenesisParameters, SessionKeys>,
        wasm_binary: &Vec<u8>,
    ) -> gtest_runtime::GenesisConfig {
        let super::gen_genesis_data::GenesisData {
            accounts,
            treasury_balance,
            certs_by_receiver,
            first_ud,
            first_ud_reeval,
            identities,
            initial_authorities,
            initial_monetary_mass,
            memberships,
            parameters,
            common_parameters,
            session_keys_map,
            smith_certs_by_receiver,
            smith_memberships,
            sudo_key,
            technical_committee_members,
            ud,
        } = genesis_data;
    
        gtest_runtime::GenesisConfig {
            system: SystemConfig {
                // Add Wasm runtime to storage.
                code: wasm_binary.to_vec(),
            },
            account: AccountConfig {
                accounts,
                treasury_balance,
            },
            authority_discovery: Default::default(),
            authority_members: AuthorityMembersConfig {
                initial_authorities,
            },
            balances: Default::default(),
            babe: BabeConfig {
                authorities: Vec::with_capacity(0),
                epoch_config: Some(BABE_GENESIS_EPOCH_CONFIG),
            },
            grandpa: Default::default(),
            im_online: Default::default(),
            session: SessionConfig {
                keys: session_keys_map
                    .into_iter()
                    .map(|(account_id, session_keys)| (account_id.clone(), account_id, session_keys))
                    .collect::<Vec<_>>(),
            },
            sudo: SudoConfig { key: sudo_key },
            technical_committee: TechnicalCommitteeConfig {
                members: technical_committee_members,
                ..Default::default()
            },
            identity: IdentityConfig {
                identities: identities
                    .into_iter()
                    .enumerate()
                    .map(
                        |(
                            i,
                            GenesisIdentity {
                                idty_index,
                                name,
                                owner_key,
                                old_owner_key,
                                active,
                            },
                        )| GenesisIdty {
                            index: idty_index,
                            name: common_runtime::IdtyName::from(name.as_str()),
                            value: common_runtime::IdtyValue {
                                data: IdtyData::new(),
                                next_creatable_identity_on: 0,
                                old_owner_key: old_owner_key.clone().map(|address| (address, 0)),
                                owner_key,
                                removable_on: if active { 0 } else { 2 },
                                status: IdtyStatus::Validated,
                            },
                        },
                    )
                    .collect(),
            },
            cert: CertConfig {
                apply_cert_period_at_genesis: true,
                certs_by_receiver,
            },
            membership: MembershipConfig { memberships },
            smith_cert: SmithCertConfig {
                apply_cert_period_at_genesis: true,
                certs_by_receiver: smith_certs_by_receiver,
            },
            smith_membership: SmithMembershipConfig {
                memberships: smith_memberships,
            },
            universal_dividend: UniversalDividendConfig {
                first_reeval: first_ud_reeval,
                first_ud,
                initial_monetary_mass,
                ud,
                #[cfg(test)]
                initial_members: vec![],
            },
            treasury: Default::default(),
        }
    }
    
    /// Get the WASM bytes either from filesytem (`WASM_FILE` env variable giving the path to the wasm blob)
    /// or else get the one compiled from source code.
    /// Goal: allow to provide the WASM built with srtool, which is reproductible.
    fn get_wasm_binary() -> Option<Vec<u8>> {
        let wasm_bytes_from_file = if let Ok(file_path) = env::var("WASM_FILE") {
            Some(fs::read(file_path).unwrap_or_else(|e| panic!("Could not read wasm file: {}", e)))
        } else {
            None
        };
        wasm_bytes_from_file.or(WASM_BINARY.map(|bytes| bytes.to_vec()))
    }