#[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::{
AdministratorAccount, Chainspec, GenesisAccount, GenesisValidator, HoldBalanceHandling, Motes,
PublicKey, SystemConfig, WasmConfig,
};
use super::StorageCosts;
pub const DEFAULT_VALIDATOR_SLOTS: u32 = 5;
pub const DEFAULT_AUCTION_DELAY: u64 = 1;
pub const DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS: u64 = 0;
pub const DEFAULT_UNBONDING_DELAY: u64 = 7;
pub const DEFAULT_ROUND_SEIGNIORAGE_RATE: Ratio<u64> = Ratio::new_raw(7, 175070816);
pub const DEFAULT_GENESIS_TIMESTAMP_MILLIS: u64 = 0;
pub const DEFAULT_GAS_HOLD_INTERVAL_MILLIS: u64 = 24 * 60 * 60 * 60;
pub const DEFAULT_GAS_HOLD_BALANCE_HANDLING: HoldBalanceHandling = HoldBalanceHandling::Accrued;
pub const DEFAULT_ENABLE_ENTITY: bool = false;
#[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,
storage_costs: StorageCosts,
}
impl GenesisConfig {
#[deprecated(
since = "3.0.0",
note = "prefer to use ExecConfigBuilder to construct an ExecConfig"
)]
#[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,
storage_costs: StorageCosts,
) -> 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,
storage_costs,
}
}
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);
}
}
}
#[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();
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,
storage_costs,
}
}
}
#[derive(Default, Debug)]
pub struct GenesisConfigBuilder {
accounts: Option<Vec<GenesisAccount>>,
wasm_config: Option<WasmConfig>,
system_config: Option<SystemConfig>,
validator_slots: Option<u32>,
auction_delay: Option<u64>,
locked_funds_period_millis: Option<u64>,
round_seigniorage_rate: Option<Ratio<u64>>,
unbonding_delay: Option<u64>,
genesis_timestamp_millis: Option<u64>,
gas_hold_balance_handling: Option<HoldBalanceHandling>,
gas_hold_interval_millis: Option<u64>,
enable_addressable_entity: Option<bool>,
storage_costs: Option<StorageCosts>,
}
impl GenesisConfigBuilder {
pub fn new() -> Self {
GenesisConfigBuilder::default()
}
pub fn with_accounts(mut self, accounts: Vec<GenesisAccount>) -> Self {
self.accounts = Some(accounts);
self
}
pub fn with_wasm_config(mut self, wasm_config: WasmConfig) -> Self {
self.wasm_config = Some(wasm_config);
self
}
pub fn with_system_config(mut self, system_config: SystemConfig) -> Self {
self.system_config = Some(system_config);
self
}
pub fn with_validator_slots(mut self, validator_slots: u32) -> Self {
self.validator_slots = Some(validator_slots);
self
}
pub fn with_auction_delay(mut self, auction_delay: u64) -> Self {
self.auction_delay = Some(auction_delay);
self
}
pub fn with_locked_funds_period_millis(mut self, locked_funds_period_millis: u64) -> Self {
self.locked_funds_period_millis = Some(locked_funds_period_millis);
self
}
pub fn with_round_seigniorage_rate(mut self, round_seigniorage_rate: Ratio<u64>) -> Self {
self.round_seigniorage_rate = Some(round_seigniorage_rate);
self
}
pub fn with_unbonding_delay(mut self, unbonding_delay: u64) -> Self {
self.unbonding_delay = Some(unbonding_delay);
self
}
pub fn with_genesis_timestamp_millis(mut self, genesis_timestamp_millis: u64) -> Self {
self.genesis_timestamp_millis = Some(genesis_timestamp_millis);
self
}
pub fn with_gas_hold_interval_millis(mut self, gas_hold_interval_millis: u64) -> Self {
self.gas_hold_interval_millis = Some(gas_hold_interval_millis);
self
}
pub fn with_gas_hold_balance_handling(
mut self,
gas_hold_balance_handling: HoldBalanceHandling,
) -> Self {
self.gas_hold_balance_handling = Some(gas_hold_balance_handling);
self
}
pub fn with_enable_addressable_entity(mut self, enable_addressable_entity: bool) -> Self {
self.enable_addressable_entity = Some(enable_addressable_entity);
self
}
pub fn with_storage_costs(mut self, storage_costs: StorageCosts) -> Self {
self.storage_costs = Some(storage_costs);
self
}
pub fn build(self) -> GenesisConfig {
GenesisConfig {
accounts: self.accounts.unwrap_or_default(),
wasm_config: self.wasm_config.unwrap_or_default(),
system_config: self.system_config.unwrap_or_default(),
validator_slots: self.validator_slots.unwrap_or(DEFAULT_VALIDATOR_SLOTS),
auction_delay: self.auction_delay.unwrap_or(DEFAULT_AUCTION_DELAY),
locked_funds_period_millis: self
.locked_funds_period_millis
.unwrap_or(DEFAULT_LOCKED_FUNDS_PERIOD_MILLIS),
round_seigniorage_rate: self
.round_seigniorage_rate
.unwrap_or(DEFAULT_ROUND_SEIGNIORAGE_RATE),
unbonding_delay: self.unbonding_delay.unwrap_or(DEFAULT_UNBONDING_DELAY),
genesis_timestamp_millis: self
.genesis_timestamp_millis
.unwrap_or(DEFAULT_GENESIS_TIMESTAMP_MILLIS),
gas_hold_balance_handling: self
.gas_hold_balance_handling
.unwrap_or(DEFAULT_GAS_HOLD_BALANCE_HANDLING),
gas_hold_interval_millis: self
.gas_hold_interval_millis
.unwrap_or(DEFAULT_GAS_HOLD_INTERVAL_MILLIS),
enable_addressable_entity: self
.enable_addressable_entity
.unwrap_or(DEFAULT_ENABLE_ENTITY),
storage_costs: self.storage_costs.unwrap_or_default(),
}
}
}
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 storage_costs = chainspec.storage_costs;
GenesisConfigBuilder::default()
.with_accounts(chainspec.network_config.accounts_config.clone().into())
.with_wasm_config(chainspec.wasm_config)
.with_system_config(chainspec.system_costs_config)
.with_validator_slots(chainspec.core_config.validator_slots)
.with_auction_delay(chainspec.core_config.auction_delay)
.with_locked_funds_period_millis(chainspec.core_config.locked_funds_period.millis())
.with_round_seigniorage_rate(chainspec.core_config.round_seigniorage_rate)
.with_unbonding_delay(chainspec.core_config.unbonding_delay)
.with_genesis_timestamp_millis(genesis_timestamp_millis)
.with_gas_hold_balance_handling(gas_hold_balance_handling)
.with_gas_hold_interval_millis(gas_hold_interval_millis)
.with_enable_addressable_entity(chainspec.core_config.enable_addressable_entity)
.with_storage_costs(storage_costs)
.build()
}
}