-
Notifications
You must be signed in to change notification settings - Fork 1
feat: add morph receipt and consensus validation #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fba7179
535e1d5
9ccd1b6
96845c8
f30e31d
41fb4ac
41edb11
bb5ea8e
c08b2db
cc7ad29
90337ca
02c82d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| //! Morph chainspec constants. | ||
|
|
||
| /// The Morph Mainnet chain ID. | ||
| pub const MORPH_MAINNET_CHAIN_ID: u64 = 2818; | ||
|
|
||
| /// The Morph Hoodi (testnet) chain ID. | ||
| pub const MORPH_HOODI_CHAIN_ID: u64 = 2910; | ||
|
|
||
| /// The default L2 sequencer fee (0.001 Gwei = 1_000_000 wei). | ||
| /// The sequencer has the right to set any base fee below `MORPH_MAX_BASE_FEE`. | ||
| pub const MORPH_BASE_FEE: u64 = 1_000_000; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,187 @@ | ||||||||||||||||||||||||||||
| //! Morph types for genesis data. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| use alloy_primitives::Address; | ||||||||||||||||||||||||||||
| use alloy_serde::OtherFields; | ||||||||||||||||||||||||||||
| use serde::{Deserialize, Serialize, de::Error as _}; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| /// Container type for all Morph-specific fields in a genesis file. | ||||||||||||||||||||||||||||
| #[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] | ||||||||||||||||||||||||||||
| #[serde(rename_all = "camelCase")] | ||||||||||||||||||||||||||||
| pub struct MorphGenesisInfo { | ||||||||||||||||||||||||||||
| /// Information about hard forks specific to the Morph chain. | ||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||
| pub hard_fork_info: Option<MorphHardforkInfo>, | ||||||||||||||||||||||||||||
| /// Morph chain-specific configuration details. | ||||||||||||||||||||||||||||
| pub morph_chain_info: MorphChainConfig, | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| impl MorphGenesisInfo { | ||||||||||||||||||||||||||||
| /// Extracts the Morph specific fields from a genesis file. | ||||||||||||||||||||||||||||
| pub fn extract_from(others: &OtherFields) -> Option<Self> { | ||||||||||||||||||||||||||||
| Self::try_from(others).ok() | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| impl TryFrom<&OtherFields> for MorphGenesisInfo { | ||||||||||||||||||||||||||||
| type Error = serde_json::Error; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| fn try_from(others: &OtherFields) -> Result<Self, Self::Error> { | ||||||||||||||||||||||||||||
| let hard_fork_info = MorphHardforkInfo::try_from(others).ok(); | ||||||||||||||||||||||||||||
| let morph_chain_info = MorphChainConfig::try_from(others)?; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Ok(Self { | ||||||||||||||||||||||||||||
| hard_fork_info, | ||||||||||||||||||||||||||||
| morph_chain_info, | ||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| /// Morph hardfork info specifies the block numbers and timestamps at which | ||||||||||||||||||||||||||||
| /// the Morph hardforks were activated. | ||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||
| /// Note: Bernoulli and Curie use block-based activation, while Morph203, Viridian, | ||||||||||||||||||||||||||||
| /// and Emerald use timestamp-based activation (matching go-ethereum behavior). | ||||||||||||||||||||||||||||
| #[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] | ||||||||||||||||||||||||||||
| #[serde(rename_all = "camelCase")] | ||||||||||||||||||||||||||||
| pub struct MorphHardforkInfo { | ||||||||||||||||||||||||||||
| /// Bernoulli hardfork block number. | ||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||
| pub bernoulli_block: Option<u64>, | ||||||||||||||||||||||||||||
| /// Curie hardfork block number. | ||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||
| pub curie_block: Option<u64>, | ||||||||||||||||||||||||||||
| /// Morph203 hardfork timestamp. | ||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||
| pub morph203_time: Option<u64>, | ||||||||||||||||||||||||||||
| /// Viridian hardfork timestamp. | ||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||
| pub viridian_time: Option<u64>, | ||||||||||||||||||||||||||||
| /// Emerald hardfork timestamp. | ||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||
| pub emerald_time: Option<u64>, | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| impl MorphHardforkInfo { | ||||||||||||||||||||||||||||
| /// Extract the Morph-specific genesis info from a genesis file. | ||||||||||||||||||||||||||||
| pub fn extract_from(others: &OtherFields) -> Option<Self> { | ||||||||||||||||||||||||||||
| Self::try_from(others).ok() | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| impl TryFrom<&OtherFields> for MorphHardforkInfo { | ||||||||||||||||||||||||||||
| type Error = serde_json::Error; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| fn try_from(others: &OtherFields) -> Result<Self, Self::Error> { | ||||||||||||||||||||||||||||
| others.deserialize_as() | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| /// The configuration for the Morph chain. | ||||||||||||||||||||||||||||
| #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] | ||||||||||||||||||||||||||||
| #[serde(rename_all = "camelCase")] | ||||||||||||||||||||||||||||
| pub struct MorphChainConfig { | ||||||||||||||||||||||||||||
| /// The address of the L2 transaction fee vault. | ||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||
| pub fee_vault_address: Option<Address>, | ||||||||||||||||||||||||||||
| /// The maximum tx payload size per block in bytes. | ||||||||||||||||||||||||||||
| #[serde(skip_serializing_if = "Option::is_none")] | ||||||||||||||||||||||||||||
| pub max_tx_payload_bytes_per_block: Option<usize>, | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| impl MorphChainConfig { | ||||||||||||||||||||||||||||
| /// Extracts the morph config by looking for the `morph` key in genesis. | ||||||||||||||||||||||||||||
| pub fn extract_from(others: &OtherFields) -> Option<Self> { | ||||||||||||||||||||||||||||
| Self::try_from(others).ok() | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| /// Returns whether the fee vault is enabled. | ||||||||||||||||||||||||||||
| pub const fn is_fee_vault_enabled(&self) -> bool { | ||||||||||||||||||||||||||||
| self.fee_vault_address.is_some() | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| /// Checks if the given block size (in bytes) is valid for this chain. | ||||||||||||||||||||||||||||
| pub fn is_valid_block_size(&self, size: usize) -> bool { | ||||||||||||||||||||||||||||
| self.max_tx_payload_bytes_per_block | ||||||||||||||||||||||||||||
| .map(|max| size <= max) | ||||||||||||||||||||||||||||
| .unwrap_or(true) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| impl TryFrom<&OtherFields> for MorphChainConfig { | ||||||||||||||||||||||||||||
| type Error = serde_json::Error; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| fn try_from(others: &OtherFields) -> Result<Self, Self::Error> { | ||||||||||||||||||||||||||||
| if let Some(Ok(morph_config)) = others.get_deserialized::<Self>("morph") { | ||||||||||||||||||||||||||||
| Ok(morph_config) | ||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||
| Err(serde_json::Error::missing_field("morph")) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
Comment on lines
+113
to
+118
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, locate and examine the file
find . -name "genesis.rs" -path "*/chainspec/*" | head -5Repository: morph-l2/morph-reth Length of output: 96 🏁 Script executed: # Read the specific lines mentioned in the review
sed -n '105,125p' crates/chainspec/src/genesis.rsRepository: morph-l2/morph-reth Length of output: 577 🏁 Script executed: # Get more context around the try_from implementation
sed -n '100,150p' crates/chainspec/src/genesis.rsRepository: morph-l2/morph-reth Length of output: 1501 🏁 Script executed: # Search for get_deserialized to understand its return type
rg "get_deserialized" --type rust -B 2 -A 2Repository: morph-l2/morph-reth Length of output: 421 🏁 Script executed: # Find the OtherFields type and get_deserialized method definition
rg "struct OtherFields" --type rust -A 5Repository: morph-l2/morph-reth Length of output: 45 🏁 Script executed: # Search for the get_deserialized method implementation
rg "fn get_deserialized" --type rust -B 2 -A 10Repository: morph-l2/morph-reth Length of output: 45 🏁 Script executed: # Also check the import statements to understand the types
head -30 crates/chainspec/src/genesis.rsRepository: morph-l2/morph-reth Length of output: 1179 🏁 Script executed: # OtherFields is from alloy_serde, let's check if it's in the repo
find . -name "*.rs" | xargs grep -l "impl.*OtherFields" | head -5Repository: morph-l2/morph-reth Length of output: 96 🏁 Script executed: # Let's search for documentation or usage patterns of get_deserialized
rg "get_deserialized" --type rust -B 5 -A 5 | head -100Repository: morph-l2/morph-reth Length of output: 775 🏁 Script executed: # Check if there are tests for the MorphChainConfig::try_from
sed -n '120,200p' crates/chainspec/src/genesis.rsRepository: morph-l2/morph-reth Length of output: 2074 🏁 Script executed: # Search for alloy_serde crate definition or get_deserialized method
rg "alloy_serde" --type rust | head -20Repository: morph-l2/morph-reth Length of output: 2128 🏁 Script executed: # Let's check the Cargo.toml to see alloy_serde version
grep -A 5 "alloy-serde\|alloy_serde" Cargo.tomlRepository: morph-l2/morph-reth Length of output: 251 🏁 Script executed: # Search for usage of get_deserialized in other files to understand the pattern
find . -name "*.rs" -exec grep -l "get_deserialized" {} \;Repository: morph-l2/morph-reth Length of output: 96 🌐 Web query:
💡 Result: I couldn’t find any get_deserialized method in the alloy-serde 1.1.3 API. The alloy-serde crate docs (crate page and module index) do not list a get_deserialized item. See the crate docs: [1], [2]. If you meant a different crate (or a different version) please tell me which one and I’ll look it up. Sources:
🏁 Script executed: # Let's also check if there's error handling testing for malformed morph config
sed -n '150,300p' crates/chainspec/src/genesis.rsRepository: morph-l2/morph-reth Length of output: 1270 🏁 Script executed: # Search for the definition of get_deserialized in the codebase
rg "fn get_deserialized\|get_deserialized.*=" --type rust -B 3 -A 10Repository: morph-l2/morph-reth Length of output: 45 🏁 Script executed: # Check if OtherFields is extended with get_deserialized somewhere
rg "impl.*OtherFields\|trait.*Ext" --type rust -B 2 -A 15Repository: morph-l2/morph-reth Length of output: 45 🏁 Script executed: # Let's check the alloy dependencies more carefully
grep -B 5 -A 10 "alloy-serde" Cargo.toml | head -20Repository: morph-l2/morph-reth Length of output: 608 🏁 Script executed: # Search for where get_deserialized might be defined as an extension
rg "get_deserialized" --type rust -B 10 | head -80Repository: morph-l2/morph-reth Length of output: 771 🏁 Script executed: # Let's check what OtherFields is from alloy_serde - maybe it has get_deserialized
rg "OtherFields" --type rust -B 5 -A 10 | head -150Repository: morph-l2/morph-reth Length of output: 8301 🏁 Script executed: # Check if get_deserialized might be defined as a trait method somewhere
rg "trait\|impl" --type rust crates/chainspec/src/genesis.rs | head -20Repository: morph-l2/morph-reth Length of output: 45 🏁 Script executed: # Let's look at the entire genesis.rs file to understand imports and context
wc -l crates/chainspec/src/genesis.rsRepository: morph-l2/morph-reth Length of output: 98 🏁 Script executed: # Read the entire file to understand structure
cat crates/chainspec/src/genesis.rsRepository: morph-l2/morph-reth Length of output: 6231 🏁 Script executed: # Let's check if there are any tests that verify error handling for malformed morph config
rg "test.*morph\|#\[test\]" crates/chainspec/src/genesis.rs -A 30 | grep -A 30 "malformed\|invalid\|error"Repository: morph-l2/morph-reth Length of output: 45 🏁 Script executed: # Also check if get_deserialized behavior is tested elsewhere
find . -name "*.rs" -exec grep -l "get_deserialized" {} \; | xargs grep -A 10 "get_deserialized" 2>/dev/null | head -100Repository: morph-l2/morph-reth Length of output: 312 🏁 Script executed: # Search for trait extensions or methods on OtherFields
rg "OtherFields\|get_deserialized" --type rust | grep -i "trait\|extend\|impl" | head -20Repository: morph-l2/morph-reth Length of output: 45 🏁 Script executed: # Check if there's an extension trait defined elsewhere in the codebase
find . -name "*.rs" -exec grep -l "trait.*Ext\|fn get_deserialized" {} \; 2>/dev/nullRepository: morph-l2/morph-reth Length of output: 133 🏁 Script executed: # Let's look at the alloy-serde source to understand OtherFields
python3 << 'PYTHON_EOF'
import json
import subprocess
# Try to find what the get_deserialized method actually returns
result = subprocess.run(
['rg', 'get_deserialized', '--type', 'rust', '-B', '5', '-A', '15'],
capture_output=True,
text=True
)
# Print just the method signature and usage
lines = result.stdout.split('\n')
for i, line in enumerate(lines):
if 'get_deserialized' in line:
# Print context around it
start = max(0, i - 3)
end = min(len(lines), i + 10)
for j in range(start, end):
print(lines[j])
print("---")
PYTHON_EOFRepository: morph-l2/morph-reth Length of output: 149 🏁 Script executed: # Let's check the usage in alt_fee.rs
grep -B 5 -A 10 "get_deserialized" crates/primitives/src/transaction/alt_fee.rsRepository: morph-l2/morph-reth Length of output: 45 🏁 Script executed: # And check the usage in tx.rs
grep -B 5 -A 10 "get_deserialized" crates/revm/src/tx.rsRepository: morph-l2/morph-reth Length of output: 45 🏁 Script executed: # Let's search for any trait definition that might provide get_deserialized
rg "trait\|impl.*OtherFields" --type rust -A 10 | head -100Repository: morph-l2/morph-reth Length of output: 45 🏁 Script executed: # Check if it's imported from elsewhere or if there's a custom implementation
rg "get_deserialized|OtherFieldsExt" --type rust -B 10 -A 5Repository: morph-l2/morph-reth Length of output: 1052 🏁 Script executed: # Let's examine the Cargo.lock or check what version of alloy-serde is actually used
find . -name "Cargo.lock" -exec head -200 {} \; | grep -A 5 "alloy-serde"Repository: morph-l2/morph-reth Length of output: 294 🏁 Script executed: # Let's verify those files actually exist and contain get_deserialized
ls -la crates/primitives/src/transaction/alt_fee.rs crates/revm/src/tx.rs 2>&1 | head -10Repository: morph-l2/morph-reth Length of output: 229 🏁 Script executed: # Search the entire repository for "get_deserialized" definition
rg "fn get_deserialized|get_deserialized\s*(" --type rust -B 2 -A 8 crates/Repository: morph-l2/morph-reth Length of output: 193 🏁 Script executed: # Let's check if this is a method provided by OtherFields from alloy-serde
# by looking at how OtherFields is used in the test
grep -B 20 "OtherFields.*from_str\|serde_json::from_str.*OtherFields" crates/chainspec/src/genesis.rs | head -30Repository: morph-l2/morph-reth Length of output: 747 🏁 Script executed: # Let's fix the regex and search properly
rg "fn get_deserialized" --type rust -B 2 -A 8Repository: morph-l2/morph-reth Length of output: 45 🏁 Script executed: # Check if get_deserialized is defined in this repo or if it's external
rg "get_deserialized" --type rust | wc -lRepository: morph-l2/morph-reth Length of output: 64 🏁 Script executed: # Let's look at what methods OtherFields provides - check if there's a trait
rg "deserialize_as|OtherFields" crates/chainspec/src/genesis.rs | head -20Repository: morph-l2/morph-reth Length of output: 830 🏁 Script executed: # Let's look at what deserialize_as does in OtherFields
rg "deserialize_as" --type rust -B 5 -A 10 | head -100Repository: morph-l2/morph-reth Length of output: 1110 🏁 Script executed: # Check if get_deserialized is perhaps a method that returns Option<Result>
# Let's look at actual trait implementations or check if this code even compiles
# by examining if there are any CI configs or test results
find . -name "*.toml" -path "*/chainspec*" | head -5Repository: morph-l2/morph-reth Length of output: 92 🏁 Script executed: # Let's check if get_deserialized might be a custom method added to OtherFields somewhere in the codebase
rg "impl.*OtherFields\|trait.*OtherFields" --type rust -B 3 -A 20Repository: morph-l2/morph-reth Length of output: 45 🏁 Script executed: # Let's check the Cargo.toml to see what alloy-serde provides
cat crates/chainspec/Cargo.tomlRepository: morph-l2/morph-reth Length of output: 970 🏁 Script executed: # Let's see if there's a way to test the malformed config scenario
grep -A 50 "test_extract_morph_chain_config" crates/chainspec/src/genesis.rsRepository: morph-l2/morph-reth Length of output: 1226 🏁 Script executed: # Let's look for any error case tests for MorphChainConfig
grep -n "Err\|error\|malformed\|invalid" crates/chainspec/src/genesis.rsRepository: morph-l2/morph-reth Length of output: 515 Preserve deserialization errors for When 🛠️ Suggested fix- if let Some(Ok(morph_config)) = others.get_deserialized::<Self>("morph") {
- Ok(morph_config)
- } else {
- Err(serde_json::Error::missing_field("morph"))
- }
+ match others.get_deserialized::<Self>("morph") {
+ Some(Ok(morph_config)) => Ok(morph_config),
+ Some(Err(err)) => Err(err),
+ None => Err(serde_json::Error::missing_field("morph")),
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| #[cfg(test)] | ||||||||||||||||||||||||||||
| mod tests { | ||||||||||||||||||||||||||||
| use super::*; | ||||||||||||||||||||||||||||
| use alloy_primitives::address; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||||
| fn test_extract_morph_hardfork_info() { | ||||||||||||||||||||||||||||
| let genesis_info = r#" | ||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||
| "bernoulliBlock": 0, | ||||||||||||||||||||||||||||
| "curieBlock": 100, | ||||||||||||||||||||||||||||
| "morph203Time": 3000, | ||||||||||||||||||||||||||||
| "viridianTime": 4000, | ||||||||||||||||||||||||||||
| "emeraldTime": 5000 | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| "#; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| let others: OtherFields = serde_json::from_str(genesis_info).unwrap(); | ||||||||||||||||||||||||||||
| let hardfork_info = MorphHardforkInfo::extract_from(&others).unwrap(); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| assert_eq!( | ||||||||||||||||||||||||||||
| hardfork_info, | ||||||||||||||||||||||||||||
| MorphHardforkInfo { | ||||||||||||||||||||||||||||
| bernoulli_block: Some(0), | ||||||||||||||||||||||||||||
| curie_block: Some(100), | ||||||||||||||||||||||||||||
| morph203_time: Some(3000), | ||||||||||||||||||||||||||||
| viridian_time: Some(4000), | ||||||||||||||||||||||||||||
| emerald_time: Some(5000), | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||||
| fn test_extract_morph_chain_config() { | ||||||||||||||||||||||||||||
| let config_str = r#" | ||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||
| "morph": { | ||||||||||||||||||||||||||||
| "feeVaultAddress": "0x530000000000000000000000000000000000000a", | ||||||||||||||||||||||||||||
| "maxTxPayloadBytesPerBlock": 122880 | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| "#; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| let others: OtherFields = serde_json::from_str(config_str).unwrap(); | ||||||||||||||||||||||||||||
| let config = MorphChainConfig::extract_from(&others).unwrap(); | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| assert_eq!( | ||||||||||||||||||||||||||||
| config.fee_vault_address, | ||||||||||||||||||||||||||||
| Some(address!("530000000000000000000000000000000000000a")) | ||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||
| assert_eq!(config.max_tx_payload_bytes_per_block, Some(122880)); | ||||||||||||||||||||||||||||
| assert!(config.is_fee_vault_enabled()); | ||||||||||||||||||||||||||||
| assert!(config.is_valid_block_size(100000)); | ||||||||||||||||||||||||||||
| assert!(!config.is_valid_block_size(200000)); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| #[test] | ||||||||||||||||||||||||||||
| fn test_default_config() { | ||||||||||||||||||||||||||||
| let config = MorphChainConfig::default(); | ||||||||||||||||||||||||||||
| assert!(!config.is_fee_vault_enabled()); | ||||||||||||||||||||||||||||
| assert_eq!(config.fee_vault_address, None); | ||||||||||||||||||||||||||||
| assert_eq!(config.max_tx_payload_bytes_per_block, None); | ||||||||||||||||||||||||||||
| // Without max size limit, any size is valid | ||||||||||||||||||||||||||||
| assert!(config.is_valid_block_size(usize::MAX)); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: morph-l2/morph-reth
Length of output: 81
🏁 Script executed:
Repository: morph-l2/morph-reth
Length of output: 679
🏁 Script executed:
Repository: morph-l2/morph-reth
Length of output: 425
🏁 Script executed:
Repository: morph-l2/morph-reth
Length of output: 45
🏁 Script executed:
Repository: morph-l2/morph-reth
Length of output: 2860
🏁 Script executed:
Repository: morph-l2/morph-reth
Length of output: 1945
🏁 Script executed:
Repository: morph-l2/morph-reth
Length of output: 1135
Propagate deserialization errors for hardfork configuration.
When hardfork data is provided in the genesis file but malformed,
.ok()silently converts the error toNone, making it indistinguishable from an omitted field. This can cause data loss and incorrect fork schedules without alerting the user. Propagate errors instead so invalid hardfork config is caught during genesis parsing.🛠️ Suggested fix
📝 Committable suggestion
🤖 Prompt for AI Agents