gitlab.com/flarenetwork/coreth@v0.1.1/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  	"gitlab.com/flarenetwork/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.chain.GetTxPool(),
    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  	gpu.handleUpdate(gpu.setter.SetMinFee, gpu.chainConfig.ApricotPhase3BlockTimestamp, big.NewInt(params.ApricotPhase3MinBaseFee))
    53  }
    54  
    55  // handleUpdate handles calling update(price) at the appropriate time based on
    56  // the value of [timestamp].
    57  // 1) If [timestamp] is nil, update is never called
    58  // 2) If [timestamp] has already passed, update is called immediately
    59  // 3) [timestamp] is some time in the future, starts a goroutine that will call update(price) at the time
    60  // given by [timestamp].
    61  func (gpu *gasPriceUpdater) handleUpdate(update func(price *big.Int), timestamp *big.Int, price *big.Int) bool {
    62  	if timestamp == nil {
    63  		return true
    64  	}
    65  
    66  	currentTime := time.Now()
    67  	upgradeTime := time.Unix(timestamp.Int64(), 0)
    68  	if currentTime.After(upgradeTime) {
    69  		update(price)
    70  	} else {
    71  		gpu.wg.Add(1)
    72  		go gpu.updatePrice(update, time.Until(upgradeTime), price)
    73  	}
    74  	return false
    75  }
    76  
    77  // updatePrice calls update(updatedPrice) after waiting for [duration] or shuts down early
    78  // if the [shutdownChan] is closed.
    79  func (gpu *gasPriceUpdater) updatePrice(update func(price *big.Int), duration time.Duration, updatedPrice *big.Int) {
    80  	defer gpu.wg.Done()
    81  	select {
    82  	case <-time.After(duration):
    83  		update(updatedPrice)
    84  	case <-gpu.shutdownChan:
    85  	}
    86  }