mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 10:20:44 +00:00
consensus/XDPoS, eth: fix potential rpc.BlockNumber overflow, close XFN-69 (#1735)
This commit is contained in:
parent
0fc4c82350
commit
f24e68b015
3 changed files with 89 additions and 18 deletions
|
|
@ -139,6 +139,8 @@ func (api *API) GetSnapshot(number *rpc.BlockNumber) (*utils.PublicApiSnapshot,
|
||||||
var header *types.Header
|
var header *types.Header
|
||||||
if number == nil || *number == rpc.LatestBlockNumber {
|
if number == nil || *number == rpc.LatestBlockNumber {
|
||||||
header = api.chain.CurrentHeader()
|
header = api.chain.CurrentHeader()
|
||||||
|
} else if number.Int64() < 0 {
|
||||||
|
return nil, fmt.Errorf("invalid block number %d", number.Int64())
|
||||||
} else {
|
} else {
|
||||||
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
|
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
|
||||||
}
|
}
|
||||||
|
|
@ -164,6 +166,8 @@ func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) {
|
||||||
var header *types.Header
|
var header *types.Header
|
||||||
if number == nil || *number == rpc.LatestBlockNumber {
|
if number == nil || *number == rpc.LatestBlockNumber {
|
||||||
header = api.chain.CurrentHeader()
|
header = api.chain.CurrentHeader()
|
||||||
|
} else if number.Int64() < 0 {
|
||||||
|
return nil, fmt.Errorf("invalid block number %d", number.Int64())
|
||||||
} else {
|
} else {
|
||||||
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
|
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
|
||||||
}
|
}
|
||||||
|
|
@ -192,13 +196,22 @@ func (api *API) GetMasternodesByNumber(number *rpc.BlockNumber) MasternodesStatu
|
||||||
if info := api.XDPoS.EngineV2.GetLatestCommittedBlockInfo(); info != nil {
|
if info := api.XDPoS.EngineV2.GetLatestCommittedBlockInfo(); info != nil {
|
||||||
header = api.chain.GetHeaderByHash(info.Hash)
|
header = api.chain.GetHeaderByHash(info.Hash)
|
||||||
}
|
}
|
||||||
|
} else if number.Int64() < 0 {
|
||||||
|
return MasternodesStatus{
|
||||||
|
Error: fmt.Errorf("invalid block number %d", number.Int64()),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
|
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if header == nil {
|
if header == nil {
|
||||||
|
if number == nil {
|
||||||
|
return MasternodesStatus{
|
||||||
|
Error: errors.New("can not get header by nil number"),
|
||||||
|
}
|
||||||
|
}
|
||||||
return MasternodesStatus{
|
return MasternodesStatus{
|
||||||
Error: fmt.Errorf("can not get header by number: %v", number),
|
Error: fmt.Errorf("can not get header by number %d", number.Int64()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -311,7 +324,12 @@ func (api *API) GetV2BlockByHeader(header *types.Header, uncle bool) *V2BlockInf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) GetV2BlockByNumber(number *rpc.BlockNumber) *V2BlockInfo {
|
func (api *API) GetV2BlockByNumber(number *rpc.BlockNumber) *V2BlockInfo {
|
||||||
header := api.getHeaderFromApiBlockNum(number)
|
header, err := api.getHeaderFromApiBlockNum(number)
|
||||||
|
if err != nil {
|
||||||
|
return &V2BlockInfo{
|
||||||
|
Error: err.Error(),
|
||||||
|
}
|
||||||
|
}
|
||||||
if header == nil {
|
if header == nil {
|
||||||
if number == nil {
|
if number == nil {
|
||||||
return &V2BlockInfo{
|
return &V2BlockInfo{
|
||||||
|
|
@ -368,10 +386,20 @@ func (api *API) NetworkInformation() NetworkInformation {
|
||||||
An API exclusively for V2 consensus, designed to assist in troubleshooting miners by identifying who mined during their allocated term.
|
An API exclusively for V2 consensus, designed to assist in troubleshooting miners by identifying who mined during their allocated term.
|
||||||
*/
|
*/
|
||||||
func (api *API) GetMissedRoundsInEpochByBlockNum(number *rpc.BlockNumber) (*utils.PublicApiMissedRoundsMetadata, error) {
|
func (api *API) GetMissedRoundsInEpochByBlockNum(number *rpc.BlockNumber) (*utils.PublicApiMissedRoundsMetadata, error) {
|
||||||
return api.XDPoS.CalculateMissingRounds(api.chain, api.getHeaderFromApiBlockNum(number))
|
header, err := api.getHeaderFromApiBlockNum(number)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if header == nil {
|
||||||
|
if number == nil {
|
||||||
|
return nil, errors.New("can not get header by nil number")
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("can not get header by number %d", number.Int64())
|
||||||
|
}
|
||||||
|
return api.XDPoS.CalculateMissingRounds(api.chain, header)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) getHeaderFromApiBlockNum(number *rpc.BlockNumber) *types.Header {
|
func (api *API) getHeaderFromApiBlockNum(number *rpc.BlockNumber) (*types.Header, error) {
|
||||||
var header *types.Header
|
var header *types.Header
|
||||||
if number == nil || *number == rpc.LatestBlockNumber {
|
if number == nil || *number == rpc.LatestBlockNumber {
|
||||||
header = api.chain.CurrentHeader()
|
header = api.chain.CurrentHeader()
|
||||||
|
|
@ -379,10 +407,12 @@ func (api *API) getHeaderFromApiBlockNum(number *rpc.BlockNumber) *types.Header
|
||||||
if info := api.XDPoS.EngineV2.GetLatestCommittedBlockInfo(); info != nil {
|
if info := api.XDPoS.EngineV2.GetLatestCommittedBlockInfo(); info != nil {
|
||||||
header = api.chain.GetHeaderByHash(info.Hash)
|
header = api.chain.GetHeaderByHash(info.Hash)
|
||||||
}
|
}
|
||||||
|
} else if number.Int64() < 0 {
|
||||||
|
return nil, fmt.Errorf("invalid block number %d", number.Int64())
|
||||||
} else {
|
} else {
|
||||||
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
|
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
|
||||||
}
|
}
|
||||||
return header
|
return header, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateSigners(message map[string]SignerTypes, pool map[string]map[common.Hash]utils.PoolObj, masternodes []common.Address) {
|
func calculateSigners(message map[string]SignerTypes, pool map[string]map[common.Hash]utils.PoolObj, masternodes []common.Address) {
|
||||||
|
|
@ -464,16 +494,34 @@ func (api *API) GetRewardByAccount(account common.Address, begin rpc.BlockNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) getRewardFileNamesInRange(begin, end *rpc.BlockNumber) ([]rewardFileName, error) {
|
func (api *API) getRewardFileNamesInRange(begin, end *rpc.BlockNumber) ([]rewardFileName, error) {
|
||||||
beginHeader := api.getHeaderFromApiBlockNum(begin)
|
beginHeader, err := api.getHeaderFromApiBlockNum(begin)
|
||||||
if beginHeader == nil {
|
if err != nil {
|
||||||
return nil, errors.New("illegal begin block number")
|
if begin == nil {
|
||||||
|
return nil, fmt.Errorf("can not get begin header from nil number, err: %w", err)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("can not get begin header from number %d, err: %w", begin.Int64(), err)
|
||||||
|
}
|
||||||
|
if beginHeader == nil {
|
||||||
|
if begin == nil {
|
||||||
|
return nil, errors.New("begin block number is nil")
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("illegal begin block number %d", begin.Int64())
|
||||||
|
}
|
||||||
|
endHeader, err := api.getHeaderFromApiBlockNum(end)
|
||||||
|
if err != nil {
|
||||||
|
if end == nil {
|
||||||
|
return nil, fmt.Errorf("can not get end header from nil number, err: %w", err)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("can not get end header from number %d, err: %w", end.Int64(), err)
|
||||||
}
|
}
|
||||||
endHeader := api.getHeaderFromApiBlockNum(end)
|
|
||||||
if endHeader == nil {
|
if endHeader == nil {
|
||||||
return nil, errors.New("illegal end block number")
|
if end == nil {
|
||||||
|
return nil, errors.New("end block number is nil")
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("illegal end block number %d", end.Int64())
|
||||||
}
|
}
|
||||||
if beginHeader.Number.Cmp(endHeader.Number) > 0 {
|
if beginHeader.Number.Cmp(endHeader.Number) > 0 {
|
||||||
return nil, errors.New("illegal begin and end block number, begin > end")
|
return nil, fmt.Errorf("illegal block numbers: begin(%d) > end(%d)", beginHeader.Number.Int64(), endHeader.Number.Int64())
|
||||||
}
|
}
|
||||||
diff := new(big.Int).Sub(endHeader.Number, beginHeader.Number).Int64()
|
diff := new(big.Int).Sub(endHeader.Number, beginHeader.Number).Int64()
|
||||||
if diff < 0 {
|
if diff < 0 {
|
||||||
|
|
@ -621,18 +669,36 @@ func (rewardObj *AccountEpochReward) getRewardAndStatus(account string, data map
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) GetEpochNumbersBetween(begin, end *rpc.BlockNumber) ([]uint64, error) {
|
func (api *API) GetEpochNumbersBetween(begin, end *rpc.BlockNumber) ([]uint64, error) {
|
||||||
beginHeader := api.getHeaderFromApiBlockNum(begin)
|
beginHeader, err := api.getHeaderFromApiBlockNum(begin)
|
||||||
|
if err != nil {
|
||||||
|
if begin == nil {
|
||||||
|
return nil, fmt.Errorf("can not get begin header from nil number, err: %w", err)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("can not get begin header from number %d, err: %w", begin.Int64(), err)
|
||||||
|
}
|
||||||
if beginHeader == nil {
|
if beginHeader == nil {
|
||||||
return nil, errors.New("illegal begin block number")
|
if begin == nil {
|
||||||
|
return nil, errors.New("begin block is nil")
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("illegal begin block number %d", begin.Int64())
|
||||||
|
}
|
||||||
|
endHeader, err := api.getHeaderFromApiBlockNum(end)
|
||||||
|
if err != nil {
|
||||||
|
if end == nil {
|
||||||
|
return nil, fmt.Errorf("can not get end header from nil number, err: %w", err)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("can not get end header from number %d, err: %w", end.Int64(), err)
|
||||||
}
|
}
|
||||||
endHeader := api.getHeaderFromApiBlockNum(end)
|
|
||||||
if endHeader == nil {
|
if endHeader == nil {
|
||||||
return nil, errors.New("illegal end block number")
|
if end == nil {
|
||||||
|
return nil, errors.New("end block number is nil")
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("illegal end block number %d", end.Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
diff := new(big.Int).Sub(endHeader.Number, beginHeader.Number).Int64()
|
diff := new(big.Int).Sub(endHeader.Number, beginHeader.Number).Int64()
|
||||||
if diff < 0 {
|
if diff < 0 {
|
||||||
return nil, errors.New("illegal begin and end block number, begin > end")
|
return nil, errors.New("illegal begin and end block number, begin > end")
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ func TestGetEpochNumbersBetween(t *testing.T) {
|
||||||
numbers, err = engine.APIs(bc.BlockChain())[0].Service.(*XDPoS.API).GetEpochNumbersBetween(&begin, &end)
|
numbers, err = engine.APIs(bc.BlockChain())[0].Service.(*XDPoS.API).GetEpochNumbersBetween(&begin, &end)
|
||||||
|
|
||||||
assert.Nil(t, numbers)
|
assert.Nil(t, numbers)
|
||||||
assert.EqualError(t, err, "illegal end block number")
|
assert.EqualError(t, err, "illegal end block number 1803")
|
||||||
|
|
||||||
// 1803 not exist
|
// 1803 not exist
|
||||||
begin = rpc.BlockNumber(1803)
|
begin = rpc.BlockNumber(1803)
|
||||||
|
|
@ -166,7 +166,7 @@ func TestGetEpochNumbersBetween(t *testing.T) {
|
||||||
numbers, err = engine.APIs(bc.BlockChain())[0].Service.(*XDPoS.API).GetEpochNumbersBetween(&begin, &end)
|
numbers, err = engine.APIs(bc.BlockChain())[0].Service.(*XDPoS.API).GetEpochNumbersBetween(&begin, &end)
|
||||||
|
|
||||||
assert.Nil(t, numbers)
|
assert.Nil(t, numbers)
|
||||||
assert.EqualError(t, err, "illegal begin block number")
|
assert.EqualError(t, err, "illegal begin block number 1803")
|
||||||
}
|
}
|
||||||
func TestGetBlockByEpochNumber(t *testing.T) {
|
func TestGetBlockByEpochNumber(t *testing.T) {
|
||||||
blockchain, _, currentBlock, signer, signFn := PrepareXDCTestBlockChainWithPenaltyForV2Engine(t, 1802, params.TestXDPoSMockChainConfig)
|
blockchain, _, currentBlock, signer, signFn := PrepareXDCTestBlockChainWithPenaltyForV2Engine(t, 1802, params.TestXDPoSMockChainConfig)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -97,6 +98,8 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
|
||||||
} else {
|
} else {
|
||||||
return nil, errors.New("PoS V1 does not support confirmed block lookup")
|
return nil, errors.New("PoS V1 does not support confirmed block lookup")
|
||||||
}
|
}
|
||||||
|
} else if number.Int64() < 0 {
|
||||||
|
return nil, fmt.Errorf("invalid block number %d", number.Int64())
|
||||||
}
|
}
|
||||||
header := b.eth.blockchain.GetHeaderByNumber(uint64(number))
|
header := b.eth.blockchain.GetHeaderByNumber(uint64(number))
|
||||||
if header == nil {
|
if header == nil {
|
||||||
|
|
@ -147,6 +150,8 @@ func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumbe
|
||||||
} else {
|
} else {
|
||||||
return nil, errors.New("PoS V1 does not support confirmed block lookup")
|
return nil, errors.New("PoS V1 does not support confirmed block lookup")
|
||||||
}
|
}
|
||||||
|
} else if number.Int64() < 0 {
|
||||||
|
return nil, fmt.Errorf("invalid block number %d", number.Int64())
|
||||||
}
|
}
|
||||||
return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil
|
return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue