From d4bb90ae8ca9b3fa4acd49360675cfa4eec70e29 Mon Sep 17 00:00:00 2001 From: shana Date: Fri, 28 Jul 2023 16:35:17 -0700 Subject: [PATCH] Upgrade go-boost-utils (#488) * Upgrade go-boost-utils * pr comments * remove commented out code --- .golangci.yaml | 3 +- beaconclient/beacon_client_test.go | 3 +- beaconclient/mock_beacon_instance.go | 12 +- beaconclient/mock_multi_beacon_client.go | 4 - beaconclient/multi_beacon_client.go | 2 +- beaconclient/prod_beacon_instance.go | 3 +- common/test_utils.go | 42 ++-- common/types.go | 41 ++-- common/types_spec.go | 57 ++++-- common/utils.go | 19 +- common/utils_test.go | 84 ++++++++ database/database.go | 6 +- database/database_test.go | 13 +- database/mockdb.go | 4 +- database/types.go | 21 +- datastore/datastore.go | 26 +-- datastore/datastore_test.go | 25 --- datastore/memcached_test.go | 19 +- datastore/redis.go | 11 +- datastore/redis_test.go | 115 ++--------- go.mod | 18 +- go.sum | 8 +- .../main.go | 19 +- .../main_test.go | 21 +- services/api/optimistic_test.go | 33 ++-- services/api/service.go | 66 ++++--- services/api/service_test.go | 186 +++++------------- services/api/types_test.go | 53 ++--- services/api/utils.go | 10 +- services/housekeeper/housekeeper.go | 6 +- 30 files changed, 431 insertions(+), 499 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index baa7e72a..7cb84f25 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -93,7 +93,8 @@ linters-settings: # # Easier to read with only one of the versioned payloads. # - - 'api.VersionedExecutionPayload' + - 'VersionedExecutionPayload' + - 'VersionedSignedBuilderBid' # # Structures outside our control that have a ton of settings. It doesn't diff --git a/beaconclient/beacon_client_test.go b/beaconclient/beacon_client_test.go index a6c807d8..1a3530eb 100644 --- a/beaconclient/beacon_client_test.go +++ b/beaconclient/beacon_client_test.go @@ -7,7 +7,6 @@ import ( "testing" "time" - "github.com/flashbots/go-boost-utils/types" "github.com/flashbots/mev-boost-relay/common" "github.com/gorilla/mux" "github.com/stretchr/testify/require" @@ -194,7 +193,7 @@ func TestFetchValidators(t *testing.T) { // only beacon 2 should have a validator, and should be used by default backend.beaconInstances[0].MockFetchValidatorsErr = nil - backend.beaconInstances[1].SetValidators(make(map[types.PubkeyHex]ValidatorResponseEntry)) + backend.beaconInstances[1].SetValidators(make(map[common.PubkeyHex]ValidatorResponseEntry)) backend.beaconInstances[2].MockFetchValidatorsErr = nil backend.beaconInstances[2].AddValidator(entry) diff --git a/beaconclient/mock_beacon_instance.go b/beaconclient/mock_beacon_instance.go index cfffd830..a09127e9 100644 --- a/beaconclient/mock_beacon_instance.go +++ b/beaconclient/mock_beacon_instance.go @@ -5,12 +5,12 @@ import ( "time" "github.com/attestantio/go-eth2-client/spec" - "github.com/flashbots/go-boost-utils/types" + "github.com/flashbots/mev-boost-relay/common" ) type MockBeaconInstance struct { mu sync.RWMutex - validatorSet map[types.PubkeyHex]ValidatorResponseEntry + validatorSet map[common.PubkeyHex]ValidatorResponseEntry MockSyncStatus *SyncStatusPayloadData MockSyncStatusErr error @@ -23,7 +23,7 @@ type MockBeaconInstance struct { func NewMockBeaconInstance() *MockBeaconInstance { return &MockBeaconInstance{ - validatorSet: make(map[types.PubkeyHex]ValidatorResponseEntry), + validatorSet: make(map[common.PubkeyHex]ValidatorResponseEntry), MockSyncStatus: &SyncStatusPayloadData{ HeadSlot: 1, @@ -44,17 +44,17 @@ func NewMockBeaconInstance() *MockBeaconInstance { func (c *MockBeaconInstance) AddValidator(entry ValidatorResponseEntry) { c.mu.Lock() - c.validatorSet[types.NewPubkeyHex(entry.Validator.Pubkey)] = entry + c.validatorSet[common.NewPubkeyHex(entry.Validator.Pubkey)] = entry c.mu.Unlock() } -func (c *MockBeaconInstance) SetValidators(validatorSet map[types.PubkeyHex]ValidatorResponseEntry) { +func (c *MockBeaconInstance) SetValidators(validatorSet map[common.PubkeyHex]ValidatorResponseEntry) { c.mu.Lock() c.validatorSet = validatorSet c.mu.Unlock() } -func (c *MockBeaconInstance) IsValidator(pubkey types.PubkeyHex) bool { +func (c *MockBeaconInstance) IsValidator(pubkey common.PubkeyHex) bool { c.mu.RLock() _, found := c.validatorSet[pubkey] c.mu.RUnlock() diff --git a/beaconclient/mock_multi_beacon_client.go b/beaconclient/mock_multi_beacon_client.go index 4efacf14..e5935b5e 100644 --- a/beaconclient/mock_multi_beacon_client.go +++ b/beaconclient/mock_multi_beacon_client.go @@ -20,10 +20,6 @@ func (*MockMultiBeaconClient) SubscribeToHeadEvents(slotC chan HeadEventData) {} func (*MockMultiBeaconClient) SubscribeToPayloadAttributesEvents(payloadAttrC chan PayloadAttributesEvent) { } -// func (*MockMultiBeaconClient) FetchValidators(headSlot uint64) (map[types.PubkeyHex]ValidatorResponseEntry, error) { -// return nil, nil -// } - func (*MockMultiBeaconClient) GetStateValidators(stateID string) (*GetStateValidatorsResponse, error) { return nil, nil } diff --git a/beaconclient/multi_beacon_client.go b/beaconclient/multi_beacon_client.go index c549d5d0..466092f5 100644 --- a/beaconclient/multi_beacon_client.go +++ b/beaconclient/multi_beacon_client.go @@ -261,7 +261,7 @@ func (c *MultiBeaconClient) PublishBlock(block *spec.VersionedSignedBeaconBlock) c.log.WithError(err).Warn("failed to publish block as block slot is missing") return 0, err } - blockHash, err := block.BlockHash() + blockHash, err := block.ExecutionBlockHash() if err != nil { c.log.WithError(err).Warn("failed to publish block as block hash is missing") return 0, err diff --git a/beaconclient/prod_beacon_instance.go b/beaconclient/prod_beacon_instance.go index 27f07d1e..0ed63126 100644 --- a/beaconclient/prod_beacon_instance.go +++ b/beaconclient/prod_beacon_instance.go @@ -9,7 +9,6 @@ import ( "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/flashbots/go-boost-utils/types" "github.com/flashbots/mev-boost-relay/common" "github.com/r3labs/sse/v2" "github.com/sirupsen/logrus" @@ -243,7 +242,7 @@ type GetBlockResponse struct { Message struct { Slot uint64 `json:"slot,string"` Body struct { - ExecutionPayload types.ExecutionPayload `json:"execution_payload"` + ExecutionPayload capella.ExecutionPayload `json:"execution_payload"` } } } diff --git a/common/test_utils.go b/common/test_utils.go index 29aae959..eabbd7d8 100644 --- a/common/test_utils.go +++ b/common/test_utils.go @@ -8,14 +8,18 @@ import ( "io" "os" "testing" + "time" "github.com/attestantio/go-builder-client/api/capella" + apiv1 "github.com/attestantio/go-builder-client/api/v1" "github.com/attestantio/go-builder-client/spec" consensusspec "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/bellatrix" consensuscapella "github.com/attestantio/go-eth2-client/spec/capella" + "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/flashbots/go-boost-utils/bls" - boostTypes "github.com/flashbots/go-boost-utils/types" + "github.com/flashbots/go-boost-utils/ssz" + "github.com/flashbots/go-boost-utils/utils" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" ) @@ -31,33 +35,37 @@ func check(err error, args ...interface{}) { } // _HexToAddress converts a hexadecimal string to an Ethereum address -func _HexToAddress(s string) (ret boostTypes.Address) { - check(ret.UnmarshalText([]byte(s)), " _HexToAddress: ", s) +func _HexToAddress(s string) (ret bellatrix.ExecutionAddress) { + ret, err := utils.HexToAddress(s) + check(err, " _HexToAddress: ", s) return ret } // _HexToPubkey converts a hexadecimal string to a BLS Public Key -func _HexToPubkey(s string) (ret boostTypes.PublicKey) { - check(ret.UnmarshalText([]byte(s)), " _HexToPubkey: ", s) - return +func _HexToPubkey(s string) (ret phase0.BLSPubKey) { + ret, err := utils.HexToPubkey(s) + check(err, " _HexToPubkey: ", s) + return ret } // _HexToSignature converts a hexadecimal string to a BLS Signature -func _HexToSignature(s string) (ret boostTypes.Signature) { - check(ret.UnmarshalText([]byte(s)), " _HexToSignature: ", s) - return +func _HexToSignature(s string) (ret phase0.BLSSignature) { + ret, err := utils.HexToSignature(s) + check(err, " _HexToSignature: ", s) + return ret } // _HexToHash converts a hexadecimal string to a Hash -func _HexToHash(s string) (ret boostTypes.Hash) { - check(ret.FromSlice([]byte(s)), " _HexToHash: ", s) - return +func _HexToHash(s string) (ret phase0.Hash32) { + ret, err := utils.HexToHash(s) + check(err, " _HexToHash: ", s) + return ret } -var ValidPayloadRegisterValidator = boostTypes.SignedValidatorRegistration{ - Message: &boostTypes.RegisterValidatorRequestMessage{ +var ValidPayloadRegisterValidator = apiv1.SignedValidatorRegistration{ + Message: &apiv1.ValidatorRegistration{ FeeRecipient: _HexToAddress("0xdb65fEd33dc262Fe09D9a2Ba8F80b329BA25f941"), - Timestamp: 1606824043, + Timestamp: time.Unix(1606824043, 0), GasLimit: 30000000, Pubkey: _HexToPubkey( "0x84e975405f8691ad7118527ee9ee4ed2e4e8bae973f6e29aa9ca9ee4aea83605ae3536d22acc9aa1af0545064eacf82e"), @@ -67,7 +75,7 @@ var ValidPayloadRegisterValidator = boostTypes.SignedValidatorRegistration{ } func TestBuilderSubmitBlockRequest(sk *bls.SecretKey, bid *BidTraceV2) spec.VersionedSubmitBlockRequest { - signature, err := boostTypes.SignMessage(bid, boostTypes.DomainBuilder, sk) + signature, err := ssz.SignMessage(bid, ssz.DomainBuilder, sk) check(err, " SignMessage: ", bid, sk) return spec.VersionedSubmitBlockRequest{ //nolint:exhaustruct Version: consensusspec.DataVersionCapella, @@ -77,7 +85,7 @@ func TestBuilderSubmitBlockRequest(sk *bls.SecretKey, bid *BidTraceV2) spec.Vers ExecutionPayload: &consensuscapella.ExecutionPayload{ //nolint:exhaustruct Transactions: []bellatrix.Transaction{[]byte{0x03}}, Timestamp: bid.Slot * 12, // 12 seconds per slot. - PrevRandao: _HexToHash("01234567890123456789012345678901"), + PrevRandao: _HexToHash("0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"), Withdrawals: []*consensuscapella.Withdrawal{}, }, }, diff --git a/common/types.go b/common/types.go index d0557f74..1d2331bf 100644 --- a/common/types.go +++ b/common/types.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "strings" apiv1 "github.com/attestantio/go-builder-client/api/v1" consensusbellatrix "github.com/attestantio/go-eth2-client/spec/bellatrix" @@ -64,10 +65,10 @@ type EthNetworkDetails struct { CapellaForkVersionHex string DenebForkVersionHex string - DomainBuilder boostTypes.Domain - DomainBeaconProposerBellatrix boostTypes.Domain - DomainBeaconProposerCapella boostTypes.Domain - DomainBeaconProposerDeneb boostTypes.Domain + DomainBuilder phase0.Domain + DomainBeaconProposerBellatrix phase0.Domain + DomainBeaconProposerCapella phase0.Domain + DomainBeaconProposerDeneb phase0.Domain } func NewEthNetworkDetails(networkName string) (ret *EthNetworkDetails, err error) { @@ -76,10 +77,10 @@ func NewEthNetworkDetails(networkName string) (ret *EthNetworkDetails, err error var bellatrixForkVersion string var capellaForkVersion string var denebForkVersion string - var domainBuilder boostTypes.Domain - var domainBeaconProposerBellatrix boostTypes.Domain - var domainBeaconProposerCapella boostTypes.Domain - var domainBeaconProposerDeneb boostTypes.Domain + var domainBuilder phase0.Domain + var domainBeaconProposerBellatrix phase0.Domain + var domainBeaconProposerCapella phase0.Domain + var domainBeaconProposerDeneb phase0.Domain switch networkName { case EthNetworkHolesky: @@ -116,22 +117,22 @@ func NewEthNetworkDetails(networkName string) (ret *EthNetworkDetails, err error return nil, fmt.Errorf("%w: %s", ErrUnknownNetwork, networkName) } - domainBuilder, err = ComputeDomain(boostTypes.DomainTypeAppBuilder, genesisForkVersion, boostTypes.Root{}.String()) + domainBuilder, err = ComputeDomain(ssz.DomainTypeAppBuilder, genesisForkVersion, phase0.Root{}.String()) if err != nil { return nil, err } - domainBeaconProposerBellatrix, err = ComputeDomain(boostTypes.DomainTypeBeaconProposer, bellatrixForkVersion, genesisValidatorsRoot) + domainBeaconProposerBellatrix, err = ComputeDomain(ssz.DomainTypeBeaconProposer, bellatrixForkVersion, genesisValidatorsRoot) if err != nil { return nil, err } - domainBeaconProposerCapella, err = ComputeDomain(boostTypes.DomainTypeBeaconProposer, capellaForkVersion, genesisValidatorsRoot) + domainBeaconProposerCapella, err = ComputeDomain(ssz.DomainTypeBeaconProposer, capellaForkVersion, genesisValidatorsRoot) if err != nil { return nil, err } - domainBeaconProposerDeneb, err = ComputeDomain(boostTypes.DomainTypeBeaconProposer, denebForkVersion, genesisValidatorsRoot) + domainBeaconProposerDeneb, err = ComputeDomain(ssz.DomainTypeBeaconProposer, denebForkVersion, genesisValidatorsRoot) if err != nil { return nil, err } @@ -176,10 +177,20 @@ func (e *EthNetworkDetails) String() string { e.DomainBeaconProposerDeneb) } +type PubkeyHex string + +func NewPubkeyHex(pk string) PubkeyHex { + return PubkeyHex(strings.ToLower(pk)) +} + +func (p PubkeyHex) String() string { + return string(p) +} + type BuilderGetValidatorsResponseEntry struct { - Slot uint64 `json:"slot,string"` - ValidatorIndex uint64 `json:"validator_index,string"` - Entry *boostTypes.SignedValidatorRegistration `json:"entry"` + Slot uint64 `json:"slot,string"` + ValidatorIndex uint64 `json:"validator_index,string"` + Entry *apiv1.SignedValidatorRegistration `json:"entry"` } type BidTraceV2 struct { diff --git a/common/types_spec.go b/common/types_spec.go index 26f02d1e..5fb2685c 100644 --- a/common/types_spec.go +++ b/common/types_spec.go @@ -14,7 +14,9 @@ import ( utilbellatrix "github.com/attestantio/go-eth2-client/util/bellatrix" utilcapella "github.com/attestantio/go-eth2-client/util/capella" "github.com/flashbots/go-boost-utils/bls" + "github.com/flashbots/go-boost-utils/ssz" boostTypes "github.com/flashbots/go-boost-utils/types" + "github.com/flashbots/go-boost-utils/utils" "github.com/pkg/errors" ) @@ -34,7 +36,7 @@ var NilResponse = struct{}{} var ZeroU256 = boostTypes.IntToU256(0) -func BuildGetHeaderResponse(payload *spec.VersionedSubmitBlockRequest, sk *bls.SecretKey, pubkey *boostTypes.PublicKey, domain boostTypes.Domain) (*spec.VersionedSignedBuilderBid, error) { +func BuildGetHeaderResponse(payload *spec.VersionedSubmitBlockRequest, sk *bls.SecretKey, pubkey *phase0.BLSPubKey, domain phase0.Domain) (*spec.VersionedSignedBuilderBid, error) { if payload == nil { return nil, ErrMissingRequest } @@ -44,7 +46,7 @@ func BuildGetHeaderResponse(payload *spec.VersionedSubmitBlockRequest, sk *bls.S } if payload.Capella != nil { - signedBuilderBid, err := CapellaBuilderSubmitBlockRequestToSignedBuilderBid(payload.Capella, sk, (*phase0.BLSPubKey)(pubkey), domain) + signedBuilderBid, err := CapellaBuilderSubmitBlockRequestToSignedBuilderBid(payload.Capella, sk, pubkey, domain) if err != nil { return nil, err } @@ -68,30 +70,45 @@ func BuildGetPayloadResponse(payload *spec.VersionedSubmitBlockRequest) (*api.Ve return nil, ErrEmptyPayload } -func BuilderSubmitBlockRequestToSignedBuilderBid(req *boostTypes.BuilderSubmitBlockRequest, sk *bls.SecretKey, pubkey *boostTypes.PublicKey, domain boostTypes.Domain) (*boostTypes.SignedBuilderBid, error) { - header, err := boostTypes.PayloadToPayloadHeader(req.ExecutionPayload) +func BuilderSubmitBlockRequestToSignedBuilderBid(req *spec.VersionedSubmitBlockRequest, sk *bls.SecretKey, pubkey *phase0.BLSPubKey, domain phase0.Domain) (*spec.VersionedSignedBuilderBid, error) { + value, err := req.Value() if err != nil { return nil, err } - builderBid := boostTypes.BuilderBid{ - Value: req.Message.Value, - Header: header, - Pubkey: *pubkey, - } + switch req.Version { + case consensusspec.DataVersionCapella: + header, err := utils.PayloadToPayloadHeader(&api.VersionedExecutionPayload{Version: req.Version, Capella: req.Capella.ExecutionPayload}) + if err != nil { + return nil, err + } - sig, err := boostTypes.SignMessage(&builderBid, domain, sk) - if err != nil { - return nil, err - } + builderBid := capella.BuilderBid{ + Value: value, + Header: header.Capella, + Pubkey: *pubkey, + } - return &boostTypes.SignedBuilderBid{ - Message: &builderBid, - Signature: sig, - }, nil + sig, err := ssz.SignMessage(&builderBid, domain, sk) + if err != nil { + return nil, err + } + + return &spec.VersionedSignedBuilderBid{ + Version: consensusspec.DataVersionCapella, + Capella: &capella.SignedBuilderBid{ + Message: &builderBid, + Signature: sig, + }, + }, nil + case consensusspec.DataVersionUnknown, consensusspec.DataVersionPhase0, consensusspec.DataVersionAltair, consensusspec.DataVersionBellatrix, consensusspec.DataVersionDeneb: + return nil, errors.Wrap(ErrInvalidVersion, fmt.Sprintf("%s is not supported", req.Version.String())) + default: + return nil, errors.Wrap(ErrInvalidVersion, fmt.Sprintf("%s is not supported", req.Version.String())) + } } -func CapellaBuilderSubmitBlockRequestToSignedBuilderBid(req *capella.SubmitBlockRequest, sk *bls.SecretKey, pubkey *phase0.BLSPubKey, domain boostTypes.Domain) (*capella.SignedBuilderBid, error) { +func CapellaBuilderSubmitBlockRequestToSignedBuilderBid(req *capella.SubmitBlockRequest, sk *bls.SecretKey, pubkey *phase0.BLSPubKey, domain phase0.Domain) (*capella.SignedBuilderBid, error) { header, err := CapellaPayloadToPayloadHeader(req.ExecutionPayload) if err != nil { return nil, err @@ -103,14 +120,14 @@ func CapellaBuilderSubmitBlockRequestToSignedBuilderBid(req *capella.SubmitBlock Pubkey: *pubkey, } - sig, err := boostTypes.SignMessage(&builderBid, domain, sk) + sig, err := ssz.SignMessage(&builderBid, domain, sk) if err != nil { return nil, err } return &capella.SignedBuilderBid{ Message: &builderBid, - Signature: phase0.BLSSignature(sig), + Signature: sig, }, nil } diff --git a/common/utils.go b/common/utils.go index 76ee403e..33b33468 100644 --- a/common/utils.go +++ b/common/utils.go @@ -17,7 +17,7 @@ import ( "github.com/attestantio/go-builder-client/api" "github.com/attestantio/go-builder-client/api/capella" - v1 "github.com/attestantio/go-builder-client/api/v1" + apiv1 "github.com/attestantio/go-builder-client/api/v1" "github.com/attestantio/go-builder-client/spec" consensusspec "github.com/attestantio/go-eth2-client/spec" capellaspec "github.com/attestantio/go-eth2-client/spec/capella" @@ -25,6 +25,7 @@ import ( ethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/flashbots/go-boost-utils/bls" + "github.com/flashbots/go-boost-utils/ssz" "github.com/flashbots/go-boost-utils/types" "github.com/holiman/uint256" "github.com/stretchr/testify/require" @@ -77,15 +78,15 @@ func makeRequest(ctx context.Context, client http.Client, method, url string, pa } // ComputeDomain computes the signing domain -func ComputeDomain(domainType types.DomainType, forkVersionHex, genesisValidatorsRootHex string) (domain types.Domain, err error) { - genesisValidatorsRoot := types.Root(ethcommon.HexToHash(genesisValidatorsRootHex)) +func ComputeDomain(domainType phase0.DomainType, forkVersionHex, genesisValidatorsRootHex string) (domain phase0.Domain, err error) { + genesisValidatorsRoot := phase0.Root(ethcommon.HexToHash(genesisValidatorsRootHex)) forkVersionBytes, err := hexutil.Decode(forkVersionHex) if err != nil || len(forkVersionBytes) != 4 { return domain, ErrInvalidForkVersion } var forkVersion [4]byte copy(forkVersion[:], forkVersionBytes[:4]) - return types.ComputeDomain(domainType, forkVersion, genesisValidatorsRoot), nil + return ssz.ComputeDomain(domainType, forkVersion, genesisValidatorsRoot), nil } func GetEnv(key, defaultValue string) string { @@ -176,8 +177,8 @@ func StrToPhase0Hash(s string) (ret phase0.Hash32, err error) { type CreateTestBlockSubmissionOpts struct { relaySk bls.SecretKey - relayPk types.PublicKey - domain types.Domain + relayPk phase0.BLSPubKey + domain phase0.Domain Slot uint64 ParentHash string @@ -190,8 +191,8 @@ func CreateTestBlockSubmission(t *testing.T, builderPubkey string, value *uint25 slot := uint64(0) relaySk := bls.SecretKey{} - relayPk := types.PublicKey{} - domain := types.Domain{} + relayPk := phase0.BLSPubKey{} + domain := phase0.Domain{} proposerPk := phase0.BLSPubKey{} parentHash := phase0.Hash32{} @@ -218,7 +219,7 @@ func CreateTestBlockSubmission(t *testing.T, builderPubkey string, value *uint25 payload = &spec.VersionedSubmitBlockRequest{ //nolint:exhaustruct Version: consensusspec.DataVersionCapella, Capella: &capella.SubmitBlockRequest{ - Message: &v1.BidTrace{ //nolint:exhaustruct + Message: &apiv1.BidTrace{ //nolint:exhaustruct BuilderPubkey: builderPk, Value: value, Slot: slot, diff --git a/common/utils_test.go b/common/utils_test.go index 80f88504..70ed2056 100644 --- a/common/utils_test.go +++ b/common/utils_test.go @@ -7,6 +7,13 @@ import ( "os" "testing" + "github.com/attestantio/go-builder-client/api/bellatrix" + "github.com/attestantio/go-builder-client/api/capella" + apiv1 "github.com/attestantio/go-builder-client/api/v1" + "github.com/attestantio/go-builder-client/spec" + consensusspec "github.com/attestantio/go-eth2-client/spec" + consensusbellatrix "github.com/attestantio/go-eth2-client/spec/bellatrix" + consensuscapella "github.com/attestantio/go-eth2-client/spec/capella" "github.com/ethereum/go-ethereum/common" boostTypes "github.com/flashbots/go-boost-utils/types" "github.com/stretchr/testify/require" @@ -98,3 +105,80 @@ func TestGetEnvStrSlice(t *testing.T) { require.Equal(t, "str2", r[1]) os.Unsetenv(testEnvVar) } + +func TestGetBlockSubmissionInfo(t *testing.T) { + cases := []struct { + name string + payload *spec.VersionedSubmitBlockRequest + expected *BlockSubmissionInfo + err string + }{ + { + name: "valid capella", + payload: &spec.VersionedSubmitBlockRequest{ + Version: consensusspec.DataVersionCapella, + Capella: &capella.SubmitBlockRequest{ + Message: &apiv1.BidTrace{}, + ExecutionPayload: &consensuscapella.ExecutionPayload{}, + }, + }, + expected: &BlockSubmissionInfo{ + BidTrace: &apiv1.BidTrace{}, + }, + }, + { + name: "unsupported version", + payload: &spec.VersionedSubmitBlockRequest{ + Version: consensusspec.DataVersionBellatrix, + Bellatrix: &bellatrix.SubmitBlockRequest{ + Message: &apiv1.BidTrace{}, + ExecutionPayload: &consensusbellatrix.ExecutionPayload{}, + }, + }, + expected: nil, + err: "unsupported version", + }, + { + name: "missing data", + payload: &spec.VersionedSubmitBlockRequest{ + Version: consensusspec.DataVersionCapella, + }, + expected: nil, + err: "no data", + }, + { + name: "missing message", + payload: &spec.VersionedSubmitBlockRequest{ + Version: consensusspec.DataVersionCapella, + Capella: &capella.SubmitBlockRequest{ + ExecutionPayload: &consensuscapella.ExecutionPayload{}, + }, + }, + expected: nil, + err: "no data message", + }, + { + name: "missing execution payload", + payload: &spec.VersionedSubmitBlockRequest{ + Version: consensusspec.DataVersionCapella, + Capella: &capella.SubmitBlockRequest{ + Message: &apiv1.BidTrace{}, + }, + }, + expected: nil, + err: "no data execution payload", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + submission, err := GetBlockSubmissionInfo(tc.payload) + require.Equal(t, tc.expected, submission) + if tc.err == "" { + require.Nil(t, err) + } else { + require.Equal(t, tc.err, err.Error()) + } + }) + } +} diff --git a/database/database.go b/database/database.go index 555da5f7..578ca62a 100644 --- a/database/database.go +++ b/database/database.go @@ -9,10 +9,10 @@ import ( "strings" "time" + apiv1 "github.com/attestantio/go-builder-client/api/v1" "github.com/attestantio/go-builder-client/spec" consensusapi "github.com/attestantio/go-eth2-client/api" consensusspec "github.com/attestantio/go-eth2-client/spec" - "github.com/flashbots/go-boost-utils/types" "github.com/flashbots/mev-boost-relay/common" "github.com/flashbots/mev-boost-relay/database/migrations" "github.com/flashbots/mev-boost-relay/database/vars" @@ -51,7 +51,7 @@ type IDatabaseService interface { IncBlockBuilderStatsAfterGetPayload(builderPubkey string) error InsertBuilderDemotion(submitBlockRequest *spec.VersionedSubmitBlockRequest, simError error) error - UpdateBuilderDemotion(trace *common.BidTraceV2, signedBlock *consensusspec.VersionedSignedBeaconBlock, signedRegistration *types.SignedValidatorRegistration) error + UpdateBuilderDemotion(trace *common.BidTraceV2, signedBlock *consensusspec.VersionedSignedBeaconBlock, signedRegistration *apiv1.SignedValidatorRegistration) error GetBuilderDemotion(trace *common.BidTraceV2) (*BuilderDemotionEntry, error) GetTooLateGetPayload(slot uint64) (entries []*TooLateGetPayloadEntry, err error) @@ -577,7 +577,7 @@ func (s *DatabaseService) InsertBuilderDemotion(submitBlockRequest *spec.Version return err } -func (s *DatabaseService) UpdateBuilderDemotion(trace *common.BidTraceV2, signedBlock *consensusspec.VersionedSignedBeaconBlock, signedRegistration *types.SignedValidatorRegistration) error { +func (s *DatabaseService) UpdateBuilderDemotion(trace *common.BidTraceV2, signedBlock *consensusspec.VersionedSignedBeaconBlock, signedRegistration *apiv1.SignedValidatorRegistration) error { _signedBeaconBlock, err := json.Marshal(signedBlock.Capella) if err != nil { return err diff --git a/database/database_test.go b/database/database_test.go index 2648b325..e457cc32 100644 --- a/database/database_test.go +++ b/database/database_test.go @@ -7,14 +7,13 @@ import ( "testing" "time" - v1 "github.com/attestantio/go-builder-client/api/v1" + apiv1 "github.com/attestantio/go-builder-client/api/v1" "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/bellatrix" consensuscapella "github.com/attestantio/go-eth2-client/spec/capella" "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/flashbots/go-boost-utils/bls" - "github.com/flashbots/go-boost-utils/types" "github.com/flashbots/mev-boost-relay/common" "github.com/flashbots/mev-boost-relay/database/migrations" "github.com/flashbots/mev-boost-relay/database/vars" @@ -28,7 +27,7 @@ const ( collateral = 1000 collateralStr = "1000" builderID = "builder0x69" - randao = "01234567890123456789012345678901" + randao = "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" optimisticSubmission = true ) @@ -77,7 +76,7 @@ func insertTestBuilder(t *testing.T, db IDatabaseService) string { require.NoError(t, err) copy(testBlockHash[:], hashSlice) req := common.TestBuilderSubmitBlockRequest(sk, &common.BidTraceV2{ - BidTrace: v1.BidTrace{ + BidTrace: apiv1.BidTrace{ BlockHash: testBlockHash, Slot: slot, BuilderPubkey: *pk, @@ -299,7 +298,7 @@ func TestInsertBuilderDemotion(t *testing.T) { require.NoError(t, err) copy(testBlockHash[:], hashSlice) trace := &common.BidTraceV2{ - BidTrace: v1.BidTrace{ + BidTrace: apiv1.BidTrace{ BlockHash: testBlockHash, Slot: slot, BuilderPubkey: *pk, @@ -328,7 +327,7 @@ func TestUpdateBuilderDemotion(t *testing.T) { require.NoError(t, err) copy(testBlockHash[:], hashSlice) bt := &common.BidTraceV2{ - BidTrace: v1.BidTrace{ + BidTrace: apiv1.BidTrace{ BlockHash: testBlockHash, Slot: slot, BuilderPubkey: *pk, @@ -360,7 +359,7 @@ func TestUpdateBuilderDemotion(t *testing.T) { bb := &spec.VersionedSignedBeaconBlock{ Capella: &consensuscapella.SignedBeaconBlock{}, } - err = db.UpdateBuilderDemotion(bt, bb, &types.SignedValidatorRegistration{}) + err = db.UpdateBuilderDemotion(bt, bb, &apiv1.SignedValidatorRegistration{}) require.NoError(t, err) // Signed block and validation should now be valid and non-empty. diff --git a/database/mockdb.go b/database/mockdb.go index f2c9c28b..0c332ec4 100644 --- a/database/mockdb.go +++ b/database/mockdb.go @@ -5,10 +5,10 @@ import ( "fmt" "time" + apiv1 "github.com/attestantio/go-builder-client/api/v1" "github.com/attestantio/go-builder-client/spec" consensusapi "github.com/attestantio/go-eth2-client/api" consensusspec "github.com/attestantio/go-eth2-client/spec" - "github.com/flashbots/go-boost-utils/types" "github.com/flashbots/mev-boost-relay/common" ) @@ -165,7 +165,7 @@ func (db MockDB) InsertBuilderDemotion(submitBlockRequest *spec.VersionedSubmitB return nil } -func (db MockDB) UpdateBuilderDemotion(trace *common.BidTraceV2, signedBlock *consensusspec.VersionedSignedBeaconBlock, signedRegistration *types.SignedValidatorRegistration) error { +func (db MockDB) UpdateBuilderDemotion(trace *common.BidTraceV2, signedBlock *consensusspec.VersionedSignedBeaconBlock, signedRegistration *apiv1.SignedValidatorRegistration) error { pubkey := trace.BuilderPubkey.String() _, ok := db.Builders[pubkey] if !ok { diff --git a/database/types.go b/database/types.go index 662e862f..ce1c6e97 100644 --- a/database/types.go +++ b/database/types.go @@ -5,7 +5,8 @@ import ( "fmt" "time" - "github.com/flashbots/go-boost-utils/types" + apiv1 "github.com/attestantio/go-builder-client/api/v1" + "github.com/flashbots/go-boost-utils/utils" ) func NewNullInt64(i int64) sql.NullInt64 { @@ -60,38 +61,38 @@ type ValidatorRegistrationEntry struct { Signature string `db:"signature"` } -func (reg ValidatorRegistrationEntry) ToSignedValidatorRegistration() (*types.SignedValidatorRegistration, error) { - pubkey, err := types.HexToPubkey(reg.Pubkey) +func (reg ValidatorRegistrationEntry) ToSignedValidatorRegistration() (*apiv1.SignedValidatorRegistration, error) { + pubkey, err := utils.HexToPubkey(reg.Pubkey) if err != nil { return nil, err } - feeRec, err := types.HexToAddress(reg.FeeRecipient) + feeRec, err := utils.HexToAddress(reg.FeeRecipient) if err != nil { return nil, err } - sig, err := types.HexToSignature(reg.Signature) + sig, err := utils.HexToSignature(reg.Signature) if err != nil { return nil, err } - return &types.SignedValidatorRegistration{ - Message: &types.RegisterValidatorRequestMessage{ + return &apiv1.SignedValidatorRegistration{ + Message: &apiv1.ValidatorRegistration{ Pubkey: pubkey, FeeRecipient: feeRec, - Timestamp: reg.Timestamp, + Timestamp: time.Unix(int64(reg.Timestamp), 0), GasLimit: reg.GasLimit, }, Signature: sig, }, nil } -func SignedValidatorRegistrationToEntry(valReg types.SignedValidatorRegistration) ValidatorRegistrationEntry { +func SignedValidatorRegistrationToEntry(valReg apiv1.SignedValidatorRegistration) ValidatorRegistrationEntry { return ValidatorRegistrationEntry{ Pubkey: valReg.Message.Pubkey.String(), FeeRecipient: valReg.Message.FeeRecipient.String(), - Timestamp: valReg.Message.Timestamp, + Timestamp: uint64(valReg.Message.Timestamp.Unix()), GasLimit: valReg.Message.GasLimit, Signature: valReg.Signature.String(), } diff --git a/datastore/datastore.go b/datastore/datastore.go index 007e97ae..eccfecb9 100644 --- a/datastore/datastore.go +++ b/datastore/datastore.go @@ -9,8 +9,8 @@ import ( "time" "github.com/attestantio/go-builder-client/api" + apiv1 "github.com/attestantio/go-builder-client/api/v1" "github.com/bradfitz/gomemcache/memcache" - "github.com/flashbots/go-boost-utils/types" "github.com/flashbots/mev-boost-relay/beaconclient" "github.com/flashbots/mev-boost-relay/common" "github.com/flashbots/mev-boost-relay/database" @@ -40,8 +40,8 @@ type Datastore struct { memcached *Memcached db database.IDatabaseService - knownValidatorsByPubkey map[types.PubkeyHex]uint64 - knownValidatorsByIndex map[uint64]types.PubkeyHex + knownValidatorsByPubkey map[common.PubkeyHex]uint64 + knownValidatorsByIndex map[uint64]common.PubkeyHex knownValidatorsLock sync.RWMutex knownValidatorsIsUpdating uberatomic.Bool knownValidatorsLastSlot uberatomic.Uint64 @@ -55,8 +55,8 @@ func NewDatastore(redisCache *RedisCache, memcached *Memcached, db database.IDat db: db, memcached: memcached, redis: redisCache, - knownValidatorsByPubkey: make(map[types.PubkeyHex]uint64), - knownValidatorsByIndex: make(map[uint64]types.PubkeyHex), + knownValidatorsByPubkey: make(map[common.PubkeyHex]uint64), + knownValidatorsByIndex: make(map[uint64]common.PubkeyHex), } return ds, err @@ -130,11 +130,11 @@ func (ds *Datastore) RefreshKnownValidators(log *logrus.Entry, beaconClient beac // At this point, consider the update successful ds.knownValidatorsLastSlot.Store(slot) - knownValidatorsByPubkey := make(map[types.PubkeyHex]uint64) - knownValidatorsByIndex := make(map[uint64]types.PubkeyHex) + knownValidatorsByPubkey := make(map[common.PubkeyHex]uint64) + knownValidatorsByIndex := make(map[uint64]common.PubkeyHex) for _, valEntry := range validators.Data { - pk := types.NewPubkeyHex(valEntry.Validator.Pubkey) + pk := common.NewPubkeyHex(valEntry.Validator.Pubkey) knownValidatorsByPubkey[pk] = valEntry.Index knownValidatorsByIndex[valEntry.Index] = pk } @@ -148,14 +148,14 @@ func (ds *Datastore) RefreshKnownValidators(log *logrus.Entry, beaconClient beac log.Infof("known validators updated") } -func (ds *Datastore) IsKnownValidator(pubkeyHex types.PubkeyHex) bool { +func (ds *Datastore) IsKnownValidator(pubkeyHex common.PubkeyHex) bool { ds.knownValidatorsLock.RLock() defer ds.knownValidatorsLock.RUnlock() _, found := ds.knownValidatorsByPubkey[pubkeyHex] return found } -func (ds *Datastore) GetKnownValidatorPubkeyByIndex(index uint64) (types.PubkeyHex, bool) { +func (ds *Datastore) GetKnownValidatorPubkeyByIndex(index uint64) (common.PubkeyHex, bool) { ds.knownValidatorsLock.RLock() defer ds.knownValidatorsLock.RUnlock() pk, found := ds.knownValidatorsByIndex[index] @@ -173,7 +173,7 @@ func (ds *Datastore) NumRegisteredValidators() (uint64, error) { } // SaveValidatorRegistration saves a validator registration into both Redis and the database -func (ds *Datastore) SaveValidatorRegistration(entry types.SignedValidatorRegistration) error { +func (ds *Datastore) SaveValidatorRegistration(entry apiv1.SignedValidatorRegistration) error { // First save in the database err := ds.db.SaveValidatorRegistration(database.SignedValidatorRegistrationToEntry(entry)) if err != nil { @@ -181,8 +181,8 @@ func (ds *Datastore) SaveValidatorRegistration(entry types.SignedValidatorRegist } // then save in redis - pk := types.NewPubkeyHex(entry.Message.Pubkey.String()) - err = ds.redis.SetValidatorRegistrationTimestampIfNewer(pk, entry.Message.Timestamp) + pk := common.NewPubkeyHex(entry.Message.Pubkey.String()) + err = ds.redis.SetValidatorRegistrationTimestampIfNewer(pk, uint64(entry.Message.Timestamp.Unix())) if err != nil { return errors.Wrap(err, "failed saving validator registration to redis") } diff --git a/datastore/datastore_test.go b/datastore/datastore_test.go index 76f58ca3..d338a95d 100644 --- a/datastore/datastore_test.go +++ b/datastore/datastore_test.go @@ -48,28 +48,3 @@ func TestGetPayloadDatabaseFallback(t *testing.T) { require.NoError(t, err) require.Equal(t, "0x1bafdc454116b605005364976b134d761dd736cb4788d25c835783b46daeb121", payload.Capella.BlockHash.String()) } - -// func TestProdProposerValidatorRegistration(t *testing.T) { -// ds := setupTestDatastore(t) - -// var reg1 types.SignedValidatorRegistration -// err := copier.Copy(®1, &common.ValidPayloadRegisterValidator) -// require.NoError(t, err) - -// key := types.NewPubkeyHex(reg1.Message.Pubkey.String()) - -// // Set known validator and save registration -// err = ds.redis.SetKnownValidator(key, 1) -// require.NoError(t, err) - -// // Check if validator is known -// cnt, err := ds.RefreshKnownValidators() -// require.NoError(t, err) -// require.Equal(t, 1, cnt) -// require.True(t, ds.IsKnownValidator(key)) - -// // Copy the original registration -// var reg2 types.SignedValidatorRegistration -// err = copier.Copy(®2, ®1) -// require.NoError(t, err) -// } diff --git a/datastore/memcached_test.go b/datastore/memcached_test.go index 5bdf8db8..415ed3e8 100644 --- a/datastore/memcached_test.go +++ b/datastore/memcached_test.go @@ -19,6 +19,7 @@ import ( "github.com/ethereum/go-ethereum/common/math" "github.com/flashbots/go-boost-utils/bls" "github.com/flashbots/go-boost-utils/types" + "github.com/flashbots/go-boost-utils/utils" "github.com/flashbots/mev-boost-relay/common" "github.com/holiman/uint256" "github.com/stretchr/testify/require" @@ -54,7 +55,7 @@ func testBuilderSubmitBlockRequest(pubkey phase0.BLSPubKey, signature phase0.BLS FeeRecipient: bellatrix.ExecutionAddress{0x02}, StateRoot: phase0.Root{0x03}, ReceiptsRoot: phase0.Root{0x04}, - LogsBloom: types.Bloom{0x05}, + LogsBloom: [256]byte{0x05}, PrevRandao: phase0.Hash32{0x06}, BlockNumber: 5001, GasLimit: 5002, @@ -123,16 +124,16 @@ func TestMemcached(t *testing.T) { require.NoError(t, err) require.NotNil(t, mem) - builderPk, err := types.HexToPubkey("0xf9716c94aab536227804e859d15207aa7eaaacd839f39dcbdb5adc942842a8d2fb730f9f49fc719fdb86f1873e0ed1c2") + builderPk, err := utils.HexToPubkey("0xf9716c94aab536227804e859d15207aa7eaaacd839f39dcbdb5adc942842a8d2fb730f9f49fc719fdb86f1873e0ed1c2") require.NoError(t, err) - builderSk, err := types.HexToSignature("0x8209b5391cd69f392b1f02dbc03bab61f574bb6bb54bf87b59e2a85bdc0756f7db6a71ce1b41b727a1f46ccc77b213bf0df1426177b5b29926b39956114421eaa36ec4602969f6f6370a44de44a6bce6dae2136e5fb594cce2a476354264d1ea") + builderSk, err := utils.HexToSignature("0x8209b5391cd69f392b1f02dbc03bab61f574bb6bb54bf87b59e2a85bdc0756f7db6a71ce1b41b727a1f46ccc77b213bf0df1426177b5b29926b39956114421eaa36ec4602969f6f6370a44de44a6bce6dae2136e5fb594cce2a476354264d1ea") require.NoError(t, err) testCases := []test{ { Description: "Given an invalid execution payload, we expect an invalid payload error when attempting to create a payload response", - Input: testBuilderSubmitBlockRequest(phase0.BLSPubKey(builderPk), phase0.BLSSignature(builderSk), math.MaxUint64), + Input: testBuilderSubmitBlockRequest(builderPk, builderSk, math.MaxUint64), TestSuite: func(tc *test) func(*testing.T) { return func(t *testing.T) { t.Helper() @@ -145,7 +146,7 @@ func TestMemcached(t *testing.T) { }, { Description: "Given a valid builder submit block request, we expect to successfully store and retrieve the value from memcached", - Input: testBuilderSubmitBlockRequest(phase0.BLSPubKey(builderPk), phase0.BLSSignature(builderSk), consensusspec.DataVersionBellatrix), + Input: testBuilderSubmitBlockRequest(builderPk, builderSk, consensusspec.DataVersionBellatrix), TestSuite: func(tc *test) func(*testing.T) { return func(t *testing.T) { t.Helper() @@ -201,7 +202,7 @@ func TestMemcached(t *testing.T) { }, { Description: "Given a valid builder submit block request, updates to the same key should overwrite existing entry and return the last written value", - Input: testBuilderSubmitBlockRequest(phase0.BLSPubKey(builderPk), phase0.BLSSignature(builderSk), consensusspec.DataVersionBellatrix), + Input: testBuilderSubmitBlockRequest(builderPk, builderSk, consensusspec.DataVersionBellatrix), TestSuite: func(tc *test) func(*testing.T) { return func(t *testing.T) { t.Helper() @@ -238,7 +239,7 @@ func TestMemcached(t *testing.T) { }, { Description: fmt.Sprintf("Given a valid builder submit block request, memcached entry should expire after %d seconds", defaultMemcachedExpirySeconds), - Input: testBuilderSubmitBlockRequest(phase0.BLSPubKey(builderPk), phase0.BLSSignature(builderSk), consensusspec.DataVersionBellatrix), + Input: testBuilderSubmitBlockRequest(builderPk, builderSk, consensusspec.DataVersionBellatrix), TestSuite: func(tc *test) func(*testing.T) { return func(t *testing.T) { t.Helper() @@ -247,10 +248,10 @@ func TestMemcached(t *testing.T) { _, pubkey, err := bls.GenerateNewKeypair() require.NoError(t, err) - pk, err := types.BlsPublicKeyToPublicKey(pubkey) + pk, err := utils.BlsPublicKeyToPublicKey(pubkey) require.NoError(t, err) - tc.Input.Capella.Message.ProposerPubkey = phase0.BLSPubKey(pk) + tc.Input.Capella.Message.ProposerPubkey = pk payload, err := common.GetBlockSubmissionExecutionPayload(&tc.Input) require.NoError( t, diff --git a/datastore/redis.go b/datastore/redis.go index f6a82b41..4e7091dc 100644 --- a/datastore/redis.go +++ b/datastore/redis.go @@ -14,7 +14,6 @@ import ( "github.com/attestantio/go-builder-client/spec" consensusspec "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/capella" - boostTypes "github.com/flashbots/go-boost-utils/types" "github.com/flashbots/go-utils/cli" "github.com/flashbots/mev-boost-relay/common" "github.com/go-redis/redis/v9" @@ -41,10 +40,6 @@ var ( redisWriteTimeoutSec = cli.GetEnvInt("REDIS_WRITE_TIMEOUT_SEC", 0) // 0 means use default (3 seconds) ) -func PubkeyHexToLowerStr(pk boostTypes.PubkeyHex) string { - return strings.ToLower(string(pk)) -} - func connectRedis(redisURI string) (*redis.Client, error) { // Handle both URIs and full URLs, assume unencrypted connections if !strings.HasPrefix(redisURI, "redis://") && !strings.HasPrefix(redisURI, "rediss://") { @@ -230,7 +225,7 @@ func (r *RedisCache) HSetObj(key, field string, value any, expiration time.Durat return r.client.Expire(context.Background(), key, expiration).Err() } -func (r *RedisCache) GetValidatorRegistrationTimestamp(proposerPubkey boostTypes.PubkeyHex) (uint64, error) { +func (r *RedisCache) GetValidatorRegistrationTimestamp(proposerPubkey common.PubkeyHex) (uint64, error) { timestamp, err := r.client.HGet(context.Background(), r.keyValidatorRegistrationTimestamp, strings.ToLower(proposerPubkey.String())).Uint64() if errors.Is(err, redis.Nil) { return 0, nil @@ -238,7 +233,7 @@ func (r *RedisCache) GetValidatorRegistrationTimestamp(proposerPubkey boostTypes return timestamp, err } -func (r *RedisCache) SetValidatorRegistrationTimestampIfNewer(proposerPubkey boostTypes.PubkeyHex, timestamp uint64) error { +func (r *RedisCache) SetValidatorRegistrationTimestampIfNewer(proposerPubkey common.PubkeyHex, timestamp uint64) error { knownTimestamp, err := r.GetValidatorRegistrationTimestamp(proposerPubkey) if err != nil { return err @@ -249,7 +244,7 @@ func (r *RedisCache) SetValidatorRegistrationTimestampIfNewer(proposerPubkey boo return r.SetValidatorRegistrationTimestamp(proposerPubkey, timestamp) } -func (r *RedisCache) SetValidatorRegistrationTimestamp(proposerPubkey boostTypes.PubkeyHex, timestamp uint64) error { +func (r *RedisCache) SetValidatorRegistrationTimestamp(proposerPubkey common.PubkeyHex, timestamp uint64) error { return r.client.HSet(context.Background(), r.keyValidatorRegistrationTimestamp, proposerPubkey.String(), timestamp).Err() } diff --git a/datastore/redis_test.go b/datastore/redis_test.go index a03908c7..7b071587 100644 --- a/datastore/redis_test.go +++ b/datastore/redis_test.go @@ -10,10 +10,11 @@ import ( "github.com/alicebob/miniredis/v2" "github.com/attestantio/go-builder-client/api/capella" - v1 "github.com/attestantio/go-builder-client/api/v1" + apiv1 "github.com/attestantio/go-builder-client/api/v1" "github.com/attestantio/go-builder-client/spec" consensusspec "github.com/attestantio/go-eth2-client/spec" - "github.com/flashbots/go-boost-utils/types" + "github.com/attestantio/go-eth2-client/spec/bellatrix" + "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/flashbots/mev-boost-relay/common" "github.com/go-redis/redis/v9" "github.com/holiman/uint256" @@ -39,17 +40,17 @@ func TestRedisValidatorRegistration(t *testing.T) { t.Run("Can save and get validator registration from cache", func(t *testing.T) { key := common.ValidPayloadRegisterValidator.Message.Pubkey value := common.ValidPayloadRegisterValidator - pkHex := types.NewPubkeyHex(key.String()) - err := cache.SetValidatorRegistrationTimestamp(pkHex, value.Message.Timestamp) + pkHex := common.NewPubkeyHex(key.String()) + err := cache.SetValidatorRegistrationTimestamp(pkHex, uint64(value.Message.Timestamp.Unix())) require.NoError(t, err) - result, err := cache.GetValidatorRegistrationTimestamp(key.PubkeyHex()) + result, err := cache.GetValidatorRegistrationTimestamp(common.NewPubkeyHex(key.String())) require.NoError(t, err) - require.Equal(t, result, value.Message.Timestamp) + require.Equal(t, result, uint64(value.Message.Timestamp.Unix())) }) t.Run("Returns nil if validator registration is not in cache", func(t *testing.T) { - key := types.PublicKey{} - result, err := cache.GetValidatorRegistrationTimestamp(key.PubkeyHex()) + key := phase0.BLSPubKey{} + result, err := cache.GetValidatorRegistrationTimestamp(common.NewPubkeyHex(key.String())) require.NoError(t, err) require.Equal(t, uint64(0), result) }) @@ -58,13 +59,13 @@ func TestRedisValidatorRegistration(t *testing.T) { key := common.ValidPayloadRegisterValidator.Message.Pubkey value := common.ValidPayloadRegisterValidator - pkHex := types.NewPubkeyHex(key.String()) - timestamp := value.Message.Timestamp + pkHex := common.NewPubkeyHex(key.String()) + timestamp := uint64(value.Message.Timestamp.Unix()) err := cache.SetValidatorRegistrationTimestampIfNewer(pkHex, timestamp) require.NoError(t, err) - result, err := cache.GetValidatorRegistrationTimestamp(key.PubkeyHex()) + result, err := cache.GetValidatorRegistrationTimestamp(common.NewPubkeyHex(key.String())) require.NoError(t, err) require.Equal(t, result, timestamp) @@ -72,7 +73,7 @@ func TestRedisValidatorRegistration(t *testing.T) { timestamp2 := timestamp - 10 err = cache.SetValidatorRegistrationTimestampIfNewer(pkHex, timestamp2) require.NoError(t, err) - result, err = cache.GetValidatorRegistrationTimestamp(key.PubkeyHex()) + result, err = cache.GetValidatorRegistrationTimestamp(common.NewPubkeyHex(key.String())) require.NoError(t, err) require.Equal(t, result, timestamp) @@ -80,98 +81,24 @@ func TestRedisValidatorRegistration(t *testing.T) { timestamp3 := timestamp + 10 err = cache.SetValidatorRegistrationTimestampIfNewer(pkHex, timestamp3) require.NoError(t, err) - result, err = cache.GetValidatorRegistrationTimestamp(key.PubkeyHex()) + result, err = cache.GetValidatorRegistrationTimestamp(common.NewPubkeyHex(key.String())) require.NoError(t, err) require.Equal(t, result, timestamp3) }) } -// func TestRedisKnownValidators(t *testing.T) { -// cache := setupTestRedis(t) - -// t.Run("Can save and get known validators", func(t *testing.T) { -// key1 := types.NewPubkeyHex("0x1a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249") -// index1 := uint64(1) -// key2 := types.NewPubkeyHex("0x2a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249") -// index2 := uint64(2) -// require.NoError(t, cache.SetKnownValidator(key1, index1)) -// require.NoError(t, cache.SetKnownValidator(key2, index2)) - -// knownVals, err := cache.GetKnownValidators() -// require.NoError(t, err) -// require.Equal(t, 2, len(knownVals)) -// require.Contains(t, knownVals, index1) -// require.Equal(t, key1, knownVals[index1]) -// require.Contains(t, knownVals, index2) -// require.Equal(t, key2, knownVals[index2]) -// }) - -// t.Run("Can save multi and get known validators", func(t *testing.T) { -// key1 := types.NewPubkeyHex("0x1a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249") -// index1 := uint64(1) -// key2 := types.NewPubkeyHex("0x2a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249") -// index2 := uint64(2) - -// indexPkMap := map[uint64]types.PubkeyHex{index1: key1, index2: key2} -// require.NoError(t, cache.SetMultiKnownValidator(indexPkMap)) - -// knownVals, err := cache.GetKnownValidators() -// require.NoError(t, err) -// require.Equal(t, 2, len(knownVals)) -// require.Contains(t, knownVals, index1) -// require.Equal(t, key1, knownVals[index1]) -// require.Contains(t, knownVals, index2) -// require.Equal(t, key2, knownVals[index2]) -// }) -// } - -// func TestRedisValidatorRegistrations(t *testing.T) { -// cache := setupTestRedis(t) - -// t.Run("Can save and get validator registrations", func(t *testing.T) { -// key1 := types.NewPubkeyHex("0x1a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249") -// // index1 := uint64(1) -// // require.NoError(t, cache.SetKnownValidator(key1, index1)) - -// // knownVals, err := cache.GetKnownValidators() -// // require.NoError(t, err) -// // require.Equal(t, 1, len(knownVals)) -// // require.Contains(t, knownVals, index1) - -// // Create a signed registration for key1 -// // require.NoError(t, err) -// entry := types.SignedValidatorRegistration{ -// Message: &types.RegisterValidatorRequestMessage{ -// FeeRecipient: types.Address{0x02}, -// GasLimit: 5000, -// Timestamp: 0xffffffff, -// Pubkey: key1, -// }, -// Signature: types.Signature{}, -// } - -// pkHex := types.NewPubkeyHex(entry.Message.Pubkey.String()) -// err := cache.SetValidatorRegistrationTimestamp(pkHex, entry.Message.Timestamp) -// require.NoError(t, err) - -// reg, err := cache.GetValidatorRegistrationTimestamp(key1) -// require.NoError(t, err) -// require.Equal(t, uint64(0xffffffff), reg) -// }) -// } - func TestRedisProposerDuties(t *testing.T) { cache := setupTestRedis(t) duties := []common.BuilderGetValidatorsResponseEntry{ { Slot: 1, - Entry: &types.SignedValidatorRegistration{ - Signature: types.Signature{}, - Message: &types.RegisterValidatorRequestMessage{ - FeeRecipient: types.Address{0x02}, + Entry: &apiv1.SignedValidatorRegistration{ + Signature: phase0.BLSSignature{}, + Message: &apiv1.ValidatorRegistration{ + FeeRecipient: bellatrix.ExecutionAddress{0x02}, GasLimit: 5000, - Timestamp: 0xffffffff, - Pubkey: types.PublicKey{}, + Timestamp: time.Unix(0xffffffff, 0), + Pubkey: phase0.BLSPubKey{}, }, }, }, @@ -197,7 +124,7 @@ func TestBuilderBids(t *testing.T) { } trace := &common.BidTraceV2{ - BidTrace: v1.BidTrace{ + BidTrace: apiv1.BidTrace{ Value: uint256.NewInt(123), }, } diff --git a/go.mod b/go.mod index 1c2a80ff..78d80270 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/btcsuite/btcd/btcutil v1.1.2 github.com/buger/jsonparser v1.1.1 github.com/ethereum/go-ethereum v1.13.4 - github.com/flashbots/go-boost-utils v1.6.0 + github.com/flashbots/go-boost-utils v1.7.1-0.20230625230411-8c44018f4777 github.com/flashbots/go-utils v0.5.0 github.com/go-redis/redis/v9 v9.0.0-rc.1 github.com/gorilla/mux v1.8.1 @@ -31,6 +31,8 @@ require ( require ( github.com/DataDog/zstd v1.5.2 // indirect + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/cockroachdb/errors v1.9.1 // indirect @@ -45,10 +47,12 @@ require ( github.com/fatih/color v1.16.0 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect + github.com/go-ole/go-ole v1.2.5 // indirect github.com/goccy/go-yaml v1.11.2 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/uuid v1.3.1 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect @@ -57,6 +61,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.42.0 // indirect @@ -64,7 +69,9 @@ require ( github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/supranational/blst v0.3.11 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect golang.org/x/sync v0.3.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/protobuf v1.30.0 // indirect @@ -72,8 +79,6 @@ require ( ) require ( - github.com/StackExchange/wmi v1.2.1 // indirect - github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect github.com/btcsuite/btcd v0.23.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -83,20 +88,15 @@ require ( github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/ferranbt/fastssz v0.1.3 - github.com/go-ole/go-ole v1.2.5 // indirect github.com/go-stack/stack v1.8.1 // indirect - github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rubenv/sql-migrate v1.5.2 - github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/tdewolff/parse v2.3.4+incompatible // indirect github.com/tdewolff/test v1.0.7 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect @@ -122,6 +122,4 @@ retract ( v1.0.0-alpha1 ) -replace github.com/attestantio/go-eth2-client => github.com/avalonche/go-eth2-client v0.0.0-20230720061256-82081347600e - replace github.com/attestantio/go-builder-client => github.com/avalonche/go-builder-client v0.0.0-20230711071258-c1ca05d6e8b7 diff --git a/go.sum b/go.sum index 84f78e9f..f30052e0 100644 --- a/go.sum +++ b/go.sum @@ -23,10 +23,10 @@ github.com/alicebob/miniredis/v2 v2.31.0/go.mod h1:UB/T2Uztp7MlFSDakaX1sTXUv5CAS github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/attestantio/go-eth2-client v0.19.9 h1:g5LLX3X7cLC0KS0oai/MtxBOZz3U3QPIX5qryYMxgVE= +github.com/attestantio/go-eth2-client v0.19.9/go.mod h1:TTz7YF6w4z6ahvxKiHuGPn6DbQn7gH6HPuWm/DEQeGE= github.com/avalonche/go-builder-client v0.0.0-20230711071258-c1ca05d6e8b7 h1:NQt83tMbCmK2V1OuPUUEIudvi8EeULl3iWG3Ht1bdCk= github.com/avalonche/go-builder-client v0.0.0-20230711071258-c1ca05d6e8b7/go.mod h1:DwesMTOqnCp4u+n3uZ+fWL8wwnSBZVD9VMIVPDR+AZE= -github.com/avalonche/go-eth2-client v0.0.0-20230720061256-82081347600e h1:WhEhbE/udrh+M8MltkFhXy4BCTB+Q3ubinTdTidt10I= -github.com/avalonche/go-eth2-client v0.0.0-20230720061256-82081347600e/go.mod h1:KSVlZSW1A3jUg5H8O89DLtqxgJprRfTtI7k89fLdhu0= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -126,8 +126,8 @@ github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4Nij github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/ferranbt/fastssz v0.1.3 h1:ZI+z3JH05h4kgmFXdHuR1aWYsgrg7o+Fw7/NCzM16Mo= github.com/ferranbt/fastssz v0.1.3/go.mod h1:0Y9TEd/9XuFlh7mskMPfXiI2Dkw4Ddg9EyXt1W7MRvE= -github.com/flashbots/go-boost-utils v1.6.0 h1:XIcPDG6q0Tesh3kcCXyv61ncD/WVYOMCO2OVzPznvMA= -github.com/flashbots/go-boost-utils v1.6.0/go.mod h1:fL9Jc738zFENkbn5HNnVzIfuRcvCO1djlT/ylyT34Zw= +github.com/flashbots/go-boost-utils v1.7.1-0.20230625230411-8c44018f4777 h1:mnwpdE/JW74My5u3Ag1IMX8PgCa7aZwgFNPB20HN/DM= +github.com/flashbots/go-boost-utils v1.7.1-0.20230625230411-8c44018f4777/go.mod h1:Rckma9iiHGuw4PQj/BFV1ddN13lUib4sTfF3QUY40Z8= github.com/flashbots/go-utils v0.5.0 h1:ldjWta9B9//DJU2QcwRbErez3+1aKhSn6EoFc6d5kPY= github.com/flashbots/go-utils v0.5.0/go.mod h1:LauDwifaRdSK0mS5X34GR59pJtUu1T/lOFNdff1BqtI= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= diff --git a/internal/investigations/validator-registration-signature-check/main.go b/internal/investigations/validator-registration-signature-check/main.go index c06555d7..302de147 100644 --- a/internal/investigations/validator-registration-signature-check/main.go +++ b/internal/investigations/validator-registration-signature-check/main.go @@ -6,16 +6,19 @@ package main import ( "fmt" + "time" + apiv1 "github.com/attestantio/go-builder-client/api/v1" "github.com/flashbots/go-boost-utils/bls" - boostTypes "github.com/flashbots/go-boost-utils/types" + "github.com/flashbots/go-boost-utils/ssz" + "github.com/flashbots/go-boost-utils/utils" "github.com/flashbots/mev-boost-relay/common" ) var ( gasLimit = 30000000 feeRecipient = "0xdb65fEd33dc262Fe09D9a2Ba8F80b329BA25f941" - timestamp = 1606824043 + timestamp = int64(1606824043) ) func Perr(err error) { @@ -31,21 +34,21 @@ func main() { sk, pubkey, err := bls.GenerateNewKeypair() Perr(err) - pk, err := boostTypes.BlsPublicKeyToPublicKey(pubkey) + pk, err := utils.BlsPublicKeyToPublicKey(pubkey) Perr(err) // Fill in validator registration details - validatorRegistration := boostTypes.RegisterValidatorRequestMessage{ //nolint:exhaustruct + validatorRegistration := apiv1.ValidatorRegistration{ //nolint:exhaustruct GasLimit: uint64(gasLimit), - Timestamp: uint64(timestamp), + Timestamp: time.Unix(timestamp, 0), } - validatorRegistration.Pubkey, err = boostTypes.HexToPubkey(pk.String()) + validatorRegistration.Pubkey, err = utils.HexToPubkey(pk.String()) Perr(err) - validatorRegistration.FeeRecipient, err = boostTypes.HexToAddress(feeRecipient) + validatorRegistration.FeeRecipient, err = utils.HexToAddress(feeRecipient) Perr(err) - sig, err := boostTypes.SignMessage(&validatorRegistration, mainnetDetails.DomainBuilder, sk) + sig, err := ssz.SignMessage(&validatorRegistration, mainnetDetails.DomainBuilder, sk) Perr(err) fmt.Println("privkey:", sk.String()) fmt.Println("pubkey: ", pk.String()) diff --git a/internal/investigations/validator-registration-signature-check/main_test.go b/internal/investigations/validator-registration-signature-check/main_test.go index d1528d09..a0300fbe 100644 --- a/internal/investigations/validator-registration-signature-check/main_test.go +++ b/internal/investigations/validator-registration-signature-check/main_test.go @@ -2,8 +2,11 @@ package main import ( "testing" + "time" - boostTypes "github.com/flashbots/go-boost-utils/types" + apiv1 "github.com/attestantio/go-builder-client/api/v1" + "github.com/flashbots/go-boost-utils/ssz" + "github.com/flashbots/go-boost-utils/utils" "github.com/flashbots/mev-boost-relay/common" "github.com/stretchr/testify/require" ) @@ -14,29 +17,29 @@ func TestValidatorRegistrationSignature(t *testing.T) { pubkey := "0x84e975405f8691ad7118527ee9ee4ed2e4e8bae973f6e29aa9ca9ee4aea83605ae3536d22acc9aa1af0545064eacf82e" gasLimit := 30000000 feeRecipient := "0xdb65fed33dc262fe09d9a2ba8f80b329ba25f941" - timestamp := 1606824043 + timestamp := int64(1606824043) signature := "0xaf12df007a0c78abb5575067e5f8b089cfcc6227e4a91db7dd8cf517fe86fb944ead859f0781277d9b78c672e4a18c5d06368b603374673cf2007966cece9540f3a1b3f6f9e1bf421d779c4e8010368e6aac134649c7a009210780d401a778a5" // Constructing the object - payload := boostTypes.SignedValidatorRegistration{ - Message: &boostTypes.RegisterValidatorRequestMessage{ + payload := apiv1.SignedValidatorRegistration{ + Message: &apiv1.ValidatorRegistration{ GasLimit: uint64(gasLimit), - Timestamp: uint64(timestamp), + Timestamp: time.Unix(timestamp, 0), }, } var err error - payload.Message.Pubkey, err = boostTypes.HexToPubkey(pubkey) + payload.Message.Pubkey, err = utils.HexToPubkey(pubkey) require.NoError(t, err) - payload.Signature, err = boostTypes.HexToSignature(signature) + payload.Signature, err = utils.HexToSignature(signature) require.NoError(t, err) - payload.Message.FeeRecipient, err = boostTypes.HexToAddress(feeRecipient) + payload.Message.FeeRecipient, err = utils.HexToAddress(feeRecipient) require.NoError(t, err) mainnetDetails, err := common.NewEthNetworkDetails(common.EthNetworkMainnet) require.NoError(t, err) - ok, err := boostTypes.VerifySignature(payload.Message, mainnetDetails.DomainBuilder, payload.Message.Pubkey[:], payload.Signature[:]) + ok, err := ssz.VerifySignature(payload.Message, mainnetDetails.DomainBuilder, payload.Message.Pubkey[:], payload.Signature[:]) require.NoError(t, err) require.True(t, ok) } diff --git a/services/api/optimistic_test.go b/services/api/optimistic_test.go index 6cdcc489..61ebf166 100644 --- a/services/api/optimistic_test.go +++ b/services/api/optimistic_test.go @@ -12,12 +12,12 @@ import ( "time" "github.com/alicebob/miniredis/v2" - v1 "github.com/attestantio/go-builder-client/api/v1" + apiv1 "github.com/attestantio/go-builder-client/api/v1" "github.com/attestantio/go-eth2-client/spec/bellatrix" consensuscapella "github.com/attestantio/go-eth2-client/spec/capella" "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/flashbots/go-boost-utils/bls" - boostTypes "github.com/flashbots/go-boost-utils/types" + "github.com/flashbots/go-boost-utils/utils" "github.com/flashbots/mev-boost-relay/beaconclient" "github.com/flashbots/mev-boost-relay/common" "github.com/flashbots/mev-boost-relay/database" @@ -30,7 +30,7 @@ const ( slot = uint64(41) collateral = 1000 builderID = "builder0x69" - randao = "01234567890123456789012345678901" + randao = "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" emptyHash = "0x0000000000000000000000000000000000000000000000000000000000000000" proposerInd = uint64(987) genesis = 1606824023 @@ -43,7 +43,7 @@ var ( func getTestBidTrace(pubkey phase0.BLSPubKey, value uint64) *common.BidTraceV2 { return &common.BidTraceV2{ - BidTrace: v1.BidTrace{ + BidTrace: apiv1.BidTrace{ Slot: slot, BuilderPubkey: pubkey, ProposerFeeRecipient: feeRecipient, @@ -56,7 +56,7 @@ type blockRequestOpts struct { pubkey phase0.BLSPubKey secretkey *bls.SecretKey blockValue uint64 - domain boostTypes.Domain + domain phase0.Domain } func startTestBackend(t *testing.T) (*phase0.BLSPubKey, *bls.SecretKey, *testBackend) { @@ -66,9 +66,8 @@ func startTestBackend(t *testing.T) (*phase0.BLSPubKey, *bls.SecretKey, *testBac require.NoError(t, err) blsPubkey, err := bls.PublicKeyFromSecretKey(sk) require.NoError(t, err) - pkBytes := blsPubkey.Bytes() - var pubkey phase0.BLSPubKey - copy(pubkey[:], pkBytes[:]) + pubkey, err := utils.BlsPublicKeyToPublicKey(blsPubkey) + require.NoError(t, err) pkStr := pubkey.String() // Setup test backend. @@ -77,11 +76,11 @@ func startTestBackend(t *testing.T) (*phase0.BLSPubKey, *bls.SecretKey, *testBac backend.relay.genesisInfo.Data.GenesisTime = 0 backend.relay.proposerDutiesMap = map[uint64]*common.BuilderGetValidatorsResponseEntry{ slot: { - Entry: &boostTypes.SignedValidatorRegistration{ - Message: &boostTypes.RegisterValidatorRequestMessage{ + Entry: &apiv1.SignedValidatorRegistration{ + Message: &apiv1.ValidatorRegistration{ FeeRecipient: [20]byte(feeRecipient), GasLimit: 5000, - Timestamp: 0xffffffff, + Timestamp: time.Unix(0xffffffff, 0), Pubkey: [48]byte(phase0.BLSPubKey{}), }, }, @@ -125,14 +124,6 @@ func startTestBackend(t *testing.T) (*phase0.BLSPubKey, *bls.SecretKey, *testBac backend.relay.redis = mockRedis backend.relay.db = mockDB - // Prepare redis - // err = backend.relay.redis.SetKnownValidator(boostTypes.NewPubkeyHex(pubkey.String()), proposerInd) - // require.NoError(t, err) - - // count, err := backend.relay.datastore.RefreshKnownValidators() - // require.NoError(t, err) - // require.Equal(t, count, 1) - backend.relay.headSlot.Store(40) return &pubkey, sk, backend } @@ -353,8 +344,8 @@ func TestBuilderApiSubmitNewBlockOptimistic(t *testing.T) { pubkey, secretkey, backend := startTestBackend(t) backend.relay.optimisticSlot.Store(slot) backend.relay.capellaEpoch = 1 - var randaoHash boostTypes.Hash - err := randaoHash.FromSlice([]byte(randao)) + + randaoHash, err := utils.HexToHash(randao) require.NoError(t, err) withRoot, err := ComputeWithdrawalsRoot([]*consensuscapella.Withdrawal{}) require.NoError(t, err) diff --git a/services/api/service.go b/services/api/service.go index ba30a2d0..57c62351 100644 --- a/services/api/service.go +++ b/services/api/service.go @@ -22,6 +22,7 @@ import ( "github.com/NYTimes/gziphandler" builderCapella "github.com/attestantio/go-builder-client/api/capella" + apiv1 "github.com/attestantio/go-builder-client/api/v1" "github.com/attestantio/go-builder-client/spec" consensusapi "github.com/attestantio/go-eth2-client/api" "github.com/attestantio/go-eth2-client/api/v1/capella" @@ -29,7 +30,8 @@ import ( "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/buger/jsonparser" "github.com/flashbots/go-boost-utils/bls" - boostTypes "github.com/flashbots/go-boost-utils/types" + "github.com/flashbots/go-boost-utils/ssz" + "github.com/flashbots/go-boost-utils/utils" "github.com/flashbots/go-utils/cli" "github.com/flashbots/go-utils/httplogger" "github.com/flashbots/mev-boost-relay/beaconclient" @@ -170,7 +172,7 @@ type RelayAPI struct { log *logrus.Entry blsSk *bls.SecretKey - publicKey *boostTypes.PublicKey + publicKey *phase0.BLSPubKey srv *http.Server srvStarted uberatomic.Bool @@ -195,7 +197,7 @@ type RelayAPI struct { blockSimRateLimiter IBlockSimRateLimiter - validatorRegC chan boostTypes.SignedValidatorRegistration + validatorRegC chan apiv1.SignedValidatorRegistration // used to wait on any active getPayload calls on shutdown getPayloadCallsInFlight sync.WaitGroup @@ -237,7 +239,7 @@ func NewRelayAPI(opts RelayAPIOpts) (api *RelayAPI, err error) { } // If block-builder API is enabled, then ensure secret key is all set - var publicKey boostTypes.PublicKey + var publicKey phase0.BLSPubKey if opts.BlockBuilderAPI { if opts.SecretKey == nil { return nil, ErrBuilderAPIWithoutSecretKey @@ -248,7 +250,7 @@ func NewRelayAPI(opts RelayAPIOpts) (api *RelayAPI, err error) { if err != nil { return nil, err } - publicKey, err = boostTypes.BlsPublicKeyToPublicKey(blsPubkey) + publicKey, err = utils.BlsPublicKeyToPublicKey(blsPubkey) if err != nil { return nil, err } @@ -284,7 +286,7 @@ func NewRelayAPI(opts RelayAPIOpts) (api *RelayAPI, err error) { proposerDutiesResponse: &[]byte{}, blockSimRateLimiter: NewBlockSimulationRateLimiter(opts.BlockSimURL), - validatorRegC: make(chan boostTypes.SignedValidatorRegistration, 450_000), + validatorRegC: make(chan apiv1.SignedValidatorRegistration, 450_000), } if os.Getenv("FORCE_GET_HEADER_204") == "1" { @@ -910,14 +912,14 @@ func (api *RelayAPI) handleRegisterValidator(w http.ResponseWriter, req *http.Re } req.Body.Close() - parseRegistration := func(value []byte) (reg *boostTypes.SignedValidatorRegistration, err error) { + parseRegistration := func(value []byte) (reg *apiv1.SignedValidatorRegistration, err error) { // Pubkey _pubkey, err := jsonparser.GetUnsafeString(value, "message", "pubkey") if err != nil { return nil, fmt.Errorf("registration message error (pubkey): %w", err) } - pubkey, err := boostTypes.HexToPubkey(_pubkey) + pubkey, err := utils.HexToPubkey(_pubkey) if err != nil { return nil, fmt.Errorf("registration message error (pubkey): %w", err) } @@ -928,10 +930,13 @@ func (api *RelayAPI) handleRegisterValidator(w http.ResponseWriter, req *http.Re return nil, fmt.Errorf("registration message error (timestamp): %w", err) } - timestamp, err := strconv.ParseUint(_timestamp, 10, 64) + timestamp, err := strconv.ParseInt(_timestamp, 10, 64) if err != nil { return nil, fmt.Errorf("invalid timestamp: %w", err) } + if timestamp < 0 { + return nil, ErrNegativeTimestamp + } // GasLimit _gasLimit, err := jsonparser.GetUnsafeString(value, "message", "gas_limit") @@ -950,7 +955,7 @@ func (api *RelayAPI) handleRegisterValidator(w http.ResponseWriter, req *http.Re return nil, fmt.Errorf("registration message error (fee_recipient): %w", err) } - feeRecipient, err := boostTypes.HexToAddress(_feeRecipient) + feeRecipient, err := utils.HexToAddress(_feeRecipient) if err != nil { return nil, fmt.Errorf("registration message error (fee_recipient): %w", err) } @@ -961,17 +966,17 @@ func (api *RelayAPI) handleRegisterValidator(w http.ResponseWriter, req *http.Re return nil, fmt.Errorf("registration message error (signature): %w", err) } - signature, err := boostTypes.HexToSignature(_signature) + signature, err := utils.HexToSignature(_signature) if err != nil { return nil, fmt.Errorf("registration message error (signature): %w", err) } // Construct and return full registration object - reg = &boostTypes.SignedValidatorRegistration{ - Message: &boostTypes.RegisterValidatorRequestMessage{ + reg = &apiv1.SignedValidatorRegistration{ + Message: &apiv1.ValidatorRegistration{ FeeRecipient: feeRecipient, GasLimit: gasLimit, - Timestamp: timestamp, + Timestamp: time.Unix(timestamp, 0), Pubkey: pubkey, }, Signature: signature, @@ -1000,7 +1005,7 @@ func (api *RelayAPI) handleRegisterValidator(w http.ResponseWriter, req *http.Re } // Add validator pubkey to logs - pkHex := signedValidatorRegistration.Message.Pubkey.PubkeyHex() + pkHex := common.PubkeyHex(signedValidatorRegistration.Message.Pubkey.String()) regLog = regLog.WithFields(logrus.Fields{ "pubkey": pkHex, "signature": signedValidatorRegistration.Signature.String(), @@ -1010,7 +1015,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 := int64(signedValidatorRegistration.Message.Timestamp) + registrationTimestamp := signedValidatorRegistration.Message.Timestamp.Unix() if registrationTimestamp < int64(api.genesisInfo.Data.GenesisTime) { handleError(regLog, http.StatusBadRequest, "timestamp too early") return @@ -1022,7 +1027,7 @@ func (api *RelayAPI) handleRegisterValidator(w http.ResponseWriter, req *http.Re // Check if a real validator isKnownValidator := api.datastore.IsKnownValidator(pkHex) if !isKnownValidator { - handleError(regLog, http.StatusBadRequest, fmt.Sprintf("not a known validator: %s", pkHex.String())) + handleError(regLog, http.StatusBadRequest, fmt.Sprintf("not a known validator: %s", pkHex)) return } @@ -1030,13 +1035,13 @@ 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 >= signedValidatorRegistration.Message.Timestamp { + } else if prevTimestamp >= uint64(signedValidatorRegistration.Message.Timestamp.Unix()) { // abort if the current registration timestamp is older or equal to the last known one return } // Verify the signature - ok, err := boostTypes.VerifySignature(signedValidatorRegistration.Message, api.opts.EthNetDetails.DomainBuilder, signedValidatorRegistration.Message.Pubkey[:], signedValidatorRegistration.Signature[:]) + ok, err := ssz.VerifySignature(signedValidatorRegistration.Message, api.opts.EthNetDetails.DomainBuilder, signedValidatorRegistration.Message.Pubkey[:], signedValidatorRegistration.Signature[:]) if err != nil { regLog.WithError(err).Error("error verifying registerValidator signature") return @@ -1241,7 +1246,7 @@ func (api *RelayAPI) handleGetPayload(w http.ResponseWriter, req *http.Request) log.WithError(err).Warn("failed to get payload slot") api.RespondError(w, http.StatusBadRequest, "failed to get payload slot") } - blockHash, err := payload.BlockHash() + blockHash, err := payload.ExecutionBlockHash() if err != nil { log.WithError(err).Warn("failed to get payload block hash") api.RespondError(w, http.StatusBadRequest, "failed to get payload block hash") @@ -1290,10 +1295,10 @@ func (api *RelayAPI) handleGetPayload(w http.ResponseWriter, req *http.Request) log = log.WithField("proposerPubkey", proposerPubkey.String()) // Create a BLS pubkey from the hex pubkey - pk, err := boostTypes.HexToPubkey(proposerPubkey.String()) + pk, err := utils.HexToPubkey(proposerPubkey.String()) if err != nil { - log.WithError(err).Warn("could not convert pubkey to types.PublicKey") - api.RespondError(w, http.StatusBadRequest, "could not convert pubkey to types.PublicKey") + log.WithError(err).Warn("could not convert pubkey to phase0.BLSPubKey") + api.RespondError(w, http.StatusBadRequest, "could not convert pubkey to phase0.BLSPubKey") return } @@ -1501,7 +1506,7 @@ func (api *RelayAPI) handleGetPayload(w http.ResponseWriter, req *http.Request) // respond to the HTTP request api.RespondOK(w, getPayloadResp) - blockNumber, err := payload.BlockNumber() + blockNumber, err := payload.ExecutionBlockNumber() if err != nil { log.WithError(err).Info("failed to get block number") } @@ -1891,7 +1896,7 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque // Verify the signature log = log.WithField("timestampBeforeSignatureCheck", time.Now().UTC().UnixMilli()) signature := submission.Signature - ok, err = boostTypes.VerifySignature(submission.BidTrace, api.opts.EthNetDetails.DomainBuilder, builderPubkey[:], signature[:]) + ok, err = ssz.VerifySignature(submission.BidTrace, api.opts.EthNetDetails.DomainBuilder, builderPubkey[:], signature[:]) log = log.WithField("timestampAfterSignatureCheck", time.Now().UTC().UnixMilli()) if err != nil { log.WithError(err).Warn("failed verifying builder signature") @@ -1984,7 +1989,7 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque builder: builderEntry, req: &common.BuilderBlockValidationRequest{ VersionedSubmitBlockRequest: *payload, - RegisteredGasLimit: gasLimit, + RegisteredGasLimit: gasLimit, }, } // With sufficient collateral, process the block optimistically. @@ -2207,8 +2212,7 @@ func (api *RelayAPI) handleDataProposerPayloadDelivered(w http.ResponseWriter, r } if args.Get("block_hash") != "" { - var hash boostTypes.Hash - err = hash.UnmarshalText([]byte(args.Get("block_hash"))) + _, err := utils.HexToHash(args.Get("block_hash")) if err != nil { api.RespondError(w, http.StatusBadRequest, "invalid block_hash argument") return @@ -2300,8 +2304,7 @@ func (api *RelayAPI) handleDataBuilderBidsReceived(w http.ResponseWriter, req *h } if args.Get("block_hash") != "" { - var hash boostTypes.Hash - err = hash.UnmarshalText([]byte(args.Get("block_hash"))) + _, err := utils.HexToHash(args.Get("block_hash")) if err != nil { api.RespondError(w, http.StatusBadRequest, "invalid block_hash argument") return @@ -2366,8 +2369,7 @@ func (api *RelayAPI) handleDataValidatorRegistration(w http.ResponseWriter, req return } - var pk boostTypes.PublicKey - err := pk.UnmarshalText([]byte(pkStr)) + _, err := utils.HexToPubkey(pkStr) if err != nil { api.RespondError(w, http.StatusBadRequest, "invalid pubkey") return diff --git a/services/api/service_test.go b/services/api/service_test.go index 0a0a8d0a..553e1c5b 100644 --- a/services/api/service_test.go +++ b/services/api/service_test.go @@ -13,15 +13,14 @@ import ( "github.com/alicebob/miniredis/v2" builderCapella "github.com/attestantio/go-builder-client/api/capella" - v1 "github.com/attestantio/go-builder-client/api/v1" + apiv1 "github.com/attestantio/go-builder-client/api/v1" "github.com/attestantio/go-builder-client/spec" consensusspec "github.com/attestantio/go-eth2-client/spec" "github.com/attestantio/go-eth2-client/spec/bellatrix" "github.com/attestantio/go-eth2-client/spec/capella" "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/flashbots/go-boost-utils/bls" - "github.com/flashbots/go-boost-utils/types" + "github.com/flashbots/go-boost-utils/utils" "github.com/flashbots/mev-boost-relay/beaconclient" "github.com/flashbots/mev-boost-relay/common" "github.com/flashbots/mev-boost-relay/database" @@ -41,9 +40,8 @@ const ( ) var ( - builderSigningDomain = types.Domain([32]byte{0, 0, 0, 1, 245, 165, 253, 66, 209, 106, 32, 48, 39, 152, 239, 110, 211, 9, 151, 155, 67, 0, 61, 35, 32, 217, 240, 232, 234, 152, 49, 169}) - testAddress = types.Address([20]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}) - testAddress2 = types.Address([20]byte{1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}) + testAddress = bellatrix.ExecutionAddress([20]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}) + testAddress2 = bellatrix.ExecutionAddress([20]byte{1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}) ) type testBackend struct { @@ -160,40 +158,6 @@ func (be *testBackend) requestWithUA(method, path, userAgent string, payload any return rr } -// func generateSignedValidatorRegistration(sk *bls.SecretKey, feeRecipient types.Address, timestamp uint64) (*types.SignedValidatorRegistration, error) { -// var err error -// if sk == nil { -// sk, _, err = bls.GenerateNewKeypair() -// if err != nil { -// return nil, err -// } -// } - -// blsPubKey, _ := bls.PublicKeyFromSecretKey(sk) - -// var pubKey types.PublicKey -// err = pubKey.FromSlice(bls.PublicKeyToBytes(blsPubKey)) -// if err != nil { -// return nil, err -// } -// msg := &types.RegisterValidatorRequestMessage{ -// FeeRecipient: feeRecipient, -// Timestamp: timestamp, -// Pubkey: pubKey, -// GasLimit: 278234191203, -// } - -// sig, err := types.SignMessage(msg, builderSigningDomain, sk) -// if err != nil { -// return nil, err -// } - -// return &types.SignedValidatorRegistration{ -// Message: msg, -// Signature: sig, -// }, nil -// } - func TestWebserver(t *testing.T) { t.Run("errors when webserver is already existing", func(t *testing.T) { backend := newTestBackend(t, 1) @@ -227,65 +191,12 @@ func TestLivez(t *testing.T) { func TestRegisterValidator(t *testing.T) { path := "/eth/v1/builder/validators" - // t.Run("Normal function", func(t *testing.T) { - // backend := newTestBackend(t, 1) - // pubkeyHex := common.ValidPayloadRegisterValidator.Message.Pubkey.PubkeyHex() - // index := uint64(17) - // err := backend.redis.SetKnownValidator(pubkeyHex, index) - // require.NoError(t, err) - - // // Update datastore - // _, err = backend.datastore.RefreshKnownValidators() - // require.NoError(t, err) - // require.True(t, backend.datastore.IsKnownValidator(pubkeyHex)) - // pkH, ok := backend.datastore.GetKnownValidatorPubkeyByIndex(index) - // require.True(t, ok) - // require.Equal(t, pubkeyHex, pkH) - - // payload := []types.SignedValidatorRegistration{common.ValidPayloadRegisterValidator} - // rr := backend.request(http.MethodPost, path, payload) - // require.Equal(t, http.StatusOK, rr.Code) - // time.Sleep(20 * time.Millisecond) // registrations are processed asynchronously - - // isKnown := backend.datastore.IsKnownValidator(pubkeyHex) - // require.True(t, isKnown) - // }) - t.Run("not a known validator", func(t *testing.T) { backend := newTestBackend(t, 1) - rr := backend.request(http.MethodPost, path, []types.SignedValidatorRegistration{common.ValidPayloadRegisterValidator}) + rr := backend.request(http.MethodPost, path, []apiv1.SignedValidatorRegistration{common.ValidPayloadRegisterValidator}) require.Equal(t, http.StatusBadRequest, rr.Code) }) - - // t.Run("Reject registration for >10sec into the future", func(t *testing.T) { - // backend := newTestBackend(t, 1) - - // // Allow +10 sec - // td := uint64(time.Now().Unix()) - // payload, err := generateSignedValidatorRegistration(nil, types.Address{1}, td+10) - // require.NoError(t, err) - // err = backend.redis.SetKnownValidator(payload.Message.Pubkey.PubkeyHex(), 1) - // require.NoError(t, err) - // _, err = backend.datastore.RefreshKnownValidators() - // require.NoError(t, err) - - // rr := backend.request(http.MethodPost, path, []types.SignedValidatorRegistration{*payload}) - // require.Equal(t, http.StatusOK, rr.Code, rr.Body.String()) - - // // Disallow +11 sec - // td = uint64(time.Now().Unix()) - // payload, err = generateSignedValidatorRegistration(nil, types.Address{1}, td+12) - // require.NoError(t, err) - // err = backend.redis.SetKnownValidator(payload.Message.Pubkey.PubkeyHex(), 1) - // require.NoError(t, err) - // _, err = backend.datastore.RefreshKnownValidators() - // require.NoError(t, err) - - // rr = backend.request(http.MethodPost, path, []types.SignedValidatorRegistration{*payload}) - // require.Equal(t, http.StatusBadRequest, rr.Code) - // require.Contains(t, rr.Body.String(), "timestamp too far in the future") - // }) } func TestGetHeader(t *testing.T) { @@ -305,7 +216,7 @@ func TestGetHeader(t *testing.T) { builderPubkey := "0xfa1ed37c3553d0ce1e9349b2c5063cf6e394d231c8d3e0df75e9462257c081543086109ffddaacc0aa76f33dc9661c83" bidValue := uint256.NewInt(99) trace := &common.BidTraceV2{ - BidTrace: v1.BidTrace{ + BidTrace: apiv1.BidTrace{ Value: bidValue, }, } @@ -424,10 +335,9 @@ func TestBuilderSubmitBlock(t *testing.T) { // Payload attributes payloadJSONFilename := "../../testdata/submitBlockPayloadCapella_Goerli.json.gz" parentHash := "0xbd3291854dc822b7ec585925cda0e18f06af28fa2886e15f52d52dd4b6f94ed6" - feeRec, err := types.HexToAddress("0x5cc0dde14e7256340cc820415a6022a7d1c93a35") + feeRec, err := utils.HexToAddress("0x5cc0dde14e7256340cc820415a6022a7d1c93a35") require.NoError(t, err) - var withdrawalsRoot types.Hash - err = withdrawalsRoot.UnmarshalText([]byte("0xb15ed76298ff84a586b1d875df08b6676c98dfe9c7cd73fab88450348d8e70c8")) + withdrawalsRoot, err := utils.HexToHash("0xb15ed76298ff84a586b1d875df08b6676c98dfe9c7cd73fab88450348d8e70c8") require.NoError(t, err) prevRandao := "0x9962816e9d0a39fd4c80935338a741dc916d1545694e41eb5a505e1a3098f9e4" @@ -438,8 +348,8 @@ func TestBuilderSubmitBlock(t *testing.T) { backend.relay.proposerDutiesMap = make(map[uint64]*common.BuilderGetValidatorsResponseEntry) backend.relay.proposerDutiesMap[headSlot+1] = &common.BuilderGetValidatorsResponseEntry{ Slot: headSlot, - Entry: &types.SignedValidatorRegistration{ - Message: &types.RegisterValidatorRequestMessage{ + Entry: &apiv1.SignedValidatorRegistration{ + Message: &apiv1.ValidatorRegistration{ FeeRecipient: feeRec, }, }, @@ -521,8 +431,8 @@ func TestCheckSubmissionFeeRecipient(t *testing.T) { { description: "success", slotDuty: &common.BuilderGetValidatorsResponseEntry{ - Entry: &types.SignedValidatorRegistration{ - Message: &types.RegisterValidatorRequestMessage{ + Entry: &apiv1.SignedValidatorRegistration{ + Message: &apiv1.ValidatorRegistration{ FeeRecipient: testAddress, GasLimit: testGasLimit, }, @@ -531,10 +441,11 @@ func TestCheckSubmissionFeeRecipient(t *testing.T) { payload: &spec.VersionedSubmitBlockRequest{ Version: consensusspec.DataVersionCapella, Capella: &builderCapella.SubmitBlockRequest{ - Message: &v1.BidTrace{ + Message: &apiv1.BidTrace{ Slot: testSlot, - ProposerFeeRecipient: bellatrix.ExecutionAddress(testAddress), + ProposerFeeRecipient: testAddress, }, + ExecutionPayload: &capella.ExecutionPayload{}, }, }, expectOk: true, @@ -546,9 +457,10 @@ func TestCheckSubmissionFeeRecipient(t *testing.T) { payload: &spec.VersionedSubmitBlockRequest{ Version: consensusspec.DataVersionCapella, Capella: &builderCapella.SubmitBlockRequest{ - Message: &v1.BidTrace{ + Message: &apiv1.BidTrace{ Slot: testSlot, }, + ExecutionPayload: &capella.ExecutionPayload{}, }, }, expectOk: false, @@ -557,8 +469,8 @@ func TestCheckSubmissionFeeRecipient(t *testing.T) { { description: "failure_diff_fee_recipient", slotDuty: &common.BuilderGetValidatorsResponseEntry{ - Entry: &types.SignedValidatorRegistration{ - Message: &types.RegisterValidatorRequestMessage{ + Entry: &apiv1.SignedValidatorRegistration{ + Message: &apiv1.ValidatorRegistration{ FeeRecipient: testAddress, GasLimit: testGasLimit, }, @@ -567,10 +479,11 @@ func TestCheckSubmissionFeeRecipient(t *testing.T) { payload: &spec.VersionedSubmitBlockRequest{ Version: consensusspec.DataVersionCapella, Capella: &builderCapella.SubmitBlockRequest{ - Message: &v1.BidTrace{ + Message: &apiv1.BidTrace{ Slot: testSlot, - ProposerFeeRecipient: bellatrix.ExecutionAddress(testAddress2), + ProposerFeeRecipient: testAddress2, }, + ExecutionPayload: &capella.ExecutionPayload{}, }, }, expectOk: false, @@ -599,11 +512,11 @@ func TestCheckSubmissionFeeRecipient(t *testing.T) { } func TestCheckSubmissionPayloadAttrs(t *testing.T) { - withdrawalsRoot, err := hexutil.Decode(testWithdrawalsRoot) + withdrawalsRoot, err := utils.HexToHash(testWithdrawalsRoot) require.NoError(t, err) - prevRandao, err := hexutil.Decode(testPrevRandao) + prevRandao, err := utils.HexToHash(testPrevRandao) require.NoError(t, err) - parentHash, err := hexutil.Decode(testParentHash) + parentHash, err := utils.HexToHash(testParentHash) require.NoError(t, err) cases := []struct { @@ -617,7 +530,7 @@ func TestCheckSubmissionPayloadAttrs(t *testing.T) { attrs: payloadAttributesHelper{ slot: testSlot, parentHash: testParentHash, - withdrawalsRoot: withdrawalsRoot, + withdrawalsRoot: phase0.Root(withdrawalsRoot), payloadAttributes: beaconclient.PayloadAttributes{ PrevRandao: testPrevRandao, }, @@ -626,16 +539,16 @@ func TestCheckSubmissionPayloadAttrs(t *testing.T) { Version: consensusspec.DataVersionCapella, Capella: &builderCapella.SubmitBlockRequest{ ExecutionPayload: &capella.ExecutionPayload{ - PrevRandao: [32]byte(prevRandao), + PrevRandao: prevRandao, Withdrawals: []*capella.Withdrawal{ { Index: 989694, }, }, }, - Message: &v1.BidTrace{ + Message: &apiv1.BidTrace{ Slot: testSlot, - ParentHash: phase0.Hash32(parentHash), + ParentHash: parentHash, }, }, }, @@ -647,10 +560,12 @@ func TestCheckSubmissionPayloadAttrs(t *testing.T) { slot: testSlot, }, payload: &spec.VersionedSubmitBlockRequest{ + Version: consensusspec.DataVersionCapella, Capella: &builderCapella.SubmitBlockRequest{ - Message: &v1.BidTrace{ + Message: &apiv1.BidTrace{ Slot: testSlot + 1, // submission for a future slot }, + ExecutionPayload: &capella.ExecutionPayload{}, }, }, expectOk: false, @@ -664,10 +579,11 @@ func TestCheckSubmissionPayloadAttrs(t *testing.T) { }, }, payload: &spec.VersionedSubmitBlockRequest{ + Version: consensusspec.DataVersionCapella, Capella: &builderCapella.SubmitBlockRequest{ - Message: &v1.BidTrace{ + Message: &apiv1.BidTrace{ Slot: testSlot, - ParentHash: phase0.Hash32(parentHash), + ParentHash: parentHash, }, ExecutionPayload: &capella.ExecutionPayload{ PrevRandao: [32]byte(parentHash), // use a different hash to cause an error @@ -685,10 +601,11 @@ func TestCheckSubmissionPayloadAttrs(t *testing.T) { }, }, payload: &spec.VersionedSubmitBlockRequest{ + Version: consensusspec.DataVersionCapella, Capella: &builderCapella.SubmitBlockRequest{ - Message: &v1.BidTrace{ + Message: &apiv1.BidTrace{ Slot: testSlot, - ParentHash: phase0.Hash32(parentHash), + ParentHash: parentHash, }, ExecutionPayload: &capella.ExecutionPayload{ PrevRandao: [32]byte(prevRandao), @@ -709,6 +626,7 @@ func TestCheckSubmissionPayloadAttrs(t *testing.T) { }, }, payload: &spec.VersionedSubmitBlockRequest{ + Version: consensusspec.DataVersionCapella, Capella: &builderCapella.SubmitBlockRequest{ ExecutionPayload: &capella.ExecutionPayload{ PrevRandao: [32]byte(prevRandao), @@ -718,9 +636,9 @@ func TestCheckSubmissionPayloadAttrs(t *testing.T) { }, }, }, - Message: &v1.BidTrace{ + Message: &apiv1.BidTrace{ Slot: testSlot, - ParentHash: phase0.Hash32(parentHash), + ParentHash: parentHash, }, }, }, @@ -749,36 +667,32 @@ func TestCheckSubmissionSlotDetails(t *testing.T) { cases := []struct { description string payload *spec.VersionedSubmitBlockRequest - expectOk bool + expectOk bool }{ { description: "success", payload: &spec.VersionedSubmitBlockRequest{ + Version: consensusspec.DataVersionCapella, Capella: &builderCapella.SubmitBlockRequest{ ExecutionPayload: &capella.ExecutionPayload{ Timestamp: testSlot * common.SecondsPerSlot, }, - Message: &v1.BidTrace{ + Message: &apiv1.BidTrace{ Slot: testSlot, }, }, }, expectOk: true, }, - { - description: "failure_nil_capella", - payload: &spec.VersionedSubmitBlockRequest{ - Capella: nil, // nil to cause error - }, - expectOk: false, - }, { description: "failure_past_slot", payload: &spec.VersionedSubmitBlockRequest{ + Version: consensusspec.DataVersionCapella, Capella: &builderCapella.SubmitBlockRequest{ - Message: &v1.BidTrace{ + Message: &apiv1.BidTrace{ Slot: testSlot - 1, // use old slot to cause error }, + ExecutionPayload: &capella.ExecutionPayload{}, }, }, expectOk: false, @@ -786,11 +700,12 @@ func TestCheckSubmissionSlotDetails(t *testing.T) { { description: "failure_wrong_timestamp", payload: &spec.VersionedSubmitBlockRequest{ + Version: consensusspec.DataVersionCapella, Capella: &builderCapella.SubmitBlockRequest{ ExecutionPayload: &capella.ExecutionPayload{ Timestamp: testSlot*common.SecondsPerSlot - 1, // use wrong timestamp to cause error }, - Message: &v1.BidTrace{ + Message: &apiv1.BidTrace{ Slot: testSlot, }, }, @@ -815,9 +730,8 @@ func TestCheckSubmissionSlotDetails(t *testing.T) { } func TestCheckBuilderEntry(t *testing.T) { - builderPubkeyByte, err := hexutil.Decode(testBuilderPubkey) + builderPubkey, err := utils.HexToPubkey(testBuilderPubkey) require.NoError(t, err) - builderPubkey := phase0.BLSPubKey(builderPubkeyByte) diffPubkey := builderPubkey diffPubkey[0] = 0xff cases := []struct { diff --git a/services/api/types_test.go b/services/api/types_test.go index 08ceb132..ffb36775 100644 --- a/services/api/types_test.go +++ b/services/api/types_test.go @@ -3,45 +3,52 @@ package api import ( "testing" - "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/attestantio/go-builder-client/api/capella" + apiv1 "github.com/attestantio/go-builder-client/api/v1" + "github.com/attestantio/go-eth2-client/spec/bellatrix" + capellaspec "github.com/attestantio/go-eth2-client/spec/capella" + "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/flashbots/go-boost-utils/bls" + "github.com/flashbots/go-boost-utils/ssz" "github.com/flashbots/go-boost-utils/types" + "github.com/flashbots/go-boost-utils/utils" "github.com/flashbots/mev-boost-relay/common" + "github.com/holiman/uint256" "github.com/stretchr/testify/require" ) -func TestBuilderBlockRequestToSignedBuilderBid(t *testing.T) { - builderPk, err := types.HexToPubkey("0xf9716c94aab536227804e859d15207aa7eaaacd839f39dcbdb5adc942842a8d2fb730f9f49fc719fdb86f1873e0ed1c2") +func TestCapellaBuilderBlockRequestToSignedBuilderBid(t *testing.T) { + builderPk, err := utils.HexToPubkey("0xf9716c94aab536227804e859d15207aa7eaaacd839f39dcbdb5adc942842a8d2fb730f9f49fc719fdb86f1873e0ed1c2") require.NoError(t, err) - builderSk, err := types.HexToSignature("0x8209b5391cd69f392b1f02dbc03bab61f574bb6bb54bf87b59e2a85bdc0756f7db6a71ce1b41b727a1f46ccc77b213bf0df1426177b5b29926b39956114421eaa36ec4602969f6f6370a44de44a6bce6dae2136e5fb594cce2a476354264d1ea") + builderSk, err := utils.HexToSignature("0x8209b5391cd69f392b1f02dbc03bab61f574bb6bb54bf87b59e2a85bdc0756f7db6a71ce1b41b727a1f46ccc77b213bf0df1426177b5b29926b39956114421eaa36ec4602969f6f6370a44de44a6bce6dae2136e5fb594cce2a476354264d1ea") require.NoError(t, err) - reqPayload := types.BuilderSubmitBlockRequest{ - ExecutionPayload: &types.ExecutionPayload{ - ParentHash: types.Hash{0x01}, - FeeRecipient: types.Address{0x02}, - StateRoot: types.Root{0x03}, - ReceiptsRoot: types.Root{0x04}, - LogsBloom: types.Bloom{0x05}, - Random: types.Hash{0x06}, + reqPayload := capella.SubmitBlockRequest{ + ExecutionPayload: &capellaspec.ExecutionPayload{ + ParentHash: phase0.Hash32{0x01}, + FeeRecipient: bellatrix.ExecutionAddress{0x02}, + StateRoot: phase0.Root{0x03}, + ReceiptsRoot: phase0.Root{0x04}, + LogsBloom: [256]byte{0x05}, + PrevRandao: phase0.Hash32{0x06}, BlockNumber: 5001, GasLimit: 5002, GasUsed: 5003, Timestamp: 5004, ExtraData: []byte{0x07}, BaseFeePerGas: types.IntToU256(123), - BlockHash: types.Hash{0x09}, - Transactions: []hexutil.Bytes{}, + BlockHash: phase0.Hash32{0x09}, + Transactions: []bellatrix.Transaction{}, }, - Message: &types.BidTrace{ + Message: &apiv1.BidTrace{ Slot: 1, - ParentHash: types.Hash{0x01}, - BlockHash: types.Hash{0x09}, + ParentHash: phase0.Hash32{0x01}, + BlockHash: phase0.Hash32{0x09}, BuilderPubkey: builderPk, - ProposerPubkey: types.PublicKey{0x03}, - ProposerFeeRecipient: types.Address{0x04}, - Value: types.IntToU256(123), + ProposerPubkey: phase0.BLSPubKey{0x03}, + ProposerFeeRecipient: bellatrix.ExecutionAddress{0x04}, + Value: uint256.NewInt(123), GasLimit: 5002, GasUsed: 5003, }, @@ -54,12 +61,12 @@ func TestBuilderBlockRequestToSignedBuilderBid(t *testing.T) { pubkey, err := bls.PublicKeyFromSecretKey(sk) require.NoError(t, err) - publicKey, err := types.BlsPublicKeyToPublicKey(pubkey) + publicKey, err := utils.BlsPublicKeyToPublicKey(pubkey) require.NoError(t, err) - signedBuilderBid, err := common.BuilderSubmitBlockRequestToSignedBuilderBid(&reqPayload, sk, &publicKey, builderSigningDomain) + signedBuilderBid, err := common.CapellaBuilderSubmitBlockRequestToSignedBuilderBid(&reqPayload, sk, &publicKey, ssz.DomainBuilder) require.NoError(t, err) - require.Equal(t, 0, signedBuilderBid.Message.Value.Cmp(&reqPayload.Message.Value)) + require.Equal(t, 0, signedBuilderBid.Message.Value.Cmp(reqPayload.Message.Value)) require.Equal(t, reqPayload.Message.BlockHash, signedBuilderBid.Message.Header.BlockHash) } diff --git a/services/api/utils.go b/services/api/utils.go index e4655d0f..0b67d06b 100644 --- a/services/api/utils.go +++ b/services/api/utils.go @@ -10,7 +10,7 @@ import ( "github.com/attestantio/go-eth2-client/spec/phase0" utilcapella "github.com/attestantio/go-eth2-client/util/capella" "github.com/flashbots/go-boost-utils/bls" - boostTypes "github.com/flashbots/go-boost-utils/types" + "github.com/flashbots/go-boost-utils/utils" "github.com/flashbots/mev-boost-relay/common" ) @@ -81,8 +81,8 @@ func EqExecutionPayloadToHeader(bb *consensusapi.VersionedSignedBlindedBeaconBlo } func checkBLSPublicKeyHex(pkHex string) error { - var proposerPubkey boostTypes.PublicKey - return proposerPubkey.UnmarshalText([]byte(pkHex)) + _, err := utils.HexToPubkey(pkHex) + return err } func hasReachedFork(slot, forkEpoch uint64) bool { @@ -90,7 +90,7 @@ func hasReachedFork(slot, forkEpoch uint64) bool { return currentEpoch >= forkEpoch } -func checkProposerSignature(block *consensusapi.VersionedSignedBlindedBeaconBlock, domain boostTypes.Domain, pubKey []byte) (bool, error) { +func checkProposerSignature(block *consensusapi.VersionedSignedBlindedBeaconBlock, domain phase0.Domain, pubKey []byte) (bool, error) { root, err := block.Root() if err != nil { return false, err @@ -99,7 +99,7 @@ func checkProposerSignature(block *consensusapi.VersionedSignedBlindedBeaconBloc if err != nil { return false, err } - signingData := boostTypes.SigningData{Root: boostTypes.Root(root), Domain: domain} + signingData := phase0.SigningData{ObjectRoot: root, Domain: domain} msg, err := signingData.HashTreeRoot() if err != nil { return false, err diff --git a/services/housekeeper/housekeeper.go b/services/housekeeper/housekeeper.go index 59aaf1b0..320fa62b 100644 --- a/services/housekeeper/housekeeper.go +++ b/services/housekeeper/housekeeper.go @@ -16,7 +16,7 @@ import ( "strings" "time" - "github.com/flashbots/go-boost-utils/types" + apiv1 "github.com/attestantio/go-builder-client/api/v1" "github.com/flashbots/mev-boost-relay/beaconclient" "github.com/flashbots/mev-boost-relay/common" "github.com/flashbots/mev-boost-relay/database" @@ -204,7 +204,7 @@ func (hk *Housekeeper) updateProposerDuties(headSlot uint64) { } // Convert db entries to signed validator registration type - signedValidatorRegistrations := make(map[string]*types.SignedValidatorRegistration) + signedValidatorRegistrations := make(map[string]*apiv1.SignedValidatorRegistration) for _, regEntry := range validatorRegistrationEntries { signedEntry, err := regEntry.ToSignedValidatorRegistration() if err != nil { @@ -256,7 +256,7 @@ func (hk *Housekeeper) updateValidatorRegistrationsInRedis() { timeStarted := time.Now() for _, reg := range regs { - err = hk.redis.SetValidatorRegistrationTimestampIfNewer(types.PubkeyHex(reg.Pubkey), reg.Timestamp) + err = hk.redis.SetValidatorRegistrationTimestampIfNewer(common.NewPubkeyHex(reg.Pubkey), reg.Timestamp) if err != nil { hk.log.WithError(err).Error("failed to set validator registration") continue