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  }