Skip to content

feat(gossip): add partial messages extension for PeerDAS#8748

Draft
raulk wants to merge 2 commits intoChainSafe:unstablefrom
raulk:feat/partial-messages-extension
Draft

feat(gossip): add partial messages extension for PeerDAS#8748
raulk wants to merge 2 commits intoChainSafe:unstablefrom
raulk:feat/partial-messages-extension

Conversation

@raulk
Copy link

@raulk raulk commented Jan 15, 2026

Summary

  • Implement partial messages extension for efficient PeerDAS data column propagation
  • Enable nodes to exchange only missing data column cells, reducing bandwidth by ~500KiB per slot
  • Integrate with js-libp2p-gossipsub fork that implements the partial messages protocol

New files

Core implementation

  • columnAvailability.ts - Interface for tracking which columns are available per block
  • columnAvailabilityStore.ts - In-memory LRU implementation (64 blocks, ~2 epochs TTL)
  • reconstructionState.ts - Tracks peer column metadata and incoming partial messages
  • partialColumnNetwork.ts - Network layer integration with req/resp fallback
  • partialColumns.ts - AggregatedPartialDataColumn and PartialColumnBroadcaster classes

Validation

  • chain/validation/partialDataColumn.ts - KZG proof validation for incoming partial columns

Tests

  • columnAvailabilityStore.test.ts - 32 unit tests for column tracking
  • reconstructionState.test.ts - 47 unit tests for peer metadata and reconstruction
  • partialColumns.test.ts - Unit tests for bitmap utilities

Modified files

  • gossipsub.ts - Added enablePartialMessages and partialMessageExtension options
  • networkCore.ts - Wire up PartialColumnBroadcaster in network initialization
  • network/options.ts - Added enablePartialMessages config option
  • cli/options/beaconNodeOptions/network.ts - Added --network.partialMessages CLI flag
  • metrics/lodestar.ts - Added 5 Prometheus metrics for observability

Implementation details

Column availability tracking

  • 16-byte bitmap tracks 128 columns per block root
  • LRU eviction when capacity reached (default: 64 blocks)
  • TTL-based expiry (default: 384 seconds / 32 slots)

Aggregated HAVE set

  • Unlike single-column approach, tracks ALL columns for a block
  • partialMessageBytes() sends only columns the peer is missing
  • Efficient bitmap operations for metadata merging

Reconstruction state

  • Tracks peer-advertised column metadata
  • Detects duplicate vs new columns
  • Provides peer selection for fetching missing custody columns

Rebroadcast logic

  • When new columns received, advertise to mesh peers
  • Triggers req/resp fallback when custody columns missing

Metrics

  • lodestar_partial_columns_received_total - Received partials (new/duplicate/invalid)
  • lodestar_partial_columns_rebroadcast_total - Rebroadcasts sent
  • lodestar_partial_columns_fetched_total - Columns fetched via req/resp
  • lodestar_partial_groups_tracked - Block roots being tracked
  • lodestar_partial_column_availability_ratio - Column availability histogram

Test plan

  • Type checking passes (yarn check-types)
  • Unit tests pass (79 tests across 3 test files)
  • js-libp2p interop tests pass (covers the gossipsub protocol Lodestar uses)
  • Cross-implementation interop with Go works (js-and-go tests pass)

@raulk raulk requested a review from a team as a code owner January 15, 2026 16:30
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @raulk, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly upgrades the network's data propagation capabilities by introducing partial message support for PeerDAS data columns. This enhancement allows nodes to efficiently exchange only the missing parts of data columns, reducing network overhead and accelerating the assembly of complete messages. The core logic resides in new classes that manage partial message state and integrate seamlessly with a modified Gossipsub implementation.

Highlights

  • Partial Messages Extension: Implemented support for partial messages within the gossip protocol to enhance the efficiency of PeerDAS data column propagation.
  • Gossipsub Integration: Integrated a custom fork of js-libp2p-gossipsub that includes the necessary partial messages protocol, enabling nodes to exchange parts metadata and assemble complete messages.
  • New Core Components: Introduced PartialDataColumn and PartialColumnBroadcaster classes to manage the lifecycle of partial data columns, including bitmap-based metadata for tracking received parts.
  • Gossipsub Configuration: Updated the Eth2Gossipsub configuration to enable partial message handling and register the new PartialColumnBroadcaster.
  • Unit Testing: Added comprehensive unit tests for the new partial message utility functions, ensuring correctness of bitmap encoding, decoding, and validation.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for the partial messages extension for PeerDAS, which is a significant feature for efficient data column propagation. The changes are well-structured, with the core logic encapsulated in the new partialColumns.ts file and integrated into the existing network stack. The new functionality is also accompanied by a comprehensive set of unit tests.

