diff --git a/node/src/chain_spec/gdev.rs b/node/src/chain_spec/gdev.rs index 6d8b46dc340ee5c9715d659861820a37737f68f0..32041088d9b879b2e78c343504dceb8d72b95abc 100644 --- a/node/src/chain_spec/gdev.rs +++ b/node/src/chain_spec/gdev.rs @@ -27,10 +27,8 @@ use gdev_runtime::{ use sc_service::ChainType; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_babe::AuthorityId as BabeId; -use sp_core::{blake2_256, sr25519, Encode, H256}; +use sp_core::{sr25519, Encode}; use sp_finality_grandpa::AuthorityId as GrandpaId; -use sp_membership::MembershipData; -use std::collections::BTreeMap; pub type AuthorityKeys = ( AccountId, @@ -72,14 +70,14 @@ fn get_session_keys_from_seed(s: &str) -> SessionKeys { } /// get environment variable -fn get_env<T: std::str::FromStr>(env_var_name: &'static str, default_value: T) -> T { +pub fn get_env<T: std::str::FromStr>(env_var_name: &'static str, default_value: T) -> T { std::env::var(env_var_name) .map_or(Ok(default_value), |s| s.parse()) .unwrap_or_else(|_| panic!("{} must be a {}", env_var_name, std::any::type_name::<T>())) } /// make session keys struct -fn session_keys( +pub fn session_keys( grandpa: GrandpaId, babe: BabeId, im_online: ImOnlineId, @@ -96,145 +94,100 @@ fn session_keys( /// generate development chainspec with Alice validator pub fn development_chain_spec() -> Result<ChainSpec, String> { let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; - - // custom genesis - if std::env::var("DUNITER_GENESIS_CONFIG").is_ok() { - super::gen_genesis_data::generate_genesis_data( - |genesis_data| { - ChainSpec::from_genesis( - // Name - "Development", - // ID - "gdev", - // chain type - sc_service::ChainType::Development, - // constructor - move || genesis_data_to_gdev_genesis_conf(genesis_data.clone(), 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, - ) - }, - Some(get_session_keys_from_seed("Alice").encode()), - ) - } - // generated genesis - else { - Ok(ChainSpec::from_genesis( - // Name - "Development", - // ID - "gdev", - // 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!({ + gen_genesis_data::generate_genesis_data( + json_file_path.to_owned(), + |genesis_data| { + ChainSpec::from_genesis( + // Name + "Development", + // ID + "gdev", + // chain type + sc_service::ChainType::Development, + // constructor + move || genesis_data_to_gdev_genesis_conf(genesis_data.clone(), 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, - )) - } + }) + .as_object() + .expect("must be a map") + .clone(), + ), + // Extensions + None, + ) + }, + Some(( + "Alice".to_owned(), + get_session_keys_from_seed("Alice").encode(), + )), + ) } /// generate chainspecs used for benchmarks pub fn benchmark_chain_spec() -> Result<ChainSpec, String> { let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; - - Ok(ChainSpec::from_genesis( - // Name - "Development", - // ID - "gdev-benchmark", - ChainType::Development, - move || { - gen_genesis_for_benchmark_chain( - wasm_binary, - // Initial authorities len - 1, - // Initial smiths members len - 3, - // Inital identities len - 4, - // Sudo account - get_account_id_from_seed::<sr25519::Public>("Alice"), - true, + gen_genesis_data::generate_genesis_data_for_benchmark_chain( + // Initial authorities len + 1, + // Initial smiths members len + 3, + // Inital identities len + 4, + // Sudo account + get_account_id_from_seed::<sr25519::Public>("Alice"), + true, + |genesis_data| { + ChainSpec::from_genesis( + // Name + "Development", + // ID + "gdev-benchmark", + ChainType::Development, + // constructor + move || genesis_data_to_gdev_genesis_conf(genesis_data.clone(), 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, ) }, - // 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, - )) + ) } /// generate live network chainspecs -pub fn gen_live_conf() -> Result<ChainSpec, String> { +pub fn gen_live_conf(json_file_path: &str) -> Result<ChainSpec, String> { let wasm_binary = WASM_BINARY.ok_or_else(|| "wasm not available".to_string())?; super::gen_genesis_data::generate_genesis_data( + json_file_path.to_owned(), |genesis_data| { ChainSpec::from_genesis( // Name @@ -282,402 +235,48 @@ pub fn local_testnet_config( initial_identities_len: usize, ) -> Result<ChainSpec, String> { let wasm_binary = WASM_BINARY.ok_or_else(|| "wasm not available".to_string())?; - - Ok(ChainSpec::from_genesis( - // Name - "Ğdev Local Testnet", - // ID - "gdev_local", - ChainType::Local, - move || { - gen_genesis_for_local_chain( - wasm_binary, - // Initial authorities len - initial_authorities_len, - // Initial smiths len, - initial_smiths_len, - // Initial identities len - initial_identities_len, - // 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, - )) -} - -/// generate genesis -fn gen_genesis_for_local_chain( - wasm_binary: &[u8], - initial_authorities_len: usize, - initial_smiths_len: usize, - initial_identities_len: usize, - root_key: AccountId, - _enable_println: bool, -) -> gdev_runtime::GenesisConfig { - assert!(initial_identities_len <= 6); - assert!(initial_smiths_len <= initial_identities_len); - assert!(initial_authorities_len <= initial_smiths_len); - - let babe_epoch_duration = get_env("DUNITER_BABE_EPOCH_DURATION", 30) as u64; - let cert_validity_period = get_env("DUNITER_CERT_VALIDITY_PERIOD", 1_000); - let membership_period = get_env("DUNITER_MEMBERSHIP_PERIOD", 1_000); - let smith_cert_validity_period = get_env("DUNITER_SMITH_CERT_VALIDITY_PERIOD", 1_000); - let smith_membership_period = get_env("DUNITER_SMITH_MEMBERSHIP_PERIOD", 1_000); - let ud_creation_period = get_env("DUNITER_UD_CREATION_PERIOD", 60_000); - let ud_reeval_period = get_env("DUNITER_UD_REEEVAL_PERIOD", 1_200_000); - let ud = 1_000; - - let initial_smiths = (0..initial_smiths_len) - .map(|i| get_authority_keys_from_seed(NAMES[i])) - .collect::<Vec<AuthorityKeys>>(); - let initial_identities = (0..initial_identities_len) - .map(|i| { - ( - IdtyName::from(NAMES[i]), - get_account_id_from_seed::<sr25519::Public>(NAMES[i]), - ) - }) - .collect::<BTreeMap<IdtyName, AccountId>>(); - - gdev_runtime::GenesisConfig { - system: SystemConfig { - // Add Wasm runtime to storage. - code: wasm_binary.to_vec(), - }, - account: AccountConfig { - accounts: initial_identities - .iter() - .enumerate() - .map(|(i, (_, owner_key))| { - ( - owner_key.clone(), - GenesisAccountData { - random_id: H256(blake2_256(&(i as u32, owner_key).encode())), - balance: ud, - is_identity: true, - }, - ) - }) - .collect(), - }, - parameters: ParametersConfig { - parameters: GenesisParameters { - babe_epoch_duration, - cert_period: 15, - cert_max_by_issuer: 10, - cert_min_received_cert_to_issue_cert: 2, - cert_validity_period, - idty_confirm_period: 40, - idty_creation_period: 50, - membership_period, - pending_membership_period: 500, - ud_creation_period, - ud_reeval_period, - smith_cert_period: 15, - smith_cert_max_by_issuer: 8, - smith_cert_min_received_cert_to_issue_cert: 2, - smith_cert_validity_period, - smith_membership_period, - smith_pending_membership_period: 500, - smith_wot_first_cert_issuable_on: 20, - smith_wot_min_cert_for_membership: 2, - wot_first_cert_issuable_on: 20, - wot_min_cert_for_create_idty_right: 2, - wot_min_cert_for_membership: 2, - }, - }, - authority_discovery: Default::default(), - authority_members: AuthorityMembersConfig { - initial_authorities: initial_smiths - .iter() - .enumerate() - .map(|(i, keys)| (i as u32 + 1, (keys.0.clone(), i < initial_authorities_len))) - .collect(), - }, - 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: initial_smiths - .iter() - .map(|x| { - ( - x.0.clone(), - x.0.clone(), - session_keys(x.1.clone(), x.2.clone(), x.3.clone(), x.4.clone()), - ) - }) - .collect::<Vec<_>>(), - }, - sudo: SudoConfig { - // Assign network admin rights. - key: Some(root_key), - }, - technical_committee: TechnicalCommitteeConfig { - members: initial_smiths - .iter() - .map(|x| x.0.clone()) - .collect::<Vec<_>>(), - ..Default::default() - }, - identity: IdentityConfig { - identities: initial_identities - .iter() - .enumerate() - .map(|(i, (name, owner_key))| GenesisIdty { - index: i as u32 + 1, - name: name.clone(), - value: IdtyValue { - data: IdtyData::new(), - next_creatable_identity_on: Default::default(), - old_owner_key: None, - owner_key: owner_key.clone(), - removable_on: 0, - status: IdtyStatus::Validated, - }, - }) - .collect(), - }, - membership: MembershipConfig { - memberships: (1..=initial_identities.len()) - .map(|i| (i as u32, MembershipData { expire_on: 0 })) - .collect(), - }, - cert: CertConfig { - apply_cert_period_at_genesis: false, - certs_by_receiver: clique_wot(initial_identities.len()), - }, - smith_membership: SmithMembershipConfig { - memberships: (1..=initial_smiths_len) - .map(|i| (i as u32, MembershipData { expire_on: 0 })) - .collect(), - }, - smith_cert: SmithCertConfig { - apply_cert_period_at_genesis: false, - certs_by_receiver: clique_wot(initial_smiths_len), - }, - universal_dividend: UniversalDividendConfig { - first_reeval: None, - first_ud: None, - initial_monetary_mass: initial_identities_len as u64 * ud, - ud, - }, - treasury: Default::default(), - } -} - -/// genesis used for benchmark -/// contain identities prepared for testing -fn gen_genesis_for_benchmark_chain( - wasm_binary: &[u8], - initial_authorities_len: usize, - initial_smiths_len: usize, - initial_identities_len: usize, - root_key: AccountId, - _enable_println: bool, -) -> gdev_runtime::GenesisConfig { - assert!(initial_identities_len <= 6); - assert!(initial_smiths_len <= initial_identities_len); - assert!(initial_authorities_len <= initial_smiths_len); - - let babe_epoch_duration = get_env("DUNITER_BABE_EPOCH_DURATION", 30) as u64; - let cert_validity_period = get_env("DUNITER_CERT_VALIDITY_PERIOD", 1_000); - let membership_period = get_env("DUNITER_MEMBERSHIP_PERIOD", 1_000); - let smith_cert_validity_period = get_env("DUNITER_SMITH_CERT_VALIDITY_PERIOD", 1_000); - let smith_membership_period = get_env("DUNITER_SMITH_MEMBERSHIP_PERIOD", 1_000); - let ud_creation_period = get_env("DUNITER_UD_CREATION_PERIOD", 60_000); - let ud_reeval_period = get_env("DUNITER_UD_REEEVAL_PERIOD", 1_200_000); - let ud = 1_000; - - let initial_smiths = (0..initial_smiths_len) - .map(|i| get_authority_keys_from_seed(NAMES[i])) - .collect::<Vec<AuthorityKeys>>(); - let initial_identities = (0..initial_identities_len) - .map(|i| { - ( - IdtyName::from(NAMES[i]), - get_account_id_from_seed::<sr25519::Public>(NAMES[i]), + gen_genesis_data::generate_genesis_data_for_local_chain( + // Initial authorities len + initial_authorities_len, + // Initial smiths len, + initial_smiths_len, + // Initial identities len + initial_identities_len, + // Sudo account + get_account_id_from_seed::<sr25519::Public>("Alice"), + true, + |genesis_data| { + ChainSpec::from_genesis( + // Name + "Ğdev Local Testnet", + // ID + "gdev_local", + ChainType::Local, + // constructor + move || genesis_data_to_gdev_genesis_conf(genesis_data.clone(), 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, ) - }) - .collect::<BTreeMap<IdtyName, AccountId>>(); - - gdev_runtime::GenesisConfig { - system: SystemConfig { - // Add Wasm runtime to storage. - code: wasm_binary.to_vec(), - }, - account: AccountConfig { - accounts: initial_identities - .iter() - .enumerate() - .map(|(i, (_, owner_key))| { - ( - owner_key.clone(), - GenesisAccountData { - random_id: H256(blake2_256(&(i as u32, owner_key).encode())), - balance: ud, - is_identity: true, - }, - ) - }) - .collect(), - }, - parameters: ParametersConfig { - parameters: GenesisParameters { - babe_epoch_duration, - cert_period: 15, - cert_max_by_issuer: 10, - cert_min_received_cert_to_issue_cert: 2, - cert_validity_period, - idty_confirm_period: 40, - idty_creation_period: 50, - membership_period, - pending_membership_period: 500, - ud_creation_period, - ud_reeval_period, - smith_cert_period: 15, - smith_cert_max_by_issuer: 8, - smith_cert_min_received_cert_to_issue_cert: 2, - smith_cert_validity_period, - smith_membership_period, - smith_pending_membership_period: 500, - smith_wot_first_cert_issuable_on: 20, - smith_wot_min_cert_for_membership: 2, - wot_first_cert_issuable_on: 20, - wot_min_cert_for_create_idty_right: 2, - wot_min_cert_for_membership: 2, - }, - }, - authority_discovery: Default::default(), - authority_members: AuthorityMembersConfig { - initial_authorities: initial_smiths - .iter() - .enumerate() - .map(|(i, keys)| (i as u32 + 1, (keys.0.clone(), i < initial_authorities_len))) - .collect(), - }, - 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: initial_smiths - .iter() - .map(|x| { - ( - x.0.clone(), - x.0.clone(), - session_keys(x.1.clone(), x.2.clone(), x.3.clone(), x.4.clone()), - ) - }) - .collect::<Vec<_>>(), - }, - sudo: SudoConfig { - // Assign network admin rights. - key: Some(root_key), - }, - technical_committee: TechnicalCommitteeConfig { - members: initial_smiths - .iter() - .map(|x| x.0.clone()) - .collect::<Vec<_>>(), - ..Default::default() - }, - identity: IdentityConfig { - identities: initial_identities - .iter() - .enumerate() - .map(|(i, (name, owner_key))| { - if i != initial_identities_len - 1 { - GenesisIdty { - index: i as u32 + 1, - name: name.clone(), - value: IdtyValue { - data: IdtyData::new(), - next_creatable_identity_on: Default::default(), - old_owner_key: None, - owner_key: owner_key.clone(), - removable_on: 0, - status: IdtyStatus::Validated, - }, - } - } else { - GenesisIdty { - index: i as u32 + 1, - name: name.clone(), - value: IdtyValue { - data: IdtyData::new(), - next_creatable_identity_on: Default::default(), - old_owner_key: None, - owner_key: owner_key.clone(), - removable_on: 0, - status: IdtyStatus::Created, - }, - } - } - }) - .collect(), - }, - membership: MembershipConfig { - memberships: (1..=initial_identities.len()) - .filter_map(|i| { - if i != initial_identities_len { - Some((i as u32, MembershipData { expire_on: 0 })) - } else { - None - } - }) - .collect(), - }, - cert: CertConfig { - apply_cert_period_at_genesis: false, - certs_by_receiver: clique_wot(initial_identities.len()), - }, - smith_membership: SmithMembershipConfig { - memberships: (1..=initial_smiths_len) - .map(|i| (i as u32, MembershipData { expire_on: 0 })) - .collect(), - }, - smith_cert: SmithCertConfig { - apply_cert_period_at_genesis: false, - certs_by_receiver: clique_wot(initial_smiths_len), - }, - universal_dividend: UniversalDividendConfig { - first_reeval: None, - first_ud: None, - initial_monetary_mass: initial_identities_len as u64 * ud, - ud, - }, - treasury: Default::default(), - } + ) } /// custom genesis diff --git a/node/src/chain_spec/gen_genesis_data.rs b/node/src/chain_spec/gen_genesis_data.rs index 3d4dd4d713a9c507f305f6949859cdd9d04cc8eb..a55b354671efd0d3cb4aa3dd0b65e20239fbaf29 100644 --- a/node/src/chain_spec/gen_genesis_data.rs +++ b/node/src/chain_spec/gen_genesis_data.rs @@ -14,13 +14,14 @@ // 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 crate::chain_spec::gdev::{get_authority_keys_from_seed, get_env, session_keys, AuthorityKeys}; +use crate::chain_spec::{clique_wot, get_account_id_from_seed, NAMES}; use common_runtime::*; use maplit::btreemap; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use sp_core::crypto::AccountId32; -use sp_core::{blake2_256, Decode, Encode, H256}; +use sp_core::{blake2_256, sr25519, Decode, Encode, H256}; use std::collections::BTreeMap; -use std::fmt::format; type MembershipData = sp_membership::MembershipData<u32>; @@ -61,7 +62,7 @@ struct GenesisConfig<Parameters> { #[serde(default)] parameters: Parameters, #[serde(rename = "smiths")] - smith_identities: BTreeMap<String, SmithData>, + smith_identities: Vec<SmithData>, sudo_key: Option<AccountId>, technical_committee: Vec<String>, ud: u64, @@ -87,9 +88,8 @@ struct Idty { #[derive(Clone, Deserialize, Serialize)] struct SmithData { + name: String, session_keys: Option<String>, - #[serde(default)] - certs: Vec<Cert>, } #[derive(Clone, Deserialize, Serialize)] @@ -111,8 +111,9 @@ impl From<Cert> for (String, Option<u32>) { /// takes DUNITER_GENESIS_CONFIG env var if present or duniter-gen-conf.json by default // this function is targeting dev chainspecs, do not use in production network pub fn generate_genesis_data<CS, P, SK, F>( + json_file_path: String, f: F, - maybe_force_authority: Option<Vec<u8>>, + maybe_force_authority: Option<(String, Vec<u8>)>, ) -> Result<CS, String> where P: Default + DeserializeOwned, @@ -138,7 +139,9 @@ where technical_committee, ud, // wallets, - } = get_genesis_config::<P>()?; + } = get_genesis_config::<P>( + std::env::var("DUNITER_GENESIS_CONFIG").unwrap_or_else(|_| json_file_path.to_owned()), + )?; let GenesisMigrationData { identities, @@ -247,16 +250,16 @@ where } // Verify certifications coherence + let mut not_enough_certs: Vec<u32> = vec![]; for (idty_index, receiver_certs) in &certs_by_receiver { if receiver_certs.len() < genesis_certs_min_received as usize { - return Err(format!( - "Identity n°{} has received only {}/{} certifications)", - idty_index, - receiver_certs.len(), - genesis_certs_min_received - )); + not_enough_certs.push(*idty_index); } } + // Trim these identities + not_enough_certs.into_iter().for_each(|idty_index| { + certs_by_receiver.remove(&idty_index); + }); // SMITHS SUB-WOT // @@ -265,13 +268,25 @@ where let mut session_keys_map = BTreeMap::new(); let mut smith_memberships = BTreeMap::new(); let mut smith_certs_by_receiver = BTreeMap::new(); - for (idty_name, smith_data) in smith_identities { + + // Authorities + let authority_idty_index = maybe_force_authority.clone().map(|(name, _)| { + idty_index_of + .get(&name) + .ok_or(format!("Identity '{}' not exist", name)) + .expect("Initial authority must have an identity") + }); + for SmithData { + name: idty_name, + session_keys, + } in &smith_identities + { let idty_index = idty_index_of - .get(&idty_name) - .ok_or(format!("Identity '{}' not exist", &idty_name))?; + .get(idty_name) + .ok_or(format!("Identity '{}' not exist", idty_name))?; let identity = identities - .get(&idty_name) - .ok_or(format!("Identity '{}' not exist", &idty_name))?; + .get(idty_name) + .ok_or(format!("Identity '{}' not exist", idty_name))?; if identity.balance < EXISTENTIAL_DEPOSIT { return Err(format!( @@ -281,11 +296,11 @@ where } // Initial authorities - if maybe_force_authority.is_some() { - if smith_data.session_keys.is_some() { + if let Some(authority_idty_index) = authority_idty_index { + if session_keys.is_some() { return Err("session_keys field forbidden".to_owned()); } - if *idty_index == 1 { + if *idty_index == *authority_idty_index { // online authority initial_authorities.insert(1, (identity.pubkey.clone(), true)); } else { @@ -295,16 +310,17 @@ where } else { initial_authorities.insert( *idty_index, - (identity.pubkey.clone(), smith_data.session_keys.is_some()), + (identity.pubkey.clone(), session_keys.is_some()), ); } // Session keys - let session_keys_bytes = if let Some(ref session_keys) = smith_data.session_keys { + let session_keys_bytes = if let Some(ref session_keys) = session_keys { online_authorities_counter += 1; hex::decode(&session_keys[2..]) - .map_err(|_| format!("invalid session keys for idty {}", &idty_name))? - } else if let (1, Some(ref session_keys_bytes)) = (*idty_index, &maybe_force_authority) { + .map_err(|_| format!("invalid session keys for idty {}", idty_name))? + } else if let (1, Some((_, ref session_keys_bytes))) = (*idty_index, &maybe_force_authority) + { session_keys_bytes.clone() } else { // Create fake session keys (must be unique and deterministic) @@ -316,18 +332,22 @@ where //vec![initial_authorities.len() as u8; std::mem::size_of::<SK>()] }; let session_keys = SK::decode(&mut &session_keys_bytes[..]) - .map_err(|_| format!("invalid session keys for idty {}", &idty_name))?; + .map_err(|_| format!("invalid session keys for idty {}", idty_name))?; session_keys_map.insert(identity.pubkey.clone(), session_keys); // Certifications let mut receiver_certs = BTreeMap::new(); - for cert in &smith_data.certs { - let (issuer, maybe_expire_on) = cert.clone().into(); - let issuer_index = idty_index_of - .get(&issuer) - .ok_or(format!("Identity '{}' not exist", issuer))?; - receiver_certs.insert(*issuer_index, maybe_expire_on); - } + // All initial smiths are considered to be certifying all each other + smith_identities + .iter() + .filter(|s| s.name.to_owned() != *idty_name) + .for_each(|other_smith| { + let issuer_index = idty_index_of + .get(&other_smith.name) + .ok_or(format!("Identity '{}' not exist", other_smith.name)) + .unwrap(); + receiver_certs.insert(*issuer_index, None); // TODO: put duration + }); smith_certs_by_receiver.insert(*idty_index, receiver_certs); // Memberships @@ -382,6 +402,173 @@ where Ok(f(genesis_data)) } +pub fn generate_genesis_data_for_benchmark_chain<CS, P, SK, F>( + initial_authorities_len: usize, + initial_smiths_len: usize, + initial_identities_len: usize, + root_key: AccountId, + _enable_println: bool, + f: F, +) -> Result<CS, String> +where + P: Default + DeserializeOwned, + SK: Decode, + F: Fn(GenesisData<P, SK>) -> CS, +{ + // Same as local chain + generate_genesis_data_for_local_chain( + initial_authorities_len, + initial_smiths_len, + initial_identities_len, + root_key, + _enable_println, + f, + ) +} + +pub fn generate_genesis_data_for_local_chain<CS, P, SK, F>( + initial_authorities_len: usize, + initial_smiths_len: usize, + initial_identities_len: usize, + root_key: AccountId, + _enable_println: bool, + f: F, +) -> Result<CS, String> +where + P: Default + DeserializeOwned, + SK: Decode, + F: Fn(GenesisData<P, SK>) -> CS, +{ + assert!(initial_identities_len <= 6); + assert!(initial_smiths_len <= initial_identities_len); + assert!(initial_authorities_len <= initial_smiths_len); + + let babe_epoch_duration = get_env("DUNITER_BABE_EPOCH_DURATION", 30) as u64; + let cert_validity_period = get_env("DUNITER_CERT_VALIDITY_PERIOD", 1_000); + let membership_period = get_env("DUNITER_MEMBERSHIP_PERIOD", 1_000); + let smith_cert_validity_period = get_env("DUNITER_SMITH_CERT_VALIDITY_PERIOD", 1_000); + let smith_membership_period = get_env("DUNITER_SMITH_MEMBERSHIP_PERIOD", 1_000); + let ud_creation_period = get_env("DUNITER_UD_CREATION_PERIOD", 60_000); + let ud_reeval_period = get_env("DUNITER_UD_REEEVAL_PERIOD", 1_200_000); + let ud = 1_000; + + let initial_smiths = (0..initial_smiths_len) + .map(|i| get_authority_keys_from_seed(NAMES[i])) + .collect::<Vec<AuthorityKeys>>(); + let initial_identities = (0..initial_identities_len) + .map(|i| { + ( + IdtyName::from(NAMES[i]), + get_account_id_from_seed::<sr25519::Public>(NAMES[i]), + ) + }) + .collect::<BTreeMap<IdtyName, AccountId>>(); + + let mut session_keys_map = BTreeMap::new(); + initial_smiths.iter().for_each(|x| { + let session_keys_bytes = + session_keys(x.1.clone(), x.2.clone(), x.3.clone(), x.4.clone()).encode(); + let sk = SK::decode(&mut &session_keys_bytes[..]) + .map_err(|_| format!("invalid session keys for idty {}", x.0.clone())) + .unwrap(); + session_keys_map.insert(x.0.clone(), sk); + }); + + let identities_ = initial_identities + .iter() + .enumerate() + .map(|(_, (name, owner_key))| { + ( + String::from_utf8(name.0.clone()).unwrap(), + owner_key.clone(), + ) + }) + .collect(); + + let parameters = serde_json::from_slice::<P>( + format!( + "{{ + \"babe_epoch_duration\": {}, + \"cert_period\": 15, + \"cert_max_by_issuer\": 10, + \"cert_min_received_cert_to_issue_cert\": 2, + \"cert_validity_period\": {}, + \"idty_confirm_period\": 40, + \"idty_creation_period\": 50, + \"membership_period\": {}, + \"pending_membership_period\": 500, + \"ud_creation_period\": {}, + \"ud_reeval_period\": {}, + \"smith_cert_period\": 15, + \"smith_cert_max_by_issuer\": 8, + \"smith_cert_min_received_cert_to_issue_cert\": 2, + \"smith_cert_validity_period\": {}, + \"smith_membership_period\": {}, + \"smith_pending_membership_period\": 500, + \"smith_wot_first_cert_issuable_on\": 20, + \"smith_wot_min_cert_for_membership\": 2, + \"wot_first_cert_issuable_on\": 20, + \"wot_min_cert_for_create_idty_right\": 2, + \"wot_min_cert_for_membership\": 2 + }}", + babe_epoch_duration, + cert_validity_period, + membership_period, + ud_creation_period, + ud_reeval_period, + smith_cert_validity_period, + smith_membership_period + ) + .as_bytes(), + ) + .map_err(|e| format!("Error parsing json conf: {}", e))?; + + let genesis_data = GenesisData { + accounts: initial_identities + .iter() + .enumerate() + .map(|(i, (_, owner_key))| { + ( + owner_key.clone(), + GenesisAccountData { + random_id: H256(blake2_256(&(i as u32, owner_key).encode())), + balance: ud, + is_identity: true, + }, + ) + }) + .collect(), + certs_by_receiver: clique_wot(initial_identities.len()), + first_ud: None, + first_ud_reeval: None, + identities: identities_, + initial_authorities: initial_smiths + .iter() + .enumerate() + .map(|(i, keys)| (i as u32 + 1, (keys.0.clone(), i < initial_authorities_len))) + .collect(), + initial_monetary_mass: initial_identities_len as u64 * ud, + memberships: (1..=initial_identities.len()) + .map(|i| (i as u32, MembershipData { expire_on: 0 })) + .collect(), + // TODO: remove this P generic parameter thats makes this ugly parsing mandatory + parameters, + session_keys_map, + smith_certs_by_receiver: clique_wot(initial_smiths_len), + smith_memberships: (1..=initial_smiths_len) + .map(|i| (i as u32, MembershipData { expire_on: 0 })) + .collect(), + sudo_key: Some(root_key), + technical_committee_members: initial_smiths + .iter() + .map(|x| x.0.clone()) + .collect::<Vec<_>>(), + ud, + }; + + Ok(f(genesis_data)) +} + fn check_parameters_consistency( wallets: &BTreeMap<AccountId32, u64>, first_ud: &Option<u64>, @@ -415,9 +602,9 @@ fn check_parameters_consistency( Ok(()) } -fn get_genesis_config<P: Default + DeserializeOwned>() -> Result<GenesisConfig<P>, String> { - let json_file_path = std::env::var("DUNITER_GENESIS_CONFIG") - .unwrap_or_else(|_| "duniter-gen-conf.json".to_owned()); +fn get_genesis_config<P: Default + DeserializeOwned>( + json_file_path: String, +) -> Result<GenesisConfig<P>, String> { // We mmap the file into memory first, as this is *a lot* faster than using // `serde_json::from_reader`. See https://github.com/serde-rs/json/issues/160 let file = std::fs::File::open(&json_file_path)