beacon/engine, rpc: use json.Marshaler for direct result encoding

This commit is contained in:
jonny rhea 2026-03-09 18:54:08 -05:00
parent ca18d7e655
commit bdaa6d6f94
4 changed files with 12 additions and 49 deletions

View file

@ -12,31 +12,6 @@ import (
var _ = (*executionPayloadEnvelopeMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
type ExecutionPayloadEnvelope struct {
ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
BlobsBundle *BlobsBundle `json:"blobsBundle"`
Requests []hexutil.Bytes `json:"executionRequests"`
Override bool `json:"shouldOverrideBuilder"`
Witness *hexutil.Bytes `json:"witness,omitempty"`
}
var enc ExecutionPayloadEnvelope
enc.ExecutionPayload = e.ExecutionPayload
enc.BlockValue = (*hexutil.Big)(e.BlockValue)
enc.BlobsBundle = e.BlobsBundle
if e.Requests != nil {
enc.Requests = make([]hexutil.Bytes, len(e.Requests))
for k, v := range e.Requests {
enc.Requests[k] = v
}
}
enc.Override = e.Override
enc.Witness = e.Witness
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
type ExecutionPayloadEnvelope struct {

View file

@ -68,9 +68,6 @@ func marshalHexBytesArray(buf []byte, items []hexutil.Bytes) []byte {
}
// writeHexBytes writes a hex-encoded byte slice as a JSON string ("0x...") to buf.
// NOTE: This function avoids allocations by pre-allocating the buffer space needed;
// otherwise, we would use hexutil.Encode() and append the result to the buffer.
// hexutil.Encode() uses 64% more memory than writing to buffer directly.
func writeHexBytes(buf []byte, data []byte) []byte {
buf = append(buf, '"', '0', 'x')
buf = slices.Grow(buf, len(data)*2+1)
@ -81,10 +78,8 @@ func writeHexBytes(buf []byte, data []byte) []byte {
return buf
}
// PremarshaledJSON implements rpc.JSONPremarshaled. It returns pre-serialized
// JSON by delegating small fields to their existing MarshalJSON methods and
// hand-rolling only the BlobsBundle.
func (e ExecutionPayloadEnvelope) PremarshaledJSON() ([]byte, error) {
// MarshalJSON implements json.Marshaler.
func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
// Marshal the execution payload using its gencodec MarshalJSON.
payload, err := e.ExecutionPayload.MarshalJSON()
if err != nil {

View file

@ -47,7 +47,7 @@ type encodingType int
const (
encNone encodingType = iota
encJSON
encJSONPremarshaled
encJSONCustom
encRLP
)
@ -57,8 +57,8 @@ func (e encodingType) String() string {
return "none"
case encJSON:
return "json"
case encJSONPremarshaled:
return "json_premarshaled"
case encJSONCustom:
return "json_custom"
case encRLP:
return "rlp"
default:
@ -66,7 +66,7 @@ func (e encodingType) String() string {
}
}
var encodingTypes = []encodingType{encNone, encJSON, encJSONPremarshaled, encRLP}
var encodingTypes = []encodingType{encNone, encJSON, encJSONCustom, encRLP}
// benchEncode encodes the value using the specified encoding type.
// It fails the benchmark if encoding fails.
@ -78,14 +78,14 @@ func benchEncode(b *testing.B, enc encodingType, v any) {
if err != nil {
b.Fatalf("JSON marshal failed: %v", err)
}
case encJSONPremarshaled:
if pm, ok := v.(rpc.JSONPremarshaled); ok {
_, err = pm.PremarshaledJSON()
case encJSONCustom:
if m, ok := v.(json.Marshaler); ok {
_, err = m.MarshalJSON()
} else {
_, err = json.Marshal(v)
}
if err != nil {
b.Fatalf("JSON premarshaled marshal failed: %v", err)
b.Fatalf("JSON MarshalJSON failed: %v", err)
}
case encRLP:
_, err = rlp.EncodeToBytes(v)

View file

@ -113,20 +113,13 @@ func (msg *jsonrpcMessage) errorResponse(err error) *jsonrpcMessage {
return resp
}
// JSONPremarshaled may be implemented by RPC return types that provide
// pre-serialized JSON. This bypasses json.Marshal and its re-validation
// pass. Implementors must ensure the returned bytes are valid JSON.
type JSONPremarshaled interface {
PremarshaledJSON() ([]byte, error)
}
func (msg *jsonrpcMessage) response(result interface{}) *jsonrpcMessage {
var (
enc []byte
err error
)
if pm, ok := result.(JSONPremarshaled); ok {
enc, err = pm.PremarshaledJSON()
if m, ok := result.(json.Marshaler); ok {
enc, err = m.MarshalJSON()
} else {
enc, err = json.Marshal(result)
}