Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Greptile SummaryThis PR refactors Confidence Score: 5/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[EnsureBlinded] --> B{Already blinded?}
B -- yes --> C[Return as-is per fork]
B -- no --> D{Fork version}
D -- Capella --> E[computePayloadRoots\ntxs, withdrawals]
E --> F[Build capella.ExecutionPayloadHeader\ninline]
F --> G[Return CapellaBlinded]
D -- Deneb --> H[buildDenebPayloadHeader\npayload]
D -- Electra --> H
D -- Fulu --> H
H --> I[computePayloadRoots\ntxs, withdrawals]
I --> J[Build deneb.ExecutionPayloadHeader]
J --> K{Fork}
K -- Deneb --> L[Return DenebBlinded]
K -- Electra --> M[Return ElectraBlinded]
K -- Fulu --> N[Return FuluBlinded]
Reviews (1): Last reviewed commit: "Refactor: blind pkg" | Re-trigger Greptile |
| // buildDenebPayloadHeader converts a Deneb-shaped ExecutionPayload into its header form. | ||
| // Deneb, Electra, and Fulu all use deneb.ExecutionPayload / deneb.ExecutionPayloadHeader, | ||
| // so one builder serves all three forks. | ||
| func buildDenebPayloadHeader(payload *deneb.ExecutionPayload) (*deneb.ExecutionPayloadHeader, error) { |
There was a problem hiding this comment.
Might be worth adding a nil guard on payload here — all three callers already check before calling, so it's safe today, but a one-liner if payload == nil { return nil, fmt.Errorf("nil execution payload") } would be cheap insurance against future misuse.
Summary
Extract two small helpers from
EnsureBlinded(inprotocol/v2/blockchain/beacon/blind/blind.go) to reduce copy-paste duplication across the Capella/Deneb/Electra/Fulu branches.Motivation
EnsureBlindedconverts a full beacon block to its blinded form per fork. Each of the four fork branches was independently reimplementing:SSZ hash-tree-root computation for the transactions and withdrawals lists. The tx type (
[]bellatrix.Transaction) and withdrawal type ([]*capella.Withdrawal) are identical across all four forks, but each branch repeated the same(&utilbellatrix.ExecutionPayloadTransactions{...}).HashTreeRoot()/(&utilcapella.ExecutionPayloadWithdrawals{...}).HashTreeRoot()boilerplate with its own error-wrapping.Construction of a
deneb.ExecutionPayloadHeader. Deneb, Electra, and Fulu all use the exact samedeneb.ExecutionPayload→deneb.ExecutionPayloadHeaderconversion, with the exact same 16 field assignments. A field added todeneb.ExecutionPayloadHeaderpreviously required touching three call sites.Ticket CQ-5 originally recommended extracting "common blinding logic into a generic helper parameterized by fork version." I'm intentionally not going that far — the four blinded block types (
apiv1capella.BlindedBeaconBlock,apiv1deneb.BlindedBeaconBlock,apiv1electra.BlindedBeaconBlockused for both Electra and Fulu) have different body field sets and don't share a Go interface. A unified helper would require reflection or heavily-constrained generics for no readability win, and any future fork that changes the body layout would need to fork the abstraction anyway. The per-forkswitchbranches stay as-is; only the mechanically duplicated parts are factored out.Changes
protocol/v2/blockchain/beacon/blind/blind.go:computePayloadRoots(txs, withdrawals) (txRoot, wRoot, error)— used by all four fork branches.buildDenebPayloadHeader(*deneb.ExecutionPayload) (*deneb.ExecutionPayloadHeader, error)— used by Deneb, Electra, and Fulu.capella.ExecutionPayloadHeader(different type, no blob fields) but now usescomputePayloadRootsfor the roots.Net: 291 → 256 lines. Deneb/Electra/Fulu payload-header construction goes from ~20 lines of field copies each to a single helper call.
Closes https://github.com/ssvlabs/ssv-node-board/issues/560