mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
Add a new API to help debug when there are missed rounds
This commit is contained in:
parent
c7a42fd7c9
commit
e28b550a24
7 changed files with 85 additions and 1 deletions
|
|
@ -433,6 +433,16 @@ func (x *XDPoS) GetCurrentEpochSwitchBlock(chain consensus.ChainReader, blockNum
|
|||
}
|
||||
}
|
||||
|
||||
func (x *XDPoS) CalculateMissingRounds(chain consensus.ChainReader, hash common.Hash) (*utils.PublicApiMissedRoundsMetadata, error) {
|
||||
header := chain.GetHeaderByHash(hash)
|
||||
switch x.config.BlockConsensusVersion(header.Number, header.Extra, ExtraFieldCheck) {
|
||||
case params.ConsensusEngineVersion2:
|
||||
return x.EngineV2.CalculateMissingRounds(chain, header)
|
||||
default: // Default "v1"
|
||||
return nil, fmt.Errorf("Not supported in the v1 consensus")
|
||||
}
|
||||
}
|
||||
|
||||
// Same DB across all consensus engines
|
||||
func (x *XDPoS) GetDb() ethdb.Database {
|
||||
return x.db
|
||||
|
|
|
|||
|
|
@ -285,6 +285,13 @@ func (api *API) NetworkInformation() NetworkInformation {
|
|||
return info
|
||||
}
|
||||
|
||||
/*
|
||||
An API exclusively for V2 consensus, designed to assist in troubleshooting miners by identifying who mined during their allocated term.
|
||||
*/
|
||||
func (api *API) GetMissiedRoundsInEpochByBlockHash(hash common.Hash) (*utils.PublicApiMissedRoundsMetadata, error) {
|
||||
return api.XDPoS.CalculateMissingRounds(api.chain, hash)
|
||||
}
|
||||
|
||||
func calculateSigners(message map[string]SignerTypes, pool map[string]map[common.Hash]utils.PoolObj, masternodes []common.Address) {
|
||||
for name, objs := range pool {
|
||||
var currentSigners []common.Address
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ func (x *XDPoS_v2) Prepare(chain consensus.ChainReader, header *types.Header) er
|
|||
}
|
||||
|
||||
if header.Coinbase != signer {
|
||||
log.Error("[Prepare] The mined blocker header coinbase address mismatch with waller address", "headerCoinbase", header.Coinbase.Hex(), "WalletAddress", signer.Hex())
|
||||
log.Error("[Prepare] The mined blocker header coinbase address mismatch with wallet address", "headerCoinbase", header.Coinbase.Hex(), "WalletAddress", signer.Hex())
|
||||
return consensus.ErrCoinbaseMismatch
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ func (x *XDPoS_v2) yourturn(chain consensus.ChainReader, round types.Round, pare
|
|||
return false, nil
|
||||
}
|
||||
|
||||
// TODO: USE BELOW FOR THE NEW API
|
||||
leaderIndex := uint64(round) % x.config.Epoch % uint64(len(masterNodes))
|
||||
x.whosTurn = masterNodes[leaderIndex]
|
||||
if x.whosTurn != signer {
|
||||
|
|
|
|||
|
|
@ -163,3 +163,52 @@ func (x *XDPoS_v2) GetSignersFromSnapshot(chain consensus.ChainReader, header *t
|
|||
snap, err := x.getSnapshot(chain, header.Number.Uint64(), false)
|
||||
return snap.NextEpochMasterNodes, err
|
||||
}
|
||||
|
||||
func (x *XDPoS_v2) CalculateMissingRounds(chain consensus.ChainReader, header *types.Header) (*utils.PublicApiMissedRoundsMetadata, error) {
|
||||
var missedRounds []utils.MissedRoundInfo
|
||||
switchInfo, err := x.getEpochSwitchInfo(chain, header, header.Hash())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
masternodes := switchInfo.Masternodes
|
||||
|
||||
// Loop through from the epoch switch block to the current "header" block
|
||||
nextHeader := header
|
||||
for nextHeader.Number.Cmp(switchInfo.EpochSwitchBlockInfo.Number) > 0 {
|
||||
parentHeader := chain.GetHeaderByHash(nextHeader.ParentHash)
|
||||
parentRound, err := x.GetRoundNumber(parentHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currRound, err := x.GetRoundNumber(nextHeader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// This means there is a missing round incrementation when producing blocks
|
||||
if parentRound+1 != currRound {
|
||||
// We need to loop through between parentRound and the currRound to assess which miner did not mine
|
||||
for i := parentRound; i < currRound; i++ {
|
||||
leaderIndex := uint64(i) % x.config.Epoch % uint64(len(masternodes))
|
||||
whosTerm := masternodes[leaderIndex]
|
||||
missedRounds = append(
|
||||
missedRounds,
|
||||
utils.MissedRoundInfo{
|
||||
Round: i,
|
||||
Miner: whosTerm,
|
||||
CurrentBlockHash: nextHeader.Hash(),
|
||||
ParentBlockHash: parentHeader.Hash(),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
// Assign the pointer to the next one
|
||||
nextHeader = parentHeader
|
||||
}
|
||||
missedRoundsMetadata := &utils.PublicApiMissedRoundsMetadata{
|
||||
EpochRound: switchInfo.EpochSwitchBlockInfo.Round,
|
||||
EpochBlockNumber: switchInfo.EpochSwitchBlockInfo.Number,
|
||||
MissedRounds: missedRounds,
|
||||
}
|
||||
|
||||
return missedRoundsMetadata, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,3 +57,15 @@ type PublicApiSnapshot struct {
|
|||
Votes []*clique.Vote `json:"votes"` // List of votes cast in chronological order
|
||||
Tally map[common.Address]clique.Tally `json:"tally"` // Current vote tally to avoid recalculating
|
||||
}
|
||||
|
||||
type MissedRoundInfo struct {
|
||||
Round types.Round
|
||||
Miner common.Address
|
||||
CurrentBlockHash common.Hash
|
||||
ParentBlockHash common.Hash
|
||||
}
|
||||
type PublicApiMissedRoundsMetadata struct {
|
||||
EpochRound types.Round
|
||||
EpochBlockNumber *big.Int
|
||||
MissedRounds []MissedRoundInfo
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,6 +156,11 @@ web3._extend({
|
|||
name: 'getLatestPoolStatus',
|
||||
call: 'XDPoS_getLatestPoolStatus'
|
||||
}),
|
||||
new web3._extend.Method({
|
||||
name: 'GetMissiedRoundsInEpochByBlockHash',
|
||||
call: 'XDPoS_GetMissiedRoundsInEpochByBlockHash',
|
||||
params: 1
|
||||
}),
|
||||
],
|
||||
properties: [
|
||||
new web3._extend.Property({
|
||||
|
|
|
|||
Loading…
Reference in a new issue