Compare commits

...

6 Commits

Author SHA1 Message Date
Manu NALEPA
6a0db40e76 Add changelog. 2025-10-21 23:38:28 +02:00
Manu NALEPA
5fcf393f3a verifyByRPCDataColumnSidecars: Verify the proposer signature. 2025-10-21 23:35:47 +02:00
Manu NALEPA
6c7944cdfe Use mock verifier. 2025-10-21 23:35:27 +02:00
Manu NALEPA
6d3fd80035 Add context for future usage. 2025-10-21 18:11:57 +02:00
Manu NALEPA
96032555e7 Rename verifyByRootDataColumnSidecars to verifyByRPCDataColumnSidecars.
(Since the same function is used for both the by root and by range cases.)
2025-10-21 18:01:25 +02:00
Manu NALEPA
4de7a24077 Remove unused ByRangeRequestDataColumnSidecarRequirements.
Rename `ByRootRequestDataColumnSidecarRequirements` to `ByRPCRequestDataColumnSidecarRequirements`, since it is used to upgrade data column sidecars to verified data column sidecars when received by root RPC and by range RPC requests.
2025-10-21 17:59:58 +02:00
6 changed files with 58 additions and 64 deletions

View File

@@ -288,7 +288,7 @@ func requestDirectSidecarsFromPeers(
roDataColumnsByPeer := fetchDataColumnSidecarsFromPeers(params, slotByRoot, slotsWithCommitments, indicesByRootByPeerToQuery)
// Verify the received data column sidecars.
verifiedRoDataColumnSidecars, err := verifyDataColumnSidecarsByPeer(params.P2P, params.NewVerifier, roDataColumnsByPeer)
verifiedRoDataColumnSidecars, err := verifyDataColumnSidecarsByPeer(params.Ctx, params.P2P, params.NewVerifier, roDataColumnsByPeer)
if err != nil {
return nil, errors.Wrap(err, "verify data columns sidecars by peer")
}
@@ -398,7 +398,7 @@ func requestIndirectSidecarsFromPeers(
roDataColumnsByPeer := fetchDataColumnSidecarsFromPeers(p, slotByRoot, slotsWithCommitments, indicesByRootByPeerToQuery)
// Verify the received data column sidecars.
verifiedRoDataColumnSidecars, err := verifyDataColumnSidecarsByPeer(p.P2P, p.NewVerifier, roDataColumnsByPeer)
verifiedRoDataColumnSidecars, err := verifyDataColumnSidecarsByPeer(p.Ctx, p.P2P, p.NewVerifier, roDataColumnsByPeer)
if err != nil {
return nil, errors.Wrap(err, "verify data columns sidecars by peer")
}
@@ -942,6 +942,7 @@ func buildByRootRequest(indicesByRoot map[[fieldparams.RootLength]byte]map[uint6
// If at least one sidecar from a peer is invalid, the peer is downscored and
// all its sidecars are rejected. (Sidecars from other peers are still accepted.)
func verifyDataColumnSidecarsByPeer(
ctx context.Context,
p2p prysmP2P.P2P,
newVerifier verification.NewDataColumnsVerifier,
roDataColumnsByPeer map[goPeer.ID][]blocks.RODataColumn,
@@ -957,7 +958,7 @@ func verifyDataColumnSidecarsByPeer(
roDataColumnSidecars = append(roDataColumnSidecars, columns...)
}
verifiedRoDataColumnSidecars, err := verifyByRootDataColumnSidecars(newVerifier, roDataColumnSidecars)
verifiedRoDataColumnSidecars, err := verifyByRPCDataColumnSidecars(ctx, newVerifier, roDataColumnSidecars)
if err == nil {
// This is the happy path where all sidecars are verified.
return verifiedRoDataColumnSidecars, nil
@@ -967,7 +968,7 @@ func verifyDataColumnSidecarsByPeer(
// Reverify peer by peer to identify faulty peer(s), reject all its sidecars, and downscore it.
verifiedRoDataColumnSidecars = make([]blocks.VerifiedRODataColumn, 0, count)
for peer, columns := range roDataColumnsByPeer {
peerVerifiedRoDataColumnSidecars, err := verifyByRootDataColumnSidecars(newVerifier, columns)
peerVerifiedRoDataColumnSidecars, err := verifyByRPCDataColumnSidecars(ctx, newVerifier, columns)
if err != nil {
// This peer has invalid sidecars.
log := log.WithError(err).WithField("peerID", peer)
@@ -982,10 +983,14 @@ func verifyDataColumnSidecarsByPeer(
return verifiedRoDataColumnSidecars, nil
}
// verifyByRootDataColumnSidecars verifies the provided read-only data columns against the
// verifyByRPCDataColumnSidecars verifies the provided read-only data columns against the
// requirements for data column sidecars received via the by root request.
func verifyByRootDataColumnSidecars(newVerifier verification.NewDataColumnsVerifier, roDataColumns []blocks.RODataColumn) ([]blocks.VerifiedRODataColumn, error) {
verifier := newVerifier(roDataColumns, verification.ByRootRequestDataColumnSidecarRequirements)
func verifyByRPCDataColumnSidecars(ctx context.Context, newVerifier verification.NewDataColumnsVerifier, roDataColumns []blocks.RODataColumn) ([]blocks.VerifiedRODataColumn, error) {
verifier := newVerifier(roDataColumns, verification.ByRPCRequestDataColumnSidecarRequirements)
if err := verifier.ValidProposerSignature(ctx); err != nil {
return nil, errors.Wrap(err, "valid proposer signature")
}
if err := verifier.ValidFields(); err != nil {
return nil, errors.Wrap(err, "valid fields")

View File

@@ -2,6 +2,7 @@ package sync
import (
"context"
"errors"
"fmt"
"math/rand"
"testing"
@@ -154,12 +155,6 @@ func TestFetchDataColumnSidecars(t *testing.T) {
err = gs.SetClock(startup.NewClock(time.Unix(4113849600, 0), [fieldparams.RootLength]byte{}))
require.NoError(t, err)
waiter := verification.NewInitializerWaiter(gs, nil, nil)
initializer, err := waiter.WaitForInitializer(t.Context())
require.NoError(t, err)
newDataColumnsVerifier := newDataColumnsVerifierFromInitializer(initializer)
other.SetStreamHandler(byRangeProtocol, func(stream network.Stream) {
expectedRequest := &ethpb.DataColumnSidecarsByRangeRequest{
StartSlot: 3,
@@ -247,7 +242,7 @@ func TestFetchDataColumnSidecars(t *testing.T) {
RateLimiter: leakybucket.NewCollector(1., 10, time.Second, false /* deleteEmptyBuckets */),
CtxMap: ctxMap,
Storage: storage,
NewVerifier: newDataColumnsVerifier,
NewVerifier: testNewDataColumnSidecarsVerifier(verification.MockDataColumnsVerifier{}),
}
expectedResult := map[[fieldparams.RootLength]byte][]blocks.VerifiedRODataColumn{
@@ -761,6 +756,8 @@ func TestVerifyDataColumnSidecarsByPeer(t *testing.T) {
err := kzg.Start()
require.NoError(t, err)
ctx := t.Context()
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig()
cfg.FuluForkEpoch = 0
@@ -783,16 +780,9 @@ func TestVerifyDataColumnSidecarsByPeer(t *testing.T) {
"peer2": roDataColumnSidecars[5:9],
"peer3": roDataColumnSidecars[9:stop],
}
gs := startup.NewClockSynchronizer()
err := gs.SetClock(startup.NewClock(time.Unix(4113849600, 0), [fieldparams.RootLength]byte{}))
require.NoError(t, err)
waiter := verification.NewInitializerWaiter(gs, nil, nil)
initializer, err := waiter.WaitForInitializer(t.Context())
require.NoError(t, err)
newDataColumnsVerifier := newDataColumnsVerifierFromInitializer(initializer)
actual, err := verifyDataColumnSidecarsByPeer(p2p, newDataColumnsVerifier, roDataColumnsByPeer)
newDataColumnsVerifier := testNewDataColumnSidecarsVerifier(verification.MockDataColumnsVerifier{})
actual, err := verifyDataColumnSidecarsByPeer(ctx, p2p, newDataColumnsVerifier, roDataColumnsByPeer)
require.NoError(t, err)
require.Equal(t, stop-start, len(actual))
@@ -816,28 +806,14 @@ func TestVerifyDataColumnSidecarsByPeer(t *testing.T) {
// Setup test data and expectations
_, roDataColumnSidecars, expected := util.GenerateTestFuluBlockWithSidecars(t, blobCount)
// Modify one sidecar to ensure proof verification fails.
if roDataColumnSidecars[middle].KzgProofs[0][0] == 0 {
roDataColumnSidecars[middle].KzgProofs[0][0]++
} else {
roDataColumnSidecars[middle].KzgProofs[0][0]--
}
roDataColumnsByPeer := map[peer.ID][]blocks.RODataColumn{
"peer1": roDataColumnSidecars[start:middle],
"peer2": roDataColumnSidecars[5:middle],
"peer3": roDataColumnSidecars[middle:stop],
}
gs := startup.NewClockSynchronizer()
err := gs.SetClock(startup.NewClock(time.Unix(4113849600, 0), [fieldparams.RootLength]byte{}))
require.NoError(t, err)
waiter := verification.NewInitializerWaiter(gs, nil, nil)
initializer, err := waiter.WaitForInitializer(t.Context())
require.NoError(t, err)
newDataColumnsVerifier := newDataColumnsVerifierFromInitializer(initializer)
actual, err := verifyDataColumnSidecarsByPeer(p2p, newDataColumnsVerifier, roDataColumnsByPeer)
newDataColumnsVerifier := testNewDataColumnSidecarsVerifier(verification.MockDataColumnsVerifier{FailIndex: middle, ErrSidecarKzgProofVerifiedOnFailIndex: errors.New("an error")})
actual, err := verifyDataColumnSidecarsByPeer(ctx, p2p, newDataColumnsVerifier, roDataColumnsByPeer)
require.NoError(t, err)
require.Equal(t, middle-start, len(actual))

View File

@@ -218,7 +218,8 @@ func TestValidateDataColumn(t *testing.T) {
}
func testNewDataColumnSidecarsVerifier(verifier verification.MockDataColumnsVerifier) verification.NewDataColumnsVerifier {
return func([]blocks.RODataColumn, []verification.Requirement) verification.DataColumnsVerifier {
return func(sidecars []blocks.RODataColumn, _ []verification.Requirement) verification.DataColumnsVerifier {
verifier.Sidecars = sidecars
return &verifier
}
}

View File

@@ -39,19 +39,12 @@ var (
RequireSidecarProposerExpected,
}
// ByRangeRequestDataColumnSidecarRequirements defines the set of requirements that DataColumnSidecars received
// via the by range request must satisfy in order to upgrade an RODataColumn to a VerifiedRODataColumn.
// ByRPCRequestDataColumnSidecarRequirements defines the set of requirements that DataColumnSidecars received
// via the by RPC request must satisfy in order to upgrade an RODataColumn to a VerifiedRODataColumn.
// https://github.com/ethereum/consensus-specs/blob/master/specs/fulu/p2p-interface.md#datacolumnsidecarsbyrange-v1
ByRangeRequestDataColumnSidecarRequirements = []Requirement{
RequireValidFields,
RequireSidecarInclusionProven,
RequireSidecarKzgProofVerified,
}
// ByRootRequestDataColumnSidecarRequirements defines the set of requirements that DataColumnSidecars received
// via the by root request must satisfy in order to upgrade an RODataColumn to a VerifiedRODataColumn.
// https://github.com/ethereum/consensus-specs/blob/master/specs/fulu/p2p-interface.md#datacolumnsidecarsbyroot-v1
ByRootRequestDataColumnSidecarRequirements = []Requirement{
ByRPCRequestDataColumnSidecarRequirements = []Requirement{
RequireValidProposerSignature,
RequireValidFields,
RequireSidecarInclusionProven,
RequireSidecarKzgProofVerified,

View File

@@ -79,24 +79,34 @@ func (*MockBlobVerifier) SatisfyRequirement(_ Requirement) {}
// --------------------
type MockDataColumnsVerifier struct {
ErrValidFields error
ErrCorrectSubnet error
ErrNotFromFutureSlot error
ErrSlotAboveFinalized error
ErrSidecarParentSeen error
ErrSidecarParentValid error
ErrValidProposerSignature error
ErrSidecarParentSlotLower error
ErrSidecarDescendsFromFinalized error
ErrSidecarInclusionProven error
ErrSidecarKzgProofVerified error
ErrSidecarProposerExpected error
ErrValidFields error
ErrCorrectSubnet error
ErrNotFromFutureSlot error
ErrSlotAboveFinalized error
ErrSidecarParentSeen error
ErrSidecarParentValid error
ErrValidProposerSignature error
ErrSidecarParentSlotLower error
ErrSidecarDescendsFromFinalized error
ErrSidecarInclusionProven error
ErrSidecarKzgProofVerified error
ErrSidecarKzgProofVerifiedOnFailIndex error
ErrSidecarProposerExpected error
FailIndex uint64
Sidecars []blocks.RODataColumn
}
var _ DataColumnsVerifier = &MockDataColumnsVerifier{}
func (m *MockDataColumnsVerifier) VerifiedRODataColumns() ([]blocks.VerifiedRODataColumn, error) {
return []blocks.VerifiedRODataColumn{{}}, nil
verifiedSidecars := make([]blocks.VerifiedRODataColumn, 0, len(m.Sidecars))
for _, sidecar := range m.Sidecars {
verifiedSidecar := blocks.NewVerifiedRODataColumn(sidecar)
verifiedSidecars = append(verifiedSidecars, verifiedSidecar)
}
return verifiedSidecars, nil
}
func (m *MockDataColumnsVerifier) SatisfyRequirement(_ Requirement) {}
@@ -142,6 +152,13 @@ func (m *MockDataColumnsVerifier) SidecarInclusionProven() error {
}
func (m *MockDataColumnsVerifier) SidecarKzgProofVerified() error {
for _, sidecar := range m.Sidecars {
if m.ErrSidecarKzgProofVerifiedOnFailIndex != nil && sidecar.Index == m.FailIndex {
m.Sidecars = nil
return m.ErrSidecarKzgProofVerifiedOnFailIndex
}
}
return m.ErrSidecarKzgProofVerified
}

View File

@@ -0,0 +1,2 @@
### Fixed
- `verifyByRPCDataColumnSidecars`: Verify the proposer signature.