Skip to content
This repository was archived by the owner on Jun 25, 2024. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion chain/indexer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub use near_indexer_primitives::{
IndexerExecutionOutcomeWithReceipt, IndexerShard, IndexerTransactionWithOutcome,
StreamerMessage,
};
use near_primitives::config::PatchGenesisConfig;

mod streamer;

Expand Down Expand Up @@ -106,7 +107,7 @@ impl Indexer {
GenesisValidationMode::UnsafeFast
};
let near_config =
nearcore::config::load_config(&indexer_config.home_dir, genesis_validation_mode)
nearcore::config::load_config(&indexer_config.home_dir, genesis_validation_mode, PatchGenesisConfig::Skip)
.unwrap_or_else(|e| panic!("Error loading config: {:#}", e));

assert!(
Expand Down
23 changes: 22 additions & 1 deletion core/chain-configs/src/genesis_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use near_primitives::{
use num_rational::Rational32;
use serde::de::{self, DeserializeSeed, IgnoredAny, MapAccess, SeqAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize};
use serde_json::Serializer;
use serde_json::{Serializer, Value};
use sha2::digest::Digest;
use smart_default::SmartDefault;
use std::collections::HashSet;
Expand All @@ -33,6 +33,7 @@ use std::fs::File;
use std::io::{BufReader, Read};
use std::path::{Path, PathBuf};
use tracing::warn;
use crate::genesis_config_patch::GenesisConfigPatch;

const MAX_GAS_PRICE: Balance = 10_000_000_000_000_000_000_000;

Expand Down Expand Up @@ -534,6 +535,26 @@ impl Genesis {
Ok(genesis)
}

fn merge_jsons(base: Value, patch: Value) -> Value {
let mut base_obj = base.clone().as_object().unwrap().clone();
let patch_obj = patch.as_object().unwrap().clone();

for (key, value) in patch_obj {
if !value.is_null() {
base_obj.insert(key, value);
}
}

Value::Object(base_obj)
}

pub fn apply_patch(&mut self, patch: GenesisConfigPatch) {
let patch_fields = serde_json::to_value(&patch).expect("Failed to serialize struct");
let config_fields = serde_json::to_value(self.clone()).unwrap();
let merged_fields = Self::merge_jsons(config_fields, patch_fields);
*self = serde_json::from_value(merged_fields).unwrap();
}

/// Reads Genesis from config and records files.
pub fn from_files<P1, P2>(
config_path: P1,
Expand Down
80 changes: 80 additions & 0 deletions core/chain-configs/src/genesis_config_patch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use near_config_utils::ValidationError;
use near_primitives::shard_layout::ShardLayout;
use near_primitives::{
serialize::dec_format,
types::{
AccountId, AccountInfo, Balance, BlockHeightDelta, Gas, NumBlocks, NumSeats
},
};
use num_rational::Rational32;
use std::fs::File;
use std::io::Read;
use std::path::Path;

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GenesisConfigPatch {
pub num_block_producer_seats: Option<NumSeats>,
pub num_block_producer_seats_per_shard: Option<Vec<NumSeats>>,
pub avg_hidden_validator_seats_per_shard: Option<Vec<NumSeats>>,
pub dynamic_resharding: Option<bool>,
pub protocol_upgrade_stake_threshold: Option<Rational32>,
pub epoch_length: Option<BlockHeightDelta>,
pub gas_limit: Option<Gas>,
#[serde(with = "dec_format")]
#[serde(default)]
pub min_gas_price: Option<Balance>,
#[serde(with = "dec_format")]
#[serde(default)]
pub max_gas_price: Option<Balance>,
pub block_producer_kickout_threshold: Option<u8>,
pub chunk_producer_kickout_threshold: Option<u8>,
pub online_min_threshold: Option<Rational32>,
pub online_max_threshold: Option<Rational32>,
pub gas_price_adjustment_rate: Option<Rational32>,
pub validators: Option<Vec<AccountInfo>>,
pub transaction_validity_period: Option<NumBlocks>,
pub protocol_reward_rate: Option<Rational32>,
pub max_inflation_rate: Option<Rational32>,
#[serde(with = "dec_format")]
#[serde(default)]
pub total_supply: Option<Balance>,
pub num_blocks_per_year: Option<NumBlocks>,
pub protocol_treasury_account: Option<AccountId>,
#[serde(with = "dec_format")]
#[serde(default)]
pub fishermen_threshold: Option<Balance>,
pub minimum_stake_divisor: Option<u64>,
pub shard_layout: Option<ShardLayout>,
pub num_chunk_only_producer_seats: Option<NumSeats>,
pub minimum_validators_per_shard: Option<NumSeats>,
pub max_kickout_stake_perc: Option<u8>,
pub minimum_stake_ratio: Option<Rational32>,
Comment on lines +16 to +51

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: order properties alphabetically by name to improve readability

Btw, some of the fields from initial GenesisConfig are ommitted, how did you choose which to include in the patch?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the order, I would prefer that order is the same as in the original genesis config struct. I do not have any preferences in fields being in alphabetical or current order. I can change it in both structs, but my guess is that they are ok with the current order of fields. Probably @mhalambek would know more about this

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have omitted the first 4 fields from the original genesis config struct (protocol_version, genesis_time, chain_id, and genesis_height).

I have omitted them because it seemed to me that Calimero (or similar Near forks) would not use override of those fields as discussed earlier with Hala. I have no strong preference here, I can also include all fields for the simplicity

}

impl GenesisConfigPatch {
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<GenesisConfigPatch, ValidationError> {
let mut file = File::open(&path).map_err(|_| ValidationError::GenesisFileError {
error_message: format!(
"Could not open genesis patch config file at path {}.",
&path.as_ref().display()
),
})?;

let mut json_str = String::new();
file.read_to_string(&mut json_str).map_err(|_| ValidationError::GenesisFileError {
error_message: "Failed to read genesis patch config file to string. ".to_string(),
})?;

let json_str_without_comments = near_config_utils::strip_comments_from_json_str(&json_str)
.map_err(|_| ValidationError::GenesisFileError {
error_message: "Failed to strip comments from genesis patch config file".to_string(),
})?;

let genesis_patch = serde_json::from_str::<GenesisConfigPatch>(&json_str_without_comments)
.map_err(|_| ValidationError::GenesisFileError {
error_message: "Failed to deserialize the genesis patch records.".to_string(),
})?;

Ok(genesis_patch)
}
}
2 changes: 2 additions & 0 deletions core/chain-configs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod client_config;
mod genesis_config_patch;
mod genesis_config;
pub mod genesis_validate;
#[cfg(feature = "metrics")]
Expand All @@ -10,6 +11,7 @@ pub use client_config::{
LogSummaryStyle, StateSyncConfig, SyncConfig, DEFAULT_GC_NUM_EPOCHS_TO_KEEP,
MIN_GC_NUM_EPOCHS_TO_KEEP, TEST_STATE_SYNC_TIMEOUT,
};
pub use genesis_config_patch::GenesisConfigPatch;
pub use genesis_config::{
get_initial_supply, stream_records_from_file, Genesis, GenesisChangeConfig, GenesisConfig,
GenesisRecords, GenesisValidationMode, ProtocolConfig, ProtocolConfigView,
Expand Down
8 changes: 8 additions & 0 deletions core/primitives-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,3 +564,11 @@ impl ExtCosts {
}
}
}

#[derive(Debug, PartialEq)]
pub enum PatchGenesisConfig {
/// Genesis config override with values from patch file.
Patch = 0,
/// Skip genesis config overrides.
Skip = 1,
}
24 changes: 21 additions & 3 deletions nearcore/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::download_file::{run_download_file, FileDownloadError};
use anyhow::{anyhow, bail, Context};
use near_chain_configs::{
get_initial_supply, ClientConfig, GCConfig, Genesis, GenesisConfig, GenesisValidationMode,
LogSummaryStyle, MutableConfigValue, StateSyncConfig,
get_initial_supply, ClientConfig, GCConfig, Genesis, GenesisConfig, GenesisConfigPatch,
GenesisValidationMode, LogSummaryStyle, MutableConfigValue, StateSyncConfig,
};
use near_config_utils::{ValidationError, ValidationErrors};
use near_crypto::{InMemorySigner, KeyFile, KeyType, PublicKey, Signer};
Expand All @@ -11,6 +11,7 @@ use near_jsonrpc::RpcConfig;
use near_network::config::NetworkConfig;
use near_network::tcp;
use near_primitives::account::{AccessKey, Account};
use near_primitives::config::PatchGenesisConfig;
use near_primitives::hash::CryptoHash;
#[cfg(test)]
use near_primitives::shard_layout::account_id_to_shard_id;
Expand Down Expand Up @@ -119,6 +120,7 @@ pub const MINIMUM_STAKE_DIVISOR: u64 = 10;

pub const CONFIG_FILENAME: &str = "config.json";
pub const GENESIS_CONFIG_FILENAME: &str = "genesis.json";
pub const GENESIS_PATCH_CONFIG_FILENAME: &str = "genesis_patch.json";
pub const NODE_KEY_FILE: &str = "node_key.json";
pub const VALIDATOR_KEY_FILE: &str = "validator_key.json";

Expand Down Expand Up @@ -280,6 +282,7 @@ impl Default for Consensus {
pub struct Config {
pub genesis_file: String,
pub genesis_records_file: Option<String>,
pub genesis_patch_file: String,
pub validator_key_file: String,
pub node_key_file: String,
#[cfg(feature = "json_rpc")]
Expand Down Expand Up @@ -356,6 +359,7 @@ impl Default for Config {
Config {
genesis_file: GENESIS_CONFIG_FILENAME.to_string(),
genesis_records_file: None,
genesis_patch_file: GENESIS_PATCH_CONFIG_FILENAME.to_string(),
validator_key_file: VALIDATOR_KEY_FILE.to_string(),
node_key_file: NODE_KEY_FILE.to_string(),
#[cfg(feature = "json_rpc")]
Expand Down Expand Up @@ -1408,6 +1412,7 @@ impl From<NodeKeyFile> for KeyFile {
pub fn load_config(
dir: &Path,
genesis_validation: GenesisValidationMode,
patch_genesis_config: PatchGenesisConfig,
) -> anyhow::Result<NearConfig> {
let mut validation_errors = ValidationErrors::new();

Expand Down Expand Up @@ -1460,7 +1465,20 @@ pub fn load_config(
};

let genesis = match genesis_result {
Ok(genesis) => {
Ok(mut genesis) => {
if patch_genesis_config == PatchGenesisConfig::Patch {
let genesis_patch_file = dir.join(&config.genesis_patch_file);
let patch_result = GenesisConfigPatch::from_file(&genesis_patch_file);
match patch_result {
Ok(patch) => {
genesis.apply_patch(patch);
}
Err(e) => {
validation_errors.push_errors(e);
}
}
}

if let Err(e) = genesis.validate(genesis_validation) {
validation_errors.push_errors(e)
};
Expand Down
22 changes: 19 additions & 3 deletions neard/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use std::sync::Arc;
use tokio::sync::broadcast;
use tokio::sync::broadcast::Receiver;
use tracing::{debug, error, info, warn};
use near_primitives::config::PatchGenesisConfig;

/// NEAR Protocol Node
#[derive(clap::Parser)]
Expand Down Expand Up @@ -406,6 +407,12 @@ pub(super) struct RunCmd {
/// configuration will be taken.
#[clap(long)]
max_gas_burnt_view: Option<Gas>,
// To apply patch (or override) of values in genesis file pass true with this flag and prepare
// patch file in the same folder as genesis file.
// This is used for running forks of Near network (such as Calimero) and customizing genesis
// chain config when starting the new network.
#[clap(long)]
patch_config: Option<bool>,
}

impl RunCmd {
Expand All @@ -416,9 +423,18 @@ impl RunCmd {
verbose_target: Option<&str>,
o11y_opts: &near_o11y::Options,
) {
let patch_genesis_config = if self.patch_config.is_some() && self.patch_config.unwrap() {
PatchGenesisConfig::Patch
} else {
PatchGenesisConfig::Skip
};

// Load configs from home.
let mut near_config = nearcore::config::load_config(home_dir, genesis_validation)
.unwrap_or_else(|e| panic!("Error loading config: {:#}", e));
let mut near_config = nearcore::config::load_config(
home_dir,
genesis_validation,
patch_genesis_config,
).unwrap_or_else(|e| panic!("Error loading config: {:#}", e));

check_release_build(&near_config.client_config.chain_id);

Expand Down Expand Up @@ -806,7 +822,7 @@ pub(super) struct ValidateConfigCommand {}

impl ValidateConfigCommand {
pub(super) fn run(&self, home_dir: &Path) -> anyhow::Result<()> {
nearcore::config::load_config(home_dir, GenesisValidationMode::Full)?;
nearcore::config::load_config(home_dir, GenesisValidationMode::Full, PatchGenesisConfig::Skip)?;
Ok(())
}
}
Expand Down
2 changes: 2 additions & 0 deletions tools/cold-store/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rand::seq::SliceRandom;
use std::io::Result;
use std::path::Path;
use strum::IntoEnumIterator;
use near_primitives::config::PatchGenesisConfig;

#[derive(clap::Parser)]
pub struct ColdStoreCommand {
Expand Down Expand Up @@ -62,6 +63,7 @@ impl ColdStoreCommand {
let mut near_config = nearcore::config::load_config(
&home_dir,
near_chain_configs::GenesisValidationMode::Full,
PatchGenesisConfig::Skip,
)
.unwrap_or_else(|e| panic!("Error loading config: {:#}", e));

Expand Down
3 changes: 2 additions & 1 deletion tools/flat-storage/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use nearcore::{load_config, NearConfig, NightshadeRuntime};
use std::sync::atomic::AtomicBool;
use std::{path::PathBuf, sync::Arc, time::Duration};
use tqdm::tqdm;
use near_primitives::config::PatchGenesisConfig;

#[derive(Parser)]
pub struct FlatStorageCommand {
Expand Down Expand Up @@ -128,7 +129,7 @@ impl FlatStorageCommand {
}

pub fn run(&self, home_dir: &PathBuf) -> anyhow::Result<()> {
let near_config = load_config(home_dir, near_chain_configs::GenesisValidationMode::Full)?;
let near_config = load_config(home_dir, near_chain_configs::GenesisValidationMode::Full, PatchGenesisConfig::Skip)?;
let opener = NodeStorage::opener(home_dir, false, &near_config.config.store, None);

match &self.subcmd {
Expand Down
3 changes: 2 additions & 1 deletion tools/mirror/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ mod online;
mod secret;

pub use cli::MirrorCommand;
use near_primitives::config::PatchGenesisConfig;

#[derive(strum::EnumIter)]
enum DBCol {
Expand Down Expand Up @@ -852,7 +853,7 @@ impl<T: ChainAccess> TxMirror<T> {
secret: Option<[u8; crate::secret::SECRET_LEN]>,
) -> anyhow::Result<Self> {
let target_config =
nearcore::config::load_config(target_home.as_ref(), GenesisValidationMode::UnsafeFast)
nearcore::config::load_config(target_home.as_ref(), GenesisValidationMode::UnsafeFast, PatchGenesisConfig::Skip)
.with_context(|| {
format!("Error loading target config from {:?}", target_home.as_ref())
})?;
Expand Down
3 changes: 2 additions & 1 deletion tools/mirror/src/offline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use near_primitives_core::types::ShardId;
use nearcore::NightshadeRuntime;
use std::path::Path;
use std::sync::Arc;
use near_primitives::config::PatchGenesisConfig;

fn is_on_current_chain(
chain: &ChainStore,
Expand All @@ -36,7 +37,7 @@ pub(crate) struct ChainAccess {
impl ChainAccess {
pub(crate) fn new<P: AsRef<Path>>(home: P) -> anyhow::Result<Self> {
let mut config =
nearcore::config::load_config(home.as_ref(), GenesisValidationMode::UnsafeFast)
nearcore::config::load_config(home.as_ref(), GenesisValidationMode::UnsafeFast, PatchGenesisConfig::Skip)
.with_context(|| format!("Error loading config from {:?}", home.as_ref()))?;
let node_storage =
nearcore::open_storage(home.as_ref(), &mut config).context("failed opening storage")?;
Expand Down
3 changes: 2 additions & 1 deletion tools/mirror/src/online.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use near_primitives_core::types::ShardId;
use std::path::Path;
use std::sync::Arc;
use std::time::Duration;
use near_indexer::near_primitives::config::PatchGenesisConfig;

pub(crate) struct ChainAccess {
view_client: Addr<ViewClientActor>,
Expand All @@ -29,7 +30,7 @@ pub(crate) struct ChainAccess {
impl ChainAccess {
pub(crate) fn new<P: AsRef<Path>>(home: P) -> anyhow::Result<Self> {
let config =
nearcore::config::load_config(home.as_ref(), GenesisValidationMode::UnsafeFast)
nearcore::config::load_config(home.as_ref(), GenesisValidationMode::UnsafeFast, PatchGenesisConfig::Skip)
.with_context(|| format!("Error loading config from {:?}", home.as_ref()))?;

let node = nearcore::start_with_config(home.as_ref(), config)
Expand Down
3 changes: 2 additions & 1 deletion tools/state-viewer/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use nearcore::{load_config, NearConfig};
use std::path::{Path, PathBuf};

use std::str::FromStr;
use near_primitives::config::PatchGenesisConfig;

#[derive(clap::Subcommand)]
#[clap(subcommand_required = true, arg_required_else_help = true)]
Expand Down Expand Up @@ -104,7 +105,7 @@ impl StateViewerSubCommand {
mode: Mode,
temperature: Temperature,
) {
let near_config = load_config(home_dir, genesis_validation)
let near_config = load_config(home_dir, genesis_validation, PatchGenesisConfig::Skip)
.unwrap_or_else(|e| panic!("Error loading config: {:#}", e));

let cold_config: Option<&near_store::StoreConfig> = near_config.config.cold_store.as_ref();
Expand Down
Loading