github.com/MetalBlockchain/subnet-evm@v0.4.9/plugin/evm/gasprice_update.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package evm 5 6 import ( 7 "math/big" 8 "sync" 9 "time" 10 11 "github.com/MetalBlockchain/subnet-evm/params" 12 ) 13 14 type gasPriceUpdater struct { 15 setter gasPriceSetter 16 chainConfig *params.ChainConfig 17 shutdownChan <-chan struct{} 18 19 wg *sync.WaitGroup 20 } 21 22 type gasPriceSetter interface { 23 SetGasPrice(price *big.Int) 24 SetMinFee(price *big.Int) 25 } 26 27 // handleGasPriceUpdates creates and runs an instance of 28 func (vm *VM) handleGasPriceUpdates() { 29 gpu := &gasPriceUpdater{ 30 setter: vm.txPool, 31 chainConfig: vm.chainConfig, 32 shutdownChan: vm.shutdownChan, 33 wg: &vm.shutdownWg, 34 } 35 36 gpu.start() 37 } 38 39 // start handles the appropriate gas price and minimum fee updates required by [gpu.chainConfig] 40 func (gpu *gasPriceUpdater) start() { 41 // Updates to the minimum gas price as of Subnet EVM if it's already in effect or starts a goroutine to enable it at the correct time 42 if disabled := gpu.handleUpdate(gpu.setter.SetGasPrice, gpu.chainConfig.SubnetEVMTimestamp, big.NewInt(0)); disabled { 43 return 44 } 45 minBaseFee := gpu.chainConfig.FeeConfig.MinBaseFee 46 // Updates to the minimum gas price as of Subnet EVM if it's already in effect or starts a goroutine to enable it at the correct time 47 gpu.handleUpdate(gpu.setter.SetMinFee, gpu.chainConfig.SubnetEVMTimestamp, minBaseFee) 48 } 49 50 // handleUpdate handles calling update(price) at the appropriate time based on 51 // the value of [timestamp]. 52 // 1) If [timestamp] is nil, update is never called 53 // 2) If [timestamp] has already passed, update is called immediately 54 // 3) [timestamp] is some time in the future, starts a goroutine that will call update(price) at the time 55 // given by [timestamp]. 56 func (gpu *gasPriceUpdater) handleUpdate(update func(price *big.Int), timestamp *big.Int, price *big.Int) bool { 57 if timestamp == nil { 58 return true 59 } 60 61 currentTime := time.Now() 62 upgradeTime := time.Unix(timestamp.Int64(), 0) 63 if currentTime.After(upgradeTime) { 64 update(price) 65 } else { 66 gpu.wg.Add(1) 67 go gpu.updatePrice(update, time.Until(upgradeTime), price) 68 } 69 return false 70 } 71 72 // updatePrice calls update(updatedPrice) after waiting for [duration] or shuts down early 73 // if the [shutdownChan] is closed. 74 func (gpu *gasPriceUpdater) updatePrice(update func(price *big.Int), duration time.Duration, updatedPrice *big.Int) { 75 defer gpu.wg.Done() 76 select { 77 case <-time.After(duration): 78 update(updatedPrice) 79 case <-gpu.shutdownChan: 80 } 81 }