From 271f473540b6ca5e739f2d02129f2255a31523c2 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 19 Feb 2025 07:53:23 -0600 Subject: [PATCH 01/12] Remove deprecated linters --- .golangci.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index c091d7a6..61bb16cf 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -11,7 +11,6 @@ linters: - gocritic - godot - godox - - gomnd - lll - musttag - mnd @@ -38,11 +37,6 @@ linters: - sqlclosecheck - wastedassign - # - # Disabled because deprecated: - # - - execinquery - linters-settings: # # The G108 rule throws a false positive. We're not actually vulnerable. If From 191a0a578e49c948c876fe394ce432410963a9fe Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 19 Feb 2025 07:53:54 -0600 Subject: [PATCH 02/12] Use new range in benchmark loops --- common/ssz_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/ssz_test.go b/common/ssz_test.go index f73e62e0..d2c77e02 100644 --- a/common/ssz_test.go +++ b/common/ssz_test.go @@ -160,14 +160,14 @@ func BenchmarkDecoding(b *testing.B) { payload := new(builderSpec.VersionedSignedBuilderBid) b.Run("capella json", func(b *testing.B) { - for i := 0; i < b.N; i++ { + for range b.N { err = json.Unmarshal(jsonBytes, &payload) require.NoError(b, err) } }) payload.Capella = new(builderApiCapella.SignedBuilderBid) b.Run("capella ssz", func(b *testing.B) { - for i := 0; i < b.N; i++ { + for range b.N { err = payload.Capella.UnmarshalSSZ(sszBytes) require.NoError(b, err) } @@ -180,14 +180,14 @@ func BenchmarkDecoding(b *testing.B) { require.NoError(b, err) payload = new(builderSpec.VersionedSignedBuilderBid) b.Run("deneb json", func(b *testing.B) { - for i := 0; i < b.N; i++ { + for range b.N { err = json.Unmarshal(jsonBytes, &payload) require.NoError(b, err) } }) payload.Deneb = new(builderApiDeneb.SignedBuilderBid) b.Run("deneb ssz", func(b *testing.B) { - for i := 0; i < b.N; i++ { + for range b.N { err = payload.Deneb.UnmarshalSSZ(sszBytes) require.NoError(b, err) } From ff88b7fa3b50bc938a6bfadfa1ef4e1ff069b537 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 19 Feb 2025 07:54:45 -0600 Subject: [PATCH 03/12] Add timestamp overflow check for validator registrations --- database/types.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/database/types.go b/database/types.go index 25470141..564e65dd 100644 --- a/database/types.go +++ b/database/types.go @@ -2,6 +2,8 @@ package database import ( "database/sql" + "errors" + "math" "strconv" "time" @@ -78,6 +80,10 @@ func (reg ValidatorRegistrationEntry) ToSignedValidatorRegistration() (*builderA return nil, err } + if reg.Timestamp > uint64(math.MaxInt64) { + return nil, errors.New("timestamp overflow") + } + return &builderApiV1.SignedValidatorRegistration{ Message: &builderApiV1.ValidatorRegistration{ Pubkey: pubkey, From 220df66b2338ad1ee39f93fca2f35f1251730813 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 19 Feb 2025 07:55:12 -0600 Subject: [PATCH 04/12] Define gasLimit as a uint64 --- .../validator-registration-signature-check/main.go | 4 ++-- .../validator-registration-signature-check/main_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/investigations/validator-registration-signature-check/main.go b/internal/investigations/validator-registration-signature-check/main.go index 4e22ec5e..e7d7de52 100644 --- a/internal/investigations/validator-registration-signature-check/main.go +++ b/internal/investigations/validator-registration-signature-check/main.go @@ -16,7 +16,7 @@ import ( ) var ( - gasLimit = 30000000 + gasLimit = uint64(30000000) feeRecipient = "0xdb65fEd33dc262Fe09D9a2Ba8F80b329BA25f941" timestamp = int64(1606824043) ) @@ -39,7 +39,7 @@ func main() { // Fill in validator registration details validatorRegistration := builderApiV1.ValidatorRegistration{ //nolint:exhaustruct - GasLimit: uint64(gasLimit), + GasLimit: gasLimit, Timestamp: time.Unix(timestamp, 0), } diff --git a/internal/investigations/validator-registration-signature-check/main_test.go b/internal/investigations/validator-registration-signature-check/main_test.go index 2b31a2cc..604e6992 100644 --- a/internal/investigations/validator-registration-signature-check/main_test.go +++ b/internal/investigations/validator-registration-signature-check/main_test.go @@ -15,7 +15,7 @@ import ( func TestValidatorRegistrationSignature(t *testing.T) { // Fill in validator registration details pubkey := "0x84e975405f8691ad7118527ee9ee4ed2e4e8bae973f6e29aa9ca9ee4aea83605ae3536d22acc9aa1af0545064eacf82e" - gasLimit := 30000000 + gasLimit := uint64(30000000) feeRecipient := "0xdb65fed33dc262fe09d9a2ba8f80b329ba25f941" timestamp := int64(1606824043) signature := "0xaf12df007a0c78abb5575067e5f8b089cfcc6227e4a91db7dd8cf517fe86fb944ead859f0781277d9b78c672e4a18c5d06368b603374673cf2007966cece9540f3a1b3f6f9e1bf421d779c4e8010368e6aac134649c7a009210780d401a778a5" @@ -23,7 +23,7 @@ func TestValidatorRegistrationSignature(t *testing.T) { // Constructing the object payload := builderApiV1.SignedValidatorRegistration{ Message: &builderApiV1.ValidatorRegistration{ - GasLimit: uint64(gasLimit), + GasLimit: gasLimit, Timestamp: time.Unix(timestamp, 0), }, } From a6d5079385b7b5440d42cfda485e16757a4e5cf4 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 19 Feb 2025 07:57:22 -0600 Subject: [PATCH 05/12] Replace "golang.org/x/exp/slices" with stdlib "slices" --- services/api/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/api/service.go b/services/api/service.go index 35581152..a186b36a 100644 --- a/services/api/service.go +++ b/services/api/service.go @@ -13,6 +13,7 @@ import ( "net/http" _ "net/http/pprof" "os" + "slices" "sort" "strconv" "strings" @@ -44,7 +45,6 @@ import ( "go.opentelemetry.io/otel/attribute" otelapi "go.opentelemetry.io/otel/metric" uberatomic "go.uber.org/atomic" - "golang.org/x/exp/slices" ) const ( From 0f8bbc71f777023384e6680ab9e24df3e02f6425 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 19 Feb 2025 08:05:46 -0600 Subject: [PATCH 06/12] Use require.JSONEq --- common/ssz_test.go | 4 ++-- common/types_spec_test.go | 6 +++--- services/api/service_test.go | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/common/ssz_test.go b/common/ssz_test.go index d2c77e02..9d6c92b9 100644 --- a/common/ssz_test.go +++ b/common/ssz_test.go @@ -62,7 +62,7 @@ func TestSSZBuilderSubmission(t *testing.T) { buffer := new(bytes.Buffer) err = json.Compact(buffer, jsonBytes) require.NoError(t, err) - require.Equal(t, buffer.Bytes(), marshalledJSONBytes) + require.JSONEq(t, buffer.String(), string(marshalledJSONBytes)) }) } } @@ -146,7 +146,7 @@ func TestSSZGetHeaderResponse(t *testing.T) { buffer := new(bytes.Buffer) err = json.Compact(buffer, jsonBytes) require.NoError(t, err) - require.Equal(t, buffer.Bytes(), marshalledJSONBytes) + require.JSONEq(t, buffer.String(), string(marshalledJSONBytes)) }) } } diff --git a/common/types_spec_test.go b/common/types_spec_test.go index 411253ae..9f8ccc01 100644 --- a/common/types_spec_test.go +++ b/common/types_spec_test.go @@ -23,7 +23,7 @@ func TestSubmitBuilderBlockJSON(t *testing.T) { require.NoError(t, err) expectedJSONBytes := buffer.Bytes() - require.Equal(t, expectedJSONBytes, marshalledJSONBytes) + require.JSONEq(t, string(expectedJSONBytes), string(marshalledJSONBytes)) } func TestSignedBeaconBlockJSON(t *testing.T) { @@ -56,7 +56,7 @@ func TestSignedBeaconBlockJSON(t *testing.T) { marshalledJSONBytes, err := json.Marshal(blockRequest) require.NoError(t, err) - require.Equal(t, expectedJSONBytes, marshalledJSONBytes) + require.JSONEq(t, string(expectedJSONBytes), string(marshalledJSONBytes)) }) } } @@ -91,7 +91,7 @@ func TestSignedBlindedBlockJSON(t *testing.T) { marshalledJSONBytes, err := json.Marshal(blockRequest) require.NoError(t, err) - require.Equal(t, expectedJSONBytes, marshalledJSONBytes) + require.JSONEq(t, string(expectedJSONBytes), string(marshalledJSONBytes)) }) } } diff --git a/services/api/service_test.go b/services/api/service_test.go index ba6a43ce..2c4ed356 100644 --- a/services/api/service_test.go +++ b/services/api/service_test.go @@ -188,7 +188,7 @@ func TestLivez(t *testing.T) { path := "/livez" rr := backend.request(http.MethodGet, path, nil) require.Equal(t, http.StatusOK, rr.Code) - require.Equal(t, "{\"message\":\"live\"}\n", rr.Body.String()) + require.JSONEq(t, "{\"message\":\"live\"}\n", rr.Body.String()) } func TestRegisterValidator(t *testing.T) { @@ -513,7 +513,7 @@ func TestBuilderSubmitBlock(t *testing.T) { require.Len(t, reqJSONBytes, testCase.data.jsonReqSize) reqJSONBytes2, err := json.Marshal(req) require.NoError(t, err) - require.Equal(t, reqJSONBytes, reqJSONBytes2) + require.JSONEq(t, string(reqJSONBytes), string(reqJSONBytes2)) rr := backend.requestBytes(http.MethodPost, path, reqJSONBytes, nil) require.Contains(t, rr.Body.String(), "invalid signature") require.Equal(t, http.StatusBadRequest, rr.Code) From e9efdbe235124892590d4726e60e81969fd3e502 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 19 Feb 2025 08:16:03 -0600 Subject: [PATCH 07/12] Add a bunch of //nolint:gosec comments for timestamp conversions --- database/types.go | 2 +- datastore/datastore.go | 2 +- datastore/redis_test.go | 6 +++--- services/api/optimistic_test.go | 2 +- services/api/service.go | 38 ++++++++++++++++----------------- services/api/service_test.go | 6 +++--- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/database/types.go b/database/types.go index 564e65dd..6091fc97 100644 --- a/database/types.go +++ b/database/types.go @@ -99,7 +99,7 @@ func SignedValidatorRegistrationToEntry(valReg builderApiV1.SignedValidatorRegis return ValidatorRegistrationEntry{ Pubkey: valReg.Message.Pubkey.String(), FeeRecipient: valReg.Message.FeeRecipient.String(), - Timestamp: uint64(valReg.Message.Timestamp.Unix()), + Timestamp: uint64(valReg.Message.Timestamp.Unix()), //nolint:gosec GasLimit: valReg.Message.GasLimit, Signature: valReg.Signature.String(), } diff --git a/datastore/datastore.go b/datastore/datastore.go index 3dc7be13..05489e94 100644 --- a/datastore/datastore.go +++ b/datastore/datastore.go @@ -194,7 +194,7 @@ func (ds *Datastore) SaveValidatorRegistration(entry builderApiV1.SignedValidato // then save in redis pk := common.NewPubkeyHex(entry.Message.Pubkey.String()) - err = ds.redis.SetValidatorRegistrationTimestampIfNewer(pk, uint64(entry.Message.Timestamp.Unix())) + err = ds.redis.SetValidatorRegistrationTimestampIfNewer(pk, uint64(entry.Message.Timestamp.Unix())) //nolint:gosec if err != nil { return errors.Wrap(err, "failed saving validator registration to redis") } diff --git a/datastore/redis_test.go b/datastore/redis_test.go index 2d60b6b1..649a633c 100644 --- a/datastore/redis_test.go +++ b/datastore/redis_test.go @@ -41,11 +41,11 @@ func TestRedisValidatorRegistration(t *testing.T) { key := common.ValidPayloadRegisterValidator.Message.Pubkey value := common.ValidPayloadRegisterValidator pkHex := common.NewPubkeyHex(key.String()) - err := cache.SetValidatorRegistrationTimestamp(pkHex, uint64(value.Message.Timestamp.Unix())) + err := cache.SetValidatorRegistrationTimestamp(pkHex, uint64(value.Message.Timestamp.Unix())) //nolint:gosec require.NoError(t, err) result, err := cache.GetValidatorRegistrationTimestamp(common.NewPubkeyHex(key.String())) require.NoError(t, err) - require.Equal(t, result, uint64(value.Message.Timestamp.Unix())) + require.Equal(t, result, uint64(value.Message.Timestamp.Unix())) //nolint:gosec }) t.Run("Returns nil if validator registration is not in cache", func(t *testing.T) { @@ -60,7 +60,7 @@ func TestRedisValidatorRegistration(t *testing.T) { value := common.ValidPayloadRegisterValidator pkHex := common.NewPubkeyHex(key.String()) - timestamp := uint64(value.Message.Timestamp.Unix()) + timestamp := uint64(value.Message.Timestamp.Unix()) //nolint:gosec err := cache.SetValidatorRegistrationTimestampIfNewer(pkHex, timestamp) require.NoError(t, err) diff --git a/services/api/optimistic_test.go b/services/api/optimistic_test.go index d5d17eb9..59e31be0 100644 --- a/services/api/optimistic_test.go +++ b/services/api/optimistic_test.go @@ -489,7 +489,7 @@ func TestBuilderApiSubmitNewBlockOptimistic(t *testing.T) { }, tc.simulationError, backend) // Check http code. - require.Equal(t, uint64(rr.Code), tc.httpCode) + require.EqualValues(t, rr.Code, tc.httpCode) // Check status in db. builder, err := backend.relay.db.GetBlockBuilderByPubkey(pkStr) diff --git a/services/api/service.go b/services/api/service.go index a186b36a..a1fef185 100644 --- a/services/api/service.go +++ b/services/api/service.go @@ -434,11 +434,11 @@ func (api *RelayAPI) StartServer() (err error) { log.Infof("forkSchedule: version=%s / epoch=%d", fork.CurrentVersion, fork.Epoch) switch fork.CurrentVersion { case api.opts.EthNetDetails.CapellaForkVersionHex: - api.capellaEpoch = int64(fork.Epoch) + api.capellaEpoch = int64(fork.Epoch) //nolint:gosec case api.opts.EthNetDetails.DenebForkVersionHex: - api.denebEpoch = int64(fork.Epoch) + api.denebEpoch = int64(fork.Epoch) //nolint:gosec case api.opts.EthNetDetails.ElectraForkVersionHex: - api.electraEpoch = int64(fork.Epoch) + api.electraEpoch = int64(fork.Epoch) //nolint:gosec } } @@ -1098,7 +1098,7 @@ func (api *RelayAPI) handleRegisterValidator(w http.ResponseWriter, req *http.Re // Ensure a valid timestamp (not too early, and not too far in the future) registrationTimestamp := signedValidatorRegistration.Message.Timestamp.Unix() - if registrationTimestamp < int64(api.genesisInfo.Data.GenesisTime) { + if registrationTimestamp < int64(api.genesisInfo.Data.GenesisTime) { //nolint:gosec handleError(regLog, http.StatusBadRequest, "timestamp too early") return } else if registrationTimestamp > registrationTimestampUpperBound { @@ -1117,7 +1117,7 @@ func (api *RelayAPI) handleRegisterValidator(w http.ResponseWriter, req *http.Re prevTimestamp, err := api.redis.GetValidatorRegistrationTimestamp(pkHex) if err != nil { regLog.WithError(err).Error("error getting last registration timestamp") - } else if prevTimestamp >= uint64(signedValidatorRegistration.Message.Timestamp.Unix()) { + } else if prevTimestamp >= uint64(signedValidatorRegistration.Message.Timestamp.Unix()) { //nolint:gosec // abort if the current registration timestamp is older or equal to the last known one return } @@ -1189,7 +1189,7 @@ func (api *RelayAPI) handleGetHeader(w http.ResponseWriter, req *http.Request) { requestTime := time.Now().UTC() slotStartTimestamp := api.genesisInfo.Data.GenesisTime + (slot * common.SecondsPerSlot) - msIntoSlot := requestTime.UnixMilli() - int64((slotStartTimestamp * 1000)) + msIntoSlot := requestTime.UnixMilli() - int64(slotStartTimestamp*1000) //nolint:gosec log := api.log.WithFields(logrus.Fields{ "method": "getHeader", @@ -1371,7 +1371,7 @@ func (api *RelayAPI) handleGetPayload(w http.ResponseWriter, req *http.Request) return } slotStartTimestamp := api.genesisInfo.Data.GenesisTime + (uint64(slot) * common.SecondsPerSlot) - msIntoSlot := decodeTime.UnixMilli() - int64((slotStartTimestamp * 1000)) + msIntoSlot := decodeTime.UnixMilli() - int64(slotStartTimestamp*1000) //nolint:gosec log = log.WithFields(logrus.Fields{ "slot": slot, "slotEpochPos": (uint64(slot) % common.SlotsPerEpoch) + 1, @@ -1577,7 +1577,7 @@ func (api *RelayAPI) handleGetPayload(w http.ResponseWriter, req *http.Request) // Handle early/late requests if msIntoSlot < 0 { // Wait until slot start (t=0) if still in the future - _msSinceSlotStart := time.Now().UTC().UnixMilli() - int64((slotStartTimestamp * 1000)) + _msSinceSlotStart := time.Now().UTC().UnixMilli() - int64(slotStartTimestamp*1000) //nolint:gosec if _msSinceSlotStart < 0 { delayMillis := _msSinceSlotStart * -1 log = log.WithField("delayMillis", delayMillis) @@ -1590,7 +1590,7 @@ func (api *RelayAPI) handleGetPayload(w http.ResponseWriter, req *http.Request) api.RespondError(w, http.StatusBadRequest, fmt.Sprintf("sent too late - %d ms into slot", msIntoSlot)) go func() { - err := api.db.InsertTooLateGetPayload(uint64(slot), proposerPubkey.String(), blockHash.String(), slotStartTimestamp, uint64(receivedAt.UnixMilli()), uint64(decodeTime.UnixMilli()), uint64(msIntoSlot)) + err := api.db.InsertTooLateGetPayload(uint64(slot), proposerPubkey.String(), blockHash.String(), slotStartTimestamp, uint64(receivedAt.UnixMilli()), uint64(decodeTime.UnixMilli()), uint64(msIntoSlot)) //nolint:gosec if err != nil { log.WithError(err).Error("failed to insert payload too late into db") } @@ -1623,7 +1623,7 @@ func (api *RelayAPI) handleGetPayload(w http.ResponseWriter, req *http.Request) } timeAfterPublish := time.Now().UTC().UnixMilli() - msNeededForPublishing = uint64(timeAfterPublish - timeBeforePublish) + msNeededForPublishing = uint64(timeAfterPublish - timeBeforePublish) //nolint:gosec log = log.WithField("timestampAfterPublishing", timeAfterPublish) log.WithField("msNeededForPublishing", msNeededForPublishing).Info("block published through beacon node") metrics.PublishBlockLatencyHistogram.Record(req.Context(), float64(msNeededForPublishing)) @@ -1974,7 +1974,7 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque } nextTime = time.Now().UTC() - pf.PayloadLoad = uint64(nextTime.Sub(prevTime).Microseconds()) + pf.PayloadLoad = uint64(nextTime.Sub(prevTime).Microseconds()) //nolint:gosec prevTime = nextTime payload := new(common.VersionedSubmitBlockRequest) @@ -2009,7 +2009,7 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque } nextTime = time.Now().UTC() - pf.Decode = uint64(nextTime.Sub(prevTime).Microseconds()) + pf.Decode = uint64(nextTime.Sub(prevTime).Microseconds()) //nolint:gosec prevTime = nextTime isLargeRequest := len(requestPayloadBytes) > fastTrackPayloadSizeLimit @@ -2181,7 +2181,7 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque log = log.WithField("timestampAfterCheckingTopBid", time.Now().UTC().UnixMilli()) nextTime = time.Now().UTC() - pf.Prechecks = uint64(nextTime.Sub(prevTime).Microseconds()) + pf.Prechecks = uint64(nextTime.Sub(prevTime).Microseconds()) //nolint:gosec prevTime = nextTime // Simulate the block submission and save to db @@ -2237,7 +2237,7 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque } nextTime = time.Now().UTC() - pf.Simulation = uint64(nextTime.Sub(prevTime).Microseconds()) + pf.Simulation = uint64(nextTime.Sub(prevTime).Microseconds()) //nolint:gosec pf.SimulationSuccess = true prevTime = nextTime @@ -2305,12 +2305,12 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque } nextTime = time.Now().UTC() - pf.RedisUpdate = uint64(nextTime.Sub(prevTime).Microseconds()) pf.WasBidSaved = updateBidResult.WasBidSaved - pf.RedisSavePayload = uint64(updateBidResult.TimeSavePayload.Microseconds()) - pf.RedisUpdateTopBid = uint64(updateBidResult.TimeUpdateTopBid.Microseconds()) - pf.RedisUpdateFloor = uint64(updateBidResult.TimeUpdateFloor.Microseconds()) - pf.Total = uint64(nextTime.Sub(receivedAt).Microseconds()) + pf.RedisUpdate = uint64(nextTime.Sub(prevTime).Microseconds()) //nolint:gosec + pf.RedisSavePayload = uint64(updateBidResult.TimeSavePayload.Microseconds()) //nolint:gosec + pf.RedisUpdateTopBid = uint64(updateBidResult.TimeUpdateTopBid.Microseconds()) //nolint:gosec + pf.RedisUpdateFloor = uint64(updateBidResult.TimeUpdateFloor.Microseconds()) //nolint:gosec + pf.Total = uint64(nextTime.Sub(receivedAt).Microseconds()) //nolint:gosec // All done, log with profiling information log.WithFields(logrus.Fields{ diff --git a/services/api/service_test.go b/services/api/service_test.go index 2c4ed356..3fec89e0 100644 --- a/services/api/service_test.go +++ b/services/api/service_test.go @@ -229,7 +229,7 @@ func TestGetHeader(t *testing.T) { backend := newTestBackend(t, 1) backend.relay.genesisInfo = &beaconclient.GetGenesisResponse{ Data: beaconclient.GetGenesisResponseData{ - GenesisTime: uint64(time.Now().UTC().Unix()), + GenesisTime: uint64(time.Now().UTC().Unix()), //nolint:gosec }, } @@ -499,10 +499,10 @@ func TestBuilderSubmitBlock(t *testing.T) { switch req.Version { //nolint:exhaustive case spec.DataVersionCapella: req.Capella.Message.Slot = submissionSlot - req.Capella.ExecutionPayload.Timestamp = uint64(submissionTimestamp) + req.Capella.ExecutionPayload.Timestamp = uint64(submissionTimestamp) //nolint:gosec case spec.DataVersionDeneb: req.Deneb.Message.Slot = submissionSlot - req.Deneb.ExecutionPayload.Timestamp = uint64(submissionTimestamp) + req.Deneb.ExecutionPayload.Timestamp = uint64(submissionTimestamp) //nolint:gosec default: require.Fail(t, "unknown data version") } From e9c98fabbbf4dc8f2bc3428ed6c9d61f5ad0dd35 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 19 Feb 2025 08:29:07 -0600 Subject: [PATCH 08/12] Disable deprecated tenv linter --- .golangci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.golangci.yaml b/.golangci.yaml index 61bb16cf..cfa60f9d 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -28,6 +28,7 @@ linters: - wsl - interfacebloat - exhaustruct + - tenv # # Disabled because of generics: From f0eee93d94456cd19cc2faa3d816df0bdf4d5a4d Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 19 Feb 2025 08:29:23 -0600 Subject: [PATCH 09/12] Define new errTimestampOverflow var --- database/types.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/database/types.go b/database/types.go index 6091fc97..16b1295b 100644 --- a/database/types.go +++ b/database/types.go @@ -11,6 +11,8 @@ import ( "github.com/flashbots/go-boost-utils/utils" ) +var errTimestampOverflow = errors.New("timestamp overflow") + func NewNullInt64(i int64) sql.NullInt64 { return sql.NullInt64{ Int64: i, @@ -81,7 +83,7 @@ func (reg ValidatorRegistrationEntry) ToSignedValidatorRegistration() (*builderA } if reg.Timestamp > uint64(math.MaxInt64) { - return nil, errors.New("timestamp overflow") + return nil, errTimestampOverflow } return &builderApiV1.SignedValidatorRegistration{ From 6f79ac9503ea33203bd2952dcce8c5d7a8419eb2 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 19 Feb 2025 08:40:53 -0600 Subject: [PATCH 10/12] Bump golang to v1.24 --- .github/workflows/checks.yml | 4 ++-- Dockerfile | 2 +- go.mod | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 2f8dddca..b8d6af64 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -14,7 +14,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: ^1.22 + go-version: ^1.24 id: go - name: Check out code into the Go module directory @@ -40,7 +40,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: ^1.22 + go-version: ^1.24 id: go - name: Check out code into the Go module directory diff --git a/Dockerfile b/Dockerfile index fb9e0d94..ab746c4e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.22 as builder +FROM golang:1.24 as builder ARG VERSION WORKDIR /build diff --git a/go.mod b/go.mod index 0e3e979d..47967fb8 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/flashbots/mev-boost-relay -go 1.22.0 +go 1.24.0 require ( github.com/NYTimes/gziphandler v1.1.1 From b69d5135679373ee12d02e53819112a2f3016e65 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 19 Feb 2025 08:41:27 -0600 Subject: [PATCH 11/12] Run go mod tidy --- go.mod | 1 - 1 file changed, 1 deletion(-) diff --git a/go.mod b/go.mod index 47967fb8..6e24d54d 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,6 @@ require ( go.opentelemetry.io/otel/sdk v1.25.0 go.opentelemetry.io/otel/sdk/metric v1.25.0 go.uber.org/atomic v1.11.0 - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/text v0.21.0 ) From 72f01d5753eccef5a6668d4890ff6cba84dfb025 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Wed, 19 Feb 2025 08:52:43 -0600 Subject: [PATCH 12/12] Replace context.Background() with t.Context() in tests --- common/utils_test.go | 3 +-- datastore/redis_test.go | 42 ++++++++++++++++----------------- services/api/optimistic_test.go | 3 +-- services/api/service_test.go | 5 ++-- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/common/utils_test.go b/common/utils_test.go index 9565a1da..7c52b782 100644 --- a/common/utils_test.go +++ b/common/utils_test.go @@ -1,7 +1,6 @@ package common import ( - "context" "fmt" "net/http" "os" @@ -22,7 +21,7 @@ import ( func TestMakePostRequest(t *testing.T) { // Test errors var x chan bool - resp, err := makeRequest(context.Background(), *http.DefaultClient, http.MethodGet, "", x) + resp, err := makeRequest(t.Context(), *http.DefaultClient, http.MethodGet, "", x) require.Error(t, err) require.Nil(t, resp) diff --git a/datastore/redis_test.go b/datastore/redis_test.go index 649a633c..a0c1e321 100644 --- a/datastore/redis_test.go +++ b/datastore/redis_test.go @@ -156,7 +156,7 @@ func TestBuilderBids(t *testing.T) { require.NoError(t, err) require.Equal(t, big.NewInt(expectedValue), value.ToBig()) - topBidValue, err := cache.GetTopBidValue(context.Background(), cache.client.Pipeline(), slot, parentHash, proposerPubkey) + topBidValue, err := cache.GetTopBidValue(t.Context(), cache.client.Pipeline(), slot, parentHash, proposerPubkey) require.NoError(t, err) require.Equal(t, big.NewInt(expectedValue), topBidValue) @@ -168,18 +168,18 @@ func TestBuilderBids(t *testing.T) { } ensureBidFloor := func(expectedValue int64) { - floorValue, err := cache.GetFloorBidValue(context.Background(), cache.client.Pipeline(), slot, parentHash, proposerPubkey) + floorValue, err := cache.GetFloorBidValue(t.Context(), cache.client.Pipeline(), slot, parentHash, proposerPubkey) require.NoError(t, err) require.Equal(t, big.NewInt(expectedValue), floorValue) } // deleting a bid that doesn't exist should not error - err := cache.DelBuilderBid(context.Background(), cache.client.Pipeline(), slot, parentHash, proposerPubkey, bApubkey) + err := cache.DelBuilderBid(t.Context(), cache.client.Pipeline(), slot, parentHash, proposerPubkey, bApubkey) require.NoError(t, err) // submit ba1=10 payload, getPayloadResp, getHeaderResp := common.CreateTestBlockSubmission(t, bApubkey, uint256.NewInt(10), &opts) - resp, err := cache.SaveBidAndUpdateTopBid(context.Background(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) + resp, err := cache.SaveBidAndUpdateTopBid(t.Context(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) require.NoError(t, err) require.True(t, resp.WasBidSaved, resp) require.True(t, resp.WasTopBidUpdated) @@ -189,7 +189,7 @@ func TestBuilderBids(t *testing.T) { ensureBidFloor(10) // deleting ba1 - err = cache.DelBuilderBid(context.Background(), cache.client.Pipeline(), slot, parentHash, proposerPubkey, bApubkey) + err = cache.DelBuilderBid(t.Context(), cache.client.Pipeline(), slot, parentHash, proposerPubkey, bApubkey) require.NoError(t, err) // best bid and floor should still exist, because it was the floor bid @@ -198,7 +198,7 @@ func TestBuilderBids(t *testing.T) { // submit ba2=5 (should not update, because floor is 10) payload, getPayloadResp, getHeaderResp = common.CreateTestBlockSubmission(t, bApubkey, uint256.NewInt(5), &opts) - resp, err = cache.SaveBidAndUpdateTopBid(context.Background(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) + resp, err = cache.SaveBidAndUpdateTopBid(t.Context(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) require.NoError(t, err) require.False(t, resp.WasBidSaved, resp) require.False(t, resp.WasTopBidUpdated) @@ -209,7 +209,7 @@ func TestBuilderBids(t *testing.T) { // submit ba3c=5 (should not update, because floor is 10) payload, getPayloadResp, getHeaderResp = common.CreateTestBlockSubmission(t, bApubkey, uint256.NewInt(5), &opts) - resp, err = cache.SaveBidAndUpdateTopBid(context.Background(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), true, nil) + resp, err = cache.SaveBidAndUpdateTopBid(t.Context(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), true, nil) require.NoError(t, err) require.True(t, resp.WasBidSaved) require.False(t, resp.WasTopBidUpdated) @@ -221,7 +221,7 @@ func TestBuilderBids(t *testing.T) { // submit bb1=20 payload, getPayloadResp, getHeaderResp = common.CreateTestBlockSubmission(t, bBpubkey, uint256.NewInt(20), &opts) - resp, err = cache.SaveBidAndUpdateTopBid(context.Background(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) + resp, err = cache.SaveBidAndUpdateTopBid(t.Context(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) require.NoError(t, err) require.True(t, resp.WasBidSaved) require.True(t, resp.WasTopBidUpdated) @@ -232,7 +232,7 @@ func TestBuilderBids(t *testing.T) { // submit bb2c=22 payload, getPayloadResp, getHeaderResp = common.CreateTestBlockSubmission(t, bBpubkey, uint256.NewInt(22), &opts) - resp, err = cache.SaveBidAndUpdateTopBid(context.Background(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), true, nil) + resp, err = cache.SaveBidAndUpdateTopBid(t.Context(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), true, nil) require.NoError(t, err) require.True(t, resp.WasBidSaved) require.True(t, resp.WasTopBidUpdated) @@ -243,7 +243,7 @@ func TestBuilderBids(t *testing.T) { // submit bb3c=12 (should update top bid, using floor at 20) payload, getPayloadResp, getHeaderResp = common.CreateTestBlockSubmission(t, bBpubkey, uint256.NewInt(12), &opts) - resp, err = cache.SaveBidAndUpdateTopBid(context.Background(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), true, nil) + resp, err = cache.SaveBidAndUpdateTopBid(t.Context(), cache.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), true, nil) require.NoError(t, err) require.True(t, resp.WasBidSaved) require.True(t, resp.WasTopBidUpdated) @@ -290,7 +290,7 @@ func TestCheckAndSetLastSlotAndHashDelivered(t *testing.T) { newHash := "0x0000000000000000000000000000000000000000000000000000000000000000" // should return redis.Nil if wasn't set - slot, err := cache.GetLastSlotDelivered(context.Background(), cache.NewPipeline()) + slot, err := cache.GetLastSlotDelivered(t.Context(), cache.NewPipeline()) require.ErrorIs(t, err, redis.Nil) require.Equal(t, uint64(0), slot) @@ -299,7 +299,7 @@ func TestCheckAndSetLastSlotAndHashDelivered(t *testing.T) { require.NoError(t, err) // should get slot - slot, err = cache.GetLastSlotDelivered(context.Background(), cache.NewPipeline()) + slot, err = cache.GetLastSlotDelivered(t.Context(), cache.NewPipeline()) require.NoError(t, err) require.Equal(t, newSlot, slot) @@ -426,8 +426,8 @@ func TestGetBuilderLatestValue(t *testing.T) { }, } - _, err = cache.client.TxPipelined(context.Background(), func(pipeliner redis.Pipeliner) error { - return cache.SaveBuilderBid(context.Background(), pipeliner, slot, parentHash, proposerPubkey, builderPubkey, time.Now().UTC(), getHeaderResp) + _, err = cache.client.TxPipelined(t.Context(), func(pipeliner redis.Pipeliner) error { + return cache.SaveBuilderBid(t.Context(), pipeliner, slot, parentHash, proposerPubkey, builderPubkey, time.Now().UTC(), getHeaderResp) }) require.NoError(t, err) @@ -439,7 +439,7 @@ func TestGetBuilderLatestValue(t *testing.T) { func TestPipelineNilCheck(t *testing.T) { cache := setupTestRedis(t) - f, err := cache.GetFloorBidValue(context.Background(), cache.NewPipeline(), 0, "1", "2") + f, err := cache.GetFloorBidValue(t.Context(), cache.NewPipeline(), 0, "1", "2") require.NoError(t, err) require.Equal(t, big.NewInt(0), f) } @@ -450,24 +450,24 @@ func TestPipelineNilCheck(t *testing.T) { // key1 := "test1" // key2 := "test123" // val := "foo" -// err := cache.client.Set(context.Background(), key1, val, 0).Err() +// err := cache.client.Set(t.Context(), key1, val, 0).Err() // require.NoError(t, err) -// _, err = cache.client.TxPipelined(context.Background(), func(pipeliner redis.Pipeliner) error { -// c := tx.Get(context.Background(), key1) -// _, err := tx.Exec(context.Background()) +// _, err = cache.client.TxPipelined(t.Context(), func(pipeliner redis.Pipeliner) error { +// c := tx.Get(t.Context(), key1) +// _, err := tx.Exec(t.Context()) // require.NoError(t, err) // str, err := c.Result() // require.NoError(t, err) // require.Equal(t, val, str) -// err = tx.Set(context.Background(), key2, val, 0).Err() +// err = tx.Set(t.Context(), key2, val, 0).Err() // require.NoError(t, err) // return nil // }) // require.NoError(t, err) -// str, err := cache.client.Get(context.Background(), key2).Result() +// str, err := cache.client.Get(t.Context(), key2).Result() // require.NoError(t, err) // require.Equal(t, val, str) // } diff --git a/services/api/optimistic_test.go b/services/api/optimistic_test.go index 59e31be0..10bc781e 100644 --- a/services/api/optimistic_test.go +++ b/services/api/optimistic_test.go @@ -1,7 +1,6 @@ package api import ( - "context" "encoding/json" "errors" "math/big" @@ -200,7 +199,7 @@ func TestSimulateBlock(t *testing.T) { backend.relay.blockSimRateLimiter = &MockBlockSimulationRateLimiter{ simulationError: tc.simulationError, } - _, _, simErr := backend.relay.simulateBlock(context.Background(), blockSimOptions{ + _, _, simErr := backend.relay.simulateBlock(t.Context(), blockSimOptions{ isHighPrio: true, log: backend.relay.log, builder: &blockBuilderCacheEntry{ diff --git a/services/api/service_test.go b/services/api/service_test.go index 3fec89e0..dd8bcee5 100644 --- a/services/api/service_test.go +++ b/services/api/service_test.go @@ -3,7 +3,6 @@ package api import ( "bytes" "compress/gzip" - "context" "encoding/json" "fmt" "math/big" @@ -257,7 +256,7 @@ func TestGetHeader(t *testing.T) { Version: spec.DataVersionCapella, } payload, getPayloadResp, getHeaderResp := common.CreateTestBlockSubmission(t, builderPubkey, bidValue, &opts) - _, err := backend.redis.SaveBidAndUpdateTopBid(context.Background(), backend.redis.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) + _, err := backend.redis.SaveBidAndUpdateTopBid(t.Context(), backend.redis.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) require.NoError(t, err) // Check 1: regular capella request works and returns a bid @@ -280,7 +279,7 @@ func TestGetHeader(t *testing.T) { Version: spec.DataVersionDeneb, } payload, getPayloadResp, getHeaderResp = common.CreateTestBlockSubmission(t, builderPubkey, bidValue, &opts) - _, err = backend.redis.SaveBidAndUpdateTopBid(context.Background(), backend.redis.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) + _, err = backend.redis.SaveBidAndUpdateTopBid(t.Context(), backend.redis.NewPipeline(), trace, payload, getPayloadResp, getHeaderResp, time.Now(), false, nil) require.NoError(t, err) // Check 2: regular deneb request works and returns a bid