diff --git a/node/src/chain_spec/gen_genesis_data.rs b/node/src/chain_spec/gen_genesis_data.rs index 2fdd6cef08caa4a40d06c1c9b40e6ec197f44a14..3d4dd4d713a9c507f305f6949859cdd9d04cc8eb 100644 --- a/node/src/chain_spec/gen_genesis_data.rs +++ b/node/src/chain_spec/gen_genesis_data.rs @@ -15,9 +15,12 @@ // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. 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 std::collections::BTreeMap; +use std::fmt::format; type MembershipData = sp_membership::MembershipData<u32>; @@ -55,7 +58,6 @@ struct GenesisConfig<Parameters> { first_ud: Option<u64>, first_ud_reeval: Option<u64>, genesis_parameters: ParamsAppliedAtGenesis, - identities: BTreeMap<String, Idty>, #[serde(default)] parameters: Parameters, #[serde(rename = "smiths")] @@ -63,6 +65,11 @@ struct GenesisConfig<Parameters> { sudo_key: Option<AccountId>, technical_committee: Vec<String>, ud: u64, +} + +#[derive(Deserialize, Serialize)] +struct GenesisMigrationData { + identities: BTreeMap<String, Idty>, #[serde(default)] wallets: BTreeMap<AccountId, u64>, } @@ -112,36 +119,8 @@ where SK: Decode, F: Fn(GenesisData<P, SK>) -> CS, { - 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() - }; - - let json_file_path = std::env::var("DUNITER_GENESIS_CONFIG") - .unwrap_or_else(|_| "duniter-gen-conf.json".to_owned()); - - // 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) - .map_err(|e| format!("Error opening gen conf file `{}`: {}", json_file_path, e))?; + let genesis_timestamp: u64 = get_genesis_timestamp()?; - // SAFETY: `mmap` is fundamentally unsafe since technically the file can change - // underneath us while it is mapped; in practice it's unlikely to be a problem - let bytes = unsafe { - memmap2::Mmap::map(&file) - .map_err(|e| format!("Error mmaping gen conf file `{}`: {}", json_file_path, e))? - }; - - let genesis_config = serde_json::from_slice(&bytes) - .map_err(|e| format!("Error parsing gen conf file: {}", e))?; let GenesisConfig { sudo_key, first_ud, @@ -154,12 +133,19 @@ where genesis_smith_memberships_expire_on, }, parameters, - identities, + // identities, smith_identities, technical_committee, ud, + // wallets, + } = get_genesis_config::<P>()?; + + let GenesisMigrationData { + identities, wallets, - } = genesis_config; + } = get_genesis_migration_data()?; + + check_parameters_consistency(&wallets, &first_ud, &first_ud_reeval, &ud)?; // MONEY ANDÂ WOT // @@ -396,6 +382,89 @@ where Ok(f(genesis_data)) } +fn check_parameters_consistency( + wallets: &BTreeMap<AccountId32, u64>, + first_ud: &Option<u64>, + first_reeval: &Option<u64>, + ud: &u64, +) -> Result<(), String> { + // No empty wallet + if let Some((account, _)) = wallets.iter().find(|(_, amount)| **amount == 0) { + return Err(format!("Wallet {} is empty", account)); + } + + // TODO: check ud_reeval_period / ud_creation_period (can round to zero) + + if first_reeval.is_none() { + return Err("Please provied a value for `first_ud_reeval`".to_owned()); + } + if first_ud.is_none() { + return Err("Please provied a value for `first_ud`".to_owned()); + } + if first_ud.unwrap() > first_reeval.unwrap() { + return Err(format!( + "`first_ud` ({}) should be lower than `first_ud_reeval` ({})", + first_ud.unwrap(), + first_reeval.unwrap() + ) + .to_owned()); + } + if *ud == 0 { + return Err("`ud` is expected to be > 0".to_owned()); + } + 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()); + // 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) + .map_err(|e| format!("Error opening gen conf file `{}`: {}", json_file_path, e))?; + // SAFETY: `mmap` is fundamentally unsafe since technically the file can change + // underneath us while it is mapped; in practice it's unlikely to be a problem + let bytes = unsafe { + memmap2::Mmap::map(&file) + .map_err(|e| format!("Error mmaping gen conf file `{}`: {}", json_file_path, e))? + }; + serde_json::from_slice::<GenesisConfig<P>>(&bytes) + .map_err(|e| format!("Error parsing gen conf file: {}", e)) +} + +fn get_genesis_migration_data() -> Result<GenesisMigrationData, String> { + if let Ok(json_file_path) = std::env::var("DUNITER_GENESIS_MIGRATION") { + let file = std::fs::File::open(&json_file_path) + .map_err(|e| format!("Error opening gen conf file `{}`: {}", json_file_path, e))?; + let bytes = unsafe { + memmap2::Mmap::map(&file) + .map_err(|e| format!("Error mmaping gen conf file `{}`: {}", json_file_path, e))? + }; + serde_json::from_slice::<GenesisMigrationData>(&bytes) + .map_err(|e| format!("Error parsing gen conf file: {}", e)) + } else { + // No data + Ok(GenesisMigrationData { + wallets: btreemap! {}, + identities: btreemap! {}, + }) + } +} + +fn get_genesis_timestamp() -> Result<u64, String> { + 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; + Ok(SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .expect("SystemTime before UNIX EPOCH!") + .as_secs()) + } +} + // Timestamp to block number fn to_bn(genesis_timestamp: u64, timestamp: u64) -> u32 { let duration_in_secs = timestamp.saturating_sub(genesis_timestamp); diff --git a/resources/gdev.json b/resources/gdev.json index b2ec211ee6f63eb90f5c80b900f87ec914e41c2d..6a128da4e678e15b39b93c5f149fa829ea3b0b35 100644 --- a/resources/gdev.json +++ b/resources/gdev.json @@ -1,6 +1,7 @@ { "first_ud": 10000, "first_ud_reeval": 100800, + "ud": 1068, "genesis_parameters": { "genesis_certs_expire_on": 2102400, "genesis_certs_min_received": 3, @@ -9,142 +10,6 @@ "genesis_smith_certs_min_received": 3, "genesis_smith_memberships_expire_on": 1051200 }, - "identities": { - "Elois": { - "balance": 10000, - "certs": [ - "poka", - "cgeek", - "vit", - "tuxmain", - "HugoTrentesaux", - "ManUtopiK", - "moul", - "1000i100", - "kapis", - "David B", - "Gamaliel", - "wellno1" - ], - "pubkey": "5H95G8bwuf4yyNNNa83hDhj7wpYaSRhZiGezZ9TDbyqNdAhY" - }, - "Elois2": { - "balance": 10000, - "certs": ["tuxmain", "Elois", "HugoTrentesaux"], - "pubkey": "5GFEEx7kqvP4QEPCAXkALeYCG7m8DiA5LQ4YzW62j7FytQyg" - }, - "poka": { - "balance": 10000, - "certs": ["cgeek", "vit", "tuxmain", "Elois", "HugoTrentesaux"], - "pubkey": "5CQ8T4qpbYJq7uVsxGPQ5q2df7x3Wa4aRY6HUWMBYjfLZhnn" - }, - "tuxmain": { - "balance": 10000, - "certs": [ - "cgeek", - "Elois", - "HugoTrentesaux", - "ManUtopiK", - "poka", - "moul", - "1000i100" - ], - "pubkey": "5D2DnScFpxoEUXDwZbJH18tRsQMygBSh1F6YCcWvTYzKY2W7" - }, - "vit": { - "balance": 10000, - "certs": [ - "cgeek", - "Elois", - "HugoTrentesaux", - "ManUtopiK", - "poka", - "tuxmain", - "moul" - ], - "pubkey": "5DqkYGjiT5TFm2pGMUBMuZW4sw13vDEZmxqkxmky5AoQvUwd" - }, - "cgeek": { - "balance": 10000, - "certs": ["poka", "vit", "tuxmain", "Elois", "HugoTrentesaux", "moul"], - "pubkey": "5DP7ze5cJwtHbqXaP2aNtJ5jkULzcTCqXuMzDvk9JjneFjfq" - }, - "HugoTrentesaux": { - "balance": 10000, - "certs": [ - "poka", - "vit", - "tuxmain", - "Elois", - "moul", - "1000i100", - "ManUtopiK", - "kapis", - "David B", - "Gamaliel", - "wellno1" - ], - "pubkey": "5Dq8xjvkmbz7q4g2LbZgyExD26VSCutfEc6n4W4AfQeVHZqz" - }, - "ManUtopiK": { - "balance": 10000, - "certs": [ - "poka", - "vit", - "tuxmain", - "Elois", - "HugoTrentesaux", - "1000i100" - ], - "pubkey": "5DUjwHRqPayt3tAZk1fqEgU99xZB9jzBHKy2sMSTNcc7m9D1" - }, - "1000i100": { - "balance": 10000, - "certs": [ - "Elois", - "poka", - "cgeek", - "vit", - "tuxmain", - "HugoTrentesaux", - "ManUtopiK", - "moul" - ], - "pubkey": "5CCrBS67BrpBx3ihGHc72HZp3eHHbETxWFuNfwbbdoGSJFN8" - }, - "moul": { - "balance": 10000, - "certs": [ - "ManUtopiK", - "vit", - "tuxmain", - "Elois", - "HugoTrentesaux", - "1000i100" - ], - "pubkey": "5EPGRtBYLwfDinnaAXsscM3FkffRADpJRrkZETqW8N6uhp22" - }, - "Gamaliel": { - "balance": 10000, - "certs": ["David B", "wellno1", "kapis"], - "pubkey": "5DS9iWBXW56N7XbeVyyp6CB7m4LeE5fGJYrUR9HDSStT5JN9" - }, - "kapis": { - "balance": 10000, - "certs": ["David B", "wellno1", "Gamaliel"], - "pubkey": "5HJyyim1W8Y1UD8LAbBL7cQQLjGofMoD45RtRSAmhkFQxrvs" - }, - "David B": { - "balance": 10000, - "certs": ["kapis", "wellno1", "Gamaliel"], - "pubkey": "5HKTDdXHj3MojiPRcEsVU9JaHyif5gg2br1sy3JZbsjuQebP" - }, - "wellno1": { - "balance": 10000, - "certs": ["David B", "kapis", "Gamaliel"], - "pubkey": "5DyEZNkSuK5i8wZiXtvL63zqpye9zPBsPRauCjQkMuVzZYX7" - } - }, "parameters": { "babe_epoch_duration": 600, "cert_period": 14400, @@ -200,5 +65,5 @@ } }, "sudo_key": "5Hm8sBbwuLAU99dBezvgtnRmZCrUy9mhqmbQMFyGTaeATYg7", - "technical_committee": ["Elois", "cgeek", "tuxmain", "HugoTrentesaux"] + "technical_committee": ["1000i100", "vit", "poka", "tuxmain", "cgeek", "HugoTrentesaux", "Maaltir", "Pini"] }