mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-24 08:49:29 +00:00
eip-8161: remove EIP-8160 discovery, use flag-based SSZ-REST configuration
Remove getClientCommunicationChannels, exchangeCapabilitiesV2, and getSupportedProtocols. The SSZ-REST endpoint is now enabled solely via the --authrpc.ssz-rest flag. CLs discover it via their own --ssz-rest-url flag. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
650273aa6c
commit
8851d6a5be
6 changed files with 0 additions and 287 deletions
|
|
@ -229,84 +229,6 @@ func DecodeForkChoiceResponseSSZ(buf []byte) (*ForkChoiceResponse, error) {
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
// --- CommunicationChannel SSZ ---
|
||||
|
||||
// EncodeCommunicationChannelsSSZ encodes communication channels to SSZ.
|
||||
func EncodeCommunicationChannelsSSZ(channels []CommunicationChannel) []byte {
|
||||
if len(channels) == 0 {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
var totalSize int
|
||||
for _, ch := range channels {
|
||||
totalSize += 4 + len(ch.Protocol) + 4 + len(ch.URL)
|
||||
}
|
||||
|
||||
buf := make([]byte, 4+totalSize)
|
||||
binary.LittleEndian.PutUint32(buf[0:4], uint32(len(channels)))
|
||||
|
||||
offset := 4
|
||||
for _, ch := range channels {
|
||||
protBytes := []byte(ch.Protocol)
|
||||
urlBytes := []byte(ch.URL)
|
||||
|
||||
binary.LittleEndian.PutUint32(buf[offset:offset+4], uint32(len(protBytes)))
|
||||
offset += 4
|
||||
copy(buf[offset:], protBytes)
|
||||
offset += len(protBytes)
|
||||
|
||||
binary.LittleEndian.PutUint32(buf[offset:offset+4], uint32(len(urlBytes)))
|
||||
offset += 4
|
||||
copy(buf[offset:], urlBytes)
|
||||
offset += len(urlBytes)
|
||||
}
|
||||
|
||||
return buf
|
||||
}
|
||||
|
||||
// DecodeCommunicationChannelsSSZ decodes communication channels from SSZ bytes.
|
||||
func DecodeCommunicationChannelsSSZ(buf []byte) ([]CommunicationChannel, error) {
|
||||
if len(buf) < 4 {
|
||||
return nil, fmt.Errorf("CommunicationChannels: buffer too short")
|
||||
}
|
||||
|
||||
count := binary.LittleEndian.Uint32(buf[0:4])
|
||||
if count > 16 {
|
||||
return nil, fmt.Errorf("CommunicationChannels: too many channels (%d > 16)", count)
|
||||
}
|
||||
|
||||
channels := make([]CommunicationChannel, 0, count)
|
||||
offset := uint32(4)
|
||||
|
||||
for i := uint32(0); i < count; i++ {
|
||||
if offset+4 > uint32(len(buf)) {
|
||||
return nil, fmt.Errorf("CommunicationChannels: unexpected end of buffer")
|
||||
}
|
||||
protLen := binary.LittleEndian.Uint32(buf[offset : offset+4])
|
||||
offset += 4
|
||||
if protLen > 32 || offset+protLen > uint32(len(buf)) {
|
||||
return nil, fmt.Errorf("CommunicationChannels: protocol too long or truncated")
|
||||
}
|
||||
protocol := string(buf[offset : offset+protLen])
|
||||
offset += protLen
|
||||
|
||||
if offset+4 > uint32(len(buf)) {
|
||||
return nil, fmt.Errorf("CommunicationChannels: unexpected end of buffer")
|
||||
}
|
||||
urlLen := binary.LittleEndian.Uint32(buf[offset : offset+4])
|
||||
offset += 4
|
||||
if urlLen > 256 || offset+urlLen > uint32(len(buf)) {
|
||||
return nil, fmt.Errorf("CommunicationChannels: URL too long or truncated")
|
||||
}
|
||||
url := string(buf[offset : offset+urlLen])
|
||||
offset += urlLen
|
||||
|
||||
channels = append(channels, CommunicationChannel{Protocol: protocol, URL: url})
|
||||
}
|
||||
|
||||
return channels, nil
|
||||
}
|
||||
|
||||
// --- Capabilities SSZ ---
|
||||
|
||||
// EncodeCapabilitiesSSZ encodes a list of capability strings to SSZ.
|
||||
|
|
|
|||
|
|
@ -180,29 +180,6 @@ func TestCapabilitiesSSZRoundTrip(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCommunicationChannelsSSZRoundTrip(t *testing.T) {
|
||||
channels := []CommunicationChannel{
|
||||
{Protocol: "json_rpc", URL: "localhost:8551"},
|
||||
{Protocol: "ssz_rest", URL: "http://localhost:8552"},
|
||||
}
|
||||
encoded := EncodeCommunicationChannelsSSZ(channels)
|
||||
decoded, err := DecodeCommunicationChannelsSSZ(encoded)
|
||||
if err != nil {
|
||||
t.Fatalf("decode error: %v", err)
|
||||
}
|
||||
if len(decoded) != len(channels) {
|
||||
t.Fatalf("length mismatch: got %d, want %d", len(decoded), len(channels))
|
||||
}
|
||||
for i, ch := range channels {
|
||||
if decoded[i].Protocol != ch.Protocol {
|
||||
t.Errorf("channel[%d].Protocol mismatch: got %s, want %s", i, decoded[i].Protocol, ch.Protocol)
|
||||
}
|
||||
if decoded[i].URL != ch.URL {
|
||||
t.Errorf("channel[%d].URL mismatch: got %s, want %s", i, decoded[i].URL, ch.URL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientVersionSSZRoundTrip(t *testing.T) {
|
||||
cv := &ClientVersionV1{
|
||||
Code: "GE",
|
||||
|
|
|
|||
|
|
@ -413,14 +413,3 @@ func (v *ClientVersionV1) String() string {
|
|||
return fmt.Sprintf("%s-%s-%s-%s", v.Code, v.Name, v.Version, v.Commit)
|
||||
}
|
||||
|
||||
// CommunicationChannel represents a communication protocol supported by the EL (EIP-8160).
|
||||
type CommunicationChannel struct {
|
||||
Protocol string `json:"protocol"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// ExchangeCapabilitiesV2Response is the response to engine_exchangeCapabilitiesV2 (EIP-8160).
|
||||
type ExchangeCapabilitiesV2Response struct {
|
||||
Capabilities []string `json:"capabilities"`
|
||||
SupportedProtocols []CommunicationChannel `json:"supportedProtocols"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,12 +52,7 @@ import (
|
|||
func Register(stack *node.Node, backend *eth.Ethereum) error {
|
||||
api := NewConsensusAPI(backend)
|
||||
|
||||
// Configure SSZ-REST fields from the node config
|
||||
cfg := stack.Config()
|
||||
api.authAddr = cfg.AuthAddr
|
||||
api.authPort = cfg.AuthPort
|
||||
api.sszRestEnabled = cfg.SszRestEnabled
|
||||
api.sszRestPort = cfg.SszRestPort
|
||||
|
||||
stack.RegisterAPIs([]rpc.API{
|
||||
newTestingAPI(backend),
|
||||
|
|
@ -145,11 +140,6 @@ type ConsensusAPI struct {
|
|||
forkchoiceLock sync.Mutex // Lock for the forkChoiceUpdated method
|
||||
newPayloadLock sync.Mutex // Lock for the NewPayload method
|
||||
|
||||
// SSZ-REST server config (EIP-8161)
|
||||
sszRestEnabled bool
|
||||
sszRestPort int
|
||||
authAddr string
|
||||
authPort int
|
||||
}
|
||||
|
||||
// NewConsensusAPI creates a new consensus api for the given backend.
|
||||
|
|
@ -1109,8 +1099,6 @@ func (api *ConsensusAPI) ExchangeCapabilities([]string) []string {
|
|||
// Methods that should not be advertised via V1 capabilities
|
||||
skip := map[string]bool{
|
||||
"ExchangeCapabilities": true,
|
||||
"ExchangeCapabilitiesV2": true,
|
||||
"GetClientCommunicationChannelsV1": true,
|
||||
}
|
||||
valueT := reflect.TypeOf(api)
|
||||
caps := make([]string, 0, valueT.NumMethod())
|
||||
|
|
@ -1142,37 +1130,6 @@ func (api *ConsensusAPI) GetClientVersionV1(info engine.ClientVersionV1) []engin
|
|||
}
|
||||
}
|
||||
|
||||
// ExchangeCapabilitiesV2 extends ExchangeCapabilities with supported protocols (EIP-8160).
|
||||
func (api *ConsensusAPI) ExchangeCapabilitiesV2(fromCl []string) engine.ExchangeCapabilitiesV2Response {
|
||||
capabilities := api.ExchangeCapabilities(fromCl)
|
||||
return engine.ExchangeCapabilitiesV2Response{
|
||||
Capabilities: capabilities,
|
||||
SupportedProtocols: api.getSupportedProtocols(),
|
||||
}
|
||||
}
|
||||
|
||||
// GetClientCommunicationChannelsV1 returns the communication protocols supported by this EL (EIP-8160).
|
||||
func (api *ConsensusAPI) GetClientCommunicationChannelsV1() []engine.CommunicationChannel {
|
||||
return api.getSupportedProtocols()
|
||||
}
|
||||
|
||||
// getSupportedProtocols returns the list of communication protocols supported by this EL.
|
||||
func (api *ConsensusAPI) getSupportedProtocols() []engine.CommunicationChannel {
|
||||
channels := []engine.CommunicationChannel{
|
||||
{
|
||||
Protocol: "json_rpc",
|
||||
URL: fmt.Sprintf("%s:%d", api.authAddr, api.authPort),
|
||||
},
|
||||
}
|
||||
if api.sszRestEnabled && api.sszRestPort > 0 {
|
||||
channels = append(channels, engine.CommunicationChannel{
|
||||
Protocol: "ssz_rest",
|
||||
URL: fmt.Sprintf("http://%s:%d", api.authAddr, api.sszRestPort),
|
||||
})
|
||||
}
|
||||
return channels
|
||||
}
|
||||
|
||||
// GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list
|
||||
// of block bodies by the engine api.
|
||||
func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engine.ExecutionPayloadBody {
|
||||
|
|
|
|||
|
|
@ -153,11 +153,6 @@ func (s *SszRestServer) registerRoutes(mux *http.ServeMux) {
|
|||
// getClientVersion
|
||||
mux.HandleFunc("POST /engine/v1/get_client_version", s.handleGetClientVersion)
|
||||
|
||||
// getClientCommunicationChannels (deprecated, kept for backward compat)
|
||||
mux.HandleFunc("POST /engine/v1/get_client_communication_channels", s.handleGetClientCommunicationChannels)
|
||||
|
||||
// exchangeCapabilitiesV2 (EIP-8160)
|
||||
mux.HandleFunc("POST /engine/v2/exchange_capabilities", s.handleExchangeCapabilitiesV2)
|
||||
}
|
||||
|
||||
// --- newPayload handlers ---
|
||||
|
|
@ -499,48 +494,6 @@ func (s *SszRestServer) handleGetClientVersion(w http.ResponseWriter, r *http.Re
|
|||
sszResponse(w, engine.EncodeClientVersionsSSZ(result))
|
||||
}
|
||||
|
||||
// --- exchangeCapabilitiesV2 handler (EIP-8160) ---
|
||||
|
||||
func (s *SszRestServer) handleExchangeCapabilitiesV2(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("[SSZ-REST] Received ExchangeCapabilitiesV2")
|
||||
|
||||
body, err := readBody(r, 1024*1024)
|
||||
if err != nil {
|
||||
sszErrorResponse(w, http.StatusBadRequest, -32602, "failed to read request body")
|
||||
return
|
||||
}
|
||||
|
||||
capabilities, err := engine.DecodeCapabilitiesSSZ(body)
|
||||
if err != nil {
|
||||
sszErrorResponse(w, http.StatusBadRequest, -32602, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
result := s.api.ExchangeCapabilitiesV2(capabilities)
|
||||
|
||||
capBuf := engine.EncodeCapabilitiesSSZ(result.Capabilities)
|
||||
chanBuf := engine.EncodeCommunicationChannelsSSZ(result.SupportedProtocols)
|
||||
|
||||
// SSZ Container: capabilities_offset(4) + channels_offset(4) + data
|
||||
fixedSize := uint32(8)
|
||||
buf := make([]byte, 8+len(capBuf)+len(chanBuf))
|
||||
binary.LittleEndian.PutUint32(buf[0:4], fixedSize)
|
||||
binary.LittleEndian.PutUint32(buf[4:8], fixedSize+uint32(len(capBuf)))
|
||||
copy(buf[8:], capBuf)
|
||||
copy(buf[8+len(capBuf):], chanBuf)
|
||||
|
||||
sszResponse(w, buf)
|
||||
}
|
||||
|
||||
// --- getClientCommunicationChannels handler ---
|
||||
|
||||
func (s *SszRestServer) handleGetClientCommunicationChannels(w http.ResponseWriter, r *http.Request) {
|
||||
log.Info("[SSZ-REST] Received GetClientCommunicationChannels")
|
||||
|
||||
result := s.api.GetClientCommunicationChannelsV1()
|
||||
sszResponse(w, engine.EncodeCommunicationChannelsSSZ(result))
|
||||
}
|
||||
|
||||
// handleEngineError converts engine errors to appropriate HTTP error responses.
|
||||
func (s *SszRestServer) handleEngineError(w http.ResponseWriter, err error) {
|
||||
log.Warn("[SSZ-REST] Engine error", "err", err)
|
||||
|
|
|
|||
|
|
@ -140,88 +140,3 @@ func TestSszRestSuccessFormat(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestSszRestExchangeCapabilitiesV2Format tests the V2 response container format.
|
||||
func TestSszRestExchangeCapabilitiesV2Format(t *testing.T) {
|
||||
caps := []string{"engine_newPayloadV4", "engine_getPayloadV4"}
|
||||
channels := []engine.CommunicationChannel{
|
||||
{Protocol: "json_rpc", URL: "localhost:8551"},
|
||||
{Protocol: "ssz_rest", URL: "http://localhost:8552"},
|
||||
}
|
||||
|
||||
capBuf := engine.EncodeCapabilitiesSSZ(caps)
|
||||
chanBuf := engine.EncodeCommunicationChannelsSSZ(channels)
|
||||
|
||||
// Build the V2 response container: offset(4) + offset(4) + data
|
||||
fixedSize := uint32(8)
|
||||
buf := make([]byte, 8+len(capBuf)+len(chanBuf))
|
||||
le32(buf[0:4], fixedSize)
|
||||
le32(buf[4:8], fixedSize+uint32(len(capBuf)))
|
||||
copy(buf[8:], capBuf)
|
||||
copy(buf[8+len(capBuf):], chanBuf)
|
||||
|
||||
// Decode
|
||||
capOffset := rd32(buf[0:4])
|
||||
chanOffset := rd32(buf[4:8])
|
||||
|
||||
decodedCaps, err := engine.DecodeCapabilitiesSSZ(buf[capOffset:chanOffset])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
decodedChannels, err := engine.DecodeCommunicationChannelsSSZ(buf[chanOffset:])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(decodedCaps) != 2 || decodedCaps[0] != "engine_newPayloadV4" {
|
||||
t.Errorf("caps mismatch: %v", decodedCaps)
|
||||
}
|
||||
if len(decodedChannels) != 2 || decodedChannels[1].Protocol != "ssz_rest" {
|
||||
t.Errorf("channels mismatch: %v", decodedChannels)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSszRestGetSupportedProtocols tests the getSupportedProtocols helper.
|
||||
func TestSszRestGetSupportedProtocols(t *testing.T) {
|
||||
api := &ConsensusAPI{
|
||||
sszRestEnabled: true,
|
||||
sszRestPort: 8552,
|
||||
authAddr: "127.0.0.1",
|
||||
authPort: 8551,
|
||||
}
|
||||
|
||||
channels := api.getSupportedProtocols()
|
||||
if len(channels) != 2 {
|
||||
t.Fatalf("expected 2 channels, got %d", len(channels))
|
||||
}
|
||||
if channels[0].Protocol != "json_rpc" {
|
||||
t.Errorf("first channel should be json_rpc, got %s", channels[0].Protocol)
|
||||
}
|
||||
if channels[1].Protocol != "ssz_rest" {
|
||||
t.Errorf("second channel should be ssz_rest, got %s", channels[1].Protocol)
|
||||
}
|
||||
if channels[1].URL != "http://127.0.0.1:8552" {
|
||||
t.Errorf("unexpected URL: %s", channels[1].URL)
|
||||
}
|
||||
|
||||
// Without SSZ-REST
|
||||
api2 := &ConsensusAPI{
|
||||
sszRestEnabled: false,
|
||||
authAddr: "127.0.0.1",
|
||||
authPort: 8551,
|
||||
}
|
||||
channels2 := api2.getSupportedProtocols()
|
||||
if len(channels2) != 1 {
|
||||
t.Fatalf("expected 1 channel without SSZ-REST, got %d", len(channels2))
|
||||
}
|
||||
}
|
||||
|
||||
func le32(buf []byte, v uint32) {
|
||||
buf[0] = byte(v)
|
||||
buf[1] = byte(v >> 8)
|
||||
buf[2] = byte(v >> 16)
|
||||
buf[3] = byte(v >> 24)
|
||||
}
|
||||
|
||||
func rd32(buf []byte) uint32 {
|
||||
return uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue