diff --git a/consensus/XDPoS/api.go b/consensus/XDPoS/api.go index 287e37b7f4..af8ab44ee2 100644 --- a/consensus/XDPoS/api.go +++ b/consensus/XDPoS/api.go @@ -350,13 +350,17 @@ An API exclusively for V2 consensus, designed to assist in getting rewards of th Given the epoch number, search the epoch switch block. */ func (api *API) GetBlockInfoByEpochNum(epochNumber uint64) (*utils.EpochNumInfo, error) { - result, err := api.XDPoS.EngineV2.GetBlockByEpochNumber(api.chain, epochNumber) + thisEpoch, nextEpoch, err := api.XDPoS.EngineV2.GetBlockByEpochNumber(api.chain, epochNumber) if err != nil { return nil, err } - return &utils.EpochNumInfo{ - EpochBlockHash: result.Hash, - EpochRound: result.Round, - EpochBlockNumber: result.Number, - }, nil + info := &utils.EpochNumInfo{ + EpochBlockHash: thisEpoch.Hash, + EpochRound: thisEpoch.Round, + EpochFirstBlockNumber: thisEpoch.Number, + } + if nextEpoch != nil { + info.EpochLastBlockNumber = new(big.Int).Sub(nextEpoch.Number, big.NewInt(1)) + } + return info, nil } diff --git a/consensus/XDPoS/engines/engine_v2/utils.go b/consensus/XDPoS/engines/engine_v2/utils.go index a82de0f663..c2e17b7e71 100644 --- a/consensus/XDPoS/engines/engine_v2/utils.go +++ b/consensus/XDPoS/engines/engine_v2/utils.go @@ -220,22 +220,22 @@ func (x *XDPoS_v2) CalculateMissingRounds(chain consensus.ChainReader, header *t return missedRoundsMetadata, nil } -func (x *XDPoS_v2) GetBlockByEpochNumber(chain consensus.ChainReader, targetEpochNum uint64) (*types.BlockInfo, error) { +func (x *XDPoS_v2) GetBlockByEpochNumber(chain consensus.ChainReader, targetEpochNum uint64) (*types.BlockInfo, *types.BlockInfo, error) { currentHeader := chain.CurrentHeader() epochSwitchInfo, err := x.getEpochSwitchInfo(chain, currentHeader, currentHeader.Hash()) if err != nil { - return nil, err + return nil, nil, err } epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(epochSwitchInfo.EpochSwitchBlockInfo.Round)/x.config.Epoch // since below function GetEpochSwitchInfoBetween(chain, start, end) return nil if start == end, we early return the result if targetEpochNum == epochNum { - return epochSwitchInfo.EpochSwitchBlockInfo, nil + return epochSwitchInfo.EpochSwitchBlockInfo, nil, nil } if targetEpochNum > epochNum { - return nil, errors.New("input epoch number > current epoch number") + return nil, nil, errors.New("input epoch number > current epoch number") } if targetEpochNum < x.config.V2.SwitchBlock.Uint64()/x.config.Epoch { - return nil, errors.New("input epoch number < v2 begin epoch number") + return nil, nil, errors.New("input epoch number < v2 begin epoch number") } epoch := big.NewInt(int64(x.config.Epoch)) estblockNumDiff := new(big.Int).Mul(epoch, big.NewInt(int64(epochNum-targetEpochNum))) @@ -246,13 +246,17 @@ func (x *XDPoS_v2) GetBlockByEpochNumber(chain consensus.ChainReader, targetEpoc estBlockHeader := chain.GetHeaderByNumber(estBlockNum.Uint64()) epochSwitchInfos, err := x.GetEpochSwitchInfoBetween(chain, estBlockHeader, currentHeader) if err != nil { - return nil, err + return nil, nil, err } - for _, info := range epochSwitchInfos { + for i, info := range epochSwitchInfos { epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(info.EpochSwitchBlockInfo.Round)/x.config.Epoch if epochNum == targetEpochNum { - return info.EpochSwitchBlockInfo, nil + if i < len(epochSwitchInfos)-1 { + nextEpoch := epochSwitchInfos[i+1].EpochSwitchBlockInfo + return info.EpochSwitchBlockInfo, nextEpoch, nil + } + return info.EpochSwitchBlockInfo, nil, nil } } - return nil, errors.New("input epoch number not found (all rounds in this epoch are missed, which is very rare)") + return nil, nil, errors.New("input epoch number not found (all rounds in this epoch are missed, which is very rare)") } diff --git a/consensus/XDPoS/utils/types.go b/consensus/XDPoS/utils/types.go index 96817c294e..b5d1168341 100644 --- a/consensus/XDPoS/utils/types.go +++ b/consensus/XDPoS/utils/types.go @@ -74,7 +74,8 @@ type PublicApiMissedRoundsMetadata struct { // Given an epoch number, this struct records the epoch switch block (first block in epoch) infos such as block number type EpochNumInfo struct { - EpochBlockHash common.Hash `json:"hash"` - EpochRound types.Round `json:"round"` - EpochBlockNumber *big.Int `json:"number"` + EpochBlockHash common.Hash `json:"hash"` + EpochRound types.Round `json:"round"` + EpochFirstBlockNumber *big.Int `json:"firstBlock"` + EpochLastBlockNumber *big.Int `json:"lastBlock"` } diff --git a/consensus/tests/engine_v2_tests/api_test.go b/consensus/tests/engine_v2_tests/api_test.go index f12558b7d4..723ed33090 100644 --- a/consensus/tests/engine_v2_tests/api_test.go +++ b/consensus/tests/engine_v2_tests/api_test.go @@ -204,14 +204,20 @@ func TestGetBlockByEpochNumber(t *testing.T) { assert.Nil(t, info) info, err = engine.APIs(blockchain)[0].Service.(*XDPoS.API).GetBlockInfoByEpochNum(1) + assert.Equal(t, info.EpochFirstBlockNumber.Int64(), int64(901)) + assert.Equal(t, info.EpochLastBlockNumber.Int64(), int64(1799)) assert.Equal(t, info.EpochRound, types.Round(1)) assert.Nil(t, err) info, err = engine.APIs(blockchain)[0].Service.(*XDPoS.API).GetBlockInfoByEpochNum(2) + assert.Equal(t, info.EpochFirstBlockNumber.Int64(), int64(1800)) + assert.Equal(t, info.EpochLastBlockNumber.Int64(), int64(1802)) assert.Equal(t, info.EpochRound, types.Round(900)) assert.Nil(t, err) info, err = engine.APIs(blockchain)[0].Service.(*XDPoS.API).GetBlockInfoByEpochNum(3) + assert.Equal(t, info.EpochFirstBlockNumber.Int64(), int64(1803)) + assert.Equal(t, info.EpochLastBlockNumber.Int64(), int64(1803)) assert.Equal(t, info.EpochRound, types.Round(largeRound)) assert.Nil(t, err) @@ -221,6 +227,8 @@ func TestGetBlockByEpochNumber(t *testing.T) { info, err = engine.APIs(blockchain)[0].Service.(*XDPoS.API).GetBlockInfoByEpochNum(5) assert.Equal(t, info.EpochRound, types.Round(largeRound2)) + assert.Equal(t, info.EpochFirstBlockNumber.Int64(), int64(1804)) + assert.Nil(t, info.EpochLastBlockNumber) assert.Nil(t, err) info, err = engine.APIs(blockchain)[0].Service.(*XDPoS.API).GetBlockInfoByEpochNum(6)