diff --git a/core/blockchain.go b/core/blockchain.go index bbe2909e162d..0eaa0823197b 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2584,6 +2584,8 @@ func (bc *BlockChain) UpdateM1() error { if err != nil { return err } + } else if stateDB == nil { + return errors.New("nil stateDB in UpdateM1") } else { candidates = state.GetCandidates(stateDB) } diff --git a/eth/api_backend.go b/eth/api_backend.go index 161ee5ddfb4f..1a9ebc417091 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -20,7 +20,6 @@ import ( "context" "encoding/json" "errors" - "fmt" "math/big" "os" "path/filepath" @@ -443,7 +442,11 @@ func (b *EthApiBackend) GetVotersRewards(masternodeAddr common.Address) map[comm state, err := chain.StateAt(lastCheckpointBlock.Root()) if err != nil { - fmt.Println("ERROR Trying to getting state at", lastCheckpointNumber, " Error ", err) + log.Error("fail to get state in GetVotersRewards", "lastCheckpointNumber", lastCheckpointNumber, "err", err) + return nil + } + if state == nil { + log.Error("fail to get state in GetVotersRewards", "lastCheckpointNumber", lastCheckpointNumber) return nil } @@ -503,7 +506,11 @@ func (b *EthApiBackend) GetVotersCap(checkpoint *big.Int, masterAddr common.Addr state, err := chain.StateAt(checkpointBlock.Root()) if err != nil { - fmt.Println("ERROR Trying to getting state at", checkpoint, " Error ", err) + log.Error("fail to get state in GetVotersCap", "checkpoint", checkpoint, "err", err) + return nil + } + if state != nil { + log.Error("fail to get state in GetVotersCap", "checkpoint", checkpoint) return nil } @@ -533,9 +540,12 @@ func (b *EthApiBackend) GetEpochDuration() *big.Int { func (b *EthApiBackend) GetMasternodesCap(checkpoint uint64) map[common.Address]*big.Int { checkpointBlock := b.eth.blockchain.GetBlockByNumber(checkpoint) state, err := b.eth.blockchain.StateAt(checkpointBlock.Root()) - if err != nil { - fmt.Println("ERROR Trying to getting state at", checkpoint, " Error ", err) + log.Error("fail to get state in GetMasternodesCap", "checkpoint", checkpoint, "err", err) + return nil + } + if state == nil { + log.Error("fail to get state in GetMasternodesCap", "checkpoint", checkpoint) return nil } diff --git a/eth/api_tracer.go b/eth/api_tracer.go index 01abc14b340f..fbd3bfabd8c6 100644 --- a/eth/api_tracer.go +++ b/eth/api_tracer.go @@ -106,6 +106,32 @@ type txTraceTask struct { index int // Transaction offset in the block } +// blockByNumber is the wrapper of the chain access function offered by the backend. +// It will return an error if the block is not found. +func (api *PrivateDebugAPI) blockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { + block, err := api.eth.ApiBackend.BlockByNumber(ctx, number) + if err != nil { + return nil, err + } + if block == nil { + return nil, fmt.Errorf("block #%d not found", number) + } + return block, nil +} + +// blockByHash is the wrapper of the chain access function offered by the backend. +// It will return an error if the block is not found. +func (api *PrivateDebugAPI) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { + block, err := api.eth.ApiBackend.BlockByHash(ctx, hash) + if err != nil { + return nil, err + } + if block == nil { + return nil, fmt.Errorf("block %s not found", hash.Hex()) + } + return block, nil +} + // TraceChain returns the structured logs created during the execution of EVM // between two blocks (excluding start) and returns them as a JSON object. func (api *PrivateDebugAPI) TraceChain(ctx context.Context, start, end rpc.BlockNumber, config *TraceConfig) (*rpc.Subscription, error) { @@ -640,7 +666,7 @@ func (api *PrivateDebugAPI) TraceCall(ctx context.Context, args ethapi.CallArgs, block *types.Block ) if hash, ok := blockNrOrHash.Hash(); ok { - block, err = api.eth.ApiBackend.BlockByHash(ctx, hash) + block, err = api.blockByHash(ctx, hash) } else if number, ok := blockNrOrHash.Number(); ok { if number == rpc.PendingBlockNumber { // We don't have access to the miner here. For tracing 'future' transactions, @@ -650,7 +676,7 @@ func (api *PrivateDebugAPI) TraceCall(ctx context.Context, args ethapi.CallArgs, // of what the next actual block is likely to contain. return nil, errors.New("tracing on top of pending is not supported") } - block, err = api.eth.ApiBackend.BlockByNumber(ctx, number) + block, err = api.blockByNumber(ctx, number) } else { return nil, errors.New("invalid arguments; neither block nor hash specified") } diff --git a/eth/backend.go b/eth/backend.go index 253d280e046a..f9063d5127e2 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -192,11 +192,14 @@ func New(ctx *node.ServiceContext, config *ethconfig.Config, XDCXServ *XDCx.XDCX eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain) eth.orderPool = core.NewOrderPool(eth.chainConfig, eth.blockchain) eth.lendingPool = core.NewLendingPool(eth.chainConfig, eth.blockchain) - if common.RollbackHash != common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000") { + if common.RollbackHash != (common.Hash{}) { curBlock := eth.blockchain.CurrentBlock() + if curBlock == nil { + log.Warn("not find current block when rollback") + } prevBlock := eth.blockchain.GetBlockByHash(common.RollbackHash) - if curBlock.NumberU64() > prevBlock.NumberU64() { + if curBlock != nil && prevBlock != nil && curBlock.NumberU64() > prevBlock.NumberU64() { for ; curBlock != nil && curBlock.NumberU64() != prevBlock.NumberU64(); curBlock = eth.blockchain.GetBlock(curBlock.ParentHash(), curBlock.NumberU64()-1) { eth.blockchain.Rollback([]common.Hash{curBlock.Hash()}) } @@ -208,6 +211,8 @@ func New(ctx *node.ServiceContext, config *ethconfig.Config, XDCXServ *XDCx.XDCX log.Crit("Err Rollback", "err", err) return nil, err } + } else { + log.Error("skip SetHead because target block is nil when rollback") } } diff --git a/eth/hooks/engine_v1_hooks.go b/eth/hooks/engine_v1_hooks.go index 950e231ba016..65c84d1c30b0 100644 --- a/eth/hooks/engine_v1_hooks.go +++ b/eth/hooks/engine_v1_hooks.go @@ -228,11 +228,14 @@ func AttachConsensusV1Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf ) stateDB, err := bc.StateAt(bc.GetBlockByHash(block).Root()) - candidateAddresses = state.GetCandidates(stateDB) - if err != nil { return nil, err } + if stateDB == nil { + return nil, errors.New("nil stateDB in HookGetSignersFromContract") + } + + candidateAddresses = state.GetCandidates(stateDB) for _, address := range candidateAddresses { v, err := validator.GetCandidateCap(opts, address) if err != nil { diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 1f31f604125c..622c297ccadd 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -897,6 +897,10 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd result[fieldSuccess] = false return result, err } + if statedb == nil { + result[fieldSuccess] = false + return result, errors.New("nil statedb in GetCandidateStatus") + } candidatesAddresses := state.GetCandidates(statedb) candidates = make([]utils.Masternode, 0, len(candidatesAddresses)) for _, address := range candidatesAddresses { @@ -1052,6 +1056,10 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch result[fieldSuccess] = false return result, err } + if statedb == nil { + result[fieldSuccess] = false + return result, errors.New("nil statedb in GetCandidates") + } candidatesAddresses := state.GetCandidates(statedb) candidates = make([]utils.Masternode, 0, len(candidatesAddresses)) for _, address := range candidatesAddresses { @@ -1305,6 +1313,9 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo if statedb == nil || err != nil { return nil, 0, false, err, nil } + if header == nil { + return nil, 0, false, errors.New("nil header in DoCall"), nil + } if err := overrides.Apply(statedb); err != nil { return nil, 0, false, err, nil } @@ -1327,6 +1338,9 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo if err != nil { return nil, 0, false, err, nil } + if block == nil { + return nil, 0, false, fmt.Errorf("nil block in DoCall: number=%d, hash=%s", header.Number.Uint64(), header.Hash().Hex()), nil + } author, err := b.GetEngine().Author(block.Header()) if err != nil { return nil, 0, false, err, nil @@ -1948,6 +1962,9 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH if err != nil { return nil, 0, nil, err } + if block == nil { + return nil, 0, nil, fmt.Errorf("nil block in AccessList: number=%d, hash=%s", header.Number.Uint64(), header.Hash().Hex()) + } author, err := b.GetEngine().Author(block.Header()) if err != nil { return nil, 0, nil, err @@ -3617,10 +3634,16 @@ func GetSignersFromBlocks(b Backend, blockNumber uint64, blockHash common.Hash, if err != nil { return addrs, err } + if header == nil { + return addrs, errors.New("nil header in GetSignersFromBlocks") + } blockData, err := b.BlockByNumber(nil, rpc.BlockNumber(i)) if err != nil { return addrs, err } + if blockData == nil { + return addrs, errors.New("nil blockData in GetSignersFromBlocks") + } signTxs := engine.CacheSigningTxs(header.Hash(), blockData.Transactions()) for _, signtx := range signTxs { blkHash := common.BytesToHash(signtx.Data()[len(signtx.Data())-32:])