fix: publish only subscribed columns from reconstruction#9464
Conversation
Mirror the getBlobsV2 path in getDataColumnSidecarsFromExecution and align with Lighthouse/Prysm by publishing only sampled (custody + sampling) columns after matrix recovery, instead of cross-seeding every recovered column to non-subscribed subnets. Per consensus-specs PR ChainSafe#4657, eager fanout for non-custody columns floods the network with duplicates because the sender lacks visibility into which peers already saw the message via the topic mesh. A node custodying 65 columns ends up publishing at least 64 (63 non-custody + 1 missing custody) columns every reconstruction, which is more outbound bandwidth than a supernode. Refs: ethereum/consensus-specs#4657 🤖 Generated with AI assistance
There was a problem hiding this comment.
Code Review
This pull request updates the recoverDataColumnSidecars function in dataColumns.ts to only publish reconstructed columns that the node is subscribed to (custody and sampling), aligning with consensus-specs PR #4657. It introduces tracking for both reconstructed and published sidecars separately, ensuring metrics are correctly incremented for all reconstructed columns while only publishing the missing sampled ones. There are no review comments, and I have no feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
nflaig
left a comment
There was a problem hiding this comment.
LGTM, seems like @matthewkeil is happy with it as well, merging
|
🎉 This PR is included in v1.44.0 🎉 |
Summary
Mirror the getBlobsV2 path in
getDataColumnSidecarsFromExecutionand align with Lighthouse/Prysm by publishing only the sampled (custody + sampling) columns after matrix recovery, instead of cross-seeding every recovered column to non-subscribed subnets.Per consensus-specs PR #4657 ("Only require nodes to publish custody columns from reconstruction"), eager fanout for non-custody columns floods the network with duplicates because the sender lacks visibility into which peers already saw the message via the topic mesh.
A node custodying 65 columns ends up publishing at least 64 (63 non-custody + 1 missing custody) columns every reconstruction, which is more outbound bandwidth than a supernode. This change brings Lodestar in line with the other clients.
Change
packages/beacon-node/src/util/dataColumns.ts—recoverDataColumnSidecars:input.getMissingSampledColumnMeta().missingbefore adding reconstructed columns (otherwise the indices are no longer "missing" afteraddColumn).sidecarsToPublishwhen the index is in the captured missing-sampled set.peerDas.reconstructedColumnsanddataColumns.bySource{source=recovery}now correctly count reconstructed columns (sidecarsReconstructed.length) instead of accidentally tracking only published ones — they happened to be equal under the old behavior, but diverge now.The existing getBlobsV2 path in
util/execution.ts:198-203already follows this "publish iff subscribed" pattern using the samegetMissingSampledColumnMeta()API; matrix recovery now matches.Spec note
Spec PR #4657 also tightens the reconstruction trigger ("custodies more than 50%") and softens the cross-seed clause (SHOULD → MAY). This PR only implements the publish-side change, which is what Lighthouse/Prysm already do in practice. The trigger-side wording change does not require a Lodestar code change (we already only attempt reconstruction when we have ≥50%, gated by sampling).
Test plan
recoverDataColumnSidecarsor the equivalent execution.ts publish path; covered by integration/sim. Happy to add a dedicated unit test if reviewers want it — it would need real KZG + a mockedBlockInputColumns.🤖 Generated with AI assistance