Skip to content

Commit

Permalink
getPayload only to origin relays
Browse files Browse the repository at this point in the history
  • Loading branch information
metachris committed Sep 22, 2022
1 parent e1bce51 commit d2fd6b5
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 29 deletions.
17 changes: 16 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,22 @@ We appreciate you, friend <3.

The extended deploy steps are necessary for installations with `go install` to include the correct version.

* Ensure linter and tests are working: `make lint && make test-race`
### Before the release

Run these commands:

```bash
make lint
make test-race

# Start mev-boost with relay check, and call the mev-boost status endpoint
go run . -mainnet -relay-check -relays https://0xac6e77dfe25ecd6110b8e780608cce0dab71fdd5ebea22a16c0205200f2f8e2e3ad3b71d3499c54ad14d6c21b41a37ae@boost-relay.flashbots.net,https://0x8b5d2e73e2a3a55c6c87b8b6eb92e0149a125c852751db1422fa951e42a09b82c142c3ea98d0d9930b056a3bc9896b8f@bloxroute.max-profit.blxrbdn.com,https://0xb3ee7afcf27f1f1259ac1787876318c6584ee353097a50ed84f51a1f21a323b3736f271a895c7ce918c038e4265918be@relay.edennetwork.io,https://0x9000009807ed12c1f08bf4e81c6da3ba8e3fc3d953898ce0102433094e5f22f21102ec057841fcb81978ed1ea0fa8246@builder-relay-mainnet.blocknative.com -debug
curl localhost:18550/eth/v1/builder/status
```


### Releasing a new version

* Update `Version` in `config/vars.go`
* it will be next_version-dev (eg. `v0.7.11-dev`)
* change it to the next version (eg. `v0.7.11`), and commit
Expand Down
10 changes: 1 addition & 9 deletions cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func Main() {
flag.Usage()
log.Fatal("no relays specified")
}
log.WithField("relays", relaysToStrings(relays)).Infof("using %d relays", len(relays))
log.WithField("relays", server.RelayEntriesToStrings(relays)).Infof("using %d relays", len(relays))

relayMonitors := parseRelayMonitorURLs(*relayMonitorURLs)
if len(relayMonitors) > 0 {
Expand Down Expand Up @@ -193,11 +193,3 @@ func parseRelayMonitorURLs(relayMonitorURLs string) (ret []*url.URL) {
}
return ret
}

