#[cfg(any(feature = "testing", test))]
use std::iter;
use num_rational::Ratio;
#[cfg(any(feature = "testing", test))]
use rand::{
distributions::{Distribution, Standard},
Rng,
};
use serde::{Deserialize, Serialize};
use crate::{
system::auction::DelegationRate, AdministratorAccount, Chainspec, GenesisAccount,
GenesisValidator, HoldBalanceHandling, Motes, PublicKey, RewardsHandling, SystemConfig,
WasmConfig,
};
use super::StorageCosts;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct GenesisConfig {
accounts: Vec<GenesisAccount>,
wasm_config: WasmConfig,
system_config: SystemConfig,
validator_slots: u32,
auction_delay: u64,
locked_funds_period_millis: u64,
round_seigniorage_rate: Ratio<u64>,
unbonding_delay: u64,
genesis_timestamp_millis: u64,
gas_hold_balance_handling: HoldBalanceHandling,
gas_hold_interval_millis: u64,
enable_addressable_entity: bool,
rewards_ratio: Option<Ratio<u64>>,
storage_costs: StorageCosts,
minimum_delegation_rate: DelegationRate,
}
impl GenesisConfig {
#[allow(clippy::too_many_arguments)]
pub fn new(
accounts: Vec<GenesisAccount>,
wasm_config: WasmConfig,
system_config: SystemConfig,
validator_slots: u32,
auction_delay: u64,
locked_funds_period_millis: u64,
round_seigniorage_rate: Ratio<u64>,
unbonding_delay: u64,
genesis_timestamp_millis: u64,
gas_hold_balance_handling: HoldBalanceHandling,
gas_hold_interval_millis: u64,
enable_addressable_entity: bool,
rewards_handling: Option<Ratio<u64>>,
storage_costs: StorageCosts,
minimum_delegation_rate: DelegationRate,
) -> GenesisConfig {
GenesisConfig {
accounts,
wasm_config,
system_config,
validator_slots,
auction_delay,
locked_funds_period_millis,
round_seigniorage_rate,
unbonding_delay,
genesis_timestamp_millis,
gas_hold_balance_handling,
gas_hold_interval_millis,
enable_addressable_entity,
rewards_ratio: rewards_handling,
storage_costs,
minimum_delegation_rate,
}
}
pub fn wasm_config(&self) -> &WasmConfig {
&self.wasm_config
}
pub fn system_config(&self) -> &SystemConfig {
&self.system_config
}
pub fn get_bonded_validators(&self) -> impl Iterator<Item = &GenesisAccount> {
self.accounts_iter()
.filter(|&genesis_account| genesis_account.is_validator())
}
pub fn get_bonded_delegators(
&self,
) -> impl Iterator<Item = (&PublicKey, &PublicKey, &Motes, &Motes)> {
self.accounts
.iter()
.filter_map(|genesis_account| genesis_account.as_delegator())
}
pub fn accounts(&self) -> &[GenesisAccount] {
self.accounts.as_slice()
}
pub fn accounts_iter(&self) -> impl Iterator<Item = &GenesisAccount> {
self.accounts.iter()
}
pub fn administrative_accounts(&self) -> impl Iterator<Item = &AdministratorAccount> {
self.accounts
.iter()
.filter_map(GenesisAccount::as_administrator_account)
}
pub fn push_account(&mut self, account: GenesisAccount) {
self.accounts.push(account)
}
pub fn validator_slots(&self) -> u32 {
self.validator_slots
}
pub fn auction_delay(&self) -> u64 {
self.auction_delay
}
pub fn locked_funds_period_millis(&self) -> u64 {
self.locked_funds_period_millis
}
pub fn round_seigniorage_rate(&self) -> Ratio<u64> {
self.round_seigniorage_rate
}
pub fn unbonding_delay(&self) -> u64 {
self.unbonding_delay
}
pub fn genesis_timestamp_millis(&self) -> u64 {
self.genesis_timestamp_millis
}
pub fn gas_hold_balance_handling(&self) -> HoldBalanceHandling {
self.gas_hold_balance_handling
}
pub fn gas_hold_interval_millis(&self) -> u64 {
self.gas_hold_interval_millis
}
pub fn enable_entity(&self) -> bool {
self.enable_addressable_entity
}
pub fn set_enable_entity(&mut self, enable: bool) {
self.enable_addressable_entity = enable
}
pub fn push_genesis_validator(
&mut self,
public_key: &PublicKey,
genesis_validator: GenesisValidator,
) {
if let Some(genesis_account) = self
.accounts
.iter_mut()
.find(|x| &x.public_key() == public_key)
{
genesis_account.try_set_validator(genesis_validator);
}
}
pub fn rewards_ratio(&self) -> Option<Ratio<u64>> {
self.rewards_ratio
}
pub fn push_rewards_ratio(&mut self, rewards_ratio: Ratio<u64>) {
self.rewards_ratio = Some(rewards_ratio);
}
pub fn minimum_delegation_rate(&self) -> DelegationRate {
self.minimum_delegation_rate
}
}
#[cfg(any(feature = "testing", test))]
impl Distribution<GenesisConfig> for Standard {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> GenesisConfig {
let count = rng.gen_range(1..10);
let accounts = iter::repeat(()).map(|_| rng.gen()).take(count).collect();
let wasm_config = rng.gen();
let system_config = rng.gen();
let validator_slots = rng.gen();
let auction_delay = rng.gen();
let locked_funds_period_millis = rng.gen();
let round_seigniorage_rate = Ratio::new(
rng.gen_range(1..1_000_000_000),
rng.gen_range(1..1_000_000_000),
);
let unbonding_delay = rng.gen();
let genesis_timestamp_millis = rng.gen();
let gas_hold_balance_handling = rng.gen();
let gas_hold_interval_millis = rng.gen();
let storage_costs = rng.gen();
let minimum_delegation_rate = rng.gen();
GenesisConfig {
accounts,
wasm_config,
system_config,
validator_slots,
auction_delay,
locked_funds_period_millis,
round_seigniorage_rate,
unbonding_delay,
genesis_timestamp_millis,
gas_hold_balance_handling,
gas_hold_interval_millis,
enable_addressable_entity: false,
rewards_ratio: None,
storage_costs,
minimum_delegation_rate,
}
}
}
impl From<&Chainspec> for GenesisConfig {
fn from(chainspec: &Chainspec) -> Self {
let genesis_timestamp_millis = chainspec
.protocol_config
.activation_point
.genesis_timestamp()
.map_or(0, |timestamp| timestamp.millis());
let gas_hold_interval_millis = chainspec.core_config.gas_hold_interval.millis();
let gas_hold_balance_handling = chainspec.core_config.gas_hold_balance_handling;
let rewards_ratio = match chainspec.core_config.rewards_handling {
RewardsHandling::Standard => None,
RewardsHandling::Sustain { ratio, .. } => Some(ratio),
};
let storage_costs = chainspec.storage_costs;
GenesisConfig {
accounts: chainspec.network_config.accounts_config.clone().into(),
wasm_config: chainspec.wasm_config,
system_config: chainspec.system_costs_config,
validator_slots: chainspec.core_config.validator_slots,
auction_delay: chainspec.core_config.auction_delay,
locked_funds_period_millis: chainspec.core_config.locked_funds_period.millis(),
round_seigniorage_rate: chainspec.core_config.round_seigniorage_rate,
unbonding_delay: chainspec.core_config.unbonding_delay,
genesis_timestamp_millis,
gas_hold_balance_handling,
gas_hold_interval_millis,
enable_addressable_entity: chainspec.core_config.enable_addressable_entity,
rewards_ratio,
storage_costs,
minimum_delegation_rate: chainspec.core_config.minimum_delegation_rate,
}
}
}