From ca6c877e1b7459773a0021cdb4087a26a01aff8f Mon Sep 17 00:00:00 2001 From: Hugo Trentesaux <hugo.trentesaux@lilo.org> Date: Mon, 22 May 2023 20:12:13 +0200 Subject: [PATCH] gtest genesis new format (nodes/rust/duniter-v2s!168) * fix smith certification validity * get values of parameters * tuxmain review * add checks and improve formatting * improve genesis parsing adds info * fix json with new format * fix warnings * new gtest genesis format * get build working with gtest feature `cargo build --features gtest --no-default-features` * update lib.rs * update cargo.toml * add readme for runtimes --- .vscode/settings.json | 2 +- Cargo.lock | 7 +- node/src/chain_spec.rs | 3 + node/src/chain_spec/gtest.rs | 189 ++++++---- node/src/chain_spec/gtest_genesis.rs | 528 +++++++++++++++++++++++++++ node/src/service/client.rs | 19 +- resources/gtest.json | 331 +++++++++++++++++ runtime/g1/README.md | 4 + runtime/gdev/README.md | 5 + runtime/gtest/Cargo.toml | 46 ++- runtime/gtest/README.md | 10 + runtime/gtest/src/lib.rs | 31 +- 12 files changed, 1085 insertions(+), 90 deletions(-) create mode 100644 node/src/chain_spec/gtest_genesis.rs create mode 100644 resources/gtest.json create mode 100644 runtime/g1/README.md create mode 100644 runtime/gdev/README.md create mode 100644 runtime/gtest/README.md diff --git a/.vscode/settings.json b/.vscode/settings.json index fe6423f76..3070b8018 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,7 +4,7 @@ 100 ], "[json]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "vscode.json-language-features" }, "[yaml]": { "editor.defaultFormatter": "esbenp.prettier-vscode" diff --git a/Cargo.lock b/Cargo.lock index 0c68f2968..7c5fc58d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2865,7 +2865,6 @@ dependencies = [ "pallet-certification", "pallet-collective", "pallet-duniter-account", - "pallet-duniter-test-parameters", "pallet-duniter-wot", "pallet-grandpa", "pallet-identity", @@ -2879,6 +2878,7 @@ dependencies = [ "pallet-proxy", "pallet-scheduler", "pallet-session", + "pallet-session-benchmarking", "pallet-sudo", "pallet-timestamp", "pallet-transaction-payment", @@ -2890,6 +2890,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", + "serde_derive", "sp-api", "sp-arithmetic", "sp-authority-discovery", @@ -9722,9 +9723,9 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "digest 0.10.6", - "rand 0.7.3", + "rand 0.8.5", "static_assertions", ] diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 8bdef9198..580e076e4 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -14,6 +14,7 @@ // 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/>. +#[cfg(feature = "gdev")] pub mod gen_genesis_data; #[cfg(feature = "g1")] @@ -22,6 +23,8 @@ pub mod g1; pub mod gdev; #[cfg(feature = "gtest")] pub mod gtest; +#[cfg(feature = "gtest")] +pub mod gtest_genesis; use common_runtime::{AccountId, IdtyIndex, Signature}; use sp_core::{Pair, Public}; diff --git a/node/src/chain_spec/gtest.rs b/node/src/chain_spec/gtest.rs index 180dce2b2..d45890721 100644 --- a/node/src/chain_spec/gtest.rs +++ b/node/src/chain_spec/gtest.rs @@ -19,10 +19,10 @@ use common_runtime::constants::*; use common_runtime::entities::IdtyData; use common_runtime::*; use gtest_runtime::{ - opaque::SessionKeys, AccountConfig, AccountId, AuthorityMembersConfig, BabeConfig, - BalancesConfig, CertConfig, GenesisConfig, IdentityConfig, IdtyValue, ImOnlineId, - MembershipConfig, SessionConfig, SmithCertConfig, SmithMembershipConfig, SudoConfig, - SystemConfig, TechnicalCommitteeConfig, UniversalDividendConfig, WASM_BINARY, + opaque::SessionKeys, AccountConfig, AccountId, AuthorityMembersConfig, BabeConfig, CertConfig, + GenesisConfig, IdentityConfig, ImOnlineId, MembershipConfig, SessionConfig, SmithCertConfig, + SmithMembershipConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, + UniversalDividendConfig, WASM_BINARY, }; use sc_service::ChainType; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; @@ -34,8 +34,8 @@ use std::collections::BTreeMap; pub type AuthorityKeys = ( AccountId, - BabeId, GrandpaId, + BabeId, ImOnlineId, AuthorityDiscoveryId, ); @@ -51,57 +51,136 @@ const TOKEN_SYMBOL: &str = "ĞT"; pub fn get_authority_keys_from_seed(s: &str) -> AuthorityKeys { ( get_account_id_from_seed::<sr25519::Public>(s), - get_from_seed::<BabeId>(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, + } +} + +/// generate development chainspec with Alice validator pub fn development_chain_spec() -> Result<ChainSpec, String> { let wasm_binary = WASM_BINARY.ok_or_else(|| "wasm not available".to_string())?; - Ok(ChainSpec::from_genesis( - // Name - "Ğtest Development", - // ID - "gtest_dev", - ChainType::Development, - move || { - gen_genesis_for_local_chain( - wasm_binary, - // Initial authorities len - 1, - // Initial smith members len - 3, - // Inital identities len - 4, - // Sudo account - get_account_id_from_seed::<sr25519::Public>("Alice"), - true, - ) - }, - // Bootnodes - vec![], - // Telemetry - None, - // Protocol ID - None, - //Fork ID - None, - // Properties - Some( - serde_json::json!({ + // custom genesis when DUNITER_GTEST_GENESIS is set + if let Ok(genesis_json_path) = std::env::var("DUNITER_GTEST_GENESIS") { + // log + log::info!("loading genesis from {genesis_json_path}"); + // return chainspecs + Ok(ChainSpec::from_genesis( + // Name + "ĞTest Development", + // ID + "gtest_dev", + // chain type + sc_service::ChainType::Development, + // genesis config constructor + move || { + super::gtest_genesis::build_genesis( + // path of json genesis + &genesis_json_path, + // wasm binary + wasm_binary, + // replace authority by Alice + Some(get_session_keys_from_seed("Alice").encode()), + ) + .expect("genesis building failed") + }, + // 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, - )) + }) + .as_object() + .expect("must be a map") + .clone(), + ), + // Extensions + None, + )) + } else { + // log + log::info!("generating genesis"); + // generated genesis + Ok(ChainSpec::from_genesis( + // Name + "ĞTest Development", + // ID + "gtest_dev", + // chain type + ChainType::Development, + // constructor + move || { + gen_genesis_for_local_chain( + wasm_binary, + // Initial authorities len + 1, + // Initial smith members len + 3, + // Inital identities len + 4, + // Sudo account + get_account_id_from_seed::<sr25519::Public>("Alice"), + true, + ) + }, + // 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, + )) + } } pub fn local_testnet_config( @@ -113,7 +192,7 @@ pub fn local_testnet_config( Ok(ChainSpec::from_genesis( // Name - "Ğtest Local Testnet", + "ĞTest Local Testnet", // ID "gtest_local", ChainType::Local, @@ -209,9 +288,7 @@ fn gen_genesis_for_local_chain( .map(|(i, keys)| (i as u32 + 1, (keys.0.clone(), true))) .collect(), }, - balances: BalancesConfig { - balances: Vec::with_capacity(0), - }, + balances: Default::default(), babe: BabeConfig { authorities: Vec::with_capacity(0), epoch_config: Some(BABE_GENESIS_EPOCH_CONFIG), @@ -299,17 +376,3 @@ fn gen_genesis_for_local_chain( treasury: Default::default(), } } - -fn session_keys( - babe: BabeId, - grandpa: GrandpaId, - im_online: ImOnlineId, - authority_discovery: AuthorityDiscoveryId, -) -> SessionKeys { - SessionKeys { - babe, - grandpa, - im_online, - authority_discovery, - } -} diff --git a/node/src/chain_spec/gtest_genesis.rs b/node/src/chain_spec/gtest_genesis.rs new file mode 100644 index 000000000..9aa6f737f --- /dev/null +++ b/node/src/chain_spec/gtest_genesis.rs @@ -0,0 +1,528 @@ +// 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 common_runtime::constants::*; +use common_runtime::entities::IdtyData; +use common_runtime::*; +use gtest_runtime::{ + opaque::SessionKeys, parameters, AccountConfig, AccountId, AuthorityMembersConfig, BabeConfig, + CertConfig, GenesisConfig, IdentityConfig, MembershipConfig, SessionConfig, SmithCertConfig, + SmithMembershipConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, + UniversalDividendConfig, +}; +use serde::Deserialize; +use sp_core::{blake2_256, Decode, Encode, H256}; +use std::collections::{BTreeMap, HashMap}; + +type MembershipData = sp_membership::MembershipData<u32>; + +// get values of parameters +static EXISTENTIAL_DEPOSIT: u64 = parameters::ExistentialDeposit::get(); +static SMITH_MEMBERSHIP_EXPIRE_ON: u32 = parameters::SmithMembershipPeriod::get(); +static SMITH_CERTS_EXPIRE_ON: u32 = parameters::SmithValidityPeriod::get(); +static MIN_CERT: u32 = parameters::WotMinCertForMembership::get(); +static SMITH_MIN_CERT: u32 = parameters::SmithWotMinCertForMembership::get(); + +// define structure of json +#[derive(Clone, Deserialize)] +struct GenesisJson { + identities: HashMap<String, Identity>, + smiths: HashMap<String, Smith>, + first_ud: u64, + first_ud_reeval: u32, + initial_monetary_mass: u64, + wallets: HashMap<AccountId, u64>, // u128 + sudo_key: Option<AccountId>, + technical_committee: Vec<String>, +} + +/// identities +#[derive(Clone, Deserialize)] +struct Identity { + /// indentity index matching the order of appearance in the Ǧ1v1 blockchain + index: u32, + /// ss58 address in gtest network + owner_key: AccountId, + /// optional ss58 address in the Ğ1v1 + old_owner_key: Option<AccountId>, + /// block at which the membership is set to expire (0 for expired members) + membership_expire_on: u32, + /// block at which the next cert can be emitted + next_cert_issuable_on: u32, + /// balance of the account of this identity + balance: u64, // u128 + /// certs received with their expiration block + certs_received: HashMap<String, u32>, +} + +/// smith members +#[derive(Clone, Deserialize)] +struct Smith { + /// optional pre-set session keys (at least for the smith bootstraping the blockchain) + session_keys: Option<String>, + /// smith certification received + certs_received: Vec<String>, +} + +// Timestamp to block number +// fn to_bn(genesis_timestamp: u64, timestamp: u64) -> u32 { +// let duration_in_secs = timestamp.saturating_sub(genesis_timestamp); +// (duration_in_secs / 6) as u32 +// } + +// copied from duniter primitives +fn validate_idty_name(idty_name: &str) -> bool { + idty_name.len() >= 3 + && idty_name.len() <= 42 // length smaller than 42 + // all characters are alphanumeric or - or _ + && idty_name + .chars() + .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_') +} + +/// ============================================================================================ /// +/// build genesis from json file +pub fn build_genesis( + // path of genesis config + genesis_config_path: &str, + // wasm binary + wasm_binary: &[u8], + // useful to enforce Alice authority when developing + maybe_force_authority: Option<Vec<u8>>, +) -> Result<GenesisConfig, String> { + // preparatory steps + + // define genesis timestamp + let genesis_timestamp: u64 = + if let Ok(genesis_timestamp) = std::env::var("DUNITER_GENESIS_TIMESTAMP") { + genesis_timestamp + .parse() + .map_err(|_| "DUNITER_GENESIS_TIMESTAMP must be a number".to_owned())? + } else { + use std::time::SystemTime; + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .expect("SystemTime before UNIX EPOCH!") + .as_secs() + }; + log::info!("genesis timestamp: {}", genesis_timestamp); + + // open json genesis file + let file = std::fs::File::open(&genesis_config_path).map_err(|e| { + format!( + "Error opening gen conf file `{}`: {}", + genesis_config_path, e + ) + })?; + + // memory map the file to avoid loading it in memory + let bytes = unsafe { + memmap2::Mmap::map(&file).map_err(|e| { + format!( + "Error mmaping gen conf file `{}`: {}", + genesis_config_path, e + ) + })? + }; + + // parse the json file + let genesis_data: GenesisJson = serde_json::from_slice(&bytes) + .map_err(|e| format!("Error parsing gen conf file: {}", e))?; + + // declare variables for building genesis + // ------------------------------------- + // track if fatal error occured, but let processing continue + let mut fatal = false; + // monetary mass for double check + let mut monetary_mass = 0u64; // u128 + // wallet index to generate random id + let mut wallet_index: u32 = 0; + // counter for online authorities at genesis + let mut counter_online_authorities = 0; + // track identity index + let mut identity_index = HashMap::new(); + // counter for certifications + let mut counter_cert = 0u32; + // counter for smith certifications + let mut counter_smith_cert = 0u32; + // track inactive identities + let mut inactive_identities = HashMap::<u32, &str>::new(); + + // declare variables to fill in genesis + // ------------------------------------- + // account inserted in genesis + let mut accounts = BTreeMap::new(); + // members of technical committee + let mut technical_committee_members = Vec::new(); + // memberships + let mut memberships = BTreeMap::new(); + // identities + let mut identities = Vec::new(); + // certifications + let mut certs_by_receiver = BTreeMap::new(); + // initial authorities + let mut initial_authorities = BTreeMap::new(); + // session keys + let mut session_keys_map = BTreeMap::new(); + // smith memberships + let mut smith_memberships = BTreeMap::new(); + // smith certifications + let mut smith_certs_by_receiver = BTreeMap::new(); + + // SIMPLE WALLETS // + for (pubkey, balance) in &genesis_data.wallets { + // check existential deposit + if balance < &EXISTENTIAL_DEPOSIT { + log::warn!("wallet {pubkey} has {balance} cǦT which is below {EXISTENTIAL_DEPOSIT}"); + fatal = true; + } + + // double check the monetary mass + monetary_mass += balance; + + wallet_index += 1; + // json prevents duplicate wallets + accounts.insert( + pubkey.clone(), + GenesisAccountData { + random_id: H256(blake2_256(&(wallet_index, &pubkey).encode())), + balance: *balance, + is_identity: false, + }, + ); + } + + // IDENTITIES // + for (name, identity) in &genesis_data.identities { + // identity name + if !validate_idty_name(&name) { + return Err(format!("Identity name '{}' is invalid", &name)); + } + + // check existential deposit + if identity.balance < EXISTENTIAL_DEPOSIT { + if identity.membership_expire_on != 0 { + log::warn!( + "expired identity {name} has {} cǦT which is below {EXISTENTIAL_DEPOSIT}", + identity.balance + ); + fatal = true; + } else { + // member identities can still be below existential deposit thanks to sufficient + log::info!( + "identity {name} has {} cǦT which is below {EXISTENTIAL_DEPOSIT}", + identity.balance + ); + } + } + + // Money + // check that wallet with same owner_key does not exist + if accounts.get(&identity.owner_key).is_some() { + log::warn!( + "{name} owner_key {} already exists as a simple wallet", + identity.owner_key + ); + fatal = true; + } + // insert as an account + accounts.insert( + identity.owner_key.clone(), + GenesisAccountData { + random_id: H256(blake2_256(&(identity.index, &identity.owner_key).encode())), + balance: identity.balance, + is_identity: true, + }, + ); + + // double check the monetary mass + monetary_mass += identity.balance; + + // insert identity + // check that index does not already exist + if let Some(other_name) = identity_index.get(&identity.index) { + log::warn!( + "{other_name} already has identity index {} of {name}", + identity.index + ); + fatal = true; + } + identity_index.insert(identity.index, name); + + // only add the identity if not expired + if identity.membership_expire_on != 0 { + identities.push(GenesisIdty { + index: identity.index, + name: common_runtime::IdtyName::from(name.as_str()), + value: common_runtime::IdtyValue { + data: IdtyData::new(), + next_creatable_identity_on: identity.next_cert_issuable_on, + old_owner_key: match identity.old_owner_key.clone() { + Some(address) => Some((address, 0)), // FIXME old owner key expiration + None => None, + }, + // old_owner_key: None, + owner_key: identity.owner_key.clone(), + // TODO remove the removable_on field of identity + removable_on: 0, + status: IdtyStatus::Validated, + }, + }); + } else { + inactive_identities.insert(identity.index, name); + }; + + // insert the membershup data (only if not expired) + if identity.membership_expire_on != 0 { + memberships.insert( + identity.index, + MembershipData { + expire_on: identity.membership_expire_on, + }, + ); + } + } + + // Technical Comittee // + // NOTE : when changing owner key, the technical committee is not changed + for name in &genesis_data.technical_committee { + if let Some(identity) = &genesis_data.identities.get(name) { + technical_committee_members.push(identity.owner_key.clone()); + } else { + log::error!("Identity '{}' does not exist", name); + fatal = true; + } + } + + // CERTIFICATIONS // + for (_, identity) in &genesis_data.identities { + let mut certs = BTreeMap::new(); + for (issuer, expire_on) in &identity.certs_received { + if let Some(issuer) = &genesis_data.identities.get(issuer) { + certs.insert(issuer.index, Some(expire_on.clone())); + counter_cert += 1; + } else { + log::error!("Identity '{}' does not exist", issuer); + fatal = true; + }; + } + certs_by_receiver.insert(identity.index, certs); + } + + // SMITHS SUB-WOT // + for (name, smith_data) in &genesis_data.smiths { + // check that smith exists + if let Some(identity) = &genesis_data.identities.get(&name.clone()) { + // Initial authorities and session keys + let session_keys_bytes = if let Some(declared_session_keys) = &smith_data.session_keys { + counter_online_authorities += 1; + // insert authority as online + initial_authorities.insert(identity.index, (identity.owner_key.clone(), true)); + // decode session keys or force to given value + match maybe_force_authority { + Some(ref bytes) => bytes.clone(), + None => hex::decode(&declared_session_keys[2..]) + .map_err(|_| format!("invalid session keys for idty {}", &name))?, + } + } else { + // still authority but offline + initial_authorities.insert(identity.index, (identity.owner_key.clone(), false)); + // fake session keys + let mut fake_bytes = Vec::with_capacity(128); + for _ in 0..4 { + fake_bytes.extend_from_slice(identity.owner_key.as_ref()) + } + fake_bytes + }; + + // insert session keys to map + session_keys_map.insert( + identity.owner_key.clone(), + SessionKeys::decode(&mut &session_keys_bytes[..]).unwrap(), + ); + + // smith certifications + let mut certs = BTreeMap::new(); + for issuer in &smith_data.certs_received { + let issuer_index = &genesis_data + .identities + .get(issuer) + .ok_or(format!("Identity '{}' does not exist", issuer))? + .index; + certs.insert(*issuer_index, Some(SMITH_CERTS_EXPIRE_ON)); + counter_smith_cert += 1; + } + smith_certs_by_receiver.insert(identity.index, certs); + + // smith memberships + smith_memberships.insert( + identity.index, + MembershipData { + expire_on: SMITH_MEMBERSHIP_EXPIRE_ON, + }, + ); + } else { + log::error!("Smith '{}' does not correspond to exising identity", &name); + fatal = true; + } + } + + // Verify certifications coherence (can be ignored for old users) + for (idty_index, receiver_certs) in &certs_by_receiver { + if receiver_certs.len() < MIN_CERT as usize { + let name = identity_index.get(idty_index).unwrap(); + let identity = genesis_data.identities.get(name.clone()).unwrap(); + if identity.membership_expire_on != 0 { + log::warn!( + "[{}] has received only {}/{} certifications", + name, + receiver_certs.len(), + MIN_CERT + ); + fatal = true; + } + } + } + + // Verify smith certifications coherence + for (idty_index, certs) in &smith_certs_by_receiver { + if certs.len() < SMITH_MIN_CERT as usize { + log::warn!( + "[{}] has received only {}/{} smith certifications", + identity_index.get(idty_index).unwrap(), + certs.len(), + SMITH_MIN_CERT + ); + fatal = true; + } + } + + // check number of online authorities + if counter_online_authorities != 1 { + log::error!("one and only one smith must be online, not {counter_online_authorities}"); + } + + // check monetary mass + if monetary_mass != genesis_data.initial_monetary_mass { + log::warn!( + "actuel monetary_mass ({monetary_mass}) and initial_monetary_mass ({}) do not match", + genesis_data.initial_monetary_mass + ); + fatal = true; + } + + // give genesis info + log::info!( + "prepared genesis with: + - {} accounts ({} identities, {} simple wallets) + - {} total identities ({} active, {} inactive) + - {} smiths + - {} initial online authorities + - {} certifications + - {} smith certifications + - {} members in technical committee", + accounts.len(), + identity_index.len(), + &genesis_data.wallets.len(), + identity_index.len(), + identities.len(), + inactive_identities.len(), + smith_memberships.len(), + counter_online_authorities, + counter_cert, + counter_smith_cert, + technical_committee_members.len(), + ); + + // some more checks + assert_eq!(identities.len(), memberships.len()); + assert_eq!(smith_memberships.len(), initial_authorities.len()); + assert_eq!(smith_memberships.len(), session_keys_map.len()); + assert_eq!( + identity_index.len(), + identities.len() + inactive_identities.len() + ); + assert_eq!( + accounts.len(), + identity_index.len() + &genesis_data.wallets.len() + ); + // no inactive tech comm + for tech_com_member in &genesis_data.technical_committee { + assert!(!inactive_identities.values().any(|&v| v == tech_com_member)); + } + // no inactive smith + for (smith, _) in &genesis_data.smiths { + assert!(!inactive_identities.values().any(|&v| v == smith)); + } + + // check the logs to see all the fatal error preventing from starting gtest currency + if fatal { + log::error!("some previously logged error prevent from building a sane genesis"); + panic!(); + } + + // return genesis config + Ok(gtest_runtime::GenesisConfig { + system: SystemConfig { + // Add Wasm runtime to storage. + code: wasm_binary.to_vec(), + }, + account: AccountConfig { accounts }, + 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: genesis_data.sudo_key, + }, + technical_committee: TechnicalCommitteeConfig { + members: technical_committee_members, + ..Default::default() + }, + identity: IdentityConfig { identities }, + cert: CertConfig { + apply_cert_period_at_genesis: false, + 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: genesis_data.first_ud_reeval, + first_ud: genesis_data.first_ud, + initial_monetary_mass: genesis_data.initial_monetary_mass, + }, + treasury: Default::default(), + }) +} diff --git a/node/src/service/client.rs b/node/src/service/client.rs index 16cb4b412..ca2c0da82 100644 --- a/node/src/service/client.rs +++ b/node/src/service/client.rs @@ -307,20 +307,29 @@ trait BenchmarkCallSigner<RuntimeCall: Encode + Clone, Signer: Pair> { ) -> sp_runtime::OpaqueExtrinsic; } +#[cfg(feature = "g1")] +use g1_runtime as runtime; #[cfg(feature = "gdev")] -impl BenchmarkCallSigner<gdev_runtime::RuntimeCall, sp_core::sr25519::Pair> - for super::FullClient<gdev_runtime::RuntimeApi, super::GDevExecutor> -{ +use gdev_runtime as runtime; +#[cfg(feature = "gdev")] +type FullClient = super::FullClient<runtime::RuntimeApi, super::GDevExecutor>; +#[cfg(feature = "gtest")] +use gtest_runtime as runtime; +#[cfg(feature = "gtest")] +type FullClient = super::FullClient<runtime::RuntimeApi, super::GTestExecutor>; + +#[cfg(any(feature = "gdev", feature = "gtest"))] +impl BenchmarkCallSigner<runtime::RuntimeCall, sp_core::sr25519::Pair> for FullClient { fn sign_call( &self, - call: gdev_runtime::RuntimeCall, + call: runtime::RuntimeCall, nonce: u32, current_block: u64, period: u64, genesis: sp_core::H256, acc: sp_core::sr25519::Pair, ) -> sp_runtime::OpaqueExtrinsic { - use gdev_runtime as runtime; + // use runtime; let extra: runtime::SignedExtra = ( frame_system::CheckNonZeroSender::<runtime::Runtime>::new(), diff --git a/resources/gtest.json b/resources/gtest.json new file mode 100644 index 000000000..9050fa621 --- /dev/null +++ b/resources/gtest.json @@ -0,0 +1,331 @@ +{ + "first_ud": 10000, + "first_ud_reeval": 100800, + "initial_monetary_mass": 531481, + "identities": { + "old_user1": { + "index": 7777, + "owner_key": "5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw", + "membership_expire_on": 0, + "next_cert_issuable_on": 0, + "balance": 12, + "certs_received": { + "elois": 10 + } + }, + "old_user2": { + "index": 8888, + "owner_key": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", + "membership_expire_on": 0, + "next_cert_issuable_on": 0, + "balance": 12, + "certs_received": { + "elois": 10 + } + }, + "old_user3": { + "index": 6666, + "owner_key": "5Fxune7f71ZbpP2FoY3mhYcmM596Erhv1gRue4nsPwkxMR4n", + "membership_expire_on": 0, + "next_cert_issuable_on": 0, + "balance": 12, + "certs_received": { + "elois": 10 + } + }, + "elois": { + "index": 2, + "owner_key": "5CUjxa4wVKMj3FqKdqAUf7zcEMr4MYAjXeWmUf44B41neLmJ", + "membership_expire_on": 1000, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "poka": 100, + "cgeek": 100, + "vit": 100, + "tuxmain": 100, + "HugoTrentesaux": 100, + "ManUtopiK": 100, + "moul": 100, + "1000i100": 100, + "kapis": 100, + "DavidB": 100, + "Gamaliel": 100, + "wellno1": 100, + "old_user1": 50 + } + }, + "HugoTrentesaux": { + "index": 344, + "owner_key": "5Dq8xjvkmbz7q4g2LbZgyExD26VSCutfEc6n4W4AfQeVHZqz", + "old_owner_key": "5Dq8xjvkmbz7q4g2LbZgyExD26VSCutfEc6n4W4AfQeVHZqz", + "membership_expire_on": 1000, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "poka": 100, + "vit": 100, + "tuxmain": 100, + "elois": 100, + "moul": 100, + "1000i100": 100, + "ManUtopiK": 100, + "kapis": 100, + "DavidB": 100, + "Gamaliel": 100, + "wellno1": 100 + } + }, + "poka": { + "index": 62, + "owner_key": "5CQ8T4qpbYJq7uVsxGPQ5q2df7x3Wa4aRY6HUWMBYjfLZhnn", + "membership_expire_on": 1000, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "cgeek": 100, + "vit": 100, + "tuxmain": 100, + "elois": 100, + "HugoTrentesaux": 100 + } + }, + "tuxmain": { + "index": 1401, + "owner_key": "5D2DnScFpxoEUXDwZbJH18tRsQMygBSh1F6YCcWvTYzKY2W7", + "membership_expire_on": 1000, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "cgeek": 100, + "elois": 100, + "HugoTrentesaux": 100, + "ManUtopiK": 100, + "poka": 100, + "moul": 100, + "1000i100": 100 + } + }, + "vit": { + "index": 20, + "owner_key": "5DqkYGjiT5TFm2pGMUBMuZW4sw13vDEZmxqkxmky5AoQvUwd", + "membership_expire_on": 1000, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "cgeek": 100, + "elois": 100, + "HugoTrentesaux": 100, + "ManUtopiK": 100, + "poka": 100, + "tuxmain": 100, + "moul": 100 + } + }, + "cgeek": { + "index": 1, + "owner_key": "5DP7ze5cJwtHbqXaP2aNtJ5jkULzcTCqXuMzDvk9JjneFjfq", + "membership_expire_on": 1000, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "poka": 100, + "vit": 100, + "tuxmain": 100, + "elois": 100, + "HugoTrentesaux": 100, + "moul": 100 + } + }, + "ManUtopiK": { + "index": 2316, + "owner_key": "5DUjwHRqPayt3tAZk1fqEgU99xZB9jzBHKy2sMSTNcc7m9D1", + "membership_expire_on": 1000, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "poka": 100, + "vit": 100, + "tuxmain": 100, + "elois": 100, + "HugoTrentesaux": 100, + "1000i100": 100 + } + }, + "1000i100": { + "index": 72, + "owner_key": "5CCrBS67BrpBx3ihGHc72HZp3eHHbETxWFuNfwbbdoGSJFN8", + "membership_expire_on": 1000, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "elois": 100, + "poka": 100, + "cgeek": 100, + "vit": 100, + "tuxmain": 100, + "HugoTrentesaux": 100, + "ManUtopiK": 100, + "moul": 100 + } + }, + "moul": { + "index": 32, + "owner_key": "5EPGRtBYLwfDinnaAXsscM3FkffRADpJRrkZETqW8N6uhp22", + "membership_expire_on": 1000, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "ManUtopiK": 100, + "vit": 100, + "tuxmain": 100, + "elois": 100, + "HugoTrentesaux": 100, + "1000i100": 100 + } + }, + "Gamaliel": { + "index": 3994, + "owner_key": "5DS9iWBXW56N7XbeVyyp6CB7m4LeE5fGJYrUR9HDSStT5JN9", + "membership_expire_on": 0, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "DavidB": 100, + "wellno1": 100, + "kapis": 100 + } + }, + "kapis": { + "index": 3883, + "owner_key": "5HJyyim1W8Y1UD8LAbBL7cQQLjGofMoD45RtRSAmhkFQxrvs", + "membership_expire_on": 22, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "DavidB": 100, + "wellno1": 100, + "Gamaliel": 100, + "HugoTrentesaux": 100, + "elois": 100 + } + }, + "DavidB": { + "index": 2277, + "owner_key": "5HKTDdXHj3MojiPRcEsVU9JaHyif5gg2br1sy3JZbsjuQebP", + "membership_expire_on": 0, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "kapis": 100, + "wellno1": 100, + "Gamaliel": 100 + } + }, + "wellno1": { + "index": 9999, + "owner_key": "5DyEZNkSuK5i8wZiXtvL63zqpye9zPBsPRauCjQkMuVzZYX7", + "membership_expire_on": 0, + "next_cert_issuable_on": 100, + "balance": 10000, + "certs_received": { + "DavidB": 100, + "kapis": 100, + "Gamaliel": 100 + } + } + }, + "smiths": { + "elois": { + "certs_received": [ + "poka", + "cgeek", + "vit", + "tuxmain", + "HugoTrentesaux", + "kapis" + ], + "session_keys": "0x92743b12d55242276539d7256951cdfda85371caefbd325396da9331011b737d14084d2537f77e786a75b9bcbe351051fad52946ec211724b5e8c93bb8aa7a6f14084d2537f77e786a75b9bcbe351051fad52946ec211724b5e8c93bb8aa7a6f14084d2537f77e786a75b9bcbe351051fad52946ec211724b5e8c93bb8aa7a6f" + }, + "poka": { + "certs_received": [ + "cgeek", + "vit", + "tuxmain", + "elois", + "HugoTrentesaux" + ] + }, + "tuxmain": { + "certs_received": [ + "cgeek", + "elois", + "HugoTrentesaux", + "poka", + "kapis" + ] + }, + "vit": { + "certs_received": [ + "cgeek", + "elois", + "HugoTrentesaux", + "poka", + "tuxmain" + ] + }, + "cgeek": { + "certs_received": [ + "poka", + "vit", + "tuxmain", + "elois", + "HugoTrentesaux" + ] + }, + "HugoTrentesaux": { + "certs_received": [ + "poka", + "vit", + "tuxmain", + "elois", + "kapis" + ] + }, + "1000i100": { + "certs_received": [ + "cgeek", + "vit", + "tuxmain", + "elois", + "HugoTrentesaux", + "poka" + ] + }, + "kapis": { + "certs_received": [ + "elois", + "tuxmain", + "HugoTrentesaux", + "1000i100", + "vit" + ] + } + }, + "wallets": { + "5C558MohmEJ3Z1o1wv8AAR7dFc3ZsUQZGBUHLxvHetWaN53U": 304, + "5C56NAAgLYBXEiWsRhRD2vKZquSgZHULUuiCWpcVg8k21Kex": 5000, + "5C59KZ3X6AEt23FSLxsLvtXqN41SHyaWa5CQmXiYLUek3ECd": 24507, + "5C5KjPbZfvwFXh24KkKEjeofCNng2tZM4YjJN8mMYhLAzn8H": 1042, + "5C5VrnckbfuizDDFn9ubcQDEKSnRFbB3jfa5kMaQxmRFzLJX": 10800, + "5C5YfjAyZnLPfyMQNreng5knFW87PRTVphRhPUXpWszF7sB9": 200, + "5C5YfjAyZnLPfyMQNreng5knFW87PRTVphRkQoupWszF7pte": 359592 + }, + "sudo_key": "5Hm8sBbwuLAU99dBezvgtnRmZCrUy9mhqmbQMFyGTaeATYg7", + "technical_committee": [ + "elois", + "cgeek", + "tuxmain", + "HugoTrentesaux" + ] +} \ No newline at end of file diff --git a/runtime/g1/README.md b/runtime/g1/README.md new file mode 100644 index 000000000..69f65e64a --- /dev/null +++ b/runtime/g1/README.md @@ -0,0 +1,4 @@ +# Ğ1 runtime + +Ğ1 runtime is the one used in the production Ğ1 network. +It is the same as ĞTest runtime with a bit of delay on updates necessary to test them. \ No newline at end of file diff --git a/runtime/gdev/README.md b/runtime/gdev/README.md new file mode 100644 index 000000000..8047cd84f --- /dev/null +++ b/runtime/gdev/README.md @@ -0,0 +1,5 @@ +# ĞDev runtime + +Gdev runtime exists for development purposes. It can be changed without consequenses for exploration. +It uses the pallet `duniter-test-parameters` to be able to change parameters values more easily without runtime upgrades. +This is the runtime used by default when running a local blockchain. \ No newline at end of file diff --git a/runtime/gtest/Cargo.toml b/runtime/gtest/Cargo.toml index 034ab8621..a3802c838 100644 --- a/runtime/gtest/Cargo.toml +++ b/runtime/gtest/Cargo.toml @@ -16,34 +16,53 @@ targets = ['x86_64-unknown-linux-gnu'] [features] default = ['std'] runtime-benchmarks = [ - 'frame-benchmarking', + 'common-runtime/runtime-benchmarks', + 'frame-benchmarking/runtime-benchmarks', 'frame-support/runtime-benchmarks', 'frame-system-benchmarking', 'frame-system/runtime-benchmarks', 'hex-literal', + 'pallet-authority-members/runtime-benchmarks', + 'pallet-babe/runtime-benchmarks', 'pallet-balances/runtime-benchmarks', + 'pallet-certification/runtime-benchmarks', + 'pallet-collective/runtime-benchmarks', + 'pallet-duniter-account/runtime-benchmarks', + 'pallet-duniter-wot/runtime-benchmarks', + 'pallet-grandpa/runtime-benchmarks', 'pallet-identity/runtime-benchmarks', + 'pallet-membership/runtime-benchmarks', + 'pallet-provide-randomness/runtime-benchmarks', + 'pallet-im-online/runtime-benchmarks', + 'pallet-multisig/runtime-benchmarks', + 'pallet-oneshot-account/runtime-benchmarks', + 'pallet-preimage/runtime-benchmarks', + 'pallet-session-benchmarking/runtime-benchmarks', + 'pallet-proxy/runtime-benchmarks', + 'pallet-scheduler/runtime-benchmarks', + 'pallet-timestamp/runtime-benchmarks', 'pallet-treasury/runtime-benchmarks', 'pallet-universal-dividend/runtime-benchmarks', - 'common-runtime/runtime-benchmarks', + 'pallet-upgrade-origin/runtime-benchmarks', + 'pallet-utility/runtime-benchmarks', 'sp-runtime/runtime-benchmarks', ] std = [ 'codec/std', + 'common-runtime/std', 'frame-executive/std', 'frame-support/std', 'frame-system-rpc-runtime-api/std', 'frame-system/std', "frame-try-runtime/std", - 'pallet-atomic-swap/std', 'log/std', + 'pallet-atomic-swap/std', 'pallet-authority-discovery/std', 'pallet-authority-members/std', 'pallet-babe/std', 'pallet-balances/std', 'pallet-certification/std', 'pallet-collective/std', - 'pallet-duniter-test-parameters/std', 'pallet-duniter-account/std', 'pallet-duniter-wot/std', 'pallet-grandpa/std', @@ -53,8 +72,10 @@ std = [ 'pallet-provide-randomness/std', 'pallet-im-online/std', 'pallet-multisig/std', + "pallet-offences/std", 'pallet-preimage/std', 'pallet-proxy/std', + "pallet-scheduler/std", 'pallet-session/std', 'pallet-sudo/std', 'pallet-universal-dividend/std', @@ -63,8 +84,9 @@ std = [ 'pallet-transaction-payment-rpc-runtime-api/std', 'pallet-transaction-payment/std', 'pallet-treasury/std', - 'common-runtime/std', - 'serde', + 'pallet-utility/std', + "serde/std", + "serde_derive", 'sp-api/std', 'sp-arithmetic/std', 'sp-authority-discovery/std', @@ -81,6 +103,7 @@ std = [ 'sp-version/std', ] try-runtime = [ + "common-runtime/try-runtime", "frame-executive/try-runtime", "frame-try-runtime", "frame-system/try-runtime", @@ -113,7 +136,6 @@ sp-keyring = { git = 'https://github.com/duniter/substrate', branch = 'duniter-s common-runtime = { path = "../common", default-features = false } pallet-authority-members = { path = '../../pallets/authority-members', default-features = false } pallet-certification = { path = '../../pallets/certification', default-features = false } -pallet-duniter-test-parameters = { path = '../../pallets/duniter-test-parameters', default-features = false } pallet-duniter-account = { path = '../../pallets/duniter-account', default-features = false } pallet-duniter-wot = { path = '../../pallets/duniter-wot', default-features = false } pallet-identity = { path = '../../pallets/identity', default-features = false } @@ -121,6 +143,7 @@ pallet-membership = { path = '../../pallets/membership', default-features = fals pallet-oneshot-account = { path = '../../pallets/oneshot-account', default-features = false } pallet-provide-randomness = { path = '../../pallets/provide-randomness', default-features = false } pallet-universal-dividend = { path = '../../pallets/universal-dividend', default-features = false } +pallet-session-benchmarking = { path = '../../pallets/session-benchmarking', default-features = false } pallet-upgrade-origin = { path = '../../pallets/upgrade-origin', default-features = false } sp-membership = { path = '../../primitives/membership', default-features = false } @@ -129,15 +152,14 @@ codec = { package = "parity-scale-codec", version = "3.1.5", features = ["derive log = { version = "0.4.17", default-features = false } hex-literal = { version = '0.3.1', optional = true } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } -serde = { version = "1.0.101", optional = true, features = ["derive"] } +serde = { version = "1.0.101", default-features = false } +serde_derive = { version = "1.0.101", optional = true } # substrate -frame-benchmarking = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', optional = true } frame-try-runtime = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', default-features = false, optional = true } frame-executive = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', default-features = false } frame-support = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', default-features = false } frame-system = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', default-features = false } -frame-system-benchmarking = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', optional = true } frame-system-rpc-runtime-api = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', default-features = false} pallet-atomic-swap = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', default-features = false } pallet-authority-discovery = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', default-features = false } @@ -172,3 +194,7 @@ sp-session = { git = 'https://github.com/duniter/substrate', branch = 'duniter-s sp-std = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', default-features = false } sp-transaction-pool = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', default-features = false } sp-version = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', default-features = false } + +# substrate benchmarking +frame-benchmarking = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', default-features = false, optional = true } +frame-system-benchmarking = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.32', default-features = false, optional = true } diff --git a/runtime/gtest/README.md b/runtime/gtest/README.md new file mode 100644 index 000000000..f7d7a6dcd --- /dev/null +++ b/runtime/gtest/README.md @@ -0,0 +1,10 @@ +# Ğtest runtime + +ĞTest runtime is the one used in ĞTest network, which is a test network for Ǧ1. +It has a sudo account to be able to test runtime upgrades more easily before deploying them to Ğ1 network. + +## ĞTest chainspecs + +ĞTest chainspecs are intended to use with real data. +There is no particular case for genesis identities. In `gtest.json`: +- no `genesis_parameters` \ No newline at end of file diff --git a/runtime/gtest/src/lib.rs b/runtime/gtest/src/lib.rs index 3d2282f26..3b94d4add 100644 --- a/runtime/gtest/src/lib.rs +++ b/runtime/gtest/src/lib.rs @@ -22,6 +22,10 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +#[cfg(feature = "runtime-benchmarks")] +#[macro_use] +extern crate frame_benchmarking; + pub mod parameters; pub use self::parameters::*; @@ -29,8 +33,8 @@ pub use common_runtime::{ constants::*, entities::*, handlers::*, AccountId, Address, Balance, BlockNumber, FullIdentificationOfImpl, GetCurrentEpochIndex, Hash, Header, IdtyIndex, Index, Signature, }; +pub use frame_system::Call as SystemCall; pub use pallet_balances::Call as BalancesCall; -pub use pallet_identity::{IdtyStatus, IdtyValue}; pub use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_session::historical as session_historical; pub use pallet_timestamp::Call as TimestampCall; @@ -112,7 +116,7 @@ pub type SignedExtra = ( frame_system::CheckTxVersion<Runtime>, frame_system::CheckGenesis<Runtime>, frame_system::CheckEra<Runtime>, - frame_system::CheckNonce<Runtime>, + pallet_oneshot_account::CheckNonce<Runtime>, frame_system::CheckWeight<Runtime>, pallet_transaction_payment::ChargeTransactionPayment<Runtime>, ); @@ -161,14 +165,16 @@ mod benches { } pub struct BaseCallFilter; + +// implement filter impl Contains<RuntimeCall> for BaseCallFilter { fn contains(call: &RuntimeCall) -> bool { !matches!( call, - RuntimeCall::System( - frame_system::Call::remark { .. } | frame_system::Call::remark_with_event { .. } - ) | RuntimeCall::Membership( - pallet_membership::Call::claim_membership { .. } + // in main web of trust, membership request and revoke are handeled through identity pallet + // the user can not call them directly + RuntimeCall::Membership( + pallet_membership::Call::request_membership { .. } | pallet_membership::Call::revoke_membership { .. } ) | RuntimeCall::Session(_) ) @@ -194,6 +200,7 @@ pub enum ProxyType { AlmostAny = 0, TransferOnly = 1, CancelProxy = 2, + TechnicalCommitteePropose = 3, } impl Default for ProxyType { fn default() -> Self { @@ -222,11 +229,19 @@ impl frame_support::traits::InstanceFilter<RuntimeCall> for ProxyType { RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) ) } + ProxyType::TechnicalCommitteePropose => { + matches!( + c, + RuntimeCall::TechnicalCommittee(pallet_collective::Call::propose { .. }) + ) + } } } } +// Configure FRAME pallets to include in runtime. common_runtime::pallets_config! { + impl pallet_sudo::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; @@ -254,7 +269,7 @@ construct_runtime!( TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event<T>} = 32, OneshotAccount: pallet_oneshot_account::{Pallet, Call, Storage, Event<T>} = 7, - // Consensus support. + // Consensus support AuthorityMembers: pallet_authority_members::{Pallet, Call, Storage, Config<T>, Event<T>} = 10, Authorship: pallet_authorship::{Pallet, Call, Storage} = 11, Offences: pallet_offences::{Pallet, Storage, Event} = 12, @@ -264,7 +279,7 @@ construct_runtime!( ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>} = 16, AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config} = 17, - // Governance stuff. + // Governance stuff Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>} = 20, UpgradeOrigin: pallet_upgrade_origin::{Pallet, Call, Event} = 21, Preimage: pallet_preimage::{Pallet, Call, Storage, Event<T>} = 22, -- GitLab