Skip to content

Commit 59549f6

Browse files
avalonchemetachris
andauthored
Add flag to publish block with ssz (#598)
* Add flag to publish block with ssz * profiling * Update beaconclient/prod_beacon_instance.go Co-authored-by: Chris Hager <chris@linuxuser.at> * Update beaconclient/prod_beacon_instance.go Co-authored-by: Chris Hager <chris@linuxuser.at> * Update beaconclient/prod_beacon_instance.go Co-authored-by: Chris Hager <chris@linuxuser.at> * Update beaconclient/prod_beacon_instance.go Co-authored-by: Chris Hager <chris@linuxuser.at> * Update beaconclient/prod_beacon_instance.go Co-authored-by: Chris Hager <chris@linuxuser.at> * Update beaconclient/prod_beacon_instance.go Co-authored-by: Chris Hager <chris@linuxuser.at> * fix naming * add slot to log * New http client for every beacon request (#603) * New http client for every beacon request * use milliseconds for timeout --------- Co-authored-by: Chris Hager <chris@linuxuser.at>
1 parent 71ebb23 commit 59549f6

File tree

3 files changed

+51
-42
lines changed

3 files changed

+51
-42
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ redis-cli DEL boost-relay/sepolia:validators-registration boost-relay/sepolia:va
153153
* `FORCE_GET_HEADER_204` - force 204 as getHeader response
154154
* `ENABLE_IGNORABLE_VALIDATION_ERRORS` - enable ignorable validation errors
155155
* `USE_V1_PUBLISH_BLOCK_ENDPOINT` - uses the v1 publish block endpoint on the beacon node
156+
* `USE_SSZ_ENCODING_PUBLISH_BLOCK` - uses the SSZ encoding for the publish block endpoint
156157

157158
#### Development Environment Variables
158159

beaconclient/prod_beacon_instance.go

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ type ProdBeaconInstance struct {
1919
beaconURI string
2020

2121
// feature flags
22-
ffUseV1PublishBlockEndpoint bool
22+
ffUseV1PublishBlockEndpoint bool
23+
ffUseSSZEncodingPublishBlock bool
2324
}
2425

2526
func NewProdBeaconInstance(log *logrus.Entry, beaconURI string) *ProdBeaconInstance {
@@ -28,14 +29,19 @@ func NewProdBeaconInstance(log *logrus.Entry, beaconURI string) *ProdBeaconInsta
2829
"beaconURI": beaconURI,
2930
})
3031

31-
client := &ProdBeaconInstance{_log, beaconURI, false}
32+
client := &ProdBeaconInstance{_log, beaconURI, false, false}
3233

3334
// feature flags
3435
if os.Getenv("USE_V1_PUBLISH_BLOCK_ENDPOINT") != "" {
3536
_log.Warn("env: USE_V1_PUBLISH_BLOCK_ENDPOINT: use the v1 publish block endpoint")
3637
client.ffUseV1PublishBlockEndpoint = true
3738
}
3839

40+
if os.Getenv("USE_SSZ_ENCODING_PUBLISH_BLOCK") != "" {
41+
_log.Warn("env: USE_SSZ_ENCODING_PUBLISH_BLOCK: using SSZ encoding to publish blocks")
42+
client.ffUseSSZEncodingPublishBlock = true
43+
}
44+
3945
return client
4046
}
4147

