diff --git a/eth/peer.go b/eth/peer.go index 7618777716..943def8212 100644 --- a/eth/peer.go +++ b/eth/peer.go @@ -17,6 +17,7 @@ package eth import ( + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/snap" ) @@ -24,7 +25,14 @@ import ( // ethPeerInfo represents a short summary of the `eth` sub-protocol metadata known // about a connected peer. type ethPeerInfo struct { - Version uint `json:"version"` // Ethereum protocol version negotiated + Version uint `json:"version"` // Ethereum protocol version negotiated + BlockRange *peerBlockRange `json:"blockRange"` +} + +type peerBlockRange struct { + Earliest uint64 `json:"earliestBlock"` + Latest uint64 `json:"latestBlock"` + LatestHash common.Hash `json:"latestBlockHash"` } // ethPeer is a wrapper around eth.Peer to maintain a few extra metadata. @@ -35,9 +43,15 @@ type ethPeer struct { // info gathers and returns some `eth` protocol metadata known about a peer. func (p *ethPeer) info() *ethPeerInfo { - return ðPeerInfo{ - Version: p.Version(), + info := ðPeerInfo{Version: p.Version()} + if br := p.BlockRange(); br != nil { + info.BlockRange = &peerBlockRange{ + Earliest: br.EarliestBlock, + Latest: br.LatestBlock, + LatestHash: br.LatestBlockHash, + } } + return info } // snapPeerInfo represents a short summary of the `snap` sub-protocol metadata known diff --git a/eth/protocols/eth/handlers.go b/eth/protocols/eth/handlers.go index f675064e10..d496e6679d 100644 --- a/eth/protocols/eth/handlers.go +++ b/eth/protocols/eth/handlers.go @@ -548,6 +548,7 @@ func handleBlockRangeUpdate(backend Backend, msg Decoder, peer *Peer) error { if err := msg.Decode(&update); err != nil { return err } - // We don't do anything with these messages for now. + // We don't do anything with these messages for now, just store them on the peer. + peer.lastRange.Store(&update) return nil } diff --git a/eth/protocols/eth/handshake.go b/eth/protocols/eth/handshake.go index 115b32ea23..1922db15b4 100644 --- a/eth/protocols/eth/handshake.go +++ b/eth/protocols/eth/handshake.go @@ -137,6 +137,12 @@ func (p *Peer) readStatus69(networkID uint64, status *StatusPacket69, genesis co if err := forkFilter(status.ForkID); err != nil { return fmt.Errorf("%w: %v", errForkIDRejected, err) } + // Handle initial block range. + p.lastRange.Store(&BlockRangeUpdatePacket{ + EarliestBlock: status.EarliestBlock, + LatestBlock: status.LatestBlock, + LatestBlockHash: status.LatestBlockHash, + }) return nil } diff --git a/eth/protocols/eth/peer.go b/eth/protocols/eth/peer.go index b553456156..40c54a3570 100644 --- a/eth/protocols/eth/peer.go +++ b/eth/protocols/eth/peer.go @@ -18,6 +18,7 @@ package eth import ( "math/rand" + "sync/atomic" mapset "github.com/deckarep/golang-set/v2" "github.com/ethereum/go-ethereum/common" @@ -47,6 +48,7 @@ type Peer struct { *p2p.Peer // The embedded P2P package peer rw p2p.MsgReadWriter // Input/output streams for snap version uint // Protocol version negotiated + lastRange atomic.Pointer[BlockRangeUpdatePacket] txpool TxPool // Transaction pool used by the broadcasters for liveness checks knownTxs *knownCache // Set of transaction hashes known to be known by this peer @@ -102,6 +104,12 @@ func (p *Peer) Version() uint { return p.version } +// BlockRange returns the latest announced block range. +// This will be nil for peers below protocol version eth/69. +func (p *Peer) BlockRange() *BlockRangeUpdatePacket { + return p.lastRange.Load() +} + // KnownTransaction returns whether peer is known to already have a transaction. func (p *Peer) KnownTransaction(hash common.Hash) bool { return p.knownTxs.Contains(hash)