consensus/clique: add clique_status API method (#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?
This commit is contained in:
parent
a3d263dd3a
commit
3f4a875bf6
@ -17,6 +17,8 @@
|
|||||||
package clique
|
package clique
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
@ -117,3 +119,59 @@ func (api *API) Discard(address common.Address) {
|
|||||||
|
|
||||||
delete(api.clique.proposals, address)
|
delete(api.clique.proposals, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Status struct {
|
||||||
|
InturnPercent float64 `json:"inturnPercent"`
|
||||||
|
SigningStatus map[common.Address]int `json:"sealerActivity""`
|
||||||
|
NumBlocks uint64 `json:"numBlocks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status returns the status of the last N blocks,
|
||||||
|
// - the number of active signers,
|
||||||
|
// - the number of signers,
|
||||||
|
// - the percentage of in-turn blocks
|
||||||
|
func (api *API) Status() (*Status, error) {
|
||||||
|
var (
|
||||||
|
numBlocks = uint64(64)
|
||||||
|
header = api.chain.CurrentHeader()
|
||||||
|
diff = uint64(0)
|
||||||
|
optimals = 0
|
||||||
|
)
|
||||||
|
snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
signers = snap.signers()
|
||||||
|
end = header.Number.Uint64()
|
||||||
|
start = end - numBlocks
|
||||||
|
)
|
||||||
|
if numBlocks > end {
|
||||||
|
start = 1
|
||||||
|
numBlocks = end - start
|
||||||
|
}
|
||||||
|
signStatus := make(map[common.Address]int)
|
||||||
|
for _, s := range signers {
|
||||||
|
signStatus[s] = 0
|
||||||
|
}
|
||||||
|
for n := start; n < end; n++ {
|
||||||
|
h := api.chain.GetHeaderByNumber(n)
|
||||||
|
if h == nil {
|
||||||
|
return nil, fmt.Errorf("missing block %d", n)
|
||||||
|
}
|
||||||
|
if h.Difficulty.Cmp(diffInTurn) == 0 {
|
||||||
|
optimals++
|
||||||
|
}
|
||||||
|
diff += h.Difficulty.Uint64()
|
||||||
|
sealer, err := api.clique.Author(h)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
signStatus[sealer]++
|
||||||
|
}
|
||||||
|
return &Status{
|
||||||
|
InturnPercent: float64((100 * optimals)) / float64(numBlocks),
|
||||||
|
SigningStatus: signStatus,
|
||||||
|
NumBlocks: numBlocks,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user