Skip to content

Commit 540ff05

Browse files
gzliudanwanwiset25
authored andcommitted
Fix some panic cuased by nil block, statedb, header (#578)
* fix panic during rollback * eth/hooks: check nil stateDB to fix issue #271 * internal/ethapi: fix eth_call crash * all: check nil statedb * eth: check nil block for tracer api * internal/ethapi: check nil header and block
1 parent b5de62b commit 540ff05

File tree

6 files changed

+80
-11
lines changed

6 files changed

+80
-11
lines changed

core/blockchain.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2584,6 +2584,8 @@ func (bc *BlockChain) UpdateM1() error {
25842584
if err != nil {
25852585
return err
25862586
}
2587+
} else if stateDB == nil {
2588+
return errors.New("nil stateDB in UpdateM1")
25872589
} else {
25882590
candidates = state.GetCandidates(stateDB)
25892591
}

eth/api_backend.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"context"
2121
"encoding/json"
2222
"errors"
23-
"fmt"
2423
"math/big"
2524
"os"
2625
"path/filepath"
@@ -443,7 +442,11 @@ func (b *EthApiBackend) GetVotersRewards(masternodeAddr common.Address) map[comm
443442

444443
state, err := chain.StateAt(lastCheckpointBlock.Root())
445444
if err != nil {
446-
fmt.Println("ERROR Trying to getting state at", lastCheckpointNumber, " Error ", err)
445+
log.Error("fail to get state in GetVotersRewards", "lastCheckpointNumber", lastCheckpointNumber, "err", err)
446+
return nil
447+
}
448+
if state == nil {
449+
log.Error("fail to get state in GetVotersRewards", "lastCheckpointNumber", lastCheckpointNumber)
447450
return nil
448451
}
449452

@@ -503,7 +506,11 @@ func (b *EthApiBackend) GetVotersCap(checkpoint *big.Int, masterAddr common.Addr
503506
state, err := chain.StateAt(checkpointBlock.Root())
504507

505508
if err != nil {
506-
fmt.Println("ERROR Trying to getting state at", checkpoint, " Error ", err)
509+
log.Error("fail to get state in GetVotersCap", "checkpoint", checkpoint, "err", err)
510+
return nil
511+
}
512+
if state != nil {
513+
log.Error("fail to get state in GetVotersCap", "checkpoint", checkpoint)
507514
return nil
508515
}
509516

@@ -533,9 +540,12 @@ func (b *EthApiBackend) GetEpochDuration() *big.Int {
533540
func (b *EthApiBackend) GetMasternodesCap(checkpoint uint64) map[common.Address]*big.Int {
534541
checkpointBlock := b.eth.blockchain.GetBlockByNumber(checkpoint)
535542
state, err := b.eth.blockchain.StateAt(checkpointBlock.Root())
536-
537543
if err != nil {
538-
fmt.Println("ERROR Trying to getting state at", checkpoint, " Error ", err)
544+
log.Error("fail to get state in GetMasternodesCap", "checkpoint", checkpoint, "err", err)
545+
return nil
546+
}
547+
if state == nil {
548+
log.Error("fail to get state in GetMasternodesCap", "checkpoint", checkpoint)
539549
return nil
540550
}
541551

eth/api_tracer.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,32 @@ type txTraceTask struct {
106106
index int // Transaction offset in the block
107107
}
108108

109+
// blockByNumber is the wrapper of the chain access function offered by the backend.
110+
// It will return an error if the block is not found.
111+
func (api *PrivateDebugAPI) blockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
112+
block, err := api.eth.ApiBackend.BlockByNumber(ctx, number)
113+
if err != nil {
114+
return nil, err
115+
}
116+
if block == nil {
117+
return nil, fmt.Errorf("block #%d not found", number)
118+
}
119+
return block, nil
120+
}
121+
122+
// blockByHash is the wrapper of the chain access function offered by the backend.
123+
// It will return an error if the block is not found.
124+
func (api *PrivateDebugAPI) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
125+
block, err := api.eth.ApiBackend.BlockByHash(ctx, hash)
126+
if err != nil {
127+
return nil, err
128+
}
129+
if block == nil {
130+
return nil, fmt.Errorf("block %s not found", hash.Hex())
131+
}
132+
return block, nil
133+
}
134+
109135
// TraceChain returns the structured logs created during the execution of EVM
110136
// between two blocks (excluding start) and returns them as a JSON object.
111137
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,
640666
block *types.Block
641667
)
642668
if hash, ok := blockNrOrHash.Hash(); ok {
643-
block, err = api.eth.ApiBackend.BlockByHash(ctx, hash)
669+
block, err = api.blockByHash(ctx, hash)
644670
} else if number, ok := blockNrOrHash.Number(); ok {
645671
if number == rpc.PendingBlockNumber {
646672
// 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,
650676
// of what the next actual block is likely to contain.
651677
return nil, errors.New("tracing on top of pending is not supported")
652678
}
653-
block, err = api.eth.ApiBackend.BlockByNumber(ctx, number)
679+
block, err = api.blockByNumber(ctx, number)
654680
} else {
655681
return nil, errors.New("invalid arguments; neither block nor hash specified")
656682
}

eth/backend.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,14 @@ func New(ctx *node.ServiceContext, config *ethconfig.Config, XDCXServ *XDCx.XDCX
189189
eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain)
190190
eth.orderPool = core.NewOrderPool(eth.chainConfig, eth.blockchain)
191191
eth.lendingPool = core.NewLendingPool(eth.chainConfig, eth.blockchain)
192-
if common.RollbackHash != common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000") {
192+
if common.RollbackHash != (common.Hash{}) {
193193
curBlock := eth.blockchain.CurrentBlock()
194+
if curBlock == nil {
195+
log.Warn("not find current block when rollback")
196+
}
194197
prevBlock := eth.blockchain.GetBlockByHash(common.RollbackHash)
195198

196-
if curBlock.NumberU64() > prevBlock.NumberU64() {
199+
if curBlock != nil && prevBlock != nil && curBlock.NumberU64() > prevBlock.NumberU64() {
197200
for ; curBlock != nil && curBlock.NumberU64() != prevBlock.NumberU64(); curBlock = eth.blockchain.GetBlock(curBlock.ParentHash(), curBlock.NumberU64()-1) {
198201
eth.blockchain.Rollback([]common.Hash{curBlock.Hash()})
199202
}
@@ -205,6 +208,8 @@ func New(ctx *node.ServiceContext, config *ethconfig.Config, XDCXServ *XDCx.XDCX
205208
log.Crit("Err Rollback", "err", err)
206209
return nil, err
207210
}
211+
} else {
212+
log.Error("skip SetHead because target block is nil when rollback")
208213
}
209214
}
210215

eth/hooks/engine_v1_hooks.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,14 @@ func AttachConsensusV1Hooks(adaptor *XDPoS.XDPoS, bc *core.BlockChain, chainConf
228228
)
229229

230230
stateDB, err := bc.StateAt(bc.GetBlockByHash(block).Root())
231-
candidateAddresses = state.GetCandidates(stateDB)
232-
233231
if err != nil {
234232
return nil, err
235233
}
234+
if stateDB == nil {
235+
return nil, errors.New("nil stateDB in HookGetSignersFromContract")
236+
}
237+
238+
candidateAddresses = state.GetCandidates(stateDB)
236239
for _, address := range candidateAddresses {
237240
v, err := validator.GetCandidateCap(opts, address)
238241
if err != nil {

internal/ethapi/api.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,10 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
897897
result[fieldSuccess] = false
898898
return result, err
899899
}
900+
if statedb == nil {
901+
result[fieldSuccess] = false
902+
return result, errors.New("nil statedb in GetCandidateStatus")
903+
}
900904
candidatesAddresses := state.GetCandidates(statedb)
901905
candidates = make([]utils.Masternode, 0, len(candidatesAddresses))
902906
for _, address := range candidatesAddresses {
@@ -1052,6 +1056,10 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
10521056
result[fieldSuccess] = false
10531057
return result, err
10541058
}
1059+
if statedb == nil {
1060+
result[fieldSuccess] = false
1061+
return result, errors.New("nil statedb in GetCandidates")
1062+
}
10551063
candidatesAddresses := state.GetCandidates(statedb)
10561064
candidates = make([]utils.Masternode, 0, len(candidatesAddresses))
10571065
for _, address := range candidatesAddresses {
@@ -1305,6 +1313,9 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo
13051313
if statedb == nil || err != nil {
13061314
return nil, 0, false, err, nil
13071315
}
1316+
if header == nil {
1317+
return nil, 0, false, errors.New("nil header in DoCall"), nil
1318+
}
13081319
if err := overrides.Apply(statedb); err != nil {
13091320
return nil, 0, false, err, nil
13101321
}
@@ -1327,6 +1338,9 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo
13271338
if err != nil {
13281339
return nil, 0, false, err, nil
13291340
}
1341+
if block == nil {
1342+
return nil, 0, false, fmt.Errorf("nil block in DoCall: number=%d, hash=%s", header.Number.Uint64(), header.Hash().Hex()), nil
1343+
}
13301344
author, err := b.GetEngine().Author(block.Header())
13311345
if err != nil {
13321346
return nil, 0, false, err, nil
@@ -1948,6 +1962,9 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
19481962
if err != nil {
19491963
return nil, 0, nil, err
19501964
}
1965+
if block == nil {
1966+
return nil, 0, nil, fmt.Errorf("nil block in AccessList: number=%d, hash=%s", header.Number.Uint64(), header.Hash().Hex())
1967+
}
19511968
author, err := b.GetEngine().Author(block.Header())
19521969
if err != nil {
19531970
return nil, 0, nil, err
@@ -3617,10 +3634,16 @@ func GetSignersFromBlocks(b Backend, blockNumber uint64, blockHash common.Hash,
36173634
if err != nil {
36183635
return addrs, err
36193636
}
3637+
if header == nil {
3638+
return addrs, errors.New("nil header in GetSignersFromBlocks")
3639+
}
36203640
blockData, err := b.BlockByNumber(nil, rpc.BlockNumber(i))
36213641
if err != nil {
36223642
return addrs, err
36233643
}
3644+
if blockData == nil {
3645+
return addrs, errors.New("nil blockData in GetSignersFromBlocks")
3646+
}
36243647
signTxs := engine.CacheSigningTxs(header.Hash(), blockData.Transactions())
36253648
for _, signtx := range signTxs {
36263649
blkHash := common.BytesToHash(signtx.Data()[len(signtx.Data())-32:])

0 commit comments

Comments
 (0)