-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
150 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,104 +1,154 @@ | ||
use std::time::Duration; | ||
use std::{collections::HashMap, str::FromStr, time::Duration}; | ||
|
||
use anyhow::Context; | ||
use serde::{Deserialize, Serialize}; | ||
use clap::Parser; | ||
use serde::{Deserialize, Deserializer}; | ||
use serde_with::serde_as; | ||
use serde_yaml::Value; | ||
use starknet_api::core::{ChainId, ContractAddress}; | ||
|
||
use mp_block::H160; | ||
use mp_chain_config::{ChainConfig, StarknetVersion}; | ||
use mp_utils::parsers::parse_key_value; | ||
use mp_utils::parsers::parse_duration; | ||
use mp_utils::parsers::parse_key_value_yaml; | ||
|
||
/// Override chain config parameters. | ||
/// Format: "--chain-config-override chain_id=NEW_MADARA --chain-config-override chain_name=NEW_NAME" | ||
#[derive(clap::Parser, Clone, Debug)] | ||
/// Format: "--chain-config-override chain_id=SN_MADARA,chain_name=MADARA,block_time=1.5" | ||
#[derive(Parser, Clone, Debug)] | ||
pub struct ChainConfigOverrideParams { | ||
#[clap(long = "chain-config-override", value_parser = parse_key_value, number_of_values = 1)] | ||
pub overrides: Vec<(String, String)>, | ||
#[clap(long = "chain-config-override", value_parser = parse_key_value_yaml, use_value_delimiter = true, value_delimiter = ',')] | ||
pub overrides: Vec<(String, Value)>, | ||
} | ||
|
||
/// Part of the Chain Config that we can override. | ||
#[serde_as] | ||
#[derive(Debug, Default, Deserialize)] | ||
pub struct ChainConfigOverridesInner { | ||
pub chain_name: Option<String>, | ||
pub chain_id: Option<ChainId>, | ||
pub native_fee_token_address: Option<ContractAddress>, | ||
pub parent_fee_token_address: Option<ContractAddress>, | ||
#[serde(default, deserialize_with = "deserialize_version")] | ||
pub latest_protocol_version: Option<StarknetVersion>, | ||
#[serde(default, deserialize_with = "deserialize_duration")] | ||
pub block_time: Option<Duration>, | ||
#[serde(default, deserialize_with = "deserialize_duration")] | ||
pub pending_block_update_time: Option<Duration>, | ||
pub execution_batch_size: Option<usize>, | ||
pub sequencer_address: Option<ContractAddress>, | ||
pub max_nonce_for_validation_skip: Option<u64>, | ||
pub eth_core_contract_address: Option<H160>, | ||
|
||
// bouncer config | ||
pub gas: Option<usize>, | ||
pub message_segment_length: Option<usize>, | ||
pub n_events: Option<usize>, | ||
pub n_steps: Option<usize>, | ||
pub state_diff_size: Option<usize>, | ||
pub add_mod: Option<usize>, | ||
pub bitwise: Option<usize>, | ||
pub ecdsa: Option<usize>, | ||
pub ec_op: Option<usize>, | ||
pub keccak: Option<usize>, | ||
pub mul_mod: Option<usize>, | ||
pub pedersen: Option<usize>, | ||
pub poseidon: Option<usize>, | ||
pub range_check: Option<usize>, | ||
pub range_check96: Option<usize>, | ||
} | ||
|
||
impl ChainConfigOverrideParams { | ||
pub fn override_chain_config(&self, chain_config: ChainConfig) -> anyhow::Result<ChainConfig> { | ||
let overridable = OverridableChainConfig::from(&chain_config); | ||
let mut config_value = | ||
serde_yaml::to_value(overridable).context("Failed to convert OverridableChainConfig to Value")?; | ||
|
||
if let Value::Mapping(ref mut map) = config_value { | ||
for (key, value) in &self.overrides { | ||
if !map.contains_key(Value::String(key.clone())) { | ||
return Err(anyhow::anyhow!("The field '{}' is not overridable for the Chain Config.", key)); | ||
pub fn override_chain_config(&self, chain_config: &mut ChainConfig) -> anyhow::Result<()> { | ||
let overrides_map: HashMap<_, _> = self.overrides.iter().cloned().collect(); | ||
let overrides_value = serde_yaml::to_value(overrides_map).context("Failed to convert overrides to Value")?; | ||
let overrides: ChainConfigOverridesInner = | ||
serde_yaml::from_value(overrides_value).context("Failed to parse YAML Value to ChainConfigOverrides")?; | ||
|
||
// Update config fields with any provided override values | ||
macro_rules! apply_override { | ||
($config:expr, $field:ident, $overrides:expr) => { | ||
if let Some(value) = &$overrides.$field { | ||
$config.$field = value.clone(); | ||
} | ||
map.insert(Value::String(key.clone()), Value::String(value.clone())); | ||
} | ||
} else { | ||
return Err(anyhow::anyhow!("Unexpected chain config structure.")); | ||
}; | ||
} | ||
|
||
let updated_overridable: OverridableChainConfig = | ||
serde_yaml::from_value(config_value).context("Failed to convert Value back to OverridableChainConfig")?; | ||
apply_override!(chain_config, chain_name, overrides); | ||
apply_override!(chain_config, chain_id, overrides); | ||
apply_override!(chain_config, native_fee_token_address, overrides); | ||
apply_override!(chain_config, parent_fee_token_address, overrides); | ||
apply_override!(chain_config, latest_protocol_version, overrides); | ||
apply_override!(chain_config, block_time, overrides); | ||
apply_override!(chain_config, pending_block_update_time, overrides); | ||
apply_override!(chain_config, execution_batch_size, overrides); | ||
apply_override!(chain_config, sequencer_address, overrides); | ||
apply_override!(chain_config, max_nonce_for_validation_skip, overrides); | ||
apply_override!(chain_config, eth_core_contract_address, overrides); | ||
|
||
Ok(ChainConfig { | ||
versioned_constants: chain_config.versioned_constants, | ||
bouncer_config: chain_config.bouncer_config, | ||
..updated_overridable.into() | ||
}) | ||
} | ||
} | ||
// Apply bouncer configurations | ||
macro_rules! apply_bouncer { | ||
($config:expr, $field:ident, $overrides:expr) => { | ||
if let Some(value) = &$overrides.$field { | ||
$config.bouncer_config.block_max_capacity.$field = *value; | ||
} | ||
}; | ||
} | ||
|
||
/// Part of the Chain Config that we can override. | ||
// We need this proxy structure to implement Serialize - | ||
// which is not possible on the original ChainConfig because the bouncer config and | ||
// the versioned constants don't implement it. | ||
// Since we don't want to override those values anyway, we can create this wrapper. | ||
#[derive(Debug, Serialize, Deserialize)] | ||
pub struct OverridableChainConfig { | ||
pub chain_name: String, | ||
pub chain_id: ChainId, | ||
pub native_fee_token_address: ContractAddress, | ||
pub parent_fee_token_address: ContractAddress, | ||
pub latest_protocol_version: StarknetVersion, | ||
pub block_time: Duration, | ||
pub pending_block_update_time: Duration, | ||
pub execution_batch_size: usize, | ||
pub sequencer_address: ContractAddress, | ||
pub max_nonce_for_validation_skip: u64, | ||
pub eth_core_contract_address: H160, | ||
apply_bouncer!(chain_config, gas, overrides); | ||
apply_bouncer!(chain_config, message_segment_length, overrides); | ||
apply_bouncer!(chain_config, n_events, overrides); | ||
apply_bouncer!(chain_config, n_steps, overrides); | ||
apply_bouncer!(chain_config, state_diff_size, overrides); | ||
|
||
// Apply builtin configurations | ||
macro_rules! apply_builtin { | ||
($config:expr, $field:ident, $overrides:expr) => { | ||
if let Some(value) = &$overrides.$field { | ||
$config.bouncer_config.block_max_capacity.builtin_count.$field = *value; | ||
} | ||
}; | ||
} | ||
|
||
apply_builtin!(chain_config, add_mod, overrides); | ||
apply_builtin!(chain_config, bitwise, overrides); | ||
apply_builtin!(chain_config, ecdsa, overrides); | ||
apply_builtin!(chain_config, ec_op, overrides); | ||
apply_builtin!(chain_config, keccak, overrides); | ||
apply_builtin!(chain_config, mul_mod, overrides); | ||
apply_builtin!(chain_config, pedersen, overrides); | ||
apply_builtin!(chain_config, poseidon, overrides); | ||
apply_builtin!(chain_config, range_check, overrides); | ||
apply_builtin!(chain_config, range_check96, overrides); | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
impl From<&ChainConfig> for OverridableChainConfig { | ||
fn from(config: &ChainConfig) -> Self { | ||
OverridableChainConfig { | ||
chain_name: config.chain_name.clone(), | ||
chain_id: config.chain_id.clone(), | ||
native_fee_token_address: config.native_fee_token_address, | ||
parent_fee_token_address: config.parent_fee_token_address, | ||
latest_protocol_version: config.latest_protocol_version, | ||
block_time: config.block_time, | ||
pending_block_update_time: config.pending_block_update_time, | ||
execution_batch_size: config.execution_batch_size, | ||
sequencer_address: config.sequencer_address, | ||
max_nonce_for_validation_skip: config.max_nonce_for_validation_skip, | ||
eth_core_contract_address: config.eth_core_contract_address, | ||
pub fn deserialize_version<'de, D>(deserializer: D) -> Result<Option<StarknetVersion>, D::Error> | ||
where | ||
D: Deserializer<'de>, | ||
{ | ||
let value: Option<Value> = Option::deserialize(deserializer)?; | ||
match value { | ||
Some(v) => { | ||
let s = v.as_str().ok_or_else(|| serde::de::Error::custom("Expected a string"))?; | ||
StarknetVersion::from_str(s).map_err(serde::de::Error::custom).map(Some) | ||
} | ||
None => Ok(None), | ||
} | ||
} | ||
|
||
impl From<OverridableChainConfig> for ChainConfig { | ||
fn from(overridable: OverridableChainConfig) -> Self { | ||
ChainConfig { | ||
chain_name: overridable.chain_name, | ||
chain_id: overridable.chain_id, | ||
native_fee_token_address: overridable.native_fee_token_address, | ||
parent_fee_token_address: overridable.parent_fee_token_address, | ||
latest_protocol_version: overridable.latest_protocol_version, | ||
block_time: overridable.block_time, | ||
pending_block_update_time: overridable.pending_block_update_time, | ||
execution_batch_size: overridable.execution_batch_size, | ||
sequencer_address: overridable.sequencer_address, | ||
max_nonce_for_validation_skip: overridable.max_nonce_for_validation_skip, | ||
eth_core_contract_address: overridable.eth_core_contract_address, | ||
versioned_constants: Default::default(), | ||
bouncer_config: Default::default(), | ||
pub fn deserialize_duration<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error> | ||
where | ||
D: Deserializer<'de>, | ||
{ | ||
let value: Option<Value> = Option::deserialize(deserializer)?; | ||
|
||
match value { | ||
Some(v) => { | ||
let s = v.as_str().ok_or_else(|| serde::de::Error::custom("Expected a string"))?; | ||
parse_duration(s).map_err(serde::de::Error::custom).map(Some) | ||
} | ||
None => Ok(None), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters