Skip to content
Snippets Groups Projects
Commit 3745d65e authored by bgallois's avatar bgallois Committed by Hugo Trentesaux
Browse files

feat(node): add genesis builder for benchmarking

Added a genesis builder for benchmarking with pre-configured accounts that can be used during the benchmarking and circumvent limitation imposed by pallets coupling.
parent 3da34f02
No related branches found
No related tags found
1 merge request!138Identity pallet benchmark
...@@ -22,13 +22,13 @@ complete real example. ...@@ -22,13 +22,13 @@ complete real example.
machine: `cargo build --release --features runtime-benchmarks` machine: `cargo build --release --features runtime-benchmarks`
4. Run the benchmarks on your local machine (to test if it work with a real runtime). The command 4. Run the benchmarks on your local machine (to test if it work with a real runtime). The command
is: `duniter benchmark pallet --chain=CURRENCY-dev --steps=50 --repeat=20 --pallet=pallet_universal_dividend --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --output=.` is: `duniter benchmark pallet --chain=CURRENCY-dev --steps=50 --repeat=20 --pallet=pallet_universal_dividend --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --output=.`
5. If it worked, use the generated file content to create or update the `WeightInfo` trait and the `()` dummy implementation. Then use the `WeightInfo` tarit in the real code of the pallet. See 79e0fd4bf3b0579279fc957da5e2fdfc6d8a17fa for a 5. If it worked, use the generated file content to create or update by hand the `WeightInfo` trait and the `()` dummy implementation. Then use the `WeightInfo` tarit in the real code of the pallet. See 79e0fd4bf3b0579279fc957da5e2fdfc6d8a17fa for a
complete real example. complete real example.
6. Redo steps `3.` and `4.` on the reference machine. 6. Redo steps `3.` and `4.` on the reference machine.
7. Put the generated file on `runtime/common/src/weights` and use it in the runtimes configuration. 7. Put the automatically generated file on `runtime/common/src/weights` and use it in the runtimes configuration.
See cee7c3b2763ba402e807f126534d9cd39a8bd025 for a complete real example. See cee7c3b2763ba402e807f126534d9cd39a8bd025 for a complete real example.
Note 1: You *must* replace `CURRENCY` by the currency type, or for ĞDev use directly `--chain=dev`. Note 1: You *must* replace `CURRENCY` by the currency type, or for ĞDev use directly `--chain=gdev-benchmark`.
Note 2: If the reference machine does not support wasmtime, you should replace `--wasm-execution=compiled` Note 2: If the reference machine does not support wasmtime, you should replace `--wasm-execution=compiled`
by `--wasm-execution=interpreted-i-know-what-i-do`. by `--wasm-execution=interpreted-i-know-what-i-do`.
......
...@@ -183,6 +183,53 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> { ...@@ -183,6 +183,53 @@ pub fn development_chain_spec() -> Result<ChainSpec, String> {
} }
} }
/// 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,
)
},
// 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 /// generate live network chainspecs
pub fn gen_live_conf() -> Result<ChainSpec, String> { pub fn gen_live_conf() -> Result<ChainSpec, String> {
let wasm_binary = WASM_BINARY.ok_or_else(|| "wasm not available".to_string())?; let wasm_binary = WASM_BINARY.ok_or_else(|| "wasm not available".to_string())?;
...@@ -443,6 +490,216 @@ fn gen_genesis_for_local_chain( ...@@ -443,6 +490,216 @@ fn gen_genesis_for_local_chain(
} }
} }
/// 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_u32("DUNITER_BABE_EPOCH_DURATION", 30) as u64;
let cert_validity_period = get_env_u32("DUNITER_CERT_VALIDITY_PERIOD", 1_000);
let first_ud = 1_000;
let membership_period = get_env_u32("DUNITER_MEMBERSHIP_PERIOD", 1_000);
let smith_cert_validity_period = get_env_u32("DUNITER_SMITH_CERT_VALIDITY_PERIOD", 1_000);
let smith_membership_period = get_env_u32("DUNITER_SMITH_MEMBERSHIP_PERIOD", 1_000);
let ud_creation_period = get_env_u32("DUNITER_UD_CREATION_PERIOD", 10);
let ud_reeval_period = get_env_u32("DUNITER_UD_REEEVAL_PERIOD", 200);
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: first_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,
smiths_wot_first_cert_issuable_on: 20,
smiths_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: BalancesConfig {
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()),
},
smiths_membership: SmithsMembershipConfig {
memberships: (1..=initial_smiths_len)
.map(|i| (i as u32, MembershipData { expire_on: 0 }))
.collect(),
},
smiths_cert: SmithsCertConfig {
apply_cert_period_at_genesis: false,
certs_by_receiver: clique_wot(initial_smiths_len),
},
universal_dividend: UniversalDividendConfig {
first_reeval: 100,
first_ud,
initial_monetary_mass: initial_identities_len as u64 * first_ud,
},
treasury: Default::default(),
}
}
fn get_env_u32(env_var_name: &'static str, default_value: u32) -> u32 {
std::env::var(env_var_name)
.map_or(Ok(default_value), |s| s.parse())
.unwrap_or_else(|_| panic!("{} must be a number", env_var_name))
}
fn session_keys(
babe: BabeId,
grandpa: GrandpaId,
im_online: ImOnlineId,
authority_discovery: AuthorityDiscoveryId,
) -> SessionKeys {
SessionKeys {
babe,
grandpa,
im_online,
authority_discovery,
}
}
/// custom genesis /// custom genesis
fn genesis_data_to_gdev_genesis_conf( fn genesis_data_to_gdev_genesis_conf(
genesis_data: super::gen_genesis_data::GenesisData<GenesisParameters, SessionKeys>, genesis_data: super::gen_genesis_data::GenesisData<GenesisParameters, SessionKeys>,
......
...@@ -105,6 +105,8 @@ impl SubstrateCli for Cli { ...@@ -105,6 +105,8 @@ impl SubstrateCli for Cli {
"gdev" => Box::new(chain_spec::gdev::ChainSpec::from_json_bytes( "gdev" => Box::new(chain_spec::gdev::ChainSpec::from_json_bytes(
&include_bytes!("../specs/gdev-raw.json")[..], &include_bytes!("../specs/gdev-raw.json")[..],
)?), )?),
#[cfg(feature = "gdev")]
"gdev-benchmark" => Box::new(chain_spec::gdev::benchmark_chain_spec()?),
#[cfg(feature = "gtest")] #[cfg(feature = "gtest")]
"gtest_dev" => Box::new(chain_spec::gtest::development_chain_spec()?), "gtest_dev" => Box::new(chain_spec::gtest::development_chain_spec()?),
#[cfg(feature = "gtest")] #[cfg(feature = "gtest")]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment