Skip to content

Commit fe8d4c5

Browse files
authored
Send getPayload request to all relays again (#788)
* Send getPayload request to all relays again * Fix mistake in comment * Maybe fix flaky test
1 parent d65d507 commit fe8d4c5

File tree

2 files changed

+73
-25
lines changed

2 files changed

+73
-25
lines changed

server/get_payload.go

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"io"
1010
"mime"
1111
"net/http"
12+
"slices"
1213
"sync/atomic"
1314
"time"
1415

@@ -128,41 +129,42 @@ func (m *BoostService) getPayload(log *logrus.Entry, signedBlindedBeaconBlockByt
128129
requestCtx, requestCtxCancel := context.WithTimeout(context.Background(), m.httpClientGetPayload.Timeout)
129130
defer requestCtxCancel()
130131

131-
// Make a list of relays without SSZ support
132-
var relaysWithoutSSZ []string
133-
for _, relay := range originalBid.relays {
134-
if !relay.SupportsSSZ {
135-
relaysWithoutSSZ = append(relaysWithoutSSZ, relay.URL.Hostname())
136-
}
137-
}
138-
139-
// Convert the blinded block to JSON if there's a relay that doesn't support SSZ yet
140-
var signedBlindedBeaconBlockBytesJSON []byte
141-
if proposerContentType == MediaTypeOctetStream && len(relaysWithoutSSZ) > 0 {
142-
log.WithField("relaysWithoutSSZ", relaysWithoutSSZ).Info("Converting request from SSZ to JSON for relay(s)")
143-
signedBlindedBeaconBlockBytesJSON, err = convertSSZToJSON(proposerEthConsensusVersion, signedBlindedBeaconBlockBytes)
144-
if err != nil {
145-
log.WithError(errFailedToConvert).Error("failed to convert SSZ to JSON")
146-
return nil, bidResp{}
147-
}
148-
}
149-
150-
// Only request payloads from relays which provided the bid. This is
151-
// necessary now because we use the bid to track relay encoding preferences.
152-
for _, relay := range originalBid.relays {
132+
for _, relay := range m.relays {
153133
go func(relay types.RelayEntry) {
154134
url := relay.GetURI(params.PathGetPayload)
155135
log := log.WithField("url", url)
156136
log.Debug("calling getPayload")
157137

158138
// If the request fails, try again a few times with 100ms between tries
159139
resp, err := retry(requestCtx, m.requestMaxRetries, 100*time.Millisecond, func() (*http.Response, error) {
160-
// If necessary, use the JSON encoded version and the JSON Content-Type header
140+
// Default to the content from the proposer
161141
requestContentType := parsedProposerContentType
162142
requestBytes := signedBlindedBeaconBlockBytes
163-
if parsedProposerContentType == MediaTypeOctetStream && !relay.SupportsSSZ {
164-
requestBytes = signedBlindedBeaconBlockBytesJSON
143+
144+
// Check if the relay supports SSZ
145+
relaySupportsSSZ := false
146+
for _, originalBidRelay := range originalBid.relays {
147+
if relay.URL == originalBidRelay.URL {
148+
relaySupportsSSZ = originalBidRelay.SupportsSSZ
149+
break
150+
}
151+
}
152+
log.WithField("relaySupportsSSZ", relaySupportsSSZ).Debug("encoding preference")
153+
154+
// If the relay provided the bid in JSON or did not provide a bid for this payload,
155+
// we must convert the signed blinded beacon block from SSZ to JSON for this relay
156+
if parsedProposerContentType == MediaTypeOctetStream && !relaySupportsSSZ {
165157
requestContentType = MediaTypeJSON
158+
startTime := time.Now()
159+
requestBytes, err = convertSSZToJSON(proposerEthConsensusVersion, signedBlindedBeaconBlockBytes)
160+
if err != nil {
161+
log.WithError(errFailedToConvert).Error("failed to convert SSZ to JSON")
162+
return nil, err
163+
}
164+
log.WithFields(logrus.Fields{
165+
"relayProvidedBid": slices.Contains(originalBid.relays, relay),
166+
"conversionTime": time.Since(startTime),
167+
}).Info("Converted request from SSZ to JSON for relay")
166168
}
167169

168170
// Make a new request

server/service_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"os"
1313
"path/filepath"
1414
"strings"
15+
"sync"
1516
"testing"
1617
"time"
1718

@@ -973,6 +974,51 @@ func TestGetPayload(t *testing.T) {
973974
require.Equal(t, MediaTypeOctetStream, rr.Header().Get(HeaderContentType))
974975
})
975976

977+
t.Run("A relay which does not provide the bid gets a JSON request", func(t *testing.T) {
978+
header := make(http.Header)
979+
header.Set("Eth-Consensus-Version", "deneb")
980+
header.Set("Accept", "application/octet-stream")
981+
header.Set("Content-Type", "application/octet-stream")
982+
983+
// Setup backend with 2 relays
984+
backend := newTestBackend(t, 2, time.Second)
985+
986+
// Add the bid to the service
987+
bid := bidResp{relays: make([]types.RelayEntry, 1)}
988+
bid.relays[0] = backend.relays[0].RelayEntry
989+
bid.relays[0].SupportsSSZ = true
990+
backend.boost.bids[bidKey(payload.Message.Slot, payload.Message.Body.ExecutionPayloadHeader.BlockHash)] = bid
991+
992+
// Make a wait group to ensure both relays get the request
993+
var wg sync.WaitGroup
994+
wg.Add(len(backend.relays))
995+
996+
// Ensure the first relay gets the request in SSZ
997+
backend.relays[0].OverrideHandleGetPayload(func(w http.ResponseWriter, req *http.Request) {
998+
defer wg.Done()
999+
require.Equal(t, MediaTypeOctetStream, req.Header.Get(HeaderContentType)) //nolint:testifylint
1000+
backend.relays[0].DefaultHandleGetPayload(w, req)
1001+
})
1002+
1003+
// Ensure the second relay gets the request in JSON
1004+
backend.relays[1].OverrideHandleGetPayload(func(w http.ResponseWriter, req *http.Request) {
1005+
defer wg.Done()
1006+
require.Equal(t, MediaTypeJSON, req.Header.Get(HeaderContentType)) //nolint:testifylint
1007+
backend.relays[1].DefaultHandleGetPayload(w, req)
1008+
})
1009+
1010+
// Send the request
1011+
payloadBytes, err := payload.MarshalSSZ()
1012+
require.NoError(t, err)
1013+
rr := backend.requestBytes(t, http.MethodPost, path, header, payloadBytes)
1014+
require.Equal(t, http.StatusOK, rr.Code, rr.Body.String())
1015+
1016+
// Ensure both relays got the request
1017+
wg.Wait()
1018+
require.Equal(t, 1, backend.relays[0].GetRequestCount(path))
1019+
require.Equal(t, 1, backend.relays[1].GetRequestCount(path))
1020+
})
1021+
9761022
t.Run("Bad response from relays", func(t *testing.T) {
9771023
header := make(http.Header)
9781024
header.Set(HeaderAccept, MediaTypeJSON)

0 commit comments

Comments
 (0)