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 | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/consensus" | ||||
| 	"github.com/ethereum/go-ethereum/core/types" | ||||
| @ -117,3 +119,59 @@ func (api *API) Discard(address common.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