From e789b4e312d4a5077b98ffae980cb0c9ed580ef6 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 28 May 2024 17:51:00 +0530 Subject: [PATCH] eth/internal: add `debug.peerStats` for stats related to all connected peers (#1252) * implement debug.peerStats for stats related to all connected peers * add identifier for ipc * display block number in peer stats * eth/downloader: log error while terminating sync --- eth/api_backend.go | 4 +++ eth/downloader/downloader.go | 2 +- eth/handler.go | 37 ++++++++++++++++++++++++ internal/ethapi/api.go | 6 ++++ internal/ethapi/api_test.go | 4 +++ internal/ethapi/backend.go | 3 ++ internal/ethapi/transaction_args_test.go | 4 +++ internal/web3ext/web3ext.go | 5 ++++ les/api_backend.go | 4 +++ 9 files changed, 68 insertions(+), 1 deletion(-) diff --git a/eth/api_backend.go b/eth/api_backend.go index 3c37756d34..e7ea41f87b 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -474,3 +474,7 @@ func (b *EthAPIBackend) GetWhitelistedMilestone() (bool, uint64, common.Hash) { func (b *EthAPIBackend) PurgeWhitelistedMilestone() { b.eth.Downloader().ChainValidator.PurgeWhitelistedMilestone() } + +func (b *EthAPIBackend) PeerStats() interface{} { + return b.eth.handler.GetPeerStats() +} diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 3659fd488f..4773275a1b 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -512,7 +512,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd * } defer func(start time.Time) { - log.Debug("Synchronisation terminated", "elapsed", common.PrettyDuration(time.Since(start))) + log.Debug("Synchronisation terminated", "elapsed", common.PrettyDuration(time.Since(start)), "err", err) }(time.Now()) // Look up the sync boundaries: the common ancestor and the target block diff --git a/eth/handler.go b/eth/handler.go index 3a2aa8f04f..c416894f89 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -728,3 +728,40 @@ func (h *handler) enableSyncedFeatures() { h.chain.TrieDB().SetBufferSize(pathdb.DefaultBufferSize) } } + +// PeerStats represents a short summary of the information known about a connected +// peer. Specifically, it contains details about the head hash and total difficulty +// of a peer which makes it a bit different from the PeerInfo. +type PeerStats struct { + Enode string `json:"enode"` // Node URL + ID string `json:"id"` // Unique node identifier + Name string `json:"name"` // Name of the node, including client type, version, OS, custom data + Hash string `json:"hash"` // Head hash of the peer + Number uint64 `json:"number"` // Head number of the peer + Td uint64 `json:"td"` // Total difficulty of the peer +} + +// PeerStats returns the current head height and td of all the connected peers +// along with few additional identifiers. +func (h *handler) GetPeerStats() []*PeerStats { + info := make([]*PeerStats, 0, len(h.peers.peers)) + + for _, peer := range h.peers.peers { + hash, td := peer.Head() + block := h.chain.GetBlockByHash(hash) + number := uint64(0) + if block != nil { + number = block.NumberU64() + } + info = append(info, &PeerStats{ + Enode: peer.Node().URLv4(), + ID: peer.ID(), + Name: peer.Name(), + Hash: hash.String(), + Number: number, + Td: td.Uint64(), + }) + } + + return info +} diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 8acc6a39b3..3dc8f46ceb 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -2729,6 +2729,12 @@ func (api *DebugAPI) GetTraceStack() string { } } +// PeerStats returns the current head height and td of all the connected peers +// along with few additional identifiers. +func (api *DebugAPI) PeerStats() interface{} { + return api.b.PeerStats() +} + // NetAPI offers network related RPC methods type NetAPI struct { net *p2p.Server diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 5c28022b42..02340405be 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -644,6 +644,10 @@ func (b testBackend) SubscribeStateSyncEvent(ch chan<- core.StateSyncEvent) even panic("implement me") } +func (b testBackend) PeerStats() interface{} { + panic("implement me") +} + func (b testBackend) GetBorBlockLogs(ctx context.Context, hash common.Hash) ([]*types.Log, error) { receipt, err := b.GetBorBlockReceipt(ctx, hash) if err != nil || receipt == nil { diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 706be22e60..bbb25330c2 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -112,6 +112,9 @@ type Backend interface { PurgeWhitelistedCheckpoint() GetWhitelistedMilestone() (bool, uint64, common.Hash) PurgeWhitelistedMilestone() + + // Networking related APIs + PeerStats() interface{} } func GetAPIs(apiBackend Backend) []rpc.API { diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index 41eeb9cee0..e8321c9ef2 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -412,3 +412,7 @@ func (b *backendMock) GetWhitelistedMilestone() (bool, uint64, common.Hash) { func (b *backendMock) PurgeWhitelistedCheckpoint() {} func (b *backendMock) PurgeWhitelistedMilestone() {} + +func (b backendMock) PeerStats() interface{} { + return nil +} diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index ef2752749d..f1fcd9974d 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -565,6 +565,11 @@ web3._extend({ call: 'debug_getTrieFlushInterval', params: 0 }), + new web3._extend.Method({ + name: 'peerStats', + call: 'debug_peerStats', + params: 0 + }), ], properties: [] }); diff --git a/les/api_backend.go b/les/api_backend.go index ec0019b219..f2f33eac3d 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -376,3 +376,7 @@ func (b *LesApiBackend) GetWhitelistedMilestone() (bool, uint64, common.Hash) { func (b *LesApiBackend) PurgeWhitelistedMilestone() { } + +func (b *LesApiBackend) PeerStats() interface{} { + return nil +}