github.com/iotexproject/iotex-core@v1.14.1-rc1/pkg/util/blockutil/block_time_calculator.go (about) 1 package blockutil 2 3 import ( 4 "errors" 5 "math" 6 "time" 7 ) 8 9 type ( 10 // BlockTimeCalculator calculates block time of a given height. 11 BlockTimeCalculator struct { 12 getBlockInterval getBlockIntervalFn 13 getTipHeight getTipHeightFn 14 getHistoryBlockTime getHistoryblockTimeFn 15 } 16 17 getBlockIntervalFn func(uint64) time.Duration 18 getTipHeightFn func() uint64 19 getHistoryblockTimeFn func(uint64) (time.Time, error) 20 ) 21 22 // NewBlockTimeCalculator creates a new BlockTimeCalculator. 23 func NewBlockTimeCalculator(getBlockInterval getBlockIntervalFn, getTipHeight getTipHeightFn, getHistoryBlockTime getHistoryblockTimeFn) (*BlockTimeCalculator, error) { 24 if getBlockInterval == nil { 25 return nil, errors.New("nil getBlockInterval") 26 } 27 if getTipHeight == nil { 28 return nil, errors.New("nil getTipHeight") 29 } 30 if getHistoryBlockTime == nil { 31 return nil, errors.New("nil getHistoryBlockTime") 32 } 33 return &BlockTimeCalculator{ 34 getBlockInterval: getBlockInterval, 35 getTipHeight: getTipHeight, 36 getHistoryBlockTime: getHistoryBlockTime, 37 }, nil 38 } 39 40 // CalculateBlockTime returns the block time of the given height. 41 // If the height is in the future, it will predict the block time according to the tip block time and interval. 42 // If the height is in the past, it will get the block time from indexer. 43 func (btc *BlockTimeCalculator) CalculateBlockTime(height uint64) (time.Time, error) { 44 // get block time from indexer if height is in the past 45 tipHeight := btc.getTipHeight() 46 if height <= tipHeight { 47 return btc.getHistoryBlockTime(height) 48 } 49 50 // predict block time according to tip block time and interval 51 blockInterval := btc.getBlockInterval(tipHeight) 52 blockNumer := time.Duration(height - tipHeight) 53 if blockNumer > math.MaxInt64/blockInterval { 54 return time.Time{}, errors.New("height overflow") 55 } 56 tipBlockTime, err := btc.getHistoryBlockTime(tipHeight) 57 if err != nil { 58 return time.Time{}, err 59 } 60 return tipBlockTime.Add(blockNumer * blockInterval), nil 61 }