aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Buchwald <aaron.buchwald56@gmail.com>2020-12-17 13:58:14 -0500
committerAaron Buchwald <aaron.buchwald56@gmail.com>2020-12-17 13:58:14 -0500
commit3960b690bf8c67afe706bb469b0ff2798424a26e (patch)
tree77b60c080f63df21af115406e6b78a7862a68ad9
parentea099f5811574d3dae79a31053d21b523d008d75 (diff)
Decrease minimum gas price at apricot upgrade
-rw-r--r--coreth.go6
-rw-r--r--eth/backend.go10
-rw-r--r--eth/gasprice/gasprice.go21
-rw-r--r--params/protocol_params.go36
-rw-r--r--plugin/evm/block.go20
-rw-r--r--plugin/evm/vm.go33
6 files changed, 105 insertions, 21 deletions
diff --git a/coreth.go b/coreth.go
index 25e9da2..c39b171 100644
--- a/coreth.go
+++ b/coreth.go
@@ -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 {