diff --git a/crates/configuration/Cargo.toml b/crates/configuration/Cargo.toml index 56d70d80a8accfc46fcefa9dce1a12b267c7bd55..b7525f21af7bcc8021744bc472d3b804ad3ca5d3 100644 --- a/crates/configuration/Cargo.toml +++ b/crates/configuration/Cargo.toml @@ -12,3 +12,4 @@ thiserror = { workspace = true } anyhow = { workspace = true } serde = { workspace = true, features = ["derive"] } toml = { workspace = true } +serde_json = { workspace = true } diff --git a/crates/configuration/src/parachain.rs b/crates/configuration/src/parachain.rs index 543b778a13576e07b7b36000012e627f73761187..8dd9c9bcd9a8c3f01041ce59794ff395c4ed690e 100644 --- a/crates/configuration/src/parachain.rs +++ b/crates/configuration/src/parachain.rs @@ -122,6 +122,7 @@ pub struct ParachainConfig { is_cumulus_based: bool, #[serde(skip_serializing_if = "std::vec::Vec::is_empty", default)] bootnodes_addresses: Vec<Multiaddr>, + genesis_overrides: Option<serde_json::Value>, #[serde(skip_serializing_if = "std::vec::Vec::is_empty", default)] collators: Vec<NodeConfig>, } @@ -197,6 +198,11 @@ impl ParachainConfig { self.genesis_state_generator.as_ref() } + /// The genesis overrides as a JSON value. + pub fn genesis_overrides(&self) -> Option<&serde_json::Value> { + self.genesis_overrides.as_ref() + } + /// The location of a pre-existing chain specification for the parachain. pub fn chain_spec_path(&self) -> Option<&AssetLocation> { self.chain_spec_path.as_ref() @@ -250,6 +256,7 @@ impl Default for ParachainConfigBuilder<Initial> { genesis_wasm_generator: None, genesis_state_path: None, genesis_state_generator: None, + genesis_overrides: None, chain_spec_path: None, is_cumulus_based: true, bootnodes_addresses: vec![], @@ -540,6 +547,18 @@ impl ParachainConfigBuilder<WithId> { } } + /// Set the genesis overrides as a JSON object. + pub fn with_genesis_overrides(self, genesis_overrides: impl Into<serde_json::Value>) -> Self { + Self::transition( + ParachainConfig { + genesis_overrides: Some(genesis_overrides.into()), + ..self.config + }, + self.validation_context, + self.errors, + ) + } + /// Set the location of a pre-existing chain specification for the parachain. pub fn with_chain_spec_path(self, location: impl Into<AssetLocation>) -> Self { Self::transition( diff --git a/crates/configuration/src/relaychain.rs b/crates/configuration/src/relaychain.rs index b087ddcf7efd1ac2d892ee3bd4c04f06092f75f5..f226b79d7ba985e3042989ce3bbf746f37bee898 100644 --- a/crates/configuration/src/relaychain.rs +++ b/crates/configuration/src/relaychain.rs @@ -27,6 +27,7 @@ pub struct RelaychainConfig { max_nominations: Option<u8>, #[serde(skip_serializing_if = "std::vec::Vec::is_empty", default)] nodes: Vec<NodeConfig>, + genesis_overrides: Option<serde_json::Value>, } impl RelaychainConfig { @@ -75,6 +76,11 @@ impl RelaychainConfig { self.max_nominations } + /// The genesis overrides as a JSON value. + pub fn genesis_overrides(&self) -> Option<&serde_json::Value> { + self.genesis_overrides.as_ref() + } + /// The nodes of the relay chain. pub fn nodes(&self) -> Vec<&NodeConfig> { self.nodes.iter().collect::<Vec<&NodeConfig>>() @@ -114,6 +120,7 @@ impl Default for RelaychainConfigBuilder<Initial> { chain_spec_path: None, random_nominators_count: None, max_nominations: None, + genesis_overrides: None, nodes: vec![], }, validation_context: Default::default(), @@ -314,6 +321,18 @@ impl RelaychainConfigBuilder<WithChain> { ) } + /// Set the genesis overrides as a JSON object. + pub fn with_genesis_overrides(self, genesis_overrides: impl Into<serde_json::Value>) -> Self { + Self::transition( + RelaychainConfig { + genesis_overrides: Some(genesis_overrides.into()), + ..self.config + }, + self.validation_context, + self.errors, + ) + } + /// Add a new node using a nested [`NodeConfigBuilder`]. pub fn with_node( self, diff --git a/crates/orchestrator/src/generators/chain_spec.rs b/crates/orchestrator/src/generators/chain_spec.rs index f302d65909d9b70fff3445f08cef675c5b58f99d..9497ebf74b7c5af9294b1783081e4b67dd7514d9 100644 --- a/crates/orchestrator/src/generators/chain_spec.rs +++ b/crates/orchestrator/src/generators/chain_spec.rs @@ -311,7 +311,13 @@ impl ChainSpec { .map_err(GeneratorError::ChainSpecGeneration)?; // make genesis overrides first. - // override_genesis() + if let Some(overrides) = ¶.genesis_overrides { + if let Some(genesis) = chain_spec_json.pointer_mut(&format!("{}/genesis", pointer)) + { + override_genesis(genesis, overrides); + } + } + clear_authorities(&pointer, &mut chain_spec_json); // Get validators to add as authorities @@ -381,7 +387,12 @@ impl ChainSpec { .map_err(GeneratorError::ChainSpecGeneration)?; // make genesis overrides first. - // override_genesis() + if let Some(overrides) = &relaychain.genesis_overrides { + if let Some(genesis) = chain_spec_json.pointer_mut(&format!("{}/genesis", pointer)) + { + override_genesis(genesis, overrides); + } + } println!( "{:#?}", @@ -596,8 +607,29 @@ fn get_runtime_config_pointer(chain_spec_json: &serde_json::Value) -> Result<Str } // Override `genesis` key if present -fn override_genesis() { - todo!() +fn override_genesis(genesis: &mut serde_json::Value, overrides: &serde_json::Value) { + if let (Some(genesis_obj), Some(overrides_obj)) = + (genesis.as_object_mut(), overrides.as_object()) + { + for overrides_key in overrides_obj.keys() { + // we only want to override keys present in the genesis object + if let Some(genesis_value) = genesis_obj.get_mut(overrides_key) { + match (&genesis_value, overrides_obj.get(overrides_key)) { + // recurse if genesis value is an object + (serde_json::Value::Object(_), Some(overrides_value)) + if overrides_value.is_object() => + { + override_genesis(genesis_value, overrides_value); + }, + // override if genesis value not an object + (_, Some(overrides_value)) => { + *genesis_value = overrides_value.clone(); + }, + _ => {}, + } + } + } + } } fn clear_authorities(runtime_config_ptr: &str, chain_spec_json: &mut serde_json::Value) { diff --git a/crates/orchestrator/src/network_spec/parachain.rs b/crates/orchestrator/src/network_spec/parachain.rs index d5334df5c9b280f209e8754738f0fe1e4c8da251..33e1217f0690f178b5a754d91f24f34768d39705 100644 --- a/crates/orchestrator/src/network_spec/parachain.rs +++ b/crates/orchestrator/src/network_spec/parachain.rs @@ -57,6 +57,9 @@ pub struct ParachainSpec { /// Genesis wasm to register the parachain pub(crate) genesis_wasm: ParaArtifact, + /// Genesis overrides as JSON value. + pub(crate) genesis_overrides: Option<serde_json::Value>, + /// Collators to spawn pub(crate) collators: Vec<NodeSpec>, } @@ -174,6 +177,7 @@ impl ParachainSpec { initial_balance: config.initial_balance(), genesis_state, genesis_wasm, + genesis_overrides: config.genesis_overrides().cloned(), collators, }; diff --git a/crates/orchestrator/src/network_spec/relaychain.rs b/crates/orchestrator/src/network_spec/relaychain.rs index 1f1fd608001b9d017b4cdd87e2aa5bc9ecebfc1d..a7adee2ab4badb87b6e71f7d75478801f9c50295 100644 --- a/crates/orchestrator/src/network_spec/relaychain.rs +++ b/crates/orchestrator/src/network_spec/relaychain.rs @@ -43,6 +43,9 @@ pub struct RelaychainSpec { /// Set the max nominators value (used with PoS networks). pub(crate) max_nominations: u8, + /// Genesis overrides as JSON value. + pub(crate) genesis_overrides: Option<serde_json::Value>, + /// Nodes to run. pub(crate) nodes: Vec<NodeSpec>, } @@ -107,6 +110,7 @@ impl RelaychainSpec { chain_spec, random_nominators_count: config.random_nominators_count().unwrap_or(0), max_nominations: config.max_nominations().unwrap_or(24), + genesis_overrides: config.genesis_overrides().cloned(), nodes, }) }