From 3cc669117895edf318c442daf9931ea5654c3dd1 Mon Sep 17 00:00:00 2001 From: Tayfun Elmas Date: Wed, 7 Aug 2024 17:08:51 +0300 Subject: [PATCH] feat: Introduce mechanism to load EpochConfigs for production chains from JSON files per version (#11896) Issue: #11265 We introduce a mechanism for storing `EpochConfigs` for mainnet/testnet/mocknet (forknet) in JSON files for various protocol versions and retrieving them from a new library called `EpochConfigStore`. The library parses JSON files containing the epoch configs and loads them in a map from (chain-id x version) to `EpochConfig`. The library is accessed from `AllEpochConfig` when `use_production_config` is set to true AND outside of tests (for this we explicitly set test overrides to default even if there is no explicit override to distinguish cases where a test uses a mainnet/testnet chanin id with a custom `EpochConfig`). We change the existing `for_protocol_version` method of `AllEpochConfig` to `generate_epoch_config` to indicate that it generates a config in code. The new version of `for_protocol_version` internall calls the config store or `generate_epoch_config` based on whether the config store is initialized. We will need to follow-up with more changes to this PR since there are tests that use mainnet/testnet chain id with custom `EpochConfig` which conflicts with the config store (which is supposed to use production configs for these chains). Our eventual goal is to remove `generate_epoch_config` and only have (1) explicitly documented production configs in JSON files or (2) custom-built configs in test but not using the hard-coded changes. --- .../client/src/test_utils/test_env_builder.rs | 6 +- chain/epoch-manager/src/lib.rs | 1 + chain/epoch-manager/src/shard_tracker.rs | 7 +- chain/epoch-manager/src/test_utils.rs | 2 +- chain/epoch-manager/src/tests/mod.rs | 2 +- .../res/epoch_configs/mainnet/100.json | 96 +++++++ .../res/epoch_configs/mainnet/101.json | 89 ++++++ .../res/epoch_configs/mainnet/143.json | 89 ++++++ .../res/epoch_configs/mainnet/29.json | 47 ++++ .../res/epoch_configs/mainnet/48.json | 71 +++++ .../res/epoch_configs/mainnet/56.json | 71 +++++ .../res/epoch_configs/mainnet/64.json | 82 ++++++ .../res/epoch_configs/mainnet/65.json | 89 ++++++ .../res/epoch_configs/mainnet/69.json | 89 ++++++ .../res/epoch_configs/mainnet/70.json | 89 ++++++ .../res/epoch_configs/mocknet/100.json | 96 +++++++ .../res/epoch_configs/mocknet/101.json | 89 ++++++ .../res/epoch_configs/mocknet/29.json | 89 ++++++ .../res/epoch_configs/mocknet/48.json | 71 +++++ .../res/epoch_configs/mocknet/64.json | 82 ++++++ .../res/epoch_configs/mocknet/65.json | 89 ++++++ .../res/epoch_configs/mocknet/69.json | 89 ++++++ .../res/epoch_configs/mocknet/70.json | 89 ++++++ .../res/epoch_configs/testnet/100.json | 96 +++++++ .../res/epoch_configs/testnet/101.json | 89 ++++++ .../res/epoch_configs/testnet/143.json | 89 ++++++ .../res/epoch_configs/testnet/29.json | 47 ++++ .../res/epoch_configs/testnet/48.json | 71 +++++ .../res/epoch_configs/testnet/56.json | 71 +++++ .../res/epoch_configs/testnet/64.json | 82 ++++++ .../res/epoch_configs/testnet/65.json | 89 ++++++ .../res/epoch_configs/testnet/69.json | 89 ++++++ .../res/epoch_configs/testnet/70.json | 89 ++++++ core/primitives/src/epoch_manager.rs | 264 +++++++++++++++++- core/primitives/src/shard_layout.rs | 10 +- .../client/features/stateless_validation.rs | 4 +- .../src/tests/client/resharding.rs | 7 +- 37 files changed, 2600 insertions(+), 21 deletions(-) create mode 100644 core/primitives/res/epoch_configs/mainnet/100.json create mode 100644 core/primitives/res/epoch_configs/mainnet/101.json create mode 100644 core/primitives/res/epoch_configs/mainnet/143.json create mode 100644 core/primitives/res/epoch_configs/mainnet/29.json create mode 100644 core/primitives/res/epoch_configs/mainnet/48.json create mode 100644 core/primitives/res/epoch_configs/mainnet/56.json create mode 100644 core/primitives/res/epoch_configs/mainnet/64.json create mode 100644 core/primitives/res/epoch_configs/mainnet/65.json create mode 100644 core/primitives/res/epoch_configs/mainnet/69.json create mode 100644 core/primitives/res/epoch_configs/mainnet/70.json create mode 100644 core/primitives/res/epoch_configs/mocknet/100.json create mode 100644 core/primitives/res/epoch_configs/mocknet/101.json create mode 100644 core/primitives/res/epoch_configs/mocknet/29.json create mode 100644 core/primitives/res/epoch_configs/mocknet/48.json create mode 100644 core/primitives/res/epoch_configs/mocknet/64.json create mode 100644 core/primitives/res/epoch_configs/mocknet/65.json create mode 100644 core/primitives/res/epoch_configs/mocknet/69.json create mode 100644 core/primitives/res/epoch_configs/mocknet/70.json create mode 100644 core/primitives/res/epoch_configs/testnet/100.json create mode 100644 core/primitives/res/epoch_configs/testnet/101.json create mode 100644 core/primitives/res/epoch_configs/testnet/143.json create mode 100644 core/primitives/res/epoch_configs/testnet/29.json create mode 100644 core/primitives/res/epoch_configs/testnet/48.json create mode 100644 core/primitives/res/epoch_configs/testnet/56.json create mode 100644 core/primitives/res/epoch_configs/testnet/64.json create mode 100644 core/primitives/res/epoch_configs/testnet/65.json create mode 100644 core/primitives/res/epoch_configs/testnet/69.json create mode 100644 core/primitives/res/epoch_configs/testnet/70.json diff --git a/chain/client/src/test_utils/test_env_builder.rs b/chain/client/src/test_utils/test_env_builder.rs index 2a3f929a1da..1364296e135 100644 --- a/chain/client/src/test_utils/test_env_builder.rs +++ b/chain/client/src/test_utils/test_env_builder.rs @@ -249,7 +249,7 @@ impl TestEnvBuilder { /// Constructs real EpochManager implementations for each instance. pub fn epoch_managers_with_test_overrides( self, - test_overrides: Option, + test_overrides: AllEpochConfigTestOverrides, ) -> Self { assert!( self.num_shards.is_none(), @@ -261,7 +261,7 @@ impl TestEnvBuilder { EpochManager::new_arc_handle_with_test_overrides( ret.stores.as_ref().unwrap()[i].clone(), &ret.genesis_config, - test_overrides.clone(), + Some(test_overrides.clone()), ) }) .collect(); @@ -274,7 +274,7 @@ impl TestEnvBuilder { if ret.epoch_managers.is_some() { return ret; } - ret.epoch_managers_with_test_overrides(None) + ret.epoch_managers_with_test_overrides(AllEpochConfigTestOverrides::default()) } /// Constructs MockEpochManager implementations for each instance. diff --git a/chain/epoch-manager/src/lib.rs b/chain/epoch-manager/src/lib.rs index 5a1b6f665d9..8433e697368 100644 --- a/chain/epoch-manager/src/lib.rs +++ b/chain/epoch-manager/src/lib.rs @@ -220,6 +220,7 @@ impl EpochManager { let initial_epoch_config = EpochConfig::from(genesis_config); let epoch_config = AllEpochConfig::new_with_test_overrides( genesis_config.use_production_config(), + genesis_config.protocol_version, initial_epoch_config, &genesis_config.chain_id, test_overrides, diff --git a/chain/epoch-manager/src/shard_tracker.rs b/chain/epoch-manager/src/shard_tracker.rs index e9677c5d55c..8517fd6c288 100644 --- a/chain/epoch-manager/src/shard_tracker.rs +++ b/chain/epoch-manager/src/shard_tracker.rs @@ -261,7 +261,12 @@ mod tests { }; EpochManager::new( store, - AllEpochConfig::new(use_production_config, initial_epoch_config, "test-chain"), + AllEpochConfig::new( + use_production_config, + genesis_protocol_version, + initial_epoch_config, + "test-chain", + ), genesis_protocol_version, reward_calculator, vec![ValidatorStake::new( diff --git a/chain/epoch-manager/src/test_utils.rs b/chain/epoch-manager/src/test_utils.rs index 365292ffeb3..b395753cc52 100644 --- a/chain/epoch-manager/src/test_utils.rs +++ b/chain/epoch-manager/src/test_utils.rs @@ -154,7 +154,7 @@ pub fn epoch_config_with_production_config( shard_layout: ShardLayout::v0(num_shards, 0), validator_max_kickout_stake_perc: 100, }; - AllEpochConfig::new(use_production_config, epoch_config, "test-chain") + AllEpochConfig::new(use_production_config, PROTOCOL_VERSION, epoch_config, "test-chain") } pub fn epoch_config( diff --git a/chain/epoch-manager/src/tests/mod.rs b/chain/epoch-manager/src/tests/mod.rs index 5e369a3e11c..afa0dc9b956 100644 --- a/chain/epoch-manager/src/tests/mod.rs +++ b/chain/epoch-manager/src/tests/mod.rs @@ -2214,7 +2214,7 @@ fn test_protocol_version_switch_with_many_seats() { validator_selection_config: Default::default(), validator_max_kickout_stake_perc: 100, }; - let config = AllEpochConfig::new(false, epoch_config, "test-chain"); + let config = AllEpochConfig::new(false, PROTOCOL_VERSION, epoch_config, "test-chain"); let amount_staked = 1_000_000; let validators = vec![ stake("test1".parse().unwrap(), amount_staked), diff --git a/core/primitives/res/epoch_configs/mainnet/100.json b/core/primitives/res/epoch_configs/mainnet/100.json new file mode 100644 index 00000000000..1a4e2ee0349 --- /dev/null +++ b/core/primitives/res/epoch_configs/mainnet/100.json @@ -0,0 +1,96 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "nightly", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2 + ], + [ + 3 + ], + [ + 4, + 5 + ], + [ + 6 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 3, + 4, + 4, + 5 + ], + "version": 4 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mainnet/101.json b/core/primitives/res/epoch_configs/mainnet/101.json new file mode 100644 index 00000000000..a72a7bfc5cf --- /dev/null +++ b/core/primitives/res/epoch_configs/mainnet/101.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mainnet/143.json b/core/primitives/res/epoch_configs/mainnet/143.json new file mode 100644 index 00000000000..a0c95f30169 --- /dev/null +++ b/core/primitives/res/epoch_configs/mainnet/143.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": true + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mainnet/29.json b/core/primitives/res/epoch_configs/mainnet/29.json new file mode 100644 index 00000000000..43fc514ce29 --- /dev/null +++ b/core/primitives/res/epoch_configs/mainnet/29.json @@ -0,0 +1,47 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0 + ], + "block_producer_kickout_threshold": 90, + "chunk_producer_kickout_threshold": 90, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 100, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V0": { + "num_shards": 1, + "version": 0 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 300, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } + } \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mainnet/48.json b/core/primitives/res/epoch_configs/mainnet/48.json new file mode 100644 index 00000000000..a949cdfb7fa --- /dev/null +++ b/core/primitives/res/epoch_configs/mainnet/48.json @@ -0,0 +1,71 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 90, + "chunk_producer_kickout_threshold": 90, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 100, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "kkuuue2akv_1630967379.near" + ], + "shards_split_map": [ + [ + 0, + 1, + 2, + 3 + ] + ], + "to_parent_shard_map": [ + 0, + 0, + 0, + 0 + ], + "version": 1 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 300, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mainnet/56.json b/core/primitives/res/epoch_configs/mainnet/56.json new file mode 100644 index 00000000000..47c67a5ade8 --- /dev/null +++ b/core/primitives/res/epoch_configs/mainnet/56.json @@ -0,0 +1,71 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "kkuuue2akv_1630967379.near" + ], + "shards_split_map": [ + [ + 0, + 1, + 2, + 3 + ] + ], + "to_parent_shard_map": [ + 0, + 0, + 0, + 0 + ], + "version": 1 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 200, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mainnet/64.json b/core/primitives/res/epoch_configs/mainnet/64.json new file mode 100644 index 00000000000..5932d2209b2 --- /dev/null +++ b/core/primitives/res/epoch_configs/mainnet/64.json @@ -0,0 +1,82 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2 + ], + [ + 3, + 4 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 3, + 3 + ], + "version": 2 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 200, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mainnet/65.json b/core/primitives/res/epoch_configs/mainnet/65.json new file mode 100644 index 00000000000..1148530396d --- /dev/null +++ b/core/primitives/res/epoch_configs/mainnet/65.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 200, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mainnet/69.json b/core/primitives/res/epoch_configs/mainnet/69.json new file mode 100644 index 00000000000..a72a7bfc5cf --- /dev/null +++ b/core/primitives/res/epoch_configs/mainnet/69.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mainnet/70.json b/core/primitives/res/epoch_configs/mainnet/70.json new file mode 100644 index 00000000000..5c1334e68ce --- /dev/null +++ b/core/primitives/res/epoch_configs/mainnet/70.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } + } \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mocknet/100.json b/core/primitives/res/epoch_configs/mocknet/100.json new file mode 100644 index 00000000000..434da0cd724 --- /dev/null +++ b/core/primitives/res/epoch_configs/mocknet/100.json @@ -0,0 +1,96 @@ +{ + "epoch_length": 2000, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "nightly", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2 + ], + [ + 3 + ], + [ + 4, + 5 + ], + [ + 6 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 3, + 4, + 4, + 5 + ], + "version": 4 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": true + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mocknet/101.json b/core/primitives/res/epoch_configs/mocknet/101.json new file mode 100644 index 00000000000..de183ae7a53 --- /dev/null +++ b/core/primitives/res/epoch_configs/mocknet/101.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 2000, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": true + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mocknet/29.json b/core/primitives/res/epoch_configs/mocknet/29.json new file mode 100644 index 00000000000..f941ebabdf3 --- /dev/null +++ b/core/primitives/res/epoch_configs/mocknet/29.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 2000, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 200, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": true + } + } \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mocknet/48.json b/core/primitives/res/epoch_configs/mocknet/48.json new file mode 100644 index 00000000000..a075a673c88 --- /dev/null +++ b/core/primitives/res/epoch_configs/mocknet/48.json @@ -0,0 +1,71 @@ +{ + "epoch_length": 2000, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "kkuuue2akv_1630967379.near" + ], + "shards_split_map": [ + [ + 0, + 1, + 2, + 3 + ] + ], + "to_parent_shard_map": [ + 0, + 0, + 0, + 0 + ], + "version": 1 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 200, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": true + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mocknet/64.json b/core/primitives/res/epoch_configs/mocknet/64.json new file mode 100644 index 00000000000..3b66652ae26 --- /dev/null +++ b/core/primitives/res/epoch_configs/mocknet/64.json @@ -0,0 +1,82 @@ +{ + "epoch_length": 2000, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2 + ], + [ + 3, + 4 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 3, + 3 + ], + "version": 2 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 200, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": true + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mocknet/65.json b/core/primitives/res/epoch_configs/mocknet/65.json new file mode 100644 index 00000000000..b13327e97c5 --- /dev/null +++ b/core/primitives/res/epoch_configs/mocknet/65.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 2000, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 200, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": true + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mocknet/69.json b/core/primitives/res/epoch_configs/mocknet/69.json new file mode 100644 index 00000000000..de183ae7a53 --- /dev/null +++ b/core/primitives/res/epoch_configs/mocknet/69.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 2000, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": true + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/mocknet/70.json b/core/primitives/res/epoch_configs/mocknet/70.json new file mode 100644 index 00000000000..176aa1ee844 --- /dev/null +++ b/core/primitives/res/epoch_configs/mocknet/70.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 2000, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": true + } + } \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/testnet/100.json b/core/primitives/res/epoch_configs/testnet/100.json new file mode 100644 index 00000000000..42bcdb3f4c0 --- /dev/null +++ b/core/primitives/res/epoch_configs/testnet/100.json @@ -0,0 +1,96 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 20, + "num_block_producer_seats_per_shard": [ + 20, + 20, + 20, + 20, + 20, + 20, + 20 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "nightly", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2 + ], + [ + 3 + ], + [ + 4, + 5 + ], + [ + 6 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 3, + 4, + 4, + 5 + ], + "version": 4 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 20, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/testnet/101.json b/core/primitives/res/epoch_configs/testnet/101.json new file mode 100644 index 00000000000..bae562937c7 --- /dev/null +++ b/core/primitives/res/epoch_configs/testnet/101.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 20, + "num_block_producer_seats_per_shard": [ + 20, + 20, + 20, + 20, + 20, + 20 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 20, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/testnet/143.json b/core/primitives/res/epoch_configs/testnet/143.json new file mode 100644 index 00000000000..7ee6f928be9 --- /dev/null +++ b/core/primitives/res/epoch_configs/testnet/143.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 20, + "num_block_producer_seats_per_shard": [ + 20, + 20, + 20, + 20, + 20, + 20 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 20, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": true + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/testnet/29.json b/core/primitives/res/epoch_configs/testnet/29.json new file mode 100644 index 00000000000..faf22361523 --- /dev/null +++ b/core/primitives/res/epoch_configs/testnet/29.json @@ -0,0 +1,47 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 200, + "num_block_producer_seats_per_shard": [ + 200 + ], + "avg_hidden_validator_seats_per_shard": [ + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 90, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 100, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V0": { + "num_shards": 1, + "version": 0 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 300, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } + } \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/testnet/48.json b/core/primitives/res/epoch_configs/testnet/48.json new file mode 100644 index 00000000000..e6281e9b3cf --- /dev/null +++ b/core/primitives/res/epoch_configs/testnet/48.json @@ -0,0 +1,71 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 200, + "num_block_producer_seats_per_shard": [ + 200, + 200, + 200, + 200 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 90, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 100, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "kkuuue2akv_1630967379.near" + ], + "shards_split_map": [ + [ + 0, + 1, + 2, + 3 + ] + ], + "to_parent_shard_map": [ + 0, + 0, + 0, + 0 + ], + "version": 1 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 300, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/testnet/56.json b/core/primitives/res/epoch_configs/testnet/56.json new file mode 100644 index 00000000000..47c67a5ade8 --- /dev/null +++ b/core/primitives/res/epoch_configs/testnet/56.json @@ -0,0 +1,71 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 100, + "num_block_producer_seats_per_shard": [ + 100, + 100, + 100, + 100 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "kkuuue2akv_1630967379.near" + ], + "shards_split_map": [ + [ + 0, + 1, + 2, + 3 + ] + ], + "to_parent_shard_map": [ + 0, + 0, + 0, + 0 + ], + "version": 1 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 200, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/testnet/64.json b/core/primitives/res/epoch_configs/testnet/64.json new file mode 100644 index 00000000000..52eb689ebb1 --- /dev/null +++ b/core/primitives/res/epoch_configs/testnet/64.json @@ -0,0 +1,82 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 20, + "num_block_producer_seats_per_shard": [ + 20, + 20, + 20, + 20, + 20 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2 + ], + [ + 3, + 4 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 3, + 3 + ], + "version": 2 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 100, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/testnet/65.json b/core/primitives/res/epoch_configs/testnet/65.json new file mode 100644 index 00000000000..646d55c8653 --- /dev/null +++ b/core/primitives/res/epoch_configs/testnet/65.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 20, + "num_block_producer_seats_per_shard": [ + 20, + 20, + 20, + 20, + 20, + 20 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 100, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 100, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/testnet/69.json b/core/primitives/res/epoch_configs/testnet/69.json new file mode 100644 index 00000000000..bae562937c7 --- /dev/null +++ b/core/primitives/res/epoch_configs/testnet/69.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 20, + "num_block_producer_seats_per_shard": [ + 20, + 20, + 20, + 20, + 20, + 20 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 20, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } +} \ No newline at end of file diff --git a/core/primitives/res/epoch_configs/testnet/70.json b/core/primitives/res/epoch_configs/testnet/70.json new file mode 100644 index 00000000000..d809843306a --- /dev/null +++ b/core/primitives/res/epoch_configs/testnet/70.json @@ -0,0 +1,89 @@ +{ + "epoch_length": 43200, + "num_block_producer_seats": 20, + "num_block_producer_seats_per_shard": [ + 20, + 20, + 20, + 20, + 20, + 20 + ], + "avg_hidden_validator_seats_per_shard": [ + 0, + 0, + 0, + 0, + 0, + 0 + ], + "block_producer_kickout_threshold": 80, + "chunk_producer_kickout_threshold": 80, + "chunk_validator_only_kickout_threshold": 80, + "target_validator_mandates_per_shard": 68, + "validator_max_kickout_stake_perc": 30, + "online_min_threshold": [ + 90, + 100 + ], + "online_max_threshold": [ + 99, + 100 + ], + "fishermen_threshold": 340282366920938463463374607431768211455, + "minimum_stake_divisor": 10, + "protocol_upgrade_stake_threshold": [ + 4, + 5 + ], + "shard_layout": { + "V1": { + "boundary_accounts": [ + "aurora", + "aurora-0", + "game.hot.tg", + "kkuuue2akv_1630967379.near", + "tge-lockup.sweat" + ], + "shards_split_map": [ + [ + 0 + ], + [ + 1 + ], + [ + 2, + 3 + ], + [ + 4 + ], + [ + 5 + ] + ], + "to_parent_shard_map": [ + 0, + 1, + 2, + 2, + 3, + 4 + ], + "version": 3 + } + }, + "validator_selection_config": { + "num_chunk_producer_seats": 20, + "num_chunk_validator_seats": 300, + "num_chunk_only_producer_seats": 0, + "minimum_validators_per_shard": 1, + "minimum_stake_ratio": [ + 1, + 6250 + ], + "chunk_producer_assignment_changes_limit": 5, + "shuffle_shard_assignment_for_chunk_producers": false + } + } \ No newline at end of file diff --git a/core/primitives/src/epoch_manager.rs b/core/primitives/src/epoch_manager.rs index 93e8f9ec399..bbcedb30211 100644 --- a/core/primitives/src/epoch_manager.rs +++ b/core/primitives/src/epoch_manager.rs @@ -13,13 +13,15 @@ use near_primitives_core::hash::CryptoHash; use near_primitives_core::types::BlockHeight; use near_schema_checker_lib::ProtocolSchema; use smart_default::SmartDefault; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; +use std::ops::Bound; +use std::sync::Arc; pub const AGGREGATOR_KEY: &[u8] = b"AGGREGATOR"; /// Epoch config, determines validator assignment for given epoch. /// Can change from epoch to epoch depending on the sharding and other parameters, etc. -#[derive(Clone, Eq, Debug, PartialEq)] +#[derive(Clone, Eq, Debug, PartialEq, serde::Serialize, serde::Deserialize)] pub struct EpochConfig { /// Epoch length in block heights. pub epoch_length: BlockHeightDelta, @@ -89,6 +91,9 @@ pub struct AllEpochConfigTestOverrides { /// and returns the EpochConfig that should be used for this protocol version. #[derive(Clone)] pub struct AllEpochConfig { + /// Store for EpochConfigs, provides configs per protocol version. + /// Initialized only for production, ie. when `use_protocol_version` is true. + config_store: Option, /// Whether this is for production (i.e., mainnet or testnet). This is a temporary implementation /// to allow us to change protocol config for mainnet and testnet without changing the genesis config use_production_config: bool, @@ -104,32 +109,63 @@ pub struct AllEpochConfig { impl AllEpochConfig { pub fn new( use_production_config: bool, + genesis_protocol_version: ProtocolVersion, genesis_epoch_config: EpochConfig, chain_id: &str, ) -> Self { - Self { + Self::new_with_test_overrides( use_production_config, + genesis_protocol_version, genesis_epoch_config, - chain_id: chain_id.to_string(), - test_overrides: AllEpochConfigTestOverrides::default(), - } + chain_id, + Some(AllEpochConfigTestOverrides::default()), + ) } pub fn new_with_test_overrides( use_production_config: bool, + genesis_protocol_version: ProtocolVersion, genesis_epoch_config: EpochConfig, chain_id: &str, test_overrides: Option, ) -> Self { - Self { + // Use the config store only for production configs and outside of tests. + let config_store = if use_production_config && test_overrides.is_none() { + EpochConfigStore::for_chain_id(chain_id) + } else { + None + }; + let all_epoch_config = Self { + config_store: config_store.clone(), use_production_config, genesis_epoch_config, chain_id: chain_id.to_string(), test_overrides: test_overrides.unwrap_or_default(), + }; + // Sanity check: Validate that the stored genesis config equals to the config generated for the genesis protocol version. + // Note that we cannot do this in unittests because we do not have direct access to the genesis config for mainnet/testnet. + // Thus, by making sure that the generated and store configs match for the genesis, we complement the unittests, which + // check that the generated and stored configs match for the versions after the genesis. + if config_store.is_some() { + debug_assert_eq!( + config_store.as_ref().unwrap().get_config(genesis_protocol_version).as_ref(), + &all_epoch_config.generate_epoch_config(genesis_protocol_version), + "Provided genesis EpochConfig for protocol version {} does not match the stored config", genesis_protocol_version + ); } + all_epoch_config } pub fn for_protocol_version(&self, protocol_version: ProtocolVersion) -> EpochConfig { + if self.config_store.is_some() { + self.config_store.as_ref().unwrap().get_config(protocol_version).as_ref().clone() + } else { + self.generate_epoch_config(protocol_version) + } + } + + /// TODO(#11265): Remove this and use the stored configs only. + pub fn generate_epoch_config(&self, protocol_version: ProtocolVersion) -> EpochConfig { let mut config = self.genesis_epoch_config.clone(); Self::config_mocknet(&mut config, &self.chain_id); @@ -283,7 +319,7 @@ impl AllEpochConfig { /// Additional configuration parameters for the new validator selection /// algorithm. See for details. -#[derive(Debug, Clone, SmartDefault, PartialEq, Eq)] +#[derive(Debug, Clone, SmartDefault, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct ValidatorSelectionConfig { #[default(100)] pub num_chunk_producer_seats: NumSeats, @@ -780,3 +816,215 @@ pub struct EpochSummary { /// epoch T+2. pub next_next_epoch_version: ProtocolVersion, } + +macro_rules! include_config { + ($chain:expr, $version:expr, $file:expr) => { + ( + $chain, + $version, + include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/res/epoch_configs/", + $chain, + "/", + $file + )), + ) + }; +} + +/// List of (chain_id, version, JSON content) tuples used to initialize the EpochConfigStore. +static CONFIGS: &[(&str, ProtocolVersion, &str)] = &[ + // Epoch configs for mainnet (genesis protool version is 29). + include_config!("mainnet", 29, "29.json"), + include_config!("mainnet", 48, "48.json"), + include_config!("mainnet", 56, "56.json"), + include_config!("mainnet", 64, "64.json"), + include_config!("mainnet", 65, "65.json"), + include_config!("mainnet", 69, "69.json"), + include_config!("mainnet", 70, "70.json"), + include_config!("mainnet", 100, "100.json"), + include_config!("mainnet", 101, "101.json"), + include_config!("mainnet", 143, "143.json"), + // Epoch configs for testnet (genesis protool version is 29). + include_config!("testnet", 29, "29.json"), + include_config!("testnet", 48, "48.json"), + include_config!("testnet", 56, "56.json"), + include_config!("testnet", 64, "64.json"), + include_config!("testnet", 65, "65.json"), + include_config!("testnet", 69, "69.json"), + include_config!("testnet", 70, "70.json"), + include_config!("testnet", 100, "100.json"), + include_config!("testnet", 101, "101.json"), + include_config!("testnet", 143, "143.json"), + // Epoch configs for mocknet (forknet) (genesis protool version is 29). + // TODO(#11900): Check the forknet config and uncomment this. + // include_config!("mocknet", 29, "29.json"), + // include_config!("mocknet", 48, "48.json"), + // include_config!("mocknet", 64, "64.json"), + // include_config!("mocknet", 65, "65.json"), + // include_config!("mocknet", 69, "69.json"), + // include_config!("mocknet", 70, "70.json"), + // include_config!("mocknet", 100, "100.json"), + // include_config!("mocknet", 101, "101.json"), +]; + +/// Store for `[EpochConfig]` per protocol version.` +#[derive(Clone)] +pub struct EpochConfigStore { + store: BTreeMap>, +} + +impl EpochConfigStore { + /// Creates a config store to contain the EpochConfigs for the given chain parsed from the JSON files. + /// Returns None if there is no epoch config file stored for the given chain. + pub fn for_chain_id(chain_id: &str) -> Option { + let mut store = BTreeMap::new(); + for (chain, version, content) in CONFIGS.iter() { + if *chain == chain_id { + let config: EpochConfig = serde_json::from_str(*content).unwrap_or_else(|e| { + panic!("Failed to load epoch config files for chain {}: {:#}", chain_id, e) + }); + store.insert(*version, Arc::new(config)); + } + } + if store.is_empty() { + None + } else { + Some(Self { store }) + } + } + + /// Returns the EpochConfig for the given protocol version. + /// This panics if no config is found for the given version, thus the initialization via `for_chain_id` should + /// only be performed for chains with some configs stored in files. + fn get_config(&self, protocol_version: ProtocolVersion) -> &Arc { + self.store + .range((Bound::Unbounded, Bound::Included(protocol_version))) + .next_back() + .unwrap_or_else(|| { + panic!("Failed to find EpochConfig for protocol version {}", protocol_version) + }) + .1 + } +} + +#[cfg(test)] +mod tests { + use std::fs; + use std::path::Path; + + use near_primitives_core::types::ProtocolVersion; + use near_primitives_core::version::PROTOCOL_VERSION; + + use crate::epoch_manager::{AllEpochConfig, EpochConfig}; + + use super::EpochConfigStore; + + /// Checks that stored epoch config for latest protocol version matches the + /// one generated by overrides from genesis config. + /// If the test fails, it is either a configuration bug or the stored + /// epoch config must be updated. + fn test_epoch_config_store(chain_id: &str, genesis_protocol_version: ProtocolVersion) { + let genesis_epoch_config = parse_config_file(chain_id, genesis_protocol_version).unwrap(); + let all_epoch_config = AllEpochConfig::new_with_test_overrides( + true, + genesis_protocol_version, + genesis_epoch_config, + chain_id, + None, + ); + + let config_store = EpochConfigStore::for_chain_id(chain_id).unwrap(); + for protocol_version in genesis_protocol_version..=PROTOCOL_VERSION { + let stored_config = config_store.get_config(protocol_version); + let expected_config = all_epoch_config.generate_epoch_config(protocol_version); + assert_eq!(*stored_config.as_ref(), expected_config); + } + } + + #[test] + fn test_epoch_config_store_ainnet() { + test_epoch_config_store("mainnet", 29); + } + + #[test] + fn test_epoch_config_store_testnet() { + test_epoch_config_store("testnet", 29); + } + + // TODO(#11900): Check the forknet config and uncomment this. + // #[test] + // fn test_epoch_config_store_mocknet() { + // test_epoch_config_store("mocknet", 29); + // } + + #[allow(unused)] + fn generate_epoch_configs(chain_id: &str, genesis_protocol_version: ProtocolVersion) { + let genesis_epoch_config = parse_config_file(chain_id, genesis_protocol_version).unwrap(); + let all_epoch_config = AllEpochConfig::new_with_test_overrides( + true, + genesis_protocol_version, + genesis_epoch_config.clone(), + chain_id, + None, + ); + + let mut prev_config = genesis_epoch_config; + for protocol_version in genesis_protocol_version + 1..=PROTOCOL_VERSION { + let next_config = all_epoch_config.generate_epoch_config(protocol_version); + if next_config != prev_config { + tracing::info!("Writing config for protocol version {}", protocol_version); + dump_config_file(&next_config, chain_id, protocol_version); + } + prev_config = next_config; + } + } + + #[test] + #[ignore] + fn generate_epoch_configs_mainnet() { + generate_epoch_configs("mainnet", 29); + } + + #[test] + #[ignore] + fn generate_epoch_configs_testnet() { + generate_epoch_configs("testnet", 29); + } + + // TODO(#11900): Check the forknet config and uncomment this. + // #[test] + // #[ignore] + // fn generate_epoch_configs_mocknet() { + // generate_epoch_configs("mocknet", 29); + // } + + #[allow(unused)] + fn parse_config_file(chain_id: &str, protocol_version: ProtocolVersion) -> Option { + let path = Path::new(env!("CARGO_MANIFEST_DIR")) + .join("res/epoch_configs") + .join(chain_id) + .join(format!("{}.json", protocol_version)); + if path.exists() { + let content = fs::read_to_string(path).unwrap(); + let config: EpochConfig = serde_json::from_str(&content).unwrap(); + Some(config) + } else { + None + } + } + + #[allow(unused)] + fn dump_config_file(config: &EpochConfig, chain_id: &str, protocol_version: ProtocolVersion) { + let content = serde_json::to_string_pretty(config).unwrap(); + fs::write( + Path::new(env!("CARGO_MANIFEST_DIR")) + .join("res/epoch_configs") + .join(chain_id) + .join(format!("{}.json", protocol_version)), + content, + ) + .unwrap() + } +} diff --git a/core/primitives/src/shard_layout.rs b/core/primitives/src/shard_layout.rs index 2f61f052a8d..f15ab81b10d 100644 --- a/core/primitives/src/shard_layout.rs +++ b/core/primitives/src/shard_layout.rs @@ -505,7 +505,7 @@ mod tests { use crate::shard_layout::{account_id_to_shard_id, ShardLayout, ShardLayoutV1, ShardUId}; use near_primitives_core::types::ProtocolVersion; use near_primitives_core::types::{AccountId, ShardId}; - use near_primitives_core::version::ProtocolFeature; + use near_primitives_core::version::{ProtocolFeature, PROTOCOL_VERSION}; use rand::distributions::Alphanumeric; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; @@ -556,7 +556,13 @@ mod tests { validator_selection_config: ValidatorSelectionConfig::default(), }; - let all_epoch_config = AllEpochConfig::new(true, genesis_epoch_config, "test-chain"); + let genesis_protocol_version = PROTOCOL_VERSION; + let all_epoch_config = AllEpochConfig::new( + true, + genesis_protocol_version, + genesis_epoch_config, + "test-chain", + ); let latest_epoch_config = all_epoch_config.for_protocol_version(protocol_version); latest_epoch_config.shard_layout } diff --git a/integration-tests/src/tests/client/features/stateless_validation.rs b/integration-tests/src/tests/client/features/stateless_validation.rs index 8a6fe86fd56..b434991ecd9 100644 --- a/integration-tests/src/tests/client/features/stateless_validation.rs +++ b/integration-tests/src/tests/client/features/stateless_validation.rs @@ -105,10 +105,10 @@ fn run_chunk_validation_test( max_inflation_rate: Rational32::new(1, 1), ..Default::default() }; - let epoch_config_test_overrides = Some(AllEpochConfigTestOverrides { + let epoch_config_test_overrides = AllEpochConfigTestOverrides { block_producer_kickout_threshold: Some(0), chunk_producer_kickout_threshold: Some(0), - }); + }; // Set up the records corresponding to the validator accounts. let mut records = Vec::new(); diff --git a/integration-tests/src/tests/client/resharding.rs b/integration-tests/src/tests/client/resharding.rs index 49bb65457da..1bc73b06651 100644 --- a/integration-tests/src/tests/client/resharding.rs +++ b/integration-tests/src/tests/client/resharding.rs @@ -230,10 +230,10 @@ impl TestReshardingEnv { // doesn't support requesting chunks and non-validators wouldn't be able // to obtain the chunks at all. // Same needs to be set in the genesis. - let epoch_config_test_overrides = Some(AllEpochConfigTestOverrides { + let epoch_config_test_overrides = AllEpochConfigTestOverrides { block_producer_kickout_threshold: Some(0), chunk_producer_kickout_threshold: Some(0), - }); + }; let env = builder .clients_count(num_clients) .validator_seats(num_validators) @@ -886,7 +886,8 @@ fn setup_genesis( genesis.config.protocol_upgrade_stake_threshold = Rational32::new(7, 10); let default_epoch_config = EpochConfig::from(&genesis.config); - let all_epoch_config = AllEpochConfig::new(true, default_epoch_config, "test-chain"); + let all_epoch_config = + AllEpochConfig::new(true, genesis_protocol_version, default_epoch_config, "test-chain"); let epoch_config = all_epoch_config.for_protocol_version(genesis_protocol_version); genesis.config.shard_layout = epoch_config.shard_layout;