Skip to content

Conversation

@CertiK-Geth
Copy link

Issue Addressed

#8400

Proposed Changes

1. consensus/types/src/chain_spec.rs - BlobSchedule::new() Method

Change: Modified to return Result<Self, String> and validate epoch uniqueness.

Before:

pub fn new(mut vec: Vec<BlobParameters>) -> Self {
    // reverse sort by epoch
    vec.sort_by(|a, b| b.epoch.cmp(&a.epoch));
    Self {
        schedule: vec,
        skip_serializing: false,
    }
}

After:

pub fn new(mut vec: Vec<BlobParameters>) -> Result<Self, String> {
    // reverse sort by epoch
    vec.sort_by(|a, b| b.epoch.cmp(&a.epoch));
    
    // Validate that all epochs are unique
    for i in 0..vec.len() {
        for j in (i + 1)..vec.len() {
            if vec[i].epoch == vec[j].epoch {
                return Err(format!(
                    "Duplicate epoch in blob schedule: epoch {}",
                    vec[i].epoch
                ));
            }
        }
    }
    
    Ok(Self {
        schedule: vec,
        skip_serializing: false,
    })
}

2. consensus/types/src/chain_spec.rs - Deserialize Implementation

Change: Updated to properly handle and propagate validation errors from BlobSchedule::new().

Before:

impl<'de> Deserialize<'de> for BlobSchedule {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let vec = Vec::<BlobParameters>::deserialize(deserializer)?;
        Ok(BlobSchedule::new(vec))
    }
}

After:

impl<'de> Deserialize<'de> for BlobSchedule {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let vec = Vec::<BlobParameters>::deserialize(deserializer)?;
        BlobSchedule::new(vec).map_err(serde::de::Error::custom)
    }
}

3. consensus/types/src/chain_spec.rs - mainnet() Method

Change: Updated to handle the Result return type from BlobSchedule::new().

Before:

blob_schedule: BlobSchedule::new(vec![
    BlobParameters {
        epoch: Epoch::new(412672),
        max_blobs_per_block: 15,
    },
    BlobParameters {
        epoch: Epoch::new(419072),
        max_blobs_per_block: 21,
    },
]),

After:

blob_schedule: BlobSchedule::new(vec![
    BlobParameters {
        epoch: Epoch::new(412672),
        max_blobs_per_block: 15,
    },
    BlobParameters {
        epoch: Epoch::new(419072),
        max_blobs_per_block: 21,
    },
])
.expect("mainnet blob schedule has unique epochs"),

4. consensus/types/src/fork_context.rs - Test Helper

Change: Updated the test helper make_chain_spec() to handle the Result return type.

Before:

spec.blob_schedule = BlobSchedule::new(blob_parameters);

After:

spec.blob_schedule = BlobSchedule::new(blob_parameters)
    .expect("test blob schedule has unique epochs");

5. Added Comprehensive Test Suite

Added blob_schedule_tests module with 4 tests:

  • test_unique_epochs_accepted() - Verifies that valid schedules with unique epochs are accepted
  • test_duplicate_epochs_rejected() - Verifies that schedules with duplicate epochs are rejected with proper error message
  • test_empty_schedule() - Verifies that empty schedules are accepted
  • test_single_entry() - Verifies that single-entry schedules are accepted

Additional Info

  1. ✅ Config deserialization properly validates blob schedule uniqueness
  2. ✅ Duplicate epochs are detected and rejected with clear error messages
  3. ✅ Valid configurations pass without issue
  4. ✅ Edge cases (empty, single entry) are handled correctly
  5. ✅ Existing code paths that hardcode valid blob schedules continue to work

@cla-assistant
Copy link

cla-assistant bot commented Nov 12, 2025

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants