From fbc86ff61f3d39dc64df918f82235435f094101b Mon Sep 17 00:00:00 2001 From: anilchinchawale Date: Thu, 29 Jan 2026 06:11:43 +0100 Subject: [PATCH] feat: add eth/62 handshake support for XDC - Added StatusPacket62 without ForkID field - Added handshake62() function for eth/62, eth/63, XDPOS2 - Added readStatus62() for reading XDC status messages Note: Peer connection still fails due to XDC's custom discovery protocol using pingXDC (type 5) instead of standard ping (type 1). This requires modification to p2p/discover layer. --- eth/protocols/eth/handshake.go | 49 ++++++++++++++++++++++++++++++++++ eth/protocols/eth/protocol.go | 13 +++++++++ 2 files changed, 62 insertions(+) diff --git a/eth/protocols/eth/handshake.go b/eth/protocols/eth/handshake.go index bb3d1b8eb4..34ca185c70 100644 --- a/eth/protocols/eth/handshake.go +++ b/eth/protocols/eth/handshake.go @@ -19,6 +19,7 @@ package eth import ( "errors" "fmt" + "math/big" "time" "github.com/ethereum/go-ethereum/common" @@ -41,11 +42,59 @@ func (p *Peer) Handshake(networkID uint64, chain forkid.Blockchain, rangeMsg Blo return p.handshake69(networkID, chain, rangeMsg) case ETH68: return p.handshake68(networkID, chain) + case ETH62, ETH63, XDPOS2: + // XDC uses eth/62, eth/63, and xdpos2 without ForkID + return p.handshake62(networkID, chain) default: return errors.New("unsupported protocol version") } } +// handshake62 performs the eth/62 handshake without ForkID (used by XDC) +func (p *Peer) handshake62(networkID uint64, chain forkid.Blockchain) error { + var ( + genesis = chain.Genesis() + latest = chain.CurrentHeader() + // XDC is pre-merge, so TD is relevant. Use a placeholder TD based on block number. + // In a proper implementation, this should come from the chain's state. + td = new(big.Int).SetUint64(latest.Number.Uint64()) + ) + errc := make(chan error, 2) + go func() { + pkt := &StatusPacket62{ + ProtocolVersion: uint32(p.version), + NetworkID: networkID, + TD: td, + Head: latest.Hash(), + Genesis: genesis.Hash(), + } + errc <- p2p.Send(p.rw, StatusMsg, pkt) + }() + var status StatusPacket62 // safe to read after two values have been received from errc + go func() { + errc <- p.readStatus62(networkID, &status, genesis.Hash()) + }() + + return waitForHandshake(errc, p) +} + +func (p *Peer) readStatus62(networkID uint64, status *StatusPacket62, genesis common.Hash) error { + if err := p.readStatusMsg(status); err != nil { + return err + } + if status.NetworkID != networkID { + return fmt.Errorf("%w: %d (!= %d)", errNetworkIDMismatch, status.NetworkID, networkID) + } + if uint(status.ProtocolVersion) != p.version { + return fmt.Errorf("%w: %d (!= %d)", errProtocolVersionMismatch, status.ProtocolVersion, p.version) + } + if status.Genesis != genesis { + return fmt.Errorf("%w: %x (!= %x)", errGenesisMismatch, status.Genesis, genesis) + } + // No ForkID check for eth/62 + return nil +} + func (p *Peer) handshake68(networkID uint64, chain forkid.Blockchain) error { var ( genesis = chain.Genesis() diff --git a/eth/protocols/eth/protocol.go b/eth/protocols/eth/protocol.go index 1ecf2f32b5..5dbcc1fec0 100644 --- a/eth/protocols/eth/protocol.go +++ b/eth/protocols/eth/protocol.go @@ -111,6 +111,16 @@ type Packet interface { Kind() byte // Kind returns the message type. } +// StatusPacket62 is the network packet for the status message in eth/62 and eth/63. +// XDC uses this format without ForkID. +type StatusPacket62 struct { + ProtocolVersion uint32 + NetworkID uint64 + TD *big.Int + Head common.Hash + Genesis common.Hash +} + // StatusPacket is the network packet for the status message. type StatusPacket68 struct { ProtocolVersion uint32 @@ -361,6 +371,9 @@ type BlockRangeUpdatePacket struct { LatestBlockHash common.Hash } +func (*StatusPacket62) Name() string { return "Status" } +func (*StatusPacket62) Kind() byte { return StatusMsg } + func (*StatusPacket68) Name() string { return "Status" } func (*StatusPacket68) Kind() byte { return StatusMsg }