unit tests for new basefee and gas target methods

This commit is contained in:
Ian Norden
2020-07-06 02:51:40 -05:00
parent 765f39aa7a
commit 1fbb6ef444
14 changed files with 372 additions and 51 deletions
+2 -3
View File
@@ -502,9 +502,8 @@ func (api *RetestethAPI) mineBlock() error {
}
var gp1559 *core.GasPool
var gasPool *core.GasPool
// See core/gaspool.go for detials on how these gas limit values are calculated
gasPool = core.NewLegacyGasPool(api.chainConfig, header.Number, new(big.Int).SetUint64(header.GasLimit))
// See core/gaspool.go for details on how these gas limit values are calculated
gasPool := core.NewLegacyGasPool(api.chainConfig, header.Number, new(big.Int).SetUint64(header.GasLimit))
if api.chainConfig.IsEIP1559(header.Number) {
gp1559 = core.NewEIP1559GasPool(api.chainConfig, header.Number, new(big.Int).SetUint64(header.GasLimit))
}
+2 -2
View File
@@ -72,8 +72,8 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
}
// Otherwise,
// BASEFEE = PARENT_BASEFEE + PARENT_BASEFEE * delta // EIP1559_GAS_TARGET // BASEFEE_MAX_CHANGE_DENOMINATOR
// Where delta = block.gas_used - EIP1559_GAS_TARGET
// BASEFEE = PARENT_BASEFEE + PARENT_BASEFEE * delta // PARENT_EIP1559_GAS_TARGET // BASEFEE_MAX_CHANGE_DENOMINATOR
// Where delta = parent.GasUsed - PARENT_EIP1559_GAS_TARGET
parentGasTarget := CalcEIP1559GasTarget(config, parent.Number, new(big.Int).SetUint64(parent.GasLimit))
delta := new(big.Int).Sub(new(big.Int).SetUint64(parent.GasUsed), parentGasTarget)
mul := new(big.Int).Mul(parent.BaseFee, delta)
+324
View File
@@ -0,0 +1,324 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package misc
import (
"math/big"
"testing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
// TestCalcEIP1559GasTarget tests that CalEIP1559GasTarget()returns the correct value
func TestCalcEIP1559GasTarget(t *testing.T) {
testConditions := []struct {
// Test inputs
config *params.ChainConfig
eip1559activation *big.Int
transitionDuration uint64
height *big.Int
gasLimit *big.Int
// Expected result
eip1559GasTarget *big.Int
}{
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(1),
big.NewInt(100000),
big.NewInt(0),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(999),
big.NewInt(100000),
big.NewInt(0),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(1000),
big.NewInt(100000),
big.NewInt(50000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(1001),
big.NewInt(100000),
big.NewInt(50050),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(1500),
big.NewInt(100000),
big.NewInt(75000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(1999),
big.NewInt(100000),
big.NewInt(99950),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(100000),
big.NewInt(100000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2001),
big.NewInt(100000),
big.NewInt(100000),
},
}
for i, test := range testConditions {
config := *test.config
config.EIP1559Block = test.eip1559activation
config.EIP1559.MigrationBlockDuration = test.transitionDuration
config.EIP1559FinalizedBlock = new(big.Int).Add(config.EIP1559Block, new(big.Int).SetUint64(config.EIP1559.MigrationBlockDuration))
gasTarget := CalcEIP1559GasTarget(&config, test.height, test.gasLimit)
if gasTarget.Cmp(test.eip1559GasTarget) != 0 {
t.Errorf("test %d expected EIP1559GasTarget %d got %d", i+1, test.eip1559GasTarget.Uint64(), gasTarget.Uint64())
}
}
}
// TestCalcBaseFee tests that CalcBaseFee()returns the correct value
func TestCalcBaseFee(t *testing.T) {
testConditions := []struct {
// Test inputs
config *params.ChainConfig
eip1559activation *big.Int
transitionDuration uint64
parentHeight *big.Int
parentBaseFee *big.Int
parentGasLimit uint64
parentGasUsed uint64
// Expected result
baseFee *big.Int
}{
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(1),
big.NewInt(1000000000),
1000000,
10000000,
nil,
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(999),
big.NewInt(1000000000),
1000000,
10000000,
new(big.Int).SetUint64(params.EIP1559ChainConfig.EIP1559.InitialBaseFee),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(1000),
big.NewInt(1000000000),
1000000,
10000000,
big.NewInt(1125000000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000), // past finalization parentGasLimit is the EIP1559GasTarget
big.NewInt(1000000000),
500000,
10000000,
big.NewInt(1125000000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1000000000),
1000000,
10000000,
big.NewInt(1125000000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1000000000),
6000000,
10000000,
big.NewInt(1083333333),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1000000000),
7000000,
10000000,
big.NewInt(1053571428),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1000000000),
8000000,
10000000,
big.NewInt(1031250000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1000000000),
9000000,
10000000,
big.NewInt(1013888888),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1000000000),
10000000,
10000000,
big.NewInt(1000000000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1000000000),
11000000,
10000000,
big.NewInt(988636363),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(900000000),
1000000,
10000000,
big.NewInt(1012500000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1100000000),
1000000,
10000000,
big.NewInt(1237500000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1200000000),
1000000,
10000000,
big.NewInt(1350000000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1000000000),
10000000,
9000000,
big.NewInt(987500000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1000000000),
10000000,
11000000,
big.NewInt(1012500000),
},
{
params.EIP1559ChainConfig,
big.NewInt(1000),
1000,
big.NewInt(2000),
big.NewInt(1000000000),
10000000,
12000000,
big.NewInt(1025000000),
},
}
for i, test := range testConditions {
config := *test.config
config.EIP1559Block = test.eip1559activation
config.EIP1559.MigrationBlockDuration = test.transitionDuration
config.EIP1559FinalizedBlock = new(big.Int).Add(config.EIP1559Block, new(big.Int).SetUint64(config.EIP1559.MigrationBlockDuration))
parent := &types.Header{
GasLimit: test.parentGasLimit,
GasUsed: test.parentGasUsed,
Number: test.parentHeight,
BaseFee: test.parentBaseFee,
}
gasTarget := CalcBaseFee(&config, parent)
if gasTarget != nil {
if test.baseFee != nil && gasTarget.Cmp(test.baseFee) != 0 {
t.Errorf("test %d expected BaseFee %d got %d", i+1, test.baseFee.Uint64(), gasTarget.Uint64())
}
if test.baseFee == nil {
t.Errorf("test %d expected nil BaseFee got %d", i+1, gasTarget.Uint64())
}
} else if test.baseFee != nil {
t.Errorf("test %d expected BaseFee %d got nil", i+1, test.baseFee.Uint64())
}
}
}
+1 -1
View File
@@ -59,7 +59,7 @@ func (b *BlockGen) SetCoinbase(addr common.Address) {
panic("coinbase can only be set once")
}
b.header.Coinbase = addr
// See core/gaspool.go for detials on how these gas limit values are calculated
// See core/gaspool.go for details on how these gas limit values are calculated
b.gasPool = NewLegacyGasPool(b.config, b.header.Number, new(big.Int).SetUint64(b.header.GasLimit))
if b.config.IsEIP1559(b.header.Number) {
b.gasPool1559 = NewEIP1559GasPool(b.config, b.header.Number, new(big.Int).SetUint64(b.header.GasLimit))
+6 -6
View File
@@ -245,8 +245,8 @@ func generateChainDuringTransition(t *testing.T) {
if state.GetBalance(addr1).Uint64() != 989000 {
t.Fatalf("expected balance of addr1 to equal %d got %d", 989000, state.GetBalance(addr1).Uint64())
}
if state.GetBalance(addr2).Uint64() != 4917051584000 {
t.Fatalf("expected balance of addr2 to equal %d got %d", 10000, state.GetBalance(addr2).Uint64())
if state.GetBalance(addr2).Uint64() != 4901403728000 {
t.Fatalf("expected balance of addr2 to equal %d got %d", 4901403728000, state.GetBalance(addr2).Uint64())
}
// This value is different because the test config we use has Constantinople active (uses ConstantinopleBlockReward)
bal, _ := new(big.Int).SetString("7875000000000001000", 10)
@@ -389,11 +389,11 @@ func generateChainAfterFinalization2(t *testing.T) {
if blockchain.CurrentBlock().Number().Uint64() != 5 {
t.Fatalf("expected last block to equal %d got %d", 5, blockchain.CurrentBlock().Number().Uint64())
}
if state.GetBalance(addr1).Uint64() != 7542051573000 {
t.Fatalf("expected balance of addr1 to equal %d got %d", 7542051573000, state.GetBalance(addr1).Uint64())
if state.GetBalance(addr1).Uint64() != 7536639348000 {
t.Fatalf("expected balance of addr1 to equal %d got %d", 7536639348000, state.GetBalance(addr1).Uint64())
}
if state.GetBalance(addr2).Uint64() != 4917051584000 {
t.Fatalf("expected balance of addr2 to equal %d got %d", 4917051584000, state.GetBalance(addr2).Uint64())
if state.GetBalance(addr2).Uint64() != 4911639359000 {
t.Fatalf("expected balance of addr2 to equal %d got %d", 4911639359000, state.GetBalance(addr2).Uint64())
}
// This value is different than in TestGenerateChain because the test config we use has Constantinople active (uses ConstantinopleBlockReward)
bal, _ := new(big.Int).SetString("7875000000000001000", 10)
+4 -4
View File
@@ -51,11 +51,11 @@ func newStatePrefetcher(config *params.ChainConfig, bc *BlockChain, engine conse
// only goal is to pre-cache transaction signatures and state trie nodes.
func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *uint32) {
var (
header = block.Header()
gp *GasPool
gp1559 *GasPool
header = block.Header()
gp *GasPool
gp1559 *GasPool
)
// See core/gaspool.go for detials on how these gas limit values are calculated
// See core/gaspool.go for details on how these gas limit values are calculated
gp = NewLegacyGasPool(p.config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
if p.config.IsEIP1559(block.Number()) {
gp1559 = NewEIP1559GasPool(p.config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
+3 -2
View File
@@ -17,6 +17,8 @@
package core
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
@@ -25,7 +27,6 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"math/big"
)
// StateProcessor is a basic Processor, which takes care of transitioning
@@ -63,7 +64,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
gp *GasPool
gp1559 *GasPool
)
// See core/gaspool.go for detials on how these gas limit values are calculated
// See core/gaspool.go for details on how these gas limit values are calculated
gp = NewLegacyGasPool(p.config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
if p.config.IsEIP1559(block.Number()) {
gp1559 = NewEIP1559GasPool(p.config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
-1
View File
@@ -333,7 +333,6 @@ func (l *txList) Filter(costLimit *big.Int, legacyGasLimit, eip1559GasLimit uint
l.costcap = new(big.Int).Set(costLimit) // Lower the caps to the thresholds
l.legacyGasCap = legacyGasLimit
l.eip1559GasCap = eip1559GasLimit
// Filter out all the transactions above the account's funds
removed := l.txs.Filter(func(tx *types.Transaction) bool {
return tx.Cost(baseFee).Cmp(costLimit) > 0 || (tx.GasPrice() != nil && tx.Gas() > legacyGasLimit) || (tx.GasPremium()) != nil && tx.Gas() > eip1559GasLimit
+11 -13
View File
@@ -920,11 +920,11 @@ func TestTransactionDoubleNonceEIP1559(t *testing.T) {
resetState()
signer := types.HomesteadSigner{}
tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 100000, big.NewInt(5), nil, nil, nil), signer, key)
tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 500000, big.NewInt(5), nil, nil, nil), signer, key)
tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, nil, nil, big.NewInt(2), big.NewInt(10)), signer, key)
tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, nil, nil, big.NewInt(1), big.NewInt(10)), signer, key)
tx4, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(6), nil, nil, nil), signer, key)
tx5, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 1000000, big.NewInt(8), nil, nil, nil), signer, key)
tx4, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 100000, big.NewInt(6), nil, nil, nil), signer, key)
tx5, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), 500000, big.NewInt(100), nil, nil, nil), signer, key)
// Add the first two transaction, ensure higher priced stays only
if replace, err := pool.add(tx1, false); err != nil || replace {
@@ -975,7 +975,7 @@ func TestTransactionDoubleNonceEIP1559(t *testing.T) {
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
}
if tx := pool.pending[addr].txs.items[0]; tx.Hash() != tx5.Hash() {
t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx2.Hash())
t.Errorf("transaction mismatch: have %x, want %x", tx.Hash(), tx5.Hash())
}
// Ensure the total transaction count is correct
if pool.all.Count() != 1 {
@@ -1298,7 +1298,7 @@ func TestTransactionDropping(t *testing.T) {
}
}
func TestTransactionDroppingEIP1559(t *testing.T) {
func TestTransactionDroppingEIP15591(t *testing.T) {
t.Parallel()
// Create a test account and fund it
@@ -1370,22 +1370,20 @@ func TestTransactionDroppingEIP1559(t *testing.T) {
t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 4)
}
// Reduce the block gas limit, check that invalidated transactions are dropped
// After EIP1559 initialization, the legacy gas limit is `params.MaxGasEIP1559 - gasLimit` and the EIP1559 gas limit is `gasLimit`
// As such by reducing the `gasLimit` we increase the legacy gas limit, this must be accounted for in these tests (tx1 is not over-gased)
pool.chain.(*testBlockChain).gasLimit = 100
pool.chain.(*testBlockChain).gasLimit = 200
<-pool.requestReset(nil, nil)
if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok {
t.Errorf("funded pending transaction missing: %v", tx0)
}
if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; !ok {
t.Errorf("funded pending transaction missing: %v", tx1)
if _, ok := pool.pending[account].txs.items[tx1.Nonce()]; ok {
t.Errorf("over-gased queued transaction present: %v", tx1)
}
if _, ok := pool.queue[account].txs.items[tx10.Nonce()]; !ok {
t.Errorf("funded queued transaction missing: %v", tx10)
}
if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; ok {
t.Errorf("over-gased queued transaction present: %v", tx11)
if _, ok := pool.queue[account].txs.items[tx11.Nonce()]; !ok {
t.Errorf("funded queued transaction missing: %v", tx11)
}
if pool.all.Count() != 3 {
t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 3)
@@ -1464,7 +1462,7 @@ func TestTransactionDroppingEIP1559Finalized(t *testing.T) {
t.Errorf("total transaction mismatch: have %d, want %d", pool.all.Count(), 4)
}
// Reduce the block gas limit, check that invalidated transactions are dropped
pool.chain.(*testBlockChain).gasLimit = 100
pool.chain.(*testBlockChain).gasLimit = 50
<-pool.requestReset(nil, nil)
if _, ok := pool.pending[account].txs.items[tx0.Nonce()]; !ok {
+2 -1
View File
@@ -19,11 +19,12 @@ package light
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum/consensus/misc"
"math/big"
"sync"
"time"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
+1 -1
View File
@@ -749,7 +749,7 @@ func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coin
return true
}
// See core/gaspool.go for detials on how these gas limit values are calculated
// See core/gaspool.go for details on how these gas limit values are calculated
var eip1559GasLimit uint64
var legacyGasLimit uint64
+8 -8
View File
@@ -358,19 +358,19 @@ type ChainConfig struct {
}
type EIP1559Config struct {
InitialBaseFee uint64
ForkBlockNumber uint64
ForkFinalizedBlockNumber uint64
MigrationBlockDuration uint64
InitialBaseFee uint64
ForkBlockNumber uint64
ForkFinalizedBlockNumber uint64
MigrationBlockDuration uint64
EIP1559BaseFeeMaxChangeDenominator uint64
EIP1559SlackCoefficient uint64
}
var DefaultEIP1559Config = &EIP1559Config{
InitialBaseFee: EIP1559InitialBaseFee,
ForkBlockNumber: EIP1559ForkBlockNumber,
ForkFinalizedBlockNumber: EIP1559ForkFinalizedBlockNumber,
MigrationBlockDuration: EIP1559MigrationBlockDuration,
InitialBaseFee: EIP1559InitialBaseFee,
ForkBlockNumber: EIP1559ForkBlockNumber,
ForkFinalizedBlockNumber: EIP1559ForkFinalizedBlockNumber,
MigrationBlockDuration: EIP1559MigrationBlockDuration,
EIP1559BaseFeeMaxChangeDenominator: EIP1559BaseFeeMaxChangeDenominator,
EIP1559SlackCoefficient: EIP1559SlackCoefficient,
}
+6 -6
View File
@@ -140,12 +140,12 @@ const (
Bls12381MapG1Gas uint64 = 5500 // Gas price for BLS12-381 mapping field element to G1 operation
Bls12381MapG2Gas uint64 = 110000 // Gas price for BLS12-381 mapping field element to G2 operation
EIP1559InitialBaseFee uint64 = 1000000000 // Wei used as the initial BaseFee
EIP1559ForkBlockNumber uint64 = 110000000 // TBD
EIP1559MigrationBlockDuration uint64 = 800000
EIP1559ForkFinalizedBlockNumber = EIP1559ForkBlockNumber + EIP1559MigrationBlockDuration
EIP1559BaseFeeMaxChangeDenominator uint64 = 8
EIP1559SlackCoefficient uint64 = 2
EIP1559InitialBaseFee uint64 = 1000000000 // Wei used as the initial BaseFee
EIP1559ForkBlockNumber uint64 = 110000000 // TBD
EIP1559MigrationBlockDuration uint64 = 800000
EIP1559ForkFinalizedBlockNumber = EIP1559ForkBlockNumber + EIP1559MigrationBlockDuration
EIP1559BaseFeeMaxChangeDenominator uint64 = 8
EIP1559SlackCoefficient uint64 = 2
)
// Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations
+2 -3
View File
@@ -184,9 +184,8 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
evm := vm.NewEVM(context, statedb, config, vmconfig)
var gp1559 *core.GasPool
var gaspool *core.GasPool
// See core/gaspool.go for detials on how these gas limit values are calculated
gaspool = core.NewLegacyGasPool(config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
// See core/gaspool.go for details on how these gas limit values are calculated
gaspool := core.NewLegacyGasPool(config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
if config.IsEIP1559(block.Number()) {
gp1559 = core.NewEIP1559GasPool(config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
}