My review focuses on improving code maintainability by reducing duplication in some of the new utility functions. Overall, this is a solid contribution.

Comment on lines +231 to +531
private countParts(metadata: Uint8Array): number {
let count = 0;
for (const byte of metadata) {
let b = byte;
while (b !== 0) {
count += b & 1;
b >>= 1;
}
}
return count;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This function has the same implementation as the exported function countColumnsInMetadata. To avoid code duplication, consider extracting this logic into a single, shared utility function that both can use.

Additionally, the current bit counting implementation can be optimized. Instead of iterating through each bit, you can use a technique that iterates only for each set bit, which is more efficient for sparse bitmaps.

Here's a suggested implementation using Brian Kernighan's algorithm:

function countSetBits(metadata: Uint8Array): number {
  let count = 0;
  for (const byte of metadata) {
    let b = byte;
    while (b > 0) {
      // This clears the least significant set bit
      b &= (b - 1);
      count++;
    }
  }
  return count;
}

Comment on lines +370 to +678
export function isCompleteMetadata(metadata: Uint8Array): boolean {
const fullBytes = Math.floor(NUMBER_OF_COLUMNS / 8);
const remainingBits = NUMBER_OF_COLUMNS % 8;

for (let i = 0; i < fullBytes; i++) {
if (metadata[i] !== 0xff) {
return false;
}
}

if (remainingBits > 0) {
const expectedMask = (1 << remainingBits) - 1;
if ((metadata[fullBytes] & expectedMask) !== expectedMask) {
return false;
}
}

return true;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This function is identical to the private method hasAllParts in the PartialDataColumn class. To improve maintainability and reduce code duplication, this logic should be consolidated into a single utility function that both can use.

For example, you can keep this exported isCompleteMetadata function and have PartialDataColumn.hasAllParts call it.

"@chainsafe/discv5": "^11.0.4",
"@chainsafe/enr": "^5.0.1",
"@chainsafe/libp2p-gossipsub": "^14.1.2",
"@chainsafe/libp2p-gossipsub": "file:../../../js-libp2p-gossipsub",
Copy link
Author

Choose a reason for hiding this comment

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

TBD, switch to an npm dep.

@raulk raulk marked this pull request as draft January 15, 2026 16:50
@raulk raulk force-pushed the feat/partial-messages-extension branch from ff13ccf to c6e771e Compare January 16, 2026 09:26
raulk added 2 commits January 16, 2026 09:30
Integrate js-libp2p-gossipsub partial messages extension to support
efficient propagation of data columns in PeerDAS. This enables nodes
to exchange parts metadata and assemble complete messages from
multiple partial transmissions.

Key changes:
- Add PartialDataColumn implementing PartialMessage interface
- Add PartialColumnBroadcaster implementing PartialMessageExtension
- Wire up partial message extension in Eth2Gossipsub via NetworkCore
- Add bitmap encoding/decoding utilities for parts metadata
- Add validation functions for partial message metadata
- Include unit tests for all utility functions

The extension uses a bitmap representation where each bit corresponds
to a data column index (0-127 for NUMBER_OF_COLUMNS=128).
Add comprwqehensive partial messages support for efficient data column
propagation. This enables nodes to exchange only the cells they're
missing rather than full columns, reducing bandwidth by ~500KiB/slot.

Key components:
- ColumnAvailabilityStore: Track available columns per block with LRU
- ReconstructionStateManager: Handle incoming partials and peer metadata
- PartialColumnBroadcaster: Rebroadcast new columns to mesh peers
- PartialColumnNetwork: Network layer integration with req/resp fallback
- Validation: KZG proof verification for incoming partial columns

Features:
- Aggregated HAVE set tracking (all columns, not single)
- Peer column metadata tracking for smart fetching
- Automatic rebroadcast when new columns received
- Req/resp fallback for missing custody columns
- CLI flag: --network.partialMessages
- Prometheus metrics for observability
- 79 unit tests for core components
@raulk raulk force-pushed the feat/partial-messages-extension branch from c6e771e to e9e7fd8 Compare January 16, 2026 09:30
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.

1 participant