github.com/ava-labs/avalanchego@v1.11.11/vms/components/gas/state.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package gas 5 6 import ( 7 "errors" 8 "math" 9 10 safemath "github.com/ava-labs/avalanchego/utils/math" 11 ) 12 13 var ErrInsufficientCapacity = errors.New("insufficient capacity") 14 15 type State struct { 16 Capacity Gas `serialize:"true" json:"capacity"` 17 Excess Gas `serialize:"true" json:"excess"` 18 } 19 20 // AdvanceTime adds maxPerSecond to capacity and subtracts targetPerSecond 21 // from excess over the provided duration. 22 // 23 // Capacity is capped at maxCapacity. 24 // Excess to be removed is capped at excess. 25 func (s State) AdvanceTime( 26 maxCapacity Gas, 27 maxPerSecond Gas, 28 targetPerSecond Gas, 29 duration uint64, 30 ) State { 31 return State{ 32 Capacity: min( 33 s.Capacity.AddPerSecond(maxPerSecond, duration), 34 maxCapacity, 35 ), 36 Excess: s.Excess.SubPerSecond(targetPerSecond, duration), 37 } 38 } 39 40 // ConsumeGas removes gas from capacity and adds gas to excess. 41 // 42 // If the capacity is insufficient, an error is returned. 43 // If the excess would overflow, it is capped at MaxUint64. 44 func (s State) ConsumeGas(gas Gas) (State, error) { 45 newCapacity, err := safemath.Sub(uint64(s.Capacity), uint64(gas)) 46 if err != nil { 47 return State{}, ErrInsufficientCapacity 48 } 49 50 newExcess, err := safemath.Add(uint64(s.Excess), uint64(gas)) 51 if err != nil { 52 //nolint:nilerr // excess is capped at MaxUint64 53 return State{ 54 Capacity: Gas(newCapacity), 55 Excess: math.MaxUint64, 56 }, nil 57 } 58 59 return State{ 60 Capacity: Gas(newCapacity), 61 Excess: Gas(newExcess), 62 }, nil 63 }