fix: gocognit on publish block and fixing publish blinded block header check (#14913)

* refactored code and added in checks for blinded endpoints

* changelog

* cleaning up some comments and error messages

* fixing linting

* adding clarifying comment
This commit is contained in:
james-prysm
2025-02-11 15:34:37 -06:00
committed by GitHub
parent 0229a2055e
commit 15025837bb
3 changed files with 630 additions and 761 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1528,7 +1528,7 @@ func TestPublishBlock(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlock(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Phase0)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Phase0)), writer.Body.String())
})
t.Run("Fulu", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
@@ -1564,7 +1564,7 @@ func TestPublishBlock(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlock(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String())
})
t.Run("wrong version header", func(t *testing.T) {
server := &Server{
@@ -1577,7 +1577,7 @@ func TestPublishBlock(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlock(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
})
t.Run("syncing", func(t *testing.T) {
chainService := &chainMock.ChainService{}
@@ -1612,6 +1612,20 @@ func TestVersionHeaderFromRequest(t *testing.T) {
require.NoError(t, err)
require.Equal(t, version.String(version.Fulu), versionHead)
})
t.Run("Blinded Fulu block returns fulu header", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
cfg.FuluForkEpoch = 7
params.OverrideBeaconConfig(cfg)
params.SetupTestConfigCleanup(t)
var signedblock *structs.SignedBlindedBeaconBlockFulu
require.NoError(t, json.Unmarshal([]byte(rpctesting.BlindedFuluBlock), &signedblock))
signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().FuluForkEpoch))
newBlock, err := json.Marshal(signedblock)
require.NoError(t, err)
versionHead, err := versionHeaderFromRequest(newBlock)
require.NoError(t, err)
require.Equal(t, version.String(version.Fulu), versionHead)
})
t.Run("Electra block contents returns electra header", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
cfg.ElectraForkEpoch = 6
@@ -1626,6 +1640,20 @@ func TestVersionHeaderFromRequest(t *testing.T) {
require.NoError(t, err)
require.Equal(t, version.String(version.Electra), versionHead)
})
t.Run("Blinded Electra block returns electra header", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
cfg.ElectraForkEpoch = 6
params.OverrideBeaconConfig(cfg)
params.SetupTestConfigCleanup(t)
var signedblock *structs.SignedBlindedBeaconBlockElectra
require.NoError(t, json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &signedblock))
signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().ElectraForkEpoch))
newBlock, err := json.Marshal(signedblock)
require.NoError(t, err)
versionHead, err := versionHeaderFromRequest(newBlock)
require.NoError(t, err)
require.Equal(t, version.String(version.Electra), versionHead)
})
t.Run("Deneb block contents returns deneb header", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
cfg.DenebForkEpoch = 5
@@ -1640,7 +1668,21 @@ func TestVersionHeaderFromRequest(t *testing.T) {
require.NoError(t, err)
require.Equal(t, version.String(version.Deneb), versionHead)
})
t.Run("Capella block returns capella header", func(t *testing.T) {
t.Run("Blinded Deneb block returns Deneb header", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
cfg.DenebForkEpoch = 5
params.OverrideBeaconConfig(cfg)
params.SetupTestConfigCleanup(t)
var signedblock *structs.SignedBlindedBeaconBlockDeneb
require.NoError(t, json.Unmarshal([]byte(rpctesting.BlindedDenebBlock), &signedblock))
signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().DenebForkEpoch))
newBlock, err := json.Marshal(signedblock)
require.NoError(t, err)
versionHead, err := versionHeaderFromRequest(newBlock)
require.NoError(t, err)
require.Equal(t, version.String(version.Deneb), versionHead)
})
t.Run("Capella block returns Capella header", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
cfg.CapellaForkEpoch = 4
params.OverrideBeaconConfig(cfg)
@@ -1654,6 +1696,20 @@ func TestVersionHeaderFromRequest(t *testing.T) {
require.NoError(t, err)
require.Equal(t, version.String(version.Capella), versionHead)
})
t.Run("Blinded Capella block returns Capella header", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
cfg.CapellaForkEpoch = 4
params.OverrideBeaconConfig(cfg)
params.SetupTestConfigCleanup(t)
var signedblock *structs.SignedBlindedBeaconBlockCapella
require.NoError(t, json.Unmarshal([]byte(rpctesting.BlindedCapellaBlock), &signedblock))
signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().CapellaForkEpoch))
newBlock, err := json.Marshal(signedblock)
require.NoError(t, err)
versionHead, err := versionHeaderFromRequest(newBlock)
require.NoError(t, err)
require.Equal(t, version.String(version.Capella), versionHead)
})
t.Run("Bellatrix block returns capella header", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
cfg.BellatrixForkEpoch = 3
@@ -1668,6 +1724,20 @@ func TestVersionHeaderFromRequest(t *testing.T) {
require.NoError(t, err)
require.Equal(t, version.String(version.Bellatrix), versionHead)
})
t.Run("Blinded Capella block returns Capella header", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
cfg.BellatrixForkEpoch = 3
params.OverrideBeaconConfig(cfg)
params.SetupTestConfigCleanup(t)
var signedblock *structs.SignedBlindedBeaconBlockBellatrix
require.NoError(t, json.Unmarshal([]byte(rpctesting.BlindedBellatrixBlock), &signedblock))
signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().BellatrixForkEpoch))
newBlock, err := json.Marshal(signedblock)
require.NoError(t, err)
versionHead, err := versionHeaderFromRequest(newBlock)
require.NoError(t, err)
require.Equal(t, version.String(version.Bellatrix), versionHead)
})
t.Run("Altair block returns capella header", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
cfg.AltairForkEpoch = 2
@@ -1909,7 +1979,7 @@ func TestPublishBlockSSZ(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlock(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String())
})
t.Run("wrong version header", func(t *testing.T) {
server := &Server{
@@ -1930,7 +2000,7 @@ func TestPublishBlockSSZ(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlock(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
})
t.Run("syncing", func(t *testing.T) {
chainService := &chainMock.ChainService{}
@@ -2072,12 +2142,11 @@ func TestPublishBlindedBlock(t *testing.T) {
t.Run("Blinded Electra", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
// Convert back Fulu to Electra when there is at least one difference between Electra and Fulu blocks.
block, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedFulu)
converted, err := structs.BlindedBeaconBlockFuluFromConsensus(block.BlindedFulu.Message)
block, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedElectra)
converted, err := structs.BlindedBeaconBlockElectraFromConsensus(block.BlindedElectra.Message)
require.NoError(t, err)
var signedblock *structs.SignedBlindedBeaconBlockFulu
err = json.Unmarshal([]byte(rpctesting.BlindedFuluBlock), &signedblock)
var signedblock *structs.SignedBlindedBeaconBlockElectra
err = json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &signedblock)
require.NoError(t, err)
require.DeepEqual(t, converted, signedblock.Message)
return ok
@@ -2094,6 +2163,52 @@ func TestPublishBlindedBlock(t *testing.T) {
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("Blinded Electra block without version header succeeds", func(t *testing.T) {
cfg := params.BeaconConfig().Copy()
cfg.ElectraForkEpoch = 6
params.OverrideBeaconConfig(cfg)
params.SetupTestConfigCleanup(t)
var signedblock *structs.SignedBlindedBeaconBlockElectra
require.NoError(t, json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &signedblock))
signedblock.Message.Slot = fmt.Sprintf("%d", uint64(params.BeaconConfig().SlotsPerEpoch)*uint64(params.BeaconConfig().ElectraForkEpoch))
newBlock, err := json.Marshal(signedblock)
require.NoError(t, err)
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
block, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedElectra)
converted, err := structs.BlindedBeaconBlockElectraFromConsensus(block.BlindedElectra.Message)
require.NoError(t, err)
var signedblock *structs.SignedBlindedBeaconBlockElectra
err = json.Unmarshal(newBlock, &signedblock)
require.NoError(t, err)
require.DeepEqual(t, converted, signedblock.Message)
return ok
}))
server := &Server{
V1Alpha1ValidatorServer: v1alpha1Server,
SyncChecker: &mockSync.Sync{IsSyncing: false},
}
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader(newBlock))
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusOK, writer.Code)
})
t.Run("Blinded Electra block without version header on wrong fork", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
server := &Server{
V1Alpha1ValidatorServer: v1alpha1Server,
SyncChecker: &mockSync.Sync{IsSyncing: false},
}
request := httptest.NewRequest(http.MethodPost, "http://foo.example", bytes.NewReader([]byte(rpctesting.BlindedElectraBlock)))
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
// block is sent with slot == 1 which means it's in the phase0 fork
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Phase0)), writer.Body.String())
})
t.Run("Blinded Fulu", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
@@ -2129,7 +2244,7 @@ func TestPublishBlindedBlock(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String())
})
t.Run("wrong version header", func(t *testing.T) {
server := &Server{
@@ -2142,7 +2257,7 @@ func TestPublishBlindedBlock(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
})
t.Run("syncing", func(t *testing.T) {
chainService := &chainMock.ChainService{}
@@ -2366,7 +2481,7 @@ func TestPublishBlindedBlockSSZ(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String())
})
t.Run("wrong version header", func(t *testing.T) {
server := &Server{
@@ -2387,7 +2502,7 @@ func TestPublishBlindedBlockSSZ(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlock(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
})
t.Run("syncing", func(t *testing.T) {
chainService := &chainMock.ChainService{}
@@ -2585,7 +2700,7 @@ func TestPublishBlockV2(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlockV2(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block:", version.String(version.Bellatrix)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block:", version.String(version.Bellatrix)), writer.Body.String())
})
t.Run("wrong version header", func(t *testing.T) {
server := &Server{
@@ -2598,7 +2713,7 @@ func TestPublishBlockV2(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlockV2(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block:", version.String(version.Capella)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block:", version.String(version.Capella)), writer.Body.String())
})
t.Run("missing version header", func(t *testing.T) {
server := &Server{
@@ -2842,7 +2957,7 @@ func TestPublishBlockV2SSZ(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlockV2(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String())
})
t.Run("wrong version header", func(t *testing.T) {
server := &Server{
@@ -2863,7 +2978,7 @@ func TestPublishBlockV2SSZ(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlockV2(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
})
t.Run("missing version header", func(t *testing.T) {
server := &Server{
@@ -3018,12 +3133,11 @@ func TestPublishBlindedBlockV2(t *testing.T) {
t.Run("Blinded Electra", func(t *testing.T) {
v1alpha1Server := mock2.NewMockBeaconNodeValidatorServer(ctrl)
v1alpha1Server.EXPECT().ProposeBeaconBlock(gomock.Any(), mock.MatchedBy(func(req *eth.GenericSignedBeaconBlock) bool {
// Convert back Fulu to Electra when there is at least one difference between Electra and Fulu blocks.
block, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedFulu)
converted, err := structs.BlindedBeaconBlockFuluFromConsensus(block.BlindedFulu.Message)
block, ok := req.Block.(*eth.GenericSignedBeaconBlock_BlindedElectra)
converted, err := structs.BlindedBeaconBlockElectraFromConsensus(block.BlindedElectra.Message)
require.NoError(t, err)
var signedblock *structs.SignedBlindedBeaconBlockFulu
err = json.Unmarshal([]byte(rpctesting.BlindedFuluBlock), &signedblock)
var signedblock *structs.SignedBlindedBeaconBlockElectra
err = json.Unmarshal([]byte(rpctesting.BlindedElectraBlock), &signedblock)
require.NoError(t, err)
require.DeepEqual(t, converted, signedblock.Message)
return ok
@@ -3075,7 +3189,7 @@ func TestPublishBlindedBlockV2(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlockV2(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block:", version.String(version.Bellatrix)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block:", version.String(version.Bellatrix)), writer.Body.String())
})
t.Run("wrong version header", func(t *testing.T) {
server := &Server{
@@ -3088,7 +3202,7 @@ func TestPublishBlindedBlockV2(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlockV2(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
})
t.Run("missing version header", func(t *testing.T) {
server := &Server{
@@ -3324,7 +3438,7 @@ func TestPublishBlindedBlockV2SSZ(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlockV2(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Bellatrix)), writer.Body.String())
})
t.Run("wrong version header", func(t *testing.T) {
server := &Server{
@@ -3345,7 +3459,7 @@ func TestPublishBlindedBlockV2SSZ(t *testing.T) {
writer.Body = &bytes.Buffer{}
server.PublishBlindedBlockV2(writer, request)
assert.Equal(t, http.StatusBadRequest, writer.Code)
assert.StringContains(t, fmt.Sprintf("Could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
assert.StringContains(t, fmt.Sprintf("could not decode request body into %s consensus block", version.String(version.Capella)), writer.Body.String())
})
t.Run("missing version header", func(t *testing.T) {
server := &Server{

View File

@@ -0,0 +1,4 @@
### Fixed
- refactored publish block and block ssz functions to fix gocognit
- refactored publish blinded block and blinded block ssz to correctly deal with version headers and sent blocks