github.com/MetalBlockchain/metalgo@v1.11.9/vms/platformvm/state/chain_time_helpers.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package state 5 6 import ( 7 "fmt" 8 "time" 9 10 "github.com/MetalBlockchain/metalgo/database" 11 "github.com/MetalBlockchain/metalgo/utils/timer/mockable" 12 ) 13 14 func NextBlockTime(state Chain, clk *mockable.Clock) (time.Time, bool, error) { 15 var ( 16 timestamp = clk.Time() 17 parentTime = state.GetTimestamp() 18 ) 19 if parentTime.After(timestamp) { 20 timestamp = parentTime 21 } 22 // [timestamp] = max(now, parentTime) 23 24 nextStakerChangeTime, err := GetNextStakerChangeTime(state) 25 if err != nil { 26 return time.Time{}, false, fmt.Errorf("failed getting next staker change time: %w", err) 27 } 28 29 // timeWasCapped means that [timestamp] was reduced to [nextStakerChangeTime] 30 timeWasCapped := !timestamp.Before(nextStakerChangeTime) 31 if timeWasCapped { 32 timestamp = nextStakerChangeTime 33 } 34 // [timestamp] = min(max(now, parentTime), nextStakerChangeTime) 35 return timestamp, timeWasCapped, nil 36 } 37 38 // GetNextStakerChangeTime returns the next time a staker will be either added 39 // or removed to/from the current validator set. 40 func GetNextStakerChangeTime(state Chain) (time.Time, error) { 41 currentStakerIterator, err := state.GetCurrentStakerIterator() 42 if err != nil { 43 return time.Time{}, err 44 } 45 defer currentStakerIterator.Release() 46 47 pendingStakerIterator, err := state.GetPendingStakerIterator() 48 if err != nil { 49 return time.Time{}, err 50 } 51 defer pendingStakerIterator.Release() 52 53 hasCurrentStaker := currentStakerIterator.Next() 54 hasPendingStaker := pendingStakerIterator.Next() 55 switch { 56 case hasCurrentStaker && hasPendingStaker: 57 nextCurrentTime := currentStakerIterator.Value().NextTime 58 nextPendingTime := pendingStakerIterator.Value().NextTime 59 if nextCurrentTime.Before(nextPendingTime) { 60 return nextCurrentTime, nil 61 } 62 return nextPendingTime, nil 63 case hasCurrentStaker: 64 return currentStakerIterator.Value().NextTime, nil 65 case hasPendingStaker: 66 return pendingStakerIterator.Value().NextTime, nil 67 default: 68 return time.Time{}, database.ErrNotFound 69 } 70 }