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)