From 40823408be482d2d9a4864b46ab79ea04197be84 Mon Sep 17 00:00:00 2001 From: cgeek <cem.moreau@gmail.com> Date: Mon, 11 Sep 2023 21:19:57 +0200 Subject: [PATCH] fix(#125): dissociate genesis config from genesis migration --- node/src/chain_spec/gen_genesis_data.rs | 133 ++++++++++++++++++------ 1 file changed, 101 insertions(+), 32 deletions(-) diff --git a/node/src/chain_spec/gen_genesis_data.rs b/node/src/chain_spec/gen_genesis_data.rs index 2fdd6cef0..3d4dd4d71 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); -- GitLab