github.com/dim4egster/coreth@v0.10.2/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/dim4egster/coreth/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 // Sets the initial gas price to the launch minimum gas price 42 gpu.setter.SetGasPrice(big.NewInt(params.LaunchMinGasPrice)) 43 44 // Updates to the minimum gas price as of ApricotPhase1 if it's already in effect or starts a goroutine to enable it at the correct time 45 if disabled := gpu.handleUpdate(gpu.setter.SetGasPrice, gpu.chainConfig.ApricotPhase1BlockTimestamp, big.NewInt(params.ApricotPhase1MinGasPrice)); disabled { 46 return 47 } 48 // Updates to the minimum gas price as of ApricotPhase3 if it's already in effect or starts a goroutine to enable it at the correct time 49 if disabled := gpu.handleUpdate(gpu.setter.SetGasPrice, gpu.chainConfig.ApricotPhase3BlockTimestamp, big.NewInt(0)); disabled { 50 return 51 } 52 if disabled := gpu.handleUpdate(gpu.setter.SetMinFee, gpu.chainConfig.ApricotPhase3BlockTimestamp, big.NewInt(params.ApricotPhase3MinBaseFee)); disabled { 53 return 54 } 55 // Updates to the minimum gas price as of ApricotPhase4 if it's already in effect or starts a goroutine to enable it at the correct time 56 gpu.handleUpdate(gpu.setter.SetMinFee, gpu.chainConfig.ApricotPhase4BlockTimestamp, big.NewInt(params.ApricotPhase4MinBaseFee)) 57 } 58 59 // handleUpdate handles calling update(price) at the appropriate time based on 60 // the value of [timestamp]. 61 // 1) If [timestamp] is nil, update is never called 62 // 2) If [timestamp] has already passed, update is called immediately 63 // 3) [timestamp] is some time in the future, starts a goroutine that will call update(price) at the time 64 // given by [timestamp]. 65 func (gpu *gasPriceUpdater) handleUpdate(update func(price *big.Int), timestamp *big.Int, price *big.Int) bool { 66 if timestamp == nil { 67 return true 68 } 69 70 currentTime := time.Now() 71 upgradeTime := time.Unix(timestamp.Int64(), 0) 72 if currentTime.After(upgradeTime) { 73 update(price) 74 } else { 75 gpu.wg.Add(1) 76 go gpu.updatePrice(update, time.Until(upgradeTime), price) 77 } 78 return false 79 } 80 81 // updatePrice calls update(updatedPrice) after waiting for [duration] or shuts down early 82 // if the [shutdownChan] is closed. 83 func (gpu *gasPriceUpdater) updatePrice(update func(price *big.Int), duration time.Duration, updatedPrice *big.Int) { 84 defer gpu.wg.Done() 85 select { 86 case <-time.After(duration): 87 update(updatedPrice) 88 case <-gpu.shutdownChan: 89 } 90 }