func relaysToStrings(relays []server.RelayEntry) []string {
ret := []string{}
for _, entry := range relays {
ret = append(ret, entry.String())
}
return ret
}
7 changes: 4 additions & 3 deletions server/mock_relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,12 @@ func (m *mockRelay) handleRegisterValidator(w http.ResponseWriter, req *http.Req

// 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, hash, publicKey string) *types.GetHeaderResponse {
func (m *mockRelay) MakeGetHeaderResponse(value uint64, blockHash, parentHash, publicKey string) *types.GetHeaderResponse {
// Fill the payload with custom values.
message := &types.BuilderBid{
Header: &types.ExecutionPayloadHeader{
BlockHash: _HexToHash(hash),
ParentHash: _HexToHash("0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7"),
BlockHash: _HexToHash(blockHash),
ParentHash: _HexToHash(parentHash),
},
Value: types.IntToU256(value),
Pubkey: _HexToPubkey(publicKey),
Expand Down Expand Up @@ -191,6 +191,7 @@ func (m *mockRelay) handleGetHeader(w http.ResponseWriter, req *http.Request) {
response := m.MakeGetHeaderResponse(
12345,
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249",
)
if m.GetHeaderResponse != nil {
Expand Down
9 changes: 9 additions & 0 deletions server/relay_entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,12 @@ func NewRelayEntry(relayURL string) (entry RelayEntry, err error) {
err = entry.PublicKey.UnmarshalText([]byte(entry.URL.User.Username()))
return entry, err
}

// RelayEntriesToStrings returns the string representation of a list of relay entries
func RelayEntriesToStrings(relays []RelayEntry) []string {
ret := make([]string, len(relays))
for i, entry := range relays {
ret[i] = entry.String()
}
return ret
}
21 changes: 12 additions & 9 deletions server/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ func (m *BoostService) handleGetHeader(w http.ResponseWriter, req *http.Request)
}

var mu sync.Mutex
relays := make(map[string][]string) // relays per blockHash
relays := make(map[string][]RelayEntry) // relays per blockHash
result := bidResp{}

ua := UserAgent(req.Header.Get("User-Agent"))
Expand Down Expand Up @@ -365,11 +365,7 @@ func (m *BoostService) handleGetHeader(w http.ResponseWriter, req *http.Request)
defer mu.Unlock()

// Remember which relays delivered which bids (multiple relays might deliver the top bid)
if _, ok := relays[blockHash]; !ok {
relays[blockHash] = []string{relay.String()}
} else {
relays[blockHash] = append(relays[blockHash], relay.String())
}
relays[blockHash] = append(relays[blockHash], relay)

// Compare the bid with already known top bid (if any)
if result.response.Data != nil {
Expand Down Expand Up @@ -408,7 +404,7 @@ func (m *BoostService) handleGetHeader(w http.ResponseWriter, req *http.Request)
"blockNumber": result.response.Data.Message.Header.BlockNumber,
"txRoot": result.response.Data.Message.Header.TransactionsRoot.String(),
"value": result.response.Data.Message.Value.String(),
"relays": strings.Join(result.relays, ", "),
"relays": strings.Join(RelayEntriesToStrings(result.relays), ", "),
}).Info("best bid")

// Remember the bid, for future logging in case of withholding
Expand Down Expand Up @@ -467,6 +463,12 @@ func (m *BoostService) handleGetPayload(w http.ResponseWriter, req *http.Request
log.Warn("bid found but no associated relays")
}

relays := originalBid.relays
if len(relays) == 0 {
log.Warn("originating relay not found, sending getPayload request to all relays")
relays = m.relays
}

var wg sync.WaitGroup
var mu sync.Mutex
result := new(types.GetPayloadResponse)
Expand All @@ -476,7 +478,7 @@ func (m *BoostService) handleGetPayload(w http.ResponseWriter, req *http.Request
requestCtx, requestCtxCancel := context.WithCancel(context.Background())
defer requestCtxCancel()

for _, relay := range m.relays {
for _, relay := range relays {
wg.Add(1)
go func(relay RelayEntry) {
defer wg.Done()
Expand Down Expand Up @@ -525,7 +527,8 @@ func (m *BoostService) handleGetPayload(w http.ResponseWriter, req *http.Request

// If no payload has been received from relay, log loudly about withholding!
if result.Data == nil || result.Data.BlockHash == nilHash {
log.WithField("relays", strings.Join(originalBid.relays, ", ")).Error("no payload received from relay -- could be a network error or withholding.")
originRelays := RelayEntriesToStrings(originalBid.relays)
log.WithField("relays", strings.Join(originRelays, ", ")).Error("no payload received from relay!")
m.respondError(w, http.StatusBadGateway, errNoSuccessfulRelayResponse.Error())
return
}
Expand Down
60 changes: 54 additions & 6 deletions server/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,15 @@ func TestRegisterValidator(t *testing.T) {
})
}

func TestGetHeader(t *testing.T) {
getPath := func(slot uint64, parentHash types.Hash, pubkey types.PublicKey) string {
return fmt.Sprintf("/eth/v1/builder/header/%d/%s/%s", slot, parentHash.String(), pubkey.String())
}
func getHeaderPath(slot uint64, parentHash types.Hash, pubkey types.PublicKey) string {
return fmt.Sprintf("/eth/v1/builder/header/%d/%s/%s", slot, parentHash.String(), pubkey.String())
}

func TestGetHeader(t *testing.T) {
hash := _HexToHash("0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7")
pubkey := _HexToPubkey(
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249")
path := getPath(1, hash, pubkey)
path := getHeaderPath(1, hash, pubkey)
require.Equal(t, "/eth/v1/builder/header/1/0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7/0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249", path)

t.Run("Okay response from relay", func(t *testing.T) {
Expand All @@ -257,6 +257,7 @@ func TestGetHeader(t *testing.T) {
resp := backend.relays[0].MakeGetHeaderResponse(
12345,
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249",
)
resp.Data.Message.Header.BlockHash = nilHash
Expand Down Expand Up @@ -284,20 +285,23 @@ func TestGetHeader(t *testing.T) {
backend.relays[0].GetHeaderResponse = backend.relays[0].MakeGetHeaderResponse(
12345,
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249",
)

// First relay will return signed response with value 12347.
backend.relays[1].GetHeaderResponse = backend.relays[1].MakeGetHeaderResponse(
12347,
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249",
)

// First relay will return signed response with value 12346.
backend.relays[2].GetHeaderResponse = backend.relays[2].MakeGetHeaderResponse(
12346,
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249",
)

Expand Down Expand Up @@ -325,18 +329,21 @@ func TestGetHeader(t *testing.T) {
backend.relays[0].GetHeaderResponse = backend.relays[0].MakeGetHeaderResponse(
12345,
"0xa38385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249",
)

backend.relays[1].GetHeaderResponse = backend.relays[1].MakeGetHeaderResponse(
12345,
"0xa18385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249",
)

backend.relays[2].GetHeaderResponse = backend.relays[2].MakeGetHeaderResponse(
12345,
"0xa28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249",
)

Expand Down Expand Up @@ -364,6 +371,7 @@ func TestGetHeader(t *testing.T) {
backend.relays[0].GetHeaderResponse = backend.relays[0].MakeGetHeaderResponse(
12345,
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249",
)

Expand All @@ -384,6 +392,7 @@ func TestGetHeader(t *testing.T) {
backend.relays[0].GetHeaderResponse = backend.relays[0].MakeGetHeaderResponse(
12345,
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0xe28385e7bd68df656cd0042b74b69c3104b5356ed1f20eb69f1f925df47a3ab7",
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249",
)

Expand Down Expand Up @@ -432,7 +441,7 @@ func TestGetHeader(t *testing.T) {
t.Run("Invalid parent hash", func(t *testing.T) {
backend := newTestBackend(t, 1, time.Second)

invalidParentHashPath := getPath(1, types.Hash{}, pubkey)
invalidParentHashPath := getHeaderPath(1, types.Hash{}, pubkey)
rr := backend.request(t, http.MethodGet, invalidParentHashPath, nil)
require.Equal(t, http.StatusNoContent, rr.Code)
require.Equal(t, 0, backend.relays[0].GetRequestCount(path))
Expand Down Expand Up @@ -579,3 +588,42 @@ func TestGetPayloadWithTestdata(t *testing.T) {
})
}
}

func TestGetPayloadToOriginRelayOnly(t *testing.T) {
// Load the signed blinded beacon block used for getPayload
jsonFile, err := os.Open("../testdata/kiln-signed-blinded-beacon-block-899730.json")
require.NoError(t, err)
defer jsonFile.Close()
signedBlindedBeaconBlock := new(types.SignedBlindedBeaconBlock)
require.NoError(t, DecodeJSON(jsonFile, &signedBlindedBeaconBlock))

// Create a test backend with 2 relays
backend := newTestBackend(t, 2, time.Second)

// call getHeader, highest bid is returned by relay 0
getHeaderPath := "/eth/v1/builder/header/899730/0xe8b9bd82aa0e957736c5a029903e53d581edf451e28ab274f4ba314c442e35a4/0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249"
backend.relays[0].GetHeaderResponse = backend.relays[0].MakeGetHeaderResponse(
12345,
"0x373fb4e59dcb659b94bd58595c25345333426aa639f821567103e2eccf34d126",
"0xe8b9bd82aa0e957736c5a029903e53d581edf451e28ab274f4ba314c442e35a4",
"0x8a1d7b8dd64e0aafe7ea7b6c95065c9364cf99d38470c12ee807d55f7de1529ad29ce2c422e0b65e3d5a05c02caca249",
)
rr := backend.request(t, http.MethodGet, getHeaderPath, nil)
require.Equal(t, http.StatusOK, rr.Code, rr.Body.String())
require.Equal(t, 1, backend.relays[0].GetRequestCount(getHeaderPath))
require.Equal(t, 1, backend.relays[1].GetRequestCount(getHeaderPath))

// Prepare getPayload response
backend.relays[0].GetPayloadResponse = &types.GetPayloadResponse{
Data: &types.ExecutionPayload{
BlockHash: signedBlindedBeaconBlock.Message.Body.ExecutionPayloadHeader.BlockHash,
},
}

// call getPayload, ensure it's only called on relay 0 (origin of the bid)
getPayloadPath := "/eth/v1/builder/blinded_blocks"
rr = backend.request(t, http.MethodPost, getPayloadPath, signedBlindedBeaconBlock)
require.Equal(t, http.StatusOK, rr.Code, rr.Body.String())
require.Equal(t, 1, backend.relays[0].GetRequestCount(getPayloadPath))
require.Equal(t, 0, backend.relays[1].GetRequestCount(getPayloadPath))
}
2 changes: 1 addition & 1 deletion server/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ type bidResp struct {
t time.Time
response types.GetHeaderResponse
blockHash string
relays []string
relays []RelayEntry
}

// bidRespKey is used as key for the bids cache
Expand Down

0 comments on commit d2fd6b5

Please sign in to comment.