mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-03 11:41:17 +00:00
* fix bug in isEpochSwitchAtRound, fix penalty test TestHookPenaltyV2Mining * fix authorised test * fix things * revert a test
103 lines
3.8 KiB
Go
103 lines
3.8 KiB
Go
package engine_v2
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/XinFinOrg/XDPoSChain/common"
|
|
"github.com/XinFinOrg/XDPoSChain/consensus"
|
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
|
"github.com/XinFinOrg/XDPoSChain/log"
|
|
)
|
|
|
|
// get epoch switch of the previous `limit` epoch
|
|
func (x *XDPoS_v2) getPreviousEpochSwitchInfoByHash(chain consensus.ChainReader, hash common.Hash, limit int) (*utils.EpochSwitchInfo, error) {
|
|
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, nil, hash)
|
|
if err != nil {
|
|
log.Error("[getPreviousEpochSwitchInfoByHash] Adaptor v2 getEpochSwitchInfo has error, potentially bug", "err", err)
|
|
return nil, err
|
|
}
|
|
for i := 0; i < limit; i++ {
|
|
epochSwitchInfo, err = x.getEpochSwitchInfo(chain, nil, epochSwitchInfo.EpochSwitchParentBlockInfo.Hash)
|
|
if err != nil {
|
|
log.Error("[getPreviousEpochSwitchInfoByHash] Adaptor v2 getEpochSwitchInfo has error, potentially bug", "err", err)
|
|
return nil, err
|
|
}
|
|
}
|
|
return epochSwitchInfo, nil
|
|
}
|
|
|
|
// Given header and its hash, get epoch switch info from the epoch switch block of that epoch,
|
|
// header is allow to be nil.
|
|
func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types.Header, hash common.Hash) (*utils.EpochSwitchInfo, error) {
|
|
e, ok := x.epochSwitches.Get(hash)
|
|
if ok {
|
|
log.Debug("[getEpochSwitchInfo] cache hit", "hash", hash.Hex())
|
|
epochSwitchInfo := e.(*utils.EpochSwitchInfo)
|
|
return epochSwitchInfo, nil
|
|
}
|
|
h := header
|
|
if h == nil {
|
|
log.Debug("[getEpochSwitchInfo] header missing, get header", "hash", hash.Hex())
|
|
h = chain.GetHeaderByHash(hash)
|
|
if h == nil {
|
|
log.Warn("[getEpochSwitchInfo] can not find header from db", "hash", hash.Hex())
|
|
return nil, fmt.Errorf("[getEpochSwitchInfo] can not find header from db hash %v", hash.Hex())
|
|
}
|
|
}
|
|
isEpochSwitch, _, err := x.IsEpochSwitch(h)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if isEpochSwitch {
|
|
log.Debug("[getEpochSwitchInfo] header is epoch switch", "hash", hash.Hex(), "number", h.Number.Uint64())
|
|
quorumCert, round, masternodes, err := x.getExtraFields(h)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
epochSwitchInfo := &utils.EpochSwitchInfo{
|
|
Masternodes: masternodes,
|
|
EpochSwitchBlockInfo: &utils.BlockInfo{
|
|
Hash: hash,
|
|
Number: h.Number,
|
|
Round: round,
|
|
},
|
|
}
|
|
if quorumCert != nil {
|
|
epochSwitchInfo.EpochSwitchParentBlockInfo = quorumCert.ProposedBlockInfo
|
|
}
|
|
|
|
x.epochSwitches.Add(hash, epochSwitchInfo)
|
|
return epochSwitchInfo, nil
|
|
}
|
|
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, nil, h.ParentHash)
|
|
if err != nil {
|
|
log.Error("[getEpochSwitchInfo] recursive error", "err", err, "hash", hash.Hex(), "number", h.Number.Uint64())
|
|
return nil, err
|
|
}
|
|
log.Debug("[getEpochSwitchInfo] get epoch switch info recursively", "hash", hash.Hex(), "number", h.Number.Uint64())
|
|
x.epochSwitches.Add(hash, epochSwitchInfo)
|
|
return epochSwitchInfo, nil
|
|
}
|
|
|
|
// IsEpochSwitchAtRound() is used by miner to check whether it mines a block in the same epoch with parent
|
|
func (x *XDPoS_v2) isEpochSwitchAtRound(round utils.Round, parentHeader *types.Header) (bool, uint64, error) {
|
|
epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(round)/x.config.Epoch
|
|
// if parent is last v1 block and this is first v2 block, this is treated as epoch switch
|
|
if parentHeader.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
|
|
return true, epochNum, nil
|
|
}
|
|
|
|
_, parentRound, _, err := x.getExtraFields(parentHeader)
|
|
if err != nil {
|
|
log.Error("[IsEpochSwitch] decode header error", "err", err, "header", parentHeader, "extra", common.Bytes2Hex(parentHeader.Extra))
|
|
return false, 0, err
|
|
}
|
|
if round <= parentRound {
|
|
// this round is no larger than parentRound, should return false
|
|
return false, epochNum, nil
|
|
}
|
|
|
|
epochStartRound := round - round%utils.Round(x.config.Epoch)
|
|
return parentRound < epochStartRound, epochNum, nil
|
|
}
|