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.
This commit is contained in:
anilchinchawale 2026-01-29 06:11:43 +01:00
parent 93bbb7c130
commit fbc86ff61f
2 changed files with 62 additions and 0 deletions

View file

@ -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()

View file

@ -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 }