Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 28 additions & 12 deletions consensus/XDPoS/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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
Expand All @@ -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)
}

Expand Down Expand Up @@ -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()))
}
Expand Down
8 changes: 8 additions & 0 deletions consensus/XDPoS/engines/engine_v2/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,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 {
Expand All @@ -887,6 +891,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())
Expand Down
8 changes: 7 additions & 1 deletion consensus/XDPoS/engines/engine_v2/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package engine_v2

import (
"encoding/json"
"fmt"

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/consensus"
Expand Down Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions consensus/XDPoS/engines/engine_v2/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions consensus/XDPoS/engines/engine_v2/verifyHeader.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions consensus/XDPoS/utils/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
17 changes: 15 additions & 2 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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)
Expand Down
30 changes: 23 additions & 7 deletions eth/hooks/engine_v2_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package hooks

import (
"errors"
"fmt"
"math/big"
"time"

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:])
Expand Down