Skip to content

eth/protocols/eth/handshake.go — Version Comparison

v1.16.8 v1.17.3
Branch etc/v1.16.8-full-node etc/v1.17.3-full-node
Delta +42 -0 +12 -1
ETC delta on v1.16.8 (+42 -0)
diff --git a/eth/protocols/eth/handshake.go b/eth/protocols/eth/handshake.go
index bb3d1b8eb..df2728402 100644
--- a/eth/protocols/eth/handshake.go
+++ b/eth/protocols/eth/handshake.go
@@ -19,12 +19,14 @@ package eth
 import (
    "errors"
    "fmt"
+   "math/big"
    "time"

    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/core/forkid"
    "github.com/ethereum/go-ethereum/metrics"
    "github.com/ethereum/go-ethereum/p2p"
+   "github.com/ethereum/go-ethereum/params"
 )

 const (
@@ -217,3 +219,43 @@ func (p *BlockRangeUpdatePacket) Validate() error {
    }
    return nil
 }
+
+// Handshake68PoW executes the eth/68 protocol handshake for perpetual PoW networks.
+// Unlike the standard ETH68 handshake, this version sends and receives TD (Total Difficulty)
+// which is required for proper chain synchronization in PoW networks.
+// After a successful handshake, it initializes the PoW extension with the peer's head info.
+func (p *Peer) Handshake68PoW(networkID uint64, td *big.Int, head common.Hash, genesis common.Hash, forkID forkid.ID, forkFilter forkid.Filter) error {
+   errc := make(chan error, 2)
+   go func() {
+       pkt := &StatusPacket68{
+           ProtocolVersion: uint32(p.version),
+           NetworkID:       networkID,
+           TD:              td,
+           Head:            head,
+           Genesis:         genesis,
+           ForkID:          forkID,
+       }
+       errc <- p2p.Send(p.rw, StatusMsg, pkt)
+   }()
+
+   var status StatusPacket68 // safe to read after two values have been received from errc
+   go func() {
+       errc <- p.readStatus68(networkID, &status, genesis, forkFilter)
+   }()
+
+   if err := waitForHandshake(errc, p); err != nil {
+       return err
+   }
+   // Reject peers with TD >= ETH mainnet's TTD. Such high TD indicates the peer
+   // is from ETH mainnet (which shares the same genesis hash but much higher TD).
+   if status.TD != nil && status.TD.Cmp(params.MainnetTerminalTotalDifficulty) >= 0 {
+       return fmt.Errorf("peer TD %v exceeds ETH TTD, likely wrong network", status.TD)
+   }
+   // Reject peers with nil TD - required for proper PoW sync
+   if status.TD == nil {
+       return errors.New("peer has nil TD, rejecting for PoW sync")
+   }
+   // Initialize PoW extension with peer's head info directly
+   p.InitPoWExtension(status.Head, status.TD)
+   return nil
+}
ETC delta on v1.17.3 (+12 -1)
diff --git a/eth/protocols/eth/handshake.go b/eth/protocols/eth/handshake.go
index 359e4e36b..9af18d00c 100644
--- a/eth/protocols/eth/handshake.go
+++ b/eth/protocols/eth/handshake.go
@@ -34,8 +34,19 @@ const (
 )

 // Handshake executes the eth protocol handshake, negotiating version number,
-// network IDs, difficulties, head and genesis blocks.
+// network IDs, difficulties, head and genesis blocks. ETH68 is handled by
+// Handshake68PoW directly from the PoW handler branch; it intentionally
+// has no case here so non-PoW callers never enter a TD-less ETH68 path.
 func (p *Peer) Handshake(networkID uint64, chain forkid.Blockchain, rangeMsg BlockRangeUpdatePacket) error {
+   switch p.version {
+   case ETH70, ETH69:
+       return p.handshake69(networkID, chain, rangeMsg)
+   default:
+       return errors.New("unsupported protocol version")
+   }
+}
+
+func (p *Peer) handshake69(networkID uint64, chain forkid.Blockchain, rangeMsg BlockRangeUpdatePacket) error {
    var (
        genesis    = chain.Genesis()
        latest     = chain.CurrentHeader()

← Back to Version Comparison