Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

server: move mock relay into mock package #642

Merged
merged 5 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions cli/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ import (
"net/url"
"strings"

"github.com/flashbots/mev-boost/server"
"github.com/flashbots/mev-boost/server/types"
)

var errDuplicateEntry = errors.New("duplicate entry")

type relayList []server.RelayEntry
type relayList []types.RelayEntry

func (r *relayList) String() string {
return strings.Join(server.RelayEntriesToStrings(*r), ",")
return strings.Join(types.RelayEntriesToStrings(*r), ",")
}

func (r *relayList) Contains(relay server.RelayEntry) bool {
func (r *relayList) Contains(relay types.RelayEntry) bool {
for _, entry := range *r {
if relay.String() == entry.String() {
return true
Expand All @@ -26,7 +26,7 @@ func (r *relayList) Contains(relay server.RelayEntry) bool {
}

func (r *relayList) Set(value string) error {
relay, err := server.NewRelayEntry(value)
relay, err := types.NewRelayEntry(value)
if err != nil {
return err
}
Expand Down
9 changes: 0 additions & 9 deletions server/backend.go

This file was deleted.

85 changes: 47 additions & 38 deletions server/mock_relay.go → server/mock/mock_relay.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package server
package mock

import (
"encoding/json"
Expand All @@ -22,6 +22,8 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/flashbots/go-boost-utils/bls"
"github.com/flashbots/go-boost-utils/ssz"
"github.com/flashbots/mev-boost/server/params"
"github.com/flashbots/mev-boost/server/types"
"github.com/gorilla/mux"
"github.com/holiman/uint256"
"github.com/stretchr/testify/require"
Expand All @@ -37,17 +39,17 @@ var (
mockRelayPublicKey, _ = bls.PublicKeyFromSecretKey(mockRelaySecretKey)
)

// mockRelay is used to fake a relay's behavior.
// Relay is used to fake a relay's behavior.
// You can override each of its handler by setting the instance's HandlerOverride_METHOD_TO_OVERRIDE to your own
// handler.
type mockRelay struct {
type Relay struct {
// Used to panic if impossible error happens
t *testing.T

// KeyPair used to sign messages
secretKey *bls.SecretKey
publicKey *bls.PublicKey
RelayEntry RelayEntry
RelayEntry types.RelayEntry

// Used to count each Request made to the relay, either if it fails or not, for each method
mu sync.Mutex
Expand All @@ -67,11 +69,11 @@ type mockRelay struct {
ResponseDelay time.Duration
}

// newMockRelay creates a mocked relay which implements the backend.BoostBackend interface
// NewRelay creates a mocked relay which implements the backend.BoostBackend interface
// A secret key must be provided to sign default and custom response messages
func newMockRelay(t *testing.T) *mockRelay {
func NewRelay(t *testing.T) *Relay {
t.Helper()
relay := &mockRelay{t: t, secretKey: mockRelaySecretKey, publicKey: mockRelayPublicKey, requestCount: make(map[string]int)}
relay := &Relay{t: t, secretKey: mockRelaySecretKey, publicKey: mockRelayPublicKey, requestCount: make(map[string]int)}

// Initialize server
relay.Server = httptest.NewServer(relay.getRouter())
Expand All @@ -80,13 +82,13 @@ func newMockRelay(t *testing.T) *mockRelay {
url, err := url.Parse(relay.Server.URL)
require.NoError(t, err)
urlWithKey := fmt.Sprintf("%s://%s@%s", url.Scheme, hexutil.Encode(bls.PublicKeyToBytes(mockRelayPublicKey)), url.Host)
relay.RelayEntry, err = NewRelayEntry(urlWithKey)
relay.RelayEntry, err = types.NewRelayEntry(urlWithKey)
require.NoError(t, err)
return relay
}

// newTestMiddleware creates a middleware which increases the Request counter and creates a fake delay for the response
func (m *mockRelay) newTestMiddleware(next http.Handler) http.Handler {
func (m *Relay) newTestMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
// Request counter
Expand All @@ -106,43 +108,43 @@ func (m *mockRelay) newTestMiddleware(next http.Handler) http.Handler {
}

// getRouter registers all methods from the backend, apply the test middleware and return the configured router
func (m *mockRelay) getRouter() http.Handler {
func (m *Relay) getRouter() http.Handler {
// Create router.
r := mux.NewRouter()

// Register handlers
r.HandleFunc("/", m.handleRoot).Methods(http.MethodGet)
r.HandleFunc(pathStatus, m.handleStatus).Methods(http.MethodGet)
r.HandleFunc(pathRegisterValidator, m.handleRegisterValidator).Methods(http.MethodPost)
r.HandleFunc(pathGetHeader, m.handleGetHeader).Methods(http.MethodGet)
r.HandleFunc(pathGetPayload, m.handleGetPayload).Methods(http.MethodPost)
r.HandleFunc(params.PathStatus, m.handleStatus).Methods(http.MethodGet)
r.HandleFunc(params.PathRegisterValidator, m.handleRegisterValidator).Methods(http.MethodPost)
r.HandleFunc(params.PathGetHeader, m.handleGetHeader).Methods(http.MethodGet)
r.HandleFunc(params.PathGetPayload, m.handleGetPayload).Methods(http.MethodPost)

return m.newTestMiddleware(r)
}

// GetRequestCount returns the number of Request made to a specific URL
func (m *mockRelay) GetRequestCount(path string) int {
func (m *Relay) GetRequestCount(path string) int {
m.mu.Lock()
defer m.mu.Unlock()
return m.requestCount[path]
}

// By default, handleRoot returns the relay's status
func (m *mockRelay) handleRoot(w http.ResponseWriter, _ *http.Request) {
func (m *Relay) handleRoot(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `{}`)
}

// By default, handleStatus returns the relay's status as http.StatusOK
func (m *mockRelay) handleStatus(w http.ResponseWriter, _ *http.Request) {
func (m *Relay) handleStatus(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `{}`)
}

// By default, handleRegisterValidator returns a default builderApiV1.SignedValidatorRegistration
func (m *mockRelay) handleRegisterValidator(w http.ResponseWriter, req *http.Request) {
func (m *Relay) handleRegisterValidator(w http.ResponseWriter, req *http.Request) {
m.mu.Lock()
defer m.mu.Unlock()
if m.handlerOverrideRegisterValidator != nil {
Expand All @@ -153,9 +155,9 @@ func (m *mockRelay) handleRegisterValidator(w http.ResponseWriter, req *http.Req
}

// defaultHandleRegisterValidator returns the default handler for handleRegisterValidator
func (m *mockRelay) defaultHandleRegisterValidator(w http.ResponseWriter, req *http.Request) {
func (m *Relay) defaultHandleRegisterValidator(w http.ResponseWriter, req *http.Request) {
payload := []builderApiV1.SignedValidatorRegistration{}
if err := DecodeJSON(req.Body, &payload); err != nil {
if err := json.NewDecoder(req.Body).Decode(&payload); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
MariusVanDerWijden marked this conversation as resolved.
Show resolved Hide resolved
return
}
Expand All @@ -166,18 +168,18 @@ func (m *mockRelay) defaultHandleRegisterValidator(w http.ResponseWriter, req *h

// MakeGetHeaderResponse is used to create the default or can be used to create a custom response to the getHeader
// method
func (m *mockRelay) MakeGetHeaderResponse(value uint64, blockHash, parentHash, publicKey string, version spec.DataVersion) *builderSpec.VersionedSignedBuilderBid {
func (m *Relay) MakeGetHeaderResponse(value uint64, blockHash, parentHash, publicKey string, version spec.DataVersion) *builderSpec.VersionedSignedBuilderBid {
switch version {
case spec.DataVersionCapella:
// Fill the payload with custom values.
message := &builderApiCapella.BuilderBid{
Header: &capella.ExecutionPayloadHeader{
BlockHash: _HexToHash(blockHash),
ParentHash: _HexToHash(parentHash),
BlockHash: HexToHash(blockHash),
ParentHash: HexToHash(parentHash),
WithdrawalsRoot: phase0.Root{},
},
Value: uint256.NewInt(value),
Pubkey: _HexToPubkey(publicKey),
Pubkey: HexToPubkey(publicKey),
}

// Sign the message.
Expand All @@ -194,14 +196,14 @@ func (m *mockRelay) MakeGetHeaderResponse(value uint64, blockHash, parentHash, p
case spec.DataVersionDeneb:
message := &builderApiDeneb.BuilderBid{
Header: &deneb.ExecutionPayloadHeader{
BlockHash: _HexToHash(blockHash),
ParentHash: _HexToHash(parentHash),
BlockHash: HexToHash(blockHash),
ParentHash: HexToHash(parentHash),
WithdrawalsRoot: phase0.Root{},
BaseFeePerGas: uint256.NewInt(0),
},
BlobKZGCommitments: make([]deneb.KZGCommitment, 0),
Value: uint256.NewInt(value),
Pubkey: _HexToPubkey(publicKey),
Pubkey: HexToPubkey(publicKey),
}

// Sign the message.
Expand All @@ -222,7 +224,7 @@ func (m *mockRelay) MakeGetHeaderResponse(value uint64, blockHash, parentHash, p
}

// handleGetHeader handles incoming requests to server.pathGetHeader
func (m *mockRelay) handleGetHeader(w http.ResponseWriter, req *http.Request) {
func (m *Relay) handleGetHeader(w http.ResponseWriter, req *http.Request) {
m.mu.Lock()
defer m.mu.Unlock()
// Try to override default behavior is custom handler is specified.
Expand All @@ -234,7 +236,7 @@ func (m *mockRelay) handleGetHeader(w http.ResponseWriter, req *http.Request) {
}

// defaultHandleGetHeader returns the default handler for handleGetHeader
func (m *mockRelay) defaultHandleGetHeader(w http.ResponseWriter) {
func (m *Relay) defaultHandleGetHeader(w http.ResponseWriter) {
// By default, everything will be ok.
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
Expand All @@ -259,33 +261,33 @@ func (m *mockRelay) defaultHandleGetHeader(w http.ResponseWriter) {

// MakeGetPayloadResponse is used to create the default or can be used to create a custom response to the getPayload
// method
func (m *mockRelay) MakeGetPayloadResponse(parentHash, blockHash, feeRecipient string, blockNumber uint64, version spec.DataVersion) *builderApi.VersionedSubmitBlindedBlockResponse {
func (m *Relay) MakeGetPayloadResponse(parentHash, blockHash, feeRecipient string, blockNumber uint64, version spec.DataVersion) *builderApi.VersionedSubmitBlindedBlockResponse {
return &builderApi.VersionedSubmitBlindedBlockResponse{
Version: version,
Capella: &capella.ExecutionPayload{
ParentHash: _HexToHash(parentHash),
BlockHash: _HexToHash(blockHash),
ParentHash: HexToHash(parentHash),
BlockHash: HexToHash(blockHash),
BlockNumber: blockNumber,
FeeRecipient: _HexToAddress(feeRecipient),
FeeRecipient: HexToAddress(feeRecipient),
Withdrawals: make([]*capella.Withdrawal, 0),
},
}
}

// handleGetPayload handles incoming requests to server.pathGetPayload
func (m *mockRelay) handleGetPayload(w http.ResponseWriter, req *http.Request) {
func (m *Relay) handleGetPayload(w http.ResponseWriter, req *http.Request) {
m.mu.Lock()
defer m.mu.Unlock()
// Try to override default behavior is custom handler is specified.
if m.handlerOverrideGetPayload != nil {
m.handlerOverrideGetPayload(w, req)
return
}
m.defaultHandleGetPayload(w)
m.DefaultHandleGetPayload(w)
}

// defaultHandleGetPayload returns the default handler for handleGetPayload
func (m *mockRelay) defaultHandleGetPayload(w http.ResponseWriter) {
// DefaultHandleGetPayload returns the default handler for handleGetPayload
func (m *Relay) DefaultHandleGetPayload(w http.ResponseWriter) {
// By default, everything will be ok.
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
Expand All @@ -309,9 +311,16 @@ func (m *mockRelay) defaultHandleGetPayload(w http.ResponseWriter) {
}
}

func (m *mockRelay) overrideHandleRegisterValidator(method func(w http.ResponseWriter, req *http.Request)) {
func (m *Relay) OverrideHandleRegisterValidator(method func(w http.ResponseWriter, req *http.Request)) {
m.mu.Lock()
defer m.mu.Unlock()

m.handlerOverrideRegisterValidator = method
}

func (m *Relay) OverrideHandleGetPayload(method func(w http.ResponseWriter, req *http.Request)) {
m.mu.Lock()
defer m.mu.Unlock()

m.handlerOverrideGetPayload = method
}
7 changes: 4 additions & 3 deletions server/mock_relay_test.go → server/mock/mock_relay_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
package server
package mock

import (
"bytes"
"net/http"
"net/http/httptest"
"testing"

"github.com/flashbots/mev-boost/server/params"
"github.com/stretchr/testify/require"
)

func Test_mockRelay(t *testing.T) {
t.Run("bad payload", func(t *testing.T) {
relay := newMockRelay(t)
req, err := http.NewRequest(http.MethodPost, pathRegisterValidator, bytes.NewReader([]byte("123")))
relay := NewRelay(t)
req, err := http.NewRequest(http.MethodPost, params.PathRegisterValidator, bytes.NewReader([]byte("123")))
require.NoError(t, err)
rr := httptest.NewRecorder()
relay.getRouter().ServeHTTP(rr, req)
Expand Down
61 changes: 61 additions & 0 deletions server/mock/mock_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package mock

import (
"github.com/attestantio/go-eth2-client/spec/bellatrix"
"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/flashbots/go-boost-utils/utils"
"github.com/sirupsen/logrus"
)

// TestLog is used to log information in the test methods
var TestLog = logrus.NewEntry(logrus.New())

// HexToBytes converts a hexadecimal string to a byte array
func HexToBytes(hex string) []byte {
res, err := hexutil.Decode(hex)
if err != nil {
panic(err)
}
return res
}

// HexToHash converts a hexadecimal string to an Ethereum hash
func HexToHash(s string) (ret phase0.Hash32) {
ret, err := utils.HexToHash(s)
if err != nil {
TestLog.Error(err, " _HexToHash: ", s)
panic(err)
}
return ret
}

// HexToAddress converts a hexadecimal string to an Ethereum address
func HexToAddress(s string) (ret bellatrix.ExecutionAddress) {
ret, err := utils.HexToAddress(s)
if err != nil {
TestLog.Error(err, " _HexToAddress: ", s)
panic(err)
}
return ret
}

// HexToPubkey converts a hexadecimal string to a BLS Public Key
func HexToPubkey(s string) (ret phase0.BLSPubKey) {
ret, err := utils.HexToPubkey(s)
if err != nil {
TestLog.Error(err, " _HexToPubkey: ", s)
panic(err)
}
return
}

// HexToSignature converts a hexadecimal string to a BLS Signature
func HexToSignature(s string) (ret phase0.BLSSignature) {
ret, err := utils.HexToSignature(s)
if err != nil {
TestLog.Error(err, " _HexToSignature: ", s)
panic(err)
}
return
}
Loading
Loading