diff options
author | Aaron Buchwald <[email protected]> | 2020-12-17 13:58:14 -0500 |
---|---|---|
committer | Aaron Buchwald <[email protected]> | 2020-12-17 13:58:14 -0500 |
commit | 3960b690bf8c67afe706bb469b0ff2798424a26e (patch) | |
tree | 77b60c080f63df21af115406e6b78a7862a68ad9 | |
parent | ea099f5811574d3dae79a31053d21b523d008d75 (diff) |
Decrease minimum gas price at apricot upgrade
-rw-r--r-- | coreth.go | 6 | ||||
-rw-r--r-- | eth/backend.go | 10 | ||||
-rw-r--r-- | eth/gasprice/gasprice.go | 21 | ||||
-rw-r--r-- | params/protocol_params.go | 36 | ||||
-rw-r--r-- | plugin/evm/block.go | 20 | ||||
-rw-r--r-- | plugin/evm/vm.go | 33 |
6 files changed, 105 insertions, 21 deletions
@@ -3,6 +3,7 @@ package coreth import ( "crypto/ecdsa" "io" + "math/big" "os" "github.com/ava-labs/coreth/consensus/dummy" @@ -213,6 +214,11 @@ func (self *ETHChain) GetTxPool() *core.TxPool { return self.backend.TxPool() } +// SetGasPrice sets the gas price on the backend +func (self *ETHChain) SetGasPrice(newGasPrice *big.Int) { + self.backend.SetGasPrice(newGasPrice) +} + type Key struct { Address common.Address PrivateKey *ecdsa.PrivateKey diff --git a/eth/backend.go b/eth/backend.go index e26cbb3..9b6f1e4 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -559,3 +559,13 @@ func (s *Ethereum) AcceptedBlock() *types.Block { } return s.blockchain.CurrentBlock() } + +// SetGasPrice sets the minimum gas price to [newGasPrice] +// sets the price on [s], [txPool], and the gas price oracle +func (s *Ethereum) SetGasPrice(newGasPrice *big.Int) { + s.lock.Lock() + s.gasPrice = newGasPrice + s.lock.Unlock() + s.txPool.SetGasPrice(newGasPrice) + s.APIBackend.gpo.SetGasPrice(newGasPrice) +} diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index 33810b2..dc62ad6 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -48,12 +48,12 @@ type OracleBackend interface { // Oracle recommends gas prices based on the content of recent // blocks. Suitable for both light and full clients. type Oracle struct { - backend OracleBackend - lastHead common.Hash - lastPrice *big.Int - maxPrice *big.Int - cacheLock sync.RWMutex - fetchLock sync.Mutex + backend OracleBackend + lastHead common.Hash + minGasPrice *big.Int + maxPrice *big.Int + cacheLock sync.RWMutex + fetchLock sync.Mutex checkBlocks int percentile int @@ -83,7 +83,7 @@ func NewOracle(backend OracleBackend, params Config) *Oracle { } return &Oracle{ backend: backend, - lastPrice: params.Default, + minGasPrice: params.Default, maxPrice: maxPrice, checkBlocks: blocks, percentile: percent, @@ -93,7 +93,12 @@ func NewOracle(backend OracleBackend, params Config) *Oracle { // SuggestPrice returns a gasprice so that newly created transaction can // have a very high chance to be included in the following blocks. func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) { - return params.MinGasPrice, nil + return gpo.minGasPrice, nil +} + +// SetGasPrice sets the minimum gas price to [newGasPrice] +func (gpo *Oracle) SetGasPrice(newGasPrice *big.Int) { + gpo.minGasPrice = newGasPrice } type getBlockPricesResult struct { diff --git a/params/protocol_params.go b/params/protocol_params.go index fdfb9a5..fe6e6c2 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -152,8 +152,42 @@ var ( GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block. MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be. DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. +) +// Minimum Gas Price +var ( // MinGasPrice is the number of nAVAX required per gas unit for a transaction // to be valid, measured in wei - MinGasPrice = big.NewInt(470 * GWei) + MinGasPrice = big.NewInt(470 * GWei) + LaunchMinGasPrice = big.NewInt(470 * GWei) + ApricotMinGasPrice = big.NewInt(100 * GWei) ) + +// GasPrice provides an interface to get the minimum +// gas price +type GasPrice interface { + GetMin(blockTimestamp *big.Int) *big.Int +} + +// NewGasPrice returns a getter for the GasPrice based on a block timestamp +func NewGasPrice(apricotTimestamp *big.Int) GasPrice { + return &minGasPriceFetcher{ + launchPrice: LaunchMinGasPrice, + apricotPrice: ApricotMinGasPrice, + apricotTimestamp: apricotTimestamp, + } +} + +type minGasPriceFetcher struct { + apricotTimestamp *big.Int + launchPrice, apricotPrice *big.Int +} + +// GetMin returns the minimum gas price for a block with the given timestamp +func (m *minGasPriceFetcher) GetMin(blockTimestamp *big.Int) *big.Int { + if m.apricotTimestamp == nil || blockTimestamp.Cmp(m.apricotTimestamp) >= 0 { + return m.apricotPrice + } + + return m.launchPrice +} diff --git a/plugin/evm/block.go b/plugin/evm/block.go index 5a0d377..08ef231 100644 --- a/plugin/evm/block.go +++ b/plugin/evm/block.go @@ -6,9 +6,9 @@ package evm import ( "errors" "fmt" + "math/big" "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/params" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" @@ -85,9 +85,11 @@ func (b *Block) Verify() error { // Only enforce a minimum fee when bootstrapping has finished if b.vm.ctx.IsBootstrapped() { // Ensure the minimum gas price is paid for every transaction + timestamp := b.ethBlock.Header().Time + minGasPrice := b.vm.minGasPrice.GetMin(new(big.Int).SetUint64(timestamp)) for _, tx := range b.ethBlock.Transactions() { - if tx.GasPrice().Cmp(params.MinGasPrice) < 0 { - return errInvalidBlock + if tx.GasPrice().Cmp(minGasPrice) < 0 { + return fmt.Errorf("block contains tx %s with gas price too low (%d < %d), timestamp: %d", tx.Hash(), tx.GasPrice(), minGasPrice, timestamp) } } } @@ -139,17 +141,21 @@ func (b *Block) Verify() error { } utx := tx.UnsignedTx.(UnsignedAtomicTx) - if utx.SemanticVerify(vm, tx) != nil { - return errInvalidBlock + if err := utx.SemanticVerify(vm, tx); err != nil { + return fmt.Errorf("block atomic tx failed verification due to: %w", err) } bc := vm.chain.BlockChain() _, _, _, err = bc.Processor().Process(b.ethBlock, pState, *bc.GetVMConfig()) if err != nil { - return errInvalidBlock + return fmt.Errorf("block failed processing due to: %w", err) } } _, err := b.vm.chain.InsertChain([]*types.Block{b.ethBlock}) - return err + if err != nil { + return fmt.Errorf("failed to insert block into chain due to: %w", err) + } + + return nil } // Bytes implements the snowman.Block interface diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 9f5607a..ac1eb56 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -185,6 +185,8 @@ type VM struct { shutdownWg sync.WaitGroup fx secp256k1fx.Fx + + minGasPrice params.GasPrice } func (vm *VM) getAtomicTx(block *types.Block) *Tx { @@ -262,13 +264,34 @@ func (vm *VM) Initialize( config.Miner.ManualMining = true config.Miner.DisableUncle = true - // Set minimum price for mining and default gas price oracle value to the min - // gas price to prevent so transactions and blocks all use the correct fees - config.Miner.GasPrice = params.MinGasPrice + // Set minimum gas price and launch goroutine to sleep until + // network upgrade when the gas price must be changed + vm.minGasPrice = params.NewGasPrice(g.Config.ApricotBlockTimestamp) + if g.Config.ApricotBlockTimestamp == nil { + config.Miner.GasPrice = params.ApricotMinGasPrice + config.GPO.Default = params.ApricotMinGasPrice + config.TxPool.PriceLimit = params.ApricotMinGasPrice.Uint64() + } else { + apricotTime := time.Unix(g.Config.ApricotBlockTimestamp.Int64(), 0) + if time.Now().Before(apricotTime) { + config.Miner.GasPrice = params.LaunchMinGasPrice + config.GPO.Default = params.LaunchMinGasPrice + config.TxPool.PriceLimit = params.LaunchMinGasPrice.Uint64() + + go func() { + time.Sleep(time.Until(apricotTime)) + + vm.chain.SetGasPrice(params.ApricotMinGasPrice) + }() + } else { + config.Miner.GasPrice = params.ApricotMinGasPrice + config.GPO.Default = params.ApricotMinGasPrice + config.TxPool.PriceLimit = params.ApricotMinGasPrice.Uint64() + } + } + config.RPCGasCap = vm.CLIConfig.RPCGasCap config.RPCTxFeeCap = vm.CLIConfig.RPCTxFeeCap - config.GPO.Default = params.MinGasPrice - config.TxPool.PriceLimit = params.MinGasPrice.Uint64() config.TxPool.NoLocals = true if err := config.SetGCMode("archive"); err != nil { |