@@ -251,7 +257,37 @@ func (c *ProdBeaconInstance) PublishBlock(block *common.VersionedSignedProposal,
251257
}
252258
headers := http.Header{}
253259
headers.Add("Eth-Consensus-Version", strings.ToLower(block.Version.String())) // optional in v1, required in v2
254-
return fetchBeacon(http.MethodPost, uri, block, nil, nil, headers, false)
260+
261+
slot, err := block.Slot()
262+
if err != nil {
263+
slot = 0
264+
}
265+
266+
var payloadBytes []byte
267+
useSSZ := c.ffUseSSZEncodingPublishBlock
268+
log := c.log
269+
encodeStartTime := time.Now().UTC()
270+
if useSSZ {
271+
log = log.WithField("publishContentType", "ssz")
272+
payloadBytes, err = block.MarshalSSZ()
273+
} else {
274+
log = log.WithField("publishContentType", "json")
275+
payloadBytes, err = json.Marshal(block)
276+
}
277+
if err != nil {
278+
return 0, fmt.Errorf("could not marshal request: %w", err)
279+
}
280+
publishingStartTime := time.Now().UTC()
281+
encodeDurationMs := publishingStartTime.Sub(encodeStartTime).Milliseconds()
282+
code, err = fetchBeacon(http.MethodPost, uri, payloadBytes, nil, nil, headers, useSSZ)
283+
publishDurationMs := time.Now().UTC().Sub(publishingStartTime).Milliseconds()
284+
log.WithFields(logrus.Fields{
285+
"slot": slot,
286+
"encodeDurationMs": encodeDurationMs,
287+
"publishDurationMs": publishDurationMs,
288+
"payloadBytes": len(payloadBytes),
289+
}).Info("finished publish block request")
290+
return code, err
255291
}
256292

257293
type GetGenesisResponse struct {

beaconclient/util.go

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -31,61 +31,33 @@ func parseBroadcastModeString(s string) (BroadcastMode, bool) {
3131
return b, ok
3232
}
3333

34-
func makeJSONRequest(method, url string, payload any) (*http.Request, error) {
35-
payloadBytes, err := json.Marshal(payload)
36-
if err != nil {
37-
return nil, fmt.Errorf("could not marshal request: %w", err)
38-
}
39-
req, err := http.NewRequest(method, url, bytes.NewReader(payloadBytes))
40-
if err != nil {
41-
return nil, fmt.Errorf("invalid request for %s: %w", url, err)
42-
}
43-
// Set content-type
44-
req.Header.Add("Content-Type", "application/json")
45-
return req, nil
46-
}
47-
48-
func makeSSZRequest(method, url string, payload any) (*http.Request, error) {
49-
payloadBytes, ok := payload.([]byte)
50-
if !ok {
51-
return nil, fmt.Errorf("invalid payload type for SSZ request: %w", ErrInvalidRequestPayload)
52-
}
53-
req, err := http.NewRequest(method, url, bytes.NewReader(payloadBytes))
54-
if err != nil {
55-
return nil, fmt.Errorf("invalid request for %s: %w", url, err)
56-
}
57-
// Set content-type
58-
req.Header.Add("Content-Type", "application/octet-stream")
59-
return req, nil
60-
}
61-
62-
func fetchBeacon(method, url string, payload, dst any, timeout *time.Duration, headers http.Header, ssz bool) (code int, err error) {
34+
func fetchBeacon(method, url string, payload []byte, dst any, timeout *time.Duration, headers http.Header, ssz bool) (code int, err error) {
6335
var req *http.Request
6436

6537
if payload == nil {
6638
req, err = http.NewRequest(method, url, nil)
6739
} else {
68-
if ssz {
69-
req, err = makeSSZRequest(method, url, payload)
70-
} else {
71-
req, err = makeJSONRequest(method, url, payload)
72-
}
40+
req, err = http.NewRequest(method, url, bytes.NewReader(payload))
7341
}
7442

7543
if err != nil {
7644
return 0, fmt.Errorf("invalid request for %s: %w", url, err)
7745
}
7846

47+
if ssz {
48+
req.Header.Add("Content-Type", "application/octet-stream")
49+
} else {
50+
req.Header.Add("Content-Type", "application/json")
51+
}
52+
7953
for k, v := range headers {
8054
req.Header.Add(k, v[0])
8155
}
8256
req.Header.Set("accept", "application/json")
8357

84-
client := http.DefaultClient
85-
if timeout != nil && timeout.Seconds() > 0 {
86-
client = &http.Client{ //nolint:exhaustruct
87-
Timeout: *timeout,
88-
}
58+
client := &http.Client{}
59+
if timeout != nil && timeout.Milliseconds() > 0 {
60+
client.Timeout = *timeout
8961
}
9062
resp, err := client.Do(req)
9163
if err != nil {

0 commit comments

Comments
 (0)