Skip to content
This repository was archived by the owner on May 21, 2024. It is now read-only.

Commit 2bd68c3

Browse files
holimanelizabethengelman
authored andcommitted
consensus/clique: add clique_status API method (ethereum#20103)
This PR introduces clique_status which gives info about the health of the clique network. It's currently a bit PITA to find out how a clique network is performing, and it can easily happen that sealers drop off -- and everything is 'fine' until one more signer drops off, and the network suddenly halts. The new method provides the following stats: - Which signers are currently active, and have signed blocks in the last N (set to 64) blocks? - How many blocks has each signer signed? - What is the difficulty in the last N blocks, compared to the theoretical maximum?
1 parent b8b1edd commit 2bd68c3

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

consensus/clique/api.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package clique
1818

1919
import (
20+
"fmt"
21+
2022
"github.com/ethereum/go-ethereum/common"
2123
"github.com/ethereum/go-ethereum/consensus"
2224
"github.com/ethereum/go-ethereum/core/types"
@@ -117,3 +119,59 @@ func (api *API) Discard(address common.Address) {
117119

118120
delete(api.clique.proposals, address)
119121
}
122+
123+
type Status struct {
124+
InturnPercent float64 `json:"inturnPercent"`
125+
SigningStatus map[common.Address]int `json:"sealerActivity""`
126+
NumBlocks uint64 `json:"numBlocks"`
127+
}
128+
129+
// Status returns the status of the last N blocks,
130+
// - the number of active signers,
131+
// - the number of signers,
132+
// - the percentage of in-turn blocks
133+
func (api *API) Status() (*Status, error) {
134+
var (
135+
numBlocks = uint64(64)
136+
header = api.chain.CurrentHeader()
137+
diff = uint64(0)
138+
optimals = 0
139+
)
140+
snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
141+
if err != nil {
142+
return nil, err
143+
}
144+
var (
145+
signers = snap.signers()
146+
end = header.Number.Uint64()
147+
start = end - numBlocks
148+
)
149+
if numBlocks > end {
150+
start = 1
151+
numBlocks = end - start
152+
}
153+
signStatus := make(map[common.Address]int)
154+
for _, s := range signers {
155+
signStatus[s] = 0
156+
}
157+
for n := start; n < end; n++ {
158+
h := api.chain.GetHeaderByNumber(n)
159+
if h == nil {
160+
return nil, fmt.Errorf("missing block %d", n)
161+
}
162+
if h.Difficulty.Cmp(diffInTurn) == 0 {
163+
optimals++
164+
}
165+
diff += h.Difficulty.Uint64()
166+
sealer, err := api.clique.Author(h)
167+
if err != nil {
168+
return nil, err
169+
}
170+
signStatus[sealer]++
171+
}
172+
return &Status{
173+
InturnPercent: float64((100 * optimals)) / float64(numBlocks),
174+
SigningStatus: signStatus,
175+
NumBlocks: numBlocks,
176+
}, nil
177+
}

0 commit comments

Comments
 (0)