all: fix missing nil check, close XFN-114 (#1695)

This commit is contained in:
Daniel Liu 2025-11-02 01:51:44 +08:00 committed by GitHub
parent 2fd4030cb8
commit 9d85990309
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 98 additions and 22 deletions

View file

@ -189,12 +189,19 @@ func (api *API) GetMasternodesByNumber(number *rpc.BlockNumber) MasternodesStatu
if number == nil || *number == rpc.LatestBlockNumber {
header = api.chain.CurrentHeader()
} else if *number == rpc.CommittedBlockNumber {
hash := api.XDPoS.EngineV2.GetLatestCommittedBlockInfo().Hash
header = api.chain.GetHeaderByHash(hash)
if info := api.XDPoS.EngineV2.GetLatestCommittedBlockInfo(); info != nil {
header = api.chain.GetHeaderByHash(info.Hash)
}
} else {
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
}
if header == nil {
return MasternodesStatus{
Error: fmt.Errorf("can not get header by number: %v", number),
}
}
round, err := api.XDPoS.EngineV2.GetRoundNumber(header)
if err != nil {
return MasternodesStatus{
@ -306,14 +313,19 @@ func (api *API) GetV2BlockByHeader(header *types.Header, uncle bool) *V2BlockInf
func (api *API) GetV2BlockByNumber(number *rpc.BlockNumber) *V2BlockInfo {
header := api.getHeaderFromApiBlockNum(number)
if header == nil {
return &V2BlockInfo{
Number: big.NewInt(number.Int64()),
Error: "can not find block from this number",
if number == nil {
return &V2BlockInfo{
Error: "can not find block from nil number",
}
} else {
return &V2BlockInfo{
Number: big.NewInt(number.Int64()),
Error: "can not find block from this number",
}
}
}
uncle := false
return api.GetV2BlockByHeader(header, uncle)
return api.GetV2BlockByHeader(header, false)
}
// Confirm V2 Block Committed Status
@ -328,11 +340,14 @@ func (api *API) GetV2BlockByHash(blockHash common.Hash) *V2BlockInfo {
// confirm this is on the main chain
chainHeader := api.chain.GetHeaderByNumber(header.Number.Uint64())
uncle := false
if header.Hash() != chainHeader.Hash() {
uncle = true
if chainHeader == nil {
return &V2BlockInfo{
Number: header.Number,
Error: "can not find chain header from this number",
}
}
uncle := header.Hash() != chainHeader.Hash()
return api.GetV2BlockByHeader(header, uncle)
}
@ -361,8 +376,9 @@ func (api *API) getHeaderFromApiBlockNum(number *rpc.BlockNumber) *types.Header
if number == nil || *number == rpc.LatestBlockNumber {
header = api.chain.CurrentHeader()
} else if *number == rpc.CommittedBlockNumber {
hash := api.XDPoS.EngineV2.GetLatestCommittedBlockInfo().Hash
header = api.chain.GetHeaderByHash(hash)
if info := api.XDPoS.EngineV2.GetLatestCommittedBlockInfo(); info != nil {
header = api.chain.GetHeaderByHash(info.Hash)
}
} else {
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
}

View file

@ -877,6 +877,10 @@ func (x *XDPoS_v2) commitBlocks(blockChainReader consensus.ChainReader, proposed
}
// Find the last two parent block and check their rounds are the continuous
parentBlock := blockChainReader.GetHeaderByHash(proposedBlockHeader.ParentHash)
if parentBlock == nil {
log.Error("[commitBlocks] Fail to get header by parent hash", "hash", proposedBlockHeader.ParentHash)
return false, fmt.Errorf("commitBlocks fail to get header by parent hash: %v", proposedBlockHeader.ParentHash)
}
_, round, _, err := x.getExtraFields(parentBlock)
if err != nil {
@ -890,6 +894,10 @@ func (x *XDPoS_v2) commitBlocks(blockChainReader consensus.ChainReader, proposed
// If parent round is continuous, we check grandparent
grandParentBlock := blockChainReader.GetHeaderByHash(parentBlock.ParentHash)
if grandParentBlock == nil {
log.Error("[commitBlocks] Fail to get header by grandparent hash", "hash", parentBlock.ParentHash)
return false, fmt.Errorf("commitBlocks fail to get header by grandparent hash: %v", parentBlock.ParentHash)
}
_, round, _, err = x.getExtraFields(grandParentBlock)
if err != nil {
log.Error("Fail to execute second DecodeBytesExtraFields for committing block", "parentBlockHash", parentBlock.Hash())

View file

@ -2,6 +2,7 @@ package engine_v2
import (
"encoding/json"
"fmt"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/consensus"
@ -84,7 +85,12 @@ func (x *XDPoS_v2) getSnapshot(chain consensus.ChainReader, number uint64, isGap
}
}
gapBlockHash := chain.GetHeaderByNumber(gapBlockNum).Hash()
gapHeader := chain.GetHeaderByNumber(gapBlockNum)
if gapHeader == nil {
log.Error("[getSnapshot] Fail to get header", "number", gapBlockNum)
return nil, fmt.Errorf("getSnapshot fail to get header by number: %v", gapBlockNum)
}
gapBlockHash := gapHeader.Hash()
log.Debug("get snapshot from gap block", "number", gapBlockNum, "hash", gapBlockHash.Hex())
// If an in-memory SnapshotV2 was found, use that

View file

@ -96,6 +96,9 @@ func (x *XDPoS_v2) signSignature(signingHash common.Hash) (types.Signature, erro
signer, signFn := x.signer, x.signFn
x.signLock.RUnlock()
if signFn == nil {
return nil, errors.New("signFn is nil")
}
signedHash, err := signFn(accounts.Account{Address: signer}, signingHash.Bytes())
if err != nil {
return nil, fmt.Errorf("error %v while signing hash", err)
@ -182,6 +185,9 @@ func (x *XDPoS_v2) CalculateMissingRounds(chain consensus.ChainReader, header *t
nextHeader := header
for nextHeader.Number.Cmp(switchInfo.EpochSwitchBlockInfo.Number) > 0 {
parentHeader := chain.GetHeaderByHash(nextHeader.ParentHash)
if parentHeader == nil {
return nil, fmt.Errorf("fail to get header by hash %v: ", nextHeader.ParentHash)
}
parentRound, err := x.GetRoundNumber(parentHeader)
if err != nil {
return nil, err
@ -299,6 +305,9 @@ func (x *XDPoS_v2) binarySearchBlockByEpochNumber(chain consensus.ChainReader, t
func (x *XDPoS_v2) GetBlockByEpochNumber(chain consensus.ChainReader, targetEpochNum uint64) (*types.BlockInfo, error) {
currentHeader := chain.CurrentHeader()
if currentHeader == nil {
return nil, errors.New("current header is nil")
}
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, currentHeader, currentHeader.Hash())
if err != nil {
return nil, err
@ -332,6 +341,9 @@ func (x *XDPoS_v2) GetBlockByEpochNumber(chain consensus.ChainReader, targetEpoc
closeEpochNum := uint64(2)
if closeEpochNum >= epochNum-targetEpochNum {
estBlockHeader := chain.GetHeaderByNumber(estBlockNum.Uint64())
if estBlockHeader == nil {
return nil, fmt.Errorf("fail to get est block header by number: %v", estBlockNum)
}
epochSwitchInfos, err := x.GetEpochSwitchInfoBetween(chain, estBlockHeader, currentHeader)
if err != nil {
return nil, err

View file

@ -79,6 +79,10 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
log.Warn("[verifyHeader] decode extra field error", "err", err)
return utils.ErrInvalidV2Extra
}
if quorumCert == nil {
log.Warn("[verifyHeader] quorumCert is nil")
return utils.ErrInvalidQuorumCert
}
minePeriod := uint64(x.config.V2.Config(uint64(round)).MinePeriod)
if parent.Number.Uint64() >= x.config.V2.SwitchBlock.Uint64() && parent.Time+minePeriod > header.Time {

View file

@ -88,6 +88,7 @@ var (
ErrEmptyEpochSwitchValidators = errors.New("empty validators list on epoch switch block")
ErrInvalidV2Extra = errors.New("invalid v2 extra in the block")
ErrInvalidQuorumCert = errors.New("invalid quorum cert")
ErrInvalidQC = errors.New("invalid QC content")
ErrInvalidQCSignatures = errors.New("invalid QC Signatures")
ErrInvalidTC = errors.New("invalid TC content")

View file

@ -743,7 +743,11 @@ func (bc *BlockChain) repair(head **types.Block) error {
log.Info("Rewound blockchain to past state", "number", (*head).Number(), "hash", (*head).Hash())
}
// Otherwise rewind one block and recheck state availability there
(*head) = bc.GetBlock((*head).ParentHash(), (*head).NumberU64()-1)
block := bc.GetBlock((*head).ParentHash(), (*head).NumberU64()-1)
if block == nil {
panic(fmt.Sprintf("repair fail to get block at number: %v, hash: %v", (*head).NumberU64()-1, (*head).ParentHash()))
}
(*head) = block
}
}
@ -1018,10 +1022,16 @@ func (bc *BlockChain) GetBlocksHashCache(number uint64) []common.Hash {
func (bc *BlockChain) AreTwoBlockSamePath(bh1 common.Hash, bh2 common.Hash) bool {
bl1 := bc.GetBlockByHash(bh1)
bl2 := bc.GetBlockByHash(bh2)
toBlockLevel := bl2.Number().Uint64()
if bl1 == nil || bl2 == nil {
return false
}
toBlockLevel := bl2.Number().Uint64()
for bl1.Number().Uint64() > toBlockLevel {
bl1 = bc.GetBlockByHash(bl1.ParentHash())
if bl1 == nil {
return false
}
}
return (bl1.Hash() == bl2.Hash())
@ -2141,6 +2151,9 @@ func (bc *BlockChain) getResultBlock(block *types.Block, verifiedM2 bool) (*Resu
var winner []*types.Block
parent := bc.GetBlock(block.ParentHash(), block.NumberU64()-1)
if parent == nil {
return nil, fmt.Errorf("fail to get parent block at number: %v, hash: %v", block.NumberU64()-1, block.ParentHash())
}
for !bc.HasFullState(parent) {
winner = append(winner, parent)
parent = bc.GetBlock(parent.ParentHash(), parent.NumberU64()-1)

View file

@ -2,6 +2,7 @@ package hooks
import (
"errors"
"fmt"
"math/big"
"slices"
"time"
@ -72,6 +73,10 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
for i := uint64(1); ; i++ {
parentHeader := chain.GetHeader(parentHash, parentNumber)
if parentHeader == nil {
log.Error("[HookPenalty] fail to get parent header")
return []common.Address{}, fmt.Errorf("hook penalty fail to get parent header at number: %v, hash: %v", parentNumber, parentHash)
}
isEpochSwitch, _, err := adaptor.EngineV2.IsEpochSwitch(parentHeader)
if err != nil {
log.Error("[HookPenalty] isEpochSwitch", "err", err)
@ -149,8 +154,10 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
signingTxs, ok := adaptor.GetCachedSigningTxs(bhash)
if !ok {
block := chain.GetBlock(bhash, blockNumber)
txs := block.Transactions()
signingTxs = adaptor.CacheSigningTxs(bhash, txs)
if block != nil {
txs := block.Transactions()
signingTxs = adaptor.CacheSigningTxs(bhash, txs)
}
}
// Check signer signed?
for _, tx := range signingTxs {
@ -221,8 +228,10 @@ func AttachConsensusV2Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
signingTxs, ok := adaptor.GetCachedSigningTxs(bhash)
if !ok {
block := chain.GetBlock(bhash, blockNumber)
txs := block.Transactions()
signingTxs = adaptor.CacheSigningTxs(bhash, txs)
if block != nil {
txs := block.Transactions()
signingTxs = adaptor.CacheSigningTxs(bhash, txs)
}
}
// Check signer signed?
for _, tx := range signingTxs {
@ -404,7 +413,12 @@ func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *type
h := header
for i := number - 1; ; i-- {
h = chain.GetHeader(h.ParentHash, i)
parentHash := h.ParentHash
h = chain.GetHeader(parentHash, i)
if h == nil {
log.Error("[GetSigningTxCount] fail to get header", "number", i, "hash", parentHash)
return nil, fmt.Errorf("fail to get header in GetSigningTxCount at number: %v, hash: %v", i, parentHash)
}
isEpochSwitch, _, err := c.IsEpochSwitch(h)
if err != nil {
return nil, err
@ -464,8 +478,10 @@ func GetSigningTxCount(c *XDPoS.XDPoS, chain consensus.ChainReader, header *type
if !ok {
log.Debug("Failed get from cached", "hash", h.Hash().String(), "number", i)
block := chain.GetBlock(h.Hash(), i)
txs := block.Transactions()
signingTxs = c.CacheSigningTxs(h.Hash(), txs)
if block != nil {
txs := block.Transactions()
signingTxs = c.CacheSigningTxs(h.Hash(), txs)
}
}
for _, tx := range signingTxs {
blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:])